Skip to content

fix(VGE): replace oxygen gizmo sync fields with sync methods#577

Merged
notfood merged 1 commit intorwmt:masterfrom
sviyh:fix/s9-oxygen-sync-method
Apr 13, 2026
Merged

fix(VGE): replace oxygen gizmo sync fields with sync methods#577
notfood merged 1 commit intorwmt:masterfrom
sviyh:fix/s9-oxygen-sync-method

Conversation

@sviyh
Copy link
Copy Markdown
Contributor

@sviyh sviyh commented Apr 11, 2026

Summary

  • Replace sync field + watch on comp fields (rechargeAtCharges, automaticRechargeEnabled) with sync method for the toggle and targetValuePct sync on the gizmo for the slider
  • Add SyncWorker to serialize the oxygen gizmo via its backing comp

Root cause

The old approach synced rechargeAtCharges on the comp, but Gizmo_Slider.targetValuePct (a private cache in the base class) overwrites the comp field every frame via Target = targetValuePct, defeating the sync. This is the same pattern the MP mod itself uses for GeneGizmo_Resource and ActivityGizmo — sync the gizmo's targetValuePct directly.

Approach

  • Toggle (AutomaticRechargeEnabled): RegisterSyncMethod on the property setter — discrete event, no need for field watching
  • Slider (targetValuePct): RegisterSyncField with SetBufferChanges() on the gizmo, plus a SyncWorker and targetType override (the compat API resolves to the declaring base type)

Matches review item S9: "All of this should be easy to do with just sync methods, sync fields are just an extra overhead."

Test plan

  • Builds cleanly
  • Manual in-game test: slider and toggle sync between host and client
  • No desync after normal play

🤖 Generated with Claude Code

sviyh added a commit to sviyh/Multiplayer-Compatibility that referenced this pull request Apr 12, 2026
FieldRef<object, ThingComp> and FieldRef<object, Gizmo_Slider> let
callsites drop the (ThingComp) and (Gizmo_Slider) casts. Only the
field generic needs to be compile-time known; the runtime Type arg
passed to FieldRefAccess stays dynamic.

Review feedback from rwmt#577.
Replaces the oxygen gizmo sync fields with a SyncMethod + SyncWorker
so the Gizmo_Slider.targetValuePct cache round-trips cleanly instead
of being overwritten every frame by the base-class slider logic.

Uses AccessTools.FieldRef<object, ThingComp> / FieldRef<object,
Gizmo_Slider> so callsites don't need casts. targetType is set via
reflection on the ISyncField because RegisterSyncField resolves it
via FieldInfo.ReflectedType, which returns the base Gizmo_Slider
rather than the concrete subclass. See rwmt/Multiplayer#880.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants