PyREUser3 0.6.0__tar.gz → 0.7.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pyreuser3-0.6.0 → pyreuser3-0.7.1}/PKG-INFO +24 -1
- {pyreuser3-0.6.0 → pyreuser3-0.7.1}/PyREUser3.egg-info/PKG-INFO +24 -1
- {pyreuser3-0.6.0 → pyreuser3-0.7.1}/PyREUser3.egg-info/SOURCES.txt +5 -1
- pyreuser3-0.7.1/README.md +269 -0
- pyreuser3-0.7.1/docs/PYPI.md +63 -0
- {pyreuser3-0.6.0 → pyreuser3-0.7.1}/docs/README.zh-CN.md +95 -6
- {pyreuser3-0.6.0 → pyreuser3-0.7.1}/pyproject.toml +1 -1
- {pyreuser3-0.6.0 → pyreuser3-0.7.1}/pyreuser3/__init__.py +9 -0
- {pyreuser3-0.6.0 → pyreuser3-0.7.1}/pyreuser3/api.py +138 -19
- {pyreuser3-0.6.0 → pyreuser3-0.7.1}/pyreuser3/cli.py +62 -6
- {pyreuser3-0.6.0 → pyreuser3-0.7.1}/pyreuser3/core.py +5 -2
- {pyreuser3-0.6.0 → pyreuser3-0.7.1}/pyreuser3/export/base.py +34 -11
- {pyreuser3-0.6.0 → pyreuser3-0.7.1}/pyreuser3/export/fields.py +79 -4
- {pyreuser3-0.6.0 → pyreuser3-0.7.1}/pyreuser3/export/metadata.py +13 -7
- {pyreuser3-0.6.0 → pyreuser3-0.7.1}/pyreuser3/export/user3.py +155 -97
- {pyreuser3-0.6.0 → pyreuser3-0.7.1}/pyreuser3/pack/base.py +78 -21
- {pyreuser3-0.6.0 → pyreuser3-0.7.1}/pyreuser3/pack/models.py +54 -0
- {pyreuser3-0.6.0 → pyreuser3-0.7.1}/pyreuser3/pack/plan.py +318 -9
- {pyreuser3-0.6.0 → pyreuser3-0.7.1}/pyreuser3/pack/writer.py +348 -41
- pyreuser3-0.7.1/pyreuser3/usr_container.py +619 -0
- pyreuser3-0.7.1/pyreuser3/usr_layouts.py +368 -0
- pyreuser3-0.7.1/tests/test_api_cache.py +120 -0
- {pyreuser3-0.6.0 → pyreuser3-0.7.1}/tests/test_enum_binary.py +1 -0
- {pyreuser3-0.6.0 → pyreuser3-0.7.1}/tests/test_enum_codec.py +11 -3
- pyreuser3-0.7.1/tests/test_usr_container.py +780 -0
- pyreuser3-0.6.0/README.md +0 -165
- pyreuser3-0.6.0/docs/PYPI.md +0 -40
- {pyreuser3-0.6.0 → pyreuser3-0.7.1}/LICENSE +0 -0
- {pyreuser3-0.6.0 → pyreuser3-0.7.1}/MANIFEST.in +0 -0
- {pyreuser3-0.6.0 → pyreuser3-0.7.1}/PyREUser3.egg-info/dependency_links.txt +0 -0
- {pyreuser3-0.6.0 → pyreuser3-0.7.1}/PyREUser3.egg-info/entry_points.txt +0 -0
- {pyreuser3-0.6.0 → pyreuser3-0.7.1}/PyREUser3.egg-info/requires.txt +0 -0
- {pyreuser3-0.6.0 → pyreuser3-0.7.1}/PyREUser3.egg-info/top_level.txt +0 -0
- {pyreuser3-0.6.0 → pyreuser3-0.7.1}/pyreuser3/__main__.py +0 -0
- {pyreuser3-0.6.0 → pyreuser3-0.7.1}/pyreuser3/enum_codec.py +0 -0
- {pyreuser3-0.6.0 → pyreuser3-0.7.1}/pyreuser3/export/__init__.py +0 -0
- {pyreuser3-0.6.0 → pyreuser3-0.7.1}/pyreuser3/export/enums.py +0 -0
- {pyreuser3-0.6.0 → pyreuser3-0.7.1}/pyreuser3/export/postprocess.py +0 -0
- {pyreuser3-0.6.0 → pyreuser3-0.7.1}/pyreuser3/export/tree.py +0 -0
- {pyreuser3-0.6.0 → pyreuser3-0.7.1}/pyreuser3/pack/__init__.py +0 -0
- {pyreuser3-0.6.0 → pyreuser3-0.7.1}/pyreuser3/rich_ui.py +0 -0
- {pyreuser3-0.6.0 → pyreuser3-0.7.1}/pyreuser3/schema.py +0 -0
- {pyreuser3-0.6.0 → pyreuser3-0.7.1}/pyreuser3/web/__init__.py +0 -0
- {pyreuser3-0.6.0 → pyreuser3-0.7.1}/pyreuser3/web/__main__.py +0 -0
- {pyreuser3-0.6.0 → pyreuser3-0.7.1}/pyreuser3/web/handler.py +0 -0
- {pyreuser3-0.6.0 → pyreuser3-0.7.1}/pyreuser3/web/jobs.py +0 -0
- {pyreuser3-0.6.0 → pyreuser3-0.7.1}/pyreuser3/web/page.py +0 -0
- {pyreuser3-0.6.0 → pyreuser3-0.7.1}/pyreuser3/web/picker.py +0 -0
- {pyreuser3-0.6.0 → pyreuser3-0.7.1}/pyreuser3/web/runners.py +0 -0
- {pyreuser3-0.6.0 → pyreuser3-0.7.1}/pyreuser3/web/server.py +0 -0
- {pyreuser3-0.6.0 → pyreuser3-0.7.1}/pyreuser3/web/settings.py +0 -0
- {pyreuser3-0.6.0 → pyreuser3-0.7.1}/setup.cfg +0 -0
- {pyreuser3-0.6.0 → pyreuser3-0.7.1}/tests/test_export_enums.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: PyREUser3
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.1
|
|
4
4
|
Summary: Pure Python tools for converting RE Engine .user.3 files to and from JSON.
|
|
5
5
|
Author: Egg Targaryen
|
|
6
6
|
License-Expression: MIT
|
|
@@ -47,12 +47,33 @@ pip install pyreuser3
|
|
|
47
47
|
- `JSON -> .user.3` packing.
|
|
48
48
|
- A reusable Python API through `REUser3Converter`.
|
|
49
49
|
- CLI commands through `pyreuser3`.
|
|
50
|
+
- Schema-free layout probing through `pyreuser3 probe` and the public probe API.
|
|
50
51
|
- A local `.user.3` export Web UI through `pyreuser3-web`.
|
|
52
|
+
- Automatic separation of the USR outer layout from the embedded RSZ header family;
|
|
53
|
+
modern RSZ v4+ files preserve their original numeric version during repack.
|
|
51
54
|
|
|
52
55
|
The published package intentionally does not include game resources, dumped game data, RE_RSZ templates,
|
|
53
56
|
`il2cpp_dump.json`, or repository-specific helper scripts. You need to provide data files that match the target game and
|
|
54
57
|
version.
|
|
55
58
|
|
|
59
|
+
Verified H30/modern layouts support repacking. Experimental physical H28 and legacy
|
|
60
|
+
RSZ v3 layouts are readable for analysis but intentionally blocked from repacking
|
|
61
|
+
until real fixtures provide byte-for-byte validation.
|
|
62
|
+
|
|
63
|
+
Version 0.7.1 fixes the 0.7.0 modern RSZ alignment regression. Modern userdata and
|
|
64
|
+
data targets use absolute 16-byte file alignment even though their stored offsets
|
|
65
|
+
remain RSZ-relative. Readable parsing accepts alignment-only deviations without
|
|
66
|
+
hiding structural corruption, while the probe API reports them explicitly. Repack
|
|
67
|
+
output blocks layouts carrying unverified diagnostics. The strict schema-free
|
|
68
|
+
probe can validate large local corpora.
|
|
69
|
+
|
|
70
|
+
Repeated operations on one `REUser3Converter` reuse schema and il2cpp metadata,
|
|
71
|
+
with automatic file-signature invalidation and an explicit
|
|
72
|
+
`clear_metadata_cache()` escape hatch. Batch patching reuses one exporter and
|
|
73
|
+
packer. Signed `-1` null object references and very large fixed-width arrays are
|
|
74
|
+
preserved losslessly; large arrays use a compact raw payload instead of millions
|
|
75
|
+
of Python scalar objects.
|
|
76
|
+
|
|
56
77
|
## Requirements
|
|
57
78
|
|
|
58
79
|
- Python 3.9 or newer.
|
|
@@ -60,6 +81,8 @@ version.
|
|
|
60
81
|
- An `il2cpp_dump.json` file when exporting readable enum labels.
|
|
61
82
|
- One or more unpacked `.user.3` files.
|
|
62
83
|
|
|
84
|
+
`pyreuser3 probe` does not require a schema or `il2cpp_dump.json`.
|
|
85
|
+
|
|
63
86
|
## Usage
|
|
64
87
|
|
|
65
88
|
Usage details may change as the package evolves. For the latest command-line and Python API examples, read the GitHub README:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: PyREUser3
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.1
|
|
4
4
|
Summary: Pure Python tools for converting RE Engine .user.3 files to and from JSON.
|
|
5
5
|
Author: Egg Targaryen
|
|
6
6
|
License-Expression: MIT
|
|
@@ -47,12 +47,33 @@ pip install pyreuser3
|
|
|
47
47
|
- `JSON -> .user.3` packing.
|
|
48
48
|
- A reusable Python API through `REUser3Converter`.
|
|
49
49
|
- CLI commands through `pyreuser3`.
|
|
50
|
+
- Schema-free layout probing through `pyreuser3 probe` and the public probe API.
|
|
50
51
|
- A local `.user.3` export Web UI through `pyreuser3-web`.
|
|
52
|
+
- Automatic separation of the USR outer layout from the embedded RSZ header family;
|
|
53
|
+
modern RSZ v4+ files preserve their original numeric version during repack.
|
|
51
54
|
|
|
52
55
|
The published package intentionally does not include game resources, dumped game data, RE_RSZ templates,
|
|
53
56
|
`il2cpp_dump.json`, or repository-specific helper scripts. You need to provide data files that match the target game and
|
|
54
57
|
version.
|
|
55
58
|
|
|
59
|
+
Verified H30/modern layouts support repacking. Experimental physical H28 and legacy
|
|
60
|
+
RSZ v3 layouts are readable for analysis but intentionally blocked from repacking
|
|
61
|
+
until real fixtures provide byte-for-byte validation.
|
|
62
|
+
|
|
63
|
+
Version 0.7.1 fixes the 0.7.0 modern RSZ alignment regression. Modern userdata and
|
|
64
|
+
data targets use absolute 16-byte file alignment even though their stored offsets
|
|
65
|
+
remain RSZ-relative. Readable parsing accepts alignment-only deviations without
|
|
66
|
+
hiding structural corruption, while the probe API reports them explicitly. Repack
|
|
67
|
+
output blocks layouts carrying unverified diagnostics. The strict schema-free
|
|
68
|
+
probe can validate large local corpora.
|
|
69
|
+
|
|
70
|
+
Repeated operations on one `REUser3Converter` reuse schema and il2cpp metadata,
|
|
71
|
+
with automatic file-signature invalidation and an explicit
|
|
72
|
+
`clear_metadata_cache()` escape hatch. Batch patching reuses one exporter and
|
|
73
|
+
packer. Signed `-1` null object references and very large fixed-width arrays are
|
|
74
|
+
preserved losslessly; large arrays use a compact raw payload instead of millions
|
|
75
|
+
of Python scalar objects.
|
|
76
|
+
|
|
56
77
|
## Requirements
|
|
57
78
|
|
|
58
79
|
- Python 3.9 or newer.
|
|
@@ -60,6 +81,8 @@ version.
|
|
|
60
81
|
- An `il2cpp_dump.json` file when exporting readable enum labels.
|
|
61
82
|
- One or more unpacked `.user.3` files.
|
|
62
83
|
|
|
84
|
+
`pyreuser3 probe` does not require a schema or `il2cpp_dump.json`.
|
|
85
|
+
|
|
63
86
|
## Usage
|
|
64
87
|
|
|
65
88
|
Usage details may change as the package evolves. For the latest command-line and Python API examples, read the GitHub README:
|
|
@@ -18,6 +18,8 @@ pyreuser3/core.py
|
|
|
18
18
|
pyreuser3/enum_codec.py
|
|
19
19
|
pyreuser3/rich_ui.py
|
|
20
20
|
pyreuser3/schema.py
|
|
21
|
+
pyreuser3/usr_container.py
|
|
22
|
+
pyreuser3/usr_layouts.py
|
|
21
23
|
pyreuser3/export/__init__.py
|
|
22
24
|
pyreuser3/export/base.py
|
|
23
25
|
pyreuser3/export/enums.py
|
|
@@ -40,6 +42,8 @@ pyreuser3/web/picker.py
|
|
|
40
42
|
pyreuser3/web/runners.py
|
|
41
43
|
pyreuser3/web/server.py
|
|
42
44
|
pyreuser3/web/settings.py
|
|
45
|
+
tests/test_api_cache.py
|
|
43
46
|
tests/test_enum_binary.py
|
|
44
47
|
tests/test_enum_codec.py
|
|
45
|
-
tests/test_export_enums.py
|
|
48
|
+
tests/test_export_enums.py
|
|
49
|
+
tests/test_usr_container.py
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
<h1 align="center">PyREUser3</h1>
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
English | <a href="https://github.com/dzxrly/PyREUser3/blob/main/docs/README.zh-CN.md">简体中文</a>
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
<a href="https://pypi.org/project/PyREUser3/"><img alt="PyPI Project" src="https://img.shields.io/badge/PyPI-PyREUser3-blue"></a>
|
|
9
|
+
<a href="https://pypi.org/project/PyREUser3/"><img alt="PyPI Version" src="https://img.shields.io/pypi/v/PyREUser3"></a>
|
|
10
|
+
<a href="https://pepy.tech/project/PyREUser3"><img alt="Downloads" src="https://static.pepy.tech/badge/PyREUser3"></a>
|
|
11
|
+
<a href="https://github.com/dzxrly/PyREUser3/blob/main/LICENSE"><img alt="License" src="https://img.shields.io/pypi/l/PyREUser3"></a>
|
|
12
|
+
</p>
|
|
13
|
+
|
|
14
|
+
PyREUser3 is a pure Python package for converting RE Engine `.user.3` database files to JSON and packing compatible JSON back to `.user.3`.
|
|
15
|
+
|
|
16
|
+
Install it with:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
pip install pyreuser3
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Import it with the same normalized package name:
|
|
23
|
+
|
|
24
|
+
```python
|
|
25
|
+
from pyreuser3 import REUser3Converter
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## What Is Included
|
|
29
|
+
|
|
30
|
+
- `.user.3 -> JSON` export.
|
|
31
|
+
- `JSON -> .user.3` packing.
|
|
32
|
+
- A reusable Python API through `REUser3Converter`.
|
|
33
|
+
- CLI commands through `pyreuser3`.
|
|
34
|
+
- Schema-free layout probing for individual files and whole corpora.
|
|
35
|
+
- A local `.user.3` export Web UI through `pyreuser3-web`.
|
|
36
|
+
|
|
37
|
+
This PyPI package intentionally does not include game resources, dumped game data, RE_RSZ templates, `il2cpp_dump.json`,
|
|
38
|
+
or repository-specific helper scripts.
|
|
39
|
+
|
|
40
|
+
## Requirements
|
|
41
|
+
|
|
42
|
+
- Python 3.9 or newer.
|
|
43
|
+
- A RE_RSZ schema JSON file for the target game/version.
|
|
44
|
+
- An `il2cpp_dump.json` file when exporting readable enum labels.
|
|
45
|
+
- One or more unpacked `.user.3` files.
|
|
46
|
+
|
|
47
|
+
Layout probing is the exception: `pyreuser3 probe` only inspects the USR/RSZ
|
|
48
|
+
container and does not require a schema or `il2cpp_dump.json`.
|
|
49
|
+
|
|
50
|
+
## Command Line
|
|
51
|
+
|
|
52
|
+
Export `.user.3` files to JSON:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
pyreuser3 export \
|
|
56
|
+
-i <input-user3-file-or-directory> \
|
|
57
|
+
-s <RE_RSZ-schema.json> \
|
|
58
|
+
-o <json-output-directory> \
|
|
59
|
+
-p <il2cpp_dump.json>
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Export full repack JSON, then pack it back to `.user.3`:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
pyreuser3 export \
|
|
66
|
+
-i <input-user3-file-or-directory> \
|
|
67
|
+
-s <RE_RSZ-schema.json> \
|
|
68
|
+
-o <repack-json-output-directory> \
|
|
69
|
+
-p <il2cpp_dump.json> \
|
|
70
|
+
--json-format repack
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
pyreuser3 pack \
|
|
75
|
+
-j <input-repack-json-file-or-directory> \
|
|
76
|
+
-s <RE_RSZ-schema.json> \
|
|
77
|
+
-o <user3-output-directory> \
|
|
78
|
+
-p <il2cpp_dump.json>
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
The `-p/--il2cpp-dump-path` option is required for export and optional for pack. Passing it during pack is recommended when enum names need to be resolved back to numeric values.
|
|
82
|
+
|
|
83
|
+
Probe a file or directory without loading game metadata:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
pyreuser3 probe -i <input-user3-file-or-directory>
|
|
87
|
+
pyreuser3 probe -i <input-user3-file-or-directory> --strict -o layout-report.json
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
The default probe uses the same safety policy as readable export: structural
|
|
91
|
+
corruption remains fatal, while non-canonical alignment is reported as a warning.
|
|
92
|
+
`--strict` rejects every layout deviation and is intended for corpus validation.
|
|
93
|
+
The optional JSON report contains totals grouped by detected layout, RSZ version,
|
|
94
|
+
and diagnostic code.
|
|
95
|
+
|
|
96
|
+
Start the local `.user.3` export Web UI:
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
pyreuser3-web --port 8765
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
The Web UI only handles `.user.3` export. It does not pack files.
|
|
103
|
+
|
|
104
|
+
## Python API
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
from pyreuser3 import REUser3Converter
|
|
108
|
+
|
|
109
|
+
converter = REUser3Converter(
|
|
110
|
+
schema_path="D:/schema/rsz_game.json",
|
|
111
|
+
il2cpp_dump_path="D:/game/il2cpp_dump.json",
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
converter.export_file(
|
|
115
|
+
"input/OtomonData.user.3",
|
|
116
|
+
"json/OtomonData.user.3.json",
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
# Packing only accepts the full repack document. Readable exports are read-only.
|
|
120
|
+
converter.export_file(
|
|
121
|
+
"input/OtomonData.user.3",
|
|
122
|
+
"json/OtomonData.user.3.pack.json",
|
|
123
|
+
json_format="repack",
|
|
124
|
+
)
|
|
125
|
+
converter.pack_file(
|
|
126
|
+
"json/OtomonData.user.3.pack.json",
|
|
127
|
+
"mod/OtomonData.user.3",
|
|
128
|
+
)
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
`REUser3Converter` loads schema and il2cpp metadata lazily and caches it for the
|
|
132
|
+
lifetime of that converter. Repeated readable, repack, pack, and patch calls no
|
|
133
|
+
longer rescan large metadata files. Cache entries are invalidated automatically
|
|
134
|
+
when the source path, size, or nanosecond modification time changes; callers that
|
|
135
|
+
replace metadata in an unusual way can force a reload with:
|
|
136
|
+
|
|
137
|
+
```python
|
|
138
|
+
converter.clear_metadata_cache()
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
`patch_directory()` also reuses one prepared exporter and packer for the complete
|
|
142
|
+
batch instead of constructing them once per file.
|
|
143
|
+
|
|
144
|
+
Container layout probing is also available without constructing a converter or
|
|
145
|
+
loading a schema:
|
|
146
|
+
|
|
147
|
+
```python
|
|
148
|
+
from pyreuser3 import probe_usr_file, probe_usr_path
|
|
149
|
+
|
|
150
|
+
one_file = probe_usr_file("input/example.user.3")
|
|
151
|
+
whole_tree = probe_usr_path("input/natives", policy="strict_probe")
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Convert a `.user.3` file to an in-memory JSON-compatible Python object without writing a JSON file:
|
|
155
|
+
|
|
156
|
+
```python
|
|
157
|
+
readable_data = converter.user3_to_json(
|
|
158
|
+
"input/OtomonData.user.3",
|
|
159
|
+
json_format="readable",
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
repack_data = converter.user3_to_json(
|
|
163
|
+
"input/OtomonData.user.3",
|
|
164
|
+
json_format="repack",
|
|
165
|
+
)
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Use `json_format="readable"` for the same shape produced by `export_file()`. This
|
|
169
|
+
shape is read-only. Use `json_format="repack"` for the full document accepted by
|
|
170
|
+
`pack()`; the packer rejects readable JSON.
|
|
171
|
+
|
|
172
|
+
Enum fields are rendered as `[numeric] Name` labels using the enum's actual storage
|
|
173
|
+
width. Scalar flag enums are rendered as arrays of labels. ``ace.Bitset`1<T>`` values are
|
|
174
|
+
rendered as enum-index labels together with `_MaxElement` and `_WordCount`, so unknown
|
|
175
|
+
bits and padded word arrays remain reversible. Repack exports use
|
|
176
|
+
`re_user3_pack_v3`, which records the independently detected USR outer layout, RSZ
|
|
177
|
+
header family, and numeric RSZ version while preserving resource and userdata
|
|
178
|
+
dependency tables. Layout candidates and their read/repack capability status are
|
|
179
|
+
declared in `pyreuser3/usr_layouts.py`; RSZ field definitions still come from the
|
|
180
|
+
supplied REFramework-compatible schema. The verified modern header family accepts
|
|
181
|
+
structurally valid RSZ v4+ files and preserves their original version instead of
|
|
182
|
+
forcing MHWS version 16. For this family, offset values remain relative to the RSZ
|
|
183
|
+
section, but the userdata and data targets are aligned to absolute 16-byte file
|
|
184
|
+
positions. Readable export accepts alignment-only deviations, and the probe API
|
|
185
|
+
reports them as structured warnings. Repack export records the same diagnostics in
|
|
186
|
+
`_warnings` and blocks packing through `_unsupported` until the layout is verified.
|
|
187
|
+
Experimental physical H28 and legacy RSZ v3 candidates are read-only until real
|
|
188
|
+
fixtures validate byte-for-byte repacking. V1 and v2 documents are recognized for
|
|
189
|
+
diagnostics but must be re-exported as v3 before packing because they do not record
|
|
190
|
+
the required layout metadata.
|
|
191
|
+
|
|
192
|
+
Modern files may use signed `-1` as an explicit null `Object` reference; repack
|
|
193
|
+
preserves that sentinel while continuing to reject every other missing instance
|
|
194
|
+
ID. Fixed-width arrays above one million elements are kept compactly as
|
|
195
|
+
`_raw_array_count` plus `_raw_array_hex`. This representation is intentionally
|
|
196
|
+
opaque but lossless, avoids expanding millions of Python integers, and validates
|
|
197
|
+
the count/payload length before packing.
|
|
198
|
+
|
|
199
|
+
For stable patch-and-repack workflows, use `patch_file()` or `parse_pack_file()`:
|
|
200
|
+
|
|
201
|
+
```python
|
|
202
|
+
from pyreuser3 import REUser3Converter
|
|
203
|
+
|
|
204
|
+
converter = REUser3Converter(
|
|
205
|
+
schema_path="D:/schema/rsz_game.json",
|
|
206
|
+
il2cpp_dump_path="D:/game/il2cpp_dump.json",
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
def patch(data, source_path):
|
|
210
|
+
# Modify the full instance-table JSON in place.
|
|
211
|
+
return None
|
|
212
|
+
|
|
213
|
+
converter.patch_file(
|
|
214
|
+
"input/example.user.3",
|
|
215
|
+
"output/example.user.3",
|
|
216
|
+
patch,
|
|
217
|
+
)
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
## Compatibility Validation
|
|
221
|
+
|
|
222
|
+
The repository includes a schema-free corpus runner. Game files are not committed;
|
|
223
|
+
point it at a locally unpacked `natives` tree:
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
python tests/corpus_probe.py D:/game/natives \
|
|
227
|
+
--expected-total 62768 \
|
|
228
|
+
--expected-version 16 \
|
|
229
|
+
--report layout-report.json
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
Version 0.7.1 fixes modern RSZ alignment regression found in 0.7.0 and folds the
|
|
233
|
+
planned compatibility work into the bug-fix release: staged layout detection,
|
|
234
|
+
structured diagnostics, safe readable parsing, verified-only repacking, and the
|
|
235
|
+
schema-free probe command. The modern rule was validated against 62,768 MHWS
|
|
236
|
+
`.user.3` files; four SystemSetting fixtures additionally passed readable export,
|
|
237
|
+
repack export, byte-identical packing, and reparse checks.
|
|
238
|
+
|
|
239
|
+
A second corpus from Monster Hunter Stories 3 was also validated: all 42,945 files
|
|
240
|
+
passed strict layout detection and schema-driven repack export. All 42,945 rebuilt
|
|
241
|
+
without exceptions; 38,548 were byte-identical. The remaining 4,397 are successful
|
|
242
|
+
rebuilds but not byte-identical; observed causes include nonzero padding and
|
|
243
|
+
alternate empty-string encodings, so they are not claimed as byte-identical
|
|
244
|
+
fixtures. Two voxel files use the compact large-array representation; both rebuilt
|
|
245
|
+
byte-identically, including the 6.55 MB `dg100_Root` payload.
|
|
246
|
+
|
|
247
|
+
## Build From Source
|
|
248
|
+
|
|
249
|
+
```bash
|
|
250
|
+
python -m pip install -U build twine
|
|
251
|
+
python -m build
|
|
252
|
+
python -m twine check dist/*
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
Upload to TestPyPI first:
|
|
256
|
+
|
|
257
|
+
```bash
|
|
258
|
+
python -m twine upload -r testpypi dist/*
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
Then upload the same checked distribution files to PyPI:
|
|
262
|
+
|
|
263
|
+
```bash
|
|
264
|
+
python -m twine upload dist/*
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
## License
|
|
268
|
+
|
|
269
|
+
MIT License.
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# PyREUser3
|
|
2
|
+
|
|
3
|
+
PyREUser3 is a pure Python package for converting RE Engine `.user.3` database files to JSON and packing compatible JSON back to `.user.3`.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install pyreuser3
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## What Is Included
|
|
12
|
+
|
|
13
|
+
- `.user.3 -> JSON` export.
|
|
14
|
+
- `JSON -> .user.3` packing.
|
|
15
|
+
- A reusable Python API through `REUser3Converter`.
|
|
16
|
+
- CLI commands through `pyreuser3`.
|
|
17
|
+
- Schema-free layout probing through `pyreuser3 probe` and the public probe API.
|
|
18
|
+
- A local `.user.3` export Web UI through `pyreuser3-web`.
|
|
19
|
+
- Automatic separation of the USR outer layout from the embedded RSZ header family;
|
|
20
|
+
modern RSZ v4+ files preserve their original numeric version during repack.
|
|
21
|
+
|
|
22
|
+
The published package intentionally does not include game resources, dumped game data, RE_RSZ templates,
|
|
23
|
+
`il2cpp_dump.json`, or repository-specific helper scripts. You need to provide data files that match the target game and
|
|
24
|
+
version.
|
|
25
|
+
|
|
26
|
+
Verified H30/modern layouts support repacking. Experimental physical H28 and legacy
|
|
27
|
+
RSZ v3 layouts are readable for analysis but intentionally blocked from repacking
|
|
28
|
+
until real fixtures provide byte-for-byte validation.
|
|
29
|
+
|
|
30
|
+
Version 0.7.1 fixes the 0.7.0 modern RSZ alignment regression. Modern userdata and
|
|
31
|
+
data targets use absolute 16-byte file alignment even though their stored offsets
|
|
32
|
+
remain RSZ-relative. Readable parsing accepts alignment-only deviations without
|
|
33
|
+
hiding structural corruption, while the probe API reports them explicitly. Repack
|
|
34
|
+
output blocks layouts carrying unverified diagnostics. The strict schema-free
|
|
35
|
+
probe can validate large local corpora.
|
|
36
|
+
|
|
37
|
+
Repeated operations on one `REUser3Converter` reuse schema and il2cpp metadata,
|
|
38
|
+
with automatic file-signature invalidation and an explicit
|
|
39
|
+
`clear_metadata_cache()` escape hatch. Batch patching reuses one exporter and
|
|
40
|
+
packer. Signed `-1` null object references and very large fixed-width arrays are
|
|
41
|
+
preserved losslessly; large arrays use a compact raw payload instead of millions
|
|
42
|
+
of Python scalar objects.
|
|
43
|
+
|
|
44
|
+
## Requirements
|
|
45
|
+
|
|
46
|
+
- Python 3.9 or newer.
|
|
47
|
+
- A RE_RSZ schema JSON file for the target game/version.
|
|
48
|
+
- An `il2cpp_dump.json` file when exporting readable enum labels.
|
|
49
|
+
- One or more unpacked `.user.3` files.
|
|
50
|
+
|
|
51
|
+
`pyreuser3 probe` does not require a schema or `il2cpp_dump.json`.
|
|
52
|
+
|
|
53
|
+
## Usage
|
|
54
|
+
|
|
55
|
+
Usage details may change as the package evolves. For the latest command-line and Python API examples, read the GitHub README:
|
|
56
|
+
|
|
57
|
+
https://github.com/dzxrly/PyREUser3#readme
|
|
58
|
+
|
|
59
|
+
## Links
|
|
60
|
+
|
|
61
|
+
- Homepage: https://github.com/dzxrly/PyREUser3
|
|
62
|
+
- Issues: https://github.com/dzxrly/PyREUser3/issues
|
|
63
|
+
- License: MIT License
|
|
@@ -33,6 +33,7 @@ PyREUser3 当前提供:
|
|
|
33
33
|
- `JSON -> .user.3` 封包;
|
|
34
34
|
- 面向其他项目调用的 `REUser3Converter` Python API;
|
|
35
35
|
- `pyreuser3` 命令行工具;
|
|
36
|
+
- 无需 schema 的单文件与整批布局探测;
|
|
36
37
|
- `pyreuser3-web` 本地 Web 导出界面。
|
|
37
38
|
|
|
38
39
|
PyPI 包不会包含游戏资源、游戏 dump、RE_RSZ 模板、`il2cpp_dump.json`、或特定仓库脚本。调用方需要自己准备与目标游戏版本匹配的数据文件。
|
|
@@ -44,6 +45,9 @@ PyPI 包不会包含游戏资源、游戏 dump、RE_RSZ 模板、`il2cpp_dump.js
|
|
|
44
45
|
- 导出可读枚举标签时需要 `il2cpp_dump.json`;
|
|
45
46
|
- 一个或多个已解包的 `.user.3` 文件。
|
|
46
47
|
|
|
48
|
+
布局探测是例外:`pyreuser3 probe` 只检查 USR/RSZ 容器,不需要 schema 或
|
|
49
|
+
`il2cpp_dump.json`。
|
|
50
|
+
|
|
47
51
|
## 命令行使用
|
|
48
52
|
|
|
49
53
|
导出 `.user.3` 为 JSON:
|
|
@@ -56,11 +60,20 @@ pyreuser3 export \
|
|
|
56
60
|
-p <il2cpp_dump.json>
|
|
57
61
|
```
|
|
58
62
|
|
|
59
|
-
|
|
63
|
+
导出完整 repack JSON,然后封回 `.user.3`:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
pyreuser3 export \
|
|
67
|
+
-i <输入的-user3-文件或目录> \
|
|
68
|
+
-s <RE_RSZ-schema.json> \
|
|
69
|
+
-o <repack-JSON-输出目录> \
|
|
70
|
+
-p <il2cpp_dump.json> \
|
|
71
|
+
--json-format repack
|
|
72
|
+
```
|
|
60
73
|
|
|
61
74
|
```bash
|
|
62
75
|
pyreuser3 pack \
|
|
63
|
-
-j <输入的-JSON-文件或目录> \
|
|
76
|
+
-j <输入的-repack-JSON-文件或目录> \
|
|
64
77
|
-s <RE_RSZ-schema.json> \
|
|
65
78
|
-o <user3-输出目录> \
|
|
66
79
|
-p <il2cpp_dump.json>
|
|
@@ -73,6 +86,17 @@ pyreuser3 pack \
|
|
|
73
86
|
- `-s/--schema-path` 必须指向具体 schema JSON 文件,不应传目录;
|
|
74
87
|
- `-i`、`-j` 都可以传单个文件或目录,目录会递归处理。
|
|
75
88
|
|
|
89
|
+
无需加载游戏元数据即可探测单个文件或整个目录:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
pyreuser3 probe -i <输入的-user3-文件或目录>
|
|
93
|
+
pyreuser3 probe -i <输入的-user3-文件或目录> --strict -o layout-report.json
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
默认探测采用与 readable 导出相同的安全策略:结构损坏仍会直接失败,只有非规范对齐会记录为
|
|
97
|
+
警告。`--strict` 会拒绝任何布局偏差,适合整批语料验证。可选的 JSON 报告会按布局、RSZ
|
|
98
|
+
版本和诊断代码汇总结果。
|
|
99
|
+
|
|
76
100
|
可用 `--user-magic` 和 `--rsz-magic` 覆盖默认 magic,例如:
|
|
77
101
|
|
|
78
102
|
```bash
|
|
@@ -118,12 +142,39 @@ converter.export_file(
|
|
|
118
142
|
"json/OtomonData.user.3.json",
|
|
119
143
|
)
|
|
120
144
|
|
|
145
|
+
# 封包只接受完整 repack 文档;readable 导出仅供读取。
|
|
146
|
+
converter.export_file(
|
|
147
|
+
"input/OtomonData.user.3",
|
|
148
|
+
"json/OtomonData.user.3.pack.json",
|
|
149
|
+
json_format="repack",
|
|
150
|
+
)
|
|
121
151
|
converter.pack_file(
|
|
122
|
-
"json/OtomonData.user.3.json",
|
|
152
|
+
"json/OtomonData.user.3.pack.json",
|
|
123
153
|
"mod/OtomonData.user.3",
|
|
124
154
|
)
|
|
125
155
|
```
|
|
126
156
|
|
|
157
|
+
`REUser3Converter` 会延迟加载 schema 和 il2cpp metadata,并在该 converter 的生命周期内复用。
|
|
158
|
+
连续执行 readable、repack、pack 或 patch 时,不再反复扫描大型 metadata 文件。源文件的绝对
|
|
159
|
+
路径、大小或纳秒修改时间变化后缓存会自动失效;如果调用方以特殊方式原地替换文件,也可以强制
|
|
160
|
+
清理:
|
|
161
|
+
|
|
162
|
+
```python
|
|
163
|
+
converter.clear_metadata_cache()
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
`patch_directory()` 现在也会让整批文件复用同一个已准备好的 exporter 和 packer,不再为每个
|
|
167
|
+
文件重复构造。
|
|
168
|
+
|
|
169
|
+
也可以不创建 converter、不加载 schema,直接调用容器布局探测 API:
|
|
170
|
+
|
|
171
|
+
```python
|
|
172
|
+
from pyreuser3 import probe_usr_file, probe_usr_path
|
|
173
|
+
|
|
174
|
+
one_file = probe_usr_file("input/example.user.3")
|
|
175
|
+
whole_tree = probe_usr_path("input/natives", policy="strict_probe")
|
|
176
|
+
```
|
|
177
|
+
|
|
127
178
|
不写入 JSON 文件,直接把 `.user.3` 转成内存中的 JSON 兼容 Python 对象:
|
|
128
179
|
|
|
129
180
|
```python
|
|
@@ -138,12 +189,26 @@ repack_data = converter.user3_to_json(
|
|
|
138
189
|
)
|
|
139
190
|
```
|
|
140
191
|
|
|
141
|
-
使用 `json_format="readable"` 时返回与 `export_file()`
|
|
192
|
+
使用 `json_format="readable"` 时返回与 `export_file()` 一致的只读导出结构;使用
|
|
193
|
+
`json_format="repack"` 时返回可传给 `pack()` 的完整实例表结构。封回器会拒绝 readable JSON。
|
|
142
194
|
|
|
143
195
|
枚举字段会按照真实底层存储宽度输出为 `[数值] 名称`。标量位标志枚举输出为标签数组;
|
|
144
196
|
``ace.Bitset`1<T>`` 输出为枚举索引标签,并保留 `_MaxElement` 与 `_WordCount`,因此未知位和
|
|
145
|
-
填充词也可以无损封回。新的 repack 文档格式为 `
|
|
146
|
-
|
|
197
|
+
填充词也可以无损封回。新的 repack 文档格式为 `re_user3_pack_v3`,它会分别记录自动探测到的
|
|
198
|
+
USR 外层布局、RSZ 头族和文件中的真实 RSZ 版本,并保留 resource 与 userdata 依赖表。布局
|
|
199
|
+
候选及其读取/回封能力状态集中声明在 `pyreuser3/usr_layouts.py`,RSZ 字段定义仍来自传入的
|
|
200
|
+
REFramework 兼容模板。已验证的现代头族接受通过完整结构校验的 RSZ v4+ 文件,并原样保留
|
|
201
|
+
版本号,不再固定为 MHWS 的版本 16。这个头族中的 offset 数值仍以 RSZ 段为基准,但 userdata
|
|
202
|
+
与 data 的目标位置按整个文件的绝对 16 字节边界对齐。readable 导出会接受仅对齐偏差,probe
|
|
203
|
+
API 则把它们报告为结构化警告;repack 导出会把同一诊断写入 `_warnings`,并通过
|
|
204
|
+
`_unsupported` 阻止未经验证的布局被封回。实验性的物理 H28 与 legacy RSZ v3 候选暂时只读,
|
|
205
|
+
获得真实样本并完成逐字节回封验证后才能启用 repack。v1 和 v2 文档仍可识别以便诊断,但由于
|
|
206
|
+
缺少必要的布局元数据,封回前必须从源文件重新导出为 v3。
|
|
207
|
+
|
|
208
|
+
部分现代文件会用有符号 `-1` 明确表示空 `Object` 引用;repack 会原样保留这个哨兵,同时继续
|
|
209
|
+
拒绝其他不存在的实例 ID。超过一百万项的定长数组会紧凑保存为 `_raw_array_count` 和
|
|
210
|
+
`_raw_array_hex`。这种表示不提供逐项可读性,但能够无损回封、避免展开数百万个 Python 整数,
|
|
211
|
+
并会在封包前校验 count 与 payload 长度是否匹配。
|
|
147
212
|
|
|
148
213
|
批量处理目录:
|
|
149
214
|
|
|
@@ -158,6 +223,7 @@ converter = REUser3Converter(
|
|
|
158
223
|
export_result = converter.export_directory(
|
|
159
224
|
"D:/game/unpacked",
|
|
160
225
|
"D:/game/json",
|
|
226
|
+
json_format="repack",
|
|
161
227
|
)
|
|
162
228
|
|
|
163
229
|
pack_result = converter.pack_directory(
|
|
@@ -190,6 +256,29 @@ converter.patch_file(
|
|
|
190
256
|
)
|
|
191
257
|
```
|
|
192
258
|
|
|
259
|
+
## 兼容性验证
|
|
260
|
+
|
|
261
|
+
仓库内提供无需 schema 的语料测试脚本。游戏文件不会提交到仓库,请让脚本指向本地已解包的
|
|
262
|
+
`natives` 目录:
|
|
263
|
+
|
|
264
|
+
```bash
|
|
265
|
+
python tests/corpus_probe.py D:/game/natives \
|
|
266
|
+
--expected-total 62768 \
|
|
267
|
+
--expected-version 16 \
|
|
268
|
+
--report layout-report.json
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
0.7.1 修复了 0.7.0 引入的现代 RSZ 对齐回归,并把原计划中的兼容性工作合并进本次 bugfix:
|
|
272
|
+
分阶段布局探测、结构化诊断、安全 readable 解析、仅验证布局可 repack,以及无需 schema 的
|
|
273
|
+
probe 命令。新的现代布局规则已用 62,768 个 MHWS `.user.3` 文件验证;其中四个
|
|
274
|
+
SystemSetting 样本还完成了 readable 导出、repack 导出、逐字节一致回封和二次解析验证。
|
|
275
|
+
|
|
276
|
+
另外还验证了 Monster Hunter Stories 3 语料:42,945 个文件全部通过严格 layout 探测和
|
|
277
|
+
schema 驱动的 repack 导出;42,945 个文件全部能够无异常地重新构建,其中 38,548 个逐字节
|
|
278
|
+
一致。其余 4,397 个可以成功重建但并非逐字节一致;已观察到的原因包括非零 padding、空字符串
|
|
279
|
+
的另一种物理编码,因此不把它们宣称为逐字节 fixture。两个使用紧凑超大数组表示的 voxel 文件
|
|
280
|
+
都能逐字节一致回封,其中包括 6.55 MB 的 `dg100_Root` payload。
|
|
281
|
+
|
|
193
282
|
## 常见注意事项
|
|
194
283
|
|
|
195
284
|
- schema JSON、`il2cpp_dump.json` 和 `.user.3` 文件应来自同一个游戏版本;
|
|
@@ -9,15 +9,21 @@ from __future__ import annotations
|
|
|
9
9
|
from importlib import import_module
|
|
10
10
|
from typing import Any
|
|
11
11
|
|
|
12
|
+
__version__ = "0.7.1"
|
|
13
|
+
|
|
12
14
|
__all__ = [
|
|
15
|
+
"__version__",
|
|
13
16
|
"BinaryReader",
|
|
14
17
|
"ClassDef",
|
|
15
18
|
"FieldDef",
|
|
16
19
|
"PackError",
|
|
17
20
|
"ParseError",
|
|
21
|
+
"LayoutValidationIssue",
|
|
18
22
|
"TypeDB",
|
|
19
23
|
"REUser3Converter",
|
|
20
24
|
"RSZ_MAGIC",
|
|
25
|
+
"probe_usr_file",
|
|
26
|
+
"probe_usr_path",
|
|
21
27
|
"User3Exporter",
|
|
22
28
|
"User3Packer",
|
|
23
29
|
"USR_MAGIC",
|
|
@@ -28,6 +34,9 @@ _EXPORT_MODULES = {
|
|
|
28
34
|
"ParseError": ".core",
|
|
29
35
|
"RSZ_MAGIC": ".core",
|
|
30
36
|
"USR_MAGIC": ".core",
|
|
37
|
+
"LayoutValidationIssue": ".usr_container",
|
|
38
|
+
"probe_usr_file": ".usr_container",
|
|
39
|
+
"probe_usr_path": ".usr_container",
|
|
31
40
|
"ClassDef": ".schema",
|
|
32
41
|
"FieldDef": ".schema",
|
|
33
42
|
"TypeDB": ".schema",
|