diff --git a/distribution/openrct2.d.ts b/distribution/openrct2.d.ts index 7e97a2eb31..7e88986af0 100644 --- a/distribution/openrct2.d.ts +++ b/distribution/openrct2.d.ts @@ -147,8 +147,8 @@ export interface CorruptElement extends TileElement { } export interface Tile { - x: number; - y: number; + readonly x: number; + readonly y: number; elements: TileElement[]; getElement(index: number): TileElement; @@ -162,7 +162,7 @@ export interface Ride { totalCustomers: number; } -export type TileElementType = +export type ThingType = "car" | "duck" | "peep"; export interface Thing { @@ -177,9 +177,9 @@ export interface Thing { } export interface Map { - size: { x: number; y: number; }; - rides: number; - things: number; + readonly size: { x: number; y: number; }; + readonly rides: number; + readonly things: number; getRide(id: number): Ride; getTile(x: number, y: number): Tile; @@ -253,9 +253,9 @@ export interface WindowDesc { } export interface Ui { - width: number; - height: number; - windows: number; + readonly width: number; + readonly height: number; + readonly windows: number; getWindow(id: number): Window; getWindow(classification: string, id?: number): Window; @@ -265,15 +265,65 @@ export interface Ui { } export interface Player { + readonly id: number; + readonly name: string; + group: number; + readonly ping: number; + readonly commandsRan: number; + readonly moneySpent: number; +} + +export type PermissionType = + "chat" | + "terraform" | + "set_water_level" | + "toggle_pause" | + "create_ride" | + "remove_ride" | + "build_ride" | + "ride_properties" | + "scenery" | + "path" | + "clear_landscape" | + "guest" | + "staff" | + "park_properties" | + "park_funding" | + "kick_player" | + "modify_groups" | + "set_player_group" | + "cheat" | + "toggle_scenery_cluster" | + "passwordless_login" | + "modify_tile" | + "edit_scenario_options"; + +export interface PlayerGroup { + readonly id: number; name: string; + permissions: PermissionType[]; +} + +export interface ServerInfo { + readonly name: string; + readonly description: string; + readonly greeting: string; + readonly providerName: string; + readonly providerEmail: string; + readonly providerWebsite: string; } export interface Network { - players: number; + readonly groups: number; + readonly players: number; + defaultGroup: number; + getServerInfo(): ServerInfo; + getGroup(index: number): PlayerGroup; + setGroups(groups: PlayerGroup[]): void; getPlayer(index: number): Player; - sendMessage(message: string); - sendMessage(players: number[], message: string); + sendMessage(message: string): void; + sendMessage(players: number[], message: string): void; } declare global { diff --git a/src/openrct2/scripting/ScNetwork.hpp b/src/openrct2/scripting/ScNetwork.hpp index 4de87192af..ea74774ebd 100644 --- a/src/openrct2/scripting/ScNetwork.hpp +++ b/src/openrct2/scripting/ScNetwork.hpp @@ -9,11 +9,132 @@ #pragma once +#include "../actions/NetworkModifyGroupAction.hpp" +#include "../actions/PlayerSetGroupAction.hpp" +#include "../network/NetworkAction.h" #include "../network/network.h" #include "Duktape.hpp" namespace OpenRCT2::Scripting { + class ScPlayerGroup + { + private: + int32_t _id; + + public: + ScPlayerGroup(int32_t id) + : _id(id) + { + } + + int32_t id_get() + { + return _id; + } + + std::string name_get() + { + auto index = network_get_group_index(_id); + if (index == -1) + return {}; + return network_get_group_name(index); + } + void name_set(std::string value) + { + auto action = NetworkModifyGroupAction(ModifyGroupType::SetName, _id, value); + GameActions::Execute(&action); + } + + std::vector permissions_get() + { + auto index = network_get_group_index(_id); + if (index == -1) + return {}; + + // Create array of permissions + std::vector result; + auto permissionIndex = 0; + for (const auto& action : NetworkActions::Actions) + { + if (network_can_perform_action(index, permissionIndex)) + { + auto p = TransformPermissionKeyToJS(action.PermissionName); + result.push_back(p); + } + permissionIndex++; + } + return result; + } + void permissions_set(std::vector value) + { + auto groupIndex = network_get_group_index(_id); + if (groupIndex == -1) + return; + + // First clear all permissions + auto networkAction = NetworkModifyGroupAction( + ModifyGroupType::SetPermissions, _id, "", 0, PermissionState::ClearAll); + GameActions::Execute(&networkAction); + + std::vector enabledPermissions; + enabledPermissions.resize(NetworkActions::Actions.size()); + for (const auto& p : value) + { + auto permissionName = TransformPermissionKeyToInternal(p); + + auto permissionIndex = 0; + for (const auto& action : NetworkActions::Actions) + { + if (action.PermissionName == permissionName) + { + enabledPermissions[permissionIndex] = true; + } + permissionIndex++; + } + } + + for (size_t i = 0; i < enabledPermissions.size(); i++) + { + auto toggle = (enabledPermissions[i] != (network_can_perform_action(groupIndex, (uint32_t)i) != 0)); + if (toggle) + { + auto networkAction2 = NetworkModifyGroupAction( + ModifyGroupType::SetPermissions, _id, "", (uint32_t)i, PermissionState::Toggle); + GameActions::Execute(&networkAction2); + } + } + } + + static void Register(duk_context* ctx) + { + dukglue_register_property(ctx, &ScPlayerGroup::id_get, nullptr, "id"); + dukglue_register_property(ctx, &ScPlayerGroup::name_get, &ScPlayerGroup::name_set, "name"); + dukglue_register_property(ctx, &ScPlayerGroup::permissions_get, &ScPlayerGroup::permissions_set, "permissions"); + } + + private: + std::string TransformPermissionKeyToJS(const std::string& s) + { + auto result = s.substr(11); + for (auto& c : result) + { + c = std::tolower(c); + } + return result; + } + + std::string TransformPermissionKeyToInternal(const std::string& s) + { + auto result = "PERMISSION_" + s; + for (auto& c : result) + { + c = std::toupper(c); + } + return result; + } + }; + class ScPlayer { private: @@ -38,10 +159,51 @@ namespace OpenRCT2::Scripting return network_get_player_name(index); } + int32_t group_get() + { + auto index = network_get_player_index(_id); + if (index == -1) + return {}; + return network_get_player_group(index); + } + void group_set(int32_t value) + { + auto playerSetGroupAction = PlayerSetGroupAction(_id, value); + GameActions::Execute(&playerSetGroupAction); + } + + int32_t ping_get() + { + auto index = network_get_player_index(_id); + if (index == -1) + return {}; + return network_get_player_ping(index); + } + + int32_t commandsRan_get() + { + auto index = network_get_player_index(_id); + if (index == -1) + return {}; + return network_get_player_commands_ran(index); + } + + int32_t moneySpent_get() + { + auto index = network_get_player_index(_id); + if (index == -1) + return {}; + return network_get_player_money_spent(index); + } + static void Register(duk_context* ctx) { dukglue_register_property(ctx, &ScPlayer::id_get, nullptr, "id"); dukglue_register_property(ctx, &ScPlayer::name_get, nullptr, "name"); + dukglue_register_property(ctx, &ScPlayer::group_get, &ScPlayer::group_set, "group"); + dukglue_register_property(ctx, &ScPlayer::ping_get, nullptr, "ping"); + dukglue_register_property(ctx, &ScPlayer::commandsRan_get, nullptr, "commandsRan"); + dukglue_register_property(ctx, &ScPlayer::moneySpent_get, nullptr, "moneySpent"); } }; @@ -60,6 +222,19 @@ namespace OpenRCT2::Scripting { return network_get_num_players(); } + int32_t groups_get() + { + return network_get_num_groups(); + } + int32_t defaultGroup_get() + { + return network_get_default_group(); + } + void defaultGroup_set(int32_t value) + { + auto action = NetworkModifyGroupAction(ModifyGroupType::SetDefault, value); + GameActions::Execute(&action); + } std::shared_ptr getPlayer(int32_t index) { @@ -72,10 +247,24 @@ namespace OpenRCT2::Scripting return nullptr; } + std::shared_ptr getGroup(int32_t index) + { + auto numGroups = network_get_num_groups(); + if (index < numGroups) + { + auto groupId = network_get_group_id(index); + return std::make_shared(groupId); + } + return nullptr; + } + static void Register(duk_context* ctx) { + dukglue_register_property(ctx, &ScNetwork::groups_get, nullptr, "groups"); dukglue_register_property(ctx, &ScNetwork::players_get, nullptr, "players"); + dukglue_register_property(ctx, &ScNetwork::defaultGroup_get, &ScNetwork::defaultGroup_set, "defaultGroup"); dukglue_register_method(ctx, &ScNetwork::getPlayer, "getPlayer"); + dukglue_register_method(ctx, &ScNetwork::getGroup, "getGroup"); } }; } // namespace OpenRCT2::Scripting diff --git a/src/openrct2/scripting/ScriptEngine.cpp b/src/openrct2/scripting/ScriptEngine.cpp index 842b6301d0..eaa1b41cf2 100644 --- a/src/openrct2/scripting/ScriptEngine.cpp +++ b/src/openrct2/scripting/ScriptEngine.cpp @@ -63,6 +63,7 @@ void ScriptEngine::Initialise() ScNetwork::Register(ctx); ScPark::Register(ctx); ScPlayer::Register(ctx); + ScPlayerGroup::Register(ctx); ScTile::Register(ctx); ScTileElement::Register(ctx); ScThing::Register(ctx);