-
Notifications
You must be signed in to change notification settings - Fork 12
Multiplayer
Important
If you are running Mac or Linux you may need a Custom ENet Build
First familiarize yourself with how to create your own packets.
Create a script that extends from GodotClient. Everything else in the script will look different for your game. Also have a look at the Client API.
public partial class GameClient : GodotClient
{
public GameClient()
{
// Do something when this packet is received by the client
RegisterPacketHandler<SPacketHello>(packet => Log(packet.Message));
}
protected override void OnConnect(Event netEvent)
{
// Send a packet to the server
Send(new CPacketPlayerInfo()
{
Username = "Valk",
Position = new Vector2(100, 100)
});
}
}Create a script that extends from GodotServer. Everything else in the script will look different for your game. Also have a look at the Server API.
public partial class GameServer : GodotServer
{
// Keep track of players
public Dictionary<uint, Player> Players { get; } = [];
private PlayerSystems _playerSystems;
public GameServer()
{
_playerSystems = new PlayerSystems(this);
// Add the player when they connect
RegisterPacketHandler<CPacketPlayerInfo>(_playerSystems.OnPlayerInfo);
}
protected override void OnPeerDisconnect(Event netEvent)
{
// Remove the player when they disconnect
_playerSystems.OnPlayerDisconnect(netEvent);
}
}PlayerSystems is just managing what gets added or removed from Players and your code may look very different from this so don't worry too much about how this looks.
PlayerSystems.cs
public class PlayerSystems
{
private readonly GameServer _server;
public PlayerSystems(GameServer server)
{
_server = server;
}
public void OnPlayerInfo(CPacketPlayerInfo info, Peer peer)
{
if (_server.Players.ContainsKey(peer.ID))
{
_server.Log($"Received player info for peer {peer.ID} (username {info.Username}) but they exist on the server already");
return;
}
_server.Players[peer.ID] = new Player
{
Username = info.Username,
Position = info.Position
};
_server.Send(new SPacketHello { Message = "What's up?" }, peer);
}
public void OnPlayerDisconnect(Event netEvent)
{
uint id = netEvent.Peer.ID;
if (!_server.Players.ContainsKey(id))
{
_server.Log($"Can't remove peer {id} from players because they never existed to begin with");
return;
}
_server.Players.Remove(id);
_server.Log($"Removed peer {id} from players");
}
}This is the UI interface and how you will be able to start the server and client.
Create a script that extends from NetControlPanelLow<GameClient, GameServer>. Attach this script to a UI node in your scene and supply all the exposed export nodes. For example you need a LineEdit for the IP and a Button to start the server.
public partial class NetControlPanel : NetControlPanelLow<GameClient, GameServer>
{
protected override ENetOptions Options { get; set; } = new()
{
PrintPacketByteSize = true,
PrintPacketData = true,
PrintPacketReceived = true,
PrintPacketSent = true
};
}
Enabling the print packet options can be very useful.
Before you start please also read common mistakes.
Example netcode has been provided in res://Framework/GodotUtils/Netcode/Sandbox/TopDown/World.tscn
You should now have everything you need to develop your multiplayer game!