mirror of
https://git.chinosk6.cn/chinosk/gkms-local.git
synced 2026-02-04 17:13:59 +00:00
Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c50fdfd678 | ||
|
|
3c1d1f139a | ||
|
|
6ac94178fa | ||
|
|
c27085772f | ||
|
|
361c48e2c9 | ||
|
|
e9ba8b58fd | ||
|
|
e03736bd7d | ||
|
|
06b552a097 | ||
|
|
bd9bcae01d | ||
|
|
8c850ad7db | ||
|
|
7bf429336b | ||
|
|
c7e3d4f718 | ||
|
|
b74713be78 | ||
|
|
67945c86dd | ||
|
|
06a96a450e | ||
|
|
6e512d9380 |
@@ -15,7 +15,7 @@
|
||||
|
||||
- [x] 卡片信息、TIPS 等部分的文本 hook (`generic`)
|
||||
- [ ] 更多类型的文件替换
|
||||
- [ ] LSPatch 集成模式无效
|
||||
- [x] LSPatch 集成模式无效
|
||||
|
||||
... and more
|
||||
|
||||
|
||||
@@ -15,8 +15,8 @@ android {
|
||||
applicationId "io.github.chinosk.gakumas.localify"
|
||||
minSdk 29
|
||||
targetSdk 34
|
||||
versionCode 4
|
||||
versionName "v1.6.1"
|
||||
versionCode 5
|
||||
versionName "v1.6.8"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
vectorDrawables {
|
||||
|
||||
Binary file not shown.
Binary file not shown.
3
app/lint.xml
Normal file
3
app/lint.xml
Normal file
@@ -0,0 +1,3 @@
|
||||
<lint>
|
||||
<issue id="ExtraTranslation" severity="ignore" />
|
||||
</lint>
|
||||
Submodule app/src/main/assets/gakumas-local updated: 52aefc27eb...df448152cf
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -466,20 +466,248 @@ namespace GakumasLocal::HookMain {
|
||||
// return UnityResolve::UnityType::String::New("[I18]" + ret->ToString());
|
||||
}
|
||||
|
||||
DEFINE_HOOK(void, PictureBookLiveThumbnailView_SetData, (void* self, void* liveData, bool isUnlocked, bool isNew, void* ct, void* mtd)) {
|
||||
// Log::DebugFmt("PictureBookLiveThumbnailView_SetData: isUnlocked: %d, isNew: %d", isUnlocked, isNew);
|
||||
/*
|
||||
DEFINE_HOOK(void*, UserDataManagerBase_get__userIdolCardSkinList, (void* self, void* mtd)) { // Live默认选择
|
||||
auto ret = UserDataManagerBase_get__userIdolCardSkinList_Orig(self, mtd);
|
||||
Log::DebugFmt("UserDataManagerBase_get__userIdolCardSkinList: %p", ret);
|
||||
return ret;
|
||||
}
|
||||
DEFINE_HOOK(void*, UserDataManagerBase_get__userCostumeList, (void* self, void* mtd)) { // 服装选择界面
|
||||
auto ret = UserDataManagerBase_get__userCostumeList_Orig(self, mtd);
|
||||
Log::DebugFmt("UserDataManagerBase_get__userCostumeList: %p", ret);
|
||||
return ret;
|
||||
}
|
||||
DEFINE_HOOK(void*, UserDataManagerBase_get__userCostumeHeadList, (void* self, void* mtd)) { // 服装选择界面
|
||||
auto ret = UserDataManagerBase_get__userCostumeHeadList_Orig(self, mtd);
|
||||
Log::DebugFmt("UserDataManagerBase_get__userCostumeHeadList: %p", ret);
|
||||
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);
|
||||
if (!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, 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_SetData_Orig(self, liveData, isUnlocked, isNew, ct, mtd);
|
||||
PictureBookLiveThumbnailView_SetDataAsync_Orig(self, liveData, isReleased, isUnlocked, isNew, hasLiveSkin, ct, mtd);
|
||||
}
|
||||
|
||||
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<UnityResolve::UnityType::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();
|
||||
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 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,
|
||||
UnityResolve::Method* get_CostumeId, UnityResolve::Method* set_CostumeId, UnityResolve::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(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)) {
|
||||
// Log::DebugFmt("GetLiveMusics: %s", charaId->ToString().c_str());
|
||||
|
||||
if (Config::unlockAllLive) {
|
||||
PictureBookWindowPresenter_instance = self;
|
||||
PictureBookWindowPresenter_charaId = charaId->ToString();
|
||||
|
||||
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<UnityResolve::UnityType::List<Il2cppString*>*>(self, existsMusicIds_field);
|
||||
|
||||
if (!existsMusicIds) {
|
||||
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 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());
|
||||
newListEditor.Add(Il2cppString::New(i));
|
||||
}
|
||||
Il2cppUtils::ClassSetFieldValue(self, existsMusicIds_field, newList);
|
||||
// Log::DebugFmt("GetLiveMusics - set end: %d", fullIds.size());
|
||||
}
|
||||
}
|
||||
|
||||
return PictureBookWindowPresenter_GetLiveMusics_Orig(self, charaId, mtd);
|
||||
}
|
||||
|
||||
DEFINE_HOOK(void, PictureBookLiveSelectScreenModel_ctor, (void* self, void* transitionParam, UnityResolve::UnityType::List<void*>* musics, void* mtd)) {
|
||||
// Log::DebugFmt("PictureBookLiveSelectScreenModel_ctor");
|
||||
|
||||
if (Config::unlockAllLive) {
|
||||
static auto GetLiveMusics = Il2cppUtils::GetMethod("Assembly-CSharp.dll", "Campus.OutGame",
|
||||
"PictureBookWindowPresenter", "GetLiveMusics");
|
||||
if (PictureBookWindowPresenter_instance && !PictureBookWindowPresenter_charaId.empty()) {
|
||||
auto fullMusics = GetLiveMusics->Invoke<UnityResolve::UnityType::List<void*>*>(PictureBookWindowPresenter_instance,
|
||||
Il2cppString::New(PictureBookWindowPresenter_charaId));
|
||||
return PictureBookLiveSelectScreenModel_ctor_Orig(self, transitionParam, fullMusics, mtd);
|
||||
}
|
||||
}
|
||||
|
||||
return PictureBookLiveSelectScreenModel_ctor_Orig(self, transitionParam, musics, mtd);
|
||||
}
|
||||
|
||||
bool needRestoreHides = false;
|
||||
DEFINE_HOOK(void*, PictureBookLiveSelectScreenPresenter_MoveLiveScene, (void* self, void* produceLive,
|
||||
Il2cppString* characterId, Il2cppString* costumeId, Il2cppString* costumeHeadId)) {
|
||||
Il2cppString* characterId, Il2cppString* idolCardId, Il2cppString* costumeId, Il2cppString* costumeHeadId, void* mtd)) {
|
||||
needRestoreHides = false;
|
||||
Log::InfoFmt("MoveLiveScene: characterId: %s, costumeId: %s, costumeHeadId: %s,",
|
||||
characterId->ToString().c_str(), costumeId->ToString().c_str(), costumeHeadId->ToString().c_str());
|
||||
Log::InfoFmt("MoveLiveScene: characterId: %s, idolCardId: %s, costumeId: %s, costumeHeadId: %s,",
|
||||
characterId->ToString().c_str(), idolCardId->ToString().c_str(), costumeId->ToString().c_str(), costumeHeadId->ToString().c_str());
|
||||
|
||||
/*
|
||||
characterId: hski, costumeId: hski-cstm-0002, costumeHeadId: costume_head_hski-cstm-0002,
|
||||
@@ -488,12 +716,13 @@ namespace GakumasLocal::HookMain {
|
||||
|
||||
if (Config::dbgMode && Config::enableLiveCustomeDress) {
|
||||
// 修改 LiveFixedData_GetCharacter 可以更改 Loading 角色和演唱者名字,而不变更实际登台人
|
||||
return PictureBookLiveSelectScreenPresenter_MoveLiveScene_Orig(self, produceLive, characterId,
|
||||
return PictureBookLiveSelectScreenPresenter_MoveLiveScene_Orig(self, produceLive, characterId, idolCardId,
|
||||
Config::liveCustomeCostumeId.empty() ? costumeId : Il2cppString::New(Config::liveCustomeCostumeId),
|
||||
Config::liveCustomeHeadId.empty() ? costumeHeadId : Il2cppString::New(Config::liveCustomeHeadId));
|
||||
Config::liveCustomeHeadId.empty() ? costumeHeadId : Il2cppString::New(Config::liveCustomeHeadId),
|
||||
mtd);
|
||||
}
|
||||
|
||||
return PictureBookLiveSelectScreenPresenter_MoveLiveScene_Orig(self, produceLive, characterId, costumeId, costumeHeadId);
|
||||
return PictureBookLiveSelectScreenPresenter_MoveLiveScene_Orig(self, produceLive, characterId, idolCardId, costumeId, costumeHeadId, mtd);
|
||||
}
|
||||
|
||||
// std::string lastMusicId;
|
||||
@@ -733,6 +962,32 @@ namespace GakumasLocal::HookMain {
|
||||
CampusActorController_LateUpdate_Orig(self, mtd);
|
||||
}
|
||||
|
||||
DEFINE_HOOK(bool, PlatformInformation_get_IsAndroid, ()) {
|
||||
if (Config::loginAsIOS) {
|
||||
return false;
|
||||
}
|
||||
// Log::DebugFmt("PlatformInformation_get_IsAndroid: 0x%x", ret);
|
||||
return PlatformInformation_get_IsAndroid_Orig();
|
||||
}
|
||||
|
||||
DEFINE_HOOK(bool, PlatformInformation_get_IsIOS, ()) {
|
||||
if (Config::loginAsIOS) {
|
||||
return true;
|
||||
}
|
||||
// Log::DebugFmt("PlatformInformation_get_IsIOS: 0x%x", ret);
|
||||
return PlatformInformation_get_IsIOS_Orig();
|
||||
}
|
||||
|
||||
DEFINE_HOOK(Il2cppString*, ApiBase_GetPlatformString, (void* self, void* mtd)) {
|
||||
if (Config::loginAsIOS) {
|
||||
return Il2cppString::New("iOS");
|
||||
}
|
||||
// auto ret = ApiBase_GetPlatformString_Orig(self, mtd);
|
||||
// Log::DebugFmt("ApiBase_GetPlatformString: %s", ret->ToString().c_str());
|
||||
return ApiBase_GetPlatformString_Orig(self, mtd);
|
||||
}
|
||||
|
||||
|
||||
void UpdateSwingBreastBonesData(void* initializeData) {
|
||||
if (!Config::enableBreastParam) return;
|
||||
static auto CampusActorAnimationInitializeData_klass = Il2cppUtils::GetClass("campus-submodule.Runtime.dll", "ActorAnimation",
|
||||
@@ -880,9 +1135,51 @@ namespace GakumasLocal::HookMain {
|
||||
Il2cppUtils::GetMethodPointer("Octo.dll", "Octo",
|
||||
"OnDownloadProgress", "Invoke"));
|
||||
|
||||
ADD_HOOK(PictureBookLiveThumbnailView_SetData,
|
||||
/*
|
||||
auto UserDataManager_klass = Il2cppUtils::GetClass("Assembly-CSharp.dll", "Campus.Common.User",
|
||||
"UserDataManager");
|
||||
if (UserDataManager_klass) {
|
||||
auto UserDataManagerBase_klass = UnityResolve::Invoke<Il2cppUtils::Il2CppClassHead*>("il2cpp_class_get_parent", UserDataManager_klass->address);
|
||||
if (UserDataManagerBase_klass) {
|
||||
auto get_userIdolCardSkinList_mtd = Il2cppUtils::il2cpp_class_get_method_from_name(UserDataManagerBase_klass, "get__userIdolCardSkinList", 0);
|
||||
if (get_userIdolCardSkinList_mtd) {
|
||||
ADD_HOOK(UserDataManagerBase_get__userIdolCardSkinList, get_userIdolCardSkinList_mtd->methodPointer);
|
||||
}
|
||||
auto get_userCostumeList_mtd = Il2cppUtils::il2cpp_class_get_method_from_name(UserDataManagerBase_klass, "get__userCostumeList", 0);
|
||||
if (get_userCostumeList_mtd) {
|
||||
ADD_HOOK(UserDataManagerBase_get__userCostumeList, get_userCostumeList_mtd->methodPointer);
|
||||
}
|
||||
auto get_userCostumeHeadList_mtd = Il2cppUtils::il2cpp_class_get_method_from_name(UserDataManagerBase_klass, "get__userCostumeHeadList", 0);
|
||||
if (get_userCostumeHeadList_mtd) {
|
||||
ADD_HOOK(UserDataManagerBase_get__userCostumeHeadList, get_userCostumeHeadList_mtd->methodPointer);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
auto UserIdolCardSkinCollection_klass = Il2cppUtils::GetClass("Assembly-CSharp.dll", "Campus.Common.User",
|
||||
"UserIdolCardSkinCollection");
|
||||
auto UserIdolCardSkinCollection_Exists_mtd = Il2cppUtils::il2cpp_class_get_method_from_name(UserIdolCardSkinCollection_klass->address, "Exists", 1);
|
||||
if (UserIdolCardSkinCollection_Exists_mtd) {
|
||||
ADD_HOOK(UserIdolCardSkinCollection_Exists, UserIdolCardSkinCollection_Exists_mtd->methodPointer);
|
||||
}
|
||||
|
||||
auto UserCostumeCollection_klass = Il2cppUtils::GetClass("Assembly-CSharp.dll", "Campus.Common.User",
|
||||
"UserCostumeCollection");
|
||||
auto UserCostumeCollection_FindBy_mtd = Il2cppUtils::il2cpp_class_get_method_from_name(
|
||||
UserCostumeCollection_klass->address, "FindBy", 1);
|
||||
if (UserCostumeCollection_FindBy_mtd) {
|
||||
ADD_HOOK(UserCostumeCollection_FindBy, UserCostumeCollection_FindBy_mtd->methodPointer);
|
||||
}
|
||||
|
||||
ADD_HOOK(PictureBookLiveThumbnailView_SetDataAsync,
|
||||
Il2cppUtils::GetMethodPointer("Assembly-CSharp.dll", "Campus.OutGame.PictureBook",
|
||||
"PictureBookLiveThumbnailView", "SetDataAsync", {"*", "*", "*", "*"}));
|
||||
"PictureBookLiveThumbnailView", "SetDataAsync", {"*", "*", "*", "*", "*"}));
|
||||
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"));
|
||||
|
||||
ADD_HOOK(PictureBookLiveSelectScreenPresenter_MoveLiveScene,
|
||||
Il2cppUtils::GetMethodPointer("Assembly-CSharp.dll", "Campus.OutGame",
|
||||
@@ -918,6 +1215,22 @@ namespace GakumasLocal::HookMain {
|
||||
ADD_HOOK(CampusActorController_LateUpdate,
|
||||
Il2cppUtils::GetMethodPointer("campus-submodule.Runtime.dll", "Campus.Common",
|
||||
"CampusActorController", "LateUpdate"));
|
||||
|
||||
ADD_HOOK(PlatformInformation_get_IsAndroid, Il2cppUtils::GetMethodPointer("Firebase.Platform.dll", "Firebase.Platform",
|
||||
"PlatformInformation", "get_IsAndroid"));
|
||||
ADD_HOOK(PlatformInformation_get_IsIOS, Il2cppUtils::GetMethodPointer("Firebase.Platform.dll", "Firebase.Platform",
|
||||
"PlatformInformation", "get_IsIOS"));
|
||||
|
||||
auto api_klass = Il2cppUtils::GetClass("Assembly-CSharp.dll", "Campus.Common.Network", "Api");
|
||||
if (api_klass) {
|
||||
// Qua.Network.ApiBase
|
||||
auto api_parent = UnityResolve::Invoke<Il2cppUtils::Il2CppClassHead*>("il2cpp_class_get_parent", api_klass->address);
|
||||
if (api_parent) {
|
||||
// Log::DebugFmt("api_parent at %p, name: %s::%s", api_parent, api_parent->namespaze, api_parent->name);
|
||||
ADD_HOOK(ApiBase_GetPlatformString, Il2cppUtils::il2cpp_class_get_method_from_name(api_parent, "GetPlatformString", 0)->methodPointer);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
static auto CampusActorController_klass = Il2cppUtils::GetClass("campus-submodule.Runtime.dll",
|
||||
"Campus.Common", "CampusActorController");
|
||||
|
||||
@@ -36,6 +36,74 @@ namespace Il2cppUtils {
|
||||
uint8_t is_marshaled_from_native : 1;
|
||||
};
|
||||
|
||||
struct Il2CppObject
|
||||
{
|
||||
union
|
||||
{
|
||||
void* klass;
|
||||
void* vtable;
|
||||
};
|
||||
void* monitor;
|
||||
};
|
||||
|
||||
enum Il2CppTypeEnum
|
||||
{
|
||||
IL2CPP_TYPE_END = 0x00, /* End of List */
|
||||
IL2CPP_TYPE_VOID = 0x01,
|
||||
IL2CPP_TYPE_BOOLEAN = 0x02,
|
||||
IL2CPP_TYPE_CHAR = 0x03,
|
||||
IL2CPP_TYPE_I1 = 0x04,
|
||||
IL2CPP_TYPE_U1 = 0x05,
|
||||
IL2CPP_TYPE_I2 = 0x06,
|
||||
IL2CPP_TYPE_U2 = 0x07,
|
||||
IL2CPP_TYPE_I4 = 0x08,
|
||||
IL2CPP_TYPE_U4 = 0x09,
|
||||
IL2CPP_TYPE_I8 = 0x0a,
|
||||
IL2CPP_TYPE_U8 = 0x0b,
|
||||
IL2CPP_TYPE_R4 = 0x0c,
|
||||
IL2CPP_TYPE_R8 = 0x0d,
|
||||
IL2CPP_TYPE_STRING = 0x0e,
|
||||
IL2CPP_TYPE_PTR = 0x0f,
|
||||
IL2CPP_TYPE_BYREF = 0x10,
|
||||
IL2CPP_TYPE_VALUETYPE = 0x11,
|
||||
IL2CPP_TYPE_CLASS = 0x12,
|
||||
IL2CPP_TYPE_VAR = 0x13,
|
||||
IL2CPP_TYPE_ARRAY = 0x14,
|
||||
IL2CPP_TYPE_GENERICINST = 0x15,
|
||||
IL2CPP_TYPE_TYPEDBYREF = 0x16,
|
||||
IL2CPP_TYPE_I = 0x18,
|
||||
IL2CPP_TYPE_U = 0x19,
|
||||
IL2CPP_TYPE_FNPTR = 0x1b,
|
||||
IL2CPP_TYPE_OBJECT = 0x1c,
|
||||
IL2CPP_TYPE_SZARRAY = 0x1d,
|
||||
IL2CPP_TYPE_MVAR = 0x1e,
|
||||
IL2CPP_TYPE_CMOD_REQD = 0x1f,
|
||||
IL2CPP_TYPE_CMOD_OPT = 0x20,
|
||||
IL2CPP_TYPE_INTERNAL = 0x21,
|
||||
|
||||
IL2CPP_TYPE_MODIFIER = 0x40,
|
||||
IL2CPP_TYPE_SENTINEL = 0x41,
|
||||
IL2CPP_TYPE_PINNED = 0x45,
|
||||
|
||||
IL2CPP_TYPE_ENUM = 0x55
|
||||
};
|
||||
|
||||
typedef struct Il2CppType
|
||||
{
|
||||
void* dummy;
|
||||
unsigned int attrs : 16;
|
||||
Il2CppTypeEnum type : 8;
|
||||
unsigned int num_mods : 6;
|
||||
unsigned int byref : 1;
|
||||
unsigned int pinned : 1;
|
||||
} Il2CppType;
|
||||
|
||||
struct Il2CppReflectionType
|
||||
{
|
||||
Il2CppObject object;
|
||||
const Il2CppType* type;
|
||||
};
|
||||
|
||||
struct Resolution_t {
|
||||
int width;
|
||||
int height;
|
||||
@@ -160,5 +228,111 @@ namespace Il2cppUtils {
|
||||
*reinterpret_cast<RType*>(reinterpret_cast<uintptr_t>(obj) + field->offset) = value;
|
||||
}
|
||||
|
||||
void* get_system_class_from_reflection_type_str(const char* typeStr, const char* assemblyName = "mscorlib") {
|
||||
using Il2CppString = UnityResolve::UnityType::String;
|
||||
|
||||
static auto assemblyLoad = reinterpret_cast<void* (*)(Il2CppString*)>(
|
||||
GetMethodPointer("mscorlib.dll", "System.Reflection",
|
||||
"Assembly", "Load", {"*"})
|
||||
);
|
||||
static auto assemblyGetType = reinterpret_cast<Il2CppReflectionType * (*)(void*, Il2CppString*)>(
|
||||
GetMethodPointer("mscorlib.dll", "System.Reflection",
|
||||
"Assembly", "GetType", {"*"})
|
||||
);
|
||||
|
||||
static auto reflectionAssembly = assemblyLoad(Il2CppString::New(assemblyName));
|
||||
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;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -521,6 +521,17 @@ namespace GakumasLocal::Local {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 匹配升级卡名
|
||||
if (auto plusPos = origText.find_last_not_of('+'); plusPos != std::string::npos) {
|
||||
const auto noPlusText = origText.substr(0, plusPos + 1);
|
||||
|
||||
if (const auto iter = genericText.find(noPlusText); iter != genericText.end()) {
|
||||
size_t plusCount = origText.length() - (plusPos + 1);
|
||||
*newStr = iter->second + std::string(plusCount, '+');
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// fmt 文本
|
||||
auto fmtText = StringParser::ParseItems::parse(origText, false);
|
||||
if (fmtText.isValid) {
|
||||
|
||||
@@ -16,11 +16,14 @@ namespace GakumasLocal::Config {
|
||||
bool enableFreeCamera = false;
|
||||
int targetFrameRate = 0;
|
||||
bool unlockAllLive = false;
|
||||
bool unlockAllLiveCostume = false;
|
||||
|
||||
bool enableLiveCustomeDress = false;
|
||||
std::string liveCustomeHeadId = "";
|
||||
std::string liveCustomeCostumeId = "";
|
||||
|
||||
bool loginAsIOS = false;
|
||||
|
||||
bool useCustomeGraphicSettings = false;
|
||||
float renderScale = 0.77f;
|
||||
int qualitySettingsLevel = 3;
|
||||
@@ -65,9 +68,11 @@ namespace GakumasLocal::Config {
|
||||
GetConfigItem(targetFrameRate);
|
||||
GetConfigItem(enableFreeCamera);
|
||||
GetConfigItem(unlockAllLive);
|
||||
GetConfigItem(unlockAllLiveCostume);
|
||||
GetConfigItem(enableLiveCustomeDress);
|
||||
GetConfigItem(liveCustomeHeadId);
|
||||
GetConfigItem(liveCustomeCostumeId);
|
||||
GetConfigItem(loginAsIOS);
|
||||
GetConfigItem(useCustomeGraphicSettings);
|
||||
GetConfigItem(renderScale);
|
||||
GetConfigItem(qualitySettingsLevel);
|
||||
|
||||
@@ -14,11 +14,14 @@ namespace GakumasLocal::Config {
|
||||
extern bool enableFreeCamera;
|
||||
extern int targetFrameRate;
|
||||
extern bool unlockAllLive;
|
||||
extern bool unlockAllLiveCostume;
|
||||
|
||||
extern bool enableLiveCustomeDress;
|
||||
extern std::string liveCustomeHeadId;
|
||||
extern std::string liveCustomeCostumeId;
|
||||
|
||||
extern bool loginAsIOS;
|
||||
|
||||
extern bool useCustomeGraphicSettings;
|
||||
extern float renderScale;
|
||||
extern int qualitySettingsLevel;
|
||||
|
||||
@@ -128,7 +128,15 @@ fun <T> T.onClickStartGame() where T : Activity, T : IHasConfigItems {
|
||||
"io.github.chinosk.gakumas.localify.fileprovider",
|
||||
File(targetFile.absolutePath)
|
||||
)
|
||||
intent.setDataAndType(dirUri, "resource/file")
|
||||
// intent.setDataAndType(dirUri, "resource/file")
|
||||
|
||||
grantUriPermission(
|
||||
"com.bandainamcoent.idolmaster_gakuen",
|
||||
dirUri,
|
||||
Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
||||
)
|
||||
intent.putExtra("resource_file", dirUri)
|
||||
// intent.clipData = ClipData.newRawUri("resource_file", dirUri)
|
||||
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
|
||||
}
|
||||
|
||||
|
||||
@@ -17,12 +17,14 @@ import kotlinx.coroutines.runBlocking
|
||||
interface ConfigListener {
|
||||
fun onEnabledChanged(value: Boolean)
|
||||
fun onForceExportResourceChanged(value: Boolean)
|
||||
fun onLoginAsIOSChanged(value: Boolean)
|
||||
fun onTextTestChanged(value: Boolean)
|
||||
fun onReplaceFontChanged(value: Boolean)
|
||||
fun onLazyInitChanged(value: Boolean)
|
||||
fun onEnableFreeCameraChanged(value: Boolean)
|
||||
fun onTargetFpsChanged(s: CharSequence, start: Int, before: Int, count: Int)
|
||||
fun onUnlockAllLiveChanged(value: Boolean)
|
||||
fun onUnlockAllLiveCostumeChanged(value: Boolean)
|
||||
fun onLiveCustomeDressChanged(value: Boolean)
|
||||
fun onLiveCustomeHeadIdChanged(s: CharSequence, start: Int, before: Int, count: Int)
|
||||
fun onLiveCustomeCostumeIdChanged(s: CharSequence, start: Int, before: Int, count: Int)
|
||||
@@ -115,6 +117,11 @@ interface ConfigUpdateListener: ConfigListener, IHasConfigItems {
|
||||
pushKeyEvent(KeyEvent(1145, 30))
|
||||
}
|
||||
|
||||
override fun onLoginAsIOSChanged(value: Boolean) {
|
||||
config.loginAsIOS = value
|
||||
saveConfig()
|
||||
}
|
||||
|
||||
override fun onReplaceFontChanged(value: Boolean) {
|
||||
config.replaceFont = value
|
||||
saveConfig()
|
||||
@@ -146,6 +153,11 @@ interface ConfigUpdateListener: ConfigListener, IHasConfigItems {
|
||||
saveConfig()
|
||||
}
|
||||
|
||||
override fun onUnlockAllLiveCostumeChanged(value: Boolean) {
|
||||
config.unlockAllLiveCostume = value
|
||||
saveConfig()
|
||||
}
|
||||
|
||||
override fun onTargetFpsChanged(s: CharSequence, start: Int, before: Int, count: Int) {
|
||||
try {
|
||||
val valueStr = s.toString()
|
||||
|
||||
@@ -8,6 +8,7 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.util.Log
|
||||
@@ -282,7 +283,14 @@ class GakumasHookMain : IXposedHookLoadPackage, IXposedHookZygoteInit {
|
||||
|
||||
// 使用热更新文件
|
||||
if ((programConfig?.useRemoteAssets == true) || (programConfig?.useAPIAssets == true)) {
|
||||
val dataUri = intent.data
|
||||
// val dataUri = intent.data
|
||||
val dataUri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
intent.getParcelableExtra("resource_file", Uri::class.java)
|
||||
} else {
|
||||
@Suppress("DEPRECATION")
|
||||
intent.getParcelableExtra<Uri>("resource_file")
|
||||
}
|
||||
|
||||
if (dataUri != null) {
|
||||
if (!externalFilesChecked) {
|
||||
externalFilesChecked = true
|
||||
|
||||
@@ -645,7 +645,7 @@ class PatchActivity : ComponentActivity() {
|
||||
val copyFilesCmd: MutableList<String> = mutableListOf()
|
||||
val movedFiles: MutableList<String> = mutableListOf()
|
||||
savedFileNames.forEach { file ->
|
||||
val movedFileName = "$installDS/${file}"
|
||||
val movedFileName = "\"$installDS/${file}\""
|
||||
movedFiles.add(movedFileName)
|
||||
val dlSaveFileName = File(targetDirectory, file)
|
||||
copyFilesCmd.add("$action ${dlSaveFileName.absolutePath} $movedFileName")
|
||||
|
||||
@@ -84,7 +84,7 @@ object FilesChecker {
|
||||
for (i in assets.list(localizationFilesDir)!!) {
|
||||
if (i.toString() == "version.txt") {
|
||||
val stream = assets.open("$localizationFilesDir/$i")
|
||||
return convertToString(stream)
|
||||
return convertToString(stream).trim()
|
||||
}
|
||||
}
|
||||
return "0.0"
|
||||
@@ -96,7 +96,7 @@ object FilesChecker {
|
||||
|
||||
val versionFile = File(pluginFilesDir, "version.txt")
|
||||
if (!versionFile.exists()) return "0.0"
|
||||
return versionFile.readText()
|
||||
return versionFile.readText().trim()
|
||||
}
|
||||
|
||||
fun convertToString(inputStream: InputStream?): String {
|
||||
|
||||
@@ -15,10 +15,13 @@ data class GakumasConfig (
|
||||
var enableFreeCamera: Boolean = false,
|
||||
var targetFrameRate: Int = 0,
|
||||
var unlockAllLive: Boolean = false,
|
||||
var unlockAllLiveCostume: Boolean = false,
|
||||
var enableLiveCustomeDress: Boolean = false,
|
||||
var liveCustomeHeadId: String = "",
|
||||
var liveCustomeCostumeId: String = "",
|
||||
|
||||
var loginAsIOS: Boolean = false,
|
||||
|
||||
var useCustomeGraphicSettings: Boolean = false,
|
||||
var renderScale: Float = 0.77f,
|
||||
var qualitySettingsLevel: Int = 3,
|
||||
|
||||
@@ -86,6 +86,10 @@ fun AdvanceSettingsPage(modifier: Modifier = Modifier,
|
||||
GakuSwitch(modifier, stringResource(R.string.force_export_resource), checked = config.value.forceExportResource) {
|
||||
v -> context?.onForceExportResourceChanged(v)
|
||||
}
|
||||
|
||||
GakuSwitch(modifier, stringResource(R.string.login_as_ios), checked = config.value.loginAsIOS) {
|
||||
v -> context?.onLoginAsIOSChanged(v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -353,6 +357,10 @@ fun AdvanceSettingsPage(modifier: Modifier = Modifier,
|
||||
checked = config.value.unlockAllLive) {
|
||||
v -> context?.onUnlockAllLiveChanged(v)
|
||||
}
|
||||
GakuSwitch(modifier, stringResource(R.string.unlockAllLiveCostume),
|
||||
checked = config.value.unlockAllLiveCostume) {
|
||||
v -> context?.onUnlockAllLiveCostumeChanged(v)
|
||||
}
|
||||
HorizontalDivider(
|
||||
thickness = 1.dp,
|
||||
color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.12f)
|
||||
|
||||
130
app/src/main/res/values-ja/strings.xml
Normal file
130
app/src/main/res/values-ja/strings.xml
Normal file
@@ -0,0 +1,130 @@
|
||||
<resources>
|
||||
<string name="about">情報</string>
|
||||
<string name="about_about_p1">このプラグインは完全に無料で提供されます。このプラグインで料金を支払ってしまった場合は、販売者に報告をしてください。</string>
|
||||
<string name="about_about_p2">プラグインの QQ グループ: 975854705</string>
|
||||
<string name="about_about_title">このプラグインについて</string>
|
||||
<string name="about_contributors_asset_file">about_contributors_en.json</string>
|
||||
<string name="about_warn_p1">このプラグインは学習とコミュニケーションのみを目的としています。</string>
|
||||
<string name="about_warn_p2">外部プラグインは関連する TOS に違反するため、自己責任でご使用ください。</string>
|
||||
<string name="about_warn_title">警告</string>
|
||||
<string name="advanced_settings">高度な設定</string>
|
||||
<string name="api_addr">APIアドレス (GitHub の最新リリース API)</string>
|
||||
<string name="app_name">Gakumas Localify</string>
|
||||
<string name="average">平均</string>
|
||||
<string name="axisx_x">X 軸.x</string>
|
||||
<string name="axisx_y">X 軸.y</string>
|
||||
<string name="axisy_x">Y 軸.x</string>
|
||||
<string name="axisy_y">Y 軸.y</string>
|
||||
<string name="axisz_x">Z 軸.x</string>
|
||||
<string name="axisz_y">Z 軸.y</string>
|
||||
<string name="basic_settings">基本設定</string>
|
||||
<string name="breast_param">胸のパラメーター</string>
|
||||
<string name="breast_scale">胸の大きさ</string>
|
||||
<string name="camera_settings">カメラ設定</string>
|
||||
<string name="cancel">キャンセル</string>
|
||||
<string name="character_counter_content_description">%1$d の %2$d に入力された文字</string>
|
||||
<string name="character_counter_overflowed_content_description">文字制限が %2$d 文字中、 %1$d 文字を超えています</string>
|
||||
<string name="character_counter_pattern">%1$d/%2$d</string>
|
||||
<string name="check_built_in_resource">内蔵アセットのアップデートを確認</string>
|
||||
<string name="check_resource_from_api">リソースアップデートを API から確認</string>
|
||||
<string name="check_update">確認</string>
|
||||
<string name="clear_text_end_icon_content_description">テキストを消去</string>
|
||||
<string name="close_drawer">ナビゲーションメニューを閉じる</string>
|
||||
<string name="close_sheet">シートを閉じる</string>
|
||||
<string name="contributors">貢献者</string>
|
||||
<string name="damping">ダンプ中</string>
|
||||
<string name="debug_settings">デバッグ設定</string>
|
||||
<string name="default_assets_check_api">https://api.github.com/repos/NatsumeLS/Gakumas-Translation-Data-EN/releases/latest</string>
|
||||
<string name="default_error_message">入力が無効です</string>
|
||||
<string name="default_popup_window_title">ポップアップウィンドウ</string>
|
||||
<string name="del_remote_after_update">キャッシュファイルをアップデート後に削除</string>
|
||||
<string name="delete_plugin_resource">プラグインリソースを削除</string>
|
||||
<string name="download">ダウンロード</string>
|
||||
<string name="downloaded_resource_version">ダウンロードされたバージョン</string>
|
||||
<string name="dropdown_menu">ドロップダウンメニュー</string>
|
||||
<string name="enable_breast_param">胸のパラメーターを有効化</string>
|
||||
<string name="enable_free_camera">フリーカメラを有効化</string>
|
||||
<string name="enable_plugin">プラグイン有効化 (ホットリロードなし)</string>
|
||||
<string name="error_a11y_label">エラー: 無効</string>
|
||||
<string name="error_icon_content_description">エラー</string>
|
||||
<string name="export_text">テキストをエクスポート</string>
|
||||
<string name="exposed_dropdown_menu_content_description">ドロップダウンメニューを表示</string>
|
||||
<string name="force_export_resource">リソースのアップデートを強制する</string>
|
||||
<string name="login_as_ios">iOSとしてログイン</string>
|
||||
<string name="gakumas_localify">Gakumas Localify</string>
|
||||
<string name="game_patch">ゲームパッチ</string>
|
||||
<string name="graphic_settings">グラフィック設定</string>
|
||||
<string name="hign">高</string>
|
||||
<string name="home">ホーム</string>
|
||||
<string name="home_shizuku_warning">一部の機能が使用できません</string>
|
||||
<string name="icon_content_description">ダイアログアイコン</string>
|
||||
<string name="in_progress">実行中</string>
|
||||
<string name="indeterminate">部分的にチェック済み</string>
|
||||
<string name="install">インストール</string>
|
||||
<string name="installing">インストール中</string>
|
||||
<string name="invalid_zip_file">無効なファイル</string>
|
||||
<string name="invalid_zip_file_warn">このファイルは有効な ZIP 翻訳リソースパックではありません。</string>
|
||||
<string name="isdirty">IsDirty</string>
|
||||
<string name="item_view_role_description">タブ</string>
|
||||
<string name="lazy_init">高速な初期化 (読み込みを遅延)</string>
|
||||
<string name="liveUseCustomeDress">ライブのキャラクターをカスタム</string>
|
||||
<string name="live_costume_head_id">ライブのカスタムヘッド ID (例: costume_head_hski-cstm-0002)</string>
|
||||
<string name="live_custome_dress_id">ライブ衣装のカスタム ID (例: hski-cstm-0002)</string>
|
||||
<string name="low">低</string>
|
||||
<string name="max_high">ウルトラ</string>
|
||||
<string name="middle">中</string>
|
||||
<string name="off">OFF</string>
|
||||
<string name="ok">OK</string>
|
||||
<string name="on">ON</string>
|
||||
<string name="orientation_landscape">横画面</string>
|
||||
<string name="orientation_lock">画面を固定</string>
|
||||
<string name="orientation_orig">オリジナル</string>
|
||||
<string name="orientation_portrait">縦画面</string>
|
||||
<string name="password_toggle_content_description">パスワードを表示</string>
|
||||
<string name="patch_debuggable">デバッグを可能にする</string>
|
||||
<string name="patch_finished">パッチが完了しました。インストールをしますか?</string>
|
||||
<string name="patch_integrated">統合</string>
|
||||
<string name="patch_integrated_desc">"モジュールを埋め込んだ状態なアプリでパッチを当てます。\nパッチを適用したアプリは LSPatch Manager なしで実行できますが、動的に管理はできません。\n統合パッチが適用されたアプリは、LSPatch Manager がインストールされていないデバイスでも使用が可能です。"</string>
|
||||
<string name="patch_local">ローカル</string>
|
||||
<string name="patch_local_desc">"モジュールを埋め込まずにアプリにパッチを当てます。\nXposed スコープは再パッチなしで動的に変更が可能です。\nローカルでのパッチを当てたアプリは、ローカルのデバイスでのみ実行可能です。"</string>
|
||||
<string name="patch_mode">パッチモード</string>
|
||||
<string name="patch_uninstall_confirm">アンインストールをしてもよろしいですか?</string>
|
||||
<string name="patch_uninstall_text">"署名が異なるため、パッチをインストールする前に元となるアプリをアンインストールする必要があります。\n個人データのバックアップを設定済みであることを確認してください。"</string>
|
||||
<string name="pendulum">揺れ</string>
|
||||
<string name="pendulumrange">揺れの範囲</string>
|
||||
<string name="plugin_code">プラグインのコード</string>
|
||||
<string name="project_contribution">プロジェクトの貢献者</string>
|
||||
<string name="range_end">範囲の終了</string>
|
||||
<string name="range_start">範囲の開始</string>
|
||||
<string name="renderscale">RenderScale (0.5/0.59/0.67/0.77/1.0)</string>
|
||||
<string name="replace_font">フォントを置換する</string>
|
||||
<string name="reserve_patched">パッチ済みの APK を予約する</string>
|
||||
<string name="resource_settings">リソース設定</string>
|
||||
<string name="resource_url">リソース URL</string>
|
||||
<string name="rootweight">ルートウェイト</string>
|
||||
<string name="selected">選択済み</string>
|
||||
<string name="setFpsTitle">最大 FPS (0 はオリジナルの設定を使用します)</string>
|
||||
<string name="shizuku_available">Shizuku サービスが有効です</string>
|
||||
<string name="shizuku_unavailable">Shizuku サービスが接続されていません</string>
|
||||
<string name="spring">跳ね</string>
|
||||
<string name="start_game">ゲーム開始 / ホットリロードの設定</string>
|
||||
<string name="stiffness">剛性</string>
|
||||
<string name="support_file_types">"対応ファイル:\n単一または複数選択: apk\n単一選択: apks、xapk、zip"</string>
|
||||
<string name="switch_role">切り替え</string>
|
||||
<string name="tab">タブ</string>
|
||||
<string name="template_percent">%1$d パーセント。</string>
|
||||
<string name="test_mode_live">テストモード - ライブ</string>
|
||||
<string name="text_hook_test_mode">テキストフックテストモード</string>
|
||||
<string name="translation_repository">翻訳のリポジトリ</string>
|
||||
<string name="translation_resource_update">翻訳リソースをアップデート</string>
|
||||
<string name="unlockAllLive">すべてのライブを開放</string>
|
||||
<string name="unlockAllLiveCostume">すべてのライブ衣装を開放</string>
|
||||
<string name="useCustomeGraphicSettings">カスタムグラフィック設定を使用する</string>
|
||||
<string name="use_remote_zip_resource">リモート ZIP リソースを使用する</string>
|
||||
<string name="usearmcorrection">Arm コレクションを使用する</string>
|
||||
<string name="uselimit_0_1">リミットレンジの倍率 (0 は無制限)</string>
|
||||
<string name="uselimitmultiplier">乗数制限を使用する</string>
|
||||
<string name="usescale">胸の大きさを使用する</string>
|
||||
<string name="very_high">最高</string>
|
||||
<string name="warning">警告</string>
|
||||
</resources>
|
||||
@@ -8,6 +8,7 @@
|
||||
<string name="start_game">以上述配置启动游戏/重载配置</string>
|
||||
<string name="setFpsTitle">最大 FPS (0 为保持游戏原设置)</string>
|
||||
<string name="unlockAllLive">解锁所有 Live</string>
|
||||
<string name="unlockAllLiveCostume">解锁所有 Live 服装</string>
|
||||
<string name="liveUseCustomeDress">Live 使用自定义角色</string>
|
||||
<string name="live_costume_head_id">Live 自定义头部 ID (例: costume_head_hski-cstm-0002)</string>
|
||||
<string name="live_custome_dress_id">Live 自定义服装 ID (例: hski-cstm-0002)</string>
|
||||
@@ -16,6 +17,7 @@
|
||||
<string name="text_hook_test_mode">文本 hook 测试模式</string>
|
||||
<string name="export_text">导出文本</string>
|
||||
<string name="force_export_resource">启动后强制导出资源</string>
|
||||
<string name="login_as_ios">以 iOS 登陆</string>
|
||||
<string name="max_high">极高</string>
|
||||
<string name="very_high">超高</string>
|
||||
<string name="hign">高</string>
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
<string name="start_game">Start Game / Hot Reload Config</string>
|
||||
<string name="setFpsTitle">Max FPS (0 is Use Original Settings)</string>
|
||||
<string name="unlockAllLive">Unlock All Live</string>
|
||||
<string name="unlockAllLiveCostume">Unlock All Live Costume</string>
|
||||
<string name="liveUseCustomeDress">Live Custom Character</string>
|
||||
<string name="live_costume_head_id">Live Custom Head ID (eg. costume_head_hski-cstm-0002)</string>
|
||||
<string name="live_custome_dress_id">Live Custom Dress ID (eg. hski-cstm-0002)</string>
|
||||
@@ -16,6 +17,7 @@
|
||||
<string name="text_hook_test_mode">Text Hook Test Mode</string>
|
||||
<string name="export_text">Export Text</string>
|
||||
<string name="force_export_resource">Force Update Resource</string>
|
||||
<string name="login_as_ios">Login as iOS</string>
|
||||
<string name="max_high">Ultra</string>
|
||||
<string name="very_high">Very High</string>
|
||||
<string name="hign">High</string>
|
||||
|
||||
Reference in New Issue
Block a user