mirror of
https://github.com/MirrorNetworking/Mirror.git
synced 2024-11-17 18:40:33 +00:00
Compare commits
7 Commits
a044250723
...
30e1d4d53a
Author | SHA1 | Date | |
---|---|---|---|
|
30e1d4d53a | ||
|
451c297a43 | ||
|
1e04c9833b | ||
|
1187a59b18 | ||
|
499e4daea3 | ||
|
703a998790 | ||
|
167d49e365 |
@ -23,6 +23,7 @@
|
|||||||
namespace Mirror
|
namespace Mirror
|
||||||
{
|
{
|
||||||
public enum CoordinateSpace { Local, World }
|
public enum CoordinateSpace { Local, World }
|
||||||
|
public enum UpdateMethod { Update, LateUpdate, FixedUpdate }
|
||||||
|
|
||||||
public abstract class NetworkTransformBase : NetworkBehaviour
|
public abstract class NetworkTransformBase : NetworkBehaviour
|
||||||
{
|
{
|
||||||
@ -119,6 +120,11 @@ public uint sendIntervalMultiplier
|
|||||||
protected double timeStampAdjustment => NetworkServer.sendInterval * (sendIntervalMultiplier - 1);
|
protected double timeStampAdjustment => NetworkServer.sendInterval * (sendIntervalMultiplier - 1);
|
||||||
protected double offset => timelineOffset ? NetworkServer.sendInterval * sendIntervalMultiplier : 0;
|
protected double offset => timelineOffset ? NetworkServer.sendInterval * sendIntervalMultiplier : 0;
|
||||||
|
|
||||||
|
// Update Method ///////////////////////////////////////////////////////////
|
||||||
|
[Header("Update Method")]
|
||||||
|
[Tooltip("Update by default. Try a different method when having problems with Physics or Animations.")]
|
||||||
|
public UpdateMethod updateMethod = UpdateMethod.Update;
|
||||||
|
|
||||||
// debugging ///////////////////////////////////////////////////////////
|
// debugging ///////////////////////////////////////////////////////////
|
||||||
[Header("Debug")]
|
[Header("Debug")]
|
||||||
public bool showGizmos;
|
public bool showGizmos;
|
||||||
|
1501
Assets/Mirror/Components/NetworkTransform/NetworkTransformHybrid.cs
Normal file
1501
Assets/Mirror/Components/NetworkTransform/NetworkTransformHybrid.cs
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 8f63ea2e505fd484193fb31c5c55ca73
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -45,15 +45,15 @@ public class NetworkTransformReliable : NetworkTransformBase
|
|||||||
// update //////////////////////////////////////////////////////////////
|
// update //////////////////////////////////////////////////////////////
|
||||||
void Update()
|
void Update()
|
||||||
{
|
{
|
||||||
// if server then always sync to others.
|
if (updateMethod == UpdateMethod.Update)
|
||||||
if (isServer) UpdateServer();
|
UpdateCall();
|
||||||
// 'else if' because host mode shouldn't send anything to server.
|
|
||||||
// it is the server. don't overwrite anything there.
|
|
||||||
else if (isClient) UpdateClient();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LateUpdate()
|
void LateUpdate()
|
||||||
{
|
{
|
||||||
|
if (updateMethod == UpdateMethod.LateUpdate)
|
||||||
|
UpdateCall();
|
||||||
|
|
||||||
// set dirty to trigger OnSerialize. either always, or only if changed.
|
// set dirty to trigger OnSerialize. either always, or only if changed.
|
||||||
// It has to be checked in LateUpdate() for onlySyncOnChange to avoid
|
// It has to be checked in LateUpdate() for onlySyncOnChange to avoid
|
||||||
// the possibility of Update() running first before the object's movement
|
// the possibility of Update() running first before the object's movement
|
||||||
@ -68,6 +68,21 @@ void LateUpdate()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FixedUpdate()
|
||||||
|
{
|
||||||
|
if (updateMethod == UpdateMethod.FixedUpdate)
|
||||||
|
UpdateCall();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateCall()
|
||||||
|
{
|
||||||
|
// if server then always sync to others.
|
||||||
|
if (isServer) UpdateServer();
|
||||||
|
// 'else if' because host mode shouldn't send anything to server.
|
||||||
|
// it is the server. don't overwrite anything there.
|
||||||
|
else if (isClient) UpdateClient();
|
||||||
|
}
|
||||||
|
|
||||||
protected virtual void UpdateServer()
|
protected virtual void UpdateServer()
|
||||||
{
|
{
|
||||||
// apply buffered snapshots IF client authority
|
// apply buffered snapshots IF client authority
|
||||||
|
@ -29,11 +29,8 @@ public class NetworkTransformUnreliable : NetworkTransformBase
|
|||||||
// Update applies interpolation
|
// Update applies interpolation
|
||||||
void Update()
|
void Update()
|
||||||
{
|
{
|
||||||
if (isServer) UpdateServerInterpolation();
|
if (updateMethod == UpdateMethod.Update)
|
||||||
// for all other clients (and for local player if !authority),
|
UpdateCall();
|
||||||
// we need to apply snapshots from the buffer.
|
|
||||||
// 'else if' because host mode shouldn't interpolate client
|
|
||||||
else if (isClient && !IsClientWithAuthority) UpdateClientInterpolation();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// LateUpdate broadcasts.
|
// LateUpdate broadcasts.
|
||||||
@ -43,6 +40,9 @@ void Update()
|
|||||||
// this could cause visible jitter.
|
// this could cause visible jitter.
|
||||||
void LateUpdate()
|
void LateUpdate()
|
||||||
{
|
{
|
||||||
|
if (updateMethod == UpdateMethod.LateUpdate)
|
||||||
|
UpdateCall();
|
||||||
|
|
||||||
// if server then always sync to others.
|
// if server then always sync to others.
|
||||||
if (isServer) UpdateServerBroadcast();
|
if (isServer) UpdateServerBroadcast();
|
||||||
// client authority, and local player (= allowed to move myself)?
|
// client authority, and local player (= allowed to move myself)?
|
||||||
@ -51,6 +51,21 @@ void LateUpdate()
|
|||||||
else if (isClient && IsClientWithAuthority) UpdateClientBroadcast();
|
else if (isClient && IsClientWithAuthority) UpdateClientBroadcast();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FixedUpdate()
|
||||||
|
{
|
||||||
|
if (updateMethod == UpdateMethod.FixedUpdate)
|
||||||
|
UpdateCall();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateCall()
|
||||||
|
{
|
||||||
|
if (isServer) UpdateServerInterpolation();
|
||||||
|
// for all other clients (and for local player if !authority),
|
||||||
|
// we need to apply snapshots from the buffer.
|
||||||
|
// 'else if' because host mode shouldn't interpolate client
|
||||||
|
else if (isClient && !IsClientWithAuthority) UpdateClientInterpolation();
|
||||||
|
}
|
||||||
|
|
||||||
protected virtual void CheckLastSendTime()
|
protected virtual void CheckLastSendTime()
|
||||||
{
|
{
|
||||||
// We check interval every frame, and then send if interval is reached.
|
// We check interval every frame, and then send if interval is reached.
|
||||||
|
@ -48,28 +48,28 @@ public class TargetRpcAttribute : Attribute
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Prevents clients from running this method.
|
/// Only an active server will run this method.
|
||||||
/// <para>Prints a warning if a client tries to execute this method.</para>
|
/// <para>Prints a warning if a client or in-active server tries to execute this method.</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[AttributeUsage(AttributeTargets.Method)]
|
[AttributeUsage(AttributeTargets.Method)]
|
||||||
public class ServerAttribute : Attribute {}
|
public class ServerAttribute : Attribute {}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Prevents clients from running this method.
|
/// Only an active server will run this method.
|
||||||
/// <para>No warning is thrown.</para>
|
/// <para>No warning is thrown.</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[AttributeUsage(AttributeTargets.Method)]
|
[AttributeUsage(AttributeTargets.Method)]
|
||||||
public class ServerCallbackAttribute : Attribute {}
|
public class ServerCallbackAttribute : Attribute {}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Prevents the server from running this method.
|
/// Only an active client will run this method.
|
||||||
/// <para>Prints a warning if the server tries to execute this method.</para>
|
/// <para>Prints a warning if the server or in-active client tries to execute this method.</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[AttributeUsage(AttributeTargets.Method)]
|
[AttributeUsage(AttributeTargets.Method)]
|
||||||
public class ClientAttribute : Attribute {}
|
public class ClientAttribute : Attribute {}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Prevents the server from running this method.
|
/// Only an active client will run this method.
|
||||||
/// <para>No warning is printed.</para>
|
/// <para>No warning is printed.</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[AttributeUsage(AttributeTargets.Method)]
|
[AttributeUsage(AttributeTargets.Method)]
|
||||||
|
@ -863,7 +863,7 @@ internal void OnStopLocalPlayer()
|
|||||||
for (int i = 0; i < components.Length; ++i)
|
for (int i = 0; i < components.Length; ++i)
|
||||||
{
|
{
|
||||||
NetworkBehaviour component = components[i];
|
NetworkBehaviour component = components[i];
|
||||||
ulong nthBit = (1u << i);
|
ulong nthBit = 1ul << i;
|
||||||
|
|
||||||
bool dirty = component.IsDirty();
|
bool dirty = component.IsDirty();
|
||||||
|
|
||||||
@ -910,7 +910,7 @@ ulong ClientDirtyMask()
|
|||||||
|
|
||||||
// on client, only consider owned components with SyncDirection to server
|
// on client, only consider owned components with SyncDirection to server
|
||||||
NetworkBehaviour component = components[i];
|
NetworkBehaviour component = components[i];
|
||||||
ulong nthBit = (1u << i);
|
ulong nthBit = 1ul << i;
|
||||||
|
|
||||||
if (isOwned && component.syncDirection == SyncDirection.ClientToServer)
|
if (isOwned && component.syncDirection == SyncDirection.ClientToServer)
|
||||||
{
|
{
|
||||||
@ -928,7 +928,7 @@ ulong ClientDirtyMask()
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
internal static bool IsDirty(ulong mask, int index)
|
internal static bool IsDirty(ulong mask, int index)
|
||||||
{
|
{
|
||||||
ulong nthBit = (ulong)(1 << index);
|
ulong nthBit = 1ul << index;
|
||||||
return (mask & nthBit) != 0;
|
return (mask & nthBit) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
// base class for networking tests to make things easier.
|
// base class for networking tests to make things easier.
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
@ -81,6 +82,18 @@ protected void CreateNetworked(out GameObject go, out NetworkIdentity identity)
|
|||||||
instantiated.Add(go);
|
instantiated.Add(go);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void CreateNetworked(out GameObject go, out NetworkIdentity identity, Action<NetworkIdentity> preAwake)
|
||||||
|
{
|
||||||
|
go = new GameObject();
|
||||||
|
identity = go.AddComponent<NetworkIdentity>();
|
||||||
|
preAwake(identity);
|
||||||
|
// Awake is only called in play mode.
|
||||||
|
// call manually for initialization.
|
||||||
|
identity.Awake();
|
||||||
|
// track
|
||||||
|
instantiated.Add(go);
|
||||||
|
}
|
||||||
|
|
||||||
// create GameObject + NetworkIdentity + NetworkBehaviour<T>
|
// create GameObject + NetworkIdentity + NetworkBehaviour<T>
|
||||||
// add to tracker list if needed (useful for cleanups afterwards)
|
// add to tracker list if needed (useful for cleanups afterwards)
|
||||||
protected void CreateNetworked<T>(out GameObject go, out NetworkIdentity identity, out T component)
|
protected void CreateNetworked<T>(out GameObject go, out NetworkIdentity identity, out T component)
|
||||||
@ -269,6 +282,44 @@ protected void CreateNetworkedAndSpawn(
|
|||||||
Assert.That(NetworkClient.spawned.ContainsKey(serverIdentity.netId));
|
Assert.That(NetworkClient.spawned.ContainsKey(serverIdentity.netId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// create GameObject + NetworkIdentity + NetworkBehaviour & SPAWN
|
||||||
|
// => preAwake callbacks can be used to add network behaviours to the NI
|
||||||
|
// => ownerConnection can be NetworkServer.localConnection if needed.
|
||||||
|
// => returns objects from client and from server.
|
||||||
|
// will be same in host mode.
|
||||||
|
protected void CreateNetworkedAndSpawn(
|
||||||
|
out GameObject serverGO, out NetworkIdentity serverIdentity, Action<NetworkIdentity> serverPreAwake,
|
||||||
|
out GameObject clientGO, out NetworkIdentity clientIdentity, Action<NetworkIdentity> clientPreAwake,
|
||||||
|
NetworkConnectionToClient ownerConnection = null)
|
||||||
|
{
|
||||||
|
// server & client need to be active before spawning
|
||||||
|
Debug.Assert(NetworkClient.active, "NetworkClient needs to be active before spawning.");
|
||||||
|
Debug.Assert(NetworkServer.active, "NetworkServer needs to be active before spawning.");
|
||||||
|
|
||||||
|
// create one on server, one on client
|
||||||
|
// (spawning has to find it on client, it doesn't create it)
|
||||||
|
CreateNetworked(out serverGO, out serverIdentity, serverPreAwake);
|
||||||
|
CreateNetworked(out clientGO, out clientIdentity, clientPreAwake);
|
||||||
|
|
||||||
|
// give both a scene id and register it on client for spawnables
|
||||||
|
clientIdentity.sceneId = serverIdentity.sceneId = (ulong)serverGO.GetHashCode();
|
||||||
|
NetworkClient.spawnableObjects[clientIdentity.sceneId] = clientIdentity;
|
||||||
|
|
||||||
|
// spawn
|
||||||
|
NetworkServer.Spawn(serverGO, ownerConnection);
|
||||||
|
ProcessMessages();
|
||||||
|
|
||||||
|
// double check isServer/isClient. avoids debugging headaches.
|
||||||
|
Assert.That(serverIdentity.isServer, Is.True);
|
||||||
|
Assert.That(clientIdentity.isClient, Is.True);
|
||||||
|
|
||||||
|
// double check that we have authority if we passed an owner connection
|
||||||
|
if (ownerConnection != null)
|
||||||
|
Debug.Assert(clientIdentity.isOwned == true, $"Behaviour Had Wrong Authority when spawned, This means that the test is broken and will give the wrong results");
|
||||||
|
|
||||||
|
// make sure the client really spawned it.
|
||||||
|
Assert.That(NetworkClient.spawned.ContainsKey(serverIdentity.netId));
|
||||||
|
}
|
||||||
// create GameObject + NetworkIdentity + NetworkBehaviour & SPAWN
|
// create GameObject + NetworkIdentity + NetworkBehaviour & SPAWN
|
||||||
// => ownerConnection can be NetworkServer.localConnection if needed.
|
// => ownerConnection can be NetworkServer.localConnection if needed.
|
||||||
protected void CreateNetworkedAndSpawn<T>(out GameObject go, out NetworkIdentity identity, out T component, NetworkConnectionToClient ownerConnection = null)
|
protected void CreateNetworkedAndSpawn<T>(out GameObject go, out NetworkIdentity identity, out T component, NetworkConnectionToClient ownerConnection = null)
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
// OnDe/SerializeSafely tests.
|
// OnDe/SerializeSafely tests.
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using Mirror.Tests.EditorBehaviours.NetworkIdentities;
|
using Mirror.Tests.EditorBehaviours.NetworkIdentities;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
@ -42,7 +43,7 @@ public void SerializeAndDeserializeAll()
|
|||||||
);
|
);
|
||||||
|
|
||||||
// set sync modes
|
// set sync modes
|
||||||
serverOwnerComp.syncMode = clientOwnerComp.syncMode = SyncMode.Owner;
|
serverOwnerComp.syncMode = clientOwnerComp.syncMode = SyncMode.Owner;
|
||||||
serverObserversComp.syncMode = clientObserversComp.syncMode = SyncMode.Observers;
|
serverObserversComp.syncMode = clientObserversComp.syncMode = SyncMode.Observers;
|
||||||
|
|
||||||
// set unique values on server components
|
// set unique values on server components
|
||||||
@ -65,10 +66,127 @@ public void SerializeAndDeserializeAll()
|
|||||||
// deserialize client object with OBSERVERS payload
|
// deserialize client object with OBSERVERS payload
|
||||||
reader = new NetworkReader(observersWriter.ToArray());
|
reader = new NetworkReader(observersWriter.ToArray());
|
||||||
clientIdentity.DeserializeClient(reader, true);
|
clientIdentity.DeserializeClient(reader, true);
|
||||||
Assert.That(clientOwnerComp.value, Is.EqualTo(null)); // owner mode shouldn't be in data
|
Assert.That(clientOwnerComp.value, Is.EqualTo(null)); // owner mode shouldn't be in data
|
||||||
Assert.That(clientObserversComp.value, Is.EqualTo(42)); // observers mode should be in data
|
Assert.That(clientObserversComp.value, Is.EqualTo(42)); // observers mode should be in data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// test serialize -> deserialize of any supported number of components
|
||||||
|
[Test]
|
||||||
|
public void SerializeAndDeserializeN([NUnit.Framework.Range(1, 64)] int numberOfNBs)
|
||||||
|
{
|
||||||
|
List<SerializeTest1NetworkBehaviour> serverNBs = new List<SerializeTest1NetworkBehaviour>();
|
||||||
|
List<SerializeTest1NetworkBehaviour> clientNBs = new List<SerializeTest1NetworkBehaviour>();
|
||||||
|
// need two of both versions so we can serialize -> deserialize
|
||||||
|
CreateNetworkedAndSpawn(
|
||||||
|
out _, out NetworkIdentity serverIdentity, ni =>
|
||||||
|
{
|
||||||
|
for (int i = 0; i < numberOfNBs; i++)
|
||||||
|
{
|
||||||
|
SerializeTest1NetworkBehaviour nb = ni.gameObject.AddComponent<SerializeTest1NetworkBehaviour>();
|
||||||
|
nb.syncInterval = 0;
|
||||||
|
nb.syncMode = SyncMode.Observers;
|
||||||
|
serverNBs.Add(nb);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
out _, out NetworkIdentity clientIdentity, ni =>
|
||||||
|
{
|
||||||
|
for (int i = 0; i < numberOfNBs; i++)
|
||||||
|
{
|
||||||
|
SerializeTest1NetworkBehaviour nb = ni.gameObject.AddComponent<SerializeTest1NetworkBehaviour>();
|
||||||
|
nb.syncInterval = 0;
|
||||||
|
nb.syncMode = SyncMode.Observers;
|
||||||
|
clientNBs.Add(nb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// INITIAL SYNC
|
||||||
|
// set unique values on server components
|
||||||
|
for (int i = 0; i < serverNBs.Count; i++)
|
||||||
|
{
|
||||||
|
serverNBs[i].value = (i + 1) * 3;
|
||||||
|
serverNBs[i].SetDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
// serialize server object
|
||||||
|
serverIdentity.SerializeServer(true, ownerWriter, observersWriter);
|
||||||
|
|
||||||
|
// deserialize client object with OBSERVERS payload
|
||||||
|
NetworkReader reader = new NetworkReader(observersWriter.ToArray());
|
||||||
|
clientIdentity.DeserializeClient(reader, true);
|
||||||
|
for (int i = 0; i < clientNBs.Count; i++)
|
||||||
|
{
|
||||||
|
int expected = (i + 1) * 3;
|
||||||
|
Assert.That(clientNBs[i].value, Is.EqualTo(expected), $"Expected the clientNBs[{i}] to have a value of {expected}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear dirty bits for incremental sync
|
||||||
|
foreach (SerializeTest1NetworkBehaviour serverNB in serverNBs)
|
||||||
|
serverNB.ClearAllDirtyBits();
|
||||||
|
|
||||||
|
// INCREMENTAL SYNC ALL
|
||||||
|
// set unique values on server components
|
||||||
|
for (int i = 0; i < serverNBs.Count; i++)
|
||||||
|
{
|
||||||
|
serverNBs[i].value = (i + 1) * 11;
|
||||||
|
serverNBs[i].SetDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
ownerWriter.Reset();
|
||||||
|
observersWriter.Reset();
|
||||||
|
// serialize server object
|
||||||
|
serverIdentity.SerializeServer(false, ownerWriter, observersWriter);
|
||||||
|
|
||||||
|
// deserialize client object with OBSERVERS payload
|
||||||
|
reader = new NetworkReader(observersWriter.ToArray());
|
||||||
|
clientIdentity.DeserializeClient(reader, false);
|
||||||
|
for (int i = 0; i < clientNBs.Count; i++)
|
||||||
|
{
|
||||||
|
int expected = (i + 1) * 11;
|
||||||
|
Assert.That(clientNBs[i].value, Is.EqualTo(expected), $"Expected the clientNBs[{i}] to have a value of {expected}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear dirty bits for incremental sync
|
||||||
|
foreach (SerializeTest1NetworkBehaviour serverNB in serverNBs)
|
||||||
|
serverNB.ClearAllDirtyBits();
|
||||||
|
|
||||||
|
// INCREMENTAL SYNC INDIVIDUAL
|
||||||
|
for (int i = 0; i < numberOfNBs; i++)
|
||||||
|
{
|
||||||
|
// reset all client nbs
|
||||||
|
foreach (SerializeTest1NetworkBehaviour clientNB in clientNBs)
|
||||||
|
clientNB.value = 0;
|
||||||
|
|
||||||
|
int expected = (i + 1) * 7;
|
||||||
|
|
||||||
|
// set unique value on server components
|
||||||
|
serverNBs[i].value = expected;
|
||||||
|
serverNBs[i].SetDirty();
|
||||||
|
|
||||||
|
ownerWriter.Reset();
|
||||||
|
observersWriter.Reset();
|
||||||
|
// serialize server object
|
||||||
|
serverIdentity.SerializeServer(false, ownerWriter, observersWriter);
|
||||||
|
|
||||||
|
// deserialize client object with OBSERVERS payload
|
||||||
|
reader = new NetworkReader(observersWriter.ToArray());
|
||||||
|
clientIdentity.DeserializeClient(reader, false);
|
||||||
|
for (int index = 0; index < clientNBs.Count; index++)
|
||||||
|
{
|
||||||
|
SerializeTest1NetworkBehaviour clientNB = clientNBs[index];
|
||||||
|
if (index == i)
|
||||||
|
{
|
||||||
|
Assert.That(clientNB.value, Is.EqualTo(expected), $"Expected the clientNBs[{index}] to have a value of {expected}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Assert.That(clientNB.value, Is.EqualTo(0), $"Expected the clientNBs[{index}] to have a value of 0 since we're not syncing that index (on sync of #{i})");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// serialization should work even if a component throws an exception.
|
// serialization should work even if a component throws an exception.
|
||||||
// so if first component throws, second should still be serialized fine.
|
// so if first component throws, second should still be serialized fine.
|
||||||
[Test]
|
[Test]
|
||||||
@ -150,20 +268,20 @@ public void TooManyComponents()
|
|||||||
public void ErrorCorrection()
|
public void ErrorCorrection()
|
||||||
{
|
{
|
||||||
int original = 0x12345678;
|
int original = 0x12345678;
|
||||||
byte safety = 0x78; // last byte
|
byte safety = 0x78; // last byte
|
||||||
|
|
||||||
// correct size shouldn't be corrected
|
// correct size shouldn't be corrected
|
||||||
Assert.That(NetworkBehaviour.ErrorCorrection(original + 0, safety), Is.EqualTo(original));
|
Assert.That(NetworkBehaviour.ErrorCorrection(original + 0, safety), Is.EqualTo(original));
|
||||||
|
|
||||||
// read a little too much
|
// read a little too much
|
||||||
Assert.That(NetworkBehaviour.ErrorCorrection(original + 1, safety), Is.EqualTo(original));
|
Assert.That(NetworkBehaviour.ErrorCorrection(original + 1, safety), Is.EqualTo(original));
|
||||||
Assert.That(NetworkBehaviour.ErrorCorrection(original + 2, safety), Is.EqualTo(original));
|
Assert.That(NetworkBehaviour.ErrorCorrection(original + 2, safety), Is.EqualTo(original));
|
||||||
Assert.That(NetworkBehaviour.ErrorCorrection(original + 42, safety), Is.EqualTo(original));
|
Assert.That(NetworkBehaviour.ErrorCorrection(original + 42, safety), Is.EqualTo(original));
|
||||||
|
|
||||||
// read a little too less
|
// read a little too less
|
||||||
Assert.That(NetworkBehaviour.ErrorCorrection(original - 1, safety), Is.EqualTo(original));
|
Assert.That(NetworkBehaviour.ErrorCorrection(original - 1, safety), Is.EqualTo(original));
|
||||||
Assert.That(NetworkBehaviour.ErrorCorrection(original - 2, safety), Is.EqualTo(original));
|
Assert.That(NetworkBehaviour.ErrorCorrection(original - 2, safety), Is.EqualTo(original));
|
||||||
Assert.That(NetworkBehaviour.ErrorCorrection(original - 42, safety), Is.EqualTo(original));
|
Assert.That(NetworkBehaviour.ErrorCorrection(original - 42, safety), Is.EqualTo(original));
|
||||||
|
|
||||||
// reading way too much / less is expected to fail.
|
// reading way too much / less is expected to fail.
|
||||||
// we can only correct the last byte, not more.
|
// we can only correct the last byte, not more.
|
||||||
|
Loading…
Reference in New Issue
Block a user