2009-05-08 13:28:41 +00:00
/*
* OpenClonk , http : //www.openclonk.org
*
2013-12-17 20:01:09 +00:00
* Copyright ( c ) 2006 - 2009 , RedWolf Design GmbH , http : //www.clonk.de/
2016-04-03 18:18:29 +00:00
* Copyright ( c ) 2009 - 2016 , The OpenClonk Team and contributors
2013-12-17 20:01:09 +00:00
*
* Distributed under the terms of the ISC license ; see accompanying file
* " COPYING " for details .
*
* " Clonk " is a registered trademark of Matthes Bender , used with permission .
* See accompanying file " TRADEMARK " for details .
*
* To redistribute this file separately , substitute the full license texts
* for the above references .
*/
2009-05-08 13:28:41 +00:00
// Startup screen for non-parameterized engine start: Network game selection dialog
2016-04-03 18:07:56 +00:00
# include "C4Include.h"
# include "gui/C4StartupNetDlg.h"
2009-05-08 13:28:41 +00:00
2016-04-03 18:07:56 +00:00
# include "game/C4Application.h"
2016-10-20 21:42:46 +00:00
# include "graphics/C4Draw.h"
2017-04-30 08:49:09 +00:00
# include "graphics/C4GraphicsResource.h"
# include "gui/C4ChatDlg.h"
# include "gui/C4StartupScenSelDlg.h"
# include "gui/C4UpdateDlg.h"
2016-04-03 18:07:56 +00:00
# include "network/C4Network2Reference.h"
2009-05-08 13:28:41 +00:00
// ----------- C4StartupNetListEntry -----------------------------------------------------------------------
C4StartupNetListEntry : : C4StartupNetListEntry ( C4GUI : : ListBox * pForListBox , C4GUI : : Element * pInsertBefore , C4StartupNetDlg * pNetDlg )
2016-11-02 23:58:02 +00:00
: pNetDlg ( pNetDlg ) , pList ( pForListBox ) , pRefClient ( nullptr ) , pRef ( nullptr ) , fError ( false ) , eQueryType ( NRQT_Unknown ) , iTimeout ( 0 ) , iInfoIconCount ( 0 ) , iSortOrder ( 0 ) , fIsSmall ( false ) , fIsCollapsed ( false ) , fIsEnabled ( true ) , fIsImportant ( false )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// calc height
2010-06-27 00:42:48 +00:00
int32_t iLineHgt = : : GraphicsResource . TextFont . GetLineHeight ( ) , iHeight = iLineHgt * 2 + 4 ;
2009-05-08 13:28:41 +00:00
// add icons - normal icons use small size, only animated netgetref uses full size
rctIconLarge . Set ( 0 , 0 , iHeight , iHeight ) ;
int32_t iSmallIcon = iHeight * 2 / 3 ; rctIconSmall . Set ( ( iHeight - iSmallIcon ) / 2 , ( iHeight - iSmallIcon ) / 2 , iSmallIcon , iSmallIcon ) ;
pIcon = new C4GUI : : Icon ( rctIconSmall , C4GUI : : Ico_Host ) ;
AddElement ( pIcon ) ;
SetBounds ( pIcon - > GetBounds ( ) ) ;
// add to listbox (will get resized horizontally and moved)
pForListBox - > InsertElement ( this , pInsertBefore ) ;
// add status icons and text labels now that width is known
2010-06-27 00:42:48 +00:00
CStdFont * pUseFont = & ( : : GraphicsResource . TextFont ) ;
2009-05-08 13:28:41 +00:00
int32_t iIconSize = pUseFont - > GetLineHeight ( ) ;
C4Rect rcIconRect = GetContainedClientRect ( ) ;
int32_t iThisWdt = rcIconRect . Wdt ;
rcIconRect . x = iThisWdt - iIconSize * ( iInfoIconCount + 1 ) ;
rcIconRect . Wdt = rcIconRect . Hgt = iIconSize ;
2017-05-03 18:28:00 +00:00
for ( auto & pInfoIcon : pInfoIcons )
2010-03-28 18:58:01 +00:00
{
2017-05-03 18:28:00 +00:00
AddElement ( pInfoIcon = new C4GUI : : Icon ( rcIconRect , C4GUI : : Ico_None ) ) ;
2009-05-08 13:28:41 +00:00
rcIconRect . x - = rcIconRect . Wdt ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
C4Rect rcLabelBounds ;
rcLabelBounds . x = iHeight + 3 ;
rcLabelBounds . Hgt = iLineHgt ;
for ( int i = 0 ; i < InfoLabelCount ; + + i )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
C4GUI : : Label * pLbl ;
rcLabelBounds . y = 1 + i * ( iLineHgt + 2 ) ;
rcLabelBounds . Wdt = iThisWdt - rcLabelBounds . x - 1 ;
if ( ! i ) rcLabelBounds . Wdt - = iLineHgt ; // leave space for topright extra icon
AddElement ( pLbl = pInfoLbl [ i ] = new C4GUI : : Label ( " " , rcLabelBounds , ALeft , C4GUI_CaptionFontClr ) ) ;
// label will have collapsed due to no text: Repair it
pLbl - > SetAutosize ( false ) ;
pLbl - > SetBounds ( rcLabelBounds ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// update small state, which will resize this to a small entry
UpdateSmallState ( ) ;
// Set*-function will fill icon and text and calculate actual size
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
C4StartupNetListEntry : : ~ C4StartupNetListEntry ( )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
ClearRef ( ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4StartupNetListEntry : : DrawElement ( C4TargetFacet & cgo )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
typedef C4GUI : : Window ParentClass ;
// background if important and not selected
if ( fIsImportant & & ! IsSelectedChild ( this ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
int32_t x1 = cgo . X + cgo . TargetX + rcBounds . x ;
int32_t y1 = cgo . Y + cgo . TargetY + rcBounds . y ;
2011-10-03 14:30:18 +00:00
pDraw - > DrawBoxDw ( cgo . Surface , x1 , y1 , x1 + rcBounds . Wdt , y1 + rcBounds . Hgt , C4GUI_ImportantBGColor ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// inherited
ParentClass : : DrawElement ( cgo ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4StartupNetListEntry : : ClearRef ( )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// del old ref data
if ( pRefClient )
2010-03-28 18:58:01 +00:00
{
2010-03-27 16:05:02 +00:00
C4InteractiveThread & Thread = Application . InteractiveThread ;
Thread . RemoveProc ( pRefClient ) ;
2016-11-02 23:58:02 +00:00
delete pRefClient ; pRefClient = nullptr ;
2010-03-28 18:58:01 +00:00
}
2016-11-02 23:58:02 +00:00
if ( pRef ) { delete pRef ; pRef = nullptr ; }
2009-05-08 13:28:41 +00:00
eQueryType = NRQT_Unknown ;
iTimeout = iRequestTimeout = 0 ;
fError = false ;
sError . Clear ( ) ;
int32_t i ;
for ( i = 0 ; i < InfoLabelCount ; + + i ) sInfoText [ i ] . Clear ( ) ;
InvalidateStatusIcons ( ) ;
sRefClientAddress . Clear ( ) ;
fIsEnabled = true ;
fIsImportant = false ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
const char * C4StartupNetListEntry : : GetQueryTypeName ( QueryType eQueryType )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
switch ( eQueryType )
2010-03-28 18:58:01 +00:00
{
case NRQT_GameDiscovery : return LoadResStr ( " IDS_NET_QUERY_LOCALNET " ) ;
case NRQT_Masterserver : return LoadResStr ( " IDS_NET_QUERY_MASTERSRV " ) ;
case NRQT_DirectJoin : return LoadResStr ( " IDS_NET_QUERY_DIRECTJOIN " ) ;
default : return " " ;
} ;
}
2009-05-08 13:28:41 +00:00
void C4StartupNetListEntry : : SetRefQuery ( const char * szAddress , enum QueryType eQueryType )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// safety: clear previous
ClearRef ( ) ;
// setup layout
2015-08-31 18:52:39 +00:00
const_cast < C4Facet & > ( reinterpret_cast < const C4Facet & > ( pIcon - > GetFacet ( ) ) )
= ( const C4Facet & ) C4Startup : : Get ( ) - > Graphics . fctNetGetRef ;
2009-05-08 13:28:41 +00:00
pIcon - > SetAnimated ( true , 1 ) ;
pIcon - > SetBounds ( rctIconLarge ) ;
// init a new ref client to query
sRefClientAddress . Copy ( szAddress ) ;
this - > eQueryType = eQueryType ;
pRefClient = new C4Network2RefClient ( ) ;
if ( ! pRefClient - > Init ( ) | | ! pRefClient - > SetServer ( szAddress ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// should not happen
sInfoText [ 0 ] . Clear ( ) ;
SetError ( pRefClient - > GetError ( ) , TT_RefReqWait ) ;
return ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// set info
sInfoText [ 0 ] . Format ( LoadResStr ( " IDS_NET_CLIENTONNET " ) , GetQueryTypeName ( eQueryType ) , pRefClient - > getServerName ( ) ) ;
sInfoText [ 1 ] . Copy ( LoadResStr ( " IDS_NET_INFOQUERY " ) ) ;
UpdateSmallState ( ) ; UpdateText ( ) ;
pRefClient - > SetNotify ( & Application . InteractiveThread ) ;
// masterserver: always on top
if ( eQueryType = = NRQT_Masterserver )
iSortOrder = 100 ;
2010-03-27 16:05:02 +00:00
// register proc
C4InteractiveThread & Thread = Application . InteractiveThread ;
Thread . AddProc ( pRefClient ) ;
2009-05-08 13:28:41 +00:00
// start querying!
QueryReferences ( ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
bool C4StartupNetListEntry : : QueryReferences ( )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// begin querying
if ( ! pRefClient - > QueryReferences ( ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
SetError ( pRefClient - > GetError ( ) , TT_RefReqWait ) ;
return false ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// set up timeout
2016-11-02 23:58:02 +00:00
iRequestTimeout = time ( nullptr ) + C4NetRefRequestTimeout ;
2009-05-08 13:28:41 +00:00
return true ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
bool C4StartupNetListEntry : : Execute ( )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// update entries
// if the return value is false, this entry will be deleted
// timer running?
2016-11-02 23:58:02 +00:00
if ( iTimeout ) if ( time ( nullptr ) > = iTimeout )
2009-05-08 13:28:41 +00:00
{
2010-03-28 18:58:01 +00:00
// timeout!
// for internet servers, this means refresh needed - search anew!
if ( pRefClient & & eQueryType = = NRQT_Masterserver )
2009-05-08 13:28:41 +00:00
{
2010-03-28 18:58:01 +00:00
fError = false ;
sError . Clear ( ) ;
2015-08-29 12:33:00 +00:00
pIcon - > SetFacet ( C4Startup : : Get ( ) - > Graphics . fctNetGetRef ) ;
2010-03-28 18:58:01 +00:00
pIcon - > SetAnimated ( true , 1 ) ;
pIcon - > SetBounds ( rctIconLarge ) ;
sInfoText [ 1 ] . Copy ( LoadResStr ( " IDS_NET_INFOQUERY " ) ) ;
iTimeout = 0 ;
QueryReferences ( ) ;
// always keep item even if query failed
return true ;
2009-05-08 13:28:41 +00:00
}
2010-03-28 18:58:01 +00:00
// any other item is just removed - return value marks this
return false ;
2009-05-08 13:28:41 +00:00
}
// failed without a timer. Nothing to be done about it.
if ( fError ) return true ;
// updates need to be done for references being retrieved only
if ( ! pRefClient ) return true ;
// check if it has arrived
if ( pRefClient - > isBusy ( ) )
// still requesting - but do not wait forever
2016-11-02 23:58:02 +00:00
if ( time ( nullptr ) > = iRequestTimeout )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
SetError ( LoadResStr ( " IDS_NET_ERR_REFREQTIMEOUT " ) , TT_RefReqWait ) ;
2010-03-27 16:05:02 +00:00
pRefClient - > Cancel ( " Timeout " ) ;
2010-03-28 18:58:01 +00:00
}
2010-03-27 16:05:02 +00:00
return true ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
bool C4StartupNetListEntry : : OnReference ( )
2010-03-28 18:58:01 +00:00
{
2010-03-27 16:05:02 +00:00
// wrong type / still busy?
if ( ! pRefClient | | pRefClient - > isBusy ( ) )
return true ;
2009-05-08 13:28:41 +00:00
// successful?
if ( ! pRefClient - > isSuccess ( ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// couldn't get references
SetError ( pRefClient - > GetError ( ) , TT_RefReqWait ) ;
2010-03-27 16:05:02 +00:00
return true ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// Ref getting done!
pIcon - > SetAnimated ( false , 1 ) ;
// Get reference information from client
2016-11-02 23:58:02 +00:00
C4Network2Reference * * ppNewRefs = nullptr ; int32_t iNewRefCount ;
2010-03-28 18:58:01 +00:00
if ( ! pRefClient - > GetReferences ( ppNewRefs , iNewRefCount ) )
{
2009-05-08 13:28:41 +00:00
// References could be retrieved but not read
SetError ( LoadResStr ( " IDS_NET_ERR_REFINVALID " ) , TT_RefReqWait ) ;
delete [ ] ppNewRefs ;
return true ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
if ( ! iNewRefCount )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// References retrieved but no game open: Inform user
sInfoText [ 1 ] . Copy ( LoadResStr ( " IDS_NET_INFONOGAME " ) ) ;
UpdateText ( ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
else
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// Grab references, count players
C4StartupNetListEntry * pNewRefEntry = this ; int iPlayerCount = 0 ;
2010-03-28 18:58:01 +00:00
for ( int i = 0 ; i < iNewRefCount ; i + + )
{
2009-05-08 13:28:41 +00:00
pNewRefEntry = AddReference ( ppNewRefs [ i ] , pNewRefEntry - > GetNextLower ( ppNewRefs [ i ] - > getSortOrder ( ) ) ) ;
iPlayerCount + = ppNewRefs [ i ] - > Parameters . PlayerInfos . GetActivePlayerCount ( false ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// Count player
sInfoText [ 1 ] . Format ( LoadResStr ( " IDS_NET_INFOGAMES " ) , ( int ) iNewRefCount , iPlayerCount ) ;
UpdateText ( ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
delete [ ] ppNewRefs ;
// special masterserver handling
if ( eQueryType = = NRQT_Masterserver )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// masterserver: schedule next query
sInfoText [ 1 ] . Format ( LoadResStr ( " IDS_NET_INFOGAMES " ) , ( int ) iNewRefCount ) ;
SetTimeout ( TT_Masterserver ) ;
return true ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// non-masterserver
if ( iNewRefCount )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// this item has been "converted" into the references - remove without further feedback
return false ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
else
2014-10-04 20:50:34 +00:00
{
2009-05-08 13:28:41 +00:00
// no ref found on custom adress: Schedule re-check
SetTimeout ( TT_RefReqWait ) ;
2014-10-04 20:50:34 +00:00
}
2010-03-27 16:05:02 +00:00
return true ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
C4GUI : : Element * C4StartupNetListEntry : : GetNextLower ( int32_t sortOrder )
{
// search list for the next element of a lower sort order
for ( C4GUI : : Element * pElem = pList - > GetFirst ( ) ; pElem ; pElem = pElem - > GetNext ( ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
C4StartupNetListEntry * pEntry = static_cast < C4StartupNetListEntry * > ( pElem ) ;
if ( pEntry - > iSortOrder < sortOrder )
return pElem ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// none found: insert at start
2016-11-02 23:58:02 +00:00
return nullptr ;
2009-05-08 13:28:41 +00:00
}
void C4StartupNetListEntry : : UpdateCollapsed ( bool fToCollapseValue )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// if collapsed state changed, update the text
if ( fIsCollapsed = = fToCollapseValue ) return ;
fIsCollapsed = fToCollapseValue ;
UpdateSmallState ( ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4StartupNetListEntry : : UpdateSmallState ( )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// small view: Always collapsed if there is no extended text
bool fNewIsSmall = ! sInfoText [ 2 ] . getLength ( ) | | fIsCollapsed ;
if ( fNewIsSmall = = fIsSmall ) return ;
fIsSmall = fNewIsSmall ;
for ( int i = 2 ; i < InfoLabelCount ; + + i ) pInfoLbl [ i ] - > SetVisibility ( ! fIsSmall ) ;
UpdateEntrySize ( ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4StartupNetListEntry : : UpdateEntrySize ( )
2010-03-28 18:58:01 +00:00
{
2010-09-19 17:01:31 +00:00
if ( fVisible ) {
// restack all labels by their size
int32_t iLblCnt = ( fIsSmall ? 2 : InfoLabelCount ) , iY = 1 ;
for ( int i = 0 ; i < iLblCnt ; + + i )
{
C4Rect rcBounds = pInfoLbl [ i ] - > GetBounds ( ) ;
rcBounds . y = iY ;
iY + = rcBounds . Hgt + 2 ;
2009-05-08 13:28:41 +00:00
pInfoLbl [ i ] - > SetBounds ( rcBounds ) ;
2010-09-19 17:01:31 +00:00
}
// resize this control
GetBounds ( ) . Hgt = iY - 1 ;
} else GetBounds ( ) . Hgt = 0 ;
2009-05-08 13:28:41 +00:00
UpdateSize ( ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4StartupNetListEntry : : UpdateText ( )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
bool fRestackElements = false ;
2010-06-27 00:42:48 +00:00
CStdFont * pUseFont = & ( : : GraphicsResource . TextFont ) ;
2009-05-08 13:28:41 +00:00
// adjust icons
int32_t sx = iInfoIconCount * pUseFont - > GetLineHeight ( ) ;
int32_t i ;
for ( i = iInfoIconCount ; i < MaxInfoIconCount ; + + i )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
pInfoIcons [ i ] - > SetIcon ( C4GUI : : Ico_None ) ;
2016-11-02 23:58:02 +00:00
pInfoIcons [ i ] - > SetToolTip ( nullptr ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// text to labels
for ( i = 0 ; i < InfoLabelCount ; + + i )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
int iAvailableWdt = GetClientRect ( ) . Wdt - pInfoLbl [ i ] - > GetBounds ( ) . x - 1 ;
if ( ! i ) iAvailableWdt - = sx ;
StdStrBuf BrokenText ;
pUseFont - > BreakMessage ( sInfoText [ i ] . getData ( ) , iAvailableWdt , & BrokenText , true ) ;
int32_t iHgt , iWdt ;
if ( pUseFont - > GetTextExtent ( BrokenText . getData ( ) , iWdt , iHgt , true ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
if ( ( pInfoLbl [ i ] - > GetBounds ( ) . Hgt ! = iHgt ) | | ( pInfoLbl [ i ] - > GetBounds ( ) . Wdt ! = iAvailableWdt ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
C4Rect rcBounds = pInfoLbl [ i ] - > GetBounds ( ) ;
rcBounds . Wdt = iAvailableWdt ;
rcBounds . Hgt = iHgt ;
pInfoLbl [ i ] - > SetBounds ( rcBounds ) ;
fRestackElements = true ;
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
pInfoLbl [ i ] - > SetText ( BrokenText . getData ( ) ) ;
pInfoLbl [ i ] - > SetColor ( fIsEnabled ? C4GUI_MessageFontClr : C4GUI_InactMessageFontClr ) ;
}
2010-03-28 18:58:01 +00:00
if ( fRestackElements ) UpdateEntrySize ( ) ;
}
2009-05-08 13:28:41 +00:00
2010-09-19 17:01:31 +00:00
void C4StartupNetListEntry : : SetVisibility ( bool fToValue ) {
bool fChange = fToValue ! = fVisible ;
C4GUI : : Window : : SetVisibility ( fToValue ) ;
if ( fChange ) UpdateEntrySize ( ) ;
}
2009-05-08 13:28:41 +00:00
void C4StartupNetListEntry : : AddStatusIcon ( C4GUI : : Icons eIcon , const char * szToolTip )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// safety
if ( iInfoIconCount = = MaxInfoIconCount ) return ;
// set icon to the left of the existing icons to the desired data
pInfoIcons [ iInfoIconCount ] - > SetIcon ( eIcon ) ;
pInfoIcons [ iInfoIconCount ] - > SetToolTip ( szToolTip ) ;
+ + iInfoIconCount ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4StartupNetListEntry : : SetReference ( C4Network2Reference * pRef )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// safety: clear previous
ClearRef ( ) ;
// set info
this - > pRef = pRef ;
int32_t iIcon = pRef - > getIcon ( ) ;
if ( ! Inside < int32_t > ( iIcon , 0 , C4StartupScenSel_IconCount - 1 ) ) iIcon = C4StartupScenSel_DefaultIcon_Scenario ;
pIcon - > SetFacet ( C4Startup : : Get ( ) - > Graphics . fctScenSelIcons . GetPhase ( iIcon ) ) ;
pIcon - > SetAnimated ( false , 0 ) ;
pIcon - > SetBounds ( rctIconSmall ) ;
2016-08-10 23:35:07 +00:00
int32_t iPlrCnt = pRef - > isEditor ( ) ? pRef - > Parameters . PlayerInfos . GetActivePlayerCount ( false ) : pRef - > Parameters . Clients . getClientCnt ( ) ;
2009-05-08 13:28:41 +00:00
C4Client * pHost = pRef - > Parameters . Clients . getHost ( ) ;
sInfoText [ 0 ] . Format ( LoadResStr ( " IDS_NET_REFONCLIENT " ) , pRef - > getTitle ( ) , pHost ? pHost - > getName ( ) : " unknown " ) ;
2016-08-10 23:35:07 +00:00
if ( pRef - > isEditor ( ) )
{
sInfoText [ 1 ] . Format ( LoadResStr ( " IDS_NET_INFOEDITOR " ) ,
( int ) iPlrCnt ,
StdStrBuf ( pRef - > getGameStatus ( ) . getDescription ( ) , true ) . getData ( ) ) ;
}
else
{
sInfoText [ 1 ] . Format ( LoadResStr ( " IDS_NET_INFOPLRSGOALDESC " ) ,
( int ) iPlrCnt ,
( int ) pRef - > Parameters . MaxPlayers ,
pRef - > getGameGoalString ( ) . getData ( ) ,
StdStrBuf ( pRef - > getGameStatus ( ) . getDescription ( ) , true ) . getData ( ) ) ;
}
2009-05-08 13:28:41 +00:00
if ( pRef - > getTime ( ) > 0 )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
StdStrBuf strDuration ; strDuration . Format ( " %02d:%02d:%02d " , pRef - > getTime ( ) / 3600 , ( pRef - > getTime ( ) % 3600 ) / 60 , pRef - > getTime ( ) % 60 ) ;
sInfoText [ 1 ] . Append ( " - " ) ; sInfoText [ 1 ] . Append ( strDuration ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
sInfoText [ 2 ] . Format ( LoadResStr ( " IDS_DESC_VERSION " ) , pRef - > getGameVersion ( ) . GetString ( ) . getData ( ) ) ;
sInfoText [ 3 ] . Format ( " %s: %s " , LoadResStr ( " IDS_CTL_COMMENT " ) , pRef - > getComment ( ) ) ;
StdStrBuf sAddress ;
for ( int i = 0 ; i < pRef - > getAddrCnt ( ) ; + + i )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
if ( i ) sAddress . Append ( " , " ) ;
sAddress . Append ( pRef - > getAddr ( i ) . toString ( ) ) ;
2010-03-28 18:58:01 +00:00
}
2016-08-10 23:35:07 +00:00
// editor reference
if ( pRef - > isEditor ( ) )
AddStatusIcon ( C4GUI : : Ico_Editor , LoadResStr ( " IDS_CNS_CONSOLE " ) ) ;
2009-05-08 13:28:41 +00:00
// password
if ( pRef - > isPasswordNeeded ( ) )
AddStatusIcon ( C4GUI : : Ico_Ex_LockedFrontal , LoadResStr ( " IDS_NET_INFOPASSWORD " ) ) ;
// league
if ( pRef - > Parameters . isLeague ( ) )
AddStatusIcon ( C4GUI : : Ico_Ex_League , pRef - > Parameters . getLeague ( ) ) ;
// lobby active
if ( pRef - > getGameStatus ( ) . isLobbyActive ( ) )
AddStatusIcon ( C4GUI : : Ico_Lobby , LoadResStr ( " IDS_DESC_EXPECTING " ) ) ;
// game running
if ( pRef - > getGameStatus ( ) . isPastLobby ( ) )
AddStatusIcon ( C4GUI : : Ico_GameRunning , LoadResStr ( " IDS_NET_INFOINPROGR " ) ) ;
// runtime join
if ( pRef - > isJoinAllowed ( ) & & pRef - > getGameStatus ( ) . isPastLobby ( ) ) // A little workaround to determine RuntimeJoin...
AddStatusIcon ( C4GUI : : Ico_RuntimeJoin , LoadResStr ( " IDS_NET_RUNTIMEJOINFREE " ) ) ;
// official server
if ( pRef - > isOfficialServer ( ) & & ! Config . Network . UseAlternateServer ) // Offical server icon is only displayed if references are obtained from official league server
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
fIsImportant = true ;
AddStatusIcon ( C4GUI : : Ico_OfficialServer , LoadResStr ( " IDS_NET_OFFICIALSERVER " ) ) ;
2010-03-28 18:58:01 +00:00
}
2016-08-10 23:35:07 +00:00
// list participating player/client names
if ( pRef - > isEditor ( ) )
{
sInfoText [ 4 ] . Format ( " %s%s " , LoadResStr ( " IDS_DESC_CLIENTS " ) , iPlrCnt ? pRef - > Parameters . Clients . GetAllClientNames ( ) . getData ( ) : LoadResStr ( " IDS_CTL_NONE " ) ) ;
}
else
{
sInfoText [ 4 ] . Format ( " %s: %s " , LoadResStr ( " IDS_CTL_PLAYER " ) , iPlrCnt ? pRef - > Parameters . PlayerInfos . GetActivePlayerNames ( false ) . getData ( ) : LoadResStr ( " IDS_CTL_NONE " ) ) ;
}
2009-05-08 13:28:41 +00:00
// disabled if join is not possible for some reason
C4GameVersion verThis ;
if ( ! pRef - > isJoinAllowed ( ) | | ! ( pRef - > getGameVersion ( ) = = verThis ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
fIsEnabled = false ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// store sort order
iSortOrder = pRef - > getSortOrder ( ) ;
// all references expire after a while
SetTimeout ( TT_Reference ) ;
UpdateSmallState ( ) ; UpdateText ( ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4StartupNetListEntry : : SetError ( const char * szErrorText , TimeoutType eTimeout )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// set error message
fError = true ;
sInfoText [ 1 ] . Copy ( szErrorText ) ;
for ( int i = 2 ; i < InfoLabelCount ; + + i ) sInfoText [ i ] . Clear ( ) ;
InvalidateStatusIcons ( ) ;
UpdateSmallState ( ) ; UpdateText ( ) ;
pIcon - > SetIcon ( C4GUI : : Ico_Close ) ;
pIcon - > SetAnimated ( false , 0 ) ;
pIcon - > SetBounds ( rctIconSmall ) ;
SetTimeout ( eTimeout ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4StartupNetListEntry : : SetTimeout ( TimeoutType eTimeout )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
int iTime = 0 ;
switch ( eTimeout )
2010-03-28 18:58:01 +00:00
{
case TT_RefReqWait : iTime = ( eQueryType = = NRQT_Masterserver ) ? C4NetMasterServerQueryInterval : C4NetErrorRefTimeout ; break ;
case TT_Reference : iTime = C4NetReferenceTimeout ; break ;
case TT_Masterserver : iTime = C4NetMasterServerQueryInterval ; break ;
} ;
2009-05-08 13:28:41 +00:00
if ( ! iTime ) return ;
2016-11-02 23:58:02 +00:00
iTimeout = time ( nullptr ) + iTime ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
C4StartupNetListEntry * C4StartupNetListEntry : : AddReference ( C4Network2Reference * pAddRef , C4GUI : : Element * pInsertBefore )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// check list whether the same reference has been added already
2010-03-28 18:58:01 +00:00
for ( C4GUI : : Element * pElem = pList - > GetFirst ( ) ; pElem ; pElem = pElem - > GetNext ( ) )
{
2009-05-08 13:28:41 +00:00
C4StartupNetListEntry * pEntry = static_cast < C4StartupNetListEntry * > ( pElem ) ;
// match to existing reference entry:
// * same host (checking for same name and nick)
// * at least one match in address and port
// * the incoming reference is newer than (or same as) the current one
if ( pEntry - > IsSameHost ( pAddRef )
2010-03-28 18:58:01 +00:00
& & pEntry - > IsSameAddress ( pAddRef )
& & ( pEntry - > GetReference ( ) - > getStartTime ( ) < = pAddRef - > getStartTime ( ) ) )
{
2009-05-08 13:28:41 +00:00
// update existing entry
pEntry - > SetReference ( pAddRef ) ;
return pEntry ;
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// no update - just add
C4StartupNetListEntry * pNewRefEntry = new C4StartupNetListEntry ( pList , pInsertBefore , pNetDlg ) ;
pNewRefEntry - > SetReference ( pAddRef ) ;
pNetDlg - > OnReferenceEntryAdd ( pNewRefEntry ) ;
return pNewRefEntry ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
bool C4StartupNetListEntry : : IsSameHost ( const C4Network2Reference * pRef2 )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// not if ref has not been retrieved yet
if ( ! pRef ) return false ;
C4Client * pHost1 = pRef - > Parameters . Clients . getHost ( ) ;
C4Client * pHost2 = pRef2 - > Parameters . Clients . getHost ( ) ;
2010-03-28 18:58:01 +00:00
if ( ! pHost1 | | ! pHost2 ) return false ;
2009-05-08 13:28:41 +00:00
// check
return SEqual ( pHost1 - > getCUID ( ) , pHost2 - > getCUID ( ) ) & & SEqual ( pHost1 - > getName ( ) , pHost2 - > getName ( ) ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
bool C4StartupNetListEntry : : IsSameAddress ( const C4Network2Reference * pRef2 )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// not if ref has not been retrieved yet
if ( ! pRef ) return false ;
// check all of our addresses
for ( int i = 0 ; i < pRef - > getAddrCnt ( ) ; i + + )
// against all of the other ref's addresses
for ( int j = 0 ; j < pRef2 - > getAddrCnt ( ) ; j + + )
// at least one match!
if ( pRef - > getAddr ( i ) = = pRef2 - > getAddr ( j ) )
return true ;
// no match
return false ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
bool C4StartupNetListEntry : : IsSameRefQueryAddress ( const char * szJoinaddress )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// only unretrieved references
if ( ! pRefClient ) return false ;
// if request failed, create a duplicate anyway in case the game is opened now
// except masterservers, which would re-search some time later anyway
if ( fError & & eQueryType ! = NRQT_Masterserver ) return false ;
// check equality of address
// do it the simple way for now
return SEqualNoCase ( sRefClientAddress . getData ( ) , szJoinaddress ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2010-09-19 17:01:31 +00:00
bool C4StartupNetListEntry : : KeywordMatch ( const char * szMatch )
{
// only finished references
if ( ! pRef ) return false ;
if ( SSearchNoCase ( pRef - > getTitle ( ) , szMatch ) ) return true ;
C4Client * pHost = pRef - > Parameters . Clients . getHost ( ) ;
if ( pHost & & SSearchNoCase ( pHost - > getName ( ) , szMatch ) ) return true ;
if ( SSearchNoCase ( pRef - > getComment ( ) , szMatch ) ) return true ;
return false ;
}
2009-05-08 13:28:41 +00:00
const char * C4StartupNetListEntry : : GetJoinAddress ( )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// only unresolved references
2016-11-02 23:58:02 +00:00
if ( ! pRefClient ) return nullptr ;
2009-05-08 13:28:41 +00:00
// not masterservers (cannot join directly on clonk.de)
2016-11-02 23:58:02 +00:00
if ( eQueryType = = NRQT_Masterserver ) return nullptr ;
2009-05-08 13:28:41 +00:00
// return join address
return pRefClient - > getServerName ( ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
C4Network2Reference * C4StartupNetListEntry : : GrabReference ( )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
C4Network2Reference * pOldRef = pRef ;
2016-11-02 23:58:02 +00:00
pRef = nullptr ;
2009-05-08 13:28:41 +00:00
return pOldRef ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// ----------- C4StartupNetDlg ---------------------------------------------------------------------------------
2017-05-07 11:50:00 +00:00
C4StartupNetDlg : : C4StartupNetDlg ( ) : C4StartupDlg ( LoadResStr ( " IDS_DLG_NETSTART " ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// ctor
// key bindings
C4CustomKey : : CodeList keys ;
2017-05-03 18:28:00 +00:00
keys . emplace_back ( K_BACK ) ; keys . emplace_back ( K_LEFT ) ;
2009-05-08 13:28:41 +00:00
pKeyBack = new C4KeyBinding ( keys , " StartupNetBack " , KEYSCOPE_Gui ,
2010-03-28 18:58:01 +00:00
new C4GUI : : DlgKeyCB < C4StartupNetDlg > ( * this , & C4StartupNetDlg : : KeyBack ) , C4CustomKey : : PRIO_Dlg ) ;
2009-05-08 13:28:41 +00:00
pKeyRefresh = new C4KeyBinding ( C4KeyCodeEx ( K_F5 ) , " StartupNetReload " , KEYSCOPE_Gui ,
2010-03-28 18:58:01 +00:00
new C4GUI : : DlgKeyCB < C4StartupNetDlg > ( * this , & C4StartupNetDlg : : KeyRefresh ) , C4CustomKey : : PRIO_CtrlOverride ) ;
2009-05-08 13:28:41 +00:00
// screen calculations
UpdateSize ( ) ;
int32_t iIconSize = C4GUI_IconExWdt ;
2015-11-15 12:53:01 +00:00
int32_t iButtonWidth , iCaptionFontHgt , iSideSize = std : : max < int32_t > ( GetBounds ( ) . Wdt / 6 , iIconSize ) ;
2009-05-08 13:28:41 +00:00
int32_t iButtonHeight = C4GUI_ButtonHgt , iButtonIndent = GetBounds ( ) . Wdt / 40 ;
2010-06-27 00:42:48 +00:00
: : GraphicsResource . CaptionFont . GetTextExtent ( " << BACK " , iButtonWidth , iCaptionFontHgt , true ) ;
2009-05-08 13:28:41 +00:00
iButtonWidth * = 3 ;
C4GUI : : ComponentAligner caMain ( GetClientRect ( ) , 0 , 0 , true ) ;
C4GUI : : ComponentAligner caButtonArea ( caMain . GetFromBottom ( caMain . GetHeight ( ) / 7 ) , 0 , 0 ) ;
int32_t iButtonAreaWdt = caButtonArea . GetWidth ( ) * 7 / 8 ;
2015-11-15 12:53:01 +00:00
iButtonWidth = std : : min < int32_t > ( iButtonWidth , ( iButtonAreaWdt - 8 * iButtonIndent ) / 4 ) ;
2009-05-08 13:28:41 +00:00
iButtonIndent = ( iButtonAreaWdt - 4 * iButtonWidth ) / 8 ;
C4GUI : : ComponentAligner caButtons ( caButtonArea . GetCentered ( iButtonAreaWdt , iButtonHeight ) , iButtonIndent , 0 ) ;
2015-11-15 12:53:01 +00:00
C4GUI : : ComponentAligner caLeftBtnArea ( caMain . GetFromLeft ( iSideSize ) , std : : min < int32_t > ( caMain . GetWidth ( ) / 20 , ( iSideSize - C4GUI_IconExWdt ) / 2 ) , caMain . GetHeight ( ) / 40 ) ;
C4GUI : : ComponentAligner caConfigArea ( caMain . GetFromRight ( iSideSize ) , std : : min < int32_t > ( caMain . GetWidth ( ) / 20 , ( iSideSize - C4GUI_IconExWdt ) / 2 ) , caMain . GetHeight ( ) / 40 ) ;
2009-05-08 13:28:41 +00:00
// left button area: Switch between chat and game list
if ( C4ChatDlg : : IsChatEnabled ( ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
btnGameList = new C4GUI : : CallbackButton < C4StartupNetDlg , C4GUI : : IconButton > ( C4GUI : : Ico_Ex_GameList , caLeftBtnArea . GetFromTop ( iIconSize , iIconSize ) , ' \0 ' , & C4StartupNetDlg : : OnBtnGameList ) ;
btnGameList - > SetToolTip ( LoadResStr ( " IDS_DESC_SHOWSAVAILABLENETWORKGAME " ) ) ;
btnGameList - > SetText ( LoadResStr ( " IDS_BTN_GAMES " ) ) ;
AddElement ( btnGameList ) ;
btnChat = new C4GUI : : CallbackButton < C4StartupNetDlg , C4GUI : : IconButton > ( C4GUI : : Ico_Ex_Chat , caLeftBtnArea . GetFromTop ( iIconSize , iIconSize ) , ' \0 ' , & C4StartupNetDlg : : OnBtnChat ) ;
btnChat - > SetToolTip ( LoadResStr ( " IDS_DESC_CONNECTSTOANIRCCHATSERVER " ) ) ;
btnChat - > SetText ( LoadResStr ( " IDS_BTN_CHAT " ) ) ;
AddElement ( btnChat ) ;
2010-03-28 18:58:01 +00:00
}
2016-11-02 23:58:02 +00:00
else btnChat = nullptr ;
2009-05-08 13:28:41 +00:00
// main area: Tabular to switch between game list and chat
pMainTabular = new C4GUI : : Tabular ( caMain . GetAll ( ) , C4GUI : : Tabular : : tbNone ) ;
pMainTabular - > SetDrawDecoration ( false ) ;
pMainTabular - > SetSheetMargin ( 0 ) ;
AddElement ( pMainTabular ) ;
// main area: game selection sheet
2016-11-02 23:58:02 +00:00
C4GUI : : Tabular : : Sheet * pSheetGameList = pMainTabular - > AddSheet ( nullptr ) ;
2009-05-08 13:28:41 +00:00
C4GUI : : ComponentAligner caGameList ( pSheetGameList - > GetContainedClientRect ( ) , 0 , 0 , false ) ;
2010-06-27 00:42:48 +00:00
C4GUI : : WoodenLabel * pGameListLbl ; int32_t iCaptHgt = C4GUI : : WoodenLabel : : GetDefaultHeight ( & : : GraphicsResource . TextFont ) ;
pGameListLbl = new C4GUI : : WoodenLabel ( LoadResStr ( " IDS_NET_GAMELIST " ) , caGameList . GetFromTop ( iCaptHgt ) , C4GUI_Caption2FontClr , & : : GraphicsResource . TextFont , ALeft ) ;
2010-09-19 17:01:31 +00:00
// search field
C4GUI : : WoodenLabel * pSearchLbl ;
const char * szSearchLblText = LoadResStr ( " IDS_NET_MSSEARCH " ) ;
int32_t iSearchWdt = 100 , iSearchHgt ;
: : GraphicsResource . TextFont . GetTextExtent ( szSearchLblText , iSearchWdt , iSearchHgt , true ) ;
C4GUI : : ComponentAligner caSearch ( caGameList . GetFromTop ( iSearchHgt ) , 0 , 0 ) ;
pSearchLbl = new C4GUI : : WoodenLabel ( szSearchLblText , caSearch . GetFromLeft ( iSearchWdt + 10 ) , C4GUI_Caption2FontClr , & : : GraphicsResource . TextFont ) ;
const char * szSearchTip = LoadResStr ( " IDS_NET_MSSEARCH_DESC " ) ;
pSearchLbl - > SetToolTip ( szSearchTip ) ;
pSheetGameList - > AddElement ( pSearchLbl ) ;
pSearchFieldEdt = new C4GUI : : CallbackEdit < C4StartupNetDlg > ( caSearch . GetAll ( ) , this , & C4StartupNetDlg : : OnSearchFieldEnter ) ;
pSearchFieldEdt - > SetToolTip ( szSearchTip ) ;
pSheetGameList - > AddElement ( pSearchFieldEdt ) ;
2009-05-08 13:28:41 +00:00
pSheetGameList - > AddElement ( pGameListLbl ) ;
pGameSelList = new C4GUI : : ListBox ( caGameList . GetFromTop ( caGameList . GetHeight ( ) - iCaptHgt ) ) ;
2016-11-02 23:58:02 +00:00
pGameSelList - > SetDecoration ( true , nullptr , true , true ) ;
2009-05-08 13:28:41 +00:00
pGameSelList - > UpdateElementPositions ( ) ;
pGameSelList - > SetSelectionDblClickFn ( new C4GUI : : CallbackHandler < C4StartupNetDlg > ( this , & C4StartupNetDlg : : OnSelDblClick ) ) ;
pGameSelList - > SetSelectionChangeCallbackFn ( new C4GUI : : CallbackHandler < C4StartupNetDlg > ( this , & C4StartupNetDlg : : OnSelChange ) ) ;
pSheetGameList - > AddElement ( pGameSelList ) ;
C4GUI : : ComponentAligner caIP ( caGameList . GetAll ( ) , 0 , 0 ) ;
C4GUI : : WoodenLabel * pIPLbl ;
const char * szIPLblText = LoadResStr ( " IDS_NET_IP " ) ;
int32_t iIPWdt = 100 , Q ;
2010-06-27 00:42:48 +00:00
: : GraphicsResource . TextFont . GetTextExtent ( szIPLblText , iIPWdt , Q , true ) ;
pIPLbl = new C4GUI : : WoodenLabel ( szIPLblText , caIP . GetFromLeft ( iIPWdt + 10 ) , C4GUI_Caption2FontClr , & : : GraphicsResource . TextFont ) ;
2009-05-08 13:28:41 +00:00
const char * szIPTip = LoadResStr ( " IDS_NET_IP_DESC " ) ;
pIPLbl - > SetToolTip ( szIPTip ) ;
pSheetGameList - > AddElement ( pIPLbl ) ;
pJoinAddressEdt = new C4GUI : : CallbackEdit < C4StartupNetDlg > ( caIP . GetAll ( ) , this , & C4StartupNetDlg : : OnJoinAddressEnter ) ;
pJoinAddressEdt - > SetToolTip ( szIPTip ) ;
pSheetGameList - > AddElement ( pJoinAddressEdt ) ;
// main area: chat sheet
if ( C4ChatDlg : : IsChatEnabled ( ) )
2010-03-28 18:58:01 +00:00
{
2016-11-02 23:58:02 +00:00
C4GUI : : Tabular : : Sheet * pSheetChat = pMainTabular - > AddSheet ( nullptr ) ;
2009-05-08 13:28:41 +00:00
C4GUI : : ComponentAligner caChat ( pSheetChat - > GetContainedClientRect ( ) , 0 , 0 , false ) ;
2010-06-27 00:42:48 +00:00
pSheetChat - > AddElement ( pChatTitleLabel = new C4GUI : : WoodenLabel ( " " , caChat . GetFromTop ( iCaptHgt ) , C4GUI_Caption2FontClr , & : : GraphicsResource . TextFont , ALeft , false ) ) ;
2009-05-08 13:28:41 +00:00
C4GUI : : GroupBox * pChatGroup = new C4GUI : : GroupBox ( caChat . GetAll ( ) ) ;
pChatGroup - > SetColors ( 0u , C4GUI_CaptionFontClr , C4GUI_StandardBGColor ) ;
pChatGroup - > SetMargin ( 2 ) ;
pSheetChat - > AddElement ( pChatGroup ) ;
2010-03-27 16:05:02 +00:00
pChatCtrl = new C4ChatControl ( & Application . IRCClient ) ;
2009-05-08 13:28:41 +00:00
pChatCtrl - > SetBounds ( pChatGroup - > GetContainedClientRect ( ) ) ;
pChatCtrl - > SetTitleChangeCB ( new C4GUI : : InputCallback < C4StartupNetDlg > ( this , & C4StartupNetDlg : : OnChatTitleChange ) ) ;
StdStrBuf sCurrTitle ; sCurrTitle . Ref ( pChatCtrl - > GetTitle ( ) ) ; OnChatTitleChange ( sCurrTitle ) ;
pChatGroup - > AddElement ( pChatCtrl ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// config area
btnInternet = new C4GUI : : CallbackButton < C4StartupNetDlg , C4GUI : : IconButton > ( Config . Network . MasterServerSignUp ? C4GUI : : Ico_Ex_InternetOn : C4GUI : : Ico_Ex_InternetOff , caConfigArea . GetFromTop ( iIconSize , iIconSize ) , ' \0 ' , & C4StartupNetDlg : : OnBtnInternet ) ;
btnInternet - > SetToolTip ( LoadResStr ( " IDS_DLGTIP_SEARCHINTERNETGAME " ) ) ;
btnInternet - > SetText ( LoadResStr ( " IDS_CTL_INETSERVER " ) ) ;
AddElement ( btnInternet ) ;
btnRecord = new C4GUI : : CallbackButton < C4StartupNetDlg , C4GUI : : IconButton > ( Game . Record ? C4GUI : : Ico_Ex_RecordOn : C4GUI : : Ico_Ex_RecordOff , caConfigArea . GetFromTop ( iIconSize , iIconSize ) , ' \0 ' , & C4StartupNetDlg : : OnBtnRecord ) ;
btnRecord - > SetToolTip ( LoadResStr ( " IDS_DLGTIP_RECORD " ) ) ;
btnRecord - > SetText ( LoadResStr ( " IDS_CTL_RECORD " ) ) ;
AddElement ( btnRecord ) ;
2010-12-26 20:39:52 +00:00
# ifdef WITH_AUTOMATIC_UPDATE
2009-05-08 13:28:41 +00:00
btnUpdate = new C4GUI : : CallbackButton < C4StartupNetDlg , C4GUI : : IconButton > ( C4GUI : : Ico_Ex_Update , caConfigArea . GetFromTop ( iIconSize , iIconSize ) , ' \0 ' , & C4StartupNetDlg : : OnBtnUpdate ) ;
btnUpdate - > SetVisibility ( false ) ; // update only available if masterserver notifies it
btnUpdate - > SetToolTip ( LoadResStr ( " IDS_DLGTIP_UPDATE " ) ) ;
btnUpdate - > SetText ( LoadResStr ( " IDS_CTL_UPDATE " ) ) ;
AddElement ( btnUpdate ) ;
2010-12-26 20:39:52 +00:00
# endif
2009-05-08 13:28:41 +00:00
// button area
C4GUI : : CallbackButton < C4StartupNetDlg > * btn ;
AddElement ( btn = new C4GUI : : CallbackButton < C4StartupNetDlg > ( LoadResStr ( " IDS_BTN_BACK " ) , caButtons . GetFromLeft ( iButtonWidth ) , & C4StartupNetDlg : : OnBackBtn ) ) ;
btn - > SetToolTip ( LoadResStr ( " IDS_DLGTIP_BACKMAIN " ) ) ;
AddElement ( btnRefresh = new C4GUI : : CallbackButton < C4StartupNetDlg > ( LoadResStr ( " IDS_BTN_RELOAD " ) , caButtons . GetFromLeft ( iButtonWidth ) , & C4StartupNetDlg : : OnRefreshBtn ) ) ;
btnRefresh - > SetToolTip ( LoadResStr ( " IDS_NET_RELOAD_DESC " ) ) ;
AddElement ( btnJoin = new C4GUI : : CallbackButton < C4StartupNetDlg > ( LoadResStr ( " IDS_NET_JOINGAME_BTN " ) , caButtons . GetFromLeft ( iButtonWidth ) , & C4StartupNetDlg : : OnJoinGameBtn ) ) ;
btnJoin - > SetToolTip ( LoadResStr ( " IDS_NET_JOINGAME_DESC " ) ) ;
AddElement ( btn = new C4GUI : : CallbackButton < C4StartupNetDlg > ( LoadResStr ( " IDS_NET_NEWGAME " ) , caButtons . GetFromLeft ( iButtonWidth ) , & C4StartupNetDlg : : OnCreateGameBtn ) ) ;
btn - > SetToolTip ( LoadResStr ( " IDS_NET_NEWGAME_DESC " ) ) ;
// initial dlg mode
UpdateDlgMode ( ) ;
// initial focus
SetFocus ( GetDlgModeFocusControl ( ) , false ) ;
// initialize discovery
DiscoverClient . Init ( Config . Network . PortDiscovery ) ;
DiscoverClient . StartDiscovery ( ) ;
iGameDiscoverInterval = C4NetGameDiscoveryInterval ;
// register timer
Application . Add ( this ) ;
2010-03-27 16:05:02 +00:00
// register as receiver of reference notifies
Application . InteractiveThread . SetCallback ( Ev_HTTP_Response , this ) ;
2009-05-08 13:28:41 +00:00
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
C4StartupNetDlg : : ~ C4StartupNetDlg ( )
2010-03-28 18:58:01 +00:00
{
2010-03-27 16:05:02 +00:00
// disable notifies
Application . InteractiveThread . ClearCallback ( Ev_HTTP_Response , this ) ;
2014-10-04 20:50:34 +00:00
Application . InteractiveThread . RemoveProc ( & pUpdateClient ) ;
2009-05-08 13:28:41 +00:00
DiscoverClient . Close ( ) ;
Application . Remove ( this ) ;
if ( pMasterserverClient ) delete pMasterserverClient ;
// dtor
delete pKeyBack ;
delete pKeyRefresh ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4StartupNetDlg : : DrawElement ( C4TargetFacet & cgo )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// draw background
2013-05-26 15:51:35 +00:00
typedef C4GUI : : FullscreenDialog Base ;
Base : : DrawElement ( cgo ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4StartupNetDlg : : OnShown ( )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// callback when shown: Start searching for games
C4StartupDlg : : OnShown ( ) ;
2014-10-04 20:50:34 +00:00
CheckVersionUpdate ( ) ;
2009-05-08 13:28:41 +00:00
UpdateList ( ) ;
2014-10-05 13:11:06 +00:00
UpdateUpdateButton ( ) ; // in case update check was finished before callback registration
2009-05-08 13:28:41 +00:00
UpdateMasterserver ( ) ;
OnSec1Timer ( ) ;
2017-05-03 18:28:00 +00:00
tLastRefresh = time ( nullptr ) ;
2009-05-08 13:28:41 +00:00
// also update chat
if ( pChatCtrl ) pChatCtrl - > OnShown ( ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4StartupNetDlg : : OnClosed ( bool fOK )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// dlg abort: return to main screen
2016-11-02 23:58:02 +00:00
if ( pMasterserverClient ) { delete pMasterserverClient ; pMasterserverClient = nullptr ; }
2009-05-08 13:28:41 +00:00
if ( ! fOK ) DoBack ( ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
C4GUI : : Control * C4StartupNetDlg : : GetDefaultControl ( )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// default control depends on whether dlg is in chat or game list mode
if ( GetDlgMode ( ) = = SNDM_Chat & & pChatCtrl )
// chat mode: Chat input edit
return pChatCtrl - > GetDefaultControl ( ) ;
else
// game list mode: No default control, because it would move focus away from IP input edit
2016-11-02 23:58:02 +00:00
return nullptr ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
C4GUI : : Control * C4StartupNetDlg : : GetDlgModeFocusControl ( )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// default control depends on whether dlg is in chat or game list mode
if ( GetDlgMode ( ) = = SNDM_Chat & & pChatCtrl )
// chat mode: Chat input edit
return pChatCtrl - > GetDefaultControl ( ) ;
else
// game list mode: Game list box
return pGameSelList ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4StartupNetDlg : : OnBtnGameList ( C4GUI : : Control * btn )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// switch to game list dialog
pMainTabular - > SelectSheet ( SNDM_GameList , true ) ;
UpdateDlgMode ( ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4StartupNetDlg : : OnBtnChat ( C4GUI : : Control * btn )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// toggle chat / game list
if ( pChatCtrl )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
if ( pMainTabular - > GetActiveSheetIndex ( ) = = SNDM_GameList )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
pMainTabular - > SelectSheet ( SNDM_Chat , true ) ;
pChatCtrl - > OnShown ( ) ;
UpdateDlgMode ( ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
else
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
pMainTabular - > SelectSheet ( SNDM_GameList , true ) ;
UpdateDlgMode ( ) ;
2010-01-25 04:00:59 +00:00
}
2009-05-08 13:28:41 +00:00
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4StartupNetDlg : : OnBtnInternet ( C4GUI : : Control * btn )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// toggle masterserver game search
Config . Network . MasterServerSignUp = ! Config . Network . MasterServerSignUp ;
UpdateMasterserver ( ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4StartupNetDlg : : OnBtnRecord ( C4GUI : : Control * btn )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// toggle league signup flag
2015-08-29 12:33:00 +00:00
bool fCheck = ! Game . Record ;
Game . Record = fCheck ;
Config . General . DefRec = fCheck ;
2009-05-08 13:28:41 +00:00
btnRecord - > SetIcon ( fCheck ? C4GUI : : Ico_Ex_RecordOn : C4GUI : : Ico_Ex_RecordOff ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2010-12-26 20:39:52 +00:00
# ifdef WITH_AUTOMATIC_UPDATE
2009-05-08 13:28:41 +00:00
void C4StartupNetDlg : : OnBtnUpdate ( C4GUI : : Control * btn )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// do update
2010-12-01 20:37:47 +00:00
if ( ! C4UpdateDlg : : DoUpdate ( UpdateURL . getData ( ) , GetScreen ( ) ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
GetScreen ( ) - > ShowMessage ( LoadResStr ( " IDS_MSG_UPDATEFAILED " ) , LoadResStr ( " IDS_TYPE_UPDATE " ) , C4GUI : : Ico_Ex_Update ) ;
}
2010-03-28 18:58:01 +00:00
}
2010-12-26 20:39:52 +00:00
# endif
2009-05-08 13:28:41 +00:00
void C4StartupNetDlg : : UpdateMasterserver ( )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// update button icon to current state
btnInternet - > SetIcon ( Config . Network . MasterServerSignUp ? C4GUI : : Ico_Ex_InternetOn : C4GUI : : Ico_Ex_InternetOff ) ;
// creates masterserver object if masterserver is enabled; destroy otherwise
if ( ! Config . Network . MasterServerSignUp = = ! pMasterserverClient ) return ;
if ( ! Config . Network . MasterServerSignUp )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
delete pMasterserverClient ;
2016-11-02 23:58:02 +00:00
pMasterserverClient = nullptr ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
else
2010-03-28 18:58:01 +00:00
{
2016-11-02 23:58:02 +00:00
pMasterserverClient = new C4StartupNetListEntry ( pGameSelList , nullptr , this ) ;
2014-12-12 20:57:52 +00:00
StdStrBuf strVersion ; strVersion . Format ( " %d.%d " , C4XVER1 , C4XVER2 ) ;
2010-12-02 17:21:57 +00:00
StdStrBuf strQuery ; strQuery . Format ( " %s?version=%s&platform=%s " , Config . Network . GetLeagueServerAddress ( ) , strVersion . getData ( ) , C4_OS ) ;
2010-12-01 20:37:47 +00:00
pMasterserverClient - > SetRefQuery ( strQuery . getData ( ) , C4StartupNetListEntry : : NRQT_Masterserver ) ;
2009-05-08 13:28:41 +00:00
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4StartupNetDlg : : UpdateList ( bool fGotReference )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// recursion check
if ( fUpdatingList ) return ;
fUpdatingList = true ;
pGameSelList - > FreezeScrolling ( ) ;
2010-09-19 17:01:31 +00:00
// Games display mask
const char * szGameMask = pSearchFieldEdt - > GetText ( ) ;
if ( ! szGameMask ) szGameMask = " " ;
2009-05-08 13:28:41 +00:00
// Update all child entries
bool fAnyRemoval = false ;
C4GUI : : Element * pElem , * pNextElem = pGameSelList - > GetFirst ( ) ;
2010-01-25 04:00:59 +00:00
while ( ( pElem = pNextElem ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
pNextElem = pElem - > GetNext ( ) ; // determine next exec element now - execution
C4StartupNetListEntry * pEntry = static_cast < C4StartupNetListEntry * > ( pElem ) ;
2010-03-27 16:05:02 +00:00
// do item updates
2010-09-19 17:01:31 +00:00
if ( pEntry - > GetReference ( ) ) pEntry - > SetVisibility ( pEntry - > KeywordMatch ( szGameMask ) ) ;
2010-03-27 16:05:02 +00:00
bool fKeepEntry = true ;
2010-03-28 18:58:01 +00:00
if ( fGotReference )
2010-03-27 16:05:02 +00:00
fKeepEntry = pEntry - > OnReference ( ) ;
2010-03-28 18:58:01 +00:00
if ( fKeepEntry )
2010-03-27 16:05:02 +00:00
fKeepEntry = pEntry - > Execute ( ) ;
2009-05-08 13:28:41 +00:00
// remove?
if ( ! fKeepEntry )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// entry wishes to be removed
// if the selected entry is being removed, the next entry should be selected (which might be the ref for a finished refquery)
if ( pGameSelList - > GetSelectedItem ( ) = = pEntry )
if ( pEntry - > GetNext ( ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
pGameSelList - > SelectEntry ( pEntry - > GetNext ( ) , false ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
delete pEntry ;
fAnyRemoval = true ; // setting any removal will also update collapsed state of all entries; so no need to do updates because of selection change here
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// Add LAN games
C4NetIO : : addr_t Discover ;
while ( DiscoverClient . PopDiscover ( Discover ) )
2010-03-28 18:58:01 +00:00
{
2013-02-18 14:30:00 +00:00
StdStrBuf Address ( Discover . ToString ( ) ) ;
2009-05-08 13:28:41 +00:00
AddReferenceQuery ( Address . getData ( ) , C4StartupNetListEntry : : NRQT_GameDiscovery ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// check whether view needs to be collapsed or uncollapsed
if ( fIsCollapsed & & fAnyRemoval )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// try uncollapsing
fIsCollapsed = false ;
UpdateCollapsed ( ) ;
// if scrolling is still necessary, the view will be collapsed again immediately
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
if ( ! fIsCollapsed & & pGameSelList - > IsScrollingNecessary ( ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
fIsCollapsed = true ;
UpdateCollapsed ( ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
fUpdatingList = false ;
// done; selection might have changed
pGameSelList - > UnFreezeScrolling ( ) ;
UpdateSelection ( false ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4StartupNetDlg : : UpdateCollapsed ( )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// update collapsed state for all child entries
for ( C4GUI : : Element * pElem = pGameSelList - > GetFirst ( ) ; pElem ; pElem = pElem - > GetNext ( ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
C4StartupNetListEntry * pEntry = static_cast < C4StartupNetListEntry * > ( pElem ) ;
pEntry - > UpdateCollapsed ( fIsCollapsed & & pElem ! = pGameSelList - > GetSelectedItem ( ) ) ;
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4StartupNetDlg : : UpdateSelection ( bool fUpdateCollapsed )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// not during list updates - list update call will do this
if ( fUpdatingList ) return ;
// in collapsed view, updating the selection may uncollapse something
if ( fIsCollapsed & & fUpdateCollapsed ) UpdateCollapsed ( ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4StartupNetDlg : : UpdateDlgMode ( )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
DlgMode eMode = GetDlgMode ( ) ;
// buttons for game joining only visible in game list mode
btnInternet - > SetVisibility ( eMode = = SNDM_GameList ) ;
btnRecord - > SetVisibility ( eMode = = SNDM_GameList ) ;
btnJoin - > SetVisibility ( eMode = = SNDM_GameList ) ;
btnRefresh - > SetVisibility ( eMode = = SNDM_GameList ) ;
// focus update
if ( ! GetFocus ( ) ) SetFocus ( GetDlgModeFocusControl ( ) , false ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
C4StartupNetDlg : : DlgMode C4StartupNetDlg : : GetDlgMode ( )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// dlg mode determined by active tabular sheet
if ( pMainTabular - > GetActiveSheetIndex ( ) = = SNDM_Chat ) return SNDM_Chat ; else return SNDM_GameList ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4StartupNetDlg : : OnThreadEvent ( C4InteractiveEventType eEvent , void * pEventData )
2010-03-28 18:58:01 +00:00
{
2014-10-04 20:50:34 +00:00
UpdateUpdateButton ( ) ;
2010-03-27 16:05:02 +00:00
UpdateList ( true ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2014-10-04 20:50:34 +00:00
void C4StartupNetDlg : : UpdateUpdateButton ( )
{
2014-10-05 13:11:06 +00:00
if ( ! fUpdateCheckPending ) return ;
2014-10-04 20:50:34 +00:00
if ( ! pUpdateClient . isSuccess ( ) | | pUpdateClient . isBusy ( ) ) return ;
2016-11-02 23:58:02 +00:00
pUpdateClient . SetNotify ( nullptr ) ;
2014-10-04 20:50:34 +00:00
StdCopyStrBuf versionInfo ;
pUpdateClient . GetVersion ( & versionInfo ) ;
pUpdateClient . GetUpdateURL ( & UpdateURL ) ;
# ifdef WITH_AUTOMATIC_UPDATE
btnUpdate - > SetVisibility ( C4UpdateDlg : : IsValidUpdate ( versionInfo . getData ( ) ) ) ;
# endif
2014-10-05 13:11:06 +00:00
fUpdateCheckPending = false ;
2014-10-04 20:50:34 +00:00
}
2009-05-08 13:28:41 +00:00
bool C4StartupNetDlg : : DoOK ( )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// OK in chat mode? Forward to chat control
if ( GetDlgMode ( ) = = SNDM_Chat ) return pChatCtrl - > DlgEnter ( ) ;
// OK on editbox with text enetered: Add the specified IP for reference retrieval
if ( GetFocus ( ) = = pJoinAddressEdt )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
const char * szDirectJoinAddress = pJoinAddressEdt - > GetText ( ) ;
if ( szDirectJoinAddress & & * szDirectJoinAddress )
2010-03-28 18:58:01 +00:00
{
2010-01-26 02:11:16 +00:00
// First do some acrobatics to avoid trying to resolve addresses with leading
// or trailing whitespace, which is easily pasted in with an IP address.
// We can trivially skip whitespace at the beginning, but we need a copy to
// omit whitespace at the end.
2010-03-28 18:58:01 +00:00
while ( std : : isspace ( * szDirectJoinAddress ) )
2010-01-26 02:11:16 +00:00
// skip whitespace at the beginning
+ + szDirectJoinAddress ;
2010-03-28 18:58:01 +00:00
if ( ! * szDirectJoinAddress )
2010-01-26 02:11:16 +00:00
// entry empty, apart from whitespace
return true ;
const char * szDirectJoinAddressEnd = szDirectJoinAddress + std : : strlen ( szDirectJoinAddress ) - 1 ;
2010-03-28 18:58:01 +00:00
while ( std : : isspace ( * szDirectJoinAddressEnd ) )
2010-01-26 02:11:16 +00:00
// skip whitespace at the end
- - szDirectJoinAddressEnd ;
2010-03-28 18:58:01 +00:00
if ( * + + szDirectJoinAddressEnd )
{
2010-01-26 02:11:16 +00:00
// Make a temporary copy of the part that is not trailing whitespace, if any
std : : string strDirectJoinAddressStripped ( szDirectJoinAddress , szDirectJoinAddressEnd - szDirectJoinAddress ) ;
AddReferenceQuery ( strDirectJoinAddressStripped . c_str ( ) , C4StartupNetListEntry : : NRQT_DirectJoin ) ;
2010-03-28 18:58:01 +00:00
}
2010-01-26 02:11:16 +00:00
else
AddReferenceQuery ( szDirectJoinAddress , C4StartupNetListEntry : : NRQT_DirectJoin ) ;
2009-05-08 13:28:41 +00:00
// Switch focus to list so another OK joins the specified address
SetFocus ( pGameSelList , true ) ;
return true ;
}
2010-03-28 18:58:01 +00:00
}
2010-09-19 17:01:31 +00:00
if ( GetFocus ( ) = = pSearchFieldEdt )
{
UpdateList ( ) ;
return true ;
}
2009-05-08 13:28:41 +00:00
// get currently selected item
C4GUI : : Element * pSelection = pGameSelList - > GetSelectedItem ( ) ;
2010-03-28 18:58:01 +00:00
StdCopyStrBuf strNoJoin ( LoadResStr ( " IDS_NET_NOJOIN " ) ) ;
if ( ! pSelection )
{
2009-05-08 13:28:41 +00:00
// no ref selected: Oh noes!
2009-06-05 16:53:56 +00:00
: : pGUI - > ShowMessageModal (
2010-03-28 18:58:01 +00:00
LoadResStr ( " IDS_NET_NOJOIN_NOREF " ) ,
strNoJoin . getData ( ) ,
C4GUI : : MessageDialog : : btnOK ,
C4GUI : : Ico_Error ) ;
return true ;
}
2009-05-08 13:28:41 +00:00
C4StartupNetListEntry * pRefEntry = static_cast < C4StartupNetListEntry * > ( pSelection ) ;
const char * szError ;
2010-01-25 04:00:59 +00:00
if ( ( szError = pRefEntry - > GetError ( ) ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// erroneous ref selected: Oh noes!
2009-06-05 16:53:56 +00:00
: : pGUI - > ShowMessageModal (
2010-03-28 18:58:01 +00:00
FormatString ( LoadResStr ( " IDS_NET_NOJOIN_BADREF " ) , szError ) . getData ( ) ,
strNoJoin . getData ( ) ,
C4GUI : : MessageDialog : : btnOK ,
C4GUI : : Ico_Error ) ;
2009-05-08 13:28:41 +00:00
return true ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
C4Network2Reference * pRef = pRefEntry - > GetReference ( ) ;
const char * szDirectJoinAddress = pRefEntry - > GetJoinAddress ( ) ;
if ( ! pRef & & ! ( szDirectJoinAddress & & * szDirectJoinAddress ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// something strange has been selected (e.g., a masterserver entry). Error.
2009-06-05 16:53:56 +00:00
: : pGUI - > ShowMessageModal (
2010-03-28 18:58:01 +00:00
LoadResStr ( " IDS_NET_NOJOIN_NOREF " ) ,
strNoJoin . getData ( ) ,
C4GUI : : MessageDialog : : btnOK ,
C4GUI : : Ico_Error ) ;
return true ;
}
2009-05-08 13:28:41 +00:00
// check if join to this reference is possible at all
if ( pRef )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// version mismatch
C4GameVersion verThis ;
if ( ! ( pRef - > getGameVersion ( ) = = verThis ) )
2010-03-28 18:58:01 +00:00
{
2009-06-05 16:53:56 +00:00
: : pGUI - > ShowMessageModal (
2010-03-28 18:58:01 +00:00
FormatString ( LoadResStr ( " IDS_NET_NOJOIN_BADVER " ) ,
pRef - > getGameVersion ( ) . GetString ( ) . getData ( ) ,
verThis . GetString ( ) . getData ( ) ) . getData ( ) ,
strNoJoin . getData ( ) ,
C4GUI : : MessageDialog : : btnOK ,
C4GUI : : Ico_Error ) ;
2009-05-08 13:28:41 +00:00
return true ;
2010-03-28 18:58:01 +00:00
}
2018-01-28 16:34:45 +00:00
if ( pRef - > getGameStatus ( ) . isPastLobby ( ) )
2010-03-28 18:58:01 +00:00
{
2018-01-28 16:34:45 +00:00
// no runtime join
if ( ! pRef - > isJoinAllowed ( ) )
2010-03-28 18:58:01 +00:00
{
2018-01-28 16:34:45 +00:00
if ( ! : : pGUI - > ShowMessageModal (
LoadResStr ( " IDS_NET_NOJOIN_NORUNTIME " ) ,
strNoJoin . getData ( ) ,
C4GUI : : MessageDialog : : btnYes | C4GUI : : MessageDialog : : btnNo ,
C4GUI : : Ico_Error ) )
{
return true ;
}
}
else
{
if ( ! : : pGUI - > ShowMessageModal (
LoadResStr ( " IDS_NET_NOJOIN_RUNTIMEBROKEN " ) ,
strNoJoin . getData ( ) ,
C4GUI : : MessageDialog : : btnYes | C4GUI : : MessageDialog : : btnNo ,
C4GUI : : Ico_Error ) )
{
return true ;
}
2009-05-08 13:28:41 +00:00
}
}
2010-03-28 18:58:01 +00:00
}
2016-08-10 23:35:07 +00:00
// OK; joining!
if ( pRef - > isEditor ( ) )
{
bool success = false ;
// Editor mode join: Serialize reference to temp file and join on that
// (could pass through environment, but that's hard to do platform-independent
// (QProcessEnvironment? But then there's a Qt dependency in the network init code))
2016-10-31 00:40:40 +00:00
StdStrBuf tmpfn ( Config . AtTempPath ( " ocjoin " ) , true ) ;
2016-08-10 23:35:07 +00:00
MakeTempFilename ( & tmpfn ) ;
2018-02-17 23:30:08 +00:00
StdStrBuf join_data = DecompileToBuf < StdCompilerINIWrite > ( mkNamingAdapt ( * pRef , " Reference " ) ) ;
2016-08-10 23:35:07 +00:00
if ( join_data . getSize ( ) )
{
if ( join_data . SaveToFile ( tmpfn . getData ( ) ) )
{
2016-08-11 20:11:15 +00:00
if ( RestartApplication ( { " --editor " , FormatString ( " --join=%s%s " , C4Game : : DirectJoinFilePrefix , tmpfn . getData ( ) ) . getData ( ) } ) ) // hope for no " in temp path
2016-08-10 23:35:07 +00:00
{
// Application.Quit() has been called. Will quit after returning from this callback.
// The temp file will be deleted by the new instance
success = true ;
}
else
{
EraseFile ( tmpfn . getData ( ) ) ;
}
}
}
if ( ! success )
{
C4GUI : : TheScreen . ShowErrorMessage ( LoadResStr ( " IDS_ERR_STARTEDITOR " ) ) ;
}
return true ;
}
else
{
// Player mode join
// Take over reference
pRefEntry - > GrabReference ( ) ;
// Set join parameters
* Game . ScenarioFilename = ' \0 ' ;
if ( szDirectJoinAddress ) SCopy ( szDirectJoinAddress , Game . DirectJoinAddress , _MAX_PATH ) ; else * Game . DirectJoinAddress = ' \0 ' ;
SCopy ( " Objects.ocd " , Game . DefinitionFilenames ) ;
Game . NetworkActive = true ;
Game . fObserve = false ;
Game . pJoinReference . reset ( pRef ) ;
// start with this set!
Application . OpenGame ( ) ;
return true ;
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
bool C4StartupNetDlg : : DoBack ( )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// abort dialog: Back to main
C4Startup : : Get ( ) - > SwitchDialog ( C4Startup : : SDID_Back ) ;
return true ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4StartupNetDlg : : DoRefresh ( )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// check min refresh timer
2017-05-03 18:28:00 +00:00
time_t tNow = time ( nullptr ) ;
2009-05-08 13:28:41 +00:00
if ( tLastRefresh & & tNow < tLastRefresh + C4NetMinRefreshInterval )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// avoid hammering on refresh key
2015-12-13 21:14:55 +00:00
C4GUI : : GUISound ( " UI::Error " ) ;
2009-05-08 13:28:41 +00:00
return ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
tLastRefresh = tNow ;
// empty list of all old entries
fUpdatingList = true ;
while ( pGameSelList - > GetFirst ( ) ) delete pGameSelList - > GetFirst ( ) ;
2016-11-02 23:58:02 +00:00
pMasterserverClient = nullptr ;
2009-05-08 13:28:41 +00:00
// (Re-)Start discovery
2010-03-28 18:58:01 +00:00
if ( ! DiscoverClient . StartDiscovery ( ) )
{
StdCopyStrBuf strNoDiscovery ( LoadResStr ( " IDS_NET_NODISCOVERY " ) ) ;
2009-06-05 16:53:56 +00:00
: : pGUI - > ShowMessageModal (
2010-03-28 18:58:01 +00:00
FormatString ( LoadResStr ( " IDS_NET_NODISCOVERY_DESC " ) , DiscoverClient . GetError ( ) ) . getData ( ) ,
strNoDiscovery . getData ( ) ,
C4GUI : : MessageDialog : : btnAbort ,
C4GUI : : Ico_Error ) ;
}
2009-05-08 13:28:41 +00:00
iGameDiscoverInterval = C4NetGameDiscoveryInterval ;
// restart masterserver query
UpdateMasterserver ( ) ;
// done; update stuff
fUpdatingList = false ;
UpdateList ( ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4StartupNetDlg : : CreateGame ( )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
C4Startup : : Get ( ) - > SwitchDialog ( C4Startup : : SDID_ScenSelNetwork ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4StartupNetDlg : : OnSec1Timer ( )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// no updates if dialog is inactive (e.g., because a join password dlg is shown!)
if ( ! IsActive ( true ) )
return ;
// Execute discovery
if ( ! iGameDiscoverInterval - - )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
DiscoverClient . StartDiscovery ( ) ;
iGameDiscoverInterval = C4NetGameDiscoveryInterval ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
DiscoverClient . Execute ( 0 ) ;
UpdateList ( false ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4StartupNetDlg : : AddReferenceQuery ( const char * szAddress , C4StartupNetListEntry : : QueryType eQueryType )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// Check for an active reference query to the same address
2010-03-28 18:58:01 +00:00
for ( C4GUI : : Element * pElem = pGameSelList - > GetFirst ( ) ; pElem ; pElem = pElem - > GetNext ( ) )
{
2009-05-08 13:28:41 +00:00
C4StartupNetListEntry * pEntry = static_cast < C4StartupNetListEntry * > ( pElem ) ;
// same address
2010-03-28 18:58:01 +00:00
if ( pEntry - > IsSameRefQueryAddress ( szAddress ) )
{
2009-05-08 13:28:41 +00:00
// nothing to do, xcept maybe select it
if ( eQueryType = = C4StartupNetListEntry : : NRQT_DirectJoin ) pGameSelList - > SelectEntry ( pEntry , true ) ;
return ;
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// No reference from same host found - create a new entry
2016-11-02 23:58:02 +00:00
C4StartupNetListEntry * pEntry = new C4StartupNetListEntry ( pGameSelList , nullptr , this ) ;
2009-05-08 13:28:41 +00:00
pEntry - > SetRefQuery ( szAddress , eQueryType ) ;
if ( eQueryType = = C4StartupNetListEntry : : NRQT_DirectJoin )
pGameSelList - > SelectEntry ( pEntry , true ) ;
else if ( fIsCollapsed )
pEntry - > UpdateCollapsed ( true ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4StartupNetDlg : : OnReferenceEntryAdd ( C4StartupNetListEntry * pEntry )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// collapse the new entry if desired
if ( fIsCollapsed & & pEntry ! = pGameSelList - > GetSelectedItem ( ) )
pEntry - > UpdateCollapsed ( true ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2014-10-04 20:50:34 +00:00
void C4StartupNetDlg : : CheckVersionUpdate ( )
2010-03-28 18:58:01 +00:00
{
2014-10-04 21:01:53 +00:00
# ifdef WITH_AUTOMATIC_UPDATE
2014-12-12 20:57:52 +00:00
StdStrBuf strVersion ; strVersion . Format ( " %d.%d " , C4XVER1 , C4XVER2 ) ;
2014-10-04 20:50:34 +00:00
StdStrBuf strQuery ; strQuery . Format ( " %s?version=%s&platform=%s&action=version " , Config . Network . UpdateServerAddress , strVersion . getData ( ) , C4_OS ) ;
if ( pUpdateClient . Init ( ) & & pUpdateClient . SetServer ( strQuery . getData ( ) ) & & pUpdateClient . QueryUpdateURL ( ) )
2010-12-26 20:39:52 +00:00
{
2014-10-04 20:50:34 +00:00
pUpdateClient . SetNotify ( & Application . InteractiveThread ) ;
Application . InteractiveThread . AddProc ( & pUpdateClient ) ;
2010-12-26 20:39:52 +00:00
}
2014-10-05 13:11:06 +00:00
fUpdateCheckPending = true ;
2014-10-04 21:01:53 +00:00
# endif
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4StartupNetDlg : : OnChatTitleChange ( const StdStrBuf & sNewTitle )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// update label
if ( pChatTitleLabel ) pChatTitleLabel - > SetText ( FormatString ( " %s - %s " , LoadResStr ( " IDS_DLG_CHAT " ) , sNewTitle . getData ( ) ) . getData ( ) ) ;
2010-03-28 18:58:01 +00:00
}