Multiplayer Compatible Help

Place to get help with not working mods / modding interface.
Post Reply
TheSAguy
Smart Inserter
Smart Inserter
Posts: 1449
Joined: Mon Jan 13, 2014 6:17 pm
Contact:

Multiplayer Compatible Help

Post by TheSAguy »

I don't play multiplayer myself and can't test my mod to see if it is, I was told that "game.player" is not multiplayer compatible and was hoping I could get some help to fix this.

I use "game.player" a few places in my Mod.
The attached mod has not yet been released. It's also here on GitHub

In "Natural_Evolution_Expansion_5.0.0" it is used in the below code:
If the player has build a Rocket Silo, I have the biters attack them by using: (so "game.player" is used twice here)

Code: Select all

			if global.RocketSiloBuilt > 0 then
				---- Attack the player, since you have a silo built
				game.player.surface.set_multi_command({type=defines.command.attack,target=game.player.character,distraction=defines.distraction.by_enemy},Enemy_Count)

			end 
I also use it to print the below message when the player builds a Rocket Silo.

Code: Select all

game.player.print("WARNING!")


In "Natural_Evolution_Enemies_5.0.0" it is used in the below code: (so "game.player" is used twice here)
If the player kills a spawner, I have the nearby enemies attack him:

Code: Select all

if event.entity.type == "unit-spawner" then
game.player.surface.set_multi_command({type=defines.command.attack,target=game.player.character,distraction=defines.distraction.by_enemy},(20+math.floor(game.evolution_factor*100)))
end



I'm not sure if the same goes for "game.players"
In "Natural_Evolution_Buildings_5.0.0" it is used in the below code:

Code: Select all

game.on_event(defines.events.on_tick, function(event)
	--	Evolution_MOD
	if event.tick % update_com_count == 0 then
		for index, player in ipairs(game.players) do
			if player.character then
				UpdateUnitsCommands(index)		
			end
		end
	end
end)
Thanks.
Attachments
Natural_Evolution_Expansion_5.0.0.zip
N.E. Expansion
(7.3 KiB) Downloaded 127 times
Natural_Evolution_Enemies_5.0.0.zip
N.E. Enemies
(119.05 KiB) Downloaded 114 times
Natural_Evolution_Buildings_5.0.0.zip
N.E. Buildings
(1.15 MiB) Downloaded 122 times

Outsider
Fast Inserter
Fast Inserter
Posts: 115
Joined: Sat Jan 10, 2015 12:23 am
Contact:

Re: Multiplayer Compatible Help

Post by Outsider »

You need to change all references to game.player, to a specific player object.. there are several ways to do that depending on where and how your functions are called.

Generally speaking if you are initializing any conflagration options specific to players you'd loop the game.players, you usually have to use this for any player specific code that runs inside the on_tick or on_init/load events.

Then you have events that come with a player_index, ex : on_built_entity, on_put_item, on_preplayer_mined_item, on_player_created, on_gui_click...

these should cover all the event you might be using in your mods, so let's say in one of your functions that handles the rocket silo, you'd have to change the function parameters to accept a player/player_index and then use that player object in your calls :

Code: Select all

function handleSilos(index) 
         player = game.players[index]
         if global.RocketSiloBuilt[index] > 0 then
            ---- Attack the player, since you have a silo built
                   player.surface.set_multi_command({type=defines.command.attack,target=game.player.character,distraction=defines.distraction.by_enemy},Enemy_Count)

         end
end
Note how you also should consider setting your globals scope per player or per force depending on what your mod does..

Your Enemies mod however might be a bit trickier - i haven't really looked at the full code, just your sample here, but i assume you are using the on_entity_died event which has no reference to a specific player. so not sure what you can do here to make it mp friendly other than looping and attacking all players, another option here tho would be to look for a nearby player based on the killed spawner position and a radius and that would give you the closest player who "probably" killed that spawner - not ideal but could work?

another thing to note that i ran into is how the player index is handled, i believe right now it depends on the join order and is tied to the player name.. so for instance if a player joined a game and later on disconnected and came back using the same name, he'd still have the same index.. if that player changed their name they'd have a new index, something to consider when doing mp work.. i personally just use the player indexes for configuration scope, but using the player name could be a viable option too.. haven't really play tested on mp enough to make up my mind on this.
Advanced Logistics System - Provides a detailed view of your logistics network and the items within it

TheSAguy
Smart Inserter
Smart Inserter
Posts: 1449
Joined: Mon Jan 13, 2014 6:17 pm
Contact:

Re: Multiplayer Compatible Help

Post by TheSAguy »

Outlander,

Thanks for your input.

For the Enemies Mod, Let's say I want to cycle through the players and attack them all when a spawner is killed, would I do it this way:

Code: Select all

	
if event.entity.type == "unit-spawner" then
        for i = 1, #game.players, 1 do
	      player = game.players[i]
	      player.surface.set_multi_command({type=defines.command.attack,target=player.character,distraction=defines.distraction.by_enemy},20)
      end
end
I'm still looking into your answer on the silo's. So you created a function, but now I need to figure out how to call it :)

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

Re: Multiplayer Compatible Help

Post by jorgenRe »

This is how i do it to cycle through all the players to write in the console for all:

Code: Select all

function message(mes)
  for i, player in ipairs(game.players) do
    player.print(mes)
  end
end
The player.print(mes) can be changed to whatever you want to do with each player.
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

Outsider
Fast Inserter
Fast Inserter
Posts: 115
Joined: Sat Jan 10, 2015 12:23 am
Contact:

Re: Multiplayer Compatible Help

Post by Outsider »

TheSAguy wrote:Outlander,

Thanks for your input.

For the Enemies Mod, Let's say I want to cycle through the players and attack them all when a spawner is killed, would I do it this way:

Code: Select all

	
if event.entity.type == "unit-spawner" then
        for i = 1, #game.players, 1 do
	      player = game.players[i]
	      player.surface.set_multi_command({type=defines.command.attack,target=player.character,distraction=defines.distraction.by_enemy},20)
      end
end
I'm still looking into your answer on the silo's. So you created a function, but now I need to figure out how to call it :)
i was thinking more like finding player entities around the spawner that died and sending attacks at those players or maybe one of them.. but it's up to you if you want to send the attack to all players on the map.

the code below is untested so it might not work right away, it basically searches for player entities in a specific radius around a dead spawner and sends attacks to all the players found.

Code: Select all

game.on_event(defines.events.on_entity_died, function(event)
   if event.entity.type == "unit-spawner" then
       local surface = game.get_surface(0) -- i'm really not sure how surfaces work between different forces and entities so i mostly use this.
       local radius = 25
       local pos = event.entity.position
       local area = {{pos.x - radius, pos.y - radius}, {pos.x + radius, pos.y + radius}}

       -- find nearby players
       local players = surface.find_entities_filtered{area=area, type="player"}

        -- send attacks to all nearby players
        for i,player in pairs(players) do
            surface.set_multi_command({type=defines.command.attack,target=player.character,distraction=defines.distraction.by_enemy},(20+math.floor(game.evolution_factor*100)))
        end

   end
end)
as for the silos, you'd call that function in an on_entity_built event like so :

Code: Select all

game.on_event(defines.events.on_built_entity, function(event)
    local index = event.player_index
    if index then
        handleSilos(index)
    end
end)
you obviously can do checks here to see if the entity being built is actually a rocket silo.. you don't even need a function you can have the whole code right on the event callback itself.
Advanced Logistics System - Provides a detailed view of your logistics network and the items within it

Post Reply

Return to “Modding help”