add ListEditor tool function
This commit is contained in:
parent
c27085772f
commit
6ac94178fa
|
@ -483,32 +483,6 @@ namespace GakumasLocal::HookMain {
|
|||
return ret;
|
||||
}*/
|
||||
|
||||
DEFINE_HOOK(void*, UserCostumeCollection_FindBy, (void* self, void* predicate, void* mtd)) {
|
||||
auto ret = UserCostumeCollection_FindBy_Orig(self, predicate, mtd);
|
||||
if (!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 = reinterpret_cast<void* (*)(void*, void*)>(UserCostumeCollection_GetAllList_mtd->methodPointer);
|
||||
|
||||
std::string thisKlassName(this_klass->name);
|
||||
// Campus.Common.User::UserCostumeHeadCollection || Campus.Common.User::UserCostumeCollection
|
||||
// 两个 class 的 GetAllList 均使用的父类 Qua.UserDataManagement.UserDataCollectionBase`2 的方法,地址一致
|
||||
if ((thisKlassName == "UserCostumeHeadCollection") || (thisKlassName == "UserCostumeCollection")) {
|
||||
// auto ret_klass = Il2cppUtils::get_class_from_instance(ret); // WhereEnumerableIterator
|
||||
return UserCostumeCollection_GetAllList(self, nullptr);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
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);
|
||||
|
@ -533,7 +507,13 @@ namespace GakumasLocal::HookMain {
|
|||
PictureBookLiveThumbnailView_SetDataAsync_Orig(self, liveData, isReleased, isUnlocked, isNew, hasLiveSkin, ct, mtd);
|
||||
}
|
||||
|
||||
std::vector<std::string> GetIdolMusicIdAll(const std::string& charaNameId = "") {
|
||||
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");
|
||||
|
@ -542,6 +522,8 @@ namespace GakumasLocal::HookMain {
|
|||
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");
|
||||
|
||||
|
@ -561,15 +543,27 @@ namespace GakumasLocal::HookMain {
|
|||
// Log::DebugFmt("checkStartCharaId: %s", checkStartCharaId.c_str());
|
||||
|
||||
// origMusics->Clear();
|
||||
UnityResolve::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 musicId = IdolCardSkin_get_MusicId->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 = musicId->ToString();
|
||||
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);
|
||||
|
@ -579,6 +573,92 @@ namespace GakumasLocal::HookMain {
|
|||
return ret;
|
||||
}
|
||||
|
||||
void* AddIdsToUserDataCollectionFromMaster(void* origList, std::vector<std::string>& allIds,
|
||||
UnityResolve::Method* get_CostumeId, UnityResolve::Method* set_CostumeId, UnityResolve::Method* Clone) {
|
||||
Il2cppUtils::Tools::CSListEditor listEditor(origList);
|
||||
if (listEditor.get_Count() <= 0) {
|
||||
return origList;
|
||||
}
|
||||
|
||||
for (auto i : listEditor) {
|
||||
auto currCostumeId = get_CostumeId->Invoke<Il2cppString*>(i);
|
||||
if (!currCostumeId) continue;
|
||||
std::string currCostumeIdStr = currCostumeId->ToString();
|
||||
if (std::find(allIds.begin(), allIds.end(), currCostumeIdStr) == allIds.end()) {
|
||||
allIds.emplace_back(currCostumeIdStr);
|
||||
}
|
||||
}
|
||||
|
||||
int currIndex = 0;
|
||||
int origSize = listEditor.get_Count();
|
||||
for (auto& i : allIds) {
|
||||
if (i.empty()) continue;
|
||||
// Log::DebugFmt("Try add %s", i.c_str());
|
||||
|
||||
if (currIndex < origSize) {
|
||||
auto userCostume = listEditor.get_Item(currIndex);
|
||||
set_CostumeId->Invoke<void>(userCostume, Il2cppString::New(i));
|
||||
listEditor.set_Item(currIndex, userCostume);
|
||||
}
|
||||
else {
|
||||
auto userCostume = Clone->Invoke<void*>(listEditor.get_Item(0));
|
||||
set_CostumeId->Invoke<void>(userCostume, Il2cppString::New(i));
|
||||
listEditor.Add(userCostume);
|
||||
}
|
||||
currIndex++;
|
||||
}
|
||||
return origList;
|
||||
}
|
||||
|
||||
DEFINE_HOOK(void*, UserCostumeCollection_FindBy, (void* self, void* predicate, void* mtd)) {
|
||||
auto ret = UserCostumeCollection_FindBy_Orig(self, predicate, mtd);
|
||||
if (!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 = reinterpret_cast<void* (*)(void*, void*)>(UserCostumeCollection_GetAllList_mtd->methodPointer);
|
||||
|
||||
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)) {
|
||||
|
@ -598,18 +678,16 @@ namespace GakumasLocal::HookMain {
|
|||
"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);
|
||||
static auto List_String_Add_mtd = Il2cppUtils::il2cpp_class_get_method_from_name(List_String_klass, "Add", 1);
|
||||
static auto List_String_Add = reinterpret_cast<void (*)(void*, void*, void*)>(List_String_Add_mtd->methodPointer);
|
||||
|
||||
auto newList = UnityResolve::Invoke<void*>("il2cpp_object_new", List_String_klass);
|
||||
List_String_ctor(newList, List_String_ctor_mtd);
|
||||
Il2cppUtils::Tools::CSListEditor<Il2cppString*> newListEditor(newList);
|
||||
|
||||
auto fullIds = GetIdolMusicIdAll();
|
||||
|
||||
for (auto& i : fullIds) {
|
||||
// Log::DebugFmt("GetLiveMusics - Add: %s", i.c_str());
|
||||
// newList->Add(Il2cppString::New(i));
|
||||
List_String_Add(newList, Il2cppString::New(i), List_String_Add_mtd);
|
||||
newListEditor.Add(Il2cppString::New(i));
|
||||
}
|
||||
Il2cppUtils::ClassSetFieldValue(self, existsMusicIds_field, newList);
|
||||
// Log::DebugFmt("GetLiveMusics - set end: %d", fullIds.size());
|
||||
|
|
|
@ -244,4 +244,95 @@ namespace Il2cppUtils {
|
|||
auto reflectionType = assemblyGetType(reflectionAssembly, Il2CppString::New(typeStr));
|
||||
return UnityResolve::Invoke<void*>("il2cpp_class_from_system_type", reflectionType);
|
||||
}
|
||||
|
||||
namespace Tools {
|
||||
|
||||
template <typename T = void*>
|
||||
class CSListEditor {
|
||||
public:
|
||||
CSListEditor(void* list) {
|
||||
list_klass = get_class_from_instance(list);
|
||||
lst = list;
|
||||
|
||||
lst_get_Count_method = il2cpp_class_get_method_from_name(list_klass, "get_Count", 0);
|
||||
lst_get_Item_method = il2cpp_class_get_method_from_name(list_klass, "get_Item", 1);
|
||||
lst_set_Item_method = il2cpp_class_get_method_from_name(list_klass, "set_Item", 2);
|
||||
lst_Add_method = il2cpp_class_get_method_from_name(list_klass, "Add", 1);
|
||||
|
||||
lst_get_Count = reinterpret_cast<lst_get_Count_t>(lst_get_Count_method->methodPointer);
|
||||
lst_get_Item = reinterpret_cast<lst_get_Item_t>(lst_get_Item_method->methodPointer);
|
||||
lst_set_Item = reinterpret_cast<lst_set_Item_t>(lst_set_Item_method->methodPointer);
|
||||
lst_Add = reinterpret_cast<lst_Add_t>(lst_Add_method->methodPointer);
|
||||
}
|
||||
|
||||
void Add(T value) {
|
||||
lst_Add(lst, value, lst_Add_method);
|
||||
}
|
||||
|
||||
T get_Item(int index) {
|
||||
return lst_get_Item(lst, index, lst_get_Item_method);
|
||||
}
|
||||
|
||||
void set_Item(int index, T value) {
|
||||
return lst_set_Item(lst, index, value, lst_set_Item_method);
|
||||
}
|
||||
|
||||
int get_Count() {
|
||||
return lst_get_Count(lst, lst_get_Count_method);
|
||||
}
|
||||
|
||||
T operator[] (int key) {
|
||||
return get_Item(key);
|
||||
}
|
||||
|
||||
class Iterator {
|
||||
public:
|
||||
Iterator(CSListEditor<T>* editor, int index) : editor(editor), index(index) {}
|
||||
|
||||
T operator*() const {
|
||||
return editor->get_Item(index);
|
||||
}
|
||||
|
||||
Iterator& operator++() {
|
||||
++index;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator!=(const Iterator& other) const {
|
||||
return index != other.index;
|
||||
}
|
||||
|
||||
private:
|
||||
CSListEditor<T>* editor;
|
||||
int index;
|
||||
};
|
||||
|
||||
Iterator begin() {
|
||||
return Iterator(this, 0);
|
||||
}
|
||||
|
||||
Iterator end() {
|
||||
return Iterator(this, get_Count());
|
||||
}
|
||||
|
||||
void* lst;
|
||||
void* list_klass;
|
||||
private:
|
||||
typedef T(*lst_get_Item_t)(void*, int, void* mtd);
|
||||
typedef void(*lst_Add_t)(void*, T, void* mtd);
|
||||
typedef void(*lst_set_Item_t)(void*, int, T, void* mtd);
|
||||
typedef int(*lst_get_Count_t)(void*, void* mtd);
|
||||
|
||||
MethodInfo* lst_get_Item_method;
|
||||
MethodInfo* lst_Add_method;
|
||||
MethodInfo* lst_get_Count_method;
|
||||
MethodInfo* lst_set_Item_method;
|
||||
|
||||
lst_get_Item_t lst_get_Item;
|
||||
lst_set_Item_t lst_set_Item;
|
||||
lst_Add_t lst_Add;
|
||||
lst_get_Count_t lst_get_Count;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue