Problems with surface transfer:

Place to get help with not working mods / modding interface.
Greave
Burner Inserter
Burner Inserter
Posts: 5
Joined: Wed Jan 03, 2018 8:22 am
Contact:

Problems with surface transfer:

Post by Greave »

Hi all,

Having some problems with a control.lua file im working on for a headless server im putting together.
The point of the server is to have a very intense, normally fairly short (the longest weve lasted so far is about 2.5 hours, survival mode.
At the end, you typically are swarmed by biters and completely overwhelmed.
This is where the scenario control.lua ive been working on comes in, allowing players to vote for a game over, logging time played, taking a screenshot of the base, creating a new surface, deleting the old surface and transfering players to the new surface.
I finally got everything working, and have most of it running properly.
But Ive run into one very weird problem, when succeeding in voting for a round end, you are transferred properly to the new surface, but you lose your character, leaving you to float around the map as if youre in an RTS or something. I cant for the life of me figure out why this is happening, does anyone have any suggestions?

Heres the code from the control.lua:

Code: Select all

require("silo-script")
local version = 1

script.on_init(function()
    global.version = version
    silo_script.init()
end)

script.on_event(defines.events.on_player_created, function(event) 
local player = game.players[event.player_index]
  player.print("Welcome to Grim Galaxy!") 
  player.print("---------------------------------")
  player.print("Your goal is to survive.")
  player.print("The current highscore is 2.5 hours.")
  player.force.recipes.loader.enabled=true
  player.force.technologies["stone-walls"].researched = true
  player.force.technologies["turrets"].researched = true
  player.force.technologies["military"].researched=true 
  player.insert{name="iron-plate", count=8}
  player.insert{name="pistol", count=1}
  player.insert{name="stone-wall", count=50}
  player.insert{name="firearm-magazine", count=40}
  player.insert{name="burner-mining-drill", count = 2}
  player.insert{name="gun-turret", count = 1} 
  player.insert{name="stone-furnace", count = 1}
  player.force.chart(player.surface, {{player.position.x - 200, player.position.y - 200}, {player.position.x + 200, player.position.y + 200}})
end)

local function count_votes()
    global.voters = global.voters or {}
    local yes, no = 0, 0
    for _, vote in pairs(global.voters) do
        if vote == true then
            yes = yes + 1
        elseif vote == false then
            no = no + 1
        end
    end
    return yes, no, yes > no
end

local function generate_new_world()
	map_num = 1
	map_num = map_num + 1
	local new_map = game.create_surface("new_map " .. map_num)

	for _, player in pairs(game.players) do
		player.teleport({0,0}, new_map)
		player.force.chart(new_map, {{player.position.x - 200, player.position.y - 200}, {player.position.x + 200, player.position.y + 200}})
	end
	for _, force in pairs(game.forces) do
		force.set_spawn_position({0,0}, new_map)
		global.tech_reset = true
	end
	for _,surface in pairs(game.surfaces) do
		if surface.name == "nauvis" then --can't delete nauvis
			local entities = surface.find_entities()
			for _, entity in pairs(entities) do
					script.raise_event(defines.events.on_entity_died, {entity=entity}) --raise event so that mods can do their stuff with the entities
			end
			for _, entity in pairs(entities) do
					if entity.valid then entity.destroy() end
				end
			for chunk in surface.get_chunks() do --so I delete its chunks on it
					surface.delete_chunk({chunk.x, chunk.y})
			end
		elseif not (surface.name ~= "new_map " .. map_num) then --don't delete factorissimo stuff or the new surface
			game.delete_surface(surface)
		end
	end	
end		

local function end_voting(player)
    if global.voting_type then
        if global.voting_type == "end_vote" then
            if select(3, count_votes()) then            
                    game.print("The majority has voted to end the round.")
					 generate_new_world()
                   else              
                    game.print("The majority has voted to continue the round.")
				end
			end
		end
	global.voters = nil
    global.voting_ends = nil
    global.voting_type = nil
end
		
local function process_vote(player_index, yes_or_no)
        global.voters = global.voters or {}
            if global.voters[player_index] == nil then
                global.voters[player_index] = yes_or_no
                local yes, no = count_votes()
                    game.players[player_index].print("You have voted to " .. (yes_or_no and "end" or "continue") .. " the round.")
                    game.players[player_index].print("For: " .. yes .. " Against: " .. no)
    end
end

commands.add_command(
    "yes",
    "Vote Yes",
    function(e)
        process_vote(e.player_index, true)
    end
)

commands.add_command(
    "no",
    "Vote No",
    function(e)
        process_vote(e.player_index, false)
    end
)


commands.add_command(
    "over",
    "Start a vote to end the map.",
    function(e)
        --first argument to /over is the time to wait before declaring a winner in minutes, defaults to 1 minute
        global.voting_ends = game.tick + ((e.parameter and (tonumber(e.parameter)) or 1 ) * 30 * 30)
        global.voting_type = "end_vote"
        global.voters = {}
        game.print(game.players[e.player_index].name .. " has started a vote to end the map, type /yes or /no to vote.")
        game.print("Voting will end in 60 seconds!")
    end
)

-- register tick handler, or add it your current tick handler
script.on_event(
    defines.events.on_tick,
    function(e)
        if e.tick == global.voting_ends then
            end_voting()
        end
    end)

script.on_event(defines.events.on_player_respawned, function(event)
  local player = game.players[event.player_index]
  player.insert{name="pistol", count=1}
  player.insert{name="firearm-magazine", count=10}
end)

script.on_event(defines.events.on_gui_click, function(event)
  silo_script.on_gui_click(event)
end)

script.on_event(defines.events.on_rocket_launched, function(event)
  silo_script.on_rocket_launched(event)
end)

script.on_configuration_changed(function(event)
  if global.version ~= version then
    global.version = version
  end
  silo_script.on_configuration_changed(event)
end)

silo_script.add_remote_interface()
Thanks.
Bilka
Factorio Staff
Factorio Staff
Posts: 3470
Joined: Sat Aug 13, 2016 9:20 am
Contact:

Re: Problems with surface transfer:

Post by Bilka »

Ahhhh why are you using my old code??? I even said why it's broken :( Try using my current code and see if it works then.
I'm an admin over at https://wiki.factorio.com. Feel free to contact me if there's anything wrong (or right) with it.
Greave
Burner Inserter
Burner Inserter
Posts: 5
Joined: Wed Jan 03, 2018 8:22 am
Contact:

Re: Problems with surface transfer:

Post by Greave »

Bilka wrote:Ahhhh why are you using my old code??? I even said why it's broken :( Try using my current code and see if it works then.
Were stuck using 0.15.00 due to one of the mods we want to use not updating since then, thats why im using older code.
Hope you dont mind me piecing things together like that, im still learning.

I did get it to work actually, mostly at least. Ive got everything tied into a chat voting poll system for a trigger, all I need to do is figure out how to solve this weird problem with the player state.
Bilka
Factorio Staff
Factorio Staff
Posts: 3470
Joined: Sat Aug 13, 2016 9:20 am
Contact:

Re: Problems with surface transfer:

Post by Bilka »

The 0.16 code also works in 0.15, at least the part you are using, so I'm begging, you: DON'T USE MY OLD CODE, USE THE CURRENT STUFF. The old code can lead to crashing due to running out of memory and other fun things.
I'm an admin over at https://wiki.factorio.com. Feel free to contact me if there's anything wrong (or right) with it.
Greave
Burner Inserter
Burner Inserter
Posts: 5
Joined: Wed Jan 03, 2018 8:22 am
Contact:

Re: Problems with surface transfer:

Post by Greave »

Bilka wrote:The 0.16 code also works in 0.15, at least the part you are using, so I'm begging, you: DON'T USE MY OLD CODE, USE THE CURRENT STUFF. The old code can lead to crashing due to running out of memory and other fun things.
okay, okay, i tried it out.
the only difference i found between the two, so far as what i was using, was:

Code: Select all

[[local entities = surface.find_entities()
			for _, entity in pairs(entities) do
				script.raise_event(defines.events.on_entity_died, {entity=entity}) --raise event so that mods can do their stuff with the entities
			end]] -- no longer dong this because it creates tons of entity objects which bloats ram. Quoting Rseding: "Not your problem if other mods don't check .valid"
Im still having the same issue.
I deleted the section you indicated above, that was the main difference between the 0.15 version and the 0.16 version, for the parts i was using.
Now when the vote is completed succesfully for the first time, i get this error:
"Error while running event level::on_tick (ID 0)
...Data/Roaming/Factorio/temp/currently-playing/control.lua:44: attempt to concatenate global 'map_num' (a nil value)"

Heres the code updated with your 0.16 code:

Code: Select all

require("silo-script")
local version = 1

script.on_init(function()
	global.map_num = 1
    global.version = version
    silo_script.init()
end)

script.on_event(defines.events.on_player_created, function(event) 
local player = game.players[event.player_index]
  player.print("Welcome to Grim Galaxy!") 
  player.print("---------------------------------")
  player.print("Your goal is to survive.")
  player.print("The current highscore is 2.5 hours.")
  player.force.recipes.loader.enabled=true
  player.force.technologies["stone-walls"].researched = true
  player.force.technologies["turrets"].researched = true
  player.force.technologies["military"].researched=true 
  player.insert{name="iron-plate", count=8}
  player.insert{name="pistol", count=1}
  player.insert{name="stone-wall", count=50}
  player.insert{name="firearm-magazine", count=40}
  player.insert{name="burner-mining-drill", count = 2}
  player.insert{name="gun-turret", count = 1} 
  player.insert{name="stone-furnace", count = 1}
  player.force.chart(player.surface, {{player.position.x - 200, player.position.y - 200}, {player.position.x + 200, player.position.y + 200}})
end)

local function count_votes()
    global.voters = global.voters or {}
    local yes, no = 0, 0
    for _, vote in pairs(global.voters) do
        if vote == true then
            yes = yes + 1
        elseif vote == false then
            no = no + 1
        end
    end
    return yes, no, yes > no
end

local function generate_new_world()
   local new_map = game.create_surface("new_map " .. map_num)
   for _, player in pairs(game.players) do
      player.teleport({0,0}, new_map)
      player.force.chart(new_map, {{player.position.x - 200, player.position.y - 200}, {player.position.x + 200, player.position.y + 200}})
   end
   for _, force in pairs(game.forces) do
      force.set_spawn_position({0,0}, new_map)
      global.tech_reset = true
   end
   	for _,surface in pairs(game.surfaces) do
		if surface.name == "nauvis" then
			for chunk in surface.get_chunks() do --so I delete its chunks
				surface.delete_chunk({chunk.x, chunk.y})
			end
		elseif not surface.name:find("Factory floor") and (surface.name ~= "new_map " .. global.map_num) then --don't delete factorissimo stuff or the new surface
		game.delete_surface(surface)
		end
	end
	global.map_num = global.map_num + 1
	global.rocket_launched = false
end      

local function end_voting(player)
    if global.voting_type then
        if global.voting_type == "end_vote" then
            if select(3, count_votes()) then            
                    game.print("The majority has voted to end the round.")
                generate_new_world()
                   else              
                    game.print("The majority has voted to continue the round.")
            end
         end
      end
   global.voters = nil
    global.voting_ends = nil
    global.voting_type = nil
end
      
local function process_vote(player_index, yes_or_no)
        global.voters = global.voters or {}
            if global.voters[player_index] == nil then
                global.voters[player_index] = yes_or_no
                local yes, no = count_votes()
                    game.players[player_index].print("You have voted to " .. (yes_or_no and "end" or "continue") .. " the round.")
                    game.players[player_index].print("For: " .. yes .. " Against: " .. no)
    end
end

commands.add_command(
    "yes",
    "Vote Yes",
    function(e)
        process_vote(e.player_index, true)
    end
)

commands.add_command(
    "no",
    "Vote No",
    function(e)
        process_vote(e.player_index, false)
    end
)


commands.add_command(
    "over",
    "Start a vote to end the map.",
    function(e)
        --first argument to /over is the time to wait before declaring a winner in minutes, defaults to 1 minute
        global.voting_ends = game.tick + ((e.parameter and (tonumber(e.parameter)) or 1 ) * 15 * 15)
        global.voting_type = "end_vote"
        global.voters = {}
        game.print(game.players[e.player_index].name .. " has started a vote to end the map, type /yes or /no to vote.")
        game.print("Voting will end in 60 seconds!")
    end
)

-- register tick handler, or add it your current tick handler
script.on_event(
    defines.events.on_tick,
    function(e)
        if e.tick == global.voting_ends then
            end_voting()
        end
    end)

script.on_event(defines.events.on_player_respawned, function(event)
  local player = game.players[event.player_index]
  player.insert{name="pistol", count=1}
  player.insert{name="firearm-magazine", count=10}
end)

script.on_event(defines.events.on_gui_click, function(event)
  silo_script.on_gui_click(event)
end)

script.on_event(defines.events.on_rocket_launched, function(event)
  silo_script.on_rocket_launched(event)
end)

script.on_configuration_changed(function(event)
  if global.version ~= version then
    global.version = version
  end
  silo_script.on_configuration_changed(event)
end)

silo_script.add_remote_interface()
Post Reply

Return to “Modding help”