1 /* 2 * OpenClonk, http://www.openclonk.org 3 * 4 * Copyright (c) 2006-2009, RedWolf Design GmbH, http://www.clonk.de/ 5 * Copyright (c) 2010-2016, The OpenClonk Team and contributors 6 * 7 * Distributed under the terms of the ISC license; see accompanying file 8 * "COPYING" for details. 9 * 10 * "Clonk" is a registered trademark of Matthes Bender, used with permission. 11 * See accompanying file "TRADEMARK" for details. 12 * 13 * To redistribute this file separately, substitute the full license texts 14 * for the above references. 15 */ 16 // Startup screen for non-parameterized engine start: Network game selection dialog 17 18 #ifndef INC_C4StartupNetDlg 19 #define INC_C4StartupNetDlg 20 21 #include "gui/C4Startup.h" 22 #include "network/C4Network2Discover.h" 23 #include "network/C4Network2Reference.h" 24 25 // ----------------------------------------------- 26 27 const int C4NetMasterServerQueryInterval = 30; // seconds after last and beforenew game query to master server 28 const int C4NetRefRequestTimeout = 12; // seconds after which the reference request is interrupted 29 const int C4NetReferenceTimeout = 42; // seconds after which references are removed from the list (C4NetRefRequestTimeout + C4NetMasterServerQueryInterval) 30 const int C4NetErrorRefTimeout = 10; // seconds after which failed reference requestsare removed 31 const int C4NetGameDiscoveryInterval = 30; // seconds 32 const int C4NetMinRefreshInterval = 1; // seconds; minimum time between refreshes 33 34 35 class C4StartupNetListEntry : public C4GUI::Window 36 { 37 public: 38 C4StartupNetListEntry(C4GUI::ListBox *pForListBox, C4GUI::Element *pInsertBefore, class C4StartupNetDlg *pNetDlg); 39 ~C4StartupNetListEntry() override; 40 41 enum QueryType // where the game ref is coming from 42 { 43 NRQT_Unknown, // unknown source 44 NRQT_GameDiscovery, // by UDP broadcast in local network 45 NRQT_Masterserver, // by internet masterserver 46 NRQT_DirectJoin // by user-entered address 47 }; 48 49 enum TimeoutType 50 { 51 TT_RefReqWait, // C4NetMasterServerQueryInterval for masterserver; C4NetErrorRefTimeout for other ref clients 52 TT_Reference, // C4NetReferenceTimeout 53 TT_Masterserver // C4NetMasterServerQueryInterval 54 }; 55 56 enum { InfoLabelCount=5, MaxInfoIconCount=10 }; 57 58 private: 59 C4StartupNetDlg *pNetDlg; 60 C4GUI::ListBox *pList; 61 StdStrBuf sRefClientAddress; // set during reference retrieval: reference server address 62 C4Network2RefClient *pRefClient; // set during reference retrieval: reference request client 63 C4Network2Reference *pRef; // set for retrieved references 64 65 bool fError; // if set, the label was changed to an error message and no more updates are done 66 StdStrBuf sError; 67 QueryType eQueryType; // valid if pRefClient is set: Where the ref query is originating 68 69 time_t iTimeout; // lifetime: If set, marks time when the item is removed or should re-query 70 time_t iRequestTimeout; // if this times out while the request remains busy, the ref client assumes that the tcp socket blocked upon request and aborts it 71 72 C4GUI::Icon *pIcon; // scenario icon 73 C4GUI::Label *pInfoLbl[InfoLabelCount]; // info labels for reference or query 74 C4GUI::Icon *pInfoIcons[MaxInfoIconCount]; // right-aligned status icons at topright position 75 int32_t iInfoIconCount; 76 int32_t iSortOrder; 77 bool fIsSmall; // set if the item is in collapsed state 78 bool fIsCollapsed; // set if the item is forced to collapsed state 79 bool fIsEnabled; // if not set, the item is grayed out 80 bool fIsImportant; // if set, the item is presented in yellow (lower priority than fIsEnabled) 81 C4Rect rctIconSmall; // bounds for small icon 82 C4Rect rctIconLarge; // bounds for large icon 83 84 StdStrBuf sInfoText[InfoLabelCount]; 85 86 bool QueryReferences(); 87 static const char *GetQueryTypeName(QueryType eQueryType); // name of QueryType values 88 void SetError(const char *szErrorText, TimeoutType eTimeout); // change secondary label to error label, mark error and set a removal timer 89 void SetTimeout(TimeoutType eTimeout); 90 C4StartupNetListEntry *AddReference(C4Network2Reference *pAddRef, C4GUI::Element *pInsertBefore); // add a reference list item to the same list InvalidateStatusIcons()91 void InvalidateStatusIcons() { iInfoIconCount=0; } // schedule all current status icons for removal when UpdateText is called next 92 void AddStatusIcon(C4GUI::Icons eIcon, const char *szToolTip); // add a status icon with the specified tooltip 93 94 void UpdateSmallState(); 95 void UpdateEntrySize(); 96 void UpdateText(); // strings to labels 97 98 protected: GetListItemTopSpacing()99 int32_t GetListItemTopSpacing() override { return fIsCollapsed ? 5 : 10; } 100 void DrawElement(C4TargetFacet &cgo) override; 101 102 C4GUI::Element* GetNextLower(int32_t sortOrder); // returns the element before which this element should be inserted 103 104 public: 105 void ClearRef(); // del any ref/refclient/error data 106 void SetRefQuery(const char *szAddress, QueryType eQueryType); // start loading references fromt he specified address 107 void SetReference(C4Network2Reference *pNewRef); // replace the reference 108 109 bool Execute(); // update stuff - if false is returned, the item is to be removed 110 bool OnReference(); // like Execute(), but only called if some reference was received 111 void UpdateCollapsed(bool fToCollapseValue); 112 void SetVisibility(bool fToValue) override; 113 GetError()114 const char *GetError() { return fError ? sError.getData() : nullptr; } // return error message, if any is set 115 C4Network2Reference *GrabReference(); // grab the reference so it won't be deleted when this item is removed GetReference()116 C4Network2Reference *GetReference() const { return pRef; } // have a look at the reference 117 bool IsSameHost(const C4Network2Reference *pRef2); // check whether the reference was created by the same host as this one 118 bool IsSameAddress(const C4Network2Reference *pRef2); // check whether there is at least one matching address (address and port) 119 bool IsSameRefQueryAddress(const char *szJoinAddress); // check whether reference query was created with same host address 120 bool KeywordMatch(const char *szMatch); // check whether any of the reference contents match a given keyword 121 const char *GetJoinAddress(); // ref queries only: Get direct join address 122 123 }; 124 125 // startup dialog: Network game selection 126 class C4StartupNetDlg : public C4StartupDlg, private C4InteractiveThread::Callback, private C4ApplicationSec1Timer 127 { 128 public: 129 C4StartupNetDlg(); // ctor 130 ~C4StartupNetDlg() override; // dtor 131 132 private: 133 enum DlgMode { SNDM_GameList=0, SNDM_Chat=1 }; 134 C4GUI::Tabular *pMainTabular; // main tabular control: Contains game selection list and chat control 135 C4GUI::ListBox *pGameSelList; // game selection listbox 136 C4KeyBinding *pKeyRefresh, *pKeyBack, *pKeyForward; 137 C4GUI::CallbackButton<C4StartupNetDlg, C4GUI::IconButton> *btnGameList , *btnChat; // left side buttons 138 C4GUI::CallbackButton<C4StartupNetDlg, C4GUI::IconButton> *btnInternet, *btnRecord; // right side buttons 139 #ifdef WITH_AUTOMATIC_UPDATE 140 C4GUI::CallbackButton<C4StartupNetDlg, C4GUI::IconButton> *btnUpdate; 141 #endif 142 C4GUI::Button *btnJoin, *btnRefresh; 143 C4GUI::Edit *pJoinAddressEdt; 144 C4GUI::Edit *pSearchFieldEdt; 145 class C4ChatControl *pChatCtrl; 146 C4GUI::WoodenLabel *pChatTitleLabel{nullptr}; 147 C4StartupNetListEntry *pMasterserverClient{nullptr}; // set if masterserver query is enabled: Checks clonk.de for new games 148 bool fIsCollapsed{false}; // set if the number of games in the list requires them to be displayed in a condensed format 149 bool fUpdatingList{false}; // set during list update - prevent selection update calls 150 StdCopyStrBuf UpdateURL; // set if update button is visible: Version to be updated to 151 152 C4Network2IODiscoverClient DiscoverClient; // disocver client to search for local hosts 153 int iGameDiscoverInterval{0}; // next time until a game discovery is started 154 time_t tLastRefresh{0}; // time of last refresh 155 156 157 protected: HasBackground()158 bool HasBackground() override { return false; } 159 void DrawElement(C4TargetFacet &cgo) override; 160 161 C4GUI::Control *GetDefaultControl() override; // get Auto-Focus control 162 C4GUI::Control *GetDlgModeFocusControl(); // get control to be focused when main tabular sheet changes 163 OnEnter()164 bool OnEnter() override { DoOK(); return true; } OnEscape()165 bool OnEscape() override { DoBack(); return true; } KeyBack()166 bool KeyBack() { return DoBack(); } KeyRefresh()167 bool KeyRefresh() { DoRefresh(); return true; } KeyForward()168 bool KeyForward() { DoOK(); return true; } 169 170 void OnShown() override; // callback when shown: Start searching for games 171 void OnClosed(bool fOK) override; // callback when dlg got closed: Return to main screen OnBackBtn(C4GUI::Control * btn)172 void OnBackBtn(C4GUI::Control *btn) { DoBack(); } OnRefreshBtn(C4GUI::Control * btn)173 void OnRefreshBtn(C4GUI::Control *btn) { DoRefresh(); } OnCreateGameBtn(C4GUI::Control * btn)174 void OnCreateGameBtn(C4GUI::Control *btn) { CreateGame(); } OnJoinGameBtn(C4GUI::Control * btn)175 void OnJoinGameBtn(C4GUI::Control *btn) { DoOK(); } OnSelChange(class C4GUI::Element * pEl)176 void OnSelChange(class C4GUI::Element *pEl) { UpdateSelection(true); } OnSelDblClick(class C4GUI::Element * pEl)177 void OnSelDblClick(class C4GUI::Element *pEl) { DoOK(); } 178 void OnBtnGameList(C4GUI::Control *btn); 179 void OnBtnChat(C4GUI::Control *btn); 180 void OnBtnInternet(C4GUI::Control *btn); 181 void OnBtnRecord(C4GUI::Control *btn); 182 #ifdef WITH_AUTOMATIC_UPDATE 183 void OnBtnUpdate(C4GUI::Control *btn); 184 #endif OnJoinAddressEnter(C4GUI::Edit * edt,bool fPasting,bool fPastingMore)185 C4GUI::Edit::InputResult OnJoinAddressEnter(C4GUI::Edit *edt, bool fPasting, bool fPastingMore) 186 { DoOK(); return C4GUI::Edit::IR_Abort; } OnSearchFieldEnter(C4GUI::Edit * edt,bool fPasting,bool fPastingMore)187 C4GUI::Edit::InputResult OnSearchFieldEnter(C4GUI::Edit *edt, bool fPasting, bool fPastingMore) 188 { DoOK(); return C4GUI::Edit::IR_Abort; } 189 void OnChatTitleChange(const StdStrBuf &sNewTitle); 190 191 private: 192 void UpdateMasterserver(); // creates masterserver object if masterserver is enabled; destroy otherwise 193 void UpdateList(bool fGotReference = false); 194 void UpdateUpdateButton(); 195 void UpdateCollapsed(); 196 void UpdateSelection(bool fUpdateCollapsed); 197 void UpdateDlgMode(); // update button visibility after switching between game sel list and chat 198 199 void AddReferenceQuery(const char *szAddress, C4StartupNetListEntry::QueryType eQueryType); // add a ref searcher entry and start searching 200 201 // set during update information retrieval 202 C4Network2UpdateClient pUpdateClient; 203 bool fUpdateCheckPending{false}; 204 205 DlgMode GetDlgMode(); 206 207 // callback from C4Network2ReferenceClient 208 void OnThreadEvent(C4InteractiveEventType eEvent, void *pEventData) override; 209 210 public: 211 bool DoOK(); // join currently selected item 212 bool DoBack(); // abort dialog 213 void DoRefresh(); // restart network search 214 void CreateGame(); // switch to scenario selection in network mode 215 216 void OnReferenceEntryAdd(C4StartupNetListEntry *pEntry); 217 218 void OnSec1Timer() override; // idle proc: update list 219 220 void CheckVersionUpdate(); // check if a new update is available and make an update button visible if yes 221 }; 222 223 224 #endif // INC_C4StartupNetDlg 225