-- Copyright (C) 2022 veden -- This program is free software: you can redistribute it and/or modify -- it under the terms of the GNU General Public License as published by -- the Free Software Foundation, either version 3 of the License, or -- (at your option) any later version. -- This program is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU General Public License for more details. -- You should have received a copy of the GNU General Public License -- along with this program. If not, see . if mapUtilsG then return mapUtilsG end local mapUtils = {} -- imports local constants = require("Constants") local chunkPropertyUtils = require("ChunkPropertyUtils") -- constants local CHUNK_NORTH_SOUTH = constants.CHUNK_NORTH_SOUTH local CHUNK_EAST_WEST = constants.CHUNK_EAST_WEST local CHUNK_IMPASSABLE = constants.CHUNK_IMPASSABLE local CHUNK_ALL_DIRECTIONS = constants.CHUNK_ALL_DIRECTIONS local CHUNK_SIZE = constants.CHUNK_SIZE local CHUNK_SIZE_DIVIDER = constants.CHUNK_SIZE_DIVIDER -- imported functions local mFloor = math.floor local getPassable = chunkPropertyUtils.getPassable local tRemove = table.remove local mCeil = math.ceil -- module code function mapUtils.getChunkByXY(map, x, y) local chunkX = map[x] if chunkX then return chunkX[y] or -1 end return -1 end function mapUtils.getChunkByPosition(map, position) local chunkX = map[mFloor(position.x * CHUNK_SIZE_DIVIDER) * CHUNK_SIZE] if chunkX then local chunkY = mFloor(position.y * CHUNK_SIZE_DIVIDER) * CHUNK_SIZE return chunkX[chunkY] or -1 end return -1 end function mapUtils.getChunkById(map, chunkId) return map.universe.chunkIdToChunk[chunkId] or -1 end function mapUtils.positionToChunkXY(position) local chunkX = mFloor(position.x * CHUNK_SIZE_DIVIDER) * CHUNK_SIZE local chunkY = mFloor(position.y * CHUNK_SIZE_DIVIDER) * CHUNK_SIZE return chunkX, chunkY end function mapUtils.queueGeneratedChunk(universe, event) local map = universe.maps[event.surface.index] if not map then return end event.tick = (event.tick or game.tick) + 20 event.id = universe.eventId event.map = map universe.pendingChunks[event.id] = event universe.eventId = universe.eventId + 1 end function mapUtils.nextMap(universe) local mapIterator = universe.mapIterator repeat local map universe.mapIterator, map = next(universe.maps, universe.mapIterator) if map and map.activeSurface then return map end until mapIterator == universe.mapIterator end function mapUtils.removeChunkToNest(universe, chunkId) universe.chunkToNests[chunkId] = nil if (chunkId == universe.processNestIterator) then universe.processNestIterator = nil end if (chunkId == universe.processMigrationIterator) then universe.processMigrationIterator = nil end end function mapUtils.findInsertionPoint(processQueue, chunk) local low = 1 local high = #processQueue local pivot while (low <= high) do pivot = mCeil((low + high) * 0.5) local pivotChunk = processQueue[pivot] if (pivotChunk.dOrigin > chunk.dOrigin) then high = pivot - 1 elseif (pivotChunk.dOrigin <= chunk.dOrigin) then low = pivot + 1 end end return low end function mapUtils.removeProcessQueueChunk(processQueue, chunk) local insertionPoint = mapUtils.findInsertionPoint(processQueue, chunk) if insertionPoint > #processQueue then insertionPoint = insertionPoint - 1 end for i=insertionPoint,1,-1 do local pqChunk = processQueue[i] if pqChunk.id == chunk.id then tRemove(processQueue, i) return elseif pqChunk.dOrigin < chunk.dOrigin then return end end end function mapUtils.removeChunkFromMap(map, chunk) local chunkId = chunk.id local x = chunk.x local y = chunk.y mapUtils.removeProcessQueueChunk(map.processQueue, chunk) local universe = map.universe map[x][y] = nil universe.chunkIdToChunk[chunkId] = nil universe.chunkToActiveNest[chunkId] = nil universe.chunkToActiveRaidNest[chunkId] = nil universe.chunkToDrained[chunkId] = nil universe.chunkToRetreats[chunkId] = nil universe.chunkToRallys[chunkId] = nil universe.chunkToPassScan[chunkId] = nil universe.chunkToNests[chunkId] = nil universe.vengenceQueue[chunkId] = nil universe.processActiveNest[chunkId] = nil universe.chunkToVictory[chunkId] = nil local base = map.chunkToBase[chunkId] if base then base.chunkCount = base.chunkCount - 1 map.chunkToBase[chunkId] = nil end map.chunkToTurrets[chunkId] = nil map.chunkToTraps[chunkId] = nil map.chunkToUtilities[chunkId] = nil map.chunkToHives[chunkId] = nil map.chunkToNestIds[chunkId] = nil map.chunkToHiveIds[chunkId] = nil map.chunkToTrapIds[chunkId] = nil map.chunkToTurretIds[chunkId] = nil map.chunkToUtilityIds[chunkId] = nil map.chunkToPlayerBase[chunkId] = nil map.chunkToResource[chunkId] = nil map.chunkToPlayerCount[chunkId] = nil map.chunkToSquad[chunkId] = nil map.chunkToPassable[chunkId] = nil map.chunkToPathRating[chunkId] = nil map.chunkToDeathGenerator[chunkId] = nil if universe.processActiveNestIterator == chunkId then universe.processActiveNestIterator = nil end if universe.victoryScentIterator == chunkId then universe.victoryScentIterator = nil end if universe.processNestIterator == chunkId then universe.processNestIterator = nil end if universe.chunkToDrainedIterator == chunkId then universe.chunkToDrainedIterator = nil end if universe.chunkToRetreatIterator == chunkId then universe.chunkToRetreatIterator = nil end if universe.chunkToRallyIterator == chunkId then universe.chunkToRallyIterator = nil end if universe.chunkToPassScanIterator == chunkId then universe.chunkToPassScanIterator = nil end if universe.processActiveSpawnerIterator == chunkId then universe.processActiveSpawnerIterator = nil end if universe.processActiveRaidSpawnerIterator == chunkId then universe.processActiveRaidSpawnerIterator = nil end if universe.processMigrationIterator == chunkId then universe.processMigrationIterator = nil end if universe.deployVengenceIterator == chunkId then universe.deployVengenceIterator = nil end end --[[ 1 2 3 \|/ 4- -5 /|\ 6 7 8 ]]-- function mapUtils.getNeighborChunks(map, x, y) local neighbors = map.universe.neighbors local chunkYRow1 = y - CHUNK_SIZE local chunkYRow3 = y + CHUNK_SIZE local xChunks = map[x-CHUNK_SIZE] if xChunks then neighbors[1] = xChunks[chunkYRow1] or -1 neighbors[4] = xChunks[y] or -1 neighbors[6] = xChunks[chunkYRow3] or -1 else neighbors[1] = -1 neighbors[4] = -1 neighbors[6] = -1 end xChunks = map[x+CHUNK_SIZE] if xChunks then neighbors[3] = xChunks[chunkYRow1] or -1 neighbors[5] = xChunks[y] or -1 neighbors[8] = xChunks[chunkYRow3] or -1 else neighbors[3] = -1 neighbors[5] = -1 neighbors[8] = -1 end xChunks = map[x] if xChunks then neighbors[2] = xChunks[chunkYRow1] or -1 neighbors[7] = xChunks[chunkYRow3] or -1 else neighbors[2] = -1 neighbors[7] = -1 end return neighbors end --[[ 1 2 3 \|/ 4- -5 /|\ 6 7 8 ]]-- function mapUtils.canMoveChunkDirection(map, direction, startChunk, endChunk) local canMove = false local startPassable = getPassable(map, startChunk) local endPassable = getPassable(map, endChunk) if (startPassable == CHUNK_ALL_DIRECTIONS) then if ((direction == 1) or (direction == 3) or (direction == 6) or (direction == 8)) then canMove = (endPassable == CHUNK_ALL_DIRECTIONS) elseif (direction == 2) or (direction == 7) then canMove = ((endPassable == CHUNK_NORTH_SOUTH) or (endPassable == CHUNK_ALL_DIRECTIONS)) elseif (direction == 4) or (direction == 5) then canMove = ((endPassable == CHUNK_EAST_WEST) or (endPassable == CHUNK_ALL_DIRECTIONS)) end elseif (startPassable == CHUNK_NORTH_SOUTH) then if ((direction == 1) or (direction == 3) or (direction == 6) or (direction == 8)) then canMove = (endPassable == CHUNK_ALL_DIRECTIONS) elseif (direction == 2) or (direction == 7) then canMove = ((endPassable == CHUNK_NORTH_SOUTH) or (endPassable == CHUNK_ALL_DIRECTIONS)) end elseif (startPassable == CHUNK_EAST_WEST) then if ((direction == 1) or (direction == 3) or (direction == 6) or (direction == 8)) then canMove = (endPassable == CHUNK_ALL_DIRECTIONS) elseif (direction == 4) or (direction == 5) then canMove = ((endPassable == CHUNK_EAST_WEST) or (endPassable == CHUNK_ALL_DIRECTIONS)) end else canMove = (endPassable ~= CHUNK_IMPASSABLE) end return canMove end function mapUtils.getCardinalChunks(map, x, y) local neighbors = map.universe.cardinalNeighbors local xChunks = map[x] if xChunks then neighbors[1] = xChunks[y-CHUNK_SIZE] or -1 neighbors[4] = xChunks[y+CHUNK_SIZE] or -1 else neighbors[1] = -1 neighbors[4] = -1 end xChunks = map[x-CHUNK_SIZE] if xChunks then neighbors[2] = xChunks[y] or -1 else neighbors[2] = -1 end xChunks = map[x+CHUNK_SIZE] if xChunks then neighbors[3] = xChunks[y] or -1 else neighbors[3] = -1 end return neighbors end function mapUtils.positionFromDirectionAndChunk(direction, startPosition, scaling) local endPosition = {} if (direction == 1) then endPosition.x = startPosition.x - CHUNK_SIZE * (scaling - 0.1) endPosition.y = startPosition.y - CHUNK_SIZE * (scaling - 0.1) elseif (direction == 2) then endPosition.x = startPosition.x endPosition.y = startPosition.y - CHUNK_SIZE * (scaling + 0.25) elseif (direction == 3) then endPosition.x = startPosition.x + CHUNK_SIZE * (scaling - 0.1) endPosition.y = startPosition.y - CHUNK_SIZE * (scaling - 0.1) elseif (direction == 4) then endPosition.x = startPosition.x - CHUNK_SIZE * (scaling + 0.25) endPosition.y = startPosition.y elseif (direction == 5) then endPosition.x = startPosition.x + CHUNK_SIZE * (scaling + 0.25) endPosition.y = startPosition.y elseif (direction == 6) then endPosition.x = startPosition.x - CHUNK_SIZE * (scaling - 0.1) endPosition.y = startPosition.y + CHUNK_SIZE * (scaling - 0.1) elseif (direction == 7) then endPosition.x = startPosition.x endPosition.y = startPosition.y + CHUNK_SIZE * (scaling + 0.25) elseif (direction == 8) then endPosition.x = startPosition.x + CHUNK_SIZE * (scaling - 0.1) endPosition.y = startPosition.y + CHUNK_SIZE * (scaling - 0.1) end return endPosition end function mapUtils.positionFromDirectionAndFlat(direction, startPosition, multipler) local lx = startPosition.x local ly = startPosition.y if not multipler then multipler = 1 end if (direction == 1) then lx = lx - CHUNK_SIZE * multipler ly = ly - CHUNK_SIZE * multipler elseif (direction == 2) then ly = ly - CHUNK_SIZE * multipler elseif (direction == 3) then lx = lx + CHUNK_SIZE * multipler ly = ly - CHUNK_SIZE * multipler elseif (direction == 4) then lx = lx - CHUNK_SIZE * multipler elseif (direction == 5) then lx = lx + CHUNK_SIZE * multipler elseif (direction == 6) then lx = lx - CHUNK_SIZE * multipler ly = ly + CHUNK_SIZE * multipler elseif (direction == 7) then ly = ly + CHUNK_SIZE * multipler elseif (direction == 8) then lx = lx + CHUNK_SIZE * multipler ly = ly + CHUNK_SIZE * multipler end return { x = lx, y = ly } end mapUtilsG = mapUtils return mapUtils