From df09599d6bb09a01c8e6ec65fd0127467f3bbb9d Mon Sep 17 00:00:00 2001 From: PREMIEREHELL <88470674+PREMIEREHELL@users.noreply.github.com> Date: Tue, 4 Jun 2024 13:44:01 -0700 Subject: [PATCH 1/6] Ready Java Lighting the game will recalculate the light levels for (19w08b) 1934 <= 1.14 => 1.21 --- amulet/level/formats/anvil_world/format.py | 32 +++++++++++------ .../interfaces/chunk/anvil/anvil_1934.py | 34 +++++++++++++++++++ .../interfaces/chunk/anvil/anvil_2844.py | 2 +- 3 files changed, 57 insertions(+), 11 deletions(-) diff --git a/amulet/level/formats/anvil_world/format.py b/amulet/level/formats/anvil_world/format.py index b760640d2..77c506901 100644 --- a/amulet/level/formats/anvil_world/format.py +++ b/amulet/level/formats/anvil_world/format.py @@ -495,12 +495,12 @@ def pre_save_operation( except StopIteration as e: height_changed = e.value - # light = self._calculate_light(level, changed_chunks) - # try: - # while True: - # yield next(light) / 2 - # except StopIteration as e: - # light_changed = e.value + light = self._calculate_light(level, changed_chunks) + try: + while True: + yield next(light) / 2 + except StopIteration as e: + light_changed = e.value return height_changed # or light_changed @@ -539,11 +539,24 @@ def _calculate_light( changed = False if level.level_wrapper.version < 1934: # the version may be less than 1934 but is at least 1924 - # calculate the light values + # TODO need to calculate the light values for 1,12 > 1.13. + # for i, (dimension, cx, cz) in enumerate(chunks): + # try: + # chunk = level.get_chunk(cx, cz, dimension) + # except ChunkLoadError: + # pass + # else: + # changed_ = False + # changed_ |= chunk.misc.pop("block_light", None) is not None + # changed_ |= chunk.misc.pop("sky_light", None) is not None + # if changed_: + # changed = True + # chunk.changed = True + # yield i / chunk_count pass - # TODO else: # the game will recalculate the light levels + # applies to versions (19w08b) 1934 to 3949 (1.21.Pre2) for i, (dimension, cx, cz) in enumerate(chunks): try: chunk = level.get_chunk(cx, cz, dimension) @@ -551,8 +564,7 @@ def _calculate_light( pass else: changed_ = False - changed_ |= chunk.misc.pop("block_light", None) is not None - changed_ |= chunk.misc.pop("sky_light", None) is not None + changed_ |= chunk.misc.pop("isLightOn", None) is not None if changed_: changed = True chunk.changed = True diff --git a/amulet/level/interfaces/chunk/anvil/anvil_1934.py b/amulet/level/interfaces/chunk/anvil/anvil_1934.py index bb13f74d7..b19bd0b68 100644 --- a/amulet/level/interfaces/chunk/anvil/anvil_1934.py +++ b/amulet/level/interfaces/chunk/anvil/anvil_1934.py @@ -1,17 +1,51 @@ from __future__ import annotations +from typing import List, Tuple, TYPE_CHECKING + +if TYPE_CHECKING: + from amulet.api.chunk import Chunk + +from amulet_nbt import CompoundTag, ByteTag + +from .base_anvil_interface import ChunkDataType, ChunkPathType + from .anvil_1912 import Anvil1912Interface as ParentInterface class Anvil1934Interface(ParentInterface): + isLightOn: ChunkPathType = ( + "region", + [("Level", CompoundTag), ("isLightOn", ByteTag)], + ByteTag, + ) """ Made lighting optional + Made game recalculate lighting """ def __init__(self): super().__init__() self._set_feature("light_optional", "true") + self._register_decoder(self._decode_islighton) + self._register_encoder(self._encode_islighton) + + def _decode_islighton( + self, chunk: Chunk, data: ChunkDataType, floor_cy: int, height_cy: int + ): + chunk.misc["isLightOn"] = self.get_layer_obj( + data, self.isLightOn, pop_last=True + ) + + def _encode_islighton( + self, chunk: Chunk, data: ChunkDataType, floor_cy: int, height_cy: int + ): + self.set_layer_obj( + data, + self.isLightOn, + chunk.misc.get("isLightOn", None), + ) + @staticmethod def minor_is_valid(key: int): return 1934 <= key < 2203 diff --git a/amulet/level/interfaces/chunk/anvil/anvil_2844.py b/amulet/level/interfaces/chunk/anvil/anvil_2844.py index 6c21c0018..24991e7a9 100644 --- a/amulet/level/interfaces/chunk/anvil/anvil_2844.py +++ b/amulet/level/interfaces/chunk/anvil/anvil_2844.py @@ -57,7 +57,7 @@ class Anvil2844Interface(ParentInterface): OldLevel: ChunkPathType = ("region", [("Level", CompoundTag)], CompoundTag) Level: ChunkPathType = ("region", [], CompoundTag) Sections: ChunkPathType = ("region", [("sections", ListTag)], ListTag) - + isLightOn: ChunkPathType = ("region", [("isLightOn", ByteTag)], ByteTag) Entities: ChunkPathType = ("region", [("entities", ListTag)], ListTag) BlockEntities: ChunkPathType = ("region", [("block_entities", ListTag)], ListTag) BlockTicks: ChunkPathType = ("region", [("block_ticks", ListTag)], ListTag) From 16b063564d43441aa2d9ed83d0088b85600f84d1 Mon Sep 17 00:00:00 2001 From: PREMIEREHELL <88470674+PREMIEREHELL@users.noreply.github.com> Date: Tue, 4 Jun 2024 16:30:18 -0700 Subject: [PATCH 2/6] Fixed a typo, bug [Bug report] #286 --- amulet/level/interfaces/chunk/anvil/anvil_na.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/amulet/level/interfaces/chunk/anvil/anvil_na.py b/amulet/level/interfaces/chunk/anvil/anvil_na.py index b180bf5de..57c528dd6 100644 --- a/amulet/level/interfaces/chunk/anvil/anvil_na.py +++ b/amulet/level/interfaces/chunk/anvil/anvil_na.py @@ -537,7 +537,7 @@ def _encode_ticks(ticks: Dict[BlockCoordinates, Tuple[str, int, int]]) -> ListTa "t": IntTag(t), "x": IntTag(x), "y": IntTag(y), - "z": IntTag(x), + "z": IntTag(z), } ) ) From d94ce7199396e326ebf6bcd0fc5be0bd591a2614 Mon Sep 17 00:00:00 2001 From: PREMIEREHELL <88470674+PREMIEREHELL@users.noreply.github.com> Date: Wed, 5 Jun 2024 05:24:49 -0700 Subject: [PATCH 3/6] Revert "Fixed a typo, bug [Bug report] #286" This reverts commit 16b063564d43441aa2d9ed83d0088b85600f84d1. --- amulet/level/interfaces/chunk/anvil/anvil_na.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/amulet/level/interfaces/chunk/anvil/anvil_na.py b/amulet/level/interfaces/chunk/anvil/anvil_na.py index 57c528dd6..b180bf5de 100644 --- a/amulet/level/interfaces/chunk/anvil/anvil_na.py +++ b/amulet/level/interfaces/chunk/anvil/anvil_na.py @@ -537,7 +537,7 @@ def _encode_ticks(ticks: Dict[BlockCoordinates, Tuple[str, int, int]]) -> ListTa "t": IntTag(t), "x": IntTag(x), "y": IntTag(y), - "z": IntTag(z), + "z": IntTag(x), } ) ) From 10b481bee6b1cfe4fde81cf725a658ab67658c56 Mon Sep 17 00:00:00 2001 From: PREMIEREHELL <88470674+PREMIEREHELL@users.noreply.github.com> Date: Wed, 5 Jun 2024 08:52:00 -0700 Subject: [PATCH 4/6] Updated Fixed this issue where it always evaluates to true and adds the tag. I think its better to set the value to 0 than to remove the tag, --- amulet/level/formats/anvil_world/format.py | 2 +- amulet/level/interfaces/chunk/anvil/anvil_1934.py | 14 ++++++-------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/amulet/level/formats/anvil_world/format.py b/amulet/level/formats/anvil_world/format.py index 77c506901..3f04c3cfe 100644 --- a/amulet/level/formats/anvil_world/format.py +++ b/amulet/level/formats/anvil_world/format.py @@ -564,7 +564,7 @@ def _calculate_light( pass else: changed_ = False - changed_ |= chunk.misc.pop("isLightOn", None) is not None + changed_ |= chunk.misc.get("isLightOn", None) is not None if changed_: changed = True chunk.changed = True diff --git a/amulet/level/interfaces/chunk/anvil/anvil_1934.py b/amulet/level/interfaces/chunk/anvil/anvil_1934.py index b19bd0b68..1c4f6722a 100644 --- a/amulet/level/interfaces/chunk/anvil/anvil_1934.py +++ b/amulet/level/interfaces/chunk/anvil/anvil_1934.py @@ -33,18 +33,16 @@ def __init__(self): def _decode_islighton( self, chunk: Chunk, data: ChunkDataType, floor_cy: int, height_cy: int ): - chunk.misc["isLightOn"] = self.get_layer_obj( - data, self.isLightOn, pop_last=True - ) + if self.get_layer_obj(data, self.isLightOn) == ByteTag(1): + chunk.misc["isLightOn"] = self.get_layer_obj( + data, self.isLightOn, pop_last=True + ) def _encode_islighton( self, chunk: Chunk, data: ChunkDataType, floor_cy: int, height_cy: int ): - self.set_layer_obj( - data, - self.isLightOn, - chunk.misc.get("isLightOn", None), - ) + if chunk.misc.get("isLightOn", None): + self.set_layer_obj(data, self.isLightOn, ByteTag(0)) @staticmethod def minor_is_valid(key: int): From f37b2314a1622b0723329a21834b918d82c1bd7f Mon Sep 17 00:00:00 2001 From: PREMIEREHELL <88470674+PREMIEREHELL@users.noreply.github.com> Date: Tue, 4 Jun 2024 13:44:01 -0700 Subject: [PATCH 5/6] Ready Java Lighting the game will recalculate the light levels for (19w08b) 1934 <= 1.14 => 1.21 Fixed a typo, bug [Bug report] #286 Updated Fixed this issue where it always evaluates to true and adds the tag. I think its better to set the value to 0 than to remove the tag, Revert "Fixed a typo, bug [Bug report] #286" This reverts commit 16b063564d43441aa2d9ed83d0088b85600f84d1. --- amulet/level/formats/anvil_world/format.py | 32 +++++++++++++------ .../interfaces/chunk/anvil/anvil_1934.py | 32 +++++++++++++++++++ .../interfaces/chunk/anvil/anvil_2844.py | 2 +- 3 files changed, 55 insertions(+), 11 deletions(-) diff --git a/amulet/level/formats/anvil_world/format.py b/amulet/level/formats/anvil_world/format.py index b760640d2..3f04c3cfe 100644 --- a/amulet/level/formats/anvil_world/format.py +++ b/amulet/level/formats/anvil_world/format.py @@ -495,12 +495,12 @@ def pre_save_operation( except StopIteration as e: height_changed = e.value - # light = self._calculate_light(level, changed_chunks) - # try: - # while True: - # yield next(light) / 2 - # except StopIteration as e: - # light_changed = e.value + light = self._calculate_light(level, changed_chunks) + try: + while True: + yield next(light) / 2 + except StopIteration as e: + light_changed = e.value return height_changed # or light_changed @@ -539,11 +539,24 @@ def _calculate_light( changed = False if level.level_wrapper.version < 1934: # the version may be less than 1934 but is at least 1924 - # calculate the light values + # TODO need to calculate the light values for 1,12 > 1.13. + # for i, (dimension, cx, cz) in enumerate(chunks): + # try: + # chunk = level.get_chunk(cx, cz, dimension) + # except ChunkLoadError: + # pass + # else: + # changed_ = False + # changed_ |= chunk.misc.pop("block_light", None) is not None + # changed_ |= chunk.misc.pop("sky_light", None) is not None + # if changed_: + # changed = True + # chunk.changed = True + # yield i / chunk_count pass - # TODO else: # the game will recalculate the light levels + # applies to versions (19w08b) 1934 to 3949 (1.21.Pre2) for i, (dimension, cx, cz) in enumerate(chunks): try: chunk = level.get_chunk(cx, cz, dimension) @@ -551,8 +564,7 @@ def _calculate_light( pass else: changed_ = False - changed_ |= chunk.misc.pop("block_light", None) is not None - changed_ |= chunk.misc.pop("sky_light", None) is not None + changed_ |= chunk.misc.get("isLightOn", None) is not None if changed_: changed = True chunk.changed = True diff --git a/amulet/level/interfaces/chunk/anvil/anvil_1934.py b/amulet/level/interfaces/chunk/anvil/anvil_1934.py index bb13f74d7..1c4f6722a 100644 --- a/amulet/level/interfaces/chunk/anvil/anvil_1934.py +++ b/amulet/level/interfaces/chunk/anvil/anvil_1934.py @@ -1,17 +1,49 @@ from __future__ import annotations +from typing import List, Tuple, TYPE_CHECKING + +if TYPE_CHECKING: + from amulet.api.chunk import Chunk + +from amulet_nbt import CompoundTag, ByteTag + +from .base_anvil_interface import ChunkDataType, ChunkPathType + from .anvil_1912 import Anvil1912Interface as ParentInterface class Anvil1934Interface(ParentInterface): + isLightOn: ChunkPathType = ( + "region", + [("Level", CompoundTag), ("isLightOn", ByteTag)], + ByteTag, + ) """ Made lighting optional + Made game recalculate lighting """ def __init__(self): super().__init__() self._set_feature("light_optional", "true") + self._register_decoder(self._decode_islighton) + self._register_encoder(self._encode_islighton) + + def _decode_islighton( + self, chunk: Chunk, data: ChunkDataType, floor_cy: int, height_cy: int + ): + if self.get_layer_obj(data, self.isLightOn) == ByteTag(1): + chunk.misc["isLightOn"] = self.get_layer_obj( + data, self.isLightOn, pop_last=True + ) + + def _encode_islighton( + self, chunk: Chunk, data: ChunkDataType, floor_cy: int, height_cy: int + ): + if chunk.misc.get("isLightOn", None): + self.set_layer_obj(data, self.isLightOn, ByteTag(0)) + @staticmethod def minor_is_valid(key: int): return 1934 <= key < 2203 diff --git a/amulet/level/interfaces/chunk/anvil/anvil_2844.py b/amulet/level/interfaces/chunk/anvil/anvil_2844.py index 6c21c0018..24991e7a9 100644 --- a/amulet/level/interfaces/chunk/anvil/anvil_2844.py +++ b/amulet/level/interfaces/chunk/anvil/anvil_2844.py @@ -57,7 +57,7 @@ class Anvil2844Interface(ParentInterface): OldLevel: ChunkPathType = ("region", [("Level", CompoundTag)], CompoundTag) Level: ChunkPathType = ("region", [], CompoundTag) Sections: ChunkPathType = ("region", [("sections", ListTag)], ListTag) - + isLightOn: ChunkPathType = ("region", [("isLightOn", ByteTag)], ByteTag) Entities: ChunkPathType = ("region", [("entities", ListTag)], ListTag) BlockEntities: ChunkPathType = ("region", [("block_entities", ListTag)], ListTag) BlockTicks: ChunkPathType = ("region", [("block_ticks", ListTag)], ListTag) From bbf2eecb93cb7bedb2f8fe95889a83d5ad857025 Mon Sep 17 00:00:00 2001 From: PREMIEREHELL <88470674+PREMIEREHELL@users.noreply.github.com> Date: Thu, 6 Jun 2024 17:47:36 -0700 Subject: [PATCH 6/6] This should work this will update only the chunks that have the isLightOn tag set to 1 , --- amulet/api/chunk/chunk.py | 15 ++++- amulet/level/formats/anvil_world/format.py | 3 +- .../interfaces/chunk/anvil/anvil_1934.py | 62 +++++++++++-------- 3 files changed, 51 insertions(+), 29 deletions(-) diff --git a/amulet/api/chunk/chunk.py b/amulet/api/chunk/chunk.py index fb9eb8536..ba0775a48 100644 --- a/amulet/api/chunk/chunk.py +++ b/amulet/api/chunk/chunk.py @@ -45,7 +45,7 @@ def __init__(self, cx: int, cz: int): self._block_entities = BlockEntityDict() self._status = Status() self._misc = {} # all entries that are not important enough to get an attribute - + self._set_light_off = False # TODO: remove these variables. They are temporary until the translator supports entities self._native_version: VersionIdentifierType = ("java", 0) self._native_entities = EntityList() @@ -69,6 +69,7 @@ def pickle(self) -> bytes: tuple(self._block_entities.data.values()), self._status.value, self.misc, + self.set_light_off, self._native_entities, self._native_version, ) @@ -98,6 +99,7 @@ def unpickle( self.block_entities, self.status, self.misc, + self.set_light_off, self._native_entities, self._native_version, ) = chunk_data[3:] @@ -387,3 +389,14 @@ def misc(self) -> dict: def misc(self, misc: dict): assert isinstance(misc, dict), "misc must be a dictionary." self._misc = misc + + @property + def set_light_off(self) -> bool: + """ + A Boolean for isLightOn tag. + """ + return self._set_light_off + + @set_light_off.setter + def set_light_off(self, set_light_off: bool): + self._set_light_off = set_light_off diff --git a/amulet/level/formats/anvil_world/format.py b/amulet/level/formats/anvil_world/format.py index 3f04c3cfe..dc747a4e9 100644 --- a/amulet/level/formats/anvil_world/format.py +++ b/amulet/level/formats/anvil_world/format.py @@ -564,10 +564,11 @@ def _calculate_light( pass else: changed_ = False - changed_ |= chunk.misc.get("isLightOn", None) is not None + changed_ |= chunk.set_light_off if changed_: changed = True chunk.changed = True + yield i / chunk_count return changed diff --git a/amulet/level/interfaces/chunk/anvil/anvil_1934.py b/amulet/level/interfaces/chunk/anvil/anvil_1934.py index 1c4f6722a..766e74418 100644 --- a/amulet/level/interfaces/chunk/anvil/anvil_1934.py +++ b/amulet/level/interfaces/chunk/anvil/anvil_1934.py @@ -23,30 +23,38 @@ class Anvil1934Interface(ParentInterface): Made game recalculate lighting """ - def __init__(self): - super().__init__() - self._set_feature("light_optional", "true") - - self._register_decoder(self._decode_islighton) - self._register_encoder(self._encode_islighton) - - def _decode_islighton( - self, chunk: Chunk, data: ChunkDataType, floor_cy: int, height_cy: int - ): - if self.get_layer_obj(data, self.isLightOn) == ByteTag(1): - chunk.misc["isLightOn"] = self.get_layer_obj( - data, self.isLightOn, pop_last=True - ) - - def _encode_islighton( - self, chunk: Chunk, data: ChunkDataType, floor_cy: int, height_cy: int - ): - if chunk.misc.get("isLightOn", None): - self.set_layer_obj(data, self.isLightOn, ByteTag(0)) - - @staticmethod - def minor_is_valid(key: int): - return 1934 <= key < 2203 - - -export = Anvil1934Interface + class Anvil1934Interface(ParentInterface): + isLightOn: ChunkPathType = ( + "region", + [("Level", CompoundTag), ("isLightOn", ByteTag)], + ByteTag, + ) + """ + Made game recalulate lighting + """ + + def __init__(self): + super().__init__() + self._set_feature("light_optional", "true") + + self._register_decoder(self._decode_islighton) + self._register_encoder(self._encode_islighton) + + @staticmethod + def minor_is_valid(key: int): + return 1934 <= key < 2203 + + def _decode_islighton( + self, chunk: Chunk, data: ChunkDataType, floor_cy: int, height_cy: int + ): + light_on = self.get_layer_obj(data, self.isLightOn) + if light_on == ByteTag(1): + chunk.set_light_off = True + + def _encode_islighton( + self, chunk: Chunk, data: ChunkDataType, floor_cy: int, height_cy: int + ): + if chunk.set_light_off: + self.set_layer_obj(data, self.isLightOn, ByteTag(0)) + + export = Anvil1934Interface