using System.Collections; using System.Collections.Generic; using UnityEngine; using NeonTea.Quakeball.Players; using NeonTea.Quakeball.Networking.Packets; using NeonTea.Quakeball.Interface; using NeonTea.Quakeball.TeaNet.Peers; using NeonTea.Quakeball.TeaNet.Packets; namespace NeonTea.Quakeball.Networking.Instances { public class Client : NetInstance { private NetChaperone Net; private Connection Server; private bool SelfIdentified = false; public float Ping { get; private set; } private float LastPingReceived; private byte LastPingIdent; public Client() { Net = GameObject.FindGameObjectWithTag("Net").GetComponent(); LocalPlayer = new NetPlayer(ulong.MaxValue - 1, false); LocalPlayer.Controlled = GameObject.FindGameObjectWithTag("Player").GetComponent(); } 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(0); byte ident = Peer.RegisterProtocol(new GameProtocol(this)); Peer.Connect(address, port, ident); LocalPlayer.Nick = nick; } public override void OnStop() { Peer.Disconnect(Server.uid); Server = null; foreach (NetPlayer p in Players.Values) { if (p.Id != LocalPlayer.Id) { GameObject.Destroy(p.Controlled.gameObject); } } Players.Clear(); Ping = 0; } public override void Connected(Connection conn) { Terminal.Singleton.Println($"{conn.uid} Connected"); if (Server == null) { Server = conn; } else { Peer.Disconnect(conn.uid); } } public override void Disconnected(Connection conn) { Terminal.Singleton.Println($"{conn.uid} Disconnected: {conn.ClosingReason}"); if (Server == conn) { Server = null; foreach (NetPlayer p in Players.Values) { if (p.Id != LocalPlayer.Id) { GameObject.Destroy(p.Controlled.gameObject); } } Players.Clear(); PlayerList.Clear(); Peer.Stop(); Ping = 0; } } public override void Handle(Connection conn, Packet packet) { if (packet is SelfIdentPckt) { SelfIdentPckt ident = (SelfIdentPckt)packet; LocalPlayer.Id = ident.PlayerId; LocalPlayer.Team = ident.Team; LocalPlayer.Controlled.NetId = LocalPlayer.Id; AddPlayer(LocalPlayer); SelfIdentified = true; LocalPlayer.Ready = true; NicknamePckt nickpckt = new NicknamePckt(LocalPlayer.Nick); Peer.SendReliableLater(Server.uid, nickpckt); ReadyPckt ready = new ReadyPckt(); Peer.SendReliable(Server.uid, ready); } else if (packet is NicknamePckt) { NicknamePckt nick = (NicknamePckt)packet; if (nick.PlayerId != LocalPlayer.Id) { Players[nick.PlayerId].Nick = nick.Nick; } } else if (packet is SpawnPckt) { SpawnPckt spawn = (SpawnPckt)packet; if (spawn.IsInitial) { if (spawn.PlayerId == LocalPlayer.Id) { HandlePlayerRespawn(spawn.PlayerId, spawn.Location); } else { Player obj = Net.SpawnPlayer(spawn.Location).GetComponent(); Players[spawn.PlayerId].Controlled = obj; } } else if (Players[spawn.PlayerId].Controlled.IsDead) { if (Players.ContainsKey(spawn.PlayerId)) { HandlePlayerRespawn(spawn.PlayerId, spawn.Location); } } } else if (packet is PlayerInitPckt) { PlayerInitPckt init = (PlayerInitPckt)packet; if (Players.ContainsKey(init.PlayerId)) { return; // Got the same init twice } NetPlayer player = new NetPlayer(init.PlayerId, true); player.Nick = init.NicknamePckt.Nick; player.Team = init.Team; Player obj = Net.SpawnPlayer(init.SpawnPckt.Location).GetComponent(); player.Controlled = obj; AddPlayer(player); Debug.Log("Added player" + player.Nick); } else if (packet is DeadPckt) { DeadPckt dead = (DeadPckt)packet; if (Players.ContainsKey(dead.DeadPlayerId)) { HandlePlayerDeath(dead.DeadPlayerId, dead.KillerPlayerId); } } else if (packet is MultiplePlayerUpdatesPckt) { MultiplePlayerUpdatesPckt multiple = (MultiplePlayerUpdatesPckt)packet; foreach (PlayerUpdatePckt pckt in multiple.Updates) { HandleUpdatePlayer(pckt); } } else if (packet is MultipleSyncsPckt) { MultipleSyncsPckt multiple = (MultipleSyncsPckt)packet; foreach (PlayerSyncPacket pckt in multiple.Syncs) { HandleSyncPckt(pckt); } } else if (packet is PlayerActionPckt) { PlayerActionPckt action = (PlayerActionPckt)packet; HandleAction(action); } else if (packet is PingPckt) { PingPckt ping = (PingPckt)packet; ping.ClientReceived = true; if (!ping.ServerReceived) { Peer.SendReliable(Server.uid, ping); LastPingIdent = ping.Identifier; LastPingReceived = Time.time; } else { if (LastPingIdent == ping.Identifier) { Ping = Time.time - LastPingReceived; } else { Ping = Instances.Server.PingInterval + 0.001f; } LocalPlayer.Ping = Ping; UpdatePingBias(); } } else if (packet is PingListPckt) { PingListPckt pinglist = (PingListPckt)packet; foreach (PingInfo info in pinglist.Pings) { if (info.PlayerId != LocalPlayer.Id) { Players[info.PlayerId].Ping = info.Ping; } } } else if (packet is HitPckt) { HitPckt hit = (HitPckt)packet; if (Players[hit.Target].Controlled != null) { Players[hit.Target].Controlled.Hit(hit.Source); } } } private void HandleUpdatePlayer(PlayerUpdatePckt pckt) { if (pckt.PlayerId == LocalPlayer.Id || !Players.ContainsKey(pckt.PlayerId)) { return; // Ignore, again. } Players[pckt.PlayerId].Controlled.ProcessUpdatePacket(pckt); } private void HandleSyncPckt(PlayerSyncPacket syncPckt) { if (Players.ContainsKey(syncPckt.PlayerId) && (syncPckt.Unsynced || syncPckt.PlayerId != LocalPlayer.Id)) { Players[syncPckt.PlayerId].Controlled.ProcessSyncPacket(syncPckt); } } private void HandleAction(PlayerActionPckt action) { switch (action.Action) { case PlayerAction.Jump: Players[action.PlayerId].Controlled.Jump(); break; case PlayerAction.Shoot: ShootData shootData = (ShootData)action.Serializable; HandleSyncPckt(shootData.SyncPckt); Players[action.PlayerId].Controlled.Shoot(); break; } } private void UpdatePingBias() { foreach (NetPlayer p in Players.Values) { if (p.Id != LocalPlayer.Id) { p.Controlled.PingBias = Ping; } } } public override void UpdateLocalPlayer() { if (SelfIdentified && Server != null) { PlayerUpdatePckt pckt = LocalPlayer.Controlled.CreateUpdatePacket(); Peer.SendUnreliable(Server.uid, pckt); } } public override void LocalPlayerAction(PlayerAction action, Serializable serializable = null) { if (SelfIdentified && Server != null) { PlayerActionPckt actionPckt = new PlayerActionPckt(action, serializable); Peer.SendReliable(Server.uid, actionPckt); } } public override void SendPlayerSync() { if (SelfIdentified && Server != null) { PlayerSyncPacket packet = LocalPlayer.Controlled.CreateSyncPacket(); Peer.SendUnreliable(Server.uid, packet); } } public void HandlePlayerDeath(ulong dead, ulong killer) { if (Players[dead].Controlled != null) { Players[dead].Controlled.Dead(killer); } } public void HandlePlayerRespawn(ulong uid, Vector3 respawn) { if (Players[uid].Controlled != null) { Players[uid].Controlled.Respawn(respawn); } } } }