Page 1 of 1

Multiplayer Desync on Item Creation

Posted: Thu Apr 14, 2016 8:55 pm
by AenAllAin
I wrote a pretty simple mod of a wall with an invisible electric pole as a helper entity. I got it to work in single-player just fine; however, when I play multiplayer the game desyncs every time one of the item pairs is placed. I was hoping someone would know a very basic multiplayer mistake I am making creating additional items in the "on_built_entity" event handler ...if not, I can post the code and the logs. Thanks.

Re: Multiplayer Desync on Item Creation

Posted: Thu Apr 14, 2016 8:59 pm
by prg
Having the actual code to look at instead of making wild guesses would be useful.

Re: Multiplayer Desync on Item Creation

Posted: Thu Apr 14, 2016 9:06 pm
by AenAllAin
prg wrote:Having the actual code to look at instead of making wild guesses would be useful.
I'll post the code when I get home ...but like I said, I was hoping there was a simple/common explanation since it happened so consistently and immediately.

Re: Multiplayer Desync on Item Creation

Posted: Thu Apr 14, 2016 9:12 pm
by prg
Not putting things that need to survive a save/load into global would be a likely reason. Or you might be printing some debug information that contains table addresses which are allocated differently on every system. First things that come to mind...

Re: Multiplayer Desync on Item Creation

Posted: Thu Apr 14, 2016 9:34 pm
by AenAllAin

Code: Select all

function init_powered_walls()
	script.on_event(defines.events.on_built_entity, build_powered_wall)
	script.on_event(defines.events.on_robot_built_entity, build_powered_wall)
	script.on_event(defines.events.on_preplayer_mined_item, mined_powered_wall)
	script.on_event(defines.events.on_robot_pre_mined, mined_powered_wall)
	script.on_event(defines.events.on_entity_died, death_powered_wall)
end

...

function build_powered_wall(event)
	local entity = event.created_entity
	if entity and entity.name == "powered-wall-wall" then
		local l_name = "powered-wall-pole"
		local l_surface = game.get_surface(game.players[event.player_index].surface.name)
		local l_force = entity.force
		local l_position = entity.position
		local l_wall = entity
		local l_pole = l_surface.create_entity{name = l_name, position = l_position, force = l_force}

		group_entities(cantor(l_position.x,l_position.y), { l_wall, l_pole })
	end
end
Here is a snippet of the relevant portion; this causes a guaranteed desync on placement every time in multiplayer, but still works and creates both entities; no issue manifests in single-player.

Re: Multiplayer Desync on Item Creation

Posted: Thu Apr 14, 2016 9:37 pm
by AenAllAin
I also, tried changing it to a queued a-sync event that triggers on tick update, but that still desyncs.

Re: Multiplayer Desync on Item Creation

Posted: Thu Apr 14, 2016 9:45 pm
by prg
What's group_entities and cantor?

(A problem for later: in on_robot_built_entity, event won't contain a player_index)

Re: Multiplayer Desync on Item Creation

Posted: Thu Apr 14, 2016 9:50 pm
by AenAllAin
prg wrote:What's group_entities and cantor?

(A problem for later: in on_robot_built_entity, event won't contain a player_index)
Yes; it is a work in progress.

Code: Select all

function group_entities(entity_groupid, entity_list)
	return group("entities", entity_groupid, entity_list)
end
...

Code: Select all

-- Grouping
--
function group(index_id, group_id, members)
	_init_group(index_id, group_id)

	if index_id == nil then
	 index_id = "default"
 	end

	if group_id then
		for ix, vx in ipairs(members) do
			_addto_group(index_id, group_id, vx)
		end
		return group_id
	else
		-- no GID, then assign one
		return group(index_id, _new_group(index_id), members)
	end
end
...

and "cantor"; Standard Cantor-type hash

Code: Select all

-------------------------------------------------------------------
-- Cantor Hash
-------------------------------------------------------------------
function cantor(k1, k2)
	return (0.5 * (k1+k2) * (k1+k2+1) + k2)
end
-------------------------------------------------------------------

Re: Multiplayer Desync on Item Creation

Posted: Thu Apr 14, 2016 9:51 pm
by Rseding91
AenAllAin wrote:

Code: Select all

function init_powered_walls()
	script.on_event(defines.events.on_built_entity, build_powered_wall)
	script.on_event(defines.events.on_robot_built_entity, build_powered_wall)
	script.on_event(defines.events.on_preplayer_mined_item, mined_powered_wall)
	script.on_event(defines.events.on_robot_pre_mined, mined_powered_wall)
	script.on_event(defines.events.on_entity_died, death_powered_wall)
end

...

function build_powered_wall(event)
	local entity = event.created_entity
	if entity and entity.name == "powered-wall-wall" then
		local l_name = "powered-wall-pole"
		local l_surface = game.get_surface(game.players[event.player_index].surface.name)
		local l_force = entity.force
		local l_position = entity.position
		local l_wall = entity
		local l_pole = l_surface.create_entity{name = l_name, position = l_position, force = l_force}

		group_entities(cantor(l_position.x,l_position.y), { l_wall, l_pole })
	end
end
Here is a snippet of the relevant portion; this causes a guaranteed desync on placement every time in multiplayer, but still works and creates both entities; no issue manifests in single-player.
You've excluded a vast amount of the code which almost certainly contains the trouble code.

Re: Multiplayer Desync on Item Creation

Posted: Thu Apr 14, 2016 9:57 pm
by AenAllAin
Rseding91 wrote:
AenAllAin wrote:...
You've excluded a vast amount of the code which almost certainly contains the trouble code.
Yes; I didn't want to just blast a bunch of text at first; I'll post the whole mod in .zip form after I get home.

I was hoping it was something simple and a standard noobie mistake, not something that needed your complete parse.

Re: Multiplayer Desync on Item Creation

Posted: Fri Apr 15, 2016 1:41 am
by AenAllAin
Here is the mod/code. The desync issue is now gone it seems ...don't know why exactly. I updated the version number and the recipe name, and it stopped desyncing. I think it had something to do with the recipe and the saved game I was using and nothing to do with the code. I might be able to replicate it with a previous version and the saved game if there is any interest; I dunno.