using System.Collections; using System.Collections.Generic; using UnityEngine; using NeonTea.Quakeball.Networking.Packets; using NeonTea.Quakeball.Players; using NeonTea.Quakeball.Game; 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 ulong PlayerIdCounter; private byte LastPingIdent; private float LastSentPing; public static float PingInterval = 1; public GameMaster GameMaster; public Server() { LocalPlayer = new NetPlayer(ulong.MaxValue, true); } public override void Start(string address, int port, string nick, PeerMessageListener listener) { if (Peer.Running) { return; } Players.Clear(); Peer = new Peer(Fingerprint); Peer.MessageListener = listener; Peer.Start(port); Peer.RegisterProtocol(new GameProtocol(this)); Peer.StartListen(address, port); Net = GameObject.FindGameObjectWithTag("Net").GetComponent(); GameMaster = new GameMaster(); Player obj = GameObject.FindGameObjectWithTag("Player").GetComponent(); LocalPlayer.Controlled = obj; LocalPlayer.Nick = nick; AddPlayer(LocalPlayer); GameMaster.PlayerJoined(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 (!IsReady(p.Id)) { // Not yet ready, sending later. continue; } NicknamePckt nick = new NicknamePckt(p.Nick, p.Id); SpawnPckt spawn = new SpawnPckt(p.Controlled.transform.position, p.Id); PlayerInitPckt init = new PlayerInitPckt(p.Id, p.Team, nick, spawn); Peer.SendReliableLater(conn.uid, init); } NetPlayer RemotePlayer = new NetPlayer(PlayerIdCounter++, false); GameMaster.PlayerJoined(RemotePlayer); AddPlayer(RemotePlayer); SelfIdentPckt ident = new SelfIdentPckt(RemotePlayer.Id, RemotePlayer.Team); Peer.SendReliable(conn.uid, ident); } public override void Disconnected(Connection conn) { Terminal.Singleton.Println($"{conn.uid} Disconnected: {conn.ClosingReason}"); if (Players.ContainsKey(conn.uid)) { NetPlayer player = Players[conn.uid]; GameMaster.PlayerLeft(player); GameObject.Destroy(player.Controlled.gameObject); RemovePlayer(player); } } public void PlayerJoined(NetPlayer player) { player.Ready = true; NicknamePckt nick = new NicknamePckt(player.Nick, player.Id); SpawnPckt spawn = new SpawnPckt(player.Controlled.transform.position, player.Id); PlayerInitPckt init = new PlayerInitPckt(player.Id, player.Team, nick, spawn); Debug.Log("Sending init: " + player.Id); SendReliableToAll(init, except: player.Id); } public override void Handle(Connection conn, Packet packet) { if (packet is ReadyPckt) { if (!IsReady(conn.uid)) { NetPlayer player = Players[conn.uid]; Player obj = Net.SpawnPlayer(GameMaster.GetSpawn(player)).GetComponent(); player.Controlled = obj; SpawnPckt spawn = new SpawnPckt(obj.transform.position, player.Id); Peer.SendReliable(conn.uid, spawn); PlayerJoined(player); } } else if (packet is NicknamePckt) { NicknamePckt nick = (NicknamePckt)packet; Players[conn.uid].Nick = nick.Nick; nick.PlayerId = conn.uid; if (IsReady(conn.uid)) { SendReliableToAll(nick); } } 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 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 bool IsReady(ulong uid) { return Players.ContainsKey(uid) && Players[uid].ReadyAndSpawned; } 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 = GameMaster.GetSpawn(Players[uid]); Players[uid].Controlled.Respawn(point); SpawnPckt spawn = new SpawnPckt(point, uid, false); SendReliableToAll(spawn); } } }