non MP-safe WML

The place to post your WML questions and answers.

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.
User avatar
Sapient
Inactive Developer
Posts: 4453
Joined: November 26th, 2005, 7:41 am
Contact:

non MP-safe WML

Post by Sapient »

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
Last edited by Pentarctagon on May 29th, 2017, 2:34 pm, edited 2 times in total.
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."
Anonymissimus
Inactive Developer
Posts: 2461
Joined: August 15th, 2008, 8:46 pm
Location: Germany

Re: non MP-safe WML

Post by Anonymissimus »

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
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:4.) [set_variable] random= - unsafe for MP and deprecated. use [set_variable] rand= instead
Support is actually removed now, use 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.
projects (BfW 1.12):
A Simple Campaign: campaign draft for wml startersPlan Your Advancements: mp mod
The Earth's Gut: sp campaignSettlers of Wesnoth: mp scenarioWesnoth Lua Pack: lua tags and utils
updated to 1.8 and handed over: A Gryphon's Tale: sp campaign
H-Hour
Posts: 222
Joined: April 14th, 2010, 12:27 pm

Re: non MP-safe WML

Post by H-Hour »

Are custom events safe if triggered from inside a synchronized event?
User avatar
tekelili
Posts: 1039
Joined: August 19th, 2009, 9:28 pm

Re: non MP-safe WML

Post by tekelili »

H-Hour wrote:Are custom events safe if triggered from inside a synchronized event?
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.

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
User avatar
iceiceice
Posts: 1056
Joined: August 23rd, 2013, 2:10 am

Re: non MP-safe WML

Post by iceiceice »

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.
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.

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...
gfgtdf
Developer
Posts: 1432
Joined: February 10th, 2013, 2:25 pm

Re: non MP-safe WML

Post by gfgtdf »

H-Hour wrote:Are custom events safe if triggered from inside a synchronized event?
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.
iceiceice wrote:
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.
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.

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...
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.
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.
User avatar
iceiceice
Posts: 1056
Joined: August 23rd, 2013, 2:10 am

Re: non MP-safe WML

Post by iceiceice »

I was only talking about 1.11.13+. Thanks for clarifying, gfgtdf.
myav
Posts: 85
Joined: August 23rd, 2008, 12:53 pm

Re: non MP-safe WML

Post by myav »

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.
Only dialog on lua is non mp-safe or WML dialog with input is non mp-safe too ?

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]
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.
User avatar
Turuk
Sithslayer
Posts: 5283
Joined: February 28th, 2007, 8:58 pm
Contact:

Re: non MP-safe WML

Post by Turuk »

myav 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 #1
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
myav
Posts: 85
Joined: August 23rd, 2008, 12:53 pm

Re: non MP-safe WML

Post by myav »

Turuk wrote: Thread #1
Thread #2 (Started at the relevant point)
Thread #3 (Others troubleshooting)
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.
User avatar
Turuk
Sithslayer
Posts: 5283
Joined: February 28th, 2007, 8:58 pm
Contact:

Re: non MP-safe WML

Post by Turuk »

myav wrote: Turk, you not see my question? All 3 your links are useless for this my example
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.
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
Vanagandr
Posts: 36
Joined: May 17th, 2014, 5:48 pm

Re: non MP-safe WML

Post by Vanagandr »

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.

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]
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.
gfgtdf
Developer
Posts: 1432
Joined: February 10th, 2013, 2:25 pm

Re: non MP-safe WML

Post by gfgtdf »

@Vanagandr

The wiki says this example is 1.13 only, especialy in 1.10 this is most likeley a OOS.
Vanagandr 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.

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]
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.
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_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.
Vanagandr
Posts: 36
Joined: May 17th, 2014, 5:48 pm

Re: non MP-safe WML

Post by Vanagandr »

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?
gfgtdf
Developer
Posts: 1432
Joined: February 10th, 2013, 2:25 pm

Re: non MP-safe WML

Post by gfgtdf »

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?
i added an edit in teh answer above.

[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.
Post Reply