00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "aa_config.h"
00029 #include <fstream>
00030 #include <iomanip>
00031 #include <iostream>
00032 #include "tConfiguration.h"
00033 #include <stdlib.h>
00034 #include <ctype.h>
00035 #include <string>
00036 #include <sstream>
00037 #include "tString.h"
00038 #include "tToDo.h"
00039 #include "tConsole.h"
00040 #include "tDirectories.h"
00041 #include "tLocale.h"
00042 #include "tRecorder.h"
00043 #include "tCommandLine.h"
00044 #include "tResourceManager.h"
00045 #include "tError.h"
00046
00047 #include <vector>
00048 #include <string.h>
00049
00050 #ifndef WIN32
00051 #include <signal.h>
00052 #endif
00053
00054 bool tConfItemBase::printChange=true;
00055 bool tConfItemBase::printErrors=true;
00056
00057
00060 tCurrentAccessLevel::tCurrentAccessLevel( tAccessLevel newLevel, bool allowElevation )
00061 {
00062
00063 if ( !allowElevation && newLevel < currentLevel_ )
00064 {
00065
00066 st_Breakpoint();
00067 newLevel = currentLevel_;
00068 }
00069
00070 lastLevel_ = currentLevel_;
00071 currentLevel_ = newLevel;
00072 }
00073
00074
00075 tCurrentAccessLevel::tCurrentAccessLevel()
00076 {
00077 lastLevel_ = currentLevel_;
00078 }
00079
00080 tCurrentAccessLevel::~tCurrentAccessLevel()
00081 {
00082 currentLevel_ = lastLevel_;
00083 }
00084
00086 tAccessLevel tCurrentAccessLevel::GetAccessLevel()
00087 {
00088 return currentLevel_;
00089 }
00090
00091
00092 tString tCurrentAccessLevel::GetName( tAccessLevel level )
00093 {
00094 std::ostringstream s;
00095 s << "$config_accesslevel_" << level;
00096 return tString( tOutput( s.str().c_str() ) );
00097 }
00098
00099 tAccessLevel tCurrentAccessLevel::currentLevel_ = tAccessLevel_Owner;
00100
00101 tAccessLevelSetter::tAccessLevelSetter( tConfItemBase & item, tAccessLevel level )
00102 {
00103 item.requiredLevel = level;
00104 }
00105
00106 static std::map< tString, tConfItemBase * > * st_confMap = 0;
00107 tConfItemBase::tConfItemMap & tConfItemBase::ConfItemMap()
00108 {
00109 if (!st_confMap)
00110 st_confMap = tNEW( tConfItemMap );
00111 return *st_confMap;
00112 }
00113
00114 #ifdef KRAWALL_SERVER
00115
00116
00117 class tConfItemLevel: public tConfItemBase
00118 {
00119 public:
00120 tConfItemLevel()
00121 : tConfItemBase( "ACCESS_LEVEL" )
00122 {
00123 requiredLevel = tAccessLevel_Owner;
00124 }
00125
00126 virtual void ReadVal(std::istream &s)
00127 {
00128
00129 tString name;
00130 s >> name;
00131
00132 int levelInt;
00133 s >> levelInt;
00134 tAccessLevel level = static_cast< tAccessLevel >( levelInt );
00135
00136 if ( s.fail() )
00137 {
00138 if(printErrors)
00139 {
00140 con << tOutput( "$access_level_usage" );
00141 }
00142 return;
00143 }
00144
00145
00146 tToUpper( name );
00147
00148
00149 tConfItemMap & confmap = ConfItemMap();
00150 tConfItemMap::iterator iter = confmap.find( name );
00151 if ( iter != confmap.end() )
00152 {
00153
00154 tConfItemBase * ci = (*iter).second;
00155 if ( ci->requiredLevel != level )
00156 {
00157 ci->requiredLevel = level;
00158 if(printChange)
00159 {
00160 con << tOutput( "$access_level_change", name, tCurrentAccessLevel::GetName( level ) );
00161 }
00162 }
00163 }
00164 else if(printErrors)
00165 {
00166 con << tOutput( "$config_command_unknown", name );
00167 }
00168 }
00169
00170 virtual void WriteVal(std::ostream &s)
00171 {
00172 tASSERT(0);
00173 }
00174
00175 virtual bool Writable(){
00176 return false;
00177 }
00178
00179 virtual bool Save(){
00180 return false;
00181 }
00182 };
00183
00184 static tConfItemLevel st_confLevel;
00185
00186 static char const *st_casacl = "CASACL";
00187
00189 class tCasacl: tConfItemBase
00190 {
00191 public:
00192 tCasacl()
00193 : tConfItemBase( st_casacl )
00194 {
00195 requiredLevel = tAccessLevel_Program;
00196 }
00197
00198 virtual void ReadVal( std::istream & s )
00199 {
00200 int required_int = 0, elevated_int = 20;
00201
00202
00203 s >> required_int;
00204 s >> elevated_int;
00205
00206 tAccessLevel elevated = static_cast< tAccessLevel >( elevated_int );
00207 tAccessLevel required = static_cast< tAccessLevel >( required_int );
00208
00209 if ( s.fail() )
00210 {
00211 con << tOutput( "$casacl_usage" );
00212 throw tAbortLoading( st_casacl );
00213 }
00214 else if ( tCurrentAccessLevel::GetAccessLevel() > required )
00215 {
00216 con << tOutput( "$access_level_error",
00217 "SUDO",
00218 tCurrentAccessLevel::GetName( required ),
00219 tCurrentAccessLevel::GetName( tCurrentAccessLevel::GetAccessLevel() )
00220 );
00221 throw tAbortLoading( st_casacl );
00222 }
00223 else
00224 {
00225 tString().ReadLine(s);
00226 tCurrentAccessLevel::currentLevel_ = elevated;
00227 }
00228 }
00229
00230 virtual void WriteVal(std::ostream &s)
00231 {
00232 tASSERT(0);
00233 }
00234
00235 virtual bool Writable(){
00236 return false;
00237 }
00238
00239 virtual bool Save(){
00240 return false;
00241 }
00242 };
00243
00244 static tCasacl st_sudo;
00245
00246 #endif
00247
00248 bool st_FirstUse=true;
00249 static tConfItem<bool> fu("FIRST_USE",st_FirstUse);
00250
00251 tAbortLoading::tAbortLoading( char const * command )
00252 : command_( command )
00253 {
00254 }
00255
00256 tString tAbortLoading::DoGetName() const
00257 {
00258 return tString(tOutput( "$abort_loading_name"));
00259 }
00260
00261 tString tAbortLoading::DoGetDescription() const
00262 {
00263 return tString(tOutput( "$abort_loading_description", command_ ));
00264 }
00265
00266 tConfItemBase::tConfItemBase(const char *t, callbackFunc *cb)
00267 :id(-1),title(t),
00268 changed(false),callback(cb){
00269
00270 tConfItemMap & confmap = ConfItemMap();
00271 if ( confmap.find( title ) != confmap.end() )
00272 tERR_ERROR_INT("Two tConfItems with the same name " << t << "!");
00273
00274
00275 tString helpname;
00276 helpname << title << "_help";
00277 tToLower( helpname );
00278
00279 const_cast<tOutput&>(help).AddLocale(helpname);
00280
00281 confmap[title] = this;
00282
00283 requiredLevel = tAccessLevel_Admin;
00284 }
00285
00286 tConfItemBase::tConfItemBase(const char *t, const tOutput& h, callbackFunc *cb)
00287 :id(-1),title(t), help(h),
00288 changed(false),callback(cb){
00289
00290 tConfItemMap & confmap = ConfItemMap();
00291 if ( confmap.find( title ) != confmap.end() )
00292 tERR_ERROR_INT("Two tConfItems with the same name " << t << "!");
00293
00294 confmap[title] = this;
00295
00296 requiredLevel = tAccessLevel_Admin;
00297 }
00298
00299 tConfItemBase::~tConfItemBase()
00300 {
00301 tConfItemMap & confmap = ConfItemMap();
00302 confmap.erase(title);
00303 if ( confmap.size() == 0 )
00304 {
00305 delete st_confMap;
00306 st_confMap = 0;
00307 }
00308 }
00309
00310 void tConfItemBase::SaveAll(std::ostream &s){
00311 tConfItemMap & confmap = ConfItemMap();
00312 for(tConfItemMap::iterator iter = confmap.begin(); iter != confmap.end() ; ++iter)
00313 {
00314 tConfItemBase * ci = (*iter).second;
00315 if (ci->Save()){
00316 s << std::setw(28) << ci->title << " ";
00317 ci->WriteVal(s);
00318 s << '\n';
00319 }
00320 }
00321 }
00322
00323 int tConfItemBase::EatWhitespace(std::istream &s){
00324 int c=' ';
00325
00326 while(isblank(c) &&
00327 c!='\n' &&
00328 s.good() &&
00329 !s.eof())
00330 c=s.get();
00331
00332 s.putback(c);
00333
00334 return c;
00335 }
00336
00337 void tConfItemBase::LoadLine(std::istream &s){
00338 if(!s.eof() && s.good()){
00339 tString name;
00340 s >> name;
00341
00342
00343 tToUpper( name );
00344
00345 bool found=false;
00346
00347 if (name.Size()==0)
00348 found=true;
00349 else if (name[0]=='#'){
00350 char c=' ';
00351 while(c!='\n' && s.good() && !s.eof()) c=s.get();
00352 found=true;
00353 }
00354
00355 tConfItemMap & confmap = ConfItemMap();
00356 tConfItemMap::iterator iter = confmap.find( name );
00357 if ( iter != confmap.end() )
00358 {
00359 tConfItemBase * ci = (*iter).second;
00360
00361 bool cb=ci->changed;
00362 ci->changed=false;
00363
00364 if ( ci->requiredLevel >= tCurrentAccessLevel::GetAccessLevel() )
00365 {
00366 ci->ReadVal(s);
00367 if (ci->changed)
00368 ci->WasChanged();
00369 else
00370 ci->changed=cb;
00371 }
00372 else
00373 {
00374 tString discard;
00375 discard.ReadLine(s);
00376
00377 con << tOutput( "$access_level_error",
00378 name,
00379 tCurrentAccessLevel::GetName( ci->requiredLevel ),
00380 tCurrentAccessLevel::GetName( tCurrentAccessLevel::GetAccessLevel() )
00381 );
00382 return;
00383 }
00384
00385 found=true;
00386 }
00387
00388 if (!found){
00389
00390 tString rest;
00391 rest.ReadLine( s );
00392 #ifdef MACOSX
00393 printErrors = false;
00394 #endif
00395 if (printErrors)
00396 {
00397 tOutput o;
00398 o.SetTemplateParameter(1, name);
00399 o << "$config_command_unknown";
00400 con << o;
00401
00402 if (printChange)
00403 {
00404 int sim_maxlen=-1;
00405
00406 for(tConfItemMap::iterator iter = confmap.begin(); iter != confmap.end() ; ++iter)
00407 {
00408 tConfItemBase * ci = (*iter).second;
00409 if (strstr(ci->title,name) &&
00410 static_cast<int>(strlen(ci->title)) > sim_maxlen)
00411 sim_maxlen=strlen(ci->title);
00412 }
00413
00414 if (sim_maxlen>0 && printChange ){
00415 int len = name.Len()-1;
00416 int printMax = 1 + 3 * len * len * len;
00417 con << tOutput("$config_command_other");
00418 for(tConfItemMap::iterator iter = confmap.begin(); iter != confmap.end() ; ++iter)
00419 {
00420 tConfItemBase * ci = (*iter).second;
00421 if (strstr(ci->title,name))
00422 {
00423 tString help ( ci->help );
00424 if ( --printMax > 0 )
00425 {
00426 tString mess;
00427 mess << ci->title;
00428 mess.SetPos( sim_maxlen+2, false );
00429 mess << "(";
00430 mess << help;
00431 mess << ")\n";
00432 con << mess;
00433 }
00434 }
00435 }
00436 if (printMax <= 0 )
00437 con << tOutput("$config_command_more");
00438 }
00439 }
00440 else
00441 {
00442 con << '\n';
00443 }
00444 }
00445 }
00446 }
00447
00448
00449 }
00450
00451 static char const * recordingSection = "CONFIG";
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483 static bool s_Veto( tString line_in, std::vector< tString > const & vetos )
00484 {
00485
00486 tToUpper( line_in );
00487
00488
00489 char const * test = line_in;
00490 while( isblank(*test) )
00491 test++;
00492
00493
00494 tString line( test );
00495 if ( line.StartsWith( "LAST_" ) )
00496 line = tString( static_cast< char const * >(line) + 5 );
00497
00498
00499 for ( std::vector< tString >::const_iterator iter = vetos.begin(); iter != vetos.end(); ++iter )
00500 {
00501 tString const & veto = *iter;
00502
00503 if ( line.StartsWith( veto ) )
00504 {
00505 #ifdef DEBUG_X
00506 if ( !line.StartsWith( "INCLUDE" ) && tRecorder::IsRunning() )
00507 {
00508 con << "Veto on config line: " << line << "\n";
00509 }
00510 #endif
00511
00512 return true;
00513 }
00514 }
00515
00516 return false;
00517 }
00518
00519
00520
00521 static std::vector< tString > st_Stringify( char const * vetos[] )
00522 {
00523 std::vector< tString > ret;
00524
00525 char const * * v = vetos;
00526 while ( *v )
00527 {
00528 ret.push_back( tString( *v ) );
00529 ++v;
00530 }
00531
00532 return ret;
00533 }
00534
00535 static bool s_VetoPlayback( tString const & line )
00536 {
00537 static char const * vetos_char[]=
00538 { "USE_DISPLAYLISTS", "CHECK_ERRORS", "ZDEPTH",
00539 "COLORDEPTH", "FULLSCREEN ", "ARMAGETRON_LAST_WINDOWSIZE",
00540 "ARMAGETRON_WINDOWSIZE", "ARMAGETRON_LAST_SCREENMODE",
00541 "ARMAGETRON_SCREENMODE", "CUSTOM_SCREEN", "SOUND",
00542 "PASSWORD", "ADMIN_PASS", "RECORDING_DEBUGLEVEL",
00543 "ZTRICK", "MOUSE_GRAB", "PNG_SCREENSHOT",
00544 "KEEP_WINDOW_ACTIVE", "TEXTURE_MODE", "TEXTURES_HI", "LAG_O_METER", "INFINITY_PLANE",
00545 "SKY_WOBBLE", "LOWER_SKY", "UPPER_SKY", "DITHER", "HIGH_RIM", "FLOOR_DETAIL",
00546 "FLOOR_MIRROR", "SHOW_FPS", "TEXT_OUT", "SMOOTH_SHADING", "ALPHA_BLEND",
00547 "PERSP_CORRECT", "POLY_ANTIALIAS", "LINE_ANTIALIAS", "FAST_FORWARD_MAXSTEP",
00548 "DEBUG_GNUPLOT", "FLOOR_", "MOVIEPACK_", "RIM_WALL_", "INCLUDE", "SINCLUDE",
00549 0 };
00550
00551 static std::vector< tString > vetos = st_Stringify( vetos_char );
00552
00553
00554 return s_Veto( line, vetos );
00555 }
00556
00557
00558
00559 static bool s_VetoRecording( tString const & line )
00560 {
00561 static char const * vetos_char[]=
00562 { "#", "PASSWORD", "ADMIN_PASS", "LOCAL_USER", "LOCAL_TEAM",
00563 0 };
00564
00565 static std::vector< tString > vetos = st_Stringify( vetos_char );
00566
00567
00568 return s_Veto( line, vetos );
00569 }
00570
00571 void tConfItemBase::LoadAll(std::istream &s){
00572 tCurrentAccessLevel levelResetter;
00573
00574 try{
00575
00576 while(!s.eof() && s.good())
00577 {
00578 tString line;
00579
00580
00581 line.ReadLine( s );
00582
00584 while ( line.Size() > 0 && line[line.Size()-1] == '\\' && s.good() && !s.eof() )
00585 {
00586 line = line.SubStr( 0, line.Size()-1 );
00587
00588
00589 if ( line.Size() > 0 && line[line.Size()-1] == '\\' )
00590 {
00591 break;
00592 }
00593
00594 tString rest;
00595 rest.ReadLine( s );
00596 line << rest;
00597 }
00598
00599 if ( line.Len() <= 1 )
00600 continue;
00601
00602
00603 if ( !s_VetoRecording( line ) )
00604 {
00605
00606 static tString instantChat("INSTANT_CHAT_STRING");
00607 if ( line.StartsWith( instantChat ) && strstr( line, "/login" ) )
00608 {
00609 tString newLine = line.SubStr( 0, strstr( line, "/login" ) - (char const *)line );
00610 newLine += "/login NONE";
00611 if ( line[strlen(line)-1] == '\\' )
00612 newLine += '\\';
00613 tRecorder::Record( recordingSection, newLine );
00614 }
00615 else
00616 tRecorder::Record( recordingSection, line );
00617 }
00618
00619
00620
00621
00622
00623 if ( !tRecorder::IsPlayingBack() || s_VetoPlayback( line ) )
00624 {
00625 std::stringstream str(static_cast< char const * >( line ) );
00626 tConfItemBase::LoadLine(str);
00627
00628 }
00629 }
00630 }
00631 catch( tAbortLoading const & e )
00632 {
00633
00634 con << e.GetDescription() << "\n";
00635 }
00636 }
00637
00638 void tConfItemBase::DocAll(std::ostream &s){
00639 tConfItemMap & confmap = ConfItemMap();
00640 for(tConfItemMap::iterator iter = confmap.begin(); iter != confmap.end() ; ++iter)
00641 {
00642 tConfItemBase * ci = (*iter).second;
00643
00644 tString help ( ci->help );
00645 if ( help != "UNDOCUMENTED" )
00646 {
00647 tString line;
00648 line << ci->title;
00649 line.SetPos( 30, false );
00650 line << help;
00651 s << line << '\n';
00652 }
00653 }
00654 }
00655
00656 std::deque<tString> tConfItemBase::GetCommands(){
00657 std::deque<tString> ret;
00658 tConfItemMap & confmap = ConfItemMap();
00659 for(tConfItemMap::iterator iter = confmap.begin(); iter != confmap.end() ; ++iter)
00660 {
00661 tConfItemBase * ci = (*iter).second;
00662
00663 ret.push_back(ci->title.ToLower());
00664 }
00665 return ret;
00666 }
00667 tConfItemBase *tConfItemBase::FindConfigItem(tString const &name) {
00668 tConfItemMap & confmap = ConfItemMap();
00669 tConfItemMap::iterator iter = confmap.find( name.ToUpper() );
00670 if ( iter != confmap.end() ) {
00671 return iter->second;
00672 } else {
00673 return 0;
00674 }
00675 }
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702 bool tConfItemBase::LoadPlayback( bool print )
00703 {
00704 if ( !tRecorder::IsPlayingBack() )
00705 return false;
00706
00707
00708 tString line;
00709 while ( tRecorder::Playback( recordingSection, line ) )
00710 {
00711 tRecorder::Record( recordingSection, line );
00712 if ( !s_VetoPlayback( line ) )
00713 {
00714
00715 if ( print ) con << "Playback input : " << line << '\n';
00716 std::stringstream str(static_cast< char const * >( line ) );
00717 tConfItemBase::LoadLine(str);
00718 }
00719 }
00720
00721 return true;
00722 }
00723
00724 static bool Load( const tPath& path, const char* filename )
00725 {
00726
00727 if ( !filename )
00728 {
00729 return false;
00730 }
00731
00732 std::ifstream s;
00733 if ( path.Open( s, filename ) )
00734 {
00735 tConfItemBase::LoadAll( s );
00736 return true;
00737 }
00738 else
00739 {
00740 return false;
00741 }
00742 }
00743
00744
00745 static bool st_settingsFromRecording = false;
00746
00747 #ifdef DEDICATED
00748 tString extraConfig("NONE");
00749
00750 class tExtraConfigCommandLineAnalyzer: public tCommandLineAnalyzer
00751 {
00752 private:
00753 virtual bool DoAnalyze( tCommandLineParser & parser )
00754 {
00755 return parser.GetOption(extraConfig, "--extraconfig", "-e");
00756 }
00757
00758 virtual void DoHelp( std::ostream & s )
00759 {
00760 s << "-e, --extraconfig : open an extra configuration file after\n"
00761 << " settings_dedicated.cfg\n";
00762 }
00763 };
00764
00765 static tExtraConfigCommandLineAnalyzer s_extraAnalyzer;
00766 #endif
00767
00768
00769
00770
00771 char const * st_userConfigs[] = { "user_3_1.cfg", "user_3_0.cfg", "user.cfg", 0 };
00772
00773 static void st_InstallSigHupHandler();
00774
00775 void st_LoadConfig( bool printChange )
00776 {
00777 st_InstallSigHupHandler();
00778
00779 const tPath& var = tDirectories::Var();
00780 const tPath& config = tDirectories::Config();
00781 const tPath& data = tDirectories::Data();
00782
00783 tConfItemBase::printChange=printChange;
00784 #ifdef DEDICATED
00785 tConfItemBase::printErrors=false;
00786 #endif
00787 {
00788
00789 char const * const * userConfig = st_userConfigs;
00790 while ( *userConfig && !Load( var, *userConfig ) )
00791 userConfig++;
00792 }
00793 tConfItemBase::printErrors=true;
00794
00795 Load( config, "settings.cfg" );
00796 #ifdef DEDICATED
00797 Load( config, "settings_dedicated.cfg" );
00798 if( extraConfig != "NONE" ) Load( config, extraConfig );
00799 #else
00800 if (st_FirstUse)
00801 {
00802 Load( config, "default.cfg" );
00803 }
00804 #endif
00805
00806 Load( data, "moviepack/settings.cfg" );
00807
00808 Load( config, "autoexec.cfg" );
00809 Load( var, "autoexec.cfg" );
00810
00811
00812 tConfItemBase::LoadPlayback();
00813 st_settingsFromRecording = tRecorder::IsPlayingBack();
00814
00815 tConfItemBase::printChange=true;
00816 }
00817
00818 void st_SaveConfig()
00819 {
00820
00821 if ( st_settingsFromRecording )
00822 {
00823 return;
00824 }
00825
00826 std::ofstream s;
00827 if ( tDirectories::Var().Open( s, st_userConfigs[0], std::ios::out, true ) )
00828 {
00829 tConfItemBase::SaveAll(s);
00830 }
00831 else
00832 {
00833 tOutput o("$config_file_write_error");
00834 con << o;
00835 std::cerr << o;
00836 }
00837 }
00838
00839 void st_LoadConfig()
00840 {
00841 st_LoadConfig( false );
00842 }
00843
00844 static void st_DoHandleSigHup()
00845 {
00846 con << tOutput("$config_sighup");
00847 st_SaveConfig();
00848 st_LoadConfig();
00849 }
00850
00851 static void st_HandleSigHup( int signal )
00852 {
00853 st_ToDo_Signal( st_DoHandleSigHup );
00854 }
00855
00856 static void st_InstallSigHupHandler()
00857 {
00858 #ifndef WIN32
00859 static bool installed = false;
00860 if ( !installed )
00861 {
00862 signal( SIGHUP, &st_HandleSigHup );
00863 installed = true;
00864 }
00865 #endif
00866 }
00867
00868 void tConfItemLine::ReadVal(std::istream &s){
00869 tString dummy;
00870 dummy.ReadLine(s, true);
00871 if(strcmp(dummy,*target)){
00872 if (printChange)
00873 {
00874 tColoredString oldval;
00875 oldval << *target << tColoredString::ColorString(1,1,1);
00876 tColoredString newval;
00877 newval << dummy << tColoredString::ColorString(1,1,1);
00878 tOutput o;
00879 o.SetTemplateParameter(1, title);
00880 o.SetTemplateParameter(2, oldval);
00881 o.SetTemplateParameter(3, newval);
00882 o << "$config_value_changed";
00883 con << o;
00884 }
00885 *target=dummy;
00886 changed=true;
00887
00888 ExecuteCallback();
00889 }
00890
00891 *target=dummy;
00892 }
00893
00894
00895 void tConfItemLine::WriteVal(std::ostream &s){
00896 tConfItem<tString>::WriteVal(s);
00897
00898
00899
00900 if ( target->Len() >= 2 &&
00901 target->operator()(target->Len() - 2) == '\\' )
00902 s << "\\";
00903 }
00904
00905 tConfItemFunc::tConfItemFunc
00906 (const char *title, CONF_FUNC *func)
00907 :tConfItemBase(title),f(func){}
00908
00909 tConfItemFunc::~tConfItemFunc(){}
00910
00911 void tConfItemFunc::ReadVal(std::istream &s){(*f)(s);}
00912 void tConfItemFunc::WriteVal(std::ostream &){}
00913
00914 bool tConfItemFunc::Save(){return false;}
00915
00916 void st_Include( tString const & file, bool reportError )
00917 {
00918
00919 if( !tPath::IsValidPath( file ) )
00920 return;
00921
00922 if ( !Load( tDirectories::Var(), file ) )
00923 {
00924 if (!Load( tDirectories::Config(), file ) && reportError )
00925 {
00926 con << tOutput( "$config_include_not_found", file );
00927 }
00928 }
00929 }
00930
00931 static void Include(std::istream& s, bool error )
00932 {
00933 tString file;
00934 s >> file;
00935
00936 st_Include( file, error );
00937 }
00938
00939 static void Include(std::istream& s )
00940 {
00941 Include( s, true );
00942 }
00943
00944 static void SInclude(std::istream& s )
00945 {
00946 Include( s, false );
00947 }
00948
00949 static tConfItemFunc s_Include("INCLUDE", &Include);
00950 static tConfItemFunc s_SInclude("SINCLUDE", &SInclude);
00951
00952
00953 static void st_Dummy(std::istream &s){tString rest; rest.ReadLine(s);}
00954 static tConfItemFunc st_DummyMpHack("MOVIEPACK_HACK",&st_Dummy);
00955
00956 #ifdef DEDICATED
00957
00958 static tConfItemFunc st_Dummy1("ARENA_WALL_SHADOW_NEAR", &st_Dummy);
00959 static tConfItemFunc st_Dummy2("ARENA_WALL_SHADOW_DIST", &st_Dummy);
00960 static tConfItemFunc st_Dummy3("ARENA_WALL_SHADOW_SIDEDIST", &st_Dummy);
00961 static tConfItemFunc st_Dummy4("ARENA_WALL_SHADOW_SIZE", &st_Dummy);
00962 static tConfItemFunc st_Dummy5("BUG_TRANSPARENCY_DEMAND", &st_Dummy);
00963 static tConfItemFunc st_Dummy6("BUG_TRANSPARENCY", &st_Dummy);
00964 static tConfItemFunc st_Dummy7("SHOW_OWN_NAME", &st_Dummy);
00965 static tConfItemFunc st_Dummy8("FADEOUT_NAME_DELAY", &st_Dummy);
00966 static tConfItemFunc st_Dummy9("FLOOR_MIRROR_INT", &st_Dummy);
00967 #endif
00968 #ifndef DEBUG
00969
00970 static tConfItemFunc st_Dummy10("SIMULATE_RECEIVE_PACKET_LOSS", &st_Dummy);
00971 static tConfItemFunc st_Dummy11("SIMULATE_SEND_PACKET_LOSS", &st_Dummy);
00972 #endif
00973