S&box Wiki

Networked Types

Any property on your Entity, EntityComponent or BaseNetworkable can be networked (synced from server to client).

Making a property networked

Adding the [Net] attribute makes it networked.

[Net] public float HeadSize { get; set; }
Classes containing networked members have to be marked as partial in order to work properly.
This is because codegen adds a supporting class in another file.


The properties can also be predicted.

[Net, Predicted] public float HeadSize { get; set; }

This changes two things:

  • The variable is backed up and restored properly by the prediction system
  • You can change the value clientside


You can make your networked property Local too, meaning it'll only be sent to the owner of the entity. This is useful if the data is only useful to the controlling client, or for anti-cheat reasons you wouldn't want other players to see the value.

[Net, Local] public int Money { get; set; }

Networkable Types

Type Name Support
float, int, bool, byte, long, short Any built in value type will work
string Supported
Enum Supported
Vector2, Vector3, Rotation, Angles, Transform Supported
Structs only structs containing unmanaged types
Classes Must be derived from BaseNetworkable
Entity Supported (If the Entity isn't transmitted it will be invalid clientside)
Material Supported as reference, must already be loaded on client
Model Supported as reference, must already be loaded on client
Custom Asset (Surface, Decal, Sound) Supported as reference
IList<T> Where T is any supported network type
IDictionary<TKey, TVal> Where TKey, TVal are any supported network type.
Additionally TVal can be object or derived from BaseNetworkable.

Custom Structs

If you want to transmit a struct it needs to be plain old data. It should contain no strings, no classes, no lists, no entities.

public struct AnotherStruct { public int A; public int B; public Vector3 C; } public struct CustomStruct { public float Delta; public AnotherStruct Data; public ulong Dump; }

Either of the above are valid.


By deriving a class from BaseNetworkable you'll be able to sync that using [Net] too. It has a few characteristics that you should know about.

  • You can derive from the class and it'll create the right class on the client.
  • Marking properties as Predicted or Local won't do anything - you can only use them when networking the whole thing.
public partial class MyBaseNetworkable : BaseNetworkable { // the Predicted here won't do anything [Net, Predicted] public int Value { get; set; } } // this works though! [Net, Predicted] public MyBaseNetworkable Stuff { get; set; }

An example usage of BaseNetworkable is to provide things like Camera. By networking a Camera class on a var, we allow the server to set the camera class directly and configure its variables. The server can set the Pawn.Camera to a new FirstPersonCamera and the client will receive that variable and create that class, like magic. This adds a lot of versatility to these kinds of systems.

public partial class NetworkableTest : BaseNetworkable { [Net] public int IntValue { get; set; } [Net] public Vector3 VectorValue { get; set; } }


If there is something you can't do with [Net] attributes alone, you can implement your own network serializer.

public partial class NetworkableTest : BaseNetworkable, INetworkSerializer { public Dictionary<int, int> MyDict { get; set; } void INetworkSerializer.Write( NetWrite write ) { write.Write( MyDict.Count ); foreach ( var pair in MyDict ) { write.Write( pair.Key ); write.Write( pair.Value ); } } void INetworkSerializer.Read( NetRead read ) { MyDict = new(); var count = read.Read<int>(); for ( int i = 0; i < count; i++ ) { var key = read.Read<int>(); var value = read.Read<int>(); MyDict[key] = value; } } }

When using INetworkSerializer this will override the default behavior of network tables, meaning any properties marked as [Net] will not be automatically replicated for you.

When using INetworkSerializer values will not be replicated until you call BaseNetworkable.WriteNetworkData().


When you mark an IList with [Net] codegen will implement it transparently as an ObservableList. With that comes a few behaviors:

  • It will never be null
  • Setting it to null will just clear the list
  • Setting it to another List will copy from that list
    • Further changes to the original list won't apply to the Networked List
  • If <T> is a BaseNetworkable then you cannot exchange them between networked lists

Materials, Models

Resources such as Materials and Models are able to be replicated, with these conditions:

  • Resource should already be precached on the client
  • Loaded from disk (needs to be filename match)

Under the hood they're networked as a hash of the filename.

Custom Assets

Custom Assets (decals, surfaces, sounds) that are loaded from disk should be fully compatible.

Since they're lightweight, all Custom Assets are loaded from disk on startup, which makes networking them a lot simpler. Under the hood they use the exact same system as Materials and Models to transmit, but since they're all loaded already you shouldn't run into the same worries about precaching.