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) {
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 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) {

View File

@ -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);
}
}
}

View File

@ -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<string> MessageQueue = new Queue<string>();
private Queue<SpawnInfo> SpawnQueue = new Queue<SpawnInfo>();
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);
}
}
}

View File

@ -14,6 +14,8 @@ namespace NeonTea.Quakeball.TeaNet.Peers {
private Dictionary<ulong, List<Packet>> PacketQueue = new Dictionary<ulong, List<Packet>>();
private Peer Peer;
public Dictionary<ulong, Queue<ProtocolAction>> ProtocolActionQueues = new Dictionary<ulong, Queue<ProtocolAction>>();
private Thread UpdateThread;
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) {
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;
}
}
}

View File

@ -6,7 +6,7 @@ using System.Net.Sockets;
using NeonTea.Quakeball.TeaNet.Packets;
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 {
/// <summary>Underlying UdpClient. Do not touch unless you know what you are doing.</summary>
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<ProtocolAction>());
protocol.Peer = this;
return ident;
}
@ -133,6 +134,11 @@ namespace NeonTea.Quakeball.TeaNet.Peers {
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 Err(string msg) { }