A fix to occasional "unknown object header" errors.
If an entity had been removed and it's ID taken by some other entity, clients who hadn't received a message about the removal and the new entity would end up reading ENTITY_POSITION messages for the new entity incorrectly. Reading an incorrect number of bits from the message would also prevent the clients from reading the rest of the data in the packet properly. Now the server doesn't send position updates to clients during midround syncing (because there's no guarantee they know about the entity yet). Clients also force the read position to the correct place after reading a position update in case something goes wrong when reading the msg.
This commit is contained in:
@@ -425,11 +425,9 @@ namespace Barotrauma
|
||||
tempBuffer.Write(aiming);
|
||||
tempBuffer.Write(use);
|
||||
|
||||
if (AnimController.Limbs.Any(l => l != null && l.attack != null))
|
||||
{
|
||||
tempBuffer.Write(attack);
|
||||
}
|
||||
|
||||
bool hasAttackLimb = AnimController.Limbs.Any(l => l != null && l.attack != null);
|
||||
tempBuffer.Write(hasAttackLimb);
|
||||
if (hasAttackLimb) tempBuffer.Write(attack);
|
||||
|
||||
if (aiming)
|
||||
{
|
||||
@@ -491,7 +489,8 @@ namespace Barotrauma
|
||||
keys[(int)InputType.Use].Held = useInput;
|
||||
keys[(int)InputType.Use].SetState(false, useInput);
|
||||
|
||||
if (AnimController.Limbs.Any(l => l != null && l.attack != null))
|
||||
bool hasAttackLimb = msg.ReadBoolean();
|
||||
if (hasAttackLimb)
|
||||
{
|
||||
bool attackInput = msg.ReadBoolean();
|
||||
keys[(int)InputType.Attack].Held = attackInput;
|
||||
|
||||
@@ -921,18 +921,17 @@ namespace Barotrauma.Networking
|
||||
UInt16 id = inc.ReadUInt16();
|
||||
byte msgLength = inc.ReadByte();
|
||||
|
||||
long msgEndPos = inc.Position + msgLength * 8;
|
||||
|
||||
var entity = Entity.FindEntityByID(id) as IServerSerializable;
|
||||
if (entity == null)
|
||||
{
|
||||
//skip through the rest of the message
|
||||
inc.Position += msgLength * 8;
|
||||
}
|
||||
else
|
||||
if (entity != null)
|
||||
{
|
||||
entity.ClientRead(objHeader, inc, sendingTime);
|
||||
}
|
||||
|
||||
inc.ReadPadBits();
|
||||
//force to the correct position in case the entity doesn't exist
|
||||
//or the message wasn't read correctly for whatever reason
|
||||
inc.Position = msgEndPos;
|
||||
break;
|
||||
case ServerNetObject.ENTITY_EVENT:
|
||||
case ServerNetObject.ENTITY_EVENT_INITIAL:
|
||||
|
||||
@@ -703,12 +703,12 @@ namespace Barotrauma.Networking
|
||||
#if DEBUG
|
||||
//client thinks they've received a msg we haven't sent yet (corrupted packet, msg read/written incorrectly?)
|
||||
if (NetIdUtils.IdMoreRecent(lastRecvChatMsgID, c.lastChatMsgQueueID))
|
||||
DebugConsole.ThrowError("client.lastRecvChatMsgID > lastChatMsgQueueID");
|
||||
|
||||
DebugConsole.ThrowError("client.lastRecvChatMsgID > lastChatMsgQueueID (" + c.lastRecvChatMsgID + " > " + c.lastChatMsgQueueID + ")");
|
||||
|
||||
if (lastRecvEntityEventID > lastEntityEventID)
|
||||
DebugConsole.ThrowError("client.lastRecvEntityEventID > lastEntityEventID");
|
||||
DebugConsole.ThrowError("client.lastRecvEntityEventID > lastEntityEventID (" + c.lastRecvEntityEventID + " > " + lastEntityEventID + ")");
|
||||
#endif
|
||||
|
||||
|
||||
if (NetIdUtils.IdMoreRecent(lastRecvChatMsgID, c.lastRecvChatMsgID)) c.lastRecvChatMsgID = lastRecvChatMsgID;
|
||||
if (NetIdUtils.IdMoreRecent(c.lastRecvChatMsgID, c.lastChatMsgQueueID)) c.lastRecvChatMsgID = c.lastChatMsgQueueID;
|
||||
|
||||
@@ -833,40 +833,45 @@ namespace Barotrauma.Networking
|
||||
cMsg.ServerWrite(outmsg, c);
|
||||
}
|
||||
|
||||
foreach (Character character in Character.CharacterList)
|
||||
//don't send position updates to characters who are still midround syncing
|
||||
//characters or items spawned mid-round don't necessarily exist at the client's end yet
|
||||
if (!c.NeedsMidRoundSync)
|
||||
{
|
||||
if (!character.Enabled) continue;
|
||||
|
||||
if (c.Character != null &&
|
||||
Vector2.DistanceSquared(character.WorldPosition, c.Character.WorldPosition) >=
|
||||
NetConfig.CharacterIgnoreDistance * NetConfig.CharacterIgnoreDistance)
|
||||
foreach (Character character in Character.CharacterList)
|
||||
{
|
||||
continue;
|
||||
if (!character.Enabled) continue;
|
||||
|
||||
if (c.Character != null &&
|
||||
Vector2.DistanceSquared(character.WorldPosition, c.Character.WorldPosition) >=
|
||||
NetConfig.CharacterIgnoreDistance * NetConfig.CharacterIgnoreDistance)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
outmsg.Write((byte)ServerNetObject.ENTITY_POSITION);
|
||||
character.ServerWrite(outmsg, c);
|
||||
outmsg.WritePadBits();
|
||||
}
|
||||
|
||||
outmsg.Write((byte)ServerNetObject.ENTITY_POSITION);
|
||||
character.ServerWrite(outmsg, c);
|
||||
outmsg.WritePadBits();
|
||||
}
|
||||
foreach (Submarine sub in Submarine.Loaded)
|
||||
{
|
||||
//if docked to a sub with a smaller ID, don't send an update
|
||||
// (= update is only sent for the docked sub that has the smallest ID, doesn't matter if it's the main sub or a shuttle)
|
||||
if (sub.DockedTo.Any(s => s.ID < sub.ID)) continue;
|
||||
|
||||
foreach (Submarine sub in Submarine.Loaded)
|
||||
{
|
||||
//if docked to a sub with a smaller ID, don't send an update
|
||||
// (= update is only sent for the docked sub that has the smallest ID, doesn't matter if it's the main sub or a shuttle)
|
||||
if (sub.DockedTo.Any(s => s.ID < sub.ID)) continue;
|
||||
outmsg.Write((byte)ServerNetObject.ENTITY_POSITION);
|
||||
sub.ServerWrite(outmsg, c);
|
||||
outmsg.WritePadBits();
|
||||
}
|
||||
|
||||
outmsg.Write((byte)ServerNetObject.ENTITY_POSITION);
|
||||
sub.ServerWrite(outmsg, c);
|
||||
outmsg.WritePadBits();
|
||||
}
|
||||
foreach (Item item in Item.ItemList)
|
||||
{
|
||||
if (!item.NeedsPositionUpdate) continue;
|
||||
|
||||
foreach (Item item in Item.ItemList)
|
||||
{
|
||||
if (!item.NeedsPositionUpdate) continue;
|
||||
|
||||
outmsg.Write((byte)ServerNetObject.ENTITY_POSITION);
|
||||
item.ServerWritePosition(outmsg, c);
|
||||
outmsg.WritePadBits();
|
||||
outmsg.Write((byte)ServerNetObject.ENTITY_POSITION);
|
||||
item.ServerWritePosition(outmsg, c);
|
||||
outmsg.WritePadBits();
|
||||
}
|
||||
}
|
||||
|
||||
entityEventManager.Write(c, outmsg);
|
||||
|
||||
Reference in New Issue
Block a user