From 1277c1a0d246398588f79600e183ba6d126bd155 Mon Sep 17 00:00:00 2001 From: zsilencer Date: Thu, 21 Jan 2016 23:32:40 -0700 Subject: [PATCH] MP permissions update 2 --- data/language/english_uk.txt | 8 ++ src/game.c | 10 +- src/game.h | 6 +- src/localisation/string_ids.h | 10 ++ src/network/network.cpp | 243 +++++++++++++++++++++------------- src/network/network.h | 48 +++---- src/windows/multiplayer.c | 52 +++++--- src/windows/player.c | 25 ++-- 8 files changed, 254 insertions(+), 148 deletions(-) diff --git a/data/language/english_uk.txt b/data/language/english_uk.txt index 03e41f9d47..9cc4fe7cfd 100644 --- a/data/language/english_uk.txt +++ b/data/language/english_uk.txt @@ -4044,6 +4044,14 @@ STR_5702 :Set Banner Style STR_5703 :Set Sign Style STR_5704 :Set Player Group STR_5705 :Modify Groups +STR_5706 :Can't remove group that players belong to +STR_5707 :This group cannot be modified +STR_5708 :Can't change the group that the host belongs to +STR_5709 :Rename Group +STR_5710 :Group name +STR_5711 :Enter new name for this group: +STR_5712 :Can't set permission that you do not have yourself +STR_5713 :Kick Player ############# # Scenarios # diff --git a/src/game.c b/src/game.c index 7d4241d3a8..801f04a3ca 100644 --- a/src/game.c +++ b/src/game.c @@ -72,6 +72,7 @@ GAME_COMMAND_CALLBACK_POINTER* game_command_callback_table[] = { game_command_callback_ride_construct_placed_back, game_command_callback_ride_remove_track_piece, }; +uint8 game_command_playerid = 0; int game_command_callback_get_index(GAME_COMMAND_CALLBACK_POINTER* callback) { @@ -469,6 +470,10 @@ int game_do_command_p(int command, int *eax, int *ebx, int *ecx, int *edx, int * scenery_remove_ghost_tool_placement(); } + if (!(flags & GAME_COMMAND_FLAG_NETWORKED)) { + game_command_playerid = network_get_current_player_id(); + } + *ebx &= ~GAME_COMMAND_FLAG_APPLY; // First call for validity and price check @@ -1175,7 +1180,7 @@ void game_load_or_quit_no_save_prompt() } } -GAME_COMMAND_POINTER* new_game_command_table[64] = { +GAME_COMMAND_POINTER* new_game_command_table[65] = { game_command_set_ride_appearance, game_command_set_land_height, game_pause_toggle, @@ -1239,5 +1244,6 @@ GAME_COMMAND_POINTER* new_game_command_table[64] = { game_command_set_banner_style, game_command_set_sign_style, game_command_set_player_group, - game_command_modify_groups + game_command_modify_groups, + game_command_kick_player }; diff --git a/src/game.h b/src/game.h index abd795fe0c..aeab5329a1 100644 --- a/src/game.h +++ b/src/game.h @@ -89,7 +89,8 @@ enum GAME_COMMAND { GAME_COMMAND_SET_BANNER_STYLE, GAME_COMMAND_SET_SIGN_STYLE, GAME_COMMAND_SET_PLAYER_GROUP, - GAME_COMMAND_MODIFY_GROUPS + GAME_COMMAND_MODIFY_GROUPS, + GAME_COMMAND_KICK_PLAYER }; enum { @@ -113,8 +114,9 @@ typedef void (GAME_COMMAND_CALLBACK_POINTER)(int eax, int ebx, int ecx, int edx, extern GAME_COMMAND_CALLBACK_POINTER* game_command_callback; int game_command_callback_get_index(GAME_COMMAND_CALLBACK_POINTER* callback); GAME_COMMAND_CALLBACK_POINTER* game_command_callback_get_callback(int index); +extern uint8 game_command_playerid; -extern GAME_COMMAND_POINTER* new_game_command_table[64]; +extern GAME_COMMAND_POINTER* new_game_command_table[65]; extern int gGameSpeed; extern float gDayNightCycle; diff --git a/src/localisation/string_ids.h b/src/localisation/string_ids.h index 620c414ce3..09c5c0ef99 100644 --- a/src/localisation/string_ids.h +++ b/src/localisation/string_ids.h @@ -2332,6 +2332,16 @@ enum { STR_ACTION_SET_SIGN_STYLE = 5703, STR_ACTION_SET_PLAYER_GROUP = 5704, STR_ACTION_MODIFY_GROUPS = 5705, + + STR_CANT_REMOVE_GROUP_THAT_PLAYERS_BELONG_TO = 5706, + STR_THIS_GROUP_CANNOT_BE_MODIFIED = 5707, + STR_CANT_CHANGE_GROUP_THAT_THE_HOST_BELONGS_TO = 5708, + STR_RENAME_GROUP = 5709, + STR_GROUP_NAME = 5710, + STR_ENTER_NEW_NAME_FOR_THIS_GROUP = 5711, + STR_CANT_SET_PERMISSION_THAT_YOU_DO_NOT_HAVE_YOURSELF = 5712, + + STR_ACTION_KICK_PLAYER = 5713, // 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 8fcf2fb136..2d8500b845 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -231,6 +231,7 @@ int NetworkActions::FindGameCommand(int command) NetworkGroup::NetworkGroup() { name_string_id = STR_NONE; + actions_allowed = {0}; } NetworkGroup::~NetworkGroup() @@ -284,11 +285,8 @@ bool NetworkGroup::CanPerformAction(size_t index) return (actions_allowed[byte] & (1 << bit)) ? true : false; } -bool NetworkGroup::CanPerformGameCommand(uint32 command) +bool NetworkGroup::CanPerformGameCommand(int command) { - if ((size_t)command >= Util::CountOf(new_game_command_table)) { - return false; - } int action = gNetworkActions.FindGameCommand(command); if (action != -1) { return CanPerformAction(action); @@ -532,6 +530,7 @@ Network::Network() 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; + client_command_handlers[NETWORK_COMMAND_GROUPLIST] = &Network::Client_Handle_GROUPLIST; 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; @@ -570,6 +569,14 @@ bool Network::Init() spectator->ToggleActionPermission(0); spectator->id = 1; group_list.push_back(std::move(spectator)); + std::unique_ptr user(new NetworkGroup()); // change to make_unique in c++14 + user->SetName("User"); + user->actions_allowed.fill(0xFF); + user->ToggleActionPermission(59); + user->ToggleActionPermission(60); + user->ToggleActionPermission(61); + user->id = 2; + group_list.push_back(std::move(user)); SetDefaultGroup(1); status = NETWORK_STATUS_READY; @@ -1138,13 +1145,18 @@ NetworkGroup* Network::AddGroup() group->SetName("Group #" + std::to_string(newid)); addedgroup = group.get(); group_list.push_back(std::move(group)); - if (GetMode() == NETWORK_MODE_SERVER) { - Server_Send_GROUPLIST(); - } } return addedgroup; } +void Network::RemoveGroup(uint8 id) +{ + auto group = GetGroupIteratorByID(id); + if (group != group_list.end()) { + group_list.erase(group); + } +} + uint8 Network::GetDefaultGroup() { return default_group; @@ -1259,7 +1271,7 @@ void Network::Server_Send_TICK() void Network::Server_Send_PLAYERLIST() { std::unique_ptr packet = std::move(NetworkPacket::Allocate()); - *packet << (uint32)NETWORK_COMMAND_PLAYERLIST << (uint32)player_list.size(); + *packet << (uint32)NETWORK_COMMAND_PLAYERLIST << (uint8)player_list.size(); for (unsigned int i = 0; i < player_list.size(); i++) { player_list[i]->Write(*packet); } @@ -1287,7 +1299,7 @@ void Network::Server_Send_PING() void Network::Server_Send_PINGLIST() { std::unique_ptr packet = std::move(NetworkPacket::Allocate()); - *packet << (uint32)NETWORK_COMMAND_PINGLIST << (uint32)player_list.size(); + *packet << (uint32)NETWORK_COMMAND_PINGLIST << (uint8)player_list.size(); for (unsigned int i = 0; i < player_list.size(); i++) { *packet << player_list[i]->id << player_list[i]->ping; } @@ -1336,11 +1348,14 @@ void Network::Server_Send_SHOWERROR(NetworkConnection& connection, rct_string_id connection.QueuePacket(std::move(packet)); } -void Network::Server_Send_GROUPLIST() +void Network::Server_Send_GROUPLIST(NetworkConnection& connection) { std::unique_ptr packet = std::move(NetworkPacket::Allocate()); - *packet << (uint32)NETWORK_COMMAND_GROUPLIST; - SendPacketToClients(*packet); + *packet << (uint32)NETWORK_COMMAND_GROUPLIST << (uint8)group_list.size(); + for (unsigned int i = 0; i < group_list.size(); i++) { + group_list[i]->Write(*packet); + } + connection.QueuePacket(std::move(packet)); } bool Network::ProcessConnection(NetworkConnection& connection) @@ -1489,7 +1504,7 @@ void Network::PrintError() } -int Network::Client_Handle_AUTH(NetworkConnection& connection, NetworkPacket& packet) +void Network::Client_Handle_AUTH(NetworkConnection& connection, NetworkPacket& packet) { packet >> (uint32&)connection.authstatus >> (uint8&)player_id; switch(connection.authstatus) { @@ -1513,10 +1528,9 @@ int Network::Client_Handle_AUTH(NetworkConnection& connection, NetworkPacket& pa window_network_status_open_password(); break; } - return 1; } -int Network::Server_Handle_AUTH(NetworkConnection& connection, NetworkPacket& packet) +void Network::Server_Handle_AUTH(NetworkConnection& connection, NetworkPacket& packet) { if (connection.authstatus != NETWORK_AUTH_OK) { const char* gameversion = packet.ReadString(); @@ -1550,25 +1564,25 @@ int Network::Server_Handle_AUTH(NetworkConnection& connection, NetworkPacket& pa chat_history_add(text); Server_Send_MAP(&connection); gNetwork.Server_Send_CHAT(text); + Server_Send_GROUPLIST(connection); Server_Send_PLAYERLIST(); } } Server_Send_AUTH(connection); } - return 1; } -int Network::Client_Handle_MAP(NetworkConnection& connection, NetworkPacket& packet) +void Network::Client_Handle_MAP(NetworkConnection& connection, NetworkPacket& packet) { uint32 size, offset; packet >> size >> offset; if (offset > 0x600000) { // too big - return 0; + return; } else { int chunksize = packet.size - packet.read; if (chunksize <= 0) { - return 0; + return; } if (offset + chunksize > chunk_buffer.size()) { chunk_buffer.resize(offset + chunksize); @@ -1592,7 +1606,7 @@ int Network::Client_Handle_MAP(NetworkConnection& connection, NetworkPacket& pac if (data == NULL) { log_warning("Failed to decompress data sent from server."); - return 0; + return; } } else { log_warning("Assuming received map is in plain sv6 format"); @@ -1614,30 +1628,35 @@ int Network::Client_Handle_MAP(NetworkConnection& connection, NetworkPacket& pac } } } - return 1; } -int Network::Client_Handle_CHAT(NetworkConnection& connection, NetworkPacket& packet) +void Network::Client_Handle_CHAT(NetworkConnection& connection, NetworkPacket& packet) { const char* text = packet.ReadString(); if (text) { chat_history_add(text); } - return 1; } -int Network::Server_Handle_CHAT(NetworkConnection& connection, NetworkPacket& packet) +void Network::Server_Handle_CHAT(NetworkConnection& connection, NetworkPacket& packet) { + if (connection.player) { + NetworkGroup* group = GetGroupByID(connection.player->group); + if (group) { + if (!group->CanPerformGameCommand(-1)) { + return; + } + } + } const char* text = packet.ReadString(); if (text) { const char* formatted = FormatChat(connection.player, text); chat_history_add(formatted); Server_Send_CHAT(formatted); } - return 1; } -int Network::Client_Handle_GAMECMD(NetworkConnection& connection, NetworkPacket& packet) +void Network::Client_Handle_GAMECMD(NetworkConnection& connection, NetworkPacket& packet) { uint32 tick; uint32 args[7]; @@ -1647,10 +1666,9 @@ int Network::Client_Handle_GAMECMD(NetworkConnection& connection, NetworkPacket& GameCommand gc = GameCommand(tick, args, playerid, callback); game_command_queue.insert(gc); - return 1; } -int Network::Server_Handle_GAMECMD(NetworkConnection& connection, NetworkPacket& packet) +void Network::Server_Handle_GAMECMD(NetworkConnection& connection, NetworkPacket& packet) { uint32 tick; uint32 args[7]; @@ -1658,7 +1676,7 @@ int Network::Server_Handle_GAMECMD(NetworkConnection& connection, NetworkPacket& uint8 callback; if (!connection.player) { - return 0; + return; } playerid = connection.player->id; @@ -1671,29 +1689,28 @@ int Network::Server_Handle_GAMECMD(NetworkConnection& connection, NetworkPacket& NetworkGroup* group = GetGroupByID(connection.player->group); if (group && !group->CanPerformGameCommand(commandCommand)) { Server_Send_SHOWERROR(connection, STR_CANT_DO_THIS, STR_PERMISSION_DENIED); - return 0; + return; } // Don't let clients send pause or quit if (commandCommand == GAME_COMMAND_TOGGLE_PAUSE || commandCommand == GAME_COMMAND_LOAD_OR_QUIT ) { - return 0; + return; } - + // Set this to reference inside of game command functions + game_command_playerid = playerid; // 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; + return; } 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; } -int Network::Client_Handle_TICK(NetworkConnection& connection, NetworkPacket& packet) +void Network::Client_Handle_TICK(NetworkConnection& connection, NetworkPacket& packet) { uint32 srand0; packet >> server_tick >> srand0; @@ -1701,12 +1718,11 @@ int Network::Client_Handle_TICK(NetworkConnection& connection, NetworkPacket& pa server_srand0 = srand0; server_srand0_tick = server_tick; } - return 1; } -int Network::Client_Handle_PLAYERLIST(NetworkConnection& connection, NetworkPacket& packet) +void Network::Client_Handle_PLAYERLIST(NetworkConnection& connection, NetworkPacket& packet) { - uint32 size; + uint8 size; packet >> size; std::vector ids; for (unsigned int i = 0; i < size; i++) { @@ -1732,16 +1748,14 @@ int Network::Client_Handle_PLAYERLIST(NetworkConnection& connection, NetworkPack it++; } } - return 1; } -int Network::Client_Handle_PING(NetworkConnection& connection, NetworkPacket& packet) +void Network::Client_Handle_PING(NetworkConnection& connection, NetworkPacket& packet) { Client_Send_PING(); - return 1; } -int Network::Server_Handle_PING(NetworkConnection& connection, NetworkPacket& packet) +void Network::Server_Handle_PING(NetworkConnection& connection, NetworkPacket& packet) { int ping = SDL_GetTicks() - connection.ping_time; if (ping < 0) { @@ -1751,12 +1765,11 @@ int Network::Server_Handle_PING(NetworkConnection& connection, NetworkPacket& pa connection.player->ping = ping; window_invalidate_by_number(WC_PLAYER, connection.player->id); } - return 1; } -int Network::Client_Handle_PINGLIST(NetworkConnection& connection, NetworkPacket& packet) +void Network::Client_Handle_PINGLIST(NetworkConnection& connection, NetworkPacket& packet) { - uint32 size; + uint8 size; packet >> size; for (unsigned int i = 0; i < size; i++) { uint8 id; @@ -1768,10 +1781,9 @@ int Network::Client_Handle_PINGLIST(NetworkConnection& connection, NetworkPacket } } window_invalidate_by_class(WC_PLAYER); - return 1; } -int Network::Client_Handle_SETDISCONNECTMSG(NetworkConnection& connection, NetworkPacket& packet) +void Network::Client_Handle_SETDISCONNECTMSG(NetworkConnection& connection, NetworkPacket& packet) { static std::string msg; const char* disconnectmsg = packet.ReadString(); @@ -1779,21 +1791,31 @@ int Network::Client_Handle_SETDISCONNECTMSG(NetworkConnection& connection, Netwo msg = disconnectmsg; connection.last_disconnect_reason = msg.c_str(); } - return 1; } -int Network::Server_Handle_GAMEINFO(NetworkConnection& connection, NetworkPacket& packet) +void Network::Server_Handle_GAMEINFO(NetworkConnection& connection, NetworkPacket& packet) { Server_Send_GAMEINFO(connection); - return 1; } -int Network::Client_Handle_SHOWERROR(NetworkConnection& connection, NetworkPacket& packet) +void Network::Client_Handle_SHOWERROR(NetworkConnection& connection, NetworkPacket& packet) { rct_string_id title, message; packet >> title >> message; window_error_open(title, message); - return 1; +} + +void Network::Client_Handle_GROUPLIST(NetworkConnection& connection, NetworkPacket& packet) +{ + group_list.clear(); + uint8 size; + packet >> size; + for (unsigned int i = 0; i < size; i++) { + NetworkGroup group; + group.Read(packet); + std::unique_ptr newgroup(new NetworkGroup(group)); // change to make_unique in c++14 + group_list.push_back(std::move(newgroup)); + } } int network_init() @@ -1953,7 +1975,7 @@ void game_command_set_player_group(int* eax, int* ebx, int* ecx, int* edx, int* return; } if (player->flags & NETWORK_PLAYER_FLAG_ISSERVER) { - RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = STR_CANT_DO_THIS; + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = STR_CANT_CHANGE_GROUP_THAT_THE_HOST_BELONGS_TO; *ebx = MONEY32_UNDEFINED; return; } @@ -1970,33 +1992,72 @@ void game_command_modify_groups(int *eax, int *ebx, int *ecx, int *edx, int *esi uint8 groupid = (uint8)(*eax >> 8); uint8 nameChunkIndex = (uint8)(*eax >> 16); - rct_string_id newUserStringId; char oldName[128]; static char newName[128]; switch (action) { case 0:{ // add group - NetworkGroup* newgroup = gNetwork.AddGroup(); - if (!newgroup) { - *ebx = MONEY32_UNDEFINED; - return; + if (*ebx & GAME_COMMAND_FLAG_APPLY) { + NetworkGroup* newgroup = gNetwork.AddGroup(); + if (!newgroup) { + *ebx = MONEY32_UNDEFINED; + return; + } } }break; case 1:{ // remove group - - }break; - case 2:{ // toggle permission - if (groupid == 0) { // cant change admin group permissions - RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = STR_CANT_DO_THIS; + if (groupid == 0) { + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = STR_THIS_GROUP_CANNOT_BE_MODIFIED; *ebx = MONEY32_UNDEFINED; return; } + for (auto it = gNetwork.player_list.begin(); it != gNetwork.player_list.end(); it++) { + if((*it)->group == groupid) { + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = STR_CANT_REMOVE_GROUP_THAT_PLAYERS_BELONG_TO; + *ebx = MONEY32_UNDEFINED; + return; + } + } + if (*ebx & GAME_COMMAND_FLAG_APPLY) { + gNetwork.RemoveGroup(groupid); + } + }break; + case 2:{ // set permissions + int index = *ecx; + bool all = *edx & 1; + bool allvalue = (*edx >> 1) & 1; + if (groupid == 0) { // cant change admin group permissions + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = STR_THIS_GROUP_CANNOT_BE_MODIFIED; + *ebx = MONEY32_UNDEFINED; + return; + } + NetworkGroup* mygroup = nullptr; + NetworkPlayer* player = gNetwork.GetPlayerByID(game_command_playerid); + if (player) { + mygroup = gNetwork.GetGroupByID(player->group); + if (mygroup) { + if (!all && !mygroup->CanPerformAction(index)) { + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = STR_CANT_SET_PERMISSION_THAT_YOU_DO_NOT_HAVE_YOURSELF; + *ebx = MONEY32_UNDEFINED; + return; + } + } + } if (*ebx & GAME_COMMAND_FLAG_APPLY) { - int index = *ecx; NetworkGroup* group = gNetwork.GetGroupByID(groupid); if (group) { - group->ToggleActionPermission(index); + if (all) { + if (mygroup) { + if (allvalue) { + group->actions_allowed = mygroup->actions_allowed; + } else { + group->actions_allowed.fill(0x00); + } + } + } else { + group->ToggleActionPermission(index); + } } } }break; @@ -2005,7 +2066,7 @@ void game_command_modify_groups(int *eax, int *ebx, int *ecx, int *edx, int *esi if (nameChunkOffset < 0) nameChunkOffset = 2; nameChunkOffset *= 12; - nameChunkOffset = min(nameChunkOffset, Util::CountOf(newName) - 12); + nameChunkOffset = (std::min)(nameChunkOffset, Util::CountOf(newName) - 12); RCT2_GLOBAL(newName + nameChunkOffset + 0, uint32) = *edx; RCT2_GLOBAL(newName + nameChunkOffset + 4, uint32) = *ebp; RCT2_GLOBAL(newName + nameChunkOffset + 8, uint32) = *edi; @@ -2026,21 +2087,16 @@ void game_command_modify_groups(int *eax, int *ebx, int *ecx, int *edx, int *esi return; } - newUserStringId = user_string_allocate(4, newName); - if (newUserStringId == 0) { - RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_INVALID_NAME_FOR_PARK; - *ebx = MONEY32_UNDEFINED; - return; - } - if (*ebx & GAME_COMMAND_FLAG_APPLY) { - // Free the old ride name - user_string_free(RCT2_GLOBAL(RCT2_ADDRESS_PARK_NAME, rct_string_id)); - RCT2_GLOBAL(RCT2_ADDRESS_PARK_NAME, rct_string_id) = newUserStringId; - - gfx_invalidate_screen(); - } else { - user_string_free(newUserStringId); + NetworkGroup* group = gNetwork.GetGroupByID(groupid); + if (group) { + group->SetName(newName); + } + } + }break; + case 4:{ // set default group + if (*ebx & GAME_COMMAND_FLAG_APPLY) { + gNetwork.SetDefaultGroup(groupid); } }break; } @@ -2048,16 +2104,22 @@ void game_command_modify_groups(int *eax, int *ebx, int *ecx, int *edx, int *esi *ebx = 0; } +void game_command_kick_player(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp) +{ + uint8 playerid = (uint8)*eax; + if (*ebx & GAME_COMMAND_FLAG_APPLY) { + if (gNetwork.GetMode() == NETWORK_MODE_SERVER) { + gNetwork.KickPlayer(playerid); + } + } + *ebx = 0; +} + uint8 network_get_default_group() { return gNetwork.GetDefaultGroup(); } -void network_set_default_group(uint8 id) -{ - gNetwork.SetDefaultGroup(id); -} - int network_get_num_actions() { return gNetworkActions.actions.size(); @@ -2108,11 +2170,6 @@ void network_send_password(const char* password) gNetwork.Client_Send_AUTH(gConfigNetwork.player_name, password); } -void network_kick_player(int playerId) -{ - gNetwork.KickPlayer(playerId); -} - void network_set_password(const char* password) { gNetwork.SetPassword(password); @@ -2145,8 +2202,9 @@ 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) { } +void game_command_modify_groups(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) { } +void game_command_kick_player(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) { } int network_get_num_actions() { return 0; } rct_string_id network_get_action_name_string_id(unsigned int index) { return -1; } int network_can_perform_action(unsigned int groupindex, unsigned int index) { return 0; } @@ -2154,7 +2212,6 @@ void network_send_chat(const char* text) {} void network_send_password(const char* password) {} void network_close() {} void network_shutdown_client() {} -void network_kick_player(int playerId) {} void network_set_password(const char* password) {} uint8 network_get_current_player_id() { return 0; } #endif /* DISABLE_NETWORK */ diff --git a/src/network/network.h b/src/network/network.h index be26ecb363..f531dc5688 100644 --- a/src/network/network.h +++ b/src/network/network.h @@ -237,7 +237,8 @@ public: {STR_ACTION_SET_BANNER_STYLE, GAME_COMMAND_SET_BANNER_STYLE}, {STR_ACTION_SET_SIGN_STYLE, GAME_COMMAND_SET_SIGN_STYLE}, {STR_ACTION_SET_PLAYER_GROUP, GAME_COMMAND_SET_PLAYER_GROUP}, - {STR_ACTION_MODIFY_GROUPS, GAME_COMMAND_MODIFY_GROUPS} + {STR_ACTION_MODIFY_GROUPS, GAME_COMMAND_MODIFY_GROUPS}, + {STR_ACTION_KICK_PLAYER, GAME_COMMAND_KICK_PLAYER} }; }; @@ -251,11 +252,11 @@ public: void FreeNameStringId(); void ToggleActionPermission(size_t index); bool CanPerformAction(size_t index); - bool CanPerformGameCommand(uint32 command); + bool CanPerformGameCommand(int command); std::string& GetName(); void SetName(std::string name); rct_string_id GetNameStringId(); - std::array actions_allowed = {0}; + std::array actions_allowed; uint8 id; private: @@ -345,6 +346,7 @@ public: void AdvertiseRegister(); void AdvertiseHeartbeat(); NetworkGroup* AddGroup(); + void RemoveGroup(uint8 id); uint8 GetDefaultGroup(); void SetDefaultGroup(uint8 id); @@ -363,7 +365,7 @@ public: 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); - void Server_Send_GROUPLIST(); + void Server_Send_GROUPLIST(NetworkConnection& connection); std::vector> player_list; std::vector> group_list; @@ -421,23 +423,24 @@ private: void UpdateClient(); private: - std::vector client_command_handlers; - std::vector server_command_handlers; - int Client_Handle_AUTH(NetworkConnection& connection, NetworkPacket& packet); - int Server_Handle_AUTH(NetworkConnection& connection, NetworkPacket& packet); - int Client_Handle_MAP(NetworkConnection& connection, NetworkPacket& packet); - int Client_Handle_CHAT(NetworkConnection& connection, NetworkPacket& packet); - int Server_Handle_CHAT(NetworkConnection& connection, NetworkPacket& packet); - 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); - int Client_Handle_PING(NetworkConnection& connection, NetworkPacket& packet); - int Server_Handle_PING(NetworkConnection& connection, NetworkPacket& packet); - 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); + std::vector client_command_handlers; + std::vector server_command_handlers; + void Client_Handle_AUTH(NetworkConnection& connection, NetworkPacket& packet); + void Server_Handle_AUTH(NetworkConnection& connection, NetworkPacket& packet); + void Client_Handle_MAP(NetworkConnection& connection, NetworkPacket& packet); + void Client_Handle_CHAT(NetworkConnection& connection, NetworkPacket& packet); + void Server_Handle_CHAT(NetworkConnection& connection, NetworkPacket& packet); + void Client_Handle_GAMECMD(NetworkConnection& connection, NetworkPacket& packet); + void Server_Handle_GAMECMD(NetworkConnection& connection, NetworkPacket& packet); + void Client_Handle_TICK(NetworkConnection& connection, NetworkPacket& packet); + void Client_Handle_PLAYERLIST(NetworkConnection& connection, NetworkPacket& packet); + void Client_Handle_PING(NetworkConnection& connection, NetworkPacket& packet); + void Server_Handle_PING(NetworkConnection& connection, NetworkPacket& packet); + void Client_Handle_PINGLIST(NetworkConnection& connection, NetworkPacket& packet); + void Client_Handle_SETDISCONNECTMSG(NetworkConnection& connection, NetworkPacket& packet); + void Server_Handle_GAMEINFO(NetworkConnection& connection, NetworkPacket& packet); + void Client_Handle_SHOWERROR(NetworkConnection& connection, NetworkPacket& packet); + void Client_Handle_GROUPLIST(NetworkConnection& connection, NetworkPacket& packet); }; #endif // __cplusplus @@ -476,8 +479,8 @@ 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); void game_command_modify_groups(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp); +void game_command_kick_player(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); int network_get_num_actions(); rct_string_id network_get_action_name_string_id(unsigned int index); int network_can_perform_action(unsigned int groupindex, unsigned int index); @@ -487,7 +490,6 @@ void network_send_chat(const char* text); void network_send_gamecmd(uint32 eax, uint32 ebx, uint32 ecx, uint32 edx, uint32 esi, uint32 edi, uint32 ebp, uint8 callback); void network_send_password(const char* password); -void network_kick_player(int playerId); void network_set_password(const char* password); void network_print_error(); diff --git a/src/windows/multiplayer.c b/src/windows/multiplayer.c index 2a68e95b66..2dc2f5f096 100644 --- a/src/windows/multiplayer.c +++ b/src/windows/multiplayer.c @@ -46,6 +46,7 @@ enum WINDOW_MULTIPLAYER_WIDGET_IDX { WIDX_DEFAULT_GROUP_DROPDOWN, WIDX_ADD_GROUP, WIDX_REMOVE_GROUP, + WIDX_RENAME_GROUP, WIDX_SELECTED_GROUP, WIDX_SELECTED_GROUP_DROPDOWN, WIDX_PERMISSIONS_LIST, @@ -71,8 +72,9 @@ static rct_widget window_multiplayer_groups_widgets[] = { { 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 }, // - { WWT_DROPDOWN_BUTTON, 1, 44, 134, 65, 76, STR_ADD_GROUP, STR_NONE }, // add group button - { WWT_DROPDOWN_BUTTON, 1, 178, 268, 65, 76, STR_REMOVE_GROUP, STR_NONE }, // remove group button + { WWT_DROPDOWN_BUTTON, 1, 11, 102, 65, 76, STR_ADD_GROUP, STR_NONE }, // add group button + { WWT_DROPDOWN_BUTTON, 1, 113, 204, 65, 76, STR_REMOVE_GROUP, STR_NONE }, // remove group button + { WWT_DROPDOWN_BUTTON, 1, 215, 306, 65, 76, STR_RENAME_GROUP, STR_NONE }, // rename group button { WWT_DROPDOWN, 1, 72, 246, 80, 91, 0x0FFFFFFFF, STR_NONE }, // selected group { WWT_DROPDOWN_BUTTON, 1, 236, 246, 81, 90, 876, STR_NONE }, // { WWT_SCROLL, 1, 3, 316, 94, 300, 2, STR_NONE }, // permissions list @@ -86,7 +88,7 @@ static rct_widget *window_multiplayer_page_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) | (1 << WIDX_ADD_GROUP) | (1 << WIDX_REMOVE_GROUP) | (1 << WIDX_SELECTED_GROUP) | (1 << WIDX_SELECTED_GROUP_DROPDOWN) + (1 << WIDX_CLOSE) | (1 << WIDX_TAB1) | (1 << WIDX_TAB2) | (1 << WIDX_DEFAULT_GROUP) | (1 << WIDX_DEFAULT_GROUP_DROPDOWN) | (1 << WIDX_ADD_GROUP) | (1 << WIDX_REMOVE_GROUP) | (1 << WIDX_RENAME_GROUP) | (1 << WIDX_SELECTED_GROUP) | (1 << WIDX_SELECTED_GROUP_DROPDOWN) }; static uint8 _selectedGroup = 0; @@ -110,6 +112,7 @@ static void window_multiplayer_groups_update(rct_window *w); static void window_multiplayer_groups_scrollgetsize(rct_window *w, int scrollIndex, int *width, int *height); static void window_multiplayer_groups_scrollmousedown(rct_window *w, int scrollIndex, int x, int y); static void window_multiplayer_groups_scrollmouseover(rct_window *w, int scrollIndex, int x, int y); +static void window_multiplayer_groups_text_input(rct_window *w, int widgetIndex, char *text); static void window_multiplayer_groups_invalidate(rct_window *w); static void window_multiplayer_groups_paint(rct_window *w, rct_drawpixelinfo *dpi); static void window_multiplayer_groups_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int scrollIndex); @@ -165,7 +168,7 @@ static rct_window_event_list window_multiplayer_groups_events = { window_multiplayer_groups_scrollmousedown, NULL, window_multiplayer_groups_scrollmouseover, - NULL, + window_multiplayer_groups_text_input, NULL, NULL, NULL, @@ -455,6 +458,15 @@ static void window_multiplayer_groups_mouseup(rct_window *w, int widgetIndex) case WIDX_CLOSE: window_close(w); break; + case WIDX_ADD_GROUP: + game_do_command(0, GAME_COMMAND_FLAG_APPLY, 0, 0, GAME_COMMAND_MODIFY_GROUPS, 0, 0); + break; + case WIDX_REMOVE_GROUP: + game_do_command(1 | (_selectedGroup << 8), GAME_COMMAND_FLAG_APPLY, 0, 0, GAME_COMMAND_MODIFY_GROUPS, 0, 0); + break; + case WIDX_RENAME_GROUP: + window_text_input_open(w, widgetIndex, STR_GROUP_NAME, STR_ENTER_NEW_NAME_FOR_THIS_GROUP, 0, 0, 32); + break; } } @@ -495,9 +507,7 @@ static void window_multiplayer_groups_dropdown(rct_window *w, int widgetIndex, i switch(widgetIndex){ case WIDX_DEFAULT_GROUP_DROPDOWN: - if (network_get_mode() == NETWORK_MODE_SERVER) { - network_set_default_group(network_get_group_id(dropdownIndex)); - } + game_do_command(4 | (network_get_group_id(dropdownIndex) << 8), GAME_COMMAND_FLAG_APPLY, 0, 0, GAME_COMMAND_MODIFY_GROUPS, 0, 0); break; case WIDX_SELECTED_GROUP_DROPDOWN: _selectedGroup = network_get_group_id(dropdownIndex); @@ -562,6 +572,19 @@ static void window_multiplayer_groups_scrollmouseover(rct_window *w, int scrollI window_invalidate(w); } +static void window_multiplayer_groups_text_input(rct_window *w, int widgetIndex, char *text) +{ + if (widgetIndex != WIDX_RENAME_GROUP) + return; + + if (text == NULL) + return; + + game_do_command(3 | (_selectedGroup << 8) | (1 << 16), GAME_COMMAND_FLAG_APPLY, w->number, *((int*)(text + 0)), GAME_COMMAND_MODIFY_GROUPS, *((int*)(text + 8)), *((int*)(text + 4))); + game_do_command(3 | (_selectedGroup << 8) | (2 << 16), GAME_COMMAND_FLAG_APPLY, w->number, *((int*)(text + 12)), GAME_COMMAND_MODIFY_GROUPS, *((int*)(text + 20)), *((int*)(text + 16))); + game_do_command(3 | (_selectedGroup << 8) | (0 << 16), GAME_COMMAND_FLAG_APPLY, w->number, *((int*)(text + 24)), GAME_COMMAND_MODIFY_GROUPS, *((int*)(text + 32)), *((int*)(text + 28))); +} + static void window_multiplayer_groups_invalidate(rct_window *w) { window_multiplayer_set_pressed_tab(w); @@ -569,6 +592,11 @@ static void window_multiplayer_groups_invalidate(rct_window *w) window_multiplayer_groups_widgets[WIDX_PERMISSIONS_LIST].right = w->width - 4; window_multiplayer_groups_widgets[WIDX_PERMISSIONS_LIST].bottom = w->height - 0x0F; window_align_tabs(w, WIDX_TAB1, WIDX_TAB2); + + // select other group if one is removed + while (network_get_group_index(_selectedGroup) == -1 && _selectedGroup > 0) { + _selectedGroup--; + } } static void window_multiplayer_groups_paint(rct_window *w, rct_drawpixelinfo *dpi) @@ -644,16 +672,6 @@ static void window_multiplayer_groups_scrollpaint(rct_window *w, rct_drawpixelin // Draw action name RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = network_get_action_name_string_id(i); gfx_draw_string_left(dpi, 1193, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, 10, y - 1); - - /* - char buffer[300]; - char* lineCh; - lineCh = buffer; - int group = i; - lineCh = utf8_write_codepoint(lineCh, FORMAT_WINDOW_COLOUR_2); - safe_strcpy(lineCh, network_get_action_name(group), sizeof(buffer) - (lineCh - buffer)); - gfx_clip_string(buffer, 80); - gfx_draw_string(dpi, buffer, 0, 0, y - 1);*/ } y += 10; } diff --git a/src/windows/player.c b/src/windows/player.c index 06ab25f34a..c96d6b18f5 100644 --- a/src/windows/player.c +++ b/src/windows/player.c @@ -215,7 +215,7 @@ void window_player_overview_mouse_up(rct_window *w, int widgetIndex) window_player_set_page(w, widgetIndex - WIDX_TAB_1); break; case WIDX_KICK: - network_kick_player(w->number); + game_do_command(w->number, GAME_COMMAND_FLAG_APPLY, 0, 0, GAME_COMMAND_KICK_PLAYER, 0, 0); break; } } @@ -308,17 +308,20 @@ void window_player_overview_paint(rct_window *w, rct_drawpixelinfo *dpi) 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)); + int groupindex = network_get_group_index(network_get_player_group(player)); + if (groupindex != -1) { + rct_widget* widget = &window_player_overview_widgets[WIDX_GROUP]; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = network_get_group_name_string_id(groupindex); - 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_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;