PyLibMS 4.3.2__tar.gz → 4.3.3__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.
- {pylibms-4.3.2 → pylibms-4.3.3}/PKG-INFO +1 -1
- {pylibms-4.3.2 → pylibms-4.3.3}/PyLibMS.egg-info/PKG-INFO +1 -1
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/common/lms_constants.py +2 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/common/stream/fileinfo.py +2 -2
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/flowchart/definitions/node.py +17 -10
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/flowchart/msbf.py +11 -4
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/flowchart/msbfio.py +3 -9
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/titleconfig/config.py +17 -10
- {pylibms-4.3.2 → pylibms-4.3.3}/pyproject.toml +1 -1
- {pylibms-4.3.2 → pylibms-4.3.3}/LICENSE +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/MANIFEST.in +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/PyLibMS.egg-info/SOURCES.txt +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/PyLibMS.egg-info/dependency_links.txt +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/PyLibMS.egg-info/requires.txt +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/PyLibMS.egg-info/top_level.txt +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/README.md +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/__init__.py +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/common/__init__.py +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/common/field/__init__.py +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/common/field/io.py +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/common/field/lms_datatype.py +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/common/field/lms_field.py +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/common/lms_exceptions.py +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/common/lms_fileinfo.py +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/common/stream/hashtable.py +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/common/stream/section.py +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/fileio/encoding.py +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/fileio/io.py +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/flowchart/__init__.py +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/flowchart/definitions/__init__.py +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/flowchart/definitions/flowchart.py +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/flowchart/definitions/lms_nodeexceptions.py +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/flowchart/definitions/node_type.py +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/flowchart/flw3.py +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/message/__init__.py +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/message/definitions/__init__.py +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/message/definitions/field/__init__.py +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/message/lms_messagetext.py +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/message/msbt.py +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/message/msbtentry.py +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/message/msbtio.py +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/message/section/__init__.py +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/message/section/atr1.py +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/message/section/nli1.py +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/message/section/tsy1.py +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/message/section/txt2.py +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/message/tag/__init__.py +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/message/tag/io/param_io.py +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/message/tag/io/tag_io.py +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/message/tag/lms_tag.py +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/message/tag/lms_tagexceptions.py +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/project/__init__.py +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/project/definitions/__init__.py +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/project/definitions/attribute.py +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/project/definitions/color.py +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/project/definitions/style.py +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/project/definitions/tag.py +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/project/msbp.py +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/project/msbpread.py +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/project/section/ali2.py +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/project/section/ati2.py +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/project/section/clr1.py +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/project/section/string.py +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/project/section/syl3.py +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/project/section/tag2.py +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/project/section/tgg2.py +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/project/section/tgp2.py +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/titleconfig/__init__.py +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/titleconfig/definitions/__init__.py +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/titleconfig/definitions/attribute.py +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/titleconfig/definitions/nodes.py +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/titleconfig/definitions/tags.py +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/titleconfig/definitions/value.py +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/titleconfig/presets/Badge Arcade.yaml +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/titleconfig/presets/Brain Age Concentration Training.yaml +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/titleconfig/presets/Kirby Planet Robobot.yaml +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/titleconfig/presets/Super Mario 3D Land.yaml +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/titleconfig/presets/Super Mario 3D World + Bowsers Fury.yaml +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/titleconfig/presets/Super Mario Odyssey.yaml +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/titleconfig/presets/The Legend of Zelda Echos of Wisdom.yaml +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/titleconfig/presets/The Legend of Zelda a Link Between Worlds.yaml +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/lms/titleconfig/presets/Tomodachi Life Living The Dream.yaml +0 -0
- {pylibms-4.3.2 → pylibms-4.3.3}/setup.cfg +0 -0
|
@@ -3,7 +3,7 @@ from lms.common.lms_constants import (
|
|
|
3
3
|
BIG_ENDIAN_BOM,
|
|
4
4
|
SECTION_DATA_START,
|
|
5
5
|
LITTLE_ENDIAN_BOM,
|
|
6
|
-
SIZE_OFFSET,
|
|
6
|
+
SIZE_OFFSET, LMS_MINIMUM_VERSION,
|
|
7
7
|
)
|
|
8
8
|
from lms.common.lms_fileinfo import LMS_FileInfo
|
|
9
9
|
from lms.fileio.encoding import FileEncoding
|
|
@@ -29,7 +29,7 @@ def read_file_info(reader: FileReader, expected_magic: str) -> LMS_FileInfo:
|
|
|
29
29
|
|
|
30
30
|
version = reader.read_uint8()
|
|
31
31
|
|
|
32
|
-
if version <
|
|
32
|
+
if version < LMS_MINIMUM_VERSION:
|
|
33
33
|
raise lms_exceptions.LMS_UnsupportedFileVersionError(
|
|
34
34
|
"Only version 3+ files are supported!"
|
|
35
35
|
)
|
|
@@ -185,7 +185,7 @@ class LMS_MessageNode(LMS_BaseNode):
|
|
|
185
185
|
|
|
186
186
|
@property
|
|
187
187
|
def msbt(self) -> MSBT | None:
|
|
188
|
-
"""MSBT instance the node references. Optional,
|
|
188
|
+
"""MSBT instance the node references. Optional, is set by providing a MSBT file on reading."""
|
|
189
189
|
return self._msbt
|
|
190
190
|
|
|
191
191
|
@property
|
|
@@ -313,26 +313,33 @@ class LMS_BranchNode(LMS_BaseNode):
|
|
|
313
313
|
case_map.setdefault(branch, []).append(case)
|
|
314
314
|
|
|
315
315
|
if self.definition is not None:
|
|
316
|
-
|
|
316
|
+
definition: NodeDefinition = self.definition
|
|
317
|
+
|
|
318
|
+
if definition.case_options:
|
|
317
319
|
for case, branch in self._branches.items():
|
|
318
|
-
|
|
319
|
-
case,
|
|
320
|
+
case_format = definition.case_options.get(
|
|
321
|
+
case, None,
|
|
320
322
|
)
|
|
321
323
|
|
|
322
|
-
|
|
324
|
+
if case_format is None:
|
|
325
|
+
formatted_message = f"Case {case}"
|
|
326
|
+
else:
|
|
327
|
+
formatted_message = self._format_case_message(case, case_format)
|
|
328
|
+
|
|
329
|
+
result.append(((case,), formatted_message, branch))
|
|
323
330
|
|
|
324
331
|
return result
|
|
325
332
|
|
|
326
|
-
if
|
|
333
|
+
if definition.case_format is not None:
|
|
327
334
|
if compress_shared_references:
|
|
328
335
|
for branch, cases in case_map.items():
|
|
329
336
|
case_message = self._format_case_message(
|
|
330
|
-
merge_shared_cases(cases)
|
|
337
|
+
merge_shared_cases(cases), definition.case_format
|
|
331
338
|
)
|
|
332
339
|
result.append((tuple(cases), case_message, branch))
|
|
333
340
|
else:
|
|
334
341
|
for case, branch in self._branches.items():
|
|
335
|
-
case_message = self._format_case_message(case)
|
|
342
|
+
case_message = self._format_case_message(case, definition.case_format)
|
|
336
343
|
result.append(((case,), case_message, branch))
|
|
337
344
|
|
|
338
345
|
return result
|
|
@@ -352,8 +359,8 @@ class LMS_BranchNode(LMS_BaseNode):
|
|
|
352
359
|
|
|
353
360
|
return result
|
|
354
361
|
|
|
355
|
-
def _format_case_message(self, case_prefix: str):
|
|
356
|
-
prefix = string.Template(
|
|
362
|
+
def _format_case_message(self, case_prefix: str, case_format: str):
|
|
363
|
+
prefix = string.Template(case_format)
|
|
357
364
|
|
|
358
365
|
# Unpack dict for formatting $case and $param formats
|
|
359
366
|
# Allows inserting parameter values dynamically into the case message
|
|
@@ -22,14 +22,17 @@ class MSBF:
|
|
|
22
22
|
"""
|
|
23
23
|
|
|
24
24
|
MAGIC = "MsgFlwBn"
|
|
25
|
-
|
|
26
25
|
DEFAULT_SLOT_COUNT = 59
|
|
27
26
|
|
|
28
27
|
def __init__(
|
|
29
28
|
self, info: LMS_FileInfo | None = None, flowcharts: list[LMS_Flowchart] = None
|
|
30
29
|
):
|
|
31
30
|
self._info = info if info is not None else LMS_FileInfo()
|
|
32
|
-
|
|
31
|
+
|
|
32
|
+
# While unlikely to vary, and have yet to find a file that changes the slot count (unlike MSBT)
|
|
33
|
+
# it is wiser to store an editable attribute just in case a game decides to vary the amount.
|
|
34
|
+
self.slot_count = MSBF.DEFAULT_SLOT_COUNT
|
|
35
|
+
|
|
33
36
|
self._flowcharts = flowcharts or []
|
|
34
37
|
self._nodes: dict[int, LMS_BaseNode] = {}
|
|
35
38
|
self._global_node_id = 0
|
|
@@ -77,7 +80,11 @@ class MSBF:
|
|
|
77
80
|
)
|
|
78
81
|
|
|
79
82
|
def get_flowchart_references(self, node_id: int) -> set[LMS_Flowchart]:
|
|
80
|
-
"""
|
|
83
|
+
"""
|
|
84
|
+
Determines which flowcharts contain this node.
|
|
85
|
+
|
|
86
|
+
:param node_id: The node to find references for.
|
|
87
|
+
"""
|
|
81
88
|
return {flowchart for flowchart in self._flowcharts if node_id in flowchart.nodes}
|
|
82
89
|
|
|
83
90
|
def register_node(self, node: LMS_BaseNode, flowchart: LMS_Flowchart = None) -> None:
|
|
@@ -85,7 +92,7 @@ class MSBF:
|
|
|
85
92
|
Registers a node to the MSBF instance.
|
|
86
93
|
|
|
87
94
|
:param node: The node to register.
|
|
88
|
-
:param flowchart:
|
|
95
|
+
:param flowchart: Optional argument that registers the node to that flowchart.
|
|
89
96
|
"""
|
|
90
97
|
if not isinstance(node, LMS_BaseNode):
|
|
91
98
|
raise TypeError(
|
|
@@ -59,13 +59,12 @@ def read_msbf(
|
|
|
59
59
|
file_info = read_file_info(reader, MSBF.MAGIC)
|
|
60
60
|
|
|
61
61
|
msbf = MSBF(file_info)
|
|
62
|
-
|
|
63
62
|
for magic, size in read_section_data(reader, file_info.section_count):
|
|
64
63
|
match magic:
|
|
65
64
|
case "FLW3":
|
|
66
65
|
entry_nodes = read_flw3(reader, config, msbt)
|
|
67
66
|
case "FEN1":
|
|
68
|
-
labels,
|
|
67
|
+
labels, slot_count = read_labels(reader)
|
|
69
68
|
case "REF1":
|
|
70
69
|
raise LMS_UnsupportedSectionError("""REF1 was found in the MSBF file! Please report this file as an issue
|
|
71
70
|
in the PyLibMS repository https://github.com/AbdyyEee/PylibMS""")
|
|
@@ -74,6 +73,7 @@ def read_msbf(
|
|
|
74
73
|
entry_nodes[i].flowchart_name = label
|
|
75
74
|
msbf.add_flowchart(label, entry_nodes[i])
|
|
76
75
|
|
|
76
|
+
msbf.slot_count = slot_count
|
|
77
77
|
return msbf
|
|
78
78
|
|
|
79
79
|
|
|
@@ -115,12 +115,6 @@ def write_msbf(file: MSBF) -> bytes:
|
|
|
115
115
|
# Saved here so ids aren't mutated in the current state
|
|
116
116
|
stream_ids = {node: stream_id for stream_id, node in enumerate(file.nodes.values())}
|
|
117
117
|
|
|
118
|
-
for chart in file:
|
|
119
|
-
if amount := len(chart.get_dangling_nodes()):
|
|
120
|
-
raise LMS_Error(
|
|
121
|
-
f"Unable to write the flowchart '{chart.name}'! There are {amount} dangling nodes."
|
|
122
|
-
)
|
|
123
|
-
|
|
124
118
|
index_map = {
|
|
125
119
|
flowchart.name: stream_ids[flowchart.entry_point] for flowchart in file
|
|
126
120
|
}
|
|
@@ -131,7 +125,7 @@ def write_msbf(file: MSBF) -> bytes:
|
|
|
131
125
|
"FEN1",
|
|
132
126
|
write_labels,
|
|
133
127
|
list(file.flowcharts.keys()),
|
|
134
|
-
|
|
128
|
+
file.slot_count,
|
|
135
129
|
index_map,
|
|
136
130
|
)
|
|
137
131
|
write_file_size(writer)
|
|
@@ -218,7 +218,7 @@ class TitleConfig:
|
|
|
218
218
|
game = parsed_content.get("game")
|
|
219
219
|
|
|
220
220
|
attribute_configs = {}
|
|
221
|
-
for config in parsed_content
|
|
221
|
+
for config in parsed_content.get(cls.ATTR_KEY, []):
|
|
222
222
|
definitions = [
|
|
223
223
|
ValueDefinition.from_dict(value_def)
|
|
224
224
|
for value_def in config["definitions"]
|
|
@@ -227,21 +227,28 @@ class TitleConfig:
|
|
|
227
227
|
config["name"], config.get("description", ""), definitions
|
|
228
228
|
)
|
|
229
229
|
|
|
230
|
+
tag_config = None
|
|
230
231
|
tag_definitions: dict[int, list[TagDefinition]] = {}
|
|
231
|
-
|
|
232
|
+
tag_content = parsed_content.get(cls.TAG_KEY, None)
|
|
232
233
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
if definition.group_id not in tag_definitions:
|
|
236
|
-
tag_definitions[definition.group_id] = []
|
|
237
|
-
tag_definitions[definition.group_id].append(definition)
|
|
234
|
+
if tag_content is not None:
|
|
235
|
+
group_map = tag_content["groups"]
|
|
238
236
|
|
|
239
|
-
|
|
237
|
+
for tag_def in tag_content["tags"]:
|
|
238
|
+
definition = TagDefinition.from_dict(tag_def, group_map)
|
|
239
|
+
if definition.group_id not in tag_definitions:
|
|
240
|
+
tag_definitions[definition.group_id] = []
|
|
241
|
+
tag_definitions[definition.group_id].append(definition)
|
|
242
|
+
|
|
243
|
+
tag_config = TagConfig(group_map, tag_definitions)
|
|
240
244
|
|
|
241
245
|
branch_nodes: dict[int, NodeDefinition | tuple[NodeDefinition, ...]] = {}
|
|
242
246
|
event_nodes: dict[int, tuple[NodeDefinition, ...]] = {}
|
|
243
247
|
|
|
244
|
-
|
|
248
|
+
node_data = parsed_content.get(cls.NODE_KEY, [])
|
|
249
|
+
branch_data, event_data = node_data.get("branch", []), node_data.get("event", [])
|
|
250
|
+
|
|
251
|
+
for definition in branch_data:
|
|
245
252
|
node_id = definition["id"]
|
|
246
253
|
|
|
247
254
|
node_definition = NodeDefinition.from_dict(
|
|
@@ -259,7 +266,7 @@ class TitleConfig:
|
|
|
259
266
|
else:
|
|
260
267
|
branch_nodes[node_id] = (existing, node_definition)
|
|
261
268
|
|
|
262
|
-
for definition in
|
|
269
|
+
for definition in event_data:
|
|
263
270
|
node_id = definition["id"]
|
|
264
271
|
|
|
265
272
|
node_definition = NodeDefinition.from_dict(
|
|
@@ -7,7 +7,7 @@ include = ["lms*"]
|
|
|
7
7
|
|
|
8
8
|
[project]
|
|
9
9
|
name = "PyLibMS"
|
|
10
|
-
version = "4.3.
|
|
10
|
+
version = "4.3.3"
|
|
11
11
|
requires-python = ">=3.10"
|
|
12
12
|
description = "Python library built for the libMessageStudio (LMS) proprietary file formats from Nintendo. Supports MSBT, MSBP, and MSBF."
|
|
13
13
|
readme = "README.md"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pylibms-4.3.2 → pylibms-4.3.3}/lms/titleconfig/presets/Brain Age Concentration Training.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pylibms-4.3.2 → pylibms-4.3.3}/lms/titleconfig/presets/Super Mario 3D World + Bowsers Fury.yaml
RENAMED
|
File without changes
|
|
File without changes
|
{pylibms-4.3.2 → pylibms-4.3.3}/lms/titleconfig/presets/The Legend of Zelda Echos of Wisdom.yaml
RENAMED
|
File without changes
|
|
File without changes
|
{pylibms-4.3.2 → pylibms-4.3.3}/lms/titleconfig/presets/Tomodachi Life Living The Dream.yaml
RENAMED
|
File without changes
|
|
File without changes
|