From 46109d95f6703ec681daf87f190b99413fb82865 Mon Sep 17 00:00:00 2001 From: Ji O Date: Mon, 23 Sep 2024 01:00:19 +0900 Subject: [PATCH] Add notificationJobs option --- src/config/config.cpp | 3 + src/config/config.hpp | 1 + src/hook.cpp | 370 +++--------------- src/hook.h | 7 - src/masterdb/masterdb.hpp | 49 +++ src/msgpack/msgpack_data.hpp | 260 +++++++----- .../DesktopNotificationManagerCompat.cpp | 120 +++++- .../DesktopNotificationManagerCompat.h | 6 +- src/openxr/openxr.cpp | 33 +- .../UnityEngine/Application.cpp | 8 + .../UnityEngine/Application.hpp | 1 + .../umamusume/Gallop/Cryptographer.cpp | 23 ++ .../umamusume/Gallop/Cryptographer.hpp | 11 + .../umamusume/Gallop/LocalPushDefine.hpp | 23 ++ .../Gallop/PushNotificationManager.cpp | 48 ++- .../Gallop/PushNotificationManager.hpp | 16 +- src/stdinclude.hpp | 27 +- src/string_utils.hpp | 25 ++ 18 files changed, 547 insertions(+), 484 deletions(-) create mode 100644 src/scripts/umamusume/Gallop/Cryptographer.cpp create mode 100644 src/scripts/umamusume/Gallop/Cryptographer.hpp diff --git a/src/config/config.cpp b/src/config/config.cpp index 84ac8d5..5350f88 100644 --- a/src/config/config.cpp +++ b/src/config/config.cpp @@ -68,6 +68,7 @@ namespace config bool unlock_live_chara = false; bool notification_tp = false; bool notification_rp = false; + bool notification_jobs = false; bool msgpack_notifier = false; bool msgpack_notifier_request = false; wstring msgpack_notifier_host = L"http://localhost:4693"; @@ -339,6 +340,8 @@ if (document.HasMember(L##_name_) && document[L##_name_].Is##_type_())\ GetValue("notificationRp", Bool, notification_rp); + GetValue("notificationJobs", Bool, notification_jobs); + GetValue("msgpackNotifier", Bool, msgpack_notifier); GetValue("msgpackNotifierRequest", Bool, msgpack_notifier_request); diff --git a/src/config/config.hpp b/src/config/config.hpp index df00c6a..6e565b7 100644 --- a/src/config/config.hpp +++ b/src/config/config.hpp @@ -98,6 +98,7 @@ namespace config extern bool unlock_live_chara; extern bool notification_tp; extern bool notification_rp; + extern bool notification_jobs; extern bool msgpack_notifier; extern bool msgpack_notifier_request; extern wstring msgpack_notifier_host; diff --git a/src/hook.cpp b/src/hook.cpp index 0137b53..9647807 100644 --- a/src/hook.cpp +++ b/src/hook.cpp @@ -71,6 +71,8 @@ #include "smtc/SystemMediaTransportControlsManager.hpp" +#include "scripts/ScriptInternal.hpp" + #include "scripts/mscorlib/System/Boolean.hpp" #include "scripts/mscorlib/System/Enum.hpp" #include "scripts/mscorlib/System/Int32.hpp" @@ -264,13 +266,8 @@ namespace bool isRequiredInitNotification = true; - Il2CppObject* GetSingletonInstance(Il2CppClass* klass); - bool (*uobject_IsNativeObjectAlive)(Il2CppObject* uObject); - template - Il2CppMulticastDelegate* CreateDelegateWithClass(Il2CppClass* klass, Il2CppObject* target, R(*fn)(Il2CppObject*, T...)); - void SetNotificationDisplayTime(float time) { if (!notification) @@ -991,11 +988,6 @@ namespace return UnityMain_hook(hInstance, hPrevInstance, lpCmdLine, nShowCmd); } - Il2CppObject* GetRuntimeType(const char* assemblyName, const char* namespaze, const char* klassName); - - template - Il2CppDelegate* CreateUnityActionStatic(R(*fn)()); - IUnityInterfaces* unityInterfaces; void* UnityPluginLoad_orig = nullptr; @@ -1280,51 +1272,6 @@ namespace wcout << trace()->chars << endl; } - Il2CppObject* GetRuntimeType(const char* assemblyName, const char* namespaze, const char* klassName) - { - return il2cpp_type_get_object(il2cpp_class_get_type(il2cpp_symbols::get_class(assemblyName, namespaze, klassName))); - } - - Il2CppObject* GetRuntimeType(Il2CppClass* klass) - { - return il2cpp_type_get_object(il2cpp_class_get_type(klass)); - } - - template - Il2CppClass* GetGenericClass(Il2CppObject* baseRuntimeType, Ts... runtimeTypes) - { - auto typeArray = reinterpret_cast(il2cpp_array_new(il2cpp_symbols::get_class("mscorlib.dll", "System", "Type"), sizeof...(runtimeTypes))); - - int i = 0; - for (const auto type : { runtimeTypes... }) - { - il2cpp_array_setref(typeArray, i, type); - i++; - } - - auto runtimeType = il2cpp_class_get_method_from_name_type(baseRuntimeType->klass, "MakeGenericType", 1)->methodPointer(baseRuntimeType, typeArray); - auto newType = runtimeType->type.type; - - return il2cpp_class_from_type(newType); - } - - template - const MethodInfo* GetGenericMethod(const MethodInfo* baseMethodInfo, Ts... runtimeTypes) - { - auto runtimeMethodInfo = il2cpp_method_get_object(baseMethodInfo, nullptr); - auto typeArray = reinterpret_cast(il2cpp_array_new(il2cpp_symbols::get_class("mscorlib.dll", "System", "Type"), sizeof...(runtimeTypes))); - - int i = 0; - for (const auto type : { runtimeTypes... }) - { - il2cpp_array_setref(typeArray, i, type); - i++; - } - - auto runtimeType = il2cpp_class_get_method_from_name_type(runtimeMethodInfo->object.klass, "MakeGenericMethod", 1)->methodPointer(&runtimeMethodInfo->object, typeArray); - return il2cpp_method_get_from_reflection(runtimeType); - } - template InvokerMethod GetInvokerMethod(R(*fn)(Il2CppObject*, T...), index_sequence) { @@ -1343,212 +1290,6 @@ namespace }); } - template - Il2CppMulticastDelegate* CreateDelegateWithClass(Il2CppClass* klass, Il2CppObject* target, R(*fn)(Il2CppObject*, T...)) - { - auto delegate = reinterpret_cast(il2cpp_object_new(klass)); - delegate->delegate.method_ptr = reinterpret_cast(fn); - - const auto methodInfo = new MethodInfo{}; - methodInfo->name = "AnonymousMethod"; - methodInfo->methodPointer = delegate->delegate.method_ptr; - methodInfo->klass = il2cpp_defaults.mono_method_class; - // methodInfo->invoker_method = GetInvokerMethod(fn, index_sequence_for{}); - methodInfo->slot = kInvalidIl2CppMethodSlot; - // methodInfo->flags = METHOD_ATTRIBUTE_PINVOKE_IMPL; - methodInfo->parameters_count = sizeof...(T); - - methodInfo->nativeFunction = reinterpret_cast(fn); - methodInfo->is_marshaled_from_native = true; - - delegate->delegate.method = reinterpret_cast(il2cpp_method_get_object(methodInfo, methodInfo->klass)); - // delegate->delegate.invoke_impl = il2cpp_class_get_method_from_name(klass, "Invoke", IgnoreNumberOfArguments)->invoker_method; - - delegate->delegates = il2cpp_array_new(klass, 1); - il2cpp_array_setref(delegate->delegates, 0, &delegate->delegate); - - auto object1 = reinterpret_cast(&delegate->delegate); - - il2cpp_gc_wbarrier_set_field(object1, reinterpret_cast(&(delegate->delegate).target), target); - - return delegate; - } - - template - Il2CppDelegate* CreateDelegate(Il2CppObject* target, R(*fn)(Il2CppObject*, T...)) - { - auto delegate = reinterpret_cast(il2cpp_object_new(il2cpp_defaults.delegate_class)); - delegate->method_ptr = reinterpret_cast(fn); - - const auto methodInfo = new MethodInfo{}; - methodInfo->name = "AnonymousMethod"; - methodInfo->methodPointer = delegate->method_ptr; - methodInfo->klass = il2cpp_defaults.mono_method_class; - // methodInfo->invoker_method = GetInvokerMethod(fn, index_sequence_for{}); - methodInfo->slot = kInvalidIl2CppMethodSlot; - // methodInfo->flags = METHOD_ATTRIBUTE_PINVOKE_IMPL; - methodInfo->parameters_count = sizeof...(T); - - methodInfo->nativeFunction = reinterpret_cast(fn); - methodInfo->is_marshaled_from_native = true; - - delegate->method = reinterpret_cast(il2cpp_method_get_object(methodInfo, methodInfo->klass)); - // delegate->invoke_impl = methodInfo->invoker_method; - - auto object = reinterpret_cast(delegate); - - il2cpp_gc_wbarrier_set_field(object, reinterpret_cast(&(delegate)->target), target); - - return delegate; - } - - template - Il2CppMulticastDelegate* CreateUnityAction(Il2CppObject* target, R(*fn)(Il2CppObject*, T...)) - { - const auto delegateClass = il2cpp_symbols::get_class("UnityEngine.CoreModule.dll", "UnityEngine.Events", "UnityAction"); - auto delegate = reinterpret_cast(il2cpp_object_new(delegateClass)); - delegate->delegate.method_ptr = reinterpret_cast(fn); - - const auto methodInfo = new MethodInfo{}; - methodInfo->name = "AnonymousMethod"; - methodInfo->methodPointer = delegate->delegate.method_ptr; - methodInfo->klass = il2cpp_defaults.mono_method_class; - // methodInfo->invoker_method = GetInvokerMethod(fn, index_sequence_for{}); - methodInfo->slot = kInvalidIl2CppMethodSlot; - // methodInfo->flags = METHOD_ATTRIBUTE_PINVOKE_IMPL; - methodInfo->parameters_count = sizeof...(T); - - methodInfo->nativeFunction = reinterpret_cast(fn); - methodInfo->is_marshaled_from_native = true; - - delegate->delegate.method = reinterpret_cast(il2cpp_method_get_object(methodInfo, methodInfo->klass)); - // delegate->delegate.invoke_impl = il2cpp_class_get_method_from_name(delegateClass, "Invoke", IgnoreNumberOfArguments)->invoker_method; - - delegate->delegates = il2cpp_array_new(delegateClass, 1); - il2cpp_array_setref(delegate->delegates, 0, &delegate->delegate); - - auto object1 = reinterpret_cast(&delegate->delegate); - - il2cpp_gc_wbarrier_set_field(object1, reinterpret_cast(&(delegate->delegate).target), target); - - return delegate; - } - - template - Il2CppReflectionMethod* GetRuntimeMethodInfo(R(*fn)(void*, T...)) - { - const auto methodInfo = new MethodInfo{}; - methodInfo->name = "AnonymousMethod"; - methodInfo->methodPointer = reinterpret_cast(fn); - methodInfo->klass = il2cpp_defaults.mono_method_class; - // methodInfo->invoker_method = GetInvokerMethod(fn, index_sequence_for{}); - methodInfo->slot = kInvalidIl2CppMethodSlot; - // methodInfo->flags = METHOD_ATTRIBUTE_PINVOKE_IMPL; - methodInfo->parameters_count = sizeof...(T); - - methodInfo->nativeFunction = reinterpret_cast(fn); - methodInfo->is_marshaled_from_native = true; - - return il2cpp_method_get_object(methodInfo, methodInfo->klass); - } - - template - Il2CppMulticastDelegate* CreateDelegateWithClassStatic(Il2CppClass* klass, R(*fn)(void*, T...)) - { - auto delegate = reinterpret_cast(il2cpp_object_new(klass)); - delegate->delegate.method_ptr = reinterpret_cast(fn); - - const auto methodInfo = new MethodInfo{}; - methodInfo->name = "AnonymousStaticMethod"; - methodInfo->methodPointer = delegate->delegate.method_ptr; - methodInfo->klass = il2cpp_defaults.mono_method_class; - // methodInfo->invoker_method = GetInvokerMethod(fn, index_sequence_for{}); - methodInfo->slot = kInvalidIl2CppMethodSlot; - methodInfo->flags = METHOD_ATTRIBUTE_STATIC; - methodInfo->parameters_count = sizeof...(T); - - methodInfo->nativeFunction = reinterpret_cast(fn); - methodInfo->is_marshaled_from_native = true; - - delegate->delegate.method = reinterpret_cast(il2cpp_method_get_object(methodInfo, methodInfo->klass)); - // delegate->delegate.invoke_impl = il2cpp_class_get_method_from_name(klass, "Invoke", IgnoreNumberOfArguments)->invoker_method; - - delegate->delegates = il2cpp_array_new(klass, 1); - il2cpp_array_setref(delegate->delegates, 0, &delegate->delegate); - - return delegate; - } - - template - Il2CppMulticastDelegate* CreateDelegateWithClassStatic(Il2CppClass* klass, R(*fn)()) - { - return CreateDelegateWithClassStatic(klass, reinterpret_cast(fn)); - } - - template - Il2CppDelegate* CreateDelegateStatic(R(*fn)(void*, T...)) - { - auto delegate = reinterpret_cast(il2cpp_object_new(il2cpp_defaults.delegate_class)); - delegate->method_ptr = reinterpret_cast(fn); - - const auto methodInfo = new MethodInfo{}; - methodInfo->name = "AnonymousStaticMethod"; - methodInfo->methodPointer = delegate->method_ptr; - methodInfo->klass = il2cpp_defaults.mono_method_class; - // methodInfo->invoker_method = GetInvokerMethod(fn, index_sequence_for{}); - methodInfo->slot = kInvalidIl2CppMethodSlot; - methodInfo->flags = METHOD_ATTRIBUTE_STATIC; - methodInfo->parameters_count = sizeof...(T); - - methodInfo->nativeFunction = reinterpret_cast(fn); - methodInfo->is_marshaled_from_native = true; - - delegate->method = reinterpret_cast(il2cpp_method_get_object(methodInfo, methodInfo->klass)); - // delegate->invoke_impl = methodInfo->invoker_method; - - return delegate; - } - - template - Il2CppDelegate* CreateDelegateStatic(R(*fn)()) - { - return CreateDelegateStatic(reinterpret_cast(fn)); - } - - template - Il2CppMulticastDelegate* CreateUnityActionStatic(R(*fn)(void*, T...)) - { - const auto delegateClass = il2cpp_symbols::get_class("UnityEngine.CoreModule.dll", "UnityEngine.Events", "UnityAction"); - auto delegate = reinterpret_cast(il2cpp_object_new(delegateClass)); - delegate->delegate.method_ptr = reinterpret_cast(fn); - - const auto methodInfo = new MethodInfo{}; - methodInfo->name = "AnonymousStaticMethod"; - methodInfo->methodPointer = delegate->delegate.method_ptr; - methodInfo->klass = il2cpp_defaults.mono_method_class; - // methodInfo->invoker_method = GetInvokerMethod(fn, index_sequence_for{}); - methodInfo->slot = kInvalidIl2CppMethodSlot; - methodInfo->flags = METHOD_ATTRIBUTE_STATIC; - methodInfo->parameters_count = sizeof...(T); - - methodInfo->nativeFunction = reinterpret_cast(fn); - methodInfo->is_marshaled_from_native = true; - - delegate->delegate.method = reinterpret_cast(il2cpp_method_get_object(methodInfo, methodInfo->klass)); - // delegate->delegate.invoke_impl = il2cpp_class_get_method_from_name(delegateClass, "Invoke", IgnoreNumberOfArguments)->invoker_method; - - delegate->delegates = il2cpp_array_new(delegateClass, 1); - il2cpp_array_setref(delegate->delegates, 0, &delegate->delegate); - - return delegate; - } - - template - Il2CppMulticastDelegate* CreateUnityActionStatic(R(*fn)()) - { - return CreateUnityActionStatic(reinterpret_cast(fn)); - } - Il2CppDelegate* GetButtonCommonOnClickDelegate(Il2CppObject* object) { if (!object) @@ -1610,40 +1351,6 @@ namespace return nullptr; } - Il2CppObject* GetSingletonInstance(Il2CppClass* klass) - { - if (!klass || !klass->parent) - { - return nullptr; - } - auto instanceField = il2cpp_class_get_field_from_name_wrap(klass, "_instance"); - if (!instanceField) - { - instanceField = il2cpp_class_get_field_from_name_wrap(klass, "instance"); - if (!instanceField) - { - return nullptr; - } - } - Il2CppObject* instance; - il2cpp_field_static_get_value(instanceField, &instance); - return instance; - } - - Il2CppObject* GetSingletonInstanceByMethod(Il2CppClass* klass) - { - if (!klass || !klass->parent) - { - return nullptr; - } - auto get_Instance = il2cpp_class_get_method_from_name_type(klass, "get_Instance", IgnoreNumberOfArguments); - if (get_Instance) - { - return get_Instance->methodPointer(); - } - return nullptr; - } - Il2CppObject* GetInt32Instance(int value) { return il2cpp_value_box(il2cpp_defaults.int32_class, &value); @@ -7172,9 +6879,12 @@ namespace for (int i = objects.size() - 1; i >= 0; i--) // for (int i = 0; i < objects.size(); i++) { - auto rectTransform = GetRectTransform(objects[i]); - il2cpp_class_get_method_from_name_type(rectTransform->klass, "SetParent", 2)->methodPointer(rectTransform, parentRectTransform, false); - il2cpp_class_get_method_from_name_type(rectTransform->klass, "SetAsFirstSibling", 0)->methodPointer(rectTransform); + if (objects[i]) + { + auto rectTransform = GetRectTransform(objects[i]); + il2cpp_class_get_method_from_name_type(rectTransform->klass, "SetParent", 2)->methodPointer(rectTransform, parentRectTransform, false); + il2cpp_class_get_method_from_name_type(rectTransform->klass, "SetAsFirstSibling", 0)->methodPointer(rectTransform); + } } } @@ -8695,6 +8405,8 @@ namespace AddOrSet(configDocument, L"notificationRp", GetOptionItemOnOffIsOn("notification_rp")); + AddOrSet(configDocument, L"notificationJobs", GetOptionItemOnOffIsOn("notification_jobs")); + AddOrSet(configDocument, L"dumpMsgPack", GetOptionItemOnOffIsOn("dump_msgpack")); AddOrSet(configDocument, L"dumpMsgPackRequest", GetOptionItemOnOffIsOn("dump_msgpack_request")); @@ -8797,6 +8509,17 @@ namespace DesktopNotificationManagerCompat::RemoveFromScheduleByTag(L"RP"); } + config::notification_jobs = configDocument[L"notificationJobs"].GetBool(); + + if (config::notification_jobs) + { + MsgPackData::RegisterJobsScheduledToast(); + } + else + { + DesktopNotificationManagerCompat::RemoveFromScheduleByGroup(L"Jobs"); + } + config::dump_msgpack = configDocument[L"dumpMsgPack"].GetBool(); config::dump_msgpack_request = configDocument[L"dumpMsgPackRequest"].GetBool(); @@ -8940,6 +8663,7 @@ namespace float uiAnimationScale = 1; bool notificationTp = false; bool notificationRp = false; + bool notificationJobs = false; bool dumpMsgPack = false; bool dumpMsgPackRequest = false; bool unlockLiveChara = false; @@ -9031,6 +8755,11 @@ namespace notificationRp = configDocument[L"notificationRp"].GetBool(); } + if (configDocument.HasMember(L"notificationJobs")) + { + notificationJobs = configDocument[L"notificationJobs"].GetBool(); + } + if (configDocument.HasMember(L"dumpMsgPack")) { dumpMsgPack = configDocument[L"dumpMsgPack"].GetBool(); @@ -9081,10 +8810,22 @@ namespace { freeFormUiScaleLandscape = configDocument[L"freeFormUiScaleLandscape"].GetFloat(); } - } + } vector graphicsQualityOptions = GetGraphicsQualityOptions(); + bool isJobsExist = false; + + try + { + GetTextIdByName(L"Jobs600005"); + isJobsExist = true; + } + catch (const Il2CppExceptionWrapper& ex) + { + wcout << ex.ex->message->chars << endl; + } + AddToLayout(m_Content, { GetOptionItemTitle(LocalifySettings::GetText("graphics")), @@ -9202,6 +8943,7 @@ namespace GetOptionItemTitle(localize_get_hook(GetTextIdByName(L"Outgame0293"))->chars), GetOptionItemOnOff("notification_tp", localize_get_hook(GetTextIdByName(L"Outgame0294"))->chars), GetOptionItemOnOff("notification_rp", localize_get_hook(GetTextIdByName(L"Outgame0437"))->chars), + isJobsExist ? GetOptionItemOnOff("notification_jobs", localize_get_hook(GetTextIdByName(L"Jobs600005"))->chars) : nullptr, GetOptionItemButton("show_notification", LocalifySettings::GetText("show_notification")), GetOptionItemAttention(localize_get_hook(GetTextIdByName(L"Outgame0297"))->chars), GetOptionItemTitle(LocalifySettings::GetText("title")), @@ -9267,6 +9009,10 @@ namespace { })); + SetOptionItemOnOffAction("notification_jobs", notificationJobs, *([](Il2CppObject*, bool isOn) + { + })); + SetOptionItemOnOffAction("dump_msgpack", dumpMsgPack, *([](Il2CppObject*, bool isOn) { })); @@ -9333,7 +9079,7 @@ namespace replaceAll(contentU8, "\\n", "\n"); auto content = u8_wide(contentU8); - DesktopNotificationManagerCompat::ShowToastNotification(title.data(), content.data(), MsgPackData::GetIconPath(leader_chara_id)->chars); + DesktopNotificationManagerCompat::ShowToastNotification(title.data(), content.data(), MsgPackData::GetIconPath(Gallop::LocalPushDefine::LocalPushType::Tp)->chars); })); SetOptionItemButtonAction("graphics_quality", *([](Il2CppObject*) @@ -9560,7 +9306,7 @@ namespace il2cpp_field_set_value(dialogData, ContentsObjectField, gameObject); settingsDialog = il2cpp_symbols::get_method_pointer("umamusume.dll", "Gallop", "DialogManager", "PushDialog", 1)(dialogData); - } + } void OpenLiveSettings() { @@ -12211,12 +11957,12 @@ namespace char* buf1 = reinterpret_cast(data) + kIl2CppSizeOfArray; memcpy(buf1, modified.data(), modified.size()); - } -} + } + } #endif return reinterpret_cast(UploadHandlerRaw_Create_orig)(self, data); - } + } void* DownloadHandler_InternalGetByteArray_orig = nullptr; @@ -12252,12 +11998,12 @@ namespace char* buf1 = reinterpret_cast(data) + kIl2CppSizeOfArray; memcpy(buf1, modified.data(), modified.size()); - } + } } #endif return data; - } + } void* HttpHelper_CompressRequest_orig = nullptr; @@ -12291,12 +12037,12 @@ namespace char* buf1 = reinterpret_cast(data) + kIl2CppSizeOfArray; memcpy(buf1, modified.data(), modified.size()); - } + } } #endif return reinterpret_cast(HttpHelper_CompressRequest_orig)(data); - } + } void* HttpHelper_DecompressResponse_orig = nullptr; @@ -12332,12 +12078,12 @@ namespace char* buf1 = reinterpret_cast(data) + kIl2CppSizeOfArray; memcpy(buf1, modified.data(), modified.size()); - } + } } #endif return data; - } + } Il2CppObject* GetRaceManager() { @@ -14641,7 +14387,7 @@ namespace }); } } -} + } void* MessageBoxW_orig = nullptr; @@ -14999,7 +14745,7 @@ bool init_hook_base() MH_CreateHook(InternetCrackUrlW, InternetCrackUrlW_hook, &InternetCrackUrlW_orig); MH_EnableHook(InternetCrackUrlW); #endif -} + } MH_CreateHook(FindFirstFileExW, FindFirstFileExW_hook, &FindFirstFileExW_orig); MH_EnableHook(FindFirstFileExW); diff --git a/src/hook.h b/src/hook.h index 93af091..71237b1 100644 --- a/src/hook.h +++ b/src/hook.h @@ -1,8 +1 @@ #include "il2cpp/il2cpp_symbols.hpp" - -namespace -{ - Il2CppObject* GetRuntimeType(const char* assemblyName, const char* namespaze, const char* klassName); - Il2CppObject* GetSingletonInstance(Il2CppClass* klass); - Il2CppObject* GetSingletonInstanceByMethod(Il2CppClass* klass); -} diff --git a/src/masterdb/masterdb.hpp b/src/masterdb/masterdb.hpp index 1deb46a..a57a6a4 100644 --- a/src/masterdb/masterdb.hpp +++ b/src/masterdb/masterdb.hpp @@ -1,4 +1,8 @@ #pragma once +#include +#include +#include + #include #include "il2cpp/il2cpp_symbols.hpp" @@ -93,4 +97,49 @@ namespace MasterDB return ""; } + + tuple GetJobsInfo(int rewardId) + { + if (!masterDB) + { + InitMasterDB(); + } + + auto statement = new SQLite::Statement(*masterDB, R"(SELECT place_id, genre_id FROM jobs_reward WHERE "id" = ?1)"); + statement->bind(1, rewardId); + + while (statement->executeStep()) + { + auto placeId = statement->getColumn(0).getInt(); + auto genreId = statement->getColumn(1).getInt(); + delete statement; + return tuple{ placeId, genreId }; + } + + delete statement; + + return tuple{ 0, 0 }; + } + + int GetJobsPlaceRaceTrackId(int placeId) + { + if (!masterDB) + { + InitMasterDB(); + } + + auto statement = new SQLite::Statement(*masterDB, R"(SELECT race_track_id FROM jobs_place WHERE "id" = ?1)"); + statement->bind(1, placeId); + + while (statement->executeStep()) + { + auto raceTrackId = statement->getColumn(0).getInt(); + delete statement; + return raceTrackId; + } + + delete statement; + + return 0; + } } diff --git a/src/msgpack/msgpack_data.hpp b/src/msgpack/msgpack_data.hpp index cfd3050..4631bab 100644 --- a/src/msgpack/msgpack_data.hpp +++ b/src/msgpack/msgpack_data.hpp @@ -18,11 +18,13 @@ #include "masterdb/masterdb.hpp" -#include "hook.h" +#include "string_utils.hpp" #include "notification/DesktopNotificationManagerCompat.h" +#include "scripts/ScriptInternal.hpp" #include "scripts/UnityEngine.CoreModule/UnityEngine/Rect.hpp" +#include "scripts/umamusume/Gallop/PushNotificationManager.hpp" using namespace std; using namespace msgpack11; @@ -35,19 +37,14 @@ namespace MsgPackData MsgPack::object tp_info; MsgPack::object rp_info; - Il2CppString* GetIconPath(int unitId) - { - auto newMethod = il2cpp_class_get_method_from_name_type(il2cpp_symbols::get_class("umamusume.dll", "Gallop", "PushNotificationManager"), "createFavIconFilePath", 2); - - if (newMethod) - { - return newMethod->methodPointer(nullptr, unitId, 2); - } + MsgPack::array jobs_going_info_array; - return il2cpp_class_get_method_from_name_type(il2cpp_symbols::get_class("umamusume.dll", "Gallop", "PushNotificationManager"), "createFavIconFilePath", 1)->methodPointer(nullptr, unitId); + Il2CppString* GetIconPath(Gallop::LocalPushDefine::LocalPushType localPushType) + { + return Gallop::PushNotificationManager::Instance().CreatePushIconFilePath(localPushType); } - void DumpTexture2D(int unitId, Il2CppObject* texture) + void DumpTexture2D(int unitId, Gallop::LocalPushDefine::LocalPushType localPushType, Il2CppObject* texture) { auto width = il2cpp_class_get_method_from_name_type(texture->klass, "get_width", 0)->methodPointer(texture); @@ -88,7 +85,7 @@ namespace MsgPackData return; } - auto wPath = GetIconPath(unitId); + auto wPath = GetIconPath(localPushType); wstring path = wPath->chars; auto parentDir = filesystem::path(path).parent_path(); @@ -100,50 +97,62 @@ namespace MsgPackData il2cpp_symbols::get_method_pointer*)>("mscorlib.dll", "System.IO", "File", "WriteAllBytes", 2)(il2cpp_string_new_utf16(path.data(), path.size()), pngData); } - void RegisterTPScheduledToast() + Il2CppObject* GetCharaPushIcon(int charaId, int dressId) { - if (!MsgPackData::user_info.empty() || !MsgPackData::tp_info.empty()) - { - int leader_chara_id = MsgPackData::user_info["leader_chara_id"].int_value(); - int leader_chara_dress_id = MsgPackData::user_info["leader_chara_dress_id"].int_value(); + auto old_str = to_string(dressId); + size_t n_zero = 6; + auto new_str = std::string(n_zero - std::min(n_zero, old_str.length()), '0') + old_str; - auto old_str = to_string(leader_chara_dress_id); - size_t n_zero = 6; - auto new_str = std::string(n_zero - std::min(n_zero, old_str.length()), '0') + old_str; + auto push_icon = "push_icon_"s + to_string(charaId) + "_" + new_str; + auto path = "chara/chr"s + to_string(charaId) + "/" + push_icon; + auto path2 = "chara/chr"s + to_string(charaId) + "/" + push_icon + "_01"; - auto push_icon = "push_icon_"s + to_string(leader_chara_id) + "_" + new_str; - auto path = "chara/chr"s + to_string(leader_chara_id) + "/" + push_icon; + auto loader = il2cpp_symbols::get_method_pointer("umamusume.dll", "Gallop", "AssetManager", "get_Loader", IgnoreNumberOfArguments)(); + auto asset = il2cpp_class_get_method_from_name_type(loader->klass, "LoadAssetHandle", 2)->methodPointer(loader, il2cpp_string_new(path.data()), false); + + if (!asset) + { + auto asset = il2cpp_class_get_method_from_name_type(loader->klass, "LoadAssetHandle", 2)->methodPointer(loader, il2cpp_string_new(path2.data()), false); - auto loader = il2cpp_symbols::get_method_pointer("umamusume.dll", "Gallop", "AssetManager", "get_Loader", IgnoreNumberOfArguments)(); - auto asset = il2cpp_class_get_method_from_name_type(loader->klass, "LoadAssetHandle", 2)->methodPointer(loader, il2cpp_string_new(path.data()), false); if (!asset) { - return; + return nullptr; } + } + + auto assetBundle = il2cpp_class_get_method_from_name_type(asset->klass, "get_assetBundle", 0)->methodPointer(asset); + if (!assetBundle) + { + return nullptr; + } + + auto texture2DType = reinterpret_cast(::GetRuntimeType("UnityEngine.CoreModule.dll", "UnityEngine", "Texture2D")); + return reinterpret_cast(il2cpp_resolve_icall("UnityEngine.AssetBundle::LoadAsset_Internal(System.String,System.Type)"))(assetBundle, il2cpp_string_new(push_icon.data()), texture2DType); + } + + void RegisterTPScheduledToast() + { + if (!MsgPackData::user_info.empty() || !MsgPackData::tp_info.empty()) + { + int leader_chara_id = MsgPackData::user_info["leader_chara_id"].int_value(); + int leader_chara_dress_id = MsgPackData::user_info["leader_chara_dress_id"].int_value(); - auto assetBundle = il2cpp_class_get_method_from_name_type(asset->klass, "get_assetBundle", 0)->methodPointer(asset); - if (!assetBundle) + auto texture2D = GetCharaPushIcon(leader_chara_id, leader_chara_dress_id); + if (!texture2D) { return; } - auto texture2DType = reinterpret_cast(::GetRuntimeType("UnityEngine.CoreModule.dll", "UnityEngine", "Texture2D")); - auto texture2D = reinterpret_cast(il2cpp_resolve_icall("UnityEngine.AssetBundle::LoadAsset_Internal(System.String,System.Type)"))(assetBundle, il2cpp_string_new(push_icon.data()), texture2DType); - - DumpTexture2D(leader_chara_id, texture2D); + DumpTexture2D(leader_chara_id, Gallop::LocalPushDefine::LocalPushType::Tp, texture2D); if (config::notification_tp) { - // unique_ptr history; - // DesktopNotificationManagerCompat::get_History(&history); - if ((!MsgPackData::user_info.empty() || !MsgPackData::tp_info.empty()) && config::notification_tp) { DesktopNotificationManagerCompat::RemoveFromScheduleByTag(L"TP"); auto title = u8_wide(MasterDB::GetTextData(6, leader_chara_id)); auto content = u8_wide(MasterDB::GetTextData(184, leader_chara_id)); - // history->RemoveGroupedTag(L"TP", L"Generic"); - DesktopNotificationManagerCompat::AddScheduledToastNotification(title.data(), content.data(), L"TP", GetIconPath(leader_chara_id)->chars, MsgPackData::tp_info["max_recovery_time"].int64_value() * 1000); + DesktopNotificationManagerCompat::AddScheduledToastNotification(title.data(), content.data(), L"TP", GetIconPath(Gallop::LocalPushDefine::LocalPushType::Tp)->chars, MsgPackData::tp_info["max_recovery_time"].int64_value() * 1000); } } } @@ -156,43 +165,78 @@ namespace MsgPackData int leader_chara_id = MsgPackData::user_info["leader_chara_id"].int_value(); int leader_chara_dress_id = MsgPackData::user_info["leader_chara_dress_id"].int_value(); - auto old_str = to_string(leader_chara_dress_id); - size_t n_zero = 6; - auto new_str = std::string(n_zero - std::min(n_zero, old_str.length()), '0') + old_str; - - auto push_icon = "push_icon_"s + to_string(leader_chara_id) + "_" + new_str; - auto path = "chara/chr"s + to_string(leader_chara_id) + "/" + push_icon; - - auto loader = il2cpp_symbols::get_method_pointer("umamusume.dll", "Gallop", "AssetManager", "get_Loader", IgnoreNumberOfArguments)(); - auto asset = il2cpp_class_get_method_from_name_type(loader->klass, "LoadAssetHandle", 2)->methodPointer(loader, il2cpp_string_new(path.data()), false); - if (!asset) - { - return; - } - - auto assetBundle = il2cpp_class_get_method_from_name_type(asset->klass, "get_assetBundle", 0)->methodPointer(asset); - if (!assetBundle) + auto texture2D = GetCharaPushIcon(leader_chara_id, leader_chara_dress_id); + if (!texture2D) { return; } - auto texture2DType = reinterpret_cast(::GetRuntimeType("UnityEngine.CoreModule.dll", "UnityEngine", "Texture2D")); - auto texture2D = reinterpret_cast(il2cpp_resolve_icall("UnityEngine.AssetBundle::LoadAsset_Internal(System.String,System.Type)"))(assetBundle, il2cpp_string_new(push_icon.data()), texture2DType); - - DumpTexture2D(leader_chara_id, texture2D); + DumpTexture2D(leader_chara_id, Gallop::LocalPushDefine::LocalPushType::Rp, texture2D); if (config::notification_rp) { - // unique_ptr history; - // DesktopNotificationManagerCompat::get_History(&history); - if ((!MsgPackData::user_info.empty() || !MsgPackData::rp_info.empty()) && config::notification_rp) { DesktopNotificationManagerCompat::RemoveFromScheduleByTag(L"RP"); auto title = u8_wide(MasterDB::GetTextData(6, leader_chara_id)); auto content = u8_wide(MasterDB::GetTextData(185, leader_chara_id)); - // history->RemoveGroupedTag(L"TP", L"Generic"); - DesktopNotificationManagerCompat::AddScheduledToastNotification(title.data(), content.data(), L"RP", GetIconPath(leader_chara_id)->chars, MsgPackData::rp_info["max_recovery_time"].int64_value() * 1000); + DesktopNotificationManagerCompat::AddScheduledToastNotification(title.data(), content.data(), L"RP", GetIconPath(Gallop::LocalPushDefine::LocalPushType::Rp)->chars, MsgPackData::rp_info["max_recovery_time"].int64_value() * 1000); + } + } + } + } + + void RegisterJobsScheduledToast() + { + if (!MsgPackData::jobs_going_info_array.empty()) + { + if (config::notification_rp) + { + if ((!MsgPackData::user_info.empty() || !MsgPackData::rp_info.empty()) && config::notification_rp) + { + DesktopNotificationManagerCompat::RemoveFromScheduleByGroup(L"Jobs"); + + for (MsgPack msgPack : MsgPackData::jobs_going_info_array) + { + MsgPack::object info = msgPack.object_items(); + MsgPack::array attend_card_info_array = info["attend_card_info_array"].array_items(); + MsgPack::object leader_card_info = attend_card_info_array[0].object_items(); + + int leader_chara_id = static_cast(floorf(leader_card_info["card_id"].int_value() * 0.01f)); + int leader_chara_dress_id = leader_card_info["dress_id"].int_value(); + + auto texture2D = GetCharaPushIcon(leader_chara_id, leader_chara_dress_id); + if (!texture2D) + { + continue; + } + + auto title = u8_wide(MasterDB::GetTextData(6, leader_chara_id)); + auto jobs_reward_id = info["jobs_reward_id"].int_value(); + auto local_push_type_index = info["local_push_type_index"].int_value(); + + DumpTexture2D(leader_chara_id, Gallop::LocalPushDefine::GetJobsLocalPushTypeByIndex(local_push_type_index), texture2D); + + auto jobsInfo = MasterDB::GetJobsInfo(jobs_reward_id); + auto raceTrackId = MasterDB::GetJobsPlaceRaceTrackId(std::get<0>(jobsInfo)); + auto raceTrack = u8_wide(MasterDB::GetTextData(34, raceTrackId)); + auto genre = u8_wide(MasterDB::GetTextData(357, std::get<1>(jobsInfo))); + auto content = u8_wide(MasterDB::GetTextData(360, leader_chara_id)); + + auto jobs_placename = L"\u3010" + raceTrack + L"\u3011" + genre; + replaceAll(content, LR"()", jobs_placename); + replaceAll(content, L"\\n", L"\n"); + + tm tm{}; + stringstream ss(info["end_time"].string_value()); + ss >> get_time(&tm, "%Y-%m-%d %H:%M:%S"); + chrono::system_clock::time_point tp = chrono::system_clock::from_time_t(mktime(&tm)); + int64_t end_time = chrono::duration_cast(tp.time_since_epoch()).count(); + + int notiId = Gallop::PushNotificationManager::Instance().MakeNotificationId(Gallop::LocalPushDefine::GetJobsLocalPushTypeByIndex(local_push_type_index), 0); + + DesktopNotificationManagerCompat::AddScheduledToastNotification(title.data(), content.data(), (L"Jobs" + to_wstring(notiId)).data(), GetIconPath(Gallop::LocalPushDefine::GetJobsLocalPushTypeByIndex(local_push_type_index))->chars, end_time, L"Jobs"); + } } } } @@ -227,7 +271,9 @@ namespace MsgPackData { MsgPack::object data = object["data"].object_items(); - if (data["tp_info"].is_object() || data["rp_info"].is_object() || data["user_info"].is_object()) + if (data["tp_info"].is_object() || data["rp_info"].is_object() || + data["jobs_load_info"].is_object() || data["jobs_going_info_array"].is_object() || + data["user_info"].is_object()) { int leader_chara_id; int leader_chara_dress_id; @@ -247,50 +293,88 @@ namespace MsgPackData MsgPackData::rp_info = data["rp_info"].object_items(); } - leader_chara_id = MsgPackData::user_info["leader_chara_id"].int_value(); - leader_chara_dress_id = MsgPackData::user_info["leader_chara_dress_id"].int_value(); - - auto old_str = to_string(leader_chara_dress_id); - size_t n_zero = 6; - auto new_str = std::string(n_zero - std::min(n_zero, old_str.length()), '0') + old_str; + if (data["jobs_load_info"].is_object()) + { + MsgPack::object jobs_load_info = data["jobs_load_info"].object_items(); + MsgPackData::jobs_going_info_array = jobs_load_info["jobs_going_info_array"].array_items(); + } - auto push_icon = "push_icon_"s + to_string(leader_chara_id) + "_" + new_str; - auto path = "chara/chr"s + to_string(leader_chara_id) + "/" + push_icon; + if (data["jobs_going_info_array"].is_array()) + { + MsgPackData::jobs_going_info_array = data["jobs_going_info_array"].array_items(); + } - auto loader = il2cpp_symbols::get_method_pointer("umamusume.dll", "Gallop", "AssetManager", "get_Loader", IgnoreNumberOfArguments)(); - auto asset = il2cpp_class_get_method_from_name_type(loader->klass, "LoadAssetHandle", 2)->methodPointer(loader, il2cpp_string_new(path.data()), false); + leader_chara_id = MsgPackData::user_info["leader_chara_id"].int_value(); + leader_chara_dress_id = MsgPackData::user_info["leader_chara_dress_id"].int_value(); - if (!asset) + auto texture2D = GetCharaPushIcon(leader_chara_id, leader_chara_dress_id); + if (!texture2D) { return; } - auto assetBundle = il2cpp_class_get_method_from_name_type(asset->klass, "get_assetBundle", 0)->methodPointer(asset); - - auto texture2DType = reinterpret_cast(::GetRuntimeType("UnityEngine.CoreModule.dll", "UnityEngine", "Texture2D")); - auto texture2D = reinterpret_cast(il2cpp_resolve_icall("UnityEngine.AssetBundle::LoadAsset_Internal(System.String,System.Type)"))(assetBundle, il2cpp_string_new(push_icon.data()), texture2DType); - - DumpTexture2D(leader_chara_id, texture2D); - - if (config::notification_tp || config::notification_rp) + if (config::notification_tp || config::notification_rp || config::notification_jobs) { - // unique_ptr history; - // DesktopNotificationManagerCompat::get_History(&history); - auto title = u8_wide(MasterDB::GetTextData(6, leader_chara_id)); if ((data["user_info"].is_object() || data["tp_info"].is_object()) && config::notification_tp) { + DumpTexture2D(leader_chara_id, Gallop::LocalPushDefine::LocalPushType::Tp, texture2D); DesktopNotificationManagerCompat::RemoveFromScheduleByTag(L"TP"); auto content = u8_wide(MasterDB::GetTextData(184, leader_chara_id)); - // history->RemoveGroupedTag(L"TP", L"Generic"); - DesktopNotificationManagerCompat::AddScheduledToastNotification(title.data(), content.data(), L"TP", GetIconPath(leader_chara_id)->chars, MsgPackData::tp_info["max_recovery_time"].int64_value() * 1000); + DesktopNotificationManagerCompat::AddScheduledToastNotification(title.data(), content.data(), L"TP", GetIconPath(Gallop::LocalPushDefine::LocalPushType::Tp)->chars, MsgPackData::tp_info["max_recovery_time"].int64_value() * 1000); } if ((data["user_info"].is_object() || data["rp_info"].is_object()) && config::notification_rp) { + DumpTexture2D(leader_chara_id, Gallop::LocalPushDefine::LocalPushType::Rp, texture2D); DesktopNotificationManagerCompat::RemoveFromScheduleByTag(L"RP"); auto content = u8_wide(MasterDB::GetTextData(185, leader_chara_id)); - // history->RemoveGroupedTag(L"RP", L"Generic"); - DesktopNotificationManagerCompat::AddScheduledToastNotification(title.data(), content.data(), L"RP", GetIconPath(leader_chara_id)->chars, MsgPackData::rp_info["max_recovery_time"].int64_value() * 1000); + DesktopNotificationManagerCompat::AddScheduledToastNotification(title.data(), content.data(), L"RP", GetIconPath(Gallop::LocalPushDefine::LocalPushType::Rp)->chars, MsgPackData::rp_info["max_recovery_time"].int64_value() * 1000); + } + if ((data["jobs_load_info"].is_object() || data["jobs_going_info_array"].is_array()) && config::notification_jobs) + { + DesktopNotificationManagerCompat::RemoveFromScheduleByGroup(L"Jobs"); + + for (MsgPack msgPack : MsgPackData::jobs_going_info_array) + { + MsgPack::object info = msgPack.object_items(); + MsgPack::array attend_card_info_array = info["attend_card_info_array"].array_items(); + MsgPack::object leader_card_info = attend_card_info_array[0].object_items(); + + int leader_chara_id = static_cast(floorf(leader_card_info["card_id"].int_value() * 0.01f)); + int leader_chara_dress_id = leader_card_info["dress_id"].int_value(); + + auto texture2D = GetCharaPushIcon(leader_chara_id, leader_chara_dress_id); + if (!texture2D) + { + continue; + } + + auto title = u8_wide(MasterDB::GetTextData(6, leader_chara_id)); + auto jobs_reward_id = info["jobs_reward_id"].int_value(); + auto local_push_type_index = info["local_push_type_index"].int_value(); + + DumpTexture2D(leader_chara_id, Gallop::LocalPushDefine::GetJobsLocalPushTypeByIndex(local_push_type_index), texture2D); + + auto jobsInfo = MasterDB::GetJobsInfo(jobs_reward_id); + auto raceTrackId = MasterDB::GetJobsPlaceRaceTrackId(std::get<0>(jobsInfo)); + auto raceTrack = u8_wide(MasterDB::GetTextData(34, raceTrackId)); + auto genre = u8_wide(MasterDB::GetTextData(357, std::get<1>(jobsInfo))); + auto content = u8_wide(MasterDB::GetTextData(360, leader_chara_id)); + + auto jobs_placename = L"\u3010" + raceTrack + L"\u3011" + genre; + replaceAll(content, LR"()", jobs_placename); + replaceAll(content, L"\\n", L"\n"); + + tm tm{}; + stringstream ss(info["end_time"].string_value()); + ss >> get_time(&tm, "%Y-%m-%d %H:%M:%S"); + chrono::system_clock::time_point tp = chrono::system_clock::from_time_t(mktime(&tm)); + int64_t end_time = chrono::duration_cast(tp.time_since_epoch()).count(); + + int notiId = Gallop::PushNotificationManager::Instance().MakeNotificationId(Gallop::LocalPushDefine::GetJobsLocalPushTypeByIndex(local_push_type_index), 0); + + DesktopNotificationManagerCompat::AddScheduledToastNotification(title.data(), content.data(), (L"Jobs" + to_wstring(notiId)).data(), GetIconPath(Gallop::LocalPushDefine::GetJobsLocalPushTypeByIndex(local_push_type_index))->chars, end_time, L"Jobs"); + } } } } diff --git a/src/notification/DesktopNotificationManagerCompat.cpp b/src/notification/DesktopNotificationManagerCompat.cpp index 03907f1..cbdced3 100644 --- a/src/notification/DesktopNotificationManagerCompat.cpp +++ b/src/notification/DesktopNotificationManagerCompat.cpp @@ -294,11 +294,12 @@ namespace DesktopNotificationManagerCompat return S_OK; } - ComPtr doc; - RETURN_IF_FAILED(CreateXmlDocumentFromString( - LR"( + wstring templateString = LR"( New Notification - )", &doc)); + )"; + + ComPtr doc; + RETURN_IF_FAILED(CreateXmlDocumentFromString(templateString.data(), &doc)); ComPtr notifier; RETURN_IF_FAILED(CreateToastNotifier(¬ifier)); @@ -341,20 +342,20 @@ namespace DesktopNotificationManagerCompat if (!iconPath) { - RETURN_IF_FAILED(CreateXmlDocumentFromString( - (LR"( + wstring templateString = LR"( )"s + title + LR"( )" + content + LR"( - )").data(), &doc)); + )"; + RETURN_IF_FAILED(CreateXmlDocumentFromString(templateString.data(), &doc)); } else { - RETURN_IF_FAILED(CreateXmlDocumentFromString( - (LR"( + wstring templateString = LR"( )" + title + LR"( )" + content + LR"( - )").data(), &doc)); + )"; + RETURN_IF_FAILED(CreateXmlDocumentFromString(templateString.data(), &doc)); } // Create the notifier @@ -380,19 +381,70 @@ namespace DesktopNotificationManagerCompat return notifier->Show(toast.Get()); } - HRESULT AddScheduledToastNotification(const wchar_t* title, const wchar_t* content, const wchar_t* tag, const wchar_t* iconPath, int64_t epoch) + HRESULT ShowToastNotification(const wchar_t* title, const wchar_t* content, const wchar_t* tag, const wchar_t* iconPath, bool removeHistory, bool suppressPopup) + { + RETURN_IF_FAILED(EnsureRegistered()); + + ComPtr doc; + + if (!iconPath) + { + wstring templateString = LR"( + )"s + title + LR"( + )" + content + LR"( + )"; + RETURN_IF_FAILED(CreateXmlDocumentFromString(templateString.data(), &doc)); + } + else + { + wstring templateString = LR"( + + )" + title + LR"( + )" + content + LR"( + )"; + RETURN_IF_FAILED(CreateXmlDocumentFromString(templateString.data(), &doc)); + } + + // Create the notifier + // Desktop apps must use the compat method to create the notifier. + ComPtr notifier; + RETURN_IF_FAILED(CreateToastNotifier(¬ifier)); + + if (removeHistory) + { + unique_ptr history; + RETURN_IF_FAILED(get_History(&history)); + history->RemoveGroupedTag(tag, L"Generic"); + } + + // Create the notification itself (using helper method from compat library) + ComPtr toast; + RETURN_IF_FAILED(CreateToastNotification(doc.Get(), &toast)); + + ComPtr toast2; + RETURN_IF_FAILED(toast.As(&toast2)); + + toast2.Get()->put_Group(HStringReference(L"Generic").Get()); + toast2.Get()->put_Tag(HStringReference(tag).Get()); + toast2.Get()->put_SuppressPopup(suppressPopup); + + return notifier->Show(toast.Get()); + } + + HRESULT AddScheduledToastNotification(const wchar_t* title, const wchar_t* content, const wchar_t* tag, const wchar_t* iconPath, int64_t epoch, const wchar_t* group) { RETURN_IF_FAILED(EnsureRegistered()); RETURN_IF_FAILED(PreRegisterIdentityLessApp()); - ComPtr doc; - RETURN_IF_FAILED(CreateXmlDocumentFromString( - (LR"( + wstring templateString = LR"( )" + title + LR"( )" + content + LR"( - )").data(), &doc)); + )"; + + ComPtr doc; + RETURN_IF_FAILED(CreateXmlDocumentFromString(templateString.data(), &doc)); // Create the notifier // Desktop apps must use the compat method to create the notifier. @@ -415,7 +467,7 @@ namespace DesktopNotificationManagerCompat ComPtr toast2; RETURN_IF_FAILED(toast.As(&toast2)); - toast2.Get()->put_Group(HStringReference(L"Generic").Get()); + toast2.Get()->put_Group(HStringReference(group).Get()); toast2.Get()->put_Tag(HStringReference(tag).Get()); return notifier->AddToSchedule(toast.Get()); @@ -457,6 +509,42 @@ namespace DesktopNotificationManagerCompat return S_OK; } + HRESULT RemoveFromScheduleByGroup(const wchar_t* group) + { + RETURN_IF_FAILED(EnsureRegistered()); + + // Create the notifier + // Desktop apps must use the compat method to create the notifier. + ComPtr notifier; + RETURN_IF_FAILED(CreateToastNotifier(¬ifier)); + + ABI::Windows::Foundation::Collections::IVectorView* toasts; + RETURN_IF_FAILED(notifier.Get()->GetScheduledToastNotifications(&toasts)); + + uint32_t size; + RETURN_IF_FAILED(toasts->get_Size(&size)); + for (int i = 0; i < size; i++) + { + ABI::IScheduledToastNotification* toast; + RETURN_IF_FAILED(toasts->GetAt(i, &toast)); + + ABI::IScheduledToastNotification2* toast2; + RETURN_IF_FAILED(toast->QueryInterface(&toast2)); + + HSTRING hGroup; + RETURN_IF_FAILED(toast2->get_Group(&hGroup)); + + auto group1 = WindowsGetStringRawBuffer(hGroup, nullptr); + + if (group1 == wstring(group)) + { + RETURN_IF_FAILED(notifier.Get()->RemoveFromSchedule(toast)); + } + } + + return S_OK; + } + HRESULT EnsureRegistered() { // If not registered AUMID yet diff --git a/src/notification/DesktopNotificationManagerCompat.h b/src/notification/DesktopNotificationManagerCompat.h index 370bd50..1c303c4 100644 --- a/src/notification/DesktopNotificationManagerCompat.h +++ b/src/notification/DesktopNotificationManagerCompat.h @@ -70,10 +70,14 @@ namespace DesktopNotificationManagerCompat HRESULT ShowToastNotification(const wchar_t* title, const wchar_t* content, const wchar_t* iconPath, bool suppressPopup = false); - HRESULT AddScheduledToastNotification(const wchar_t* title, const wchar_t* content, const wchar_t* tag, const wchar_t* iconPath, int64_t epoch); + HRESULT ShowToastNotification(const wchar_t* title, const wchar_t* content, const wchar_t* tag, const wchar_t* iconPath, bool removeHistory = false, bool suppressPopup = false); + + HRESULT AddScheduledToastNotification(const wchar_t* title, const wchar_t* content, const wchar_t* tag, const wchar_t* iconPath, int64_t epoch, const wchar_t* group = L"Generic"); HRESULT RemoveFromScheduleByTag(const wchar_t* tag); + HRESULT RemoveFromScheduleByGroup(const wchar_t* group); + /// /// Gets the DesktopNotificationHistoryCompat object. You must have called RegisterActivator first (and also RegisterAumidAndComServer if you're a classic Win32 app), or this will throw an exception. /// diff --git a/src/openxr/openxr.cpp b/src/openxr/openxr.cpp index c654c03..a55e320 100644 --- a/src/openxr/openxr.cpp +++ b/src/openxr/openxr.cpp @@ -6,6 +6,7 @@ #include "il2cpp/il2cpp-api-functions.hpp" #include "string_utils.hpp" +#include "scripts/ScriptInternal.hpp" #include "scripts/UnityEngine.CoreModule/UnityEngine/BeforeRenderHelper.hpp" namespace Unity @@ -333,34 +334,6 @@ namespace Unity } }; - template - Il2CppDelegate* CreateUnityActionStatic(R(*fn)(void*, T...)) - { - const auto delegateClass = il2cpp_symbols::get_class("UnityEngine.CoreModule.dll", "UnityEngine.Events", "UnityAction"); - auto delegate = reinterpret_cast(il2cpp_object_new(delegateClass)); - delegate->method_ptr = reinterpret_cast(fn); - - const auto methodInfo = new MethodInfo{}; - methodInfo->name = "AnonymousStaticMethod"; - methodInfo->methodPointer = delegate->method_ptr; - methodInfo->klass = il2cpp_symbols::get_class("mscorlib.dll", "System.Reflection", "MonoMethod"); - // methodInfo->invoker_method = GetInvokerMethod(fn, index_sequence_for{}); - methodInfo->slot = kInvalidIl2CppMethodSlot; - methodInfo->flags = METHOD_ATTRIBUTE_STATIC; - methodInfo->parameters_count = sizeof...(T); - - delegate->method = reinterpret_cast(il2cpp_method_get_object(methodInfo, methodInfo->klass)); - // delegate->invoke_impl = il2cpp_class_get_method_from_name(delegateClass, "Invoke", IgnoreNumberOfArguments)->invoker_method; - - return delegate; - } - - template - Il2CppDelegate* CreateUnityActionStatic(R(*fn)()) - { - return CreateUnityActionStatic(reinterpret_cast(fn)); - } - void OpenXR::InitLibrary(IUnityInterfaces* interfaces) { auto productName = il2cpp_resolve_icall_type("UnityEngine.Application::get_productName")()->chars; @@ -518,11 +491,11 @@ namespace Unity auto orderBlock = reinterpret_cast(il2cpp_object_new(orderClass)); orderBlock->order = 0; - orderBlock->callback = CreateUnityActionStatic(*([]() + orderBlock->callback = &CreateUnityActionStatic(*([]() { cout << "BeforeRender" << endl; Internal_PumpMessageLoop(); - })); + }))->delegate; il2cpp_array_setref(array2, array1->max_length, orderBlock); diff --git a/src/scripts/UnityEngine.CoreModule/UnityEngine/Application.cpp b/src/scripts/UnityEngine.CoreModule/UnityEngine/Application.cpp index 4f8bf78..fa2a28e 100644 --- a/src/scripts/UnityEngine.CoreModule/UnityEngine/Application.cpp +++ b/src/scripts/UnityEngine.CoreModule/UnityEngine/Application.cpp @@ -16,6 +16,8 @@ void* get_unityVersion_addr = nullptr; void* get_companyName_addr = nullptr; +void* get_persistentDataPath_addr = nullptr; + void* set_targetFrameRate_addr = nullptr; void* set_targetFrameRate_orig = nullptr; @@ -55,6 +57,7 @@ static void InitAddress() OpenURL_addr = il2cpp_symbols::get_method_pointer(ASSEMBLY_NAME, "UnityEngine", "Application", "OpenURL", 1); get_unityVersion_addr = il2cpp_resolve_icall("UnityEngine.Application::get_unityVersion()"); get_companyName_addr = il2cpp_resolve_icall("UnityEngine.Application::get_companyName()"); + get_persistentDataPath_addr = il2cpp_resolve_icall("UnityEngine.Application::get_persistentDataPath()"); set_targetFrameRate_addr = il2cpp_resolve_icall("UnityEngine.Application::set_targetFrameRate(System.Int32)"); } @@ -96,6 +99,11 @@ namespace UnityEngine return reinterpret_cast(get_companyName_addr)(); } + Il2CppString* Application::persistentDataPath() + { + return reinterpret_cast(get_persistentDataPath_addr)(); + } + void Application::targetFrameRate(int value) { reinterpret_cast(set_targetFrameRate_addr)(value); diff --git a/src/scripts/UnityEngine.CoreModule/UnityEngine/Application.hpp b/src/scripts/UnityEngine.CoreModule/UnityEngine/Application.hpp index c755995..705c37b 100644 --- a/src/scripts/UnityEngine.CoreModule/UnityEngine/Application.hpp +++ b/src/scripts/UnityEngine.CoreModule/UnityEngine/Application.hpp @@ -10,6 +10,7 @@ namespace UnityEngine static void OpenURL(Il2CppString* url); static Il2CppString* unityVersion(); static Il2CppString* companyName(); + static Il2CppString* persistentDataPath(); static void targetFrameRate(int value); static void Exit(int exitCode); diff --git a/src/scripts/umamusume/Gallop/Cryptographer.cpp b/src/scripts/umamusume/Gallop/Cryptographer.cpp new file mode 100644 index 0000000..76947df --- /dev/null +++ b/src/scripts/umamusume/Gallop/Cryptographer.cpp @@ -0,0 +1,23 @@ +#include "../umamusume.hpp" +#include "../../ScriptInternal.hpp" +#include "Cryptographer.hpp" + +void* MakeMd5_addr = nullptr; + +static void InitAddress() +{ + MakeMd5_addr = il2cpp_symbols::get_method_pointer(ASSEMBLY_NAME, "Gallop", "Cryptographer", "MakeMd5", 1); +} + +STATIC +{ + il2cpp_symbols::init_callbacks.emplace_back(InitAddress); +} + +namespace Gallop +{ + Il2CppString* Cryptographer::MakeMd5(Il2CppString* input) + { + return reinterpret_cast(MakeMd5_addr)(input); + } +} diff --git a/src/scripts/umamusume/Gallop/Cryptographer.hpp b/src/scripts/umamusume/Gallop/Cryptographer.hpp new file mode 100644 index 0000000..6cdfc46 --- /dev/null +++ b/src/scripts/umamusume/Gallop/Cryptographer.hpp @@ -0,0 +1,11 @@ +#pragma once +#include "il2cpp/il2cpp_symbols.hpp" + +namespace Gallop +{ + class Cryptographer + { + public: + static Il2CppString* MakeMd5(Il2CppString* input); + }; +} diff --git a/src/scripts/umamusume/Gallop/LocalPushDefine.hpp b/src/scripts/umamusume/Gallop/LocalPushDefine.hpp index 4376590..1d7dbf7 100644 --- a/src/scripts/umamusume/Gallop/LocalPushDefine.hpp +++ b/src/scripts/umamusume/Gallop/LocalPushDefine.hpp @@ -18,5 +18,28 @@ namespace Gallop Job7, Job8, }; + + static LocalPushType GetJobsLocalPushTypeByIndex(int index) + { + switch (index) + { + case 1: + return LocalPushType::Job2; + case 2: + return LocalPushType::Job3; + case 3: + return LocalPushType::Job4; + case 4: + return LocalPushType::Job5; + case 5: + return LocalPushType::Job6; + case 6: + return LocalPushType::Job7; + case 7: + return LocalPushType::Job8; + } + + return LocalPushType::Job1; + } }; } diff --git a/src/scripts/umamusume/Gallop/PushNotificationManager.cpp b/src/scripts/umamusume/Gallop/PushNotificationManager.cpp index 819817f..1b6151e 100644 --- a/src/scripts/umamusume/Gallop/PushNotificationManager.cpp +++ b/src/scripts/umamusume/Gallop/PushNotificationManager.cpp @@ -1,14 +1,21 @@ #include "../umamusume.hpp" #include "../../ScriptInternal.hpp" #include "PushNotificationManager.hpp" +#include "Cryptographer.hpp" + +#include + +#include "scripts/UnityEngine.CoreModule/UnityEngine/Application.hpp" #include "config/config.hpp" +void* MakeNotificationId_addr = nullptr; void* createFavIconFilePath_addr = nullptr; void* legacy_createFavIconFilePath_addr = nullptr; static void InitAddress() { + MakeNotificationId_addr = il2cpp_symbols::get_method_pointer(ASSEMBLY_NAME, "Gallop", "PushNotificationManager", "MakeNotificationId", 2); createFavIconFilePath_addr = il2cpp_symbols::get_method_pointer(ASSEMBLY_NAME, "Gallop", "PushNotificationManager", "createFavIconFilePath", 2); legacy_createFavIconFilePath_addr = il2cpp_symbols::get_method_pointer(ASSEMBLY_NAME, "Gallop", "PushNotificationManager", "createFavIconFilePath", 1); } @@ -20,13 +27,50 @@ STATIC namespace Gallop { + PushNotificationManager PushNotificationManager::Instance() + { + auto instanceField = il2cpp_class_get_field_from_name_wrap(il2cpp_symbols::get_class(ASSEMBLY_NAME, "Gallop", "PushNotificationManager"), "_instance"); + Il2CppObject* instance; + il2cpp_field_static_get_value(instanceField, &instance); + return PushNotificationManager(instance); + } + + Il2CppString* PushNotificationManager::CreatePushIconFilePath(LocalPushDefine::LocalPushType localPushType) + { + auto id = Instance().MakeNotificationId(localPushType, 0); + + auto iconName = "NotifceIcon"s; + if (id > 200) + { + iconName.append(to_string(id)); + } + + auto fileName = wstring(Cryptographer::MakeMd5(il2cpp_string_new(iconName.data()))->chars); + fileName.append(L".png"); + + auto path = wstring(UnityEngine::Application::persistentDataPath()->chars); + path.append(L"/lpfi"); + + if (!filesystem::exists(path)) + { + filesystem::create_directories(path); + } + + return il2cpp_string_new16((path + L"/" + fileName).data()); + } + + int PushNotificationManager::MakeNotificationId(LocalPushDefine::LocalPushType localPushType, int key) + { + return reinterpret_cast(MakeNotificationId_addr)(instance, localPushType, key); + } + Il2CppString* PushNotificationManager::createFavIconFilePath(int _unitId, LocalPushDefine::LocalPushType localPushType) { if (createFavIconFilePath_addr) { - return reinterpret_cast(createFavIconFilePath_addr)(_unitId, localPushType); + return reinterpret_cast(createFavIconFilePath_addr)(instance, _unitId, localPushType); } - return reinterpret_cast(legacy_createFavIconFilePath_addr)(_unitId); + return reinterpret_cast(legacy_createFavIconFilePath_addr)(instance, _unitId); } } diff --git a/src/scripts/umamusume/Gallop/PushNotificationManager.hpp b/src/scripts/umamusume/Gallop/PushNotificationManager.hpp index 3240e12..f4df88e 100644 --- a/src/scripts/umamusume/Gallop/PushNotificationManager.hpp +++ b/src/scripts/umamusume/Gallop/PushNotificationManager.hpp @@ -1,14 +1,24 @@ #pragma once #include "il2cpp/il2cpp_symbols.hpp" -#include "scripts/UnityEngine.CoreModule/UnityEngine/ScreenOrientation.hpp" +#include "scripts/UnityEngine.CoreModule/UnityEngine/MonoBehaviour.hpp" #include "scripts/umamusume/Gallop/LocalPushDefine.hpp" +using namespace UnityEngine; + namespace Gallop { - class PushNotificationManager + class PushNotificationManager : public MonoBehaviour { public: - static Il2CppString* createFavIconFilePath(int _unitId, LocalPushDefine::LocalPushType localPushType); + static PushNotificationManager Instance(); + + static Il2CppString* CreatePushIconFilePath(LocalPushDefine::LocalPushType localPushType); + + Il2CppString* createFavIconFilePath(int _unitId, LocalPushDefine::LocalPushType localPushType); + + int MakeNotificationId(LocalPushDefine::LocalPushType localPushType, int key); + + using MonoBehaviour::MonoBehaviour; }; } diff --git a/src/stdinclude.hpp b/src/stdinclude.hpp index b53aabe..e549589 100644 --- a/src/stdinclude.hpp +++ b/src/stdinclude.hpp @@ -35,35 +35,12 @@ #include "local/local.hpp" #include "logger/logger.hpp" +constexpr auto Cryptographer_KEY = "r!I@mt8e5i="; + // Unity App icon constexpr auto IDI_APP_ICON = 103; namespace { - // copy-pasted from https://stackoverflow.com/questions/3418231/replace-part-of-a-string-with-another-string - void replaceAll(std::string& str, const std::string& from, const std::string& to) - { - if (from.empty()) - return; - size_t start_pos = 0; - while ((start_pos = str.find(from, start_pos)) != std::string::npos) - { - str.replace(start_pos, from.length(), to); - start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx' - } - } - - void replaceAll(std::wstring& str, const std::wstring& from, const std::wstring& to) - { - if (from.empty()) - return; - size_t start_pos = 0; - while ((start_pos = str.find(from, start_pos)) != std::wstring::npos) - { - str.replace(start_pos, from.length(), to); - start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx' - } - } - BOOL IsElevated() { BOOL fRet = FALSE; HANDLE hToken = NULL; diff --git a/src/string_utils.hpp b/src/string_utils.hpp index b426667..3a05fc6 100644 --- a/src/string_utils.hpp +++ b/src/string_utils.hpp @@ -8,6 +8,31 @@ using namespace std; +// copy-pasted from https://stackoverflow.com/questions/3418231/replace-part-of-a-string-with-another-string +inline void replaceAll(std::string& str, const std::string& from, const std::string& to) +{ + if (from.empty()) + return; + size_t start_pos = 0; + while ((start_pos = str.find(from, start_pos)) != std::string::npos) + { + str.replace(start_pos, from.length(), to); + start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx' + } +} + +inline void replaceAll(std::wstring& str, const std::wstring& from, const std::wstring& to) +{ + if (from.empty()) + return; + size_t start_pos = 0; + while ((start_pos = str.find(from, start_pos)) != std::wstring::npos) + { + str.replace(start_pos, from.length(), to); + start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx' + } +} + inline string wide_u8(const wstring& wstr) { #ifdef _MSC_VER