-
Notifications
You must be signed in to change notification settings - Fork 48
/
Copy pathBaseConflict.Classes.Gamestates.Actions.pas
340 lines (280 loc) · 8.1 KB
/
BaseConflict.Classes.Gamestates.Actions.pas
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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
unit BaseConflict.Classes.Gamestates.Actions;
interface
uses
// Engine
Engine.Helferlein,
Engine.Helferlein.DataStructures,
Engine.GUI,
// Game
BaseConflict.Globals.Client,
BaseConflict.Classes.Client,
BaseConflict.Classes.Gamestates;
type
TActionClient = class(TAction)
private
FInverted, FDoInExecute, FDoInExecuteSynchronized, FDoInFinished : boolean;
public
function Invert : TActionClient;
function InvertIf(const Condition : boolean) : TActionClient;
function DoInExecute : TActionClient;
function DoInExecuteSynchronized : TActionClient;
function DoInFinished : TActionClient;
procedure Deploy;
end;
ProcInlineActionWithValue<T> = reference to procedure(const Value : T);
TActionInlineWithValue<T> = class(TActionInline)
strict private
FEmulateWithValue, FRollbackWithValue : ProcInlineActionWithValue<T>;
public
Value : T;
constructor Create(const Value : T);
procedure Deploy;
function OnEmulate(const Action : ProcInlineActionWithValue<T>) : TActionInlineWithValue<T>; overload;
function OnRollback(const Action : ProcInlineActionWithValue<T>) : TActionInlineWithValue<T>; overload;
procedure Emulate; override;
procedure Rollback; override;
end;
TActionGeneric<T> = class(TActionClient)
private
FValueT : T;
public
constructor Create(const ValueT : T);
end;
TActionGeneric<T, U> = class(TActionGeneric<T>)
private
FValueU : U;
public
constructor Create(const ValueT : T; const ValueU : U);
end;
/// <summary> Activates the given component at the given state. </summary>
TActionActivateStateComponent = class(TActionGeneric<TGameState, CGameStateComponent>)
public
procedure Emulate; override;
procedure Rollback; override;
end;
/// <summary> Shows the specified gui component. </summary>
TActionShowComponent = class(TActionGeneric<string>)
private
FFormerState : boolean;
public
procedure Emulate; override;
procedure Rollback; override;
end;
/// <summary> Adds the specified gui class. </summary>
TActionAddClassToComponent = class(TActionGeneric<string, string>)
private
FHasAdded : boolean;
public
procedure Emulate; override;
procedure Rollback; override;
end;
ProcSetter<T> = reference to procedure(const Value : T);
TActionSetVariable<T> = class(TActionClient)
public type
PT = ^T;
private
FNewValue, FFormerValue : T;
FSetter : ProcSetter<T>;
public
constructor Create(const NewValue : T; const FormerValue : T; const ValueSetter : ProcSetter<T>);
procedure Emulate; override;
function Execute : boolean; override;
function ExecuteSynchronized : boolean; override;
procedure Rollback; override;
procedure Finished; override;
end;
/// <summary> Frees the old variable after the action completed sucessfully. </summary>
TActionSetInstanceVariable<T : class> = class(TActionSetVariable<T>)
public
function Execute : boolean; override;
procedure Rollback; override;
end;
TActionCompound = class
private
FInverted : boolean;
FActions : TArray<TActionClient>;
public
constructor Create(const Actions : array of TActionClient);
function Invert : TActionCompound;
function InvertIf(const Condition : boolean) : TActionCompound;
/// <summary> Should be called at the end of chain. Frees the compound. </summary>
procedure Deploy;
end;
implementation
uses
BaseConflict.Api;
{ TActionActivateStateComponent }
procedure TActionActivateStateComponent.Emulate;
begin
FValueT.SetComponentActive(FValueU, FInverted);
end;
procedure TActionActivateStateComponent.Rollback;
begin
FValueT.SetComponentActive(FValueU, not FInverted);
end;
{ TActionGeneric<T> }
constructor TActionGeneric<T>.Create(const ValueT : T);
begin
inherited Create;
FValueT := ValueT;
end;
{ TActionGeneric<T, U> }
constructor TActionGeneric<T, U>.Create(const ValueT : T; const ValueU : U);
begin
inherited Create(ValueT);
FValueU := ValueU;
end;
{ TActionInlineWithValue<T> }
constructor TActionInlineWithValue<T>.Create(const Value : T);
begin
inherited Create;
self.Value := Value;
end;
procedure TActionInlineWithValue<T>.Deploy;
begin
MainActionQueue.DoAction(self);
end;
procedure TActionInlineWithValue<T>.Emulate;
begin
inherited;
if assigned(FEmulateWithValue) then FEmulateWithValue(Value);
end;
function TActionInlineWithValue<T>.OnEmulate(const Action : ProcInlineActionWithValue<T>) : TActionInlineWithValue<T>;
begin
Result := self;
FEmulateWithValue := Action;
end;
function TActionInlineWithValue<T>.OnRollback(const Action : ProcInlineActionWithValue<T>) : TActionInlineWithValue<T>;
begin
Result := self;
FRollbackWithValue := Action;
end;
procedure TActionInlineWithValue<T>.Rollback;
begin
inherited;
if assigned(FRollbackWithValue) then FRollbackWithValue(Value);
end;
{ TActionShowComponent }
procedure TActionShowComponent.Emulate;
var
Element : TGUIComponent;
begin
Element := GUI.FindUnique(FValueT);
FFormerState := Element.Visible;
Element.Visible := not FInverted;
end;
procedure TActionShowComponent.Rollback;
begin
GUI.FindUnique(FValueT).Visible := FFormerState;
end;
{ TActionAddClassToComponent }
procedure TActionAddClassToComponent.Emulate;
begin
if FInverted then FHasAdded := GUI.FindUnique(FValueT).RemoveClass(FValueU)
else FHasAdded := GUI.FindUnique(FValueT).AddClass(FValueU);
end;
procedure TActionAddClassToComponent.Rollback;
begin
if FHasAdded then
begin
if FInverted then GUI.FindUnique(FValueT).AddClass(FValueU)
else GUI.FindUnique(FValueT).RemoveClass(FValueU);
end;
end;
{ TActionCompound }
constructor TActionCompound.Create(const Actions : array of TActionClient);
begin
FActions := HArray.ConvertDynamicToTArray<TActionClient>(Actions);
end;
procedure TActionCompound.Deploy;
var
i : Integer;
begin
for i := 0 to length(FActions) - 1 do
FActions[i].InvertIf(FInverted).Deploy;
Free;
end;
function TActionCompound.Invert : TActionCompound;
begin
Result := InvertIf(True);
end;
function TActionCompound.InvertIf(const Condition : boolean) : TActionCompound;
begin
Result := self;
FInverted := Condition;
end;
{ TActionClient }
procedure TActionClient.Deploy;
begin
MainActionQueue.DoAction(self);
end;
function TActionClient.DoInExecute : TActionClient;
begin
Result := self;
FDoInExecute := True;
end;
function TActionClient.DoInExecuteSynchronized : TActionClient;
begin
Result := self;
FDoInExecuteSynchronized := True;
end;
function TActionClient.DoInFinished : TActionClient;
begin
Result := self;
FDoInFinished := True;
end;
function TActionClient.Invert : TActionClient;
begin
Result := InvertIf(True);
end;
function TActionClient.InvertIf(const Condition : boolean) : TActionClient;
begin
Result := self;
FInverted := Condition;
end;
{ TActionSetVariable<T> }
constructor TActionSetVariable<T>.Create(const NewValue : T; const FormerValue : T; const ValueSetter : ProcSetter<T>);
begin
inherited Create;
FNewValue := NewValue;
FFormerValue := FormerValue;
FSetter := ValueSetter;
end;
procedure TActionSetVariable<T>.Emulate;
begin
inherited;
assert(not FInverted, 'TActionSetVariable<T> is not invertible!');
if not FDoInExecute and not FDoInExecuteSynchronized and not FDoInFinished then FSetter(FNewValue);
end;
function TActionSetVariable<T>.Execute : boolean;
begin
Result := True;
if FDoInExecute then FSetter(FNewValue);
end;
function TActionSetVariable<T>.ExecuteSynchronized : boolean;
begin
Result := True;
if FDoInExecuteSynchronized then FSetter(FNewValue);
end;
procedure TActionSetVariable<T>.Finished;
begin
inherited;
if FDoInFinished then FSetter(FNewValue);
end;
procedure TActionSetVariable<T>.Rollback;
begin
inherited;
if not FDoInExecute and not FDoInFinished then FSetter(FFormerValue);
end;
{ TActionSetInstanceVariable<T> }
function TActionSetInstanceVariable<T>.Execute : boolean;
begin
Result := True;
FFormerValue.Free;
end;
procedure TActionSetInstanceVariable<T>.Rollback;
begin
inherited;
FNewValue.Free;
end;
end.