mirror of
https://github.com/MirrorNetworking/Mirror.git
synced 2024-11-18 02:50:32 +00:00
NetworkIdentity: SerializeServer split into Spawn and Broadcast to prepare for Unreliable sync method
This commit is contained in:
parent
43365aee5a
commit
32939d129e
@ -924,9 +924,9 @@ internal static bool IsDirty(ulong mask, int index)
|
||||
return (mask & nthBit) != 0;
|
||||
}
|
||||
|
||||
// serialize components into writer on the server.
|
||||
// serialize server components, with full state for spawn message.
|
||||
// check ownerWritten/observersWritten to know if anything was written
|
||||
internal void SerializeServer(bool initialState, NetworkWriter ownerWriter, NetworkWriter observersWriter)
|
||||
internal void SerializeServer_Spawn(NetworkWriter ownerWriter, NetworkWriter observersWriter)
|
||||
{
|
||||
// ensure NetworkBehaviours are valid before usage
|
||||
ValidateComponents();
|
||||
@ -939,7 +939,7 @@ internal void SerializeServer(bool initialState, NetworkWriter ownerWriter, Netw
|
||||
// instead of writing a 1 byte index per component,
|
||||
// we limit components to 64 bits and write one ulong instead.
|
||||
// the ulong is also varint compressed for minimum bandwidth.
|
||||
(ulong ownerMask, ulong observerMask) = ServerDirtyMasks(initialState);
|
||||
(ulong ownerMask, ulong observerMask) = ServerDirtyMasks(true);
|
||||
|
||||
// if nothing dirty, then don't even write the mask.
|
||||
// otherwise, every unchanged object would send a 1 byte dirty mask!
|
||||
@ -973,7 +973,7 @@ internal void SerializeServer(bool initialState, NetworkWriter ownerWriter, Netw
|
||||
// serialize into helper writer
|
||||
using (NetworkWriterPooled temp = NetworkWriterPool.Get())
|
||||
{
|
||||
comp.Serialize(temp, initialState);
|
||||
comp.Serialize(temp, true);
|
||||
ArraySegment<byte> segment = temp.ToArraySegment();
|
||||
|
||||
// copy to owner / observers as needed
|
||||
@ -981,18 +981,76 @@ internal void SerializeServer(bool initialState, NetworkWriter ownerWriter, Netw
|
||||
if (observersDirty) observersWriter.WriteBytes(segment.Array, segment.Offset, segment.Count);
|
||||
}
|
||||
|
||||
// clear dirty bits for the components that we serialized.
|
||||
// do not clear for _all_ components, only the ones that
|
||||
// were dirty and had their syncInterval elapsed.
|
||||
// dirty bits indicate 'changed since last delta sync'.
|
||||
// don't clear then on full sync here, since full sync
|
||||
// is called whenever a new player spawns and needs the
|
||||
// full state!
|
||||
//comp.ClearAllDirtyBits();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// serialize server components, with delta state for broadcast messages.
|
||||
// check ownerWritten/observersWritten to know if anything was written
|
||||
internal void SerializeServer_Broadcast(NetworkWriter ownerWriter, NetworkWriter observersWriter)
|
||||
{
|
||||
// ensure NetworkBehaviours are valid before usage
|
||||
ValidateComponents();
|
||||
NetworkBehaviour[] components = NetworkBehaviours;
|
||||
|
||||
// check which components are dirty for owner / observers.
|
||||
// this is quite complicated with SyncMode + SyncDirection.
|
||||
// see the function for explanation.
|
||||
//
|
||||
// we don't want to clear bits before the syncInterval
|
||||
// was elapsed, as then they wouldn't be synced.
|
||||
// instead of writing a 1 byte index per component,
|
||||
// we limit components to 64 bits and write one ulong instead.
|
||||
// the ulong is also varint compressed for minimum bandwidth.
|
||||
(ulong ownerMask, ulong observerMask) = ServerDirtyMasks(false);
|
||||
|
||||
// if nothing dirty, then don't even write the mask.
|
||||
// otherwise, every unchanged object would send a 1 byte dirty mask!
|
||||
if (ownerMask != 0) Compression.CompressVarUInt(ownerWriter, ownerMask);
|
||||
if (observerMask != 0) Compression.CompressVarUInt(observersWriter, observerMask);
|
||||
|
||||
// serialize all components
|
||||
// perf: only iterate if either dirty mask has dirty bits.
|
||||
if ((ownerMask | observerMask) != 0)
|
||||
{
|
||||
for (int i = 0; i < components.Length; ++i)
|
||||
{
|
||||
NetworkBehaviour comp = components[i];
|
||||
|
||||
// is the component dirty for anyone (owner or observers)?
|
||||
// may be serialized to owner, observer, both, or neither.
|
||||
//
|
||||
// only clear for delta, not for full (spawn messages).
|
||||
// otherwise if a player joins, we serialize monster,
|
||||
// and shouldn't clear dirty bits not yet synced to
|
||||
// other players.
|
||||
if (!initialState) comp.ClearAllDirtyBits();
|
||||
// OnSerialize should only be called once.
|
||||
// this is faster, and it cleaner because it may set
|
||||
// internal state, counters, logs, etc.
|
||||
//
|
||||
// previously we always serialized to owner and then copied
|
||||
// the serialization to observers. however, since
|
||||
// SyncDirection it's not guaranteed to be in owner anymore.
|
||||
// so we need to serialize to temporary writer first.
|
||||
// and then copy as needed.
|
||||
bool ownerDirty = IsDirty(ownerMask, i);
|
||||
bool observersDirty = IsDirty(observerMask, i);
|
||||
if (ownerDirty || observersDirty)
|
||||
{
|
||||
// serialize into helper writer
|
||||
using (NetworkWriterPooled temp = NetworkWriterPool.Get())
|
||||
{
|
||||
comp.Serialize(temp, false);
|
||||
ArraySegment<byte> segment = temp.ToArraySegment();
|
||||
|
||||
// copy to owner / observers as needed
|
||||
if (ownerDirty) ownerWriter.WriteBytes(segment.Array, segment.Offset, segment.Count);
|
||||
if (observersDirty) observersWriter.WriteBytes(segment.Array, segment.Offset, segment.Count);
|
||||
}
|
||||
|
||||
// dirty bits indicate 'changed since last delta sync'.
|
||||
// clear them after a delta sync here.
|
||||
comp.ClearAllDirtyBits();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1143,8 +1201,7 @@ internal NetworkIdentitySerialization GetServerSerializationAtTick(int tick)
|
||||
lastSerialization.ResetWriters();
|
||||
|
||||
// serialize
|
||||
SerializeServer(false,
|
||||
lastSerialization.ownerWriter,
|
||||
SerializeServer_Broadcast(lastSerialization.ownerWriter,
|
||||
lastSerialization.observersWriter);
|
||||
|
||||
// set tick
|
||||
|
@ -1405,7 +1405,7 @@ static ArraySegment<byte> CreateSpawnMessagePayload(bool isOwner, NetworkIdentit
|
||||
|
||||
// serialize all components with initialState = true
|
||||
// (can be null if has none)
|
||||
identity.SerializeServer(true, ownerWriter, observersWriter);
|
||||
identity.SerializeServer_Spawn(ownerWriter, observersWriter);
|
||||
|
||||
// convert to ArraySegment to avoid reader allocations
|
||||
// if nothing was written, .ToArraySegment returns an empty segment.
|
||||
|
@ -50,7 +50,7 @@ public void SerializeAndDeserializeAll()
|
||||
serverObserversComp.value = 42;
|
||||
|
||||
// serialize server object
|
||||
serverIdentity.SerializeServer(true, ownerWriter, observersWriter);
|
||||
serverIdentity.SerializeServer_Spawn(ownerWriter, observersWriter);
|
||||
|
||||
// deserialize client object with OWNER payload
|
||||
NetworkReader reader = new NetworkReader(ownerWriter.ToArray());
|
||||
@ -96,7 +96,7 @@ public void SerializationException()
|
||||
// serialize server object
|
||||
// should work even if compExc throws an exception.
|
||||
// error log because of the exception is expected.
|
||||
serverIdentity.SerializeServer(true, ownerWriter, observersWriter);
|
||||
serverIdentity.SerializeServer_Spawn(ownerWriter, observersWriter);
|
||||
|
||||
// deserialize client object with OWNER payload
|
||||
// should work even if compExc throws an exception
|
||||
@ -187,7 +187,7 @@ public void SerializationMismatch()
|
||||
serverComp.value = "42";
|
||||
|
||||
// serialize server object
|
||||
serverIdentity.SerializeServer(true, ownerWriter, observersWriter);
|
||||
serverIdentity.SerializeServer_Spawn(ownerWriter, observersWriter);
|
||||
|
||||
// deserialize on client
|
||||
// ignore warning log because of serialization mismatch
|
||||
@ -219,7 +219,7 @@ public void SerializeServer_NotInitial_NotDirty_WritesNothing()
|
||||
// serialize server object.
|
||||
// 'initial' would write everything.
|
||||
// instead, try 'not initial' with 0 dirty bits
|
||||
serverIdentity.SerializeServer(false, ownerWriter, observersWriter);
|
||||
serverIdentity.SerializeServer_Broadcast(ownerWriter, observersWriter);
|
||||
Assert.That(ownerWriter.Position, Is.EqualTo(0));
|
||||
Assert.That(observersWriter.Position, Is.EqualTo(0));
|
||||
}
|
||||
@ -292,7 +292,7 @@ public void SerializeServer_OwnerMode_ClientToServer()
|
||||
comp.SetValue(11); // modify with helper function to avoid #3525
|
||||
|
||||
// initial: should still write for owner
|
||||
identity.SerializeServer(true, ownerWriter, observersWriter);
|
||||
identity.SerializeServer_Spawn(ownerWriter, observersWriter);
|
||||
Debug.Log("initial ownerWriter: " + ownerWriter);
|
||||
Debug.Log("initial observerWriter: " + observersWriter);
|
||||
Assert.That(ownerWriter.Position, Is.GreaterThan(0));
|
||||
@ -302,7 +302,7 @@ public void SerializeServer_OwnerMode_ClientToServer()
|
||||
comp.SetValue(22); // modify with helper function to avoid #3525
|
||||
ownerWriter.Position = 0;
|
||||
observersWriter.Position = 0;
|
||||
identity.SerializeServer(false, ownerWriter, observersWriter);
|
||||
identity.SerializeServer_Broadcast(ownerWriter, observersWriter);
|
||||
Debug.Log("delta ownerWriter: " + ownerWriter);
|
||||
Debug.Log("delta observersWriter: " + observersWriter);
|
||||
Assert.That(ownerWriter.Position, Is.EqualTo(0));
|
||||
@ -330,7 +330,7 @@ public void SerializeServer_ObserversMode_ClientToServer()
|
||||
comp.SetValue(11); // modify with helper function to avoid #3525
|
||||
|
||||
// initial: should write something for owner and observers
|
||||
identity.SerializeServer(true, ownerWriter, observersWriter);
|
||||
identity.SerializeServer_Spawn(ownerWriter, observersWriter);
|
||||
Debug.Log("initial ownerWriter: " + ownerWriter);
|
||||
Debug.Log("initial observerWriter: " + observersWriter);
|
||||
Assert.That(ownerWriter.Position, Is.GreaterThan(0));
|
||||
@ -340,7 +340,7 @@ public void SerializeServer_ObserversMode_ClientToServer()
|
||||
comp.SetValue(22); // modify with helper function to avoid #3525
|
||||
ownerWriter.Position = 0;
|
||||
observersWriter.Position = 0;
|
||||
identity.SerializeServer(false, ownerWriter, observersWriter);
|
||||
identity.SerializeServer_Broadcast(ownerWriter, observersWriter);
|
||||
Debug.Log("delta ownerWriter: " + ownerWriter);
|
||||
Debug.Log("delta observersWriter: " + observersWriter);
|
||||
Assert.That(ownerWriter.Position, Is.EqualTo(0));
|
||||
|
@ -404,7 +404,7 @@ public void TestSyncingAbstractNetworkBehaviour()
|
||||
NetworkWriter ownerWriter = new NetworkWriter();
|
||||
// not really used in this Test
|
||||
NetworkWriter observersWriter = new NetworkWriter();
|
||||
serverIdentity.SerializeServer(true, ownerWriter, observersWriter);
|
||||
serverIdentity.SerializeServer_Spawn(ownerWriter, observersWriter);
|
||||
|
||||
// set up a "client" object
|
||||
CreateNetworked(out _, out NetworkIdentity clientIdentity, out SyncVarAbstractNetworkBehaviour clientBehaviour);
|
||||
|
Loading…
Reference in New Issue
Block a user