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; public Dictionary Players { get; private set; } = new Dictionary(); public List PlayerList { get; private set; } = new List(); private ulong PlayerIdCounter; private byte LastPingIdent; private float LastSentPing; public static float PingInterval = 1; public Server() { LocalPlayer = new NetPlayer(ulong.MaxValue); } public override void Start(string address, int port, string nick, 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; LocalPlayer.Nick = nick; 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; } NicknamePckt nick = new NicknamePckt(p.Nick, p.Id); Peer.SendReliableLater(conn.uid, nick); SpawnPckt spawn = new SpawnPckt(p.Controlled.transform.position, p.Id); 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 NicknamePckt) { NicknamePckt nick = (NicknamePckt)packet; Players[conn.uid].Nick = nick.Nick; nick.PlayerId = conn.uid; SendReliableToAll(nick); } else if (packet is SpawnPckt) { SpawnPckt spawn = (SpawnPckt)packet; if (Players[conn.uid].Controlled == null && spawn.IsInitial) { Player obj = Net.SpawnPlayer(spawn.Location).GetComponent(); Players[conn.uid].Controlled = obj; spawn = new SpawnPckt(obj.transform.position, conn.uid); SendReliableToAll(spawn, except: spawn.PlayerId); } } else if (packet is PlayerUpdatePckt) { PlayerUpdatePckt updatePckt = (PlayerUpdatePckt)packet; HandleUpdatePckt(conn.uid, updatePckt); } else if (packet is PlayerSyncPacket) { PlayerSyncPacket syncPckt = (PlayerSyncPacket)packet; HandleSyncPckt(conn.uid, syncPckt); } 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); NetPlayer p = Players[conn.uid]; if (ping.Identifier == LastPingIdent) { p.Ping = Time.time - LastSentPing; } else { p.Ping = PingInterval + 0.001f; } if (p.Controlled != null) { p.Controlled.PingBias = p.Ping; } } } } public override void Update() { if (Time.time > LastSentPing + PingInterval) { LastPingIdent = (byte)((LastPingIdent + 1) % 200); PingPckt ping = new PingPckt(LastPingIdent); SendReliableToAll(ping); LastSentPing = Time.time; PingListPckt pinglist = new PingListPckt(PlayerList); SendReliableToAll(pinglist); } } 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 HandleUpdatePckt(ulong uid, PlayerUpdatePckt pckt) { if (Players[uid].Controlled != null && !Players[uid].Controlled.IsDead) { pckt.PlayerId = uid; Players[uid].Controlled.ProcessUpdatePacket(pckt); } } private void HandleSyncPckt(ulong uid, PlayerSyncPacket pckt) { if (Players[uid].Controlled != null && !Players[uid].Controlled.IsDead) { pckt.PlayerId = uid; if (!Players[uid].Controlled.ProcessSyncPacket(pckt, false)) { Players[uid].Unsynced = true; } } } private void HandleAction(ulong uid, PlayerActionPckt action) { switch (action.Action) { case PlayerAction.Jump: if (Players[uid].Controlled.Jump()) { action.PlayerId = uid; SendReliableToAll(action); } break; case PlayerAction.Shoot: ShootData shootData = (ShootData)action.Serializable; HandleSyncPckt(uid, shootData.SyncPckt); Players[uid].Controlled.Shoot(); action.PlayerId = uid; NetPlayer Player = Players[uid]; shootData.SyncPckt = Player.Controlled.CreateSyncPacket(Player.Id, Player.Unsynced); Player.Unsynced = false; 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 LocalPlayerAction(PlayerAction action, Serializable serializable = null) { PlayerActionPckt actionPckt = new PlayerActionPckt(action, serializable, LocalPlayer.Id); SendReliableToAll(actionPckt); } public override void SendPlayerSync() { MultipleSyncsPckt pckt = new MultipleSyncsPckt(PlayerList); SendUnreliableToAll(pckt); } public void SendHit(ulong source, ulong target) { HitPckt hit = new HitPckt(source, target); SendReliableToAll(hit); } public void HandlePlayerDeath(ulong deadid, ulong killerid) { Players[deadid].Controlled.Dead(killerid); DeadPckt dead = new DeadPckt(deadid, killerid); SendReliableToAll(dead); } public void HandlePlayerRespawn(ulong uid) { Vector3 point = GameObject.FindGameObjectWithTag("Respawn").transform.position; Players[uid].Controlled.Respawn(point); SpawnPckt spawn = new SpawnPckt(point, uid, false); SendReliableToAll(spawn); } } }