mirror of
https://github.com/Mr-X-GTA/YimMenu.git
synced 2025-06-23 01:02:23 +08:00
refactor!: repo cleanup (#2650)
- Move cmake files to dedicated cmake folder - Move scattered python files to `scripts/` folder - Update CMakeLists.txt to reflect changes * feat(scripts): add README to folder
This commit is contained in:
39
scripts/README.md
Normal file
39
scripts/README.md
Normal file
@ -0,0 +1,39 @@
|
||||
# Scripts
|
||||
|
||||
This directory contains a collection of scripts used to generate certain parts of the code base.
|
||||
|
||||
## Doc Gen
|
||||
|
||||
`doc_gen.py` is used to generate the Lua documentation that's provided by YimMenu.
|
||||
It relies on specifically formatted code comments to generate Lua documentation.
|
||||
|
||||
## Generate Natives
|
||||
|
||||
`generate_natives.py` is responsible for generating the `src/natives.hpp` and `src/invoker/crossmap.hpp` files.
|
||||
|
||||
It takes a `natives.json` from [here](https://github.com/alloc8or/gta5-nativedb-data) and a `crossmap.txt` file which needs follow a certain format of:
|
||||
```csv
|
||||
[first_seen_native_hash]<comma>[current_native_hash]
|
||||
```
|
||||
|
||||
Example:
|
||||
```csv
|
||||
0xE1A0450ED46A7812,0x11FD21BA1B765FE2
|
||||
0x39BE7CEA8D9CC8E6,0x5F7C6361179DFFC4
|
||||
0x3C5FD37B5499582E,0x54BC5E0B6A29AE8A
|
||||
0xE2A99A9B524BEFFF,0x1FDE21A286357401
|
||||
0x51F1A8E48C3D2F6D,0xD1BAD83E70275AEB
|
||||
0x0A6D923DFFC9BD89,0x93693D93BD53ACB1
|
||||
0x112CEF1615A1139F,0x203607236413B185
|
||||
0xD47A2C1BA117471D,0x4F3198DEED415E95
|
||||
0xC2F7FE5309181C7D,0xCFE92984BF3486D5
|
||||
0x23789E777D14CE44,0x2B3725FC402B94A8
|
||||
0x350AA5EBC03D3BD2,0x606408352C7741AD
|
||||
0x498C1E05CE5F7877,0x59E8FA762FB527C5
|
||||
...
|
||||
```
|
||||
|
||||
## Natives Gen
|
||||
|
||||
`natives_gen.py` is used to generate the Lua bindings for all the natives currently present in the menu.
|
||||
It'll read through the `src/natives.hpp` file and generate the appropriate bindings under `src/lua/natives/`.
|
@ -1,12 +0,0 @@
|
||||
include(FetchContent)
|
||||
|
||||
message("AsyncLogger")
|
||||
FetchContent_Declare(
|
||||
AsyncLogger
|
||||
GIT_REPOSITORY https://github.com/Yimura/AsyncLogger.git
|
||||
GIT_TAG v0.0.6
|
||||
GIT_PROGRESS TRUE
|
||||
)
|
||||
FetchContent_MakeAvailable(AsyncLogger)
|
||||
|
||||
set_property(TARGET AsyncLogger PROPERTY CXX_STANDARD 23)
|
@ -1,14 +0,0 @@
|
||||
include(FetchContent)
|
||||
|
||||
set(BUILD_TESTING_BEFORE ${BUILD_TESTING})
|
||||
set(CURL_DISABLE_TESTS OFF)
|
||||
FetchContent_Declare(
|
||||
cpr
|
||||
GIT_REPOSITORY https://github.com/libcpr/cpr.git
|
||||
GIT_TAG 1.10.5
|
||||
GIT_PROGRESS TRUE
|
||||
)
|
||||
message("cpr")
|
||||
FetchContent_MakeAvailable(cpr)
|
||||
|
||||
set(BUILD_TESTING ${BUILD_TESTING_BEFORE} CACHE INTERNAL "" FORCE)
|
6568
scripts/crossmap.txt
Normal file
6568
scripts/crossmap.txt
Normal file
File diff suppressed because it is too large
Load Diff
724
scripts/doc_gen.py
Normal file
724
scripts/doc_gen.py
Normal file
@ -0,0 +1,724 @@
|
||||
import os
|
||||
from enum import Enum
|
||||
|
||||
src_folder = "../../src/"
|
||||
|
||||
lua_api_comment_identifier = "lua api"
|
||||
lua_api_comment_separator = ":"
|
||||
|
||||
tables = {}
|
||||
classes = {}
|
||||
functions = {}
|
||||
|
||||
|
||||
class DocKind(Enum):
|
||||
Table = "table"
|
||||
Class = "class"
|
||||
Field = "field"
|
||||
Constructor = "constructor"
|
||||
Function = "function"
|
||||
Tabs = "tabs"
|
||||
Infraction = "infraction"
|
||||
|
||||
|
||||
class Table:
|
||||
def __init__(self, name, fields, functions, description):
|
||||
self.name = name.strip()
|
||||
self.fields = fields
|
||||
self.functions = functions
|
||||
self.description = description
|
||||
|
||||
def __str__(self):
|
||||
s = f"# Table: {self.name}\n"
|
||||
s += "\n"
|
||||
|
||||
if len(self.description) > 0:
|
||||
s += f"{self.description}\n"
|
||||
s += "\n"
|
||||
|
||||
if len(self.fields) > 0:
|
||||
s += f"## Fields ({len(self.fields)})\n"
|
||||
s += "\n"
|
||||
|
||||
self.check_for_duplicate_fields_names()
|
||||
|
||||
for field in self.fields:
|
||||
s += field.print_markdown()
|
||||
|
||||
if len(self.functions) > 0:
|
||||
s += f"## Functions ({len(self.functions)})\n"
|
||||
s += "\n"
|
||||
|
||||
for func in self.functions:
|
||||
s += func.print_markdown(f"{self.name}.")
|
||||
|
||||
s += "\n"
|
||||
|
||||
return s
|
||||
|
||||
def check_for_duplicate_fields_names(self):
|
||||
seen = set()
|
||||
duplicates = [x for x in self.fields if x.name in seen or seen.add(x.name)]
|
||||
if len(duplicates) > 0:
|
||||
print("Error while building lua doc. Duplicate field names:")
|
||||
for dup in duplicates:
|
||||
print(dup)
|
||||
exit(1)
|
||||
|
||||
|
||||
class Class:
|
||||
def __init__(self, name, inheritance, fields, constructors, functions, description):
|
||||
self.name = name.strip()
|
||||
self.inheritance = inheritance
|
||||
self.fields = fields
|
||||
self.constructors = constructors
|
||||
self.functions = functions
|
||||
self.description = description
|
||||
|
||||
def __str__(self):
|
||||
s = f"# Class: {self.name}\n"
|
||||
s += "\n"
|
||||
|
||||
if len(self.inheritance) > 0:
|
||||
inherited_class_names = ", ".join(self.inheritance)
|
||||
s += f"## Inherit from {len(self.inheritance)} class: {inherited_class_names}\n"
|
||||
s += "\n"
|
||||
|
||||
if len(self.description) > 0:
|
||||
s += f"{self.description}\n"
|
||||
s += "\n"
|
||||
|
||||
if len(self.fields) > 0:
|
||||
s += f"## Fields ({len(self.fields)})\n"
|
||||
s += "\n"
|
||||
|
||||
self.check_for_duplicate_fields_names()
|
||||
|
||||
for field in self.fields:
|
||||
s += field.print_markdown()
|
||||
|
||||
if len(self.constructors) > 0:
|
||||
s += f"## Constructors ({len(self.constructors)})\n"
|
||||
s += "\n"
|
||||
|
||||
for ctor in self.constructors:
|
||||
s += ctor.print_markdown()
|
||||
|
||||
if len(self.functions) > 0:
|
||||
s += f"## Functions ({len(self.functions)})\n"
|
||||
s += "\n"
|
||||
|
||||
for func in self.functions:
|
||||
s += func.print_markdown(f"{self.name}:")
|
||||
|
||||
s += "\n"
|
||||
|
||||
return s
|
||||
|
||||
def check_for_duplicate_fields_names(self):
|
||||
seen = set()
|
||||
duplicates = [x for x in self.fields if x.name in seen or seen.add(x.name)]
|
||||
if len(duplicates) > 0:
|
||||
print("Error while building lua doc. Duplicate field names:")
|
||||
for dup in duplicates:
|
||||
print(dup)
|
||||
exit(1)
|
||||
|
||||
|
||||
class Field:
|
||||
def __init__(self, name, type_, description):
|
||||
self.name = name.strip()
|
||||
self.type_ = type_.strip()
|
||||
self.description = description
|
||||
|
||||
def __str__(self):
|
||||
s = f"Field: {self.name}\n"
|
||||
s += f"Type: {self.type_}\n"
|
||||
s += f"Description: {self.description.strip()}\n"
|
||||
return s
|
||||
|
||||
def print_markdown(self):
|
||||
s = ""
|
||||
|
||||
s += f"### `{self.name}`\n"
|
||||
s += "\n"
|
||||
|
||||
if len(self.description) > 0:
|
||||
s += f"{self.description}\n"
|
||||
s += "\n"
|
||||
|
||||
if self.type_ is not None and len(self.type_) > 0:
|
||||
s += f"- Type: `{self.type_}`\n"
|
||||
|
||||
s += "\n"
|
||||
|
||||
return s
|
||||
|
||||
|
||||
class Constructor:
|
||||
def __init__(self, parent, parameters, description):
|
||||
self.parent = parent
|
||||
self.parameters = parameters
|
||||
self.description = description
|
||||
|
||||
def print_markdown(self):
|
||||
s = ""
|
||||
|
||||
parameters_str = ", ".join(p.name for p in self.parameters)
|
||||
|
||||
s += f"### `new({parameters_str})`\n"
|
||||
s += "\n"
|
||||
|
||||
if len(self.description) > 0:
|
||||
s += f"{self.description}\n"
|
||||
s += "\n"
|
||||
|
||||
if len(self.parameters) > 0:
|
||||
s += f"- **Parameters:**\n"
|
||||
for param in self.parameters:
|
||||
s += f" - `{param.name}` ({param.type_})"
|
||||
if len(param.description) > 0:
|
||||
s += f": {param.description}\n"
|
||||
else:
|
||||
s += f"\n"
|
||||
s += "\n"
|
||||
|
||||
s += f"**Example Usage:**\n"
|
||||
s += "```lua\n"
|
||||
|
||||
s += f"myInstance = {self.parent.name}:new({parameters_str})\n"
|
||||
|
||||
s += "```\n"
|
||||
s += "\n"
|
||||
|
||||
return s
|
||||
|
||||
|
||||
class Parameter:
|
||||
def __init__(self, name, type_, description):
|
||||
self.name = name.strip()
|
||||
self.type_ = type_.strip()
|
||||
self.description = description
|
||||
|
||||
def __str__(self):
|
||||
s = f"Parameter: {self.name}\n"
|
||||
s += f"Type: {self.type_}\n"
|
||||
s += f"Description: {self.description.strip()}\n"
|
||||
return s
|
||||
|
||||
|
||||
class Function:
|
||||
def __init__(
|
||||
self, name, parent, parameters, return_type, return_description, description
|
||||
):
|
||||
self.name = name.strip()
|
||||
self.parent = parent
|
||||
self.parameters = parameters
|
||||
self.return_type = return_type
|
||||
self.return_description = return_description
|
||||
self.description = description
|
||||
|
||||
def __str__(self):
|
||||
s = f"Function: {self.name}\n"
|
||||
|
||||
type_name = str(type(self.parent)).split(".")[1][:-2]
|
||||
s += f"Parent: {self.parent.name} ({type_name})\n"
|
||||
|
||||
s += f"Parameters: {len(self.parameters)}\n"
|
||||
i = 1
|
||||
for param in self.parameters:
|
||||
s += f"Parameter {i}\n"
|
||||
s += str(param) + "\n"
|
||||
i += 1
|
||||
|
||||
s += f"Return Type: {self.return_type}\n"
|
||||
s += f"Return Description: {self.return_description}\n"
|
||||
|
||||
s += f"Description: {self.description}\n"
|
||||
return s
|
||||
|
||||
def print_markdown(self, prefix):
|
||||
s = ""
|
||||
|
||||
parameters_str = ", ".join(p.name for p in self.parameters)
|
||||
|
||||
s += f"### `{self.name}({parameters_str})`\n"
|
||||
s += "\n"
|
||||
|
||||
if len(self.description) > 0:
|
||||
s += f"{self.description}\n"
|
||||
s += "\n"
|
||||
|
||||
if len(self.parameters) > 0:
|
||||
s += f"- **Parameters:**\n"
|
||||
for param in self.parameters:
|
||||
s += f" - `{param.name}` ({param.type_})"
|
||||
if len(param.description) > 0:
|
||||
s += f": {param.description}\n"
|
||||
else:
|
||||
s += f"\n"
|
||||
s += "\n"
|
||||
|
||||
if self.return_type is not None and len(self.return_type) > 0:
|
||||
s += f"- **Returns:**\n"
|
||||
s += f" - `{self.return_type}`: {self.return_description}\n"
|
||||
|
||||
s += "\n"
|
||||
|
||||
s += f"**Example Usage:**\n"
|
||||
s += "```lua\n"
|
||||
if self.return_type is not None and len(self.return_type) > 0:
|
||||
s += self.return_type + " = "
|
||||
|
||||
if "Global Table" in prefix:
|
||||
prefix = ""
|
||||
s += f"{prefix}{self.name}({parameters_str})\n"
|
||||
|
||||
s += "```\n"
|
||||
s += "\n"
|
||||
|
||||
return s
|
||||
|
||||
|
||||
def make_table(table_name):
|
||||
if table_name not in tables:
|
||||
tables[table_name] = Table(table_name, [], [], "")
|
||||
cur_table = tables[table_name]
|
||||
return cur_table
|
||||
|
||||
|
||||
def make_class(class_name):
|
||||
if class_name not in classes:
|
||||
classes[class_name] = Class(class_name, [], [], [], [], "")
|
||||
cur_class = classes[class_name]
|
||||
return cur_class
|
||||
|
||||
|
||||
def is_comment_a_lua_api_doc_comment(text_lower):
|
||||
return (
|
||||
lua_api_comment_identifier in text_lower
|
||||
and lua_api_comment_separator in text_lower
|
||||
and "//" in text_lower
|
||||
)
|
||||
|
||||
|
||||
def parse_lua_api_doc(folder_path):
|
||||
for root, dirs, files in os.walk(folder_path):
|
||||
for file_name in files:
|
||||
if os.path.splitext(file_name)[1].startswith((".c", ".h")):
|
||||
file_path = os.path.join(root, file_name)
|
||||
with open(file_path, "r") as file:
|
||||
doc_kind = None
|
||||
cur_table = None
|
||||
cur_class = None
|
||||
cur_function = None
|
||||
cur_field = None
|
||||
cur_constructor = None
|
||||
|
||||
for line in file:
|
||||
line = line.strip()
|
||||
line_lower = line.lower()
|
||||
if is_comment_a_lua_api_doc_comment(line_lower):
|
||||
doc_kind = DocKind(
|
||||
line.split(lua_api_comment_separator, 1)[1]
|
||||
.strip()
|
||||
.lower()
|
||||
)
|
||||
|
||||
if (
|
||||
doc_kind is not DocKind.Tabs
|
||||
and doc_kind is not DocKind.Infraction
|
||||
):
|
||||
continue
|
||||
|
||||
if doc_kind is not None and "//" in line:
|
||||
match doc_kind:
|
||||
case DocKind.Table:
|
||||
cur_table = parse_table_doc(
|
||||
cur_table, line, line_lower
|
||||
)
|
||||
case DocKind.Class:
|
||||
cur_class = parse_class_doc(
|
||||
cur_class, line, line_lower
|
||||
)
|
||||
case DocKind.Function:
|
||||
(
|
||||
cur_function,
|
||||
cur_table,
|
||||
cur_class,
|
||||
) = parse_function_doc(
|
||||
cur_function,
|
||||
cur_table,
|
||||
cur_class,
|
||||
line,
|
||||
line_lower,
|
||||
)
|
||||
case DocKind.Field:
|
||||
(cur_field, cur_table, cur_class) = parse_field_doc(
|
||||
cur_field,
|
||||
cur_table,
|
||||
cur_class,
|
||||
line,
|
||||
line_lower,
|
||||
)
|
||||
case DocKind.Constructor:
|
||||
(
|
||||
cur_constructor,
|
||||
cur_class,
|
||||
) = parse_constructor_doc(
|
||||
cur_constructor,
|
||||
cur_class,
|
||||
line,
|
||||
line_lower,
|
||||
)
|
||||
case DocKind.Tabs:
|
||||
parse_tabs_doc(file)
|
||||
case DocKind.Infraction:
|
||||
parse_infraction_doc(file)
|
||||
case _:
|
||||
# print("unsupported doc kind: " + str(doc_kind))
|
||||
pass
|
||||
else:
|
||||
doc_kind = None
|
||||
|
||||
|
||||
def parse_table_doc(cur_table, line, line_lower):
|
||||
if is_lua_doc_comment_startswith(line_lower, "name"):
|
||||
table_name = line.split(lua_api_comment_separator, 1)[1].strip()
|
||||
cur_table = make_table(table_name)
|
||||
else:
|
||||
if len(cur_table.description) != 0:
|
||||
cur_table.description += "\n"
|
||||
cur_table.description += sanitize_description(line)
|
||||
|
||||
return cur_table
|
||||
|
||||
|
||||
def parse_class_doc(cur_class, line, line_lower):
|
||||
if is_lua_doc_comment_startswith(line_lower, "name"):
|
||||
class_name = line.split(lua_api_comment_separator, 1)[1].strip()
|
||||
cur_class = make_class(class_name)
|
||||
elif is_lua_doc_comment_startswith(line_lower, "inherit"):
|
||||
inherited_class_name = line.split(lua_api_comment_separator, 1)[1].strip()
|
||||
cur_class.inheritance.append(inherited_class_name)
|
||||
else:
|
||||
if len(cur_class.description) != 0:
|
||||
cur_class.description += "\n"
|
||||
cur_class.description += sanitize_description(line)
|
||||
|
||||
return cur_class
|
||||
|
||||
|
||||
def parse_function_doc(cur_function, cur_table, cur_class, line, line_lower):
|
||||
if (
|
||||
is_lua_doc_comment_startswith(line_lower, "table")
|
||||
and lua_api_comment_separator in line_lower
|
||||
):
|
||||
table_name = line.split(lua_api_comment_separator, 1)[1].strip()
|
||||
cur_table = make_table(table_name)
|
||||
|
||||
cur_function = Function("Didnt get name yet", cur_table, [], None, "", "")
|
||||
cur_table.functions.append(cur_function)
|
||||
elif (
|
||||
is_lua_doc_comment_startswith(line_lower, "class")
|
||||
and lua_api_comment_separator in line_lower
|
||||
):
|
||||
class_name = line.split(lua_api_comment_separator, 1)[1].strip()
|
||||
cur_class = make_class(class_name)
|
||||
|
||||
cur_function = Function("Didnt get name yet", cur_class, [], None, "", "")
|
||||
cur_class.functions.append(cur_function)
|
||||
elif (
|
||||
is_lua_doc_comment_startswith(line_lower, "name")
|
||||
and lua_api_comment_separator in line_lower
|
||||
):
|
||||
function_name = line.split(lua_api_comment_separator, 1)[1].strip()
|
||||
cur_function.name = function_name
|
||||
|
||||
if function_name not in functions:
|
||||
functions[function_name] = cur_function
|
||||
elif (
|
||||
is_lua_doc_comment_startswith(line_lower, "param")
|
||||
and lua_api_comment_separator in line_lower
|
||||
):
|
||||
parameter = make_parameter_from_doc_line(line)
|
||||
cur_function.parameters.append(parameter)
|
||||
elif (
|
||||
is_lua_doc_comment_startswith(line_lower, "return")
|
||||
and lua_api_comment_separator in line_lower
|
||||
):
|
||||
return_info = line.split(lua_api_comment_separator, 2)
|
||||
try:
|
||||
cur_function.return_type = return_info[1].strip()
|
||||
cur_function.return_description = return_info[2].strip()
|
||||
except IndexError:
|
||||
pass
|
||||
else:
|
||||
if len(cur_function.description) != 0:
|
||||
cur_function.description += "\n"
|
||||
cur_function.description += sanitize_description(line)
|
||||
|
||||
return cur_function, cur_table, cur_class
|
||||
|
||||
|
||||
def parse_field_doc(cur_field, cur_table, cur_class, line, line_lower):
|
||||
if (
|
||||
is_lua_doc_comment_startswith(line_lower, "table")
|
||||
and lua_api_comment_separator in line_lower
|
||||
):
|
||||
table_name = line.split(lua_api_comment_separator, 1)[1].strip()
|
||||
cur_table = make_table(table_name)
|
||||
|
||||
cur_field = Field("Didnt get name yet", "", "")
|
||||
cur_table.fields.append(cur_field)
|
||||
elif (
|
||||
is_lua_doc_comment_startswith(line_lower, "class")
|
||||
and lua_api_comment_separator in line_lower
|
||||
):
|
||||
class_name = line.split(lua_api_comment_separator, 1)[1].strip()
|
||||
cur_class = make_class(class_name)
|
||||
|
||||
cur_field = Field("Didnt get name yet", "", "")
|
||||
cur_class.fields.append(cur_field)
|
||||
elif (
|
||||
is_lua_doc_comment_startswith(line_lower, "field")
|
||||
and lua_api_comment_separator in line_lower
|
||||
):
|
||||
field_info = line.split(lua_api_comment_separator, 2)
|
||||
cur_field.name = field_info[1].strip()
|
||||
cur_field.type_ = field_info[2].strip()
|
||||
else:
|
||||
if len(cur_field.description) != 0:
|
||||
cur_field.description += "\n"
|
||||
|
||||
if line.startswith("// "):
|
||||
line = line[3:]
|
||||
cur_field.description += sanitize_description(line)
|
||||
|
||||
return cur_field, cur_table, cur_class
|
||||
|
||||
|
||||
def parse_constructor_doc(cur_constructor, cur_class, line, line_lower):
|
||||
if (
|
||||
is_lua_doc_comment_startswith(line_lower, "class")
|
||||
and lua_api_comment_separator in line_lower
|
||||
):
|
||||
class_name = line.split(lua_api_comment_separator, 1)[1].strip()
|
||||
cur_class = make_class(class_name)
|
||||
|
||||
cur_constructor = Constructor(cur_class, [], "")
|
||||
cur_class.constructors.append(cur_constructor)
|
||||
elif (
|
||||
is_lua_doc_comment_startswith(line_lower, "param")
|
||||
and lua_api_comment_separator in line_lower
|
||||
):
|
||||
parameter = make_parameter_from_doc_line(line)
|
||||
cur_constructor.parameters.append(parameter)
|
||||
else:
|
||||
if len(cur_constructor.description) != 0:
|
||||
cur_constructor.description += "\n"
|
||||
cur_constructor.description += sanitize_description(line)
|
||||
|
||||
return cur_constructor, cur_class
|
||||
|
||||
|
||||
tabs_enum = []
|
||||
|
||||
|
||||
def parse_tabs_doc(file):
|
||||
start_parsing = False
|
||||
for line in file:
|
||||
if "enum class" in line.lower():
|
||||
start_parsing = True
|
||||
continue
|
||||
|
||||
if start_parsing:
|
||||
if "};" in line.lower():
|
||||
return
|
||||
if "{" == line.lower().strip():
|
||||
continue
|
||||
if "//" in line.lower():
|
||||
continue
|
||||
if "" == line.lower().strip():
|
||||
continue
|
||||
else:
|
||||
tabs_enum.append(line.replace(",", "").strip())
|
||||
|
||||
|
||||
infraction_enum = []
|
||||
|
||||
|
||||
def parse_infraction_doc(file):
|
||||
start_parsing = False
|
||||
for line in file:
|
||||
if "enum class" in line.lower():
|
||||
start_parsing = True
|
||||
continue
|
||||
|
||||
if start_parsing:
|
||||
if "};" in line.lower():
|
||||
return
|
||||
if "{" == line.lower().strip():
|
||||
continue
|
||||
if "//" in line.lower():
|
||||
continue
|
||||
if "" == line.lower().strip():
|
||||
continue
|
||||
else:
|
||||
infraction_enum.append(line.replace(",", "").strip())
|
||||
|
||||
|
||||
def make_parameter_from_doc_line(line):
|
||||
param_info = line.split(lua_api_comment_separator, 3)[1:]
|
||||
param_name = param_type = param_desc = ""
|
||||
|
||||
try:
|
||||
param_name = param_info[0].strip()
|
||||
param_type = param_info[1].strip()
|
||||
param_desc = param_info[2].strip()
|
||||
except IndexError:
|
||||
pass
|
||||
|
||||
return Parameter(param_name, param_type, param_desc)
|
||||
|
||||
|
||||
def sanitize_description(line):
|
||||
if line.startswith("// ") and line[3] != " ":
|
||||
line = line[3:]
|
||||
if line.startswith("//"):
|
||||
line = line[2:]
|
||||
return line.rstrip()
|
||||
|
||||
|
||||
def is_lua_doc_comment_startswith(line_lower, starts_with_text):
|
||||
return line_lower.replace("//", "").strip().startswith(starts_with_text)
|
||||
|
||||
|
||||
parse_lua_api_doc(src_folder)
|
||||
|
||||
try:
|
||||
os.makedirs("./tables/")
|
||||
except:
|
||||
pass
|
||||
|
||||
for table_name, table in tables.items():
|
||||
file_name = f"./tables/{table_name}.md"
|
||||
if os.path.exists(file_name):
|
||||
os.remove(file_name)
|
||||
f = open(file_name, "ba")
|
||||
f.write(bytes(str(table), "UTF8"))
|
||||
f.close()
|
||||
|
||||
tabs_file_name = f"./tabs.md"
|
||||
if os.path.exists(tabs_file_name):
|
||||
os.remove(tabs_file_name)
|
||||
f = open(tabs_file_name, "a")
|
||||
|
||||
f.write(
|
||||
"""# Tabs
|
||||
|
||||
All the tabs from the menu are listed below, used as parameter for adding gui elements to them.
|
||||
|
||||
**Example Usage:**
|
||||
|
||||
```lua
|
||||
missionsTab = gui.get_tab("GUI_TAB_MISSIONS")
|
||||
missionsTab:add_button("Click me", function ()
|
||||
log.info("You clicked!")
|
||||
end)
|
||||
```
|
||||
|
||||
For a complete list of available gui functions, please refer to the tab class documentation and the gui table documentation.
|
||||
|
||||
"""
|
||||
)
|
||||
|
||||
f.write(f"## Tab Count: {len(tabs_enum)}\n\n")
|
||||
|
||||
# Minus the first, because it's the `NONE` tab, minus the last one because it's for runtime defined tabs.
|
||||
for i in range(1, len(tabs_enum) - 1):
|
||||
f.write("### `GUI_TAB_" + tabs_enum[i] + "`\n")
|
||||
|
||||
f.close()
|
||||
|
||||
infraction_file_name = f"../lua/infraction.md"
|
||||
if os.path.exists(infraction_file_name):
|
||||
os.remove(infraction_file_name)
|
||||
f = open(infraction_file_name, "a")
|
||||
|
||||
f.write(
|
||||
"""# Infraction
|
||||
|
||||
All the infraction from the menu are listed below, used as parameter for adding an infraction to a given player, for flagging them as modder.
|
||||
|
||||
**Example Usage:**
|
||||
```lua
|
||||
network.flag_player_as_modder(player_index, infraction.CUSTOM_REASON, "My custom reason on why the player is flagged as a modder")
|
||||
```
|
||||
|
||||
"""
|
||||
)
|
||||
|
||||
f.write(f"## Infraction Count: {len(infraction_enum)}\n\n")
|
||||
|
||||
for i in range(0, len(infraction_enum)):
|
||||
f.write("### `" + infraction_enum[i] + "`\n")
|
||||
|
||||
f.close()
|
||||
|
||||
try:
|
||||
os.makedirs("./classes/")
|
||||
except:
|
||||
pass
|
||||
|
||||
for class_name, class_ in classes.items():
|
||||
file_name = f"./classes/{class_name}.md"
|
||||
if os.path.exists(file_name):
|
||||
os.remove(file_name)
|
||||
f = open(file_name, "ba")
|
||||
f.write(bytes(str(class_), "UTF8"))
|
||||
f.close()
|
||||
|
||||
|
||||
commands_file_name = f"./commands.md"
|
||||
if os.path.exists(commands_file_name):
|
||||
os.remove(commands_file_name)
|
||||
f = open(commands_file_name, "a")
|
||||
|
||||
f.write(
|
||||
"""# Commands
|
||||
|
||||
All the current commands from the menu are listed below.
|
||||
|
||||
**Example Usage through Lua:**
|
||||
|
||||
```lua
|
||||
command.call("spawn", {joaat("adder")})
|
||||
command.call_player(somePlayerIndex, "spawn", {joaat("adder")})
|
||||
```
|
||||
|
||||
For a complete list of available command functions, please refer to the command table documentation.
|
||||
|
||||
"""
|
||||
)
|
||||
|
||||
|
||||
commands = []
|
||||
with open("./commands_dump.txt", "r") as file:
|
||||
for line in file:
|
||||
cmd = line.split("|", 1)[1].strip().split("|")
|
||||
commands.append(cmd)
|
||||
|
||||
f.write(f"## Command Count: {len(commands)}\n\n")
|
||||
|
||||
for cmd in commands:
|
||||
name = cmd[0]
|
||||
label = cmd[1]
|
||||
desc = cmd[2]
|
||||
arg_count = cmd[3]
|
||||
f.write(f"### {name}\n")
|
||||
f.write(f"{desc}\n")
|
||||
f.write(f"Arg Count: {arg_count}\n")
|
||||
f.write("\n")
|
||||
|
||||
f.close()
|
123
scripts/generate_natives.py
Normal file
123
scripts/generate_natives.py
Normal file
@ -0,0 +1,123 @@
|
||||
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()
|
@ -1,38 +0,0 @@
|
||||
find_package(Git)
|
||||
if(Git_FOUND)
|
||||
message("Git found: ${GIT_EXECUTABLE}")
|
||||
|
||||
# the commit's SHA1, and whether the building workspace was dirty or not
|
||||
execute_process(COMMAND
|
||||
"${GIT_EXECUTABLE}" describe --match=NeVeRmAtCh --always --abbrev=40 --dirty
|
||||
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
OUTPUT_VARIABLE GIT_SHA1
|
||||
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
|
||||
# the date of the commit
|
||||
execute_process(COMMAND
|
||||
"${GIT_EXECUTABLE}" log -1 --format=%ad --date=local
|
||||
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
OUTPUT_VARIABLE GIT_DATE
|
||||
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
|
||||
# the subject of the commit
|
||||
execute_process(COMMAND
|
||||
"${GIT_EXECUTABLE}" log -1 --format=%s
|
||||
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
OUTPUT_VARIABLE GIT_COMMIT_SUBJECT
|
||||
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
|
||||
# Commit messages may have quotes in them, which can affect the const char* variable.
|
||||
string(REPLACE "\"" "\\\"" GIT_COMMIT_SUBJECT "${GIT_COMMIT_SUBJECT}")
|
||||
|
||||
# branch name
|
||||
execute_process(COMMAND
|
||||
"${GIT_EXECUTABLE}" branch --show-current
|
||||
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
OUTPUT_VARIABLE GIT_BRANCH
|
||||
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
|
||||
# generate version.cpp
|
||||
configure_file("${SRC_DIR}/version.cpp.in" "${SRC_DIR}/version.cpp" @ONLY)
|
||||
endif()
|
@ -1,14 +0,0 @@
|
||||
include(FetchContent)
|
||||
|
||||
FetchContent_Declare(
|
||||
gtav_classes
|
||||
GIT_REPOSITORY https://github.com/Yimura/GTAV-Classes.git
|
||||
GIT_TAG e8d8bdd2b3152253f6e1fde48720e4caeab19f83
|
||||
GIT_PROGRESS TRUE
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
)
|
||||
message("GTAV-Classes")
|
||||
if(NOT gtav_classes_POPULATED)
|
||||
FetchContent_Populate(gtav_classes)
|
||||
endif()
|
@ -1,28 +0,0 @@
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
imgui
|
||||
GIT_REPOSITORY https://github.com/ocornut/imgui.git
|
||||
GIT_TAG v1.90
|
||||
GIT_PROGRESS TRUE
|
||||
)
|
||||
message("ImGui")
|
||||
FetchContent_GetProperties(imgui)
|
||||
if(NOT imgui_POPULATED)
|
||||
FetchContent_Populate(imgui)
|
||||
|
||||
file(GLOB SRC_IMGUI
|
||||
"${imgui_SOURCE_DIR}/*.cpp"
|
||||
"${imgui_SOURCE_DIR}/backends/imgui_impl_win32.cpp"
|
||||
"${imgui_SOURCE_DIR}/backends/imgui_impl_dx11.cpp"
|
||||
"${imgui_SOURCE_DIR}/misc/cpp/imgui_stdlib.cpp"
|
||||
)
|
||||
|
||||
add_library(imgui STATIC ${SRC_IMGUI} )
|
||||
source_group(TREE ${imgui_SOURCE_DIR} PREFIX "imgui" FILES ${SRC_IMGUI})
|
||||
target_include_directories(imgui PRIVATE
|
||||
"${imgui_SOURCE_DIR}"
|
||||
"${imgui_SOURCE_DIR}/backends"
|
||||
"${imgui_SOURCE_DIR}/misc/cpp"
|
||||
)
|
||||
endif()
|
||||
set_property(TARGET imgui PROPERTY CXX_STANDARD 23)
|
@ -1,12 +0,0 @@
|
||||
include(FetchContent)
|
||||
|
||||
set(JSON_MultipleHeaders OFF)
|
||||
|
||||
FetchContent_Declare(
|
||||
json
|
||||
GIT_REPOSITORY https://github.com/ArthurSonzogni/nlohmann_json_cmake_fetchcontent.git
|
||||
GIT_TAG 67e6070f9d9a44b4dec79ebe6b591f39d2285593
|
||||
GIT_PROGRESS TRUE
|
||||
)
|
||||
message("json")
|
||||
FetchContent_MakeAvailable(json)
|
@ -1,12 +0,0 @@
|
||||
include(FetchContent)
|
||||
|
||||
message("Lua")
|
||||
FetchContent_Declare(
|
||||
Lua
|
||||
GIT_REPOSITORY https://github.com/walterschell/Lua.git
|
||||
GIT_TAG a2e0125df529894f5e25d7d477b2df4e37690e0f
|
||||
GIT_PROGRESS TRUE
|
||||
)
|
||||
FetchContent_MakeAvailable(Lua)
|
||||
|
||||
set_property(TARGET lua_static PROPERTY CXX_STANDARD 23)
|
@ -1,11 +0,0 @@
|
||||
include(FetchContent)
|
||||
|
||||
FetchContent_Declare(
|
||||
minhook
|
||||
GIT_REPOSITORY https://github.com/YimMenu/minhook.git
|
||||
GIT_TAG 902ab63e0a771547961e132ccc0700d62e2a1423
|
||||
GIT_PROGRESS TRUE
|
||||
)
|
||||
message("MinHook")
|
||||
FetchContent_MakeAvailable(minhook)
|
||||
set_property(TARGET minhook PROPERTY CXX_STANDARD 23)
|
119453
scripts/natives.json
Normal file
119453
scripts/natives.json
Normal file
File diff suppressed because one or more lines are too long
330
scripts/natives_gen.py
Normal file
330
scripts/natives_gen.py
Normal file
@ -0,0 +1,330 @@
|
||||
import os
|
||||
|
||||
natives_hpp = open("../../natives.hpp", "r")
|
||||
|
||||
cpp_print_buf = ""
|
||||
hpp_print_buf = ""
|
||||
|
||||
hpp_lua_native_wrappers_print_buf = ""
|
||||
|
||||
|
||||
def print_cpp(text):
|
||||
global cpp_print_buf
|
||||
cpp_print_buf += text + "\n"
|
||||
|
||||
|
||||
def print_hpp(text):
|
||||
global hpp_print_buf
|
||||
hpp_print_buf += text + "\n"
|
||||
|
||||
|
||||
class Arg:
|
||||
def __init__(self, name, type_):
|
||||
self.name = name
|
||||
self.type_ = type_.replace("BOOL", "bool")
|
||||
self.is_pointer_arg = "*" in type_ and "const char" not in type_
|
||||
self.type_no_star = self.type_.replace("*", "")
|
||||
|
||||
def __str__(self) -> str:
|
||||
return str(self.type_) + " " + str(self.name)
|
||||
|
||||
|
||||
class NativeFunc:
|
||||
def __init__(self, namespace, lua_name, cpp_name, args, return_type):
|
||||
self.namespace = namespace
|
||||
self.lua_name = lua_name
|
||||
self.cpp_name = cpp_name
|
||||
self.args = args
|
||||
self.return_type = return_type.replace("BOOL", "bool")
|
||||
|
||||
self.out_params = []
|
||||
if self.return_type != "void":
|
||||
retvalArg = Arg("retval", self.return_type)
|
||||
# Any* case: this is incorrect but
|
||||
# we'd need a custom lua usertype and write code for it inside the native function wrappers,
|
||||
# it also only affect some of the DATAFILE natives.
|
||||
retvalArg.is_pointer_arg = False
|
||||
self.out_params.append(retvalArg)
|
||||
for arg in self.args:
|
||||
if arg.is_pointer_arg:
|
||||
self.out_params.append(arg)
|
||||
|
||||
def __str__(self) -> str:
|
||||
s = ""
|
||||
|
||||
returning_multiple_values = False
|
||||
tuple_type = ""
|
||||
fixed_return = self.return_type
|
||||
if len(self.out_params) > 1:
|
||||
fixed_return = "std::tuple<"
|
||||
for out_param in self.out_params:
|
||||
if out_param.is_pointer_arg:
|
||||
fixed_return += out_param.type_no_star + ", "
|
||||
else:
|
||||
fixed_return += out_param.type_ + ", "
|
||||
fixed_return = fixed_return[:-2] + ">"
|
||||
returning_multiple_values = True
|
||||
tuple_type = fixed_return
|
||||
elif len(self.out_params) == 1:
|
||||
if self.out_params[0].is_pointer_arg:
|
||||
fixed_return = self.out_params[0].type_no_star
|
||||
else:
|
||||
fixed_return = self.out_params[0].type_
|
||||
|
||||
fixed_params = ""
|
||||
if len(self.args) > 0:
|
||||
for arg in self.args:
|
||||
if not arg.is_pointer_arg:
|
||||
fixed_params += arg.type_ + " " + arg.name + ", "
|
||||
else:
|
||||
fixed_params += arg.type_no_star + " " + arg.name + ", "
|
||||
fixed_params = fixed_params[:-2]
|
||||
|
||||
s += (
|
||||
fixed_return
|
||||
+ " "
|
||||
+ "LUA_NATIVE_"
|
||||
+ self.namespace
|
||||
+ "_"
|
||||
+ self.lua_name
|
||||
+ "("
|
||||
+ fixed_params
|
||||
+ ")"
|
||||
)
|
||||
|
||||
s += "\n"
|
||||
s += "\t{\n"
|
||||
|
||||
if self.cpp_name == "ADD_OWNED_EXPLOSION":
|
||||
s+= "\t\tbig::explosion_anti_cheat_bypass::apply();\n\n"
|
||||
|
||||
call_native = "\t\t"
|
||||
if len(self.out_params) > 0:
|
||||
if returning_multiple_values:
|
||||
tuple_declaration = tuple_type + " return_values;"
|
||||
s += "\t\t" + tuple_declaration + "\n"
|
||||
if self.return_type != "void":
|
||||
call_native += "std::get<0>(return_values) = "
|
||||
if self.return_type == "bool":
|
||||
call_native += "(bool)"
|
||||
elif self.return_type != "void":
|
||||
call_native += "auto retval = "
|
||||
if self.return_type == "bool":
|
||||
call_native += "(bool)"
|
||||
|
||||
call_native += self.namespace + "::" + self.cpp_name + "("
|
||||
else:
|
||||
call_native += self.namespace + "::" + self.cpp_name + "("
|
||||
|
||||
if len(self.args) > 0:
|
||||
for arg in self.args:
|
||||
if arg.is_pointer_arg:
|
||||
if arg.type_ == "bool*":
|
||||
call_native += "(BOOL*)"
|
||||
call_native += "&"
|
||||
|
||||
call_native += arg.name + ", "
|
||||
call_native = call_native[:-2]
|
||||
|
||||
call_native += ");"
|
||||
|
||||
s += call_native
|
||||
|
||||
if self.cpp_name == "ADD_OWNED_EXPLOSION":
|
||||
s+= "\n\n\t\tbig::explosion_anti_cheat_bypass::restore();"
|
||||
|
||||
if returning_multiple_values:
|
||||
assign_return_values = "\n"
|
||||
if self.return_type != "void":
|
||||
i = 1
|
||||
else:
|
||||
i = 0
|
||||
for arg in self.args:
|
||||
if arg.is_pointer_arg:
|
||||
assign_return_values += (
|
||||
"\t\tstd::get<"
|
||||
+ str(i)
|
||||
+ ">(return_values) = "
|
||||
+ arg.name
|
||||
+ ";\n"
|
||||
)
|
||||
i += 1
|
||||
s += assign_return_values
|
||||
|
||||
return_statement = ""
|
||||
if len(self.out_params) > 0:
|
||||
if returning_multiple_values:
|
||||
return_statement = "return return_values;"
|
||||
elif self.return_type != "void":
|
||||
return_statement = "return retval;"
|
||||
else:
|
||||
for arg in self.args:
|
||||
if arg.is_pointer_arg:
|
||||
return_statement = "return " + arg.name + ";"
|
||||
s += "\n\t\t" + return_statement
|
||||
|
||||
s += "\n\t}"
|
||||
|
||||
return s
|
||||
|
||||
|
||||
def get_natives_func_from_natives_hpp_file(natives_hpp):
|
||||
functions_per_namespaces = {}
|
||||
current_namespace = ""
|
||||
start_parsing = False
|
||||
for line in natives_hpp.readlines():
|
||||
if "namespace SYSTEM" not in line and not start_parsing:
|
||||
continue
|
||||
else:
|
||||
start_parsing = True
|
||||
|
||||
if not start_parsing:
|
||||
continue
|
||||
|
||||
if "namespace " in line:
|
||||
current_namespace = line.replace("namespace ", "").strip()
|
||||
functions_per_namespaces[current_namespace] = []
|
||||
elif "NATIVE_DECL" in line:
|
||||
words = line.split()
|
||||
|
||||
# remove NATIVE_DECL from the words array
|
||||
words.pop(0)
|
||||
|
||||
func_name = ""
|
||||
for word in words:
|
||||
if "(" in word:
|
||||
if func_name == "":
|
||||
func_name = word.split("(")[0]
|
||||
|
||||
continue
|
||||
|
||||
# Sol somehow choke on this, terrible software
|
||||
if func_name == "DRAW_TEXTURED_POLY_WITH_THREE_COLOURS":
|
||||
continue
|
||||
|
||||
args = []
|
||||
args_start = line.split("(")[1]
|
||||
if args_start[0] == ")":
|
||||
# no args
|
||||
pass
|
||||
else:
|
||||
args_str = args_start.split(")")[0]
|
||||
i = 0
|
||||
for arg in args_str.split(","):
|
||||
arg_type = arg[: arg.rfind(" ")].strip()
|
||||
arg_name = arg[arg.rfind(" ") :].strip()
|
||||
args.append(Arg(arg_name, arg_type))
|
||||
i += 1
|
||||
|
||||
return_type = (
|
||||
line[: line.find(func_name)].replace("NATIVE_DECL", "").strip()
|
||||
)
|
||||
|
||||
lua_name = func_name
|
||||
if lua_name.startswith('_'):
|
||||
lua_name = lua_name.removeprefix("_")
|
||||
lua_name = lua_name + "_"
|
||||
|
||||
native_func = NativeFunc(current_namespace, lua_name, func_name, args, return_type)
|
||||
|
||||
functions_per_namespaces[current_namespace].append(native_func)
|
||||
|
||||
return functions_per_namespaces
|
||||
|
||||
|
||||
functions_per_namespaces = get_natives_func_from_natives_hpp_file(natives_hpp)
|
||||
|
||||
def generate_native_binding_cpp_and_hpp_files(functions_per_namespaces):
|
||||
generated_function_name = "void init_native_binding(sol::state& L)"
|
||||
|
||||
print_hpp("#pragma once")
|
||||
# print_hpp('#include "lua/sol.hpp"')
|
||||
print_hpp("")
|
||||
print_hpp("namespace lua::native")
|
||||
print_hpp("{")
|
||||
print_hpp("\t" + generated_function_name + ";")
|
||||
print_hpp("")
|
||||
for namespace_name, native_funcs in functions_per_namespaces.items():
|
||||
print_hpp("\t" + "void init_native_binding_" + namespace_name + "(sol::state& L);")
|
||||
print_hpp("}")
|
||||
|
||||
print_cpp('#include "lua_native_binding.hpp"')
|
||||
print_cpp("")
|
||||
print_cpp("namespace lua::native")
|
||||
print_cpp("{")
|
||||
|
||||
i = 0
|
||||
|
||||
for namespace_name, native_funcs in functions_per_namespaces.items():
|
||||
|
||||
|
||||
file_name_cpp = "lua_native_binding_" + namespace_name + ".cpp"
|
||||
if os.path.exists(file_name_cpp):
|
||||
os.remove(file_name_cpp)
|
||||
f = open(file_name_cpp, "a")
|
||||
|
||||
file_buffer = ""
|
||||
|
||||
|
||||
file_buffer += '#include "lua_native_binding.hpp"\n'
|
||||
file_buffer += '#include "natives.hpp"\n'
|
||||
if namespace_name == "FIRE":
|
||||
file_buffer += '#include "util/explosion_anti_cheat_bypass.hpp"\n'
|
||||
file_buffer += "\n"
|
||||
file_buffer += "namespace lua::native\n"
|
||||
file_buffer += "{\n"
|
||||
|
||||
for native_func in native_funcs:
|
||||
file_buffer += "\tstatic " + str(native_func) + "\n\n"
|
||||
|
||||
file_buffer += "\t" + "void init_native_binding_" + namespace_name + "(sol::state& L)\n"
|
||||
file_buffer += "\t{\n"
|
||||
|
||||
file_buffer += "\t\tauto " + namespace_name + ' = L["' + namespace_name + '"].get_or_create<sol::table>();\n'
|
||||
|
||||
for native_func in native_funcs:
|
||||
i += 1
|
||||
file_buffer += "\t\t"+ namespace_name+ '.set_function("'+ native_func.lua_name+ '", '+ "LUA_NATIVE_"+ native_func.namespace+ "_"+ native_func.lua_name+ ");\n"
|
||||
|
||||
file_buffer+= "\t}\n"
|
||||
file_buffer+= "}\n"
|
||||
|
||||
f.write(file_buffer)
|
||||
f.close()
|
||||
|
||||
print_cpp("\t" + generated_function_name)
|
||||
print_cpp("\t{")
|
||||
|
||||
for namespace_name, native_funcs in functions_per_namespaces.items():
|
||||
# call each binding functions inside generated_function_name
|
||||
|
||||
print_cpp("\t\t" + "init_native_binding_" + namespace_name + "(L);")
|
||||
|
||||
print_cpp("\t}")
|
||||
print_cpp("}")
|
||||
|
||||
print(f"Wrote binding for {i} native functions")
|
||||
|
||||
|
||||
generate_native_binding_cpp_and_hpp_files(functions_per_namespaces)
|
||||
|
||||
def write_cpp_code(cpp_print_buf):
|
||||
file_name = "lua_native_binding.cpp"
|
||||
if os.path.exists(file_name):
|
||||
os.remove(file_name)
|
||||
f = open(file_name, "a")
|
||||
f.write(cpp_print_buf)
|
||||
f.close()
|
||||
|
||||
|
||||
def write_hpp_code(hpp_print_buf):
|
||||
file_name = "lua_native_binding.hpp"
|
||||
if os.path.exists(file_name):
|
||||
os.remove(file_name)
|
||||
f = open(file_name, "a")
|
||||
f.write(hpp_print_buf)
|
||||
f.close()
|
||||
|
||||
write_cpp_code(cpp_print_buf)
|
||||
write_hpp_code(hpp_print_buf)
|
||||
|
@ -1,11 +0,0 @@
|
||||
include(FetchContent)
|
||||
|
||||
FetchContent_Declare(
|
||||
pugixml
|
||||
GIT_REPOSITORY https://github.com/zeux/pugixml.git
|
||||
GIT_TAG a0e064336317c9347a91224112af9933598714e9
|
||||
GIT_PROGRESS TRUE
|
||||
)
|
||||
message("pugixml")
|
||||
FetchContent_MakeAvailable(pugixml)
|
||||
set_property(TARGET pugixml PROPERTY CXX_STANDARD 23)
|
Reference in New Issue
Block a user