238 lines
6.2 KiB
Lua

if (chunkProcessorG) then
return chunkProcessorG
end
local chunkProcessor = {}
-- imports
local chunkUtils = require("ChunkUtils")
local mathUtils = require("MathUtils")
local constants = require("Constants")
local baseUtils = require("BaseUtils")
-- constants
local CHUNK_SIZE = constants.CHUNK_SIZE
local MAX_TICKS_BEFORE_SORT_CHUNKS = constants.MAX_TICKS_BEFORE_SORT_CHUNKS
-- imported functions
local mapScanEnemyChunk = chunkUtils.mapScanEnemyChunk
local mapScanPlayerChunk = chunkUtils.mapScanPlayerChunk
local mapScanResourceChunk = chunkUtils.mapScanResourceChunk
local createChunk = chunkUtils.createChunk
local initialScan = chunkUtils.initialScan
local chunkPassScan = chunkUtils.chunkPassScan
local euclideanDistanceNamed = mathUtils.euclideanDistanceNamed
local changeEntityAndUpdateDynamicRates = baseUtils.changeEntityAndUpdateDynamicRates
local getDynamicRates = baseUtils.getDynamicRates
local tSort = table.sort
local abs = math.abs
local next = next
local table_size = table_size
local tRemove = table.remove
-- module code
local origin = {x=0,y=0}
local function sorter(a, b)
local aDistance = euclideanDistanceNamed(a, origin)
local bDistance = euclideanDistanceNamed(b, origin)
if (aDistance == bDistance) then
if (a.x == b.x) then
return (abs(a.y) < abs(b.y))
else
return (abs(a.x) < abs(b.x))
end
end
return (aDistance < bDistance)
end
function chunkProcessor.processPendingChunks(universe, tick, flush)
local pendingChunks = universe.pendingChunks
local area = universe.area
local topOffset = area[1]
local bottomOffset = area[2]
local endCount = 2
local chunkCount = 0
-- if flush then
-- endCount = table_size(pendingChunks)
-- end
for event, _ in pairs(pendingChunks) do
local map = event.surface.valid and universe.maps[event.surface.index]
if map then
chunkCount = chunkCount + 1
local topLeft = event.area.left_top
local x = topLeft.x
local y = topLeft.y
topOffset[1] = x
topOffset[2] = y
bottomOffset[1] = x + CHUNK_SIZE
bottomOffset[2] = y + CHUNK_SIZE
if map[x] and map[x][y] then
local chunk = map[x][y]
mapScanPlayerChunk(chunk, map)
mapScanEnemyChunk(chunk, map)
mapScanResourceChunk(chunk, map)
else
if map[x] == nil then
map[x] = {}
end
local chunk = createChunk(x, y)
chunk = initialScan(chunk, map, tick)
if (chunk ~= -1) then
map[x][y] = chunk
local processQueue = map.processQueue
processQueue[#processQueue+1] = chunk
end
end
end
pendingChunks[event] = nil
if (not flush) and (chunkCount >= endCount) then
break
end
end
-- if (#processQueue > map.nextChunkSort) or
-- (((tick - map.nextChunkSortTick) > MAX_TICKS_BEFORE_SORT_CHUNKS) and
-- ((map.nextChunkSort - 150) < #processQueue))
-- then
-- map.nextChunkSort = #processQueue + 150
-- map.nextChunkSortTick = tick
-- tSort(processQueue, sorter)
-- end
end
function chunkProcessor.processScanChunks(universe)
local area = universe.area
local topOffset = area[1]
local bottomOffset = area[2]
--local removals = map.chunkRemovals
local endCount = 2
local chunkCount = 0
local chunkToPassScan = universe.chunkToPassScan
for chunkIndex, chunkData in pairs(chunkToPassScan) do
local x = chunkData[1]
local y = chunkData[2]
local map = universe.maps[chunkData[3]]
if map then
topOffset[1] = x
topOffset[2] = y
bottomOffset[1] = x + CHUNK_SIZE
bottomOffset[2] = y + CHUNK_SIZE
local preScanChunk = map[x] and map[x][y]
if not preScanChunk or (chunkPassScan(preScanChunk, map) == -1) then
map[x][y] = nil
-- removals[chunkCount] = preScanChunk
end
chunkCount = chunkCount + 1
chunkToPassScan[chunkIndex] = nil
if chunkCount >= endCount then
break
end
else
chunkToPassScan[chunkIndex] = nil
end
end
-- if (chunkCount > 0) then
-- local processQueue = map.processQueue
-- for i=#processQueue,1,-1 do
-- for ri=chunkCount,1,-1 do
-- if (removals[ri] == processQueue[i]) then
-- tRemove(processQueue, i)
-- -- tRemove(removals, ri)
-- break
-- end
-- end
-- end
-- end
end
function chunkProcessor.processPendingMutations(universe)
local pendingChunks = universe.pendingMutations["chunks"]
local pendingEntities = universe.pendingMutations["entities"]
local entityId = universe.pendingMutationsIterator
local entityData
if not entityId then
entityId, entityData = next(pendingEntities, nil)
else
entityData = pendingEntities[entityId]
end
if not entityId then
universe.pendingMutationsIterator = nil
return
end
local dynamicRates
local base
local map
local processedCnt = 0
local mutatesCnt = 0
local maxMutations = 1
while entityId and (maxMutations > mutatesCnt) and (processedCnt < 100) do
local entityValid
local chunkIndex = entityData.chunkIndex
map = universe.maps[entityData.surfaceIndex]
entityValid = entityData.entity.valid and entityData.base and map
if entityValid then
if not base or (base ~= entityData.base) then
base = entityData.base
dynamicRates = getDynamicRates(base)
end
newBuilding = changeEntityAndUpdateDynamicRates(entityData.entity, dynamicRates, map, base)
if newBuilding then
mutatesCnt = mutatesCnt + 1
end
end
processedCnt = processedCnt + 1
pendingEntities[entityId] = nil
pendingChunks[chunkIndex] = pendingChunks[chunkIndex] - 1
entityId, entityData = next(pendingEntities, entityId)
end
local pendingEntities_left = table_size(pendingEntities)
if pendingEntities_left == 0 then
universe.pendingMutationsIterator = nil
universe.pendingMutations = {
["chunks"] = {},
["entities"] = {}
}
else
universe.pendingMutationsIterator = entityId
end
end
chunkProcessorG = chunkProcessor
return chunkProcessor