Is creating new surfaces implemented?

Place to get help with not working mods / modding interface.
memcallen
Inserter
Inserter
Posts: 34
Joined: Sat Mar 28, 2015 1:22 am
Contact:

Is creating new surfaces implemented?

Post by memcallen »

I've looked around and it looks like adding surfaces isn't implemented yet, although the wiki says something about an API. Can I make another surface, and if so how?

ratchetfreak
Filter Inserter
Filter Inserter
Posts: 952
Joined: Sat May 23, 2015 12:10 pm
Contact:

Re: Is creating new surfaces implemented?

Post by ratchetfreak »

memcallen wrote:I've looked around and it looks like adding surfaces isn't implemented yet, although the wiki says something about an API. Can I make another surface, and if so how?
https://forums.factorio.com/wiki/inde ... te_surface

memcallen
Inserter
Inserter
Posts: 34
Joined: Sat Mar 28, 2015 1:22 am
Contact:

Re: Is creating new surfaces implemented?

Post by memcallen »

How did I miss that? I even looked at merge forces...

How can I change what tiles are used and which ores are created when generating the surface?

Rseding91
Factorio Staff
Factorio Staff
Posts: 14150
Joined: Wed Jun 11, 2014 5:23 am
Contact:

Re: Is creating new surfaces implemented?

Post by Rseding91 »

memcallen wrote:How did I miss that? I even looked at merge forces...

How can I change what tiles are used and which ores are created when generating the surface?
That's currently not possible at surface creation in 0.12. It's something I want to add to 0.13 but we'll see if time allows it.

For now, you would need to use on_chunk_generated and set entities/tiles to what you want.
If you want to get ahold of me I'm almost always on Discord.

memcallen
Inserter
Inserter
Posts: 34
Joined: Sat Mar 28, 2015 1:22 am
Contact:

Re: Is creating new surfaces implemented?

Post by memcallen »

Ok, thanks. Hopefully I can make something work that isn't too much of a hack.

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

Re: Is creating new surfaces implemented?

Post by orzelek »

Find a mod called underground - it made it work from what I seen. A least a bit - I'm missing some nice non script way to transfer materials to different surface to make it really possible.

Rseding91
Factorio Staff
Factorio Staff
Posts: 14150
Joined: Wed Jun 11, 2014 5:23 am
Contact:

Re: Is creating new surfaces implemented?

Post by Rseding91 »

orzelek wrote:Find a mod called underground - it made it work from what I seen. A least a bit - I'm missing some nice non script way to transfer materials to different surface to make it really possible.
There's no non script way to do anything with surfaces at this point :) Surfaces exist only in the sense that the game knows how handle multiple of them and the API has a few methods to work with them. Transferring items between surfaces and players is only possible to do through the API right now.
If you want to get ahold of me I'm almost always on Discord.

memcallen
Inserter
Inserter
Posts: 34
Joined: Sat Mar 28, 2015 1:22 am
Contact:

Re: Is creating new surfaces implemented?

Post by memcallen »

@orzelek, that sucks, I thought that no one else created a cave world type mod yet. Oh well, I need the lua practice anyways.

jorgenRe
Filter Inserter
Filter Inserter
Posts: 535
Joined: Wed Apr 09, 2014 3:32 pm
Contact:

Re: Is creating new surfaces implemented?

Post by jorgenRe »

Rseding91 wrote:
memcallen wrote:How did I miss that? I even looked at merge forces...

How can I change what tiles are used and which ores are created when generating the surface?
That's currently not possible at surface creation in 0.12. It's something I want to add to 0.13 but we'll see if time allows it.

For now, you would need to use on_chunk_generated and set entities/tiles to what you want.
Enjoy the most hackiest code i have made for Factorio:
Meet the tilechanger code:

Code: Select all

--First place down the markers in as big of an area as possible
distBetween = 30
function placeMarkers()
  for x = 1, 200 do
    xPos = (x-100) * distBetween 
    for y = 1, 200 do
	  game.surfaces["theUnderground"].create_entity({name = "marker", position = {xPos, (y - 100) * distBetween}, force = game.forces.player})
	end
  end
end
--Find those chests and if its closer than 50 tiles then change all the tiles in its space to the new tiles
searchDist = 150
function changetiles2()	
  chestsFound = {}
  tiles = {}
  lamps = {}
  found = 0
  --Change the tiles
  results = game.surfaces["theUnderground"].find_entities_filtered{area = {{game.players[1].position.x -searchDist, game.players[1].position.y -searchDist}, {game.players[1].position.x +searchDist, game.players[1].position.y +searchDist}}, name= "marker"}
  for d,ent in pairs(results) do
    if ent.position ~= nil then
      chestsFound[d] = ent.position
	  found = found + 1
	  ent.destroy()
	end
  end
  for n = 1, found do
    --if ent ~= nil then
	if chestsFound[n] ~= nil then

      for x = 1, 30 do
        xPos = chestsFound[n].x + x - 2	
	    for y = 1, 30 do
	      yPos = chestsFound[n].y + y - 2
		  --If it collides with a player turn it into lava if not turn it to lavaStone
          if game.surfaces["theUnderground"].get_tile(xPos, yPos).collides_with("player-layer") then 
	        --game.players[1].print("yes!") 
			table.insert(tiles, {name = "lava", position = {xPos, yPos}})
			if y == 7 and x == 7then
			  table.insert(lamps, {xPos, yPos})  
			elseif y == 14 and x == 14then
			  table.insert(lamps, {xPos, yPos})
            elseif y == 21 and x == 21 then
			  table.insert(lamps, {xPos, yPos}) 
            elseif y == 28 and x == 28 then
			  table.insert(lamps, {xPos, yPos})   			  
			end
	      else
			table.insert(tiles, {name = "lavaStone", position = {xPos, yPos}})
	      end
	    end
	  end
--ent.destroy()
	--end
	end
  end
  if found > 0 then
    game.surfaces["theUnderground"].set_tiles(tiles)
	newLamp(lamps)
  end
  --Remove the trees and change rocks to 
  results = game.surfaces["theUnderground"].find_entities_filtered{area = {{game.players[1].position.x -searchDist, game.players[1].position.y -searchDist}, {game.players[1].position.x +searchDist, game.players[1].position.y +searchDist}}, type = "tree"}
  for d,ent in pairs(results) do
    ent.destroy()
  end
  results = game.surfaces["theUnderground"].find_entities_filtered{area = {{game.players[1].position.x -searchDist, game.players[1].position.y -searchDist}, {game.players[1].position.x +searchDist, game.players[1].position.y +searchDist}}, name = "stone-rock"}
    for d,ent in pairs(results) do
      game.surfaces["theUnderground"].create_entity({name = "lava", position = ent.position})
      game.surfaces["theUnderground"].create_entity({name = "fake-pole", position = ent.position})
      game.surfaces["theUnderground"].create_entity({name = "fake-battery", position = ent.position})
	    if game.surfaces["theUnderground"].count_entities_filtered{area = {{ent.position.x-25, ent.position.y-25}, {ent.position.x+25, ent.position.y+25}}, name= "opening"} == 0 then
          if game.surfaces["theUnderground"].get_tile(ent.position.x+10, ent.position.y+10).name == "lavaStone" then
		    --game.surfaces["theUnderground"].create_entity({name = "shadow-spawner", position = {ent.position.x+10, ent.position.y+10}})
		  end
		  if game.surfaces["theUnderground"].get_tile(ent.position.x+10, ent.position.y).name == "lavaStone" then
			--game.surfaces["theUnderground"].create_entity({name = "shadow-spawner", position = {ent.position.x+10, ent.position.y}})
		  end
		end
	 ent.destroy()
  end
end
Next is to add the entity marker:

Code: Select all

{
    type = "container",
    name = "marker",
    icon = "__base__/graphics/icons/iron-chest.png",
    flags = {"placeable-neutral", "player-creation"},
    minable = {mining_time = 1, result = "marker"},
    max_health = 100,
    corpse = "small-remnants",
    open_sound = { filename = "__base__/sound/metallic-chest-open.ogg", volume=0.65 },
    close_sound = { filename = "__base__/sound/metallic-chest-close.ogg", volume = 0.7 },
    resistances =
    {
      {
        type = "fire",
        percent = 80
      }
    },
    collision_box = {{-0.35, -0.35}, {0.35, 0.35}},
    selection_box = {{-0.5, -0.5}, {0.5, 0.5}},
    fast_replaceable_group = "container",
    inventory_size = 32,
    vehicle_impact_sound =  { filename = "__base__/sound/car-metal-impact.ogg", volume = 0.65 },
    picture =
    {
      filename = "__base__/graphics/entity/iron-chest/iron-chest.png",
      priority = "extra-high",
      width = 48,
      height = 34,
      shift = {0.2, 0}
    }
  },
--Todo on my todo list is to use the on_chunk_generated
Next is the removal of trees and such and changing of the rocks to cheaty lamps that runs with no power:

Code: Select all

script.on_event(defines.events.on_chunk_generated, function(event)
    
    --local caves = game.surfaces.Caves
    local area = event.area
    local entitiesSpawned = game.surfaces["nauvis"].find_entities{{area.left_top.x, area.left_top.y}, {area.right_bottom.x, area.right_bottom.y}}
    for _,v in pairs(entitiesSpawned) do
      message("Found a: "..v.type)
	  local destroyed = false
      if(v.type == "resource" or v.type == "decorative") then
        v.destroy()
		message("Removed it :P")
		destroyed = true
      end
	  if (destroyed == false) then
      if(v.type == "tree") then
        v.destroy()
      end
	  end
    end
end)
This is done on chunk generated so much cleaner. When creating a new entity do something like:

Code: Select all

game.surfaces["theUnderground"].create_entity({name = "lava", position = v.position})
v is the entity btw
Run that code everytime something like a specific tree is found.
Also use area.surface to get the current surface it happens on.
Then for the ores you can easily check if the surface the event happened on was on the normal and there delete your ores, but underground you can delete the normal ores or something ;)!
Logo
Noticed the told change in FFF #111 so il continue to use my signature ^_^
Thanks for listening to our suggestions, devs :D!
I would jump of joy if we could specify which tiles spawned in a surfaces

jorgenRe
Filter Inserter
Filter Inserter
Posts: 535
Joined: Wed Apr 09, 2014 3:32 pm
Contact:

Re: Is creating new surfaces implemented?

Post by jorgenRe »

Rseding91 wrote:
memcallen wrote:How did I miss that? I even looked at merge forces...

How can I change what tiles are used and which ores are created when generating the surface?
That's currently not possible at surface creation in 0.12. It's something I want to add to 0.13 but we'll see if time allows it.

For now, you would need to use on_chunk_generated and set entities/tiles to what you want.
:o

THANK YOU THANK YOU SO MUCH!!!!
Removing my tilechanger code will be such a happy thing even though it is a little late for that now. atleast for me :lol:!
But thanks :)!
Logo
Noticed the told change in FFF #111 so il continue to use my signature ^_^
Thanks for listening to our suggestions, devs :D!
I would jump of joy if we could specify which tiles spawned in a surfaces

memcallen
Inserter
Inserter
Posts: 34
Joined: Sat Mar 28, 2015 1:22 am
Contact:

Re: Is creating new surfaces implemented?

Post by memcallen »

@jorgenRe, what I plan to do is check when my entrance is auto-genned, if there's a chasm/lava where the player would spawn and if there is, move the entrance to somewhere that it won't affect the player. This would all happen in on_chunk_generated, so the player would never see it happen. You can use this if you want to, I don't care. Also I have an event that detects when the player teleports surfaces, but I'm not at my pc so I can't show it right now.

Rseding91
Factorio Staff
Factorio Staff
Posts: 14150
Joined: Wed Jun 11, 2014 5:23 am
Contact:

Re: Is creating new surfaces implemented?

Post by Rseding91 »

This is untested but until 0.13.0 (or when ever we get around to adding support for creation-time tile definitions) this should run orders of magnitude faster in replacing tiles:

Code: Select all

--First place down the markers in as big of an area as possible
function placeMarkers()
  local distBetween = 30
  local surface = game.surfaces["theUnderground"]
  local force = game.forces.player
  local xPos
  
  for x = 1, 200 do
    xPos = (x-100) * distBetween 
    for y = 1, 200 do
      surface.create_entity({name = "marker", position = {xPos, (y - 100) * distBetween}, force = force})
    end
  end
end

--Find those chests and if its closer than 50 tiles then change all the tiles in its space to the new tiles
function changetiles2()
  local searchDist = 150
  local results
  local xPos, yPos
  local chestsFound = {}
  local tiles = {}
  local lamps = {}
  local found = false
  local surface = game.surfaces["theUnderground"]
  local position = game.players[1].position
  local lampOffsets = {
    [7] = {[7] = true},
    [14] = {[14] = true},
    [21] = {[21] = true},
    [28] = {[28] = true}
  }
  
  --Change the tiles
  results = surface.find_entities_filtered{area = {{position.x -searchDist, position.y -searchDist}, {position.x +searchDist, position.y +searchDist}}, name= "marker"}
  for d,ent in pairs(results) do
    table.insert(chestsFound, ent.position)
    ent.destroy()
    found = true
  end
  
  for k,chest in pairs(chestsFound) do
    for x = 1, 30 do
      xPos = chest.x + x - 2
      for y = 1, 30 do
        yPos = chest.y + y - 2
        --If it collides with a player turn it into lava if not turn it to lavaStone
        if surface.get_tile(xPos, yPos).collides_with("player-layer") then
          --game.players[1].print("yes!")
          table.insert(tiles, {name = "lava", position = {xPos, yPos}})
          
          if lampOffsets[x] ~= nil and lampOffsets[x][y] ~= nil then
            table.insert(lamps, {xPos, yPos})
          end
        else
          table.insert(tiles, {name = "lavaStone", position = {xPos, yPos}})
        end
      end
    end
  end
  
  if found then
    surface.set_tiles(tiles)
    newLamp(lamps)
  end
  
  --Remove the trees and change rocks to 
  results = surface.find_entities_filtered{area = {{position.x -searchDist, position.y -searchDist}, {position.x +searchDist, position.y +searchDist}}, type = "tree"}
  for k,entity in pairs(results) do
    entity.destroy()
  end
  
  results = surface.find_entities_filtered{area = {{position.x -searchDist, position.y -searchDist}, {position.x +searchDist, position.y +searchDist}}, name = "stone-rock"}
  for k,entity in pairs(results) do
    local entityPosition = entity.position
    entity.destroy()
    surface.create_entity({name = "lava", position = entityPosition})
    surface.create_entity({name = "fake-pole", position = entityPosition})
    surface.create_entity({name = "fake-battery", position = entityPosition})
  end
end
It is still of course locked to player #1, force: "player" which you could fix later if you so wanted. Every time you call "game.surfaces[...]" it creates a table of all the surfaces with new surface objects. The same applies for "game.players[...]" and many other API calls that return tables of results. You however never needed to do that except the first time you start the function and can re-use the same surface object for the lifetime of the function.

I did a rough count and before (as you pasted it) the placeMarkers() function was creating:
  • 40,000 Surface objects
  • 40,000 Player objects
  • 40,000 force objects
After I cleaned it up (the paste above) it's now creating:
  • 1 Surface object
  • 1 Player object
  • 1 Force object
A rough count of the changetiles2() function was creating:
  • 3 Surface objects
  • 12 Player objects
  • Count of found chests * 900 Surface objects
  • Count of found chests * 900 Tile objects
  • Count of found stone-chest objects * 4-6 Surface objects
  • Count of found stone-chest objects * 0-2 Tile objects
After I cleaned up that function:
  • 1 Surface object
  • 1 Player object
  • Count of found chests * 900 Tile objects
If you want to get ahold of me I'm almost always on Discord.

jorgenRe
Filter Inserter
Filter Inserter
Posts: 535
Joined: Wed Apr 09, 2014 3:32 pm
Contact:

Re: Is creating new surfaces implemented?

Post by jorgenRe »

Rseding91 wrote:This is untested but until 0.13.0 (or when ever we get around to adding support for creation-time tile definitions) this should run orders of magnitude faster in replacing tiles:
Wow i guess that is one really big difference o_0!
Thanks for the tip :)!
Logo
Noticed the told change in FFF #111 so il continue to use my signature ^_^
Thanks for listening to our suggestions, devs :D!
I would jump of joy if we could specify which tiles spawned in a surfaces

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

Re: Is creating new surfaces implemented?

Post by orzelek »

Can one of you post simple explanation why those marker chests are required?

Wouldn't normal on_chunk generated work to replace the tiles ?

jorgenRe
Filter Inserter
Filter Inserter
Posts: 535
Joined: Wed Apr 09, 2014 3:32 pm
Contact:

Re: Is creating new surfaces implemented?

Post by jorgenRe »

orzelek wrote:Can one of you post simple explanation why those marker chests are required?

Wouldn't normal on_chunk generated work to replace the tiles ?
On chunk generated would work, but when I created that tile changer code I did not know about it so I used the markers. It should be simple to instead use the on chunk generated event ;)!
Logo
Noticed the told change in FFF #111 so il continue to use my signature ^_^
Thanks for listening to our suggestions, devs :D!
I would jump of joy if we could specify which tiles spawned in a surfaces

Post Reply

Return to “Modding help”