From 1d8e027558c1be8129bf690f41045017445ee059 Mon Sep 17 00:00:00 2001 From: teascade Date: Fri, 7 Aug 2020 05:11:53 +0300 Subject: [PATCH] Make Protocol only be called on mainthread --- Assets/Scripts/Net/Instances/Client.cs | 8 +-- Assets/Scripts/Net/Instances/NetInstance.cs | 1 - Assets/Scripts/Net/Instances/Server.cs | 17 ++--- Assets/Scripts/Net/NetChaperone.cs | 24 ++----- .../Scripts/TeaNet/Peers/ConnectionManager.cs | 68 +++++++++++++++++-- Assets/Scripts/TeaNet/Peers/Peer.cs | 8 ++- 6 files changed, 83 insertions(+), 43 deletions(-) diff --git a/Assets/Scripts/Net/Instances/Client.cs b/Assets/Scripts/Net/Instances/Client.cs index f5709e4..a9d1d1a 100644 --- a/Assets/Scripts/Net/Instances/Client.cs +++ b/Assets/Scripts/Net/Instances/Client.cs @@ -60,13 +60,9 @@ namespace NeonTea.Quakeball.Net.Instances { if (spawn.PlayerId == LocalPlayer.Id) { return; // Ignore, it's their own. } - Net.SpawnPlayer(spawn.PlayerId, spawn.Location); + GameObject obj = Net.SpawnPlayer(spawn.Location); + NetPlayer player = new NetPlayer(spawn.PlayerId, obj); } } - - public override void PlayerSpawned(ulong uid, GameObject obj) { - NetPlayer player = new NetPlayer(uid); - player.Controlled = obj; - } } } \ No newline at end of file diff --git a/Assets/Scripts/Net/Instances/NetInstance.cs b/Assets/Scripts/Net/Instances/NetInstance.cs index 1db5aff..9eba097 100644 --- a/Assets/Scripts/Net/Instances/NetInstance.cs +++ b/Assets/Scripts/Net/Instances/NetInstance.cs @@ -16,7 +16,6 @@ namespace NeonTea.Quakeball.Net.Instances { public abstract void Connected(Connection conn); public abstract void Disconnected(Connection conn); public abstract void Handle(Connection conn, Packet packet); - public abstract void PlayerSpawned(ulong uid, GameObject obj); public void Stop() { if (Peer != null) { diff --git a/Assets/Scripts/Net/Instances/Server.cs b/Assets/Scripts/Net/Instances/Server.cs index d6e5586..efa742c 100644 --- a/Assets/Scripts/Net/Instances/Server.cs +++ b/Assets/Scripts/Net/Instances/Server.cs @@ -56,7 +56,13 @@ namespace NeonTea.Quakeball.Net.Instances { if (packet is SpawnPckt) { SpawnPckt spawn = (SpawnPckt)packet; if (Players[conn.uid].Controlled == null) { - Net.SpawnPlayer(conn.uid, spawn.Location); + GameObject obj = Net.SpawnPlayer(spawn.Location); + Players[conn.uid].Controlled = obj; + + spawn = new SpawnPckt(); + spawn.PlayerId = conn.uid; + spawn.Location = obj.transform.position; + SendReliableToAll(spawn); } } } @@ -66,14 +72,5 @@ namespace NeonTea.Quakeball.Net.Instances { Peer.SendReliable(p.Id, packet); } } - - public override void PlayerSpawned(ulong uid, GameObject obj) { - Players[uid].Controlled = obj; - - SpawnPckt spawn = new SpawnPckt(); - spawn.PlayerId = uid; - spawn.Location = obj.transform.position; - SendReliableToAll(spawn); - } } } \ No newline at end of file diff --git a/Assets/Scripts/Net/NetChaperone.cs b/Assets/Scripts/Net/NetChaperone.cs index d45273d..eb5dd35 100644 --- a/Assets/Scripts/Net/NetChaperone.cs +++ b/Assets/Scripts/Net/NetChaperone.cs @@ -2,6 +2,7 @@ using System; using UnityEngine; using NeonTea.Quakeball.Interface; +using NeonTea.Quakeball.Net; using NeonTea.Quakeball.TeaNet.Peers; namespace NeonTea.Quakeball.Net { @@ -13,18 +14,10 @@ namespace NeonTea.Quakeball.Net { private Queue MessageQueue = new Queue(); - private Queue SpawnQueue = new Queue(); - - class SpawnInfo { - public ulong id; - public Vector3 location; - } - - public void SpawnPlayer(ulong uid, Vector3 location) { - SpawnInfo info = new SpawnInfo(); - info.id = uid; - info.location = location; - SpawnQueue.Enqueue(info); + public GameObject SpawnPlayer(Vector3 location) { + GameObject obj = GameObject.Instantiate(SpawnedRemotePlayer); + obj.transform.position = location; + return obj; } private void Start() { @@ -36,16 +29,11 @@ namespace NeonTea.Quakeball.Net { } private void Update() { + Net.Singleton.Instance.Peer.Update(); if (Terminal != null && Terminal.isActiveAndEnabled) { while (MessageQueue.Count > 0) { Terminal.Println(MessageQueue.Dequeue()); } - while (SpawnQueue.Count > 0) { - SpawnInfo info = SpawnQueue.Dequeue(); - GameObject obj = GameObject.Instantiate(SpawnedRemotePlayer); - obj.transform.position = info.location; - Net.Singleton.Instance.PlayerSpawned(info.id, obj); - } } } diff --git a/Assets/Scripts/TeaNet/Peers/ConnectionManager.cs b/Assets/Scripts/TeaNet/Peers/ConnectionManager.cs index bf2e63c..d7777a2 100644 --- a/Assets/Scripts/TeaNet/Peers/ConnectionManager.cs +++ b/Assets/Scripts/TeaNet/Peers/ConnectionManager.cs @@ -14,6 +14,8 @@ namespace NeonTea.Quakeball.TeaNet.Peers { private Dictionary> PacketQueue = new Dictionary>(); private Peer Peer; + public Dictionary> ProtocolActionQueues = new Dictionary>(); + private Thread UpdateThread; public long Timeout = 8000; @@ -111,6 +113,26 @@ namespace NeonTea.Quakeball.TeaNet.Peers { } } + /// Go through queue of networking actions that have happened since last update. + public void Update() { + foreach (byte id in ProtocolActionQueues.Keys) { + Protocol protocol = Peer.GetProtocol(id); + while (ProtocolActionQueues[id].Count > 0) { + ProtocolAction action = ProtocolActionQueues[id].Dequeue(); + if (action is ReceiveAction) { + ReceiveAction receive = (ReceiveAction)action; + protocol.Receive(receive.Connection, receive.Packet); + } else if (action is ConnectionChangedAction) { + ConnectionChangedAction changed = (ConnectionChangedAction)action; + protocol.ConnectionStatusChanged(changed.OldStatus, changed.NewStatus, changed.Connection); + } else if (action is TimeoutAction) { + TimeoutAction changed = (TimeoutAction)action; + protocol.Timeout(changed.Connection); + } + } + } + } + private void AddConnection(Connection conn) { conn.uid = ConnectionCounter++; Connections.Add(conn.uid, conn); @@ -160,7 +182,7 @@ namespace NeonTea.Quakeball.TeaNet.Peers { conn.Status = ConnectionStatus.Ready; } if (protocol != null) { - protocol.ConnectionStatusChanged(oldStatus, conn.Status, conn); + ProtocolActionQueues[protocol.Identifier].Enqueue(new ConnectionChangedAction(oldStatus, conn.Status, conn)); } } break; @@ -168,7 +190,7 @@ namespace NeonTea.Quakeball.TeaNet.Peers { conn.Status = ConnectionStatus.Closed; conn.ClosingReason = buffer.ReadClosingReason(); if (protocol != null) { - protocol.ConnectionStatusChanged(oldStatus, conn.Status, conn); + ProtocolActionQueues[protocol.Identifier].Enqueue(new ConnectionChangedAction(oldStatus, conn.Status, conn)); } break; case PacketStage.Closed: @@ -177,7 +199,7 @@ namespace NeonTea.Quakeball.TeaNet.Peers { } conn.Status = ConnectionStatus.Stopped; if (protocol != null) { - protocol.ConnectionStatusChanged(oldStatus, conn.Status, conn); + ProtocolActionQueues[protocol.Identifier].Enqueue(new ConnectionChangedAction(oldStatus, conn.Status, conn)); } break; case PacketStage.Ready: @@ -186,7 +208,7 @@ namespace NeonTea.Quakeball.TeaNet.Peers { } if (oldStatus == ConnectionStatus.Establishing) { // Update connection status conn.Status = ConnectionStatus.Ready; - protocol.ConnectionStatusChanged(oldStatus, conn.Status, conn); + ProtocolActionQueues[protocol.Identifier].Enqueue(new ConnectionChangedAction(oldStatus, conn.Status, conn)); } else { break; // They're cheating! No cheating! } @@ -202,11 +224,11 @@ namespace NeonTea.Quakeball.TeaNet.Peers { if (p.PacketIsReliable) { if (p.PacketId > conn.Internal.LatestInwardReliable) { conn.Internal.LatestInwardReliable = p.PacketId; - protocol.Receive(conn, p); + ProtocolActionQueues[protocol.Identifier].Enqueue(new ReceiveAction(conn, p)); } } else if (p.PacketId > conn.Internal.LatestInwardUnreliable) { conn.Internal.LatestInwardUnreliable = p.PacketId; - protocol.Receive(conn, p); + ProtocolActionQueues[protocol.Identifier].Enqueue(new ReceiveAction(conn, p)); } } break; @@ -241,7 +263,7 @@ namespace NeonTea.Quakeball.TeaNet.Peers { Protocol protocol = Peer.GetProtocol(conn.Internal.AssignedProtocol); if (protocol != null) { conn.ClosingReason = ClosingReason.Timeout; - protocol.Timeout(conn); + ProtocolActionQueues[conn.Internal.AssignedProtocol].Enqueue(new TimeoutAction(conn)); } } } @@ -252,4 +274,36 @@ namespace NeonTea.Quakeball.TeaNet.Peers { } } } + + public abstract class ProtocolAction { }; + + class ReceiveAction : ProtocolAction { + public Connection Connection; + public Packet Packet; + + public ReceiveAction(Connection connection, Packet packet) { + Connection = connection; + Packet = packet; + } + } + + class ConnectionChangedAction : ProtocolAction { + public ConnectionStatus OldStatus; + public ConnectionStatus NewStatus; + public Connection Connection; + + public ConnectionChangedAction(ConnectionStatus old, ConnectionStatus newstatus, Connection connection) { + Connection = connection; + OldStatus = old; + NewStatus = newstatus; + } + } + + class TimeoutAction : ProtocolAction { + public Connection Connection; + + public TimeoutAction(Connection connection) { + Connection = connection; + } + } } \ No newline at end of file diff --git a/Assets/Scripts/TeaNet/Peers/Peer.cs b/Assets/Scripts/TeaNet/Peers/Peer.cs index d805805..8c4479f 100644 --- a/Assets/Scripts/TeaNet/Peers/Peer.cs +++ b/Assets/Scripts/TeaNet/Peers/Peer.cs @@ -6,7 +6,7 @@ using System.Net.Sockets; using NeonTea.Quakeball.TeaNet.Packets; namespace NeonTea.Quakeball.TeaNet.Peers { - /// Main class for networking. Remember to register a protocol before using. + /// Main class for networking. Remember to register a protocol before using. Remember to call Update from a gameobject! public class Peer : PeerMessageListener { /// Underlying UdpClient. Do not touch unless you know what you are doing. public UdpClient UdpClient { get; private set; } @@ -121,6 +121,7 @@ namespace NeonTea.Quakeball.TeaNet.Peers { return 0; } RegisteredProtocols.Add(ident, protocol); + ConnectionManager.ProtocolActionQueues.Add(ident, new Queue()); protocol.Peer = this; return ident; } @@ -133,6 +134,11 @@ namespace NeonTea.Quakeball.TeaNet.Peers { return null; } + /// Shorthand for Peer.ConnectionManager.Update(): Handles network stuff that was received since last update. + public void Update() { + ConnectionManager.Update(); + } + public void Message(string msg) { } public void Err(string msg) { }