diff --git a/functions.h b/functions.h index 9816a56af6..6f24b05c96 100644 --- a/functions.h +++ b/functions.h @@ -1,6 +1,8 @@ #ifndef FUNCTIONS_H #define FUNCTIONS_H +#include "network.h" + /* vehicle.c */ /* window.c */ @@ -144,16 +146,17 @@ void NetworkCoreShutdown(); void NetworkCoreDisconnect(); void NetworkCoreLoop(bool incomming); bool NetworkCoreConnectGame(const byte* b, unsigned short port); +bool NetworkCoreConnectGameStruct(NetworkGameList * item); bool NetworkCoreStartGame(); void NetworkLobbyShutdown(); void NetworkLobbyInit(); void NetworkGameListClear(); -char * NetworkGameListAdd(); +NetworkGameList * NetworkGameListAdd(); void NetworkGameListFromLAN(); void NetworkGameListFromInternet(); -char * NetworkGameListItem(uint16 index); +NetworkGameList * NetworkGameListItem(uint16 index); void NetworkGameFillDefaults(); void NetworkGameChangeDate(uint16 newdate); diff --git a/lang/american.txt b/lang/american.txt index b658b67b4d..c7332b9ee3 100644 --- a/lang/american.txt +++ b/lang/american.txt @@ -1145,6 +1145,8 @@ STR_NETWORK_MAP_SIZE_TIP :{BLACK}Size of the map STR_NETWORK_INFO_ICONS_TIP :{BLACK}Language, server version, etc. STR_NETWORK_CLICK_GAME_TO_SELECT :{BLACK}Click a game from the list to select it +STR_NETWORK_PLAYERS_VAL :{BLACK}{COMMA8}/{COMMA8} + STR_NETWORK_JOIN_GAME :{BLACK}Join game diff --git a/lang/czech.txt b/lang/czech.txt index e88b2251ec..d6ef6a76b7 100644 --- a/lang/czech.txt +++ b/lang/czech.txt @@ -1199,6 +1199,8 @@ STR_NETWORK_MAP_SIZE_TIP :{BLACK}Velikost mapy STR_NETWORK_INFO_ICONS_TIP :{BLACK}Jazyk, verze serveru, atd. STR_NETWORK_CLICK_GAME_TO_SELECT :{BLACK}Hru vyberes kliknutim do seznamu +STR_NETWORK_PLAYERS_VAL :{BLACK}{COMMA8}/{COMMA8} + STR_NETWORK_JOIN_GAME :{BLACK}Pridat se diff --git a/lang/dutch.txt b/lang/dutch.txt index 1d473e81aa..ef5f61c1f7 100644 --- a/lang/dutch.txt +++ b/lang/dutch.txt @@ -1144,6 +1144,8 @@ STR_NETWORK_MAP_SIZE_TIP :{BLACK}Grootte van de kaart STR_NETWORK_INFO_ICONS_TIP :{BLACK}Taal, serverversie, etc. STR_NETWORK_CLICK_GAME_TO_SELECT :{BLACK}Klik op een spel uit de lijst om deze te selecteren +STR_NETWORK_PLAYERS_VAL :{BLACK}{COMMA8}/{COMMA8} + STR_NETWORK_JOIN_GAME :{BLACK}Meespelen diff --git a/lang/english.txt b/lang/english.txt index 71d078684a..e99a6ffc5d 100644 --- a/lang/english.txt +++ b/lang/english.txt @@ -799,10 +799,10 @@ STR_02FC_LOAD_A_SAVED_GAME_FROM :{BLACK}Load a saved game from disk STR_02FD_VIEW_DEMONSTRATIONS_TUTORIALS :{BLACK}View demonstrations/tutorials STR_02FE_CREATE_A_CUSTOMIZED_GAME :{BLACK}Create a customized game world/scenario STR_02FF_SELECT_SINGLE_PLAYER_GAME :{BLACK}Select single-player game -STR_0300_SELECT_TWO_PLAYER_GAME :{BLACK}Select two-player game +STR_0300_SELECT_TWO_PLAYER_GAME :{BLACK}Select multiplayer game of 2-8 players STR_0301_DISPLAY_GAME_OPTIONS :{BLACK}Display game options STR_0302_DISPLAY_DIFFICULTY_OPTIONS :{BLACK}Display difficulty options -STR_0303_START_A_NEW_GAME_USING :{BLACK}Start a new game, using a customized scenario +STR_0303_START_A_NEW_GAME_USING :{BLACK}Start a new game, using a customized scenario from disk STR_0304_QUIT :{BLACK}Quit STR_0305_LEAVE_OPENTTD :{BLACK}Leave 'OpenTTD', and quit STR_0306_VIEW_DEMONSTRATION_TUTORIAL :{BLACK}View demonstration/tutorial @@ -956,9 +956,9 @@ STR_ROADVEHICLE_AUTORENEW_FAILED :{WHITE}Autorenew failed on road vehicle {CO STR_SHIP_AUTORENEW_FAILED :{WHITE}Autorenew failed on ship {COMMA16} (money limit) STR_AIRCRAFT_AUTORENEW_FAILED :{WHITE}Autorenew failed on aircraft {COMMA16} (money limit) -STR_CONFIG_PATCHES :{BLACK}Configure Patches -STR_CONFIG_PATCHES_TIP :{BLACK}Configure the patches -STR_CONFIG_PATCHES_CAPTION :{WHITE}Configure Patches +STR_CONFIG_PATCHES :{BLACK}Configure Patches +STR_CONFIG_PATCHES_TIP :{BLACK}Configure the patches +STR_CONFIG_PATCHES_CAPTION :{WHITE}Configure Patches STR_CONFIG_PATCHES_OFF :Off STR_CONFIG_PATCHES_ON :On @@ -1169,7 +1169,7 @@ TEMP_AI_ACTIVATED :{WHITE}Warning: this new AI is still alpha! Currently, o ############ network gui strings -TEMP_STRING_NO_NETWORK :{WHITE}Network interface is not fully working yet!{}Some options work, but others like lobby, etc. don't. Just so you know. +TEMP_STRING_NO_NETWORK :{WHITE}Network interface is not yet fully operational!{}Not working items have been disabled. STR_NETWORK_MULTIPLAYER :{WHITE}Multiplayer @@ -1185,7 +1185,7 @@ STR_NETWORK_PLAYER_NAME :{BLACK}Player name: STR_NETWORK_ENTER_NAME_TIP :{BLACK}This is the name other players will identify you by STR_NETWORK_SELECT_CONNECTION :{BLACK}Select connection type: -STR_NETWORK_CONNECTION_TYPE_TIP :{BLACK}Chose between an internet game or a local area nework game +STR_NETWORK_CONNECTION_TYPE_TIP :{BLACK}Choose between an internet game or a local area nework game STR_NETWORK_COMBO1 :{BLACK}{SKIP}{SKIP}{STRING} STR_NETWORK_LAN :LAN STR_NETWORK_INTERNET :Internet @@ -1199,10 +1199,12 @@ STR_NETWORK_MAP_SIZE_TIP :{BLACK}Size of the map STR_NETWORK_INFO_ICONS_TIP :{BLACK}Language, server version, etc. STR_NETWORK_CLICK_GAME_TO_SELECT :{BLACK}Click a game from the list to select it +STR_NETWORK_PLAYERS_VAL :{BLACK}{COMMA8}/{COMMA8} + STR_NETWORK_JOIN_GAME :{BLACK}Join game -STR_NETWORK_START_GAME_WINDOW :{WHITE}Start new game +STR_NETWORK_START_GAME_WINDOW :{WHITE}Start new multiplayer game STR_NETWORK_NEW_GAME_NAME :{BLACK}Game name: STR_NETWORK_NEW_GAME_NAME_TIP :{BLACK}The game name will be displayed to other players in the multiplayer game selection menu @@ -1211,7 +1213,7 @@ STR_NETWORK_PASSWORD_TIP :{BLACK}Protect your game with a password if you do STR_NETWORK_SELECT_MAP :{BLACK}Select a map: STR_NETWORK_SELECT_MAP_TIP :{BLACK}Which map do you want to play? STR_NETWORK_NUMBER_OF_PLAYERS :{BLACK}Number of players: -STR_NETWORK_NUMBER_OF_PLAYERS_TIP :{BLACK}Chose a maximum number of players. Not all slots need to be filled. +STR_NETWORK_NUMBER_OF_PLAYERS_TIP :{BLACK}Choose a maximum number of players. Not all slots need to be filled. STR_NETWORK_COMBO2 :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING} STR_NETWORK_2_PLAYERS :2 players STR_NETWORK_3_PLAYERS :3 players @@ -1221,8 +1223,11 @@ STR_NETWORK_6_PLAYERS :6 players STR_NETWORK_7_PLAYERS :7 players STR_NETWORK_8_PLAYERS :8 players STR_NETWORK_START_GAME :{BLACK}Start Game +STR_NETWORK_START_GAME_TIP :{BLACK}Start a new network game from a random map, or scenario STR_NETWORK_LOAD_GAME :{BLACK}Load Game +STR_NETWORK_LOAD_GAME_TIP :{BLACK}Resume an earlier saved multiplayer game (be sure to connect as the correct player) STR_NETWORK_LOAD_SCENARIO :{BLACK}Load Scenario +STR_NETWORK_LOAD_SCENARIO_TIP :{BLACK}Start a new network game from a scenario STR_NETWORK_GAME_LOBBY :{WHITE}Multiplayer game lobby @@ -1237,7 +1242,7 @@ STR_NETWORK_NEW_COMPANY_TIP :{BLACK}Open a new company STR_NETWORK_READY :{BLACK}Ready STR_NETWORK_ERR_NOTAVAILABLE :{WHITE} No network devices found or compiled without ENABLE_NETWORK -STR_NETWORK_ERR_NOSERVER :{WHITE} Could not find any network game +STR_NETWORK_ERR_NOSERVER :{WHITE} Could not find any network games STR_NETWORK_ERR_NOCONNECTION :{WHITE} The server didn't answer the request STR_NETWORK_ERR_DESYNC :{WHITE} Network-Game synchronization failed. STR_NETWORK_ERR_LOSTCONNECTION :{WHITE} Network-Game connection lost. diff --git a/lang/french.txt b/lang/french.txt index 16244fb17f..3380833f7c 100644 --- a/lang/french.txt +++ b/lang/french.txt @@ -1199,6 +1199,8 @@ STR_NETWORK_MAP_SIZE_TIP :{BLACK}Taille de la carte STR_NETWORK_INFO_ICONS_TIP :{BLACK}Langage, version du serveur, etc. STR_NETWORK_CLICK_GAME_TO_SELECT :{BLACK}Cliquez une partie de la liste pour la sélectionner +STR_NETWORK_PLAYERS_VAL :{BLACK}{COMMA8}/{COMMA8} + STR_NETWORK_JOIN_GAME :{BLACK}Rejoindre la partie diff --git a/lang/galician.txt b/lang/galician.txt index c40d7245b1..339b8d100e 100644 --- a/lang/galician.txt +++ b/lang/galician.txt @@ -1145,6 +1145,8 @@ STR_NETWORK_MAP_SIZE_TIP :{BLACK}Tama STR_NETWORK_INFO_ICONS_TIP :{BLACK}Idioma, versión do servidor, etc. STR_NETWORK_CLICK_GAME_TO_SELECT :{BLACK}Pincha nunha partida da lista para seleccionala +STR_NETWORK_PLAYERS_VAL :{BLACK}{COMMA8}/{COMMA8} + STR_NETWORK_JOIN_GAME :{BLACK}Unirse á partida diff --git a/lang/german.txt b/lang/german.txt index 0d6322f315..3dd9510c2b 100644 --- a/lang/german.txt +++ b/lang/german.txt @@ -1199,6 +1199,8 @@ STR_NETWORK_MAP_SIZE_TIP :{BLACK}Gr STR_NETWORK_INFO_ICONS_TIP :{BLACK}Sprache, Server version, etc. STR_NETWORK_CLICK_GAME_TO_SELECT :{BLACK}Ein Spiel der Liste mit Anklicken wählen +STR_NETWORK_PLAYERS_VAL :{BLACK}{COMMA8}/{COMMA8} + STR_NETWORK_JOIN_GAME :{BLACK}Zum Spiel beitreten diff --git a/lang/hungarian.txt b/lang/hungarian.txt index 8d966f01a5..fe047611a1 100644 --- a/lang/hungarian.txt +++ b/lang/hungarian.txt @@ -1199,6 +1199,8 @@ STR_NETWORK_MAP_SIZE_TIP :{BLACK}A t STR_NETWORK_INFO_ICONS_TIP :{BLACK}Nyelv, szerver verzió, stb. STR_NETWORK_CLICK_GAME_TO_SELECT :{BLACK}Kattints a listában a jatékra hogy kiválaszd +STR_NETWORK_PLAYERS_VAL :{BLACK}{COMMA8}/{COMMA8} + STR_NETWORK_JOIN_GAME :{BLACK}Csatlakozás a játékhoz diff --git a/lang/italian.txt b/lang/italian.txt index e526911e46..dc4e23b733 100644 --- a/lang/italian.txt +++ b/lang/italian.txt @@ -1162,6 +1162,8 @@ STR_NETWORK_MAP_SIZE_TIP :{BLACK}Dimensione della mappa STR_NETWORK_INFO_ICONS_TIP :{BLACK}Lingua, versione server, ecc. STR_NETWORK_CLICK_GAME_TO_SELECT :{BLACK}Clicca su un nome della lista per selezionarlo +STR_NETWORK_PLAYERS_VAL :{BLACK}{COMMA8}/{COMMA8} + STR_NETWORK_JOIN_GAME :{BLACK}Entra nel gioco diff --git a/lang/polish.txt b/lang/polish.txt index 6934bf28e3..1decc5bfcb 100644 --- a/lang/polish.txt +++ b/lang/polish.txt @@ -1111,6 +1111,8 @@ STR_NETWORK_MAP_SIZE_TIP :{BLACK}Rozmiar mapy STR_NETWORK_INFO_ICONS_TIP :{BLACK}Jezyk, wersja serwera, itp. STR_NETWORK_CLICK_GAME_TO_SELECT :{BLACK}Klinknij na grze z listy by ja wybrac +STR_NETWORK_PLAYERS_VAL :{BLACK}{COMMA8}/{COMMA8} + STR_NETWORK_JOIN_GAME :{BLACK}Przylacz sie do gry diff --git a/lang/swedish.txt b/lang/swedish.txt index 81d97e172d..1a3ec62ee8 100644 --- a/lang/swedish.txt +++ b/lang/swedish.txt @@ -1117,6 +1117,8 @@ STR_NETWORK_MAP_SIZE_TIP :{BLACK}Storlek p STR_NETWORK_INFO_ICONS_TIP :{BLACK}Sprĺk, server version, mm STR_NETWORK_CLICK_GAME_TO_SELECT :{BLACK}Klicka pĺ ett spel frĺn listan för att välja det +STR_NETWORK_PLAYERS_VAL :{BLACK}{COMMA8}/{COMMA8} + STR_NETWORK_JOIN_GAME :{BLACK}Gĺ med i spelet diff --git a/network.c b/network.c index 3b8407e150..27f2d3065e 100644 --- a/network.c +++ b/network.c @@ -246,31 +246,6 @@ static size_t _transmit_file_size; static FILE *_recv_file; -typedef struct NetworkGameInfo { - char server_name[40]; // name of the game - char server_revision[8]; // server game version - byte server_lang; // langid - byte players_max; // max players allowed on server - byte players_on; // current count of players on server - uint16 game_date; // current date - char game_password[10]; // should fit ... 10 chars - char map_name[40]; // map which is played ["random" for a randomized map] - uint map_width; // map width / 8 - uint map_height; // map height / 8 - byte map_set; // graphical set -} NetworkGameInfo; - -typedef struct NetworkGameList { - NetworkGameInfo item; - uint32 ip; - uint16 port; - char * _next; -} NetworkGameList; - -static NetworkGameInfo _network_game; -static NetworkGameList * _network_game_list = NULL; - - /* multi os compatible sleep function */ void CSleep(int milliseconds) { #if defined(WIN32) @@ -327,6 +302,7 @@ static void NetworkHandleConnectionLost() _switch_mode = SM_MENU; _switch_mode_errorstr = STR_NETWORK_ERR_LOSTCONNECTION; } + static void NetworkHandleDeSync() { DEBUG(net, 0) ("[NET] Fatal ERROR: network sync error at frame %i", _frame_counter); @@ -354,7 +330,8 @@ static QueuedCommand *AllocQueuedCommand(CommandQueue *nq) return qp; } -static void QueueClear(CommandQueue *nq) { +static void QueueClear(CommandQueue *nq) +{ QueuedCommand *qp; while ((qp=nq->head)) { // unlink it. @@ -676,7 +653,8 @@ static void HandleFilePacket(FilePacketHdr *fp) } } -static void HandleWelcomePacket(WelcomePacket *wp) { +static void HandleWelcomePacket(WelcomePacket *wp) +{ int i; for (i=0; iplayer_seeds[i][0]; @@ -1036,7 +1014,6 @@ static void NetworkAcceptClients() // * sync - games are in sync } - static void SendQueuedCommandsToNewClient(ClientState *cs) { // send the commands in the server queue to the new client. @@ -1072,8 +1049,8 @@ static void SendQueuedCommandsToNewClient(ClientState *cs) } - -bool NetworkCheckClientReady() { +bool NetworkCheckClientReady() +{ bool ready_all = true; uint16 count = 0; ClientState *cs; @@ -1095,7 +1072,8 @@ bool NetworkCheckClientReady() { // * TCP Networking * // // ************************** // -unsigned long NetworkResolveHost(const char *hostname) { +unsigned long NetworkResolveHost(const char *hostname) +{ struct hostent* remotehost; if ((hostname[0]<0x30) || (hostname[0]>0x39)) { @@ -1291,6 +1269,7 @@ void NetworkInitialize() QueueClear(&_command_queue); QueueClear(&_ack_queue); _command_queue.last = &_command_queue.head; + _network_game_list = NULL; // invalidate all clients for(cs=_clients; cs != &_clients[MAX_CLIENTS]; cs++) @@ -1298,7 +1277,8 @@ void NetworkInitialize() } -void NetworkClose(bool client) { +void NetworkClose(bool client) +{ ClientState *cs; // invalidate all clients @@ -1312,7 +1292,7 @@ void NetworkClose(bool client) { closesocket(_listensocket); _listensocket= INVALID_SOCKET; DEBUG(net, 1) ("[NET][TCP] closed listener on port %i", _network_server_port); - } + } } void NetworkShutdown() @@ -1331,6 +1311,7 @@ void NetworkStartSync(bool fcreset) DEBUG(net, 3) ("[NET][SYNC] switching to synced game mode"); _networking_sync = true; _frame_counter = 0; + if (fcreset) { _frame_counter_max = 0; _frame_counter_srv = 0; @@ -1339,22 +1320,23 @@ void NetworkStartSync(bool fcreset) _num_future_seed = 0; _sync_seed_1 = _sync_seed_2 = 0; memset(_my_seed_list, 0, sizeof(_my_seed_list)); - } // ********************************* // // * Network Core Console Commands * // // ********************************* // -static _iconsole_var * NetworkConsoleCmdConnect(byte argc, byte* argv[], byte argt[]) { +static _iconsole_var * NetworkConsoleCmdConnect(byte argc, byte* argv[], byte argt[]) +{ if (argc<2) return NULL; - if (argc==2) { + + if (argc == 2) { IConsolePrintF(_iconsole_color_default, "connecting to %s",argv[1]); NetworkCoreConnectGame(argv[1],_network_server_port); - } else if (argc==3) { + } else if (argc == 3) { IConsolePrintF(_iconsole_color_default, "connecting to %s on port %s",argv[1],argv[2]); NetworkCoreConnectGame(argv[1],atoi(argv[2])); - } else if (argc==4) { + } else if (argc == 4) { IConsolePrintF(_iconsole_color_default, "connecting to %s on port %s as player %s",argv[1],argv[2],argv[3]); _network_playas = atoi(argv[3]); NetworkCoreConnectGame(argv[1],atoi(argv[2])); @@ -1401,7 +1383,8 @@ void NetworkUDPListen(bool client) } -void NetworkUDPClose(bool client) { +void NetworkUDPClose(bool client) +{ if (client) { DEBUG(net, 1) ("[NET][UDP] closed listener on port %i", _network_client_port); closesocket(_udp_client_socket); @@ -1413,7 +1396,8 @@ void NetworkUDPClose(bool client) { }; } -void NetworkUDPReceive(bool client) { +void NetworkUDPReceive(bool client) +{ struct sockaddr_in client_addr; #ifndef __MORPHOS__ int client_len; @@ -1465,9 +1449,8 @@ void NetworkUDPReceive(bool client) { } } - - -void NetworkUDPBroadCast(bool client, struct UDPPacket packet) { +void NetworkUDPBroadCast(bool client, struct UDPPacket packet) +{ int i=0, res; struct sockaddr_in out_addr; uint32 bcaddr; @@ -1490,8 +1473,8 @@ void NetworkUDPBroadCast(bool client, struct UDPPacket packet) { } -void NetworkUDPSend(bool client, struct sockaddr_in recv,struct UDPPacket packet) { - +void NetworkUDPSend(bool client, struct sockaddr_in recv,struct UDPPacket packet) +{ SOCKET udp; if (client) udp=_udp_client_socket; else udp=_udp_server_socket; @@ -1499,7 +1482,8 @@ void NetworkUDPSend(bool client, struct sockaddr_in recv,struct UDPPacket packet } -bool NetworkUDPSearchGame(const byte ** _network_detected_serverip, unsigned short * _network_detected_serverport) { +bool NetworkUDPSearchGame(const byte ** _network_detected_serverip, unsigned short * _network_detected_serverport) +{ struct UDPPacket packet; int timeout=3000; @@ -1537,7 +1521,8 @@ bool NetworkUDPSearchGame(const byte ** _network_detected_serverip, unsigned sho // * New Network Core System * // // *************************** // -void NetworkIPListInit() { +void NetworkIPListInit() +{ struct hostent* he = NULL; char hostname[250]; uint32 bcaddr; @@ -1573,103 +1558,98 @@ void NetworkIPListInit() { /* *************************************************** */ -void NetworkCoreInit() { - -DEBUG(net, 3) ("[NET][Core] init()"); -_network_available=true; -_network_client_timeout=300; - -// [win32] winsock startup - -#if defined(WIN32) +void NetworkCoreInit() { - WSADATA wsa; - DEBUG(net, 3) ("[NET][Core] using windows socket library"); - if (WSAStartup(MAKEWORD(2,0), &wsa) != 0) { - DEBUG(net, 3) ("[NET][Core] error: WSAStartup failed"); - _network_available=false; - } -} -#else + DEBUG(net, 3) ("[NET][Core] init()"); + _network_available=true; + _network_client_timeout=300; -// [morphos/amigaos] bsd-socket startup + // [win32] winsock startup -#if defined(__MORPHOS__) || defined(__AMIGA__) -{ - DEBUG(misc,3) ("[NET][Core] using bsd socket library"); - if (!(SocketBase = OpenLibrary("bsdsocket.library", 4))) { - DEBUG(net, 3) ("[NET][Core] Couldn't open bsdsocket.library version 4."); - _network_available=false; - } + #if defined(WIN32) + { + WSADATA wsa; + DEBUG(net, 3) ("[NET][Core] using windows socket library"); + if (WSAStartup(MAKEWORD(2,0), &wsa) != 0) { + DEBUG(net, 3) ("[NET][Core] error: WSAStartup failed"); + _network_available=false; + } + } + #else - #if !defined(__MORPHOS__) - // for usleep() implementation (only required for legacy AmigaOS builds) - if ( (TimerPort = CreateMsgPort()) ) { - if ( (TimerRequest = (struct timerequest *) CreateIORequest(TimerPort, sizeof(struct timerequest))) ) { - if ( OpenDevice("timer.device", UNIT_MICROHZ, (struct IORequest *) TimerRequest, 0) == 0 ) { - if ( !(TimerBase = TimerRequest->tr_node.io_Device) ) { - // free ressources... - DEBUG(net, 3) ("[NET][Core] Couldn't initialize timer."); - _network_available=false; + // [morphos/amigaos] bsd-socket startup + + #if defined(__MORPHOS__) || defined(__AMIGA__) + { + DEBUG(misc,3) ("[NET][Core] using bsd socket library"); + if (!(SocketBase = OpenLibrary("bsdsocket.library", 4))) { + DEBUG(net, 3) ("[NET][Core] Couldn't open bsdsocket.library version 4."); + _network_available=false; + } + + #if !defined(__MORPHOS__) + // for usleep() implementation (only required for legacy AmigaOS builds) + if ( (TimerPort = CreateMsgPort()) ) { + if ( (TimerRequest = (struct timerequest *) CreateIORequest(TimerPort, sizeof(struct timerequest))) ) { + if ( OpenDevice("timer.device", UNIT_MICROHZ, (struct IORequest *) TimerRequest, 0) == 0 ) { + if ( !(TimerBase = TimerRequest->tr_node.io_Device) ) { + // free ressources... + DEBUG(net, 3) ("[NET][Core] Couldn't initialize timer."); + _network_available=false; + } } } } + #endif + } + #else + + // [linux/macos] unix-socket startup + + DEBUG(net, 3) ("[NET][Core] using unix socket library"); + #endif -} -#else - -// [linux/macos] unix-socket startup - - DEBUG(net, 3) ("[NET][Core] using unix socket library"); - -#endif - -#endif + #endif -if (_network_available) { - DEBUG(net, 3) ("[NET][Core] OK: multiplayer available"); - // initiate network ip list - NetworkIPListInit(); - IConsoleCmdRegister("connect",NetworkConsoleCmdConnect); - IConsoleVarRegister("net_client_timeout",&_network_client_timeout,ICONSOLE_VAR_UINT16); - IConsoleVarRegister("net_ready_ahead",&_network_ready_ahead,ICONSOLE_VAR_UINT16); - IConsoleVarRegister("net_sync_freq",&_network_sync_freq,ICONSOLE_VAR_UINT16); - } else { - DEBUG(net, 3) ("[NET][Core] FAILED: multiplayer not available"); - } + if (_network_available) { + DEBUG(net, 3) ("[NET][Core] OK: multiplayer available"); + // initiate network ip list + NetworkIPListInit(); + IConsoleCmdRegister("connect",NetworkConsoleCmdConnect); + IConsoleVarRegister("net_client_timeout",&_network_client_timeout,ICONSOLE_VAR_UINT16); + IConsoleVarRegister("net_ready_ahead",&_network_ready_ahead,ICONSOLE_VAR_UINT16); + IConsoleVarRegister("net_sync_freq",&_network_sync_freq,ICONSOLE_VAR_UINT16); + } else + DEBUG(net, 3) ("[NET][Core] FAILED: multiplayer not available"); } /* *************************************************** */ -void NetworkCoreShutdown() { - -DEBUG(net, 3) ("[NET][Core] shutdown()"); - -#if defined(__MORPHOS__) || defined(__AMIGA__) +void NetworkCoreShutdown() { - // free allocated ressources - #if !defined(__MORPHOS__) - if (TimerBase) { CloseDevice((struct IORequest *) TimerRequest); } - if (TimerRequest) { DeleteIORequest(TimerRequest); } - if (TimerPort) { DeleteMsgPort(TimerPort); } + DEBUG(net, 3) ("[NET][Core] shutdown()"); + + #if defined(__MORPHOS__) || defined(__AMIGA__) + { + // free allocated ressources + #if !defined(__MORPHOS__) + if (TimerBase) { CloseDevice((struct IORequest *) TimerRequest); } + if (TimerRequest) { DeleteIORequest(TimerRequest); } + if (TimerPort) { DeleteMsgPort(TimerPort); } + #endif + + if (SocketBase) { + CloseLibrary(SocketBase); + } + } #endif - if (SocketBase) { - CloseLibrary(SocketBase); - } -} -#endif - - -#if defined(WIN32) -{ - WSACleanup(); -} -#endif - + #if defined(WIN32) + { WSACleanup();} + #endif } /* *************************************************** */ @@ -1707,6 +1687,13 @@ bool NetworkCoreConnectGame(const byte* b, unsigned short port) /* *************************************************** */ +bool NetworkCoreConnectGameStruct(NetworkGameList * item) +{ + return NetworkCoreConnectGame(inet_ntoa(*(struct in_addr *) &item->ip),item->port); +} + +/* *************************************************** */ + bool NetworkCoreStartGame() { if (!_network_available) return false; @@ -1741,39 +1728,33 @@ void NetworkCoreDisconnect() /* *************************************************** */ -void NetworkCoreLoop(bool incomming) { +void NetworkCoreLoop(bool incomming) +{ + if (incomming) { + // incomming + if ( _udp_client_socket != INVALID_SOCKET ) NetworkUDPReceive(true); + if ( _udp_server_socket != INVALID_SOCKET ) NetworkUDPReceive(false); - -if (incomming) { - - // incomming - - if ( _udp_client_socket != INVALID_SOCKET ) NetworkUDPReceive(true); - if ( _udp_server_socket != INVALID_SOCKET ) NetworkUDPReceive(false); - - if (_networking) { - NetworkReceive(); - } + if (_networking) + NetworkReceive(); } else { + if ( _udp_client_socket != INVALID_SOCKET ) NetworkUDPReceive(true); + if ( _udp_server_socket != INVALID_SOCKET ) NetworkUDPReceive(false); - if ( _udp_client_socket != INVALID_SOCKET ) NetworkUDPReceive(true); - if ( _udp_server_socket != INVALID_SOCKET ) NetworkUDPReceive(false); - - if (_networking) { - NetworkSend(); - } - + if (_networking) + NetworkSend(); } - } -void NetworkLobbyInit() { +void NetworkLobbyInit() +{ DEBUG(net, 3) ("[NET][Lobby] init()"); NetworkUDPListen(true); } -void NetworkLobbyShutdown() { +void NetworkLobbyShutdown() +{ DEBUG(net, 3) ("[NET][Lobby] shutdown()"); NetworkUDPClose(true); } @@ -1783,46 +1764,52 @@ void NetworkLobbyShutdown() { // * Network Game List Extensions * // // ******************************** // -void NetworkGameListClear() { -NetworkGameList * item; -NetworkGameList * next; +void NetworkGameListClear() +{ + NetworkGameList * item; + NetworkGameList * next; -DEBUG(net, 4) ("[NET][G-List] cleared server list"); + DEBUG(net, 4) ("[NET][G-List] cleared server list"); -item = _network_game_list; -while (item != NULL) { - next = (NetworkGameList *) item -> _next; - free (item); - item = next; + item = _network_game_list; + + while (item != NULL) { + next = (NetworkGameList *) item -> _next; + free (item); + item = next; } -_network_game_list=NULL; -_network_game_count=0; + _network_game_list=NULL; + _network_game_count=0; } -char * NetworkGameListAdd() { -NetworkGameList * item; -NetworkGameList * before; +NetworkGameList * NetworkGameListAdd() +{ + NetworkGameList * item; + NetworkGameList * before; -DEBUG(net, 4) ("[NET][G-List] added server to list"); + DEBUG(net, 4) ("[NET][G-List] added server to list"); -item = _network_game_list; -before = item; -while (item != NULL) { + item = _network_game_list; before = item; - item = (NetworkGameList *) item -> _next; + while (item != NULL) { + before = item; + item = (NetworkGameList *) item -> _next; } -item = malloc(sizeof(NetworkGameList)); -item -> _next = NULL; -if (before == NULL) { - _network_game_list = item; - } else { - before -> _next = (char *) item; - } -_network_game_count++; -return (char *) item; + + item = malloc(sizeof(NetworkGameList)); + item -> _next = NULL; + + if (before == NULL) { + _network_game_list = item; + } else + before -> _next = item; + + _network_game_count++; + return item; } -void NetworkGameListFromLAN() { +void NetworkGameListFromLAN() +{ struct UDPPacket packet; DEBUG(net, 2) ("[NET][G-List] searching server over lan"); NetworkGameListClear(); @@ -1831,35 +1818,37 @@ void NetworkGameListFromLAN() { NetworkUDPBroadCast(true,packet); } -void NetworkGameListFromInternet() { +void NetworkGameListFromInternet() +{ DEBUG(net, 2) ("[NET][G-List] searching servers over internet"); NetworkGameListClear(); // **TODO** masterserver communication [internet protocol list] - } -char * NetworkGameListItem(uint16 index) { -NetworkGameList * item; -NetworkGameList * next; -uint16 cnt = 0; +NetworkGameList * NetworkGameListItem(uint16 index) +{ + NetworkGameList * item; + NetworkGameList * next; + uint16 cnt = 0; -item = _network_game_list; + item = _network_game_list; -while ((item != NULL) && (cnt != index)) { - next = (NetworkGameList *) item -> _next; - item = next; - cnt++; + while ((item != NULL) && (cnt != index)) { + next = (NetworkGameList *) item -> _next; + item = next; + cnt++; } -return (char *) item; + return item; } // *************************** // // * Network Game Extensions * // // *************************** // -void NetworkGameFillDefaults() { +void NetworkGameFillDefaults() +{ NetworkGameInfo * game = &_network_game; #if defined(WITH_REV) extern char _openttd_revision[]; @@ -1887,10 +1876,10 @@ void NetworkGameFillDefaults() { game->server_lang=_dynlang.curr; } -void NetworkGameChangeDate(uint16 newdate) { - if (_networking_server) { +void NetworkGameChangeDate(uint16 newdate) +{ + if (_networking_server) _network_game.game_date = newdate; - } } #else // not ENABLE_NETWORK diff --git a/network.h b/network.h new file mode 100644 index 0000000000..e4fd42a360 --- /dev/null +++ b/network.h @@ -0,0 +1,30 @@ +#ifndef NETWORK_H +#define NETWORK_H + +typedef struct NetworkGameInfo { + char server_name[40]; // name of the game + char server_revision[8]; // server game version + byte server_lang; // langid + byte players_max; // max players allowed on server + byte players_on; // current count of players on server + uint16 game_date; // current date + char game_password[10]; // should fit ... 10 chars + char map_name[40]; // map which is played ["random" for a randomized map] + uint map_width; // map width / 8 + uint map_height; // map height / 8 + byte map_set; // graphical set +} NetworkGameInfo; + +//typedef struct NetworkGameList; + +typedef struct NetworkGameList { + NetworkGameInfo item; + uint32 ip; + uint16 port; + struct NetworkGameList * _next; +} NetworkGameList; + +NetworkGameInfo _network_game; +NetworkGameList * _network_game_list; + +#endif /* NETWORK_H */ diff --git a/network_gui.c b/network_gui.c index 200c924b1f..005fe5069e 100644 --- a/network_gui.c +++ b/network_gui.c @@ -4,6 +4,7 @@ #include "gui.h" #include "gfx.h" #include "command.h" +#include "network.h" #define BGC 5 #define BTC 15 @@ -33,15 +34,16 @@ static byte _players_max; static byte _network_connection; static uint16 _network_game_count_last; +enum { + NET_PRC__OFFSET_TOP_WIDGET = 93, + NET_PRC__SIZE_OF_ROW = 14, +}; + +static NetworkGameList *selected_item = NULL; + static void NetworkGameWindowWndProc(Window *w, WindowEvent *e) { switch(e->event) { - case WE_TICK: { - if (_network_game_count_last != _network_game_count) { - SetWindowDirty(w); - } - } - break; case WE_PAINT: { SET_DPARAM16(0, 0x00); @@ -57,6 +59,26 @@ static void NetworkGameWindowWndProc(Window *w, WindowEvent *e) DrawString(238, 82, STR_NETWORK_PLAYERS, 2); DrawString(288, 82, STR_NETWORK_MAP_SIZE, 2); + { // draw list of games + uint16 y = NET_PRC__OFFSET_TOP_WIDGET + 3; + int32 n = 0; + NetworkGameList *cur_item = _network_game_list; + while (cur_item != NULL) { + if (cur_item == selected_item) + GfxFillRect(11, y - 2, 380, y + 9, 10); // show highlighted item with a different colour + + DoDrawString(cur_item->item.server_name, 15, y, 16); // server name + + SET_DPARAM8(0, cur_item->item.players_on); + SET_DPARAM8(1, cur_item->item.players_max); + DrawString(238, y, STR_NETWORK_PLAYERS_VAL, 2); // #/# + + DoDrawString(cur_item->item.map_name, 288, y, 16); // map size + cur_item = cur_item->_next; + y += NET_PRC__SIZE_OF_ROW; + if (++n == w->vscroll.cap) { break;} // max number of games in the window + } + } } break; case WE_CLICK: @@ -88,23 +110,48 @@ static void NetworkGameWindowWndProc(Window *w, WindowEvent *e) case 7: case 8: /* Connection type */ ShowDropDownMenu(w, _connection_types_dropdown, _network_connection, 8, 0); // do it for widget 8 return; + case 14: { /* Matrix to show networkgames */ + uint32 id_v = (e->click.pt.y - NET_PRC__OFFSET_TOP_WIDGET) / NET_PRC__SIZE_OF_ROW; + + if (id_v >= w->vscroll.cap) { return;} // click out of bounds + + id_v += w->vscroll.pos; + + { + NetworkGameList *cur_item = _network_game_list; + int32 n = 0; + while (cur_item != NULL) { + if (n++ == id_v) { break;} // found clicked item + + cur_item = cur_item->_next; + } + + if (cur_item == NULL) { return;} // click out of vehicle bounds + + selected_item = cur_item; + } + } break; + case 16: /* Join Game */ + if (selected_item != NULL) + NetworkCoreConnectGameStruct(selected_item); + break; } break; case WE_DROPDOWN_SELECT: /* we have selected a dropdown item in the list */ _network_connection = e->dropdown.index; switch (_network_connection) { - case 0: + case 0: /* LAN */ NetworkGameListFromLAN(); - _network_game_count_last = _network_game_count; - SetWindowDirty(w); break; - case 1: + case 1: /* Internet */ NetworkGameListFromInternet(); - _network_game_count_last = _network_game_count; - SetWindowDirty(w); break; } + + _network_game_count_last = _network_game_count; + SetWindowDirty(w); + break; case WE_MOUSELOOP: @@ -126,16 +173,20 @@ static void NetworkGameWindowWndProc(Window *w, WindowEvent *e) case WE_ON_EDIT_TEXT: { const byte *b = e->edittext.str; - if (*b == 0) - return; - NetworkCoreConnectGame(b,_network_server_port); + if (*b != 0) + NetworkCoreConnectGame(b, _network_server_port); + } break; + + case WE_TICK: { + if (_network_game_count_last != _network_game_count) + SetWindowDirty(w); } break; } } static const Widget _network_game_window_widgets[] = { -{ WWT_PUSHTXTBTN, BGC, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CLOSEBOX, BGC, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, { WWT_CAPTION, BGC, 10, 399, 0, 13, STR_NETWORK_MULTIPLAYER, STR_NULL}, { WWT_IMGBTN, BGC, 0, 399, 14, 199, 0x0, STR_NULL}, @@ -148,14 +199,14 @@ static const Widget _network_game_window_widgets[] = { { WWT_6, BGC, 250, 393, 62, 73, STR_NETWORK_COMBO1, STR_NETWORK_CONNECTION_TYPE_TIP}, { WWT_CLOSEBOX, BGC, 382, 392, 63, 72, STR_0225, STR_NETWORK_CONNECTION_TYPE_TIP}, -{ WWT_SCROLLBAR, BGC, 382, 392, 81, 175, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, +{ WWT_SCROLLBAR, BGC, 382, 392, 81, 176, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, { WWT_IMGBTN, BTC, 10, 231, 81, 92, 0x0, STR_NETWORK_GAME_NAME_TIP }, { WWT_IMGBTN, BTC, 232, 281, 81, 92, 0x0, STR_NETWORK_PLAYERS_TIP }, { WWT_IMGBTN, BTC, 282, 331, 81, 92, 0x0, STR_NETWORK_MAP_SIZE_TIP }, { WWT_IMGBTN, BTC, 332, 381, 81, 92, 0x0, STR_NETWORK_INFO_ICONS_TIP }, -{ WWT_MATRIX, BGC, 10, 381, 93, 175, 0x601, STR_NETWORK_CLICK_GAME_TO_SELECT}, +{ WWT_MATRIX, BGC, 10, 381, 93, 176, 0x601, STR_NETWORK_CLICK_GAME_TO_SELECT}, { WWT_PUSHTXTBTN, BTC, 145, 255, 180, 191, STR_012E_CANCEL, STR_NULL}, { WWT_PUSHTXTBTN, BTC, 270, 392, 180, 191, STR_NETWORK_JOIN_GAME, STR_NULL}, @@ -180,6 +231,9 @@ void ShowNetworkGameWindow() w = AllocateWindowDesc(&_network_game_window_desc); strcpy(_edit_str_buf, "Your name"); + w->vscroll.cap = 6; + w->disabled_state = (1<<6) | (1<<7) | (1<<8); // disable buttons not yet working + NetworkGameListFromLAN(); // default dropdown item is LAN, so fill that array _network_game_count_last = _network_game_count; @@ -232,18 +286,21 @@ static void NetworkStartServerWindowWndProc(Window *w, WindowEvent *e) return; case 9: /* Start game */ NetworkCoreStartGame(); + strcpy(_network_game.server_name, WP(w,querystr_d).buf); //ShowNetworkLobbyWindow(); DoCommandP(0, 0, 0, NULL, CMD_START_NEW_GAME); break; case 10: /* Load game */ NetworkCoreStartGame(); + strcpy(_network_game.server_name, WP(w,querystr_d).buf); //ShowNetworkLobbyWindow(); ShowSaveLoadDialog(SLD_LOAD_GAME); break; case 11: /* Load scenario */ NetworkCoreStartGame(); + strcpy(_network_game.server_name, WP(w,querystr_d).buf); //ShowNetworkLobbyWindow(); - ShowSaveLoadDialog(SLD_LOAD_SCENARIO);; + ShowSaveLoadDialog(SLD_LOAD_SCENARIO); break; } break; @@ -287,9 +344,9 @@ static const Widget _network_start_server_window_widgets[] = { { WWT_6, BGC, 260, 390, 81, 92, STR_NETWORK_COMBO2, STR_NETWORK_NUMBER_OF_PLAYERS_TIP}, { WWT_CLOSEBOX, BGC, 379, 389, 82, 91, STR_0225, STR_NETWORK_NUMBER_OF_PLAYERS_TIP}, -{ WWT_PUSHTXTBTN, BTC, 10, 100, 180, 191, STR_NETWORK_START_GAME, STR_NULL}, -{ WWT_PUSHTXTBTN, BTC, 110, 200, 180, 191, STR_NETWORK_LOAD_GAME, STR_NULL}, -{ WWT_PUSHTXTBTN, BTC, 210, 300, 180, 191, STR_NETWORK_LOAD_SCENARIO, STR_NULL}, +{ WWT_PUSHTXTBTN, BTC, 10, 100, 180, 191, STR_NETWORK_START_GAME, STR_NETWORK_START_GAME_TIP}, +{ WWT_PUSHTXTBTN, BTC, 110, 200, 180, 191, STR_NETWORK_LOAD_GAME, STR_NETWORK_LOAD_GAME_TIP}, +{ WWT_PUSHTXTBTN, BTC, 210, 300, 180, 191, STR_NETWORK_LOAD_SCENARIO, STR_NETWORK_LOAD_SCENARIO_TIP}, { WWT_PUSHTXTBTN, BTC, 310, 390, 180, 191, STR_012E_CANCEL, STR_NULL}, { WIDGETS_END}, }; @@ -309,6 +366,7 @@ static void ShowNetworkStartServerWindow() w = AllocateWindowDesc(&_network_start_server_window_desc); strcpy(_edit_str_buf, ""); + w->disabled_state = (1<<4) | (1<<5) | (1<<6) | (1<<7) | (1<<8); // disable buttons not yet working WP(w,querystr_d).caret = 1; WP(w,querystr_d).maxlen = MAX_QUERYSTR_LEN; @@ -375,7 +433,7 @@ static void NetworkLobbyWindowWndProc(Window *w, WindowEvent *e) } static const Widget _network_lobby_window_widgets[] = { -{ WWT_PUSHTXTBTN, BGC, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW }, +{ WWT_CLOSEBOX, BGC, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW }, { WWT_CAPTION, BGC, 10, 399, 0, 13, STR_NETWORK_GAME_LOBBY, STR_NULL}, { WWT_IMGBTN, BGC, 0, 399, 14, 299, 0x0, STR_NULL}, diff --git a/ttd.vcproj b/ttd.vcproj index 74dad20a43..364c67acd5 100644 --- a/ttd.vcproj +++ b/ttd.vcproj @@ -1134,6 +1134,9 @@ + + diff --git a/window.c b/window.c index 92dd93b57e..2f70df88c0 100644 --- a/window.c +++ b/window.c @@ -25,19 +25,19 @@ void DispatchLeftClickEvent(Window *w, int x, int y) { if (e.click.widget < 0) return; /* exit if clicked outside of widgets */ wi = &w->widget[e.click.widget]; + + /* don't allow any interaction if the button has been disabled */ + if (HASBIT(w->disabled_state, e.click.widget)) + return; if (wi->type & 0xE0) { - /* special widget handling */ + /* special widget handling for buttons*/ switch(wi->type) { - case WWT_IMGBTN | WWB_PUSHBUTTON: - case WWT_TEXTBTN | WWB_PUSHBUTTON: - if (HASBIT(w->disabled_state, e.click.widget)) - return; /* don't allow click if disabled */ + case WWT_IMGBTN | WWB_PUSHBUTTON: /* WWT_PUSHIMGBTN */ + case WWT_TEXTBTN | WWB_PUSHBUTTON: /* WWT_PUSHTXTBTN */ HandleButtonClick(w, e.click.widget); break; case WWT_NODISTXTBTN: - if (HASBIT(w->disabled_state, e.click.widget)) - return; /* don't allow click if disabled */ break; } } else if (wi->type == WWT_SCROLLBAR || wi->type == WWT_HSCROLLBAR) {