Regenerate map under existing factory, any ideas?

Anything that prevents you from playing the game properly. Do you have issues playing for the game, downloading it or successfully running it on your computer? Let us know here.
User avatar
Dixi
Fast Inserter
Fast Inserter
Posts: 141
Joined: Sat Nov 04, 2017 1:47 pm
Contact:

Regenerate map under existing factory, any ideas?

Post by Dixi »

I have reasonably sized base (360 hours playtime, 1k SPM, 1 rocket/min, ~8000 rockets launched) started on 0.15 map. Biters present on a map, normal settings.
Since change to 0.16 new chunks are generated by different algorithm so map looks inconsistent. But I used to it, to some degree. In 0.17 map generating will likely change again.

I don't want to spend another ~300 hours of gameplay to build a new base of similar size on a new 0.17 map. And I still like to expand existing base.
I wonder is it possible to destroy whole map, while keeping structures, and communications intact, and have it regenerated whole?
I understand that water areas and all mineral deposits will move, and at some areas cliffs might appear, but fixing my base after such "disaster" looks much more interesting for me, comparing to fresh start from scratch.

Empty explored chunks of map can be easily destroyed by mod, and then regenerated by game as new. But is it possible to destroy terrain in a chunk without affecting other structures? Or to mark all chunks "needed to be map generated"? For sample, when I manually shoot from an artillery cannon to a maximum distance, map is likely generated "on a fly" under flying cannon shell. Is it possible to use same mechanic, by marking whole map for regeneration?

User avatar
steinio
Smart Inserter
Smart Inserter
Posts: 2633
Joined: Sat Mar 12, 2016 4:19 pm
Contact:

Re: Regenerate map under existing factory, any ideas?

Post by steinio »

At least you can delete generated chunks which are still empty (without buildings of you)
https://mods.factorio.com/mod/DeleteEmptyChunks
Image

Transport Belt Repair Man

View unread Posts

User avatar
Dixi
Fast Inserter
Fast Inserter
Posts: 141
Joined: Sat Nov 04, 2017 1:47 pm
Contact:

Re: Regenerate map under existing factory, any ideas?

Post by Dixi »

Yes I know about that and another similar but older mods.
But question is about replacing whole map.
I suppose it might be done in LUA, by telling to engine that map need to be regenerated chunk by chunk.
Mentioned above mod also iterate all chunks, checking some conditions, and in the end deleting some chunks. After that deleted pieces getting regenerated by game engine.
In my case deleting chunks probably will not work, since player structures are also store there, are they? Or not?

Jap2.0
Smart Inserter
Smart Inserter
Posts: 2339
Joined: Tue Jun 20, 2017 12:02 am
Contact:

Re: Regenerate map under existing factory, any ideas?

Post by Jap2.0 »

Dixi wrote:
Sun Dec 30, 2018 2:04 pm
Yes I know about that and another similar but older mods.
But question is about replacing whole map.
I suppose it might be done in LUA, by telling to engine that map need to be regenerated chunk by chunk.
Mentioned above mod also iterate all chunks, checking some conditions, and in the end deleting some chunks. After that deleted pieces getting regenerated by game engine.
In my case deleting chunks probably will not work, since player structures are also store there, are they? Or not?
I believe they are. Does anyone know if it would be possible to store the contents of a chunk, delete it, regenerate it, and restore the contents (possibly landfilling/removing trees/cliffs) via mod? It seems like something that should be possible but I wouldn't know.
There are 10 types of people: those who get this joke and those who don't.


User avatar
Dixi
Fast Inserter
Fast Inserter
Posts: 141
Joined: Sat Nov 04, 2017 1:47 pm
Contact:

Re: Regenerate map under existing factory, any ideas?

Post by Dixi »

darkfrei wrote:
Mon Dec 31, 2018 8:49 am
You are need https://mods.factorio.com/mod/NewGamePlus
That is an interesting option but not the thing I'm looking for.
I want to keep existing base, not to get in a new world, while keeping research and full pockets.
Jap2.0 wrote:
Mon Dec 31, 2018 12:17 am
Does anyone know if it would be possible to store the contents of a chunk, delete it, regenerate it, and restore the contents (possibly landfilling/removing trees/cliffs) via mod?
Are you sure that engine creates map only on empty chunks?
In API calls there are methods

request_to_generate_chunks(position, radius)
force_generate_chunk_requests()
set_chunk_generated_status(position, status)

I wonder what will happen if one calls
request_to_generate_chunks({0,0}, 1000)
Will it wipe the map and generate new or only terrain will regenerate, as I want?

I can't find chunk structure description. I afraid, that that it's actually C++ game data, that can be referenced from LUA calls, and only limited methods are available to us.

Update.
So far results were .... umm ... unexpected.
/c game.player.surface.request_to_generate_chunks({0,0}, 1000)
Freezes the game and crushed: game, steam, web browser. Probably, because it tried to allocate too much RAM.
Smaller request
/c game.player.surface.request_to_generate_chunks({0,0}, 100)
drops FPS/UPS to 3 for a minute. When operation was complete, nothing changes.

It seems that map on chunks with player owned structures are not generated by above call.

orzelek
Smart Inserter
Smart Inserter
Posts: 3911
Joined: Fri Apr 03, 2015 10:20 am
Contact:

Re: Regenerate map under existing factory, any ideas?

Post by orzelek »

It's a bit of a guess but I think you might need to set status of all chunks first.
Calling just generate will check they are there already and skip them.
Setting them all to defines.chunk_generated_status.nothing might cause some reaction - I did not try so it might do nothing as well :D

User avatar
darkfrei
Smart Inserter
Smart Inserter
Posts: 2903
Joined: Thu Nov 20, 2014 11:11 pm
Contact:

Re: Regenerate map under existing factory, any ideas?

Post by darkfrei »

Dixi wrote:
Mon Dec 31, 2018 9:07 am
darkfrei wrote:
Mon Dec 31, 2018 8:49 am
You are need https://mods.factorio.com/mod/NewGamePlus
That is an interesting option but not the thing I'm looking for.
I want to keep existing base, not to get in a new world, while keeping research and full pockets.
Ohh, then you can try https://mods.factorio.com/mod/nicefill, it makes new generated hidden map surface and when you place landfill, it takes tiles from hidden surface and places correctly and smooth.

So if your surface is "nauvis" then hidden surface will be "NiceFill_nauvis" and you can make reading from one surface and rewrite chunks on your surface.

User avatar
Dixi
Fast Inserter
Fast Inserter
Posts: 141
Joined: Sat Nov 04, 2017 1:47 pm
Contact:

Re: Regenerate map under existing factory, any ideas?

Post by Dixi »

I've checked NiceFill mod LUA code. I understand how he creates a new surface and calls map generator to create terrain chunks there, but I don't understand how to copy chunks (or tiles) from there to primary surface. In NiceFill that method might be a little complicated since he wants to copy only "landiffled" tiles, and sometimes 1-2 tiles around them for terrain blending or to make land-water borders looks correctly.

staviq
Fast Inserter
Fast Inserter
Posts: 129
Joined: Wed Jun 29, 2016 1:22 pm
Contact:

Re: Regenerate map under existing factory, any ideas?

Post by staviq »

darkfrei wrote:
Mon Dec 31, 2018 10:24 am
Ohh, then you can try https://mods.factorio.com/mod/nicefill, it makes new generated hidden map surface and when you place landfill, it takes tiles from hidden surface and places correctly and smooth.

So if your surface is "nauvis" then hidden surface will be "NiceFill_nauvis" and you can make reading from one surface and rewrite chunks on your surface.
I was thinking at some point about adding a "cleanup" function to NiceFill, that would traverse chunks and fix inconsistent ground texture, and i might actually do it now that somebody actually has use for it.
There is however a problem of foliage, aka decorations that NiceFill currently ignores. I need to think about it.

User avatar
Dixi
Fast Inserter
Fast Inserter
Posts: 141
Joined: Sat Nov 04, 2017 1:47 pm
Contact:

Re: Regenerate map under existing factory, any ideas?

Post by Dixi »

staviq wrote:
Mon Dec 31, 2018 11:10 am
I was thinking at some point about adding a "cleanup" function to NiceFill, that would traverse chunks and fix inconsistent ground texture, and i might actually do it now that somebody actually has use for it.
There is however a problem of foliage, aka decorations that NiceFill currently ignores. I need to think about it.
Do you mean that copying just tiles or whole chunks from new generated surface to original "nauvis" is not enough, and it won't make map "like a new"? "foliage, aka decorations" - are they additional objects on a map? Are they like player structures, attached to some tiles?

User avatar
darkfrei
Smart Inserter
Smart Inserter
Posts: 2903
Joined: Thu Nov 20, 2014 11:11 pm
Contact:

Re: Regenerate map under existing factory, any ideas?

Post by darkfrei »

Useful links:
https://lua-api.factorio.com/latest/LuaGameScript.html
https://lua-api.factorio.com/latest/Lua ... rator.html
https://lua-api.factorio.com/latest/LuaSurface.html

Here is the code that you looking for:
code
It makes new hidden map surface, copy settings from old surface, than replaces your map with new generated tiles.

Before:
2018-12-31 12_49_35-Window.png
2018-12-31 12_49_35-Window.png (2.63 KiB) Viewed 6289 times
After:
2018-12-31 12_49_26-Window.png
2018-12-31 12_49_26-Window.png (3.69 KiB) Viewed 6289 times
Last edited by darkfrei on Mon Dec 31, 2018 3:53 pm, edited 2 times in total.

User avatar
darkfrei
Smart Inserter
Smart Inserter
Posts: 2903
Joined: Thu Nov 20, 2014 11:11 pm
Contact:

Re: Regenerate map under existing factory, any ideas?

Post by darkfrei »

Optimized code, needs much more time, but works with megabases.

Code: Select all

/c
log ('start')
local surface = game.player.surface
local nf_surface_name = 'nf_'..surface.name
if not game.surfaces[('nf_'..surface.name)] then
  local settings = surface.map_gen_settings
  settings.autoplace_controls["enemy-base"] = {frequency="none",size="none",richness="none"}
  settings.autoplace_controls["trees"] = {frequency="none",size="none",richness="none"}
  settings.autoplace_settings =
      { entity = {treat_missing_as_default = false, settings = {frequency = "none", size = "none", richness = "none"}},
        decorative = {treat_missing_as_default = false, settings = {frequency = "none", size = "none", richness="none"}}}
  settings.water = "none"
  settings.starting_area = "none"
  settings.peaceful_mode = true
  settings.cliff_settings = {cliff_elevation_0 = 0, cliff_elevation_interval = 0, name = "cliff"}
  game.create_surface(nf_surface_name, settings)
end
log ('hidden map is created')
local nf_surface = game.surfaces[nf_surface_name]
for chunk in surface.get_chunks() do
  if not nf_surface.is_chunk_generated({x=chunk.x, y=chunk.y}) then
    nf_surface.request_to_generate_chunks({x=chunk.x*32, y=chunk.y*32}, 0)
  end
  nf_surface.force_generate_chunk_requests()
  local tiles = {}
  for x = (chunk.x*32), (chunk.x*32+31) do
    for y = (chunk.y*32), (chunk.y*32+31) do
      local tile = surface.get_tile(x, y)
      if tile.collides_with("ground-tile") then
        local nf_tile = nf_surface.get_tile(x, y)
        table.insert (tiles, {name=nf_tile.name, position = {x=x,y=y}})
      end
    end
  end
  surface.set_tiles(tiles)
  nf_surface.delete_chunk({x=chunk.x*32, y=chunk.y*32})
end
log ('complete')
Example:
I have one 500 hours long save game from 0.15, save file is about 92 MB, it has 96469 chunks and need up to about 14.7 GB of memory. It was ready in 1837 seconds or about 30 minutes.

Before:
2018-12-31 13_14_15-Window.png
2018-12-31 13_14_15-Window.png (158.63 KiB) Viewed 6254 times
After:
2018-12-31 16_03_14-Window.png
2018-12-31 16_03_14-Window.png (139.33 KiB) Viewed 6254 times
Last edited by darkfrei on Mon Dec 31, 2018 3:50 pm, edited 1 time in total.

User avatar
Dixi
Fast Inserter
Fast Inserter
Posts: 141
Joined: Sat Nov 04, 2017 1:47 pm
Contact:

Re: Regenerate map under existing factory, any ideas?

Post by Dixi »

Yes this code works. But it does not moves whole player made structures to a new map. It only replacing old terrain types with new, without any changes to geography and ore deposits. As staviq correctly mentioned, new copied terrain will looks really flat and lifeless, since we do not copy foliage and other decorations.

It seems to me that task of coping existing base to a new map is more complicated then it was on first glance.

If I will not find another solution to move existing base to a new map, in the end, idea of NewGamePlus mod might be useful. Fill whole inventory with nuclear plant, some miners/smelters, factories, bots, and start on a new map with existing research tree. I only doubt that my pockets will carry enough stuff. Need to check NewGamePlus forum part, to see if anyone already made "shopping list" to fill my inventory most optimal way.
Last edited by Dixi on Mon Dec 31, 2018 6:17 pm, edited 1 time in total.

Jap2.0
Smart Inserter
Smart Inserter
Posts: 2339
Joined: Tue Jun 20, 2017 12:02 am
Contact:

Re: Regenerate map under existing factory, any ideas?

Post by Jap2.0 »

Well, I've been meaning to learn lua anyway...
There are 10 types of people: those who get this joke and those who don't.

User avatar
Optera
Smart Inserter
Smart Inserter
Posts: 2916
Joined: Sat Jun 11, 2016 6:41 am
Contact:

Re: Regenerate map under existing factory, any ideas?

Post by Optera »

darkfrei wrote:
Mon Dec 31, 2018 2:16 pm
Optimized code, needs much more time, but works with megabases.

Code: Select all

/c
log ('start')
local surface = game.player.surface
local nf_surface_name = 'nf_'..surface.name
if not game.surfaces[('nf_'..surface.name)] then
  local settings = surface.map_gen_settings
  settings.autoplace_controls["enemy-base"] = {frequency="none",size="none",richness="none"}
  settings.autoplace_controls["trees"] = {frequency="none",size="none",richness="none"}
  settings.autoplace_settings =
      { entity = {treat_missing_as_default = false, settings = {frequency = "none", size = "none", richness = "none"}},
        decorative = {treat_missing_as_default = false, settings = {frequency = "none", size = "none", richness="none"}}}
  settings.water = "none"
  settings.starting_area = "none"
  settings.peaceful_mode = true
  settings.cliff_settings = {cliff_elevation_0 = 0, cliff_elevation_interval = 0, name = "cliff"}
  game.create_surface(nf_surface_name, settings)
end
log ('hidden map is created')
local nf_surface = game.surfaces[nf_surface_name]
for chunk in surface.get_chunks() do
  if not nf_surface.is_chunk_generated({x=chunk.x, y=chunk.y}) then
    nf_surface.request_to_generate_chunks({x=chunk.x*32, y=chunk.y*32}, 0)
  end
  nf_surface.force_generate_chunk_requests()
  local tiles = {}
  for x = (chunk.x*32), (chunk.x*32+31) do
    for y = (chunk.y*32), (chunk.y*32+31) do
      local tile = surface.get_tile(x, y)
      if tile.collides_with("ground-tile") then
        local nf_tile = nf_surface.get_tile(x, y)
        table.insert (tiles, {name=nf_tile.name, position = {x=x,y=y}})
      end
    end
  end
  surface.set_tiles(tiles)
  nf_surface.delete_chunk({x=chunk.x*32, y=chunk.y*32})
end
log ('complete')
That's a nice way to update old saves to new map generator.
Would be even nicer though if you added a check so it doesn't remove all concrete.

User avatar
Dixi
Fast Inserter
Fast Inserter
Posts: 141
Joined: Sat Nov 04, 2017 1:47 pm
Contact:

Re: Regenerate map under existing factory, any ideas?

Post by Dixi »

Optera wrote:
Mon Dec 31, 2018 8:34 pm
Would be even nicer though if you added a check so it doesn't remove all concrete.
I think concrete is located in same layer as decorative foliage. And listed above code does not work with it - it only replace old tiles with new, according to changed map generator. So it's mostly cosmetic change.

User avatar
darkfrei
Smart Inserter
Smart Inserter
Posts: 2903
Joined: Thu Nov 20, 2014 11:11 pm
Contact:

Re: Regenerate map under existing factory, any ideas?

Post by darkfrei »

Dixi wrote:
Mon Dec 31, 2018 8:47 pm
Optera wrote:
Mon Dec 31, 2018 8:34 pm
Would be even nicer though if you added a check so it doesn't remove all concrete.
I think concrete is located in same layer as decorative foliage. And listed above code does not work with it - it only replace old tiles with new, according to changed map generator. So it's mostly cosmetic change.
We have also hidden tiles under concrete, that must be replaced, but not the concrete, refined concrete, hazard concrete left and right, refined hazard concrete left and right. And stone path.

User avatar
Optera
Smart Inserter
Smart Inserter
Posts: 2916
Joined: Sat Jun 11, 2016 6:41 am
Contact:

Re: Regenerate map under existing factory, any ideas?

Post by Optera »

Yes, and those hidden tiles must not be replaced with water, otherwise you get destroyed buildings or instant deaths when mining or replacing the concrete.
You can get that effect by using the creative modes magic wand to paint concrete over water.

PS:
You might also want to call game.player.force.clear_chart() afterwards so the map is forced to update.

User avatar
darkfrei
Smart Inserter
Smart Inserter
Posts: 2903
Joined: Thu Nov 20, 2014 11:11 pm
Contact:

Re: Regenerate map under existing factory, any ideas?

Post by darkfrei »

Optera wrote:
Tue Jan 01, 2019 6:29 am
Yes, and those hidden tiles must not be replaced with water, otherwise you get destroyed buildings or instant deaths when mining or replacing the concrete.
You can get that effect by using the creative modes magic wand to paint concrete over water.

PS:
You might also want to call game.player.force.clear_chart() afterwards so the map is forced to update.
Thanks! Hidden surface has no water, water by 'nauvis' will be not overwritten.

The clear_chart must help with memory leak. Maybe unchart_chunk(position, surface) https://lua-api.factorio.com/latest/Lua ... hart_chunk

Post Reply

Return to “Technical Help”