Make Protocol only be called on mainthread

This commit is contained in:
Sofia 2020-08-07 05:11:53 +03:00
parent 9daa855f81
commit 1d8e027558
6 changed files with 83 additions and 43 deletions

View File

@ -60,13 +60,9 @@ namespace NeonTea.Quakeball.Net.Instances {
if (spawn.PlayerId == LocalPlayer.Id) { if (spawn.PlayerId == LocalPlayer.Id) {
return; // Ignore, it's their own. 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;
}
} }
} }

View File

@ -16,7 +16,6 @@ namespace NeonTea.Quakeball.Net.Instances {
public abstract void Connected(Connection conn); public abstract void Connected(Connection conn);
public abstract void Disconnected(Connection conn); public abstract void Disconnected(Connection conn);
public abstract void Handle(Connection conn, Packet packet); public abstract void Handle(Connection conn, Packet packet);
public abstract void PlayerSpawned(ulong uid, GameObject obj);
public void Stop() { public void Stop() {
if (Peer != null) { if (Peer != null) {

View File

@ -56,7 +56,13 @@ namespace NeonTea.Quakeball.Net.Instances {
if (packet is SpawnPckt) { if (packet is SpawnPckt) {
SpawnPckt spawn = (SpawnPckt)packet; SpawnPckt spawn = (SpawnPckt)packet;
if (Players[conn.uid].Controlled == null) { 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); 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);
}
} }
} }

View File

@ -2,6 +2,7 @@
using System; using System;
using UnityEngine; using UnityEngine;
using NeonTea.Quakeball.Interface; using NeonTea.Quakeball.Interface;
using NeonTea.Quakeball.Net;
using NeonTea.Quakeball.TeaNet.Peers; using NeonTea.Quakeball.TeaNet.Peers;
namespace NeonTea.Quakeball.Net { namespace NeonTea.Quakeball.Net {
@ -13,18 +14,10 @@ namespace NeonTea.Quakeball.Net {
private Queue<string> MessageQueue = new Queue<string>(); private Queue<string> MessageQueue = new Queue<string>();
private Queue<SpawnInfo> SpawnQueue = new Queue<SpawnInfo>(); public GameObject SpawnPlayer(Vector3 location) {
GameObject obj = GameObject.Instantiate(SpawnedRemotePlayer);
class SpawnInfo { obj.transform.position = location;
public ulong id; return obj;
public Vector3 location;
}
public void SpawnPlayer(ulong uid, Vector3 location) {
SpawnInfo info = new SpawnInfo();
info.id = uid;
info.location = location;
SpawnQueue.Enqueue(info);
} }
private void Start() { private void Start() {
@ -36,16 +29,11 @@ namespace NeonTea.Quakeball.Net {
} }
private void Update() { private void Update() {
Net.Singleton.Instance.Peer.Update();
if (Terminal != null && Terminal.isActiveAndEnabled) { if (Terminal != null && Terminal.isActiveAndEnabled) {
while (MessageQueue.Count > 0) { while (MessageQueue.Count > 0) {
Terminal.Println(MessageQueue.Dequeue()); 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);
}
} }
} }

View File

@ -14,6 +14,8 @@ namespace NeonTea.Quakeball.TeaNet.Peers {
private Dictionary<ulong, List<Packet>> PacketQueue = new Dictionary<ulong, List<Packet>>(); private Dictionary<ulong, List<Packet>> PacketQueue = new Dictionary<ulong, List<Packet>>();
private Peer Peer; private Peer Peer;
public Dictionary<ulong, Queue<ProtocolAction>> ProtocolActionQueues = new Dictionary<ulong, Queue<ProtocolAction>>();
private Thread UpdateThread; private Thread UpdateThread;
public long Timeout = 8000; public long Timeout = 8000;
@ -111,6 +113,26 @@ namespace NeonTea.Quakeball.TeaNet.Peers {
} }
} }
/// <summary>Go through queue of networking actions that have happened since last update.</summary>
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) { private void AddConnection(Connection conn) {
conn.uid = ConnectionCounter++; conn.uid = ConnectionCounter++;
Connections.Add(conn.uid, conn); Connections.Add(conn.uid, conn);
@ -160,7 +182,7 @@ namespace NeonTea.Quakeball.TeaNet.Peers {
conn.Status = ConnectionStatus.Ready; conn.Status = ConnectionStatus.Ready;
} }
if (protocol != null) { if (protocol != null) {
protocol.ConnectionStatusChanged(oldStatus, conn.Status, conn); ProtocolActionQueues[protocol.Identifier].Enqueue(new ConnectionChangedAction(oldStatus, conn.Status, conn));
} }
} }
break; break;
@ -168,7 +190,7 @@ namespace NeonTea.Quakeball.TeaNet.Peers {
conn.Status = ConnectionStatus.Closed; conn.Status = ConnectionStatus.Closed;
conn.ClosingReason = buffer.ReadClosingReason(); conn.ClosingReason = buffer.ReadClosingReason();
if (protocol != null) { if (protocol != null) {
protocol.ConnectionStatusChanged(oldStatus, conn.Status, conn); ProtocolActionQueues[protocol.Identifier].Enqueue(new ConnectionChangedAction(oldStatus, conn.Status, conn));
} }
break; break;
case PacketStage.Closed: case PacketStage.Closed:
@ -177,7 +199,7 @@ namespace NeonTea.Quakeball.TeaNet.Peers {
} }
conn.Status = ConnectionStatus.Stopped; conn.Status = ConnectionStatus.Stopped;
if (protocol != null) { if (protocol != null) {
protocol.ConnectionStatusChanged(oldStatus, conn.Status, conn); ProtocolActionQueues[protocol.Identifier].Enqueue(new ConnectionChangedAction(oldStatus, conn.Status, conn));
} }
break; break;
case PacketStage.Ready: case PacketStage.Ready:
@ -186,7 +208,7 @@ namespace NeonTea.Quakeball.TeaNet.Peers {
} }
if (oldStatus == ConnectionStatus.Establishing) { // Update connection status if (oldStatus == ConnectionStatus.Establishing) { // Update connection status
conn.Status = ConnectionStatus.Ready; conn.Status = ConnectionStatus.Ready;
protocol.ConnectionStatusChanged(oldStatus, conn.Status, conn); ProtocolActionQueues[protocol.Identifier].Enqueue(new ConnectionChangedAction(oldStatus, conn.Status, conn));
} else { } else {
break; // They're cheating! No cheating! break; // They're cheating! No cheating!
} }
@ -202,11 +224,11 @@ namespace NeonTea.Quakeball.TeaNet.Peers {
if (p.PacketIsReliable) { if (p.PacketIsReliable) {
if (p.PacketId > conn.Internal.LatestInwardReliable) { if (p.PacketId > conn.Internal.LatestInwardReliable) {
conn.Internal.LatestInwardReliable = p.PacketId; conn.Internal.LatestInwardReliable = p.PacketId;
protocol.Receive(conn, p); ProtocolActionQueues[protocol.Identifier].Enqueue(new ReceiveAction(conn, p));
} }
} else if (p.PacketId > conn.Internal.LatestInwardUnreliable) { } else if (p.PacketId > conn.Internal.LatestInwardUnreliable) {
conn.Internal.LatestInwardUnreliable = p.PacketId; conn.Internal.LatestInwardUnreliable = p.PacketId;
protocol.Receive(conn, p); ProtocolActionQueues[protocol.Identifier].Enqueue(new ReceiveAction(conn, p));
} }
} }
break; break;
@ -241,7 +263,7 @@ namespace NeonTea.Quakeball.TeaNet.Peers {
Protocol protocol = Peer.GetProtocol(conn.Internal.AssignedProtocol); Protocol protocol = Peer.GetProtocol(conn.Internal.AssignedProtocol);
if (protocol != null) { if (protocol != null) {
conn.ClosingReason = ClosingReason.Timeout; 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;
}
}
} }

View File

@ -6,7 +6,7 @@ using System.Net.Sockets;
using NeonTea.Quakeball.TeaNet.Packets; using NeonTea.Quakeball.TeaNet.Packets;
namespace NeonTea.Quakeball.TeaNet.Peers { namespace NeonTea.Quakeball.TeaNet.Peers {
/// <summary>Main class for networking. Remember to register a protocol before using.</summary> /// <summary>Main class for networking. Remember to register a protocol before using. Remember to call Update from a gameobject!</summary>
public class Peer : PeerMessageListener { public class Peer : PeerMessageListener {
/// <summary>Underlying UdpClient. Do not touch unless you know what you are doing.</summary> /// <summary>Underlying UdpClient. Do not touch unless you know what you are doing.</summary>
public UdpClient UdpClient { get; private set; } public UdpClient UdpClient { get; private set; }
@ -121,6 +121,7 @@ namespace NeonTea.Quakeball.TeaNet.Peers {
return 0; return 0;
} }
RegisteredProtocols.Add(ident, protocol); RegisteredProtocols.Add(ident, protocol);
ConnectionManager.ProtocolActionQueues.Add(ident, new Queue<ProtocolAction>());
protocol.Peer = this; protocol.Peer = this;
return ident; return ident;
} }
@ -133,6 +134,11 @@ namespace NeonTea.Quakeball.TeaNet.Peers {
return null; return null;
} }
/// <summary>Shorthand for Peer.ConnectionManager.Update(): Handles network stuff that was received since last update.</summary>
public void Update() {
ConnectionManager.Update();
}
public void Message(string msg) { } public void Message(string msg) { }
public void Err(string msg) { } public void Err(string msg) { }