More stable

add unlock
This commit is contained in:
chinosk 2026-03-21 15:51:41 +08:00
parent 311312930b
commit 7305ad5cd7
Signed by: chinosk
GPG Key ID: 00610B08C1BF7BE9
4 changed files with 374 additions and 19 deletions

View File

@ -420,8 +420,8 @@ namespace GakumasLocal::HookMain {
// 用于本地化 MasterDB
DEFINE_HOOK(void, MessageExtensions_MergeFrom, (void* message, void* span, void* mtd)) {
MessageExtensions_MergeFrom_Orig(message, span, mtd);
DEFINE_HOOK(void, MessageExtensions_MergeFrom, (void* message, void* span, bool discardUnknownFields, void* registry, void* mtd)) {
MessageExtensions_MergeFrom_Orig(message, span, discardUnknownFields, registry, mtd);
if (message) {
auto ret_klass = Il2cppUtils::get_class_from_instance(message);
if (ret_klass) {
@ -472,6 +472,250 @@ namespace GakumasLocal::HookMain {
// return Il2cppString::New("[I18]" + ret->ToString());
}
#pragma region UnlockLive
enum class GetIdolIdType {
MusicId,
CostumeId,
CostumeHeadId
};
std::vector<std::string> GetIdolMusicIdAll(const std::string& charaNameId = "", GetIdolIdType getType = GetIdolIdType::MusicId) {
// 传入例: fktn
// System.Collections.Generic.List`1<valuetype [mscorlib]System.ValueTuple`2<class Campus.Common.Proto.Client.Master.IdolCardSkin, class Campus.Common.Proto.Client.Master.Music>>
static auto get_IdolCardSkinMaster = Il2cppUtils::GetMethod("Assembly-CSharp.dll", "Campus.Common.Master", "MasterManager", "get_IdolCardSkinMaster");
static auto Master_GetAllWithSortByKey = Il2cppUtils::GetMethod("Assembly-CSharp.dll", "Campus.Common.Master", "IdolCardSkinMaster", "GetAllWithSortByKey");
static auto IdolCardSkin_get_Id = Il2cppUtils::GetMethod("Assembly-CSharp.dll", "Campus.Common.Proto.Client.Master", "IdolCardSkin", "get_Id");
static auto IdolCardSkin_get_IdolCardId = Il2cppUtils::GetMethod("Assembly-CSharp.dll", "Campus.Common.Proto.Client.Master", "IdolCardSkin", "get_IdolCardId");
static auto IdolCardSkin_GetMusic = Il2cppUtils::GetMethod("Assembly-CSharp.dll", "Campus.Common.Proto.Client.Master", "IdolCardSkin", "GetMusic");
static auto IdolCardSkin_get_MusicId = Il2cppUtils::GetMethod("Assembly-CSharp.dll", "Campus.Common.Proto.Client.Master", "IdolCardSkin", "get_MusicId");
static auto IdolCardSkin_get_CostumeId = Il2cppUtils::GetMethod("Assembly-CSharp.dll", "Campus.Common.Proto.Client.Master", "IdolCardSkin", "get_CostumeId");
static auto IdolCardSkin_get_CostumeHeadId = Il2cppUtils::GetMethod("Assembly-CSharp.dll", "Campus.Common.Proto.Client.Master", "IdolCardSkin", "get_CostumeHeadId");
static auto GetLiveMusics = Il2cppUtils::GetMethod("Assembly-CSharp.dll", "Campus.OutGame",
"PictureBookWindowPresenter", "GetLiveMusics");
auto idolCardSkinMaster = get_IdolCardSkinMaster->Invoke<void*>(nullptr); // IdolCardSkinMaster
std::vector<std::string> ret{};
if (!idolCardSkinMaster) {
Log::ErrorFmt("get_IdolCardSkinMaster failed: %p", idolCardSkinMaster);
return ret;
}
// List<IdolCardSkin>
auto idolCardSkinList = Master_GetAllWithSortByKey->Invoke<Il2cppTypes::List<void*>*>(idolCardSkinMaster, 0x0, nullptr);
auto idolCardSkins = idolCardSkinList->ToArray()->ToVector();
const auto checkStartCharaId = "i_card-" + charaNameId;
// Log::DebugFmt("checkStartCharaId: %s", checkStartCharaId.c_str());
// origMusics->Clear();
Il2cppJson::Method* idGetFunc = nullptr;
switch (getType) {
case GetIdolIdType::MusicId: idGetFunc = IdolCardSkin_get_MusicId;
break;
case GetIdolIdType::CostumeId: idGetFunc = IdolCardSkin_get_CostumeId;
break;
case GetIdolIdType::CostumeHeadId: idGetFunc = IdolCardSkin_get_CostumeHeadId;
break;
default:
idGetFunc = IdolCardSkin_get_MusicId;
}
for (auto i : idolCardSkins) {
if (!i) continue;
// auto charaId = IdolCardSkin_get_Id->Invoke<Il2cppString*>(i);
auto targetId = idGetFunc->Invoke<Il2cppString*>(i);
auto cardId = IdolCardSkin_get_IdolCardId->Invoke<Il2cppString*>(i)->ToString();
auto music = IdolCardSkin_GetMusic->Invoke<void*>(i);
if (charaNameId.empty() || cardId.starts_with(checkStartCharaId)) {
std::string musicIdStr = targetId->ToString();
// Log::DebugFmt("Add cardId: %s, musicId: %s", cardId.c_str(), musicIdStr.c_str());
if (std::find(ret.begin(), ret.end(), musicIdStr) == ret.end()) {
ret.emplace_back(musicIdStr);
}
}
}
return ret;
}
void* AddIdsToUserDataCollectionFromMaster(void* origList, std::vector<std::string>& allIds,
Il2cppJson::Method* get_CostumeId, Il2cppJson::Method* set_CostumeId, Il2cppJson::Method* Clone) {
std::unordered_set<std::string> existIds{};
Il2cppUtils::Tools::CSListEditor listEditor(origList);
if (listEditor.get_Count() <= 0) {
return origList;
}
for (auto i : listEditor) {
auto costumeId = get_CostumeId->Invoke<Il2cppString*>(i);
if (!costumeId) continue;
existIds.emplace(costumeId->ToString());
}
for (auto& i : allIds) {
if (i.empty()) continue;
// Log::DebugFmt("Try add %s", i.c_str());
if (existIds.contains(i)) continue;
auto userCostume = Clone->Invoke<void*>(listEditor.get_Item(0));
set_CostumeId->Invoke<void>(userCostume, Il2cppString::New(i));
listEditor.Add(userCostume);
}
return origList;
}
DEFINE_HOOK(bool, UserIdolCardSkinCollection_Exists, (void* self, Il2cppString* id, void* mtd)) { // Live默认选择
auto ret = UserIdolCardSkinCollection_Exists_Orig(self, id, mtd);
// Log::DebugFmt("UserIdolCardSkinCollection_Exists: %s, ret: %d", id->ToString().c_str(), ret);
if (!(Config::dbgMode && Config::unlockAllLive)) return ret;
if (id) {
std::string idStr = id->ToString();
if (idStr.starts_with("music") || idStr.starts_with("i_card-skin")) { // eg. music-all-kllj-006, i_card-skin-hski-3-002
return true;
}
}
return ret;
}
DEFINE_HOOK(void, PictureBookLiveThumbnailView_SetDataAsync, (void* self, void* liveData, Il2cppString* characterId, bool isReleased, bool isUnlocked, bool isNew, bool hasLiveSkin, void* ct, void* mtd)) {
// Log::DebugFmt("PictureBookLiveThumbnailView_SetDataAsync: isReleased: %d, isUnlocked: %d, isNew: %d, hasLiveSkin: %d", isReleased, isUnlocked, isNew, hasLiveSkin);
if (Config::dbgMode && Config::unlockAllLive) {
isUnlocked = true;
isReleased = true;
hasLiveSkin = true;
}
PictureBookLiveThumbnailView_SetDataAsync_Orig(self, liveData, characterId, isReleased, isUnlocked, isNew, hasLiveSkin, ct, mtd);
}
DEFINE_HOOK(void*, UserCostumeCollection_FindBy, (void* self, void* predicate, void* mtd)) {
// Log::DebugFmt("UserCostumeCollection_FindBy");
auto ret = UserCostumeCollection_FindBy_Orig(self, predicate, mtd);
if (!(Config::dbgMode && Config::unlockAllLiveCostume)) return ret;
auto this_klass = Il2cppUtils::get_class_from_instance(self);
// auto predicate_klass = Il2cppUtils::get_class_from_instance(predicate); // System::Predicate`1
// Log::DebugFmt("UserCostumeCollection_FindBy this: %s::%s, predicate: %s::%s", this_klass->namespaze, this_klass->name,
// predicate_klass->namespaze, predicate_klass->name);
/*
static auto UserCostumeCollection_klass = Il2cppUtils::GetClass("Assembly-CSharp.dll", "Campus.Common.User",
"UserCostumeCollection");
static auto UserCostumeCollection_GetAllList_mtd = Il2cppUtils::il2cpp_class_get_method_from_name(
UserCostumeCollection_klass->address, "GetAllList", 1);*/
static auto UserCostumeCollection_GetAllList_mtd_pointer = Il2cppUtils::GetMethodPointerIl2cpp("Assembly-CSharp.dll", "Campus.Common.User",
"UserCostumeCollection", "GetAllList", 1);
static auto UserCostumeCollection_GetAllList = reinterpret_cast<void* (*)(void*, void*)>(UserCostumeCollection_GetAllList_mtd_pointer);
std::string thisKlassName(this_klass->name);
// Campus.Common.User::UserCostumeHeadCollection || Campus.Common.User::UserCostumeCollection
// 两个 class 的 GetAllList 均使用的父类 Qua.UserDataManagement.UserDataCollectionBase`2 的方法,地址一致
if (thisKlassName == "UserCostumeHeadCollection") {
static auto UserCostume_Clone = Il2cppUtils::GetMethod("Assembly-CSharp.dll", "Campus.Common.Proto.Client.Transaction", "UserCostumeHead", "Clone");
static auto UserCostume_get_CostumeHeadId = Il2cppUtils::GetMethod("Assembly-CSharp.dll", "Campus.Common.Proto.Client.Transaction", "UserCostumeHead", "get_CostumeHeadId");
static auto UserCostume_set_CostumeHeadId = Il2cppUtils::GetMethod("Assembly-CSharp.dll", "Campus.Common.Proto.Client.Transaction", "UserCostumeHead", "set_CostumeHeadId");
// auto ret_klass = Il2cppUtils::get_class_from_instance(ret); // WhereEnumerableIterator
auto origList = UserCostumeCollection_GetAllList(self, nullptr);
auto allIds = GetIdolMusicIdAll("", GetIdolIdType::CostumeHeadId);
// List<Campus.Common.Proto.Client.Transaction.UserCostumeHead>
return AddIdsToUserDataCollectionFromMaster(origList, allIds, UserCostume_get_CostumeHeadId, UserCostume_set_CostumeHeadId, UserCostume_Clone);
}
else if (thisKlassName == "UserCostumeCollection") {
// static auto UserCostume_klass = Il2cppUtils::GetClass("Assembly-CSharp.dll", "Campus.Common.Proto.Client.Transaction", "UserCostume");
static auto UserCostume_Clone = Il2cppUtils::GetMethod("Assembly-CSharp.dll", "Campus.Common.Proto.Client.Transaction", "UserCostume", "Clone");
static auto UserCostume_get_CostumeId = Il2cppUtils::GetMethod("Assembly-CSharp.dll", "Campus.Common.Proto.Client.Transaction", "UserCostume", "get_CostumeId");
static auto UserCostume_set_CostumeId = Il2cppUtils::GetMethod("Assembly-CSharp.dll", "Campus.Common.Proto.Client.Transaction", "UserCostume", "set_CostumeId");
// auto ret_klass = Il2cppUtils::get_class_from_instance(ret); // WhereEnumerableIterator
auto origList = UserCostumeCollection_GetAllList(self, nullptr);
auto allIds = GetIdolMusicIdAll("", GetIdolIdType::CostumeId);
// List<Campus.Common.Proto.Client.Transaction.UserCostume>
return AddIdsToUserDataCollectionFromMaster(origList, allIds, UserCostume_get_CostumeId, UserCostume_set_CostumeId, UserCostume_Clone);
}
return ret;
}
void* PictureBookWindowPresenter_instance = nullptr;
std::string PictureBookWindowPresenter_charaId;
DEFINE_HOOK(void*, PictureBookWindowPresenter_GetLiveMusics, (void* self, Il2cppString* charaId, void* mtd)) {
// Log::DebugFmt("GetLiveMusics: %s", charaId->ToString().c_str());
if (Config::dbgMode && Config::unlockAllLive) {
PictureBookWindowPresenter_instance = self;
PictureBookWindowPresenter_charaId = charaId->ToString();
static auto PictureBookWindowPresenter_klass = Il2cppUtils::get_class_from_instance(self);
static auto existsMusicIds_field = Il2cppJson::InvokeIl2cpp<Il2cppUtils::FieldInfo*>(
"il2cpp_class_get_field_from_name",
PictureBookWindowPresenter_klass,
"_existsMusicIds"
);
/*
static auto PictureBookWindowPresenter_klass = Il2cppUtils::GetClass("Assembly-CSharp.dll", "Campus.OutGame",
"PictureBookWindowPresenter");
static auto existsMusicIds_field = PictureBookWindowPresenter_klass->Get<UnityResolve::Field>("_existsMusicIds");*/
// auto existsMusicIds = Il2cppUtils::ClassGetFieldValue<Il2cppTypes::List<Il2cppString*>*>(self, existsMusicIds_field);
auto existsMusicIds = Il2cppUtils::ClassGetFieldValue<void*>(self, existsMusicIds_field);
if (!existsMusicIds) {
static auto Dict_List_String_klass = Il2cppUtils::get_system_class_from_reflection_type_str(
"System.Collections.Generic.Dictionary`2[System.String, System.Collections.Generic.List`1[System.String]]");
static auto List_String_klass = Il2cppUtils::get_system_class_from_reflection_type_str(
"System.Collections.Generic.List`1[System.String]");
static auto List_String_ctor_mtd = Il2cppUtils::il2cpp_class_get_method_from_name(List_String_klass, ".ctor", 0);
static auto List_String_ctor = reinterpret_cast<void (*)(void*, void*)>(List_String_ctor_mtd->methodPointer);
auto fullIds = GetIdolMusicIdAll();
static auto Dict_List_String_ctor_mtd = Il2cppUtils::il2cpp_class_get_method_from_name(Dict_List_String_klass, ".ctor", 0);
static auto Dict_List_String_ctor = reinterpret_cast<void (*)(void*, void*)>(Dict_List_String_ctor_mtd->methodPointer);
auto newDict = Il2cppJson::InvokeIl2cpp<void*>("il2cpp_object_new", Dict_List_String_klass);
Dict_List_String_ctor(newDict, Dict_List_String_ctor_mtd);
Il2cppUtils::Tools::CSDictEditor<Il2cppString*, void*> newDictEditor(newDict, Dict_List_String_klass);
// auto fullIds = GetIdolMusicIdAll();
for (auto& i : fullIds) {
// Log::DebugFmt("GetLiveMusics - Add: %s", i.c_str()); // eg. music-all-amao-001, music-char-hski-001
//newListEditor.Add(Il2cppString::New(i));
auto newList = Il2cppJson::InvokeIl2cpp<void*>("il2cpp_object_new", List_String_klass);
List_String_ctor(newList, List_String_ctor_mtd);
newDictEditor.Add(Il2cppString::New(i), newList);
}
Il2cppUtils::ClassSetFieldValue(self, existsMusicIds_field, newDict);
existsMusicIds = reinterpret_cast<decltype(existsMusicIds)>(newDict);
// Log::DebugFmt("GetLiveMusics - set end: %d", fullIds.size());
}
}
return PictureBookWindowPresenter_GetLiveMusics_Orig(self, charaId, mtd);
}
DEFINE_HOOK(void, PictureBookLiveSelectScreenModel_ctor, (void* self, void* transitionParam, Il2cppTypes::List<void*>* musics, void* mtd)) {
// Log::DebugFmt("PictureBookLiveSelectScreenModel_ctor");
if (Config::dbgMode && Config::unlockAllLive) {
static auto GetLiveMusics = Il2cppUtils::GetMethod("Assembly-CSharp.dll", "Campus.OutGame",
"PictureBookWindowPresenter", "GetLiveMusics");
if (PictureBookWindowPresenter_instance && !PictureBookWindowPresenter_charaId.empty()) {
auto fullMusics = GetLiveMusics->Invoke<Il2cppTypes::List<void*>*>(PictureBookWindowPresenter_instance,
Il2cppString::New(PictureBookWindowPresenter_charaId));
return PictureBookLiveSelectScreenModel_ctor_Orig(self, transitionParam, fullMusics, mtd);
}
}
return PictureBookLiveSelectScreenModel_ctor_Orig(self, transitionParam, musics, mtd);
}
#pragma endregion
void StartInjectFunctions() {
const auto hookInstaller = Plugin::GetInstance().GetHookInstaller();
@ -529,7 +773,8 @@ namespace GakumasLocal::HookMain {
ADD_HOOK(MessageExtensions_MergeFrom, Il2cppUtils::GetMethodPointer("Google.Protobuf.dll", "Google.Protobuf",
"MessageExtensions", "MergeFrom",
// {"Google.Protobuf.IMessage", "System.ReadOnlySpan<System.Byte>"}
{"IMessage", "ReadOnlySpan`1[Byte]"}
// {"IMessage", "ReadOnlySpan`1[Byte]"}
{"IMessage", "ReadOnlySpan`1[Byte]", "Boolean", "ExtensionRegistry"}
));
@ -554,6 +799,24 @@ namespace GakumasLocal::HookMain {
Il2cppUtils::GetMethodPointer("campus-submodule.Runtime.dll", "Campus.Common",
"ScreenOrientationControllerBase", "InternalSetOrientationAsync", 3));
#pragma region UnlockLive
ADD_HOOK(UserIdolCardSkinCollection_Exists, Il2cppUtils::GetMethodPointerIl2cpp("Assembly-CSharp.dll", "Campus.Common.User",
"UserIdolCardSkinCollection", "Exists", 1));
ADD_HOOK(PictureBookLiveThumbnailView_SetDataAsync,
Il2cppUtils::GetMethodPointer("Assembly-CSharp.dll", "Campus.OutGame.PictureBook",
"PictureBookLiveThumbnailView", "SetDataAsync"));
ADD_HOOK(UserCostumeCollection_FindBy, Il2cppUtils::GetMethodPointerIl2cpp("Assembly-CSharp.dll", "Campus.Common.User",
"UserCostumeCollection", "FindBy", 1));
ADD_HOOK(PictureBookWindowPresenter_GetLiveMusics,
Il2cppUtils::GetMethodPointer("Assembly-CSharp.dll", "Campus.OutGame",
"PictureBookWindowPresenter", "GetLiveMusics"));
ADD_HOOK(PictureBookLiveSelectScreenModel_ctor,
Il2cppUtils::GetMethodPointer("Assembly-CSharp.dll", "Campus.OutGame",
"PictureBookLiveSelectScreenModel", ".ctor"));
#pragma endregion
}
// 77 2640 5000

View File

@ -120,6 +120,10 @@ namespace Il2cppUtils {
uint8_t is_marshaled_from_native : 1;
};
struct Il2CppAssembly {
void* image;
};
static Il2CppClassHead* get_class_from_instance(const void* instance) {
#ifdef GKMS_IOS
return static_cast<Il2CppClassHead*>(*static_cast<void* const*>(__builtin_assume_aligned(instance, alignof(void*))));
@ -156,31 +160,33 @@ namespace Il2cppUtils {
}
inline Il2CppClassHead* GetIl2cppClassFromName(const char* assemblyName, const char* nameSpaceName, const char* className) {
Log::Info("GetMethodIl2cpp 0");
// Log::Info("GetMethodIl2cpp 0");
static auto domain = Il2cppJson::InvokeIl2cpp<void*>("il2cpp_domain_get");
if (!domain)
{
Log::ErrorFmt("GetMethodIl2cpp error: failed to get domain.");
return nullptr;
}
auto assembly = Il2cppJson::InvokeIl2cpp<void*>("il2cpp_domain_assembly_open", domain, assemblyName);
Il2cppJson::InvokeIl2cpp<void*>("il2cpp_thread_attach", domain);
auto assembly = Il2cppJson::InvokeIl2cpp<Il2CppAssembly*>("il2cpp_domain_assembly_open", domain, assemblyName);
if (!assembly)
{
Log::ErrorFmt("GetMethodIl2cpp error: failed to get assembly: %s", assemblyName);
return nullptr;
}
// auto assembly = Il2cppJson::InvokeIl2cpp<void*>("il2cpp_domain_assembly_open+1", assemblyName);
// UnityResolve::Invoke<void*>("il2cpp_thread_attach", domain);
Log::Info("GetMethodIl2cpp 1");
auto image = Il2cppJson::InvokeIl2cpp<void*>("il2cpp_assembly_get_image", assembly);
// Log::Info("GetMethodIl2cpp 1");
// auto image = Il2cppJson::InvokeIl2cpp<void*>("il2cpp_assembly_get_image", assembly);
auto image = assembly->image;
if (!image) {
Log::ErrorFmt("GetMethodIl2cpp error: assembly %s not found.", assemblyName);
return nullptr;
}
Log::InfoFmt("GetMethodIl2cpp 2, assembly: %p, image: %p, nameSpace: %s, class: %s", assembly, image, nameSpaceName, className);
// Log::InfoFmt("GetMethodIl2cpp 2, assembly: %p, image: %p, nameSpace: %s, class: %s", assembly, image, nameSpaceName, className);
auto klass = Il2cppJson::InvokeIl2cpp<Il2CppClassHead*>("il2cpp_class_from_name", image, nameSpaceName, className);
Log::Info("GetMethodIl2cpp 3");
// Log::Info("GetMethodIl2cpp 3");
if (!klass) {
Log::ErrorFmt("GetMethodIl2cpp error: Class %s::%s not found.", nameSpaceName, className);
return nullptr;
@ -192,11 +198,11 @@ namespace Il2cppUtils {
const char* className, const char* methodName, const int argsCount) {
auto klass = GetIl2cppClassFromName(assemblyName, nameSpaceName, className);
if (!klass) return nullptr;
Log::Info("GetMethodIl2cpp 4");
// Log::Info("GetMethodIl2cpp 4");
auto ret = Il2cppJson::InvokeIl2cpp<MethodInfo*>("il2cpp_class_get_method_from_name", klass, methodName, argsCount);
Log::Info("GetMethodIl2cpp 5");
// Log::Info("GetMethodIl2cpp 5");
if (!ret) {
Log::ErrorFmt("GetMethodIl2cpp error: method %s::%s.%s not found.", nameSpaceName, className, methodName);
// Log::ErrorFmt("GetMethodIl2cpp error: method %s::%s.%s not found.", nameSpaceName, className, methodName);
return nullptr;
}
return ret;
@ -251,6 +257,17 @@ namespace Il2cppUtils {
return reinterpret_cast<void*>(method->address);
}
inline void* GetMethodPointerIl2cpp(const char* assemblyName,
const char* nameSpaceName,
const char* className,
const char* methodName,
const int argsCount)
{
const auto method = GetMethodIl2cpp(assemblyName, nameSpaceName, className, methodName, argsCount);
if (!method) return nullptr;
return reinterpret_cast<void*>(method->methodPointer);
}
template <typename RType>
static auto ClassGetFieldValue(void* obj, FieldInfo* field) -> RType {
return *reinterpret_cast<RType*>(reinterpret_cast<uintptr_t>(obj) + field->offset);
@ -464,9 +481,9 @@ namespace Il2cppUtils {
// dic_klass = dicClass;
this->dict = dict;
get_Item_method = Il2cppJson::InvokeIl2cpp<MethodInfo*>("il2cpp_class_get_method_from_name", "get_Item", 1);
Add_method = Il2cppJson::InvokeIl2cpp<MethodInfo*>("il2cpp_class_get_method_from_name", "Add", 2);
ContainsKey_method = Il2cppJson::InvokeIl2cpp<MethodInfo*>("il2cpp_class_get_method_from_name", "ContainsKey", 1);
get_Item_method = il2cpp_class_get_method_from_name(dic_klass, "get_Item", 1);
Add_method = il2cpp_class_get_method_from_name(dic_klass, "Add", 2);
ContainsKey_method = il2cpp_class_get_method_from_name(dic_klass, "ContainsKey", 1);
dic_get_Item = (dic_get_Item_t)get_Item_method->methodPointer;
dic_Add = (dic_Add_t)Add_method->methodPointer;

View File

@ -29,8 +29,9 @@ inline std::map<std::string, uintptr_t>& GetIl2cppAddressMap() {
{ "il2cpp_class_from_system_type", 0x9DCC028 },
{ "il2cpp_init", 0x9D70D90 },
{ "il2cpp_class_from_name", 0x9DCE4A4 },
{ "il2cpp_assembly_get_image", 0x7C11B50 },
// { "il2cpp_assembly_get_image", 0x7C11B50 },
{ "il2cpp_domain_get", 0x9DB81AC },
{ "il2cpp_thread_attach", 0x9DBB684 },
{ "il2cpp_domain_assembly_open", 0x9D70EE4 },
{ "il2cpp_domain_assembly_open+1", 0x9DA374C },
{ "il2cpp_resolve_icall", 0x9D71304 },
@ -42,7 +43,6 @@ inline std::map<std::string, uintptr_t>& GetIl2cppAddressMap() {
// il2cpp_class_get_type
// il2cpp_field_static_set_value
// il2cpp_runtime_invoke
// il2cpp_thread_attach
// il2cpp_domain_get_assemblies
// il2cpp_image_get_filename
// il2cpp_image_get_name
@ -65,6 +65,10 @@ auto InvokeIl2cpp(const std::string& name, Args... args) -> Return {
// GakumasLocal::Log::InfoFmt("InvokeIl2cpp: %s", name.c_str());
return InvokeAddress<Return>(GetUnityBaseAddress() + it->second, args...);
}
else
{
GakumasLocal::Log::ErrorFmt("Il2cpp Method: %s not found!", name.c_str());
}
// GakumasLocal::Log::InfoFmt("InvokeIl2cpp failed: %s", name.c_str());
// return nullptr;

View File

@ -161,4 +161,75 @@ namespace Il2cppTypes
return UnityResolve::Invoke<Array*, void*, void*, std::uintptr_t>("mono_array_new", pDomain, kalss->address, size);
}*/
};
template <typename Type>
struct List : Il2CppObject {
Array<Type>* pList;
int size{};
int version{};
void* syncRoot{};
auto ToArray() -> Array<Type>* { return pList; }
/*
static auto New(const Class* kalss, const std::uintptr_t size) -> List* {
auto pList = new List<Type>();
pList->pList = Array<Type>::New(kalss, size);
pList->size = size;
}*/
auto operator[](const unsigned int m_uIndex) -> Type& { return pList->At(m_uIndex); }
/*
auto Add(Type pDate) -> void {
if (!this) return;
static Method* method;
if (!method) method = Get("mscorlib.dll")->Get("List`1")->Get<Method>("Add");
if (method) return method->Invoke<void>(this, pDate);
}
auto Remove(Type pDate) -> bool {
if (!this) return false;
static Method* method;
if (!method) method = Get("mscorlib.dll")->Get("List`1")->Get<Method>("Remove");
if (method) return method->Invoke<bool>(this, pDate);
return false;
}
auto RemoveAt(int index) -> void {
if (!this) return;
static Method* method;
if (!method) method = Get("mscorlib.dll")->Get("List`1")->Get<Method>("RemoveAt");
if (method) return method->Invoke<void>(this, index);
}
auto ForEach(void(*action)(Type pDate)) -> void {
if (!this) return;
static Method* method;
if (!method) method = Get("mscorlib.dll")->Get("List`1")->Get<Method>("ForEach");
if (method) return method->Invoke<void>(this, action);
}
auto GetRange(int index, int count) -> List* {
if (!this) return {};
static Method* method;
if (!method) method = Get("mscorlib.dll")->Get("List`1")->Get<Method>("GetRange");
if (method) return method->Invoke<List*>(this, index, count);
return nullptr;
}
auto Clear() -> void {
if (!this) return;
static Method* method;
if (!method) method = Get("mscorlib.dll")->Get("List`1")->Get<Method>("Clear");
if (method) return method->Invoke<void>(this);
}
auto Sort(int (*comparison)(Type* pX, Type* pY)) -> void {
if (!this) return;
static Method* method;
if (!method) method = Get("mscorlib.dll")->Get("List`1")->Get<Method>("Sort", { "*" });
if (method) return method->Invoke<void>(this, comparison);
}*/
};
}