using System.Collections; using System.Collections.Generic; using UnityEngine; using NeonTea.Quakeball.Networking.Packets; using NeonTea.Quakeball.Players; using NeonTea.Quakeball.Interface; using NeonTea.Quakeball.TeaNet.Peers; using NeonTea.Quakeball.TeaNet.Packets; namespace NeonTea.Quakeball.Networking.Instances { public class Server : NetInstance { private NetChaperone Net; private Dictionary Players = new Dictionary(); public List PlayerList { get; private set; } = new List(); private ulong PlayerIdCounter; private NetPlayer LocalPlayer = new NetPlayer(ulong.MaxValue); private byte LastPingIdent; private float LastSentPing; public static float PingInterval = 1; public override void Start(string address, int port, PeerMessageListener listener) { if (Peer.Running) { return; } Peer = new Peer(Fingerprint); Peer.MessageListener = listener; Peer.Start(port); Peer.RegisterProtocol(new GameProtocol(this)); Peer.StartListen(address, port); Net = GameObject.FindGameObjectWithTag("Net").GetComponent(); Player obj = GameObject.FindGameObjectWithTag("Player").GetComponent(); LocalPlayer.Controlled = obj; AddPlayer(LocalPlayer); } public override void OnStop() { foreach (NetPlayer p in PlayerList) { Peer.Disconnect(p.Id); if (p.Controlled != null && p.Id != LocalPlayer.Id) { GameObject.Destroy(p.Controlled.gameObject); } } PlayerList.Clear(); Players.Clear(); } public override void Connected(Connection conn) { Terminal.Singleton.Println($"{conn.uid} Connected"); foreach (NetPlayer p in Players.Values) { if (p.Controlled == null) { // Not yet initialized, sending later. continue; } SpawnPckt spawn = new SpawnPckt(); spawn.PlayerId = p.Id; spawn.Location = p.Controlled.transform.position; Peer.SendReliableLater(conn.uid, spawn); } NetPlayer RemotePlayer = new NetPlayer(PlayerIdCounter++); AddPlayer(RemotePlayer); SelfIdentPckt ident = new SelfIdentPckt(); ident.PlayerId = RemotePlayer.Id; Peer.SendReliable(conn.uid, ident); } public override void Disconnected(Connection conn) { Terminal.Singleton.Println($"{conn.uid} Disconnected: {conn.ClosingReason}"); if (Players.ContainsKey(conn.uid)) { GameObject.Destroy(Players[conn.uid].Controlled.gameObject); RemovePlayer(Players[conn.uid]); } } public override void Handle(Connection conn, Packet packet) { if (packet is SpawnPckt) { SpawnPckt spawn = (SpawnPckt)packet; if (Players[conn.uid].Controlled == null) { Player obj = Net.SpawnPlayer(spawn.Location).GetComponent(); Players[conn.uid].Controlled = obj; spawn = new SpawnPckt(); spawn.PlayerId = conn.uid; spawn.Location = obj.transform.position; SendReliableToAll(spawn, except: spawn.PlayerId); } } else if (packet is PlayerUpdatePckt) { PlayerUpdatePckt updatePckt = (PlayerUpdatePckt)packet; if (Players[conn.uid].Controlled != null) { updatePckt.PlayerId = conn.uid; Players[conn.uid].Controlled.ProcessUpdatePacket(updatePckt); } } else if (packet is PlayerSyncPacket) { PlayerSyncPacket syncPckt = (PlayerSyncPacket)packet; if (Players[conn.uid].Controlled != null) { syncPckt.PlayerId = conn.uid; if (!Players[conn.uid].Controlled.ProcessSyncPacket(syncPckt, false)) { Players[conn.uid].Unsynced = true; } } } else if (packet is PlayerActionPckt) { PlayerActionPckt action = (PlayerActionPckt)packet; if (Players[conn.uid].Controlled != null) { HandleAction(conn.uid, action); } } else if (packet is PingPckt) { PingPckt ping = (PingPckt)packet; if (!ping.ServerReceived) { ping.ServerReceived = true; Peer.SendReliable(conn.uid, ping); if (ping.Identifier == LastPingIdent) { Players[conn.uid].Ping = Time.time - LastSentPing; } else { Players[conn.uid].Ping = PingInterval + 0.001f; } } } } public override void Update() { if (Time.time > LastSentPing + PingInterval) { LastPingIdent = (byte)((LastPingIdent + 1) % 200); PingPckt ping = new PingPckt(LastPingIdent); SendReliableToAll(ping); LastSentPing = Time.time; } } private void AddPlayer(NetPlayer player) { Players.Add(player.Id, player); PlayerList.Add(player); } private void RemovePlayer(NetPlayer player) { Players.Remove(player.Id); PlayerList.Remove(player); } private void HandleAction(ulong uid, PlayerActionPckt action) { switch (action.Action) { case PlayerAction.Jump: if (Players[uid].Controlled.Jump()) { action.PlayerId = uid; SendReliableToAll(action); } break; } } public void SendReliableToAll(Packet packet, ulong except = ulong.MaxValue) { foreach (NetPlayer p in Players.Values) { if (p.Id == ulong.MaxValue || p.Id == except) { continue; } Peer.SendReliable(p.Id, packet); } } public void SendUnreliableToAll(Packet packet, ulong except = ulong.MaxValue) { foreach (NetPlayer p in Players.Values) { if (p.Id == ulong.MaxValue || p.Id == except) { continue; } Peer.SendUnreliable(p.Id, packet); } } public override void UpdateLocalPlayer() { MultiplePlayerUpdatesPckt pckt = new MultiplePlayerUpdatesPckt(PlayerList); SendUnreliableToAll(pckt); } public override void LocalPlayerJump() { PlayerActionPckt jump = new PlayerActionPckt(PlayerAction.Jump, LocalPlayer.Id); SendReliableToAll(jump); } public override void SendPlayerSync() { MultipleSyncsPckt pckt = new MultipleSyncsPckt(PlayerList); SendUnreliableToAll(pckt); } } }