From 34d48177959fea4d53677431fe8e737420166abd Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+DoctorMacc@users.noreply.github.com> Date: Sun, 10 May 2020 15:26:00 -0400 Subject: [PATCH] Add visual support for double chests (#523) * Add visual support for double chests * Update mappings submodule --- .../world/block/BlockStateValues.java | 19 +++ .../world/block/DoubleChestValue.java | 52 +++++++++ .../DoubleChestBlockEntityTranslator.java | 108 ++++++++++++++++++ connector/src/main/resources/mappings | 2 +- 4 files changed, 180 insertions(+), 1 deletion(-) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/world/block/DoubleChestValue.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/DoubleChestBlockEntityTranslator.java diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/BlockStateValues.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/BlockStateValues.java index de08b7e8..070a0592 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/BlockStateValues.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/BlockStateValues.java @@ -47,6 +47,7 @@ public class BlockStateValues { private static final Object2IntMap BANNER_COLORS = new Object2IntOpenHashMap<>(); private static final Object2ByteMap BED_COLORS = new Object2ByteOpenHashMap<>(); + private static final Int2ObjectMap DOUBLE_CHEST_VALUES = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap FLOWER_POT_VALUES = new Int2ObjectOpenHashMap<>(); private static final Map FLOWER_POT_BLOCKS = new HashMap<>(); private static final Object2IntMap NOTEBLOCK_PITCHES = new Object2IntOpenHashMap<>(); @@ -74,6 +75,15 @@ public class BlockStateValues { return; } + if (entry.getValue().get("double_chest_position") != null) { + boolean isX = (entry.getValue().get("x") != null); + boolean isDirectionPositive = ((entry.getValue().get("x") != null && entry.getValue().get("x").asBoolean()) || + (entry.getValue().get("z") != null && entry.getValue().get("z").asBoolean())); + boolean isLeft = (entry.getValue().get("double_chest_position").asText().contains("left")); + DOUBLE_CHEST_VALUES.put(javaBlockState.getId(), new DoubleChestValue(isX, isDirectionPositive, isLeft)); + return; + } + if (entry.getKey().contains("potted_")) { FLOWER_POT_VALUES.put(javaBlockState.getId(), entry.getKey().replace("potted_", "")); return; @@ -136,6 +146,15 @@ public class BlockStateValues { return -1; } + /** + * All double chest values are part of the block state in Java and part of the block entity tag in Bedrock. + * This gives the DoubleChestValue that can be calculated into the final tag. + * @return The map of all DoubleChestValues. + */ + public static Int2ObjectMap getDoubleChestValues() { + return DOUBLE_CHEST_VALUES; + } + /** * Get the Int2ObjectMap of flower pot block states to containing plant * @return Int2ObjectMap of flower pot values diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/DoubleChestValue.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/DoubleChestValue.java new file mode 100644 index 00000000..5bd21724 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/DoubleChestValue.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + * + */ + +package org.geysermc.connector.network.translators.world.block; + +import lombok.AllArgsConstructor; + +/** + * This stores all values of double chests that are part of the Java block state. + */ +@AllArgsConstructor +public class DoubleChestValue { + + /** + * If true, then chest is facing east/west; if false, south/north + */ + public boolean isFacingEast; + + /** + * If true, direction is positive (east/south); if false, direction is negative (west/north) + */ + public boolean isDirectionPositive; + + /** + * If true, chest is the left of a pair; if false, chest is the right of a pair. + */ + public boolean isLeft; + +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/DoubleChestBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/DoubleChestBlockEntityTranslator.java new file mode 100644 index 00000000..f5599832 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/DoubleChestBlockEntityTranslator.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + * + */ + +package org.geysermc.connector.network.translators.world.block.entity; + +import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import com.nukkitx.math.vector.Vector3i; +import com.nukkitx.nbt.CompoundTagBuilder; +import com.nukkitx.nbt.tag.ByteTag; +import com.nukkitx.nbt.tag.IntTag; +import com.nukkitx.nbt.tag.Tag; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.world.block.BlockStateValues; +import org.geysermc.connector.network.translators.world.block.DoubleChestValue; +import org.geysermc.connector.utils.BlockEntityUtils; + +import java.util.ArrayList; +import java.util.List; + +/** + * Chests have more block entity properties in Bedrock, which is solved by implementing the BedrockOnlyBlockEntity + */ +@BlockEntity(name = "Chest", regex = "chest") +public class DoubleChestBlockEntityTranslator extends BlockEntityTranslator implements BedrockOnlyBlockEntity, RequiresBlockState { + + @Override + public boolean isBlock(BlockState blockState) { + return BlockStateValues.getDoubleChestValues().containsKey(blockState.getId()); + } + + @Override + public void updateBlock(GeyserSession session, BlockState blockState, Vector3i position) { + CompoundTag javaTag = getConstantJavaTag("chest", position.getX(), position.getY(), position.getZ()); + CompoundTagBuilder tagBuilder = getConstantBedrockTag(BlockEntityUtils.getBedrockBlockEntityId("chest"), position.getX(), position.getY(), position.getZ()).toBuilder(); + translateTag(javaTag, blockState).forEach(tagBuilder::tag); + BlockEntityUtils.updateBlockEntity(session, tagBuilder.buildRootTag(), position); + } + + @Override + public List> translateTag(CompoundTag tag, BlockState blockState) { + List> tags = new ArrayList<>(); + if (blockState != null && BlockStateValues.getDoubleChestValues().containsKey(blockState.getId())) { + DoubleChestValue chestValues = BlockStateValues.getDoubleChestValues().get(blockState.getId()); + if (chestValues != null) { + int x = (int) tag.getValue().get("x").getValue(); + int z = (int) tag.getValue().get("z").getValue(); + // Calculate the position of the other chest based on the Java block state + if (chestValues.isFacingEast) { + if (chestValues.isDirectionPositive) { + // East + z = z + (chestValues.isLeft ? 1 : -1); + } else { + // West + z = z + (chestValues.isLeft ? -1 : 1); + } + } else { + if (chestValues.isDirectionPositive) { + // South + x = x + (chestValues.isLeft ? -1 : 1); + } else { + // North + x = x + (chestValues.isLeft ? 1 : -1); + } + } + tags.add(new IntTag("pairx", x)); + tags.add(new IntTag("pairz", z)); + if (!chestValues.isLeft) { + tags.add(new ByteTag("pairlead", (byte) 1)); + } + } + } + return tags; + } + + @Override + public CompoundTag getDefaultJavaTag(String javaId, int x, int y, int z) { + return null; + } + + @Override + public com.nukkitx.nbt.tag.CompoundTag getDefaultBedrockTag(String bedrockId, int x, int y, int z) { + return null; + } +} diff --git a/connector/src/main/resources/mappings b/connector/src/main/resources/mappings index 5b3a9ad1..a7963d0a 160000 --- a/connector/src/main/resources/mappings +++ b/connector/src/main/resources/mappings @@ -1 +1 @@ -Subproject commit 5b3a9ad1d2ef76105fb318e63126a096844b3195 +Subproject commit a7963d0a0236b1c47eea21718ac50706139d90cc