#4310 closed defect (fixed)
[PATCH] OOS on rejoin - Survival of the fittest
Reported by: | elexis | Owned by: | elexis |
---|---|---|---|
Priority: | Release Blocker | Milestone: | Alpha 21 |
Component: | UI & Simulation | Keywords: | patch |
Cc: | Patch: |
Attachments (2)
Change History (9)
by , 7 years ago
Attachment: | oos_survival.7z added |
---|
comment:1 by , 7 years ago
Priority: | Should Have → Must Have |
---|
comment:2 by , 7 years ago
Correction after some discussions with Itms and more debugging:
The Trigger
component does serialize playerCivicCenter
.
The rejoined client executes survivalofthefittest_triggers.js
, then deserializes the components.
Thus the DoAfterDelay
part is never executed for the rejoined client and playerCivicCenter = {}
is not responsible for that variable being empty. This can be verified by patching:
Index: binaries/data/mods/public/simulation/components/Trigger.js =================================================================== --- binaries/data/mods/public/simulation/components/Trigger.js (revision 18902) +++ binaries/data/mods/public/simulation/components/Trigger.js (working copy) @@ -32,10 +32,43 @@ Trigger.prototype.Init = function() // Each event has its own set of actions determined by the map maker. for (let eventName of this.eventNames) this["On" + eventName + "Actions"] = {}; }; +Trigger.prototype.Serialize = function() +{ + let state = {}; + for (var key in this) + { + if (!this.hasOwnProperty(key)) + continue; + + if (typeof this[key] == "function") + continue; + //warn("serializing: " + key + " = " + uneval(this[key])); + state[key] = this[key]; + } + return state; +}; + +Trigger.prototype.Deserialize = function(data) +{ + for (let key in data) + { + if (!data.hasOwnProperty(key)) + continue; + + if (key == "playerCivicCenter") + warn("deserializing: " + key + " = " + uneval(data[key])); + this[key] = data[key]; + } +}; + Trigger.prototype.RegisterTriggerPoint = function(ref, ent) { if (!this.triggerPoints[ref]) this.triggerPoints[ref] = []; this.triggerPoints[ref].push(ent);
comment:3 by , 7 years ago
Keywords: | patch review added |
---|---|
Summary: | OOS on rejoin - Survival of the fittest → [PATCH] OOS on rejoin - Survival of the fittest |
Found the actual issue: the code does not use the correct syntax for accessing the trigger component. Inside the prototype functions, this
should be used.
The syntax used at the end of the file should only be used there, because that code is called upon script files loading, not during the game. Using cmpTrigger
probably populates an outdated version of the component object, or even goes into the void when doing that on a rejoined client.
by , 7 years ago
Attachment: | survivalofthefittest_triggers.patch added |
---|
comment:6 by , 7 years ago
Keywords: | review removed |
---|---|
Priority: | Must Have → Release Blocker |
Thanks for the patch Itms, what a nasty bug again! Also edited wiki:Triggers.
The players are not defeated for the rejoined client!
Reproduce: I can reproduce the issue by rejoining after the first wave spawned, just before it defeats players. Press F9 and type
Engine.SetSimRate(20);
on all clients to fast forward or just settime
inInitializeEnemyWaves
to something short in milliseconds andattackerCount
to something that doesn't depend on the time.You have to test with 2 or more players, as one player will have won immediately, thus infinite enemy waves spawn but only standing around.
Interpretation: The
OwnershipChange
of the CivicCenter is triggered for both players, butTriggerHelper.DefeatPlayer
is only executed for the host, not for the rejoined client, which must mean thatcmpTrigger.playerCivicCenter
differs for the two clients. Since that variable is constructed inInitGame
, testing for that revealed that this method isn't executed for the rejoined client at all. Looking at the code, we can easily find the reason:cmpTrigger.DoAfterDelay(0, "InitGame", {});
that means it will init that array on turn 0, everyone who rejoined later gets the empty object. Argh.