Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Advanced Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…network starts InstantiateTemplateInstance removed the instance's NetworkObject whenever this peer was not the server, including before the network had started at all. A mod that creates its NPCs at scene load (The Big Pimpin's escorts, on the second load of a session) got NPCs without one. Their network behaviours then bound to the parent's NetworkObject (@Managers/@NPCS, already spawned): FishNet's spawn failed twice ("Failed to spawn pending NPC ... NullReferenceException") and left them inactive, and a mod that checks npc.NetworkObject.IsSpawned (Siesta) took them for spawned NPCs and hid them before their spawn. Only a client-only peer removes it now; before the network starts it is kept (or added). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
0ab3560 to
dad4a5a
Compare
ifBars
left a comment
There was a problem hiding this comment.
Thanks for investigating this. I'd like to establish a reproduction through S1API's supported NPC lifecycle before merging this change.
The custom NPC guidance explicitly says to let S1API own instancing and never manually construct custom NPCs with new. Prefab defaults belong in ConfigurePrefab, with runtime setup in OnCreated. S1API also owns prefab registration and retry timing.
Looking through Big Pimpin's 1.0.11 IL2CPP assembly, its escort path differs from that:
OnSceneWasLoaded("Main")callsEscortNPCRegistry.ResetForSceneReload().- That clears the registry's lists, then
EnsureSlots()directly constructs all fourEscortMidnight...NPCsubclasses withnew, without first obtaining the S1API-owned instances or checking peer authority. - Its readiness check only confirms that
NPCManager.GetNPC(id), the GameObject and Transform exist. S1API registers NPCs during construction, so that does not establish that they have finished spawning.
The escorts do use ConfigurePrefab and OnCreated for some setup. The separate manual construction sequence is the part that bypasses the documented lifecycle. These observations are from static inspection of the IL2CPP mod, not an independent Mono gameplay reproduction.
Distinguishing an inactive network from a confirmed client-only peer may still be a valid S1API correction. But the current reproduction doesn't establish that the normal automatic lifecycle needs it, and retaining the NetworkObject alone doesn't queue an early instance for spawning: RegisterPendingNetworkSpawn still returns when a NetworkManager exists but isn't a server.
Could you provide a minimal NPC using the documented automatic instancing pattern that reproduces the ownership problem without Big Pimpin's construction/display code or #339? Please cover initial load and menu/reload, host and joining client, and Mono/IL2CPP separately. If an instance can be created while the peer's role is unknown, we also need to establish what happens when it subsequently becomes a client.
I'm leaving this open so we can discuss a supported reproduction or a better approach. I don't want S1API to take on another mod's construction/timing workaround without identifying a framework contract that actually fails.
|
Thanks for the detailed review. I ran the reproduction you asked for, and it does not reproduce through the documented lifecycle, so I'm closing this. What I ran
What happened (host)
No spawn failures, no refusals, and no Not covered: a joining client. I don't have a second account or machine, so I can't test it, and I won't claim anything about that case. Conclusion. The documented lifecycle doesn't need this change. You're right about the rest too:
I'll fix this in Big Pimpin's own code path instead, in S1UMF, the compatibility mod I keep for other mods. Its escorts will use the instances S1API already owns, and it will release the old display leases before replacing them. I'll also raise it with The Big Pimpin's authors. |
…eload, and hide only once spawned Its EscortNPCRegistry.EnsureSlots builds the four escorts with `new` from its scene-load callback, beside the ones S1API makes: two of each on a first load, and on a reload S1API refuses to spawn them (hidden before spawn). S1UMF now waits until the save has loaded with the network up, adopts S1API's instances (building its own only if S1API made none), releases the old display leases before rebuilding, and defers a hide until the escort spawns (skipped if it is leased again by then). Applies only with an S1API whose discovery finds Big Pimpin (ifBars/S1API#333): 3.2.1-beta.7 can't spawn them at all, so there it stands down. Tested on IL2CPP, slot 5 late save, full mod set, first load and reload: with current S1API beta, one instance per escort, all four spawned on both loads, no refusals; with 3.2.1-beta.7 it stands down and the mod behaves as before. Requested in ifBars/S1API#338 and #339 instead of an S1API change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Summary
NPC.InstantiateTemplateInstanceremoved a new custom NPC'sNetworkObjectwhenever this peer was not the server, which includes the time before the network has started. The Big Pimpin 1.0.11 constructs its four escort NPCs fromOnSceneWasLoaded, which on the second load of a session runs before the server is up. Those NPCs had noNetworkObject, so their network behaviours bound to the parent's (@Managers/@NPCs, already spawned). Spawning them then failed:Mods that check
npc.NetworkObject.IsSpawnedalso took them for spawned NPCs. Siesta did, and hid them before their spawn (see #339).The change. Only a client-only peer removes the
NetworkObject, since the server spawns the NPC to it. Before the network starts, it is kept, or added if missing. The server path is unchanged.Compatibility
NetworkObject.Validation
Mono
dotnet build S1API.sln -c MonoMelon --no-restore -p:AutomateLocalDeployment=false: 0 errors, 0 warnings.dotnet test ... -c MonoMelon: 743 passed (740 onbetaplus 3 new: before the network starts, on the server, and on a client-only peer).IL2CPP
dotnet build S1API.sln -c Il2CppMelon --no-restore -p:AutomateLocalDeployment=false: 0 errors, 0 warnings.dotnet test ... -c Il2CppMelon: 723 passed (720 plus 3 new).Runtime evidence
How it was tested. Automated runs on 0.4.7f7 load a save, teleport to each custom NPC, record whether its model is shown and its network state, return to the menu and load again. They used a combined build of #332 to #339.
I also played the IL2CPP case by hand.
npc.NetworkObjectis its own, and unspawned until S1API spawns it, on both runtimes. Before this change it was@Managers/@NPCs.finalized ... (active in scene: True)on both loads, on both runtimes, both saves, and with about 60 mods. There are no spawn failures or refusals.Documentation
None needed.
🤖 Generated with Claude Code