mirror of
https://github.com/MirrorNetworking/Mirror.git
synced 2024-11-18 02:50:32 +00:00
explicit message types
This commit is contained in:
parent
72132b89a8
commit
d8e33f933f
@ -103,8 +103,25 @@ public struct EntityStateMessage : NetworkMessage
|
|||||||
public ArraySegment<byte> payload;
|
public ArraySegment<byte> payload;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// state update for unreliable sync.
|
||||||
|
// baseline is always sent over Reliable channel.
|
||||||
|
public struct EntityStateMessageUnreliableBaseline : NetworkMessage
|
||||||
|
{
|
||||||
|
// baseline messages send their tick number as byte.
|
||||||
|
// delta messages are checked against that tick to avoid applying a
|
||||||
|
// delta on top of the wrong baseline.
|
||||||
|
// (byte is enough, we just need something small to compare against)
|
||||||
|
public byte baselineTick;
|
||||||
|
|
||||||
|
public uint netId;
|
||||||
|
// the serialized component data
|
||||||
|
// -> ArraySegment to avoid unnecessary allocations
|
||||||
|
public ArraySegment<byte> payload;
|
||||||
|
}
|
||||||
|
|
||||||
// state update for unreliable sync
|
// state update for unreliable sync
|
||||||
public struct EntityStateMessageUnreliable : NetworkMessage
|
// delta is always sent over Unreliable channel.
|
||||||
|
public struct EntityStateMessageUnreliableDelta : NetworkMessage
|
||||||
{
|
{
|
||||||
// baseline messages send their tick number as byte.
|
// baseline messages send their tick number as byte.
|
||||||
// delta messages are checked against that tick to avoid applying a
|
// delta messages are checked against that tick to avoid applying a
|
||||||
|
@ -516,7 +516,8 @@ internal static void RegisterMessageHandlers(bool hostMode)
|
|||||||
RegisterHandler<ObjectSpawnFinishedMessage>(_ => { });
|
RegisterHandler<ObjectSpawnFinishedMessage>(_ => { });
|
||||||
// host mode doesn't need state updates
|
// host mode doesn't need state updates
|
||||||
RegisterHandler<EntityStateMessage>(_ => { });
|
RegisterHandler<EntityStateMessage>(_ => { });
|
||||||
RegisterHandler<EntityStateMessageUnreliable>(_ => { });
|
RegisterHandler<EntityStateMessageUnreliableBaseline>(_ => { });
|
||||||
|
RegisterHandler<EntityStateMessageUnreliableDelta>(_ => { });
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -528,7 +529,8 @@ internal static void RegisterMessageHandlers(bool hostMode)
|
|||||||
RegisterHandler<ObjectSpawnStartedMessage>(OnObjectSpawnStarted);
|
RegisterHandler<ObjectSpawnStartedMessage>(OnObjectSpawnStarted);
|
||||||
RegisterHandler<ObjectSpawnFinishedMessage>(OnObjectSpawnFinished);
|
RegisterHandler<ObjectSpawnFinishedMessage>(OnObjectSpawnFinished);
|
||||||
RegisterHandler<EntityStateMessage>(OnEntityStateMessage);
|
RegisterHandler<EntityStateMessage>(OnEntityStateMessage);
|
||||||
RegisterHandler<EntityStateMessageUnreliable>(OnEntityStateMessageUnreliable);
|
RegisterHandler<EntityStateMessageUnreliableBaseline>(OnEntityStateMessageUnreliableBaseline);
|
||||||
|
RegisterHandler<EntityStateMessageUnreliableDelta>(OnEntityStateMessageUnreliableDelta);
|
||||||
}
|
}
|
||||||
|
|
||||||
// These handlers are the same for host and remote clients
|
// These handlers are the same for host and remote clients
|
||||||
@ -1447,63 +1449,84 @@ static void OnEntityStateMessage(EntityStateMessage message)
|
|||||||
else Debug.LogWarning($"Did not find target for sync message for {message.netId}. Were all prefabs added to the NetworkManager's spawnable list?\nNote: this can be completely normal because UDP messages may arrive out of order, so this message might have arrived after a Destroy message.");
|
else Debug.LogWarning($"Did not find target for sync message for {message.netId}. Were all prefabs added to the NetworkManager's spawnable list?\nNote: this can be completely normal because UDP messages may arrive out of order, so this message might have arrived after a Destroy message.");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OnEntityStateMessageUnreliable(EntityStateMessageUnreliable message, int channelId)
|
static void OnEntityStateMessageUnreliableBaseline(EntityStateMessageUnreliableBaseline message, int channelId)
|
||||||
{
|
{
|
||||||
|
// safety check: baseline should always arrive over Reliable channel.
|
||||||
|
if (channelId != Channels.Reliable)
|
||||||
|
{
|
||||||
|
Debug.LogError($"Client OnEntityStateMessageUnreliableBaseline arrived on channel {channelId} instead of Reliable. This should never happen!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Debug.Log($"NetworkClient.OnUpdateVarsMessage {msg.netId}");
|
// Debug.Log($"NetworkClient.OnUpdateVarsMessage {msg.netId}");
|
||||||
if (spawned.TryGetValue(message.netId, out NetworkIdentity identity) && identity != null)
|
if (spawned.TryGetValue(message.netId, out NetworkIdentity identity) && identity != null)
|
||||||
{
|
{
|
||||||
// unreliable delta?
|
// set the last received reliable baseline tick number.
|
||||||
if (channelId == Channels.Unreliable)
|
identity.lastUnreliableBaselineReceived = message.baselineTick;
|
||||||
{
|
|
||||||
// unreliable state sync messages may arrive out of order.
|
|
||||||
// only ever apply state that's newer than the last received state.
|
|
||||||
// note that we send one EntityStateMessage per Entity,
|
|
||||||
// so there will be multiple with the same == timestamp.
|
|
||||||
//
|
|
||||||
// note that a reliable baseline may arrive before/after a delta.
|
|
||||||
// that is fine.
|
|
||||||
if (connection.remoteTimeStamp < identity.lastUnreliableStateTime)
|
|
||||||
{
|
|
||||||
// debug log to show that it's working.
|
|
||||||
// can be tested via LatencySimulation scramble easily.
|
|
||||||
Debug.Log($"Client caught out of order Unreliable state message for {identity.name}. This is fine.\nIdentity timestamp={identity.lastUnreliableStateTime:F3} batch remoteTimestamp={connection.remoteTimeStamp:F3}");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// UDP messages may accidentally arrive twice.
|
|
||||||
// or even intentionally, if unreliableRedundancy is turned on.
|
|
||||||
else if (connection.remoteTimeStamp == identity.lastUnreliableStateTime)
|
|
||||||
{
|
|
||||||
// only log this if unreliableRedundancy is disabled.
|
|
||||||
// otherwise it's expected and will happen a lot.
|
|
||||||
if (!unreliableRedundancy) Debug.Log($"Client caught duplicate Unreliable state message for {identity.name}. This is fine.\nIdentity timestamp={identity.lastUnreliableStateTime:F3} batch remoteTimestamp={connection.remoteTimeStamp:F3}");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// make sure this delta is for the correct baseline.
|
|
||||||
// we don't want to apply an old delta on top of a new baseline.
|
|
||||||
if (message.baselineTick != identity.lastUnreliableBaselineReceived)
|
|
||||||
{
|
|
||||||
Debug.Log($"Client caught Unreliable state message for old baseline for {identity} with baselineTick={identity.lastUnreliableBaselineReceived} messageBaseline={message.baselineTick}. This is fine.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// set the new last received time for unreliable
|
|
||||||
identity.lastUnreliableStateTime = connection.remoteTimeStamp;
|
|
||||||
}
|
|
||||||
// reliable baseline?
|
|
||||||
else if (channelId == Channels.Reliable)
|
|
||||||
{
|
|
||||||
// set the last received reliable baseline tick number.
|
|
||||||
identity.lastUnreliableBaselineReceived = message.baselineTick;
|
|
||||||
}
|
|
||||||
|
|
||||||
// iniital is always 'true' because unreliable state sync alwasy serializes full
|
// iniital is always 'true' because unreliable state sync alwasy serializes full
|
||||||
using (NetworkReaderPooled reader = NetworkReaderPool.Get(message.payload))
|
using (NetworkReaderPooled reader = NetworkReaderPool.Get(message.payload))
|
||||||
{
|
{
|
||||||
// full state updates (initial=true) arrive over reliable.
|
// full state updates (initial=true) arrive over reliable.
|
||||||
|
identity.DeserializeClient(reader, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// no warning. unreliable messages often arrive before/after the reliable spawn/despawn messages.
|
||||||
|
// else Debug.LogWarning($"Did not find target for sync message for {message.netId}. Were all prefabs added to the NetworkManager's spawnable list?\nNote: this can be completely normal because UDP messages may arrive out of order, so this message might have arrived after a Destroy message.");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void OnEntityStateMessageUnreliableDelta(EntityStateMessageUnreliableDelta message, int channelId)
|
||||||
|
{
|
||||||
|
// safety check: baseline should always arrive over Reliable channel.
|
||||||
|
if (channelId != Channels.Unreliable)
|
||||||
|
{
|
||||||
|
Debug.LogError($"Client OnEntityStateMessageUnreliableDelta arrived on channel {channelId} instead of Unreliable. This should never happen!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Debug.Log($"NetworkClient.OnUpdateVarsMessage {msg.netId}");
|
||||||
|
if (spawned.TryGetValue(message.netId, out NetworkIdentity identity) && identity != null)
|
||||||
|
{
|
||||||
|
// unreliable state sync messages may arrive out of order.
|
||||||
|
// only ever apply state that's newer than the last received state.
|
||||||
|
// note that we send one EntityStateMessage per Entity,
|
||||||
|
// so there will be multiple with the same == timestamp.
|
||||||
|
//
|
||||||
|
// note that a reliable baseline may arrive before/after a delta.
|
||||||
|
// that is fine.
|
||||||
|
if (connection.remoteTimeStamp < identity.lastUnreliableStateTime)
|
||||||
|
{
|
||||||
|
// debug log to show that it's working.
|
||||||
|
// can be tested via LatencySimulation scramble easily.
|
||||||
|
Debug.Log($"Client caught out of order Unreliable state message for {identity.name}. This is fine.\nIdentity timestamp={identity.lastUnreliableStateTime:F3} batch remoteTimestamp={connection.remoteTimeStamp:F3}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// UDP messages may accidentally arrive twice.
|
||||||
|
// or even intentionally, if unreliableRedundancy is turned on.
|
||||||
|
else if (connection.remoteTimeStamp == identity.lastUnreliableStateTime)
|
||||||
|
{
|
||||||
|
// only log this if unreliableRedundancy is disabled.
|
||||||
|
// otherwise it's expected and will happen a lot.
|
||||||
|
if (!unreliableRedundancy) Debug.Log($"Client caught duplicate Unreliable state message for {identity.name}. This is fine.\nIdentity timestamp={identity.lastUnreliableStateTime:F3} batch remoteTimestamp={connection.remoteTimeStamp:F3}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure this delta is for the correct baseline.
|
||||||
|
// we don't want to apply an old delta on top of a new baseline.
|
||||||
|
if (message.baselineTick != identity.lastUnreliableBaselineReceived)
|
||||||
|
{
|
||||||
|
Debug.Log($"Client caught Unreliable state message for old baseline for {identity} with baselineTick={identity.lastUnreliableBaselineReceived} messageBaseline={message.baselineTick}. This is fine.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set the new last received time for unreliable
|
||||||
|
identity.lastUnreliableStateTime = connection.remoteTimeStamp;
|
||||||
|
|
||||||
|
// iniital is always 'true' because unreliable state sync alwasy serializes full
|
||||||
|
using (NetworkReaderPooled reader = NetworkReaderPool.Get(message.payload))
|
||||||
|
{
|
||||||
// delta state updates (initial=false) arrive over unreliable.
|
// delta state updates (initial=false) arrive over unreliable.
|
||||||
bool initialState = channelId == Channels.Reliable;
|
identity.DeserializeClient(reader, false);
|
||||||
identity.DeserializeClient(reader, initialState);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// no warning. unreliable messages often arrive before/after the reliable spawn/despawn messages.
|
// no warning. unreliable messages often arrive before/after the reliable spawn/despawn messages.
|
||||||
@ -1755,7 +1778,7 @@ static void BroadcastToServer(bool unreliableBaselineElapsed)
|
|||||||
// (do this before baseline, since baseline clears dirty bits)
|
// (do this before baseline, since baseline clears dirty bits)
|
||||||
if (writer.Position > 0)
|
if (writer.Position > 0)
|
||||||
{
|
{
|
||||||
EntityStateMessageUnreliable message = new EntityStateMessageUnreliable
|
EntityStateMessageUnreliableDelta message = new EntityStateMessageUnreliableDelta
|
||||||
{
|
{
|
||||||
baselineTick = identity.lastUnreliableBaselineSent,
|
baselineTick = identity.lastUnreliableBaselineSent,
|
||||||
netId = identity.netId,
|
netId = identity.netId,
|
||||||
@ -1789,7 +1812,7 @@ static void BroadcastToServer(bool unreliableBaselineElapsed)
|
|||||||
identity.lastUnreliableBaselineSent = (byte)Time.frameCount;
|
identity.lastUnreliableBaselineSent = (byte)Time.frameCount;
|
||||||
|
|
||||||
// send state update message
|
// send state update message
|
||||||
EntityStateMessageUnreliable message = new EntityStateMessageUnreliable
|
EntityStateMessageUnreliableBaseline message = new EntityStateMessageUnreliableBaseline
|
||||||
{
|
{
|
||||||
baselineTick = identity.lastUnreliableBaselineSent,
|
baselineTick = identity.lastUnreliableBaselineSent,
|
||||||
netId = identity.netId,
|
netId = identity.netId,
|
||||||
|
@ -323,7 +323,8 @@ internal static void RegisterMessageHandlers()
|
|||||||
RegisterHandler<NetworkPingMessage>(NetworkTime.OnServerPing, false);
|
RegisterHandler<NetworkPingMessage>(NetworkTime.OnServerPing, false);
|
||||||
RegisterHandler<NetworkPongMessage>(NetworkTime.OnServerPong, false);
|
RegisterHandler<NetworkPongMessage>(NetworkTime.OnServerPong, false);
|
||||||
RegisterHandler<EntityStateMessage>(OnEntityStateMessage, true);
|
RegisterHandler<EntityStateMessage>(OnEntityStateMessage, true);
|
||||||
RegisterHandler<EntityStateMessageUnreliable>(OnEntityStateMessageUnreliable, true);
|
RegisterHandler<EntityStateMessageUnreliableBaseline>(OnEntityStateMessageUnreliableBaseline, true);
|
||||||
|
RegisterHandler<EntityStateMessageUnreliableDelta>(OnEntityStateMessageUnreliableDelta, true);
|
||||||
RegisterHandler<TimeSnapshotMessage>(OnTimeSnapshotMessage, false); // unreliable may arrive before reliable authority went through
|
RegisterHandler<TimeSnapshotMessage>(OnTimeSnapshotMessage, false); // unreliable may arrive before reliable authority went through
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -439,8 +440,15 @@ static void OnEntityStateMessage(NetworkConnectionToClient connection, EntitySta
|
|||||||
}
|
}
|
||||||
|
|
||||||
// for client's owned ClientToServer components.
|
// for client's owned ClientToServer components.
|
||||||
static void OnEntityStateMessageUnreliable(NetworkConnectionToClient connection, EntityStateMessageUnreliable message, int channelId)
|
static void OnEntityStateMessageUnreliableBaseline(NetworkConnectionToClient connection, EntityStateMessageUnreliableBaseline message, int channelId)
|
||||||
{
|
{
|
||||||
|
// safety check: baseline should always arrive over Reliable channel.
|
||||||
|
if (channelId != Channels.Reliable)
|
||||||
|
{
|
||||||
|
Debug.LogError($"Server OnEntityStateMessageUnreliableBaseline arrived on channel {channelId} instead of Reliable. This should never happen!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// need to validate permissions carefully.
|
// need to validate permissions carefully.
|
||||||
// an attacker may attempt to modify a not-owned or not-ClientToServer component.
|
// an attacker may attempt to modify a not-owned or not-ClientToServer component.
|
||||||
|
|
||||||
@ -450,47 +458,8 @@ static void OnEntityStateMessageUnreliable(NetworkConnectionToClient connection,
|
|||||||
// owned by the connection?
|
// owned by the connection?
|
||||||
if (identity.connectionToClient == connection)
|
if (identity.connectionToClient == connection)
|
||||||
{
|
{
|
||||||
// unreliable delta?
|
// set the last received reliable baseline tick number.
|
||||||
if (channelId == Channels.Unreliable)
|
identity.lastUnreliableBaselineReceived = message.baselineTick;
|
||||||
{
|
|
||||||
// unreliable state sync messages may arrive out of order.
|
|
||||||
// only ever apply state that's newer than the last received state.
|
|
||||||
// note that we send one EntityStateMessage per Entity,
|
|
||||||
// so there will be multiple with the same == timestamp.
|
|
||||||
if (connection.remoteTimeStamp < identity.lastUnreliableStateTime)
|
|
||||||
{
|
|
||||||
// debug log to show that it's working.
|
|
||||||
// can be tested via LatencySimulation scramble easily.
|
|
||||||
Debug.Log($"Server caught out of order Unreliable state message for {identity.name}. This is fine.\nIdentity timestamp={identity.lastUnreliableStateTime:F3} batch remoteTimestamp={connection.remoteTimeStamp:F3}");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// UDP messages may accidentally arrive twice.
|
|
||||||
// or even intentionally, if unreliableRedundancy is turned on.
|
|
||||||
else if (connection.remoteTimeStamp == identity.lastUnreliableStateTime)
|
|
||||||
{
|
|
||||||
// only log this if unreliableRedundancy is disabled.
|
|
||||||
// otherwise it's expected and will happen a lot.
|
|
||||||
if (!unreliableRedundancy) Debug.Log($"Server caught duplicate Unreliable state message for {identity.name}. This is fine.\nIdentity timestamp={identity.lastUnreliableStateTime:F3} batch remoteTimestamp={connection.remoteTimeStamp:F3}");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// make sure this delta is for the correct baseline.
|
|
||||||
// we don't want to apply an old delta on top of a new baseline.
|
|
||||||
if (message.baselineTick != identity.lastUnreliableBaselineReceived)
|
|
||||||
{
|
|
||||||
Debug.Log($"Server caught Unreliable state message for old baseline for {identity} with baselineTick={identity.lastUnreliableBaselineReceived} messageBaseline={message.baselineTick}. This is fine.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// set the new last received time for unreliable
|
|
||||||
identity.lastUnreliableStateTime = connection.remoteTimeStamp;
|
|
||||||
}
|
|
||||||
// reliable baseline?
|
|
||||||
else if (channelId == Channels.Reliable)
|
|
||||||
{
|
|
||||||
// set the last received reliable baseline tick number.
|
|
||||||
identity.lastUnreliableBaselineReceived = message.baselineTick;
|
|
||||||
}
|
|
||||||
|
|
||||||
using (NetworkReaderPooled reader = NetworkReaderPool.Get(message.payload))
|
using (NetworkReaderPooled reader = NetworkReaderPool.Get(message.payload))
|
||||||
{
|
{
|
||||||
@ -498,9 +467,87 @@ static void OnEntityStateMessageUnreliable(NetworkConnectionToClient connection,
|
|||||||
// failure to deserialize disconnects to prevent exploits.
|
// failure to deserialize disconnects to prevent exploits.
|
||||||
//
|
//
|
||||||
// full state updates (initial=true) arrive over reliable.
|
// full state updates (initial=true) arrive over reliable.
|
||||||
|
if (!identity.DeserializeServer(reader, true))
|
||||||
|
{
|
||||||
|
if (exceptionsDisconnect)
|
||||||
|
{
|
||||||
|
Debug.LogError($"Server failed to deserialize client unreliable state for {identity.name} with netId={identity.netId}, Disconnecting.");
|
||||||
|
connection.Disconnect();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Debug.LogWarning($"Server failed to deserialize client unreliable state for {identity.name} with netId={identity.netId}.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// An attacker may attempt to modify another connection's entity
|
||||||
|
// This could also be a race condition of message in flight when
|
||||||
|
// RemoveClientAuthority is called, so not malicious.
|
||||||
|
// Don't disconnect, just log the warning.
|
||||||
|
else
|
||||||
|
Debug.LogWarning($"EntityStateMessage from {connection} for {identity.name} without authority.");
|
||||||
|
}
|
||||||
|
// no warning. unreliable messages often arrive before/after the reliable spawn/despawn messages.
|
||||||
|
// else Debug.LogWarning($"Did not find target for sync message for {message.netId} . Note: this can be completely normal because UDP messages may arrive out of order, so this message might have arrived after a Destroy message.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// for client's owned ClientToServer components.
|
||||||
|
static void OnEntityStateMessageUnreliableDelta(NetworkConnectionToClient connection, EntityStateMessageUnreliableDelta message, int channelId)
|
||||||
|
{
|
||||||
|
// safety check: baseline should always arrive over Reliable channel.
|
||||||
|
if (channelId != Channels.Unreliable)
|
||||||
|
{
|
||||||
|
Debug.LogError($"Server OnEntityStateMessageUnreliableDelta arrived on channel {channelId} instead of Unreliable. This should never happen!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// need to validate permissions carefully.
|
||||||
|
// an attacker may attempt to modify a not-owned or not-ClientToServer component.
|
||||||
|
|
||||||
|
// valid netId?
|
||||||
|
if (spawned.TryGetValue(message.netId, out NetworkIdentity identity) && identity != null)
|
||||||
|
{
|
||||||
|
// owned by the connection?
|
||||||
|
if (identity.connectionToClient == connection)
|
||||||
|
{
|
||||||
|
// unreliable state sync messages may arrive out of order.
|
||||||
|
// only ever apply state that's newer than the last received state.
|
||||||
|
// note that we send one EntityStateMessage per Entity,
|
||||||
|
// so there will be multiple with the same == timestamp.
|
||||||
|
if (connection.remoteTimeStamp < identity.lastUnreliableStateTime)
|
||||||
|
{
|
||||||
|
// debug log to show that it's working.
|
||||||
|
// can be tested via LatencySimulation scramble easily.
|
||||||
|
Debug.Log($"Server caught out of order Unreliable state message for {identity.name}. This is fine.\nIdentity timestamp={identity.lastUnreliableStateTime:F3} batch remoteTimestamp={connection.remoteTimeStamp:F3}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// UDP messages may accidentally arrive twice.
|
||||||
|
// or even intentionally, if unreliableRedundancy is turned on.
|
||||||
|
else if (connection.remoteTimeStamp == identity.lastUnreliableStateTime)
|
||||||
|
{
|
||||||
|
// only log this if unreliableRedundancy is disabled.
|
||||||
|
// otherwise it's expected and will happen a lot.
|
||||||
|
if (!unreliableRedundancy) Debug.Log($"Server caught duplicate Unreliable state message for {identity.name}. This is fine.\nIdentity timestamp={identity.lastUnreliableStateTime:F3} batch remoteTimestamp={connection.remoteTimeStamp:F3}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure this delta is for the correct baseline.
|
||||||
|
// we don't want to apply an old delta on top of a new baseline.
|
||||||
|
if (message.baselineTick != identity.lastUnreliableBaselineReceived)
|
||||||
|
{
|
||||||
|
Debug.Log($"Server caught Unreliable state message for old baseline for {identity} with baselineTick={identity.lastUnreliableBaselineReceived} messageBaseline={message.baselineTick}. This is fine.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set the new last received time for unreliable
|
||||||
|
identity.lastUnreliableStateTime = connection.remoteTimeStamp;
|
||||||
|
|
||||||
|
using (NetworkReaderPooled reader = NetworkReaderPool.Get(message.payload))
|
||||||
|
{
|
||||||
|
// DeserializeServer checks permissions internally.
|
||||||
|
// failure to deserialize disconnects to prevent exploits.
|
||||||
|
//
|
||||||
// delta state updates (initial=false) arrive over unreliable.
|
// delta state updates (initial=false) arrive over unreliable.
|
||||||
bool initialState = channelId == Channels.Reliable;
|
if (!identity.DeserializeServer(reader, false))
|
||||||
if (!identity.DeserializeServer(reader, initialState))
|
|
||||||
{
|
{
|
||||||
if (exceptionsDisconnect)
|
if (exceptionsDisconnect)
|
||||||
{
|
{
|
||||||
@ -2099,7 +2146,7 @@ static void BroadcastToConnection(NetworkConnectionToClient connection, bool unr
|
|||||||
// reliable baseline also clears dirty bits, so unreliable must be sent first.
|
// reliable baseline also clears dirty bits, so unreliable must be sent first.
|
||||||
if (deltaSerialization != null)
|
if (deltaSerialization != null)
|
||||||
{
|
{
|
||||||
EntityStateMessageUnreliable message = new EntityStateMessageUnreliable
|
EntityStateMessageUnreliableDelta message = new EntityStateMessageUnreliableDelta
|
||||||
{
|
{
|
||||||
baselineTick = identity.lastUnreliableBaselineSent,
|
baselineTick = identity.lastUnreliableBaselineSent,
|
||||||
netId = identity.netId,
|
netId = identity.netId,
|
||||||
@ -2124,7 +2171,7 @@ static void BroadcastToConnection(NetworkConnectionToClient connection, bool unr
|
|||||||
// just something small to compare against.
|
// just something small to compare against.
|
||||||
identity.lastUnreliableBaselineSent = (byte)Time.frameCount;
|
identity.lastUnreliableBaselineSent = (byte)Time.frameCount;
|
||||||
|
|
||||||
EntityStateMessageUnreliable message = new EntityStateMessageUnreliable
|
EntityStateMessageUnreliableBaseline message = new EntityStateMessageUnreliableBaseline
|
||||||
{
|
{
|
||||||
baselineTick = identity.lastUnreliableBaselineSent,
|
baselineTick = identity.lastUnreliableBaselineSent,
|
||||||
netId = identity.netId,
|
netId = identity.netId,
|
||||||
|
Loading…
Reference in New Issue
Block a user