From 7ccb0eb655978bd7223a924736e9bf588e4cfb0d Mon Sep 17 00:00:00 2001 From: zsilencer Date: Thu, 16 Jul 2015 11:32:43 -0600 Subject: [PATCH] basic player list --- data/language/english_uk.txt | 1 + src/interface/window.h | 2 + src/localisation/string_ids.h | 2 + src/network/network.cpp | 148 ++++++++++++++++++----- src/network/network.h | 32 +++-- src/windows/network.c | 213 +++++++++++++++++++++++++++++++++- src/windows/top_toolbar.c | 45 ++++++- 7 files changed, 404 insertions(+), 39 deletions(-) diff --git a/data/language/english_uk.txt b/data/language/english_uk.txt index 757823577f..fe8db463bd 100644 --- a/data/language/english_uk.txt +++ b/data/language/english_uk.txt @@ -3834,3 +3834,4 @@ STR_5492 :Scenario options STR_6000 :Send Message STR_6001 :Type the message you would like to send. +STR_6002 :Player List diff --git a/src/interface/window.h b/src/interface/window.h index cd99df869c..105d268db3 100644 --- a/src/interface/window.h +++ b/src/interface/window.h @@ -447,6 +447,7 @@ enum { WC_TITLE_EDITOR = 122, WC_TITLE_COMMAND_EDITOR = 123, WC_CHAT_HOST = 124, + WC_PLAYER_LIST = 125, // Only used for colour schemes WC_STAFF = 220, @@ -612,6 +613,7 @@ void window_sign_open(rct_windownumber number); void window_sign_small_open(rct_windownumber number); void window_cheats_open(); void window_chat_open(); +void window_player_list_open(); void window_research_open(); void window_research_development_page_paint(rct_window *w, rct_drawpixelinfo *dpi, int baseWidgetIndex); diff --git a/src/localisation/string_ids.h b/src/localisation/string_ids.h index 5ae91dcca2..d28473e43d 100644 --- a/src/localisation/string_ids.h +++ b/src/localisation/string_ids.h @@ -2030,6 +2030,8 @@ enum { STR_DEBUG_DROPDOWN_INVENTIONS_LIST = 5491, STR_DEBUG_DROPDOWN_SCENARIO_OPTIONS = 5492, + STR_PLAYER_LIST = 6002, + // Have to include resource strings (from scenarios and objects) for the time being now that language is partially working STR_COUNT = 32768 }; diff --git a/src/network/network.cpp b/src/network/network.cpp index 5c5c35aedd..3e0a04cde1 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -21,6 +21,7 @@ #ifndef DISABLE_NETWORK #include +#include #include #include "network.h" extern "C" { @@ -49,7 +50,7 @@ enum { NETWORK_COMMAND_CHAT, NETWORK_COMMAND_GAMECMD, NETWORK_COMMAND_TICK, - NETWORK_COMMAND_PLAYER, + NETWORK_COMMAND_PLAYERLIST, NETWORK_COMMAND_MAX }; @@ -108,6 +109,7 @@ const char* NetworkPacket::ReadString() if (*strend != 0) { return 0; } + read++; return str; } @@ -118,9 +120,17 @@ void NetworkPacket::Clear() data->clear(); } +NetworkPlayer::NetworkPlayer(const char* name) +{ + strncpy((char*)NetworkPlayer::name, name, sizeof(NetworkPlayer::name)); + NetworkPlayer::name[sizeof(NetworkPlayer::name) - 1] = 0; + ping = 0; +} + NetworkConnection::NetworkConnection() { authstatus = NETWORK_AUTH_NONE; + player = 0; } int NetworkConnection::ReadPacket() @@ -213,6 +223,7 @@ Network::Network() client_command_handlers[NETWORK_COMMAND_CHAT] = &Network::Client_Handle_CHAT; client_command_handlers[NETWORK_COMMAND_GAMECMD] = &Network::Client_Handle_GAMECMD; client_command_handlers[NETWORK_COMMAND_TICK] = &Network::Client_Handle_TICK; + client_command_handlers[NETWORK_COMMAND_PLAYERLIST] = &Network::Client_Handle_PLAYERLIST; server_command_handlers.resize(NETWORK_COMMAND_MAX, 0); server_command_handlers[NETWORK_COMMAND_AUTH] = &Network::Server_Handle_AUTH; server_command_handlers[NETWORK_COMMAND_CHAT] = &Network::Server_Handle_CHAT; @@ -241,18 +252,21 @@ bool Network::Init() void Network::Close() { if (mode == NETWORK_MODE_CLIENT) { - mode = NETWORK_MODE_NONE; closesocket(server_socket); } else if (mode == NETWORK_MODE_SERVER) { - mode = NETWORK_MODE_NONE; closesocket(listening_socket); for(auto it = client_connection_list.begin(); it != client_connection_list.end(); it++) { closesocket((*it)->socket); } - client_connection_list.clear(); } + mode = NETWORK_MODE_NONE; + + client_connection_list.clear(); + game_command_queue.clear(); + player_list.clear(); + if (wsa_initialized) { WSACleanup(); wsa_initialized = false; @@ -261,6 +275,7 @@ void Network::Close() bool Network::BeginClient(const char* host, unsigned short port) { + Close(); if (!Init()) return false; @@ -298,6 +313,7 @@ bool Network::BeginClient(const char* host, unsigned short port) bool Network::BeginServer(unsigned short port) { + Close(); if (!Init()) return false; @@ -332,6 +348,10 @@ bool Network::BeginServer(unsigned short port) return false; } + std::unique_ptr player(new NetworkPlayer("Server Player")); // change to make_unique in c++14 + player->flags |= NETWORK_PLAYER_FLAG_ISSERVER; + player_list.push_back(std::move(player)); + printf("Ready for clients...\n"); mode = NETWORK_MODE_SERVER; @@ -343,6 +363,17 @@ int Network::GetMode() return mode; } +int Network::GetAuthStatus() +{ + if (GetMode() == NETWORK_MODE_CLIENT) { + return server_connection.authstatus; + } else + if (GetMode() == NETWORK_MODE_SERVER) { + return NETWORK_AUTH_OK; + } + return NETWORK_AUTH_NONE; +} + uint32 Network::GetServerTick() { return server_tick; @@ -362,7 +393,7 @@ void Network::Update() } else if (GetMode() == NETWORK_MODE_SERVER) { auto it = client_connection_list.begin(); - while(it != client_connection_list.end()) { + while (it != client_connection_list.end()) { if (!ProcessConnection(*(*it))) { RemoveClient((*it)); it = client_connection_list.begin(); @@ -416,7 +447,7 @@ void Network::Server_Send_MAP() std::unique_ptr packet = NetworkPacket::AllocatePacket(); *packet << (uint32)NETWORK_COMMAND_MAP << (uint32)size << (uint32)i; packet->Write(&buffer[i], datasize); - for(auto it = client_connection_list.begin(); it != client_connection_list.end(); it++) { + for (auto it = client_connection_list.begin(); it != client_connection_list.end(); it++) { (*it)->QueuePacket(NetworkPacket::DuplicatePacket(*packet)); } } @@ -436,7 +467,7 @@ void Network::Server_Send_CHAT(const char* text) std::unique_ptr packet = NetworkPacket::AllocatePacket(); *packet << (uint32)NETWORK_COMMAND_CHAT; packet->Write((uint8*)text, strlen(text) + 1); - for(auto it = client_connection_list.begin(); it != client_connection_list.end(); it++) { + for (auto it = client_connection_list.begin(); it != client_connection_list.end(); it++) { (*it)->QueuePacket(NetworkPacket::DuplicatePacket(*packet)); } } @@ -452,7 +483,7 @@ void Network::Server_Send_GAMECMD(uint32 eax, uint32 ebx, uint32 ecx, uint32 edx { std::unique_ptr packet = NetworkPacket::AllocatePacket(); *packet << (uint32)NETWORK_COMMAND_GAMECMD << (uint32)RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) << eax << (ebx | (1 << 31)) << ecx << edx << esi << edi << ebp; - for(auto it = client_connection_list.begin(); it != client_connection_list.end(); it++) { + for (auto it = client_connection_list.begin(); it != client_connection_list.end(); it++) { (*it)->QueuePacket(NetworkPacket::DuplicatePacket(*packet)); } } @@ -461,7 +492,20 @@ void Network::Server_Send_TICK() { std::unique_ptr packet = NetworkPacket::AllocatePacket(); *packet << (uint32)NETWORK_COMMAND_TICK << (uint32)RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32); - for(auto it = client_connection_list.begin(); it != client_connection_list.end(); it++) { + for (auto it = client_connection_list.begin(); it != client_connection_list.end(); it++) { + (*it)->QueuePacket(NetworkPacket::DuplicatePacket(*packet)); + } +} + +void Network::Server_Send_PLAYERLIST() +{ + std::unique_ptr packet = NetworkPacket::AllocatePacket(); + *packet << (uint32)NETWORK_COMMAND_PLAYERLIST << (uint32)player_list.size(); + for (unsigned int i = 0; i < player_list.size(); i++) { + packet->WriteString((const char*)player_list[i]->name); + *packet << player_list[i]->id << player_list[i]->flags; + } + for (auto it = client_connection_list.begin(); it != client_connection_list.end(); it++) { (*it)->QueuePacket(NetworkPacket::DuplicatePacket(*packet)); } } @@ -534,15 +578,18 @@ void Network::ProcessGameCommandQueue() void Network::AddClient(SOCKET socket) { printf("New client connection\n"); - auto networkconnection = std::unique_ptr(new NetworkConnection); // change to make_unique in c++14 - networkconnection->socket = socket; - client_connection_list.push_back(std::move(networkconnection)); + auto connection = std::unique_ptr(new NetworkConnection); // change to make_unique in c++14 + connection->socket = socket; + client_connection_list.push_back(std::move(connection)); } -void Network::RemoveClient(std::unique_ptr& networkconnection) +void Network::RemoveClient(std::unique_ptr& connection) { printf("Client removed\n"); - client_connection_list.remove(networkconnection); + NetworkPlayer* connection_player = connection->player; + player_list.erase(std::remove_if(player_list.begin(), player_list.end(), [connection_player](std::unique_ptr& player){ return player.get() == connection_player; }), player_list.end()); + client_connection_list.remove(connection); + Server_Send_PLAYERLIST(); } void Network::PrintError() @@ -561,22 +608,30 @@ int Network::Client_Handle_AUTH(NetworkConnection& connection, NetworkPacket& pa int Network::Server_Handle_AUTH(NetworkConnection& connection, NetworkPacket& packet) { - const char* gameversion = packet.ReadString(); - const char* name = packet.ReadString(); - const char* password = packet.ReadString(); - connection.authstatus = NETWORK_AUTH_OK; - if (!gameversion || strcmp(gameversion, OPENRCT2_VERSION) != 0) { - connection.authstatus = NETWORK_AUTH_BADVERSION; - } else - if (!name) { - connection.authstatus = NETWORK_AUTH_BADNAME; - } else - if (!password || strcmp(password, Network::password) != 0) { - connection.authstatus = NETWORK_AUTH_BADPASSWORD; + if (connection.authstatus != NETWORK_AUTH_OK) { + const char* gameversion = packet.ReadString(); + const char* name = packet.ReadString(); + const char* password = packet.ReadString(); + if (!gameversion || strcmp(gameversion, OPENRCT2_VERSION) != 0) { + connection.authstatus = NETWORK_AUTH_BADVERSION; + } else + if (!name) { + connection.authstatus = NETWORK_AUTH_BADNAME; + } else + if (!password || strcmp(password, Network::password) != 0) { + connection.authstatus = NETWORK_AUTH_BADPASSWORD; + } else { + connection.authstatus = NETWORK_AUTH_OK; + std::unique_ptr player(new NetworkPlayer(name)); // change to make_unique in c++14 + printf("New player: %s\n", player->name); + connection.player = player.get(); + player_list.push_back(std::move(player)); + Server_Send_PLAYERLIST(); + } + std::unique_ptr responsepacket = NetworkPacket::AllocatePacket(); + *responsepacket << (uint32)NETWORK_COMMAND_AUTH << (uint32)connection.authstatus; + connection.QueuePacket(std::move(responsepacket)); } - std::unique_ptr responsepacket = NetworkPacket::AllocatePacket(); - *responsepacket << (uint32)NETWORK_COMMAND_AUTH << (uint32)connection.authstatus; - connection.QueuePacket(std::move(responsepacket)); return 1; } @@ -598,6 +653,9 @@ int Network::Client_Handle_MAP(NetworkConnection& connection, NetworkPacket& pac SDL_RWops* rw = SDL_RWFromMem(&chunk_buffer[0], size); if (game_load_sv6(rw)) { game_load_init(); + if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) & 1) + pause_toggle(); + game_command_queue.clear(); } SDL_RWclose(rw); } @@ -661,6 +719,23 @@ int Network::Client_Handle_TICK(NetworkConnection& connection, NetworkPacket& pa return 1; } +int Network::Client_Handle_PLAYERLIST(NetworkConnection& connection, NetworkPacket& packet) +{ + player_list.clear(); + uint32 size; + packet >> size; + for (unsigned int i = 0; i < size; i++) { + const char* name = packet.ReadString(); + std::unique_ptr player(new NetworkPlayer(name)); // change to make_unique in c++14 + packet >> player->id >> player->flags; + if (player->flags & NETWORK_PLAYER_FLAG_ISSERVER) { + server_connection.player = player.get(); + } + player_list.push_back(std::move(player)); + } + return 1; +} + int network_init() { return gNetwork.Init(); @@ -691,11 +766,26 @@ int network_get_mode() return gNetwork.GetMode(); } +int network_get_authstatus() +{ + return gNetwork.GetAuthStatus(); +} + uint32 network_get_server_tick() { return gNetwork.GetServerTick(); } +int network_get_num_players() +{ + return gNetwork.player_list.size(); +} + +const char* network_get_player_name(unsigned int index) +{ + return (const char*)gNetwork.player_list[index]->name; +} + void network_send_map() { gNetwork.Server_Send_MAP(); diff --git a/src/network/network.h b/src/network/network.h index 758792eb6e..2713d91f80 100644 --- a/src/network/network.h +++ b/src/network/network.h @@ -40,6 +40,10 @@ enum { NETWORK_AUTH_BADPASSWORD }; +enum { + NETWORK_PLAYER_FLAG_ISSERVER = 1 << 0, +}; + #ifdef __cplusplus #include @@ -54,6 +58,8 @@ extern "C" { template struct ByteSwapT { }; template <> +struct ByteSwapT<1> { static uint8 SwapBE(uint8 value) { return value; } }; +template <> struct ByteSwapT<2> { static uint16 SwapBE(uint16 value) { return SDL_SwapBE16(value); } }; template <> struct ByteSwapT<4> { static uint32 SwapBE(uint32 value) { return SDL_SwapBE32(value); } }; @@ -83,6 +89,16 @@ public: int read; }; +class NetworkPlayer +{ +public: + NetworkPlayer(const char* name); + uint8 id; + uint8 name[32 + 1]; + uint16 ping; + uint32 flags; +}; + class NetworkConnection { public: @@ -94,19 +110,13 @@ public: SOCKET socket; NetworkPacket inboundpacket; int authstatus; + NetworkPlayer* player; private: int SendPacket(NetworkPacket& packet); std::list> outboundpackets; }; -class NetworkPlayer -{ -public: - uint8 name[16 + 1]; - uint16 ping; -}; - class Network { public: @@ -117,6 +127,7 @@ public: bool BeginClient(const char* host, unsigned short port); bool BeginServer(unsigned short port); int GetMode(); + int GetAuthStatus(); uint32 GetServerTick(); void Update(); @@ -127,6 +138,9 @@ public: void Client_Send_GAMECMD(uint32 eax, uint32 ebx, uint32 ecx, uint32 edx, uint32 esi, uint32 edi, uint32 ebp); void Server_Send_GAMECMD(uint32 eax, uint32 ebx, uint32 ecx, uint32 edx, uint32 esi, uint32 edi, uint32 ebp); void Server_Send_TICK(); + void Server_Send_PLAYERLIST(); + + std::vector> player_list; private: bool ProcessConnection(NetworkConnection& connection); @@ -169,6 +183,7 @@ private: int Client_Handle_GAMECMD(NetworkConnection& connection, NetworkPacket& packet); int Server_Handle_GAMECMD(NetworkConnection& connection, NetworkPacket& packet); int Client_Handle_TICK(NetworkConnection& connection, NetworkPacket& packet); + int Client_Handle_PLAYERLIST(NetworkConnection& connection, NetworkPacket& packet); }; extern "C" { @@ -181,7 +196,10 @@ int network_begin_server(int port); void network_update(); int network_get_mode(); +int network_get_authstatus(); uint32 network_get_server_tick(); +int network_get_num_players(); +const char* network_get_player_name(unsigned int index); void network_send_map(); void network_send_chat(const char* text); diff --git a/src/windows/network.c b/src/windows/network.c index edd07219d2..19019acd3e 100644 --- a/src/windows/network.c +++ b/src/windows/network.c @@ -18,12 +18,12 @@ * along with this program. If not, see . *****************************************************************************/ +#include "../interface/themes.h" +#include "../interface/widget.h" #include "../interface/window.h" #include "../localisation/localisation.h" #include "../network/network.h" -static void window_chat_host_emptysub() { } - static void window_chat_host_textinput(rct_window *w, int widgetIndex, char *text) { network_send_chat(text); @@ -71,4 +71,213 @@ void window_chat_open() w->colours[2] = 0; w->number = 0; window_text_input_open(w, 0, 6000, 6001, STR_NONE, 0, 64); +} + +enum WINDOW_PLAYER_LIST_WIDGET_IDX { + WIDX_BACKGROUND, + WIDX_TITLE, + WIDX_CLOSE, + WIDX_CONTENT_PANEL, + WIDX_TAB1, + WIDX_LIST, +}; + +static rct_widget window_player_list_widgets[] = { + { WWT_FRAME, 0, 0, 319, 0, 269, 0x0FFFFFFFF, 65535 }, // panel / background + { WWT_CAPTION, 0, 1, 318, 1, 14, STR_PLAYER_LIST, STR_WINDOW_TITLE_TIP }, // title bar + { WWT_CLOSEBOX, 0, 307, 317, 2, 13, STR_CLOSE_X, STR_CLOSE_WINDOW_TIP }, // close x button + { WWT_RESIZE, 1, 0, 319, 43, 269, 0x0FFFFFFFF, STR_NONE }, // content panel + { WWT_TAB, 1, 3, 33, 17, 43, 0x02000144E, STR_NONE }, // tab + { WWT_SCROLL, 1, 3, 316, 72, 266, 3, 65535 }, // list + { WIDGETS_END }, +}; + +static void window_player_list_mouseup(rct_window *w, int widgetIndex); +static void window_player_list_resize(rct_window *w); +static void window_player_list_mousedown(int widgetIndex, rct_window* w, rct_widget* widget); +static void window_player_list_update(rct_window *w); +static void window_player_list_scrollgetsize(rct_window *w, int scrollIndex, int *width, int *height); +static void window_player_list_invalidate(rct_window *w); +static void window_player_list_paint(rct_window *w, rct_drawpixelinfo *dpi); +static void window_player_list_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int scrollIndex); + +static rct_window_event_list window_player_list_events = { + NULL, + window_player_list_mouseup, + window_player_list_resize, + window_player_list_mousedown, + NULL, + NULL, + window_player_list_update, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + window_player_list_scrollgetsize, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + window_player_list_invalidate, + window_player_list_paint, + window_player_list_scrollpaint +}; + +static void window_player_list_refresh_list(rct_window *w); + +void window_player_list_open() +{ + rct_window* window; + + // Check if window is already open + window = window_bring_to_front_by_class(WC_PLAYER_LIST); + if (window != NULL) + return; + + window = window_create_auto_pos(320, 270, &window_player_list_events, WC_PLAYER_LIST, WF_10 | WF_RESIZABLE); + + window->widgets = window_player_list_widgets; + window->enabled_widgets = 1 << WIDX_CLOSE; + window->no_list_items = 0; + window->selected_list_item = -1; + window->frame_no = 0; + window->min_width = 320; + window->min_height = 270; + window->max_width = 500; + window->max_height = 450; + + window_init_scroll_widgets(window); + window->page = 0; + window->list_information_type = 0; + window->colours[0] = 7; + window->colours[1] = 7; + window->colours[2] = 7; +} + +static void window_player_list_mouseup(rct_window *w, int widgetIndex) +{ + switch (widgetIndex) { + case WIDX_CLOSE: + window_close(w); + break; + } +} + +static void window_player_list_resize(rct_window *w) +{ + if (w->width < w->min_width) { + window_invalidate(w); + w->width = w->min_width; + } + if (w->height < w->min_height) { + window_invalidate(w); + w->height = w->min_height; + } + + window_player_list_refresh_list(w); +} + +static void window_player_list_mousedown(int widgetIndex, rct_window* w, rct_widget* widget) +{ + switch (widgetIndex) { + case WIDX_TAB1: + if (w->page != widgetIndex - WIDX_TAB1) { + w->page = widgetIndex - WIDX_TAB1; + w->no_list_items = 0; + w->frame_no = 0; + w->selected_list_item = -1; + window_invalidate(w); + } + break; + } +} + +static void window_player_list_update(rct_window *w) +{ + widget_invalidate(w, WIDX_TAB1 + w->page); +} + +static void window_player_list_scrollgetsize(rct_window *w, int scrollIndex, int *width, int *height) +{ + int i; + + uint16 playerCount = 0; + + if (RCT2_GLOBAL(RCT2_ADDRESS_STAFF_HIGHLIGHTED_INDEX, short) != -1) { + RCT2_GLOBAL(RCT2_ADDRESS_STAFF_HIGHLIGHTED_INDEX, short) = -1; + window_invalidate(w); + } + + *height = playerCount * 10; + i = *height - window_player_list_widgets[WIDX_LIST].bottom + window_player_list_widgets[WIDX_LIST].top + 21; + if (i < 0) + i = 0; + if (i < w->scrolls[0].v_top) { + w->scrolls[0].v_top = i; + window_invalidate(w); + } + + *width = 420; +} + +static void window_player_list_invalidate(rct_window *w) +{ + for (int i = 0; i < 1; i++) + w->pressed_widgets &= ~(1 << (WIDX_TAB1 + i)); + w->pressed_widgets |= 1LL << (WIDX_TAB1 + w->page); + window_player_list_widgets[WIDX_BACKGROUND].right = w->width - 1; + window_player_list_widgets[WIDX_BACKGROUND].bottom = w->height - 1; + window_player_list_widgets[WIDX_CONTENT_PANEL].right = w->width - 1; + window_player_list_widgets[WIDX_CONTENT_PANEL].bottom = w->height - 1; + window_player_list_widgets[WIDX_TITLE].right = w->width - 2; + window_player_list_widgets[WIDX_CLOSE].left = w->width - 2 - 0x0B; + window_player_list_widgets[WIDX_CLOSE].right = w->width - 2 - 0x0B + 0x0A; + window_player_list_widgets[WIDX_LIST].right = w->width - 4; + window_player_list_widgets[WIDX_LIST].bottom = w->height - 0x0F; +} + +static void window_player_list_paint(rct_window *w, rct_drawpixelinfo *dpi) +{ + window_draw_widgets(w, dpi); +} + +static void window_player_list_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int scrollIndex) +{ + int y; + + gfx_fill_rect(dpi, dpi->x, dpi->y, dpi->x + dpi->width - 1, dpi->y + dpi->height - 1, ((char*)0x0141FC48)[w->colours[1] * 8]); + + y = 0; + for (int i = 0; i < network_get_num_players(); i++) { + if (y > dpi->y + dpi->height) { + break; + } + + int format = 1191; + + if (y + 11 >= dpi->y) { + gfx_draw_string(dpi, (char*)network_get_player_name(i), 255, 0, y - 1); + } + y += 10; + } +} + +static void window_player_list_refresh_list(rct_window *w) +{ + window_invalidate(w); + + w->no_list_items = 1; + w->list_item_positions[0] = 0; + + w->selected_list_item = -1; + window_invalidate(w); } \ No newline at end of file diff --git a/src/windows/top_toolbar.c b/src/windows/top_toolbar.c index c55bad4f31..f15b59265d 100644 --- a/src/windows/top_toolbar.c +++ b/src/windows/top_toolbar.c @@ -65,6 +65,7 @@ enum { WIDX_FINANCES, WIDX_RESEARCH, WIDX_NEWS, + WIDX_NETWORK, WIDX_SEPARATOR, }; @@ -105,6 +106,10 @@ typedef enum { DDIDX_SCENARIO_OPTIONS = 4 } TOP_TOOLBAR_DEBUG_DDIDX; +typedef enum { + DDIDX_PLAYER_LIST = 0 +} TOP_TOOLBAR_NETWORK_DDIDX; + enum { DDIDX_CHEATS, DDIDX_ENABLE_SANDBOX_MODE = 2, @@ -129,6 +134,7 @@ static const int left_aligned_widgets_order[] = { WIDX_ROTATE, WIDX_VIEW_MENU, WIDX_MAP, + WIDX_NETWORK, }; // from right to left @@ -179,6 +185,7 @@ static rct_widget window_top_toolbar_widgets[] = { { WWT_TRNBTN, 3, 0x001E, 0x003B, 0, 27, 0x20000000 | 0x15F9, 3235 }, // Finances { WWT_TRNBTN, 3, 0x001E, 0x003B, 0, 27, 0x20000000 | 0x15F9, 2275 }, // Research { WWT_TRNBTN, 3, 0x001E, 0x003B, 0, 27, 0x20000000 | 0x15F9, STR_SHOW_RECENT_MESSAGES_TIP }, // News + { WWT_TRNBTN, 1, 0x001E, 0x003B, 0, 27, 0x20000000 | 0x15F9, 2276 }, // Network { WWT_EMPTY, 0, 0, 10-1, 0, 0, 0xFFFFFFFF, STR_NONE }, // Artificial widget separator { WIDGETS_END }, @@ -234,6 +241,8 @@ void top_toolbar_init_rotate_menu(rct_window *window, rct_widget *widget); void top_toolbar_rotate_menu_dropdown(short dropdownIndex); void top_toolbar_init_debug_menu(rct_window *window, rct_widget *widget); void top_toolbar_debug_menu_dropdown(short dropdownIndex); +void top_toolbar_init_network_menu(rct_window *window, rct_widget *widget); +void top_toolbar_network_menu_dropdown(short dropdownIndex); void toggle_footpath_window(); void toggle_land_window(rct_window *topToolbar, int widgetIndex); @@ -461,6 +470,9 @@ static void window_top_toolbar_mousedown(int widgetIndex, rct_window*w, rct_widg case WIDX_DEBUG: top_toolbar_init_debug_menu(w, widget); break; + case WIDX_NETWORK: + top_toolbar_init_network_menu(w, widget); + break; } } @@ -560,6 +572,9 @@ static void window_top_toolbar_dropdown(rct_window *w, int widgetIndex, int drop case WIDX_DEBUG: top_toolbar_debug_menu_dropdown(dropdownIndex); break; + case WIDX_NETWORK: + top_toolbar_network_menu_dropdown(dropdownIndex); + break; } } @@ -598,6 +613,7 @@ static void window_top_toolbar_invalidate(rct_window *w) window_top_toolbar_widgets[WIDX_CHEATS].type = WWT_TRNBTN; window_top_toolbar_widgets[WIDX_DEBUG].type = gConfigGeneral.debugging_tools ? WWT_TRNBTN : WWT_EMPTY; window_top_toolbar_widgets[WIDX_NEWS].type = WWT_TRNBTN; + window_top_toolbar_widgets[WIDX_NETWORK].type = WWT_TRNBTN; if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & (SCREEN_FLAGS_SCENARIO_EDITOR | SCREEN_FLAGS_TRACK_DESIGNER | SCREEN_FLAGS_TRACK_MANAGER)) { window_top_toolbar_widgets[WIDX_PAUSE].type = WWT_EMPTY; @@ -645,7 +661,7 @@ static void window_top_toolbar_invalidate(rct_window *w) } enabledWidgets = 0; - for (i = WIDX_PAUSE; i <= WIDX_NEWS; i++) + for (i = WIDX_PAUSE; i <= WIDX_NETWORK; i++) if (window_top_toolbar_widgets[i].type != WWT_EMPTY) enabledWidgets |= (1 << i); w->enabled_widgets = enabledWidgets; @@ -2862,6 +2878,21 @@ void top_toolbar_init_debug_menu(rct_window* w, rct_widget* widget) { RCT2_GLOBAL(0x9DEBA2, uint16) = 0; } +void top_toolbar_init_network_menu(rct_window* w, rct_widget* widget) { + gDropdownItemsFormat[0] = STR_PLAYER_LIST; + + window_dropdown_show_text( + w->x + widget->left, + w->y + widget->top, + widget->bottom - widget->top + 1, + w->colours[1] | 0x80, + 0, + 1 + ); + + RCT2_GLOBAL(0x9DEBA2, uint16) = 0; +} + void top_toolbar_debug_menu_dropdown(short dropdownIndex) { if (dropdownIndex == -1) dropdownIndex = RCT2_GLOBAL(0x9DEBA2, uint16); rct_window* w = window_get_main(); @@ -2887,6 +2918,18 @@ void top_toolbar_debug_menu_dropdown(short dropdownIndex) { } } +void top_toolbar_network_menu_dropdown(short dropdownIndex) { + if (dropdownIndex == -1) dropdownIndex = RCT2_GLOBAL(0x9DEBA2, uint16); + rct_window* w = window_get_main(); + if (w) { + switch (dropdownIndex) { + case DDIDX_PLAYER_LIST: + window_player_list_open(); + break; + } + } +} + /** * * rct2: 0x0066CDE4