44from pathlib import Path
55from typing import BinaryIO
66
7+ from pyBjson .string_hash import get_JOAAT_hash
8+
79def readString (f : BinaryIO ) -> bytes :
810 string = b""
911 char = f .read (1 )
12+ if len (char ) != 1 :
13+ raise Exception ("End of file" )
1014 while char != b'\0 ' :
1115 string += char
1216 char = f .read (1 )
17+ if len (char ) != 1 :
18+ raise Exception ("End of file" )
1319 return string
1420
1521def readU16 (f : BinaryIO ) -> int :
1622 binary = f .read (2 )
23+ if len (binary ) != 2 :
24+ raise Exception ("End of file" )
1725 num = int .from_bytes (binary , "little" , signed = False )
1826 return num
1927
2028def readU32 (f : BinaryIO ) -> int :
2129 binary = f .read (4 )
30+ if len (binary ) != 4 :
31+ raise Exception ("End of file" )
2232 num = int .from_bytes (binary , "little" , signed = False )
2333 return num
2434
2535def readFloat (f : BinaryIO ) -> float :
2636 num = struct .unpack ("<f" , f .read (4 ))[0 ]
2737 return num
2838
29- def exportUVs (fp : str | Path , out_path : str | Path ):
39+ def searchHash (elements : list [dict ], hashval : int ) -> str | None :
40+ for element in elements :
41+ if element ["hash" ] == hashval :
42+ return element ["name" ]
43+ return None
44+
45+ def exportUVs (fp : str | Path , out_path : str | Path , verbose : bool = False ):
3046 if isinstance (fp , str ):
3147 fp = Path (fp ).absolute ()
3248 if isinstance (out_path , str ):
3349 out_path = Path (out_path ).absolute ()
3450 with open (fp , "rb" ) as f :
35- header_1 = readU32 (f )
36- header_2 = readU32 (f )
37- header_3 = readU32 (f )
51+ header_1 = readU32 (f ) # Total amount of elements not repeated
52+ header_2 = readU32 (f ) # Amount of elements including repeated
53+ header_3 = readU32 (f ) # Length of all strings
54+ if verbose :
55+ print (f"Header 1: { header_1 } " )
56+ print (f"Header 2: { header_2 } " )
57+ print (f"Header 3: { header_3 } " )
3858
39- string_ids = []
59+ string_ids : list [ str ] = []
4060 for i in range (header_2 ):
4161 string_ids .append (readString (f ).decode ("utf-8" ))
62+ f .seek (0x04 * 3 + header_3 ) # (Header) + (Length) = Start of UVs data
4263
4364 uvs_data = {}
65+ hashvals = []
4466 for i in range (header_2 ):
45- uv_1 = readFloat (f )
46- uv_2 = readFloat (f )
47- uv_3 = readFloat (f )
48- uv_4 = readFloat (f )
49- w = readU16 (f )
50- h = readU16 (f )
51- unknown1 = readU32 (f )
52- unknown2 = readU32 (f )
67+ uv_1 = readFloat (f ) # u1 [0-1]
68+ uv_2 = readFloat (f ) # v1 [0-1]
69+ uv_3 = readFloat (f ) # u2 [0-1]
70+ uv_4 = readFloat (f ) # v2 [0-1]
71+ w = readU16 (f ) # Texture width
72+ h = readU16 (f ) # Texture height
73+ unknown1 = readU32 (f ) # Idk
74+ unknown2 = readU32 (f ) # Could be some kind of binary value ?
5375 strip = string_ids [i ].split ("/" )[- 1 ]
54- uvs_data [strip ] = {"uv" : [int (uv_1 * w / 1 ), int (uv_2 * h / 1 ), int (uv_3 * w / 1 ), int (uv_4 * h / 1 )]}
76+ if verbose :
77+ print (string_ids [i ])
78+ print (f"Unknown 1: { hex (unknown1 )} " )
79+ print (format (unknown2 , "032b" ))
80+ uvs_data [strip ] = {"uv" : [int (uv_1 * w ), int (uv_2 * h ), int (uv_3 * w ), int (uv_4 * h )]}
5581 uvs_data [strip ]["tileSize" ] = uvs_data [strip ]["uv" ][2 ] - uvs_data [strip ]["uv" ][0 ]
82+ if verbose :
83+ print (uvs_data [strip ])
84+ hashvals .append ({"name" : strip , "hash" : get_JOAAT_hash (strip .lower ().encode ("utf-8" ))})
85+
86+ matched = 0
87+ # This last section seems like an index section
88+ for i in range (header_1 ):
89+ unknown3 = readU32 (f ) # Maybe a hash used to sort data ?
90+ unknown4 = readU32 (f ) # Looks like some repetition value ?
91+ unknown5 = readU32 (f ) # Looks like an index ?
92+ if verbose :
93+ str_id = searchHash (hashvals , unknown3 )
94+ if str_id != None :
95+ print (str_id )
96+ matched += 1
97+ print (unknown3 , unknown4 , unknown5 )
98+
99+ if verbose :
100+ print (f"Strings that matched: { matched } " )
101+ print (f"Elements in output: { len (uvs_data )} " )
102+ print (f"Header 1: { header_1 } " )
103+ print (f"Header 2: { header_2 } " )
104+ print (f"Header 3: { header_3 } " )
105+ print (f"Final position: { hex (f .tell ())} " )
56106
57107 with open (out_path , "w" ) as o :
58108 json .dump (uvs_data , o , indent = 4 )
59109
60110if __name__ == "__main__" :
61111 os .chdir (os .path .dirname (__file__ ))
62- exportUVs ("./atlas.items.vanilla.uvs" , "." )
112+ exportUVs ("./atlas.items.vanilla.uvs" , "./atlas.items.vanilla.uvs.json" , verbose = True )
0 commit comments