1+ using System . Collections . Generic ;
12using Improbable . Gdk . Core ;
2- using Improbable . Gdk . ReactiveComponents ;
3- using Unity . Collections ;
3+ using Improbable . Worker . CInterop ;
44using Unity . Entities ;
55using UnityEngine ;
66
77namespace Improbable . Gdk . Health
88{
99 [ UpdateInGroup ( typeof ( SpatialOSUpdateGroup ) ) ]
1010 [ UpdateAfter ( typeof ( ServerHealthModifierSystem ) ) ]
11+ [ AlwaysUpdateSystem ]
1112 public class HealthRegenSystem : ComponentSystem
1213 {
13- public struct EntitiesNeedingRegenData
14+ private WorkerSystem workerSystem ;
15+ private ComponentUpdateSystem componentUpdateSystem ;
16+ private CommandSystem commandSystem ;
17+
18+ private ComponentGroup initGroup ;
19+ private ComponentGroup regenGroup ;
20+
21+ private HashSet < EntityId > recentlyDamagedCache = new HashSet < EntityId > ( ) ;
22+
23+ protected override void OnCreateManager ( )
1424 {
15- public readonly int Length ;
16- [ ReadOnly ] public EntityArray Entities ;
17- [ ReadOnly ] public ComponentDataArray < HealthRegenComponent . Component > HealthRegenComponents ;
18- [ ReadOnly ] public SubtractiveComponent < HealthRegenData > DenotesMissingData ;
19- [ ReadOnly ] public ComponentDataArray < Authoritative < HealthComponent . Component > > DenotesAuthority ;
25+ base . OnCreateManager ( ) ;
26+
27+ workerSystem = World . GetExistingManager < WorkerSystem > ( ) ;
28+ componentUpdateSystem = World . GetExistingManager < ComponentUpdateSystem > ( ) ;
29+ commandSystem = World . GetExistingManager < CommandSystem > ( ) ;
30+
31+ initGroup = GetComponentGroup (
32+ ComponentType . ReadOnly < HealthRegenComponent . Component > ( ) ,
33+ ComponentType . Subtractive < HealthRegenData > ( ) ,
34+ ComponentType . ReadOnly < HealthComponent . ComponentAuthority > ( )
35+ ) ;
36+ initGroup . SetFilter ( HealthComponent . ComponentAuthority . Authoritative ) ;
37+
38+ regenGroup = GetComponentGroup (
39+ ComponentType . Create < HealthRegenComponent . Component > ( ) ,
40+ ComponentType . Create < HealthRegenData > ( ) ,
41+ ComponentType . ReadOnly < HealthComponent . Component > ( ) ,
42+ ComponentType . ReadOnly < SpatialEntityId > ( ) ,
43+ ComponentType . ReadOnly < HealthComponent . ComponentAuthority > ( )
44+ ) ;
45+ regenGroup . SetFilter ( HealthComponent . ComponentAuthority . Authoritative ) ;
2046 }
2147
22- public struct TakingDamage
48+ protected override void OnUpdate ( )
2349 {
24- public readonly int Length ;
25- public ComponentDataArray < HealthRegenData > RegenData ;
26- public ComponentDataArray < HealthRegenComponent . Component > HealthRegenComponents ;
27- [ ReadOnly ] public ComponentDataArray < HealthComponent . ReceivedEvents . HealthModified > HealthModifiedEvents ;
28- [ ReadOnly ] public ComponentDataArray < Authoritative < HealthComponent . Component > > DenotesAuthority ;
50+ InitializeRegenData ( ) ;
51+
52+ ProcessDamageEvents ( ) ;
53+
54+ ApplyHealthRegen ( ) ;
2955 }
3056
31- public struct EntitiesToRegen
57+ private void InitializeRegenData ( )
3258 {
33- public readonly int Length ;
34- public ComponentDataArray < HealthComponent . CommandSenders . ModifyHealth > ModifyHealthCommandSenders ;
35- public ComponentDataArray < HealthRegenComponent . Component > HealthRegenComponents ;
36- public ComponentDataArray < HealthRegenData > RegenData ;
37- [ ReadOnly ] public ComponentDataArray < HealthComponent . Component > HealthComponents ;
38- [ ReadOnly ] public ComponentDataArray < SpatialEntityId > EntityId ;
39- [ ReadOnly ] public ComponentDataArray < Authoritative < HealthComponent . Component > > DenotesAuthority ;
40- }
59+ if ( initGroup . IsEmptyIgnoreFilter )
60+ {
61+ return ;
62+ }
4163
42- [ Inject ] private EntitiesNeedingRegenData needData ;
43- [ Inject ] private TakingDamage takingDamage ;
44- [ Inject ] private EntitiesToRegen toRegen ;
64+ var entities = initGroup . GetEntityArray ( ) ;
65+ var regenComponentData = initGroup . GetComponentDataArray < HealthRegenComponent . Component > ( ) ;
4566
46- protected override void OnUpdate ( )
47- {
4867 // Add the HealthRegenData if you don't currently have it.
49- for ( var i = 0 ; i < needData . Length ; i ++ )
68+ for ( var i = 0 ; i < entities . Length ; i ++ )
5069 {
51- var healthRegenComponent = needData . HealthRegenComponents [ i ] ;
70+ var healthRegenComponent = regenComponentData [ i ] ;
5271
5372 var regenData = new HealthRegenData ( ) ;
5473
@@ -58,49 +77,71 @@ protected override void OnUpdate()
5877 regenData . NextSpatialSyncTimer = healthRegenComponent . CooldownSyncInterval ;
5978 }
6079
61- PostUpdateCommands . AddComponent ( needData . Entities [ i ] , regenData ) ;
80+ PostUpdateCommands . AddComponent ( entities [ i ] , regenData ) ;
6281 }
82+ }
6383
64- // When the HealthComponent takes a damaging event, reset the DamagedRecently timer.
65- for ( var i = 0 ; i < takingDamage . Length ; i ++ )
84+ private void ProcessDamageEvents ( )
85+ {
86+ var healthModifiedEvents = componentUpdateSystem . GetEventsReceived < HealthComponent . HealthModified . Event > ( ) ;
87+ if ( healthModifiedEvents . Count == 0 )
6688 {
67- var healthModifiedEvents = takingDamage . HealthModifiedEvents [ i ] ;
68- var damagedRecently = false ;
89+ return ;
90+ }
6991
70- foreach ( var modifiedEvent in takingDamage . HealthModifiedEvents [ i ] . Events )
92+ for ( var i = 0 ; i < healthModifiedEvents . Count ; ++ i )
93+ {
94+ ref readonly var healthEvent = ref healthModifiedEvents [ i ] ;
95+ if ( componentUpdateSystem . GetAuthority ( healthEvent . EntityId , HealthComponent . ComponentId ) ==
96+ Authority . NotAuthoritative )
7197 {
72- var modifier = modifiedEvent . Modifier ;
73- if ( modifier . Amount < 0 )
74- {
75- damagedRecently = true ;
76- break ;
77- }
98+ continue ;
7899 }
79- if ( ! damagedRecently )
100+
101+ if ( healthEvent . Event . Payload . Modifier . Amount < 0 )
80102 {
81- continue ;
103+ recentlyDamagedCache . Add ( healthEvent . EntityId ) ;
82104 }
105+ }
83106
84- var regenComponent = takingDamage . HealthRegenComponents [ i ] ;
85- var regenData = takingDamage . RegenData [ i ] ;
107+ var healthRegenComponentDataForEntity = GetComponentDataFromEntity < HealthRegenComponent . Component > ( ) ;
108+ var healthRegenDataForEntity = GetComponentDataFromEntity < HealthRegenData > ( ) ;
109+ foreach ( var entityId in recentlyDamagedCache )
110+ {
111+ workerSystem . TryGetEntity ( entityId , out var entity ) ;
112+ var regenComponent = healthRegenComponentDataForEntity [ entity ] ;
113+ var regenData = healthRegenDataForEntity [ entity ] ;
86114
87115 regenComponent . DamagedRecently = true ;
88116 regenComponent . RegenCooldownTimer = regenComponent . RegenPauseTime ;
89-
90117 regenData . DamagedRecentlyTimer = regenComponent . RegenPauseTime ;
91118 regenData . NextSpatialSyncTimer = regenComponent . CooldownSyncInterval ;
92119
93- takingDamage . HealthRegenComponents [ i ] = regenComponent ;
94- takingDamage . RegenData [ i ] = regenData ;
120+ healthRegenComponentDataForEntity [ entity ] = regenComponent ;
121+ healthRegenDataForEntity [ entity ] = regenData ;
95122 }
96123
97- // Count down the timers, and update the HealthComponent accordingly.
98- for ( var i = 0 ; i < toRegen . Length ; i ++ )
124+ recentlyDamagedCache . Clear ( ) ;
125+ }
126+
127+ private void ApplyHealthRegen ( )
128+ {
129+ if ( regenGroup . IsEmptyIgnoreFilter )
99130 {
100- var healthComponent = toRegen . HealthComponents [ i ] ;
101- var regenComponent = toRegen . HealthRegenComponents [ i ] ;
131+ return ;
132+ }
102133
103- var regenData = toRegen . RegenData [ i ] ;
134+ var spatialIdData = regenGroup . GetComponentDataArray < SpatialEntityId > ( ) ;
135+ var healthComponentData = regenGroup . GetComponentDataArray < HealthComponent . Component > ( ) ;
136+ var healthRegenComponentData = regenGroup . GetComponentDataArray < HealthRegenComponent . Component > ( ) ;
137+ var healthRegenData = regenGroup . GetComponentDataArray < HealthRegenData > ( ) ;
138+
139+ // Count down the timers, and update the HealthComponent accordingly.
140+ for ( var i = 0 ; i < spatialIdData . Length ; i ++ )
141+ {
142+ var healthComponent = healthComponentData [ i ] ;
143+ var regenComponent = healthRegenComponentData [ i ] ;
144+ var regenData = healthRegenData [ i ] ;
104145
105146 // Don't regen if dead.
106147 if ( healthComponent . Health == 0 )
@@ -118,7 +159,7 @@ protected override void OnUpdate()
118159 regenData . DamagedRecentlyTimer = 0 ;
119160 regenComponent . DamagedRecently = false ;
120161 regenComponent . RegenCooldownTimer = 0 ;
121- toRegen . HealthRegenComponents [ i ] = regenComponent ;
162+ healthRegenComponentData [ i ] = regenComponent ;
122163 }
123164 else
124165 {
@@ -128,11 +169,11 @@ protected override void OnUpdate()
128169 {
129170 regenData . NextSpatialSyncTimer += regenComponent . CooldownSyncInterval ;
130171 regenComponent . RegenCooldownTimer = regenData . DamagedRecentlyTimer ;
131- toRegen . HealthRegenComponents [ i ] = regenComponent ;
172+ healthRegenComponentData [ i ] = regenComponent ;
132173 }
133174 }
134175
135- toRegen . RegenData [ i ] = regenData ;
176+ healthRegenData [ i ] = regenData ;
136177
137178 return ;
138179 }
@@ -146,17 +187,17 @@ protected override void OnUpdate()
146187 regenData . NextRegenTimer += regenComponent . RegenInterval ;
147188
148189 // Send command to regen entity.
149- var commandSender = toRegen . ModifyHealthCommandSenders [ i ] ;
150190 var modifyHealthRequest = new HealthComponent . ModifyHealth . Request (
151- toRegen . EntityId [ i ] . EntityId ,
191+ spatialIdData [ i ] . EntityId ,
152192 new HealthModifier ( )
153193 {
154194 Amount = regenComponent . RegenAmount
155- } ) ;
156- commandSender . RequestsToSend . Add ( modifyHealthRequest ) ;
195+ }
196+ ) ;
197+ commandSystem . SendCommand ( modifyHealthRequest ) ;
157198 }
158199
159- toRegen . RegenData [ i ] = regenData ;
200+ healthRegenData [ i ] = regenData ;
160201 }
161202 }
162203 }
0 commit comments