Merge pull request #5557 from IntelOrca/feature/server-logging

Add logging for user actions in multiplayer
This commit is contained in:
Michał Janiszewski 2017-06-06 23:34:02 +02:00 committed by GitHub
commit d3fc1d9e1e
16 changed files with 765 additions and 51 deletions

View File

@ -4373,6 +4373,42 @@ STR_6061 :{SMALLFONT}{BLACK}Show animated money effect{NEWLINE}when guests ma
STR_6062 :{OUTLINE}{GREEN}+ {CURRENCY2DP}
STR_6063 :{OUTLINE}{RED}- {CURRENCY2DP}
STR_6064 :Own all land
STR_6065 :Log user actions
STR_6066 :{SMALLFONT}{BLACK}Logs all user actions to files in your user directory.
STR_6067 :Server started.
STR_6068 :Server shutdown.
STR_6069 :{STRING} was kicked from the server by {STRING}.
STR_6070 :{STRING} was set to group '{STRING}' by {STRING}.
STR_6071 :{STRING} created new player group '{STRING}'.
STR_6072 :{STRING} deleted player group '{String}'.
STR_6073 :{STRING} edited permissions for player group '{String}'.
STR_6074 :{STRING} changed player group name from '{String}' to '{String}'.
STR_6075 :{STRING} changed the default player group to '{String}'.
STR_6076 :{STRING} used/toggled cheat '{STRING}'.
STR_6077 :Add Money
STR_6078 :{STRING} created ride '{STRING}'.
STR_6079 :{STRING} demolished ride '{STRING}'.
STR_6080 :{STRING} changed the appearance of ride '{STRING}'.
STR_6081 :{STRING} changed the status of ride '{STRING}' to closed.
STR_6082 :{STRING} changed the status of ride '{STRING}' to open.
STR_6083 :{STRING} changed the status of ride '{STRING}' to testing.
STR_6084 :{STRING} changed the vehicle settings of ride '{STRING}'.
STR_6085 :{STRING} changed the ride settings of ride '{STRING}'.
STR_6086 :{STRING} renamed the ride '{STRING}' to '{STRING}'.
STR_6087 :{STRING} changed the price of ride '{STRING}' to {STRING}
STR_6088 :{STRING} changed the secondary price of ride '{STRING}' to {STRING}
STR_6089 :{STRING} renamed the park from '{STRING}' to '{STRING}'.
STR_6090 :{STRING} opened the park.
STR_6091 :{STRING} closed the park.
STR_6092 :{STRING} changed the park entrance fee to {STRING}
STR_6093 :{STRING} placed new scenery.
STR_6094 :{STRING} removed scenery.
STR_6095 :{STRING} edited scenery.
STR_6096 :{STRING} set sign name to '{STRING}'.
STR_6097 :{STRING} placed a track of ride '{STRING}'.
STR_6098 :{STRING} removed a track of ride.
STR_6099 :You connected to the server.
STR_6100 :You disconnected from the server.
#############
# Scenarios #

View File

@ -49,6 +49,7 @@ extern "C"
#include "intro.h"
#include "localisation/localisation.h"
#include "network/http.h"
#include "network/network.h"
#include "object_list.h"
#include "rct1.h"
#include "rct2.h"
@ -218,6 +219,7 @@ namespace OpenRCT2
}
http_init();
network_set_env(_env);
theme_manager_initialise();
rct2_interop_setup_hooks();

View File

@ -19,13 +19,14 @@
#include "editor.h"
#include "game.h"
#include "interface/window.h"
#include "localisation/date.h"
#include "localisation/localisation.h"
#include "management/finance.h"
#include "network/network.h"
#include "util/util.h"
#include "world/Climate.h"
#include "world/footpath.h"
#include "world/map.h"
#include "world/park.h"
#include "world/scenery.h"
#include "world/sprite.h"
@ -569,3 +570,209 @@ void cheats_reset()
gCheatsDisablePlantAging = false;
gCheatsAllowArbitraryRideTypeChanges = false;
}
//Generates the string to print for the server log when a cheat is used.
const char* cheats_get_cheat_string(int cheat, int edx, int edi) {
switch (cheat) {
case CHEAT_SANDBOXMODE:
if (gCheatsSandboxMode) {
return language_get_string(STR_CHEAT_SANDBOX_MODE_DISABLE);
} else {
return language_get_string(STR_CHEAT_SANDBOX_MODE);
}
case CHEAT_DISABLECLEARANCECHECKS: return language_get_string(STR_DISABLE_CLEARANCE_CHECKS);
case CHEAT_DISABLESUPPORTLIMITS: return language_get_string(STR_DISABLE_SUPPORT_LIMITS);
case CHEAT_SHOWALLOPERATINGMODES: return language_get_string(STR_CHEAT_SHOW_ALL_OPERATING_MODES);
case CHEAT_SHOWVEHICLESFROMOTHERTRACKTYPES: return language_get_string(STR_CHEAT_SHOW_VEHICLES_FROM_OTHER_TRACK_TYPES);
case CHEAT_FASTLIFTHILL: return language_get_string(STR_CHEAT_UNLOCK_OPERATING_LIMITS);
case CHEAT_DISABLEBRAKESFAILURE: return language_get_string(STR_CHEAT_DISABLE_BRAKES_FAILURE);
case CHEAT_DISABLEALLBREAKDOWNS: return language_get_string(STR_CHEAT_DISABLE_BREAKDOWNS);
case CHEAT_DISABLETRAINLENGTHLIMIT: return language_get_string(STR_CHEAT_DISABLE_TRAIN_LENGTH_LIMIT);
case CHEAT_ENABLECHAINLIFTONALLTRACK: return language_get_string(STR_CHEAT_ENABLE_CHAIN_LIFT_ON_ALL_TRACK);
case CHEAT_UNLOCKALLPRICES: return language_get_string(STR_CHEAT_UNLOCK_PRICES);
case CHEAT_BUILDINPAUSEMODE: return language_get_string(STR_CHEAT_BUILD_IN_PAUSE_MODE);
case CHEAT_IGNORERIDEINTENSITY: return language_get_string(STR_CHEAT_IGNORE_INTENSITY);
case CHEAT_DISABLEVANDALISM: return language_get_string(STR_CHEAT_DISABLE_VANDALISM);
case CHEAT_DISABLELITTERING: return language_get_string(STR_CHEAT_DISABLE_LITTERING);
case CHEAT_ADDMONEY: return language_get_string(STR_LOG_CHEAT_ADD_MONEY);
case CHEAT_CLEARLOAN: return language_get_string(STR_CHEAT_CLEAR_LOAN);
case CHEAT_SETGUESTPARAMETER:
{
static char cheat_string[128];
safe_strcpy(cheat_string, language_get_string(STR_CHEAT_SET_GUESTS_PARAMETERS), 128);
safe_strcat(cheat_string, " ", 128);
switch (edx) {
case GUEST_PARAMETER_HAPPINESS:
safe_strcat(cheat_string, language_get_string(STR_CHEAT_GUEST_HAPPINESS), 128);
safe_strcat(cheat_string, " ", 128);
if (edi == 255) {
safe_strcat(cheat_string, language_get_string(STR_MAX), 128);
} else if (edi == 0) {
safe_strcat(cheat_string, language_get_string(STR_MIN), 128);
}
break;
case GUEST_PARAMETER_ENERGY:
safe_strcat(cheat_string, language_get_string(STR_CHEAT_GUEST_ENERGY), 128);
safe_strcat(cheat_string, " ", 128);
if (edi == 127) {
safe_strcat(cheat_string, language_get_string(STR_MAX), 128);
} else if (edi == 0) {
safe_strcat(cheat_string, language_get_string(STR_MIN), 128);
}
break;
case GUEST_PARAMETER_HUNGER:
safe_strcat(cheat_string, language_get_string(STR_CHEAT_GUEST_HUNGER), 128);
safe_strcat(cheat_string, " ", 128);
if (edi == 255) {
safe_strcat(cheat_string, language_get_string(STR_MIN), 128);
} else if (edi == 0) {
safe_strcat(cheat_string, language_get_string(STR_MAX), 128);
}
break;
case GUEST_PARAMETER_THIRST:
safe_strcat(cheat_string, language_get_string(STR_CHEAT_GUEST_THIRST), 128);
safe_strcat(cheat_string, " ", 128);
if (edi == 255) {
safe_strcat(cheat_string, language_get_string(STR_MIN), 128);
} else if (edi == 0) {
safe_strcat(cheat_string, language_get_string(STR_MAX), 128);
}
break;
case GUEST_PARAMETER_NAUSEA:
safe_strcat(cheat_string, language_get_string(STR_CHEAT_GUEST_NAUSEA), 128);
safe_strcat(cheat_string, " ", 128);
if (edi == 255) {
safe_strcat(cheat_string, language_get_string(STR_MAX), 128);
} else if (edi == 0) {
safe_strcat(cheat_string, language_get_string(STR_MIN), 128);
}
break;
case GUEST_PARAMETER_NAUSEA_TOLERANCE:
safe_strcat(cheat_string, language_get_string(STR_CHEAT_GUEST_NAUSEA_TOLERANCE), 128);
safe_strcat(cheat_string, " ", 128);
if (edi == PEEP_NAUSEA_TOLERANCE_HIGH) {
safe_strcat(cheat_string, language_get_string(STR_MAX), 128);
} else if (edi == PEEP_NAUSEA_TOLERANCE_NONE) {
safe_strcat(cheat_string, language_get_string(STR_MIN), 128);
}
break;
case GUEST_PARAMETER_BATHROOM:
safe_strcat(cheat_string, language_get_string(STR_CHEAT_GUEST_BATHROOM), 128);
safe_strcat(cheat_string, " ", 128);
if (edi == 255) {
safe_strcat(cheat_string, language_get_string(STR_MAX), 128);
} else if (edi == 0) {
safe_strcat(cheat_string, language_get_string(STR_MIN), 128);
}
break;
case GUEST_PARAMETER_PREFERRED_RIDE_INTENSITY:
safe_strcat(cheat_string, language_get_string(STR_CHEAT_GUEST_PREFERRED_INTENSITY), 128);
safe_strcat(cheat_string, " ", 128);
if (edi == 1) {
safe_strcat(cheat_string, language_get_string(STR_CHEAT_MORE_THAN_1), 128);
} else if (edi == 0) {
safe_strcat(cheat_string, language_get_string(STR_CHEAT_LESS_THAN_15), 128);
}
break;
}
return cheat_string;
}
case CHEAT_GENERATEGUESTS: return language_get_string(STR_CHEAT_LARGE_TRAM_GUESTS);
case CHEAT_REMOVEALLGUESTS: return language_get_string(STR_CHEAT_REMOVE_ALL_GUESTS);
case CHEAT_EXPLODEGUESTS: return language_get_string(STR_CHEAT_EXPLODE);
case CHEAT_GIVEALLGUESTS:
{
static char cheat_string[64];
safe_strcpy(cheat_string, language_get_string(STR_CHEAT_GIVE_ALL_GUESTS), 64);
safe_strcat(cheat_string, " ", 64);
switch (edx) {
case OBJECT_MONEY:
{
char money[16];
set_format_arg(0, money32, CHEATS_GIVE_GUESTS_MONEY);
format_string(money, 16, STR_CHEAT_CURRENCY_FORMAT, gCommonFormatArgs);
safe_strcat(cheat_string, money, 64);
break;
}
case OBJECT_PARK_MAP: safe_strcat(cheat_string, language_get_string(STR_SHOP_ITEM_PLURAL_PARK_MAP), 64); break;
case OBJECT_BALLOON: safe_strcat(cheat_string, language_get_string(STR_SHOP_ITEM_PLURAL_BALLOON), 64); break;
case OBJECT_UMBRELLA: safe_strcat(cheat_string, language_get_string(STR_SHOP_ITEM_PLURAL_UMBRELLA), 64); break;
}
return cheat_string;
}
case CHEAT_SETGRASSLENGTH:
if (edx == 0) {
return language_get_string(STR_CHEAT_MOWED_GRASS);
} else if (edx == 1) {
return language_get_string(STR_CHEAT_CLEAR_GRASS);
}
case CHEAT_WATERPLANTS: return language_get_string(STR_CHEAT_WATER_PLANTS);
case CHEAT_FIXVANDALISM: return language_get_string(STR_CHEAT_FIX_VANDALISM);
case CHEAT_REMOVELITTER: return language_get_string(STR_CHEAT_REMOVE_LITTER);
case CHEAT_DISABLEPLANTAGING: return language_get_string(STR_CHEAT_DISABLE_PLANT_AGING);
case CHEAT_SETSTAFFSPEED:
{
static char cheat_string[64];
safe_strcpy(cheat_string, language_get_string(STR_CHEAT_STAFF_SPEED), 64);
safe_strcat(cheat_string, " ", 64);
if (edx == CHEATS_STAFF_FAST_SPEED) {
safe_strcat(cheat_string, language_get_string(STR_FAST), 64);
} else if (edx == CHEATS_STAFF_NORMAL_SPEED) {
safe_strcat(cheat_string, language_get_string(STR_NORMAL), 64);
}
return cheat_string;
}
case CHEAT_RENEWRIDES: return language_get_string(STR_CHEAT_RENEW_RIDES);
case CHEAT_MAKEDESTRUCTIBLE: return language_get_string(STR_CHEAT_MAKE_DESTRUCTABLE);
case CHEAT_FIXRIDES: return language_get_string(STR_CHEAT_FIX_ALL_RIDES);
case CHEAT_RESETCRASHSTATUS: return language_get_string(STR_CHEAT_RESET_CRASH_STATUS);
case CHEAT_10MINUTEINSPECTIONS: return language_get_string(STR_CHEAT_10_MINUTE_INSPECTIONS);
case CHEAT_WINSCENARIO: return language_get_string(STR_CHEAT_WIN_SCENARIO);
case CHEAT_FORCEWEATHER:
{
static char cheat_string[64];
safe_strcpy(cheat_string, language_get_string(STR_FORCE_WEATHER), 64);
safe_strcat(cheat_string, " ", 64);
switch (edx) {
case 0: safe_strcat(cheat_string, language_get_string(STR_SUNNY), 64); break;
case 1: safe_strcat(cheat_string, language_get_string(STR_PARTIALLY_CLOUDY), 64); break;
case 2: safe_strcat(cheat_string, language_get_string(STR_CLOUDY), 64); break;
case 3: safe_strcat(cheat_string, language_get_string(STR_RAIN), 64); break;
case 4: safe_strcat(cheat_string, language_get_string(STR_HEAVY_RAIN), 64); break;
case 5: safe_strcat(cheat_string, language_get_string(STR_THUNDERSTORM), 64); break;
}
return cheat_string;
}
case CHEAT_FREEZECLIMATE:
if (gCheatsFreezeClimate) {
return language_get_string(STR_CHEAT_UNFREEZE_CLIMATE);
} else {
return language_get_string(STR_CHEAT_FREEZE_CLIMATE);
}
case CHEAT_NEVERENDINGMARKETING: return language_get_string(STR_CHEAT_NEVERENDING_MARKETING);
case CHEAT_OPENCLOSEPARK:
if (park_is_open()) {
return language_get_string(STR_CHEAT_CLOSE_PARK);
} else {
return language_get_string(STR_CHEAT_OPEN_PARK);
}
case CHEAT_HAVEFUN: return language_get_string(STR_CHEAT_HAVE_FUN);
case CHEAT_SETFORCEDPARKRATING:
{
static char cheat_string[64];
safe_strcpy(cheat_string, language_get_string(STR_FORCE_PARK_RATING), 64);
safe_strcat(cheat_string, " ", 64);
char buffer[8];
snprintf(buffer, sizeof(buffer), "%d", park_rating_spinner_value);
char* park_rating = buffer;
safe_strcat(cheat_string, park_rating, 64);
return cheat_string;
}
case CHEAT_RESETDATE: return language_get_string(STR_CHEAT_RESET_DATE);
case CHEAT_ALLOW_ARBITRARY_RIDE_TYPE_CHANGES: return language_get_string(STR_CHEAT_ALLOW_ARBITRARY_RIDE_TYPE_CHANGES);
}
return "";
}

View File

@ -107,7 +107,10 @@ enum {
};
#define CHEATS_MONEY_INCREMENT MONEY(5000,00)
#define CHEATS_GIVE_GUESTS_MONEY MONEY(1000,00)
#define CHEATS_TRAM_INCREMENT 250
#define CHEATS_STAFF_FAST_SPEED 0xFF
#define CHEATS_STAFF_NORMAL_SPEED 0x60
extern sint32 park_rating_spinner_value;
@ -115,4 +118,6 @@ void game_command_cheat(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx, sint
void cheats_reset();
const char* cheats_get_cheat_string(int cheat, int edx, int edi);
#endif

View File

@ -359,6 +359,7 @@ namespace Config
model->provider_website = reader->GetCString("provider_website", nullptr);
model->known_keys_only = reader->GetBoolean("known_keys_only", false);
model->log_chat = reader->GetBoolean("log_chat", false);
model->log_server_actions = reader->GetBoolean("log_server_actions", false);
}
}
@ -382,6 +383,7 @@ namespace Config
writer->WriteString("provider_website", model->provider_website);
writer->WriteBoolean("known_keys_only", model->known_keys_only);
writer->WriteBoolean("log_chat", model->log_chat);
writer->WriteBoolean("log_server_actions", model->log_server_actions);
}
static void ReadNotifications(IIniReader * reader)

View File

@ -152,6 +152,7 @@ typedef struct NetworkConfiguration
utf8 * provider_website;
bool known_keys_only;
bool log_chat;
bool log_server_actions;
} NetworkConfiguration;
typedef struct NotificationConfiguration

View File

@ -512,6 +512,13 @@ sint32 game_do_command_p(sint32 command, sint32 *eax, sint32 *ebx, sint32 *ecx,
game_command_playerid = network_get_current_player_id();
}
// Log certain commands if we are in multiplayer and logging is enabled
bool serverLog = (network_get_mode() == NETWORK_MODE_SERVER) && gGameCommandNestLevel == 1 && gConfigNetwork.log_server_actions;
bool clientLog = (network_get_mode() == NETWORK_MODE_CLIENT) && (flags & GAME_COMMAND_FLAG_NETWORKED) && gGameCommandNestLevel == 1 && gConfigNetwork.log_server_actions;
if (serverLog || clientLog) {
game_log_multiplayer_command(command, eax, ebx, ecx, edx, edi, ebp);
}
*ebx &= ~GAME_COMMAND_FLAG_APPLY;
// First call for validity and price check
@ -611,6 +618,228 @@ sint32 game_do_command_p(sint32 command, sint32 *eax, sint32 *ebx, sint32 *ecx,
return MONEY32_UNDEFINED;
}
void game_log_multiplayer_command(int command, int *eax, int* ebx, int* ecx, int* edx, int* edi, int* ebp)
{
// Get player name
int player_index = network_get_player_index(game_command_playerid);
const char* player_name = network_get_player_name(player_index);
char log_msg[256];
if (command == GAME_COMMAND_CHEAT) {
// Get cheat name
const char* cheat = cheats_get_cheat_string(*ecx, *edx, *edi);
char* args[2] = {
(char *)player_name,
(char *)cheat
};
format_string(log_msg, 256, STR_LOG_CHEAT_USED, args);
network_append_server_log(log_msg);
} else if (command == GAME_COMMAND_CREATE_RIDE && *ebp == 1) { // ebp is 1 if the command comes from ride_create method in ride.c, other calls send ride_entry instead of ride and wont work
// Get ride name
rct_ride* ride = get_ride(*edx);
char ride_name[128];
format_string(ride_name, 128, ride->name, &ride->name_arguments);
char* args[2] = {
(char *)player_name,
ride_name
};
format_string(log_msg, 256, STR_LOG_CREATE_RIDE, args);
network_append_server_log(log_msg);
} else if (command == GAME_COMMAND_DEMOLISH_RIDE && (*ebp == 1 || *ebp == 0)) { // ebp is 1 if command comes from ride window prompt, so we don't log "demolishing" ride previews
// Get ride name
rct_ride* ride = get_ride(*edx);
char ride_name[128];
format_string(ride_name, 128, ride->name, &ride->name_arguments);
char* args[2] = {
(char *) player_name,
ride_name
};
format_string(log_msg, 256, STR_LOG_DEMOLISH_RIDE, args);
network_append_server_log(log_msg);
} else if (command == GAME_COMMAND_SET_RIDE_APPEARANCE || command == GAME_COMMAND_SET_RIDE_VEHICLES || command == GAME_COMMAND_SET_RIDE_SETTING) {
// Get ride name
int ride_index = *edx & 0xFF;
rct_ride* ride = get_ride(ride_index);
char ride_name[128];
format_string(ride_name, 128, ride->name, &ride->name_arguments);
char* args[2] = {
(char *) player_name,
ride_name
};
switch (command) {
case GAME_COMMAND_SET_RIDE_APPEARANCE: format_string(log_msg, 256, STR_LOG_RIDE_APPEARANCE, args); break;
case GAME_COMMAND_SET_RIDE_VEHICLES: format_string(log_msg, 256, STR_LOG_RIDE_VEHICLES, args); break;
case GAME_COMMAND_SET_RIDE_SETTING: format_string(log_msg, 256, STR_LOG_RIDE_SETTINGS, args); break;
}
network_append_server_log(log_msg);
} else if (command == GAME_COMMAND_SET_RIDE_STATUS) {
// Get ride name
int ride_index = *edx & 0xFF;
rct_ride* ride = get_ride(ride_index);
char ride_name[128];
format_string(ride_name, 128, ride->name, &ride->name_arguments);
char* args[2] = {
(char *) player_name,
ride_name
};
int status = *edx >> 8;
switch (status) {
case 0: format_string(log_msg, 256, STR_LOG_RIDE_STATUS_CLOSED, args); break;
case 1: format_string(log_msg, 256, STR_LOG_RIDE_STATUS_OPEN, args); break;
case 2: format_string(log_msg, 256, STR_LOG_RIDE_STATUS_TESTING, args); break;
}
network_append_server_log(log_msg);
} else if (command == GAME_COMMAND_SET_RIDE_PRICE) {
// Get ride name
int ride_index = *edx & 0xFF;
rct_ride* ride = get_ride(ride_index);
char ride_name[128];
format_string(ride_name, 128, ride->name, &ride->name_arguments);
// Format price
int price_args[1] = {*edi};
char price_str[16];
format_string(price_str, 16, STR_BOTTOM_TOOLBAR_CASH, price_args);
// Log change in primary or secondary price
char* args[3] = {
(char *) player_name,
ride_name,
price_str
};
if (*edx >> 8 == 0) {
format_string(log_msg, 256, STR_LOG_RIDE_PRICE, args);
} else if (*edx >> 8 == 1) {
format_string(log_msg, 256, STR_LOG_RIDE_SECONDARY_PRICE, args);
}
network_append_server_log(log_msg);
} else if (command == GAME_COMMAND_SET_PARK_OPEN) {
// Log change in park open/close
char* args[1] = {
(char *) player_name
};
if (*edx >> 8 == 0) {
format_string(log_msg, 256, STR_LOG_PARK_OPEN, args);
} else if (*edx >> 8 == 1) {
format_string(log_msg, 256, STR_LOG_PARK_CLOSED, args);
}
network_append_server_log(log_msg);
} else if (command == GAME_COMMAND_SET_PARK_ENTRANCE_FEE) {
// Format price
int price_args[1] = {*edi};
char price_str[16];
format_string(price_str, 16, STR_BOTTOM_TOOLBAR_CASH, price_args);
// Log change in park entrance fee
char* args[2] = {
(char *) player_name,
price_str
};
format_string(log_msg, 256, STR_LOG_PARK_ENTRANCE_FEE, args);
network_append_server_log(log_msg);
} else if (command == GAME_COMMAND_PLACE_SCENERY || command == GAME_COMMAND_PLACE_WALL ||
command == GAME_COMMAND_PLACE_LARGE_SCENERY || command == GAME_COMMAND_PLACE_BANNER) {
uint8 flags = *ebx & 0xFF;
if (flags & GAME_COMMAND_FLAG_GHOST) {
// Don't log ghost previews being removed
return;
}
// Log placing scenery
char* args[1] = {
(char *)player_name
};
format_string(log_msg, 256, STR_LOG_PLACE_SCENERY, args);
network_append_server_log(log_msg);
} else if (command == GAME_COMMAND_REMOVE_SCENERY || command == GAME_COMMAND_REMOVE_WALL ||
command == GAME_COMMAND_REMOVE_LARGE_SCENERY || command == GAME_COMMAND_REMOVE_BANNER) {
uint8 flags = *ebx & 0xFF;
if (flags & GAME_COMMAND_FLAG_GHOST) {
// Don't log ghost previews being removed
return;
}
// Log removing scenery
char* args[1] = {
(char *)player_name
};
format_string(log_msg, 256, STR_LOG_REMOVE_SCENERY, args);
network_append_server_log(log_msg);
} else if (command == GAME_COMMAND_SET_SCENERY_COLOUR || command == GAME_COMMAND_SET_WALL_COLOUR ||
command == GAME_COMMAND_SET_LARGE_SCENERY_COLOUR || command == GAME_COMMAND_SET_BANNER_COLOUR ||
command == GAME_COMMAND_SET_BANNER_NAME || command == GAME_COMMAND_SET_SIGN_NAME ||
command == GAME_COMMAND_SET_BANNER_STYLE || command == GAME_COMMAND_SET_SIGN_STYLE) {
// Log editing scenery
char* args[1] = {
(char *)player_name
};
format_string(log_msg, 256, STR_LOG_EDIT_SCENERY, args);
network_append_server_log(log_msg);
if (command == GAME_COMMAND_SET_BANNER_NAME || command == GAME_COMMAND_SET_SIGN_NAME) {
static char banner_name[128];
memset(banner_name, ' ', sizeof(banner_name));
int nameChunkIndex = *eax & 0xFFFF;
int nameChunkOffset = nameChunkIndex - 1;
if (nameChunkOffset < 0)
nameChunkOffset = 2;
nameChunkOffset *= 12;
nameChunkOffset = min(nameChunkOffset, countof(banner_name) - 12);
memcpy(banner_name + nameChunkOffset + 0, edx, 4);
memcpy(banner_name + nameChunkOffset + 4, ebp, 4);
memcpy(banner_name + nameChunkOffset + 8, edi, 4);
banner_name[sizeof(banner_name) - 1] = '\0';
char* args_sign[2] = {
(char *)player_name,
(char *)banner_name
};
format_string(log_msg, 256, STR_LOG_SET_SIGN_NAME, args_sign);
network_append_server_log(log_msg);
}
} else if (command == GAME_COMMAND_PLACE_TRACK) {
// Get ride name
int ride_index = *edx & 0xFF;
rct_ride* ride = get_ride(ride_index);
char ride_name[128];
format_string(ride_name, 128, ride->name, &ride->name_arguments);
char* args[2] = {
(char *) player_name,
ride_name
};
format_string(log_msg, 256, STR_LOG_PLACE_TRACK, args);
network_append_server_log(log_msg);
} else if (command == GAME_COMMAND_REMOVE_TRACK) {
char* args[1] = {
(char *) player_name
};
format_string(log_msg, 256, STR_LOG_REMOVE_TRACK, args);
network_append_server_log(log_msg);
}
}
void pause_toggle()
{
gGamePaused ^= GAME_PAUSED_NORMAL;

View File

@ -166,6 +166,8 @@ void update_palette_effects();
sint32 game_do_command(sint32 eax, sint32 ebx, sint32 ecx, sint32 edx, sint32 esi, sint32 edi, sint32 ebp);
sint32 game_do_command_p(sint32 command, sint32 *eax, sint32 *ebx, sint32 *ecx, sint32 *edx, sint32 *esi, sint32 *edi, sint32 *ebp);
void game_log_multiplayer_command(int command, int *eax, int* ebx, int* ecx, int* edx, int* edi, int* ebp);
void game_load_or_quit_no_save_prompt();
bool game_load_sv6_path(const char * path);
bool game_load_save(const utf8 *path);

View File

@ -3728,6 +3728,43 @@ enum {
STR_CHEAT_OWN_ALL_LAND = 6064,
STR_LOG_SERVER_ACTIONS = 6065,
STR_LOG_SERVER_ACTIONS_TIP = 6066,
STR_LOG_SERVER_STARTED = 6067,
STR_LOG_SERVER_STOPPED = 6068,
STR_LOG_PLAYER_KICKED = 6069,
STR_LOG_SET_PLAYER_GROUP = 6070,
STR_LOG_ADD_PLAYER_GROUP = 6071,
STR_LOG_REMOVE_PLAYER_GROUP = 6072,
STR_LOG_EDIT_PLAYER_GROUP_PERMISSIONS = 6073,
STR_LOG_EDIT_PLAYER_GROUP_NAME = 6074,
STR_LOG_EDIT_DEFAULT_PLAYER_GROUP = 6075,
STR_LOG_CHEAT_USED = 6076,
STR_LOG_CHEAT_ADD_MONEY = 6077,
STR_LOG_CREATE_RIDE = 6078,
STR_LOG_DEMOLISH_RIDE = 6079,
STR_LOG_RIDE_APPEARANCE = 6080,
STR_LOG_RIDE_STATUS_CLOSED = 6081,
STR_LOG_RIDE_STATUS_OPEN = 6082,
STR_LOG_RIDE_STATUS_TESTING = 6083,
STR_LOG_RIDE_VEHICLES = 6084,
STR_LOG_RIDE_SETTINGS = 6085,
STR_LOG_RIDE_NAME = 6086,
STR_LOG_RIDE_PRICE = 6087,
STR_LOG_RIDE_SECONDARY_PRICE = 6088,
STR_LOG_PARK_NAME = 6089,
STR_LOG_PARK_CLOSED = 6090,
STR_LOG_PARK_OPEN = 6091,
STR_LOG_PARK_ENTRANCE_FEE = 6092,
STR_LOG_PLACE_SCENERY = 6093,
STR_LOG_REMOVE_SCENERY = 6094,
STR_LOG_EDIT_SCENERY = 6095,
STR_LOG_SET_SIGN_NAME = 6096,
STR_LOG_PLACE_TRACK = 6097,
STR_LOG_REMOVE_TRACK = 6098,
STR_LOG_CLIENT_STARTED = 6099,
STR_LOG_CLIENT_STOPPED = 6100,
// Have to include resource strings (from scenarios and objects) for the time being now that language is partially working
STR_COUNT = 32768
};

View File

@ -16,6 +16,7 @@
#include "../core/Guard.hpp"
#include "../OpenRCT2.h"
#include "../PlatformEnvironment.h"
extern "C" {
#include "../platform/platform.h"
@ -125,6 +126,11 @@ Network::~Network()
Close();
}
void Network::SetEnvironment(IPlatformEnvironment * env)
{
_env = env;
}
bool Network::Init()
{
if (!InitialiseWSA()) {
@ -170,6 +176,9 @@ void Network::Close()
_advertiser = nullptr;
}
CloseChatLog();
CloseServerLog();
mode = NETWORK_MODE_NONE;
status = NETWORK_STATUS_NONE;
_lastConnectStatus = SOCKET_STATUS_CLOSED;
@ -185,7 +194,6 @@ void Network::Close()
DisposeWSA();
CloseChatLog();
gfx_invalidate_screen();
_requireClose = false;
@ -210,6 +218,7 @@ bool Network::BeginClient(const char* host, uint16 port)
_lastConnectStatus = SOCKET_STATUS_CLOSED;
BeginChatLog();
BeginServerLog();
utf8 keyPath[MAX_PATH];
network_get_private_key_path(keyPath, sizeof(keyPath), gConfigNetwork.player_name);
@ -313,6 +322,7 @@ bool Network::BeginServer(uint16 port, const char* address)
cheats_reset();
LoadGroups();
BeginChatLog();
BeginServerLog();
NetworkPlayer *player = AddPlayer(gConfigNetwork.player_name, "");
player->Flags |= NETWORK_PLAYER_FLAG_ISSERVER;
@ -823,62 +833,97 @@ void Network::LoadGroups()
group_list.at(0)->ActionsAllowed.fill(0xFF);
}
void Network::BeginChatLog()
std::string Network::BeginLog(const std::string &directory, const std::string &filenameFormat)
{
utf8 filename[32];
utf8 filename[256];
time_t timer;
struct tm * tmInfo;
time(&timer);
tmInfo = localtime(&timer);
strftime(filename, sizeof(filename), "%Y%m%d-%H%M%S.txt", tmInfo);
utf8 path[MAX_PATH];
platform_get_user_directory(path, "chatlogs", sizeof(path));
Path::Append(path, sizeof(path), filename);
_chatLogPath = std::string(path);
}
void Network::AppendChatLog(const utf8 *text)
{
if (!gConfigNetwork.log_chat) {
return;
auto tmInfo = localtime(&timer);
if (strftime(filename, sizeof(filename), filenameFormat.c_str(), tmInfo) == 0) {
throw std::runtime_error("strftime failed");
}
const utf8 *chatLogPath = _chatLogPath.c_str();
return Path::Combine(directory, filename);
}
utf8 directory[MAX_PATH];
Path::GetDirectory(directory, sizeof(directory), chatLogPath);
if (platform_ensure_directory_exists(directory)) {
void Network::AppendLog(const std::string &logPath, const std::string &s)
{
std::string directory = Path::GetDirectory(logPath);
if (platform_ensure_directory_exists(directory.c_str())) {
try
{
_chatLogStream = new FileStream(chatLogPath, FILE_MODE_APPEND);
auto fs = FileStream(logPath, FILE_MODE_APPEND);
utf8 buffer[256];
time_t timer;
struct tm * tmInfo;
time(&timer);
tmInfo = localtime(&timer);
strftime(buffer, sizeof(buffer), "[%Y/%m/%d %H:%M:%S] ", tmInfo);
auto tmInfo = localtime(&timer);
if (strftime(buffer, sizeof(buffer), "[%Y/%m/%d %H:%M:%S] ", tmInfo) != 0) {
String::Append(buffer, sizeof(buffer), s.c_str());
utf8_remove_formatting(buffer, false);
String::Append(buffer, sizeof(buffer), PLATFORM_NEWLINE);
String::Append(buffer, sizeof(buffer), text);
utf8_remove_formatting(buffer, false);
String::Append(buffer, sizeof(buffer), PLATFORM_NEWLINE);
_chatLogStream->Write(buffer, strlen(buffer));
delete _chatLogStream;
_chatLogStream = nullptr;
fs.Write(buffer, strlen(buffer));
}
}
catch (const Exception &)
catch (const Exception &ex)
{
log_error("%s", ex.GetMessage());
}
}
}
void Network::BeginChatLog()
{
auto directory = _env->GetDirectoryPath(DIRBASE::USER, DIRID::LOG_CHAT);
_chatLogPath = BeginLog(directory, _chatLogFilenameFormat);
}
void Network::AppendChatLog(const std::string &s)
{
if (gConfigNetwork.log_chat) {
AppendLog(_chatLogPath, s);
}
}
void Network::CloseChatLog()
{
}
void Network::BeginServerLog()
{
auto directory = _env->GetDirectoryPath(DIRBASE::USER, DIRID::LOG_SERVER);
_serverLogPath = BeginLog(directory, (ServerName + _serverLogFilenameFormat));
// Log server start event
utf8 logMessage[256];
if (GetMode() == NETWORK_MODE_CLIENT) {
format_string(logMessage, sizeof(logMessage), STR_LOG_CLIENT_STARTED, NULL);
} else if (GetMode() == NETWORK_MODE_SERVER) {
format_string(logMessage, sizeof(logMessage), STR_LOG_SERVER_STARTED, NULL);
}
AppendServerLog(logMessage);
}
void Network::AppendServerLog(const std::string &s)
{
if (gConfigNetwork.log_server_actions) {
AppendLog(_serverLogPath.c_str(), s);
}
}
void Network::CloseServerLog()
{
// Log server stopped event
char logMessage[256];
if (GetMode() == NETWORK_MODE_CLIENT) {
format_string(logMessage, sizeof(logMessage), STR_LOG_CLIENT_STOPPED, NULL);
} else if (GetMode() == NETWORK_MODE_SERVER) {
format_string(logMessage, sizeof(logMessage), STR_LOG_SERVER_STOPPED, NULL);
}
AppendServerLog(logMessage);
}
void Network::Client_Send_TOKEN()
{
log_verbose("requesting token");
@ -1292,6 +1337,9 @@ void Network::AddClient(ITcpSocket * socket)
{
auto connection = std::unique_ptr<NetworkConnection>(new NetworkConnection); // change to make_unique in c++14
connection->Socket = socket;
char addr[128];
snprintf(addr, sizeof(addr), "Client joined from %s", socket->GetHostName());
AppendServerLog(addr);
client_connection_list.push_back(std::move(connection));
}
@ -1317,6 +1365,9 @@ void Network::RemoveClient(std::unique_ptr<NetworkConnection>& connection)
game_do_command(pickup_peep->sprite_index, GAME_COMMAND_FLAG_APPLY, 1, 0, pickup_peep->type == PEEP_TYPE_GUEST ? GAME_COMMAND_PICKUP_GUEST : GAME_COMMAND_PICKUP_STAFF, network_get_pickup_peep_old_x(connection_player->Id), 0);
}
gNetwork.Server_Send_EVENT_PLAYER_DISCONNECTED((char*)connection_player->Name.c_str(), connection->GetLastDisconnectReason());
// Log player disconnected event
AppendServerLog(text);
}
player_list.erase(std::remove_if(player_list.begin(), player_list.end(), [connection_player](std::unique_ptr<NetworkPlayer>& player){
return player.get() == connection_player;
@ -1516,6 +1567,9 @@ void Network::Server_Client_Joined(const char* name, const std::string &keyhash,
IObjectManager * objManager = GetObjectManager();
auto objects = objManager->GetPackableObjects();
Server_Send_OBJECTS(connection, objects);
// Log player joining event
AppendServerLog(text);
}
}
@ -2138,9 +2192,9 @@ void Network::Client_Handle_GAMEINFO(NetworkConnection& connection, NetworkPacke
network_chat_show_server_greeting();
}
sint32 network_init()
void network_set_env(void * env)
{
return gNetwork.Init();
gNetwork.SetEnvironment((IPlatformEnvironment *)env);
}
void network_close()
@ -2375,6 +2429,18 @@ void game_command_set_player_group(sint32* eax, sint32* ebx, sint32* ecx, sint32
}
window_invalidate_by_number(WC_PLAYER, playerid);
// Log set player group event
NetworkPlayer* game_command_player = gNetwork.GetPlayerByID(game_command_playerid);
NetworkGroup* new_player_group = gNetwork.GetGroupByID(groupid);
char log_msg[256];
const char * args[3] = {
(char *) player->Name.c_str(),
(char *) new_player_group->GetName().c_str(),
(char *) game_command_player->Name.c_str()
};
format_string(log_msg, 256, STR_LOG_SET_PLAYER_GROUP, args);
network_append_server_log(log_msg);
}
*ebx = 0;
}
@ -2385,9 +2451,6 @@ void game_command_modify_groups(sint32 *eax, sint32 *ebx, sint32 *ecx, sint32 *e
uint8 groupid = (uint8)(*eax >> 8);
uint8 nameChunkIndex = (uint8)(*eax >> 16);
char oldName[128] = { 0 };
static char newName[128];
switch (action)
{
case 0:{ // add group
@ -2399,6 +2462,16 @@ void game_command_modify_groups(sint32 *eax, sint32 *ebx, sint32 *ecx, sint32 *e
*ebx = MONEY32_UNDEFINED;
return;
}
// Log add player group event
NetworkPlayer* game_command_player = gNetwork.GetPlayerByID(game_command_playerid);
char log_msg[256];
const char * args[2] = {
(char *) game_command_player->Name.c_str(),
(char *) newgroup->GetName().c_str()
};
format_string(log_msg, 256, STR_LOG_ADD_PLAYER_GROUP, args);
network_append_server_log(log_msg);
}
}break;
case 1:{ // remove group
@ -2417,6 +2490,18 @@ void game_command_modify_groups(sint32 *eax, sint32 *ebx, sint32 *ecx, sint32 *e
}
}
if (*ebx & GAME_COMMAND_FLAG_APPLY) {
// Log remove player group event
NetworkPlayer* game_command_player = gNetwork.GetPlayerByID(game_command_playerid);
NetworkGroup* group = gNetwork.GetGroupByID(groupid);
char* groupName = (char *)group->GetName().c_str();
char log_msg[256];
const char * args[2] = {
(char *) game_command_player->Name.c_str(),
groupName
};
format_string(log_msg, 256, STR_LOG_REMOVE_PLAYER_GROUP, args);
network_append_server_log(log_msg);
gNetwork.RemoveGroup(groupid);
}
}break;
@ -2456,9 +2541,22 @@ void game_command_modify_groups(sint32 *eax, sint32 *ebx, sint32 *ecx, sint32 *e
group->ToggleActionPermission(index);
}
}
// Log edit player group permissions event
char log_msg[256];
const char * args[2] = {
(char *) player->Name.c_str(),
(char *) group->GetName().c_str()
};
format_string(log_msg, 256, STR_LOG_EDIT_PLAYER_GROUP_PERMISSIONS, args);
network_append_server_log(log_msg);
}
}break;
case 3:{ // set group name
NetworkGroup* group = gNetwork.GetGroupByID(groupid);
const char * oldName = group->GetName().c_str();
static char newName[128];
size_t nameChunkOffset = nameChunkIndex - 1;
if (nameChunkIndex == 0)
nameChunkOffset = 2;
@ -2486,8 +2584,18 @@ void game_command_modify_groups(sint32 *eax, sint32 *ebx, sint32 *ecx, sint32 *e
}
if (*ebx & GAME_COMMAND_FLAG_APPLY) {
NetworkGroup* group = gNetwork.GetGroupByID(groupid);
if (group) {
// Log edit player group name event
NetworkPlayer* player = gNetwork.GetPlayerByID(game_command_playerid);
char log_msg[256];
const char * args[3] = {
(char *) player->Name.c_str(),
oldName,
newName
};
format_string(log_msg, 256, STR_LOG_EDIT_PLAYER_GROUP_NAME, args);
network_append_server_log(log_msg);
group->SetName(newName);
}
}
@ -2501,6 +2609,17 @@ void game_command_modify_groups(sint32 *eax, sint32 *ebx, sint32 *ecx, sint32 *e
}
if (*ebx & GAME_COMMAND_FLAG_APPLY) {
gNetwork.SetDefaultGroup(groupid);
// Log edit default player group event
NetworkPlayer* player = gNetwork.GetPlayerByID(game_command_playerid);
NetworkGroup* group = gNetwork.GetGroupByID(groupid);
char log_msg[256];
const char * args[2] = {
(char *) player->Name.c_str(),
(char *) group->GetName().c_str()
};
format_string(log_msg, 256, STR_LOG_EDIT_DEFAULT_PLAYER_GROUP, args);
network_append_server_log(log_msg);
}
}break;
}
@ -2529,6 +2648,16 @@ void game_command_kick_player(sint32 *eax, sint32 *ebx, sint32 *ecx, sint32 *edx
networkUserManager->RemoveUser(player->KeyHash);
networkUserManager->Save();
}
// Log kick player event
NetworkPlayer* kicker = gNetwork.GetPlayerByID(game_command_playerid);
char log_msg[256];
const char * args[2] = {
(char *) player->Name.c_str(),
(char *) kicker->Name.c_str(),
};
format_string(log_msg, 256, STR_LOG_PLAYER_KICKED, args);
network_append_server_log(log_msg);
}
*ebx = 0;
}
@ -2657,6 +2786,11 @@ void network_append_chat_log(const utf8 *text)
gNetwork.AppendChatLog(text);
}
void network_append_server_log(const utf8 *text)
{
gNetwork.AppendServerLog(text);
}
static void network_get_keys_directory(utf8 *buffer, size_t bufferSize)
{
platform_get_user_directory(buffer, "keys", bufferSize);
@ -2729,11 +2863,13 @@ sint32 network_get_pickup_peep_old_x(uint8 playerid) { return _pickup_peep_old_x
void network_send_chat(const char* text) {}
void network_send_password(const char* password) {}
void network_close() {}
void network_set_env(void * env) {}
void network_shutdown_client() {}
void network_set_password(const char* password) {}
uint8 network_get_current_player_id() { return 0; }
sint32 network_get_current_player_group_index() { return 0; }
void network_append_chat_log(const utf8 *text) { }
void network_append_server_log(const utf8 *text) { }
const utf8 * network_get_server_name() { return nullptr; }
const utf8 * network_get_server_description() { return nullptr; }
const utf8 * network_get_server_greeting() { return nullptr; }

View File

@ -85,13 +85,15 @@ enum {
NETWORK_TICK_FLAG_CHECKSUMS = 1 << 0,
};
struct ObjectRepositoryItem;
interface IPlatformEnvironment;
struct ObjectRepositoryItem;
class Network
{
public:
Network();
~Network();
void SetEnvironment(IPlatformEnvironment * env);
bool Init();
void Close();
bool BeginClient(const char* host, uint16 port);
@ -120,10 +122,17 @@ public:
void SaveGroups();
void LoadGroups();
std::string BeginLog(const std::string &directory, const std::string &filenameFormat);
void AppendLog(const std::string &logPath, const std::string &s);
void BeginChatLog();
void AppendChatLog(const utf8 *text);
void AppendChatLog(const std::string &s);
void CloseChatLog();
void BeginServerLog();
void AppendServerLog(const std::string &s);
void CloseServerLog();
void Client_Send_TOKEN();
void Client_Send_AUTH(const char* name, const char* password, const char *pubkey, const char *sig, size_t sigsize);
void Client_Send_AUTH(const char* name, const char* password, const char *pubkey);
@ -217,9 +226,12 @@ private:
INetworkServerAdvertiser * _advertiser = nullptr;
uint32 server_connect_time = 0;
uint8 default_group = 0;
IStream * _chatLogStream = nullptr;
std::string _chatLogPath;
uint32 game_commands_processed_this_tick = 0;
std::string _chatLogPath;
std::string _chatLogFilenameFormat = "%Y%m%d-%H%M%S.txt";
std::string _serverLogPath;
std::string _serverLogFilenameFormat = "-%Y%m%d-%H%M%S.txt";
IPlatformEnvironment * _env;
void UpdateServer();
void UpdateClient();
@ -262,7 +274,7 @@ private:
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
sint32 network_init();
void network_set_env(void * env);
void network_close();
void network_shutdown_client();
sint32 network_begin_client(const char *host, sint32 port);
@ -316,6 +328,7 @@ void network_set_password(const char* password);
void network_print_error();
void network_append_chat_log(const utf8 *text);
void network_append_server_log(const utf8 *text);
const utf8 * network_get_server_name();
const utf8 * network_get_server_description();
const utf8 * network_get_server_greeting();

View File

@ -5594,6 +5594,22 @@ void game_command_set_ride_name(sint32 *eax, sint32 *ebx, sint32 *ecx, sint32 *e
}
if (*ebx & GAME_COMMAND_FLAG_APPLY) {
// Log ride rename command if we are in multiplayer and logging is enabled
if ((network_get_mode() == NETWORK_MODE_CLIENT || network_get_mode() == NETWORK_MODE_SERVER) && gConfigNetwork.log_server_actions) {
// Get player name
int player_index = network_get_player_index(game_command_playerid);
const char* player_name = network_get_player_name(player_index);
char log_msg[256];
char* args[3] = {
(char *) player_name,
oldName,
newName
};
format_string(log_msg, 256, STR_LOG_RIDE_NAME, args);
network_append_server_log(log_msg);
}
if (ride->overall_view != (uint16)-1) {
rct_xyz16 coord;
coord.x = (ride->overall_view & 0xFF) * 32 + 16;
@ -6158,6 +6174,10 @@ foundRideEntry:
ride_set_vehicle_colours_to_random_preset(ride, 0xFF & (*outRideColour >> 8));
window_invalidate_by_class(WC_RIDE_LIST);
// Log ride creation
int ebp = 1;
game_log_multiplayer_command(GAME_COMMAND_CREATE_RIDE, 0, 0, 0, &rideIndex, 0, &ebp);
gCommandExpenditureType = RCT_EXPENDITURE_TYPE_RIDE_CONSTRUCTION;
gCommandPosition.x = 0x8000;
return 0;

View File

@ -746,10 +746,10 @@ static void window_cheats_misc_mouseup(rct_window *w, rct_widgetindex widgetInde
game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_RESETDATE, 0, GAME_COMMAND_CHEAT, 0, 0);
break;
case WIDX_FAST_STAFF:
game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_SETSTAFFSPEED, 0xFF, GAME_COMMAND_CHEAT, 0, 0);
game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_SETSTAFFSPEED, CHEATS_STAFF_FAST_SPEED, GAME_COMMAND_CHEAT, 0, 0);
break;
case WIDX_NORMAL_STAFF:
game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_SETSTAFFSPEED, 0x60, GAME_COMMAND_CHEAT, 0, 0);
game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_SETSTAFFSPEED, CHEATS_STAFF_NORMAL_SPEED, GAME_COMMAND_CHEAT, 0, 0);
break;
case WIDX_PARK_PARAMETERS:
window_editor_scenario_options_open();

View File

@ -105,7 +105,7 @@ static void window_ride_demolish_mouseup(rct_window *w, rct_widgetindex widgetIn
switch (widgetIndex) {
case WIDX_DEMOLISH:
gGameCommandErrorTitle = STR_CANT_DEMOLISH_RIDE;
game_do_command(0, 1, 0, w->number, GAME_COMMAND_DEMOLISH_RIDE, 0, 0);
game_do_command(0, 1, 0, w->number, GAME_COMMAND_DEMOLISH_RIDE, 0, 1); // Set ebp to 1 to be used to log demolish from window prompt
break;
case WIDX_CANCEL:
case WIDX_CLOSE:

View File

@ -52,6 +52,7 @@ enum WINDOW_MULTIPLAYER_WIDGET_IDX {
WIDX_PERMISSIONS_LIST,
WIDX_LOG_CHAT_CHECKBOX = 8,
WIDX_LOG_SERVER_ACTIONS_CHECKBOX,
WIDX_KNOWN_KEYS_ONLY_CHECKBOX,
};
@ -92,7 +93,8 @@ static rct_widget window_multiplayer_groups_widgets[] = {
static rct_widget window_multiplayer_options_widgets[] = {
MAIN_MULTIPLAYER_WIDGETS,
{ WWT_CHECKBOX, 1, 3, 297, 50, 61, STR_LOG_CHAT, STR_LOG_CHAT_TIP },
{ WWT_CHECKBOX, 1, 3, 297, 64, 75, STR_ALLOW_KNOWN_KEYS_ONLY, STR_ALLOW_KNOWN_KEYS_ONLY_TIP },
{ WWT_CHECKBOX, 1, 3, 297, 64, 75, STR_LOG_SERVER_ACTIONS, STR_LOG_SERVER_ACTIONS_TIP },
{ WWT_CHECKBOX, 1, 3, 297, 78, 89, STR_ALLOW_KNOWN_KEYS_ONLY, STR_ALLOW_KNOWN_KEYS_ONLY_TIP },
{ WIDGETS_END }
};
@ -107,7 +109,7 @@ const uint64 window_multiplayer_page_enabled_widgets[] = {
(1 << WIDX_CLOSE) | (1 << WIDX_TAB1) | (1 << WIDX_TAB2) | (1 << WIDX_TAB3) | (1 << WIDX_TAB4),
(1 << WIDX_CLOSE) | (1 << WIDX_TAB1) | (1 << WIDX_TAB2) | (1 << WIDX_TAB3) | (1 << WIDX_TAB4),
(1 << WIDX_CLOSE) | (1 << WIDX_TAB1) | (1 << WIDX_TAB2) | (1 << WIDX_TAB3) | (1 << WIDX_TAB4) | (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),
(1 << WIDX_CLOSE) | (1 << WIDX_TAB1) | (1 << WIDX_TAB2) | (1 << WIDX_TAB3) | (1 << WIDX_TAB4) | (1 << WIDX_LOG_CHAT_CHECKBOX) | (1 << WIDX_KNOWN_KEYS_ONLY_CHECKBOX),
(1 << WIDX_CLOSE) | (1 << WIDX_TAB1) | (1 << WIDX_TAB2) | (1 << WIDX_TAB3) | (1 << WIDX_TAB4) | (1 << WIDX_LOG_CHAT_CHECKBOX) | (1 << WIDX_LOG_SERVER_ACTIONS_CHECKBOX) | (1 << WIDX_KNOWN_KEYS_ONLY_CHECKBOX),
};
static uint8 _selectedGroup = 0;
@ -918,6 +920,10 @@ static void window_multiplayer_options_mouseup(rct_window *w, rct_widgetindex wi
gConfigNetwork.log_chat = !gConfigNetwork.log_chat;
config_save_default();
break;
case WIDX_LOG_SERVER_ACTIONS_CHECKBOX:
gConfigNetwork.log_server_actions = !gConfigNetwork.log_server_actions;
config_save_default();
break;
case WIDX_KNOWN_KEYS_ONLY_CHECKBOX:
gConfigNetwork.known_keys_only = !gConfigNetwork.known_keys_only;
config_save_default();
@ -947,6 +953,7 @@ static void window_multiplayer_options_invalidate(rct_window *w)
}
widget_set_checkbox_value(w, WIDX_LOG_CHAT_CHECKBOX, gConfigNetwork.log_chat);
widget_set_checkbox_value(w, WIDX_LOG_SERVER_ACTIONS_CHECKBOX, gConfigNetwork.log_server_actions);
widget_set_checkbox_value(w, WIDX_KNOWN_KEYS_ONLY_CHECKBOX, gConfigNetwork.known_keys_only);
}

View File

@ -25,6 +25,7 @@
#include "../management/marketing.h"
#include "../management/news_item.h"
#include "../management/research.h"
#include "../network/network.h"
#include "../peep/peep.h"
#include "../peep/staff.h"
#include "../rct2.h"
@ -840,6 +841,22 @@ void game_command_set_park_name(sint32 *eax, sint32 *ebx, sint32 *ecx, sint32 *e
}
if (*ebx & GAME_COMMAND_FLAG_APPLY) {
// Log park rename command if we are in multiplayer and logging is enabled
if ((network_get_mode() == NETWORK_MODE_CLIENT || network_get_mode() == NETWORK_MODE_SERVER) && gConfigNetwork.log_server_actions) {
// Get player name
int player_index = network_get_player_index(game_command_playerid);
const char* player_name = network_get_player_name(player_index);
char log_msg[256];
char* args[3] = {
(char *) player_name,
oldName,
newName
};
format_string(log_msg, 256, STR_LOG_PARK_NAME, args);
network_append_server_log(log_msg);
}
// Free the old ride name
user_string_free(gParkName);
gParkName = newUserStringId;