Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions skyrim-platform/src/platform_se/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,9 @@ if(NOT "${SKIP_SKYRIM_PLATFORM_BUILDING}")
target_include_directories(skyrim_platform PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/include)
target_link_libraries(skyrim_platform PRIVATE papyrus-vm-lib savefile skyrim_plugin_resources ui cef platform_lib viet serialization)
target_link_libraries(skyrim_platform PRIVATE node-embedder-api)

find_package(qjs CONFIG REQUIRED)
target_link_libraries(skyrim_platform PRIVATE qjs)

find_path(FRIDA_GUM_INCLUDE_DIR NAMES frida-gum.h)
find_library(FRIDA_GUM_LIBRARY NAMES frida-gum.lib)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ bool ConsoleComand_Execute(const RE::SCRIPT_PARAMETER* paramInfo,
}
};

SkyrimPlatform::GetSingleton()->PushAndWait(func);
SkyrimPlatform::GetSingleton()->RunTask(func);
if (iterator)
iterator->second.execute(paramInfo, scriptData, thisObj, containingObj,
scriptObj, locals, result, opcodeOffsetPtr);
Expand Down
83 changes: 77 additions & 6 deletions skyrim-platform/src/platform_se/skyrim_platform/EventsApi.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#include "EventsApi.h"
#include "EventManager.h"
#include "ExceptionPrinter.h"
#include "Handler.h"
#include "Hook.h"
#include "HookPattern.h"
#include "HooksStorage.h"
#include "IPC.h"
#include "InvalidArgumentException.h"
#include "JsUtils.h"
Expand Down Expand Up @@ -112,10 +112,14 @@ namespace {
Napi::Value CreateHookApi(Napi::Env env, std::shared_ptr<Hook> hookInfo)
{
auto hook = Napi::Object::New(env);

// hooks.sendAnimationEvent.add(sourceCode, [minSelfId], [maxSelfId],
// [pattern])
// sourceCode: string containing JS with enter(ctx) and/or leave(ctx)
hook.Set(
"add",
Napi::Function::New(env, [hookInfo](const Napi::CallbackInfo& info) {
auto handlerObj = NapiHelper::ExtractObject(info[0], "handlerObj");
auto source = NapiHelper::ExtractString(info[0], "source");

std::optional<double> minSelfId;
if (info[1].IsNumber()) {
Expand All @@ -133,9 +137,8 @@ Napi::Value CreateHookApi(Napi::Env env, std::shared_ptr<Hook> hookInfo)
pattern = HookPattern::Parse(s);
}

auto handler =
std::make_shared<Handler>(handlerObj, minSelfId, maxSelfId, pattern);
uint32_t id = hookInfo->AddHandler(handler);
uint32_t id =
hookInfo->AddScript(source, minSelfId, maxSelfId, std::move(pattern));

return Napi::Number::New(info.Env(), id);
}));
Expand All @@ -144,7 +147,7 @@ Napi::Value CreateHookApi(Napi::Env env, std::shared_ptr<Hook> hookInfo)
"remove",
Napi::Function::New(env, [hookInfo](const Napi::CallbackInfo& info) {
uint32_t toRemove = NapiHelper::ExtractUInt32(info[0], "toRemove");
hookInfo->RemoveHandler(toRemove);
hookInfo->RemoveScript(toRemove);
return info.Env().Undefined();
}));
return hook;
Expand All @@ -160,6 +163,74 @@ Napi::Value EventsApi::GetHooks(Napi::Env env)
return res;
}

Napi::Value EventsApi::GetHooksStorage(Napi::Env env)
{
auto obj = Napi::Object::New(env);

obj.Set("get", Napi::Function::New(env, [](const Napi::CallbackInfo& info) {
auto key = NapiHelper::ExtractString(info[0], "key");
auto val = HooksStorage::GetSingleton().Get(key);

Napi::Env env = info.Env();
if (std::holds_alternative<std::monostate>(val)) {
return env.Undefined();
}
if (std::holds_alternative<bool>(val)) {
return static_cast<Napi::Value>(
Napi::Boolean::New(env, std::get<bool>(val)));
}
if (std::holds_alternative<double>(val)) {
return static_cast<Napi::Value>(
Napi::Number::New(env, std::get<double>(val)));
}
if (std::holds_alternative<std::string>(val)) {
return static_cast<Napi::Value>(
Napi::String::New(env, std::get<std::string>(val)));
}
return env.Undefined();
}));

obj.Set("set", Napi::Function::New(env, [](const Napi::CallbackInfo& info) {
auto key = NapiHelper::ExtractString(info[0], "key");
Napi::Value val = info[1];

if (val.IsBoolean()) {
HooksStorage::GetSingleton().Set(key, val.As<Napi::Boolean>().Value());
} else if (val.IsNumber()) {
HooksStorage::GetSingleton().Set(key,
val.As<Napi::Number>().DoubleValue());
} else if (val.IsString()) {
HooksStorage::GetSingleton().Set(
key, val.As<Napi::String>().Utf8Value());
} else {
HooksStorage::GetSingleton().Set(key, std::monostate{});
}

return info.Env().Undefined();
}));

obj.Set("has", Napi::Function::New(env, [](const Napi::CallbackInfo& info) {
auto key = NapiHelper::ExtractString(info[0], "key");
return Napi::Boolean::New(info.Env(),
HooksStorage::GetSingleton().Has(key));
}));

obj.Set(
"erase", Napi::Function::New(env, [](const Napi::CallbackInfo& info) {
auto key = NapiHelper::ExtractString(info[0], "key");
HooksStorage::GetSingleton().Erase(key);
return info.Env().Undefined();
}));

obj.Set(
"clear", Napi::Function::New(env, [](const Napi::CallbackInfo& info) {
HooksStorage::GetSingleton().Clear();
return info.Env().Undefined();
}));

return obj;
}

namespace {
Napi::Value Subscribe(const Napi::CallbackInfo& info, bool runOnce = false)
{
Expand Down
2 changes: 2 additions & 0 deletions skyrim-platform/src/platform_se/skyrim_platform/EventsApi.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ void SendPapyrusEventEnter(uint32_t selfId,
void SendPapyrusEventLeave() noexcept;

Napi::Value GetHooks(Napi::Env env);
Napi::Value GetHooksStorage(Napi::Env env);

inline void Register(Napi::Env env, Napi::Object& exports)
{
Expand All @@ -29,6 +30,7 @@ inline void Register(Napi::Env env, Napi::Object& exports)
exports.Set("once",
Napi::Function::New(env, NapiHelper::WrapCppExceptions(Once)));
exports.Set("hooks", GetHooks(env));
exports.Set("hooksStorage", GetHooksStorage(env));
exports.Set(
"sendIpcMessage",
Napi::Function::New(env, NapiHelper::WrapCppExceptions(SendIpcMessage)));
Expand Down
9 changes: 0 additions & 9 deletions skyrim-platform/src/platform_se/skyrim_platform/Handler.h
Original file line number Diff line number Diff line change
@@ -1,13 +1,6 @@
#pragma once
#include "HookPattern.h"

// HandlerInfoPerThread structure is unique for each thread
struct HandlerInfoPerThread
{
std::shared_ptr<Napi::Reference<Napi::Object>> storage, context;
bool matchesCondition = false;
};

class Handler
{
public:
Expand All @@ -19,8 +12,6 @@ class Handler

bool Matches(uint32_t selfId, const std::string& eventName);

std::unordered_map<DWORD, HandlerInfoPerThread> perThread;

// Shared between threads
const Napi::Reference<Napi::Function> enter, leave;
const std::optional<HookPattern> pattern;
Expand Down
Loading
Loading