1 /* bzflag
2 * Copyright (c) 1993-2021 Tim Riker
3 *
4 * This package is free software; you can redistribute it and/or
5 * modify it under the terms of the license found in the file
6 * named COPYING that should have accompanied this file.
7 *
8 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
9 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
10 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
11 */
12
13 #ifndef BZF_STATE_DATABASE_H
14 #define BZF_STATE_DATABASE_H
15
16 // common header first
17 #include "common.h"
18
19 // system headers
20 #include <vector>
21 #include <map>
22 #include <iostream>
23 #include <string>
24
25 // implementation headers
26 #include "CallbackList.h"
27 #include "bzfio.h"
28 #include "Singleton.h"
29
30 /** BZDB is the generic name:value pair database within bzflag and bzfs. Its
31 * useful for data that can be serialized to a string that needs to be
32 * accessible to many areas of the code. It also provides facilities for
33 * saving persistant pairs to the config file and downloading variables from
34 * the server.
35 *
36 * BZDB is not an object broker, and isn't meant to be. If you have data
37 * within an object that needs to be accessible from a number of places, but
38 * don't want to pass the object around, you could store that data within BZDB
39 * (if accessed often, such as game variables like gravity, you will need a
40 * cached version anyway to avoid the overhead of lookup). Using BZDB adds
41 * unnecessary overhead if objects generally keep their data hidden without
42 * needing persistant state.
43 *
44 * Basically, if your data can be serialized to a string, and it makes sense
45 * to do so (eg: config file option, game variable downloaded from server), use
46 * BZDB. If you wanted an object broker, use a freakin' global.
47 */
48 class StateDatabase : public Singleton<StateDatabase>
49 {
50 public:
51
52 typedef void (*Callback)(const std::string& name, void* userData);
53 enum Permission
54 {
55 // permission levels
56 ReadWrite,
57 Locked,
58 ReadOnly,
59
60 // access levels
61 User = ReadWrite,
62 Server = Locked,
63 Client = ReadOnly
64 };
65
66 /** set a name/value pair. if access is less than the permission
67 *level of the name then this has no effect.
68 */
69 void set(const std::string& name,
70 const std::string& value,
71 Permission access = Client);
72
73 void setInt(const std::string& name,
74 const int& value,
75 Permission access = Client);
76
77 void setBool(const std::string& name,
78 const bool& value,
79 Permission access = Client);
80
81 void setFloat(const std::string& name,
82 const float& value,
83 Permission access = Client);
84 /** allow setting name/pointer pairs. this allows simple object
85 * pointer storage into the bzdb via pointer address serialization.
86 */
87 void setPointer(const std::string& name,
88 const void *value,
89 Permission access = Client);
90
91 /** unset a name if access is not less than the permission level
92 * of the name.
93 */
94 void unset(const std::string& name,
95 Permission access = Client);
96
97 /** simulate a change to a value (i.e. invoke the callbacks on it)
98 */
99 void touch(const std::string& name,
100 Permission access = Client);
101
102 /** mark a value as persistent (i.e. to be saved) or volatile.
103 * this state is stored independently of the existance of a value
104 * with the given name. that is, adding or removing the name
105 * will not affect persistence of the name. the default is
106 * volatile.
107 */
108 void setPersistent(const std::string& name,
109 bool = true);
110
111 /** set the default value for a name. if the default value is set
112 * then the value will not be written by write() if the current
113 * value is equal to the default value.
114 */
115 void setDefault(const std::string& name,
116 const std::string& value);
117
118 /** set the permission level of a name. like persistence, this is
119 * stored independently of a value with the name. the default
120 * permission is ReadWrite (i.e. full access).
121 */
122 void setPermission(const std::string& name,
123 Permission);
124
125 /** add/remove a callback to/from a name. all callbacks on a name are
126 * invoked when the value changes (either by being set or unset).
127 * each name can have any number of callbacks but any given callback
128 * function/userData pair on a name can only be registered once (i.e.
129 * multiple adds have the same effect as a single add).
130 */
131 void addCallback(const std::string& name,
132 Callback, void* userData);
133 void removeCallback(const std::string& name,
134 Callback, void* userData);
135
136 /** add/remove a global callback for all values. invoked when any value
137 * changes (either by being set or unset). each function/userData pair can
138 * only be registered once (i.e. multiple adds have the same effect as a
139 * single add).
140 */
141 void addGlobalCallback(Callback, void* userData);
142 void removeGlobalCallback(Callback, void* userData);
143
144 /** test if a name is set or not
145 */
146 bool isSet(const std::string& name) const;
147
148 /** get the value associated with a name. returns the empty string
149 * if the name isn't set.
150 */
151 std::string get(const std::string& name) const;
152
153 /** get the INT value associated with a name. Clamp value within range.
154 * Returns 0 (or min) if value is not set.
155 */
156 int getIntClamped(const std::string& name, const int min, const int max) const;
157
158 /** returns the pointer stored with a name. returns NULL if the
159 * name isn't set.
160 */
161 void * getPointer(const std::string& name) const;
162
163 /** get the value as a floating point number. this will evaluate
164 * the string as an expression
165 */
166 float eval(const std::string& name);
167 int evalInt(const std::string& name);
168 bool evalTriplet(const std::string& name, float data[3]);
169 bool evalPair(const std::string& name, float data[2]);
170
171 /** return true if the value associated with a name indicates
172 * logical true, which is when the value is not empty and not
173 * "0" and not "false" and not "no".
174 */
175 bool isTrue(const std::string& name) const;
176
177 /** test if a name is empty or not. a name is empty if it's
178 * not set or it's set to the empty string.
179 */
180 bool isEmpty(const std::string& name) const;
181
182 /** get the persistence, permission, and default for an entry
183 */
184 bool isPersistent(const std::string& name) const;
185 std::string getDefault(const std::string& name) const;
186 Permission getPermission(const std::string& name) const;
187
188 /** invoke the callback for each entry
189 */
190 void iterate(Callback, void* userData) const;
191
192 /** invoke the callback for each entry that should be written (i.e.
193 * is set, persistent, and not the default).
194 */
195 void write(Callback, void* userData) const;
196
197 /** tell the state database whether it should print debug info to stdout
198 * now and then.
199 */
200 void setDebug(bool print);
201
202 /** do we want debug output?
203 */
204 bool getDebug() const;
205
206 // true if we are in a mode where we are seting values that are to be defaults ( config and world time )
207 void setSaveDefault(bool save);
208 bool getSaveDefault() const;
209
210 static const std::string BZDB_AGILITYADVEL;
211 static const std::string BZDB_AGILITYTIMEWINDOW;
212 static const std::string BZDB_AGILITYVELDELTA;
213 static const std::string BZDB_AMBIENTLIGHT;
214 static const std::string BZDB_ANGLETOLERANCE;
215 static const std::string BZDB_ANGULARAD;
216 static const std::string BZDB_AVENUESIZE;
217 static const std::string BZDB_BASESIZE;
218 static const std::string BZDB_BOXBASE;
219 static const std::string BZDB_BOXHEIGHT;
220 static const std::string BZDB_BURROWDEPTH;
221 static const std::string BZDB_BURROWSPEEDAD;
222 static const std::string BZDB_BURROWANGULARAD;
223 static const std::string BZDB_COLDETDEPTH;
224 static const std::string BZDB_COLDETELEMENTS;
225 static const std::string BZDB_COUNTDOWNRESDELAY;
226 static const std::string BZDB_CULLDEPTH;
227 static const std::string BZDB_CULLELEMENTS;
228 static const std::string BZDB_CULLOCCLUDERS;
229 static const std::string BZDB_DISABLEBOTS;
230 static const std::string BZDB_DRAWCELESTIAL;
231 static const std::string BZDB_DRAWCLOUDS;
232 static const std::string BZDB_DRAWGROUND;
233 static const std::string BZDB_DRAWGROUNDLIGHTS;
234 static const std::string BZDB_DRAWMOUNTAINS;
235 static const std::string BZDB_DRAWSKY;
236 static const std::string BZDB_ENDSHOTDETECTION;
237 static const std::string BZDB_EXPLODETIME;
238 static const std::string BZDB_FLAGALTITUDE;
239 static const std::string BZDB_FLAGEFFECTTIME;
240 static const std::string BZDB_FLAGHEIGHT;
241 static const std::string BZDB_FLAGPOLEWIDTH;
242 static const std::string BZDB_FLAGPOLESIZE;
243 static const std::string BZDB_FLAGRADIUS;
244 static const std::string BZDB_FOGMODE;
245 static const std::string BZDB_FOGDENSITY;
246 static const std::string BZDB_FOGSTART;
247 static const std::string BZDB_FOGEND;
248 static const std::string BZDB_FOGCOLOR;
249 static const std::string BZDB_GMACTIVATIONTIME;
250 static const std::string BZDB_GMADLIFE;
251 static const std::string BZDB_GMSIZE;
252 static const std::string BZDB_GMTURNANGLE;
253 static const std::string BZDB_GRAVITY;
254 static const std::string BZDB_FRICTION;
255 static const std::string BZDB_HANDICAPSCOREDIFF;
256 static const std::string BZDB_HANDICAPVELAD;
257 static const std::string BZDB_HANDICAPANGAD;
258 static const std::string BZDB_HANDICAPSHOTAD;
259 static const std::string BZDB_HIDEFLAGSONRADAR;
260 static const std::string BZDB_HIDETEAMFLAGSONRADAR;
261 static const std::string BZDB_IDENTIFYRANGE;
262 static const std::string BZDB_JUMPVELOCITY;
263 static const std::string BZDB_LASERADVEL;
264 static const std::string BZDB_LASERADRATE;
265 static const std::string BZDB_LASERADLIFE;
266 static const std::string BZDB_LATITUDE;
267 static const std::string BZDB_LOCKONANGLE;
268 static const std::string BZDB_TARGETINGANGLE;
269 static const std::string BZDB_TARGETINGDISTANCE;
270 static const std::string BZDB_LONGITUDE;
271 static const std::string BZDB_LRADRATE;
272 static const std::string BZDB_MAXBUMPHEIGHT;
273 static const std::string BZDB_MAXFLAGGRABS;
274 static const std::string BZDB_MAXLOD;
275 static const std::string BZDB_MIRROR;
276 static const std::string BZDB_MOMENTUMLINACC;
277 static const std::string BZDB_MOMENTUMANGACC;
278 static const std::string BZDB_MOMENTUMFRICTION;
279 static const std::string BZDB_MGUNADVEL;
280 static const std::string BZDB_MGUNADRATE;
281 static const std::string BZDB_MGUNADLIFE;
282 static const std::string BZDB_MUZZLEFRONT;
283 static const std::string BZDB_MUZZLEHEIGHT;
284 static const std::string BZDB_NOCLIMB;
285 static const std::string BZDB_NOSHADOWS;
286 static const std::string BZDB_NOSMALLPACKETS;
287 static const std::string BZDB_NOTRESPONDINGTIME;
288 static const std::string BZDB_OBESEFACTOR;
289 static const std::string BZDB_PAUSEDROPTIME;
290 static const std::string BZDB_POSITIONTOLERANCE;
291 static const std::string BZDB_PYRBASE;
292 static const std::string BZDB_PYRHEIGHT;
293 static const std::string BZDB_RADARLIMIT;
294 static const std::string BZDB_REJOINTIME;
295 static const std::string BZDB_RELOADTIME;
296 static const std::string BZDB_RFIREADVEL;
297 static const std::string BZDB_RFIREADRATE;
298 static const std::string BZDB_RFIREADLIFE;
299 static const std::string BZDB_SHIELDFLIGHT;
300 static const std::string BZDB_SHOCKADLIFE;
301 static const std::string BZDB_SHOCKINRADIUS;
302 static const std::string BZDB_SHOCKOUTRADIUS;
303 static const std::string BZDB_SHOTSPEED;
304 static const std::string BZDB_SHOTRADIUS;
305 static const std::string BZDB_SHOTRANGE;
306 static const std::string BZDB_SHOTTAILLENGTH;
307 static const std::string BZDB_SHOTSKEEPVERTICALV;
308 static const std::string BZDB_SQUISHFACTOR;
309 static const std::string BZDB_SQUISHTIME;
310 static const std::string BZDB_SPEEDCHECKSLOGONLY;
311 static const std::string BZDB_SRRADIUSMULT;
312 static const std::string BZDB_SYNCLOCATION;
313 static const std::string BZDB_SYNCTIME;
314 static const std::string BZDB_TANKANGVEL;
315 static const std::string BZDB_TANKEXPLOSIONSIZE;
316 static const std::string BZDB_TANKLENGTH;
317 static const std::string BZDB_TANKWIDTH;
318 static const std::string BZDB_TANKHEIGHT;
319 static const std::string BZDB_TANKSPEED;
320 static const std::string BZDB_TANKRADIUS;
321 static const std::string BZDB_TELEBREADTH;
322 static const std::string BZDB_TELEHEIGHT;
323 static const std::string BZDB_TELEPORTTIME;
324 static const std::string BZDB_TELEWIDTH;
325 static const std::string BZDB_THIEFVELAD;
326 static const std::string BZDB_THIEFTINYFACTOR;
327 static const std::string BZDB_THIEFADSHOTVEL;
328 static const std::string BZDB_THIEFADRATE;
329 static const std::string BZDB_THIEFADLIFE;
330 static const std::string BZDB_THIEFDROPTIME;
331 static const std::string BZDB_TINYFACTOR;
332 static const std::string BZDB_TRACKFADE;
333 static const std::string BZDB_UPDATETHROTTLERATE;
334 static const std::string BZDB_VELOCITYAD;
335 static const std::string BZDB_WALLHEIGHT;
336 static const std::string BZDB_WEAPONS;
337 static const std::string BZDB_WIDEANGLEANG;
338 static const std::string BZDB_WINGSGRAVITY;
339 static const std::string BZDB_WINGSJUMPCOUNT;
340 static const std::string BZDB_WINGSJUMPVELOCITY;
341 static const std::string BZDB_WINGSSLIDETIME;
342 static const std::string BZDB_WORLDSIZE;
343
344
345 protected:
346 friend class Singleton<StateDatabase>;
347
348 private:
349
350 StateDatabase();
351 ~StateDatabase();
352
353 static bool onCallback(Callback, void* userData,
354 void* iterateData);
355
356 struct Item
357 {
358 public:
359 Item();
360
361 public:
362 std::string value;
363 std::string defValue;
364 bool isSet;
365 bool isTrue;
366 bool save;
367 Permission permission;
368 CallbackList<Callback> callbacks;
369 };
370 typedef std::map<std::string, Item> Map;
371
372 Map::iterator lookup(const std::string&);
373 void notify(Map::iterator);
374
375 private:
376 Map items;
377
378 public:
379 class ExpressionToken
380 {
381 public:
382 enum Type { Oper, Number, Variable };
383 enum Operator { add, subtract, multiply, divide, power, lparen, rparen, none };
384 struct Contents
385 {
386 public:
387 double number;
388 std::string variable;
389 Operator oper;
390 };
391
392 ExpressionToken();
393 ExpressionToken(Type _tokenType);
394 ExpressionToken(Type _tokenType, Contents _tokenContents);
395
396 void setType(Type _tokenType);
397 void setContents(Contents _tokenContents);
398 void setNumber(double number);
399 void setVariable(std::string variable);
400 void setOper(Operator oper);
401
402 Type getTokenType() const;
403 Contents getTokenContents() const;
404 double getNumber() const;
405 std::string getVariable() const;
406 Operator getOperator() const;
407
408 int getPrecedence() const;
409
410 private:
411 Type tokenType;
412 Contents tokenContents;
413 };
414
415 typedef std::vector<ExpressionToken> Expression;
416
417 private:
418 static Expression infixToPrefix(const Expression &infix);
419 float evaluate(Expression e) const;
420 typedef std::map<std::string,float> EvalMap;
421 EvalMap evalCache;
422 bool debug;
423 bool saveDefault;
424 CallbackList<Callback> globalCallbacks;
425 };
426
getDebug()427 inline bool StateDatabase::getDebug() const
428 {
429 return debug;
430 }
431
getSaveDefault()432 inline bool StateDatabase::getSaveDefault() const
433 {
434 return saveDefault;
435 }
436
437
438 std::istream& operator>>(std::istream& src, StateDatabase::Expression& dst);
439 std::string& operator>>(std::string& src, StateDatabase::Expression& dst);
440 std::ostream& operator<<(std::ostream& dst, const StateDatabase::Expression& src);
441
442 #define BZDB (StateDatabase::instance())
443
444
445 #endif // BZF_STATE_DATABASE_H
446
447 // Local Variables: ***
448 // mode: C++ ***
449 // tab-width: 4 ***
450 // c-basic-offset: 4 ***
451 // indent-tabs-mode: nil ***
452 // End: ***
453 // ex: shiftwidth=4 tabstop=4
454