This repository has been archived by the owner on Jan 18, 2022. It is now read-only.
/
EntitySnapshot.cs
157 lines (132 loc) · 5.72 KB
/
EntitySnapshot.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
using System.Collections.Generic;
using Improbable.Worker.CInterop;
namespace Improbable.Gdk.Core
{
/// <summary>
/// A snapshot of a SpatialOS entity.
/// </summary>
public struct EntitySnapshot
{
private readonly Dictionary<uint, ISpatialComponentSnapshot> components;
/// <summary>
/// Gets the SpatialOS component snapshot if present.
/// </summary>
/// <returns> The component snapshot, if it exists, or null otherwise.</returns>
/// <typeparam name="T">The component type.</typeparam>
public T? GetComponentSnapshot<T>() where T : struct, ISpatialComponentSnapshot
{
var id = ComponentDatabase.GetSnapshotComponentId<T>();
if (components.TryGetValue(id, out var data))
{
return (T) data;
}
return null;
}
/// <summary>
/// Attempts to get the SpatialOS component if present.
/// </summary>
/// <param name="snapshot">
/// When this method returns, this will be the component if it exists, default constructed otherwise.
/// </param>
/// <typeparam name="T">The component type.</typeparam>
/// <returns>True, if the component exists; false otherwise.</returns>
public bool TryGetComponentSnapshot<T>(out T snapshot) where T : struct, ISpatialComponentSnapshot
{
var maybeSnapshot = GetComponentSnapshot<T>();
snapshot = maybeSnapshot ?? default(T);
return maybeSnapshot.HasValue;
}
/// <summary>
/// Adds a component to this snapshot.
/// </summary>
/// <remarks>
/// Will override any pre-existing component in the snapshot.
/// </remarks>
/// <param name="component">The component to add.</param>
/// <typeparam name="T">The component type.</typeparam>
public void AddComponentSnapshot<T>(T component) where T : struct, ISpatialComponentSnapshot
{
components[component.ComponentId] = component;
}
internal EntitySnapshot(Entity entitySnapshot)
{
components = new Dictionary<uint, ISpatialComponentSnapshot>();
var componentDataHandler = new QueryComponentDataHandler(entitySnapshot);
foreach (var componentId in entitySnapshot.GetComponentIds())
{
Dynamic.ForComponent(componentId, componentDataHandler);
}
components = componentDataHandler.Components;
}
internal EntitySnapshot(SchemaObject entityObject)
{
var handler = new SchemaEntityDeserializer(entityObject);
var ids = entityObject.GetUniqueFieldIds();
foreach (var id in ids)
{
Dynamic.ForComponent(id, handler);
}
components = handler.Components;
}
internal void SerializeToSchemaObject(SchemaObject inObj)
{
var handler = new SchemaEntitySerializer(inObj, components);
foreach (var pair in components)
{
Dynamic.ForComponent(pair.Key, handler);
}
}
}
internal struct QueryComponentDataHandler : Dynamic.IHandler
{
public Dictionary<uint, ISpatialComponentSnapshot> Components;
private readonly Entity entitySnapshot;
public QueryComponentDataHandler(Entity entitySnapshot)
{
Components = new Dictionary<uint, ISpatialComponentSnapshot>();
this.entitySnapshot = entitySnapshot;
}
public void Accept<TUpdate, TSnapshot>(uint componentId, Dynamic.VTable<TUpdate, TSnapshot> vtable)
where TUpdate : struct, ISpatialComponentUpdate
where TSnapshot : struct, ISpatialComponentSnapshot
{
var schemaObject = entitySnapshot.Get(componentId).Value;
Components.Add(componentId, vtable.DeserializeSnapshot(schemaObject));
}
}
internal struct SchemaEntityDeserializer : Dynamic.IHandler
{
public readonly Dictionary<uint, ISpatialComponentSnapshot> Components;
private SchemaObject entityObject;
public SchemaEntityDeserializer(SchemaObject entityObject)
{
Components = new Dictionary<uint, ISpatialComponentSnapshot>();
this.entityObject = entityObject;
}
public void Accept<TUpdate, TSnapshot>(uint componentId, Dynamic.VTable<TUpdate, TSnapshot> vtable)
where TUpdate : struct, ISpatialComponentUpdate
where TSnapshot : struct, ISpatialComponentSnapshot
{
var componentObject = entityObject.GetObject(componentId);
Components[componentId] = vtable.DeserializeSnapshotRaw(componentObject);
}
}
internal struct SchemaEntitySerializer : Dynamic.IHandler
{
private Dictionary<uint, ISpatialComponentSnapshot> componentSnapshots;
private SchemaObject targetObject;
public SchemaEntitySerializer(SchemaObject targetObject, Dictionary<uint, ISpatialComponentSnapshot> componentSnapshots)
{
this.targetObject = targetObject;
this.componentSnapshots = componentSnapshots;
}
public void Accept<TUpdate, TSnapshot>(uint componentId, Dynamic.VTable<TUpdate, TSnapshot> vtable)
where TUpdate : struct, ISpatialComponentUpdate
where TSnapshot : struct, ISpatialComponentSnapshot
{
// Okay to grab the value directly, we only call this for snapshots that actually exist.
var data = componentSnapshots[componentId];
vtable.SerializeSnapshotRaw((TSnapshot) data, targetObject.AddObject(componentId));
}
}
}