non MP-safe WML
Moderator: Forum Moderators
Forum rules
- Please use [code] BBCode tags in your posts for embedding WML snippets.
- To keep your code readable so that others can easily help you, make sure to indent it following our conventions.
non MP-safe WML
The old thread was getting pretty outdated, so I am putting a new one up to list and/or discuss any WML technique which is known to cause OOS (Out-Of-Sync errors) in multiplayer. It should also be noted that any technique known to cause OOS errors in multiplayer would also probably cause corruption of saved replays in single player.
1.) "ai turn" event - the ai turn event is only fired on the hosting client so no changes to the gamestate should be performed. Historically this event was used to set goto_x and goto_y for some ai controlled units, then when the units moved it would synchronize their movement across all the clients (although the contents of unit.goto_x and unit.goto_y were only changed on the host)
2.) "select" event - the select event is not synchronized across clients so no changes to the gamestate should be based on the select event. However, graphical changes, sound effects, or purely informational messages (without options) can be triggered by the select event without causing OOS.
One notable exception to this rule is [set_menu_item] needs_select=yes which will cause the most recent select event to be sent to all clients, thus allowing changes to the game based on that select event. However there is a known bug with needs_select which may still cause OOS when a moveto event was also triggered.
3.) controller variable stored by [store_side] - the stored_side.controller variable will be different for each client, so no changes to the gamestate should be based upon the contents of this variable.
4.) [set_variable] time=stamp - obviously the result of this operation will be different for all clients, so no changes to the gamestate should be based upon the contents of this variable. It is useful for WML performance testing.
EDIT:
5) $unit.goto_x $unit.goto_y variables eigher stored automaticly or manually with [store_unit] is not MP save use wesnoth.synchnoize_choice or [sync_variable] (wesnoth 1.13 or later) if you use these in synced events.
6) $unit.facing might be unsynced under some conditions
1.) "ai turn" event - the ai turn event is only fired on the hosting client so no changes to the gamestate should be performed. Historically this event was used to set goto_x and goto_y for some ai controlled units, then when the units moved it would synchronize their movement across all the clients (although the contents of unit.goto_x and unit.goto_y were only changed on the host)
2.) "select" event - the select event is not synchronized across clients so no changes to the gamestate should be based on the select event. However, graphical changes, sound effects, or purely informational messages (without options) can be triggered by the select event without causing OOS.
One notable exception to this rule is [set_menu_item] needs_select=yes which will cause the most recent select event to be sent to all clients, thus allowing changes to the game based on that select event. However there is a known bug with needs_select which may still cause OOS when a moveto event was also triggered.
3.) controller variable stored by [store_side] - the stored_side.controller variable will be different for each client, so no changes to the gamestate should be based upon the contents of this variable.
4.) [set_variable] time=stamp - obviously the result of this operation will be different for all clients, so no changes to the gamestate should be based upon the contents of this variable. It is useful for WML performance testing.
EDIT:
5) $unit.goto_x $unit.goto_y variables eigher stored automaticly or manually with [store_unit] is not MP save use wesnoth.synchnoize_choice or [sync_variable] (wesnoth 1.13 or later) if you use these in synced events.
6) $unit.facing might be unsynced under some conditions
Last edited by Pentarctagon on May 29th, 2017, 2:34 pm, edited 2 times in total.
Reason: removed note about [set_variable] random=
Reason: removed note about [set_variable] random=
http://www.wesnoth.org/wiki/User:Sapient... "Looks like your skills saved us again. Uh, well at least, they saved Soarin's apple pie."
-
- Inactive Developer
- Posts: 2461
- Joined: August 15th, 2008, 8:46 pm
- Location: Germany
Re: non MP-safe WML
An exception is the case that the controller of a side is "null", which happens if and only if it is "null" on all other clients as well.Sapient wrote:3.) controller variable stored by [store_side] - the stored_side.controller variable will be different for each client, so no changes to the gamestate should be based upon the contents of this variable
Support is actually removed now, use rand= instead.Sapient wrote:4.) [set_variable] random= - unsafe for MP and deprecated. use [set_variable] rand= instead
-Any toplevel tag other than [multiplayer] is never submitted over the network (as well as [binary_path] data). Thus if players happen to have not the same version of an addon they can get OOS e.g. if a custom unit's hitpoints changed between these versions.
================
non mp-safe lua:
-wesnoth.game_config.debug, .version have (possibly) different values
-using wesnoth.show_dialog to query input from a client.
-math.random
-os.time, os.clock, os.date
-wesnoth.sides.controller (same as with [store_side])
-any non mp-safe wml tag called by lua, and any lua called from a non mp-safe wml event
Most of these cases should be solvable by usage of wesnoth.synchronize_choice.
Last edited by gfgtdf on December 13th, 2015, 4:36 pm, edited 3 times in total.
Reason: removed note about random_start_time=yes and helper.rand which does not cause OOS.
Reason: removed note about random_start_time=yes and helper.rand which does not cause OOS.
projects (BfW 1.12):
A Simple Campaign: campaign draft for wml starters • Plan Your Advancements: mp mod
The Earth's Gut: sp campaign • Settlers of Wesnoth: mp scenario • Wesnoth Lua Pack: lua tags and utils
updated to 1.8 and handed over: A Gryphon's Tale: sp campaign
A Simple Campaign: campaign draft for wml starters • Plan Your Advancements: mp mod
The Earth's Gut: sp campaign • Settlers of Wesnoth: mp scenario • Wesnoth Lua Pack: lua tags and utils
updated to 1.8 and handed over: A Gryphon's Tale: sp campaign
Re: non MP-safe WML
Are custom events safe if triggered from inside a synchronized event?
Re: non MP-safe WML
No... but you can do all the operatons that need multiplayer safety in the syncronized event (like generate a random number); then you can trigger your custom event using the value generated without problem.H-Hour wrote:Are custom events safe if triggered from inside a synchronized event?
A side note to Devs: in 1.10 the recall event is not as safe as recruit event. I had to hack completely the AI recalls because try to apply WML that were working for AI recruits directly crashed Wesnoth when used in recall event.
Be aware English is not my first language and I could have explained bad myself using wrong or just invented words.
World Conquest II
World Conquest II
Re: non MP-safe WML
I had hoped that gfgtdf would post here since he made a bunch of changes surrounding this in 1.11.13. Many events that previously were not safe are now safe, and you can be more liberal in your use of wesnoth.synchronize_choice.tekelili wrote: A side note to Devs: in 1.10 the recall event is not as safe as recruit event. I had to hack completely the AI recalls because try to apply WML that were working for AI recruits directly crashed Wesnoth when used in recall event.
It's not clear to me from reading the source code if recall is a safe event though, it looks like AI recalls and even whiteboard planned recalls might be? but human are not. I think part of the issue is that a unit may advance upon being recalled, prompting a user choice, which makes the whole process more complicated to properly synchronize. Hopefully someone can clarify the current situation...
Re: non MP-safe WML
I have never used custom event since i usually code nearly everything in lua when coding addons, so i have never tested, but from looking at the code i see no reason why they shouldn't be synced.H-Hour wrote:Are custom events safe if triggered from inside a synchronized event?
you mean in 1.10 or 1.11.13+ ? in 1.11.13+ both types (ai and human) call the same run_in_synced_context to recall.iceiceice wrote:I had hoped that gfgtdf would post here since he made a bunch of changes surrounding this in 1.11.13. Many events that previously were not safe are now safe, and you can be more liberal in your use of wesnoth.synchronize_choice.tekelili wrote: A side note to Devs: in 1.10 the recall event is not as safe as recruit event. I had to hack completely the AI recalls because try to apply WML that were working for AI recruits directly crashed Wesnoth when used in recall event.
It's not clear to me from reading the source code if recall is a safe event though, it looks like AI recalls and even whiteboard planned recalls might be? but human are not. I think part of the issue is that a unit may advance upon being recalled, prompting a user choice, which makes the whole process more complicated to properly synchronize. Hopefully someone can clarify the current situation...
units usually cannot advance when beeing recalled (at least i haven't seeen any code for that). Currently we only check whether a unit can advance after unstore_unit and after attacks (we call the attack_unit_and_advance function in actions/attack.cpp).
https://github.com/wesnoth/wesnoth/blob ... s.cpp#L735
https://github.com/wesnoth/wesnoth/blob ... s.cpp#L614
and the "recall" event is fired inside the place_recruit function, so i see no reason why the recall event shouldn't be fired in a replay.but ofc it's possible to execute.
I also dont know very much about the 10.7 behaviour because from 1.10.7 to when i satrted that patch, there were already much changes in that code.
Scenario with Robots SP scenario (1.11/1.12), allows you to build your units with components, PYR No preperation turn 1.12 mp-mod that allows you to select your units immideately after the game begins.
Re: non MP-safe WML
I was only talking about 1.11.13+. Thanks for clarifying, gfgtdf.
Re: non MP-safe WML
Only dialog on lua is non mp-safe or WML dialog with input is non mp-safe too ?Anonymissimus wrote: non mp-safe lua:
-any dialog wich queries input from a client
Most of these cases should be solvable by usage of wesnoth.synchronize_choice.
If WML is non safe, Please make 1 example to people (which very good know how to use WML but completely not know how to use lua) how to fix "WML dialog with input" by wesnoth.synchronize_choice ?
(for example) shortest message with input (player receive message with choice during his turn):
Code: Select all
[message]
speaker=Sadek
message= _ "A tribute of 20 gold must be paid by all new owners of this castle."
[option]
message= _ "Very well, here's 20 gold."
[command]
[gold]
amount=-20
side=3
[/gold]
{VARIABLE player3_choice 1}
[kill]
id=Sadek
[/kill]
[/command]
[/option]
[option]
message= _ "I will not pay! Get lost!"
[command]
{VARIABLE player3_choice 2}
[/command]
[/option]
[/message]
I ask this, because I have used search on google and search on the forum, and not detect any example how to use lua "wesnoth.synchronize_choice" with WML.
Re: non MP-safe WML
Thread #1myav wrote:
How to fix it with wesnoth.synchronize_choice ?
I ask this, because I have used search on google and search on the forum, and not detect any example how to use lua "wesnoth.synchronize_choice" with WML.
Thread #2 (Started at the relevant point)
Thread #3 (Others troubleshooting)
Mainline Maintainer: AOI, DM, NR, TB and THoT.
UMC Maintainer: Forward They Cried, A Few Logs, A Few More Logs, Start of the War, and Battle Against Time
UMC Maintainer: Forward They Cried, A Few Logs, A Few More Logs, Start of the War, and Battle Against Time
Re: non MP-safe WML
Turk, you not see my question? All 3 your links are useless for this my example
(we not see in that links any example about gold changing in answer, about set variable in answer and about killing unit in answer, and all this - with lua wesnoth.synchronize_choice)
So, if you know how to make it - please help with my example. if you not know -we will wait for Anonymissimus and I hope that he know how to fix.
Re: non MP-safe WML
I did see your question, and I'm well aware that those topics did not do your work for you. I was providing relevant threads that gave functional examples and discussion on the capabilities and limitations of wesnoth.synchronize_choice to help you figure it out.myav wrote: Turk, you not see my question? All 3 your links are useless for this my example
Mainline Maintainer: AOI, DM, NR, TB and THoT.
UMC Maintainer: Forward They Cried, A Few Logs, A Few More Logs, Start of the War, and Battle Against Time
UMC Maintainer: Forward They Cried, A Few Logs, A Few More Logs, Start of the War, and Battle Against Time
Re: non MP-safe WML
I adapted one of the examples on the wiki, maybe it helps you. I didn't test it though, so it may be completely wrong.
I hope this is right and I didn't mess up any brackets when getting rid of the set_wml_tag_metatable and that wesnoth.set_variable("value",result.value) makes sense.
Edit: If you want to change gold etc you can do it after the lua stuff with if...then... . Don't do it inside synchronize_choice as it would then only apply it the side which makes the choice.
Code: Select all
[event]
name = "start"
[lua]
code = <<
wesnoth.set_variable("input1",nil)
local result = wesnoth.synchronize_choice(
function()
local option1 = {"option", { message = "No", {"command", { {"set_variable", { name = "input1", value = "No"}}}}}}
local option2 = {"option", { message = "Yes", {"command", { {"set_variable", { name = "input1", value = "Yes"}}}}}}
wesnoth.fire({"message", { message = "Are you sure you want to play this game?", option1, option2}})
return { value = wesnoth.get_variable("input1") }
end,
function()
return { value = math.random(30) }
end)
wesnoth.set_variable("input1",nil)
wesnoth.set_variable("value",result.value)
>>
[/lua]
#now put your remaining WML here, the result of the choice should be in the variable value.
[/event]
Edit: If you want to change gold etc you can do it after the lua stuff with if...then... . Don't do it inside synchronize_choice as it would then only apply it the side which makes the choice.
Re: non MP-safe WML
@Vanagandr
The wiki says this example is 1.13 only, especialy in 1.10 this is most likeley a OOS.
The wiki says this example is 1.13 only, especialy in 1.10 this is most likeley a OOS.
EDIT: ok i saw you modified thids example, but still wouldn't say this is safe in 1.10. Usualy you don't need synconize_choice for wml menus. And expecialy in 1.10 i woudn't recomment to use [message][option] together with synconize_choiceVanagandr wrote:I adapted one of the examples on the wiki, maybe it helps you. I didn't test it though, so it may be completely wrong.I hope this is right and I didn't mess up any brackets when getting rid of the set_wml_tag_metatable and that wesnoth.set_variable("value",result.value) makes sense.Code: Select all
[event] name = "start" [lua] code = << wesnoth.set_variable("input1",nil) local result = wesnoth.synchronize_choice( function() local option1 = {"option", { message = "No", {"command", { {"set_variable", { name = "input1", value = "No"}}}}}} local option2 = {"option", { message = "Yes", {"command", { {"set_variable", { name = "input1", value = "Yes"}}}}}} wesnoth.fire({"message", { message = "Are you sure you want to play this game?", option1, option2}}) return { value = wesnoth.get_variable("input1") } end, function() return { value = math.random(30) } end) wesnoth.set_variable("input1",nil) wesnoth.set_variable("value",result.value) >> [/lua] #now put your remaining WML here, the result of the choice should be in the variable value. [/event]
Edit: If you want to change gold etc you can do it after the lua stuff with if...then... . Don't do it inside synchronize_choice as it would then only apply it the side which makes the choice.
Scenario with Robots SP scenario (1.11/1.12), allows you to build your units with components, PYR No preperation turn 1.12 mp-mod that allows you to select your units immideately after the game begins.
Re: non MP-safe WML
I did adapt it so that it doesn't use the sides option which is exclusive to 1.13. Do you mean it would cause OOS because of math.random?
Re: non MP-safe WML
i added an edit in teh answer above.Vanagandr wrote:I did adapt it so that it doesn't use the sides option which is exclusive to 1.13. Do you mean it would cause OOS because of math.random?
[message] with [option] uses the same code as wesnoth.synconize_choice internaly to be mpsafe. if you use [message] with [option] inside a wesnoth.synconize_choice. than this is somilary to using wesnoth.synconize_choice inside wesnoth.synconize_choice. Wesnoth 1.11.15+ is able to notice that we are already in a local choice and just executes the fnction passed to wesnoth.synconize_choice like a normal function call. But i cannot tell whether that is true for 1.10 too.
The example in the wiki uses wesnoth.synconize_choice with [message] with [option] becasue it wants to show that message on multiple clients. So it needes this 1.13 feature. If you just want to show the message on one client you don't need wesnoth.synconize_choice
Scenario with Robots SP scenario (1.11/1.12), allows you to build your units with components, PYR No preperation turn 1.12 mp-mod that allows you to select your units immideately after the game begins.