src/network/nConfig.cpp

Go to the documentation of this file.
00001 /*
00002 
00003 *************************************************************************
00004 
00005 ArmageTron -- Just another Tron Lightcycle Game in 3D.
00006 Copyright (C) 2000  Manuel Moos (manuel@moosnet.de)
00007 
00008 **************************************************************************
00009 
00010 This program is free software; you can redistribute it and/or
00011 modify it under the terms of the GNU General Public License
00012 as published by the Free Software Foundation; either version 2
00013 of the License, or (at your option) any later version.
00014 
00015 This program is distributed in the hope that it will be useful,
00016 but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 GNU General Public License for more details.
00019 
00020 You should have received a copy of the GNU General Public License
00021 along with this program; if not, write to the Free Software
00022 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
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 //nConfItemBase::nConfItemBase(const char *title,const char *help)
00039 //  :tConfItemBase(title, help){}
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(); // never accept config messages from the clients
00049     }
00050     else{
00051         tString name;
00052         m >> name;
00053 
00054         //con << "got conf message for " << name << "\n";
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                 // check if message was new
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         //con << "sending conf message for " << tConfItems(i)->title << "\n";
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     // inform watcher
00134     if (this->watcher_ )
00135         this->watcher_->Change( nonDefault );
00136 
00137     SendConfig();
00138 }
00139 
00140 bool nConfItemBase::Writable()
00141 {
00142     // network settings are read only on the client
00143     if ( sn_GetNetState() == nCLIENT )
00144         return false;
00145 
00146     // on the server, we need to check for a watcher...
00147     if ( !watcher_ )
00148         return true;
00149 
00150     // delegate
00151     return watcher_->Writable();
00152 }
00153 
00154 // *******************************************************************************************
00155 // *
00156 // *    s_RevertToDefaults
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 // *    s_SaveValues
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 // *    s_RevertToSavedValues
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 // *    nIConfItemWatcher
00256 // *
00257 // *******************************************************************************************
00261 // *******************************************************************************************
00262 
00263 nIConfItemWatcher::nIConfItemWatcher( nConfItemBase & item )
00264         :watched_( item )
00265 {
00266     item.watcher_ = this;
00267 }
00268 
00269 // *******************************************************************************************
00270 // *
00271 // *    ~nIConfItemWatcher
00272 // *
00273 // *******************************************************************************************
00276 // *******************************************************************************************
00277 
00278 nIConfItemWatcher::~nIConfItemWatcher( void )
00279 {
00280     watched_.watcher_ = NULL;
00281 }
00282 
00283 // *******************************************************************************************
00284 // *
00285 // *    OnChange
00286 // *
00287 // *******************************************************************************************
00291 // *******************************************************************************************
00292 
00293 void nIConfItemWatcher::OnChange( bool nonDefault )
00294 {
00295 }
00296 
00297 // *******************************************************************************************
00298 // *
00299 // *    nIConfItemWatcher
00300 // *
00301 // *******************************************************************************************
00304 // *******************************************************************************************
00305 
00306 //nIConfItemWatcher::nIConfItemWatcher( void )
00307 //{
00308 //}
00309 
00310 // *******************************************************************************************
00311 // *
00312 // *    nIConfItemWatcher
00313 // *
00314 // *******************************************************************************************
00318 // *******************************************************************************************
00319 
00320 //nIConfItemWatcher::nIConfItemWatcher( nIConfItemWatcher const & other )
00321 //{
00322 //}
00323 
00324 // *******************************************************************************************
00325 // *
00326 // *    operator =
00327 // *
00328 // *******************************************************************************************
00333 // *******************************************************************************************
00334 
00335 //nIConfItemWatcher & nIConfItemWatcher::operator =( nIConfItemWatcher const & other )
00336 //{
00337 //      return *this;
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 // *    nConfItemVersionWatcher
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 // *    ~nConfItemVersionWatcher
00394 // *
00395 // *******************************************************************************************
00398 // *******************************************************************************************
00399 
00400 nConfItemVersionWatcher::~nConfItemVersionWatcher( void )
00401 {
00402     sn_GetStrongWatchers().erase(this);
00403     sn_StrongWatchersRelease();
00404 }
00405 
00406 // *******************************************************************************************
00407 // *
00408 // *    OnChange
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 // mapping network version to program version
00437 static char const * sn_versionString[] =
00438     {
00439         "0.2.0",   // 0
00440         "0.2.0",   // 1
00441         "0.2.5.0", // 2
00442         "0.2.6.0", // 3
00443         "0.2.7.1", // 4
00444         "0.2.8_beta1", // 5
00445         "0.2.8_beta1", // 6
00446         "0.2.8_beta2", // 7
00447         "0.2.8_beta3", // 8
00448         "0.2.8_beta4",   // 9
00449         "0.2.8.0_rc1",     // 10
00450         "0.2.8.0",       // 11
00451         "0.2.8_alpha20060414", // 12
00452         "0.2.8.2", // 13
00453         "0.2.8.3_alpha", // 14
00454         "0.2.8.3_alpha_auth", // 15
00455         "0.2.8.3", // 16
00456         "0.2.8.4", // 17
00457         "0.2.8.5_alpha", // 18
00458         "0.2.8.5", // 19
00459         "0.3.1", // 20
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 // *    AdaptVersion
00479 // *
00480 // *******************************************************************************************
00484 // *******************************************************************************************
00485 
00486 // the last version we warned the user about
00487 static nVersion lastVersion = sn_MyVersion();
00488 
00489 void nConfItemVersionWatcher::AdaptVersion( nVersion & version )
00490 {
00491     if ( sn_GetNetState() != nSERVER )
00492         return;
00493 
00494     // iterate over all watchers
00495     nStrongWatcherList & watchers = sn_GetStrongWatchers();
00496     for ( nStrongWatcherList::iterator iter = watchers.begin(); iter != watchers.end(); ++iter )
00497     {
00498         nConfItemVersionWatcher * run = *iter;
00499 
00500         // adapt version to needs
00501         if ( run->nonDefault_ && run->GetBehavior() >= Behavior_Block )
00502         {
00503             tVERIFY( version.Merge( version, run->version_ ) );
00504             if ( version.Min() > lastVersion.Min() )
00505             {
00506                 // inform user about potential problem
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 // *    OnVersionChange
00521 // *
00522 // *******************************************************************************************
00526 // *******************************************************************************************
00527 
00528 void nConfItemVersionWatcher::OnVersionChange( nVersion const & version )
00529 {
00530     // store version for reference
00531     lastVersion = version;
00532 
00533     if ( sn_GetNetState() != nSERVER )
00534         return;
00535 
00536     // iterate over all watchers
00537     nStrongWatcherList & watchers = sn_GetStrongWatchers();
00538     for ( nStrongWatcherList::iterator iter = watchers.begin(); iter != watchers.end(); ++iter )
00539     {
00540         nConfItemVersionWatcher * run = *iter;
00541 
00542         // warn about settings that will revert or be ignored
00543         Behavior behavior = run->GetBehavior();
00544         if (run->nonDefault_ && behavior != Behavior_Block )
00545         {
00546             // don't warn twice for the same group and behavior
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                 // inform user about potential problem with nondefault settings
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         // ignore settings where this is desired
00573         if ( run->GetBehavior() == Behavior_Nothing )
00574             continue;
00575 
00576         // if version is supported..
00577         if ( run->version_.Min() <= version.Max() )
00578         {
00579             // ...restore saved value of config item
00580             if ( run->reverted_ )
00581             {
00582                 run->reverted_ = false;
00583                 run->watched_.RevertToSavedValue();
00584             }
00585         }
00586         else
00587         {
00588             // version is not supported. Revert to defaults.
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 // *    GetBehavior
00618 // *
00619 // *******************************************************************************************
00623 // *******************************************************************************************
00624 
00625 nConfItemVersionWatcher::Behavior nConfItemVersionWatcher::GetBehavior( void ) const
00626 {
00627     // look up default behavior
00628     tASSERT( 0 <= group_ && group_ < nConfItemVersionWatcher::Group_Max );
00629     Behavior behavior = sn_GroupBehaviors[ group_ ];
00630 
00631     // override it
00632     if ( Behavior_Default != this->overrideGroupBehavior_ )
00633         behavior = this->overrideGroupBehavior_;
00634 
00635     return behavior;
00636 }
00637 
00638 // *******************************************************************************************
00639 // *
00640 // *    GetBehavior
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 // *    DoWritable
00658 // *
00659 // *******************************************************************************************
00663 // *******************************************************************************************
00664 
00665 bool nConfItemVersionWatcher::DoWritable( void ) const
00666 {
00667     // if we're not set to revert, the setting is writable
00668     if ( GetBehavior() != Behavior_Revert )
00669         return true;
00670 
00671     // and if the setting is currently supported by all parites, it's writable too
00672     if ( version_.Min() <= sn_CurrentVersion().Max() )
00673         return true;
00674 
00675     // inform user about impossible change
00676     tOutput o;
00677     FillTemplateParameters(o);
00678     o << "$setting_legacy_change_blocked";
00679     con << o;
00680 
00681     // only if it's not, it needs to be protected.
00682     return false;
00683 
00684 }
00685 
00686 // *******************************************************************************************
00687 // *
00688 // *    FillTemplateParameters
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 

Generated on Sat Mar 15 22:55:49 2008 for Armagetron Advanced by  doxygen 1.5.4