maps4fs 0.9.0__py3-none-any.whl → 0.9.2__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.
- maps4fs/generator/background.py +12 -1
- maps4fs/generator/component.py +73 -4
- maps4fs/generator/config.py +11 -0
- maps4fs/generator/qgis.py +114 -0
- maps4fs/generator/texture.py +2 -16
- {maps4fs-0.9.0.dist-info → maps4fs-0.9.2.dist-info}/METADATA +7 -16
- {maps4fs-0.9.0.dist-info → maps4fs-0.9.2.dist-info}/RECORD +10 -9
- {maps4fs-0.9.0.dist-info → maps4fs-0.9.2.dist-info}/LICENSE.md +0 -0
- {maps4fs-0.9.0.dist-info → maps4fs-0.9.2.dist-info}/WHEEL +0 -0
- {maps4fs-0.9.0.dist-info → maps4fs-0.9.2.dist-info}/top_level.txt +0 -0
maps4fs/generator/background.py
CHANGED
@@ -50,7 +50,8 @@ class Background(Component):
|
|
50
50
|
tile_code=path_step.code,
|
51
51
|
auto_process=False,
|
52
52
|
blur_radius=self.kwargs.get("blur_radius"),
|
53
|
-
multiplier=1,
|
53
|
+
multiplier=self.kwargs.get("multiplier", 1),
|
54
|
+
plateau=self.kwargs.get("plateau", 0),
|
54
55
|
)
|
55
56
|
|
56
57
|
# Update the origin for the next tile.
|
@@ -80,6 +81,8 @@ class Background(Component):
|
|
80
81
|
dict[str, dict[str, float | int]] -- A dictionary with information about the tiles.
|
81
82
|
"""
|
82
83
|
data = {}
|
84
|
+
self.qgis_sequence()
|
85
|
+
|
83
86
|
for tile in self.tiles:
|
84
87
|
north, south, east, west = tile.bbox
|
85
88
|
epsg3857_string = tile.get_epsg3857_string()
|
@@ -100,6 +103,14 @@ class Background(Component):
|
|
100
103
|
|
101
104
|
return data # type: ignore
|
102
105
|
|
106
|
+
def qgis_sequence(self) -> None:
|
107
|
+
"""Generates QGIS scripts for creating bounding box layers and rasterizing them."""
|
108
|
+
qgis_layers = [
|
109
|
+
(f"Background_bbox_{tile.code}", *tile.get_espg3857_bbox()) for tile in self.tiles
|
110
|
+
]
|
111
|
+
|
112
|
+
self.create_qgis_scripts(qgis_layers) # type: ignore
|
113
|
+
|
103
114
|
def generate_obj_files(self) -> None:
|
104
115
|
"""Iterates over all tiles and generates 3D obj files based on DEM data.
|
105
116
|
If at least one DEM file is missing, the generation will be stopped at all.
|
maps4fs/generator/component.py
CHANGED
@@ -10,6 +10,8 @@ from typing import TYPE_CHECKING, Any
|
|
10
10
|
import osmnx as ox # type: ignore
|
11
11
|
from pyproj import Transformer
|
12
12
|
|
13
|
+
from maps4fs.generator.qgis import get_bbox_template, get_rasterize_template
|
14
|
+
|
13
15
|
if TYPE_CHECKING:
|
14
16
|
from maps4fs.generator.game import Game
|
15
17
|
|
@@ -47,6 +49,7 @@ class Component:
|
|
47
49
|
self.kwargs = kwargs
|
48
50
|
|
49
51
|
os.makedirs(self.previews_directory, exist_ok=True)
|
52
|
+
os.makedirs(self.scripts_directory, exist_ok=True)
|
50
53
|
|
51
54
|
self.save_bbox()
|
52
55
|
self.preprocess()
|
@@ -84,6 +87,15 @@ class Component:
|
|
84
87
|
"""
|
85
88
|
return os.path.join(self.map_directory, "previews")
|
86
89
|
|
90
|
+
@property
|
91
|
+
def scripts_directory(self) -> str:
|
92
|
+
"""The directory where the scripts are stored.
|
93
|
+
|
94
|
+
Returns:
|
95
|
+
str: The directory where the scripts are stored.
|
96
|
+
"""
|
97
|
+
return os.path.join(self.map_directory, "scripts")
|
98
|
+
|
87
99
|
@property
|
88
100
|
def generation_info_path(self) -> str:
|
89
101
|
"""The path to the generation info JSON file.
|
@@ -187,15 +199,31 @@ class Component:
|
|
187
199
|
self.bbox = self.get_bbox(project_utm=False)
|
188
200
|
self.logger.debug("Saved bounding box: %s", self.bbox)
|
189
201
|
|
190
|
-
|
191
|
-
|
202
|
+
@property
|
203
|
+
def new_bbox(self) -> tuple[float, float, float, float]:
|
204
|
+
"""This property is used for a new version of osmnx library, where the order of coordinates
|
205
|
+
has been changed to (left, bottom, right, top).
|
206
|
+
|
207
|
+
Returns:
|
208
|
+
tuple[float, float, float, float]: The bounding box of the map in the new order:
|
209
|
+
(left, bottom, right, top).
|
210
|
+
"""
|
211
|
+
# FutureWarning: The expected order of coordinates in `bbox`
|
212
|
+
# will change in the v2.0.0 release to `(left, bottom, right, top)`.
|
213
|
+
north, south, east, west = self.bbox
|
214
|
+
return west, south, east, north
|
215
|
+
|
216
|
+
def get_espg3857_bbox(
|
217
|
+
self, bbox: tuple[int, int, int, int] | None = None
|
218
|
+
) -> tuple[int, int, int, int]:
|
219
|
+
"""Converts the bounding box to EPSG:3857.
|
192
220
|
If the bounding box is not provided, the instance variable is used.
|
193
221
|
|
194
222
|
Args:
|
195
223
|
bbox (tuple[int, int, int, int], optional): The bounding box to convert.
|
196
224
|
|
197
225
|
Returns:
|
198
|
-
|
226
|
+
tuple[int, int, int, int]: The bounding box in EPSG:3857.
|
199
227
|
"""
|
200
228
|
bbox = bbox or self.bbox
|
201
229
|
north, south, east, west = bbox
|
@@ -203,4 +231,45 @@ class Component:
|
|
203
231
|
epsg3857_north, epsg3857_west = transformer.transform(north, west)
|
204
232
|
epsg3857_south, epsg3857_east = transformer.transform(south, east)
|
205
233
|
|
206
|
-
return
|
234
|
+
return epsg3857_north, epsg3857_south, epsg3857_east, epsg3857_west
|
235
|
+
|
236
|
+
def get_epsg3857_string(self, bbox: tuple[int, int, int, int] | None = None) -> str:
|
237
|
+
"""Converts the bounding box to EPSG:3857 string.
|
238
|
+
If the bounding box is not provided, the instance variable is used.
|
239
|
+
|
240
|
+
Args:
|
241
|
+
bbox (tuple[int, int, int, int], optional): The bounding box to convert.
|
242
|
+
|
243
|
+
Returns:
|
244
|
+
str: The bounding box in EPSG:3857 string.
|
245
|
+
"""
|
246
|
+
north, south, east, west = self.get_espg3857_bbox(bbox)
|
247
|
+
return f"{north},{south},{east},{west} [EPSG:3857]"
|
248
|
+
|
249
|
+
def create_qgis_scripts(
|
250
|
+
self, qgis_layers: list[tuple[str, float, float, float, float]]
|
251
|
+
) -> None:
|
252
|
+
"""Creates QGIS scripts from the given layers.
|
253
|
+
Each layer is a tuple where the first element is a name of the layer and the rest are the
|
254
|
+
bounding box coordinates in EPSG:3857.
|
255
|
+
For filenames, the class name is used as a prefix.
|
256
|
+
|
257
|
+
Args:
|
258
|
+
qgis_layers (list[tuple[str, float, float, float, float]]): The list of layers to
|
259
|
+
create scripts for.
|
260
|
+
"""
|
261
|
+
class_name = self.__class__.__name__.lower()
|
262
|
+
|
263
|
+
script_files = [
|
264
|
+
(f"{class_name}_bbox.py", get_bbox_template),
|
265
|
+
(f"{class_name}_rasterize.py", get_rasterize_template),
|
266
|
+
]
|
267
|
+
|
268
|
+
for script_file, process_function in script_files:
|
269
|
+
script_path = os.path.join(self.scripts_directory, script_file)
|
270
|
+
script_content = process_function(qgis_layers) # type: ignore
|
271
|
+
|
272
|
+
with open(script_path, "w", encoding="utf-8") as file:
|
273
|
+
file.write(script_content)
|
274
|
+
|
275
|
+
self.logger.info("QGIS script saved: %s", script_path)
|
maps4fs/generator/config.py
CHANGED
@@ -71,6 +71,8 @@ class Config(Component):
|
|
71
71
|
south, west, north, east = bbox
|
72
72
|
epsg3857_string = self.get_epsg3857_string(bbox=bbox)
|
73
73
|
|
74
|
+
self.qgis_sequence()
|
75
|
+
|
74
76
|
overview_data = {
|
75
77
|
"epsg3857_string": epsg3857_string,
|
76
78
|
"south": south,
|
@@ -86,3 +88,12 @@ class Config(Component):
|
|
86
88
|
}
|
87
89
|
|
88
90
|
return data # type: ignore
|
91
|
+
|
92
|
+
def qgis_sequence(self) -> None:
|
93
|
+
"""Generates QGIS scripts for creating bounding box layers and rasterizing them."""
|
94
|
+
bbox = self.get_bbox(height_distance=self.map_height, width_distance=self.map_width)
|
95
|
+
espg3857_bbox = self.get_espg3857_bbox(bbox=bbox)
|
96
|
+
|
97
|
+
qgis_layers = [("Overview_bbox", *espg3857_bbox)]
|
98
|
+
|
99
|
+
self.create_qgis_scripts(qgis_layers) # type: ignore
|
@@ -0,0 +1,114 @@
|
|
1
|
+
"""This module contains templates for generating QGIS scripts."""
|
2
|
+
|
3
|
+
BBOX_TEMPLATE = """
|
4
|
+
layers = [
|
5
|
+
{layers}
|
6
|
+
]
|
7
|
+
for layer in layers:
|
8
|
+
name = layer[0]
|
9
|
+
north, south, east, west = layer[1:]
|
10
|
+
|
11
|
+
# Create a rectangle geometry from the bounding box.
|
12
|
+
rect = QgsRectangle(north, east, south, west)
|
13
|
+
|
14
|
+
# Create a new memory layer to hold the bounding box.
|
15
|
+
layer = QgsVectorLayer("Polygon?crs=EPSG:3857", name, "memory")
|
16
|
+
provider = layer.dataProvider()
|
17
|
+
|
18
|
+
# Add the rectangle as a feature to the layer.
|
19
|
+
feature = QgsFeature()
|
20
|
+
feature.setGeometry(QgsGeometry.fromRect(rect))
|
21
|
+
provider.addFeatures([feature])
|
22
|
+
|
23
|
+
# Add the layer to the map.
|
24
|
+
QgsProject.instance().addMapLayer(layer)
|
25
|
+
|
26
|
+
# Set the fill opacity.
|
27
|
+
symbol = layer.renderer().symbol()
|
28
|
+
symbol_layer = symbol.symbolLayer(0)
|
29
|
+
|
30
|
+
# Set the stroke color and width.
|
31
|
+
symbol_layer.setStrokeColor(QColor(0, 255, 0))
|
32
|
+
symbol_layer.setStrokeWidth(0.2)
|
33
|
+
symbol_layer.setFillColor(QColor(0, 0, 255, 0))
|
34
|
+
layer.triggerRepaint()
|
35
|
+
"""
|
36
|
+
|
37
|
+
RASTERIZE_TEMPLATE = """
|
38
|
+
import processing
|
39
|
+
|
40
|
+
############################################################
|
41
|
+
####### ADD THE DIRECTORY FOR THE FILES TO SAVE HERE #######
|
42
|
+
############################################################
|
43
|
+
############### IT MUST END WITH A SLASH (/) ###############
|
44
|
+
############################################################
|
45
|
+
|
46
|
+
SAVE_DIR = "C:/Users/iwatk/OneDrive/Desktop/"
|
47
|
+
|
48
|
+
############################################################
|
49
|
+
|
50
|
+
layers = [
|
51
|
+
{layers}
|
52
|
+
]
|
53
|
+
|
54
|
+
for layer in layers:
|
55
|
+
name = layer[0]
|
56
|
+
north, south, east, west = layer[1:]
|
57
|
+
|
58
|
+
epsg3857_string = str(north) + "," + str(south) + "," + str(east) + "," + str(west) + " [EPSG:3857]"
|
59
|
+
file_path = SAVE_DIR + name + ".tif"
|
60
|
+
|
61
|
+
processing.run(
|
62
|
+
"native:rasterize",
|
63
|
+
{{
|
64
|
+
"EXTENT": epsg3857_string,
|
65
|
+
"EXTENT_BUFFER": 0,
|
66
|
+
"TILE_SIZE": 64,
|
67
|
+
"MAP_UNITS_PER_PIXEL": 1,
|
68
|
+
"MAKE_BACKGROUND_TRANSPARENT": False,
|
69
|
+
"MAP_THEME": None,
|
70
|
+
"LAYERS": None,
|
71
|
+
"OUTPUT": file_path,
|
72
|
+
}},
|
73
|
+
)
|
74
|
+
"""
|
75
|
+
|
76
|
+
|
77
|
+
def get_bbox_template(layers: list[tuple[str, float, float, float, float]]) -> str:
|
78
|
+
"""Returns a template for creating bounding box layers in QGIS.
|
79
|
+
|
80
|
+
Args:
|
81
|
+
layers (list[tuple[str, float, float, float, float]]): A list of tuples containing the
|
82
|
+
layer name and the bounding box coordinates.
|
83
|
+
|
84
|
+
Returns:
|
85
|
+
str: The template for creating bounding box layers in QGIS.
|
86
|
+
"""
|
87
|
+
return BBOX_TEMPLATE.format(
|
88
|
+
layers=",\n ".join(
|
89
|
+
[
|
90
|
+
f'("{name}", {north}, {south}, {east}, {west})'
|
91
|
+
for name, north, south, east, west in layers
|
92
|
+
]
|
93
|
+
)
|
94
|
+
)
|
95
|
+
|
96
|
+
|
97
|
+
def get_rasterize_template(layers: list[tuple[str, float, float, float, float]]) -> str:
|
98
|
+
"""Returns a template for rasterizing bounding box layers in QGIS.
|
99
|
+
|
100
|
+
Args:
|
101
|
+
layers (list[tuple[str, float, float, float, float]]): A list of tuples containing the
|
102
|
+
layer name and the bounding box coordinates.
|
103
|
+
|
104
|
+
Returns:
|
105
|
+
str: The template for rasterizing bounding box layers in QGIS.
|
106
|
+
"""
|
107
|
+
return RASTERIZE_TEMPLATE.format(
|
108
|
+
layers=",\n ".join(
|
109
|
+
[
|
110
|
+
f'("{name}", {north}, {south}, {east}, {west})'
|
111
|
+
for name, north, south, east, west in layers
|
112
|
+
]
|
113
|
+
)
|
114
|
+
)
|
maps4fs/generator/texture.py
CHANGED
@@ -167,14 +167,6 @@ class Texture(Component):
|
|
167
167
|
self.logger.debug("Map minimum coordinates (XxY): %s x %s.", self.minimum_x, self.minimum_y)
|
168
168
|
self.logger.debug("Map maximum coordinates (XxY): %s x %s.", self.maximum_x, self.maximum_y)
|
169
169
|
|
170
|
-
self.height = abs(north - south)
|
171
|
-
self.width = abs(east - west)
|
172
|
-
self.logger.info("Map dimensions (HxW): %s x %s.", self.height, self.width)
|
173
|
-
|
174
|
-
self.height_coef = self.height / self.map_height
|
175
|
-
self.width_coef = self.width / self.map_width
|
176
|
-
self.logger.debug("Map coefficients (HxW): %s x %s.", self.height_coef, self.width_coef)
|
177
|
-
|
178
170
|
def info_sequence(self) -> dict[str, Any]:
|
179
171
|
"""Returns the JSON representation of the generation info for textures."""
|
180
172
|
useful_attributes = [
|
@@ -186,10 +178,6 @@ class Texture(Component):
|
|
186
178
|
"minimum_y",
|
187
179
|
"maximum_x",
|
188
180
|
"maximum_y",
|
189
|
-
"height",
|
190
|
-
"width",
|
191
|
-
"height_coef",
|
192
|
-
"width_coef",
|
193
181
|
]
|
194
182
|
return {attr: getattr(self, attr, None) for attr in useful_attributes}
|
195
183
|
|
@@ -321,8 +309,7 @@ class Texture(Component):
|
|
321
309
|
Returns:
|
322
310
|
int: Relative X coordinate in map image.
|
323
311
|
"""
|
324
|
-
|
325
|
-
return int(raw_x * self.height_coef)
|
312
|
+
return int(self.map_width * (x - self.minimum_x) / (self.maximum_x - self.minimum_x))
|
326
313
|
|
327
314
|
def get_relative_y(self, y: float) -> int:
|
328
315
|
"""Converts UTM Y coordinate to relative Y coordinate in map image.
|
@@ -333,8 +320,7 @@ class Texture(Component):
|
|
333
320
|
Returns:
|
334
321
|
int: Relative Y coordinate in map image.
|
335
322
|
"""
|
336
|
-
|
337
|
-
return self.height - int(raw_y * self.width_coef)
|
323
|
+
return int(self.map_height * (1 - (y - self.minimum_y) / (self.maximum_y - self.minimum_y)))
|
338
324
|
|
339
325
|
# pylint: disable=W0613
|
340
326
|
def _to_np(self, geometry: shapely.geometry.polygon.Polygon, *args) -> np.ndarray:
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: maps4fs
|
3
|
-
Version: 0.9.
|
3
|
+
Version: 0.9.2
|
4
4
|
Summary: Generate map templates for Farming Simulator from real places.
|
5
5
|
Author-email: iwatkot <iwatkot@gmail.com>
|
6
6
|
License: MIT License
|
@@ -59,8 +59,8 @@ Requires-Dist: tifffile
|
|
59
59
|
🏞️ Generates height using SRTM dataset<br>
|
60
60
|
📦 Provides a ready-to-use map template for the Giants Editor<br>
|
61
61
|
🚜 Supports Farming Simulator 22 and 25<br>
|
62
|
-
🔷 Generates *.obj files for background terrain based on the real-world height map
|
63
|
-
📄 Generates
|
62
|
+
🔷 Generates *.obj files for background terrain based on the real-world height map<br>
|
63
|
+
📄 Generates scripts to download high-resolution satellite images from [QGIS](https://qgis.org/download/) in one click<br>
|
64
64
|
|
65
65
|
<p align="center">
|
66
66
|
<img src="https://github.com/user-attachments/assets/cf8f5752-9c69-4018-bead-290f59ba6976"><br>
|
@@ -266,10 +266,6 @@ Example of the `Texture` component:
|
|
266
266
|
"minimum_y": 5013940.540089059,
|
267
267
|
"maximum_x": 441233.5397821935,
|
268
268
|
"maximum_y": 5016006.074349126,
|
269
|
-
"height": 2065.5342600671574,
|
270
|
-
"width": 2072.295804702677,
|
271
|
-
"height_coef": 1.0085616504234167,
|
272
|
-
"width_coef": 1.011863185889979
|
273
269
|
},
|
274
270
|
```
|
275
271
|
|
@@ -282,12 +278,7 @@ And here's the list of the fields:
|
|
282
278
|
- `"minimum_x"` - the minimum x coordinate of the map (UTM projection),<br>
|
283
279
|
- `"minimum_y"` - the minimum y coordinate of the map (UTM projection),<br>
|
284
280
|
- `"maximum_x"` - the maximum x coordinate of the map (UTM projection),<br>
|
285
|
-
- `"maximum_y"` - the maximum y coordinate of the map (UTM projection)
|
286
|
-
- `"height"` - the height of the map in meters (it won't be equal to the parameters above since the Earth is not flat, sorry flat-earthers),<br>
|
287
|
-
- `"width"` - the width of the map in meters (same as above),<br>
|
288
|
-
- `"height_coef"` - since we need a texture of exact size, the height of the map is multiplied by this coefficient,<br>
|
289
|
-
- `"width_coef"` - same as above but for the width,<br>
|
290
|
-
- `"tile_name"` - the name of the SRTM tile which was used to generate the height map, e.g. "N52E013"<br>
|
281
|
+
- `"maximum_y"` - the maximum y coordinate of the map (UTM projection),
|
291
282
|
|
292
283
|
### Background
|
293
284
|
|
@@ -373,9 +364,9 @@ If you're willing to create a background terrain, you will need: Blender, the Bl
|
|
373
364
|
|
374
365
|
If you're afraid of this task, please don't be. It's really simple and I've prepaired detailed step-by-step instructions for you, you'll find them in the separate README files. Here are the steps you need to follow:
|
375
366
|
|
376
|
-
1. [Download high-resolution satellite images](README_satellite_images.md).
|
377
|
-
2. [Prepare the i3d files](README_i3d.md).
|
378
|
-
3. [Import the i3d files to Giants Editor](README_giants_editor.md).
|
367
|
+
1. [Download high-resolution satellite images](tutorials/README_satellite_images.md).
|
368
|
+
2. [Prepare the i3d files](tutorials/README_i3d.md).
|
369
|
+
3. [Import the i3d files to Giants Editor](tutorials/README_giants_editor.md).
|
379
370
|
|
380
371
|
## Overview image
|
381
372
|
The overview image is an image that is used as in-game map. No matter what the size of the map, this file is always `4096x4096 pixels`, while the region of your map is `2048x2048 pixels` in center of this file. The rest of the image is just here for nice view, but you still may add satellite pictures to this region.<br>
|
@@ -1,18 +1,19 @@
|
|
1
1
|
maps4fs/__init__.py,sha256=da4jmND2Ths9AffnkAKgzLHNkvKFOc_l21gJisPXqWY,155
|
2
2
|
maps4fs/logger.py,sha256=CneeHxQywjNUJXqQrUUSeiDxu95FfrfyK_Si1v0gMZ8,1477
|
3
3
|
maps4fs/generator/__init__.py,sha256=zZMLEkGzb4z0xql650gOtGSvcgX58DnJ2yN3vC2daRk,43
|
4
|
-
maps4fs/generator/background.py,sha256=
|
5
|
-
maps4fs/generator/component.py,sha256=
|
6
|
-
maps4fs/generator/config.py,sha256=
|
4
|
+
maps4fs/generator/background.py,sha256=2BUgn12t-FgijPTY7hvwTaYQrVzYdnZqhoz76KSBcKs,11216
|
5
|
+
maps4fs/generator/component.py,sha256=tLjjbrFn3v4CrUrUOgH9s8NuJhmQcBs74ShefkNg1VE,10584
|
6
|
+
maps4fs/generator/config.py,sha256=JL7leQv8C06JQOXIbgQ-jve2re7cNsx8vKa8dfbnxPM,3896
|
7
7
|
maps4fs/generator/dem.py,sha256=p7THncPUdYWtNR2HrTXe0bCuJ8psUV8rRpYPJkzL2gA,15220
|
8
8
|
maps4fs/generator/game.py,sha256=94HjPNOyy6XSSOnBp-uxrkBglKyC-X3ULIrrucfdlKw,6825
|
9
9
|
maps4fs/generator/i3d.py,sha256=UuQiQRusPQ2f6PvGKxJ_UZeXsx3uG15efmy8Ysnm3F8,3597
|
10
10
|
maps4fs/generator/map.py,sha256=BS8ylTCRlHRmbImg73wnHMpBB2ODckVyVZq5KJhCMfM,4236
|
11
11
|
maps4fs/generator/path_steps.py,sha256=rKslIiG9mriCVL9_0i8Oet2p0DITrpBWi0pECpvuyUM,2707
|
12
|
-
maps4fs/generator/
|
12
|
+
maps4fs/generator/qgis.py,sha256=k19miPEFyOdu_ogBFHmFVfYQ-IgF38ufJZ5DM5NSHBQ,3400
|
13
|
+
maps4fs/generator/texture.py,sha256=CwaXZfAG4e3D3YR7yVR2MC677EHpbUWTboCS3G6jkhk,17723
|
13
14
|
maps4fs/generator/tile.py,sha256=3vmfjQiPiiUZKPuIo5tg2rOKkgcP1NRVkMGK-Vo10-A,2138
|
14
|
-
maps4fs-0.9.
|
15
|
-
maps4fs-0.9.
|
16
|
-
maps4fs-0.9.
|
17
|
-
maps4fs-0.9.
|
18
|
-
maps4fs-0.9.
|
15
|
+
maps4fs-0.9.2.dist-info/LICENSE.md,sha256=-JY0v7p3dwXze61EbYiK7YEJ2aKrjaFZ8y2xYEOrmRY,1068
|
16
|
+
maps4fs-0.9.2.dist-info/METADATA,sha256=J9SVncLGsj5Le0QQu-mfSyrsQJc0EkO7tdDs1HFd8vQ,23427
|
17
|
+
maps4fs-0.9.2.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
18
|
+
maps4fs-0.9.2.dist-info/top_level.txt,sha256=Ue9DSRlejRQRCaJueB0uLcKrWwsEq9zezfv5dI5mV1M,8
|
19
|
+
maps4fs-0.9.2.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|