mirror of
https://github.com/Refactorio/RedMew.git
synced 2024-12-04 09:42:30 +02:00
Change biter corpse remover.
The biter corpse remover was attempting to be clever about removing corpses and only remove them when they exceeded a certain threshold per chunk. For some reason it is no longer working and I can't figure out why. So I replaced it with a simpler approach. Now we keep track of the corpses in a queue. When the queue size exceeds the threshold we remove and destroy the oldest corpse.
This commit is contained in:
parent
cb2b142e42
commit
21ec6fb120
@ -402,8 +402,7 @@ global.config = {
|
||||
-- when biter corpses in an area are above a threshold, remove the desired amount
|
||||
biter_corpse_remover = {
|
||||
enabled = true,
|
||||
chunk_size = 3, -- size of chunk in tiles
|
||||
corpse_threshold = 3 -- number of corpses allowed on surface inside chunk
|
||||
max_queue_size = 200 -- The number of corpses to keep in the queue before removing the oldest.
|
||||
},
|
||||
turret_active_delay = {
|
||||
enabled = true,
|
||||
|
@ -1,117 +1,42 @@
|
||||
-- dependencies
|
||||
local Event = require 'utils.event'
|
||||
local Global = require 'utils.global'
|
||||
local table = require 'utils.table'
|
||||
local remove = table.remove
|
||||
local pairs = pairs
|
||||
local next = next
|
||||
local Queue = require 'utils.queue'
|
||||
|
||||
local biter_utils_conf = global.config.biter_corpse_remover
|
||||
local queue_push = Queue.push
|
||||
local queue_pop = Queue.pop
|
||||
local queue_size = Queue.size
|
||||
|
||||
-- Factorio removes corpses that hit 15 minutes anyway
|
||||
local max_corpse_age = 15 * 60 * 60
|
||||
local kills_per_cleanup = 500
|
||||
-- config table for the max queue size
|
||||
-- Change at runtime with /sc global.config.biter_corpse_remover.max_queue_size = 100
|
||||
local biter_corpse_remover = global.config.biter_corpse_remover
|
||||
|
||||
-- x -> y -> array of {entity, tick}
|
||||
local corpse_chunks = {}
|
||||
local cleanup_count = {kills_per_cleanup}
|
||||
local corpse_queue = Queue.new()
|
||||
|
||||
Global.register(
|
||||
{
|
||||
corpse_chunks = corpse_chunks,
|
||||
cleanup_count = cleanup_count
|
||||
},
|
||||
function(tbl)
|
||||
corpse_chunks = tbl.corpse_chunks
|
||||
cleanup_count = tbl.cleanup_count
|
||||
Global.register(corpse_queue, function(tbl)
|
||||
corpse_queue = tbl
|
||||
end)
|
||||
|
||||
local function entity_died(event)
|
||||
if not event.unit_number then
|
||||
return
|
||||
end
|
||||
)
|
||||
|
||||
-- cleans up the stored list of corpses and chunks
|
||||
local function remove_outdated_corpses(now)
|
||||
-- loop each stored chunk
|
||||
for x, column in pairs(corpse_chunks) do
|
||||
for y, corpses in pairs(column) do
|
||||
local count = #corpses
|
||||
|
||||
for i = count, 1, -1 do
|
||||
if corpses[i].tick < now then
|
||||
remove(corpses, i)
|
||||
count = count - 1
|
||||
end
|
||||
end
|
||||
|
||||
if count == 0 then
|
||||
column[y] = nil
|
||||
end
|
||||
local corpses = event.corpses
|
||||
for i = 1, #corpses do
|
||||
local corpse = corpses[i]
|
||||
if corpse.valid then
|
||||
queue_push(corpse_queue, corpse)
|
||||
end
|
||||
end
|
||||
|
||||
if next(column) == nil then
|
||||
corpse_chunks[x] = nil
|
||||
local to_remove = queue_size(corpse_queue) - biter_corpse_remover.max_queue_size
|
||||
for _ = 1, to_remove do
|
||||
local corpse = queue_pop(corpse_queue)
|
||||
if corpse.valid then
|
||||
corpse.destroy()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function biter_died(event)
|
||||
local prot = event.prototype
|
||||
|
||||
-- Only trigger on dead units
|
||||
if prot.type ~= 'unit' then
|
||||
return
|
||||
end
|
||||
|
||||
local entity = event.corpses[1]
|
||||
-- Ensure there is actually a corpse
|
||||
if entity == nil then
|
||||
return
|
||||
end
|
||||
|
||||
local tick = event.tick
|
||||
|
||||
-- Chance to clean up old corpses and chunks
|
||||
local cuc = cleanup_count[1] - 1
|
||||
if cuc <= 0 then
|
||||
remove_outdated_corpses(tick)
|
||||
cleanup_count[1] = kills_per_cleanup
|
||||
else
|
||||
cleanup_count[1] = cuc
|
||||
end
|
||||
|
||||
--Calculate the chunk position
|
||||
local chunk_size = biter_utils_conf.chunk_size
|
||||
local pos = entity.position
|
||||
local x, y = pos.x, pos.y
|
||||
x = x - (x % chunk_size)
|
||||
y = y - (y % chunk_size)
|
||||
|
||||
-- check global table has this position, add if not
|
||||
local corpse_chunks_column = corpse_chunks[x]
|
||||
if corpse_chunks_column == nil then
|
||||
corpse_chunks_column = {}
|
||||
corpse_chunks[x] = corpse_chunks_column
|
||||
end
|
||||
|
||||
local corpses = corpse_chunks_column[y]
|
||||
if corpses == nil then
|
||||
corpses = {}
|
||||
corpse_chunks_column[y] = corpses
|
||||
end
|
||||
|
||||
-- Add this entity
|
||||
local count = #corpses + 1
|
||||
corpses[count] = {
|
||||
entity = entity,
|
||||
tick = tick + max_corpse_age
|
||||
}
|
||||
|
||||
-- Cleanup old corpse if above threshold
|
||||
if count > biter_utils_conf.corpse_threshold then
|
||||
local old_entity = remove(corpses, 1).entity
|
||||
|
||||
if old_entity.valid then
|
||||
old_entity.destroy()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Event.add(defines.events.on_post_entity_died, biter_died)
|
||||
Event.add(defines.events.on_post_entity_died, entity_died)
|
||||
|
Loading…
Reference in New Issue
Block a user