-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathconfig.go
354 lines (308 loc) · 9.36 KB
/
config.go
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
341
342
343
344
345
346
347
348
349
350
351
352
353
354
package config
import (
_ "embed"
"fmt"
"reflect"
"time"
"gopkg.in/ini.v1"
)
//go:embed config.ini
var configFile []byte
// Config is the configuration of the game.
var Config config = func() (config config) {
cfg, err := ini.LoadSources(ini.LoadOptions{
AllowBooleanKeys: true,
DebugFunc: Log,
AllowNestedValues: true,
Insensitive: true,
SkipUnrecognizableLines: true,
UnescapeValueDoubleQuotes: true,
}, configFile)
ThrowError(err)
// Set the block mode to false to speed up the loading.
cfg.BlockMode = false
ThrowError(cfg.MapTo(&config))
// Sanitize the configuration.
ThrowError(config.sanitize())
return
}()
// config represents the configuration of the game.
type config struct {
Bullet struct {
CriticalHitChance float64
CriticalHitFactor int
DamageProgressAmplifier int
Height float64
InitialDamage int
ModifierProgressStep int
Speed float64
SpeedDecayDuration time.Duration
Weight float64
Width float64
}
Control struct {
AnimationDuration time.Duration
AudioEnabled *bool
BackgroundAnimationEnabled *bool
CollisionDetectionVersion EnvVariable[int]
CriticalFramesPerSecondRate float64
Debug EnvVariable[bool]
DesiredFramesPerSecondRate float64
DrawEnemyHitpointBars EnvVariable[bool]
DrawObjectLabels EnvVariable[bool]
DrawSpaceshipDiscoveryProgressBar EnvVariable[bool]
DrawSpaceshipExperienceBar EnvVariable[bool]
DrawSpaceshipShield EnvVariable[bool]
GodMode EnvVariable[bool]
PlanetChoice EnvVariable[int]
RepelEnemies EnvVariable[bool]
SuspensionFrames int
}
Enemy struct {
AccelerationProgress float64
Count int
CountProgressStep int
BerserkLikeliness float64
BerserkLikelinessProgress float64
DefaultPenalty int
DefenseProgress int
Height float64
HitpointProgress int
InitialDefense int
InitialHitpoints int
InitialSpeed float64
MaximumCount int
MaximumSpeed float64
Regenerate *bool
SpecialtyLikeliness float64
Width float64
YetAgainAmplifier float64
Annihilator struct {
DefenseBoost int
HitpointsBoost int
Penalty int
SizeFactorBoost float64
SpeedModifier float64
} `ini:"Enemy.Annihilator"`
Berserker struct {
DefenseBoost int
HitpointsBoost int
Penalty int
SizeFactorBoost float64
SpeedModifier float64
} `ini:"Enemy.Berserker"`
Behemoth struct {
DefenseBoost int
HitpointsBoost int
Penalty int
SizeFactorBoost float64
SpeedModifier float64
} `ini:"Enemy.Behemoth"`
Bulwark struct {
DefenseBoost int
HitpointsBoost int
Penalty int
SizeFactorBoost float64
SpeedModifier float64
} `ini:"Enemy.Bulwark"`
Colossus struct {
DefenseBoost int
HitpointsBoost int
Penalty int
SizeFactorBoost float64
SpeedModifier float64
} `ini:"Enemy.Colossus"`
Cloaked struct {
Penalty int
SpeedModifier float64
} `ini:"Enemy.Cloaked"`
Dreadnought struct {
DefenseBoost int
HitpointsBoost int
Penalty int
SizeFactorBoost float64
SpeedModifier float64
} `ini:"Enemy.Dreadnought"`
Freezer struct {
Penalty int
} `ini:"Enemy.Freezer"`
Juggernaut struct {
DefenseBoost int
HitpointsBoost int
Penalty int
SizeFactorBoost float64
SpeedModifier float64
} `ini:"Enemy.Juggernaut"`
Leviathan struct {
DefenseBoost int
HitpointsBoost int
Penalty int
SizeFactorBoost float64
SpeedModifier float64
} `ini:"Enemy.Leviathan"`
Overlord struct {
DefenseBoost int
HitpointsBoost int
Penalty int
SizeFactorBoost float64
SpeedModifier float64
} `ini:"Enemy.Overlord"`
}
MessageBox struct {
ChannelBufferSize int
ChannelLogThrottling time.Duration
Messages struct {
AllPlanetsDiscovered TemplateString
EnemyDestroyed TemplateString
EnemyHit TemplateString
ExplainInterface TemplateString
GamePaused TemplateString
GameStarted TemplateString
GameOver TemplateString
Greeting TemplateString
HowToRestart TemplateString
PerformanceDropped TemplateString
PerformanceImproved TemplateString
PlanetDiscovered TemplateString
PlanetImpactsSystem TemplateString
Prompt TemplateString
ScoreBoardUpdated TemplateString
SpaceshipBoosted TemplateString
SpaceshipDowngradedByEnemy TemplateString
SpaceshipFrozen TemplateString
SpaceshipHijacked TemplateString
SpaceshipStillFrozen TemplateString
SpaceshipUpgradedByEnemyKill TemplateString
SpaceshipUpgradedByTank TemplateString
WaitForScoreBoardUpdate TemplateString
} `ini:"MessageBox.Messages"`
}
Planet struct {
DiscoveryCooldown time.Duration
DiscoveryProbability float64
MaximumRadius float64
MinimumRadius float64
SpeedRatio float64
Impact struct {
DefaultGravityStrength float64
Mercury struct {
BerserkLikelinessAmplifier float64
Description TemplateString
} `ini:"Planet.Impact.Mercury"`
Venus struct {
Description TemplateString
SpaceshipDeceleration float64
TankLikelinessAmplifier float64
} `ini:"Planet.Impact.Venus"`
Earth struct {
Description TemplateString
SpaceshipDeceleration float64
TankLikelinessAmplifier float64
} `ini:"Planet.Impact.Earth"`
Mars struct {
BerserkLikelinessAmplifier float64
Description TemplateString
} `ini:"Planet.Impact.Mars"`
Jupiter struct {
Description TemplateString
EnemyDefenseAmplifier int
EnemyHitpointsAmplifier int
} `ini:"Planet.Impact.Jupiter"`
Saturn struct {
Description TemplateString
EnemyDefenseAmplifier int
EnemyHitpointsAmplifier int
} `ini:"Planet.Impact.Saturn"`
Uranus struct {
Description TemplateString
SpecialFoeLikelinessAmplifier float64
} `ini:"Planet.Impact.Uranus"`
Neptune struct {
Description TemplateString
SpecialFoeLikelinessAmplifier float64
} `ini:"Planet.Impact.Neptune"`
Pluto struct {
BerserkLikelinessAmplifier float64
Description TemplateString
SpecialFoeLikelinessAmplifier float64
} `ini:"Planet.Impact.Pluto"`
Sun struct {
Description TemplateString
GravityStrength float64
} `ini:"Planet.Impact.Sun"`
BlackHole struct {
Description TemplateString
GravityStrength float64
ObjectSizeDecayDuration time.Duration
SpaceshipDestroyedReason TemplateString
} `ini:"Planet.Impact.BlackHole"`
Supernova struct {
Description TemplateString
GravityStrength float64
} `ini:"Planet.Impact.Supernova"`
} `ini:"Planet.Impact"`
}
Spaceship struct {
Acceleration float64
AdmiralDamageAmplifier int
BoostDuration time.Duration
BoostScaleSizeFactor float64
CannonProgress int
Cooldown time.Duration
DamageDuration time.Duration
ExperienceScaler float64
FreezeDuration time.Duration
Height float64
HijackDuration time.Duration
MaximumCannons int
MaximumLabelLength int
MaximumSpeed float64
ShieldChargeDuration time.Duration
Width float64
}
Star struct {
Brightness float64
Count int
MinimumInnerRadius float64
MinimumRadius float64
MinimumSpikes float64
MaximumInnerRadius float64
MaximumRadius float64
MaximumSpikes float64
SpeedRatio float64
}
}
// Sanitize sanitizes the configuration.
// It calls the Sanitize method of each field that has one.
// The Sanitize method should have the following signature:
// func (Type) Sanitize() Type
func (cfg *config) sanitize() error {
const methodName = "Sanitize"
var sanitize func(reflect.Value) error
sanitize = func(v reflect.Value) error {
if v.Kind() == reflect.Ptr {
v = v.Elem()
}
if v.Kind() == reflect.Struct {
for i := 0; i < v.NumField(); i++ {
if err := sanitize(v.Field(i)); err != nil {
return err
}
}
}
if !v.CanAddr() {
return fmt.Errorf("cannot take the address of %v", v.Type())
}
method, ok := v.Type().MethodByName(methodName)
if !ok {
return nil
}
if method.Type.NumIn() != 1 || method.Type.NumOut() != 1 || !method.Type.Out(0).AssignableTo(v.Type()) {
return fmt.Errorf("invalid signature for %[1]s method: %[2]v, expected: func (%[3]v) %[1]s() %[3]v",
methodName, method.Type, v.Type())
}
v.Set(v.Addr().MethodByName(methodName).Call(nil)[0])
return nil
}
return sanitize(reflect.ValueOf(cfg).Elem())
}