Follow-up Comment #7, bug #15560 (project wesnoth):

This breaks down like this:

We have three contexts in the code at present, I can't find meaningful names,
so lets call them R, W and S'.

In R, only one host is making decisions, other hosts are simply mirroring
those decisions at a later date in the replay. Out of sync is impossible
providing all decisions are included in the replay.

In W, all hosts are making decisions. Out of sync is impossible providing the
same criteria are used at each host.

In S', one host is making decisions, and its decisions are injected into the
current turn's replay. It is assumed that by the time any other host comes to
this decision, it is reading the replay and this choice is available.

The problem is (ultimately) that unstore_unit advance=true occurs in W, but
is fundamentally ill-posed in W, because we potentially allow a player to
choose the advancement, and the player only exists at one machine. By the
logic of the current code it should occur in S', except that unstore_unit
need not occur in a turn (it can occur in start or prestart events for
example). In addition, the correctness of S' as it is in the current code is
hard to be sure of.

There are two ways of going about this:
- maintain unstore unit in W and remove anything that can violate Ws
semantics.
- introduce a new context, say S, with independent synchronization.

Option 1: Removing anything that can violate W.

You prevent players from choosing the advancement resulting from this tag in
multiplayer. It's always random. Basically this option represents the
decision: things are complicated enough in networking, we don't have time to
rewrite right now to make it more clear what's happening, and we don't want
to deal with fine-grained synchronization.

Option 2: Introduce a synchronized context S

S would be a stronger version of S': anything that occurs in S sends or
receives its own message, without any link to the replay. The technical
problem here is that you need to provide access to the network, and you need
a message queue: you're going to transmit your sync info immediately, which
means it arrives before the current turn's replay, thus must be identified
and stored for you. If there is no current turn, however, this will work.
Probably S' should be migrated to S too if this happens.

A sensible design might look like:

[wml_sync] top level message in the network protocol, children are what event
fired it, and what it wants to communicate.

singleton wml_event_network_handler object:
- access to a queue of wml event sync entries received
- ability to send a sync entry to the network

This must guarantee the ordering of send and receive. 

wml_event_handlers:
- at any point where there is a user decision, they either call:
== wml_event_network_handler::send(who_am_i, what_i_decided)
- or
== what_was_decided = wml_event_network_handler::receive(who_am_i) 

Initial dispatch [i think in playmp_controller/need to check]:
- calls wml_event_network_handler::queue(opaque_sync_message)

This must maintain the order it got the sync messages in (which shouldn't be
a problem).

I'm willing to implement either of these options if people think this is the
correct way to go. I'm open to suggestions too!

    _______________________________________________________

Reply to this item at:

  <http://gna.org/bugs/?15560>

_______________________________________________
  Message sent via/by Gna!
  http://gna.org/


_______________________________________________
Wesnoth-bugs mailing list
[email protected]
https://mail.gna.org/listinfo/wesnoth-bugs

Reply via email to