Multiplayer/NetworkManager.cs
using System.Threading.Tasks;
using HC3;
using Sandbox.Network;

public sealed class NetworkManager : Component, Component.INetworkListener
{
	public static NetworkManager Instance { get; private set; }

	[Property] public GameObject WorldCursor { get; set; }

	protected override void OnAwake()
	{
		Instance = this;
	}

	protected override Task OnLoad()
	{
		if ( !Scene.IsEditor && !Networking.IsActive )
		{
			Networking.CreateLobby( new()
			{
				AutoSwitchToBestHost = false,
				DestroyWhenHostLeaves = true,
				MaxPlayers = 4,
				Privacy = LobbyPrivacy.FriendsOnly
			} );
		}

		return base.OnLoad();
	}

	void INetworkListener.OnActive( Connection channel )
	{
		Log.Info( channel.DisplayName + " Joined" );

		var cursor = WorldCursor?.Clone( new CloneConfig()
		{
			StartEnabled = true,
			Name = $"{channel.DisplayName}'s world cursor"
		} );

		cursor.NetworkSpawn( channel );

		if ( Stats.Get( "multiplayer.max_players" ) < Connection.All.Count )
		{
			Stats.Set( "multiplayer.max_players", Connection.All.Count );
		}

		if ( channel.IsHost )
			return;

		// Only the host can spawn or refresh objects.
		channel.CanRefreshObjects = false;
		channel.CanSpawnObjects = false;
	}
}