Skip to content
This repository was archived by the owner on Dec 5, 2018. It is now read-only.

Commit cd90f16

Browse files
committed
upgraded to SpatialOS 12.0.4
1 parent 3918918 commit cd90f16

File tree

10 files changed

+185
-27
lines changed

10 files changed

+185
-27
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package improbable.core;
2+
3+
component ClientEntityStore {
4+
id = 1006;
5+
map<string, EntityId> player_entities = 1;
6+
}
Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,25 @@
11
package improbable.core;
22

3+
enum ResponseCode {
4+
SuccessfullyCreated = 1;
5+
EntityForPlayerExists = 2;
6+
ExistingRequestInProgress = 3;
7+
Failure = 4;
8+
}
9+
310
type CreatePlayerRequest {}
411
type CreatePlayerResponse {
5-
int32 status_code = 1;
12+
ResponseCode response_code = 1;
13+
option<int32> failure_code = 2;
14+
}
15+
16+
type DeletePlayerRequest {
17+
string client_id = 1;
618
}
19+
type DeletePlayerResponse {}
720

821
component PlayerCreation {
922
id = 1001;
1023
command CreatePlayerResponse create_player(CreatePlayerRequest);
24+
command DeletePlayerResponse delete_player(DeletePlayerRequest);
1125
}

schema/improbable/player/ClientConnection.schema

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ type HeartbeatResponse{}
99
component ClientConnection {
1010
id = 1003;
1111
uint32 timeout_beats_remaining = 1;
12+
string client_id = 2;
13+
EntityId player_creator_id = 3;
1214
command HeartbeatResponse heartbeat(HeartbeatRequest);
1315
command ClientDisconnectResponse disconnect_client(ClientDisconnectRequest);
1416
}

snapshots/default.snapshot

6 Bytes
Binary file not shown.

workers/unity/Assets/Editor/SnapshotMenu.cs

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
using UnityEditor;
88
using UnityEngine;
99

10-
namespace Assets.Editor
10+
namespace Assets.Editor
1111
{
1212
public class SnapshotMenu : MonoBehaviour
1313
{
@@ -26,16 +26,20 @@ private static void GenerateDefaultSnapshot()
2626
private static void SaveSnapshot(IDictionary<EntityId, Entity> snapshotEntities)
2727
{
2828
File.Delete(SimulationSettings.DefaultSnapshotPath);
29-
var maybeError = Snapshot.Save(SimulationSettings.DefaultSnapshotPath, snapshotEntities);
30-
31-
if (maybeError.HasValue)
32-
{
33-
Debug.LogErrorFormat("Failed to generate initial world snapshot: {0}", maybeError.Value);
34-
}
35-
else
29+
using (SnapshotOutputStream stream = new SnapshotOutputStream(SimulationSettings.DefaultSnapshotPath))
3630
{
37-
Debug.LogFormat("Successfully generated initial world snapshot at {0}", SimulationSettings.DefaultSnapshotPath);
31+
foreach (var kvp in snapshotEntities)
32+
{
33+
var error = stream.WriteEntity(kvp.Key, kvp.Value);
34+
if (error.HasValue)
35+
{
36+
Debug.LogErrorFormat("Failed to generate initial world snapshot: {0}", error.Value);
37+
return;
38+
}
39+
}
3840
}
41+
42+
Debug.LogFormat("Successfully generated initial world snapshot at {0}", SimulationSettings.DefaultSnapshotPath);
3943
}
4044
}
4145
}

workers/unity/Assets/Gamelogic/Core/Bootstrap.cs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -80,14 +80,25 @@ private void RequestPlayerCreation(EntityId playerCreatorEntityId)
8080

8181
private void OnCreatePlayerCommandSuccess(CreatePlayerResponse response, EntityId playerCreatorEntityId)
8282
{
83-
var statusCode = (StatusCode) response.statusCode;
84-
if (statusCode != StatusCode.Success) {
85-
Debug.LogWarningFormat("PlayerCreator failed to create the player entity. Status code = {0}. Try again in a few seconds.", statusCode.ToString());
86-
RetryCreatePlayerCommand(playerCreatorEntityId);
83+
switch (response.responseCode)
84+
{
85+
case ResponseCode.EntityForPlayerExists:
86+
Debug.Log("Player entity already exists, request was ignored.");
87+
break;
88+
case ResponseCode.ExistingRequestInProgress:
89+
Debug.Log("A request was already in progress, this request was ignored.");
90+
RetryCreatePlayerCommand(playerCreatorEntityId);
91+
break;
92+
case ResponseCode.Failure:
93+
var failureCode = (StatusCode)response.failureCode.Value;
94+
Debug.LogWarningFormat("PlayerCreator failed to create the player entity. Status code = {0}. Try again in a few seconds.", failureCode.ToString());
95+
RetryCreatePlayerCommand(playerCreatorEntityId);
96+
break;
8797
}
8898
}
8999

90-
private void OnCreatePlayerCommandFailure(ICommandErrorDetails details, EntityId playerCreatorEntityId){
100+
private void OnCreatePlayerCommandFailure(ICommandErrorDetails details, EntityId playerCreatorEntityId)
101+
{
91102
Debug.LogWarningFormat("CreatePlayer command failed. Status code = {0}. - you probably tried to connect too soon. Try again in a few seconds.", details.StatusCode.ToString());
92103
RetryCreatePlayerCommand(playerCreatorEntityId);
93104
}

workers/unity/Assets/Gamelogic/Core/PlayerCreatingBehaviour.cs

Lines changed: 115 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@
77
using Improbable.Unity.Visualizer;
88
using UnityEngine;
99
using Improbable.Worker;
10+
using Improbable.Unity.Core.EntityQueries;
11+
using System;
12+
using System.Collections.Generic;
13+
using Improbable.Collections;
14+
using System.Linq;
15+
using Improbable.Unity.Core.Acls;
1016

1117
namespace Assets.Gamelogic.Core
1218
{
@@ -16,23 +22,128 @@ public class PlayerCreatingBehaviour : MonoBehaviour
1622
[Require]
1723
private PlayerCreation.Writer PlayerCreationWriter;
1824

25+
[Require]
26+
private ClientEntityStore.Writer ClientEntityStoreWriter;
27+
28+
private HashSet<string> inFlightClientRequests;
29+
1930
private void OnEnable()
2031
{
32+
inFlightClientRequests = new HashSet<string>();
2133
PlayerCreationWriter.CommandReceiver.OnCreatePlayer.RegisterAsyncResponse(OnCreatePlayer);
34+
PlayerCreationWriter.CommandReceiver.OnDeletePlayer.RegisterResponse(OnDeletePlayer);
2235
}
2336

2437
private void OnDisable()
2538
{
2639
PlayerCreationWriter.CommandReceiver.OnCreatePlayer.DeregisterResponse();
40+
PlayerCreationWriter.CommandReceiver.OnDeletePlayer.DeregisterResponse();
2741
}
2842

2943
private void OnCreatePlayer(ResponseHandle<PlayerCreation.Commands.CreatePlayer, CreatePlayerRequest, CreatePlayerResponse> responseHandle)
3044
{
3145
var clientWorkerId = responseHandle.CallerInfo.CallerWorkerId;
32-
var playerEntityTemplate = EntityTemplateFactory.CreatePlayerTemplate(clientWorkerId);
33-
SpatialOS.Commands.CreateEntity (PlayerCreationWriter, playerEntityTemplate)
34-
.OnSuccess (_ => responseHandle.Respond (new CreatePlayerResponse ((int) StatusCode.Success)))
35-
.OnFailure (failure => responseHandle.Respond (new CreatePlayerResponse ((int) failure.StatusCode)));
46+
47+
if (inFlightClientRequests.Contains(clientWorkerId))
48+
{
49+
responseHandle.Respond(new CreatePlayerResponse(ResponseCode.ExistingRequestInProgress, null));
50+
}
51+
else
52+
{
53+
RequestStarted(responseHandle);
54+
55+
EntityId playerEntityId;
56+
if (ClientEntityStoreWriter.Data.playerEntities.TryGetValue(clientWorkerId, out playerEntityId))
57+
{
58+
CheckPlayerEntityExists(playerEntityId, (entityExists) =>
59+
{
60+
if (entityExists)
61+
{
62+
RequestEnded(responseHandle, ResponseCode.EntityForPlayerExists);
63+
}
64+
else
65+
{
66+
CreatePlayerEntity(clientWorkerId, responseHandle);
67+
}
68+
}, (statusCode) =>
69+
{
70+
RequestEnded(responseHandle, ResponseCode.Failure, statusCode);
71+
});
72+
}
73+
else
74+
{
75+
CreatePlayerEntity(clientWorkerId, responseHandle);
76+
}
77+
78+
}
79+
}
80+
81+
private DeletePlayerResponse OnDeletePlayer(DeletePlayerRequest request, ICommandCallerInfo callerInfo)
82+
{
83+
if (callerInfo.CallerAttributeSet.Contains("physics"))
84+
{
85+
EntityId playerEntityId;
86+
if (ClientEntityStoreWriter.Data.playerEntities.TryGetValue(request.clientId, out playerEntityId))
87+
{
88+
SpatialOS.Commands.DeleteEntity(PlayerCreationWriter, playerEntityId)
89+
.OnSuccess(_ => RemoveClientId(request.clientId));
90+
}
91+
}
92+
else
93+
{
94+
Debug.LogWarningFormat("PlayerCreator ignoring command because it was sent from {0}", callerInfo.CallerWorkerId);
95+
}
96+
97+
return new DeletePlayerResponse();
98+
}
99+
100+
private void CreatePlayerEntity(string clientWorkerId,
101+
ResponseHandle<PlayerCreation.Commands.CreatePlayer, CreatePlayerRequest, CreatePlayerResponse> responseHandle)
102+
{
103+
var playerEntityTemplate = EntityTemplateFactory.CreatePlayerTemplate(clientWorkerId, gameObject.EntityId());
104+
SpatialOS.Commands.CreateEntity(PlayerCreationWriter, playerEntityTemplate)
105+
.OnSuccess(response =>
106+
{
107+
AddPlayerEntityId(clientWorkerId, response.CreatedEntityId);
108+
RequestEnded(responseHandle, ResponseCode.SuccessfullyCreated);
109+
})
110+
.OnFailure(failure => RequestEnded(responseHandle, ResponseCode.Failure, failure.StatusCode));
111+
}
112+
113+
private void CheckPlayerEntityExists(EntityId playerEntityId, Action<bool> onSuccess, Action<StatusCode> onFailure)
114+
{
115+
var query = Query.HasEntityId(playerEntityId).ReturnCount();
116+
117+
SpatialOS.Commands.SendQuery(PlayerCreationWriter, query)
118+
.OnSuccess(result => onSuccess(result.EntityCount > 0))
119+
.OnFailure(failure => onFailure(failure.StatusCode));
120+
}
121+
122+
private void AddPlayerEntityId(string clientWorkerId, EntityId playerEntityId)
123+
{
124+
var playerEntities = ClientEntityStoreWriter.Data.playerEntities;
125+
playerEntities.Add(clientWorkerId, playerEntityId);
126+
ClientEntityStoreWriter.Send(new ClientEntityStore.Update().SetPlayerEntities(playerEntities));
127+
}
128+
129+
private void RemoveClientId(string clientWorkerId)
130+
{
131+
var playerEntities = ClientEntityStoreWriter.Data.playerEntities;
132+
playerEntities.Remove(clientWorkerId);
133+
ClientEntityStoreWriter.Send(new ClientEntityStore.Update().SetPlayerEntities(playerEntities));
134+
}
135+
136+
private void RequestStarted(ResponseHandle<PlayerCreation.Commands.CreatePlayer, CreatePlayerRequest, CreatePlayerResponse> responseHandle)
137+
{
138+
inFlightClientRequests.Add(responseHandle.CallerInfo.CallerWorkerId);
139+
}
140+
141+
private void RequestEnded(ResponseHandle<PlayerCreation.Commands.CreatePlayer, CreatePlayerRequest, CreatePlayerResponse> responseHandle,
142+
ResponseCode responseCode, Option<StatusCode> failureCode = new Option<StatusCode>())
143+
{
144+
Option<int> intFailureCode = failureCode.HasValue ? (int)failureCode.Value : new Option<int>();
145+
inFlightClientRequests.Remove(responseHandle.CallerInfo.CallerWorkerId);
146+
responseHandle.Respond(new CreatePlayerResponse(responseCode, intFailureCode));
36147
}
37148
}
38149
}

workers/unity/Assets/Gamelogic/EntityTemplates/EntityTemplateFactory.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using Quaternion = UnityEngine.Quaternion;
88
using UnityEngine;
99
using Improbable.Unity.Entity;
10+
using Improbable.Collections;
1011

1112
namespace Assets.Gamelogic.EntityTemplates
1213
{
@@ -21,12 +22,13 @@ public static Entity CreatePlayerCreatorTemplate()
2122
.SetReadAcl(CommonRequirementSets.PhysicsOrVisual)
2223
.AddComponent(new Rotation.Data(Quaternion.identity.ToNativeQuaternion()), CommonRequirementSets.PhysicsOnly)
2324
.AddComponent(new PlayerCreation.Data(), CommonRequirementSets.PhysicsOnly)
25+
.AddComponent(new ClientEntityStore.Data(new Map<string, EntityId>()), CommonRequirementSets.PhysicsOnly)
2426
.Build();
2527

2628
return playerCreatorEntityTemplate;
2729
}
2830

29-
public static Entity CreatePlayerTemplate(string clientId)
31+
public static Entity CreatePlayerTemplate(string clientId, EntityId playerCreatorId)
3032
{
3133
var playerTemplate = EntityBuilder.Begin()
3234
.AddPositionComponent(Improbable.Coordinates.ZERO.ToUnityVector(), CommonRequirementSets.PhysicsOnly)
@@ -35,7 +37,7 @@ public static Entity CreatePlayerTemplate(string clientId)
3537
.SetReadAcl(CommonRequirementSets.PhysicsOrVisual)
3638
.AddComponent(new Rotation.Data(Quaternion.identity.ToNativeQuaternion()), CommonRequirementSets.PhysicsOnly)
3739
.AddComponent(new ClientAuthorityCheck.Data(), CommonRequirementSets.SpecificClientOnly(clientId))
38-
.AddComponent(new ClientConnection.Data(SimulationSettings.TotalHeartbeatsBeforeTimeout), CommonRequirementSets.PhysicsOnly)
40+
.AddComponent(new ClientConnection.Data(SimulationSettings.TotalHeartbeatsBeforeTimeout, clientId, playerCreatorId), CommonRequirementSets.PhysicsOnly)
3941
.Build();
4042

4143
return playerTemplate;

workers/unity/Assets/Gamelogic/Player/HandleClientConnection.cs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using Assets.Gamelogic.Core;
22
using Assets.Gamelogic.Utils;
3+
using Improbable.Core;
34
using Improbable.Entity.Component;
45
using Improbable.Player;
56
using Improbable.Unity;
@@ -19,7 +20,7 @@ public class HandleClientConnection : MonoBehaviour
1920

2021
private void OnEnable()
2122
{
22-
ClientConnectionWriter.CommandReceiver.OnDisconnectClient.RegisterAsyncResponse(OnDisconnectClient);
23+
ClientConnectionWriter.CommandReceiver.OnDisconnectClient.RegisterResponse(OnDisconnectClient);
2324
ClientConnectionWriter.CommandReceiver.OnHeartbeat.RegisterResponse(OnHeartbeat);
2425
heartbeatCoroutine = StartCoroutine(TimerUtils.CallRepeatedly(SimulationSettings.HeartbeatCheckIntervalSecs, CheckHeartbeat));
2526
}
@@ -31,11 +32,10 @@ private void OnDisable()
3132
StopCoroutine(heartbeatCoroutine);
3233
}
3334

34-
private void OnDisconnectClient(ResponseHandle<ClientConnection.Commands.DisconnectClient,
35-
ClientDisconnectRequest,
36-
ClientDisconnectResponse> handle)
35+
private ClientDisconnectResponse OnDisconnectClient(ClientDisconnectRequest request, ICommandCallerInfo callerinfo)
3736
{
3837
DeletePlayerEntity();
38+
return new ClientDisconnectResponse();
3939
}
4040

4141
private HeartbeatResponse OnHeartbeat(HeartbeatRequest request, ICommandCallerInfo callerinfo)
@@ -65,7 +65,10 @@ private void CheckHeartbeat()
6565

6666
private void DeletePlayerEntity()
6767
{
68-
SpatialOS.Commands.DeleteEntity(ClientConnectionWriter, gameObject.EntityId());
68+
SpatialOS.Commands.SendCommand(ClientConnectionWriter,
69+
PlayerCreation.Commands.DeletePlayer.Descriptor,
70+
new DeletePlayerRequest(ClientConnectionWriter.Data.clientId),
71+
ClientConnectionWriter.Data.playerCreatorId);
6972
}
7073
}
7174
}

workers/unity/spatialos.UnityClient.worker.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,12 @@
1717
"streaming_query": [],
1818
"component_delivery": {
1919
"default": "RELIABLE_ORDERED",
20-
"checkout_all_initially": true
20+
"checkout_all_initially": true,
21+
"override": {
22+
"improbable.core.ClientEntityStore": {
23+
"checkout_initially": false
24+
}
25+
}
2126
}
2227
},
2328
"external": {

0 commit comments

Comments
 (0)