- 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:
Regalis
2016-03-27 20:20:34 +03:00
parent c8597f76be
commit 7f40071565
6 changed files with 100 additions and 57 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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