rust-map-parser 0.1.0__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.
- rust_map_parser-0.1.0/LICENSE +21 -0
- rust_map_parser-0.1.0/MANIFEST.in +8 -0
- rust_map_parser-0.1.0/PKG-INFO +538 -0
- rust_map_parser-0.1.0/README.md +516 -0
- rust_map_parser-0.1.0/docs/export-config.md +756 -0
- rust_map_parser-0.1.0/docs/export-result.md +527 -0
- rust_map_parser-0.1.0/docs/images/heatmap-ores.png +0 -0
- rust_map_parser-0.1.0/docs/images/map-render.jpg +0 -0
- rust_map_parser-0.1.0/docs/images/no-build-zones.png +0 -0
- rust_map_parser-0.1.0/docs/images/splat-composite.png +0 -0
- rust_map_parser-0.1.0/docs/images/tunnels-layer.png +0 -0
- rust_map_parser-0.1.0/example.py +31 -0
- rust_map_parser-0.1.0/pyproject.toml +39 -0
- rust_map_parser-0.1.0/refresh_all_data.py +250 -0
- rust_map_parser-0.1.0/setup.cfg +4 -0
- rust_map_parser-0.1.0/src/rust_map_parser.egg-info/PKG-INFO +538 -0
- rust_map_parser-0.1.0/src/rust_map_parser.egg-info/SOURCES.txt +132 -0
- rust_map_parser-0.1.0/src/rust_map_parser.egg-info/dependency_links.txt +1 -0
- rust_map_parser-0.1.0/src/rust_map_parser.egg-info/requires.txt +7 -0
- rust_map_parser-0.1.0/src/rust_map_parser.egg-info/top_level.txt +1 -0
- rust_map_parser-0.1.0/src/rustmap/__init__.py +44 -0
- rust_map_parser-0.1.0/src/rustmap/config.py +236 -0
- rust_map_parser-0.1.0/src/rustmap/data/__init__.py +1 -0
- rust_map_parser-0.1.0/src/rustmap/data/monument_metadata.json +954 -0
- rust_map_parser-0.1.0/src/rustmap/data/no_build_zones.json +9543 -0
- rust_map_parser-0.1.0/src/rustmap/data/prefab_manifest.json +242637 -0
- rust_map_parser-0.1.0/src/rustmap/data/spawn_rules.json +3308 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/__init__.py +1 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_000__curve-nw-0.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_001__curve-nw-1.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_002__intersection-bb1-n.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_003__intersection-bb4-n.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_004__intersection-b5-n.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_005__intersection-b3-n.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_006__intersection-b2-n.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_007__intersection-bb2-n.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_008__intersection-b6-n.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_009__intersection-bb3-n.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_010__intersection-b4-n.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_011__intersection-bb6-n.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_012__intersection-n.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_013__intersection-b1-n.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_014__intersection-bb5-n.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_015__station-sn-0.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_016__straight-sn-3.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_017__straight-sn-2.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_018__station-sn-1.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_019__straight-sn-0.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_020__straight-sn-1.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_021__station-sn-3.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_022__straight-sn-4.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_023__station-sn-2.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_024__straight-sn-5.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_025__curve-ne-1.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_026__curve-ne-0.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_027__intersection.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_028__intersection-bb2-s.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_029__intersection-b2-s.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_030__intersection-b6-s.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_031__intersection-bb5-s.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_032__intersection-bb1-s.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_033__intersection-s.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_034__intersection-b1-s.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_035__intersection-bb6-s.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_036__intersection-b5-s.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_037__intersection-bb4-s.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_038__intersection-b3-s.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_039__intersection-bb3-s.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_040__intersection-b4-s.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_041__straight-we-3.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_042__station-we-1.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_043__straight-we-5.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_044__straight-we-4.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_045__station-we-2.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_046__station-we-3.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_047__station-we-0.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_048__straight-we-2.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_049__straight-we-1.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_050__straight-we-0.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_051__curve-se-0.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_052__curve-se-1.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_053__intersection-bb3-w.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_054__intersection-w.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_055__intersection-bb5-w.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_056__intersection-b5-w.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_057__intersection-b1-w.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_058__intersection-bb1-w.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_059__intersection-bb4-w.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_060__intersection-b4-w.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_061__intersection-b6-w.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_062__intersection-bb2-w.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_063__intersection-b3-w.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_064__intersection-b2-w.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_065__intersection-bb6-w.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_066__curve-sw-0.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_067__curve-sw-1.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_068__intersection-bb3-e.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_069__intersection-bb6-e.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_070__intersection-b4-e.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_071__intersection-b6-e.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_072__intersection-b5-e.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_073__intersection-b1-e.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_074__intersection-b3-e.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_075__intersection-bb2-e.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_076__intersection-e.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_077__intersection-bb1-e.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_078__intersection-bb4-e.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_079__intersection-b2-e.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/template_080__intersection-bb5-e.png +0 -0
- rust_map_parser-0.1.0/src/rustmap/data/tunnel_tiles/tiles.json +997 -0
- rust_map_parser-0.1.0/src/rustmap/exporter.py +409 -0
- rust_map_parser-0.1.0/src/rustmap/layers.py +323 -0
- rust_map_parser-0.1.0/src/rustmap/monument_assets.py +145 -0
- rust_map_parser-0.1.0/src/rustmap/monuments.py +226 -0
- rust_map_parser-0.1.0/src/rustmap/no_build.py +288 -0
- rust_map_parser-0.1.0/src/rustmap/no_build_assets.py +303 -0
- rust_map_parser-0.1.0/src/rustmap/parser.py +297 -0
- rust_map_parser-0.1.0/src/rustmap/png.py +18 -0
- rust_map_parser-0.1.0/src/rustmap/populations.py +361 -0
- rust_map_parser-0.1.0/src/rustmap/prefabs.py +281 -0
- rust_map_parser-0.1.0/src/rustmap/renderer.py +460 -0
- rust_map_parser-0.1.0/src/rustmap/resources.py +26 -0
- rust_map_parser-0.1.0/src/rustmap/tunnel_assets.py +398 -0
- rust_map_parser-0.1.0/src/rustmap/tunnels.py +417 -0
- rust_map_parser-0.1.0/src/rustmap/validation.py +106 -0
- rust_map_parser-0.1.0/tests/test_exporter.py +124 -0
- rust_map_parser-0.1.0/tests/test_map_tiles.py +85 -0
- rust_map_parser-0.1.0/tests/test_monuments.py +54 -0
- rust_map_parser-0.1.0/tests/test_no_build.py +170 -0
- rust_map_parser-0.1.0/tests/test_png_metadata.py +18 -0
- rust_map_parser-0.1.0/tests/test_populations.py +46 -0
- rust_map_parser-0.1.0/tests/test_renderer_water.py +55 -0
- rust_map_parser-0.1.0/tests/test_tunnels.py +166 -0
- rust_map_parser-0.1.0/tests/test_validation.py +35 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 rust-map-parser contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
include LICENSE
|
|
2
|
+
include README.md
|
|
3
|
+
include example.py
|
|
4
|
+
include refresh_all_data.py
|
|
5
|
+
recursive-include docs *.md *.png *.jpg
|
|
6
|
+
recursive-include tests *.py
|
|
7
|
+
recursive-include src/rustmap/data *.json
|
|
8
|
+
recursive-include src/rustmap/data/tunnel_tiles *.json *.png
|
|
@@ -0,0 +1,538 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: rust-map-parser
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Standalone Python parser, heatmap generator, and renderer for Facepunch Rust map files
|
|
5
|
+
Author: rust-map-parser contributors
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Classifier: Development Status :: 3 - Alpha
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
12
|
+
Requires-Python: >=3.11
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
License-File: LICENSE
|
|
15
|
+
Requires-Dist: lz4==4.4.4
|
|
16
|
+
Requires-Dist: numpy<3,>=2.0
|
|
17
|
+
Requires-Dist: Pillow<13,>=11
|
|
18
|
+
Requires-Dist: numba<1,>=0.61
|
|
19
|
+
Provides-Extra: assets
|
|
20
|
+
Requires-Dist: UnityPy==1.24.2; extra == "assets"
|
|
21
|
+
Dynamic: license-file
|
|
22
|
+
|
|
23
|
+
<div align="center">
|
|
24
|
+
|
|
25
|
+
# Rust Map Parser
|
|
26
|
+
|
|
27
|
+
### Decode, analyze, and render Rust `.map` files entirely from Python.
|
|
28
|
+
|
|
29
|
+
[](https://www.python.org/)
|
|
30
|
+
[](LICENSE)
|
|
31
|
+
[](#quick-start)
|
|
32
|
+
[](#refreshing-rust-data)
|
|
33
|
+
|
|
34
|
+
**A standalone, library-first toolkit for heatmaps, server-style terrain
|
|
35
|
+
renders, monuments, train tunnels, no-build zones, diagnostics, and map tiles.**
|
|
36
|
+
|
|
37
|
+

|
|
38
|
+
|
|
39
|
+
</div>
|
|
40
|
+
|
|
41
|
+
> [!NOTE]
|
|
42
|
+
> This is an independent community project. It is not affiliated with or
|
|
43
|
+
> endorsed by Facepunch Studios. Rust and its game assets belong to Facepunch.
|
|
44
|
+
|
|
45
|
+
## Why this project?
|
|
46
|
+
|
|
47
|
+
Rust `.map` files contain much more than a terrain image. They serialize height,
|
|
48
|
+
water, splat, biome, topology, path, and prefab data. Rust Map Parser turns those
|
|
49
|
+
layers into typed Python objects and useful artifacts without starting a game
|
|
50
|
+
server.
|
|
51
|
+
|
|
52
|
+
- **Choose exactly what runs** -- map only, heatmaps only, gameplay layers, or
|
|
53
|
+
any custom combination.
|
|
54
|
+
- **Pure Python consumer API** -- no CLI, Unity editor, or running Rust server.
|
|
55
|
+
- **Exact heatmap data** -- named `uint8` arrays in compressed NPZ files.
|
|
56
|
+
- **Server-style rendering** -- a close Python port of Rust's map renderer.
|
|
57
|
+
- **Gameplay-aware exports** -- monuments, recyclers, cards, puzzles, loot tiers,
|
|
58
|
+
tunnels, and no-build zones.
|
|
59
|
+
- **Asset-free normal use** -- sanitized, versioned runtime data ships with the
|
|
60
|
+
package.
|
|
61
|
+
|
|
62
|
+
## Output gallery
|
|
63
|
+
|
|
64
|
+
These images were generated from a real size-4500 Rust map.
|
|
65
|
+
|
|
66
|
+
<table>
|
|
67
|
+
<tr>
|
|
68
|
+
<td width="33%" align="center">
|
|
69
|
+
<img src="docs/images/tunnels-layer.png" alt="Underground train tunnel layer" />
|
|
70
|
+
<br /><strong>Underground train tunnels</strong>
|
|
71
|
+
</td>
|
|
72
|
+
<td width="33%" align="center">
|
|
73
|
+
<img src="docs/images/no-build-zones.png" alt="No-build zones" />
|
|
74
|
+
<br /><strong>Building-block exclusion zones</strong>
|
|
75
|
+
</td>
|
|
76
|
+
<td width="33%" align="center">
|
|
77
|
+
<img src="docs/images/heatmap-ores.png" alt="Ore heatmap" />
|
|
78
|
+
<br /><strong>Ore population heatmap</strong>
|
|
79
|
+
</td>
|
|
80
|
+
</tr>
|
|
81
|
+
</table>
|
|
82
|
+
|
|
83
|
+
## Features
|
|
84
|
+
|
|
85
|
+
- Rust header, legacy LZ4 stream, and protobuf world decoding
|
|
86
|
+
- Height, terrain, water, alpha, splat, biome, and topology layers
|
|
87
|
+
- Paths, monuments, and placed prefab transforms
|
|
88
|
+
- 25 procedural population heatmaps at configurable resolution
|
|
89
|
+
- Raw grayscale previews and native diagnostic layers
|
|
90
|
+
- Half-scale and world-size server-style terrain rendering
|
|
91
|
+
- Optional bottom-left-indexed padded map tiles
|
|
92
|
+
- Exact pre-rasterized underground train-tunnel layer
|
|
93
|
+
- Compact monument JSON with extracted gameplay metadata
|
|
94
|
+
- Compact circle/rectangle no-build zone JSON and overlays
|
|
95
|
+
- Detailed timings, source identities, counts, and validation metadata
|
|
96
|
+
- Correct orientation: exported images reverse rows only and never mirror X
|
|
97
|
+
|
|
98
|
+
## Requirements and installation
|
|
99
|
+
|
|
100
|
+
- Python 3.11 or newer
|
|
101
|
+
- A Rust `.map` file
|
|
102
|
+
|
|
103
|
+
Install from a checkout:
|
|
104
|
+
|
|
105
|
+
```powershell
|
|
106
|
+
python -m pip install .
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Editable development install:
|
|
110
|
+
|
|
111
|
+
```powershell
|
|
112
|
+
python -m pip install -e .
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
UnityPy and a local Rust install are not required for normal use. Maintainers
|
|
116
|
+
refreshing packaged game data can install the optional dependency:
|
|
117
|
+
|
|
118
|
+
```powershell
|
|
119
|
+
python -m pip install -e ".[assets]"
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Quick start
|
|
123
|
+
|
|
124
|
+
There is intentionally no command-line interface. Pick an output preset or
|
|
125
|
+
compose output sections in Python.
|
|
126
|
+
|
|
127
|
+
### Render only the map
|
|
128
|
+
|
|
129
|
+
```python
|
|
130
|
+
from pathlib import Path
|
|
131
|
+
|
|
132
|
+
from rustmap import ExportConfig, ExportOptions, RustMapExporter
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
config = ExportConfig(
|
|
136
|
+
map_path=Path(r"C:\path\to\procedural.map"),
|
|
137
|
+
output_dir=Path("output/map-only"),
|
|
138
|
+
exports=ExportOptions.map_only(tiles=True),
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
result = RustMapExporter(config).run()
|
|
142
|
+
print(result.full_map_image)
|
|
143
|
+
print(result.map_tiles_dir)
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
This run does not load spawn rules or generate heatmaps, diagnostics, monuments,
|
|
147
|
+
tunnels, or no-build zones.
|
|
148
|
+
|
|
149
|
+
### Generate only heatmaps
|
|
150
|
+
|
|
151
|
+
```python
|
|
152
|
+
config = ExportConfig(
|
|
153
|
+
map_path=Path(r"C:\path\to\procedural.map"),
|
|
154
|
+
output_dir=Path("output/heatmaps-only"),
|
|
155
|
+
exports=ExportOptions.heatmaps_only(
|
|
156
|
+
resolution=2048,
|
|
157
|
+
previews=False,
|
|
158
|
+
),
|
|
159
|
+
)
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### Export everything
|
|
163
|
+
|
|
164
|
+
The default remains a complete export:
|
|
165
|
+
|
|
166
|
+
```python
|
|
167
|
+
config = ExportConfig(
|
|
168
|
+
map_path=Path(r"C:\path\to\procedural.map"),
|
|
169
|
+
output_dir=Path("output/full"),
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
# Equivalent explicit form:
|
|
173
|
+
config = ExportConfig(
|
|
174
|
+
map_path=Path(r"C:\path\to\procedural.map"),
|
|
175
|
+
output_dir=Path("output/full"),
|
|
176
|
+
exports=ExportOptions.all(),
|
|
177
|
+
)
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Mix exactly what you need
|
|
181
|
+
|
|
182
|
+
```python
|
|
183
|
+
from rustmap import (
|
|
184
|
+
ExportConfig,
|
|
185
|
+
ExportOptions,
|
|
186
|
+
NoBuildZoneOptions,
|
|
187
|
+
RustMapExporter,
|
|
188
|
+
TerrainOptions,
|
|
189
|
+
TileOptions,
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
config = ExportConfig(
|
|
194
|
+
map_path=Path(r"C:\path\to\procedural.map"),
|
|
195
|
+
output_dir=Path("output/custom"),
|
|
196
|
+
exports=ExportOptions(
|
|
197
|
+
monuments=True,
|
|
198
|
+
terrain=TerrainOptions(
|
|
199
|
+
scale=0.5,
|
|
200
|
+
formats=("png",),
|
|
201
|
+
full_size=True,
|
|
202
|
+
tiles=TileOptions(size=512),
|
|
203
|
+
),
|
|
204
|
+
no_build_zones=NoBuildZoneOptions(
|
|
205
|
+
outline_width=4,
|
|
206
|
+
),
|
|
207
|
+
),
|
|
208
|
+
timing_debug=True,
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
result = RustMapExporter(config).run()
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
Only monuments, terrain, tiles, and no-build zones run in this example.
|
|
215
|
+
`None` disables configurable stages; `False` disables simple stages.
|
|
216
|
+
|
|
217
|
+
Use [`example.py`](example.py) for a complete editable example after installing
|
|
218
|
+
the package with `python -m pip install -e .`.
|
|
219
|
+
|
|
220
|
+
## The configuration model
|
|
221
|
+
|
|
222
|
+
For the complete option-by-option guide, see
|
|
223
|
+
**[ExportConfig in depth](docs/export-config.md)**. For every return field,
|
|
224
|
+
status, path guarantee, and consumption pattern, see
|
|
225
|
+
**[ExportResult in depth](docs/export-result.md)**.
|
|
226
|
+
|
|
227
|
+
The API separates three concerns:
|
|
228
|
+
|
|
229
|
+
```text
|
|
230
|
+
ExportConfig
|
|
231
|
+
|-- map_path / output_dir Where data comes from and goes
|
|
232
|
+
|-- exports: ExportOptions Which stages run and their settings
|
|
233
|
+
|-- data: DataOptions Optional packaged-data overrides
|
|
234
|
+
`-- timing_debug Console timing report
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
`ExportOptions()` starts with every stage disabled, which makes explicit custom
|
|
238
|
+
combinations predictable. `ExportConfig` itself uses `ExportOptions.all()` as
|
|
239
|
+
its default for convenient complete exports.
|
|
240
|
+
|
|
241
|
+
### Output sections
|
|
242
|
+
|
|
243
|
+
| Section | Type | Disabled value | Purpose |
|
|
244
|
+
|---|---|---|---|
|
|
245
|
+
| `heatmaps` | `HeatmapOptions` | `None` | NPZ arrays and optional previews |
|
|
246
|
+
| `diagnostics` | `bool` | `False` | Native decoded layer images |
|
|
247
|
+
| `monuments` | `bool` | `False` | Enriched gameplay monument JSON |
|
|
248
|
+
| `terrain` | `TerrainOptions` | `None` | Scaled/full terrain renders and tiles |
|
|
249
|
+
| `tunnels` | `TunnelOptions` | `None` | Train-tunnel layer and optional overlay |
|
|
250
|
+
| `no_build_zones` | `NoBuildZoneOptions` | `None` | Building exclusion layer, JSON, and overlay |
|
|
251
|
+
|
|
252
|
+
### Option types
|
|
253
|
+
|
|
254
|
+
`HeatmapOptions`:
|
|
255
|
+
|
|
256
|
+
| Field | Default | Meaning |
|
|
257
|
+
|---|---:|---|
|
|
258
|
+
| `resolution` | `2048` | Array width/height; `None` uses the world size |
|
|
259
|
+
| `previews` | `True` | Write exact grayscale PNG previews |
|
|
260
|
+
|
|
261
|
+
`TerrainOptions`:
|
|
262
|
+
|
|
263
|
+
| Field | Default | Meaning |
|
|
264
|
+
|---|---:|---|
|
|
265
|
+
| `scale` | `0.5` | Scaled map render size |
|
|
266
|
+
| `ocean_margin` | `0` | Extra ocean pixels around scaled output |
|
|
267
|
+
| `formats` | `("png", "jpg")` | Scaled formats used when `full_size=False` |
|
|
268
|
+
| `full_size` | `True` | Write only the one-pixel-per-metre render |
|
|
269
|
+
| `tiles` | `None` | Optional `TileOptions` |
|
|
270
|
+
| `debug` | `False` | Renderer debug mode |
|
|
271
|
+
|
|
272
|
+
`TunnelOptions` controls resolution, tunnel opacity, the purple-blue terrain
|
|
273
|
+
tint, and whether to write the transparent layer, terrain overlay, or both.
|
|
274
|
+
`NoBuildZoneOptions` controls
|
|
275
|
+
resolution, RGBA colors, outline width, and independent image/JSON output.
|
|
276
|
+
A `None` resolution uses the map's world size.
|
|
277
|
+
|
|
278
|
+
`DataOptions` can override the bundled version-matched resources:
|
|
279
|
+
|
|
280
|
+
```python
|
|
281
|
+
from rustmap import DataOptions
|
|
282
|
+
|
|
283
|
+
config = ExportConfig(
|
|
284
|
+
map_path=map_path,
|
|
285
|
+
output_dir=output_dir,
|
|
286
|
+
exports=ExportOptions.heatmaps_only(),
|
|
287
|
+
data=DataOptions(
|
|
288
|
+
spawn_rules_path=Path("custom/spawn_rules.json"),
|
|
289
|
+
prefab_manifest_path=Path("custom/prefab_manifest.json"),
|
|
290
|
+
),
|
|
291
|
+
)
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
Only resources needed by selected stages are loaded. A map-only export never
|
|
295
|
+
opens the prefab manifest or spawn-rule database.
|
|
296
|
+
|
|
297
|
+
## Results and metadata
|
|
298
|
+
|
|
299
|
+
`RustMapExporter.run()` returns an `ExportResult`. Paths for disabled stages are
|
|
300
|
+
`None`, counts are zero, and status strings are `"disabled"`.
|
|
301
|
+
|
|
302
|
+
Common fields:
|
|
303
|
+
|
|
304
|
+
```python
|
|
305
|
+
result.world_size
|
|
306
|
+
result.elapsed_seconds
|
|
307
|
+
result.metadata_file # export_metadata.json
|
|
308
|
+
result.heatmaps_file
|
|
309
|
+
result.heatmap_categories
|
|
310
|
+
result.full_map_image
|
|
311
|
+
result.map_tiles_dir
|
|
312
|
+
result.map_tile_count
|
|
313
|
+
result.monuments_file
|
|
314
|
+
result.monument_count
|
|
315
|
+
result.tunnels_image
|
|
316
|
+
result.tunnel_render_status
|
|
317
|
+
result.no_build_zones_file
|
|
318
|
+
result.no_build_zone_count
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
Every run writes `export_metadata.json`, a stage-neutral summary containing the
|
|
322
|
+
enabled-output selection, world metadata, artifacts, timings, validation data,
|
|
323
|
+
and per-stage results. This replaces the old heatmap-named top-level metadata
|
|
324
|
+
file, which was confusing for partial exports.
|
|
325
|
+
|
|
326
|
+
Every exported PNG also contains a non-visible `Source` text metadata field
|
|
327
|
+
linking to `https://github.com/Cooperkit/Rustmap-Parser`. The tag does not alter
|
|
328
|
+
the image pixels and can be inspected with Pillow through `image.info["Source"]`.
|
|
329
|
+
|
|
330
|
+
## Output layout
|
|
331
|
+
|
|
332
|
+
A complete export resembles:
|
|
333
|
+
|
|
334
|
+
```text
|
|
335
|
+
output/full/
|
|
336
|
+
|-- export_metadata.json
|
|
337
|
+
|-- heatmaps_2048.npz
|
|
338
|
+
|-- Heatmap-previews/
|
|
339
|
+
|-- diagnostics/
|
|
340
|
+
|-- monuments.json
|
|
341
|
+
|-- map_render_full.png
|
|
342
|
+
|-- map_render_metadata.json
|
|
343
|
+
|-- map_render_tiles/ # only when TerrainOptions.tiles is enabled
|
|
344
|
+
| |-- x_0_y_0.png
|
|
345
|
+
| `-- tiles.json
|
|
346
|
+
|-- tunnels.png
|
|
347
|
+
|-- tunnels_on_map.png
|
|
348
|
+
|-- tunnels_metadata.json
|
|
349
|
+
|-- no_build_zones.png
|
|
350
|
+
|-- no_build_zones_on_map.png
|
|
351
|
+
`-- no_build_zones.json
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
Use a fresh output directory for logically different selections. The exporter
|
|
355
|
+
does not delete artifacts from a previous run merely because their stage is now
|
|
356
|
+
disabled.
|
|
357
|
+
|
|
358
|
+
## Heatmaps
|
|
359
|
+
|
|
360
|
+
Heatmaps are named `uint8[resolution, resolution]` arrays stored in one
|
|
361
|
+
compressed NPZ archive. Values range from 0 to 255.
|
|
362
|
+
|
|
363
|
+
```text
|
|
364
|
+
bear, berries, boar, chicken, corn, crocodile, flowers, hab, hemp,
|
|
365
|
+
horse, junkpiles, logs, modularcar, mushroom, ores, pedalbike,
|
|
366
|
+
potato, pumpkin, rowboat, snake, stag, tiger, wheat, wolf, wood
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
```python
|
|
370
|
+
import numpy as np
|
|
371
|
+
|
|
372
|
+
with np.load(result.heatmaps_file) as heatmaps:
|
|
373
|
+
ores = heatmaps["ores"]
|
|
374
|
+
print(ores.dtype, ores.shape, ores.max())
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
Repeated population rules and splat samples are cached without changing final
|
|
378
|
+
NPZ bytes.
|
|
379
|
+
|
|
380
|
+
## Server-style terrain rendering
|
|
381
|
+
|
|
382
|
+
The renderer ports Rust's ordered splat blends, height normals, lighting,
|
|
383
|
+
shoreline distance field, topology lookup, water depth, contrast, brightness,
|
|
384
|
+
and offshore color.
|
|
385
|
+
|
|
386
|
+
- With `full_size=False`, `map_render.png` / `.jpg` are convenient scaled renders.
|
|
387
|
+
- With `full_size=True`, only the native one-pixel-per-metre
|
|
388
|
+
`map_render_full.png` is rendered; scaled outputs are skipped.
|
|
389
|
+
- Optional tiles crop from the in-memory full render and do not change its bytes.
|
|
390
|
+
|
|
391
|
+
Tiles use a bottom-left origin, fixed RGBA dimensions, and transparent padding
|
|
392
|
+
on partial top/right edges. A size-4250 map produces 81 512px tiles; size-6000
|
|
393
|
+
produces 144.
|
|
394
|
+
|
|
395
|
+
## Monuments
|
|
396
|
+
|
|
397
|
+
`monuments.json` includes deterministic gameplay monuments with:
|
|
398
|
+
|
|
399
|
+
- Resolved prefab path and world position
|
|
400
|
+
- Bottom-left `map_position` in metres
|
|
401
|
+
- Heading, display name, family, kind, environment, spawn group, and size class
|
|
402
|
+
- Safe-zone status, recycler count, keycards, puzzle type, and detected loot tier
|
|
403
|
+
- Searchable tags
|
|
404
|
+
|
|
405
|
+
Gameplay facts come from a sanitized, build-versioned component database
|
|
406
|
+
bundled with the package.
|
|
407
|
+
|
|
408
|
+
## Underground train tunnels
|
|
409
|
+
|
|
410
|
+
The package ships 81 sanitized final-LOD tunnel puzzle-piece PNGs rasterized at
|
|
411
|
+
8 pixels per metre. Normal exports need neither UnityPy nor installed Rust
|
|
412
|
+
assets.
|
|
413
|
+
|
|
414
|
+
- `tunnels.png` is the authoritative transparent layer.
|
|
415
|
+
- `tunnels_on_map.png` is written when a full terrain render is selected.
|
|
416
|
+
- Set `export_layer=False, export_overlay=True` for overlay-only output.
|
|
417
|
+
- Without terrain, tunnel export still succeeds and omits only the overlay.
|
|
418
|
+
- Build mismatches and missing templates are recorded instead of hidden.
|
|
419
|
+
|
|
420
|
+
Original Facepunch meshes are never shipped.
|
|
421
|
+
|
|
422
|
+
## No-build zones
|
|
423
|
+
|
|
424
|
+
No-build export represents restrictions affecting building blocks. It keeps
|
|
425
|
+
useful circles and rotated rectangles, removes shapes fully contained by a
|
|
426
|
+
larger primitive from the same owner, and excludes deployable-only volumes,
|
|
427
|
+
capsules, mesh blockers, and redundant internals.
|
|
428
|
+
|
|
429
|
+
The transparent layer and JSON work without terrain. The composited preview is
|
|
430
|
+
added only when the selected terrain section includes a full-size render. Set
|
|
431
|
+
`export_images=False, export_json=True` for a fast JSON-only export that skips
|
|
432
|
+
rasterization and PNG encoding.
|
|
433
|
+
|
|
434
|
+
## Low-level parsing
|
|
435
|
+
|
|
436
|
+
Skip the exporter entirely when you only need decoded data:
|
|
437
|
+
|
|
438
|
+
```python
|
|
439
|
+
from rustmap import load_map
|
|
440
|
+
from rustmap.layers import biome_grid, splat_grid, topology_grid, world_height_grid
|
|
441
|
+
|
|
442
|
+
world = load_map("procedural.map")
|
|
443
|
+
height = world_height_grid(world)
|
|
444
|
+
water = world_height_grid(world, "water")
|
|
445
|
+
splat = splat_grid(world)
|
|
446
|
+
biome = biome_grid(world)
|
|
447
|
+
topology = topology_grid(world)
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
## Coordinates and orientation
|
|
451
|
+
|
|
452
|
+
| Space | Origin | Axes |
|
|
453
|
+
|---|---|---|
|
|
454
|
+
| Unity world | Map center | X right, Y elevation, Z up/north |
|
|
455
|
+
| Analytical arrays | Native `[z, x]` | No image transformation |
|
|
456
|
+
| Exported images | Top-left | X preserved; Z rows reversed |
|
|
457
|
+
| `map_position` | Bottom-left | X right, Y up, metres |
|
|
458
|
+
| Tile coordinates | Bottom-left | X right, Y up |
|
|
459
|
+
|
|
460
|
+
```text
|
|
461
|
+
map_x = world_x + world_size / 2
|
|
462
|
+
map_y = world_z + world_size / 2
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
For a world-size image, one metre equals one pixel. Convert bottom-left map Y
|
|
466
|
+
to an image row with `image_y = world_size - map_y`.
|
|
467
|
+
|
|
468
|
+
## Performance
|
|
469
|
+
|
|
470
|
+
The exporter reuses decoded layers, splat samples, shoreline data, height
|
|
471
|
+
normals, and rule evaluations. Independent work uses bounded threads without
|
|
472
|
+
duplicating the full terrain state.
|
|
473
|
+
|
|
474
|
+
Recorded size-4500 timings on the development machine:
|
|
475
|
+
|
|
476
|
+
| Selection | Wall time |
|
|
477
|
+
|---|---:|
|
|
478
|
+
| Heatmaps only, no previews | 4.49 s |
|
|
479
|
+
| Gameplay layers only | 2.05 s |
|
|
480
|
+
| Map only | 18.95 s |
|
|
481
|
+
| Complete export | about 27 s |
|
|
482
|
+
|
|
483
|
+
Times depend on hardware, map size, enabled outputs, and PNG compressibility.
|
|
484
|
+
|
|
485
|
+
## Refreshing Rust data
|
|
486
|
+
|
|
487
|
+
Maintainers refresh every packaged runtime resource with one script:
|
|
488
|
+
|
|
489
|
+
```powershell
|
|
490
|
+
python -m pip install -e ".[assets]"
|
|
491
|
+
python refresh_all_data.py
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
[`refresh_all_data.py`](refresh_all_data.py) stages and validates the prefab
|
|
495
|
+
manifest, spawn rules, monument gameplay metadata, no-build geometry, and 81
|
|
496
|
+
tunnel tiles. It checks Rust build IDs, bundle identities, counts, and machine
|
|
497
|
+
path leaks before replacing `src/rustmap/data`.
|
|
498
|
+
|
|
499
|
+
## Development
|
|
500
|
+
|
|
501
|
+
```powershell
|
|
502
|
+
$env:PYTHONPATH = "src"
|
|
503
|
+
python -m pytest -q
|
|
504
|
+
python -m build
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
The suite covers configuration, selection presets, orientation, water behavior,
|
|
508
|
+
no-build containment, tunnel templates, map tiles, resources, and exact output
|
|
509
|
+
comparisons.
|
|
510
|
+
|
|
511
|
+
## Project layout
|
|
512
|
+
|
|
513
|
+
```text
|
|
514
|
+
rust-map-parser/
|
|
515
|
+
|-- src/rustmap/ # Package and implementation
|
|
516
|
+
| `-- data/ # Versioned sanitized runtime resources
|
|
517
|
+
|-- tests/ # Unit and regression tests
|
|
518
|
+
|-- docs/images/ # README showcase outputs
|
|
519
|
+
|-- example.py # Complete editable installed-package example
|
|
520
|
+
|-- refresh_all_data.py # Unified maintainer refresh
|
|
521
|
+
|-- pyproject.toml
|
|
522
|
+
`-- LICENSE
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
## Limitations
|
|
526
|
+
|
|
527
|
+
- Runtime resources are tied to their recorded Rust build.
|
|
528
|
+
- Unknown custom-map prefabs are reported and skipped rather than guessed.
|
|
529
|
+
- Runtime-only water volumes or engine floating-point details can differ from a
|
|
530
|
+
live server render.
|
|
531
|
+
- This repository does not include `.map` files, Facepunch source assets, or
|
|
532
|
+
original extracted meshes.
|
|
533
|
+
|
|
534
|
+
## License
|
|
535
|
+
|
|
536
|
+
Original Python code is licensed under the [MIT License](LICENSE). Rust, its
|
|
537
|
+
formats, assets, names, and related intellectual property remain the property
|
|
538
|
+
of Facepunch Studios.
|