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