require special permission for cluster building, closes #3045

This commit is contained in:
wolfreak99 2016-03-24 18:59:16 -04:00 committed by IntelOrca
parent f955d03206
commit 1947b1dd30
6 changed files with 47 additions and 8 deletions

View File

@ -4003,6 +4003,7 @@ STR_5661 :Set Player Group
STR_5662 :N/A
STR_5663 :Clear Landscape
STR_5664 :Cheat
STR_5665 :Toggle Scenery Cluster
STR_5701 :{WINDOW_COLOUR_2}Last action: {BLACK}{STRINGID}
STR_5702 :{SMALLFONT}{BLACK}Locate player's most recent action
STR_5703 :Can't kick the host

View File

@ -2307,7 +2307,8 @@ enum {
STR_ACTION_NA = 5662,
STR_ACTION_CLEAR_LANDSCAPE = 5663,
STR_ACTION_CHEAT = 5664,
STR_ACTION_TOGGLE_SCENERY_CLUSTER = 5665,
STR_LAST_ACTION_RAN = 5701,
STR_LOCATE_PLAYER_TIP = 5702,
STR_CANT_KICK_THE_HOST = 5703,

View File

@ -1869,13 +1869,25 @@ void Network::Server_Handle_GAMECMD(NetworkConnection& connection, NetworkPacket
int commandCommand = args[4];
int ticks = SDL_GetTicks(); //tick count is different by time last_action_time is set, keep same value.
// Check if player's group permission allows command to run
NetworkGroup* group = GetGroupByID(connection.player->group);
if (!group || (group && !group->CanPerformCommand(commandCommand))) {
Server_Send_SHOWERROR(connection, STR_CANT_DO_THIS, STR_PERMISSION_DENIED);
return;
}
// Incase someone modifies the code / memory to enable cluster build,
// require a small delay in between placing scenery to provide some security, as
// cluster mode is a for loop that runs the place_scenery code multiple times.
if (commandCommand == GAME_COMMAND_PLACE_SCENERY) {
if ((ticks - connection.player->last_action_time) < 20) {
if (!(group->CanPerformCommand(-2))) {
Server_Send_SHOWERROR(connection, STR_CANT_DO_THIS, STR_CANT_DO_THIS);
return;
}
}
}
// Don't let clients send pause or quit
if (commandCommand == GAME_COMMAND_TOGGLE_PAUSE ||
commandCommand == GAME_COMMAND_LOAD_OR_QUIT
@ -2408,6 +2420,16 @@ int network_can_perform_action(unsigned int groupindex, unsigned int index)
return gNetwork.group_list[groupindex]->CanPerformAction(index);
}
int network_can_perform_command(unsigned int groupindex, unsigned int index)
{
return gNetwork.group_list[groupindex]->CanPerformCommand(index);
}
int network_get_current_player_group_index()
{
return network_get_group_index(gNetwork.GetPlayerByID(gNetwork.GetPlayerID())->group);
}
void network_free_string_ids()
{
gNetwork.FreeStringIds();
@ -2490,6 +2512,7 @@ uint8 network_get_default_group() { return 0; }
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; }
int network_can_perform_command(unsigned int groupindex, unsigned int index) { return 0; }
void network_free_string_ids() {}
void network_send_chat(const char* text) {}
void network_send_password(const char* password) {}
@ -2497,4 +2520,5 @@ void network_close() {}
void network_shutdown_client() {}
void network_set_password(const char* password) {}
uint8 network_get_current_player_id() { return 0; }
int network_get_current_player_group_index() { return 0; }
#endif /* DISABLE_NETWORK */

View File

@ -68,7 +68,7 @@ extern "C" {
// This define specifies which version of network stream current build uses.
// It is used for making sure only compatible builds get connected, even within
// single OpenRCT2 version.
#define NETWORK_STREAM_VERSION "4"
#define NETWORK_STREAM_VERSION "5"
#define NETWORK_STREAM_ID OPENRCT2_VERSION "-" NETWORK_STREAM_VERSION
#define NETWORK_DISCONNECT_REASON_BUFFER_SIZE 256
@ -202,7 +202,8 @@ public:
{STR_ACTION_KICK_PLAYER, {GAME_COMMAND_KICK_PLAYER}},
{STR_ACTION_MODIFY_GROUPS, {GAME_COMMAND_MODIFY_GROUPS}},
{STR_ACTION_SET_PLAYER_GROUP, {GAME_COMMAND_SET_PLAYER_GROUP}},
{STR_ACTION_CHEAT, {GAME_COMMAND_CHEAT}}
{STR_ACTION_CHEAT, {GAME_COMMAND_CHEAT}},
{STR_ACTION_TOGGLE_SCENERY_CLUSTER, {-2}}
};
};
@ -453,6 +454,7 @@ 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);
int network_get_current_player_group_index();
uint8 network_get_group_id(unsigned int index);
int network_get_num_groups();
const char* network_get_group_name(unsigned int index);
@ -464,6 +466,7 @@ uint8 network_get_default_group();
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);
int network_can_perform_command(unsigned int groupindex, unsigned int index);
void network_free_string_ids();
void network_send_map();

View File

@ -33,6 +33,8 @@
#include "../world/sprite.h"
#include "dropdown.h"
#include "../interface/themes.h"
#include "../network/network.h"
#include "error.h"
#define WINDOW_SCENERY_WIDTH 634
#define WINDOW_SCENERY_HEIGHT 142
@ -547,7 +549,15 @@ static void window_scenery_mouseup(rct_window *w, int widgetIndex)
window_invalidate(w);
break;
case WIDX_SCENERY_BUILD_CLUSTER_BUTTON:
window_scenery_is_build_cluster_tool_on ^= 1;
if (window_scenery_is_build_cluster_tool_on == 1) {
window_scenery_is_build_cluster_tool_on = 0;
}
else if (network_get_mode() != NETWORK_MODE_CLIENT || network_can_perform_command(network_get_current_player_group_index(), -2)) {
window_scenery_is_build_cluster_tool_on ^= 1;
}
else {
window_error_open(STR_CANT_DO_THIS, STR_PERMISSION_DENIED);
}
window_invalidate(w);
break;
}

View File

@ -1461,10 +1461,10 @@ static void window_top_toolbar_scenery_tool_down(short x, short y, rct_window *w
case SCENERY_TYPE_SMALL:
{
int quantity = 1;
if (window_scenery_is_build_cluster_tool_on) {
bool isCluster = window_scenery_is_build_cluster_tool_on && (network_get_mode() != NETWORK_MODE_CLIENT || network_can_perform_command(network_get_current_player_group_index(), -2));
if (isCluster) {
quantity = 35;
}
int successfulPlacements = 0;
for (int q = 0; q < quantity; q++) {
int zCoordinate = RCT2_GLOBAL(RCT2_ADDRESS_SCENERY_Z_COORDINATE, sint16);
@ -1473,7 +1473,7 @@ static void window_top_toolbar_scenery_tool_down(short x, short y, rct_window *w
sint16 cur_grid_x = gridX;
sint16 cur_grid_y = gridY;
if (window_scenery_is_build_cluster_tool_on){
if (isCluster){
if (!(scenery->small_scenery.flags & SMALL_SCENERY_FLAG_FULL_TILE)){
parameter_2 &= 0xFF00;
parameter_2 |= util_rand() & 3;