import json crossmap = {} natives = {} current_idx = 0 crossmap_hash_list = [] class Arg: def __init__(self, name: str, type: str): self.name = name self.type = type#.replace("BOOL", "bool")# .replace("Any*", "void*") def __str__(self) -> str: return str(self.type) + " " + str(self.name) class NativeFunc: def __init__(self, namespace: str, name: str, hash: int, args: list[dict], return_type: str): self.namespace = namespace self.name = name self.hash = hash self.args: list[Arg] = [] self.return_type = return_type#.replace("BOOL", "bool")# .replace("Any*", "void*") self.native_index = -1 self.fix_vectors = "false" for arg in args: self.args.append(Arg(arg["name"], arg["type"])) if arg["type"] == "Vector3*": self.fix_vectors = "true" def get_native_def_str(self) -> str: assert self.native_index != -1 param_decl = "" param_pass = "" if len(self.args) > 0: for arg in self.args: param_decl += str(arg) + ", " param_pass += arg.name + ", " param_decl = param_decl[:-2] param_pass = param_pass[:-2] return f"FORCEINLINE constexpr {self.return_type} {self.name}({param_decl}) {{ return big::native_invoker::invoke<{self.native_index}, {self.fix_vectors}, {self.return_type}>({param_pass}); }}" class CrossmapEntry: def __init__(self, translated_hash: int): self.hash = translated_hash self.native_index = -1 def load_crossmap_data(): global crossmap data = open("crossmap.txt").readlines() for item in data: translation = item.split(",") crossmap[int(translation[0], 16)] = CrossmapEntry(int(translation[1], 16)) def load_natives_data(): global natives data = json.load(open("natives.json")) for ns, natives_list in data.items(): natives[ns] = [] for hash_str, native_data in natives_list.items(): natives[ns].append(NativeFunc(ns, native_data["name"], int(hash_str, 16), native_data["params"], native_data["return_type"])) def allocate_indices(): global current_idx, crossmap_hash_list for _, n in natives.items(): for native in n: hash = native.hash if hash in crossmap: crossmap[hash].native_index = current_idx native.native_index = current_idx crossmap_hash_list.append(crossmap[hash].hash) current_idx += 1 def write_crossmap_header(): open("crossmap.hpp", "w+").write(f"""#pragma once #include <script/scrNativeHandler.hpp> namespace big {{ constexpr std::array<rage::scrNativeHash, {len(crossmap_hash_list)}> g_crossmap = {{{",".join([f"0x{x:X}" for x in crossmap_hash_list])}}}; }} """) def write_natives_header(): natives_buf = "" natives_index_buf = "" for ns, nvs in natives.items(): natives_buf += f"namespace {ns}\n{{\n" for nat_data in nvs: if nat_data.native_index == -1: continue natives_buf += f"\t{nat_data.get_native_def_str()}\n" natives_index_buf += f"\t{nat_data.name} = {nat_data.native_index},\n" natives_buf += "}\n\n" natives_buf = natives_buf[:-2] open("../natives.hpp", "w+").write(f"""#pragma once #include "invoker/invoker.hpp" // clang-format off enum class NativeIndex {{ {natives_index_buf}}}; {natives_buf} // clang-format on """) if __name__ == "__main__": load_crossmap_data() load_natives_data() allocate_indices() write_crossmap_header() write_natives_header()