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 Dictionary Players = new Dictionary(); private NetPlayer LocalPlayer; private bool SelfIdentified = false; public float Ping { get; private set; } private float LastPingReceived; private byte LastPingIdent; public override void Start(string address, int port, PeerMessageListener listener) { if (Peer.Running) { return; } Peer = new Peer(Fingerprint); Peer.MessageListener = listener; Peer.Start(0); byte ident = Peer.RegisterProtocol(new GameProtocol(this)); Peer.Connect(address, port, ident); Net = GameObject.FindGameObjectWithTag("Net").GetComponent(); LocalPlayer = new NetPlayer(ulong.MaxValue - 1); LocalPlayer.Controlled = GameObject.FindGameObjectWithTag("Player").GetComponent(); } 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(); 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.Controlled.NetId = LocalPlayer.Id; Players.Add(LocalPlayer.Id, LocalPlayer); SelfIdentified = true; SpawnPckt spawn = new SpawnPckt(); spawn.Location = LocalPlayer.Controlled.transform.position; Peer.SendReliable(Server.uid, spawn); } else if (packet is SpawnPckt) { SpawnPckt spawn = (SpawnPckt)packet; if (spawn.PlayerId == LocalPlayer.Id) { return; // Ignore, it's their own. } Player obj = Net.SpawnPlayer(spawn.Location).GetComponent(); NetPlayer player = new NetPlayer(spawn.PlayerId, obj); Players.Add(spawn.PlayerId, player); } 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; } UpdatePingBias(); } } else if (packet is HitPckt) { HitPckt hit = (HitPckt)packet; if (Players[hit.Target].Controlled != null) { Players[hit.Target].Controlled.Hit(); } } } private void HandleUpdatePlayer(PlayerUpdatePckt pckt) { if (pckt.PlayerId == LocalPlayer.Id) { return; // Ignore, again. } Players[pckt.PlayerId].Controlled.ProcessUpdatePacket(pckt); } private void HandleSyncPckt(PlayerSyncPacket syncPckt) { if (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); } } } }