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 "nConfig.h"
00029 #include "nNetObject.h"
00030 #include "tConsole.h"
00031 #include "tSysTime.h"
00032 #include <set>
00033 #include <string.h>
00034
00035 nConfItemBase::nConfItemBase()
00036 :tConfItemBase(""), lastChangeTime_(-10000), lastChangeMessage_(0), watcher_(0){}
00037
00038
00039
00040
00041 nConfItemBase::nConfItemBase(const char *title)
00042 :tConfItemBase(title), lastChangeTime_(-10000), lastChangeMessage_(0), watcher_(0){}
00043
00044 nConfItemBase::~nConfItemBase(){}
00045
00046 void nConfItemBase::s_GetConfigMessage(nMessage &m){
00047 if (sn_GetNetState()==nSERVER){
00048 nReadError();
00049 }
00050 else{
00051 tString name;
00052 m >> name;
00053
00054
00055
00056 tConfItemMap & confmap = ConfItemMap();
00057 tConfItemMap::iterator iter = confmap.find( name );
00058 if ( iter != confmap.end() )
00059 {
00060 tConfItemBase * item = (*iter).second;
00061 nConfItemBase *netitem = dynamic_cast<nConfItemBase*> (item);
00062 if (netitem)
00063 {
00064
00065 if ( tSysTimeFloat() > netitem->lastChangeTime_ + 100 || sn_Update( netitem->lastChangeMessage_, m.MessageIDBig() ) )
00066 {
00067 netitem->lastChangeMessage_ = m.MessageIDBig();
00068 netitem->lastChangeTime_ = tSysTimeFloat();
00069 netitem->NetReadVal(m);
00070 }
00071 else
00072 {
00073 static bool warn = true;
00074 if ( warn )
00075 con << tOutput( "$nconfig_error_ignoreold", name );
00076 warn = false;
00077 }
00078 }
00079 else
00080 {
00081 static bool warn = true;
00082 if ( warn )
00083 con << tOutput( "$nconfig_error_nonet", name );
00084 warn = false;
00085 }
00086 }
00087 else
00088 {
00089 static bool warn = true;
00090 if ( warn )
00091 con << tOutput( "$nconfig_error_unknown", name );
00092 warn = false;
00093 }
00094 }
00095 }
00096
00097
00098 static nDescriptor transferConfig(60,nConfItemBase::s_GetConfigMessage,
00099 "transfer config");
00100
00101 void nConfItemBase::s_SendConfig(bool force, int peer){
00102 if(sn_GetNetState()==nSERVER){
00103 tConfItemMap & confmap = ConfItemMap();
00104 for(tConfItemMap::iterator iter = confmap.begin(); iter != confmap.end() ; ++iter)
00105 {
00106 tConfItemBase * item = (*iter).second;
00107
00108 nConfItemBase *netitem = dynamic_cast<nConfItemBase*> (item);
00109 if (netitem)
00110 netitem->SendConfig(force, peer);
00111 }
00112 }
00113 }
00114
00115 void nConfItemBase::SendConfig(bool force, int peer){
00116 if ( (changed || force) && sn_GetNetState()==nSERVER)
00117 {
00118
00119 nMessage *m=new nMessage(transferConfig);
00120 *m << title;
00121 NetWriteVal(*m);
00122 if (peer==-1)
00123 {
00124 m->BroadCast();
00125 changed = false;
00126 }
00127 else
00128 m->Send(peer);
00129 }
00130 }
00131
00132 void nConfItemBase::WasChanged( bool nonDefault ){
00133
00134 if (this->watcher_ )
00135 this->watcher_->Change( nonDefault );
00136
00137 SendConfig();
00138 }
00139
00140 bool nConfItemBase::Writable()
00141 {
00142
00143 if ( sn_GetNetState() == nCLIENT )
00144 return false;
00145
00146
00147 if ( !watcher_ )
00148 return true;
00149
00150
00151 return watcher_->Writable();
00152 }
00153
00154
00155
00156
00157
00158
00161
00162
00163 void nConfItemBase::s_RevertToDefaults( void )
00164 {
00165 tConfItemMap & confmap = ConfItemMap();
00166 for(tConfItemMap::iterator iter = confmap.begin(); iter != confmap.end() ; ++iter)
00167 {
00168 tConfItemBase * item = (*iter).second;
00169 nConfItemBase *netitem = dynamic_cast<nConfItemBase*> (item);
00170 if (netitem)
00171 {
00172 netitem->RevertToDefaults();
00173 }
00174 }
00175 }
00176
00177
00178
00179
00180
00181
00184
00185
00186 void nConfItemBase::s_SaveValues( void )
00187 {
00188 tConfItemMap & confmap = ConfItemMap();
00189 for(tConfItemMap::iterator iter = confmap.begin(); iter != confmap.end() ; ++iter)
00190 {
00191 tConfItemBase * item = (*iter).second;
00192 nConfItemBase *netitem = dynamic_cast<nConfItemBase*> (item);
00193 if (netitem)
00194 {
00195 netitem->SaveValue();
00196 }
00197 }
00198 }
00199
00200
00201
00202
00203
00204
00207
00208
00209 void nConfItemBase::s_RevertToSavedValues( void )
00210 {
00211 tConfItemMap & confmap = ConfItemMap();
00212 for(tConfItemMap::iterator iter = confmap.begin(); iter != confmap.end() ; ++iter)
00213 {
00214 tConfItemBase * item = (*iter).second;
00215 nConfItemBase *netitem = dynamic_cast<nConfItemBase*> (item);
00216 if (netitem)
00217 {
00218 netitem->RevertToSavedValue();
00219 }
00220 }
00221 }
00222
00223 nConfItemLine::nConfItemLine(const char *title,tString &s)
00224 :tConfItemBase(title),nConfItem<tString>(s){}
00225
00226 nConfItemLine::nConfItemLine(const char *title,tString &s, callbackFunc *cb)
00227 :tConfItemBase(title, cb),nConfItem<tString>(s){}
00228
00229 nConfItemLine::~nConfItemLine(){}
00230
00231 void nConfItemLine::ReadVal(std::istream & s)
00232 {
00233 tString dummy;
00234 dummy.ReadLine(s,true);
00235 if(strcmp(dummy,*target)){
00236 if (printChange)
00237 {
00238 tOutput o;
00239 o.SetTemplateParameter(1, title);
00240 o.SetTemplateParameter(2, *target);
00241 o.SetTemplateParameter(3, dummy);
00242 o << "$config_value_changed";
00243 con << o;
00244 }
00245 *target=dummy;
00246 changed=true;
00247 ExecuteCallback();
00248 }
00249
00250 *target=dummy;
00251 }
00252
00253
00254
00255
00256
00257
00261
00262
00263 nIConfItemWatcher::nIConfItemWatcher( nConfItemBase & item )
00264 :watched_( item )
00265 {
00266 item.watcher_ = this;
00267 }
00268
00269
00270
00271
00272
00273
00276
00277
00278 nIConfItemWatcher::~nIConfItemWatcher( void )
00279 {
00280 watched_.watcher_ = NULL;
00281 }
00282
00283
00284
00285
00286
00287
00291
00292
00293 void nIConfItemWatcher::OnChange( bool nonDefault )
00294 {
00295 }
00296
00297
00298
00299
00300
00301
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00333
00334
00335
00336
00337
00338
00339
00340 typedef std::set< nConfItemVersionWatcher * > nStrongWatcherList;
00341 static nStrongWatcherList * sn_watchers=0;
00342 static int sn_refcount=0;
00343
00344 static nStrongWatcherList & sn_GetStrongWatchers()
00345 {
00346 if (!sn_watchers)
00347 {
00348 sn_watchers = tNEW(nStrongWatcherList)();
00349 }
00350
00351 return *sn_watchers;
00352 }
00353
00354 void sn_StrongWatchersAddRef()
00355 {
00356 sn_refcount++;
00357 }
00358
00359 void sn_StrongWatchersRelease()
00360 {
00361 if ( --sn_refcount <= 0 )
00362 {
00363 tDESTROY( sn_watchers );
00364 }
00365 }
00366
00367
00368
00369
00370
00371
00376
00377
00378 nConfItemVersionWatcher::nConfItemVersionWatcher( nConfItemBase & item, Group c, int min, int max )
00379 : nIConfItemWatcher( item )
00380 , version_( min, max > 0 ? max : 0x7FFFFFFF )
00381 , nonDefault_( false )
00382 , reverted_( false )
00383 , group_( c )
00384 , overrideGroupBehavior_( Behavior_Default )
00385 , overrideGroupBehaviorConf_( item.GetTitle() + "_OVERRIDE", overrideGroupBehavior_ )
00386 {
00387 sn_StrongWatchersAddRef();
00388 sn_GetStrongWatchers().insert(this);
00389 }
00390
00391
00392
00393
00394
00395
00398
00399
00400 nConfItemVersionWatcher::~nConfItemVersionWatcher( void )
00401 {
00402 sn_GetStrongWatchers().erase(this);
00403 sn_StrongWatchersRelease();
00404 }
00405
00406
00407
00408
00409
00410
00414
00415
00416 void nConfItemVersionWatcher::OnChange( bool nonDefault )
00417 {
00418 bool changed = ( nonDefault != nonDefault_ );
00419
00420 nonDefault_ = nonDefault;
00421 if ( changed )
00422 {
00423 sn_UpdateCurrentVersion();
00424 }
00425 }
00426
00427 static char const * sn_groupName[ nConfItemVersionWatcher::Group_Max ] =
00428 {
00429 "Breaking",
00430 "Bumpy",
00431 "Annoying",
00432 "Cheating",
00433 "Visual"
00434 };
00435
00436
00437 static char const * sn_versionString[] =
00438 {
00439 "0.2.0",
00440 "0.2.0",
00441 "0.2.5.0",
00442 "0.2.6.0",
00443 "0.2.7.1",
00444 "0.2.8_beta1",
00445 "0.2.8_beta1",
00446 "0.2.8_beta2",
00447 "0.2.8_beta3",
00448 "0.2.8_beta4",
00449 "0.2.8.0_rc1",
00450 "0.2.8.0",
00451 "0.2.8_alpha20060414",
00452 "0.2.8.2",
00453 "0.2.8.3_alpha",
00454 "0.2.8.3_alpha_auth",
00455 "0.2.8.3",
00456 "0.2.8.4",
00457 "0.2.8.5_alpha",
00458 "0.2.8.5",
00459 "0.3.1",
00460 0
00461 };
00462
00463 int sn_GetCurrentProtocolVersion()
00464 {
00465 return (sizeof(sn_versionString)/sizeof(char const *)) - 2;
00466 }
00467
00468 static char const * sn_GetVersionString( int version )
00469 {
00470 tVERIFY ( version * sizeof( char * ) < sizeof sn_versionString );
00471 tVERIFY ( version >= 0 );
00472
00473 return sn_versionString[ version ];
00474 }
00475
00476
00477
00478
00479
00480
00484
00485
00486
00487 static nVersion lastVersion = sn_MyVersion();
00488
00489 void nConfItemVersionWatcher::AdaptVersion( nVersion & version )
00490 {
00491 if ( sn_GetNetState() != nSERVER )
00492 return;
00493
00494
00495 nStrongWatcherList & watchers = sn_GetStrongWatchers();
00496 for ( nStrongWatcherList::iterator iter = watchers.begin(); iter != watchers.end(); ++iter )
00497 {
00498 nConfItemVersionWatcher * run = *iter;
00499
00500
00501 if ( run->nonDefault_ && run->GetBehavior() >= Behavior_Block )
00502 {
00503 tVERIFY( version.Merge( version, run->version_ ) );
00504 if ( version.Min() > lastVersion.Min() )
00505 {
00506
00507 tOutput o;
00508 run->FillTemplateParameters(o);
00509 o << "$setting_legacy_clientblock";
00510 con << o;
00511
00512 lastVersion = version;
00513 }
00514 }
00515 }
00516 }
00517
00518
00519
00520
00521
00522
00526
00527
00528 void nConfItemVersionWatcher::OnVersionChange( nVersion const & version )
00529 {
00530
00531 lastVersion = version;
00532
00533 if ( sn_GetNetState() != nSERVER )
00534 return;
00535
00536
00537 nStrongWatcherList & watchers = sn_GetStrongWatchers();
00538 for ( nStrongWatcherList::iterator iter = watchers.begin(); iter != watchers.end(); ++iter )
00539 {
00540 nConfItemVersionWatcher * run = *iter;
00541
00542
00543 Behavior behavior = run->GetBehavior();
00544 if (run->nonDefault_ && behavior != Behavior_Block )
00545 {
00546
00547 static int warnedRevert[ Behavior_Default ][ Group_Max ];
00548 {
00549 static bool inited = false;
00550 if (!inited)
00551 {
00552 inited = true;
00553 for ( int i = Behavior_Default-1; i>=0; --i )
00554 for ( int j = Group_Max-1; j>=0; --j )
00555 warnedRevert[i][j] = sn_MyVersion().Min();
00556 }
00557 }
00558 int & warned = warnedRevert[ behavior ][ run->group_ ];
00559
00560 if ( warned < run->version_.Min() && run->version_.Min() > version.Min() )
00561 {
00562 warned = run->version_.Min();
00563
00564
00565 tOutput o;
00566 run->FillTemplateParameters(o);
00567 o << ( ( behavior == Behavior_Revert ) ? "$setting_legacy_revert" : "$setting_legacy_ignore" );
00568 con << o;
00569 }
00570 }
00571
00572
00573 if ( run->GetBehavior() == Behavior_Nothing )
00574 continue;
00575
00576
00577 if ( run->version_.Min() <= version.Max() )
00578 {
00579
00580 if ( run->reverted_ )
00581 {
00582 run->reverted_ = false;
00583 run->watched_.RevertToSavedValue();
00584 }
00585 }
00586 else
00587 {
00588
00589 if ( !run->reverted_ && run->nonDefault_ )
00590 {
00591 run->reverted_ = true;
00592 run->watched_.SaveValue();
00593 run->watched_.RevertToDefaults();
00594 }
00595 }
00596
00597 }
00598 }
00599
00600 static nConfItemVersionWatcher::Behavior sn_GroupBehaviors[ nConfItemVersionWatcher::Group_Max ] =
00601 {
00602 Behavior_Block,
00603 Behavior_Block,
00604 Behavior_Nothing,
00605 Behavior_Block,
00606 Behavior_Nothing,
00607 };
00608
00609 static tSettingItem< nConfItemVersionWatcher::Behavior > sn_GroupBehaviorBreaks( "SETTING_LEGACY_BEHAVIOR_BREAKING", sn_GroupBehaviors[ nConfItemVersionWatcher::Group_Breaking] );
00610 static tSettingItem< nConfItemVersionWatcher::Behavior > sn_GroupBehaviorBumpy( "SETTING_LEGACY_BEHAVIOR_BUMPY", sn_GroupBehaviors[ nConfItemVersionWatcher::Group_Bumpy] );
00611 static tSettingItem< nConfItemVersionWatcher::Behavior > sn_GroupBehaviorAnnoyance( "SETTING_LEGACY_BEHAVIOR_ANNOYING", sn_GroupBehaviors[ nConfItemVersionWatcher::Group_Annoying] );
00612 static tSettingItem< nConfItemVersionWatcher::Behavior > sn_GroupBehaviorCheat( "SETTING_LEGACY_BEHAVIOR_CHEATING", sn_GroupBehaviors[ nConfItemVersionWatcher::Group_Cheating] );
00613 static tSettingItem< nConfItemVersionWatcher::Behavior > sn_GroupBehaviorDisplay( "SETTING_LEGACY_BEHAVIOR_VISUAL", sn_GroupBehaviors[ nConfItemVersionWatcher::Group_Visual] );
00614
00615
00616
00617
00618
00619
00623
00624
00625 nConfItemVersionWatcher::Behavior nConfItemVersionWatcher::GetBehavior( void ) const
00626 {
00627
00628 tASSERT( 0 <= group_ && group_ < nConfItemVersionWatcher::Group_Max );
00629 Behavior behavior = sn_GroupBehaviors[ group_ ];
00630
00631
00632 if ( Behavior_Default != this->overrideGroupBehavior_ )
00633 behavior = this->overrideGroupBehavior_;
00634
00635 return behavior;
00636 }
00637
00638
00639
00640
00641
00642
00647
00648
00649 nConfItemVersionWatcher const & nConfItemVersionWatcher::GetBehavior( Behavior & behavior ) const
00650 {
00651 behavior = this->GetBehavior();
00652 return *this;
00653 }
00654
00655
00656
00657
00658
00659
00663
00664
00665 bool nConfItemVersionWatcher::DoWritable( void ) const
00666 {
00667
00668 if ( GetBehavior() != Behavior_Revert )
00669 return true;
00670
00671
00672 if ( version_.Min() <= sn_CurrentVersion().Max() )
00673 return true;
00674
00675
00676 tOutput o;
00677 FillTemplateParameters(o);
00678 o << "$setting_legacy_change_blocked";
00679 con << o;
00680
00681
00682 return false;
00683
00684 }
00685
00686
00687
00688
00689
00690
00694
00695
00696 void nConfItemVersionWatcher::FillTemplateParameters( tOutput & o ) const
00697 {
00698 o.SetTemplateParameter(1, watched_.GetTitle() );
00699 o.SetTemplateParameter(2, sn_groupName[group_] );
00700 o.SetTemplateParameter(3, sn_GetVersionString( version_.Min() ) );
00701 }
00702
00703