1
0
mirror of https://github.com/Refactorio/RedMew.git synced 2024-12-14 10:13:13 +02:00
RedMew/features/biter_corpse_remover.lua

118 lines
2.9 KiB
Lua
Raw Normal View History

2019-06-10 06:34:13 +02:00
-- dependencies
2019-06-04 21:07:43 +02:00
local Event = require 'utils.event'
2019-06-10 06:34:13 +02:00
local Global = require 'utils.global'
2019-06-10 20:47:43 +02:00
local table = require 'utils.table'
local remove = table.remove
2019-06-13 23:25:42 +02:00
local pairs = pairs
local next = next
2019-06-04 21:07:43 +02:00
local biter_utils_conf = global.config.biter_corpse_remover
2019-06-04 21:07:43 +02:00
2019-06-10 06:34:13 +02:00
-- Factorio removes corpses that hit 15 minutes anyway
local max_corpse_age = 15 * 60 * 60
2019-06-13 23:25:42 +02:00
local kills_per_cleanup = 500
-- x -> y -> array of {entity, tick}
local corpse_chunks = {}
local cleanup_count = {kills_per_cleanup}
2019-06-04 21:07:43 +02:00
2019-06-10 06:34:13 +02:00
Global.register(
{
2019-06-13 23:25:42 +02:00
corpse_chunks = corpse_chunks,
cleanup_count = cleanup_count
2019-06-10 06:34:13 +02:00
},
function(tbl)
corpse_chunks = tbl.corpse_chunks
2019-06-13 23:25:42 +02:00
cleanup_count = tbl.cleanup_count
2019-06-04 22:25:34 +02:00
end
2019-06-10 06:34:13 +02:00
)
2019-06-04 22:25:34 +02:00
2019-06-10 06:34:13 +02:00
-- cleans up the stored list of corpses and chunks
2019-06-12 19:24:00 +02:00
local function remove_outdated_corpses(now)
2019-06-10 06:34:13 +02:00
-- loop each stored chunk
2019-06-13 23:25:42 +02:00
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)
2019-06-13 23:25:42 +02:00
count = count - 1
end
2019-06-10 06:34:13 +02:00
end
2019-06-13 23:25:42 +02:00
if count == 0 then
column[y] = nil
end
2019-06-10 06:34:13 +02:00
end
if next(column) == nil then
2019-06-13 23:25:42 +02:00
corpse_chunks[x] = nil
2019-06-10 06:34:13 +02:00
end
end
2019-06-10 06:34:13 +02:00
end
local function biter_died(event)
local prot = event.prototype
-- Only trigger on dead units
if prot.type ~= 'unit' then
2019-06-04 22:25:34 +02:00
return
end
2019-06-10 06:34:13 +02:00
local entity = event.corpses[1]
-- Ensure there is actually a corpse
if entity == nil then
2019-06-04 23:28:08 +02:00
return
end
2019-06-12 19:24:00 +02:00
local tick = event.tick
2019-06-10 06:34:13 +02:00
-- Chance to clean up old corpses and chunks
2019-06-13 23:25:42 +02:00
local cuc = cleanup_count[1] - 1
if cuc <= 0 then
2019-06-12 19:24:00 +02:00
remove_outdated_corpses(tick)
2019-06-13 23:25:42 +02:00
cleanup_count[1] = kills_per_cleanup
else
cleanup_count[1] = cuc
2019-06-10 06:34:13 +02:00
end
2019-06-04 22:25:34 +02:00
2019-06-13 23:25:42 +02:00
--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)
2019-06-04 22:50:09 +02:00
2019-06-10 06:34:13 +02:00
-- check global table has this position, add if not
2019-06-13 23:25:42 +02:00
local corpse_chunks_column = corpse_chunks[x]
if corpse_chunks_column == nil then
corpse_chunks_column = {}
corpse_chunks[x] = corpse_chunks_column
2019-06-04 22:25:34 +02:00
end
2019-06-13 23:25:42 +02:00
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] = {
2019-06-10 06:34:13 +02:00
entity = entity,
2019-06-12 19:24:00 +02:00
tick = tick + max_corpse_age
2019-06-10 06:34:13 +02:00
}
2019-06-04 22:25:34 +02:00
2019-06-13 23:25:42 +02:00
-- Cleanup old corpse if above threshold
if count > biter_utils_conf.corpse_threshold then
local old_entity = remove(corpses, 1).entity
2019-06-13 23:25:42 +02:00
if old_entity.valid then
old_entity.destroy()
end
2019-06-04 21:07:43 +02:00
end
end
2019-06-10 06:34:13 +02:00
Event.add(defines.events.on_post_entity_died, biter_died)