This repository has been archived by the owner on Jan 18, 2022. It is now read-only.
/
ReactiveComponentSendSystem.cs
161 lines (138 loc) · 5.69 KB
/
ReactiveComponentSendSystem.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
158
159
160
161
using System;
using System.Collections.Generic;
using System.Reflection;
using Improbable.Gdk.Core;
using Unity.Collections;
using Unity.Entities;
using Unity.Jobs;
using UnityEngine.Profiling;
namespace Improbable.Gdk.ReactiveComponents
{
/// <summary>
/// Executes the default replication logic for each SpatialOS component.
/// </summary>
[DisableAutoCreation]
[AlwaysUpdateSystem]
[UpdateInGroup(typeof(SpatialOSSendGroup.InternalSpatialOSSendGroup))]
public class ReactiveComponentSendSystem : ComponentSystem
{
private readonly List<ComponentReplicator> componentReplicators = new List<ComponentReplicator>();
private NativeArray<ArchetypeChunk>[] chunkArrayCache;
private NativeArray<JobHandle> gatheringJobs;
protected override void OnCreate()
{
base.OnCreate();
PopulateDefaultComponentReplicators();
chunkArrayCache = new NativeArray<ArchetypeChunk>[componentReplicators.Count * 2];
gatheringJobs = new NativeArray<JobHandle>(componentReplicators.Count * 2, Allocator.Persistent);
}
protected override void OnDestroy()
{
gatheringJobs.Dispose();
base.OnDestroy();
}
protected override void OnUpdate()
{
Profiler.BeginSample("GatherChunks");
for (var i = 0; i < componentReplicators.Count; i++)
{
var replicator = componentReplicators[i];
var eventIndex = i;
var commandIndex = componentReplicators.Count + i;
var eventJobHandle = new JobHandle();
if (replicator.EventGroup != null)
{
chunkArrayCache[eventIndex] =
replicator.EventGroup.CreateArchetypeChunkArray(Allocator.TempJob, out eventJobHandle);
}
else
{
chunkArrayCache[eventIndex] = new NativeArray<ArchetypeChunk>();
}
var commandJobHandle = new JobHandle();
if (replicator.CommandGroup != null)
{
chunkArrayCache[commandIndex] =
replicator.CommandGroup.CreateArchetypeChunkArray(Allocator.TempJob, out commandJobHandle);
}
else
{
chunkArrayCache[commandIndex] = new NativeArray<ArchetypeChunk>();
}
gatheringJobs[eventIndex] = eventJobHandle;
gatheringJobs[commandIndex] = commandJobHandle;
}
Profiler.EndSample();
JobHandle.CompleteAll(gatheringJobs);
ReplicateEvents();
ReplicateCommands();
}
private void ReplicateEvents()
{
var componentUpdateSystem = World.GetExistingSystem<ComponentUpdateSystem>();
for (var i = 0; i < componentReplicators.Count; i++)
{
var eventIndex = i;
if (chunkArrayCache[eventIndex].IsCreated)
{
Profiler.BeginSample("SendEvents");
componentReplicators[i].Handler
.SendEvents(chunkArrayCache[eventIndex], this, componentUpdateSystem);
chunkArrayCache[eventIndex].Dispose();
Profiler.EndSample();
}
}
}
private void ReplicateCommands()
{
var commandSystem = World.GetExistingSystem<CommandSystem>();
for (var i = 0; i < componentReplicators.Count; i++)
{
var commandIndex = componentReplicators.Count + i;
if (chunkArrayCache[commandIndex].IsCreated)
{
Profiler.BeginSample("SendCommands");
componentReplicators[i].Handler.SendCommands(chunkArrayCache[commandIndex], this, commandSystem);
chunkArrayCache[commandIndex].Dispose();
Profiler.EndSample();
}
}
}
internal void AddComponentReplicator(IReactiveComponentReplicationHandler reactiveComponentReplicationHandler)
{
var replicator = new ComponentReplicator
{
Handler = reactiveComponentReplicationHandler,
};
if (reactiveComponentReplicationHandler.EventQuery != null)
{
replicator.EventGroup = GetEntityQuery(reactiveComponentReplicationHandler.EventQuery);
}
if (reactiveComponentReplicationHandler.CommandQueries != null)
{
replicator.CommandGroup = GetEntityQuery(reactiveComponentReplicationHandler.CommandQueries);
}
componentReplicators.Add(replicator);
}
private void PopulateDefaultComponentReplicators()
{
// Find all component specific replicators and create an instance.
var types = ReflectionUtility.GetNonAbstractTypes(typeof(IReactiveComponentReplicationHandler));
foreach (var type in types)
{
if (type.GetCustomAttribute(typeof(DisableAutoRegisterAttribute)) != null)
{
continue;
}
var componentReplicationHandler = (IReactiveComponentReplicationHandler) Activator.CreateInstance(type);
AddComponentReplicator(componentReplicationHandler);
}
}
private struct ComponentReplicator
{
public IReactiveComponentReplicationHandler Handler;
public EntityQuery EventGroup;
public EntityQuery CommandGroup;
}
}
}