mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2026-01-06 06:32:56 +01:00
Improve chat subscription
This commit is contained in:
8
distribution/openrct2.d.ts
vendored
8
distribution/openrct2.d.ts
vendored
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user