Skip to content

Commit ac0dd90

Browse files
committed
Merge branch 'master' of https://github.com/TwoTenPvP/MLAPI
2 parents 99dedf3 + 9d0e887 commit ac0dd90

File tree

6 files changed

+362
-56
lines changed

6 files changed

+362
-56
lines changed

MLAPI.Tests/NetworkingManagerComponents/Binary/BitStreamTest.cs

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ namespace MLAPI.Tests.NetworkingManagerComponents.Binary
33
{
44
using MLAPI.NetworkingManagerComponents.Binary;
55
using NUnit.Framework;
6+
using System.Text;
67

78
[TestFixture]
89
public class BitStreamTest
@@ -552,5 +553,81 @@ public void TestArraysPackedDiff()
552553
Assert.That(intInData, Is.EqualTo(intOutData));
553554
Assert.That(doubleInData, Is.EqualTo(doubleOutData));
554555
}
556+
557+
[Test]
558+
public void TestString()
559+
{
560+
string testString = "Hello, World";
561+
BitStream outStream = new BitStream();
562+
outStream.WriteString(testString);
563+
outStream.WriteString(testString, true);
564+
565+
BitStream inStream = new BitStream(outStream.GetBuffer());
566+
StringBuilder readBuilder = inStream.ReadString();
567+
StringBuilder readBuilderSingle = inStream.ReadString(true);
568+
569+
Assert.That(readBuilder.ToString(), Is.EqualTo(testString));
570+
Assert.That(readBuilderSingle.ToString(), Is.EqualTo(testString));
571+
}
572+
573+
[Test]
574+
public void TestStringPacked()
575+
{
576+
string testString = "Hello, World";
577+
BitStream outStream = new BitStream();
578+
outStream.WriteStringPacked(testString);
579+
580+
BitStream inStream = new BitStream(outStream.GetBuffer());
581+
StringBuilder readBuilder = inStream.ReadStringPacked();
582+
583+
Assert.That(readBuilder.ToString(), Is.EqualTo(testString));
584+
}
585+
586+
[Test]
587+
public void TestStringDiff()
588+
{
589+
string testString = "Hello, World"; // The simulated "new" value of testString
590+
string originalString = "Heyo, World"; // This is what testString supposedly changed *from*
591+
BitStream outStream = new BitStream();
592+
outStream.WriteStringDiff(testString, originalString);
593+
outStream.WriteStringDiff(testString, originalString, true);
594+
595+
BitStream inStream = new BitStream(outStream.GetBuffer());
596+
// Read regular diff
597+
StringBuilder readBuilder = inStream.ReadStringDiff(originalString);
598+
599+
// Read diff directly to StringBuilder
600+
inStream.BitPosition = 0;
601+
StringBuilder stringCompare = new StringBuilder(originalString);
602+
inStream.ReadStringDiff(stringCompare);
603+
604+
// Read single-byte diff
605+
StringBuilder byteBuilder = inStream.ReadStringDiff(originalString, true);
606+
607+
Assert.That(readBuilder.ToString(), Is.EqualTo(testString));
608+
Assert.That(stringCompare.ToString(), Is.EqualTo(testString));
609+
Assert.That(byteBuilder.ToString(), Is.EqualTo(testString));
610+
}
611+
612+
[Test]
613+
public void TestStringPackedDiff()
614+
{
615+
string testString = "Hello, World"; // The simulated "new" value of testString
616+
string originalString = "Heyo, World"; // This is what testString supposedly changed *from*
617+
BitStream outStream = new BitStream();
618+
outStream.WriteStringPackedDiff(testString, originalString);
619+
620+
BitStream inStream = new BitStream(outStream.GetBuffer());
621+
// Read regular diff
622+
StringBuilder readBuilder = inStream.ReadStringPackedDiff(originalString);
623+
624+
// Read diff directly to StringBuilder
625+
inStream.BitPosition = 0;
626+
StringBuilder stringCompare = new StringBuilder(originalString);
627+
inStream.ReadStringPackedDiff(stringCompare);
628+
629+
Assert.That(readBuilder.ToString(), Is.EqualTo(testString));
630+
Assert.That(stringCompare.ToString(), Is.EqualTo(testString));
631+
}
555632
}
556633
}

MLAPI/MonoBehaviours/Core/NetworkedBehaviour.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,14 @@ public abstract class NetworkedBehaviour : MonoBehaviour
2020
/// </summary>
2121
public bool isLocalPlayer => networkedObject.isLocalPlayer;
2222
/// <summary>
23-
/// Gets if the object is owned by the local player
23+
/// Gets if the object is owned by the local player or if the object is the local player object
2424
/// </summary>
2525
public bool isOwner => networkedObject.isOwner;
2626
/// <summary>
27+
/// Gets if the object is owned by the local player and this is not a player object
28+
/// </summary>
29+
public bool isObjectOwner => networkedObject.isObjectOwner;
30+
/// <summary>
2731
/// Gets if we are executing as server
2832
/// </summary>
2933
protected bool isServer => NetworkingManager.singleton.isServer;

MLAPI/MonoBehaviours/Core/NetworkedObject.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,13 @@ internal set
6868
/// </summary>
6969
public bool isLocalPlayer => isPlayerObject && (OwnerClientId == NetworkingManager.singleton.LocalClientId || (OwnerClientId == NetworkingManager.singleton.NetworkConfig.NetworkTransport.HostDummyId && NetworkingManager.singleton.isHost));
7070
/// <summary>
71-
/// Gets if the object is owned by the local player
71+
/// Gets if the object is owned by the local player or if the object is the local player object
7272
/// </summary>
73-
public bool isOwner => !isPlayerObject && (OwnerClientId == NetworkingManager.singleton.LocalClientId || (OwnerClientId == NetworkingManager.singleton.NetworkConfig.NetworkTransport.HostDummyId && NetworkingManager.singleton.isHost));
73+
public bool isOwner => isLocalPlayer || isObjectOwner;
74+
/// <summary>
75+
/// Gets if the object is owned by the local player and this is not a player object
76+
/// </summary>
77+
public bool isObjectOwner => !isPlayerObject && (OwnerClientId == NetworkingManager.singleton.LocalClientId || (OwnerClientId == NetworkingManager.singleton.NetworkConfig.NetworkTransport.HostDummyId && NetworkingManager.singleton.isHost));
7478
/// <summary>
7579
/// Gets wheter or not the object is owned by anyone
7680
/// </summary>

MLAPI/MonoBehaviours/Core/NetworkingManager.cs

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,6 @@ public class NetworkingManager : MonoBehaviour
8888
/// </summary>
8989
public Action OnServerStarted = null;
9090
/// <summary>
91-
/// Wheter or not this NetworkedManager is an multiple instance of the singleton about to be removed.
92-
/// </summary>
93-
private bool isMultipleInstance = false;
94-
/// <summary>
9591
/// Delegate type called when connection has been approved
9692
/// </summary>
9793
/// <param name="clientId">The clientId of the approved client</param>
@@ -596,25 +592,26 @@ public void StartHost(Vector3? pos = null, Quaternion? rot = null, int prefabId
596592

597593
private void OnEnable()
598594
{
599-
if (singleton != null)
595+
if (singleton != null && singleton != this)
600596
{
601-
if (LogHelper.CurrentLogLevel <= LogLevel.Normal) LogHelper.LogWarning("Multiple NetworkingManagers");
602-
this.isMultipleInstance = true;
603597
Destroy(this.gameObject);
604-
return;
605598
}
606-
singleton = this;
607-
if (DontDestroy)
608-
DontDestroyOnLoad(gameObject);
609-
if (RunInBackground)
610-
Application.runInBackground = true;
599+
else
600+
{
601+
singleton = this;
602+
if (DontDestroy)
603+
DontDestroyOnLoad(gameObject);
604+
if (RunInBackground)
605+
Application.runInBackground = true;
606+
}
611607
}
612608

613609
private void OnDestroy()
614610
{
615-
if (!isMultipleInstance) {
611+
if (singleton != null && singleton == this)
612+
{
616613
singleton = null;
617-
Shutdown();
614+
Shutdown();
618615
}
619616
}
620617

MLAPI/MonoBehaviours/Prototyping/NetworkedTransform.cs

Lines changed: 107 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using MLAPI.MonoBehaviours.Core;
1+
using System.Collections.Generic;
2+
using MLAPI.MonoBehaviours.Core;
23
using MLAPI.NetworkingManagerComponents.Binary;
34
using System.IO;
45
using UnityEngine;
@@ -11,11 +12,16 @@ namespace MLAPI.MonoBehaviours.Prototyping
1112
[AddComponentMenu("MLAPI/NetworkedTransform")]
1213
public class NetworkedTransform : NetworkedBehaviour
1314
{
14-
/// <summary>
15-
/// Sends per second
16-
/// </summary>
17-
[Range(0f, 120f)]
18-
public float SendsPerSecond = 20;
15+
public class ClientSendInfo
16+
{
17+
public uint clientId;
18+
public float lastSent;
19+
public Vector3? lastMissedPosition;
20+
public Quaternion? lastMissedRotation;
21+
}
22+
23+
[Range(0, 120)]
24+
public float FixedSendsPerSecond = 20f;
1925
/// <summary>
2026
/// Is the sends per second assumed to be the same across all instances
2127
/// </summary>
@@ -43,7 +49,6 @@ public class NetworkedTransform : NetworkedBehaviour
4349
/// The min degrees to rotate before a send it sent
4450
/// </summary>
4551
public float MinDegrees = 1.5f;
46-
private float timeForLerp;
4752
private float lerpT;
4853
private Vector3 lerpStartPos;
4954
private Quaternion lerpStartRot;
@@ -53,18 +58,17 @@ public class NetworkedTransform : NetworkedBehaviour
5358
private float lastSendTime;
5459
private Vector3 lastSentPos;
5560
private Quaternion lastSentRot;
56-
/// <summary>
57-
/// Should proximity be enabled
58-
/// </summary>
59-
public bool EnableProximity = false;
60-
/// <summary>
61-
/// The distance to use for proximity
62-
/// </summary>
63-
[Tooltip("If enable proximity is turned on, on clients within this range will be recieving position updates from the server")]
64-
public float ProximityRange = 50;
61+
62+
public bool EnableRange;
63+
public AnimationCurve DistanceSendrate = AnimationCurve.Constant(0, 500, 20);
64+
private readonly Dictionary<uint, ClientSendInfo> clientSendInfo = new Dictionary<uint, ClientSendInfo>();
6565

6666
private static byte[] positionUpdateBuffer = new byte[24];
6767

68+
public delegate bool MoveValidationDelegate(Vector3 oldPos, Vector3 newPos);
69+
70+
public MoveValidationDelegate IsMoveValidDelegate = null;
71+
6872
private void OnValidate()
6973
{
7074
if (!AssumeSyncedSends && InterpolatePosition)
@@ -77,6 +81,11 @@ private void OnValidate()
7781
MinMeters = 0;
7882
}
7983

84+
private float GetTimeForLerp(Vector3 pos1, Vector3 pos2)
85+
{
86+
return 1f / DistanceSendrate.Evaluate(Vector3.Distance(pos1, pos2));
87+
}
88+
8089
/// <summary>
8190
/// Registers message handlers
8291
/// </summary>
@@ -90,10 +99,6 @@ public override void NetworkStart()
9099
{
91100
RegisterMessageHandler("MLAPI_OnRecieveTransformFromServer", OnRecieveTransformFromServer);
92101
}
93-
if(AssumeSyncedSends)
94-
{
95-
timeForLerp = 1f / SendsPerSecond;
96-
}
97102

98103
lastSentRot = transform.rotation;
99104
lastSentPos = transform.position;
@@ -110,7 +115,7 @@ private void Update()
110115
if(isOwner || isLocalPlayer || (OwnerClientId == NetworkingManager.singleton.NetworkConfig.NetworkTransport.InvalidDummyId && isServer))
111116
{
112117
//We own the object OR we are server and the object is not owned by anyone OR we are the object.
113-
if(NetworkingManager.singleton.NetworkTime - lastSendTime >= timeForLerp && (Vector3.Distance(transform.position, lastSentPos) > MinMeters || Quaternion.Angle(transform.rotation, lastSentRot) > MinDegrees))
118+
if(NetworkingManager.singleton.NetworkTime - lastSendTime >= (1f / FixedSendsPerSecond) && (Vector3.Distance(transform.position, lastSentPos) > MinMeters || Quaternion.Angle(transform.rotation, lastSentRot) > MinDegrees))
114119
{
115120
lastSendTime = NetworkingManager.singleton.NetworkTime;
116121
lastSentPos = transform.position;
@@ -145,15 +150,27 @@ private void Update()
145150
//Snap, set T to 1 (100% of the lerp)
146151
lerpT = 1f;
147152
}
148-
lerpT += Time.unscaledDeltaTime / timeForLerp;
153+
154+
if (isServer || !EnableRange)
155+
lerpT += Time.unscaledDeltaTime / FixedSendsPerSecond;
156+
else
157+
{
158+
Vector3 myPos = NetworkingManager.singleton.ConnectedClients[NetworkingManager.singleton.LocalClientId].PlayerObject.transform.position;
159+
lerpT += Time.unscaledDeltaTime / GetTimeForLerp(transform.position, myPos);
160+
}
161+
149162
transform.position = Vector3.Lerp(lerpStartPos, lerpEndPos, lerpT);
150163
transform.rotation = Quaternion.Slerp(lerpStartRot, lerpEndRot, lerpT);
151164
}
152165
}
166+
167+
if (isServer) CheckForMissedSends();
153168
}
154169

155170
private void OnRecieveTransformFromServer(uint clientId, BitReader reader)
156171
{
172+
if (!enabled) return;
173+
157174
byte[] data = reader.ReadByteArray();
158175
using (MemoryStream stream = new MemoryStream(data))
159176
{
@@ -178,6 +195,8 @@ private void OnRecieveTransformFromServer(uint clientId, BitReader reader)
178195

179196
private void OnRecieveTransformFromClient(uint clientId, BitReader reader)
180197
{
198+
if (!enabled) return;
199+
181200
byte[] data = reader.ReadByteArray();
182201
using (MemoryStream readStream = new MemoryStream(data))
183202
{
@@ -190,6 +209,13 @@ private void OnRecieveTransformFromClient(uint clientId, BitReader reader)
190209
float xRot = bReader.ReadSingle();
191210
float yRot = bReader.ReadSingle();
192211
float zRot = bReader.ReadSingle();
212+
213+
if (IsMoveValidDelegate != null && !IsMoveValidDelegate(lerpEndPos, new Vector3(xPos, yPos, zPos)))
214+
{
215+
//Invalid move!
216+
//TODO: Add rubber band (just a message telling them to go back)
217+
return;
218+
}
193219

194220
if (InterpolateServer)
195221
{
@@ -215,14 +241,38 @@ private void OnRecieveTransformFromClient(uint clientId, BitReader reader)
215241
writer.Write(yRot);
216242
writer.Write(zRot);
217243
}
218-
if (EnableProximity)
244+
if (EnableRange)
219245
{
220246
// For instead of Foreach?! TODO!!!
221-
for (uint i = 0; i < NetworkingManager.singleton.ConnectedClients.Count; i++)
247+
for (int i = 0; i < NetworkingManager.singleton.ConnectedClientsList.Count; i++)
222248
{
223-
if (Vector3.Distance(NetworkingManager.singleton.ConnectedClients[i].PlayerObject.transform.position, transform.position) <= ProximityRange)
249+
if (!clientSendInfo.ContainsKey(NetworkingManager.singleton.ConnectedClientsList[i].ClientId))
250+
{
251+
clientSendInfo.Add(NetworkingManager.singleton.ConnectedClientsList[i].ClientId, new ClientSendInfo()
252+
{
253+
clientId = NetworkingManager.singleton.ConnectedClientsList[i].ClientId,
254+
lastMissedPosition = null,
255+
lastMissedRotation = null,
256+
lastSent = 0
257+
});
258+
}
259+
260+
ClientSendInfo info = clientSendInfo[NetworkingManager.singleton.ConnectedClientsList[i].ClientId];
261+
Vector3 receiverPosition = NetworkingManager.singleton.ConnectedClientsList[i].PlayerObject.transform.position;
262+
Vector3 senderPosition = NetworkingManager.singleton.ConnectedClients[OwnerClientId].PlayerObject.transform.position;
263+
264+
if (NetworkingManager.singleton.NetworkTime - info.lastSent >= GetTimeForLerp(receiverPosition, senderPosition))
265+
{
266+
info.lastSent = NetworkingManager.singleton.NetworkTime;
267+
info.lastMissedPosition = null;
268+
info.lastMissedRotation = null;
269+
270+
SendToClientTarget(NetworkingManager.singleton.ConnectedClientsList[i].ClientId, "MLAPI_OnRecieveTransformFromServer", "MLAPI_POSITION_UPDATE", positionUpdateBuffer, true);
271+
}
272+
else
224273
{
225-
SendToClientTarget(NetworkingManager.singleton.ConnectedClients[i].ClientId, "MLAPI_OnRecieveTransformFromServer", "MLAPI_POSITION_UPDATE", positionUpdateBuffer, true);
274+
info.lastMissedPosition = new Vector3(xPos, yPos, zPos);
275+
info.lastMissedRotation = Quaternion.Euler(xRot, yRot, zRot);
226276
}
227277
}
228278
}
@@ -234,5 +284,36 @@ private void OnRecieveTransformFromClient(uint clientId, BitReader reader)
234284
}
235285
}
236286
}
287+
288+
private void CheckForMissedSends()
289+
{
290+
for (int i = 0; i < NetworkingManager.singleton.ConnectedClientsList.Count; i++)
291+
{
292+
ClientSendInfo info = clientSendInfo[NetworkingManager.singleton.ConnectedClientsList[i].ClientId];
293+
Vector3 receiverPosition = NetworkingManager.singleton.ConnectedClientsList[i].PlayerObject.transform.position;
294+
Vector3 senderPosition = NetworkingManager.singleton.ConnectedClients[OwnerClientId].PlayerObject.transform.position;
295+
296+
if (NetworkingManager.singleton.NetworkTime - info.lastSent >= GetTimeForLerp(receiverPosition, senderPosition))
297+
{
298+
info.lastSent = NetworkingManager.singleton.NetworkTime;
299+
info.lastMissedPosition = null;
300+
info.lastMissedRotation = null;
301+
302+
SendToClientTarget(NetworkingManager.singleton.ConnectedClientsList[i].ClientId, "MLAPI_OnRecieveTransformFromServer", "MLAPI_POSITION_UPDATE", positionUpdateBuffer, true);
303+
}
304+
}
305+
}
306+
307+
public void Teleport(Vector3 position, Quaternion rotation)
308+
{
309+
if (InterpolateServer && isServer || isClient)
310+
{
311+
lerpStartPos = position;
312+
lerpStartRot = rotation;
313+
lerpEndPos = position;
314+
lerpEndRot = rotation;
315+
lerpT = 0;
316+
}
317+
}
237318
}
238319
}

0 commit comments

Comments
 (0)