mirror of
https://github.com/MirrorNetworking/Mirror.git
synced 2024-11-18 02:50:32 +00:00
EntityStateMessageUnreliable with custom handling
This commit is contained in:
parent
cdb3f9fc55
commit
7c724aaa56
@ -94,6 +94,7 @@ public struct ObjectHideMessage : NetworkMessage
|
||||
public uint netId;
|
||||
}
|
||||
|
||||
// state update for Traditional reliable sync
|
||||
public struct EntityStateMessage : NetworkMessage
|
||||
{
|
||||
public uint netId;
|
||||
@ -102,6 +103,15 @@ public struct EntityStateMessage : NetworkMessage
|
||||
public ArraySegment<byte> payload;
|
||||
}
|
||||
|
||||
// state update for FastPaced unreliable sync
|
||||
public struct EntityStateMessageUnreliable : NetworkMessage
|
||||
{
|
||||
public uint netId;
|
||||
// the serialized component data
|
||||
// -> ArraySegment to avoid unnecessary allocations
|
||||
public ArraySegment<byte> payload;
|
||||
}
|
||||
|
||||
// whoever wants to measure rtt, sends this to the other end.
|
||||
public struct NetworkPingMessage : NetworkMessage
|
||||
{
|
||||
|
@ -505,6 +505,7 @@ internal static void RegisterMessageHandlers(bool hostMode)
|
||||
RegisterHandler<ObjectSpawnFinishedMessage>(_ => { });
|
||||
// host mode doesn't need state updates
|
||||
RegisterHandler<EntityStateMessage>(_ => { });
|
||||
RegisterHandler<EntityStateMessageUnreliable>(_ => { });
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -516,6 +517,7 @@ internal static void RegisterMessageHandlers(bool hostMode)
|
||||
RegisterHandler<ObjectSpawnStartedMessage>(OnObjectSpawnStarted);
|
||||
RegisterHandler<ObjectSpawnFinishedMessage>(OnObjectSpawnFinished);
|
||||
RegisterHandler<EntityStateMessage>(OnEntityStateMessage);
|
||||
RegisterHandler<EntityStateMessageUnreliable>(OnEntityStateMessageUnreliable);
|
||||
}
|
||||
|
||||
// These handlers are the same for host and remote clients
|
||||
@ -1393,6 +1395,18 @@ 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.");
|
||||
}
|
||||
|
||||
static void OnEntityStateMessageUnreliable(EntityStateMessageUnreliable message)
|
||||
{
|
||||
// Debug.Log($"NetworkClient.OnUpdateVarsMessage {msg.netId}");
|
||||
if (spawned.TryGetValue(message.netId, out NetworkIdentity identity) && identity != null)
|
||||
{
|
||||
// iniital is always 'true' because unreliable state sync alwasy serializes full
|
||||
using (NetworkReaderPooled reader = NetworkReaderPool.Get(message.payload))
|
||||
identity.DeserializeClient(reader, true);
|
||||
}
|
||||
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 OnRPCMessage(RpcMessage message)
|
||||
{
|
||||
// Debug.Log($"NetworkClient.OnRPCMessage hash:{message.functionHash} netId:{message.netId}");
|
||||
@ -1567,7 +1581,7 @@ static void Broadcast()
|
||||
if (writer.Position > 0)
|
||||
{
|
||||
// send state update message
|
||||
EntityStateMessage message = new EntityStateMessage
|
||||
EntityStateMessageUnreliable message = new EntityStateMessageUnreliable
|
||||
{
|
||||
netId = identity.netId,
|
||||
payload = writer.ToArraySegment()
|
||||
|
@ -1090,8 +1090,9 @@ internal void SerializeClient(SyncMethod method, NetworkWriter writer)
|
||||
}
|
||||
|
||||
// deserialize components from the client on the server.
|
||||
// there's no 'initialState'. server always knows the initial state.
|
||||
internal bool DeserializeServer(NetworkReader reader)
|
||||
// for reliable state sync, server always knows the initial state.
|
||||
// for unreliable, we always sync full state so we still need the parameter.
|
||||
internal bool DeserializeServer(NetworkReader reader, bool initialState)
|
||||
{
|
||||
// ensure NetworkBehaviours are valid before usage
|
||||
ValidateComponents();
|
||||
@ -1115,7 +1116,7 @@ internal bool DeserializeServer(NetworkReader reader)
|
||||
// deserialize this component
|
||||
// server always knows the initial state (initial=false)
|
||||
// disconnect if failed, to prevent exploits etc.
|
||||
if (!comp.Deserialize(reader, false)) return false;
|
||||
if (!comp.Deserialize(reader, initialState)) return false;
|
||||
|
||||
// server received state from the owner client.
|
||||
// set dirty so it's broadcast to other clients too.
|
||||
|
@ -296,6 +296,7 @@ internal static void RegisterMessageHandlers()
|
||||
RegisterHandler<NetworkPingMessage>(NetworkTime.OnServerPing, false);
|
||||
RegisterHandler<NetworkPongMessage>(NetworkTime.OnServerPong, false);
|
||||
RegisterHandler<EntityStateMessage>(OnEntityStateMessage, true);
|
||||
RegisterHandler<EntityStateMessageUnreliable>(OnEntityStateMessageUnreliable, true);
|
||||
RegisterHandler<TimeSnapshotMessage>(OnTimeSnapshotMessage, true);
|
||||
}
|
||||
|
||||
@ -384,7 +385,8 @@ static void OnEntityStateMessage(NetworkConnectionToClient connection, EntitySta
|
||||
{
|
||||
// DeserializeServer checks permissions internally.
|
||||
// failure to deserialize disconnects to prevent exploits.
|
||||
if (!identity.DeserializeServer(reader))
|
||||
// for reliable sync, server always knows initial state so updates are initialState=false.
|
||||
if (!identity.DeserializeServer(reader, false))
|
||||
{
|
||||
if (exceptionsDisconnect)
|
||||
{
|
||||
@ -407,6 +409,46 @@ static void OnEntityStateMessage(NetworkConnectionToClient connection, EntitySta
|
||||
// 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 OnEntityStateMessageUnreliable(NetworkConnectionToClient connection, EntityStateMessageUnreliable message)
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
using (NetworkReaderPooled reader = NetworkReaderPool.Get(message.payload))
|
||||
{
|
||||
// DeserializeServer checks permissions internally.
|
||||
// failure to deserialize disconnects to prevent exploits.
|
||||
// for unreliable sync, we always send full state (initialState=true).
|
||||
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. don't spam server logs.
|
||||
// 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.");
|
||||
}
|
||||
|
||||
// client sends TimeSnapshotMessage every sendInterval.
|
||||
// batching already includes the remoteTimestamp.
|
||||
// we simply insert it on-message here.
|
||||
@ -1916,7 +1958,7 @@ static void BroadcastToConnection(NetworkConnectionToClient connection)
|
||||
serialization = SerializeForConnection(identity, connection, SyncMethod.FastPaced);
|
||||
if (serialization != null)
|
||||
{
|
||||
EntityStateMessage message = new EntityStateMessage
|
||||
EntityStateMessageUnreliable message = new EntityStateMessageUnreliable
|
||||
{
|
||||
netId = identity.netId,
|
||||
payload = serialization.ToArraySegment()
|
||||
|
@ -67,7 +67,7 @@ MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: d993bac37a92145448c1ea027b3e9ddc, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
syncMethod: 0
|
||||
syncMethod: 1
|
||||
syncDirection: 1
|
||||
syncMode: 0
|
||||
syncInterval: 0
|
||||
@ -99,7 +99,7 @@ MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: d993bac37a92145448c1ea027b3e9ddc, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
syncMethod: 0
|
||||
syncMethod: 1
|
||||
syncDirection: 1
|
||||
syncMode: 0
|
||||
syncInterval: 0
|
||||
@ -131,7 +131,7 @@ MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: 7deadf756194d461e9140e42d651693b, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
syncMethod: 0
|
||||
syncMethod: 1
|
||||
syncDirection: 0
|
||||
syncMode: 0
|
||||
syncInterval: 0.1
|
||||
|
Loading…
Reference in New Issue
Block a user