[1.1.53] Map generation + chunk copying does not work correctly
Posted: Sat Feb 05, 2022 7:32 am
I am trying to create a surface "void" where chunks are generated. I then copy chunks from there onto the surface "battleground". The chunks are copied only from the bottom right quadrant (+x +y coordinates), with tiles being created by just multiplying the x and y values, which is much easier than performing any form of rotations etc. The issue is that a form of "lines" are created on battleground (the lines along the x and y axis are intended, please ignore those), where lab tiles are present, even though they should not be - see the attachment for an example. This must be an issue with map generation and the chunks being copied before Factorio generates the chunks itself, as there is no other rational explanation for this in my opinion.
If you run the code, you will need to teleport to battleground with /c game.player.teleport(game.player.position, "battleground"). Then you will need to generate chunks with /c local radius=400 game.player.force.chart(game.player.surface, {{x = -radius, y = -radius}, {x = radius, y = radius}}).
If you run the code, you will need to teleport to battleground with /c game.player.teleport(game.player.position, "battleground"). Then you will need to generate chunks with /c local radius=400 game.player.force.chart(game.player.surface, {{x = -radius, y = -radius}, {x = radius, y = radius}}).
Code: Select all
script.on_init(function ()
game.create_surface("void") -- origin surface of tiles + entities
game.map_settings.pollution.enabled = false
local battleground = game.create_surface("battleground")
battleground.always_day = true
battleground.generate_with_lab_tiles = true
log("init done")
end)
---@param event EventData|on_player_created
script.on_event(defines.events.on_player_created, function (event)
local player = game.get_player(event.player_index)
local surface = game.get_surface("battleground")
local position = surface.find_non_colliding_position_in_box("character", {{-2, -2}, {2, 2}}, 0.5, false)
player.teleport(position or {0, 0}, "battleground")
end)
---Copy tiles across a surface. Copies tiles from the bottom right quadrant on originSurface
---@param originSurface LuaSurface
---@param targetSurface LuaSurface
---@param chunkPos ChunkPosition The position on the target surface that is meant to be copied to
---@param absPos ChunkPosition|nil Absolute position of the chunk - use {x=math.abs(x), y=math.abs(y)} to get this
local function copy_tiles(originSurface, targetSurface, chunkPos, absPos)
if originSurface.name ~= "void" then log(originSurface.name) end
local tiles = originSurface.find_tiles_filtered({
area = {
-- get the tile data from only one quadrant, positive positive (right bottom in factorio)
left_top = {x = absPos.x * 32, y = absPos.y * 32},
right_bottom = {x = (absPos.x + 1) * 32, y = (absPos.y + 1) * 32}
}
})
-- multiplier for x and y values where tiles are to be set
-- if they are less than 0 then they are flipped
local yMultiplier = chunkPos.y >= 0 and 1 or -1
local xMultiplier = chunkPos.x >= 0 and 1 or -1
local toSetTiles = {}
for _, tile in pairs(tiles) do
table.insert(toSetTiles, {name = tile.name, position = {x = tile.position.x * xMultiplier, y = tile.position.y * yMultiplier}})
end
-- log(tostring(yMultiplier) .. " " .. tostring(xMultiplier) .. " " .. serpent.line(chunkPos) .. serpent.line(absPos))
if #toSetTiles == 0 then log("chunk not getting tiles set") end
targetSurface.set_tiles(toSetTiles)
end
-- Handle chunks generateing
---@param event EventData|on_chunk_generated
script.on_event(defines.events.on_chunk_generated, function (event)
local surface = event.surface
local chunkPos = event.position
-- we are not intersted in other surfaces
if surface.name ~= "battleground" then return end
-- this is so that the line in the middle is symetrical, it's intended to be a gap that is then filled with other stuff
local tbl = { -- hashmap
[0] = true
}
if tbl[chunkPos.x] or tbl[chunkPos.y] then return end -- there should be the river here
-- FIXME: if the chunk is not generatd on_init then it doesnt work???
-- if the chunk is generated on battleground, we want to copy the chunk from void
local absPos = {x = math.abs(chunkPos.x), y = math.abs(chunkPos.y)}
local void = game.get_surface("void")
local alreadyGenerated = void.is_chunk_generated(absPos)
if not alreadyGenerated then -- the chunk isnt present on void, so we need to request for generation
-- the chunk is not generated so we tell factorio to generate it and let the handler below do the copy
void.request_to_generate_chunks({
-- * 32 because request_to_generate_chunks accepts Position but absPos is a ChunkPosition
x = absPos.x * 32,
y = absPos.y * 32,
}, 1)
void.force_generate_chunk_requests()
end
copy_tiles(void, surface, chunkPos, absPos)
end)