1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-06 06:32:56 +01:00

Improve chat subscription

This commit is contained in:
Ted John
2020-02-10 23:33:00 +00:00
parent 0e8c627324
commit c8fbc2e529
4 changed files with 80 additions and 12 deletions

View File

@@ -43,6 +43,11 @@ export type HookType =
"interval.tick" | "interval.day" |
"network.chat" | "network.action" | "network.join" | "network.leave";
export interface NetworkChatEventArgs {
player: number;
message: string;
}
export interface Context {
/**
* The user's current configuration.
@@ -68,6 +73,7 @@ export interface Context {
* Subscribes to the given hook.
*/
subscribe(hook: HookType, callback: Function): IDisposable;
subscribe(hook: "network.chat", callback: (e: NetworkChatEventArgs) => void): IDisposable;
}
export interface IntentDesc
@@ -401,7 +407,7 @@ export interface Network {
getGroup(index: number): PlayerGroup;
setGroups(groups: PlayerGroup[]): void;
getPlayer(index: number): Player;
kickPlayer(index: number): Player;
kickPlayer(index: number): void;
sendMessage(message: string): void;
sendMessage(message: string, players: number[]): void;
}

View File

@@ -2822,6 +2822,10 @@ void Network::Client_Handle_CHAT([[maybe_unused]] NetworkConnection& connection,
void Network::Server_Handle_CHAT(NetworkConnection& connection, NetworkPacket& packet)
{
auto szText = packet.ReadString();
if (szText == nullptr || szText[0] == '\0')
return;
if (connection.Player)
{
NetworkGroup* group = GetGroupByID(connection.Player->Group);
@@ -2830,19 +2834,44 @@ void Network::Server_Handle_CHAT(NetworkConnection& connection, NetworkPacket& p
return;
}
}
const char* text = packet.ReadString();
if (text)
std::string text = szText;
if (connection.Player != nullptr)
{
auto& hookEngine = GetContext()->GetScriptEngine().GetHookEngine();
hookEngine.Call(OpenRCT2::Scripting::HOOK_TYPE::NETWORK_CHAT, {
{ "player", (int32_t)connection.Player->Id },
{ "message", std::string(text) }
});
if (hookEngine.HasSubscriptions(OpenRCT2::Scripting::HOOK_TYPE::NETWORK_CHAT))
{
auto ctx = GetContext()->GetScriptEngine().GetContext();
const char* formatted = FormatChat(connection.Player, text);
chat_history_add(formatted);
Server_Send_CHAT(formatted);
// Create event args object
auto objIdx = duk_push_object(ctx);
duk_push_number(ctx, (int32_t)connection.Player->Id);
duk_put_prop_string(ctx, objIdx, "player");
duk_push_string(ctx, text.c_str());
duk_put_prop_string(ctx, objIdx, "message");
auto e = DukValue::take_from_stack(ctx);
// Call the subscriptions
hookEngine.Call(OpenRCT2::Scripting::HOOK_TYPE::NETWORK_CHAT, e);
// Update text from object if subscriptions changed it
if (e["message"].type() != DukValue::Type::STRING)
{
// Subscription set text to non-string, do not relay message
return;
}
text = e["message"].as_string();
if (text.empty())
{
// Subscription set text to empty string, do not relay message
return;
}
}
}
const char* formatted = FormatChat(connection.Player, text.c_str());
chat_history_add(formatted);
Server_Send_CHAT(formatted);
}
void Network::Client_Handle_GAME_ACTION([[maybe_unused]] NetworkConnection& connection, NetworkPacket& packet)
@@ -3582,7 +3611,8 @@ GameActionResult::Ptr network_kick_player(NetworkPlayerId_t playerId, bool isExe
NetworkPlayer* player = gNetwork.GetPlayerByID(playerId);
if (player == nullptr)
{
// Player might be already removed by the PLAYERLIST command, need to refactor non-game commands executing too early.
// Player might be already removed by the PLAYERLIST command, need to refactor non-game commands executing too
// early.
return std::make_unique<GameActionResult>(GA_ERROR::UNKNOWN, STR_NONE);
}

View File

@@ -87,6 +87,12 @@ void HookEngine::UnsubscribeAll()
}
}
bool HookEngine::HasSubscriptions(HOOK_TYPE type) const
{
auto& hookList = GetHookList(type);
return !hookList.Hooks.empty();
}
void HookEngine::Call(HOOK_TYPE type)
{
auto& hookList = GetHookList(type);
@@ -101,6 +107,23 @@ void HookEngine::Call(HOOK_TYPE type)
}
}
void HookEngine::Call(HOOK_TYPE type, DukValue args)
{
auto& hookList = GetHookList(type);
for (auto& hook : hookList.Hooks)
{
ScriptExecutionInfo::PluginScope scope(_execInfo, hook.Owner);
const auto& function = hook.Function;
auto ctx = function.context();
function.push();
args.push();
duk_pcall(ctx, 1);
duk_pop(ctx);
}
}
void HookEngine::Call(HOOK_TYPE type, const std::initializer_list<std::pair<std::string_view, std::any>>& args)
{
auto& hookList = GetHookList(type);
@@ -141,3 +164,9 @@ HookList& HookEngine::GetHookList(HOOK_TYPE type)
auto index = static_cast<size_t>(type);
return _hookMap[index];
}
const HookList& HookEngine::GetHookList(HOOK_TYPE type) const
{
auto index = static_cast<size_t>(type);
return _hookMap[index];
}

View File

@@ -51,7 +51,7 @@ namespace OpenRCT2::Scripting
struct HookList
{
HOOK_TYPE Type;
HOOK_TYPE Type{};
std::vector<Hook> Hooks;
HookList()
@@ -80,10 +80,13 @@ namespace OpenRCT2::Scripting
void Unsubscribe(HOOK_TYPE type, uint32_t cookie);
void UnsubscribeAll(std::shared_ptr<const Plugin> owner);
void UnsubscribeAll();
bool HasSubscriptions(HOOK_TYPE type) const;
void Call(HOOK_TYPE type);
void Call(HOOK_TYPE type, DukValue args);
void Call(HOOK_TYPE type, const std::initializer_list<std::pair<std::string_view, std::any>>& args);
private:
HookList& GetHookList(HOOK_TYPE type);
const HookList& GetHookList(HOOK_TYPE type) const;
};
} // namespace OpenRCT2::Scripting