koro 2.0.2__py3-none-any.whl → 2.0.3rc1__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
koro/py.typed ADDED
File without changes
koro/slot/bin.py CHANGED
@@ -5,7 +5,6 @@ from ..stage import Stage
5
5
  from .file import FileSlot
6
6
  from .xml import XmlSlot
7
7
 
8
-
9
8
  __all__ = ["BinSlot"]
10
9
 
11
10
 
koro/slot/save.py CHANGED
@@ -1,12 +1,11 @@
1
+ from collections.abc import Mapping, Sequence
1
2
  from enum import Enum, unique
2
3
  from io import BytesIO
3
4
  from operator import index as ix
4
5
  from os.path import basename, dirname, join
5
- from typing import TYPE_CHECKING, Annotated, Any, Literal, SupportsIndex
6
- from collections.abc import Mapping, Sequence
6
+ from typing import TYPE_CHECKING, Annotated, Any, Final, Literal, SupportsIndex
7
7
 
8
8
  from ..stage import Stage
9
-
10
9
  from . import Slot
11
10
  from .xml import XmlSlot
12
11
 
@@ -18,6 +17,8 @@ else:
18
17
 
19
18
  __all__ = ["EditorPage", "get_slots", "SaveSlot"]
20
19
 
20
+ _SIZE_LIMIT: Final[int] = 156864
21
+
21
22
 
22
23
  @unique
23
24
  class EditorPage(Enum):
@@ -30,7 +31,7 @@ class SaveSlot(Slot):
30
31
  __match_args__ = ("path", "page", "index")
31
32
  __slots__ = ("_offset", "_path")
32
33
 
33
- _offset: Literal[8, 156392, 312776, 469160]
34
+ _offset: Literal[8, 156872, 313736, 470600]
34
35
  _path: str | bytes
35
36
 
36
37
  def __init__(
@@ -45,8 +46,8 @@ class SaveSlot(Slot):
45
46
  ],
46
47
  ) -> None:
47
48
  index = ix(index) - 1
48
- if index in range(0, 20):
49
- self._offset = 8 + 156864 * (index & 3) # type: ignore[assignment]
49
+ if index in range(20):
50
+ self._offset = 8 + _SIZE_LIMIT * (index & 3) # type: ignore[assignment]
50
51
  self._path = join(path, f"ed{(index >> 2) + 5 * page.value:02}.dat") # type: ignore[arg-type]
51
52
  else:
52
53
  raise ValueError("index must be between 1 and 20")
@@ -72,7 +73,7 @@ class SaveSlot(Slot):
72
73
  def index(
73
74
  self,
74
75
  ) -> Literal[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]:
75
- return (int(basename(self._path)[2:4]) % 5 >> 2 | self._offset // 156864) + 1 # type: ignore[return-value]
76
+ return (int(basename(self._path)[2:4]) % 5 >> 2 | self._offset // _SIZE_LIMIT) + 1 # type: ignore[return-value]
76
77
 
77
78
  def load(self) -> Stage | None:
78
79
  try:
@@ -82,10 +83,8 @@ class SaveSlot(Slot):
82
83
  block: bytearray = bytearray()
83
84
  while True:
84
85
  block.clear()
85
- block.extend(f.read1())
86
- if len(b.getbuffer()) + len(block) > 156864:
87
- del block[156864 - len(b.getbuffer()) :]
88
- if block[-1]:
86
+ block.extend(f.read1(_SIZE_LIMIT - len(b.getbuffer())))
87
+ if block and block[-1]:
89
88
  b.write(block)
90
89
  else:
91
90
  while block:
@@ -115,11 +114,13 @@ class SaveSlot(Slot):
115
114
 
116
115
  def save(self, data: Stage | None) -> None:
117
116
  binary: bytes = b"" if data is None else XmlSlot.serialize(data)
118
- if len(binary) > 156864:
117
+ if len(binary) > _SIZE_LIMIT:
119
118
  raise ValueError("serialized stage data is too large to save")
120
119
  try:
121
120
  with open(self._path, "xb") as f:
122
- f.write(bytes(638976))
121
+ f.write(
122
+ bytes(638976)
123
+ ) # Weird. Would expect this to be 627464 (8 + 4 * (_SIZE_LIMIT))
123
124
  if data is None:
124
125
  return
125
126
  except FileExistsError:
@@ -127,7 +128,7 @@ class SaveSlot(Slot):
127
128
  with open(self._path, "r+b") as f:
128
129
  f.seek(self._offset)
129
130
  f.write(binary)
130
- f.write(bytes(156864 - len(binary)))
131
+ f.write(bytes(_SIZE_LIMIT - len(binary)))
131
132
 
132
133
 
133
134
  def get_slots(save: StrOrBytesPath, /) -> Mapping[EditorPage, Sequence[SaveSlot]]:
koro/slot/xml.py CHANGED
@@ -12,7 +12,6 @@ from ..stage.part import (
12
12
  BasePart,
13
13
  BlinkingTile,
14
14
  Bumper,
15
- TextBox,
16
15
  Cannon,
17
16
  ConveyorBelt,
18
17
  DashTunnel,
@@ -41,6 +40,7 @@ from ..stage.part import (
41
40
  Speed,
42
41
  Spring,
43
42
  Start,
43
+ TextBox,
44
44
  Thorn,
45
45
  TimedDevice,
46
46
  ToyTrain,
koro/stage/model.py CHANGED
@@ -1,7 +1,6 @@
1
1
  from enum import Enum, unique
2
2
  from typing import TypeAlias
3
3
 
4
-
5
4
  __all__ = ["DecorationModel", "DeviceModel", "Model", "PartModel"]
6
5
 
7
6
 
koro/stage/part.py CHANGED
@@ -2,14 +2,13 @@ from __future__ import annotations
2
2
 
3
3
  from abc import ABC, abstractmethod
4
4
  from collections.abc import Iterable, MutableSequence
5
- from enum import Enum, unique, Flag
5
+ from enum import Enum, Flag, unique
6
6
  from operator import index
7
7
  from sys import maxsize
8
8
  from typing import Any, Final, Iterator, Literal, Self, SupportsIndex, overload
9
9
 
10
10
  from .model import DecorationModel, DeviceModel, PartModel
11
11
 
12
-
13
12
  __all__ = [
14
13
  "Ant",
15
14
  "BasePart",
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: koro
3
- Version: 2.0.2
3
+ Version: 2.0.3rc1
4
4
  Summary: Tools for manipulating levels made in Marble Saga: Kororinpa
5
5
  Home-page: https://github.com/DigitalDetective47/koro
6
6
  Author: DigitalDetective47
@@ -14,6 +14,7 @@ Classifier: Programming Language :: Python :: 3
14
14
  Classifier: Programming Language :: Python :: 3 :: Only
15
15
  Classifier: Programming Language :: Python :: 3.11
16
16
  Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
17
18
  Classifier: Topic :: File Formats
18
19
  Classifier: Topic :: Games/Entertainment
19
20
  Classifier: Typing :: Typed
@@ -0,0 +1,15 @@
1
+ koro/__init__.py,sha256=5_P8Q_L1Jo-bqMmzAK9tPKkmaSffbuid16voHwj8vys,192
2
+ koro/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
+ koro/slot/__init__.py,sha256=YJ3FjOF4o1Vo8joMpLTw27-Dwaoxq5YfQSER-ymJjFE,398
4
+ koro/slot/bin.py,sha256=Q0vKE5hTzGIGER-kpZnRykA3oAkXaK6uSAibS5Y1gBM,6527
5
+ koro/slot/file.py,sha256=QxBIXzFqzT6mzVZ5bq8xeR8vWfcNFpjHzsEEEqSzlz4,1656
6
+ koro/slot/save.py,sha256=vgkwqwbB46FK7jS6aMXrtPwksqOZsBsGRhBCyhdPRAg,4514
7
+ koro/slot/xml.py,sha256=TXogt9AlR93_jG63j2fv3AeEbkB4D8xp3CE1OI_2OjA,42147
8
+ koro/stage/__init__.py,sha256=xdMGSuI4fNDVSSHnuSwMyzFVyRxpcsSDxCl0EQWGJJM,2448
9
+ koro/stage/model.py,sha256=ZxmuKceendBqtVgmkJUYwbVzb7lGGhSoeCumgx3zwuQ,8428
10
+ koro/stage/part.py,sha256=QE7BFltmhm2pTQKjMrH0bxMj5h5Z8neOxxQEMd6RDGw,46885
11
+ koro-2.0.3rc1.dist-info/LICENSE,sha256=awOCsWJ58m_2kBQwBUGWejVqZm6wuRtCL2hi9rfa0X4,1211
12
+ koro-2.0.3rc1.dist-info/METADATA,sha256=o2UW06QyTHlCHMJkyD2QqPVh43KCwhCvCbsSOMjRjC4,4408
13
+ koro-2.0.3rc1.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
14
+ koro-2.0.3rc1.dist-info/top_level.txt,sha256=Msq6ssMwv56hnBQqwaTdJJkxM7x7BZ-3JfQbkepQAEY,5
15
+ koro-2.0.3rc1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (70.3.0)
2
+ Generator: setuptools (75.8.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,14 +0,0 @@
1
- koro/__init__.py,sha256=5_P8Q_L1Jo-bqMmzAK9tPKkmaSffbuid16voHwj8vys,192
2
- koro/slot/__init__.py,sha256=YJ3FjOF4o1Vo8joMpLTw27-Dwaoxq5YfQSER-ymJjFE,398
3
- koro/slot/bin.py,sha256=KaspkI3MZAoUTkVD8cSNP8sjn_ZI9U7qLt885zEK5C0,6528
4
- koro/slot/file.py,sha256=QxBIXzFqzT6mzVZ5bq8xeR8vWfcNFpjHzsEEEqSzlz4,1656
5
- koro/slot/save.py,sha256=ng1lCfUunJxsok9Isux2sRfth3VbB8vRvcpz4zDIelM,4450
6
- koro/slot/xml.py,sha256=evjIx-egPC43HqMCtBmmrjggyZ3xjERquqhaSIFQz0I,42147
7
- koro/stage/__init__.py,sha256=xdMGSuI4fNDVSSHnuSwMyzFVyRxpcsSDxCl0EQWGJJM,2448
8
- koro/stage/model.py,sha256=JNN6xT9o-47oTETu0_bWZpVBPOm2xkRgItKnREExbHo,8429
9
- koro/stage/part.py,sha256=zo2uxQ6QccG3Ja7sos6IUiwnjvXJDFoWRcTbUVXeQ5E,46886
10
- koro-2.0.2.dist-info/LICENSE,sha256=awOCsWJ58m_2kBQwBUGWejVqZm6wuRtCL2hi9rfa0X4,1211
11
- koro-2.0.2.dist-info/METADATA,sha256=fhMg_HIOEOu69Q0bjpExNDLIWqMx0l0pD4PpR2VkOvE,4354
12
- koro-2.0.2.dist-info/WHEEL,sha256=Z4pYXqR_rTB7OWNDYFOm1qRk0RX6GFP2o8LgvP453Hk,91
13
- koro-2.0.2.dist-info/top_level.txt,sha256=Msq6ssMwv56hnBQqwaTdJJkxM7x7BZ-3JfQbkepQAEY,5
14
- koro-2.0.2.dist-info/RECORD,,