17
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-11-06 15:08:36 +01:00

multiplayer stage 5: the authority decides which events fire

Every peer used to evaluate event conditions for itself and put the results
straight into its own queue, so the same event could fire twice, or on one
machine only. Worse, the launchers were polled around Global.pCamera, which in
a session means "wherever one particular player happens to be looking".

Condition evaluation is now separated from execution:

    authority:  evaluate -> queueevent -> execute -> replicate
    client:     receive queueevent -> execute

- AddToQuery() takes the origin of the request. A locally evaluated launch on a
  client is dropped, on the host it is handed to the session as the ordinary
  queueevent command and comes back to be carried out by everybody, itself
  included, so it happens exactly once per peer. Scenario init (onstart,
  negative delay) and the children of an already replicated event are marked as
  authority decisions and run in place, since they are identical everywhere.
  With no session running, both branches collapse to the old behaviour
- queueevent now carries the delay as well
- event launchers are polled around every crewed vehicle instead of around the
  local camera, and a cell is polled at most once per frame no matter how many
  players stand near it - launcher activation counters are stateful
- Events.update() still services the queue on a client, with its delays and its
  execution; only the condition checking is skipped there

An event whose request is still travelling is not requested again, with a
timeout so that a lost request cannot silence it for good. Instant (AddValues)
events are exempt from that guard, because every one of their additions has to
get through.
This commit is contained in:
2026-09-06 19:09:19 +00:00
parent c3bf261934
commit 4870935983
7 changed files with 172 additions and 25 deletions

View File

@@ -21,6 +21,14 @@ http://mozilla.org/MPL/2.0/.
#include "scripting/lua.h"
#endif
// where a request to put an event in the queue came from. in a session only the
// authority evaluates conditions; everybody, the authority included, runs the event when
// it comes back as a replicated queueevent, so it fires exactly once on every peer
enum class event_launch {
evaluation, // somebody's local condition check
authority // decided by the session authority, or by deterministic scenario init
};
// common event interface
class basic_event {
@@ -98,6 +106,7 @@ public:
double m_delay { 0.0 };
double m_delayrandom { 0.0 }; // zakres dodatkowego opóźnienia // standardowo nie będzie dodatkowego losowego opóźnienia
double m_delaydeparture { std::numeric_limits<double>::quiet_NaN() }; // departure-based event delay
double m_replicationtime { -1.0 }; // when the authority last handed this one to the session
protected:
// types
@@ -683,7 +692,8 @@ public:
}
// legacy method, inserts specified event in the event query
bool
AddToQuery( basic_event *Event, TDynamicObject const *Owner, double delay = 0.0 );
AddToQuery( basic_event *Event, TDynamicObject const *Owner, double delay = 0.0,
event_launch const Source = event_launch::evaluation );
// legacy method, executes queued events
bool
CheckQuery();
@@ -719,6 +729,11 @@ private:
basic_table<TEventLauncher> m_radiodrivenlaunchers;
eventlauncher_sequence m_launcherqueue;
command_relay m_relay;
// methods
// hands a locally evaluated launch over to the session, so that it reaches every peer
// through the ordinary queueevent command instead of firing here alone
bool
defer_to_authority( basic_event *Event, TDynamicObject const *Owner, double delay );
};