1 /* 2 3 ************************************************************************* 4 5 ArmageTron -- Just another Tron Lightcycle Game in 3D. 6 Copyright (C) 2000 Manuel Moos (manuel@moosnet.de) 7 8 ************************************************************************** 9 10 This program is free software; you can redistribute it and/or 11 modify it under the terms of the GNU General Public License 12 as published by the Free Software Foundation; either version 2 13 of the License, or (at your option) any later version. 14 15 This program is distributed in the hope that it will be useful, 16 but WITHOUT ANY WARRANTY; without even the implied warranty of 17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 GNU General Public License for more details. 19 20 You should have received a copy of the GNU General Public License 21 along with this program; if not, write to the Free Software 22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 23 24 *************************************************************************** 25 26 */ 27 28 #ifndef ArmageTron_CONFIGURATION_H 29 #define ArmageTron_CONFIGURATION_H 30 31 #include "tList.h" 32 #include "tString.h" 33 #include "tLinkedList.h" 34 #include "tException.h" 35 #include "tLocale.h" 36 #include "tConsole.h" 37 #include "tLocale.h" 38 #include <iostream> 39 #include <ctype.h> 40 #include <string> 41 #include <map> 42 43 // Define this to disable compiling the new interface 44 #define NEW_CONFIGURATION_NO_COMPILE 45 46 /*********************************************************************** 47 * The new Configuration interface, currently not completely implemented 48 */ 49 50 #ifndef NEW_CONFIGURATION_NO_COMPILE 51 52 // This class stores a single configuration item 53 class tConfigurationItem { 54 public: 55 // Constructors for each data type supported 56 tConfigurationItem(string newValue); 57 tConfigurationItem(int newValue); 58 tConfigurationItem(double newValue); 59 tConfigurationItem(bool newValue); 60 61 // Sets the source of this directive. Possible values are: 62 // GAME = set during the game 63 // $path = path to the file it came from 64 // DEFAULT = default value, set by the object that registered it 65 void setSource(string source); 66 67 // Sets the destination of this directive. Optional, defaults to "NONE" 68 // Possible values are: 69 // NONE = throw it away when the game shuts down 70 // $path = save it to $path 71 void setDestination(string dest); 72 73 // Setters for each type of data supported 74 void setValue(string newValue); 75 void setValue(int newValue); 76 void setValue(double newValue); 77 void setValue(bool newValue); 78 private: 79 // _value is the authoritative value of the directive 80 string _value; 81 82 string _source; 83 string _destination; 84 85 int _intCache; 86 double _doubleCache; 87 bool _boolCache; 88 } 89 90 // This class is the workhorse configuration class. Use it and only it 91 class tConfiguration { 92 public: 93 // Use this function to get the instance of the configuration object 94 // If it doesn't exist, it will be created 95 static const tConfiguration* GetConfiguration(); 96 97 // Use this function to register your own configuration directive 98 // returns true if it was successful, false if not 99 // should return true even if it didn't register the new directive because 100 // it was already there 101 bool registerDirective(string newDirective, string defValue); 102 103 // Use this function to set a configuration directive from a string 104 bool setDirective(string oldDirective, string newValue); 105 106 // Use this function to set a configuration directive from an int 107 bool setDirective(string oldDirective, int newValue); 108 109 // Use this function to set a configuration directive from a float 110 bool setDirective(string oldDirective, double newValue); 111 112 // Use this function to set a configuration directive from a bool 113 bool setDirective(string oldDirective, bool newValue); 114 115 // Use this function to get a configuration directive as a string 116 const string& getDirective(string oldDirective); 117 118 // Use this function to get a configuration directive as an int 119 const int& getDirectiveI(string oldDirective); 120 121 // Use this function to get a configuration directive as a double 122 const double& getDirectiveF(string oldDirective); 123 124 // Use this function to get a configuration directive as a bool 125 const bool& getDirectiveB(string oldDirective); 126 127 // Use this function to load a file 128 // You *MUST* pass it a complete path from the root directory! 129 // Returns TRUE if it can open the file and load at least some of it 130 // Returns FALSE if complete failure. 131 bool LoadFile(string filename); 132 133 // Use this function to save current configuration to files 134 // Returns TRUE on success, FALSE on failure 135 bool SaveFile(); 136 137 private: 138 static tConfiguration* _instance; 139 140 // This function is used internally to actually set each directive 141 bool _setDirective(string oldDirective, tConfigurationItem& newItem); 142 143 // This function registers basic configuration directives 144 // Create a new configuration directive by going to this function and 145 // putting the appropriate line, then just use it in the game 146 // It registers global defaults, but not object-specific defaults 147 void _registerDefaults(); 148 } 149 150 #endif 151 /* 152 * The old stuff follows 153 ************************************************************************/ 154 155 //! access levels for admin interfaces; lower numeric values are better 156 enum tAccessLevel 157 { 158 tAccessLevel_Owner = 0, // the server owner 159 tAccessLevel_Admin = 1, // one of his admins 160 tAccessLevel_Moderator = 2, // one of the moderators 161 tAccessLevel_3 = 3, // reserved 162 tAccessLevel_4 = 4, // reserved 163 tAccessLevel_Armatrator = 5, // reserved 164 tAccessLevel_6 = 6, // reserved 165 tAccessLevel_TeamLeader = 7, // a team leader 166 tAccessLevel_TeamMember = 8, // a team member 167 tAccessLevel_9 = 9, // reserved 168 tAccessLevel_10 = 10, // reserved 169 tAccessLevel_11 = 11, // reserved 170 tAccessLevel_Local = 12, // user with a local account 171 tAccessLevel_13 = 13, // reserved 172 tAccessLevel_14 = 14, // reserved 173 tAccessLevel_Remote = 15, // user with remote account 174 tAccessLevel_DefaultAuthenticated = 15, // default access level for authenticated users 175 tAccessLevel_FallenFromGrace = 16, // authenticated, but not liked 176 tAccessLevel_Shunned = 17, // authenticated, but disliked 177 tAccessLevel_18 = 18, // reserved 178 tAccessLevel_Authenticated = 19,// any authenticated player 179 tAccessLevel_Program = 20, // a regular player 180 tAccessLevel_21 = 21, // reserved 181 tAccessLevel_22 = 22, // reserved 182 tAccessLevel_23 = 23, // reserved 183 tAccessLevel_24 = 24, // reserved 184 tAccessLevel_25 = 25, // reserved 185 tAccessLevel_Invalid = 255, // completely invalid level 186 tAccessLevel_Default = 20 187 }; 188 189 //! class to temporarily allow/forbid the use of casacl 190 class tCasaclPreventer 191 { 192 public: 193 tCasaclPreventer( bool prevent = true ); 194 ~tCasaclPreventer(); 195 private: 196 bool previous_; //!< previous value of prevention flag 197 }; 198 199 //! class managing the current access level 200 class tCurrentAccessLevel 201 { 202 friend class tCasacl; 203 public: 204 //! for the lifetime of this object, change the user's admit level to the passed one. 205 tCurrentAccessLevel( tAccessLevel newLevel, bool allowElevation = false ); 206 207 //! does not change the access level on construction, but resets it on destruction 208 tCurrentAccessLevel(); 209 ~tCurrentAccessLevel(); 210 211 //! returns the current access level 212 static tAccessLevel GetAccessLevel(); 213 214 //! returns the name of an access level 215 static tString GetName( tAccessLevel level ); 216 private: 217 tCurrentAccessLevel( tCurrentAccessLevel const & ); 218 tCurrentAccessLevel & operator = ( tCurrentAccessLevel const & ); 219 220 tAccessLevel lastLevel_; //!< used to restore the last admin level when the object goes out of scope 221 static tAccessLevel currentLevel_; //!< the current access level 222 }; 223 224 class tConfItemBase 225 { 226 friend class tCheckedPTRBase; 227 friend class tConfItemLevel; 228 friend class tAccessLevelSetter; 229 230 int id; 231 protected: 232 const tString title; 233 const tOutput help; 234 bool changed; 235 236 tAccessLevel requiredLevel; //!< access level required to change this setting 237 tAccessLevel setLevel; //!< access level of the user making the last change to this setting 238 239 typedef std::map< tString, tConfItemBase * > tConfItemMap; 240 static tConfItemMap & ConfItemMap(); 241 242 // static tConfItemBase* s_ConfItemAnchor; 243 //static tConfItemBase* Anchor(){return dynamic_cast<tConfItemBase *>(s_ConfItemAnchor);} 244 public: 245 static bool printChange; //!< if set, setting changes are printed to the console and, if printErrors is set as well, suggestions of typo fixes are given. 246 static bool printErrors; //!< if set, unknown settings are pointed out. 247 248 tConfItemBase(const char *title, const tOutput& help); 249 tConfItemBase(const char *title); 250 virtual ~tConfItemBase(); 251 GetTitle()252 tString const & GetTitle() const { 253 return title; 254 } 255 GetRequiredLevel()256 tAccessLevel GetRequiredLevel() const { return requiredLevel; } GetSetLevel()257 tAccessLevel GetSetLevel() const { return setLevel; } 258 259 static int EatWhitespace(std::istream &s); // eat whitespace from stream; return: first non-whitespace char 260 261 static void SaveAll(std::ostream &s); 262 static void LoadAll(std::istream &s, bool record = false ); //! loads configuration from stream 263 static void LoadAll(std::ifstream &s, bool record = false ); //! loads configuration from file 264 static void LoadLine(std::istream &s); //! loads one configuration line 265 static bool LoadPlayback( bool print = false ); //! loads configuration from playback 266 static void DocAll(std::ostream &s); 267 268 // helper functions for files (use these, they manage recording and playback properly) 269 enum SearchPath 270 { 271 Config = 1, 272 Var = 2, 273 All = 3 274 }; 275 276 static bool OpenFile( std::ifstream & s, tString const & filename, SearchPath path ); //! opens a file stream for configuration reading 277 static void ReadFile( std::ifstream & s ); //! loads configuration from a file 278 279 virtual void ReadVal(std::istream &s)=0; 280 virtual void WriteVal(std::ostream &s)=0; 281 WasChanged()282 virtual void WasChanged(){} // what to do if a read changed the thing 283 Writable()284 virtual bool Writable(){ 285 return true; 286 } 287 Save()288 virtual bool Save(){ 289 return true; 290 } 291 }; 292 293 //! just to do some work in static initializers, to modify default access levels: 294 class tAccessLevelSetter 295 { 296 public: 297 //! modifies the access level of <item> to <level> 298 tAccessLevelSetter( tConfItemBase & item, tAccessLevel level ); 299 }; 300 301 // Arg! Msvc++ could not handle bool IO. Seems to be fine now. 302 #ifdef _MSC_VER_XXX 303 inline std::istream & operator >> (std::istream &s,bool &b){ 304 int x; 305 s >> x; 306 b=(x!=0); 307 return s; 308 } 309 310 inline std::ostream & operator << (std::ostream &s,bool b){ 311 if (b) 312 return s << 1; 313 else 314 return s << 0; 315 } 316 #endif 317 318 //! type modifying class mapping types in memory to types to stream 319 template< class T > struct tTypeToConfig 320 { 321 typedef T TOSTREAM; //!< type to put into the stream 322 typedef int DUMMYREQUIRED; //!< change this type to "int *" to indicate the conversion is required 323 }; 324 325 //! macro declaring that type TYPE should be converted to type STREAM before 326 // recording (and back after playback) by specializing the tTypeToStream class template 327 #define tCONFIG_AS( TYPE, STREAM ) \ 328 template<> struct tTypeToConfig< TYPE > \ 329 { \ 330 typedef STREAM TOSTREAM; \ 331 typedef int * DUMMYREQUIRED; \ 332 } \ 333 334 //! macro for configuration enums: convert them to int. 335 #define tCONFIG_ENUM( TYPE ) tCONFIG_AS( TYPE, int ) 336 337 tCONFIG_ENUM( tAccessLevel ); 338 339 //! exception to be thrown when the current script should be aborted 340 class tAbortLoading: public tException 341 { 342 public: 343 tAbortLoading( char const * command ); 344 private: 345 tString command_; //!< the command responsible for the abort 346 347 virtual tString DoGetName() const; 348 virtual tString DoGetDescription() const; 349 }; 350 351 template<class T> class tConfItem:virtual public tConfItemBase{ 352 public: 353 typedef bool (*ShouldChangeFuncT)(T const &newValue); 354 protected: 355 T *target; 356 ShouldChangeFuncT shouldChangeFunc_; 357 tConfItem(T & t)358 tConfItem(T &t):tConfItemBase(""),target(&t), shouldChangeFunc_(NULL) {} 359 public: tConfItem(const char * title,const tOutput & help,T & t)360 tConfItem(const char *title,const tOutput& help,T& t) 361 :tConfItemBase(title,help),target(&t), shouldChangeFunc_(NULL) {} 362 tConfItem(const char * title,T & t)363 tConfItem(const char *title,T& t) 364 :tConfItemBase(title),target(&t), shouldChangeFunc_(NULL) {} 365 tConfItem(const char * title,T & t,ShouldChangeFuncT changeFunc)366 tConfItem(const char*title, T& t, ShouldChangeFuncT changeFunc) 367 :tConfItemBase(title),target(&t),shouldChangeFunc_(changeFunc) {} 368 ~tConfItem()369 virtual ~tConfItem(){} 370 371 typedef typename tTypeToConfig< T >::DUMMYREQUIRED DUMMYREQUIRED; 372 373 // read without conversion DoRead(std::istream & s,T & value,int)374 static void DoRead(std::istream &s, T & value, int ) 375 { 376 s >> value; 377 } 378 379 // read with conversion DoRead(std::istream & s,T & value,int *)380 static void DoRead(std::istream &s, T & value, int * ) 381 { 382 typename tTypeToConfig< T >::TOSTREAM dummy; 383 s >> dummy; 384 value = static_cast< T >( dummy ); 385 } 386 387 // write without conversion DoWrite(std::ostream & s,T const & value,int)388 static void DoWrite(std::ostream &s, T const & value, int ) 389 { 390 s << value; 391 } 392 393 // write with conversion DoWrite(std::ostream & s,T const & value,int *)394 static void DoWrite(std::ostream &s, T const & value, int * ) 395 { 396 s << static_cast< typename tTypeToConfig< T >::TOSTREAM >( value ); 397 } 398 ReadVal(std::istream & s)399 virtual void ReadVal(std::istream &s){ 400 // eat whitepsace 401 int c= EatWhitespace(s); 402 403 T dummy( *target ); 404 if (c!='\n' && s && !s.eof() && s.good()){ 405 DoRead( s, dummy, DUMMYREQUIRED() ); 406 if (!s.good() && !s.eof() ) 407 { 408 tOutput o; 409 o.SetTemplateParameter(1, title); 410 o << "$config_error_read"; 411 con << o; 412 } 413 else 414 if (dummy!=*target){ 415 if (!Writable()) 416 { 417 tOutput o; 418 o.SetTemplateParameter(1, title); 419 o << "$nconfig_error_protected"; 420 con << ""; 421 } 422 else{ 423 if (!shouldChangeFunc_ || shouldChangeFunc_(dummy)) 424 { 425 if (printChange) 426 { 427 tOutput o; 428 o.SetTemplateParameter(1, title); 429 o.SetTemplateParameter(2, *target); 430 o.SetTemplateParameter(3, dummy); 431 o << "$config_value_changed"; 432 con << o; 433 } 434 435 *target = dummy; 436 changed = true; 437 } 438 } 439 } 440 } 441 else 442 { 443 tOutput o; 444 o.SetTemplateParameter(1, title); 445 o.SetTemplateParameter(2, *target); 446 o << "$config_message_info"; 447 con << o; 448 } 449 450 // read the rest of the line 451 c=' '; 452 while (c!='\n' && s.good() && !s.eof()) c=s.get(); 453 } 454 WriteVal(std::ostream & s)455 virtual void WriteVal(std::ostream &s){ 456 DoWrite( s, *target, DUMMYREQUIRED() ); 457 } 458 }; 459 460 template<class T> class tSettingItem:public tConfItem<T>{ 461 public: 462 // tSettingItem(const char *title,const tOutput& help,T& t) 463 // :tConfItemBase(title,help),tConfItem<T>(t){} 464 tSettingItem(const char * title,T & t)465 tSettingItem(const char *title,T& t) 466 :tConfItemBase(title),tConfItem<T>(title, t){} 467 tSettingItem(const char * title,T & t,typename tConfItem<T>::ShouldChangeFuncT changeFunc)468 tSettingItem(const char *title, T& t, typename tConfItem<T>::ShouldChangeFuncT changeFunc) 469 :tConfItemBase(title), tConfItem<T>(title, t, changeFunc) {} 470 ~tSettingItem()471 virtual ~tSettingItem(){} 472 Save()473 virtual bool Save(){ 474 return false; 475 } 476 }; 477 478 479 class tConfItemLine:public tConfItem<tString>, virtual public tConfItemBase{ 480 public: tConfItemLine(const char * title,const char * help,tString & s)481 tConfItemLine(const char *title,const char *help,tString &s) 482 :tConfItemBase(title,help),tConfItem<tString>(title,help,s){} 483 ~tConfItemLine()484 virtual ~tConfItemLine(){} 485 tConfItemLine(const char * title,tString & s)486 tConfItemLine(const char *title, tString &s) 487 :tConfItemBase(title),tConfItem<tString>(title,s){} 488 489 virtual void ReadVal(std::istream &s); 490 virtual void WriteVal(std::ostream &s); 491 }; 492 493 typedef void CONF_FUNC(std::istream &s); 494 495 class tConfItemFunc:public tConfItemBase{ 496 CONF_FUNC *f; 497 public: 498 tConfItemFunc(const char *title, CONF_FUNC *func); 499 virtual ~tConfItemFunc(); 500 501 virtual void ReadVal(std::istream &s); 502 virtual void WriteVal(std::ostream &s); 503 504 virtual bool Save(); 505 }; 506 507 void st_LoadConfig(); 508 void st_SaveConfig(); 509 510 extern bool st_FirstUse; 511 512 #endif 513 514