public partial class MultiplayerManager : Node { [Export] public PackedScene PlayerScene { get; set; } [Export] public PackedScene WorkshopScene { get; set; } public event Action PlayerJoined; public event Action PlayerLeft; public override void _Ready() { Multiplayer.ConnectedToServer += OnMultiplayerReady; Multiplayer.ServerDisconnected += OnMultiplayerDisconnected; Multiplayer.PeerConnected += OnPeerConnected; Multiplayer.PeerDisconnected += OnPeerDisconnected; } public void Connect(string address, ushort port) { var peer = new ENetMultiplayerPeer(); peer.CreateClient(address, port); Multiplayer.MultiplayerPeer = peer; } public bool CreateServer(ushort port) { var peer = new ENetMultiplayerPeer(); if (peer.CreateServer(port) == Error.Ok) { Multiplayer.MultiplayerPeer = peer; OnMultiplayerReady(); return true; } else return false; } public void Disconnect() => OnMultiplayerDisconnected(); void OnMultiplayerReady() { SetAuthorityAndName(Game.LocalPlayer, Multiplayer.GetUniqueId()); SetAuthorityAndName(Game.LocalWorkshop, Multiplayer.GetUniqueId()); // Spawn players for all the other peers. This excludes the server, // since `OnPeerConnected` will already be called for it on connecting. foreach (var peerId in Multiplayer.GetPeers()) if (peerId != 1) OnPeerConnected(peerId); } void OnMultiplayerDisconnected() { Multiplayer.MultiplayerPeer.Close(); Multiplayer.MultiplayerPeer = new OfflineMultiplayerPeer(); foreach (var player in Game.Players) if (player != Game.LocalPlayer) OnPeerDisconnected(player.PeerId); SetAuthorityAndName(Game.LocalPlayer, Multiplayer.GetUniqueId()); SetAuthorityAndName(Game.LocalWorkshop, Multiplayer.GetUniqueId()); } void OnPeerConnected(long _peerId) { var player = PlayerScene.Instantiate(); SetAuthorityAndName(player, (int)_peerId); Game.Players.AddChild(player); PlayerJoined?.Invoke(player); } void OnPeerDisconnected(long _peerId) { var player = Game.Players.ByPeerId((int)_peerId); Game.Players.RemoveChild(player); player.QueueFree(); var workshop = Game.Workshops.ByPeerId((int)_peerId); Game.Workshops.RemoveChild(workshop); workshop.QueueFree(); PlayerLeft?.Invoke(player); } static void SetAuthorityAndName(Node node, int peerId) { node.SetMultiplayerAuthority(peerId); node.Name = peerId.ToString(); } }