From 6e3068cd0a1c03f7bbc6674c617ce634519bebb6 Mon Sep 17 00:00:00 2001 From: zsilencer Date: Wed, 20 Jan 2016 15:45:09 -0700 Subject: [PATCH] MP groups and permissions --- data/language/english_uk.txt | 10 +- openrct2.vcxproj | 3 +- openrct2.vcxproj.filters | 9 +- src/game.c | 15 +- src/game.h | 3 +- src/interface/window.h | 7 +- src/localisation/string_ids.h | 11 +- src/network/network.cpp | 322 +++++++++++++++++--- src/network/network.h | 46 ++- src/windows/multiplayer.c | 536 ++++++++++++++++++++++++++++++++++ src/windows/player.c | 377 ++++++++++++++++++++++++ src/windows/player_list.c | 359 ----------------------- src/windows/top_toolbar.c | 10 +- 13 files changed, 1292 insertions(+), 416 deletions(-) create mode 100644 src/windows/multiplayer.c create mode 100644 src/windows/player.c delete mode 100644 src/windows/player_list.c diff --git a/data/language/english_uk.txt b/data/language/english_uk.txt index d83f63383f..1111e14da7 100644 --- a/data/language/english_uk.txt +++ b/data/language/english_uk.txt @@ -3894,7 +3894,7 @@ STR_5552 :{POP16}{POP16}Year {COMMA16}, {PUSH16}{PUSH16}{PUSH16}{STRINGID} {M STR_5553 :Pause game when Steam overlay is open STR_5554 :{SMALLFONT}{BLACK}Enable mountain tool STR_5555 :Show vehicles from other track types -STR_5556 :Kick Player +STR_5556 :{SMALLFONT}{BLACK}Kick Player STR_5557 :Stay connected after desynchronisation (Multiplayer) STR_5558 :A restart is required for this setting to take effect STR_5559 :10 min. inspections @@ -3973,6 +3973,14 @@ STR_5631 :Original DLC Parks STR_5632 :Build your own... STR_5633 :CMD + STR_5634 :OPTION + +STR_5635 :{WINDOW_COLOUR_2}Money spent: {BLACK}{CURRENCY2DP} +STR_5636 :{WINDOW_COLOUR_2}Commands ran: {BLACK}{COMMA16} +STR_5637 :Can't do this... +STR_5638 :Permission denied +STR_5639 :{SMALLFONT}{BLACK}Show list of players +STR_5640 :{SMALLFONT}{BLACK}Manage groups +STR_5641 :Default Group: +STR_5642 :Group: ############# # Scenarios # diff --git a/openrct2.vcxproj b/openrct2.vcxproj index 215b153a01..0e44e7076e 100644 --- a/openrct2.vcxproj +++ b/openrct2.vcxproj @@ -102,9 +102,10 @@ + - + diff --git a/openrct2.vcxproj.filters b/openrct2.vcxproj.filters index 2ad680ca98..5fc8dbe7c9 100644 --- a/openrct2.vcxproj.filters +++ b/openrct2.vcxproj.filters @@ -498,9 +498,6 @@ Source\Windows - - Source\Windows - Source\Interface @@ -579,6 +576,12 @@ Source\Core + + Source\Windows + + + Source\Windows + diff --git a/src/game.c b/src/game.c index b9a750f995..2e60f07092 100644 --- a/src/game.c +++ b/src/game.c @@ -418,7 +418,7 @@ static int game_check_affordability(int cost) return MONEY32_UNDEFINED; } -static GAME_COMMAND_POINTER* new_game_command_table[62]; +static GAME_COMMAND_POINTER* new_game_command_table[63]; /** * @@ -451,6 +451,10 @@ int game_do_command_p(int command, int *eax, int *ebx, int *ecx, int *edx, int * original_edi = *edi; original_ebp = *ebp; + if (command >= countof(new_game_command_table)) { + return MONEY32_UNDEFINED; + } + flags = *ebx; RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = 0xFFFF; @@ -533,6 +537,10 @@ int game_do_command_p(int command, int *eax, int *ebx, int *ecx, int *edx, int * } } + if (network_get_mode() == NETWORK_MODE_SERVER && !(flags & GAME_COMMAND_FLAG_NETWORKED)) { + network_add_player_money_spent(network_get_current_player_id(), cost); + } + return cost; } } @@ -1169,7 +1177,7 @@ void game_load_or_quit_no_save_prompt() } } -static GAME_COMMAND_POINTER* new_game_command_table[62] = { +static GAME_COMMAND_POINTER* new_game_command_table[63] = { game_command_set_ride_appearance, game_command_set_land_height, game_pause_toggle, @@ -1231,5 +1239,6 @@ static GAME_COMMAND_POINTER* new_game_command_table[62] = { game_command_set_banner_name, game_command_set_sign_name, game_command_set_banner_style, - game_command_set_sign_style + game_command_set_sign_style, + game_command_set_player_group }; diff --git a/src/game.h b/src/game.h index 91e49141a5..fa646dafe5 100644 --- a/src/game.h +++ b/src/game.h @@ -87,7 +87,8 @@ enum GAME_COMMAND { GAME_COMMAND_SET_BANNER_NAME, GAME_COMMAND_SET_SIGN_NAME, GAME_COMMAND_SET_BANNER_STYLE, - GAME_COMMAND_SET_SIGN_STYLE + GAME_COMMAND_SET_SIGN_STYLE, + GAME_COMMAND_SET_PLAYER_GROUP }; enum { diff --git a/src/interface/window.h b/src/interface/window.h index 15aaa1175a..1077364831 100644 --- a/src/interface/window.h +++ b/src/interface/window.h @@ -451,8 +451,8 @@ enum { WC_CHANGELOG = 121, WC_TITLE_EDITOR = 122, WC_TITLE_COMMAND_EDITOR = 123, - WC_CHAT_HOST = 124, - WC_PLAYER_LIST = 125, + WC_MULTIPLAYER = 124, + WC_PLAYER = 125, WC_NETWORK_STATUS = 126, WC_SERVER_LIST = 127, WC_SERVER_START = 128, @@ -632,7 +632,8 @@ void window_sign_open(rct_windownumber number); void window_sign_small_open(rct_windownumber number); void window_news_options_open(); void window_cheats_open(); -void window_player_list_open(); +void window_multiplayer_open(); +void window_player_open(uint8 id); void window_network_status_open(const char* text); void window_network_status_close(); void window_network_status_open_password(); diff --git a/src/localisation/string_ids.h b/src/localisation/string_ids.h index 3556161df2..24c9871d78 100644 --- a/src/localisation/string_ids.h +++ b/src/localisation/string_ids.h @@ -2176,7 +2176,7 @@ enum { STR_CHEAT_SHOW_VEHICLES_FROM_OTHER_TRACK_TYPES = 5555, - STR_KICK_PLAYER = 5556, + STR_KICK_PLAYER_TIP = 5556, STR_STAY_CONNECTED_AFTER_DESYNC = 5557, STR_AUTO_OPEN_SHOPS = 5586, @@ -2260,6 +2260,15 @@ enum { STR_CMD_PLUS = 5633, STR_OPTION_PLUS = 5634, + STR_MONEY_SPENT = 5635, + STR_COMMANDS_RAN = 5636, + STR_CANT_DO_THIS = 5637, + STR_PERMISSION_DENIED = 5638, + STR_PLAYERS_TIP = 5639, + STR_GROUPS_TIP = 5640, + STR_DEFAULT_GROUP = 5641, + STR_GROUP = 5642, + // 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 2bc9b132df..2308b3a94d 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -72,21 +72,11 @@ enum { NETWORK_COMMAND_PINGLIST, NETWORK_COMMAND_SETDISCONNECTMSG, NETWORK_COMMAND_GAMEINFO, + NETWORK_COMMAND_SHOWERROR, NETWORK_COMMAND_MAX, NETWORK_COMMAND_INVALID = -1 }; -const char *NetworkCommandNames[] = { - "NETWORK_COMMAND_AUTH", - "NETWORK_COMMAND_MAP", - "NETWORK_COMMAND_CHAT", - "NETWORK_COMMAND_GAMECMD", - "NETWORK_COMMAND_TICK", - "NETWORK_COMMAND_PLAYERLIST", - "NETWORK_COMMAND_PING", - "NETWORK_COMMAND_PINGLIST", -}; - enum { ADVERTISE_STATUS_DISABLED, ADVERTISE_STATUS_UNREGISTERED, @@ -165,7 +155,7 @@ const char* NetworkPacket::ReadString() strend++; } if (*strend != 0) { - return 0; + return nullptr; } read++; return str; @@ -196,6 +186,35 @@ NetworkPlayer::NetworkPlayer(const char* name) NetworkPlayer::name[sizeof(NetworkPlayer::name) - 1] = 0; ping = 0; flags = 0; + money_spent = MONEY(0, 0); + commands_ran = 0; + group = 0; +} + +void NetworkPlayer::AddMoneySpent(money32 cost) +{ + money_spent += cost; + commands_ran++; + window_invalidate_by_number(WC_PLAYER, id); +} + +NetworkGroup::NetworkGroup() +{ + permissions = 0; + name_string_id = STR_NONE; +} + +NetworkGroup::~NetworkGroup() +{ + user_string_free(name_string_id); +} + +bool NetworkGroup::CanRun(int command) +{ + if (permissions) { + return true; + } + return false; } NetworkConnection::NetworkConnection() @@ -414,6 +433,7 @@ Network::Network() client_command_handlers[NETWORK_COMMAND_PING] = &Network::Client_Handle_PING; client_command_handlers[NETWORK_COMMAND_PINGLIST] = &Network::Client_Handle_PINGLIST; client_command_handlers[NETWORK_COMMAND_SETDISCONNECTMSG] = &Network::Client_Handle_SETDISCONNECTMSG; + client_command_handlers[NETWORK_COMMAND_SHOWERROR] = &Network::Client_Handle_SHOWERROR; 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; @@ -440,6 +460,20 @@ bool Network::Init() wsa_initialized = true; } #endif + + // Hardcoded permission groups + std::unique_ptr spectator(new NetworkGroup()); // change to make_unique in c++14 + spectator->name = "Spectator"; + spectator->permissions = 0; + spectator->id = 0; + group_list.push_back(std::move(spectator)); + std::unique_ptr fullaccess(new NetworkGroup()); // change to make_unique in c++14 + fullaccess->name = "Full Access"; + fullaccess->permissions = 1; + fullaccess->id = 1; + group_list.push_back(std::move(fullaccess)); + SetDefaultGroup(0); + status = NETWORK_STATUS_READY; return true; } @@ -467,6 +501,7 @@ void Network::Close() client_connection_list.clear(); game_command_queue.clear(); player_list.clear(); + group_list.clear(); #ifdef __WINDOWS__ if (wsa_initialized) { @@ -540,6 +575,7 @@ bool Network::BeginServer(unsigned short port, const char* address) NetworkPlayer* player = AddPlayer(gConfigNetwork.player_name); player->flags |= NETWORK_PLAYER_FLAG_ISSERVER; + player->group = 1; player_id = player->id; printf("Ready for clients...\n"); @@ -760,12 +796,40 @@ void Network::UpdateClient() } } -NetworkPlayer* Network::GetPlayerByID(int id) { +std::vector>::iterator Network::GetPlayerIteratorByID(uint8 id) +{ auto it = std::find_if(player_list.begin(), player_list.end(), [&id](std::unique_ptr const& player) { return player->id == id; }); if (it != player_list.end()) { - return (*it).get(); + return it; } - return 0; + return player_list.end(); +} + +NetworkPlayer* Network::GetPlayerByID(uint8 id) +{ + auto it = GetPlayerIteratorByID(id); + if (it != player_list.end()) { + return it->get(); + } + return nullptr; +} + +std::vector>::iterator Network::GetGroupIteratorByID(uint8 id) +{ + auto it = std::find_if(group_list.begin(), group_list.end(), [&id](std::unique_ptr const& group) { return group->id == id; }); + if (it != group_list.end()) { + return it; + } + return group_list.end(); +} + +NetworkGroup* Network::GetGroupByID(uint8 id) +{ + auto it = GetGroupIteratorByID(id); + if (it != group_list.end()) { + return it->get(); + } + return nullptr; } const char* Network::FormatChat(NetworkPlayer* fromplayer, const char* text) @@ -958,6 +1022,18 @@ void Network::AdvertiseHeartbeat() #endif } +uint8 Network::GetDefaultGroup() +{ + return default_group; +} + +void Network::SetDefaultGroup(uint8 id) +{ + if (GetGroupByID(id)) { + default_group = id; + } +} + void Network::Client_Send_AUTH(const char* name, const char* password) { std::unique_ptr packet = std::move(NetworkPacket::Allocate()); @@ -1063,7 +1139,7 @@ void Network::Server_Send_PLAYERLIST() *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; + *packet << player_list[i]->id << player_list[i]->flags << player_list[i]->group << player_list[i]->reserved; } SendPacketToClients(*packet); } @@ -1131,6 +1207,13 @@ void Network::Server_Send_GAMEINFO(NetworkConnection& connection) connection.QueuePacket(std::move(packet)); } +void Network::Server_Send_SHOWERROR(NetworkConnection& connection, rct_string_id title, rct_string_id message) +{ + std::unique_ptr packet = std::move(NetworkPacket::Allocate()); + *packet << (uint32)NETWORK_COMMAND_SHOWERROR << title << message; + connection.QueuePacket(std::move(packet)); +} + bool Network::ProcessConnection(NetworkConnection& connection) { int packetStatus; @@ -1171,7 +1254,6 @@ void Network::ProcessPacket(NetworkConnection& connection, NetworkPacket& packet uint32 command; packet >> command; if (command < NETWORK_COMMAND_MAX) { - // printf("RECV %s\n", NetworkCommandNames[command]); switch (gNetwork.GetMode()) { case NETWORK_MODE_SERVER: if (server_command_handlers[command]) { @@ -1198,7 +1280,13 @@ void Network::ProcessGameCommandQueue() if (GetPlayerID() == gc.playerid) { game_command_callback = game_command_callback_get_callback(gc.callback); } - game_do_command_p(gc.esi, (int*)&gc.eax, (int*)&gc.ebx, (int*)&gc.ecx, (int*)&gc.edx, (int*)&gc.esi, (int*)&gc.edi, (int*)&gc.ebp); + money32 cost = game_do_command_p(gc.esi, (int*)&gc.eax, (int*)&gc.ebx, (int*)&gc.ecx, (int*)&gc.edx, (int*)&gc.esi, (int*)&gc.edi, (int*)&gc.ebp); + if (cost != MONEY32_UNDEFINED) { + NetworkPlayer* player = GetPlayerByID(gc.playerid); + if (player) { + player->AddMoneySpent(cost); + } + } game_command_queue.erase(game_command_queue.begin()); } } @@ -1235,7 +1323,7 @@ void Network::RemoveClient(std::unique_ptr& connection) NetworkPlayer* Network::AddPlayer(const char* name) { - NetworkPlayer* addedplayer = 0; + NetworkPlayer* addedplayer = nullptr; int newid = -1; if (GetMode() == NETWORK_MODE_SERVER) { // Find first unused player id @@ -1251,6 +1339,7 @@ NetworkPlayer* Network::AddPlayer(const char* name) if (newid != -1) { std::unique_ptr player(new NetworkPlayer(name)); // change to make_unique in c++14 player->id = newid; + player->group = GetDefaultGroup(); addedplayer = player.get(); player_list.push_back(std::move(player)); if (GetMode() == NETWORK_MODE_SERVER) { @@ -1439,24 +1528,40 @@ int Network::Server_Handle_GAMECMD(NetworkConnection& connection, NetworkPacket& uint32 args[7]; uint8 playerid; uint8 callback; - if (connection.player) { - playerid = connection.player->id; + + if (!connection.player) { + return 0; } + + playerid = connection.player->id; + packet >> tick >> args[0] >> args[1] >> args[2] >> args[3] >> args[4] >> args[5] >> args[6] >> callback; int commandCommand = args[4]; - // Don't let clients send pause or quit - if (commandCommand != GAME_COMMAND_TOGGLE_PAUSE && - commandCommand != GAME_COMMAND_LOAD_OR_QUIT - ) { - // Run game command, and if it is successful send to clients - money32 cost = game_do_command(args[0], args[1] | GAME_COMMAND_FLAG_NETWORKED, args[2], args[3], args[4], args[5], args[6]); - if (cost != MONEY32_UNDEFINED) { - Server_Send_GAMECMD(args[0], args[1], args[2], args[3], args[4], args[5], args[6], playerid, callback); - } + // Check if player's group permission allows command to run + NetworkGroup* group = GetGroupByID(connection.player->group); + if (group && !group->CanRun(commandCommand)) { + Server_Send_SHOWERROR(connection, STR_CANT_DO_THIS, STR_PERMISSION_DENIED); + return 0; } + // Don't let clients send pause or quit + if (commandCommand == GAME_COMMAND_TOGGLE_PAUSE || + commandCommand == GAME_COMMAND_LOAD_OR_QUIT + ) { + return 0; + } + + + // Run game command, and if it is successful send to clients + money32 cost = game_do_command(args[0], args[1] | GAME_COMMAND_FLAG_NETWORKED, args[2], args[3], args[4], args[5], args[6]); + if (cost == MONEY32_UNDEFINED) { + return 0; + } + connection.player->AddMoneySpent(cost); + Server_Send_GAMECMD(args[0], args[1], args[2], args[3], args[4], args[5], args[6], playerid, callback); + return 1; } @@ -1473,19 +1578,39 @@ int Network::Client_Handle_TICK(NetworkConnection& connection, NetworkPacket& pa int Network::Client_Handle_PLAYERLIST(NetworkConnection& connection, NetworkPacket& packet) { - player_list.clear(); uint32 size; packet >> size; + std::vector ids; for (unsigned int i = 0; i < size; i++) { const char* name = packet.ReadString(); - NetworkPlayer* player = AddPlayer(name); - if (player) { - packet >> player->id >> player->flags; - if (player->flags & NETWORK_PLAYER_FLAG_ISSERVER) { - server_connection.player = player; + uint8 id; + uint8 flags; + uint8 group; + uint16 reserved; + packet >> id >> flags >> group >> reserved; + ids.push_back(id); + if (!GetPlayerByID(id)) { + NetworkPlayer* player = AddPlayer(name); + if (player) { + player->id = id; + player->flags = flags; + player->group = group; + player->reserved = reserved; + if (player->flags & NETWORK_PLAYER_FLAG_ISSERVER) { + server_connection.player = player; + } } } } + // Remove any players that are not in newly received list + auto it = player_list.begin(); + while (it != player_list.end()) { + if (std::find(ids.begin(), ids.end(), (*it)->id) == ids.end()) { + it = player_list.erase(it); + } else { + it++; + } + } return 1; } @@ -1503,6 +1628,7 @@ int Network::Server_Handle_PING(NetworkConnection& connection, NetworkPacket& pa } if (connection.player) { connection.player->ping = ping; + window_invalidate_by_number(WC_PLAYER, connection.player->id); } return 1; } @@ -1520,6 +1646,7 @@ int Network::Client_Handle_PINGLIST(NetworkConnection& connection, NetworkPacket player->ping = ping; } } + window_invalidate_by_class(WC_PLAYER); return 1; } @@ -1540,6 +1667,14 @@ int Network::Server_Handle_GAMEINFO(NetworkConnection& connection, NetworkPacket return 1; } +int Network::Client_Handle_SHOWERROR(NetworkConnection& connection, NetworkPacket& packet) +{ + rct_string_id title, message; + packet >> title >> message; + window_error_open(title, message); + return 1; +} + int network_init() { return gNetwork.Init(); @@ -1620,6 +1755,107 @@ int network_get_player_id(unsigned int index) return gNetwork.player_list[index]->id; } +money32 network_get_player_money_spent(unsigned int index) +{ + return gNetwork.player_list[index]->money_spent; +} + +void network_add_player_money_spent(unsigned int index, money32 cost) +{ + gNetwork.player_list[index]->AddMoneySpent(cost); +} + +unsigned int network_get_player_commands_ran(unsigned int index) +{ + return gNetwork.player_list[index]->commands_ran; +} + +int network_get_player_index(uint8 id) +{ + auto it = gNetwork.GetPlayerIteratorByID(id); + if(it == gNetwork.player_list.end()){ + return -1; + } + return gNetwork.GetPlayerIteratorByID(id) - gNetwork.player_list.begin(); +} + +uint8 network_get_player_group(unsigned int index) +{ + return gNetwork.player_list[index]->group; +} + +void network_set_player_group(unsigned int index, unsigned int groupindex) +{ + gNetwork.player_list[index]->group = gNetwork.group_list[groupindex]->id; +} + +int network_get_group_index(uint8 id) +{ + auto it = gNetwork.GetGroupIteratorByID(id); + if(it == gNetwork.group_list.end()){ + return -1; + } + return gNetwork.GetGroupIteratorByID(id) - gNetwork.group_list.begin(); +} + +uint8 network_get_group_id(unsigned int index) +{ + return gNetwork.group_list[index]->id; +} + +int network_get_num_groups() +{ + return gNetwork.group_list.size(); +} + +const char* network_get_group_name(unsigned int index) +{ + return gNetwork.group_list[index]->name.c_str(); +} + +rct_string_id network_get_group_name_string_id(unsigned int index) +{ + if (gNetwork.group_list[index]->name_string_id == STR_NONE) { + gNetwork.group_list[index]->name_string_id = user_string_allocate(128, gNetwork.group_list[index]->name.c_str()); + } + return gNetwork.group_list[index]->name_string_id; +} + +void game_command_set_player_group(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) +{ + uint8 playerid = (uint8)*ecx; + uint8 groupid = (uint8)*edx; + NetworkPlayer* player = gNetwork.GetPlayerByID(playerid); + if (!player) { + *ebx = MONEY32_UNDEFINED; + return; + } + if (!gNetwork.GetGroupByID(groupid)) { + *ebx = MONEY32_UNDEFINED; + return; + } + if (player->flags & NETWORK_PLAYER_FLAG_ISSERVER) { + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = STR_CANT_DO_THIS; + *ebx = MONEY32_UNDEFINED; + return; + } + if (*ebx & GAME_COMMAND_FLAG_APPLY) { + player->group = groupid; + window_invalidate_by_number(WC_PLAYER, playerid); + } + *ebx = 0; +} + +uint8 network_get_default_group() +{ + return gNetwork.GetDefaultGroup(); +} + +void network_set_default_group(uint8 id) +{ + gNetwork.SetDefaultGroup(id); +} + void network_send_map() { gNetwork.Server_Send_MAP(); @@ -1680,6 +1916,20 @@ const char* network_get_player_name(unsigned int index) { return "local (OpenRCT uint32 network_get_player_flags(unsigned int index) { return 0; } int network_get_player_ping(unsigned int index) { return 0; } int network_get_player_id(unsigned int index) { return 0; } +money32 network_get_player_money_spent(unsigned int index) { return MONEY(0, 0); } +void network_add_player_money_spent(unsigned int index, money32 cost) { } +unsigned int network_get_player_commands_ran(unsigned int index) { return 0; } +int network_get_player_index(uint8 id) { return -1; }; +uint8 network_get_player_group(unsigned int index) { return 0; } +void network_set_player_group(unsigned int index, unsigned int groupindex) { } +int network_get_group_index(uint8 id) { return -1; } +uint8 network_get_group_id(unsigned int index) { return 0; } +int network_get_num_groups() { return 0; } +const char* network_get_group_name(unsigned int index) { return ""; }; +rct_string_id network_get_group_name_string_id(unsigned int index) { return -1; } +void game_command_set_player_group(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) { } +uint8 network_get_default_group() { return 0; } +void network_set_default_group(uint8 id) { } void network_send_chat(const char* text) {} void network_send_password(const char* password) {} void network_close() {} diff --git a/src/network/network.h b/src/network/network.h index 2c57c76c83..e5f9ba529e 100644 --- a/src/network/network.h +++ b/src/network/network.h @@ -145,10 +145,27 @@ class NetworkPlayer { public: NetworkPlayer(const char* name); + void AddMoneySpent(money32 cost); uint8 id; uint8 name[32 + 1]; uint16 ping; - uint32 flags; + uint8 flags; + uint8 group; + uint16 reserved; + money32 money_spent; + unsigned int commands_ran; +}; + +class NetworkGroup +{ +public: + NetworkGroup(); + ~NetworkGroup(); + bool CanRun(int command); + std::string name; + uint32 permissions; + uint8 id; + rct_string_id name_string_id; }; class NetworkConnection @@ -220,7 +237,10 @@ public: uint32 GetServerTick(); uint8 GetPlayerID(); void Update(); - NetworkPlayer* GetPlayerByID(int id); + std::vector>::iterator GetPlayerIteratorByID(uint8 id); + NetworkPlayer* GetPlayerByID(uint8 id); + std::vector>::iterator GetGroupIteratorByID(uint8 id); + NetworkGroup* GetGroupByID(uint8 id); const char* FormatChat(NetworkPlayer* fromplayer, const char* text); void SendPacketToClients(NetworkPacket& packet, bool front = false); bool CheckSRAND(uint32 tick, uint32 srand0); @@ -229,6 +249,8 @@ public: void ShutdownClient(); void AdvertiseRegister(); void AdvertiseHeartbeat(); + uint8 GetDefaultGroup(); + void SetDefaultGroup(uint8 id); void Client_Send_AUTH(const char* name, const char* password); void Server_Send_AUTH(NetworkConnection& connection); @@ -244,8 +266,10 @@ public: void Server_Send_PINGLIST(); void Server_Send_SETDISCONNECTMSG(NetworkConnection& connection, const char* msg); void Server_Send_GAMEINFO(NetworkConnection& connection); + void Server_Send_SHOWERROR(NetworkConnection& connection, rct_string_id title, rct_string_id message); std::vector> player_list; + std::vector> group_list; private: bool ProcessConnection(NetworkConnection& connection); @@ -255,7 +279,7 @@ private: void RemoveClient(std::unique_ptr& connection); NetworkPlayer* AddPlayer(const char* name); void PrintError(); - const char *GetMasterServerUrl(); + const char* GetMasterServerUrl(); std::string GenerateAdvertiseKey(); struct GameCommand @@ -294,6 +318,7 @@ private: std::string advertise_key; int advertise_status; uint32 last_heartbeat_time; + uint8 default_group; void UpdateServer(); void UpdateClient(); @@ -315,6 +340,7 @@ private: int Client_Handle_PINGLIST(NetworkConnection& connection, NetworkPacket& packet); int Client_Handle_SETDISCONNECTMSG(NetworkConnection& connection, NetworkPacket& packet); int Server_Handle_GAMEINFO(NetworkConnection& connection, NetworkPacket& packet); + int Client_Handle_SHOWERROR(NetworkConnection& connection, NetworkPacket& packet); }; #endif // __cplusplus @@ -340,6 +366,20 @@ const char* network_get_player_name(unsigned int index); uint32 network_get_player_flags(unsigned int index); int network_get_player_ping(unsigned int index); int network_get_player_id(unsigned int index); +money32 network_get_player_money_spent(unsigned int index); +void network_add_player_money_spent(unsigned int index, money32 cost); +unsigned int network_get_player_commands_ran(unsigned int index); +int network_get_player_index(uint8 id); +uint8 network_get_player_group(unsigned int index); +void network_set_player_group(unsigned int index, unsigned int groupindex); +int network_get_group_index(uint8 id); +uint8 network_get_group_id(unsigned int index); +int network_get_num_groups(); +const char* network_get_group_name(unsigned int index); +rct_string_id network_get_group_name_string_id(unsigned int index); +void game_command_set_player_group(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); +uint8 network_get_default_group(); +void network_set_default_group(uint8 id); void network_send_map(); void network_send_chat(const char* text); diff --git a/src/windows/multiplayer.c b/src/windows/multiplayer.c new file mode 100644 index 0000000000..5c7b6c64f4 --- /dev/null +++ b/src/windows/multiplayer.c @@ -0,0 +1,536 @@ +/***************************************************************************** + * Copyright (c) 2014 Ted John + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * This file is part of OpenRCT2. + * + * OpenRCT2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * 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" +#include "../sprites.h" +#include "../util/util.h" +#include "dropdown.h" + +enum { + WINDOW_MULTIPLAYER_PAGE_PLAYERS, + WINDOW_MULTIPLAYER_PAGE_GROUPS +}; + +enum WINDOW_MULTIPLAYER_WIDGET_IDX { + WIDX_BACKGROUND, + WIDX_TITLE, + WIDX_CLOSE, + WIDX_CONTENT_PANEL, + WIDX_TAB1, + WIDX_TAB2, + + WIDX_LIST = 6, + + WIDX_DEFAULT_GROUP = 6, + WIDX_DEFAULT_GROUP_DROPDOWN, +}; + +static rct_widget window_multiplayer_players_widgets[] = { + { WWT_FRAME, 0, 0, 339, 0, 239, 0x0FFFFFFFF, STR_NONE }, // panel / background + { WWT_CAPTION, 0, 1, 338, 1, 14, STR_MULTIPLAYER, STR_WINDOW_TITLE_TIP }, // title bar + { WWT_CLOSEBOX, 0, 327, 337, 2, 13, STR_CLOSE_X, STR_CLOSE_WINDOW_TIP }, // close x button + { WWT_RESIZE, 1, 0, 339, 43, 239, 0x0FFFFFFFF, STR_NONE }, // content panel + { WWT_TAB, 1, 3, 33, 17, 43, 0x02000144E, STR_PLAYERS_TIP }, // tab + { WWT_TAB, 1, 3, 33, 17, 43, 0x02000144E, STR_GROUPS_TIP }, // tab + { WWT_SCROLL, 1, 3, 336, 60, 236, 2, STR_NONE }, // list + { WIDGETS_END } +}; + +static rct_widget window_multiplayer_groups_widgets[] = { + { WWT_FRAME, 0, 0, 339, 0, 239, 0x0FFFFFFFF, STR_NONE }, // panel / background + { WWT_CAPTION, 0, 1, 338, 1, 14, STR_MULTIPLAYER, STR_WINDOW_TITLE_TIP }, // title bar + { WWT_CLOSEBOX, 0, 327, 337, 2, 13, STR_CLOSE_X, STR_CLOSE_WINDOW_TIP }, // close x button + { WWT_RESIZE, 1, 0, 339, 43, 239, 0x0FFFFFFFF, STR_NONE }, // content panel + { WWT_TAB, 1, 3, 33, 17, 43, 0x02000144E, STR_PLAYERS_TIP }, // tab + { WWT_TAB, 1, 3, 33, 17, 43, 0x02000144E, STR_GROUPS_TIP }, // tab + { WWT_DROPDOWN, 1, 141, 315, 46, 57, 0x0FFFFFFFF, STR_NONE }, // default group + { WWT_DROPDOWN_BUTTON, 1, 305, 315, 47, 56, 876, STR_NONE }, // + { WIDGETS_END } +}; + +static rct_widget *window_multiplayer_page_widgets[] = { + window_multiplayer_players_widgets, + window_multiplayer_groups_widgets +}; + +const uint64 window_multiplayer_page_enabled_widgets[] = { + (1 << WIDX_CLOSE) | (1 << WIDX_TAB1) | (1 << WIDX_TAB2), + (1 << WIDX_CLOSE) | (1 << WIDX_TAB1) | (1 << WIDX_TAB2) | (1 << WIDX_DEFAULT_GROUP) | (1 << WIDX_DEFAULT_GROUP_DROPDOWN) +}; + +static void window_multiplayer_players_mouseup(rct_window *w, int widgetIndex); +static void window_multiplayer_players_resize(rct_window *w); +static void window_multiplayer_players_mousedown(int widgetIndex, rct_window* w, rct_widget* widget); +static void window_multiplayer_players_update(rct_window *w); +static void window_multiplayer_players_scrollgetsize(rct_window *w, int scrollIndex, int *width, int *height); +static void window_multiplayer_players_scrollmousedown(rct_window *w, int scrollIndex, int x, int y); +static void window_multiplayer_players_scrollmouseover(rct_window *w, int scrollIndex, int x, int y); +static void window_multiplayer_players_invalidate(rct_window *w); +static void window_multiplayer_players_paint(rct_window *w, rct_drawpixelinfo *dpi); +static void window_multiplayer_players_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int scrollIndex); + +static void window_multiplayer_groups_mouseup(rct_window *w, int widgetIndex); +static void window_multiplayer_groups_resize(rct_window *w); +static void window_multiplayer_groups_mousedown(int widgetIndex, rct_window* w, rct_widget* widget); +static void window_multiplayer_groups_dropdown(rct_window *w, int widgetIndex, int dropdownIndex); +static void window_multiplayer_groups_update(rct_window *w); +static void window_multiplayer_groups_invalidate(rct_window *w); +static void window_multiplayer_groups_paint(rct_window *w, rct_drawpixelinfo *dpi); + +static rct_window_event_list window_multiplayer_players_events = { + NULL, + window_multiplayer_players_mouseup, + window_multiplayer_players_resize, + window_multiplayer_players_mousedown, + NULL, + NULL, + window_multiplayer_players_update, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + window_multiplayer_players_scrollgetsize, + window_multiplayer_players_scrollmousedown, + NULL, + window_multiplayer_players_scrollmouseover, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + window_multiplayer_players_invalidate, + window_multiplayer_players_paint, + window_multiplayer_players_scrollpaint +}; + +static rct_window_event_list window_multiplayer_groups_events = { + NULL, + window_multiplayer_groups_mouseup, + window_multiplayer_groups_resize, + window_multiplayer_groups_mousedown, + window_multiplayer_groups_dropdown, + NULL, + window_multiplayer_groups_update, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + window_multiplayer_groups_invalidate, + window_multiplayer_groups_paint, + NULL, +}; + +static rct_window_event_list *window_multiplayer_page_events[] = { + &window_multiplayer_players_events, + &window_multiplayer_groups_events +}; + +const int window_multiplayer_animation_divisor[] = { 4, 4 }; +const int window_multiplayer_animation_frames[] = { 8, 16 }; + +static void window_multiplayer_players_refresh_list(rct_window *w); +static void window_multiplayer_draw_tab_images(rct_window *w, rct_drawpixelinfo *dpi); +static void window_multiplayer_set_page(rct_window* w, int page); + +void window_multiplayer_open() +{ + rct_window* window; + + // Check if window is already open + window = window_bring_to_front_by_class(WC_MULTIPLAYER); + if (window != NULL) + return; + + window = window_create_auto_pos(320, 144, &window_multiplayer_players_events, WC_MULTIPLAYER, WF_10 | WF_RESIZABLE); + + window_multiplayer_set_page(window, WINDOW_MULTIPLAYER_PAGE_PLAYERS); + + window->page = WINDOW_MULTIPLAYER_PAGE_PLAYERS; + window->list_information_type = 0; + window->colours[0] = 7; + window->colours[1] = 7; + window->colours[2] = 7; +} + +static void window_multiplayer_set_page(rct_window* w, int page){ + w->page = page; + w->frame_no = 0; + w->no_list_items = 0; + w->selected_list_item = -1; + + w->enabled_widgets = window_multiplayer_page_enabled_widgets[page]; + w->hold_down_widgets = 0; + w->event_handlers = window_multiplayer_page_events[page]; + w->pressed_widgets = 0; + w->widgets = window_multiplayer_page_widgets[page]; + window_event_resize_call(w); + window_event_invalidate_call(w); + window_init_scroll_widgets(w); + window_invalidate(w); +} + +static void window_multiplayer_anchor_border_widgets(rct_window *w) +{ + w->widgets[WIDX_BACKGROUND].right = w->width - 1; + w->widgets[WIDX_BACKGROUND].bottom = w->height - 1; + w->widgets[WIDX_TITLE].right = w->width - 2; + w->widgets[WIDX_CONTENT_PANEL].right = w->width - 1; + w->widgets[WIDX_CONTENT_PANEL].bottom = w->height - 1; + w->widgets[WIDX_CLOSE].left = w->width - 13; + w->widgets[WIDX_CLOSE].right = w->width - 3; +} + +static void window_multiplayer_set_pressed_tab(rct_window *w) +{ + for (int i = 0; i < 2; i++) { + w->pressed_widgets &= ~(1 << (WIDX_TAB1 + i)); + } + w->pressed_widgets |= 1LL << (WIDX_TAB1 + w->page); +} + +static void window_multiplayer_groups_show_defaultgroup_dropdown(rct_window *w, rct_widget *widget) +{ + rct_widget *dropdownWidget; + int numItems, i; + + dropdownWidget = widget - 1; + + numItems = network_get_num_groups(); + + window_dropdown_show_text_custom_width( + w->x + dropdownWidget->left, + w->y + dropdownWidget->top, + dropdownWidget->bottom - dropdownWidget->top + 1, + w->colours[1], + 0, + numItems, + widget->right - dropdownWidget->left + ); + + for (i = 0; i < network_get_num_groups(); i++) { + gDropdownItemsFormat[i] = 1142; + gDropdownItemsArgs[i] = network_get_group_name_string_id(i); + } + + dropdown_set_checked(network_get_group_index(network_get_default_group()), true); +} + +static void window_multiplayer_players_mouseup(rct_window *w, int widgetIndex) +{ + switch (widgetIndex) { + case WIDX_CLOSE: + window_close(w); + break; + } +} + +static void window_multiplayer_players_resize(rct_window *w) +{ + window_set_resize(w, 320, 124, 500, 450); + + window_multiplayer_players_refresh_list(w); +} + +static void window_multiplayer_players_mousedown(int widgetIndex, rct_window* w, rct_widget* widget) +{ + switch (widgetIndex) { + case WIDX_TAB1: + case WIDX_TAB2: + if (w->page != widgetIndex - WIDX_TAB1) { + window_multiplayer_set_page(w, widgetIndex - WIDX_TAB1); + } + break; + } +} + +static void window_multiplayer_players_update(rct_window *w) +{ + w->frame_no++; + widget_invalidate(w, WIDX_TAB1 + w->page); +} + +static void window_multiplayer_players_scrollgetsize(rct_window *w, int scrollIndex, int *width, int *height) +{ + int i; + + if (w->selected_list_item != -1) { + w->selected_list_item = -1; + window_invalidate(w); + } + + *height = network_get_num_players() * 10; + i = *height - window_multiplayer_players_widgets[WIDX_LIST].bottom + window_multiplayer_players_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); + } +} + +static void window_multiplayer_players_scrollmousedown(rct_window *w, int scrollIndex, int x, int y) +{ + int index; + + index = y / 10; + if (index >= w->no_list_items) + return; + + w->selected_list_item = index; + window_invalidate(w); + + rct_widget *listWidget = &w->widgets[WIDX_LIST]; + int ddx = w->x + listWidget->left + x - w->scrolls[0].h_left; + int ddy = w->y + listWidget->top + y - w->scrolls[0].v_top; + + window_player_open(network_get_player_id(index)); +} + +static void window_multiplayer_players_scrollmouseover(rct_window *w, int scrollIndex, int x, int y) +{ + int index; + + index = y / 10; + if (index >= w->no_list_items) + return; + + w->selected_list_item = index; + window_invalidate(w); +} + +static void window_multiplayer_players_invalidate(rct_window *w) +{ + window_multiplayer_set_pressed_tab(w); + window_multiplayer_anchor_border_widgets(w); + window_multiplayer_players_widgets[WIDX_LIST].right = w->width - 4; + window_multiplayer_players_widgets[WIDX_LIST].bottom = w->height - 0x0F; + window_align_tabs(w, WIDX_TAB1, WIDX_TAB2); +} + +static void window_multiplayer_players_paint(rct_window *w, rct_drawpixelinfo *dpi) +{ + rct_string_id stringId; + int x, y; + + window_draw_widgets(w, dpi); + window_multiplayer_draw_tab_images(w, dpi); + + // Columns + gfx_draw_string_left(dpi, STR_PLAYER, NULL, w->colours[2], w->x + 6, 58 - 12 + w->y + 1); + gfx_draw_string_left(dpi, STR_GROUP, NULL, w->colours[2], w->x + 180, 58 - 12 + w->y + 1); + gfx_draw_string_left(dpi, STR_PING, NULL, w->colours[2], w->x + 263, 58 - 12 + w->y + 1); + + // Number of players + stringId = w->no_list_items == 1 ? STR_X_PLAYER : STR_X_PLAYERS; + x = w->x + 4; + y = w->y + w->widgets[WIDX_LIST].bottom + 2; + gfx_draw_string_left(dpi, stringId, &w->no_list_items, w->colours[2], x, y); +} + +static void window_multiplayer_players_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, ColourMapA[w->colours[1]].mid_light); + + y = 0; + for (int i = 0; i < network_get_num_players(); i++) { + if (y > dpi->y + dpi->height) { + break; + } + + if (y + 11 >= dpi->y) { + char buffer[300]; + + // Draw player name + char* lineCh = buffer; + int colour = 0; + if (i == w->selected_list_item) { + gfx_fill_rect(dpi, 0, y, 800, y + 9, 0x02000031); + safe_strcpy(&buffer[0], network_get_player_name(i), sizeof(buffer)); + colour = w->colours[2]; + } else { + if (network_get_player_flags(i) & NETWORK_PLAYER_FLAG_ISSERVER) { + lineCh = utf8_write_codepoint(lineCh, FORMAT_BABYBLUE); + } else { + lineCh = utf8_write_codepoint(lineCh, FORMAT_BLACK); + } + safe_strcpy(lineCh, network_get_player_name(i), sizeof(buffer) - (lineCh - buffer)); + } + gfx_clip_string(buffer, 230); + gfx_draw_string(dpi, buffer, colour, 0, y - 1); + + // Draw group name + lineCh = buffer; + int group = network_get_group_index(network_get_player_group(i)); + if (group != -1) { + lineCh = utf8_write_codepoint(lineCh, FORMAT_BLACK); + safe_strcpy(lineCh, network_get_group_name(group), sizeof(buffer) - (lineCh - buffer)); + gfx_clip_string(buffer, 80); + gfx_draw_string(dpi, buffer, colour, 173, y - 1); + } + + // Draw ping + lineCh = buffer; + int ping = network_get_player_ping(i); + if (ping <= 100) { + lineCh = utf8_write_codepoint(lineCh, FORMAT_GREEN); + } else + if (ping <= 250) { + lineCh = utf8_write_codepoint(lineCh, FORMAT_YELLOW); + } else { + lineCh = utf8_write_codepoint(lineCh, FORMAT_RED); + } + sprintf(lineCh, "%d ms", ping); + gfx_draw_string(dpi, buffer, colour, 256, y - 1); + } + y += 10; + } +} + +static void window_multiplayer_groups_mouseup(rct_window *w, int widgetIndex) +{ + switch (widgetIndex) { + case WIDX_CLOSE: + window_close(w); + break; + } +} + +static void window_multiplayer_groups_resize(rct_window *w) +{ + window_set_resize(w, 320, 61, 320, 61); +} + +static void window_multiplayer_groups_mousedown(int widgetIndex, rct_window* w, rct_widget* widget) +{ + switch (widgetIndex) { + case WIDX_TAB1: + case WIDX_TAB2: + if (w->page != widgetIndex - WIDX_TAB1) { + window_multiplayer_set_page(w, widgetIndex - WIDX_TAB1); + } + break; + case WIDX_DEFAULT_GROUP_DROPDOWN: + window_multiplayer_groups_show_defaultgroup_dropdown(w, widget); + break; + } +} + +static void window_multiplayer_groups_dropdown(rct_window *w, int widgetIndex, int dropdownIndex) +{ + if (dropdownIndex == -1) { + return; + } + if (network_get_mode() == NETWORK_MODE_SERVER) { + network_set_default_group(network_get_group_id(dropdownIndex)); + } + window_invalidate(w); +} + +static void window_multiplayer_groups_update(rct_window *w) +{ + w->frame_no++; + widget_invalidate(w, WIDX_TAB1 + w->page); +} + +static void window_multiplayer_groups_invalidate(rct_window *w) +{ + window_multiplayer_set_pressed_tab(w); + window_multiplayer_anchor_border_widgets(w); + window_align_tabs(w, WIDX_TAB1, WIDX_TAB2); +} + +static void window_multiplayer_groups_paint(rct_window *w, rct_drawpixelinfo *dpi) +{ + window_draw_widgets(w, dpi); + window_multiplayer_draw_tab_images(w, dpi); + + rct_widget* widget = &window_multiplayer_groups_widgets[WIDX_DEFAULT_GROUP]; + int group = network_get_group_index(network_get_default_group()); + if (group != -1) { + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = network_get_group_name_string_id(group); + gfx_draw_string_centred( + dpi, + 1193, + w->x + (widget->left + widget->right - 11) / 2, + w->y + widget->top, + 0, + (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS + ); + } + + gfx_draw_string_left(dpi, STR_DEFAULT_GROUP, NULL, w->colours[2], w->x + 6, 58 - 12 + w->y + 1); +} + +static void window_multiplayer_players_refresh_list(rct_window *w) +{ + w->no_list_items = network_get_num_players(); + w->list_item_positions[0] = 0; + + w->selected_list_item = -1; + window_invalidate(w); +} + +static void window_multiplayer_draw_tab_image(rct_window *w, rct_drawpixelinfo *dpi, int page, int spriteIndex) +{ + int widgetIndex = WIDX_TAB1 + page; + + if (!(w->disabled_widgets & (1LL << widgetIndex))) { + if (w->page == page) { + int numFrames = window_multiplayer_animation_frames[w->page]; + if (numFrames > 1) { + int frame = w->frame_no / window_multiplayer_animation_divisor[w->page]; + spriteIndex += (frame % numFrames); + } + } + + gfx_draw_sprite(dpi, spriteIndex, w->x + w->widgets[widgetIndex].left, w->y + w->widgets[widgetIndex].top, 0); + } +} + +static void window_multiplayer_draw_tab_images(rct_window *w, rct_drawpixelinfo *dpi) +{ + window_multiplayer_draw_tab_image(w, dpi, 0, SPR_TAB_GUESTS_0); + window_multiplayer_draw_tab_image(w, dpi, 1, SPR_TAB_OBJECTIVE_0); +} diff --git a/src/windows/player.c b/src/windows/player.c new file mode 100644 index 0000000000..06ab25f34a --- /dev/null +++ b/src/windows/player.c @@ -0,0 +1,377 @@ +/***************************************************************************** +* Copyright (c) 2014 Ted John, Duncan Frost +* OpenRCT2, an open source clone of Roller Coaster Tycoon 2. +* +* This file is part of OpenRCT2. +* +* OpenRCT2 is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. + +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. + +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +*****************************************************************************/ + +#include "../addresses.h" +#include "../config.h" +#include "../game.h" +#include "../input.h" +#include "../management/marketing.h" +#include "../network/network.h" +#include "../peep/peep.h" +#include "../peep/staff.h" +#include "../ride/ride.h" +#include "../ride/ride_data.h" +#include "../scenario.h" +#include "../localisation/localisation.h" +#include "../sprites.h" +#include "../interface/themes.h" +#include "../interface/viewport.h" +#include "../interface/widget.h" +#include "../interface/window.h" +#include "../util/util.h" +#include "../world/footpath.h" +#include "../world/map.h" +#include "../world/sprite.h" +#include "dropdown.h" +#include "error.h" + +enum WINDOW_PLAYER_PAGE { + WINDOW_PLAYER_OVERVIEW +}; + +enum WINDOW_PLAYER_WIDGET_IDX { + WIDX_BACKGROUND, + WIDX_TITLE, + WIDX_CLOSE, + WIDX_PAGE_BACKGROUND, + WIDX_TAB_1, + WIDX_GROUP, + WIDX_GROUP_DROPDOWN, + WIDX_KICK +}; + +rct_widget window_player_overview_widgets[] = { + { WWT_FRAME, 0, 0, 191, 0, 156, 0x0FFFFFFFF, STR_NONE }, // Panel / Background + { WWT_CAPTION, 0, 1, 190, 1, 14, 865, STR_WINDOW_TITLE_TIP }, // Title + { WWT_CLOSEBOX, 0, 179, 189, 2, 13, 824, STR_CLOSE_WINDOW_TIP }, // Close x button + { WWT_RESIZE, 1, 0, 191, 43, 156, 0x0FFFFFFFF, STR_NONE }, // Resize + { WWT_TAB, 1, 3, 33, 17, 43, 0x2000144E, STR_NONE }, // Tab 1 + { WWT_DROPDOWN, 1, 3, 177, 46, 57, 0x0FFFFFFFF, STR_NONE }, // Permission group + { WWT_DROPDOWN_BUTTON, 1, 167, 177, 47, 56, 876, STR_NONE }, // + { WWT_FLATBTN, 1, 179, 190, 45, 68, SPR_DEMOLISH, STR_KICK_PLAYER_TIP }, // Kick button + { WIDGETS_END }, +}; + +rct_widget *window_player_page_widgets[] = { + window_player_overview_widgets +}; + +void window_player_set_page(rct_window* w, int page); + +void window_player_overview_close(rct_window *w); +void window_player_overview_mouse_up(rct_window *w, int widgetIndex); +void window_player_overview_resize(rct_window *w); +void window_player_overview_mouse_down(int widgetIndex, rct_window *w, rct_widget *widget); +void window_player_overview_dropdown(rct_window *w, int widgetIndex, int dropdownIndex); +void window_player_overview_update(rct_window* w); +void window_player_overview_invalidate(rct_window *w); +void window_player_overview_paint(rct_window *w, rct_drawpixelinfo *dpi); + +static rct_window_event_list window_player_overview_events = { + window_player_overview_close, + window_player_overview_mouse_up, + window_player_overview_resize, + window_player_overview_mouse_down, + window_player_overview_dropdown, + NULL, + window_player_overview_update, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + window_player_overview_invalidate, + window_player_overview_paint, + NULL +}; + +static rct_window_event_list *window_player_page_events[] = { + &window_player_overview_events +}; + +uint32 window_player_page_enabled_widgets[] = { + (1 << WIDX_CLOSE) | + (1 << WIDX_TAB_1) | + (1 << WIDX_GROUP) | + (1 << WIDX_GROUP_DROPDOWN) | + (1 << WIDX_KICK) +}; + +void window_player_open(uint8 id){ + rct_window* window; + + int player = network_get_player_index(id); + window = window_bring_to_front_by_number(WC_PLAYER, id); + if (window == NULL){ + window = window_create_auto_pos(210, 134, &window_player_overview_events, WC_PLAYER, WF_RESIZABLE); + window->widgets = window_player_overview_widgets; + window->enabled_widgets = window_player_page_enabled_widgets[0]; + window->number = id; + window->page = 0; + window->viewport_focus_coordinates.y = 0; + window->frame_no = 0; + window->list_information_type = 0; + window->picked_peep_frame = 0; + window->highlighted_item = 0; + window->min_width = 210; + window->min_height = 134; + window->max_width = 500; + window->max_height = 450; + window->no_list_items = 0; + window->selected_list_item = -1; + + window->viewport_focus_coordinates.y = -1; + window->error.var_480 = user_string_allocate(128, network_get_player_name(player)); // repurposing var_480 to store this + } + + window->page = 0; + window_invalidate(window); + + window->widgets = window_player_page_widgets[WINDOW_PLAYER_OVERVIEW]; + window->enabled_widgets = window_player_page_enabled_widgets[WINDOW_PLAYER_OVERVIEW]; + window->hold_down_widgets = 0; + window->event_handlers = window_player_page_events[WINDOW_PLAYER_OVERVIEW]; + window->pressed_widgets = 0; + + window_init_scroll_widgets(window); +} + +void window_player_overview_show_group_dropdown(rct_window *w, rct_widget *widget) +{ + rct_widget *dropdownWidget; + int numItems, i; + int player = network_get_player_index((uint8)w->number); + if (player == -1) { + return; + } + + dropdownWidget = widget - 1; + + numItems = network_get_num_groups(); + + window_dropdown_show_text_custom_width( + w->x + dropdownWidget->left, + w->y + dropdownWidget->top, + dropdownWidget->bottom - dropdownWidget->top + 1, + w->colours[1], + 0, + numItems, + widget->right - dropdownWidget->left + ); + + for (i = 0; i < network_get_num_groups(); i++) { + gDropdownItemsFormat[i] = 1142; + gDropdownItemsArgs[i] = network_get_group_name_string_id(i); + } + + dropdown_set_checked(network_get_group_index(network_get_player_group(player)), true); +} + +void window_player_overview_close(rct_window *w) +{ + if (w->error.var_480){ + user_string_free(w->error.var_480); + w->error.var_480 = 0; + } +} + +void window_player_overview_mouse_up(rct_window *w, int widgetIndex) +{ + switch(widgetIndex){ + case WIDX_CLOSE: + window_close(w); + break; + case WIDX_TAB_1: + window_player_set_page(w, widgetIndex - WIDX_TAB_1); + break; + case WIDX_KICK: + network_kick_player(w->number); + break; + } +} + +void window_player_overview_mouse_down(int widgetIndex, rct_window *w, rct_widget *widget) +{ + switch(widgetIndex){ + case WIDX_GROUP_DROPDOWN: + window_player_overview_show_group_dropdown(w, widget); + break; + } +} + +void window_player_overview_dropdown(rct_window *w, int widgetIndex, int dropdownIndex) +{ + int player = network_get_player_index((uint8)w->number); + if (player == -1) { + return; + } + if (dropdownIndex == -1) { + return; + } + int group = network_get_group_id(dropdownIndex); + game_do_command(0, GAME_COMMAND_FLAG_APPLY, w->number, group, GAME_COMMAND_SET_PLAYER_GROUP, 0, 0); + window_invalidate(w); +} + +void window_player_overview_resize(rct_window *w){ + window_set_resize(w, 210, 134, 210, 134); +} + +void window_player_overview_update(rct_window* w){ + int var_496 = w->highlighted_item >> 16; + var_496++; + var_496 %= 24; + w->highlighted_item &= 0x0000FFFF; + w->highlighted_item |= var_496 << 16; + + widget_invalidate(w, WIDX_TAB_1); + + w->list_information_type += 2; + + if ((w->highlighted_item & 0xFFFF) == 0xFFFF) + w->highlighted_item &= 0xFFFF0000; + else + w->highlighted_item++; + + if(network_get_player_index((uint8)w->number) == -1) { + window_close(w); + } +} + +void window_player_set_page(rct_window* w, int page){ + w->page = page; + w->frame_no = 0; + w->no_list_items = 0; + w->selected_list_item = -1; + + w->enabled_widgets = window_player_page_enabled_widgets[page]; + w->hold_down_widgets = 0; + w->event_handlers = window_player_page_events[page]; + w->pressed_widgets = 0; + w->widgets = window_player_page_widgets[page]; + window_invalidate(w); + window_event_resize_call(w); + window_event_invalidate_call(w); + window_init_scroll_widgets(w); + window_invalidate(w); +} + +void window_player_overview_tab_paint(rct_window* w, rct_drawpixelinfo* dpi){ + if (w->disabled_widgets & (1<widgets[WIDX_TAB_1]; + int x = widget->left + w->x; + int y = widget->top + w->y; + + int image_id = SPR_PEEP_LARGE_FACE_NORMAL; + gfx_draw_sprite(dpi, image_id, x, y, 0); +} + +void window_player_overview_paint(rct_window *w, rct_drawpixelinfo *dpi) +{ + window_draw_widgets(w, dpi); + window_player_overview_tab_paint(w, dpi); + + int player = network_get_player_index((uint8)w->number); + if (player == -1) { + return; + } + + rct_widget* widget = &window_player_overview_widgets[WIDX_GROUP]; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = network_get_group_name_string_id(network_get_player_group(player)); + + gfx_draw_string_centred( + dpi, + 1193, + w->x + (widget->left + widget->right - 11) / 2, + w->y + widget->top, + 0, + (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS + ); + + int x = w->x + window_player_overview_widgets[WIDX_PAGE_BACKGROUND].left + 4; + int y = w->y + window_player_overview_widgets[WIDX_PAGE_BACKGROUND].top + 4 + 13; + + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = STR_PING; + gfx_draw_string_left(dpi, STR_WINDOW_COLOUR_2_STRING, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x, y); + char ping[64]; + sprintf(ping, "%d ms", network_get_player_ping(player)); + gfx_draw_string(dpi, ping, w->colours[2], x + 60, y); + + y += 20; + gfx_fill_rect_inset(dpi, x, y - 6, x + 177, y - 5, w->colours[1], 32); + + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint32) = network_get_player_commands_ran(player); + gfx_draw_string_left(dpi, STR_COMMANDS_RAN, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0,x, y); + + y += 10; + + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint32) = network_get_player_money_spent(player); + gfx_draw_string_left(dpi, STR_MONEY_SPENT, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0,x, y); +} + +void window_player_overview_invalidate(rct_window *w) +{ + if (window_player_page_widgets[w->page] != w->widgets) { + w->widgets = window_player_page_widgets[w->page]; + window_init_scroll_widgets(w); + } + + w->colours[0] = 7; + w->colours[1] = 7; + w->colours[2] = 7; + + w->pressed_widgets &= ~(WIDX_TAB_1); + w->pressed_widgets |= 1ULL << (w->page + WIDX_TAB_1); + + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = w->error.var_480; // set title caption to player name + + window_player_overview_widgets[WIDX_BACKGROUND].right = w->width - 1; + window_player_overview_widgets[WIDX_BACKGROUND].bottom = w->height - 1; + + window_player_overview_widgets[WIDX_PAGE_BACKGROUND].right =w->width - 1; + window_player_overview_widgets[WIDX_PAGE_BACKGROUND].bottom = w->height - 1; + + window_player_overview_widgets[WIDX_TITLE].right = w->width - 2; + + window_player_overview_widgets[WIDX_CLOSE].left = w->width - 13; + window_player_overview_widgets[WIDX_CLOSE].right = w->width - 3; + + window_player_overview_widgets[WIDX_KICK].right = w->width - 2; + + window_player_overview_widgets[WIDX_KICK].left = w->width - 25; + + window_align_tabs(w, WIDX_TAB_1, WIDX_TAB_1); +} + diff --git a/src/windows/player_list.c b/src/windows/player_list.c deleted file mode 100644 index 34279c8631..0000000000 --- a/src/windows/player_list.c +++ /dev/null @@ -1,359 +0,0 @@ -/***************************************************************************** - * Copyright (c) 2014 Ted John - * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. - * - * This file is part of OpenRCT2. - * - * OpenRCT2 is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * 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" -#include "../sprites.h" -#include "../windows/dropdown.h" -#include "../util/util.h" - -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, 339, 0, 239, 0x0FFFFFFFF, STR_NONE }, // panel / background - { WWT_CAPTION, 0, 1, 338, 1, 14, STR_PLAYER_LIST, STR_WINDOW_TITLE_TIP }, // title bar - { WWT_CLOSEBOX, 0, 327, 337, 2, 13, STR_CLOSE_X, STR_CLOSE_WINDOW_TIP }, // close x button - { WWT_RESIZE, 1, 0, 339, 43, 239, 0x0FFFFFFFF, STR_NONE }, // content panel - { WWT_TAB, 1, 3, 33, 17, 43, 0x02000144E, STR_NONE }, // tab - { WWT_SCROLL, 1, 3, 336, 60, 236, 2, STR_NONE }, // 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_dropdown(rct_window *w, int widgetIndex, int dropdownIndex); -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_scrollmousedown(rct_window *w, int scrollIndex, int x, int y); -static void window_player_list_scrollmouseover(rct_window *w, int scrollIndex, int x, int y); -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, - window_player_list_dropdown, - NULL, - window_player_list_update, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - window_player_list_scrollgetsize, - window_player_list_scrollmousedown, - NULL, - window_player_list_scrollmouseover, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - window_player_list_invalidate, - window_player_list_paint, - window_player_list_scrollpaint -}; - -enum { - DDIDX_KICK -}; - -const int window_player_list_animation_divisor[] = { 4 }; -const int window_player_list_animation_frames[] = { 8 }; - -static void window_player_list_refresh_list(rct_window *w); -static void window_player_list_draw_tab_images(rct_window *w, rct_drawpixelinfo *dpi); - -static int _dropdownPlayerId; - -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, 144, &window_player_list_events, WC_PLAYER_LIST, WF_10 | WF_RESIZABLE); - - window->widgets = window_player_list_widgets; - window->enabled_widgets = 1 << WIDX_CLOSE; - window_init_scroll_widgets(window); - window->no_list_items = 0; - window->selected_list_item = -1; - window->frame_no = 0; - window->min_width = 320; - window->min_height = 124; - window->max_width = 500; - window->max_height = 450; - - 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_dropdown(rct_window *w, int widgetIndex, int dropdownIndex) -{ - switch (dropdownIndex) { - case DDIDX_KICK: - network_kick_player(_dropdownPlayerId); - break; - } -} - -static void window_player_list_update(rct_window *w) -{ - w->frame_no++; - widget_invalidate(w, WIDX_TAB1 + w->page); -} - -static void window_player_list_scrollgetsize(rct_window *w, int scrollIndex, int *width, int *height) -{ - int i; - - if (w->selected_list_item != -1) { - w->selected_list_item = -1; - window_invalidate(w); - } - - *height = network_get_num_players() * 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); - } -} - -static void window_player_list_scrollmousedown(rct_window *w, int scrollIndex, int x, int y) -{ - if (network_get_mode() != NETWORK_MODE_SERVER) { - return; - } - - int index; - - index = y / 10; - if (index >= w->no_list_items) - return; - - w->selected_list_item = index; - window_invalidate(w); - - rct_widget *listWidget = &w->widgets[WIDX_LIST]; - int ddx = w->x + listWidget->left + x - w->scrolls[0].h_left; - int ddy = w->y + listWidget->top + y - w->scrolls[0].v_top; - - if (index == 0) { - return; - } - _dropdownPlayerId = network_get_player_id(index); - if (_dropdownPlayerId == network_get_current_player_id()) { - return; - } - - gDropdownItemsFormat[0] = STR_KICK_PLAYER; - window_dropdown_show_text(ddx, ddy, 0, 7, 0, 1); -} - -static void window_player_list_scrollmouseover(rct_window *w, int scrollIndex, int x, int y) -{ - int index; - - index = y / 10; - if (index >= w->no_list_items) - return; - - w->selected_list_item = index; - window_invalidate(w); -} - -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) -{ - rct_string_id stringId; - int x, y; - - window_draw_widgets(w, dpi); - window_player_list_draw_tab_images(w, dpi); - - // Columns - gfx_draw_string_left(dpi, STR_PLAYER, NULL, w->colours[2], w->x + 6, 58 - 12 + w->y + 1); - gfx_draw_string_left(dpi, STR_PING, NULL, w->colours[2], w->x + 246, 58 - 12 + w->y + 1); - - // Number of players - stringId = w->no_list_items == 1 ? STR_X_PLAYER : STR_X_PLAYERS; - x = w->x + 4; - y = w->y + w->widgets[WIDX_LIST].bottom + 2; - gfx_draw_string_left(dpi, stringId, &w->no_list_items, w->colours[2], x, y); -} - -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, ColourMapA[w->colours[1]].mid_light); - - y = 0; - for (int i = 0; i < network_get_num_players(); i++) { - if (y > dpi->y + dpi->height) { - break; - } - - if (y + 11 >= dpi->y) { - char buffer[300]; - char* lineCh = buffer; - int colour = 0; - if (i == w->selected_list_item) { - gfx_fill_rect(dpi, 0, y, 800, y + 9, 0x02000031); - safe_strcpy(&buffer[0], network_get_player_name(i), sizeof(buffer)); - colour = w->colours[2]; - } else { - if (network_get_player_flags(i) & NETWORK_PLAYER_FLAG_ISSERVER) { - lineCh = utf8_write_codepoint(lineCh, FORMAT_BABYBLUE); - } else { - lineCh = utf8_write_codepoint(lineCh, FORMAT_BLACK); - } - safe_strcpy(lineCh, network_get_player_name(i), sizeof(buffer) - (lineCh - buffer)); - } - gfx_clip_string(buffer, 230); - gfx_draw_string(dpi, buffer, colour, 0, y - 1); - lineCh = buffer; - int ping = network_get_player_ping(i); - if (ping <= 100) { - lineCh = utf8_write_codepoint(lineCh, FORMAT_GREEN); - } else - if (ping <= 250) { - lineCh = utf8_write_codepoint(lineCh, FORMAT_YELLOW); - } else { - lineCh = utf8_write_codepoint(lineCh, FORMAT_RED); - } - sprintf(lineCh, "%d ms", ping); - gfx_draw_string(dpi, buffer, colour, 240, y - 1); - } - y += 10; - } -} - -static void window_player_list_refresh_list(rct_window *w) -{ - w->no_list_items = network_get_num_players(); - w->list_item_positions[0] = 0; - - w->selected_list_item = -1; - window_invalidate(w); -} - -static void window_player_list_draw_tab_image(rct_window *w, rct_drawpixelinfo *dpi, int page, int spriteIndex) -{ - int widgetIndex = WIDX_TAB1 + page; - - if (!(w->disabled_widgets & (1LL << widgetIndex))) { - if (w->page == page) { - int numFrames = window_player_list_animation_frames[w->page]; - if (numFrames > 1) { - int frame = w->frame_no / window_player_list_animation_divisor[w->page]; - spriteIndex += (frame % numFrames); - } - } - - gfx_draw_sprite(dpi, spriteIndex, w->x + w->widgets[widgetIndex].left, w->y + w->widgets[widgetIndex].top, 0); - } -} - -static void window_player_list_draw_tab_images(rct_window *w, rct_drawpixelinfo *dpi) -{ - window_player_list_draw_tab_image(w, dpi, 0, SPR_TAB_GUESTS_0); -} diff --git a/src/windows/top_toolbar.c b/src/windows/top_toolbar.c index aaa579afc5..c3ea83ec7d 100644 --- a/src/windows/top_toolbar.c +++ b/src/windows/top_toolbar.c @@ -110,7 +110,7 @@ typedef enum { } TOP_TOOLBAR_DEBUG_DDIDX; typedef enum { - DDIDX_PLAYER_LIST = 0 + DDIDX_MULTIPLAYER = 0 } TOP_TOOLBAR_NETWORK_DDIDX; enum { @@ -2941,7 +2941,7 @@ void top_toolbar_init_debug_menu(rct_window* w, rct_widget* widget) void top_toolbar_init_network_menu(rct_window* w, rct_widget* widget) { - gDropdownItemsFormat[0] = STR_PLAYER_LIST; + gDropdownItemsFormat[0] = STR_MULTIPLAYER; window_dropdown_show_text( w->x + widget->left, @@ -2952,7 +2952,7 @@ void top_toolbar_init_network_menu(rct_window* w, rct_widget* widget) 1 ); - gDropdownDefaultIndex = DDIDX_PLAYER_LIST; + gDropdownDefaultIndex = DDIDX_MULTIPLAYER; } void top_toolbar_debug_menu_dropdown(short dropdownIndex) @@ -2985,8 +2985,8 @@ void top_toolbar_network_menu_dropdown(short dropdownIndex) rct_window* w = window_get_main(); if (w) { switch (dropdownIndex) { - case DDIDX_PLAYER_LIST: - window_player_list_open(); + case DDIDX_MULTIPLAYER: + window_multiplayer_open(); break; } }