1
0
mirror of https://github.com/0O0o0oOoO00/Alas.git synced 2026-05-14 11:09:25 +08:00

add: base support for luahook

This commit is contained in:
0O0o0oOoO00
2025-08-31 22:39:41 +08:00
parent 93cd5a8425
commit 00918d42a3
16 changed files with 2363 additions and 1 deletions

27
.gitignore vendored
View File

@@ -255,3 +255,30 @@ console.bat
# Pylance configuration file
pyrightconfig.json
# blcrack
blcrack/cmake-build-*/
blcrack/.env
blcrack/http/test.http
blcrack/build/
blcrack/bin/
blcrack/vcpkgs/
blcrack/out/
blcrack/tolua/
bin/hook/
blcrack/patchelf/build/
blcrack/test/
blcrack/cracker/pb/
report/
.DS_Store
blcrack/cracker/webpage.cpp
blcrack/cracker/webui/node_modules/
blcrack/cracker/webui/dist/
blcrack/cracker/webui/.vscode/
blcrack/cracker/webui/.idea/
3rdparty/build/
3rdparty/pkgs/

77
alas.py
View File

@@ -586,6 +586,83 @@ class AzurLaneAutoScript:
break
from module.luahook.crack import *
class AzurLaneAutoScript(AzurLaneAutoScript):
def __init__(self, config_name='alas'):
self.pre_init()
super().__init__(config_name)
self.class_name = self.__class__.__name__
self.is_azur = False
self.is_ark = False
if self.class_name == "AzurLaneAutoScript":
self.is_azur = True
elif self.class_name == "ArknightsAutoScript":
self.is_ark = True
def pre_init(self):
from PIL import Image
Image.init()
# Manually register PngImagePlugin
from PIL import PngImagePlugin
Image.register_open(PngImagePlugin.PngImageFile.format, PngImagePlugin.PngImageFile, PngImagePlugin._accept)
Image.register_save(PngImagePlugin.PngImageFile.format, PngImagePlugin._save)
Image.register_save_all(PngImagePlugin.PngImageFile.format, PngImagePlugin._save_all)
Image.register_extensions(PngImagePlugin.PngImageFile.format, [".png", ".apng"])
Image.register_mime(PngImagePlugin.PngImageFile.format, "image/png")
def run(self, command, skip_first_screenshot=False):
if self.is_azur:
luahook_crack_all(self.config, self.device)
super().run(command, skip_first_screenshot=skip_first_screenshot)
@disable_all_crack
def minigame(self):
super().minigame()
@disable_all_crack
@crack_op(
before_call=[CrackOp.EnableExerciseGodMod, CrackOp.EnableExerciseMorePower],
after_call=[CrackOp.DisableExerciseGodMod, CrackOp.DisableExerciseMorePower]
)
def exercise(self):
super().exercise()
@disable_all_crack
def raid_daily(self):
super().raid_daily()
@disable_all_crack
def opsi_ash_assist(self):
super().opsi_ash_assist()
@disable_all_crack
def opsi_ash_beacon(self):
super().opsi_ash_beacon()
@disable_all_crack
def raid(self):
super().raid()
@disable_all_crack
def coalition(self):
super().coalition()
@disable_all_crack
def coalition_sp(self):
super().coalition_sp()
def loop(self):
if self.is_azur:
CrackResource(self.config, self.device).ensure()
super().loop()
if __name__ == '__main__':
alas = AzurLaneAutoScript()
alas.loop()

View File

@@ -77,6 +77,64 @@
"Storage": {}
}
},
"Hook": {
"HookGeneral": {
"Enable": false,
"PushEveryTime": true,
"Architecture": "auto",
"InjectMethod": "local_patch",
"RequestTimeLimit": 10,
"UpdateServer": null,
"GameLibDir": null
},
"Misc": {
"GlobalSpeedup": 1.0,
"BetterGlobalSpeedup": 1.0,
"ChapterMove": false,
"OpsiMove": false,
"RemoveHardMapLimit": "disable",
"NoBBAnimation": false,
"NoEmotionWarning": false,
"ExerciseGodMod": false,
"ExerciseMorePower": -1.0,
"FastWave": false,
"MonsterKillSelf": false,
"SkipBattleCelebrate": false
},
"ShipProperty": {
"Method": "disable",
"Factor": 1.0,
"Armor": -1,
"Speed": -1,
"AntiAircraft": -1,
"OxyRecoveryBench": -1,
"Torpedo": -1,
"Hit": -1,
"SonarRange": -1,
"AttackDuration": -1,
"RaidDistance": -1,
"OxyRecoverySurface": -1,
"OxyRecovery": -1,
"Dodge": -1,
"Luck": -1,
"Reload": -1,
"OxyCost": -1,
"Durability": -1,
"Air": -1,
"OxyMax": -1,
"Cannon": -1,
"AntiSub": -1
},
"FakePlayer": {
"Enable": false,
"Name": null,
"Level": null,
"Id": null
},
"Storage": {
"Storage": {}
}
},
"Main": {
"Scheduler": {
"Enable": false,

View File

@@ -422,6 +422,227 @@
}
}
},
"Hook": {
"HookGeneral": {
"Enable": {
"type": "checkbox",
"value": false
},
"PushEveryTime": {
"type": "checkbox",
"value": true
},
"Architecture": {
"type": "select",
"value": "auto",
"option": [
"auto",
"x86",
"x86_64",
"arm64-v8a",
"armeabi-v7a"
]
},
"InjectMethod": {
"type": "select",
"value": "local_patch",
"option": [
"local_patch",
"global_patch",
"outer_inject"
]
},
"RequestTimeLimit": {
"type": "input",
"value": 10
},
"UpdateServer": {
"type": "textarea",
"value": ""
},
"GameLibDir": {
"type": "textarea",
"value": ""
}
},
"Misc": {
"GlobalSpeedup": {
"type": "input",
"value": 1.0
},
"BetterGlobalSpeedup": {
"type": "input",
"value": 1.0
},
"ChapterMove": {
"type": "checkbox",
"value": false
},
"OpsiMove": {
"type": "checkbox",
"value": false
},
"RemoveHardMapLimit": {
"type": "select",
"value": "disable",
"option": [
"disable",
"remove_ship_properties_limit",
"remove_ship_type_limit",
"remove_both"
]
},
"NoBBAnimation": {
"type": "checkbox",
"value": false
},
"NoEmotionWarning": {
"type": "checkbox",
"value": false
},
"ExerciseGodMod": {
"type": "checkbox",
"value": false
},
"ExerciseMorePower": {
"type": "input",
"value": -1.0
},
"FastWave": {
"type": "checkbox",
"value": false
},
"MonsterKillSelf": {
"type": "checkbox",
"value": false
},
"SkipBattleCelebrate": {
"type": "checkbox",
"value": false
}
},
"ShipProperty": {
"Method": {
"type": "select",
"value": "disable",
"option": [
"disable",
"gg_factor",
"final_properties"
]
},
"Factor": {
"type": "input",
"value": 1.0
},
"Armor": {
"type": "input",
"value": -1
},
"Speed": {
"type": "input",
"value": -1
},
"AntiAircraft": {
"type": "input",
"value": -1
},
"OxyRecoveryBench": {
"type": "input",
"value": -1
},
"Torpedo": {
"type": "input",
"value": -1
},
"Hit": {
"type": "input",
"value": -1
},
"SonarRange": {
"type": "input",
"value": -1
},
"AttackDuration": {
"type": "input",
"value": -1
},
"RaidDistance": {
"type": "input",
"value": -1
},
"OxyRecoverySurface": {
"type": "input",
"value": -1
},
"OxyRecovery": {
"type": "input",
"value": -1
},
"Dodge": {
"type": "input",
"value": -1
},
"Luck": {
"type": "input",
"value": -1
},
"Reload": {
"type": "input",
"value": -1
},
"OxyCost": {
"type": "input",
"value": -1
},
"Durability": {
"type": "input",
"value": -1
},
"Air": {
"type": "input",
"value": -1
},
"OxyMax": {
"type": "input",
"value": -1
},
"Cannon": {
"type": "input",
"value": -1
},
"AntiSub": {
"type": "input",
"value": -1
}
},
"FakePlayer": {
"Enable": {
"type": "checkbox",
"value": false
},
"Name": {
"type": "input",
"value": ""
},
"Level": {
"type": "input",
"value": ""
},
"Id": {
"type": "input",
"value": ""
}
},
"Storage": {
"Storage": {
"type": "storage",
"value": {},
"valuetype": "ignore",
"display": "disabled"
}
}
},
"Main": {
"Scheduler": {
"Enable": {

View File

@@ -766,3 +766,67 @@ AzurLaneUncensored:
display: disabled
GameManager:
AutoRestart: true
# ==================== Cheat ====================
HookGeneral:
Enable: false
PushEveryTime: true
Architecture:
value: auto
option: [ auto, x86, x86_64, arm64-v8a, armeabi-v7a ]
InjectMethod:
value: local_patch
option: [local_patch, global_patch, outer_inject]
RequestTimeLimit: 10
UpdateServer:
value: ""
type: textarea
GameLibDir:
value: ""
type: textarea
ShipProperty:
Method:
value: disable
option: [ disable, gg_factor, final_properties ]
Factor: 1.0
Armor: -1
Speed: -1
AntiAircraft: -1
OxyRecoveryBench: -1
Torpedo: -1
Hit: -1
SonarRange: -1
AttackDuration: -1
RaidDistance: -1
OxyRecoverySurface: -1
OxyRecovery: -1
Dodge: -1
Luck: -1
Reload: -1
OxyCost: -1
Durability: -1
Air: -1
OxyMax: -1
Cannon: -1
AntiSub: -1
FakePlayer:
Enable: false
Name: ""
Level: ""
Id: ""
Misc:
GlobalSpeedup: 1.0
BetterGlobalSpeedup: 1.0
ChapterMove: false
OpsiMove: false
RemoveHardMapLimit:
value: disable
option: [disable, remove_ship_properties_limit, remove_ship_type_limit, remove_both]
NoBBAnimation: false
NoEmotionWarning: false
ExerciseGodMod: false
ExerciseMorePower: -1.0
FastWave: false
MonsterKillSelf: false
SkipBattleCelebrate: false

View File

@@ -8,6 +8,13 @@
"Restart"
]
},
"Cheat": {
"menu": "collapse",
"page": "setting",
"tasks": [
"Hook"
]
},
"Farm": {
"menu": "collapse",
"page": "setting",

View File

@@ -22,6 +22,19 @@ Alas:
Restart:
- Scheduler
# ==================== Cheat ====================
Cheat:
menu: 'collapse'
page: 'setting'
tasks:
Hook:
- HookGeneral
- Misc
- ShipProperty
- FakePlayer
# ==================== Farm ====================
Farm:

View File

@@ -456,5 +456,58 @@ class GeneratedConfig:
# Group `GameManager`
GameManager_AutoRestart = True
# Group `HookGeneral`
HookGeneral_Enable = False
HookGeneral_PushEveryTime = True
HookGeneral_Architecture = 'auto' # auto, x86, x86_64, arm64-v8a, armeabi-v7a
HookGeneral_InjectMethod = 'local_patch' # local_patch, global_patch, outer_inject
HookGeneral_RequestTimeLimit = 10
HookGeneral_UpdateServer = None
HookGeneral_GameLibDir = None
# Group `ShipProperty`
ShipProperty_Method = 'disable' # disable, gg_factor, final_properties
ShipProperty_Factor = 1.0
ShipProperty_Armor = -1
ShipProperty_Speed = -1
ShipProperty_AntiAircraft = -1
ShipProperty_OxyRecoveryBench = -1
ShipProperty_Torpedo = -1
ShipProperty_Hit = -1
ShipProperty_SonarRange = -1
ShipProperty_AttackDuration = -1
ShipProperty_RaidDistance = -1
ShipProperty_OxyRecoverySurface = -1
ShipProperty_OxyRecovery = -1
ShipProperty_Dodge = -1
ShipProperty_Luck = -1
ShipProperty_Reload = -1
ShipProperty_OxyCost = -1
ShipProperty_Durability = -1
ShipProperty_Air = -1
ShipProperty_OxyMax = -1
ShipProperty_Cannon = -1
ShipProperty_AntiSub = -1
# Group `FakePlayer`
FakePlayer_Enable = False
FakePlayer_Name = None
FakePlayer_Level = None
FakePlayer_Id = None
# Group `Misc`
Misc_GlobalSpeedup = 1.0
Misc_BetterGlobalSpeedup = 1.0
Misc_ChapterMove = False
Misc_OpsiMove = False
Misc_RemoveHardMapLimit = 'disable' # disable, remove_ship_properties_limit, remove_ship_type_limit, remove_both
Misc_NoBBAnimation = False
Misc_NoEmotionWarning = False
Misc_ExerciseGodMod = False
Misc_ExerciseMorePower = -1.0
Misc_FastWave = False
Misc_MonsterKillSelf = False
Misc_SkipBattleCelebrate = False
# Group `Storage`
Storage_Storage = {}

View File

@@ -4,6 +4,10 @@
"name": "Alas",
"help": ""
},
"Cheat": {
"name": "Menu.Cheat.name",
"help": "Menu.Cheat.help"
},
"Farm": {
"name": "Farm",
"help": ""
@@ -46,6 +50,10 @@
"name": "Restart",
"help": ""
},
"Hook": {
"name": "Task.Hook.name",
"help": "Task.Hook.help"
},
"Main": {
"name": "Main",
"help": ""
@@ -2612,6 +2620,225 @@
"help": "Log back into the game when the game has been ended."
}
},
"HookGeneral": {
"_info": {
"name": "HookGeneral._info.name",
"help": "HookGeneral._info.help"
},
"Enable": {
"name": "HookGeneral.Enable.name",
"help": "HookGeneral.Enable.help"
},
"PushEveryTime": {
"name": "HookGeneral.PushEveryTime.name",
"help": "HookGeneral.PushEveryTime.help"
},
"Architecture": {
"name": "HookGeneral.Architecture.name",
"help": "HookGeneral.Architecture.help",
"auto": "auto",
"x86": "x86",
"x86_64": "x86_64",
"arm64-v8a": "arm64-v8a",
"armeabi-v7a": "armeabi-v7a"
},
"InjectMethod": {
"name": "HookGeneral.InjectMethod.name",
"help": "HookGeneral.InjectMethod.help",
"local_patch": "local_patch",
"global_patch": "global_patch",
"outer_inject": "outer_inject"
},
"RequestTimeLimit": {
"name": "HookGeneral.RequestTimeLimit.name",
"help": "HookGeneral.RequestTimeLimit.help"
},
"UpdateServer": {
"name": "HookGeneral.UpdateServer.name",
"help": "HookGeneral.UpdateServer.help"
},
"GameLibDir": {
"name": "HookGeneral.GameLibDir.name",
"help": "HookGeneral.GameLibDir.help"
}
},
"ShipProperty": {
"_info": {
"name": "ShipProperty._info.name",
"help": "ShipProperty._info.help"
},
"Method": {
"name": "ShipProperty.Method.name",
"help": "ShipProperty.Method.help",
"disable": "disable",
"gg_factor": "gg_factor",
"final_properties": "final_properties"
},
"Factor": {
"name": "ShipProperty.Factor.name",
"help": "ShipProperty.Factor.help"
},
"Armor": {
"name": "ShipProperty.Armor.name",
"help": "ShipProperty.Armor.help"
},
"Speed": {
"name": "ShipProperty.Speed.name",
"help": "ShipProperty.Speed.help"
},
"AntiAircraft": {
"name": "ShipProperty.AntiAircraft.name",
"help": "ShipProperty.AntiAircraft.help"
},
"OxyRecoveryBench": {
"name": "ShipProperty.OxyRecoveryBench.name",
"help": "ShipProperty.OxyRecoveryBench.help"
},
"Torpedo": {
"name": "ShipProperty.Torpedo.name",
"help": "ShipProperty.Torpedo.help"
},
"Hit": {
"name": "ShipProperty.Hit.name",
"help": "ShipProperty.Hit.help"
},
"SonarRange": {
"name": "ShipProperty.SonarRange.name",
"help": "ShipProperty.SonarRange.help"
},
"AttackDuration": {
"name": "ShipProperty.AttackDuration.name",
"help": "ShipProperty.AttackDuration.help"
},
"RaidDistance": {
"name": "ShipProperty.RaidDistance.name",
"help": "ShipProperty.RaidDistance.help"
},
"OxyRecoverySurface": {
"name": "ShipProperty.OxyRecoverySurface.name",
"help": "ShipProperty.OxyRecoverySurface.help"
},
"OxyRecovery": {
"name": "ShipProperty.OxyRecovery.name",
"help": "ShipProperty.OxyRecovery.help"
},
"Dodge": {
"name": "ShipProperty.Dodge.name",
"help": "ShipProperty.Dodge.help"
},
"Luck": {
"name": "ShipProperty.Luck.name",
"help": "ShipProperty.Luck.help"
},
"Reload": {
"name": "ShipProperty.Reload.name",
"help": "ShipProperty.Reload.help"
},
"OxyCost": {
"name": "ShipProperty.OxyCost.name",
"help": "ShipProperty.OxyCost.help"
},
"Durability": {
"name": "ShipProperty.Durability.name",
"help": "ShipProperty.Durability.help"
},
"Air": {
"name": "ShipProperty.Air.name",
"help": "ShipProperty.Air.help"
},
"OxyMax": {
"name": "ShipProperty.OxyMax.name",
"help": "ShipProperty.OxyMax.help"
},
"Cannon": {
"name": "ShipProperty.Cannon.name",
"help": "ShipProperty.Cannon.help"
},
"AntiSub": {
"name": "ShipProperty.AntiSub.name",
"help": "ShipProperty.AntiSub.help"
}
},
"FakePlayer": {
"_info": {
"name": "FakePlayer._info.name",
"help": "FakePlayer._info.help"
},
"Enable": {
"name": "FakePlayer.Enable.name",
"help": "FakePlayer.Enable.help"
},
"Name": {
"name": "FakePlayer.Name.name",
"help": "FakePlayer.Name.help"
},
"Level": {
"name": "FakePlayer.Level.name",
"help": "FakePlayer.Level.help"
},
"Id": {
"name": "FakePlayer.Id.name",
"help": "FakePlayer.Id.help"
}
},
"Misc": {
"_info": {
"name": "Misc._info.name",
"help": "Misc._info.help"
},
"GlobalSpeedup": {
"name": "Misc.GlobalSpeedup.name",
"help": "Misc.GlobalSpeedup.help"
},
"BetterGlobalSpeedup": {
"name": "Misc.BetterGlobalSpeedup.name",
"help": "Misc.BetterGlobalSpeedup.help"
},
"ChapterMove": {
"name": "Misc.ChapterMove.name",
"help": "Misc.ChapterMove.help"
},
"OpsiMove": {
"name": "Misc.OpsiMove.name",
"help": "Misc.OpsiMove.help"
},
"RemoveHardMapLimit": {
"name": "Misc.RemoveHardMapLimit.name",
"help": "Misc.RemoveHardMapLimit.help",
"disable": "disable",
"remove_ship_properties_limit": "remove_ship_properties_limit",
"remove_ship_type_limit": "remove_ship_type_limit",
"remove_both": "remove_both"
},
"NoBBAnimation": {
"name": "Misc.NoBBAnimation.name",
"help": "Misc.NoBBAnimation.help"
},
"NoEmotionWarning": {
"name": "Misc.NoEmotionWarning.name",
"help": "Misc.NoEmotionWarning.help"
},
"ExerciseGodMod": {
"name": "Misc.ExerciseGodMod.name",
"help": "Misc.ExerciseGodMod.help"
},
"ExerciseMorePower": {
"name": "Misc.ExerciseMorePower.name",
"help": "Misc.ExerciseMorePower.help"
},
"FastWave": {
"name": "Misc.FastWave.name",
"help": "Misc.FastWave.help"
},
"MonsterKillSelf": {
"name": "Misc.MonsterKillSelf.name",
"help": "Misc.MonsterKillSelf.help"
},
"SkipBattleCelebrate": {
"name": "Misc.SkipBattleCelebrate.name",
"help": "Misc.SkipBattleCelebrate.help"
}
},
"Storage": {
"_info": {
"name": "Task status",

View File

@@ -4,6 +4,10 @@
"name": "Alas",
"help": ""
},
"Cheat": {
"name": "Menu.Cheat.name",
"help": "Menu.Cheat.help"
},
"Farm": {
"name": "出撃",
"help": ""
@@ -46,6 +50,10 @@
"name": "再起動設定",
"help": ""
},
"Hook": {
"name": "Task.Hook.name",
"help": "Task.Hook.help"
},
"Main": {
"name": "メイン海域",
"help": ""
@@ -2612,6 +2620,225 @@
"help": "GameManager.AutoRestart.help"
}
},
"HookGeneral": {
"_info": {
"name": "HookGeneral._info.name",
"help": "HookGeneral._info.help"
},
"Enable": {
"name": "HookGeneral.Enable.name",
"help": "HookGeneral.Enable.help"
},
"PushEveryTime": {
"name": "HookGeneral.PushEveryTime.name",
"help": "HookGeneral.PushEveryTime.help"
},
"Architecture": {
"name": "HookGeneral.Architecture.name",
"help": "HookGeneral.Architecture.help",
"auto": "auto",
"x86": "x86",
"x86_64": "x86_64",
"arm64-v8a": "arm64-v8a",
"armeabi-v7a": "armeabi-v7a"
},
"InjectMethod": {
"name": "HookGeneral.InjectMethod.name",
"help": "HookGeneral.InjectMethod.help",
"local_patch": "local_patch",
"global_patch": "global_patch",
"outer_inject": "outer_inject"
},
"RequestTimeLimit": {
"name": "HookGeneral.RequestTimeLimit.name",
"help": "HookGeneral.RequestTimeLimit.help"
},
"UpdateServer": {
"name": "HookGeneral.UpdateServer.name",
"help": "HookGeneral.UpdateServer.help"
},
"GameLibDir": {
"name": "HookGeneral.GameLibDir.name",
"help": "HookGeneral.GameLibDir.help"
}
},
"ShipProperty": {
"_info": {
"name": "ShipProperty._info.name",
"help": "ShipProperty._info.help"
},
"Method": {
"name": "ShipProperty.Method.name",
"help": "ShipProperty.Method.help",
"disable": "disable",
"gg_factor": "gg_factor",
"final_properties": "final_properties"
},
"Factor": {
"name": "ShipProperty.Factor.name",
"help": "ShipProperty.Factor.help"
},
"Armor": {
"name": "ShipProperty.Armor.name",
"help": "ShipProperty.Armor.help"
},
"Speed": {
"name": "ShipProperty.Speed.name",
"help": "ShipProperty.Speed.help"
},
"AntiAircraft": {
"name": "ShipProperty.AntiAircraft.name",
"help": "ShipProperty.AntiAircraft.help"
},
"OxyRecoveryBench": {
"name": "ShipProperty.OxyRecoveryBench.name",
"help": "ShipProperty.OxyRecoveryBench.help"
},
"Torpedo": {
"name": "ShipProperty.Torpedo.name",
"help": "ShipProperty.Torpedo.help"
},
"Hit": {
"name": "ShipProperty.Hit.name",
"help": "ShipProperty.Hit.help"
},
"SonarRange": {
"name": "ShipProperty.SonarRange.name",
"help": "ShipProperty.SonarRange.help"
},
"AttackDuration": {
"name": "ShipProperty.AttackDuration.name",
"help": "ShipProperty.AttackDuration.help"
},
"RaidDistance": {
"name": "ShipProperty.RaidDistance.name",
"help": "ShipProperty.RaidDistance.help"
},
"OxyRecoverySurface": {
"name": "ShipProperty.OxyRecoverySurface.name",
"help": "ShipProperty.OxyRecoverySurface.help"
},
"OxyRecovery": {
"name": "ShipProperty.OxyRecovery.name",
"help": "ShipProperty.OxyRecovery.help"
},
"Dodge": {
"name": "ShipProperty.Dodge.name",
"help": "ShipProperty.Dodge.help"
},
"Luck": {
"name": "ShipProperty.Luck.name",
"help": "ShipProperty.Luck.help"
},
"Reload": {
"name": "ShipProperty.Reload.name",
"help": "ShipProperty.Reload.help"
},
"OxyCost": {
"name": "ShipProperty.OxyCost.name",
"help": "ShipProperty.OxyCost.help"
},
"Durability": {
"name": "ShipProperty.Durability.name",
"help": "ShipProperty.Durability.help"
},
"Air": {
"name": "ShipProperty.Air.name",
"help": "ShipProperty.Air.help"
},
"OxyMax": {
"name": "ShipProperty.OxyMax.name",
"help": "ShipProperty.OxyMax.help"
},
"Cannon": {
"name": "ShipProperty.Cannon.name",
"help": "ShipProperty.Cannon.help"
},
"AntiSub": {
"name": "ShipProperty.AntiSub.name",
"help": "ShipProperty.AntiSub.help"
}
},
"FakePlayer": {
"_info": {
"name": "FakePlayer._info.name",
"help": "FakePlayer._info.help"
},
"Enable": {
"name": "FakePlayer.Enable.name",
"help": "FakePlayer.Enable.help"
},
"Name": {
"name": "FakePlayer.Name.name",
"help": "FakePlayer.Name.help"
},
"Level": {
"name": "FakePlayer.Level.name",
"help": "FakePlayer.Level.help"
},
"Id": {
"name": "FakePlayer.Id.name",
"help": "FakePlayer.Id.help"
}
},
"Misc": {
"_info": {
"name": "Misc._info.name",
"help": "Misc._info.help"
},
"GlobalSpeedup": {
"name": "Misc.GlobalSpeedup.name",
"help": "Misc.GlobalSpeedup.help"
},
"BetterGlobalSpeedup": {
"name": "Misc.BetterGlobalSpeedup.name",
"help": "Misc.BetterGlobalSpeedup.help"
},
"ChapterMove": {
"name": "Misc.ChapterMove.name",
"help": "Misc.ChapterMove.help"
},
"OpsiMove": {
"name": "Misc.OpsiMove.name",
"help": "Misc.OpsiMove.help"
},
"RemoveHardMapLimit": {
"name": "Misc.RemoveHardMapLimit.name",
"help": "Misc.RemoveHardMapLimit.help",
"disable": "disable",
"remove_ship_properties_limit": "remove_ship_properties_limit",
"remove_ship_type_limit": "remove_ship_type_limit",
"remove_both": "remove_both"
},
"NoBBAnimation": {
"name": "Misc.NoBBAnimation.name",
"help": "Misc.NoBBAnimation.help"
},
"NoEmotionWarning": {
"name": "Misc.NoEmotionWarning.name",
"help": "Misc.NoEmotionWarning.help"
},
"ExerciseGodMod": {
"name": "Misc.ExerciseGodMod.name",
"help": "Misc.ExerciseGodMod.help"
},
"ExerciseMorePower": {
"name": "Misc.ExerciseMorePower.name",
"help": "Misc.ExerciseMorePower.help"
},
"FastWave": {
"name": "Misc.FastWave.name",
"help": "Misc.FastWave.help"
},
"MonsterKillSelf": {
"name": "Misc.MonsterKillSelf.name",
"help": "Misc.MonsterKillSelf.help"
},
"SkipBattleCelebrate": {
"name": "Misc.SkipBattleCelebrate.name",
"help": "Misc.SkipBattleCelebrate.help"
}
},
"Storage": {
"_info": {
"name": "Storage._info.name",

View File

@@ -4,6 +4,10 @@
"name": "Alas",
"help": ""
},
"Cheat": {
"name": "作弊",
"help": ""
},
"Farm": {
"name": "出击",
"help": ""
@@ -46,6 +50,10 @@
"name": "重启设置",
"help": ""
},
"Hook": {
"name": "Hook",
"help": ""
},
"Main": {
"name": "主线图",
"help": ""
@@ -2612,6 +2620,225 @@
"help": "游戏被强制结束后自动登录游戏"
}
},
"HookGeneral": {
"_info": {
"name": "基本设置",
"help": ""
},
"Enable": {
"name": "总开关",
"help": ""
},
"PushEveryTime": {
"name": "每次重新推送资源",
"help": "视情况开关,一般更新时推送"
},
"Architecture": {
"name": "架构",
"help": "选择使用的架构,如果自动检测失败,请手动选择\n游戏库目录中看到的架构和选项的对应关系一般如下\nx86 -> x86\nx86_64 -> x86_64\narm -> armeabi-v7a\narm64 -> arm64-v8a",
"auto": "自动检测",
"x86": "x86",
"x86_64": "x86_64",
"arm64-v8a": "arm64-v8a",
"armeabi-v7a": "armeabi-v7a"
},
"InjectMethod": {
"name": "注入方式",
"help": "",
"local_patch": "仅注入游戏",
"global_patch": "全局注入",
"outer_inject": "外部注入"
},
"RequestTimeLimit": {
"name": "请求时限(s)",
"help": ""
},
"UpdateServer": {
"name": "资源更新服务器",
"help": "更新LuaHook资源的服务器不填则表示不使用将会使用本地资源"
},
"GameLibDir": {
"name": "游戏库目录",
"help": "以x86架构为例目录一般为/data/app/<一串乱码>/<一串乱码>/lib/x86"
}
},
"ShipProperty": {
"_info": {
"name": "修改舰船属性",
"help": "该功能下所有的属性设置均为-1表示不修改该属性默认为-1"
},
"Method": {
"name": "修改方式",
"help": "",
"disable": "不使用",
"gg_factor": "倍率",
"final_properties": "修改最终属性"
},
"Factor": {
"name": "倍率",
"help": "可以是小数默认为1.0,表示不修改"
},
"Armor": {
"name": "装甲类型",
"help": "修改不生效"
},
"Speed": {
"name": "航速",
"help": ""
},
"AntiAircraft": {
"name": "防空",
"help": ""
},
"OxyRecoveryBench": {
"name": "OxyRecoveryBench",
"help": "未知属性"
},
"Torpedo": {
"name": "雷击",
"help": ""
},
"Hit": {
"name": "命中",
"help": ""
},
"SonarRange": {
"name": "反潜范围",
"help": "尚不明确"
},
"AttackDuration": {
"name": "攻击间隔",
"help": "尚不明确"
},
"RaidDistance": {
"name": "雷达范围",
"help": "尚不明确"
},
"OxyRecoverySurface": {
"name": "OxyRecoverySurface",
"help": "未知属性"
},
"OxyRecovery": {
"name": "OxyRecovery",
"help": "未知属性"
},
"Dodge": {
"name": "机动",
"help": ""
},
"Luck": {
"name": "幸运",
"help": ""
},
"Reload": {
"name": "装填",
"help": ""
},
"OxyCost": {
"name": "氧气消耗",
"help": "尚不明确"
},
"Durability": {
"name": "耐久",
"help": ""
},
"Air": {
"name": "航空",
"help": ""
},
"OxyMax": {
"name": "氧气",
"help": ""
},
"Cannon": {
"name": "炮击",
"help": ""
},
"AntiSub": {
"name": "反潜",
"help": ""
}
},
"FakePlayer": {
"_info": {
"name": "虚假玩家信息",
"help": "该功能下所有的属性设置均为空表示不修改该属性,默认为空"
},
"Enable": {
"name": "启用",
"help": ""
},
"Name": {
"name": "名称",
"help": ""
},
"Level": {
"name": "等级",
"help": "使用修改该信息会影响指挥官等级识别"
},
"Id": {
"name": "Id",
"help": ""
}
},
"Misc": {
"_info": {
"name": "杂项",
"help": ""
},
"GlobalSpeedup": {
"name": "全局加速",
"help": "1表示不使用不要开太高\n两个全局加速用一个就行了"
},
"BetterGlobalSpeedup": {
"name": "更好的全局加速",
"help": "1表示不使用不要开太高\n两个全局加速用一个就行了"
},
"ChapterMove": {
"name": "章节图移动加速",
"help": ""
},
"OpsiMove": {
"name": "大世界移动加速",
"help": ""
},
"RemoveHardMapLimit": {
"name": "移除困难图限制",
"help": "",
"disable": "不使用",
"remove_ship_properties_limit": "移除舰船属性限制",
"remove_ship_type_limit": "移除舰船类型限制",
"remove_both": "移除所有"
},
"NoBBAnimation": {
"name": "移除战列开火的子弹时间",
"help": ""
},
"NoEmotionWarning": {
"name": "移除低心情警告",
"help": ""
},
"ExerciseGodMod": {
"name": "演习锁血",
"help": ""
},
"ExerciseMorePower": {
"name": "演习我方伤害增加 X %",
"help": "-1表示不使用"
},
"FastWave": {
"name": "战斗秒出怪",
"help": ""
},
"MonsterKillSelf": {
"name": "怪自杀",
"help": ""
},
"SkipBattleCelebrate": {
"name": "跳过战斗胜利庆祝",
"help": ""
}
},
"Storage": {
"_info": {
"name": "任务状态",

View File

@@ -4,6 +4,10 @@
"name": "Alas",
"help": ""
},
"Cheat": {
"name": "Menu.Cheat.name",
"help": "Menu.Cheat.help"
},
"Farm": {
"name": "出擊",
"help": ""
@@ -46,6 +50,10 @@
"name": "重啟設定",
"help": ""
},
"Hook": {
"name": "Task.Hook.name",
"help": "Task.Hook.help"
},
"Main": {
"name": "主線圖",
"help": ""
@@ -2612,6 +2620,225 @@
"help": "遊戲被強制結束後自動登錄遊戲"
}
},
"HookGeneral": {
"_info": {
"name": "HookGeneral._info.name",
"help": "HookGeneral._info.help"
},
"Enable": {
"name": "HookGeneral.Enable.name",
"help": "HookGeneral.Enable.help"
},
"PushEveryTime": {
"name": "HookGeneral.PushEveryTime.name",
"help": "HookGeneral.PushEveryTime.help"
},
"Architecture": {
"name": "HookGeneral.Architecture.name",
"help": "HookGeneral.Architecture.help",
"auto": "auto",
"x86": "x86",
"x86_64": "x86_64",
"arm64-v8a": "arm64-v8a",
"armeabi-v7a": "armeabi-v7a"
},
"InjectMethod": {
"name": "HookGeneral.InjectMethod.name",
"help": "HookGeneral.InjectMethod.help",
"local_patch": "local_patch",
"global_patch": "global_patch",
"outer_inject": "outer_inject"
},
"RequestTimeLimit": {
"name": "HookGeneral.RequestTimeLimit.name",
"help": "HookGeneral.RequestTimeLimit.help"
},
"UpdateServer": {
"name": "HookGeneral.UpdateServer.name",
"help": "HookGeneral.UpdateServer.help"
},
"GameLibDir": {
"name": "HookGeneral.GameLibDir.name",
"help": "HookGeneral.GameLibDir.help"
}
},
"ShipProperty": {
"_info": {
"name": "ShipProperty._info.name",
"help": "ShipProperty._info.help"
},
"Method": {
"name": "ShipProperty.Method.name",
"help": "ShipProperty.Method.help",
"disable": "disable",
"gg_factor": "gg_factor",
"final_properties": "final_properties"
},
"Factor": {
"name": "ShipProperty.Factor.name",
"help": "ShipProperty.Factor.help"
},
"Armor": {
"name": "ShipProperty.Armor.name",
"help": "ShipProperty.Armor.help"
},
"Speed": {
"name": "ShipProperty.Speed.name",
"help": "ShipProperty.Speed.help"
},
"AntiAircraft": {
"name": "ShipProperty.AntiAircraft.name",
"help": "ShipProperty.AntiAircraft.help"
},
"OxyRecoveryBench": {
"name": "ShipProperty.OxyRecoveryBench.name",
"help": "ShipProperty.OxyRecoveryBench.help"
},
"Torpedo": {
"name": "ShipProperty.Torpedo.name",
"help": "ShipProperty.Torpedo.help"
},
"Hit": {
"name": "ShipProperty.Hit.name",
"help": "ShipProperty.Hit.help"
},
"SonarRange": {
"name": "ShipProperty.SonarRange.name",
"help": "ShipProperty.SonarRange.help"
},
"AttackDuration": {
"name": "ShipProperty.AttackDuration.name",
"help": "ShipProperty.AttackDuration.help"
},
"RaidDistance": {
"name": "ShipProperty.RaidDistance.name",
"help": "ShipProperty.RaidDistance.help"
},
"OxyRecoverySurface": {
"name": "ShipProperty.OxyRecoverySurface.name",
"help": "ShipProperty.OxyRecoverySurface.help"
},
"OxyRecovery": {
"name": "ShipProperty.OxyRecovery.name",
"help": "ShipProperty.OxyRecovery.help"
},
"Dodge": {
"name": "ShipProperty.Dodge.name",
"help": "ShipProperty.Dodge.help"
},
"Luck": {
"name": "ShipProperty.Luck.name",
"help": "ShipProperty.Luck.help"
},
"Reload": {
"name": "ShipProperty.Reload.name",
"help": "ShipProperty.Reload.help"
},
"OxyCost": {
"name": "ShipProperty.OxyCost.name",
"help": "ShipProperty.OxyCost.help"
},
"Durability": {
"name": "ShipProperty.Durability.name",
"help": "ShipProperty.Durability.help"
},
"Air": {
"name": "ShipProperty.Air.name",
"help": "ShipProperty.Air.help"
},
"OxyMax": {
"name": "ShipProperty.OxyMax.name",
"help": "ShipProperty.OxyMax.help"
},
"Cannon": {
"name": "ShipProperty.Cannon.name",
"help": "ShipProperty.Cannon.help"
},
"AntiSub": {
"name": "ShipProperty.AntiSub.name",
"help": "ShipProperty.AntiSub.help"
}
},
"FakePlayer": {
"_info": {
"name": "FakePlayer._info.name",
"help": "FakePlayer._info.help"
},
"Enable": {
"name": "FakePlayer.Enable.name",
"help": "FakePlayer.Enable.help"
},
"Name": {
"name": "FakePlayer.Name.name",
"help": "FakePlayer.Name.help"
},
"Level": {
"name": "FakePlayer.Level.name",
"help": "FakePlayer.Level.help"
},
"Id": {
"name": "FakePlayer.Id.name",
"help": "FakePlayer.Id.help"
}
},
"Misc": {
"_info": {
"name": "Misc._info.name",
"help": "Misc._info.help"
},
"GlobalSpeedup": {
"name": "Misc.GlobalSpeedup.name",
"help": "Misc.GlobalSpeedup.help"
},
"BetterGlobalSpeedup": {
"name": "Misc.BetterGlobalSpeedup.name",
"help": "Misc.BetterGlobalSpeedup.help"
},
"ChapterMove": {
"name": "Misc.ChapterMove.name",
"help": "Misc.ChapterMove.help"
},
"OpsiMove": {
"name": "Misc.OpsiMove.name",
"help": "Misc.OpsiMove.help"
},
"RemoveHardMapLimit": {
"name": "Misc.RemoveHardMapLimit.name",
"help": "Misc.RemoveHardMapLimit.help",
"disable": "disable",
"remove_ship_properties_limit": "remove_ship_properties_limit",
"remove_ship_type_limit": "remove_ship_type_limit",
"remove_both": "remove_both"
},
"NoBBAnimation": {
"name": "Misc.NoBBAnimation.name",
"help": "Misc.NoBBAnimation.help"
},
"NoEmotionWarning": {
"name": "Misc.NoEmotionWarning.name",
"help": "Misc.NoEmotionWarning.help"
},
"ExerciseGodMod": {
"name": "Misc.ExerciseGodMod.name",
"help": "Misc.ExerciseGodMod.help"
},
"ExerciseMorePower": {
"name": "Misc.ExerciseMorePower.name",
"help": "Misc.ExerciseMorePower.help"
},
"FastWave": {
"name": "Misc.FastWave.name",
"help": "Misc.FastWave.help"
},
"MonsterKillSelf": {
"name": "Misc.MonsterKillSelf.name",
"help": "Misc.MonsterKillSelf.help"
},
"SkipBattleCelebrate": {
"name": "Misc.SkipBattleCelebrate.name",
"help": "Misc.SkipBattleCelebrate.help"
}
},
"Storage": {
"_info": {
"name": "任務狀態",

300
module/luahook/api.py Normal file
View File

@@ -0,0 +1,300 @@
import json
from typing import Dict
import requests
import adbutils
from pydantic import BaseModel
from module.luahook.exception import CrackerError
class CrackApi:
class ShipProperties(BaseModel):
armor: float = -1
speed: float = -1
antiaircraft: float = -1
oxy_recovery_bench: float = -1
torpedo: float = -1
hit: float = -1
sonarRange: float = -1
attack_duration: float = -1
raid_distance: float = -1
oxy_recovery_surface: float = -1
oxy_recovery: float = -1
dodge: float = -1
luck: float = -1
reload: float = -1
oxy_cost: float = -1
durability: float = -1
air: float = -1
oxy_max: float = -1
cannon: float = -1
antisub: float = -1
class FakePlayerInfo(BaseModel):
name: str = ""
level: str = ""
id: str = ""
class ShipInfo(BaseModel):
config_id: int
emotion: int
rarity: int
level: int
exp: int
curr_star: int
class GlobalSpeedupRate(BaseModel):
rate: float
class BetterGlobalSpeedupRate(BaseModel):
rate: float
class ExerciseMorePowerRate(BaseModel):
rate: float
def __init__(self, base_url, timeout=10):
self.api_url = base_url
self.timeout = timeout
def get(self, path, **kwargs):
args = []
for k, v in kwargs.items():
if v is None:
continue
args.append(f'{k}={v}')
if args:
url = f'{self.api_url}/{path}?{"&".join(args)}'
else:
url = f'{self.api_url}/{path}'
try:
response = requests.get(url, headers={
"Connection": "close",
}, timeout=self.timeout)
except requests.exceptions.Timeout:
raise CrackerError('CrackApi request timeout')
except Exception as e:
raise CrackerError(f'CrackApi request error: {e}')
if response.status_code != 200:
raise CrackerError(f'CrackApi response error: {response.status_code}')
return response
def post(self, path, data=None):
url = f'{self.api_url}/{path}'
if data is not None and isinstance(data, dict):
data_str = json.dumps(data)
else:
data_str = data
try:
response = requests.post(url, data=data_str, headers={
"Connection": "close",
}, timeout=self.timeout)
except requests.exceptions.Timeout:
raise CrackerError('CrackApi request timeout')
except Exception as e:
raise CrackerError(f'CrackApi request error: {e}')
if response.status_code != 200:
raise CrackerError(f'CrackApi response error: {response.status_code}')
def get_coin(self) -> int:
response = self.get('get_coin')
return int(response.text)
def get_oil(self) -> int:
response = self.get('get_oil')
return int(response.text)
def get_gems(self) -> int:
response = self.get('get_gems')
return int(response.text)
def get_level(self) -> int:
response = self.get('get_level')
return int(response.text)
def get_exp(self) -> int:
response = self.get('get_exp')
return int(response.text)
def get_merit(self) -> int:
response = self.get('get_merit')
return int(response.text)
def get_guild_coin(self) -> int:
response = self.get('get_guild_coin')
return int(response.text)
def get_design_prt(self) -> int:
response = self.get('get_design_prt')
return int(response.text)
def get_core_data(self) -> str:
response = self.get('get_core_data')
return response.text
def get_medal(self) -> int:
response = self.get('get_medal')
return int(response.text)
def get_pt(self) -> int:
response = self.get('get_pt')
return int(response.text)
def get_specialized_core(self) -> int:
response = self.get('get_specialized_core')
return int(response.text)
def get_curr_action_points(self) -> int:
response = self.get('get_curr_action_points')
return int(response.text)
def scan_dock(self) -> Dict[int, ShipInfo]:
response = self.get('scan_dock')
json_data = json.loads(response.text)
res = {}
for k, v in json_data.items():
res[int(k)] = CrackApi.ShipInfo(**v)
return res
def scan_storage(self) -> Dict[int, int]:
response = self.get('scan_storage')
json_data = json.loads(response.text)
res = {}
for k, v in json_data.items():
res[int(k)] = int(v)
return res
def get_ship_info(self, ship_id: int) -> ShipInfo:
response = self.get('get_ship_info', id=ship_id)
json_data = json.loads(response.text)
return CrackApi.ShipInfo(**json_data)
def get_storage_item_count(self, item_id: int) -> int:
response = self.get('get_storage_item_count', id=item_id)
return int(response.text)
def enable_gg_factor(self):
self.post('enable_gg_factor')
def disable_gg_factor(self):
self.post('disable_gg_factor')
def update_gg_factor(self, gg_factor: float):
self.post('update_gg_factor', data={'factor': gg_factor})
def disable_all(self):
self.post('disable_all')
def enable_global_ship_properties_crack(self):
self.post('enable_global_ship_properties_crack')
def disable_global_ship_properties_crack(self):
self.post('disable_global_ship_properties_crack')
def update_global_ship_properties(self, ship_properties: ShipProperties):
self.post('update_global_ship_properties', data=ship_properties.json())
def enable_fast_stage_move(self):
self.post("enable_fast_stage_move")
def disable_fast_stage_move(self):
self.post("disable_fast_stage_move")
def enable_remove_hard_mode_ship_properties_limit(self):
self.post("enable_remove_hard_mode_ship_properties_limit")
def disable_remove_hard_mode_ship_properties_limit(self):
self.post("disable_remove_hard_mode_ship_properties_limit")
def enable_remove_hard_mode_ship_type_limit(self):
self.post("enable_remove_hard_mode_ship_type_limit")
def disable_remove_hard_mode_ship_type_limit(self):
self.post("disable_remove_hard_mode_ship_type_limit")
def enable_remove_hard_mode_limit(self):
self.post("enable_remove_hard_mode_limit")
def disable_remove_hard_mode_limit(self):
self.post("disable_remove_hard_mode_limit")
def enable_fake_player(self):
self.post("enable_fake_player")
def disable_fake_player(self):
self.post("disable_fake_player")
def update_fake_player_info(self, fake_player_info: FakePlayerInfo):
self.post("update_fake_player_info", data=fake_player_info.json())
def enable_no_bb_animation(self):
self.post("enable_no_bb_animation")
def disable_no_bb_animation(self):
self.post("disable_no_bb_animation")
def enable_no_emotion_warning(self):
self.post("enable_no_emotion_warning")
def disable_no_emotion_warning(self):
self.post("disable_no_emotion_warning")
def enable_opsi_fast_move(self):
self.post("enable_opsi_fast_move")
def disable_opsi_fast_move(self):
self.post("disable_opsi_fast_move")
def enable_global_speedup(self):
self.post("enable_global_speedup")
def update_global_speedup_rate(self, rate: GlobalSpeedupRate):
self.post("update_global_speedup_rate", data=rate.json())
def disable_global_speedup(self):
self.post("disable_global_speedup")
def enable_better_global_speedup(self):
self.post("enable_better_global_speedup")
def update_better_global_speedup_rate(self, rate: BetterGlobalSpeedupRate):
self.post("update_better_global_speedup_rate", data=rate.json())
def disable_better_global_speedup(self):
self.post("disable_better_global_speedup")
def is_alive(self):
self.post("is_alive")
def enable_exercise_more_power(self):
self.post("enable_exercise_more_power")
def update_exercise_more_power_rate(self, rate: ExerciseMorePowerRate):
self.post("update_exercise_more_power_rate", data=rate.json())
def disable_exercise_more_power(self):
self.post("disable_exercise_more_power")
def enable_exercise_god_mode(self):
self.post("enable_exercise_god_mode")
def disable_exercise_god_mode(self):
self.post("disable_exercise_god_mode")
def enable_fast_wave(self):
self.post("enable_fast_wave")
def disable_fast_wave(self):
self.post("disable_fast_wave")
def enable_monster_kill_self(self):
self.post("enable_monster_kill_self")
def disable_monster_kill_self(self):
self.post("disable_monster_kill_self")
def enable_skip_battle_celebrate(self):
self.post("enable_skip_battle_celebrate")
def disable_skip_battle_celebrate(self):
self.post("disable_skip_battle_celebrate")

518
module/luahook/crack.py Normal file
View File

@@ -0,0 +1,518 @@
import hashlib
import json
import os
from pathlib import Path
from typing import Union, List, Type
import requests
from pydantic import BaseModel
from module.config.config import AzurLaneConfig
from module.config.deep import deep_get
from module.device.device import Device
from module.luahook.exception import CrackerError
from module.logger import logger
from module.luahook.api import CrackApi
from module.luahook.op import CrackOp
ALL_ENABLE_OPS = [
CrackOp.EnableGlobalShipProperties,
CrackOp.EnableChapterFastMove,
CrackOp.EnableRemoveHardModeLimit,
CrackOp.EnableFakePlayer,
CrackOp.EnableNoBBAnimation,
CrackOp.EnableNoEmotionWarning,
CrackOp.EnableOpsiFastMove,
CrackOp.EnableRemoveHardModeShipTypeLimit,
CrackOp.EnableRemoveHardModeShipPropertiesLimit,
CrackOp.EnableGGFactor,
CrackOp.EnableGlobalSpeedup,
CrackOp.EnableBetterGlobalSpeedup,
CrackOp.EnableExerciseGodMod,
CrackOp.EnableExerciseMorePower,
CrackOp.EnableFastWave,
CrackOp.EnableMonsterKillSelf,
CrackOp.EnableSkipBattleCelebrate,
]
REMOTE_PORT = 23897
class Cracker(CrackApi):
def __init__(self, config: AzurLaneConfig, device: Device):
self.config = config
self.device = device
super().__init__(f"http://127.0.0.1:{device.adb.forward_port(REMOTE_PORT)}")
def fix_Hook_ShipProperty_config(config: AzurLaneConfig):
enable = deep_get(config.data, "Hook.ShipProperty.Enable", False)
if not enable:
return
else:
config.modified["Hook.ShipProperty.Method"] = "final_properties"
def do_crack_op_on_func(
before_call: Union[Type[CrackOp.Op], List[Type[CrackOp.Op]]] = None,
after_call: Union[Type[CrackOp.Op], List[Type[CrackOp.Op]]] = None
):
def wrapper(func):
def inner(*args, **kwargs):
obj = args[0]
if before_call is not None:
do_crack_op(obj.config, obj.device, before_call)
try:
ret = func(*args, **kwargs)
except Exception as e:
if after_call is not None:
do_crack_op(obj.config, obj.device, after_call)
raise e
if after_call is not None:
do_crack_op(obj.config, obj.device, after_call)
return ret
return inner
return wrapper
def do_crack_op(config: AzurLaneConfig, device: Device, ops: Union[Type[CrackOp.Op], List[Type[CrackOp.Op]]]):
if not deep_get(config.data, "Hook.HookGeneral.Enable", False):
return
if isinstance(ops, list):
l = ops
else:
if ops == CrackOp.EnableAll:
l = ALL_ENABLE_OPS
else:
l = [ops]
base_url = f"http://127.0.0.1:{device.adb.forward_port(REMOTE_PORT)}"
timeout = deep_get(config.data, "Hook.HookGeneral.RequestTimeLimit", 10)
api = CrackApi(base_url, timeout=timeout)
for op in l:
if op == CrackOp.DisableAll:
api.disable_all()
elif op == CrackOp.EnableGlobalShipProperties:
fix_Hook_ShipProperty_config(config)
if deep_get(config.data, "Hook.ShipProperty.Method", "disable") != "final_properties":
continue
api.update_global_ship_properties(
CrackApi.ShipProperties(
armor=float(deep_get(config.data, "Hook.ShipProperty.Armor", -1)),
speed=float(deep_get(config.data, "Hook.ShipProperty.Speed", -1)),
antiaircraft=float(deep_get(config.data, "Hook.ShipProperty.AntiAircraft", -1)),
oxy_recovery_bench=float(deep_get(config.data, "Hook.ShipProperty.OxyRecoveryBench", -1)),
torpedo=float(deep_get(config.data, "Hook.ShipProperty.Torpedo", -1)),
hit=float(deep_get(config.data, "Hook.ShipProperty.Hit", -1)),
sonarRange=float(deep_get(config.data, "Hook.ShipProperty.SonarRange", -1)),
attack_duration=float(deep_get(config.data, "Hook.ShipProperty.AttackDuration", -1)),
raid_distance=float(deep_get(config.data, "Hook.ShipProperty.RaidDistance", -1)),
oxy_recovery_surface=float(deep_get(config.data, "Hook.ShipProperty.OxyRecoverySurface", -1)),
oxy_recovery=float(deep_get(config.data, "Hook.ShipProperty.OxyRecovery", -1)),
dodge=float(deep_get(config.data, "Hook.ShipProperty.Dodge", -1)),
luck=float(deep_get(config.data, "Hook.ShipProperty.Luck", -1)),
reload=float(deep_get(config.data, "Hook.ShipProperty.Reload", -1)),
oxy_cost=float(deep_get(config.data, "Hook.ShipProperty.OxyCost", -1)),
durability=float(deep_get(config.data, "Hook.ShipProperty.Durability", -1)),
air=float(deep_get(config.data, "Hook.ShipProperty.Air", -1)),
oxy_max=float(deep_get(config.data, "Hook.ShipProperty.OxyMax", -1)),
cannon=float(deep_get(config.data, "Hook.ShipProperty.Cannon", -1)),
antisub=float(deep_get(config.data, "Hook.ShipProperty.AntiSub", -1)),
)
)
api.enable_global_ship_properties_crack()
elif op == CrackOp.DisableGlobalShipProperties:
api.disable_global_ship_properties_crack()
elif op == CrackOp.EnableChapterFastMove:
if not deep_get(config.data, "Hook.Misc.ChapterMove", False):
continue
api.enable_fast_stage_move()
elif op == CrackOp.DisableChapterFastMove:
api.disable_fast_stage_move()
elif op == CrackOp.EnableRemoveHardModeShipPropertiesLimit:
if deep_get(config.data, "Hook.Misc.RemoveHardMapLimit", "") != "remove_ship_properties_limit":
continue
api.enable_remove_hard_mode_ship_properties_limit()
elif op == CrackOp.DisableRemoveHardModeShipPropertiesLimit:
api.disable_remove_hard_mode_ship_properties_limit()
elif op == CrackOp.EnableRemoveHardModeShipTypeLimit:
if deep_get(config.data, "Hook.Misc.RemoveHardMapLimit", "") != "remove_ship_type_limit":
continue
api.enable_remove_hard_mode_ship_type_limit()
elif op == CrackOp.DisableRemoveHardModeShipTypeLimit:
api.disable_remove_hard_mode_ship_type_limit()
elif op == CrackOp.EnableRemoveHardModeLimit:
if deep_get(config.data, "Hook.Misc.RemoveHardMapLimit", "") != "remove_both":
continue
api.enable_remove_hard_mode_limit()
elif op == CrackOp.DisableRemoveHardModeLimit:
api.disable_remove_hard_mode_limit()
elif op == CrackOp.EnableFakePlayer:
if not deep_get(config.data, "Hook.FakePlayer.Enable", False):
continue
api.update_fake_player_info(
CrackApi.FakePlayerInfo(
name=str(deep_get(config.data, "Hook.FakePlayer.Name", "")),
level=str(deep_get(config.data, "Hook.FakePlayer.Level", "")),
id=str(deep_get(config.data, "Hook.FakePlayer.Id", "")),
)
)
api.enable_fake_player()
elif op == CrackOp.DisableFakePlayer:
api.disable_fake_player()
elif op == CrackOp.EnableNoBBAnimation:
if not deep_get(config.data, "Hook.Misc.NoBBAnimation", False):
continue
api.enable_no_bb_animation()
elif op == CrackOp.DisableNoBBAnimation:
api.disable_no_bb_animation()
elif op == CrackOp.EnableNoEmotionWarning:
if not deep_get(config.data, "Hook.Misc.NoEmotionWarning", False):
continue
api.enable_no_emotion_warning()
elif op == CrackOp.DisableNoEmotionWarning:
api.disable_no_emotion_warning()
elif op == CrackOp.IsAlive:
api.is_alive()
elif op == CrackOp.EnableOpsiFastMove:
api.enable_opsi_fast_move()
elif op == CrackOp.DisableOpsiFastMove:
api.disable_opsi_fast_move()
elif op == CrackOp.EnableGGFactor:
if deep_get(config.data, "Hook.ShipProperty.Method", "disable") != "gg_factor":
continue
api.update_gg_factor(float(deep_get(config.data, "Hook.ShipProperty.Factor", 1.0)))
api.enable_gg_factor()
elif op == CrackOp.DisableGGFactor:
api.disable_gg_factor()
elif op == CrackOp.EnableGlobalSpeedup:
rate = float(deep_get(config.data, "Hook.Misc.GlobalSpeedup", 1.0))
if rate == 1.0:
continue
api.update_global_speedup_rate(CrackApi.GlobalSpeedupRate(rate=rate))
api.enable_global_speedup()
elif op == CrackOp.DisableGlobalSpeedup:
api.disable_global_speedup()
elif op == CrackOp.EnableBetterGlobalSpeedup:
rate = float(deep_get(config.data, "Hook.Misc.BetterGlobalSpeedup", 1.0))
if rate == 1.0:
continue
api.update_better_global_speedup_rate(CrackApi.BetterGlobalSpeedupRate(rate=rate))
api.enable_better_global_speedup()
elif op == CrackOp.DisableBetterGlobalSpeedup:
api.disable_better_global_speedup()
elif op == CrackOp.EnableExerciseGodMod:
if deep_get(config.data, "Hook.Misc.ExerciseGodMod", False):
api.enable_exercise_god_mode()
elif op == CrackOp.DisableExerciseGodMod:
api.disable_exercise_god_mode()
elif op == CrackOp.EnableExerciseMorePower:
rate = float(deep_get(config.data, "Hook.Misc.ExerciseMorePower", -1.0))
if rate == -1.0:
continue
api.update_exercise_more_power_rate(CrackApi.ExerciseMorePowerRate(rate=rate))
api.enable_exercise_more_power()
elif op == CrackOp.DisableExerciseMorePower:
api.disable_exercise_more_power()
elif op == CrackOp.EnableFastWave:
is_enable_fast_wave = deep_get(config.data, "Hook.Misc.FastWave", False)
if is_enable_fast_wave:
api.enable_fast_wave()
elif op == CrackOp.DisableFastWave:
api.disable_fast_wave()
elif op == CrackOp.EnableMonsterKillSelf:
is_enable_monster_kill_self = deep_get(config.data, "Hook.Misc.MonsterKillSelf", False)
if is_enable_monster_kill_self:
api.enable_monster_kill_self()
elif op == CrackOp.DisableMonsterKillSelf:
api.disable_monster_kill_self()
elif op == CrackOp.EnableSkipBattleCelebrate:
is_enable_skip_battle_celebrate = deep_get(config.data, "Hook.Misc.SkipBattleCelebrate", False)
if is_enable_skip_battle_celebrate:
api.enable_skip_battle_celebrate()
elif op == CrackOp.DisableSkipBattleCelebrate:
api.disable_skip_battle_celebrate()
else:
logger.error(f"Unsupported op: {op}")
crack_op = do_crack_op_on_func
def disable_all_crack(f):
def wrapper(*args, **kwargs):
obj = args[0]
logger.info("Disabe all luahook cracks")
do_crack_op(obj.config, obj.device, CrackOp.DisableAll)
return f(*args, **kwargs)
return wrapper
def enable_all_crack(f):
def wrapper(*args, **kwargs):
obj = args[0]
do_crack_op(obj.config, obj.device, CrackOp.EnableAll)
return f(*args, **kwargs)
return wrapper
def luahook_crack_all(config: AzurLaneConfig, device: Device):
logger.info("Crack all with luahook")
do_crack_op(config, device, CrackOp.EnableAll)
def luahook_disable_all(config: AzurLaneConfig, device: Device):
logger.info("Disable all luahook")
do_crack_op(config, device, CrackOp.DisableAll)
CHAPTER_CRACK_OPS = [
CrackOp.EnableChapterFastMove,
CrackOp.EnableNoBBAnimation,
CrackOp.EnableNoEmotionWarning,
CrackOp.EnableGlobalShipProperties,
CrackOp.EnableRemoveHardModeLimit,
CrackOp.EnableFakePlayer,
CrackOp.EnableGGFactor,
CrackOp.EnableGlobalSpeedup,
CrackOp.EnableBetterGlobalSpeedup,
CrackOp.EnableFastWave,
CrackOp.EnableMonsterKillSelf,
CrackOp.EnableSkipBattleCelebrate,
]
def chapter_task_crack(f):
def wrapper(*args, **kwargs):
obj = args[0]
do_crack_op(obj.config, obj.device, CHAPTER_CRACK_OPS)
return f(*args, **kwargs)
return wrapper
OPSI_CRACK_OPS = [
CrackOp.EnableNoBBAnimation,
CrackOp.EnableOpsiFastMove,
CrackOp.EnableGlobalShipProperties,
CrackOp.EnableFakePlayer,
CrackOp.EnableGGFactor,
CrackOp.EnableGlobalSpeedup,
CrackOp.EnableBetterGlobalSpeedup,
CrackOp.EnableFastWave,
CrackOp.EnableMonsterKillSelf,
CrackOp.EnableSkipBattleCelebrate,
]
def opsi_task_crack(f):
def wrapper(*args, **kwargs):
obj = args[0]
do_crack_op(obj.config, obj.device, OPSI_CRACK_OPS)
return f(*args, **kwargs)
return wrapper
class UpdateServerApi:
class ResourceFile(BaseModel):
arch: str
file: str
def __init__(self, api_url: str = ""):
self.api_url = api_url
def post(self, path: str, data=None):
logger.info(f"UpdateServerApi post: {path}")
url = f'{self.api_url}/{path}'
try:
response = requests.post(url, data=data) # TODO: add timeout
except requests.exceptions.Timeout:
raise CrackerError('UpdateServerApi request timeout')
except Exception as e:
raise CrackerError(f'UpdateServerApi request error: {e}')
if response.status_code != 200:
raise CrackerError(f'UpdateServerApi response error: {response.status_code}')
return response
def download_file(self, arch: str, file_name: str) -> bytes:
res = self.post("files", UpdateServerApi.ResourceFile(arch=arch, file=file_name).json())
return res.content
def get_hash(self, arch: str, file_name: str) -> str:
res = self.post("get_hash", UpdateServerApi.ResourceFile(arch=arch, file=file_name).json())
return res.text
class CrackResource:
ARCH_MAP = {
"x86": "x86",
"x86_64": "x86",
"armv7": "armeabi-v7a",
"arm64": "arm64-v8a",
"aarch64": "arm64-v8a",
"aarch": "armeabi-v7a",
}
def __init__(self, config: AzurLaneConfig, device: Device):
self.config = config
self.device = device
arch_conf = deep_get(config.data, "Hook.HookGeneral.Architecture")
if arch_conf == "auto":
arch_ret = device.adb_shell("uname -m").lower()
self.arch = self.ARCH_MAP.get(arch_ret, "")
if not self.arch:
raise CrackerError(f"Unsupported arch: {arch_ret}")
logger.info(f"Arch: {arch_ret} -> {self.arch}")
else:
self.arch = arch_conf
logger.info(f"Use arch: {self.arch}")
self.resource_root = f"./bin/hook"
self.resource_dir = f"{self.resource_root}/{self.arch}"
self.version_file = f"{self.resource_dir}/version.json"
self.first_init = False
self.has_new_version = False
self.update_server = self.__get_update_server()
self.upload_dir = f"/data/hook/{self.arch}"
self.game_lib_dir = Path(self.__format_str(deep_get(self.config.data, "Hook.HookGeneral.GameLibDir", ""))).as_posix()
def __file_hash(self, file_name):
with open(file_name, "rb") as f:
return hashlib.md5(f.read()).hexdigest()
def __gen_version_file_from_local(self):
d = {}
for file_name in os.listdir(self.resource_dir):
f = f"{self.resource_dir}/{file_name}"
if not os.path.isfile(f):
continue
if file_name.endswith(".json"):
continue
hash_value = self.__file_hash(f).upper()
d[file_name] = hash_value
with open(self.version_file, "w") as f:
json.dump(d, f, indent=4)
def __ensure_local_resource(self):
if self.update_server is None:
logger.info("No update server, skip ensure local resource")
return
if not os.path.exists(f"{self.resource_dir}/libcracker.so"):
self.__download_resource("libcracker.so")
self.first_init = True
if not os.path.exists(f"{self.resource_dir}/patchelf"):
self.__download_resource("patchelf")
self.first_init = True
__update_local_version = __gen_version_file_from_local
def __ensure_crack_resource(self, ):
if not os.path.exists(self.resource_root):
os.makedirs(self.resource_root)
if not os.path.exists(self.resource_dir):
os.makedirs(self.resource_dir)
self.__ensure_local_resource()
if not os.path.exists(self.version_file):
self.__gen_version_file_from_local()
def __download_resource(self, file_name: str):
if self.update_server is None:
logger.info("No update server, skip download resource")
return
logger.info(f"Download resource: {self.arch}/{file_name}")
res = self.update_server.download_file(self.arch, file_name)
with open(f"{self.resource_dir}/{file_name}", "wb") as f:
f.write(res)
def __is_same_version(self, version_json: dict, file_name: str):
h = self.update_server.get_hash(self.arch, file_name)
return h == version_json.get(file_name, "")
def __check_update(self):
if self.update_server is None:
logger.info("No update server, skip update check, use local resource")
return
with open(self.version_file, "r") as f:
local_version = json.load(f)
if not self.__is_same_version(local_version, "libcracker.so"):
self.__download_resource("libcracker.so")
self.has_new_version = True
if not self.__is_same_version(local_version, "patchelf"):
self.__download_resource("patchelf")
self.has_new_version = True
if self.has_new_version:
self.__update_local_version()
def __format_str(self, s: str) -> str:
return ("".join([i for i in s if i.isprintable()])).replace(" ", "").replace("\n", "")
def __get_update_server(self) -> Union[UpdateServerApi, None]:
update_server_url: str = deep_get(self.config.data, "Hook.HookGeneral.UpdateServer", "")
update_server_url = self.__format_str(update_server_url)
if not update_server_url:
return None
return UpdateServerApi(update_server_url)
def __push(self, file_name: str):
self.device.adb_shell(f"mkdir -p {self.upload_dir}")
self.device.adb_shell(f"rm {self.upload_dir}/{file_name}")
self.device.adb_push(f"{self.resource_dir}/{file_name}", f"{self.upload_dir}/{file_name}", timeout=300)
self.device.adb_shell(f"chmod 777 {self.upload_dir}/{file_name}")
def __push_resource(self):
logger.info("Push resource to device")
self.__push("libcracker.so")
self.__push("patchelf")
def __do_inject(self):
if not self.game_lib_dir:
raise CrackerError("GameLibDir not set")
logger.info(f"GameLibDir: {self.game_lib_dir}, do inject")
cmd = f"cd {self.upload_dir} && ./patchelf --local-patch --game-lib-dir '{self.game_lib_dir}'"
self.device.adb_shell(cmd)
def __is_exist(self, path):
cmd = f"if [ -f {path} ]; then echo 'exist'; else if [ -d {path} ]; then echo 'exist'; else echo 'not exist'; fi; fi"
return self.device.adb_shell(cmd) == "exist"
def __is_remote_file_exist(self) -> bool:
return self.__is_exist(self.upload_dir) and self.__is_exist(f"{self.upload_dir}/libcracker.so") and self.__is_exist(f"{self.upload_dir}/patchelf")
def __adb_su_do(self, cmd: str):
return self.device.adb_shell(f"su -c '{cmd}'")
def __adb_root(self):
self.device.adb_command(["root"])
def __check_game_lib_dir(self):
return self.__is_exist(f"{self.game_lib_dir}/libil2cpp.so") and self.__is_exist(f"{self.game_lib_dir}/libtolua.so")
def ensure(self):
if not deep_get(self.config.data, "Hook.HookGeneral.Enable", False):
return
if not self.__check_game_lib_dir():
raise CrackerError(f"GameLibDir '{self.game_lib_dir}' is invalid")
self.__adb_root()
self.__ensure_crack_resource()
if not self.first_init:
self.__check_update()
if self.has_new_version or not self.__is_remote_file_exist() or deep_get(self.config.data, "Hook.HookGeneral.PushEveryTime", True):
self.__push_resource()
self.device.app_stop()
self.config.task_call("Restart")
self.__do_inject()

View File

@@ -0,0 +1,2 @@
class CrackerError(Exception):
pass

114
module/luahook/op.py Normal file
View File

@@ -0,0 +1,114 @@
class CrackOp:
class Op:
...
class EnableAll(Op):
...
class DisableAll(Op):
...
class EnableGlobalShipProperties(Op):
...
class DisableGlobalShipProperties(Op):
...
class EnableChapterFastMove(Op):
...
class DisableChapterFastMove(Op):
...
class EnableOpsiFastMove(Op):
...
class DisableOpsiFastMove(Op):
...
class EnableRemoveHardModeShipPropertiesLimit(Op):
...
class DisableRemoveHardModeShipPropertiesLimit(Op):
...
class EnableRemoveHardModeShipTypeLimit(Op):
...
class DisableRemoveHardModeShipTypeLimit(Op):
...
class EnableRemoveHardModeLimit(Op):
...
class DisableRemoveHardModeLimit(Op):
...
class EnableFakePlayer(Op):
...
class DisableFakePlayer(Op):
...
class EnableGlobalSpeedup(Op):
...
class DisableGlobalSpeedup(Op):
...
class EnableBetterGlobalSpeedup(Op):
...
class DisableBetterGlobalSpeedup(Op):
...
class EnableNoBBAnimation(Op):
...
class DisableNoBBAnimation(Op):
...
class EnableNoEmotionWarning(Op):
...
class DisableNoEmotionWarning(Op):
...
class IsAlive(Op):
...
class EnableGGFactor(Op):
...
class DisableGGFactor(Op):
...
class EnableExerciseGodMod(Op):
...
class DisableExerciseGodMod(Op):
...
class EnableExerciseMorePower(Op):
...
class DisableExerciseMorePower(Op):
...
class EnableFastWave(Op):
...
class DisableFastWave(Op):
...
class EnableMonsterKillSelf(Op):
...
class DisableMonsterKillSelf(Op):
...
class EnableSkipBattleCelebrate(Op):
...
class DisableSkipBattleCelebrate(Op):
...