refresh metatable in global
This commit is contained in:
parent
610199494e
commit
e4c1a3ed9d
|
@ -17,7 +17,7 @@ local function sign(x)
|
||||||
return x / math.abs(x)
|
return x / math.abs(x)
|
||||||
end
|
end
|
||||||
|
|
||||||
function positionToChunk(position)
|
local function positionToChunk(position)
|
||||||
return { x = math.floor(position.x / 32), y = math.floor(position.y / 32) }
|
return { x = math.floor(position.x / 32), y = math.floor(position.y / 32) }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ function movePollution(surface, chunkFrom, chunkTo, amount)
|
||||||
end
|
end
|
||||||
|
|
||||||
function getBasePurificationRate(entity)
|
function getBasePurificationRate(entity)
|
||||||
-- Depends mostly on recipe. Should be multiplied by crafting speed to achieve actual max purification rate
|
-- Depends mostly on recipe (optimal recipe used per machine). Should be multiplied by crafting speed to achieve actual max purification rate
|
||||||
if entity.name == "air-filter-machine-1" then
|
if entity.name == "air-filter-machine-1" then
|
||||||
return 4 * INTERVAL / 60 -- 4 max pollution cleaning per second among mk1 recipes
|
return 4 * INTERVAL / 60 -- 4 max pollution cleaning per second among mk1 recipes
|
||||||
elseif entity.name == "air-filter-machine-2" or entity.name == "air-filter-machine-3" then
|
elseif entity.name == "air-filter-machine-2" or entity.name == "air-filter-machine-3" then
|
||||||
|
@ -39,6 +39,15 @@ function getBasePurificationRate(entity)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function energyCraftingModifier(entity)
|
||||||
|
-- Approximation to speed modifier for machine running out of power
|
||||||
|
if entity.electric_buffer_size then
|
||||||
|
return entity.energy / entity.electric_buffer_size
|
||||||
|
else
|
||||||
|
return 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function getSuctionRate(entity)
|
function getSuctionRate(entity)
|
||||||
if not entity.is_crafting() and getSpaceForPollution(entity) == 0 then
|
if not entity.is_crafting() and getSpaceForPollution(entity) == 0 then
|
||||||
return 0
|
return 0
|
||||||
|
@ -51,14 +60,6 @@ function getAbsorptionRate(entity)
|
||||||
return math.min(getSpaceForPollution(entity), getSuctionRate(entity))
|
return math.min(getSpaceForPollution(entity), getSuctionRate(entity))
|
||||||
end
|
end
|
||||||
|
|
||||||
function energyCraftingModifier(entity)
|
|
||||||
-- Approximation to speed modifier for machine running out of power
|
|
||||||
if entity.electric_buffer_size then
|
|
||||||
return entity.energy / entity.electric_buffer_size
|
|
||||||
else
|
|
||||||
return 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function getSpaceForPollution(entity)
|
function getSpaceForPollution(entity)
|
||||||
if #entity.fluidbox < 1 then
|
if #entity.fluidbox < 1 then
|
||||||
|
@ -73,7 +74,7 @@ function getSpaceForPollution(entity)
|
||||||
return capacity - pollution
|
return capacity - pollution
|
||||||
end
|
end
|
||||||
|
|
||||||
function inRadius(filter, radius)
|
local function inRadius(filter, radius)
|
||||||
if filter.name == "air-filter-machine-1" then
|
if filter.name == "air-filter-machine-1" then
|
||||||
return radius <= 0
|
return radius <= 0
|
||||||
elseif filter.name == "air-filter-machine-2" then
|
elseif filter.name == "air-filter-machine-2" then
|
||||||
|
@ -85,12 +86,17 @@ function inRadius(filter, radius)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function manhattan(x, y)
|
||||||
|
-- Manhattan distance from origin to xy.
|
||||||
|
return math.abs(x) + math.abs(y)
|
||||||
|
end
|
||||||
|
|
||||||
-- #####################
|
-- #####################
|
||||||
-- # Update script #
|
-- # Update script #
|
||||||
-- #####################
|
-- #####################
|
||||||
|
|
||||||
function absorbPollution(event)
|
function absorbPollution(event)
|
||||||
game.print("insertPollution")
|
-- game.print("insertPollution")
|
||||||
for _, c in pairs(global.air_filtered_chunks) do
|
for _, c in pairs(global.air_filtered_chunks) do
|
||||||
absorbChunk(c)
|
absorbChunk(c)
|
||||||
end
|
end
|
||||||
|
@ -101,40 +107,52 @@ function absorbChunk(chunk)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local totalAbsorption = 0.0
|
local totalAbsorptionRate = chunk:getTotalAbsorptionRate()
|
||||||
for _, filter in pairs(chunk.filters) do
|
|
||||||
local absorptionRate = getAbsorptionRate(filter)
|
|
||||||
totalAbsorption = totalAbsorption + absorptionRate
|
|
||||||
end
|
|
||||||
|
|
||||||
if totalAbsorption == 0 then
|
-- game.print("totalAbsorptionRate: " .. totalAbsorptionRate)
|
||||||
|
game.print("filter count: " .. #chunk.filters)
|
||||||
|
|
||||||
|
if totalAbsorptionRate == 0 then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local toAbsorb = math.min(chunk:get_pollution() , totalAbsorption)
|
local toAbsorb = math.min(chunk:get_pollution() , totalAbsorptionRate)
|
||||||
-- game.print("To absorb: " .. toAbsorb)
|
game.print("To absorb: " .. toAbsorb)
|
||||||
|
|
||||||
local totalInsertedAmount = 0.0
|
local totalInsertedAmount = 0.0
|
||||||
for _, filter in pairs(chunk.filters) do
|
for _, filter in pairs(chunk.filters) do
|
||||||
local toInsert = (getAbsorptionRate(filter) / totalAbsorption) * toAbsorb
|
local toInsert = (getAbsorptionRate(filter) / totalAbsorptionRate) * toAbsorb
|
||||||
if toInsert > 0 then
|
if toInsert > 0 then
|
||||||
local insertedAmount = filter.insert_fluid({ name = "pollution", amount = toInsert })
|
local insertedAmount = filter.insert_fluid({ name = "pollution", amount = toInsert })
|
||||||
totalInsertedAmount = totalInsertedAmount + insertedAmount
|
totalInsertedAmount = totalInsertedAmount + insertedAmount
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
-- game.print("Total inserted: " .. totalInsertedAmount)
|
game.print("Total inserted: " .. totalInsertedAmount)
|
||||||
assert(math.abs(toAbsorb - totalInsertedAmount) < 0.01, "Error with inserting pollution in air filter machine. Different amounts absorbed/inserted: " .. toAbsorb .. " absorbed and " .. totalInsertedAmount .. " inserted.")
|
assert(math.abs(toAbsorb - totalInsertedAmount) < 0.01, "Error with inserting pollution in air filter machine. Different amounts absorbed/inserted: " .. toAbsorb .. " absorbed and " .. totalInsertedAmount .. " inserted.")
|
||||||
chunk:pollute(-totalInsertedAmount)
|
chunk:pollute(-totalInsertedAmount)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function suctionUpdateChunk(chunkTo, dx, dy)
|
||||||
|
-- local totalSuction = chunkTo:getTotalSuctionRate(manhattan(dx, dy))
|
||||||
|
|
||||||
|
-- if totalSuction == 0 then
|
||||||
|
-- return
|
||||||
|
-- end
|
||||||
|
|
||||||
|
-- game.print("suction: " .. totalSuction)
|
||||||
|
|
||||||
|
|
||||||
|
-- local chunkFrom = getFilteredChunk(chunkTo.surface, chunkTo.x + dx, chunkTo.y + dy)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
local function generateSuctionFunction(dx, dy)
|
local function generateSuctionFunction(dx, dy)
|
||||||
|
|
||||||
local function suctionUpdate(event)
|
local function suctionUpdate(event)
|
||||||
game.print("suck pollution " .. dx .. ", " .. dy)
|
-- game.print("suck pollution " .. dx .. ", " .. dy)
|
||||||
-- for _, chunkTo in pairs(global.air_filtered_chunks) do
|
for _, chunkTo in pairs(global.air_filtered_chunks) do
|
||||||
-- local chunkFrom = getFilteredChunk(chunkTo.surface, chunkTo.x + dx, chunkTo.y + dy)
|
suctionUpdateChunk(chunkTo, dx, dy)
|
||||||
-- end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return suctionUpdate
|
return suctionUpdate
|
||||||
|
@ -173,6 +191,9 @@ end
|
||||||
local function generateFunctions()
|
local function generateFunctions()
|
||||||
local functions = {}
|
local functions = {}
|
||||||
|
|
||||||
|
-- Debug statement
|
||||||
|
-- table.insert(functions, init)
|
||||||
|
|
||||||
table.insert(functions, absorbPollution)
|
table.insert(functions, absorbPollution)
|
||||||
|
|
||||||
for radius = 1, 4 do
|
for radius = 1, 4 do
|
||||||
|
@ -218,80 +239,130 @@ local function spreadOverTicks(functions, interval)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
local function FilteredChunk(surface, x, y)
|
-- #####################
|
||||||
local self = {
|
-- # FilteredChunk #
|
||||||
surface = surface,
|
-- #####################
|
||||||
x = x,
|
|
||||||
y = y,
|
|
||||||
filters = {},
|
|
||||||
}
|
|
||||||
|
|
||||||
local function equal(self, other)
|
--local function FilteredChunk(surface, x, y)
|
||||||
return self.surface.name == other.surface.name and self.x == other.x and self.y == other.y
|
-- local self = {
|
||||||
end
|
-- surface = surface,
|
||||||
|
-- x = x,
|
||||||
|
-- y = y,
|
||||||
|
-- filters = {},
|
||||||
|
-- }
|
||||||
|
--
|
||||||
|
---- self.getTotalSuctionRate = getTotalSuctionRate
|
||||||
|
---- self.getTotalAbsorptionRate = getTotalAbsorptionRate
|
||||||
|
---- self.get_pollution = get_pollution
|
||||||
|
---- self.pollute = pollute
|
||||||
|
---- self.toPosition = toPosition
|
||||||
|
---- self.addFilter = addFilter
|
||||||
|
---- self.removeFilter = removeFilter
|
||||||
|
-- return self
|
||||||
|
--end
|
||||||
|
|
||||||
local function addToMap()
|
local FilteredChunk = {
|
||||||
game.print("Adding chunk to map")
|
surface = nil,
|
||||||
local chunkListX = global.air_filtered_chunks_map[surface.name] or {}
|
x = 0,
|
||||||
local chunkListY = chunkListX[x] or {}
|
y = 0,
|
||||||
assert(chunkListY[y] == nil, "Chunklist entry should not exist yet.")
|
filters = {},
|
||||||
chunkListY[y] = self
|
}
|
||||||
chunkListX[x] = chunkListY
|
|
||||||
global.air_filtered_chunks_map[surface.name] = chunkListX
|
|
||||||
table.insert(global.air_filtered_chunks, self)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function removeFromMap()
|
function FilteredChunk:equal(other)
|
||||||
game.print("Removing chunk from map")
|
return self.surface.name == other.surface.name and self.x == other.x and self.y == other.y
|
||||||
table.remove(global.air_filtered_chunks_map[surface.name][x], y)
|
|
||||||
for i, c in pairs(global.air_filtered_chunks) do
|
|
||||||
if equal(self, c) then
|
|
||||||
table.remove(global.air_filtered_chunks, i)
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function get_pollution(self)
|
|
||||||
return self.surface.get_pollution(self:toPosition())
|
|
||||||
end
|
|
||||||
|
|
||||||
local function pollute(self, amount)
|
|
||||||
self.surface.pollute(self:toPosition(), amount)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function toPosition(self)
|
|
||||||
return { x = self.x * 32, y = self.y * 32 }
|
|
||||||
end
|
|
||||||
|
|
||||||
local function addFilter(self, filter)
|
|
||||||
table.insert(self.filters, filter)
|
|
||||||
if #self.filters == 1 then
|
|
||||||
addToMap()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function removeFilter(self, filter)
|
|
||||||
for i, f in pairs(self.filters) do
|
|
||||||
if f.unit_number == filter.unit_number then
|
|
||||||
table.remove(self.filters, i)
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if #self.filters == 0 then
|
|
||||||
removeFromMap()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
self.get_pollution = get_pollution
|
|
||||||
self.pollute = pollute
|
|
||||||
self.toPosition = toPosition
|
|
||||||
self.addFilter = addFilter
|
|
||||||
self.removeFilter = removeFilter
|
|
||||||
return self
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local function getFilteredChunk(surface, x, y)
|
function FilteredChunk:addToMap()
|
||||||
|
game.print("Adding chunk to map")
|
||||||
|
local chunkListX = global.air_filtered_chunks_map[self.surface.name] or {}
|
||||||
|
local chunkListY = chunkListX[self.x] or {}
|
||||||
|
assert(chunkListY[y] == nil, "Chunklist entry should not exist yet.")
|
||||||
|
chunkListY[self.y] = self
|
||||||
|
chunkListX[self.x] = chunkListY
|
||||||
|
global.air_filtered_chunks_map[self.surface.name] = chunkListX
|
||||||
|
table.insert(global.air_filtered_chunks, self)
|
||||||
|
end
|
||||||
|
|
||||||
|
function FilteredChunk:removeFromMap()
|
||||||
|
game.print("Removing chunk from map")
|
||||||
|
table.remove(global.air_filtered_chunks_map[self.surface.name][self.x], self.y)
|
||||||
|
for i, c in pairs(global.air_filtered_chunks) do
|
||||||
|
if self:equal(c) then
|
||||||
|
table.remove(global.air_filtered_chunks, i)
|
||||||
|
game.print("Removing chunk from list")
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function FilteredChunk:getTotalAbsorptionRate()
|
||||||
|
local totalAbsorptionRate = 0.0
|
||||||
|
for _, filter in pairs(self.filters) do
|
||||||
|
local absorptionRate = getAbsorptionRate(filter)
|
||||||
|
totalAbsorptionRate = totalAbsorptionRate + absorptionRate
|
||||||
|
end
|
||||||
|
return totalAbsorptionRate
|
||||||
|
end
|
||||||
|
|
||||||
|
function FilteredChunk:getTotalSuctionRate(distance)
|
||||||
|
local totalSuctionRate = 0.0
|
||||||
|
for _, filter in pairs(self.filters) do
|
||||||
|
if inRadius(filter, distance) then
|
||||||
|
local suctionRate = getSuctionRate(filter)
|
||||||
|
totalSuctionRate = totalSuctionRate + suctionRate
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return totalSuctionRate
|
||||||
|
end
|
||||||
|
|
||||||
|
function FilteredChunk:get_pollution()
|
||||||
|
return self.surface.get_pollution(self:toPosition())
|
||||||
|
end
|
||||||
|
|
||||||
|
function FilteredChunk:pollute(amount)
|
||||||
|
self.surface.pollute(self:toPosition(), amount)
|
||||||
|
end
|
||||||
|
|
||||||
|
function FilteredChunk:toPosition()
|
||||||
|
return { x = self.x * 32, y = self.y * 32 }
|
||||||
|
end
|
||||||
|
|
||||||
|
function FilteredChunk:addFilter(filter)
|
||||||
|
table.insert(self.filters, filter)
|
||||||
|
if #self.filters == 1 then
|
||||||
|
self:addToMap()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function FilteredChunk:removeFilter(filter)
|
||||||
|
for i, f in pairs(self.filters) do
|
||||||
|
if f.unit_number == filter.unit_number then
|
||||||
|
table.remove(self.filters, i)
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if #self.filters == 0 then
|
||||||
|
self:removeFromMap()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function FilteredChunk:new (o)
|
||||||
|
o = o or {}
|
||||||
|
setmetatable(o, self)
|
||||||
|
self.__index = self
|
||||||
|
return o
|
||||||
|
end
|
||||||
|
|
||||||
|
function createFilteredChunk(surface, x, y)
|
||||||
|
local chunk = FilteredChunk:new(nil)
|
||||||
|
chunk.surface = surface
|
||||||
|
chunk.x = x
|
||||||
|
chunk.y = y
|
||||||
|
chunk.filters = {} -- this statement, though it appears to have no effect, has a large impact on the saving of global state.
|
||||||
|
return chunk
|
||||||
|
end
|
||||||
|
|
||||||
|
function getFilteredChunk(surface, x, y)
|
||||||
local chunkListX = global.air_filtered_chunks_map[surface.name]
|
local chunkListX = global.air_filtered_chunks_map[surface.name]
|
||||||
if chunkListX ~= nil then
|
if chunkListX ~= nil then
|
||||||
local chunkListY = chunkListX[x]
|
local chunkListY = chunkListX[x]
|
||||||
|
@ -302,7 +373,7 @@ local function getFilteredChunk(surface, x, y)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return FilteredChunk(surface, x, y)
|
return createFilteredChunk(surface, x, y)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@ -316,14 +387,10 @@ function isAirFilterMachine(entity)
|
||||||
end
|
end
|
||||||
|
|
||||||
function OnEntityCreated(event)
|
function OnEntityCreated(event)
|
||||||
game.print("entity created")
|
|
||||||
game.print(event.created_entity.name)
|
|
||||||
if isAirFilterMachine(event.created_entity) then
|
if isAirFilterMachine(event.created_entity) then
|
||||||
game.print("air filter created")
|
|
||||||
local chunkPos = positionToChunk(event.created_entity.position)
|
local chunkPos = positionToChunk(event.created_entity.position)
|
||||||
local chunk = getFilteredChunk(event.created_entity.surface, chunkPos.x, chunkPos.y)
|
local chunk = getFilteredChunk(event.created_entity.surface, chunkPos.x, chunkPos.y)
|
||||||
chunk:addFilter(event.created_entity)
|
chunk:addFilter(event.created_entity)
|
||||||
game.print("Air filter added to chunk")
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -339,6 +406,12 @@ script.on_event({ defines.events.on_built_entity, defines.events.on_robot_built_
|
||||||
script.on_event({ defines.events.on_pre_player_mined_item, defines.events.on_robot_pre_mined, defines.events.on_entity_died }, OnEntityRemoved)
|
script.on_event({ defines.events.on_pre_player_mined_item, defines.events.on_robot_pre_mined, defines.events.on_entity_died }, OnEntityRemoved)
|
||||||
|
|
||||||
|
|
||||||
|
function refreshMetatables()
|
||||||
|
for i, chunk in pairs(global.air_filtered_chunks) do
|
||||||
|
FilteredChunk:new(chunk) -- reset metatable
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function init()
|
function init()
|
||||||
game.print("Init")
|
game.print("Init")
|
||||||
-- gather all filters on every surface
|
-- gather all filters on every surface
|
||||||
|
@ -362,6 +435,8 @@ script.on_init(init)
|
||||||
script.on_configuration_changed(init)
|
script.on_configuration_changed(init)
|
||||||
|
|
||||||
script.on_load(function()
|
script.on_load(function()
|
||||||
|
refreshMetatables()
|
||||||
|
|
||||||
local functions = generateFunctions()
|
local functions = generateFunctions()
|
||||||
local onTick = spreadOverTicks(functions, INTERVAL)
|
local onTick = spreadOverTicks(functions, INTERVAL)
|
||||||
|
|
||||||
|
|
Reference in New Issue