245 lines
9.6 KiB
C#
245 lines
9.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 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, false);
|
|
LocalPlayer.Controlled = GameObject.FindGameObjectWithTag("Player").GetComponent<Player>();
|
|
}
|
|
|
|
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<Player>();
|
|
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>();
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
} |