rust-map-parser 0.1.0__py3-none-any.whl

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.
Files changed (110) hide show
  1. rust_map_parser-0.1.0.dist-info/METADATA +538 -0
  2. rust_map_parser-0.1.0.dist-info/RECORD +110 -0
  3. rust_map_parser-0.1.0.dist-info/WHEEL +5 -0
  4. rust_map_parser-0.1.0.dist-info/licenses/LICENSE +21 -0
  5. rust_map_parser-0.1.0.dist-info/top_level.txt +1 -0
  6. rustmap/__init__.py +44 -0
  7. rustmap/config.py +236 -0
  8. rustmap/data/__init__.py +1 -0
  9. rustmap/data/monument_metadata.json +954 -0
  10. rustmap/data/no_build_zones.json +9543 -0
  11. rustmap/data/prefab_manifest.json +242637 -0
  12. rustmap/data/spawn_rules.json +3308 -0
  13. rustmap/data/tunnel_tiles/__init__.py +1 -0
  14. rustmap/data/tunnel_tiles/template_000__curve-nw-0.png +0 -0
  15. rustmap/data/tunnel_tiles/template_001__curve-nw-1.png +0 -0
  16. rustmap/data/tunnel_tiles/template_002__intersection-bb1-n.png +0 -0
  17. rustmap/data/tunnel_tiles/template_003__intersection-bb4-n.png +0 -0
  18. rustmap/data/tunnel_tiles/template_004__intersection-b5-n.png +0 -0
  19. rustmap/data/tunnel_tiles/template_005__intersection-b3-n.png +0 -0
  20. rustmap/data/tunnel_tiles/template_006__intersection-b2-n.png +0 -0
  21. rustmap/data/tunnel_tiles/template_007__intersection-bb2-n.png +0 -0
  22. rustmap/data/tunnel_tiles/template_008__intersection-b6-n.png +0 -0
  23. rustmap/data/tunnel_tiles/template_009__intersection-bb3-n.png +0 -0
  24. rustmap/data/tunnel_tiles/template_010__intersection-b4-n.png +0 -0
  25. rustmap/data/tunnel_tiles/template_011__intersection-bb6-n.png +0 -0
  26. rustmap/data/tunnel_tiles/template_012__intersection-n.png +0 -0
  27. rustmap/data/tunnel_tiles/template_013__intersection-b1-n.png +0 -0
  28. rustmap/data/tunnel_tiles/template_014__intersection-bb5-n.png +0 -0
  29. rustmap/data/tunnel_tiles/template_015__station-sn-0.png +0 -0
  30. rustmap/data/tunnel_tiles/template_016__straight-sn-3.png +0 -0
  31. rustmap/data/tunnel_tiles/template_017__straight-sn-2.png +0 -0
  32. rustmap/data/tunnel_tiles/template_018__station-sn-1.png +0 -0
  33. rustmap/data/tunnel_tiles/template_019__straight-sn-0.png +0 -0
  34. rustmap/data/tunnel_tiles/template_020__straight-sn-1.png +0 -0
  35. rustmap/data/tunnel_tiles/template_021__station-sn-3.png +0 -0
  36. rustmap/data/tunnel_tiles/template_022__straight-sn-4.png +0 -0
  37. rustmap/data/tunnel_tiles/template_023__station-sn-2.png +0 -0
  38. rustmap/data/tunnel_tiles/template_024__straight-sn-5.png +0 -0
  39. rustmap/data/tunnel_tiles/template_025__curve-ne-1.png +0 -0
  40. rustmap/data/tunnel_tiles/template_026__curve-ne-0.png +0 -0
  41. rustmap/data/tunnel_tiles/template_027__intersection.png +0 -0
  42. rustmap/data/tunnel_tiles/template_028__intersection-bb2-s.png +0 -0
  43. rustmap/data/tunnel_tiles/template_029__intersection-b2-s.png +0 -0
  44. rustmap/data/tunnel_tiles/template_030__intersection-b6-s.png +0 -0
  45. rustmap/data/tunnel_tiles/template_031__intersection-bb5-s.png +0 -0
  46. rustmap/data/tunnel_tiles/template_032__intersection-bb1-s.png +0 -0
  47. rustmap/data/tunnel_tiles/template_033__intersection-s.png +0 -0
  48. rustmap/data/tunnel_tiles/template_034__intersection-b1-s.png +0 -0
  49. rustmap/data/tunnel_tiles/template_035__intersection-bb6-s.png +0 -0
  50. rustmap/data/tunnel_tiles/template_036__intersection-b5-s.png +0 -0
  51. rustmap/data/tunnel_tiles/template_037__intersection-bb4-s.png +0 -0
  52. rustmap/data/tunnel_tiles/template_038__intersection-b3-s.png +0 -0
  53. rustmap/data/tunnel_tiles/template_039__intersection-bb3-s.png +0 -0
  54. rustmap/data/tunnel_tiles/template_040__intersection-b4-s.png +0 -0
  55. rustmap/data/tunnel_tiles/template_041__straight-we-3.png +0 -0
  56. rustmap/data/tunnel_tiles/template_042__station-we-1.png +0 -0
  57. rustmap/data/tunnel_tiles/template_043__straight-we-5.png +0 -0
  58. rustmap/data/tunnel_tiles/template_044__straight-we-4.png +0 -0
  59. rustmap/data/tunnel_tiles/template_045__station-we-2.png +0 -0
  60. rustmap/data/tunnel_tiles/template_046__station-we-3.png +0 -0
  61. rustmap/data/tunnel_tiles/template_047__station-we-0.png +0 -0
  62. rustmap/data/tunnel_tiles/template_048__straight-we-2.png +0 -0
  63. rustmap/data/tunnel_tiles/template_049__straight-we-1.png +0 -0
  64. rustmap/data/tunnel_tiles/template_050__straight-we-0.png +0 -0
  65. rustmap/data/tunnel_tiles/template_051__curve-se-0.png +0 -0
  66. rustmap/data/tunnel_tiles/template_052__curve-se-1.png +0 -0
  67. rustmap/data/tunnel_tiles/template_053__intersection-bb3-w.png +0 -0
  68. rustmap/data/tunnel_tiles/template_054__intersection-w.png +0 -0
  69. rustmap/data/tunnel_tiles/template_055__intersection-bb5-w.png +0 -0
  70. rustmap/data/tunnel_tiles/template_056__intersection-b5-w.png +0 -0
  71. rustmap/data/tunnel_tiles/template_057__intersection-b1-w.png +0 -0
  72. rustmap/data/tunnel_tiles/template_058__intersection-bb1-w.png +0 -0
  73. rustmap/data/tunnel_tiles/template_059__intersection-bb4-w.png +0 -0
  74. rustmap/data/tunnel_tiles/template_060__intersection-b4-w.png +0 -0
  75. rustmap/data/tunnel_tiles/template_061__intersection-b6-w.png +0 -0
  76. rustmap/data/tunnel_tiles/template_062__intersection-bb2-w.png +0 -0
  77. rustmap/data/tunnel_tiles/template_063__intersection-b3-w.png +0 -0
  78. rustmap/data/tunnel_tiles/template_064__intersection-b2-w.png +0 -0
  79. rustmap/data/tunnel_tiles/template_065__intersection-bb6-w.png +0 -0
  80. rustmap/data/tunnel_tiles/template_066__curve-sw-0.png +0 -0
  81. rustmap/data/tunnel_tiles/template_067__curve-sw-1.png +0 -0
  82. rustmap/data/tunnel_tiles/template_068__intersection-bb3-e.png +0 -0
  83. rustmap/data/tunnel_tiles/template_069__intersection-bb6-e.png +0 -0
  84. rustmap/data/tunnel_tiles/template_070__intersection-b4-e.png +0 -0
  85. rustmap/data/tunnel_tiles/template_071__intersection-b6-e.png +0 -0
  86. rustmap/data/tunnel_tiles/template_072__intersection-b5-e.png +0 -0
  87. rustmap/data/tunnel_tiles/template_073__intersection-b1-e.png +0 -0
  88. rustmap/data/tunnel_tiles/template_074__intersection-b3-e.png +0 -0
  89. rustmap/data/tunnel_tiles/template_075__intersection-bb2-e.png +0 -0
  90. rustmap/data/tunnel_tiles/template_076__intersection-e.png +0 -0
  91. rustmap/data/tunnel_tiles/template_077__intersection-bb1-e.png +0 -0
  92. rustmap/data/tunnel_tiles/template_078__intersection-bb4-e.png +0 -0
  93. rustmap/data/tunnel_tiles/template_079__intersection-b2-e.png +0 -0
  94. rustmap/data/tunnel_tiles/template_080__intersection-bb5-e.png +0 -0
  95. rustmap/data/tunnel_tiles/tiles.json +997 -0
  96. rustmap/exporter.py +409 -0
  97. rustmap/layers.py +323 -0
  98. rustmap/monument_assets.py +145 -0
  99. rustmap/monuments.py +226 -0
  100. rustmap/no_build.py +288 -0
  101. rustmap/no_build_assets.py +303 -0
  102. rustmap/parser.py +297 -0
  103. rustmap/png.py +18 -0
  104. rustmap/populations.py +361 -0
  105. rustmap/prefabs.py +281 -0
  106. rustmap/renderer.py +460 -0
  107. rustmap/resources.py +26 -0
  108. rustmap/tunnel_assets.py +398 -0
  109. rustmap/tunnels.py +417 -0
  110. rustmap/validation.py +106 -0
rustmap/__init__.py ADDED
@@ -0,0 +1,44 @@
1
+ """Public API for the standalone Rust map parser."""
2
+
3
+ from .config import (
4
+ DataOptions,
5
+ ExportConfig,
6
+ ExportOptions,
7
+ ExportResult,
8
+ HeatmapOptions,
9
+ NoBuildZoneOptions,
10
+ TerrainOptions,
11
+ TileOptions,
12
+ TunnelOptions,
13
+ )
14
+ from .exporter import RustMapExporter
15
+ from .layers import generate_diagnostics
16
+ from .parser import RustMap, RustMapError, load_map
17
+ from .resources import refresh_prefab_manifest, refresh_spawn_rules
18
+ from .validation import compare_files as compare_heatmaps
19
+ from .tunnels import render_tunnel_map
20
+ from .tunnel_assets import (
21
+ install_packaged_tunnel_templates,
22
+ refresh_tunnel_geometry,
23
+ refresh_tunnel_templates,
24
+ )
25
+ from .no_build import build_no_build_export, save_no_build_zones
26
+ from .no_build_assets import refresh_no_build_zone_data
27
+ from .monuments import monument_metadata
28
+ from .monument_assets import refresh_monument_metadata
29
+
30
+ __all__ = (
31
+ "DataOptions", "ExportConfig", "ExportOptions", "ExportResult",
32
+ "HeatmapOptions", "NoBuildZoneOptions", "TerrainOptions", "TileOptions",
33
+ "TunnelOptions", "RustMapExporter", "RustMap", "RustMapError",
34
+ "load_map", "generate_diagnostics", "refresh_prefab_manifest",
35
+ "refresh_spawn_rules", "compare_heatmaps", "render_tunnel_map",
36
+ "refresh_tunnel_geometry",
37
+ "refresh_tunnel_templates",
38
+ "install_packaged_tunnel_templates",
39
+ "build_no_build_export", "save_no_build_zones", "refresh_no_build_zone_data",
40
+ "monument_metadata",
41
+ "refresh_monument_metadata",
42
+ )
43
+
44
+ __version__ = "0.1.0"
rustmap/config.py ADDED
@@ -0,0 +1,236 @@
1
+ """Composable typed configuration and result objects for Rust map exports."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from collections.abc import Sequence
6
+ from dataclasses import dataclass, field
7
+ from pathlib import Path
8
+
9
+
10
+ Color = tuple[int, int, int, int]
11
+
12
+
13
+ @dataclass(frozen=True, slots=True)
14
+ class DataOptions:
15
+ """Optional overrides for the versioned data bundled with ``rustmap``."""
16
+
17
+ spawn_rules_path: Path | None = None
18
+ prefab_manifest_path: Path | None = None
19
+
20
+
21
+ @dataclass(frozen=True, slots=True)
22
+ class HeatmapOptions:
23
+ resolution: int | None = 2048
24
+ previews: bool = True
25
+
26
+ def resolved_resolution(self, world_size: int) -> int:
27
+ """Return the configured pixel size, or one pixel per world metre."""
28
+ return int(world_size if self.resolution is None else self.resolution)
29
+
30
+
31
+ @dataclass(frozen=True, slots=True)
32
+ class TileOptions:
33
+ size: int = 512
34
+
35
+
36
+ @dataclass(frozen=True, slots=True)
37
+ class TerrainOptions:
38
+ scale: float = 0.5
39
+ ocean_margin: int = 0
40
+ formats: str | Sequence[str] = ("png", "jpg")
41
+ full_size: bool = True
42
+ tiles: TileOptions | None = None
43
+ debug: bool = False
44
+
45
+
46
+ @dataclass(frozen=True, slots=True)
47
+ class TunnelOptions:
48
+ resolution: int | None = None
49
+ overlay_opacity: float = 1.0
50
+ export_layer: bool = True
51
+ export_overlay: bool = True
52
+ tint_color: Color = (50, 45, 105, 104)
53
+
54
+
55
+ @dataclass(frozen=True, slots=True)
56
+ class NoBuildZoneOptions:
57
+ resolution: int | None = None
58
+ fill_color: Color = (255, 0, 0, 64)
59
+ outline_color: Color = (255, 0, 0, 255)
60
+ outline_width: int = 3
61
+ export_images: bool = True
62
+ export_json: bool = True
63
+
64
+
65
+ @dataclass(frozen=True, slots=True)
66
+ class ExportOptions:
67
+ """Select outputs. ``None``/``False`` means that stage does not run."""
68
+
69
+ heatmaps: HeatmapOptions | None = None
70
+ diagnostics: bool = False
71
+ monuments: bool = False
72
+ terrain: TerrainOptions | None = None
73
+ tunnels: TunnelOptions | None = None
74
+ no_build_zones: NoBuildZoneOptions | None = None
75
+
76
+ @classmethod
77
+ def all(cls) -> "ExportOptions":
78
+ return cls(
79
+ heatmaps=HeatmapOptions(), diagnostics=True, monuments=True,
80
+ terrain=TerrainOptions(), tunnels=TunnelOptions(),
81
+ no_build_zones=NoBuildZoneOptions(),
82
+ )
83
+
84
+ @classmethod
85
+ def map_only(cls, *, tiles: bool = False,
86
+ tile_size: int = 512) -> "ExportOptions":
87
+ tile_options = TileOptions(tile_size) if tiles else None
88
+ return cls(terrain=TerrainOptions(tiles=tile_options))
89
+
90
+ @classmethod
91
+ def heatmaps_only(cls, *, resolution: int | None = 2048,
92
+ previews: bool = True) -> "ExportOptions":
93
+ return cls(heatmaps=HeatmapOptions(resolution, previews))
94
+
95
+
96
+ @dataclass(frozen=True, slots=True)
97
+ class ExportConfig:
98
+ map_path: Path
99
+ output_dir: Path
100
+ exports: ExportOptions = field(default_factory=ExportOptions.all)
101
+ data: DataOptions = field(default_factory=DataOptions)
102
+ timing_debug: bool = False
103
+
104
+ def validated(self) -> "ExportConfig":
105
+ map_path = Path(self.map_path)
106
+ output_dir = Path(self.output_dir)
107
+ if not map_path.is_file():
108
+ raise FileNotFoundError(f"Rust map not found: {map_path}")
109
+ exports = self.exports
110
+ if not any((exports.heatmaps, exports.diagnostics, exports.monuments,
111
+ exports.terrain, exports.tunnels, exports.no_build_zones)):
112
+ raise ValueError("At least one export output must be enabled")
113
+
114
+ heatmaps = exports.heatmaps
115
+ if (heatmaps is not None and heatmaps.resolution is not None and
116
+ heatmaps.resolution <= 0):
117
+ raise ValueError("heatmap resolution must be positive")
118
+
119
+ terrain = exports.terrain
120
+ if terrain is not None:
121
+ if terrain.ocean_margin < 0:
122
+ raise ValueError("terrain ocean_margin cannot be negative")
123
+ requested_formats = (
124
+ (terrain.formats,) if isinstance(terrain.formats, str)
125
+ else terrain.formats
126
+ )
127
+ formats = tuple(str(item).strip().casefold() for item in requested_formats)
128
+ unsupported = set(formats) - {"png", "jpg", "jpeg"}
129
+ if unsupported:
130
+ raise ValueError(f"Unsupported terrain formats: {sorted(unsupported)}")
131
+ if not formats and not terrain.full_size:
132
+ raise ValueError("Terrain export needs a scaled format or full_size=True")
133
+ if terrain.tiles is not None:
134
+ if not terrain.full_size:
135
+ raise ValueError("Terrain tiles require full_size=True")
136
+ if terrain.tiles.size <= 0:
137
+ raise ValueError("terrain tile size must be positive")
138
+ terrain = TerrainOptions(
139
+ scale=terrain.scale, ocean_margin=terrain.ocean_margin,
140
+ formats=formats, full_size=terrain.full_size,
141
+ tiles=terrain.tiles, debug=terrain.debug,
142
+ )
143
+
144
+ tunnels = exports.tunnels
145
+ if tunnels is not None:
146
+ if tunnels.resolution is not None and tunnels.resolution <= 0:
147
+ raise ValueError("tunnel resolution must be positive")
148
+ if not 0.0 <= tunnels.overlay_opacity <= 1.0:
149
+ raise ValueError("tunnel overlay_opacity must be between 0 and 1")
150
+ if (len(tunnels.tint_color) != 4 or
151
+ any(not 0 <= int(channel) <= 255 for channel in tunnels.tint_color)):
152
+ raise ValueError("tunnel tint_color must contain four channels from 0 to 255")
153
+ if not tunnels.export_layer and not tunnels.export_overlay:
154
+ raise ValueError("Tunnel export needs export_layer or export_overlay")
155
+ if (tunnels.export_overlay and not tunnels.export_layer and
156
+ (terrain is None or not terrain.full_size)):
157
+ raise ValueError("Tunnel overlay-only export requires full-size terrain")
158
+ tunnels = TunnelOptions(
159
+ resolution=tunnels.resolution,
160
+ overlay_opacity=tunnels.overlay_opacity,
161
+ tint_color=tuple(map(int, tunnels.tint_color)),
162
+ export_layer=bool(tunnels.export_layer),
163
+ export_overlay=bool(tunnels.export_overlay),
164
+ )
165
+
166
+ no_build = exports.no_build_zones
167
+ if no_build is not None:
168
+ if no_build.resolution is not None and no_build.resolution <= 0:
169
+ raise ValueError("no-build resolution must be positive")
170
+ if no_build.outline_width < 0:
171
+ raise ValueError("no-build outline_width cannot be negative")
172
+ if not no_build.export_images and not no_build.export_json:
173
+ raise ValueError("No-build export needs export_images or export_json")
174
+ for label, color in (("fill_color", no_build.fill_color),
175
+ ("outline_color", no_build.outline_color)):
176
+ if len(color) != 4 or any(not 0 <= int(channel) <= 255 for channel in color):
177
+ raise ValueError(f"no-build {label} must contain four channels from 0 to 255")
178
+ no_build = NoBuildZoneOptions(
179
+ resolution=no_build.resolution,
180
+ fill_color=tuple(map(int, no_build.fill_color)),
181
+ outline_color=tuple(map(int, no_build.outline_color)),
182
+ outline_width=no_build.outline_width,
183
+ export_images=bool(no_build.export_images),
184
+ export_json=bool(no_build.export_json),
185
+ )
186
+
187
+ data = self.data
188
+ required_overrides = (
189
+ ("spawn rules", data.spawn_rules_path, heatmaps is not None),
190
+ ("prefab manifest", data.prefab_manifest_path,
191
+ bool(exports.monuments or tunnels or no_build)),
192
+ )
193
+ for label, value, required in required_overrides:
194
+ if required and value is not None and not Path(value).is_file():
195
+ raise FileNotFoundError(f"Override {label} file not found: {value}")
196
+ normalized_data = DataOptions(
197
+ spawn_rules_path=Path(data.spawn_rules_path) if data.spawn_rules_path else None,
198
+ prefab_manifest_path=Path(data.prefab_manifest_path) if data.prefab_manifest_path else None,
199
+ )
200
+ normalized_exports = ExportOptions(
201
+ heatmaps=heatmaps, diagnostics=bool(exports.diagnostics),
202
+ monuments=bool(exports.monuments), terrain=terrain,
203
+ tunnels=tunnels, no_build_zones=no_build,
204
+ )
205
+ return ExportConfig(
206
+ map_path=map_path, output_dir=output_dir, exports=normalized_exports,
207
+ data=normalized_data, timing_debug=bool(self.timing_debug),
208
+ )
209
+
210
+
211
+ @dataclass(frozen=True, slots=True)
212
+ class ExportResult:
213
+ output_dir: Path
214
+ world_size: int
215
+ elapsed_seconds: float
216
+ metadata_file: Path
217
+ metadata: dict
218
+ heatmap_categories: tuple[str, ...] = ()
219
+ heatmaps_file: Path | None = None
220
+ monuments_file: Path | None = None
221
+ monument_count: int = 0
222
+ map_image: Path | None = None
223
+ full_map_image: Path | None = None
224
+ map_tiles_dir: Path | None = None
225
+ map_tiles_metadata_file: Path | None = None
226
+ map_tile_count: int = 0
227
+ diagnostics_dir: Path | None = None
228
+ tunnels_image: Path | None = None
229
+ tunnels_overlay_image: Path | None = None
230
+ tunnels_metadata_file: Path | None = None
231
+ tunnel_render_status: str = "disabled"
232
+ no_build_zones_image: Path | None = None
233
+ no_build_zones_overlay_image: Path | None = None
234
+ no_build_zones_file: Path | None = None
235
+ no_build_zone_count: int = 0
236
+ no_build_zone_status: str = "disabled"
@@ -0,0 +1 @@
1
+ """Versioned Rust prefab manifest and population-rule resources."""