LANAPI.cpp 33 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298
  1. /*
  2. ** Command & Conquer Generals Zero Hour(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. ////////////////////////////////////////////////////////////////////////////////
  19. // //
  20. // (c) 2001-2003 Electronic Arts Inc. //
  21. // //
  22. ////////////////////////////////////////////////////////////////////////////////
  23. #include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
  24. #define WIN32_LEAN_AND_MEAN // only bare bones windows stuff wanted
  25. #include "Common/CRC.h"
  26. #include "Common/GameState.h"
  27. #include "Common/Registry.h"
  28. #include "GameNetwork/LANAPI.h"
  29. #include "GameNetwork/NetworkUtil.h"
  30. #include "Common/GlobalData.h"
  31. #include "Common/RandomValue.h"
  32. #include "GameClient/GameText.h"
  33. #include "GameClient/MapUtil.h"
  34. #include "Common/UserPreferences.h"
  35. #include "GameLogic/GameLogic.h"
  36. #ifdef _INTERNAL
  37. // for occasional debugging...
  38. //#pragma optimize("", off)
  39. //#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
  40. #endif
  41. static const UnsignedShort lobbyPort = 8086; ///< This is the UDP port used by all LANAPI communication
  42. AsciiString GetMessageTypeString(UnsignedInt type);
  43. const UnsignedInt LANAPI::s_resendDelta = 10 * 1000; ///< This is how often we announce ourselves to the world
  44. /*
  45. LANGame::LANGame( void )
  46. {
  47. m_gameName = L"";
  48. int player;
  49. for (player = 0; player < MAX_SLOTS; ++player)
  50. {
  51. m_playerName[player] = L"";
  52. m_playerIP[player]= 0;
  53. m_playerAccepted[player] = false;
  54. }
  55. m_lastHeard = 0;
  56. m_inProgress = false;
  57. m_next = NULL;
  58. }
  59. */
  60. LANAPI::LANAPI( void ) : m_transport(NULL)
  61. {
  62. DEBUG_LOG(("LANAPI::LANAPI() - max game option size is %d, sizeof(LANMessage)=%d, MAX_PACKET_SIZE=%d\n",
  63. m_lanMaxOptionsLength, sizeof(LANMessage), MAX_PACKET_SIZE));
  64. m_lastResendTime = 0;
  65. //
  66. m_lobbyPlayers = NULL;
  67. m_games = NULL;
  68. m_name = L""; // safe default?
  69. m_pendingAction = ACT_NONE;
  70. m_expiration = 0;
  71. m_localIP = 0;
  72. m_inLobby = true;
  73. m_isInLANMenu = TRUE;
  74. m_currentGame = NULL;
  75. m_broadcastAddr = INADDR_BROADCAST;
  76. m_directConnectRemoteIP = 0;
  77. m_actionTimeout = 5000; // ms
  78. m_lastUpdate = 0;
  79. m_transport = new Transport;
  80. m_isActive = TRUE;
  81. }
  82. LANAPI::~LANAPI( void )
  83. {
  84. reset();
  85. if (m_transport)
  86. delete m_transport;
  87. }
  88. void LANAPI::init( void )
  89. {
  90. m_gameStartTime = 0;
  91. m_gameStartSeconds = 0;
  92. m_transport->reset();
  93. m_transport->init(m_localIP, lobbyPort);
  94. m_transport->allowBroadcasts(true);
  95. m_pendingAction = ACT_NONE;
  96. m_expiration = 0;
  97. m_inLobby = true;
  98. m_isInLANMenu = TRUE;
  99. m_currentGame = NULL;
  100. m_directConnectRemoteIP = 0;
  101. m_lastGameopt = "";
  102. unsigned long bufSize = UNLEN + 1;
  103. char userName[UNLEN + 1];
  104. if (!GetUserName(userName, &bufSize))
  105. {
  106. strcpy(userName, "unknown");
  107. }
  108. m_userName = userName;
  109. bufSize = MAX_COMPUTERNAME_LENGTH + 1;
  110. char computerName[MAX_COMPUTERNAME_LENGTH + 1];
  111. if (!GetComputerName(computerName, &bufSize))
  112. {
  113. strcpy(computerName, "unknown");
  114. }
  115. m_hostName = computerName;
  116. }
  117. void LANAPI::reset( void )
  118. {
  119. if (m_inLobby)
  120. {
  121. LANMessage msg;
  122. fillInLANMessage( &msg );
  123. msg.LANMessageType = LANMessage::MSG_REQUEST_LOBBY_LEAVE;
  124. sendMessage(&msg);
  125. }
  126. m_transport->update();
  127. LANGameInfo *theGame = m_games;
  128. LANGameInfo *deletableGame = NULL;
  129. while (theGame)
  130. {
  131. deletableGame = theGame;
  132. theGame = theGame->getNext();
  133. delete deletableGame;
  134. }
  135. LANPlayer *thePlayer = m_lobbyPlayers;
  136. LANPlayer *deletablePlayer = NULL;
  137. while (thePlayer)
  138. {
  139. deletablePlayer = thePlayer;
  140. thePlayer = thePlayer->getNext();
  141. delete deletablePlayer;
  142. }
  143. m_games = NULL;
  144. m_lobbyPlayers = NULL;
  145. m_directConnectRemoteIP = 0;
  146. m_pendingAction = ACT_NONE;
  147. m_expiration = 0;
  148. m_inLobby = true;
  149. m_isInLANMenu = TRUE;
  150. m_currentGame = NULL;
  151. }
  152. void LANAPI::sendMessage(LANMessage *msg, UnsignedInt ip /* = 0 */)
  153. {
  154. if (ip != 0)
  155. {
  156. m_transport->queueSend(ip, lobbyPort, (unsigned char *)msg, sizeof(LANMessage) /*, 0, 0 */);
  157. }
  158. else if ((m_currentGame != NULL) && (m_currentGame->getIsDirectConnect()))
  159. {
  160. Int localSlot = m_currentGame->getLocalSlotNum();
  161. for (Int i = 0; i < MAX_SLOTS; ++i)
  162. {
  163. if (i != localSlot) {
  164. GameSlot *slot = m_currentGame->getSlot(i);
  165. if ((slot != NULL) && (slot->isHuman())) {
  166. m_transport->queueSend(slot->getIP(), lobbyPort, (unsigned char *)msg, sizeof(LANMessage) /*, 0, 0 */);
  167. }
  168. }
  169. }
  170. }
  171. else
  172. {
  173. m_transport->queueSend(m_broadcastAddr, lobbyPort, (unsigned char *)msg, sizeof(LANMessage) /*, 0, 0 */);
  174. }
  175. }
  176. AsciiString GetMessageTypeString(UnsignedInt type)
  177. {
  178. AsciiString returnString;
  179. switch (type)
  180. {
  181. case LANMessage::MSG_REQUEST_LOCATIONS:
  182. returnString.format( "Request Locations (%d)",type);
  183. break;
  184. case LANMessage::MSG_GAME_ANNOUNCE:
  185. returnString.format("Game Announce (%d)",type);
  186. break;
  187. case LANMessage::MSG_LOBBY_ANNOUNCE:
  188. returnString.format("Lobby Announce (%d)",type);
  189. break;
  190. case LANMessage::MSG_REQUEST_JOIN:
  191. returnString.format("Request Join (%d)",type);
  192. break;
  193. case LANMessage::MSG_JOIN_ACCEPT:
  194. returnString.format("Join Accept (%d)",type);
  195. break;
  196. case LANMessage::MSG_JOIN_DENY:
  197. returnString.format("Join Deny (%d)",type);
  198. break;
  199. case LANMessage::MSG_REQUEST_GAME_LEAVE:
  200. returnString.format("Request Game Leave (%d)",type);
  201. break;
  202. case LANMessage::MSG_REQUEST_LOBBY_LEAVE:
  203. returnString.format("Request Lobby Leave (%d)",type);
  204. break;
  205. case LANMessage::MSG_SET_ACCEPT:
  206. returnString.format("Set Accept(%d)",type);
  207. break;
  208. case LANMessage::MSG_CHAT:
  209. returnString.format("Chat (%d)",type);
  210. break;
  211. case LANMessage::MSG_GAME_START:
  212. returnString.format("Game Start (%d)",type);
  213. break;
  214. case LANMessage::MSG_GAME_START_TIMER:
  215. returnString.format("Game Start Timer (%d)",type);
  216. break;
  217. case LANMessage::MSG_GAME_OPTIONS:
  218. returnString.format("Game Options (%d)",type);
  219. break;
  220. case LANMessage::MSG_REQUEST_GAME_INFO:
  221. returnString.format("Request GameInfo (%d)", type);
  222. break;
  223. case LANMessage::MSG_INACTIVE:
  224. returnString.format("Inactive (%d)", type);
  225. break;
  226. default:
  227. returnString.format("Unknown Message (%d)",type);
  228. }
  229. return returnString;
  230. }
  231. void LANAPI::checkMOTD( void )
  232. {
  233. #if defined(_DEBUG) || defined(_INTERNAL)
  234. if (TheGlobalData->m_useLocalMOTD)
  235. {
  236. // for a playtest, let's log some play statistics, eh?
  237. if (TheGlobalData->m_playStats <= 0)
  238. TheWritableGlobalData->m_playStats = 30;
  239. static UnsignedInt oldMOTDCRC = 0;
  240. UnsignedInt newMOTDCRC = 0;
  241. AsciiString asciiMOTD;
  242. char buf[4096];
  243. FILE *fp = fopen(TheGlobalData->m_MOTDPath.str(), "r");
  244. Int len;
  245. if (fp)
  246. {
  247. while( (len = fread(buf, 1, 4096, fp)) > 0 )
  248. {
  249. buf[len] = 0;
  250. asciiMOTD.concat(buf);
  251. }
  252. fclose(fp);
  253. CRC crcObj;
  254. crcObj.computeCRC(asciiMOTD.str(), asciiMOTD.getLength());
  255. newMOTDCRC = crcObj.get();
  256. }
  257. if (oldMOTDCRC != newMOTDCRC)
  258. {
  259. // different MOTD... display it
  260. oldMOTDCRC = newMOTDCRC;
  261. AsciiString line;
  262. while (asciiMOTD.nextToken(&line, "\n"))
  263. {
  264. if (line.getCharAt(line.getLength()-1) == '\r')
  265. line.removeLastChar(); // there is a trailing '\r'
  266. if (line.isEmpty())
  267. {
  268. line = " ";
  269. }
  270. UnicodeString uniLine;
  271. uniLine.translate(line);
  272. OnChat( UnicodeString(L"MOTD"), 0, uniLine, LANCHAT_SYSTEM );
  273. }
  274. }
  275. }
  276. #endif
  277. }
  278. extern Bool LANbuttonPushed;
  279. extern Bool LANSocketErrorDetected;
  280. void LANAPI::update( void )
  281. {
  282. if(LANbuttonPushed)
  283. return;
  284. static const UnsignedInt LANAPIUpdateDelay = 200;
  285. UnsignedInt now = timeGetTime();
  286. if( now > m_lastUpdate + LANAPIUpdateDelay)
  287. {
  288. m_lastUpdate = now;
  289. }
  290. else
  291. {
  292. return;
  293. }
  294. // Let the UDP socket breathe
  295. if ((m_transport->update() == FALSE) && (LANSocketErrorDetected == FALSE)) {
  296. if (m_isInLANMenu == TRUE) {
  297. LANSocketErrorDetected = TRUE;
  298. }
  299. }
  300. // Handle any new messages
  301. int i;
  302. for (i=0; i<MAX_MESSAGES && !LANbuttonPushed; ++i)
  303. {
  304. if (m_transport->m_inBuffer[i].length > 0)
  305. {
  306. // Process the new message
  307. UnsignedInt senderIP = m_transport->m_inBuffer[i].addr;
  308. if (senderIP == m_localIP)
  309. {
  310. m_transport->m_inBuffer[i].length = 0;
  311. continue;
  312. }
  313. LANMessage *msg = (LANMessage *)(m_transport->m_inBuffer[i].data);
  314. //DEBUG_LOG(("LAN message type %s from %ls (%s@%s)\n", GetMessageTypeString(msg->LANMessageType).str(),
  315. // msg->name, msg->userName, msg->hostName));
  316. switch (msg->LANMessageType)
  317. {
  318. // Location specification
  319. case LANMessage::MSG_REQUEST_LOCATIONS: // Hey, where is everybody?
  320. DEBUG_LOG(("LANAPI::update - got a MSG_REQUEST_LOCATIONS from 0x%08x\n", senderIP));
  321. handleRequestLocations( msg, senderIP );
  322. break;
  323. case LANMessage::MSG_GAME_ANNOUNCE: // Here someone is, and here's his game info!
  324. DEBUG_LOG(("LANAPI::update - got a MSG_GAME_ANNOUNCE from 0x%08x\n", senderIP));
  325. handleGameAnnounce( msg, senderIP );
  326. break;
  327. case LANMessage::MSG_LOBBY_ANNOUNCE: // Hey, I'm in the lobby!
  328. DEBUG_LOG(("LANAPI::update - got a MSG_LOBBY_ANNOUNCE from 0x%08x\n", senderIP));
  329. handleLobbyAnnounce( msg, senderIP );
  330. break;
  331. case LANMessage::MSG_REQUEST_GAME_INFO:
  332. DEBUG_LOG(("LANAPI::update - got a MSG_REQUEST_GAME_INFO from 0x%08x\n", senderIP));
  333. handleRequestGameInfo( msg, senderIP );
  334. break;
  335. // Joining games
  336. case LANMessage::MSG_REQUEST_JOIN: // Let me in! Let me in!
  337. DEBUG_LOG(("LANAPI::update - got a MSG_REQUEST_JOIN from 0x%08x\n", senderIP));
  338. handleRequestJoin( msg, senderIP );
  339. break;
  340. case LANMessage::MSG_JOIN_ACCEPT: // Okay, you can join.
  341. DEBUG_LOG(("LANAPI::update - got a MSG_JOIN_ACCEPT from 0x%08x\n", senderIP));
  342. handleJoinAccept( msg, senderIP );
  343. break;
  344. case LANMessage::MSG_JOIN_DENY: // Go away! We don't want any!
  345. DEBUG_LOG(("LANAPI::update - got a MSG_JOIN_DENY from 0x%08x\n", senderIP));
  346. handleJoinDeny( msg, senderIP );
  347. break;
  348. // Leaving games, lobby
  349. case LANMessage::MSG_REQUEST_GAME_LEAVE: // I'm outa here!
  350. DEBUG_LOG(("LANAPI::update - got a MSG_REQUEST_GAME_LEAVE from 0x%08x\n", senderIP));
  351. handleRequestGameLeave( msg, senderIP );
  352. break;
  353. case LANMessage::MSG_REQUEST_LOBBY_LEAVE: // I'm outa here!
  354. DEBUG_LOG(("LANAPI::update - got a MSG_REQUEST_LOBBY_LEAVE from 0x%08x\n", senderIP));
  355. handleRequestLobbyLeave( msg, senderIP );
  356. break;
  357. // Game options, chat, etc
  358. case LANMessage::MSG_SET_ACCEPT: // I'm cool with everything as is.
  359. handleSetAccept( msg, senderIP );
  360. break;
  361. case LANMessage::MSG_MAP_AVAILABILITY: // Map status
  362. handleHasMap( msg, senderIP );
  363. break;
  364. case LANMessage::MSG_CHAT: // Just spouting my mouth off.
  365. handleChat( msg, senderIP );
  366. break;
  367. case LANMessage::MSG_GAME_START: // Hold on; we're starting!
  368. handleGameStart( msg, senderIP );
  369. break;
  370. case LANMessage::MSG_GAME_START_TIMER:
  371. handleGameStartTimer( msg, senderIP );
  372. break;
  373. case LANMessage::MSG_GAME_OPTIONS: // Here's some info about the game.
  374. DEBUG_LOG(("LANAPI::update - got a MSG_GAME_OPTIONS from 0x%08x\n", senderIP));
  375. handleGameOptions( msg, senderIP );
  376. break;
  377. case LANMessage::MSG_INACTIVE: // someone is telling us that we're inactive.
  378. handleInActive( msg, senderIP );
  379. break;
  380. default:
  381. DEBUG_LOG(("Unknown LAN message type %d\n", msg->LANMessageType));
  382. }
  383. // Mark it as read
  384. m_transport->m_inBuffer[i].length = 0;
  385. }
  386. } // End message handling
  387. if(LANbuttonPushed)
  388. return;
  389. // Send out periodic I'm Here messages
  390. if (now > s_resendDelta + m_lastResendTime)
  391. {
  392. m_lastResendTime = now;
  393. if (m_inLobby)
  394. {
  395. RequestSetName(m_name);
  396. }
  397. else if (m_currentGame && !m_currentGame->isGameInProgress())
  398. {
  399. if (AmIHost())
  400. {
  401. RequestGameOptions( GenerateGameOptionsString(), true );
  402. RequestGameAnnounce( );
  403. }
  404. else
  405. {
  406. AsciiString text;
  407. text.format("User=%s", m_userName.str());
  408. RequestGameOptions( text, true );
  409. text.format("Host=%s", m_hostName.str());
  410. RequestGameOptions( text, true );
  411. RequestGameOptions( "HELLO", false );
  412. }
  413. }
  414. else if (m_currentGame)
  415. {
  416. // game is in progress - RequestGameAnnounce will check if we should send it
  417. RequestGameAnnounce();
  418. }
  419. }
  420. Bool playerListChanged = false;
  421. Bool gameListChanged = false;
  422. // Weed out people we haven't heard from in a while
  423. LANPlayer *player = m_lobbyPlayers;
  424. while (player)
  425. {
  426. if (player->getLastHeard() + s_resendDelta*2 < now)
  427. {
  428. // He's gone!
  429. removePlayer(player);
  430. LANPlayer *nextPlayer = player->getNext();
  431. delete player;
  432. player = nextPlayer;
  433. playerListChanged = true;
  434. }
  435. else
  436. {
  437. player = player->getNext();
  438. }
  439. }
  440. // Weed out people we haven't heard from in a while
  441. LANGameInfo *game = m_games;
  442. while (game)
  443. {
  444. if (game != m_currentGame && game->getLastHeard() + s_resendDelta*2 < now)
  445. {
  446. // He's gone!
  447. removeGame(game);
  448. LANGameInfo *nextGame = game->getNext();
  449. delete game;
  450. game = nextGame;
  451. gameListChanged = true;
  452. }
  453. else
  454. {
  455. game = game->getNext();
  456. }
  457. }
  458. if ( m_currentGame && !m_currentGame->isGameInProgress() )
  459. {
  460. if ( !AmIHost() && (m_currentGame->getLastHeard() + s_resendDelta*16 < now) )
  461. {
  462. // We haven't heard from the host in a while. Bail.
  463. // Actually, fake a host leaving message. :)
  464. LANMessage msg;
  465. fillInLANMessage( &msg );
  466. msg.LANMessageType = LANMessage::MSG_REQUEST_GAME_LEAVE;
  467. wcsncpy(msg.name, m_currentGame->getPlayerName(0).str(), g_lanPlayerNameLength);
  468. msg.name[g_lanPlayerNameLength] = 0;
  469. handleRequestGameLeave(&msg, m_currentGame->getIP(0));
  470. UnicodeString text;
  471. text = TheGameText->fetch("LAN:HostNotResponding");
  472. OnChat(UnicodeString::TheEmptyString, m_localIP, text, LANCHAT_SYSTEM);
  473. }
  474. else if ( AmIHost() )
  475. {
  476. // Check each player for timeouts
  477. for (int p=1; p<MAX_SLOTS; ++p)
  478. {
  479. if (m_currentGame->getIP(p) && m_currentGame->getPlayerLastHeard(p) + s_resendDelta*8 < now)
  480. {
  481. LANMessage msg;
  482. fillInLANMessage( &msg );
  483. UnicodeString theStr;
  484. theStr.format(TheGameText->fetch("LAN:PlayerDropped"), m_currentGame->getPlayerName(p).str());
  485. msg.LANMessageType = LANMessage::MSG_REQUEST_GAME_LEAVE;
  486. wcsncpy(msg.name, m_currentGame->getPlayerName(p).str(), g_lanPlayerNameLength);
  487. msg.name[g_lanPlayerNameLength] = 0;
  488. handleRequestGameLeave(&msg, m_currentGame->getIP(p));
  489. OnChat(UnicodeString::TheEmptyString, m_localIP, theStr, LANCHAT_SYSTEM);
  490. }
  491. }
  492. }
  493. }
  494. if (playerListChanged)
  495. {
  496. OnPlayerList(m_lobbyPlayers);
  497. }
  498. if (gameListChanged)
  499. {
  500. OnGameList(m_games);
  501. }
  502. // Time out old actions
  503. if (m_pendingAction != ACT_NONE && now > m_expiration)
  504. {
  505. switch (m_pendingAction)
  506. {
  507. case ACT_JOIN:
  508. OnGameJoin(RET_TIMEOUT, NULL);
  509. m_pendingAction = ACT_NONE;
  510. m_currentGame = NULL;
  511. m_inLobby = true;
  512. break;
  513. case ACT_LEAVE:
  514. OnPlayerLeave(m_name);
  515. m_pendingAction = ACT_NONE;
  516. m_currentGame = NULL;
  517. m_inLobby = true;
  518. break;
  519. case ACT_JOINDIRECTCONNECT:
  520. OnGameJoin(RET_TIMEOUT, NULL);
  521. m_pendingAction = ACT_NONE;
  522. m_currentGame = NULL;
  523. m_inLobby = true;
  524. break;
  525. default:
  526. m_pendingAction = ACT_NONE;
  527. }
  528. }
  529. // send out "game starting" messages
  530. if ( m_gameStartTime && m_gameStartSeconds && m_gameStartTime <= now )
  531. {
  532. // m_gameStartTime is when the next message goes out
  533. // m_gameStartSeconds is how many seconds remain in the message
  534. RequestGameStartTimer( m_gameStartSeconds );
  535. }
  536. else if (m_gameStartTime && m_gameStartTime <= now)
  537. {
  538. // DEBUG_LOG(("m_gameStartTime=%d, now=%d, m_gameStartSeconds=%d\n", m_gameStartTime, now, m_gameStartSeconds));
  539. ResetGameStartTimer();
  540. RequestGameStart();
  541. }
  542. // Check for an MOTD every few seconds
  543. static UnsignedInt lastMOTDCheck = 0;
  544. static const UnsignedInt motdInterval = 30000;
  545. if (now > lastMOTDCheck + motdInterval)
  546. {
  547. checkMOTD();
  548. lastMOTDCheck = now;
  549. }
  550. }
  551. // Request functions generate network traffic
  552. void LANAPI::RequestLocations( void )
  553. {
  554. LANMessage msg;
  555. msg.LANMessageType = LANMessage::MSG_REQUEST_LOCATIONS;
  556. fillInLANMessage( &msg );
  557. sendMessage(&msg);
  558. }
  559. void LANAPI::RequestGameJoin( LANGameInfo *game, UnsignedInt ip /* = 0 */ )
  560. {
  561. if ((m_pendingAction != ACT_NONE) && (m_pendingAction != ACT_JOINDIRECTCONNECT))
  562. {
  563. OnGameJoin( RET_BUSY, NULL );
  564. return;
  565. }
  566. if (!game)
  567. {
  568. OnGameJoin( RET_GAME_GONE, NULL );
  569. return;
  570. }
  571. LANMessage msg;
  572. msg.LANMessageType = LANMessage::MSG_REQUEST_JOIN;
  573. fillInLANMessage( &msg );
  574. msg.GameToJoin.gameIP = game->getSlot(0)->getIP();
  575. msg.GameToJoin.exeCRC = TheGlobalData->m_exeCRC;
  576. msg.GameToJoin.iniCRC = TheGlobalData->m_iniCRC;
  577. AsciiString s = "";
  578. GetStringFromRegistry("\\ergc", "", s);
  579. strncpy(msg.GameToJoin.serial, s.str(), g_maxSerialLength);
  580. msg.GameToJoin.serial[g_maxSerialLength-1] = '\0';
  581. sendMessage(&msg, ip);
  582. m_pendingAction = ACT_JOIN;
  583. m_expiration = timeGetTime() + m_actionTimeout;
  584. }
  585. void LANAPI::RequestGameJoinDirectConnect(UnsignedInt ipaddress)
  586. {
  587. if (m_pendingAction != ACT_NONE)
  588. {
  589. OnGameJoin( RET_BUSY, NULL );
  590. return;
  591. }
  592. if (ipaddress == 0)
  593. {
  594. OnGameJoin( RET_GAME_GONE, NULL );
  595. return;
  596. }
  597. m_directConnectRemoteIP = ipaddress;
  598. LANMessage msg;
  599. msg.LANMessageType = LANMessage::MSG_REQUEST_GAME_INFO;
  600. fillInLANMessage(&msg);
  601. msg.PlayerInfo.ip = GetLocalIP();
  602. wcsncpy(msg.PlayerInfo.playerName, m_name.str(), m_name.getLength());
  603. msg.PlayerInfo.playerName[m_name.getLength()] = 0;
  604. sendMessage(&msg, ipaddress);
  605. m_pendingAction = ACT_JOINDIRECTCONNECT;
  606. m_expiration = timeGetTime() + m_actionTimeout;
  607. }
  608. void LANAPI::RequestGameLeave( void )
  609. {
  610. LANMessage msg;
  611. msg.LANMessageType = LANMessage::MSG_REQUEST_GAME_LEAVE;
  612. fillInLANMessage( &msg );
  613. wcsncpy(msg.GameToLeave.gameName, (m_currentGame)?m_currentGame->getName().str():L"", g_lanGameNameLength);
  614. msg.GameToLeave.gameName[g_lanGameNameLength] = 0;
  615. sendMessage(&msg);
  616. m_transport->update(); // Send immediately, before OnPlayerLeave below resets everything.
  617. if (m_currentGame && m_currentGame->getIP(0) == m_localIP)
  618. {
  619. // Exit out immediately if we're hosting
  620. OnPlayerLeave(m_name);
  621. removeGame(m_currentGame);
  622. m_currentGame = NULL;
  623. m_inLobby = true;
  624. }
  625. else
  626. {
  627. m_pendingAction = ACT_LEAVE;
  628. m_expiration = timeGetTime() + m_actionTimeout;
  629. }
  630. }
  631. void LANAPI::RequestGameAnnounce( void )
  632. {
  633. // In game - are we a game host?
  634. if (m_currentGame && !(m_currentGame->getIsDirectConnect()))
  635. {
  636. if (m_currentGame->getIP(0) == m_localIP || (m_currentGame->isGameInProgress() && TheNetwork && TheNetwork->isPacketRouter())) // if we're in game we should reply if we're the packet router
  637. {
  638. LANMessage reply;
  639. fillInLANMessage( &reply );
  640. reply.LANMessageType = LANMessage::MSG_GAME_ANNOUNCE;
  641. AsciiString gameOpts = GameInfoToAsciiString(m_currentGame);
  642. strncpy(reply.GameInfo.options,gameOpts.str(),m_lanMaxOptionsLength);
  643. wcsncpy(reply.GameInfo.gameName, m_currentGame->getName().str(), g_lanGameNameLength);
  644. reply.GameInfo.gameName[g_lanGameNameLength] = 0;
  645. reply.GameInfo.inProgress = m_currentGame->isGameInProgress();
  646. reply.GameInfo.isDirectConnect = m_currentGame->getIsDirectConnect();
  647. sendMessage(&reply);
  648. }
  649. }
  650. }
  651. void LANAPI::RequestAccept( void )
  652. {
  653. if (m_inLobby || !m_currentGame)
  654. return;
  655. LANMessage msg;
  656. fillInLANMessage( &msg );
  657. msg.LANMessageType = LANMessage::MSG_SET_ACCEPT;
  658. msg.Accept.isAccepted = true;
  659. wcsncpy(msg.Accept.gameName, m_currentGame->getName().str(), g_lanGameNameLength);
  660. msg.Accept.gameName[g_lanGameNameLength] = 0;
  661. sendMessage(&msg);
  662. }
  663. void LANAPI::RequestHasMap( void )
  664. {
  665. if (m_inLobby || !m_currentGame)
  666. return;
  667. LANMessage msg;
  668. fillInLANMessage( &msg );
  669. msg.LANMessageType = LANMessage::MSG_MAP_AVAILABILITY;
  670. msg.MapStatus.hasMap = m_currentGame->getSlot(m_currentGame->getLocalSlotNum())->hasMap();
  671. wcsncpy(msg.MapStatus.gameName, m_currentGame->getName().str(), g_lanGameNameLength);
  672. msg.MapStatus.gameName[g_lanGameNameLength] = 0;
  673. CRC mapNameCRC;
  674. //mapNameCRC.computeCRC(m_currentGame->getMap().str(), m_currentGame->getMap().getLength());
  675. AsciiString portableMapName = TheGameState->realMapPathToPortableMapPath(m_currentGame->getMap());
  676. mapNameCRC.computeCRC(portableMapName.str(), portableMapName.getLength());
  677. msg.MapStatus.mapCRC = mapNameCRC.get();
  678. sendMessage(&msg);
  679. if (!msg.MapStatus.hasMap)
  680. {
  681. UnicodeString text;
  682. UnicodeString mapDisplayName;
  683. const MapMetaData *mapData = TheMapCache->findMap( m_currentGame->getMap() );
  684. Bool willTransfer = TRUE;
  685. if (mapData)
  686. {
  687. mapDisplayName.format(L"%ls", mapData->m_displayName.str());
  688. if (mapData->m_isOfficial)
  689. willTransfer = FALSE;
  690. }
  691. else
  692. {
  693. mapDisplayName.format(L"%hs", TheGameState->getMapLeafName(m_currentGame->getMap()).str());
  694. willTransfer = WouldMapTransfer(m_currentGame->getMap());
  695. }
  696. if (willTransfer)
  697. text.format(TheGameText->fetch("GUI:LocalPlayerNoMapWillTransfer"), mapDisplayName.str());
  698. else
  699. text.format(TheGameText->fetch("GUI:LocalPlayerNoMap"), mapDisplayName.str());
  700. OnChat(UnicodeString(L"SYSTEM"), m_localIP, text, LANCHAT_SYSTEM);
  701. }
  702. }
  703. void LANAPI::RequestChat( UnicodeString message, ChatType format )
  704. {
  705. LANMessage msg;
  706. fillInLANMessage( &msg );
  707. wcsncpy(msg.Chat.gameName, (m_currentGame)?m_currentGame->getName().str():L"", g_lanGameNameLength);
  708. msg.Chat.gameName[g_lanGameNameLength] = 0;
  709. msg.LANMessageType = LANMessage::MSG_CHAT;
  710. msg.Chat.chatType = format;
  711. wcsncpy(msg.Chat.message, message.str(), g_lanMaxChatLength);
  712. msg.Chat.message[g_lanMaxChatLength] = 0;
  713. sendMessage(&msg);
  714. OnChat(m_name, m_localIP, message, format);
  715. }
  716. void LANAPI::RequestGameStart( void )
  717. {
  718. if (m_inLobby || !m_currentGame || m_currentGame->getIP(0) != m_localIP)
  719. return;
  720. LANMessage msg;
  721. msg.LANMessageType = LANMessage::MSG_GAME_START;
  722. fillInLANMessage( &msg );
  723. sendMessage(&msg);
  724. m_transport->update(); // force a send
  725. OnGameStart();
  726. }
  727. void LANAPI::ResetGameStartTimer( void )
  728. {
  729. m_gameStartTime = 0;
  730. m_gameStartSeconds = 0;
  731. }
  732. void LANAPI::RequestGameStartTimer( Int seconds )
  733. {
  734. if (m_inLobby || !m_currentGame || m_currentGame->getIP(0) != m_localIP)
  735. return;
  736. UnsignedInt now = timeGetTime();
  737. m_gameStartTime = now + 1000;
  738. m_gameStartSeconds = (seconds) ? seconds - 1 : 0;
  739. LANMessage msg;
  740. msg.LANMessageType = LANMessage::MSG_GAME_START_TIMER;
  741. msg.StartTimer.seconds = seconds;
  742. fillInLANMessage( &msg );
  743. sendMessage(&msg);
  744. m_transport->update(); // force a send
  745. OnGameStartTimer(seconds);
  746. }
  747. void LANAPI::RequestGameOptions( AsciiString gameOptions, Bool isPublic, UnsignedInt ip /* = 0 */ )
  748. {
  749. DEBUG_ASSERTCRASH(gameOptions.getLength() < m_lanMaxOptionsLength, ("Game options string is too long!"));
  750. if (!m_currentGame)
  751. return;
  752. LANMessage msg;
  753. fillInLANMessage( &msg );
  754. msg.LANMessageType = LANMessage::MSG_GAME_OPTIONS;
  755. strncpy(msg.GameOptions.options, gameOptions.str(), m_lanMaxOptionsLength);
  756. msg.GameOptions.options[m_lanMaxOptionsLength] = 0;
  757. sendMessage(&msg, ip);
  758. m_lastGameopt = gameOptions;
  759. int player;
  760. for (player = 0; player<MAX_SLOTS; ++player)
  761. {
  762. if (m_currentGame->getIP(player) == m_localIP)
  763. {
  764. OnGameOptions(m_localIP, player, AsciiString(msg.GameOptions.options));
  765. break;
  766. }
  767. }
  768. // We can request game options (side, color, etc) while we don't have a slot yet. Of course, we don't need to
  769. // call OnGameOptions for those, so it's okay to silently fail.
  770. //DEBUG_ASSERTCRASH(player != MAX_SLOTS, ("Requested game options, but we're not in slot list!");
  771. }
  772. void LANAPI::RequestGameCreate( UnicodeString gameName, Bool isDirectConnect )
  773. {
  774. // No games of the same name should exist... Ignore that for now.
  775. /// @todo: make sure LAN games with identical names don't crash things like in RA2.
  776. if ((!m_inLobby || m_currentGame) && !isDirectConnect)
  777. {
  778. DEBUG_ASSERTCRASH(m_inLobby && m_currentGame, ("Can't create a game while in one!"));
  779. OnGameCreate(LANAPIInterface::RET_BUSY);
  780. return;
  781. }
  782. if (m_pendingAction != ACT_NONE)
  783. {
  784. OnGameCreate(LANAPIInterface::RET_BUSY);
  785. return;
  786. }
  787. // Create the local game object
  788. m_inLobby = false;
  789. LANGameInfo *myGame = NEW LANGameInfo;
  790. myGame->setSeed(GetTickCount());
  791. // myGame->setInProgress(false);
  792. myGame->enterGame();
  793. UnicodeString s;
  794. s.format(L"%8.8X%8.8X", m_localIP, myGame->getSeed());
  795. if (gameName.isEmpty())
  796. s.concat(m_name);
  797. else
  798. s.concat(gameName);
  799. while (s.getLength() > g_lanGameNameLength)
  800. s.removeLastChar();
  801. DEBUG_LOG(("Setting local game name to '%ls'\n", s.str()));
  802. myGame->setName(s);
  803. LANGameSlot newSlot;
  804. newSlot.setState(SLOT_PLAYER, m_name);
  805. newSlot.setIP(m_localIP);
  806. newSlot.setPort(NETWORK_BASE_PORT_NUMBER); // LAN game, everyone has a unique IP, so it's ok to use the same port.
  807. newSlot.setLastHeard(0);
  808. newSlot.setLogin(m_userName);
  809. newSlot.setHost(m_hostName);
  810. myGame->setSlot(0,newSlot);
  811. myGame->setNext(NULL);
  812. LANPreferences pref;
  813. AsciiString mapName = pref.getPreferredMap();
  814. myGame->setMap(mapName);
  815. myGame->setIsDirectConnect(isDirectConnect);
  816. myGame->setLastHeard(timeGetTime());
  817. m_currentGame = myGame;
  818. /// @todo: Need to initialize the players elsewere.
  819. /* for (int player = 1; player < MAX_SLOTS; ++player)
  820. {
  821. myGame->setPlayerName(player, UnicodeString(L""));
  822. myGame->setIP(player, 0);
  823. myGame->setAccepted(player, false);
  824. }*/
  825. // Add the game to the local game list
  826. addGame(myGame);
  827. // Send an announcement
  828. //RequestSlotList();
  829. /*
  830. LANMessage msg;
  831. wcsncpy(msg.name, m_name.str(), g_lanPlayerNameLength);
  832. msg.name[g_lanPlayerNameLength] = 0;
  833. wcscpy(msg.GameInfo.gameName, myGame->getName().str());
  834. for (player=0; player<MAX_SLOTS; ++player)
  835. {
  836. wcscpy(msg.GameInfo.name[player], myGame->getPlayerName(player).str());
  837. msg.GameInfo.ip[player] = myGame->getIP(player);
  838. msg.GameInfo.playerAccepted[player] = myGame->getAccepted(player);
  839. }
  840. msg.LANMessageType = LANMessage::MSG_GAME_ANNOUNCE;
  841. */
  842. OnGameCreate(LANAPIInterface::RET_OK);
  843. }
  844. /*static const char slotListID = 'S';
  845. static const char gameOptionsID = 'G';
  846. static const char acceptID = 'A';
  847. static const char wannaStartID = 'W';
  848. AsciiString LANAPI::createSlotString( void )
  849. {
  850. AsciiString slotList;
  851. slotList.concat(slotListID);
  852. for (int i=0; i<MAX_SLOTS; ++i)
  853. {
  854. LANGameSlot *slot = GetMyGame()->getLANSlot(i);
  855. AsciiString str;
  856. if (slot->isHuman())
  857. {
  858. str = "H";
  859. LANPlayer *user = slot->getUser();
  860. DEBUG_ASSERTCRASH(user, ("Human player has no User*!"));
  861. AsciiString name;
  862. name.translate(user->getName());
  863. str.concat(name);
  864. str.concat(',');
  865. }
  866. else if (slot->isAI())
  867. {
  868. if (slot->getState() == SLOT_EASY_AI)
  869. str = "CE,";
  870. if (slot->getState() == SLOT_MED_AI)
  871. str = "CM,";
  872. else
  873. str = "CB,";
  874. }
  875. else if (slot->getState() == SLOT_OPEN)
  876. {
  877. str = "O,";
  878. }
  879. else if (slot->getState() == SLOT_CLOSED)
  880. {
  881. str = "X,";
  882. }
  883. else
  884. {
  885. DEBUG_ASSERTCRASH(false, ("Bad slot type"));
  886. str = "X,";
  887. }
  888. slotList.concat(str);
  889. }
  890. return slotList;
  891. }
  892. */
  893. /*
  894. void LANAPI::RequestSlotList( void )
  895. {
  896. LANMessage reply;
  897. reply.LANMessageType = LANMessage::MSG_GAME_ANNOUNCE;
  898. wcsncpy(reply.name, m_name.str(), g_lanPlayerNameLength);
  899. reply.name[g_lanPlayerNameLength] = 0;
  900. int player;
  901. for (player = 0; player < MAX_SLOTS; ++player)
  902. {
  903. wcsncpy(reply.GameInfo.name[player], m_currentGame->getPlayerName(player).str(), g_lanPlayerNameLength);
  904. reply.GameInfo.name[player][g_lanPlayerNameLength] = 0;
  905. reply.GameInfo.ip[player] = m_currentGame->getIP(player);
  906. reply.GameInfo.playerAccepted[player] = m_currentGame->getSlot(player)->isAccepted();
  907. }
  908. wcsncpy(reply.GameInfo.gameName, m_currentGame->getName().str(), g_lanGameNameLength);
  909. reply.GameInfo.gameName[g_lanGameNameLength] = 0;
  910. reply.GameInfo.inProgress = m_currentGame->isGameInProgress();
  911. sendMessage(&reply);
  912. OnSlotList(LANAPIInterface::RET_OK, m_currentGame);
  913. } // void LANAPI::RequestSlotList( void )
  914. */
  915. void LANAPI::RequestSetName( UnicodeString newName )
  916. {
  917. newName.trim();
  918. if (m_pendingAction != ACT_NONE)
  919. {
  920. // Can't change name while joining games
  921. OnNameChange(m_localIP, newName);
  922. return;
  923. }
  924. // Set up timer
  925. m_lastResendTime = timeGetTime();
  926. if (m_inLobby && m_pendingAction == ACT_NONE)
  927. {
  928. m_name = newName;
  929. LANMessage msg;
  930. fillInLANMessage( &msg );
  931. msg.LANMessageType = LANMessage::MSG_LOBBY_ANNOUNCE;
  932. sendMessage(&msg);
  933. // Update the interface
  934. LANPlayer *player = LookupPlayer(m_localIP);
  935. if (!player)
  936. {
  937. player = NEW LANPlayer;
  938. player->setIP(m_localIP);
  939. }
  940. else
  941. {
  942. removePlayer(player);
  943. }
  944. player->setName(m_name);
  945. player->setHost(m_hostName);
  946. player->setLogin(m_userName);
  947. player->setLastHeard(timeGetTime());
  948. addPlayer(player);
  949. OnNameChange(player->getIP(), player->getName());
  950. }
  951. }
  952. void LANAPI::fillInLANMessage( LANMessage *msg )
  953. {
  954. if (!msg)
  955. return;
  956. wcsncpy(msg->name, m_name.str(), g_lanPlayerNameLength);
  957. msg->name[g_lanPlayerNameLength] = 0;
  958. strncpy(msg->userName, m_userName.str(), g_lanLoginNameLength);
  959. msg->userName[g_lanLoginNameLength] = 0;
  960. strncpy(msg->hostName, m_hostName.str(), g_lanHostNameLength);
  961. msg->hostName[g_lanHostNameLength] = 0;
  962. }
  963. void LANAPI::RequestLobbyLeave( Bool forced )
  964. {
  965. LANMessage msg;
  966. msg.LANMessageType = LANMessage::MSG_REQUEST_LOBBY_LEAVE;
  967. fillInLANMessage( &msg );
  968. sendMessage(&msg);
  969. if (forced)
  970. m_transport->update();
  971. }
  972. // Misc utility functions
  973. LANGameInfo * LANAPI::LookupGame( UnicodeString gameName )
  974. {
  975. LANGameInfo *theGame = m_games;
  976. while (theGame && theGame->getName() != gameName)
  977. {
  978. theGame = theGame->getNext();
  979. }
  980. return theGame; // NULL means we didn't find anything.
  981. }
  982. LANGameInfo * LANAPI::LookupGameByListOffset( Int offset )
  983. {
  984. LANGameInfo *theGame = m_games;
  985. if (offset < 0)
  986. return NULL;
  987. while (offset-- && theGame)
  988. {
  989. theGame = theGame->getNext();
  990. }
  991. return theGame; // NULL means we didn't find anything.
  992. }
  993. void LANAPI::removeGame( LANGameInfo *game )
  994. {
  995. LANGameInfo *g = m_games;
  996. if (!game)
  997. {
  998. return;
  999. }
  1000. else if (m_games == game)
  1001. {
  1002. m_games = m_games->getNext();
  1003. }
  1004. else
  1005. {
  1006. while (g->getNext() && g->getNext() != game)
  1007. {
  1008. g = g->getNext();
  1009. }
  1010. if (g->getNext() == game)
  1011. {
  1012. g->setNext(game->getNext());
  1013. }
  1014. else
  1015. {
  1016. // Odd. We went the whole way without finding it in the list.
  1017. DEBUG_ASSERTCRASH(false, ("LANGameInfo wasn't in the list"));
  1018. }
  1019. }
  1020. }
  1021. LANPlayer * LANAPI::LookupPlayer( UnsignedInt playerIP )
  1022. {
  1023. LANPlayer *thePlayer = m_lobbyPlayers;
  1024. while (thePlayer && thePlayer->getIP() != playerIP)
  1025. {
  1026. thePlayer = thePlayer->getNext();
  1027. }
  1028. return thePlayer; // NULL means we didn't find anything.
  1029. }
  1030. void LANAPI::removePlayer( LANPlayer *player )
  1031. {
  1032. LANPlayer *p = m_lobbyPlayers;
  1033. if (!player)
  1034. {
  1035. return;
  1036. }
  1037. else if (m_lobbyPlayers == player)
  1038. {
  1039. m_lobbyPlayers = m_lobbyPlayers->getNext();
  1040. }
  1041. else
  1042. {
  1043. while (p->getNext() && p->getNext() != player)
  1044. {
  1045. p = p->getNext();
  1046. }
  1047. if (p->getNext() == player)
  1048. {
  1049. p->setNext(player->getNext());
  1050. }
  1051. else
  1052. {
  1053. // Odd. We went the whole way without finding it in the list.
  1054. DEBUG_ASSERTCRASH(false, ("LANPlayer wasn't in the list"));
  1055. }
  1056. }
  1057. }
  1058. void LANAPI::addGame( LANGameInfo *game )
  1059. {
  1060. if (!m_games)
  1061. {
  1062. m_games = game;
  1063. game->setNext(NULL);
  1064. return;
  1065. }
  1066. else
  1067. {
  1068. if (game->getName().compareNoCase(m_games->getName()) < 0)
  1069. {
  1070. game->setNext(m_games);
  1071. m_games = game;
  1072. return;
  1073. }
  1074. else
  1075. {
  1076. LANGameInfo *g = m_games;
  1077. while (g->getNext() && g->getNext()->getName().compareNoCase(game->getName()) > 0)
  1078. {
  1079. g = g->getNext();
  1080. }
  1081. game->setNext(g->getNext());
  1082. g->setNext(game);
  1083. return;
  1084. }
  1085. }
  1086. }
  1087. void LANAPI::addPlayer( LANPlayer *player )
  1088. {
  1089. if (!m_lobbyPlayers)
  1090. {
  1091. m_lobbyPlayers = player;
  1092. player->setNext(NULL);
  1093. return;
  1094. }
  1095. else
  1096. {
  1097. if (player->getName().compareNoCase(m_lobbyPlayers->getName()) < 0)
  1098. {
  1099. player->setNext(m_lobbyPlayers);
  1100. m_lobbyPlayers = player;
  1101. return;
  1102. }
  1103. else
  1104. {
  1105. LANPlayer *p = m_lobbyPlayers;
  1106. while (p->getNext() && p->getNext()->getName().compareNoCase(player->getName()) > 0)
  1107. {
  1108. p = p->getNext();
  1109. }
  1110. player->setNext(p->getNext());
  1111. p->setNext(player);
  1112. return;
  1113. }
  1114. }
  1115. }
  1116. Bool LANAPI::SetLocalIP( UnsignedInt localIP )
  1117. {
  1118. Bool retval = TRUE;
  1119. m_localIP = localIP;
  1120. m_transport->reset();
  1121. retval = m_transport->init(m_localIP, lobbyPort);
  1122. m_transport->allowBroadcasts(true);
  1123. return retval;
  1124. }
  1125. void LANAPI::SetLocalIP( AsciiString localIP )
  1126. {
  1127. UnsignedInt resolvedIP = ResolveIP(localIP);
  1128. SetLocalIP(resolvedIP);
  1129. }
  1130. Bool LANAPI::AmIHost( void )
  1131. {
  1132. return m_currentGame && m_currentGame->getIP(0) == m_localIP;
  1133. }
  1134. void LANAPI::setIsActive(Bool isActive) {
  1135. DEBUG_LOG(("LANAPI::setIsActive - entering\n"));
  1136. if (isActive != m_isActive) {
  1137. DEBUG_LOG(("LANAPI::setIsActive - m_isActive changed to %s\n", isActive ? "TRUE" : "FALSE"));
  1138. if (isActive == FALSE) {
  1139. if ((m_inLobby == FALSE) && (m_currentGame != NULL)) {
  1140. LANMessage msg;
  1141. fillInLANMessage( &msg );
  1142. msg.LANMessageType = LANMessage::MSG_INACTIVE;
  1143. sendMessage(&msg);
  1144. DEBUG_LOG(("LANAPI::setIsActive - sent an IsActive message\n"));
  1145. }
  1146. }
  1147. }
  1148. m_isActive = isActive;
  1149. }