refactor(engine-ambient): ViewerId/RealTimeNetworkAgent/BattleRecoveryInfo read ambient first
Step 4 of multi-instancing migration. Three additional per-battle statics front-fronted by BattleAmbient.Current, each with a static fallback for unwrapped callers. ViewerId's SavedataManager-persisting setter is preserved on the fallback path; inside a scope, the setter is a no-op (the per-battle perspective is fixed at scope entry). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -178,7 +178,7 @@ Cute\AudioManager.cs Cute\AudioManager.cs 5e0cce94bcfad63266cd298aef89bb383e541f
|
||||
Cute\BootApp.cs Cute\BootApp.cs 1a6b3066b6155aba225b9ca4e79655e428fc7b24cb16569717b53600b1f23bb5 0
|
||||
Cute\BootNetwork.cs Cute\BootNetwork.cs 99769dd6c38b2ee2ef7ad02e14530c658576e5c4a2188ed1cbcdd563f68443f6 0
|
||||
Cute\BootSystem.cs Cute\BootSystem.cs 61afa7a7c8df705504031629965440d491603dec531b047a36b9294f255ee04e 0
|
||||
Cute\Certification.cs Cute\Certification.cs 8c143ee5f98e99332bbd1d6ec091d7590004b3b7215f1dc234d39bb5402f8531 0
|
||||
Cute\Certification.cs Cute\Certification.cs ea018062d8823eb3527e7fd5e07d094a6fd444c1ad5a368bcf9132315cac99ac 1
|
||||
Cute\CryptAES.cs Cute\CryptAES.cs d3022b9e1be75bc07e57aef61093717a84b60383608eba5daa9b7dc6605b1e75 0
|
||||
Cute\Cryptographer.cs Cute\Cryptographer.cs f61bc1f4727d323004c443c9db30a4f221db3309be2cb14d6f51fc6a39590908 0
|
||||
Cute\CustomPreference.cs Cute\CustomPreference.cs ddc46cc13bf2728e4fcee7db550ec093ec3acf651ea48d3dbb5f5099d5a20f89 0
|
||||
@@ -2624,7 +2624,7 @@ Wizard\CrossoverRewardInfo.cs Wizard\CrossoverRewardInfo.cs bb3763306d0e7d3feefb
|
||||
Wizard\CsvColumns.cs Wizard\CsvColumns.cs d113f92e1f0145adb323c093deca81aab1889e8de34ed78c852b8e5a764c1c4c 0
|
||||
Wizard\CustomEasing.cs Wizard\CustomEasing.cs c7ac36e40e66f046d42e1d688db22f2acc2567399ce23c0512e3e2c8beefa598 0
|
||||
Wizard\DamagedTagCollection.cs Wizard\DamagedTagCollection.cs 8e6ecf677b4da8e16a68d3336959cd6d08af4830a0214297d65e96243f777c3f 0
|
||||
Wizard\Data.cs Wizard\Data.cs 26bd39c591da328c1a30eccf773064be022145dad1f11a29584832b8a81d36e1 0
|
||||
Wizard\Data.cs Wizard\Data.cs 88529d834ee64a12288ae2a40062824ea594f6d1b6c95d3cab2776f499369e77 1
|
||||
Wizard\DeckAttributeType.cs Wizard\DeckAttributeType.cs 006bb4c04d8a60c9caf04873dde6c962366348db03ec40a8bbc0071392f656dd 0
|
||||
Wizard\DeckAutoCreateTask.cs Wizard\DeckAutoCreateTask.cs e8c21d513114d2c42ad85a28da4adb48642bd36dc012f6029fbc8a8d72b78d6c 0
|
||||
Wizard\DeckBuildShortageCardView.cs Wizard\DeckBuildShortageCardView.cs 34428e4efb614c4fd59136d1bb87485ce117a97b2c6668f0481fff4b510a31d3 0
|
||||
@@ -3237,7 +3237,7 @@ Wizard\TargetSelectType.cs Wizard\TargetSelectType.cs 91ab18f9c069784e1140a187ea
|
||||
Wizard\TargetTagCollection.cs Wizard\TargetTagCollection.cs 1bd2fb66e58c9fae3d23fbce351972577da664c2b959ee92e0547e2396c82eb9 0
|
||||
Wizard\TextLineCreater.cs Wizard\TextLineCreater.cs fdb7f0a918c2f5b92268954b3980724f29cb16a8098ea67c2d99633ae5bd1e92 0
|
||||
Wizard\TokenPlayPattern.cs Wizard\TokenPlayPattern.cs c14d846afb81b876291013c077cbd503bebd27b651b5b78708e93d68758e2e7b 0
|
||||
Wizard\ToolboxGame.cs Wizard\ToolboxGame.cs f0a39a9ec7a06d08cc2594cc93f010c602946492ed93c002775c41000f30ef75 0
|
||||
Wizard\ToolboxGame.cs Wizard\ToolboxGame.cs ac0bde1ef076672c6e19969c5f9ec172aee79e7d5ee5bdf660e89166e8ff07ce 1
|
||||
Wizard\TournamentCell.cs Wizard\TournamentCell.cs b07b968c6768b74b9345ab3aa1ae138950de022b08f92a16966b3daef81d379c 0
|
||||
Wizard\TournamentCellData.cs Wizard\TournamentCellData.cs ecc457bdf2dbaa7db9de893f69a07ac43e589ca140dad29866d658af386e605e 0
|
||||
Wizard\TournamentController.cs Wizard\TournamentController.cs 236122aa73487c600114c9b0010ab9e9c85a5745a267550088c8f790532647c9 0
|
||||
|
||||
|
@@ -16,7 +16,7 @@ public class Certification : MonoBehaviour
|
||||
|
||||
private static string udid;
|
||||
|
||||
private static int viewer_id;
|
||||
private static int _viewerIdFallback;
|
||||
|
||||
private static int short_udid;
|
||||
|
||||
@@ -42,17 +42,25 @@ public class Certification : MonoBehaviour
|
||||
{
|
||||
get
|
||||
{
|
||||
if (viewer_id == 0)
|
||||
var c = SVSim.BattleEngine.Ambient.BattleAmbient.Current;
|
||||
if (c != null) return c.ViewerId;
|
||||
if (_viewerIdFallback == 0)
|
||||
{
|
||||
viewer_id = Toolbox.SavedataManager.GetInt("VIEWER_ID");
|
||||
_viewerIdFallback = Toolbox.SavedataManager.GetInt("VIEWER_ID");
|
||||
}
|
||||
return viewer_id;
|
||||
return _viewerIdFallback;
|
||||
}
|
||||
set
|
||||
{
|
||||
var c = SVSim.BattleEngine.Ambient.BattleAmbient.Current;
|
||||
if (c != null)
|
||||
{
|
||||
// Inside a scope, ViewerId is fixed at scope entry — swallow the write.
|
||||
return;
|
||||
}
|
||||
Toolbox.SavedataManager.SetInt("VIEWER_ID", value);
|
||||
Toolbox.SavedataManager.Save();
|
||||
viewer_id = value;
|
||||
_viewerIdFallback = value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,7 +152,7 @@ public class Certification : MonoBehaviour
|
||||
{
|
||||
sessionId = null;
|
||||
udid = null;
|
||||
viewer_id = 0;
|
||||
_viewerIdFallback = 0;
|
||||
short_udid = 0;
|
||||
Toolbox.SavedataManager.SetInt("VIEWER_ID", 0);
|
||||
Toolbox.SavedataManager.SetInt("SHORT_UDID", 0);
|
||||
|
||||
@@ -176,7 +176,17 @@ public static class Data
|
||||
|
||||
public static ReplayDetailInfo ReplayBattleInfo { get; set; }
|
||||
|
||||
public static BattleRecoveryInfo BattleRecoveryInfo { get; set; }
|
||||
private static BattleRecoveryInfo _battleRecoveryInfoFallback;
|
||||
public static BattleRecoveryInfo BattleRecoveryInfo
|
||||
{
|
||||
get => SVSim.BattleEngine.Ambient.BattleAmbient.Current?.RecoveryInfo ?? _battleRecoveryInfoFallback;
|
||||
set
|
||||
{
|
||||
var c = SVSim.BattleEngine.Ambient.BattleAmbient.Current;
|
||||
if (c != null) c.RecoveryInfo = value;
|
||||
else _battleRecoveryInfoFallback = value;
|
||||
}
|
||||
}
|
||||
|
||||
public static VoteData VoteInfo { get; set; }
|
||||
|
||||
|
||||
@@ -25,7 +25,11 @@ public static class ToolboxGame
|
||||
|
||||
private static Transform _gameTransform = null;
|
||||
|
||||
public static RealTimeNetworkAgent RealTimeNetworkAgent { get; private set; }
|
||||
private static RealTimeNetworkAgent _realTimeNetworkAgentFallback;
|
||||
public static RealTimeNetworkAgent RealTimeNetworkAgent
|
||||
{
|
||||
get => SVSim.BattleEngine.Ambient.BattleAmbient.Current?.NetworkAgent ?? _realTimeNetworkAgentFallback;
|
||||
}
|
||||
|
||||
public static Transform GameTransform
|
||||
{
|
||||
@@ -56,15 +60,20 @@ public static class ToolboxGame
|
||||
|
||||
public static void SetRealTimeNetworkBattle(RealTimeNetworkAgent agent)
|
||||
{
|
||||
RealTimeNetworkAgent = agent;
|
||||
var c = SVSim.BattleEngine.Ambient.BattleAmbient.Current;
|
||||
if (c != null) c.NetworkAgent = agent;
|
||||
else _realTimeNetworkAgentFallback = agent;
|
||||
}
|
||||
|
||||
public static void DestroyNetworkAgent()
|
||||
{
|
||||
if (RealTimeNetworkAgent != null)
|
||||
var c = SVSim.BattleEngine.Ambient.BattleAmbient.Current;
|
||||
var current = c?.NetworkAgent ?? _realTimeNetworkAgentFallback;
|
||||
if (current != null)
|
||||
{
|
||||
Object.DestroyImmediate(RealTimeNetworkAgent.gameObject);
|
||||
RealTimeNetworkAgent = null;
|
||||
Object.DestroyImmediate(current.gameObject);
|
||||
if (c != null) c.NetworkAgent = null;
|
||||
else _realTimeNetworkAgentFallback = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
Multi-instancing migration (Step 4): convert Cute.Certification.ViewerId — the per-battle
|
||||
"who is the local seat" identity — to resolve through BattleAmbient.Current when a scope is
|
||||
active, falling back to the legacy SavedataManager-backed static when not. The old `viewer_id`
|
||||
backing field is renamed to `_viewerIdFallback` so unwrapped callers (real client, in-process
|
||||
unit tests without a BattleAmbient scope) keep the original lazy-load-from-savedata + write-
|
||||
through-savedata behavior bit-for-bit; scoped callers get a per-AsyncLocal id without writing
|
||||
to savedata (design 2026-06-07-engine-multi-instancing, Task 4).
|
||||
|
||||
Inside a scope the setter is a NO-OP: ViewerId is an init-time identity (it's set at scope
|
||||
entry via `new BattleAmbientContext { ViewerId = ... }`'s init-only property), and swallowing
|
||||
the write avoids any in-battle setter from mutating sibling-battle perspective. The fallback
|
||||
setter preserves the original sequence exactly: SetInt + Save + assign backing field.
|
||||
|
||||
In-file references (3 total) handled as follows:
|
||||
- line 19 declaration → renamed to `_viewerIdFallback`
|
||||
- line 41 ViewerId property → ambient-first getter; setter swallows when scoped
|
||||
- line 147 InitializeFileds → resets the renamed `_viewerIdFallback`
|
||||
|
||||
External reflection follow-up (NOT in this patch — separate edit, same commit):
|
||||
SVSim.BattleNode/Sessions/Engine/EngineGlobalInit.cs (~line 154) reads the private field
|
||||
by name to seed the headless "who am I" perspective. Renamed there from "viewer_id" to
|
||||
"_viewerIdFallback" to match.
|
||||
|
||||
--- Engine/Cute/Certification.cs (~line 19)
|
||||
- private static int viewer_id;
|
||||
+ private static int _viewerIdFallback;
|
||||
|
||||
--- Engine/Cute/Certification.cs (~lines 41-57)
|
||||
public static int ViewerId
|
||||
{
|
||||
get
|
||||
{
|
||||
- if (viewer_id == 0)
|
||||
+ var c = SVSim.BattleEngine.Ambient.BattleAmbient.Current;
|
||||
+ if (c != null) return c.ViewerId;
|
||||
+ if (_viewerIdFallback == 0)
|
||||
{
|
||||
- viewer_id = Toolbox.SavedataManager.GetInt("VIEWER_ID");
|
||||
+ _viewerIdFallback = Toolbox.SavedataManager.GetInt("VIEWER_ID");
|
||||
}
|
||||
- return viewer_id;
|
||||
+ return _viewerIdFallback;
|
||||
}
|
||||
set
|
||||
{
|
||||
+ var c = SVSim.BattleEngine.Ambient.BattleAmbient.Current;
|
||||
+ if (c != null)
|
||||
+ {
|
||||
+ // Inside a scope, ViewerId is fixed at scope entry — swallow the write.
|
||||
+ return;
|
||||
+ }
|
||||
Toolbox.SavedataManager.SetInt("VIEWER_ID", value);
|
||||
Toolbox.SavedataManager.Save();
|
||||
- viewer_id = value;
|
||||
+ _viewerIdFallback = value;
|
||||
}
|
||||
}
|
||||
|
||||
--- Engine/Cute/Certification.cs (~line 147, InitializeFileds)
|
||||
- viewer_id = 0;
|
||||
+ _viewerIdFallback = 0;
|
||||
34
SVSim.BattleEngine/Patches/Data.ambient-recoveryinfo.patch
Normal file
34
SVSim.BattleEngine/Patches/Data.ambient-recoveryinfo.patch
Normal file
@@ -0,0 +1,34 @@
|
||||
Multi-instancing migration (Step 4): convert Wizard.Data.BattleRecoveryInfo — the per-battle
|
||||
mid-game recovery snapshot (replay/reconnect/late-join state, owned by RecoveryDataHandler /
|
||||
RecoveryNetworkManagerBase / RecoveryController) — to resolve through BattleAmbient.Current
|
||||
when a scope is active, falling back to a `_battleRecoveryInfoFallback` static when not.
|
||||
The original was a plain auto-property `{ get; set; }`; converting to a manual property +
|
||||
ambient-aware getter/setter preserves the public read/write surface byte-identical
|
||||
(design 2026-06-07-engine-multi-instancing, Task 4).
|
||||
|
||||
This is the only of the three Step-4 conversions whose setter we DO route through ambient
|
||||
(unlike ViewerId, where the in-scope setter is a no-op): recovery info is mutated during the
|
||||
battle (new snapshots overwrite old ones as recovery checkpoints stream in), so scoped writes
|
||||
must land on the AsyncLocal slot, not bleed into the process-wide fallback.
|
||||
|
||||
The existing line-348 reset inside `Data.Clear()` (`BattleRecoveryInfo = null;`) keeps working
|
||||
unchanged because it goes through the public setter, which now correctly routes to whichever
|
||||
slot the caller's scope (or lack thereof) points at.
|
||||
|
||||
In-file references (1 declaration; ~5 setter/getter call sites elsewhere in the file go through
|
||||
the public property and need no edits) handled as follows:
|
||||
- line 179 auto-property → manual ambient-first getter + ambient-routed setter
|
||||
|
||||
--- Engine/Wizard/Data.cs (~line 179)
|
||||
- public static BattleRecoveryInfo BattleRecoveryInfo { get; set; }
|
||||
+ private static BattleRecoveryInfo _battleRecoveryInfoFallback;
|
||||
+ public static BattleRecoveryInfo BattleRecoveryInfo
|
||||
+ {
|
||||
+ get => SVSim.BattleEngine.Ambient.BattleAmbient.Current?.RecoveryInfo ?? _battleRecoveryInfoFallback;
|
||||
+ set
|
||||
+ {
|
||||
+ var c = SVSim.BattleEngine.Ambient.BattleAmbient.Current;
|
||||
+ if (c != null) c.RecoveryInfo = value;
|
||||
+ else _battleRecoveryInfoFallback = value;
|
||||
+ }
|
||||
+ }
|
||||
51
SVSim.BattleEngine/Patches/ToolboxGame.ambient-rtna.patch
Normal file
51
SVSim.BattleEngine/Patches/ToolboxGame.ambient-rtna.patch
Normal file
@@ -0,0 +1,51 @@
|
||||
Multi-instancing migration (Step 4): convert Wizard.ToolboxGame.RealTimeNetworkAgent — the
|
||||
per-battle handle to the live PvP/AI network agent (RealTimeNetworkAgent owns the Socket.IO
|
||||
connection, OnEmit pipeline, and ack bookkeeping for one battle) — to resolve through
|
||||
BattleAmbient.Current when a scope is active, falling back to a renamed
|
||||
`_realTimeNetworkAgentFallback` static when not. The original was an auto-property with a
|
||||
private setter, mutated only via SetRealTimeNetworkBattle / DestroyNetworkAgent; converting
|
||||
to a manual property + ambient-aware mutators keeps the public surface byte-identical
|
||||
(design 2026-06-07-engine-multi-instancing, Task 4).
|
||||
|
||||
DestroyNetworkAgent preserves the original Unity DestroyImmediate(.gameObject) call exactly,
|
||||
just reading the "current" agent through the same ambient-first resolution and clearing the
|
||||
slot it came from. Object.DestroyImmediate resolves via the file's existing `using UnityEngine;`
|
||||
(no qualifier change needed — matches the file's existing pattern at line 36/79 that calls
|
||||
`GameObject.Find` unqualified).
|
||||
|
||||
In-file references (3 sites) handled as follows:
|
||||
- line 28 auto-property → renamed backing + manual ambient-first getter
|
||||
- line 57 SetRealTimeNetworkBattle → writes through Current?.NetworkAgent or fallback
|
||||
- line 62 DestroyNetworkAgent → reads current via ambient-first; clears the same slot
|
||||
|
||||
--- Engine/Wizard/ToolboxGame.cs (~line 28)
|
||||
- public static RealTimeNetworkAgent RealTimeNetworkAgent { get; private set; }
|
||||
+ private static RealTimeNetworkAgent _realTimeNetworkAgentFallback;
|
||||
+ public static RealTimeNetworkAgent RealTimeNetworkAgent
|
||||
+ {
|
||||
+ get => SVSim.BattleEngine.Ambient.BattleAmbient.Current?.NetworkAgent ?? _realTimeNetworkAgentFallback;
|
||||
+ }
|
||||
|
||||
--- Engine/Wizard/ToolboxGame.cs (~lines 57-69)
|
||||
public static void SetRealTimeNetworkBattle(RealTimeNetworkAgent agent)
|
||||
{
|
||||
- RealTimeNetworkAgent = agent;
|
||||
+ var c = SVSim.BattleEngine.Ambient.BattleAmbient.Current;
|
||||
+ if (c != null) c.NetworkAgent = agent;
|
||||
+ else _realTimeNetworkAgentFallback = agent;
|
||||
}
|
||||
|
||||
public static void DestroyNetworkAgent()
|
||||
{
|
||||
- if (RealTimeNetworkAgent != null)
|
||||
+ var c = SVSim.BattleEngine.Ambient.BattleAmbient.Current;
|
||||
+ var current = c?.NetworkAgent ?? _realTimeNetworkAgentFallback;
|
||||
+ if (current != null)
|
||||
{
|
||||
- Object.DestroyImmediate(RealTimeNetworkAgent.gameObject);
|
||||
- RealTimeNetworkAgent = null;
|
||||
+ Object.DestroyImmediate(current.gameObject);
|
||||
+ if (c != null) c.NetworkAgent = null;
|
||||
+ else _realTimeNetworkAgentFallback = null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user