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 "gServerBrowser.h"
00029 #include "gGame.h"
00030 #include "gLogo.h"
00031 #include "gServerFavorites.h"
00032 #include "gFriends.h"
00033
00034 #include "nServerInfo.h"
00035 #include "nNetwork.h"
00036
00037 #include "rSysdep.h"
00038 #include "rScreen.h"
00039 #include "rConsole.h"
00040 #include "rRender.h"
00041
00042 #include "uMenu.h"
00043
00044 #include "tMemManager.h"
00045 #include "tSysTime.h"
00046 #include "tToDo.h"
00047
00048 #include "tDirectories.h"
00049 #include "tConfiguration.h"
00050
00051 int gServerBrowser::lowPort = 4534;
00052
00053 int gServerBrowser::highPort = 4540;
00054 static bool continuePoll = false;
00055 static int sg_simultaneous = 5;
00056 static tSettingItem< int > sg_simultaneousConf( "BROWSER_QUERIES_SIMULTANEOUS", sg_simultaneous );
00057
00058 static tOutput *sg_StartHelpText = NULL;
00059
00060 nServerInfo::QueryType sg_queryType = nServerInfo::QUERY_OPTOUT;
00061 tCONFIG_ENUM( nServerInfo::QueryType );
00062 static tSettingItem< nServerInfo::QueryType > sg_query_type( "BROWSER_QUERY_FILTER", sg_queryType );
00063
00064 class gServerMenuItem;
00065
00066
00067 class gServerInfo: public nServerInfo
00068 {
00069 public:
00070 gServerMenuItem *menuItem;
00071 bool show;
00072
00073 gServerInfo():menuItem(NULL), show(true)
00074 {
00075 };
00076
00077 virtual ~gServerInfo();
00078
00079
00080 static gServerInfo * GetFirstServer()
00081 {
00082 return dynamic_cast< gServerInfo * >( nServerInfo::GetFirstServer() );
00083 }
00084
00085 gServerInfo * Next()
00086 {
00087 return dynamic_cast< gServerInfo * >( nServerInfo::Next() );
00088 }
00089 };
00090
00091 nServerInfo* CreateGServer()
00092 {
00093 nServerInfo *ret = tNEW(gServerInfo);
00094
00095
00096
00097
00098
00099
00100
00101 return ret;
00102 }
00103
00104
00105 class gServerMenu: public uMenu
00106 {
00107 int sortKey_;
00108
00109 public:
00110 virtual void OnRender();
00111
00112 void Update();
00113 gServerMenu(const char *title);
00114 ~gServerMenu();
00115
00116 virtual void HandleEvent( SDL_Event event );
00117
00118 void Render(REAL y,
00119 const tString &servername, const tOutput &score,
00120 const tOutput &users , const tOutput &ping);
00121
00122 void Render(REAL y,
00123 const tString &servername, const tString &score,
00124 const tString &users , const tString &ping);
00125 };
00126
00127
00128 class gBrowserMenuItem: public uMenuItem
00129 {
00130 protected:
00131 gBrowserMenuItem(uMenu *M,const tOutput &help): uMenuItem( M, help )
00132 {
00133 }
00134
00135
00136 virtual bool Event( SDL_Event& event );
00137
00138 virtual void RenderBackground();
00139 };
00140
00141 class gServerMenuItem: public gBrowserMenuItem
00142 {
00143 protected:
00144 gServerInfo *server;
00145 double lastPing_;
00146 bool favorite_;
00147 public:
00148 void AddFavorite();
00149 void SetServer(nServerInfo *s);
00150 gServerInfo *GetServer();
00151
00152 virtual void Render(REAL x,REAL y,REAL alpha=1, bool selected=0);
00153 virtual void RenderBackground();
00154
00155 virtual void Enter();
00156
00157
00158 virtual bool Event( SDL_Event& event );
00159
00160 gServerMenuItem(gServerMenu *men);
00161 virtual ~gServerMenuItem();
00162 };
00163
00164 class gServerStartMenuItem: public gBrowserMenuItem
00165 {
00166 public:
00167 virtual void Render(REAL x,REAL y,REAL alpha=1, bool selected=0);
00168
00169 virtual void Enter();
00170
00171 gServerStartMenuItem(gServerMenu *men);
00172 virtual ~gServerStartMenuItem();
00173 };
00174
00175
00176
00177
00178
00179
00180 static bool sg_RequestLANcontinuously = false;
00181
00182 void gServerBrowser::BrowseMaster()
00183 {
00184 BrowseSpecialMaster(0,"");
00185 }
00186
00187
00188 static nServerInfoBase * sg_currentMaster = 0;
00189 nServerInfoBase * gServerBrowser::CurrentMaster()
00190 {
00191 return sg_currentMaster;
00192 }
00193
00194
00195 void gServerBrowser::BrowseSpecialMaster( nServerInfoBase * master, char const * prefix )
00196 {
00197 sg_currentMaster = master;
00198
00199 sg_RequestLANcontinuously = false;
00200
00201 sn_ServerInfoCreator *cback = nServerInfo::SetCreator(&CreateGServer);
00202
00203 sr_con.autoDisplayAtNewline=true;
00204 sr_con.fullscreen=true;
00205
00206 #ifndef DEDICATED
00207 rSysDep::SwapGL();
00208 rSysDep::ClearGL();
00209 rSysDep::SwapGL();
00210 rSysDep::ClearGL();
00211 #endif
00212
00213 bool to=sr_textOut;
00214 sr_textOut=true;
00215
00216 nServerInfo::DeleteAll();
00217 nServerInfo::GetFromMaster( master, prefix );
00218 nServerInfo::Save();
00219
00220
00221
00222
00223 sr_textOut = to;
00224
00225 tOutput StartHelpTextInternet("$network_master_host_inet_help");
00226 sg_StartHelpText = &StartHelpTextInternet;
00227 sg_TalkToMaster = true;
00228
00229 BrowseServers();
00230
00231 nServerInfo::Save();
00232
00233 sg_TalkToMaster = false;
00234
00235 nServerInfo::SetCreator(cback);
00236
00237 sg_currentMaster = master;
00238 }
00239
00240 void gServerBrowser::BrowseLAN()
00241 {
00242
00243 sg_RequestLANcontinuously = true;
00244
00245
00246 sn_ServerInfoCreator *cback = nServerInfo::SetCreator(&CreateGServer);
00247
00248 sr_con.autoDisplayAtNewline=true;
00249 sr_con.fullscreen=true;
00250
00251 #ifndef DEDICATED
00252 rSysDep::SwapGL();
00253 rSysDep::ClearGL();
00254 rSysDep::SwapGL();
00255 rSysDep::ClearGL();
00256 #endif
00257
00258 bool to=sr_textOut;
00259 sr_textOut=true;
00260
00261 nServerInfo::DeleteAll();
00262 nServerInfo::GetFromLAN(lowPort, highPort);
00263
00264 sr_textOut = to;
00265
00266 tOutput StartHelpTextLAN("$network_master_host_lan_help");
00267 sg_StartHelpText = &StartHelpTextLAN;
00268 sg_TalkToMaster = false;
00269
00270 BrowseServers();
00271
00272 nServerInfo::SetCreator(cback);
00273 }
00274
00275 void gServerBrowser::BrowseServers()
00276 {
00277
00278
00279 nServerInfo::StartQueryAll( sg_queryType );
00280 continuePoll = true;
00281
00282 gServerMenu browser("Server Browser");
00283
00284 gServerStartMenuItem start(&browser);
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294 browser.Update();
00295 browser.Enter();
00296
00297 nServerInfo::GetFromLANContinuouslyStop();
00298
00299
00300
00301
00302 }
00303
00304
00305
00306
00307
00308 void gServerMenu::HandleEvent( SDL_Event event )
00309 {
00310 #ifndef DEDICATED
00311 switch (event.type)
00312 {
00313 case SDL_KEYDOWN:
00314 switch (event.key.keysym.sym)
00315 {
00316 case(SDLK_LEFT):
00317 sortKey_ = ( sortKey_ + nServerInfo::KEY_MAX-1 ) % nServerInfo::KEY_MAX;
00318 Update();
00319 return;
00320 break;
00321 case(SDLK_RIGHT):
00322 sortKey_ = ( sortKey_ + 1 ) % nServerInfo::KEY_MAX;
00323 Update();
00324 return;
00325 break;
00326 case(SDLK_m):
00327 FriendsToggle();
00328 Update();
00329 return;
00330 break;
00331 default:
00332 break;
00333 }
00334 }
00335 #endif
00336
00337 uMenu::HandleEvent( event );
00338 }
00339
00340 void gServerMenu::OnRender()
00341 {
00342 uMenu::OnRender();
00343
00344
00345 static double sg_serverMenuRefreshTimeout=-1E+32f;
00346
00347 if (sg_serverMenuRefreshTimeout < tSysTimeFloat())
00348 {
00349 Update();
00350 sg_serverMenuRefreshTimeout = tSysTimeFloat()+2.0f;
00351 }
00352 }
00353
00354 void gServerMenu::Update()
00355 {
00356
00357 gServerMenuItem *item = NULL;
00358 if ( selected < items.Len() )
00359 {
00360 item = dynamic_cast<gServerMenuItem*>(items(selected));
00361 }
00362 gServerInfo* info = NULL;
00363 if ( item )
00364 {
00365 info = item->GetServer();
00366 }
00367
00368
00369 int selectedFromTop = items.Len() - selected;
00370
00371 ReverseItems();
00372
00373 nServerInfo::CalcScoreAll();
00374 nServerInfo::Sort( nServerInfo::PrimaryKey( sortKey_ ) );
00375
00376 int mi = 1;
00377 gServerInfo *run = gServerInfo::GetFirstServer();
00378 bool oneFound = false;
00379 while (run)
00380 {
00381
00382 if (getFriendsEnabled())
00383 {
00384 run->show = false;
00385 int i;
00386 tString userNames = run->UserNames();
00387 tString* friends = getFriends();
00388 for (i = MAX_FRIENDS; i>=0; i--)
00389 {
00390 if (run->Users() > 0 && friends[i].Len() > 1 && userNames.StrPos(friends[i]) >= 0)
00391 {
00392 oneFound = true;
00393 run->show = true;
00394 }
00395 }
00396 }
00397 run = run->Next();
00398 }
00399
00400 run = gServerInfo::GetFirstServer();
00401 {
00402 while (run)
00403 {
00404 if (run->show || oneFound == false)
00405 {
00406 if (mi >= items.Len())
00407 tNEW(gServerMenuItem)(this);
00408
00409 gServerMenuItem *item = dynamic_cast<gServerMenuItem*>(items(mi));
00410 item->SetServer(run);
00411 mi++;
00412 }
00413 run = run->Next();
00414 }
00415 }
00416
00417 if (items.Len() == 1)
00418 selected = 1;
00419
00420 while(mi < items.Len() && items.Len() > 2)
00421 {
00422 uMenuItem *it = items(items.Len()-1);
00423 delete it;
00424 }
00425
00426 ReverseItems();
00427
00428
00429 selected = items.Len() - selectedFromTop;
00430
00431
00432 if ( info && info->menuItem )
00433 {
00434 selected = info->menuItem->GetID();
00435 }
00436
00437 if (sg_RequestLANcontinuously)
00438 {
00439 static REAL timeout=-1E+32f;
00440
00441 if (timeout < tSysTimeFloat())
00442 {
00443 nServerInfo::GetFromLANContinuously();
00444 if (!continuePoll)
00445 {
00446 nServerInfo::StartQueryAll( sg_queryType );
00447 continuePoll = true;
00448 }
00449 timeout = tSysTimeFloat()+10;
00450 }
00451 }
00452 }
00453
00454 gServerMenu::gServerMenu(const char *title)
00455 : uMenu(title, false)
00456 , sortKey_( nServerInfo::KEY_SCORE )
00457 {
00458 nServerInfo *run = nServerInfo::GetFirstServer();
00459 while (run)
00460 {
00461 gServerMenuItem *item = tNEW(gServerMenuItem)(this);
00462 item->SetServer(run);
00463 run = run->Next();
00464 }
00465
00466 ReverseItems();
00467
00468 if (items.Len() <= 0)
00469 {
00470 selected = 1;
00471 tNEW(gServerMenuItem)(this);
00472 }
00473 else
00474 selected = items.Len();
00475 }
00476
00477 gServerMenu::~gServerMenu()
00478 {
00479 for (int i=items.Len()-1; i>=0; i--)
00480 delete items(i);
00481 }
00482
00483 #ifndef DEDICATED
00484 static REAL text_height=.05;
00485
00486 static REAL shrink = .6f;
00487 static REAL displace = .15;
00488
00489 void gServerMenu::Render(REAL y,
00490 const tString &servername, const tString &score,
00491 const tString &users , const tString &ping)
00492 {
00493 if (sr_glOut)
00494 {
00495 DisplayText(-.9f, y, text_height, servername.c_str(), sr_fontServerBrowser, -1);
00496 DisplayText(.6f, y, text_height, ping.c_str(), sr_fontServerBrowser, 1);
00497 DisplayText(.75f, y, text_height, users.c_str(), sr_fontServerBrowser, 1);
00498 DisplayText(.9f, y, text_height, score.c_str(), sr_fontServerBrowser, 1);
00499 }
00500 }
00501
00502 void gServerMenu::Render(REAL y,
00503 const tString &servername, const tOutput &score,
00504 const tOutput &users , const tOutput &ping)
00505 {
00506 tColoredString highlight, normal;
00507 highlight << tColoredString::ColorString( 1,.7,.7 );
00508 normal << tColoredString::ColorString( .7,.3,.3 );
00509
00510 tString sn, s, u, p;
00511
00512 sn << normal;
00513 s << normal;
00514 u << normal;
00515 p << normal;
00516
00517 switch ( sortKey_ )
00518 {
00519 case nServerInfo::KEY_NAME:
00520 sn = highlight;
00521 break;
00522 case nServerInfo::KEY_PING:
00523 p = highlight;
00524 break;
00525 case nServerInfo::KEY_USERS:
00526 u = highlight;
00527 break;
00528 case nServerInfo::KEY_SCORE:
00529 s = highlight;
00530 break;
00531 case nServerInfo::KEY_MAX:
00532 break;
00533 }
00534
00535 sn << servername;
00536 s << score;
00537 u << users;
00538 p << ping;
00539
00540 Render(y, sn, s, u, p);
00541 }
00542
00543 #endif
00544 static bool sg_filterServernameColorStrings = true;
00545 static tSettingItem< bool > removeServerNameColors("FILTER_COLOR_SERVER_NAMES", sg_filterServernameColorStrings);
00546
00547 void gServerMenuItem::Render(REAL x,REAL y,REAL alpha, bool selected)
00548 {
00549 #ifndef DEDICATED
00550
00551
00552 SetColor( selected, alpha );
00553
00554 gServerMenu *serverMenu = static_cast<gServerMenu*>(menu);
00555
00556 if (server)
00557 {
00558 tColoredString name;
00559 tString score;
00560 tString users;
00561 tString ping;
00562
00563 int p = static_cast<int>(server->Ping()*1000);
00564 if (p < 0)
00565 p = 0;
00566 if (p > 10000)
00567 p = 10000;
00568
00569 int s = static_cast<int>(server->Score());
00570 if (server->Score() > 10000)
00571 s = 10000;
00572 if (server->Score() < -10000)
00573 s = -10000;
00574
00575 if (server->Polling())
00576 {
00577 score << tOutput("$network_master_polling");
00578 }
00579 else if (!server->Reachable())
00580 {
00581 score << tOutput("$network_master_unreachable");
00582 }
00583 else if ( nServerInfo::Compat_Ok != server->Compatibility() )
00584 {
00585 switch( server->Compatibility() )
00586 {
00587 case nServerInfo::Compat_Upgrade:
00588 score << tOutput( "$network_master_upgrage" );
00589 break;
00590 case nServerInfo::Compat_Downgrade:
00591 score << tOutput( "$network_master_downgrage" );
00592 break;
00593 default:
00594 score << tOutput( "$network_master_incompatible" );
00595 break;
00596 }
00597 }
00598 else if ( server->Users() >= server->MaxUsers() )
00599 {
00600 score << tOutput( "$network_master_full" );
00601 score << " (" << server->Users() << "/" << server->MaxUsers() << ")";
00602 }
00603 else
00604 {
00605 if ( favorite_ )
00606 {
00607 score << "B ";
00608 }
00609
00610 score << s;
00611 users << server->Users() << "/" << server->MaxUsers();
00612 ping << p;
00613 }
00614
00615 if ( sg_filterServernameColorStrings )
00616 name << tColoredString::RemoveColors( server->GetName() );
00617 else
00618 {
00619 name << server->GetName();
00620 }
00621
00622 serverMenu->Render(y*shrink + displace,
00623 name,
00624 score, users, ping);
00625 }
00626 else
00627 {
00628 tOutput o("$network_master_noserver");
00629 tString s;
00630 s << o;
00631 serverMenu->Render(y*shrink + displace,
00632 s,
00633 tString(""), tString(""), tString(""));
00634
00635 }
00636 #endif
00637 }
00638
00639
00640 void gServerMenuItem::RenderBackground()
00641 {
00642 #ifndef DEDICATED
00643 gBrowserMenuItem::RenderBackground();
00644
00645 if ( server )
00646 {
00647 rTextField::SetDefaultColor( tColor(1,1,1) );
00648
00649 rTextField players( -.9, -.3, text_height, sr_fontServerDetails );
00650 players.EnableLineWrap();
00651 players << tOutput( "$network_master_players" );
00652 if ( server->UserNamesOneLine().Len() > 2 )
00653 players << server->UserNamesOneLine();
00654 else
00655 players << tOutput( "$network_master_players_empty" );
00656 players << "\n" << tColoredString::ColorString(1,1,1);
00657 tColoredString uri;
00658 uri << server->Url() << tColoredString::ColorString(1,1,1);
00659 players << tOutput( "$network_master_serverinfo", server->Release(), uri, server->Options() );
00660 }
00661 #endif
00662 }
00663
00664 #ifndef DEDICATED
00665 static void Refresh()
00666 {
00667 continuePoll = true;
00668 nServerInfo::StartQueryAll( sg_queryType );
00669 }
00670 #endif
00671
00672 bool gBrowserMenuItem::Event( SDL_Event& event )
00673 {
00674 #ifndef DEDICATED
00675 switch (event.type)
00676 {
00677 case SDL_KEYDOWN:
00678 switch (event.key.keysym.sym)
00679 {
00680 case SDLK_r:
00681 {
00682 static double lastRefresh = - 100;
00683 if ( tSysTimeFloat() - lastRefresh > 2.0 )
00684 {
00685 lastRefresh = tSysTimeFloat();
00686
00687 st_ToDo( Refresh );
00688 return true;
00689 }
00690 }
00691 break;
00692 default:
00693 break;
00694 }
00695 }
00696 #endif
00697
00698 return uMenuItem::Event( event );
00699 }
00700
00701
00702 bool gServerMenuItem::Event( SDL_Event& event )
00703 {
00704 #ifndef DEDICATED
00705 switch (event.type)
00706 {
00707 case SDL_KEYDOWN:
00708 switch (event.key.keysym.sym)
00709 {
00710 case SDLK_p:
00711 continuePoll = true;
00712 if ( server && tSysTimeFloat() - lastPing_ > .5f )
00713 {
00714 lastPing_ = tSysTimeFloat();
00715
00716 server->SetQueryType( nServerInfo::QUERY_ALL );
00717 server->QueryServer();
00718 server->ClearInfoFlags();
00719 }
00720 return true;
00721 break;
00722 default:
00723 break;
00724 }
00725 switch (event.key.keysym.unicode)
00726 {
00727 case '+':
00728 if ( server )
00729 {
00730 server->SetScoreBias( server->GetScoreBias() + 10 );
00731 server->CalcScore();
00732 }
00733 (static_cast<gServerMenu*>(menu))->Update();
00734
00735 return true;
00736 break;
00737 case '-':
00738 if ( server )
00739 {
00740 server->SetScoreBias( server->GetScoreBias() - 10 );
00741 server->CalcScore();
00742 }
00743 (static_cast<gServerMenu*>(menu))->Update();
00744
00745 return true;
00746 break;
00747 case 'b':
00748 if ( server && !favorite_ )
00749 {
00750 favorite_ = gServerFavorites::AddFavorite( server );
00751 }
00752 return true;
00753 break;
00754 default:
00755 break;
00756 }
00757 }
00758 #endif
00759
00760 return gBrowserMenuItem::Event( event );
00761 }
00762
00763 void gBrowserMenuItem::RenderBackground()
00764 {
00765 sn_Receive();
00766 sn_SendPlanned();
00767
00768 menu->GenericBackground();
00769 if (continuePoll)
00770 {
00771 continuePoll = nServerInfo::DoQueryAll(sg_simultaneous);
00772 sn_Receive();
00773 sn_SendPlanned();
00774 }
00775
00776 #ifndef DEDICATED
00777 rTextField::SetDefaultColor( tColor(.8,.3,.3,1) );
00778
00779 tString sn2 = tString(tOutput("$network_master_servername"));
00780 if (getFriendsEnabled())
00781 sn2 << " - " << tOutput("$friends_enable");
00782
00783 static_cast<gServerMenu*>(menu)->Render(.62,
00784 sn2,
00785 tOutput("$network_master_score"),
00786 tOutput("$network_master_users"),
00787 tOutput("$network_master_ping"));
00788 #endif
00789 }
00790
00791 void gServerMenuItem::Enter()
00792 {
00793 nServerInfo::GetFromLANContinuouslyStop();
00794
00795 menu->Exit();
00796
00797
00798
00799
00800
00801 if (server)
00802 ConnectToServer(server);
00803 }
00804
00805
00806 void gServerMenuItem::SetServer(nServerInfo *s)
00807 {
00808 if (s == server)
00809 return;
00810
00811 if (server)
00812 server->menuItem = NULL;
00813
00814 server = dynamic_cast<gServerInfo*>(s);
00815
00816 if (server)
00817 {
00818 if (server->menuItem)
00819 server->menuItem->SetServer(NULL);
00820
00821 server->menuItem = this;
00822 }
00823
00824 favorite_ = gServerFavorites::IsFavorite( server );
00825 }
00826
00827 gServerInfo *gServerMenuItem::GetServer()
00828 {
00829 return server;
00830 }
00831
00832 static char const * sg_HelpText = "$network_master_browserhelp";
00833
00834 gServerMenuItem::gServerMenuItem(gServerMenu *men)
00835 :gBrowserMenuItem(men, sg_HelpText), server(NULL), lastPing_(-100), favorite_(false)
00836 {}
00837
00838 gServerMenuItem::~gServerMenuItem()
00839 {
00840 SetServer(NULL);
00841
00842
00843
00844 uMenuItem* last = menu->Item(menu->NumItems()-1);
00845 menu->RemoveItem(last);
00846 menu->RemoveItem(this);
00847 menu->AddItem(last);
00848 }
00849
00850
00851 gServerInfo::~gServerInfo()
00852 {
00853 if (menuItem)
00854 delete menuItem;
00855 }
00856
00857
00858 void gServerStartMenuItem::Render(REAL x,REAL y,REAL alpha, bool selected)
00859 {
00860 #ifndef DEDICATED
00861
00862
00863 SetColor( selected, alpha );
00864
00865 tString s;
00866 s << tOutput("$network_master_start");
00867 static_cast<gServerMenu*>(menu)->Render(y*shrink + displace,
00868 s,
00869 tString(), tString(), tString());
00870 #endif
00871 }
00872
00873 void gServerStartMenuItem::Enter()
00874 {
00875 nServerInfo::GetFromLANContinuouslyStop();
00876
00877 menu->Exit();
00878
00879
00880
00881
00882
00883 sg_HostGameMenu();
00884 }
00885
00886
00887
00888 gServerStartMenuItem::gServerStartMenuItem(gServerMenu *men)
00889 :gBrowserMenuItem(men, *sg_StartHelpText)
00890 {}
00891
00892 gServerStartMenuItem::~gServerStartMenuItem()
00893 {
00894 }
00895
00896