Skip to content

en SyncVar Network Sync

HoCha113 edited this page Jun 21, 2026 · 4 revisions

中文版本

SyncVar Network Sync

Mark fields with [SyncVar]; SyncVarManager serializes them in multiplayer automatically.


Core Components

Component Description
[SyncVar] Attribute tag, marks fields or properties that need synchronization
SyncVarManager Static manager, automatically discovers and serializes [SyncVar]-marked members via reflection

Quick Start

1. Mark Fields

Add the [SyncVar] attribute to any field or property in any class:

using InnoVault;

public class MyNPCOverride : NPCOverride
{
    [SyncVar]
    public int CustomHealth;

    [SyncVar]
    public float SpeedMultiplier;

    [SyncVar]
    public bool IsEnraged;

    [SyncVar]
    public Vector2 TargetPosition;

    // Fields without [SyncVar] will not be synced
    public int LocalOnlyData;
}

2. Send and Receive

SyncVarManager's Send / Receive methods automatically handle all marked fields:

// Send — writes all [SyncVar] fields to BinaryWriter
SyncVarManager.Send(myInstance, writer);

// Receive — reads from BinaryReader and sets all [SyncVar] fields
SyncVarManager.Receive(myInstance, reader);

In the NPCOverride and Actor systems, SyncVar is already automatically integrated into the network sync flow — typically no manual calls are needed.


Supported Data Types

SyncVarManager supports the following types out of the box:

Type Write Method Read Method
int Write(int) ReadInt32()
float Write(float) ReadSingle()
bool Write(bool) ReadBoolean()
string Write(string) ReadString()
byte Write(byte) ReadByte()
short Write(short) ReadInt16()
long Write(long) ReadInt64()
double Write(double) ReadDouble()
Color Write(PackedValue) new Color { PackedValue }
Vector2 WriteVector2() ReadVector2()
Point16 WritePoint16() ReadPoint16()
Point WritePoint() ReadPoint()
Item ItemIO.Send() ItemIO.Receive()

Registering Custom Types

If you need to sync types beyond the built-in ones:

// Register in Mod.Load()
SyncVarManager.RegisterSyncType<MyStruct>(
    (writer, value) => {
        writer.Write(value.X);
        writer.Write(value.Y);
        writer.Write(value.Name);
    },
    reader => new MyStruct {
        X = reader.ReadInt32(),
        Y = reader.ReadInt32(),
        Name = reader.ReadString()
    }
);

Serialization Order

SyncVarManager guarantees deterministic serialization order:

  1. Inheritance chain from base to derived: Base class fields are serialized first
  2. Same level sorted by name: Using StringComparison.Ordinal lexicographic order
  3. Both fields and properties are supported: Properties must have both get and set
public class Base {
    [SyncVar] public int Alpha;    // Serialization order 1
    [SyncVar] public int Beta;     // Serialization order 2
}

public class Child : Base {
    [SyncVar] public int Charlie;  // Serialization order 3
    [SyncVar] public int Delta;    // Serialization order 4
}

Integration with Existing Systems

NPCOverride

NPCOverride's OtherNetWorkSendHander automatically calls SyncVarManager.Send after writing custom data, and the receiver similarly calls SyncVarManager.Receive:

public class BossOverride : NPCOverride
{
    public override int TargetID => NPCID.KingSlime;

    [SyncVar]
    public int Phase;

    [SyncVar]
    public float Rage;

    public override bool AI() {
        if (VaultUtils.isServer && Phase != GetCurrentPhase()) {
            Phase = GetCurrentPhase();
            NetOtherWorkSend = true; // Trigger sync, [SyncVar] fields automatically included
        }
        return true;
    }
}

Actor

The Actor base class has built-in [SyncVar]-marked common fields (Active, Width, Height, Rotation, Scale, Position, Velocity), and automatically syncs via SendSyncData / ReceiveSyncData:

public class MyActor : Actor
{
    [SyncVar]
    public int CustomState;

    public override void AI() {
        if (CustomState != newState) {
            CustomState = newState;
            NetUpdate = true; // Mark for sync
        }
    }
}

TileProcessor

TileProcessor's SendData / ReceiveData also integrates SyncVar:

public class MyTP : TileProcessor
{
    [SyncVar]
    public int StoredEnergy;

    // SyncVar fields are automatically synced in SendData/ReceiveData
}

API Reference

SyncVarAttribute

[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class SyncVarAttribute : Attribute { }

SyncVarManager

Method Description
RegisterSyncType<T>(writer, reader) Register serialization methods for a custom type
GetSyncVars(Type) Get all [SyncVar] member list for a specified type (cached)
Send(object, BinaryWriter) Write all [SyncVar] fields of an object to the stream
Receive(object, BinaryReader) Read from the stream and set all [SyncVar] fields on an object

Notes

  1. Properties must be readable and writable: properties marked [SyncVar] need both get and set
  2. Registered types only: fields of unregistered types are silently skipped
  3. Reflection cache: the first access to a type collects member info via reflection; later calls use the cache
  4. No collection types: List, Dictionary, etc. require custom handling via RegisterSyncType
  5. Local data unaffected: fields not marked [SyncVar] are not included in network serialization

Navigation

Previous Home Next
Override System Home Actor Entity System

Clone this wiki locally