S&box Wiki

Revision Difference

Network_Basics#548391

<cat>Code.Network</cat> <title>Networking Basics</title> There are two realms in networking on S&box. The client, and the server: Client: Each person playing in your game. Server: The process that is responsible for orchestrating your game with all of the clients in it. By default, both sides will know nothing about each other. But networking allows either side to communicate and keep each other in sync. While the same code will be run on both the client and server. No variables and state information you make are shared between them. Due to this, all variables you create whether they are created the exact same way or not will become out of sync when something is done on only one realm. This is where networking comes in. This allows you to share information between both the client and the server. # Example ```csharp using Sandbox; namespace Networking { public class NetworkingExampleOne : Game { public int NumClients = 0; public override void ClientJoined( Client cl ) { base.ClientJoined( cl ); NumClients++; } public override void Simulate( Client cl ) { base.Simulate( cl ); Log.Info( $"{(Host.IsServer ? "Server:" : "Client:")} {NumClients} clients added." ); Log.Info( $"{(Game.IsServer ? "Server:" : "Client:")} {NumClients} clients added." ); } } } ``` <upload src="4d227/8d997fb94940993.png" size="2714" name="NetworkingExampleOneResult.png" /> Upon a client joining you will find the above in your console. Notice how they are not the same. ## "But why?" The `ClientJoined` method is only called on the server. Because of this, only the server adds one to the `NumClients` field. Since this integer is not networked the clients will never get an up-to-date `NumClients` field. ## "How can I fix this?" With a small edit to the code like so: ```csharp using Sandbox; namespace Networking { public partial class NetworkingExampleTwo : Game { [Net] public int NumClients { get; set; } public override void ClientJoined( Client cl ) { base.ClientJoined( cl ); NumClients++; } public override void Simulate( Client cl ) { base.Simulate( cl ); Log.Info( $"{(Host.IsServer ? "Server:" : "Client:")} {NumClients} clients added." ); Log.Info( $"{(Game.IsServer ? "Server:" : "Client:")} {NumClients} clients added." ); } } } ``` <upload src="4d227/8d997fe02f465bc.png" size="2504" name="NetworkingExampleTwoResult.png" /> Now when a client joins you will find the above in your console. ## "What changed?" Three things were changed: 1. The `partial` keyword was added to the class. The S&box code generator will attach more code to the class in a separate file to support networking types and so `partial` is required for the code to compile. 2. The field was turned into a property. This is because S&box networking cannot work with fields. It requires a property. ([What's the difference?](https://stackoverflow.com/questions/4142867/what-is-the-difference-between-a-property-and-a-variable)) 3. The `Net` attribute was applied to the `NumClients` property. This is to mark the property for networking. ## "What is the catch?" 1. Not all classes are capable of networking. Only `Entity`, `EntityComponent`, `BaseNetworkable` classes, and anything derived from those are networking capable. 2. Not all types can be networked, [see this list for available types](https://wiki.facepunch.com/sbox/Networked_Types#networkabletypes). 3. Properties marked with the `Net` attribute cannot be edited by the client. It will not produce an error, just nothing will happen. If you have code that requires updating on the client side then you need [prediction](https://wiki.facepunch.com/sbox/Prediction). ## "How will I know when my property gets updated?" You can add the `Change` attribute to your networked property and it will call On[Property]Changed on your class on the client side. ```csharp [Net, Change] public int MyNumber { get; set; } // This will be called once MyNumber is edited on the server. private void OnMyNumberChanged( int oldValue, int newValue ) { Log.Info( $"MyNumber used to be {oldValue}, now it is {newValue}" ); } ``` You can read the dedicated page for network callbacks [here](https://wiki.facepunch.com/sbox/Network_Callbacks) # Useful Links * For information on networking types. See [here](https://wiki.facepunch.com/sbox/Networked_Types) * For information on what can be networked. See [here](https://wiki.facepunch.com/sbox/Networked_Types#networkabletypes) * For information on prediction. See [here](https://wiki.facepunch.com/sbox/Prediction) * For information on Remote Procedure Calls(RPCs). See [here](https://wiki.facepunch.com/sbox/RPCs) * For information on network variable callbacks. See [here](https://wiki.facepunch.com/sbox/Network_Callbacks)