- fixed ReliableChannel going crazy if a client disconnects and reconnects immediately after: the client created a new ReliableChannel but the server was still using the old one, causing the client to rerequest a ton of messages (now the server resets the channel when a client rejoins and reliablechannel resets itself if the message IDs are too far apart)
- syncing statuseffects caused by using an item on self
This commit is contained in:
@@ -1306,7 +1306,7 @@ namespace Barotrauma
|
||||
|
||||
// while (timer < dimDuration && Character.controlled == null)
|
||||
// {
|
||||
// timer += CoroutineManager.DeltaTime;
|
||||
// timer += CoroutineManager.UnscaledDeltaTime;
|
||||
|
||||
// if (cam != null) cam.OffsetAmount = 0.0f;
|
||||
|
||||
@@ -1320,7 +1320,7 @@ namespace Barotrauma
|
||||
// float lerpLightBack = 0.0f;
|
||||
// while (lerpLightBack < 1.0f)
|
||||
// {
|
||||
// lerpLightBack = Math.Min(lerpLightBack + CoroutineManager.DeltaTime*5.0f, 1.0f);
|
||||
// lerpLightBack = Math.Min(lerpLightBack + CoroutineManager.UnscaledDeltaTime*5.0f, 1.0f);
|
||||
|
||||
// GameMain.LightManager.AmbientLight = Color.Lerp(darkLight, prevAmbientLight, lerpLightBack);
|
||||
// yield return CoroutineStatus.Running;
|
||||
@@ -1457,6 +1457,9 @@ namespace Barotrauma
|
||||
case NetworkEventType.InventoryUpdate:
|
||||
if (inventory == null) return false;
|
||||
return inventory.FillNetworkData(NetworkEventType.InventoryUpdate, message, data);
|
||||
case NetworkEventType.ApplyStatusEffect:
|
||||
message.Write((ushort)data);
|
||||
return true;
|
||||
case NetworkEventType.ImportantEntityUpdate:
|
||||
|
||||
message.WriteRangedSingle(health, minHealth, maxHealth, 8);
|
||||
@@ -1559,8 +1562,6 @@ namespace Barotrauma
|
||||
switch (type)
|
||||
{
|
||||
case NetworkEventType.PickItem:
|
||||
|
||||
|
||||
ushort itemId = message.ReadUInt16();
|
||||
|
||||
bool pickHit = message.ReadBoolean();
|
||||
@@ -1570,18 +1571,18 @@ namespace Barotrauma
|
||||
|
||||
System.Diagnostics.Debug.WriteLine("item id: "+itemId);
|
||||
|
||||
Item item = FindEntityByID(itemId) as Item;
|
||||
if (item != null)
|
||||
Item pickedItem = FindEntityByID(itemId) as Item;
|
||||
if (pickedItem != null)
|
||||
{
|
||||
if (item == selectedConstruction)
|
||||
if (pickedItem == selectedConstruction)
|
||||
{
|
||||
GameServer.Log(Name + " deselected " + item.Name, Color.Orange);
|
||||
GameServer.Log(Name + " deselected " + pickedItem.Name, Color.Orange);
|
||||
}
|
||||
else
|
||||
{
|
||||
GameServer.Log(Name + " selected " + item.Name, Color.Orange);
|
||||
GameServer.Log(Name + " selected " + pickedItem.Name, Color.Orange);
|
||||
}
|
||||
item.Pick(this, false, pickHit, actionHit);
|
||||
pickedItem.Pick(this, false, pickHit, actionHit);
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -1650,18 +1651,21 @@ namespace Barotrauma
|
||||
if (inventory == null) return;
|
||||
inventory.ReadNetworkData(NetworkEventType.InventoryUpdate, message, sendingTime);
|
||||
return;
|
||||
case NetworkEventType.ApplyStatusEffect:
|
||||
ushort id = message.ReadUInt16();
|
||||
|
||||
data = id;
|
||||
|
||||
var item = FindEntityByID(id) as Item;
|
||||
if (item == null) return;
|
||||
|
||||
item.ApplyStatusEffects(ActionType.OnUse, 1.0f, this);
|
||||
|
||||
break;
|
||||
case NetworkEventType.ImportantEntityUpdate:
|
||||
|
||||
health = message.ReadRangedSingle(minHealth, 100.0f, 8);
|
||||
|
||||
// MathHelper.Clamp((message.ReadByte() / 255.0f) * maxHealth, 0.0f, maxHealth);
|
||||
|
||||
//if (health == 0.0f)
|
||||
//{
|
||||
// causeOfDeath = (CauseOfDeath)message.ReadRangedInteger(0, Enum.GetValues(typeof(CauseOfDeath)).Length-1);
|
||||
// Kill(causeOfDeath, true);
|
||||
//}
|
||||
|
||||
bool allOk = message.ReadBoolean();
|
||||
if (allOk)
|
||||
{
|
||||
|
||||
@@ -278,7 +278,7 @@ namespace Barotrauma
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
protected void ApplyToProperty(ObjectProperty property, object value, float deltaTime)
|
||||
private void ApplyToProperty(ObjectProperty property, object value, float deltaTime)
|
||||
{
|
||||
if (disableDeltaTime || setValue) deltaTime = 1.0f;
|
||||
|
||||
|
||||
@@ -88,7 +88,8 @@ namespace Barotrauma
|
||||
|
||||
if (Items[slotIndex] == null) return false;
|
||||
|
||||
Items[slotIndex].ApplyStatusEffects(ActionType.OnUse, 0.016f, character);
|
||||
Items[slotIndex].ApplyStatusEffects(ActionType.OnUse, 1.0f, character);
|
||||
new NetworkEvent(NetworkEventType.ApplyStatusEffect, character.ID, true, Items[slotIndex].ID);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -689,6 +689,7 @@ namespace Barotrauma.Networking
|
||||
if (existingClient != null)
|
||||
{
|
||||
existingClient.Connection = inc.SenderConnection;
|
||||
existingClient.ReliableChannel = new ReliableChannel(server);
|
||||
inc.SenderConnection.Approve();
|
||||
return;
|
||||
}
|
||||
@@ -1671,7 +1672,7 @@ namespace Barotrauma.Networking
|
||||
if (client.FileStreamSender != null) client.FileStreamSender.Dispose();
|
||||
}
|
||||
|
||||
server.Shutdown("The server has shut down");
|
||||
server.Shutdown("The server has been shut down");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,9 @@ namespace Barotrauma.Networking
|
||||
UpdateProperty = 10,
|
||||
WallDamage = 11,
|
||||
|
||||
PhysicsBodyPosition = 12
|
||||
PhysicsBodyPosition = 12,
|
||||
|
||||
ApplyStatusEffect = 13
|
||||
}
|
||||
|
||||
class NetworkEvent
|
||||
@@ -44,39 +46,42 @@ namespace Barotrauma.Networking
|
||||
static NetworkEvent()
|
||||
{
|
||||
deliveryMethod = new NetworkEventDeliveryMethod[Enum.GetNames(typeof(NetworkEventType)).Length];
|
||||
deliveryMethod[(int)NetworkEventType.ImportantEntityUpdate] = NetworkEventDeliveryMethod.ReliableChannel;
|
||||
deliveryMethod[(int)NetworkEventType.ImportantComponentUpdate] = NetworkEventDeliveryMethod.ReliableChannel;
|
||||
deliveryMethod[(int)NetworkEventType.KillCharacter] = NetworkEventDeliveryMethod.ReliableLidgren;
|
||||
deliveryMethod[(int)NetworkEventType.SelectCharacter] = NetworkEventDeliveryMethod.ReliableChannel;
|
||||
deliveryMethod[(int)NetworkEventType.ImportantEntityUpdate] = NetworkEventDeliveryMethod.ReliableChannel;
|
||||
deliveryMethod[(int)NetworkEventType.ImportantComponentUpdate] = NetworkEventDeliveryMethod.ReliableChannel;
|
||||
deliveryMethod[(int)NetworkEventType.KillCharacter] = NetworkEventDeliveryMethod.ReliableLidgren;
|
||||
deliveryMethod[(int)NetworkEventType.SelectCharacter] = NetworkEventDeliveryMethod.ReliableChannel;
|
||||
|
||||
deliveryMethod[(int)NetworkEventType.ImportantComponentUpdate] = NetworkEventDeliveryMethod.ReliableChannel;
|
||||
deliveryMethod[(int)NetworkEventType.PickItem] = NetworkEventDeliveryMethod.ReliableChannel;
|
||||
deliveryMethod[(int)NetworkEventType.DropItem] = NetworkEventDeliveryMethod.ReliableChannel;
|
||||
deliveryMethod[(int)NetworkEventType.InventoryUpdate] = NetworkEventDeliveryMethod.ReliableChannel;
|
||||
deliveryMethod[(int)NetworkEventType.ItemFixed] = NetworkEventDeliveryMethod.ReliableLidgren;
|
||||
deliveryMethod[(int)NetworkEventType.ImportantComponentUpdate] = NetworkEventDeliveryMethod.ReliableChannel;
|
||||
deliveryMethod[(int)NetworkEventType.PickItem] = NetworkEventDeliveryMethod.ReliableChannel;
|
||||
deliveryMethod[(int)NetworkEventType.DropItem] = NetworkEventDeliveryMethod.ReliableChannel;
|
||||
deliveryMethod[(int)NetworkEventType.InventoryUpdate] = NetworkEventDeliveryMethod.ReliableChannel;
|
||||
deliveryMethod[(int)NetworkEventType.ItemFixed] = NetworkEventDeliveryMethod.ReliableLidgren;
|
||||
|
||||
deliveryMethod[(int)NetworkEventType.UpdateProperty] = NetworkEventDeliveryMethod.ReliableChannel;
|
||||
deliveryMethod[(int)NetworkEventType.WallDamage] = NetworkEventDeliveryMethod.ReliableChannel;
|
||||
deliveryMethod[(int)NetworkEventType.UpdateProperty] = NetworkEventDeliveryMethod.ReliableChannel;
|
||||
deliveryMethod[(int)NetworkEventType.WallDamage] = NetworkEventDeliveryMethod.ReliableChannel;
|
||||
|
||||
deliveryMethod[(int)NetworkEventType.ApplyStatusEffect] = NetworkEventDeliveryMethod.ReliableLidgren;
|
||||
|
||||
overridePrevious = new bool[deliveryMethod.Length];
|
||||
for (int i = 0; i < overridePrevious.Length; i++ )
|
||||
{
|
||||
overridePrevious[i] = true;
|
||||
}
|
||||
overridePrevious[(int)NetworkEventType.KillCharacter] = false;
|
||||
overridePrevious[(int)NetworkEventType.KillCharacter] = false;
|
||||
|
||||
overridePrevious[(int)NetworkEventType.PickItem] = false;
|
||||
overridePrevious[(int)NetworkEventType.DropItem] = false;
|
||||
overridePrevious[(int)NetworkEventType.ItemFixed] = false;
|
||||
overridePrevious[(int)NetworkEventType.PickItem] = false;
|
||||
overridePrevious[(int)NetworkEventType.DropItem] = false;
|
||||
overridePrevious[(int)NetworkEventType.ItemFixed] = false;
|
||||
overridePrevious[(int)NetworkEventType.ApplyStatusEffect] = false;
|
||||
}
|
||||
|
||||
private ushort id;
|
||||
private readonly ushort id;
|
||||
|
||||
private NetworkEventType eventType;
|
||||
private readonly NetworkEventType eventType;
|
||||
|
||||
private bool isClientEvent;
|
||||
private readonly bool isClientEvent;
|
||||
|
||||
private object data;
|
||||
private readonly object data;
|
||||
|
||||
public NetConnection SenderConnection;
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Barotrauma.Networking.ReliableMessages
|
||||
{
|
||||
@@ -61,6 +60,16 @@ namespace Barotrauma.Networking.ReliableMessages
|
||||
receiver.Update(deltaTime);
|
||||
}
|
||||
|
||||
public static int IdDiff(ushort id1, ushort id2)
|
||||
{
|
||||
if (Math.Abs((int)id1 - (int)id2) > ushort.MaxValue / 2)
|
||||
{
|
||||
return (ushort.MaxValue - Math.Max(id1, id2)) + Math.Min(id1, id2);
|
||||
}
|
||||
|
||||
return Math.Abs(id1 - id2);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal class ReliableSender
|
||||
@@ -81,14 +90,14 @@ namespace Barotrauma.Networking.ReliableMessages
|
||||
{
|
||||
this.sender = sender;
|
||||
|
||||
messageCount = ushort.MaxValue - 5;
|
||||
messageCount = 1;
|
||||
|
||||
messageBuffer = new Dictionary<ushort, ReliableMessage>();
|
||||
}
|
||||
|
||||
public ReliableMessage CreateMessage()
|
||||
{
|
||||
ushort messageID = (messageCount==ushort.MaxValue) ? (ushort)0 : (ushort)(messageCount + 1);
|
||||
ushort messageID = (messageCount == ushort.MaxValue) ? (ushort)1 : (ushort)(messageCount + 1);
|
||||
|
||||
NetOutgoingMessage message = sender.CreateMessage();
|
||||
|
||||
@@ -100,16 +109,15 @@ namespace Barotrauma.Networking.ReliableMessages
|
||||
|
||||
if (messageBuffer.Count > NetConfig.ReliableMessageBufferSize)
|
||||
{
|
||||
|
||||
int end = messageCount - NetConfig.ReliableMessageBufferSize;
|
||||
int start = end - (messageBuffer.Count - NetConfig.ReliableMessageBufferSize);
|
||||
|
||||
if (start<0)
|
||||
if (start < 0)
|
||||
{
|
||||
int wrappedStart = start + ushort.MaxValue;
|
||||
if (wrappedStart==0) wrappedStart = ushort.MaxValue;
|
||||
if (wrappedStart == 0) wrappedStart = ushort.MaxValue;
|
||||
int wrappedEnd = end + ushort.MaxValue;
|
||||
if (wrappedEnd==0) wrappedEnd = ushort.MaxValue;
|
||||
if (wrappedEnd == 0) wrappedEnd = ushort.MaxValue;
|
||||
|
||||
for (ushort i = (ushort)wrappedStart; i <= (ushort)wrappedEnd; i++)
|
||||
{
|
||||
@@ -128,8 +136,6 @@ namespace Barotrauma.Networking.ReliableMessages
|
||||
}
|
||||
|
||||
return reliableMessage;
|
||||
|
||||
//server.SendMessage(msg, server.Connections, NetDeliveryMethod.Unreliable, 0);
|
||||
}
|
||||
|
||||
public void SendMessage(ReliableMessage message, NetConnection connection)
|
||||
@@ -139,6 +145,8 @@ namespace Barotrauma.Networking.ReliableMessages
|
||||
|
||||
messageBuffer.Add(message.ID, message);
|
||||
|
||||
Debug.WriteLine("sending reliable massage (id " + message.ID + ")");
|
||||
|
||||
if (messageCount == ushort.MaxValue) messageCount = 0;
|
||||
messageCount++;
|
||||
|
||||
@@ -190,9 +198,9 @@ namespace Barotrauma.Networking.ReliableMessages
|
||||
|
||||
sender.SendMessage(message, recipient, NetDeliveryMethod.Unreliable);
|
||||
|
||||
float roundTripTime = Math.Min(recipient.AverageRoundtripTime, 0.5f);
|
||||
float roundTripTime = Math.Min(recipient.AverageRoundtripTime, 1.0f);
|
||||
|
||||
idSendTimer = Math.Max(roundTripTime, NetConfig.IdSendInterval+idSendInterval);
|
||||
idSendTimer = Math.Max(roundTripTime, NetConfig.IdSendInterval + idSendInterval);
|
||||
idSendInterval += 0.1f;
|
||||
}
|
||||
}
|
||||
@@ -212,7 +220,7 @@ namespace Barotrauma.Networking.ReliableMessages
|
||||
{
|
||||
this.receiver = receiver;
|
||||
|
||||
lastMessageID = ushort.MaxValue - 5;
|
||||
lastMessageID = 1;
|
||||
|
||||
missingMessages = new Dictionary<ushort,MissingMessage>();
|
||||
missingMessageIds = new Queue<ushort>();
|
||||
@@ -251,7 +259,7 @@ namespace Barotrauma.Networking.ReliableMessages
|
||||
receiver.SendMessage(resendRequest, recipient,
|
||||
missingMessage.ResendRequestsSent==0 ? NetDeliveryMethod.ReliableUnordered : NetDeliveryMethod.Unreliable);
|
||||
|
||||
float roundTripTime = Math.Min(recipient.AverageRoundtripTime, 0.5f);
|
||||
float roundTripTime = Math.Min(recipient.AverageRoundtripTime, 1.0f);
|
||||
|
||||
missingMessage.ResendTimer = Math.Max(roundTripTime, NetConfig.RerequestInterval);
|
||||
missingMessage.ResendRequestsSent++;
|
||||
@@ -266,6 +274,13 @@ namespace Barotrauma.Networking.ReliableMessages
|
||||
|
||||
ushort id = message.ReadUInt16();
|
||||
|
||||
if (ReliableChannel.IdDiff(lastMessageID, id) > NetConfig.ReliableMessageBufferSize)
|
||||
{
|
||||
Debug.WriteLine("id diff > NetConfig.ReliableMessageBufferSize, resetting reliable channel");
|
||||
lastMessageID = id;
|
||||
return false;
|
||||
}
|
||||
|
||||
Debug.WriteLine("received message ID " + id + " - last id: " + lastMessageID);
|
||||
|
||||
//wrapped around
|
||||
@@ -329,7 +344,10 @@ namespace Barotrauma.Networking.ReliableMessages
|
||||
if (missingMessages.ContainsKey(id)) return;
|
||||
|
||||
Debug.WriteLine("added " + id + " to missed");
|
||||
missingMessages.Add(id, new MissingMessage(id));
|
||||
|
||||
float waitTime = Math.Abs(lastMessageID - id)>1 ? 0.0f : recipient.AverageRoundtripTime*0.5f;
|
||||
|
||||
missingMessages.Add(id, new MissingMessage(id, waitTime));
|
||||
|
||||
missingMessageIds.Enqueue(id);
|
||||
}
|
||||
@@ -355,9 +373,15 @@ namespace Barotrauma.Networking.ReliableMessages
|
||||
return;
|
||||
}
|
||||
|
||||
if (ReliableChannel.IdDiff(lastMessageID, messageId) > NetConfig.ReliableMessageBufferSize)
|
||||
{
|
||||
Debug.WriteLine("id diff > NetConfig.ReliableMessageBufferSize, resetting reliable channel");
|
||||
lastMessageID = messageId;
|
||||
return;
|
||||
}
|
||||
|
||||
if (messageId < lastMessageID && 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("Received id update message: " + messageId + ": ignoring, already received (" + lastMessageID + ")");
|
||||
return;
|
||||
}
|
||||
@@ -373,7 +397,7 @@ namespace Barotrauma.Networking.ReliableMessages
|
||||
if (i == ushort.MaxValue) break;
|
||||
}
|
||||
|
||||
for (ushort i = 1; i < messageId; i++)
|
||||
for (ushort i = 1; i <= messageId; i++)
|
||||
{
|
||||
QueueMissingMessage(i);
|
||||
}
|
||||
@@ -396,6 +420,8 @@ namespace Barotrauma.Networking.ReliableMessages
|
||||
|
||||
lastMessageID = messageId;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
internal class MissingMessage
|
||||
@@ -415,6 +441,12 @@ namespace Barotrauma.Networking.ReliableMessages
|
||||
{
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public MissingMessage(ushort id, float resendTimer)
|
||||
{
|
||||
this.id = id;
|
||||
this.ResendTimer = resendTimer;
|
||||
}
|
||||
}
|
||||
|
||||
class ReliableMessage
|
||||
|
||||
Reference in New Issue
Block a user