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)