ReliableMessage improvements & bugfixes

This commit is contained in:
Regalis
2015-10-20 20:45:47 +03:00
parent 5f07d4b0c9
commit 4cf3386aa5
11 changed files with 230 additions and 142 deletions

View File

@@ -31,5 +31,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("0.2.2.0")]
[assembly: AssemblyFileVersion("0.2.2.0")]
[assembly: AssemblyVersion("0.0.0.1")]
[assembly: AssemblyFileVersion("0.0.0.1")]

View File

@@ -1107,18 +1107,22 @@ namespace Barotrauma
GetInputState(InputType.Up) ||
GetInputState(InputType.Down) ||
GetInputState(InputType.ActionHeld) ||
GetInputState(InputType.SecondaryHeld));
GetInputState(InputType.SecondaryHeld)) || LargeUpdateTimer <= 0;
message.Write(hasInputs);
message.Write(hasInputs || LargeUpdateTimer <= 0);
if (!hasInputs) return true;
message.Write((float)NetTime.Now);
// Write byte = move direction
//message.WriteRangedSingle(MathHelper.Clamp(AnimController.TargetMovement.X, -10.0f, 10.0f), -10.0f, 10.0f, 8);
//message.WriteRangedSingle(MathHelper.Clamp(AnimController.TargetMovement.Y, -10.0f, 10.0f), -10.0f, 10.0f, 8);
message.Write(keys[(int)InputType.ActionHeld].Dequeue);
message.Write(keys[(int)InputType.SecondaryHeld].Dequeue);
bool secondaryHeld = keys[(int)InputType.SecondaryHeld].Dequeue;
message.Write(secondaryHeld);
message.Write(keys[(int)InputType.Left].Dequeue);
message.Write(keys[(int)InputType.Right].Dequeue);
@@ -1128,8 +1132,15 @@ namespace Barotrauma
message.Write(keys[(int)InputType.Run].Dequeue);
message.Write(cursorPosition.X);
message.Write(cursorPosition.Y);
if (secondaryHeld)
{
message.Write(cursorPosition.X);
message.Write(cursorPosition.Y);
}
else
{
message.Write(AnimController.Dir > 0.0f);
}
message.Write(LargeUpdateTimer <= 0);
@@ -1271,21 +1282,36 @@ namespace Barotrauma
keys[(int)InputType.Run].State = runState;
float dir = 1.0f;
bool isLargeUpdate;
try
{
cursorPos = new Vector2(
message.ReadFloat(),
message.ReadFloat());
if (secondaryKeyState)
{
cursorPos = new Vector2(
message.ReadFloat(),
message.ReadFloat());
}
else
{
dir = message.ReadBoolean() ? 1.0f : -1.0f;
}
isLargeUpdate = message.ReadBoolean();
}
catch
{
return;
}
cursorPosition = cursorPos;
if (secondaryKeyState)
{
cursorPosition = cursorPos;
}
else
{
cursorPos = Position + new Vector2(1000.0f, 0.0f) * dir;
}
if (isLargeUpdate)
{

View File

@@ -238,8 +238,6 @@ namespace Barotrauma.Items.Components
public override void Update(float deltaTime, Camera cam)
{
convexHull.Enabled = true;
if (convexHull2 != null) convexHull2.Enabled = true;
if (!isStuck)
{
OpenState += deltaTime * ((isOpen) ? 2.0f : -2.0f);
@@ -253,8 +251,6 @@ namespace Barotrauma.Items.Components
public override void UpdateBroken(float deltaTime, Camera cam)
{
body.Enabled = false;
convexHull.Enabled = false;
if (convexHull2 != null) convexHull2.Enabled = false;
linkedGap.Open = 1.0f;
}

View File

@@ -116,7 +116,7 @@ namespace Barotrauma.Networking
}
updateInterval = new TimeSpan(0, 0, 0, 0, 100);
updateInterval = new TimeSpan(0, 0, 0, 0, 150);
// Set timer to tick every 50ms
//update = new System.Timers.Timer(50);
@@ -302,7 +302,7 @@ namespace Barotrauma.Networking
{
base.Update(deltaTime);
if (!connected || updateTimer > DateTime.Now) return;
if (!connected) return;
if (client.ConnectionStatus == NetConnectionStatus.Disconnected)
{
@@ -323,6 +323,21 @@ namespace Barotrauma.Networking
reconnectBox = null;
}
try
{
CheckServerMessages();
}
catch (Exception e)
{
#if DEBUG
DebugConsole.ThrowError("Error while receiving message from server", e);
#endif
}
reliableChannel.Update(deltaTime);
if (updateTimer > DateTime.Now) return;
if (myCharacter != null)
{
if (myCharacter.IsDead)
@@ -335,8 +350,6 @@ namespace Barotrauma.Networking
new NetworkEvent(myCharacter.ID, true);
}
}
reliableChannel.Update(deltaTime);
foreach (NetworkEvent networkEvent in NetworkEvent.events)
{
@@ -353,11 +366,10 @@ namespace Barotrauma.Networking
NetworkEvent.events.Clear();
try
if (PlayerInput.KeyDown(Microsoft.Xna.Framework.Input.Keys.B))
{
CheckServerMessages();
SendChatMessage("asdfsdaf");
}
catch { }
// Update current time
updateTimer = DateTime.Now + updateInterval;

View File

@@ -65,8 +65,8 @@ namespace Barotrauma.Networking
netStats = new NetStats();
#if DEBUG
config.SimulatedLoss = 0.2f;
config.SimulatedRandomLatency = 0.6f;
config.SimulatedLoss = 0.05f;
config.SimulatedRandomLatency = 0.3f;
config.SimulatedDuplicatesChance = 0.05f;
config.SimulatedMinimumLatency = 0.1f;
#endif
@@ -618,15 +618,13 @@ namespace Barotrauma.Networking
{
if (NetworkEvent.events.Count == 0) return;
List<NetConnection> recipients = new List<NetConnection>();
foreach (Client c in connectedClients)
{
if (c.character == null) continue;
//if (networkEvent.Type == NetworkEventType.UpdateEntity &&
// Vector2.Distance(e.SimPosition, c.character.SimPosition) > NetConfig.UpdateEntityDistance) continue;
List<Client> recipients = connectedClients.FindAll(c => c.character != null);
recipients.Add(c.Connection);
}
List<NetConnection> recipientConnections = new List<NetConnection>();
foreach (Client c in recipients)
{
recipientConnections.Add(c.Connection);
}
if (recipients.Count == 0) return;
@@ -635,17 +633,38 @@ namespace Barotrauma.Networking
Entity e = Entity.FindEntityByID(networkEvent.ID);
if (e == null) continue;
NetOutgoingMessage message = server.CreateMessage();
message.Write((byte)PacketTypes.NetworkEvent);
//if (!networkEvent.IsClient) continue;
networkEvent.FillData(message);
if (server.ConnectionsCount>0)
if (networkEvent.IsImportant)
{
server.SendMessage(message, recipients,
(networkEvent.IsImportant) ? NetDeliveryMethod.Unreliable : NetDeliveryMethod.ReliableUnordered, 0);
}
foreach (Client c in recipients)
{
ReliableMessage reliableMessage = c.ReliableChannel.CreateMessage();
reliableMessage.InnerMessage.Write((byte)PacketTypes.NetworkEvent);
if (!networkEvent.FillData(reliableMessage.InnerMessage))
{
break;
}
c.ReliableChannel.SendMessage(reliableMessage, c.Connection);
}
}
else
{
NetOutgoingMessage message = server.CreateMessage();
message.Write((byte)PacketTypes.NetworkEvent);
//if (!networkEvent.IsClient) continue;
if (!networkEvent.FillData(message))
{
continue;
}
if (server.ConnectionsCount>0)
{
server.SendMessage(message, recipientConnections,
(networkEvent.IsImportant) ? NetDeliveryMethod.Unreliable : NetDeliveryMethod.ReliableUnordered, 0);
}
}
}
NetworkEvent.events.Clear();
}

View File

@@ -22,5 +22,10 @@ namespace Barotrauma.Networking
public const float AllowedRagdollDistance = 0.1f;
public const float DeleteDisconnectedTime = 10.0f;
public const float AckInterval = 0.2f;
public const float RerequestInterval = 0.2f;
public const int ResendAttempts = 8;
}
}

View File

@@ -18,9 +18,8 @@ namespace Barotrauma.Networking
private Graph[] graphs;
private Queue<float>[] valueQueue;
private float[] lastValues;
private float[] totalValue;
private float[] lastValue;
const float UpdateInterval = 1.0f;
float updateTimer;
@@ -29,23 +28,21 @@ namespace Barotrauma.Networking
{
graphs = new Graph[3];
valueQueue = new Queue<float>[3];
totalValue = new float[3];
lastValue = new float[3];
for (int i = 0; i < 3; i++ )
{
valueQueue[i] = new Queue<float>();
{
graphs[i] = new Graph();
}
lastValues = new float[3];
}
}
public void AddValue(NetStatType statType, float value)
{
float valueChange = value - lastValues[(int)statType];
float valueChange = value - lastValue[(int)statType];
valueQueue[(int)statType].Enqueue(valueChange);
totalValue[(int)statType] += valueChange;
lastValues[(int)statType] = value;
lastValue[(int)statType] = value;
}
public void Update(float deltaTime)
@@ -56,17 +53,12 @@ namespace Barotrauma.Networking
for (int i = 0; i<3; i++)
{
int valueCount = valueQueue[i].Count;
float totalValue = 0.0f;
while (valueQueue[i].Count>1)
{
totalValue += valueQueue[i].Dequeue();
}
graphs[i].Update(valueCount==0 ? 0.0f : totalValue/valueCount);
graphs[i].Update(totalValue[i] * 10.0f);
totalValue[i] = 0.0f;
}
updateTimer = UpdateInterval;
updateTimer = UpdateInterval/10.0f;
}
public void Draw(SpriteBatch spriteBatch, Rectangle rect)

View File

@@ -56,7 +56,7 @@ namespace Barotrauma.Networking.ReliableMessages
internal class ReliableSender
{
private List<ReliableMessage> messageBuffer;
private Dictionary<ushort, ReliableMessage> messageBuffer;
private ushort messageCount;
@@ -66,11 +66,15 @@ namespace Barotrauma.Networking.ReliableMessages
private float ackTimer;
private float ackInterval;
public ReliableSender(NetPeer sender)
{
this.sender = sender;
messageBuffer = new List<ReliableMessage>();
messageCount = ushort.MaxValue - 5;
messageBuffer = new Dictionary<ushort, ReliableMessage>();
}
public ReliableMessage CreateMessage()
@@ -81,14 +85,42 @@ namespace Barotrauma.Networking.ReliableMessages
NetOutgoingMessage message = sender.CreateMessage();
var reliableMessage = new ReliableMessage(message, messageCount);
messageBuffer.Add(reliableMessage);
messageBuffer.Add(reliableMessage.ID, reliableMessage);
message.Write((byte)PacketTypes.ReliableMessage);
message.Write(messageCount);
while (messageBuffer.Count>100)
int bufferSize=100;
if (messageBuffer.Count>bufferSize)
{
messageBuffer.RemoveAt(0);
int end = messageCount-bufferSize;
int start = end - (messageBuffer.Count - bufferSize);
if (start<=0)
{
int wrappedStart = start + ushort.MaxValue;
if (wrappedStart==0) wrappedStart = ushort.MaxValue;
int wrappedEnd = end + ushort.MaxValue;
if (wrappedEnd==0) wrappedEnd = ushort.MaxValue;
for (ushort i = (ushort)wrappedStart; i <= (ushort)wrappedEnd; i++)
{
messageBuffer.Remove(i);
if (i == ushort.MaxValue) break;
Debug.WriteLine("removing message " + i);
}
}
for (ushort i = (ushort)Math.Max(start,1); i <= (ushort)Math.Max(end,1); i++)
{
messageBuffer.Remove(i);
if (i == ushort.MaxValue) break;
Debug.WriteLine("removing message " + i);
}
}
return reliableMessage;
@@ -98,6 +130,9 @@ namespace Barotrauma.Networking.ReliableMessages
public void SendMessage(ReliableMessage message, NetConnection connection)
{
ackInterval = 0.0f;
ackTimer = connection.AverageRoundtripTime;
message.SaveInnerMessage();
sender.SendMessage(message.InnerMessage, connection, NetDeliveryMethod.Unreliable, 0);
@@ -105,14 +140,6 @@ namespace Barotrauma.Networking.ReliableMessages
recipient = connection;
}
// NetOutgoingMessage msg = server.CreateMessage();
//reliableSender.CreateMessage(msg);
//msg.Write((byte)PacketTypes.Chatmessage);
//msg.Write((byte)type);
//msg.Write(message);
public void HandleResendRequest(NetIncomingMessage inc)
{
ushort messageId = inc.ReadUInt16();
@@ -124,15 +151,16 @@ namespace Barotrauma.Networking.ReliableMessages
private void ResendMessage(ushort messageId, NetConnection connection)
{
ReliableMessage message = messageBuffer.Find(m => m.ID == messageId);
if (message == null) return;
ReliableMessage message;
if (!messageBuffer.TryGetValue(messageId, out message)) return;
Debug.WriteLine("resending " + messageId);
NetOutgoingMessage resendMessage = sender.CreateMessage();
message.RestoreInnerMessage(resendMessage);
ackTimer = connection.AverageRoundtripTime;
sender.SendMessage(resendMessage, connection, NetDeliveryMethod.Unreliable);
}
@@ -152,7 +180,8 @@ namespace Barotrauma.Networking.ReliableMessages
sender.SendMessage(message, recipient, NetDeliveryMethod.Unreliable);
ackTimer = Math.Max(recipient.AverageRoundtripTime, 1.0f);
ackTimer = Math.Max(recipient.AverageRoundtripTime, NetConfig.AckInterval+ackInterval);
ackInterval += 0.1f;
}
}
@@ -160,6 +189,7 @@ namespace Barotrauma.Networking.ReliableMessages
{
ushort lastMessageID;
Queue<ushort> missingMessageIds;
Dictionary<ushort, MissingMessage> missingMessages;
private NetPeer receiver;
@@ -169,38 +199,49 @@ namespace Barotrauma.Networking.ReliableMessages
public ReliableReceiver(NetPeer receiver)
{
this.receiver = receiver;
lastMessageID = ushort.MaxValue - 5;
missingMessages = new Dictionary<ushort,MissingMessage>();
missingMessageIds = new Queue<ushort>();
}
public void Update(float deltaTime)
{
foreach (var message in missingMessages.Where(m => m.Value.ResendRequestsSent>10).ToList())
foreach (var message in missingMessages.Where(m => m.Value.ResendRequestsSent > NetConfig.ResendAttempts).ToList())
{
missingMessages.Remove(message.Key);
}
int bufferSize = 20;
while (missingMessageIds.Count>bufferSize)
{
ushort id = missingMessageIds.Dequeue();
missingMessages.Remove(id);
}
foreach (KeyValuePair<ushort, MissingMessage> valuePair in missingMessages)
{
MissingMessage missingMessage = valuePair.Value;
missingMessage.ResendTimer -= deltaTime;
if (missingMessage.ResendRequestsSent==0
|| missingMessage.ResendTimer<0.0f)
{
Debug.WriteLine("rerequest "+missingMessage.ID+" (try #"+missingMessage.ResendRequestsSent+")");
if (missingMessage.ResendTimer > 0.0f) continue;
Debug.WriteLine("rerequest "+missingMessage.ID+" (try #"+missingMessage.ResendRequestsSent+")");
NetOutgoingMessage resendRequest = receiver.CreateMessage();
resendRequest.Write((byte)PacketTypes.ResendRequest);
resendRequest.Write(missingMessage.ID);
NetOutgoingMessage resendRequest = receiver.CreateMessage();
resendRequest.Write((byte)PacketTypes.ResendRequest);
resendRequest.Write(missingMessage.ID);
receiver.SendMessage(resendRequest, recipient, NetDeliveryMethod.Unreliable);
receiver.SendMessage(resendRequest, recipient, NetDeliveryMethod.Unreliable);
missingMessage.ResendTimer = Math.Max(recipient.AverageRoundtripTime, 0.2f);
missingMessage.ResendRequestsSent++;
}
missingMessage.ResendTimer = Math.Max(recipient.AverageRoundtripTime, NetConfig.RerequestInterval);
missingMessage.ResendRequestsSent++;
}
}
@@ -217,23 +258,15 @@ namespace Barotrauma.Networking.ReliableMessages
if (Math.Abs((int)lastMessageID - (int)id) > ushort.MaxValue / 2)
{
//id wrapped around and we missed some messages in between, rerequest them
if (lastMessageID<=ushort.MaxValue && id>1)
if (lastMessageID>ushort.MaxValue/2 && id>=1)
{
for (ushort i = (ushort)(Math.Min(lastMessageID, (ushort)(ushort.MaxValue-1)) + 1); i < ushort.MaxValue; i++)
{
//message already marked as missed, continue
if (missingMessages.ContainsKey((i))) continue;
Debug.WriteLine("added " + i + " to missed");
missingMessages.Add(i, new MissingMessage((ushort)i));
QueueMissingMessage(i);
}
for (ushort i = 1; i < id; i++)
{
//message already marked as missed, continue
if (missingMessages.ContainsKey((i))) continue;
Debug.WriteLine("added " + i + " to missed");
missingMessages.Add(i, new MissingMessage((ushort)i));
QueueMissingMessage(i);
}
lastMessageID = id;
@@ -246,11 +279,7 @@ namespace Barotrauma.Networking.ReliableMessages
}
else
{
if (missingMessages.ContainsKey(id))
{
Debug.WriteLine("remove " + id + " from missed");
missingMessages.Remove(id);
}
RemoveMissingMessage(id);
}
}
else
@@ -259,11 +288,7 @@ namespace Barotrauma.Networking.ReliableMessages
{
for (ushort i = (ushort)(lastMessageID+1); i < id; i++ )
{
//message already marked as missed, continue
if (missingMessages.ContainsKey((i))) continue;
Debug.WriteLine("added "+i+" to missed");
missingMessages.Add(i, new MissingMessage((ushort)i));
QueueMissingMessage(i);
}
}
@@ -275,11 +300,7 @@ namespace Barotrauma.Networking.ReliableMessages
}
else
{
if (missingMessages.ContainsKey(id))
{
Debug.WriteLine("remove "+id+" from missed");
missingMessages.Remove(id);
}
RemoveMissingMessage(id);
}
lastMessageID = Math.Max(lastMessageID, id);
@@ -288,21 +309,39 @@ namespace Barotrauma.Networking.ReliableMessages
return true;
}
private void QueueMissingMessage(ushort id)
{
//message already marked as missed, continue
if (missingMessages.ContainsKey(id)) return;
Debug.WriteLine("added " + id + " to missed");
missingMessages.Add(id, new MissingMessage(id));
missingMessageIds.Enqueue(id);
}
private void RemoveMissingMessage(ushort id)
{
if (!missingMessages.ContainsKey(id)) return;
Debug.WriteLine("remove " + id + " from missed");
missingMessages.Remove(id);
}
public void HandleAckMessage(NetIncomingMessage inc)
{
int messageId = inc.ReadUInt16();
ushort messageId = inc.ReadUInt16();
recipient = inc.SenderConnection;
//id matches, all good
if (messageId == lastMessageID)
{
Debug.WriteLine("Received ack message: " + messageId + ", all good");
return;
}
if (lastMessageID > messageId)
if (lastMessageID > messageId && Math.Abs((int)lastMessageID - (int)messageId) < ushort.MaxValue / 2)
{
//shouldn't happen: we have somehow received messages that the other end hasn't sent
Debug.WriteLine("Reliable message error - recipient last sent: " + messageId + " (current count " + lastMessageID + ")");
@@ -315,11 +354,12 @@ namespace Barotrauma.Networking.ReliableMessages
{
for (ushort i = (ushort)Math.Min((int)lastMessageID + 1, ushort.MaxValue); i <= ushort.MaxValue; i++)
{
if (!missingMessages.ContainsKey(i)) missingMessages.Add(i, new MissingMessage(i));
if (i == ushort.MaxValue && lastMessageID == ushort.MaxValue) break;
if (!missingMessages.ContainsKey(i)) missingMessages.Add(i, new MissingMessage(i));
if (i == ushort.MaxValue) break;
}
for (ushort i = 1; i <= messageId; i++)
for (ushort i = 1; i < messageId; i++)
{
if (!missingMessages.ContainsKey(i)) missingMessages.Add(i, new MissingMessage(i));
}
@@ -328,22 +368,12 @@ namespace Barotrauma.Networking.ReliableMessages
{
for (ushort i = (ushort)Math.Min((int)lastMessageID+1, ushort.MaxValue); i <= messageId; i++)
{
if (!missingMessages.ContainsKey(i)) missingMessages.Add(i, new MissingMessage(i));
if (!missingMessages.ContainsKey(i)) missingMessages.Add(i, new MissingMessage(i));
if (i == ushort.MaxValue) break;
}
}
// Debug.WriteLine("received recent request for msg id " + messageId);
//ReliableMessage message = messageBuffer.Find(m => m.ID == messageId);
//if (message == null) return;
//NetOutgoingMessage resendMessage = sender.CreateMessage();
//message.RestoreInnerMessage(resendMessage);
//sender.SendMessage(resendMessage, inc.SenderConnection, NetDeliveryMethod.Unreliable);
lastMessageID = messageId;
}
}

View File

@@ -389,7 +389,7 @@ namespace Barotrauma
GUI.Draw((float)deltaTime, spriteBatch, null);
spriteBatch.DrawString(GUI.Font, "Barotrauma v"+GameMain.Version, new Vector2(10, GameMain.GraphicsHeight-20), Color.White);
spriteBatch.DrawString(GUI.Font, "Barotrauma chat lag test build", new Vector2(10, GameMain.GraphicsHeight-20), Color.White);
spriteBatch.End();
}

View File

@@ -5,6 +5,7 @@ using FarseerPhysics;
using FarseerPhysics.Dynamics;
using Microsoft.Xna.Framework;
using Barotrauma.Sounds;
using System;
namespace Barotrauma
{
@@ -41,7 +42,14 @@ namespace Barotrauma
if (oggSound == null)
{
oggSound = OggSound.Load(file);
try
{
oggSound = OggSound.Load(file);
}
catch (Exception e)
{
DebugConsole.ThrowError("Failed to load sound "+file+"!", e);
}
ALHelper.Check();
}

Binary file not shown.