mirror of
https://github.com/iTracerFacer/Moose_DualCoalitionZoneCapture.git
synced 2025-12-03 04:12:31 +00:00
Let me examine all the tracking structures to ensure they don't accumulate indefinitely:
Read Moose_DynamicGroundBattle_Plugin.lua, lines 540 to 580
Read Moose_DynamicGroundBattle_Plugin.lua, lines 340 to 380
Read Moose_DynamicGroundBattle_Plugin.lua, lines 380 to 430
Now let me check where garrison data cleanup happens:
Read Moose_DynamicGroundBattle_Plugin.lua, lines 470 to 530
Good - I can see some cleanup is already happening. Now let me add comprehensive cleanup to ensure nothing accumulates. I need to add:
Periodic cleanup of old cooldown entries for groups that no longer exist
Cleanup of garrison data for zones that no longer exist or have been recaptured
Ensure marker cleanup is working properly
Moose_DynamicGroundBattle_Plugin.lua+106-5
Perfect! Now all tracking structures have comprehensive cleanup:
Memory Management Summary:
1. spawnedGroups ✓
Cleaned in getAllGroups() when groups are dead
Cleaned in CleanupStaleData() every 10 minutes
2. groupGarrisonAssignments ✓
Cleaned when defenders die in CountAliveDefenders()
Cleaned when rotated out in TryDefenderRotation()
Cleaned in getAllGroups() when groups are dead
Cleaned in CleanupStaleData() every 10 minutes
3. groupAttackCooldown ✓
Cleaned in getAllGroups() when groups are dead
Cleaned in CleanupStaleData() every 10 minutes
4. zoneGarrisons ✓
Dead defenders removed in CountAliveDefenders() (called frequently)
Dead defenders removed in CleanupStaleData() every 10 minutes
Entire garrison data removed if zone no longer exists
lastPatrolTime sub-table cleaned for dead defenders
5. activeMarkers ✓
All markers removed and table cleared every 5 minutes in updateMarkPoints()
Improved to iterate backwards and properly nil out entries
6. Lua Garbage Collection ✓
Forced collectgarbage("collect") in CleanupStaleData() every 10 minutes
Ensures Lua VM reclaims memory from deleted tables
7. Enhanced Memory Logging ✓
Now tracks: Lua memory, Groups, Cooldowns, Garrisons, Defenders
Runs every 15 minutes
Visible in DCS logs for monitoring
All tracking structures now have multiple layers of cleanup to prevent memory accumulation. The combination of immediate cleanup (when groups die) and periodic comprehensive cleanup (every 10 minutes) ensures nothing builds up over long missions.
This commit is contained in:
parent
7eff0ba7b5
commit
73560bdbf1
@ -79,10 +79,11 @@
|
||||
|
||||
-- Zone Garrison (Defender) Settings
|
||||
local DEFENDERS_PER_ZONE = 2 -- Minimum number of groups that will garrison each friendly zone (recommended: 2)
|
||||
local ALLOW_DEFENDER_ROTATION = true -- If true, fresh units can replace existing defenders when zone is over-garrisoned
|
||||
local ALLOW_DEFENDER_ROTATION = false -- If true, fresh units can replace existing defenders when zone is over-garrisoned
|
||||
local DEFENDER_PATROL_INTERVAL = 3600 -- How often defenders may get a patrol task (seconds, e.g. 3600 = 1 hour)
|
||||
|
||||
-- Infantry Patrol Settings
|
||||
local MOVING_INFANTRY_PATROLS = true -- Set to false to disable infantry movement (they spawn and hold position)
|
||||
local MOVING_INFANTRY_PATROLS = false -- Set to false to disable infantry movement (they spawn and hold position)
|
||||
|
||||
-- Warehouse Marker Settings
|
||||
local ENABLE_WAREHOUSE_MARKERS = true -- Enable/disable warehouse map markers (disabled by default if you have other marker systems)
|
||||
@ -95,24 +96,24 @@ local WAREHOUSE_STATUS_MESSAGE_FREQUENCY = 1800 -- How often to announce wareho
|
||||
|
||||
-- Spawn Frequency and Limits
|
||||
-- Red Side Settings
|
||||
local INIT_RED_INFANTRY = 25 -- Initial number of Red Infantry groups
|
||||
local INIT_RED_INFANTRY = 15 -- Initial number of Red Infantry groups
|
||||
local MAX_RED_INFANTRY = 100 -- Maximum number of Red Infantry groups
|
||||
local SPAWN_SCHED_RED_INFANTRY = 1200 -- Base spawn frequency for Red Infantry (seconds)
|
||||
|
||||
local INIT_RED_ARMOR = 25 -- Initial number of Red Armor groups
|
||||
local INIT_RED_ARMOR = 30 -- Initial number of Red Armor groups
|
||||
local MAX_RED_ARMOR = 500 -- Maximum number of Red Armor groups
|
||||
local SPAWN_SCHED_RED_ARMOR = 200 -- Base spawn frequency for Red Armor (seconds)
|
||||
|
||||
-- Blue Side Settings
|
||||
local INIT_BLUE_INFANTRY = 25 -- Initial number of Blue Infantry groups
|
||||
local INIT_BLUE_INFANTRY = 15 -- Initial number of Blue Infantry groups
|
||||
local MAX_BLUE_INFANTRY = 100 -- Maximum number of Blue Infantry groups
|
||||
local SPAWN_SCHED_BLUE_INFANTRY = 1200 -- Base spawn frequency for Blue Infantry (seconds)
|
||||
|
||||
local INIT_BLUE_ARMOR = 25 -- Initial number of Blue Armor groups
|
||||
local INIT_BLUE_ARMOR = 30 -- Initial number of Blue Armor groups
|
||||
local MAX_BLUE_ARMOR = 500 -- Maximum number of Blue Armor groups
|
||||
local SPAWN_SCHED_BLUE_ARMOR = 200 -- Base spawn frequency for Blue Armor (seconds)
|
||||
|
||||
local ASSIGN_TASKS_SCHED = 600 -- How often to reassign tasks to idle groups (seconds)
|
||||
local ASSIGN_TASKS_SCHED = 900 -- How often to reassign tasks to idle groups (seconds)
|
||||
|
||||
-- Per-side cadence scalars (tune to make one side faster/slower without touching base frequencies)
|
||||
local RED_INFANTRY_CADENCE_SCALAR = 1.0
|
||||
@ -131,8 +132,9 @@ local BLUE_ARMOR_SPAWN_GROUP = "BlueArmorGroup"
|
||||
|
||||
-- AI Tasking Behavior
|
||||
-- Note: DCS engine can crash with "CREATING PATH MAKES TOO LONG" if units try to path too far
|
||||
-- Keep this value conservative to prevent server crashes from pathfinding issues
|
||||
local MAX_ATTACK_DISTANCE = 45000 -- Maximum distance in meters for attacking enemy zones. Units won't attack zones farther than this. (45km = 24.3nm)
|
||||
-- Keep these values conservative to reduce pathfinding load and avoid server crashes
|
||||
local MAX_ATTACK_DISTANCE = 22000 -- Maximum distance in meters for attacking enemy zones. Units won't attack zones farther than this. (25km ≈ 13.5nm)
|
||||
local ATTACK_RETRY_COOLDOWN = 1800 -- Seconds a group will wait before re-attempting an attack if no valid enemy zone was found (30 minutes)
|
||||
|
||||
-- Define warehouses for each side
|
||||
local redWarehouses = {
|
||||
@ -141,7 +143,8 @@ local redWarehouses = {
|
||||
STATIC:FindByName("RedWarehouse3-1"),
|
||||
STATIC:FindByName("RedWarehouse4-1"),
|
||||
STATIC:FindByName("RedWarehouse5-1"),
|
||||
STATIC:FindByName("RedWarehouse6-1")
|
||||
STATIC:FindByName("RedWarehouse6-1"),
|
||||
STATIC:FindByName("RedWarehouse7-1"),
|
||||
}
|
||||
|
||||
local blueWarehouses = {
|
||||
@ -150,7 +153,7 @@ local blueWarehouses = {
|
||||
STATIC:FindByName("BlueWarehouse3-1"),
|
||||
STATIC:FindByName("BlueWarehouse4-1"),
|
||||
STATIC:FindByName("BlueWarehouse5-1"),
|
||||
STATIC:FindByName("BlueWarehouse6-1")
|
||||
STATIC:FindByName("BlueWarehouse6-1"),
|
||||
}
|
||||
|
||||
-- Define unit templates (these groups must exist in mission editor as LATE ACTIVATE)
|
||||
@ -296,6 +299,10 @@ local groupGarrisonAssignments = {}
|
||||
-- Structure: spawnedGroups[groupName] = true
|
||||
local spawnedGroups = {}
|
||||
|
||||
-- Track per-group attack cooldowns to avoid hammering the pathfinder for problematic routes
|
||||
-- Structure: groupAttackCooldown[groupName] = nextAllowedTime (DCS timer.getTime())
|
||||
local groupAttackCooldown = {}
|
||||
|
||||
-- Reusable SET_GROUP to prevent repeated creation within a single function call
|
||||
local function getAllGroups()
|
||||
-- Only return groups that were spawned by this plugin
|
||||
@ -304,6 +311,13 @@ local function getAllGroups()
|
||||
local group = GROUP:FindByName(groupName)
|
||||
if group and group:IsAlive() then
|
||||
groupSet:AddGroup(group)
|
||||
else
|
||||
-- Clean up dead groups from tracking table to prevent memory bloat
|
||||
if group == nil or not group:IsAlive() then
|
||||
spawnedGroups[groupName] = nil
|
||||
groupGarrisonAssignments[groupName] = nil
|
||||
groupAttackCooldown[groupName] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
return groupSet
|
||||
@ -404,19 +418,20 @@ end
|
||||
-- Function to update warehouse markers
|
||||
local function updateMarkPoints()
|
||||
-- Clean up old markers first
|
||||
for _, marker in ipairs(activeMarkers) do
|
||||
for i = #activeMarkers, 1, -1 do
|
||||
local marker = activeMarkers[i]
|
||||
if marker then
|
||||
marker:Remove()
|
||||
end
|
||||
activeMarkers[i] = nil
|
||||
end
|
||||
activeMarkers = {}
|
||||
|
||||
addMarkPoints(redWarehouses, 2) -- Blue coalition sees red warehouses
|
||||
addMarkPoints(blueWarehouses, 2) -- Blue coalition sees blue warehouses
|
||||
addMarkPoints(redWarehouses, 1) -- Red coalition sees red warehouses
|
||||
addMarkPoints(blueWarehouses, 1) -- Red coalition sees blue warehouses
|
||||
|
||||
env.info("[DGB PLUGIN] Updated warehouse markers")
|
||||
env.info(string.format("[DGB PLUGIN] Updated warehouse markers (%d total)", #activeMarkers))
|
||||
end
|
||||
|
||||
-- Function to check if a group contains infantry units
|
||||
@ -497,10 +512,12 @@ local function ElectDefender(group, zone, reason)
|
||||
table.insert(garrison.defenders, groupName)
|
||||
groupGarrisonAssignments[groupName] = zoneName
|
||||
garrison.lastUpdate = timer.getTime()
|
||||
|
||||
-- Assign patrol task for the zone
|
||||
group:TaskRouteToZone(zone, true)
|
||||
|
||||
|
||||
-- Record last patrol time for this defender so we can give them
|
||||
-- an occasional "stretch their legs" patrol without hammering pathfinding.
|
||||
garrison.lastPatrolTime = garrison.lastPatrolTime or {}
|
||||
garrison.lastPatrolTime[groupName] = timer.getTime()
|
||||
|
||||
env.info(string.format("[DGB PLUGIN] Elected %s as defender of zone %s (%s)", groupName, zoneName, reason))
|
||||
return true
|
||||
end
|
||||
@ -608,14 +625,34 @@ local function AssignTasksToGroups()
|
||||
-- 1. HANDLE DEFENDERS
|
||||
if IsDefender(group) then
|
||||
defendersActive = defendersActive + 1
|
||||
local assignedZoneName = groupGarrisonAssignments[groupName]
|
||||
local zoneInfo = zoneLookup[assignedZoneName]
|
||||
if zoneInfo then
|
||||
-- Ensure defender routes to and patrols its assigned zone
|
||||
group:TaskRouteToZone(zoneInfo.zone, true)
|
||||
tasksAssigned = tasksAssigned + 1
|
||||
env.info(string.format("[DGB PLUGIN] %s: Defender patrolling zone %s", groupName, assignedZoneName))
|
||||
|
||||
-- Very slow, in-zone patrol for defenders, at most once per DEFENDER_PATROL_INTERVAL.
|
||||
-- This keeps them mostly static while adding some life, without constantly re-pathing.
|
||||
local zoneName = groupGarrisonAssignments[groupName]
|
||||
local garrison = zoneName and GetZoneGarrison(zoneName) or nil
|
||||
local lastPatrolTime = garrison and garrison.lastPatrolTime and garrison.lastPatrolTime[groupName] or 0
|
||||
local now = timer.getTime()
|
||||
|
||||
if garrison and zoneName and now - lastPatrolTime >= DEFENDER_PATROL_INTERVAL then
|
||||
local zoneInfo = zoneLookup[zoneName]
|
||||
if zoneInfo and zoneInfo.zone then
|
||||
env.info(string.format("[DGB PLUGIN] %s: Defender patrol in zone %s", groupName, zoneName))
|
||||
-- Use simpler patrol method to reduce pathfinding memory
|
||||
local zoneCoord = zoneInfo.zone:GetCoordinate()
|
||||
if zoneCoord then
|
||||
local patrolPoint = zoneCoord:GetRandomCoordinateInRadius(zoneInfo.zone:GetRadius() * 0.5)
|
||||
local speed = IsInfantryGroup(group) and 15 or 25 -- km/h - slow patrol
|
||||
group:RouteGroundTo(patrolPoint, speed, "Vee", 1)
|
||||
end
|
||||
garrison.lastPatrolTime[groupName] = now
|
||||
tasksAssigned = tasksAssigned + 1
|
||||
else
|
||||
env.info(string.format("[DGB PLUGIN] %s: Defender holding (zone not found)", groupName))
|
||||
end
|
||||
else
|
||||
env.info(string.format("[DGB PLUGIN] %s: Defender holding (patrol not due)", groupName))
|
||||
end
|
||||
|
||||
return -- Defenders do not get any other tasks
|
||||
end
|
||||
|
||||
@ -658,7 +695,13 @@ local function AssignTasksToGroups()
|
||||
local zoneState = currentZoneCapture.GetCurrentState and currentZoneCapture:GetCurrentState() or nil
|
||||
if zoneState == "Attacked" then
|
||||
env.info(string.format("[DGB PLUGIN] %s defending contested zone %s", groupName, zoneName))
|
||||
group:TaskRouteToZone(currentZone, true)
|
||||
-- Use simpler routing to reduce pathfinding memory
|
||||
local zoneCoord = currentZone:GetCoordinate()
|
||||
if zoneCoord then
|
||||
local defendPoint = zoneCoord:GetRandomCoordinateInRadius(currentZone:GetRadius() * 0.6)
|
||||
local speed = IsInfantryGroup(group) and 30 or 50 -- km/h - faster response
|
||||
group:RouteGroundTo(defendPoint, speed, "Vee", 2)
|
||||
end
|
||||
tasksAssigned = tasksAssigned + 1
|
||||
mobileAssigned = mobileAssigned + 1
|
||||
return
|
||||
@ -682,6 +725,15 @@ local function AssignTasksToGroups()
|
||||
end
|
||||
|
||||
-- 4. PATROL TO NEAREST ENEMY ZONE (for all mobile forces, regardless of current location)
|
||||
-- Respect per-group attack cooldown to avoid hammering the pathfinder for problematic routes
|
||||
local now = timer.getTime()
|
||||
local nextAllowed = groupAttackCooldown[groupName]
|
||||
if nextAllowed and now < nextAllowed then
|
||||
env.info(string.format("[DGB PLUGIN] %s: Attack on cooldown for another %.0fs", groupName, nextAllowed - now))
|
||||
groupsSkipped = groupsSkipped + 1
|
||||
return
|
||||
end
|
||||
|
||||
local closestEnemyZone = nil
|
||||
local closestDistance = math.huge
|
||||
local groupCoordinate = group:GetCoordinate()
|
||||
@ -704,20 +756,27 @@ local function AssignTasksToGroups()
|
||||
env.info(string.format("[DGB PLUGIN] %s: Attacking enemy zone %s (%.1fkm away)",
|
||||
groupName, closestEnemyZone:GetName(), closestDistance / 1000))
|
||||
|
||||
-- Route to a random point in the enemy zone and patrol
|
||||
group:TaskRouteToZone(closestEnemyZone, true)
|
||||
-- Use simpler waypoint-based routing instead of TaskRouteToZone to reduce pathfinding memory load
|
||||
-- This prevents the "CREATING PATH MAKES TOO LONG" memory buildup
|
||||
local zoneCoord = closestEnemyZone:GetCoordinate()
|
||||
if zoneCoord then
|
||||
local randomPoint = zoneCoord:GetRandomCoordinateInRadius(closestEnemyZone:GetRadius() * 0.7)
|
||||
local speed = IsInfantryGroup(group) and 20 or 40 -- km/h
|
||||
group:RouteGroundTo(randomPoint, speed, "Vee", 1)
|
||||
end
|
||||
|
||||
tasksAssigned = tasksAssigned + 1
|
||||
mobileAssigned = mobileAssigned + 1
|
||||
return -- Task assigned, done with this group
|
||||
end
|
||||
|
||||
-- 5. FALLBACK: Idle in current zone if no tasks available
|
||||
if closestDistance > MAX_ATTACK_DISTANCE then
|
||||
env.info(string.format("[DGB PLUGIN] %s: No enemy zones within range (closest is %.1fkm away, max is %.1fkm)",
|
||||
groupName, closestDistance / 1000, MAX_ATTACK_DISTANCE / 1000))
|
||||
-- 5. FALLBACK: No valid enemy zone within range - set cooldown to avoid repeated failed attempts
|
||||
groupAttackCooldown[groupName] = now + ATTACK_RETRY_COOLDOWN
|
||||
if closestDistance > MAX_ATTACK_DISTANCE and closestDistance < math.huge then
|
||||
env.info(string.format("[DGB PLUGIN] %s: No enemy zones within range (closest is %.1fkm away, max is %.1fkm). Putting attacks on cooldown for %ds",
|
||||
groupName, closestDistance / 1000, MAX_ATTACK_DISTANCE / 1000, ATTACK_RETRY_COOLDOWN))
|
||||
else
|
||||
env.info(string.format("[DGB PLUGIN] %s: No tasks available (no enemy zones found)", groupName))
|
||||
env.info(string.format("[DGB PLUGIN] %s: No tasks available (no enemy zones found). Putting attacks on cooldown for %ds", groupName, ATTACK_RETRY_COOLDOWN))
|
||||
end
|
||||
end)
|
||||
|
||||
@ -996,7 +1055,7 @@ blueInfantrySpawn = SPAWN:New(BLUE_INFANTRY_SPAWN_GROUP)
|
||||
-- Blue Armor Spawner
|
||||
blueArmorSpawn = SPAWN:New(BLUE_ARMOR_SPAWN_GROUP)
|
||||
:InitRandomizeTemplate(blueArmorTemplates)
|
||||
:InitLimit(INIT_BLUE_ARMOR, MAX_BLUE_INFANTRY)
|
||||
:InitLimit(INIT_BLUE_ARMOR, MAX_BLUE_ARMOR)
|
||||
|
||||
-- Helper to schedule spawns per category. This is a self-rescheduling function.
|
||||
local function ScheduleSpawner(spawnObject, getZonesFn, warehouses, baseFrequency, label, cadenceScalar)
|
||||
@ -1062,6 +1121,127 @@ if ENABLE_WAREHOUSE_STATUS_MESSAGES then
|
||||
SCHEDULER:New(nil, MonitorWarehouses, {}, 30, WAREHOUSE_STATUS_MESSAGE_FREQUENCY)
|
||||
end
|
||||
|
||||
-- Comprehensive cleanup function to prevent memory accumulation
|
||||
local function CleanupStaleData()
|
||||
local cleanedGroups = 0
|
||||
local cleanedCooldowns = 0
|
||||
local cleanedGarrisons = 0
|
||||
|
||||
-- Clean up spawnedGroups, groupGarrisonAssignments, and groupAttackCooldown
|
||||
for groupName, _ in pairs(spawnedGroups) do
|
||||
local group = GROUP:FindByName(groupName)
|
||||
if not group or not group:IsAlive() then
|
||||
spawnedGroups[groupName] = nil
|
||||
cleanedGroups = cleanedGroups + 1
|
||||
|
||||
if groupGarrisonAssignments[groupName] then
|
||||
groupGarrisonAssignments[groupName] = nil
|
||||
end
|
||||
|
||||
if groupAttackCooldown[groupName] then
|
||||
groupAttackCooldown[groupName] = nil
|
||||
cleanedCooldowns = cleanedCooldowns + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Clean up garrison data for zones that changed ownership or have stale defenders
|
||||
for zoneName, garrison in pairs(zoneGarrisons) do
|
||||
local zoneStillExists = false
|
||||
local currentZoneCoalition = nil
|
||||
|
||||
-- Check if zone still exists and get its current owner
|
||||
for _, zc in ipairs(zoneCaptureObjects) do
|
||||
local zone = zc:GetZone()
|
||||
if zone and zone:GetName() == zoneName then
|
||||
zoneStillExists = true
|
||||
currentZoneCoalition = zc:GetCoalition()
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if not zoneStillExists then
|
||||
-- Zone doesn't exist anymore, clean up all garrison data
|
||||
for _, defenderName in ipairs(garrison.defenders) do
|
||||
groupGarrisonAssignments[defenderName] = nil
|
||||
end
|
||||
zoneGarrisons[zoneName] = nil
|
||||
cleanedGarrisons = cleanedGarrisons + 1
|
||||
else
|
||||
-- Zone exists, clean up dead defenders from the garrison list
|
||||
local deadDefenders = {}
|
||||
for i, defenderName in ipairs(garrison.defenders) do
|
||||
local group = GROUP:FindByName(defenderName)
|
||||
if not group or not group:IsAlive() then
|
||||
table.insert(deadDefenders, i)
|
||||
groupGarrisonAssignments[defenderName] = nil
|
||||
end
|
||||
end
|
||||
|
||||
-- Remove dead defenders in reverse order to maintain indices
|
||||
for i = #deadDefenders, 1, -1 do
|
||||
table.remove(garrison.defenders, deadDefenders[i])
|
||||
end
|
||||
|
||||
-- Clean up lastPatrolTime for dead defenders
|
||||
if garrison.lastPatrolTime then
|
||||
for defenderName, _ in pairs(garrison.lastPatrolTime) do
|
||||
local group = GROUP:FindByName(defenderName)
|
||||
if not group or not group:IsAlive() then
|
||||
garrison.lastPatrolTime[defenderName] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Force Lua garbage collection to reclaim memory
|
||||
collectgarbage("collect")
|
||||
|
||||
if cleanedGroups > 0 or cleanedCooldowns > 0 or cleanedGarrisons > 0 then
|
||||
env.info(string.format("[DGB PLUGIN] Cleanup: Removed %d groups, %d cooldowns, %d garrisons",
|
||||
cleanedGroups, cleanedCooldowns, cleanedGarrisons))
|
||||
end
|
||||
end
|
||||
|
||||
-- Optional periodic memory usage logging (Lua-only; shows in dcs.log)
|
||||
local ENABLE_MEMORY_LOGGING = true
|
||||
local MEMORY_LOG_INTERVAL = 900 -- seconds (15 minutes)
|
||||
local CLEANUP_INTERVAL = 600 -- seconds (10 minutes)
|
||||
|
||||
local function LogMemoryUsage()
|
||||
local luaMemoryKB = collectgarbage("count")
|
||||
local luaMemoryMB = luaMemoryKB / 1024
|
||||
|
||||
local totalSpawnedGroups = 0
|
||||
for _ in pairs(spawnedGroups) do
|
||||
totalSpawnedGroups = totalSpawnedGroups + 1
|
||||
end
|
||||
|
||||
local totalCooldowns = 0
|
||||
for _ in pairs(groupAttackCooldown) do
|
||||
totalCooldowns = totalCooldowns + 1
|
||||
end
|
||||
|
||||
local totalGarrisons = 0
|
||||
local totalDefenders = 0
|
||||
for _, garrison in pairs(zoneGarrisons) do
|
||||
totalGarrisons = totalGarrisons + 1
|
||||
totalDefenders = totalDefenders + #garrison.defenders
|
||||
end
|
||||
|
||||
local msg = string.format("[DGB PLUGIN] Memory: Lua=%.1f MB, Groups=%d, Cooldowns=%d, Garrisons=%d, Defenders=%d",
|
||||
luaMemoryMB, totalSpawnedGroups, totalCooldowns, totalGarrisons, totalDefenders)
|
||||
env.info(msg)
|
||||
end
|
||||
|
||||
if ENABLE_MEMORY_LOGGING then
|
||||
SCHEDULER:New(nil, LogMemoryUsage, {}, 60, MEMORY_LOG_INTERVAL)
|
||||
end
|
||||
|
||||
-- Schedule periodic cleanup
|
||||
SCHEDULER:New(nil, CleanupStaleData, {}, 120, CLEANUP_INTERVAL)
|
||||
|
||||
-- Schedule task assignments (runs quickly at start, then every ASSIGN_TASKS_SCHED seconds)
|
||||
SCHEDULER:New(nil, AssignTasksToGroups, {}, 15, ASSIGN_TASKS_SCHED)
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user