quakeball/Assets/Scripts/Networking/Instances/Server.cs

256 lines
9.8 KiB
C#

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<NetChaperone>();
GameMaster = new GameMaster();
Player obj = GameObject.FindGameObjectWithTag("Player").GetComponent<Player>();
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>();
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);
}
}
}