quakeball/Assets/Scripts/Networking/Instances/Client.cs
2020-08-08 20:14:34 +03:00

222 lines
8.6 KiB
C#

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<ulong, NetPlayer> Players = new Dictionary<ulong, NetPlayer>();
private bool SelfIdentified = false;
public float Ping { get; private set; }
private float LastPingReceived;
private byte LastPingIdent;
public Client() {
Net = GameObject.FindGameObjectWithTag("Net").GetComponent<NetChaperone>();
LocalPlayer = new NetPlayer(ulong.MaxValue - 1);
LocalPlayer.Controlled = GameObject.FindGameObjectWithTag("Player").GetComponent<Player>();
}
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(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();
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;
NicknamePckt nickpckt = new NicknamePckt(LocalPlayer.Nick);
Peer.SendReliable(Server.uid, nickpckt);
SpawnPckt spawn = new SpawnPckt(LocalPlayer.Controlled.transform.position);
Peer.SendReliableLater(Server.uid, spawn);
} 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.PlayerId == LocalPlayer.Id && spawn.IsInitial) {
return; // Ignore, it's their own.
}
if (spawn.IsInitial) {
Player obj = Net.SpawnPlayer(spawn.Location).GetComponent<Player>();
NetPlayer player = new NetPlayer(spawn.PlayerId, obj);
Players.Add(spawn.PlayerId, player);
} else if (Players[spawn.PlayerId].Controlled.IsDead) {
if (Players.ContainsKey(spawn.PlayerId)) {
HandlePlayerRespawn(spawn.PlayerId, spawn.Location);
}
}
} 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;
}
UpdatePingBias();
}
} 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[pckt.PlayerId] != null) {
return; // Ignore, again.
}
Players[pckt.PlayerId].Controlled.ProcessUpdatePacket(pckt);
}
private void HandleSyncPckt(PlayerSyncPacket syncPckt) {
if (Players[syncPckt.PlayerId] != null && (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);
}
}
}
}