Skip to content
This repository was archived by the owner on Jan 18, 2022. It is now read-only.

Commit a073a24

Browse files
author
Jamie Brynes
authored
Fix authority changes ordering problem (#1465)
1 parent 03f85ef commit a073a24

File tree

10 files changed

+108
-8
lines changed

10 files changed

+108
-8
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@
1818
- Migrated launch configurations to latest game templates. [#1457](https://github.com/spatialos/gdk-for-unity/pull/1457)
1919
- Multithreaded component serialization through `SystemBase` jobs. [#1454](https://github.com/spatialos/gdk-for-unity/pull/1454)
2020

21+
### Fixed
22+
23+
- Fixed an issue where authority changes returned by `ComponentUpdateSystem.GetAuthorityChangesReceived()` were returned in order from newest to oldest. [#1465](https://github.com/spatialos/gdk-for-unity/pull/1465)
24+
2125
## `0.3.10` - 2020-08-18
2226

2327
### Breaking Changes
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
using Improbable.Gdk.Core;
2+
using Improbable.Gdk.Test;
3+
using Improbable.Gdk.TestUtils;
4+
using Improbable.Worker.CInterop;
5+
using NUnit.Framework;
6+
7+
namespace Improbable.Gdk.EditmodeTests
8+
{
9+
[TestFixture]
10+
public class Test : MockBase
11+
{
12+
private const long EntityId = 1;
13+
14+
[Test]
15+
public void Authority_changes_are_kept_in_order_and_applied_in_order()
16+
{
17+
World
18+
.Step(world => world.Connection.CreateEntity(EntityId, GetTemplate()))
19+
.Step(world =>
20+
{
21+
world.Connection.ChangeAuthority(EntityId, 54, Authority.Authoritative);
22+
world.Connection.ChangeAuthority(EntityId, 54, Authority.NotAuthoritative);
23+
})
24+
.Step(world =>
25+
{
26+
var authChanges = world
27+
.GetSystem<ComponentUpdateSystem>()
28+
.GetAuthorityChangesReceived(new EntityId(EntityId), 54);
29+
30+
Assert.AreEqual(2, authChanges.Count);
31+
Assert.AreEqual(Authority.Authoritative, authChanges[0].Authority);
32+
Assert.AreEqual(Authority.NotAuthoritative, authChanges[1].Authority);
33+
34+
var ecsEntity = world.GetSystem<WorkerSystem>().GetEntity(new EntityId(EntityId));
35+
36+
Assert.IsFalse(world.Worker.World.EntityManager.HasComponent<Position.HasAuthority>(ecsEntity));
37+
});
38+
}
39+
40+
[Test]
41+
public void Component_updates_are_kept_in_order()
42+
{
43+
World
44+
.Step(world => world.Connection.CreateEntity(EntityId, GetTemplate()))
45+
.Step(world =>
46+
{
47+
world.Connection.UpdateComponent(EntityId, 54, new Position.Update
48+
{
49+
Coords = new Coordinates(1, 0, 0)
50+
});
51+
world.Connection.UpdateComponent(EntityId, 54, new Position.Update
52+
{
53+
Coords = new Coordinates(-1, 0, 0)
54+
});
55+
})
56+
.Step(world =>
57+
{
58+
var componentUpdates = world
59+
.GetSystem<ComponentUpdateSystem>()
60+
.GetComponentUpdatesReceived<Position.Update>();
61+
62+
Assert.AreEqual(2, componentUpdates.Count);
63+
Assert.AreEqual(1, componentUpdates[0].Update.Coords.Value.X);
64+
Assert.AreEqual(-1, componentUpdates[1].Update.Coords.Value.X);
65+
66+
var ecsEntity = world.GetSystem<WorkerSystem>().GetEntity(new EntityId(EntityId));
67+
68+
Assert.AreEqual(-1, world.Worker.World.EntityManager.GetComponentData<Position.Component>(ecsEntity).Coords.X);
69+
});
70+
}
71+
72+
private static EntityTemplate GetTemplate()
73+
{
74+
var template = new EntityTemplate();
75+
template.AddComponent(new Position.Snapshot());
76+
return template;
77+
}
78+
}
79+
}

workers/unity/Assets/Tests/EditmodeTests/Correctness/Core/OpOrderingTests.cs.meta

+3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

workers/unity/Packages/io.improbable.gdk.core/UpdatesAndEvents/AuthorityComparer.cs

+8-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,14 @@ internal class AuthorityComparer : IComparer<AuthorityChangeReceived>
66
{
77
public int Compare(AuthorityChangeReceived x, AuthorityChangeReceived y)
88
{
9-
return x.EntityId.Id.CompareTo(y.EntityId.Id);
9+
var entityIdCompare = x.EntityId.Id.CompareTo(y.EntityId.Id);
10+
11+
if (entityIdCompare == 0)
12+
{
13+
return x.AuthorityChangeId.CompareTo(y.AuthorityChangeId);
14+
}
15+
16+
return entityIdCompare;
1017
}
1118
}
1219
}

workers/unity/Packages/io.improbable.gdk.core/UpdatesAndEvents/ComponentUpdateToSend.cs

+3-1
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,13 @@ public ComponentEventReceived(T @event, EntityId entityId, ulong updateId)
6262
{
6363
public readonly Authority Authority;
6464
public readonly EntityId EntityId;
65+
public readonly uint AuthorityChangeId;
6566

66-
public AuthorityChangeReceived(Authority authority, EntityId entityId)
67+
public AuthorityChangeReceived(Authority authority, EntityId entityId, uint authorityChangeId)
6768
{
6869
Authority = authority;
6970
EntityId = entityId;
71+
AuthorityChangeId = authorityChangeId;
7072
}
7173

7274
EntityId IReceivedEntityMessage.EntityId => EntityId;

workers/unity/Packages/io.improbable.gdk.core/UpdatesAndEvents/UpdateComparer.cs

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ internal class UpdateComparer<T> : IComparer<ComponentUpdateReceived<T>> where T
77
public int Compare(ComponentUpdateReceived<T> x, ComponentUpdateReceived<T> y)
88
{
99
var entityIdCompare = x.EntityId.Id.CompareTo(y.EntityId.Id);
10+
1011
if (entityIdCompare == 0)
1112
{
1213
return x.UpdateId.CompareTo(y.UpdateId);

workers/unity/Packages/io.improbable.gdk.core/Worker/ConnectionHandlers/MockConnectionHandler.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ internal MockConnectionHandler()
4646
}
4747

4848
private uint updateId;
49+
private uint authorityChangeId;
4950

5051
private ViewDiff CurrentDiff => diffs[currentDiffIndex];
5152

@@ -64,7 +65,7 @@ public void CreateEntity(long entityId, EntityTemplate template)
6465

6566
public void ChangeAuthority(long entityId, uint componentId, Authority newAuthority)
6667
{
67-
CurrentDiff.SetAuthority(entityId, componentId, newAuthority);
68+
CurrentDiff.SetAuthority(entityId, componentId, newAuthority, authorityChangeId++);
6869
}
6970

7071
public void UpdateComponent<T>(long entityId, uint componentId, T update) where T : ISpatialComponentUpdate

workers/unity/Packages/io.improbable.gdk.core/Worker/OpListConverter.cs

+5-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ internal class OpListConverter
1010
private readonly ViewDiff viewDiff = new ViewDiff();
1111

1212
private uint componentUpdateId;
13+
private uint authorityChangeId;
1314

1415
private bool shouldClear;
1516

@@ -86,7 +87,9 @@ public bool ParseOpListIntoDiff(OpList opList, CommandMetaData commandMetaData)
8687
break;
8788
case OpType.AuthorityChange:
8889
var authorityOp = opList.GetAuthorityChangeOp(i);
89-
viewDiff.SetAuthority(authorityOp.EntityId, authorityOp.ComponentId, authorityOp.Authority);
90+
viewDiff.SetAuthority(authorityOp.EntityId, authorityOp.ComponentId, authorityOp.Authority,
91+
authorityChangeId);
92+
authorityChangeId++;
9093
break;
9194
case OpType.ComponentUpdate:
9295
var updateOp = opList.GetComponentUpdateOp(i);
@@ -118,6 +121,7 @@ public bool ParseOpListIntoDiff(OpList opList, CommandMetaData commandMetaData)
118121
public ViewDiff GetViewDiff()
119122
{
120123
componentUpdateId = 1;
124+
authorityChangeId = 1;
121125
shouldClear = true;
122126
return viewDiff;
123127
}

workers/unity/Packages/io.improbable.gdk.core/Worker/ViewDiff.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ public void RemoveComponent(long entityId, uint componentId)
162162
storage.RemoveEntityComponent(entityId);
163163
}
164164

165-
public void SetAuthority(long entityId, uint componentId, Authority authority)
165+
public void SetAuthority(long entityId, uint componentId, Authority authority, uint authorityChangeId)
166166
{
167167
if (!componentIdToComponentStorage.TryGetValue(componentId, out var authorityStorage))
168168
{
@@ -177,7 +177,7 @@ public void SetAuthority(long entityId, uint componentId, Authority authority)
177177
}
178178

179179
((IDiffAuthorityStorage) authorityStorage).AddAuthorityChange(
180-
new AuthorityChangeReceived(authority, new EntityId(entityId)));
180+
new AuthorityChangeReceived(authority, new EntityId(entityId), authorityChangeId));
181181

182182
// Remove received command requests if authority has been lost
183183
if (authority == Authority.NotAuthoritative)

workers/unity/Packages/io.improbable.gdk.transformsynchronization/Systems/SetKinematicFromAuthoritySystem.cs

+1-2
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,7 @@ private void CreateAuthChangeAction<T>(AuthChangeFunc<T> authFunc)
8484
return;
8585
}
8686

87-
// The first element is actually the latest value!
88-
var auth = changes[0];
87+
var auth = changes[changes.Count - 1];
8988

9089
authFunc(ref kinematicStateWhenAuth, auth, component);
9190
}));

0 commit comments

Comments
 (0)