Skip to content

Commit c40a47b

Browse files
committed
feat: act24
1 parent d91e4ca commit c40a47b

19 files changed

+11145
-10061
lines changed

3rdparty/json/include/json.hpp

Lines changed: 6992 additions & 7765 deletions
Large diffs are not rendered by default.

resources/icon/FileGetter.py

Lines changed: 67 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -8,62 +8,70 @@
88
import requests
99

1010

11-
@contextmanager
12-
def get(filename):
13-
z = _get_file(filename)
14-
with z.open(filename) as f:
15-
h = hashlib.md5()
16-
while _ := f.read():
17-
h.update(_)
18-
if h.hexdigest() != file_list[filename]:
19-
warnings.warn("MD5 not match")
20-
yield f
21-
22-
23-
def _get_json(json_url: str):
24-
res = requests.get(json_url).content.decode()
25-
return json.loads(res)
26-
27-
28-
def _get_network_config() -> dict:
29-
network_config_url = "https://ak-conf.hypergryph.com/config/prod/official/network_config"
30-
network_config = _get_json(network_config_url)
31-
return json.loads(network_config["content"])
32-
33-
34-
def _get_version() -> str:
35-
funcVer = network_config["funcVer"]
36-
version_url = network_config["configs"][funcVer]["network"]["hv"]\
37-
.replace("{0}", platform)
38-
return _get_json(version_url)["resVersion"]
39-
40-
41-
def _get_file_list() -> dict:
42-
global root_url
43-
funcVer = network_config["funcVer"]
44-
root_url = network_config["configs"][funcVer]["network"]["hu"]\
45-
+ f"/{platform}/assets/{version}/"
46-
file_list_url = root_url + "hot_update_list.json"
47-
file_arr: list = _get_json(file_list_url)["abInfos"]
48-
return {_["name"]: _["md5"] for _ in file_arr}
49-
50-
51-
def _get_file(filename: str):
52-
if filename in file_list:
53-
url = root_url + \
54-
(filename.rsplit('.', 1)[0] + ".dat")\
55-
.replace('/', '_')\
56-
.replace('#', '__')
57-
return zipfile.ZipFile(io.BytesIO(requests.get(url).content), 'r')
58-
59-
60-
platform = "Android"
61-
62-
root_url = ""
63-
network_config = _get_network_config()
64-
version = _get_version()
65-
file_list = _get_file_list()
66-
67-
_get_network_config()
68-
_get_version()
69-
_get_file_list()
11+
class FileGetter:
12+
13+
_NETWORK_CONFIG_URLS = {
14+
'CN': 'https://ak-conf.hypergryph.com/config/prod/official/network_config',
15+
'JP': 'https://ak-conf.arknights.jp/config/prod/official/network_config',
16+
'US': 'https://ak-conf.arknights.global/config/prod/official/network_config',
17+
'KR': 'https://ak-conf.arknights.kr/config/prod/official/network_config',
18+
'TW': 'https://ak-conf.txwy.tw/config/prod/official/network_config',
19+
}
20+
21+
def __init__(self, server) -> None:
22+
self.server = server
23+
self._platform = "Android"
24+
self._network_config = self._get_network_config()
25+
self._version = self._get_version()
26+
self._file_list = self._get_file_list()
27+
28+
@contextmanager
29+
def get(self, filename):
30+
z = self._get_file(filename)
31+
with z.open(filename) as f:
32+
h = hashlib.md5()
33+
while _ := f.read():
34+
h.update(_)
35+
if h.hexdigest() != self._file_list[filename]:
36+
warnings.warn("MD5 not match")
37+
yield f
38+
39+
def _get_file(self, filename: str):
40+
if filename in self._file_list:
41+
url = self._root_url + \
42+
(filename.rsplit('.', 1)[0] + ".dat")\
43+
.replace('/', '_')\
44+
.replace('#', '__')
45+
return zipfile.ZipFile(io.BytesIO(requests.get(url).content), 'r')
46+
47+
@staticmethod
48+
def _get_json(json_url: str):
49+
res = requests.get(json_url).content.decode()
50+
return json.loads(res)
51+
52+
def _get_network_config(self) -> dict:
53+
network_config_url = FileGetter._NETWORK_CONFIG_URLS[self.server]
54+
network_config = self._get_json(network_config_url)
55+
return json.loads(network_config["content"])
56+
57+
def _get_version(self) -> str:
58+
funcVer = self._network_config["funcVer"]
59+
self.version_url = self._network_config["configs"][funcVer]["network"]["hv"]\
60+
.replace("{0}", self._platform)
61+
return self._get_json(self.version_url)["resVersion"]
62+
63+
def _get_file_list(self) -> dict:
64+
funcVer = self._network_config["funcVer"]
65+
self._root_url = self._network_config["configs"][funcVer]["network"]["hu"]\
66+
+ f"/{self._platform}/assets/{self._version}/"
67+
self.file_list_url = self._root_url + "hot_update_list.json"
68+
file_arr: list = self._get_json(self.file_list_url)["abInfos"]
69+
return {_["name"]: _["md5"] for _ in file_arr}
70+
71+
72+
if __name__ == "__main__":
73+
fg = FileGetter("KR")
74+
with fg.get("gamedata/excel/item_table.ab") as f:
75+
import UnityPy
76+
env = UnityPy.load(f)
77+
print(fg._get_json(fg.version_url))
2.88 KB
Loading
2.73 KB
Loading
2.34 KB
Loading
2.43 KB
Loading
2.37 KB
Loading
2.33 KB
Loading

resources/icon/filter.json

Lines changed: 0 additions & 44 deletions
This file was deleted.

resources/icon/iconGetter.py

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
import os
2+
import shutil
3+
import tempfile
4+
5+
import cv2
6+
import numpy
7+
import UnityPy
8+
from PIL import Image
9+
10+
from FileGetter import FileGetter
11+
from decrypt import decrypt
12+
13+
14+
class iconGetter:
15+
16+
file_list = [
17+
"spritepack/ui_item_icons_h1_0.ab", # basic items
18+
"spritepack/ui_item_icons_h1_acticon_0.ab", # randomMaterial
19+
"spritepack/ui_item_icons_h1_apsupply_0.ab", # ap supply
20+
"activity/commonassets.ab", # activity items
21+
"activity/[uc]act24side.ab" # activity items
22+
]
23+
24+
def __init__(self, server) -> None:
25+
self.server = server
26+
self.fg = FileGetter(server)
27+
print(self.fg.server, self.fg._version)
28+
print(self.fg.file_list_url)
29+
self.item_table = self._get_item_table()
30+
print(f"item_table: {len(self.item_table)}")
31+
self.item_list = self._get_item_list()
32+
print(f"item_list: {len(self.item_list)}")
33+
self.bkg_img_list = self._get_bkg_img()
34+
print(f"bkg_img_list: {len(self.bkg_img_list)}")
35+
self.item_img_list = self._get_item_img()
36+
print(f"item_img_list: {len(self.item_img_list)}")
37+
38+
def make_zip(self, path, hq=False):
39+
with tempfile.TemporaryDirectory() as temp:
40+
if hq:
41+
for itemId, pilimg in self.item_img_list.items():
42+
cv2img = cv2.cvtColor(numpy.array(
43+
pilimg), cv2.COLOR_RGBA2BGRA)
44+
cv2.imwrite(temp + "/" + itemId + ".png", cv2img)
45+
else:
46+
for itemId, pilimg in self.item_img_list.items():
47+
cv2img = cv2.cvtColor(numpy.array(
48+
pilimg), cv2.COLOR_RGBA2BGRA)
49+
cv2.imwrite(temp + "/" + itemId + ".jpg", cv2img,
50+
[int(cv2.IMWRITE_JPEG_QUALITY), 10])
51+
fname = "items_" + self.server + "_" + self.fg._version
52+
shutil.make_archive(os.path.join(path, fname), "zip", temp)
53+
54+
def _get_item_table(self):
55+
res = {}
56+
with self.fg.get("gamedata/excel/item_table.ab") as f:
57+
env = UnityPy.load(f)
58+
for obj in env.objects:
59+
if obj.type.name == "TextAsset":
60+
textAssetFile = obj.read()
61+
item_table = decrypt(textAssetFile)
62+
for _, item in item_table["items"].items():
63+
itemId = item["itemId"]
64+
rarity = item["rarity"]
65+
iconId = item["iconId"]
66+
res[itemId] = {
67+
"iconId": iconId, "rarity": rarity}
68+
break
69+
return res
70+
71+
def _get_item_list(self):
72+
item_set = set()
73+
penguin_stages = self.fg._get_json(
74+
"https://penguin-stats.io/PenguinStats/api/v2/stages?server=" + self.server)
75+
for stage in penguin_stages:
76+
if (stage["stageId"] == "recruit") or ("isGacha" in stage):
77+
continue
78+
if "dropInfos" in stage:
79+
for item in stage["dropInfos"]:
80+
if ("itemId" in item):
81+
item_set.add(item["itemId"])
82+
if "recognitionOnly" in stage:
83+
for item in stage["recognitionOnly"]:
84+
item_set.add(item)
85+
86+
res = {}
87+
for itemId in item_set:
88+
if (itemId == "furni") or (itemId == "4001_2000"):
89+
continue
90+
iconId = self.item_table[itemId]["iconId"]
91+
rarity = self.item_table[itemId]["rarity"]
92+
if iconId not in res:
93+
res[iconId] = []
94+
res[iconId].append({"itemId": itemId, "rarity": rarity})
95+
return res
96+
97+
@staticmethod
98+
def _get_bkg_img():
99+
res = {"item": {}, "charm": {}, "act24": {}}
100+
for i in range(6):
101+
img = Image.open(
102+
os.path.join(os.path.dirname(__file__), f"background\\sprite_item_r{i}.png"))
103+
res["item"][i] = img
104+
for i in range(4):
105+
img = Image.open(
106+
os.path.join(os.path.dirname(__file__), f"background\\charm_r{i}.png"))
107+
res["charm"][i] = img
108+
for i in range(6):
109+
img = Image.open(
110+
os.path.join(os.path.dirname(__file__), f"background\\act24side_melding_{i+1}_bg.png"))
111+
res["act24"][i] = img
112+
return res
113+
114+
def _get_item_img(self):
115+
res = {}
116+
for fname in iconGetter.file_list:
117+
with self.fg.get(fname) as f:
118+
env = UnityPy.load(f)
119+
for obj in env.objects:
120+
if obj.type.name == "Sprite":
121+
spriteFile = obj.read()
122+
if (spriteFile.name in self.item_list):
123+
item_img = spriteFile.image
124+
for item in self.item_list[spriteFile.name]:
125+
itemId = item["itemId"]
126+
rarity = item["rarity"]
127+
if "act24" in itemId:
128+
bkg_img: Image.Image = self.bkg_img_list["act24"][rarity].copy(
129+
)
130+
else:
131+
bkg_img: Image.Image = self.bkg_img_list["item"][rarity].copy(
132+
)
133+
134+
offset_ld = {"x": 0, "y": 0}
135+
m_Rect = spriteFile.m_Rect
136+
offset_ld["x"] += (bkg_img.width -
137+
m_Rect.width) / 2.0
138+
offset_ld["y"] += (bkg_img.height -
139+
m_Rect.height) / 2.0
140+
141+
textureRectOffset = spriteFile.m_RD.textureRectOffset
142+
offset_ld["x"] += textureRectOffset.X
143+
offset_ld["y"] += textureRectOffset.Y
144+
145+
offset = (
146+
round(offset_ld["x"]),
147+
bkg_img.height - item_img.height - round(offset_ld["y"]))
148+
bkg_img.alpha_composite(item_img, offset)
149+
res[itemId] = bkg_img
150+
return res
151+
152+
153+
if __name__ == "__main__":
154+
ig = iconGetter("CN")
155+
ig.make_zip("D:/R", hq=False)

0 commit comments

Comments
 (0)