From 396b03edf78f705cdd875328bf92d14cf1b2375b Mon Sep 17 00:00:00 2001 From: chickeneer Date: Thu, 23 Apr 2020 20:08:59 -0500 Subject: [PATCH] Add compatibility handlers for beds and banners for MCEdit Schematics (#561) * Add compatibility handlers for beds and banners * IntTag#getValue does not return null so do not check that (cherry picked from commit 53ac21aa8723d71040d580902cfeae551a9cabf6) --- .../clipboard/io/MCEditSchematicReader.java | 6 +- .../BannerBlockCompatibilityHandler.java | 168 ++++++++++++++++++ .../BedBlockCompatibilityHandler.java | 141 +++++++++++++++ 3 files changed, 314 insertions(+), 1 deletion(-) create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/legacycompat/BannerBlockCompatibilityHandler.java create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/legacycompat/BedBlockCompatibilityHandler.java diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/MCEditSchematicReader.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/MCEditSchematicReader.java index a2b04c9c0..e20059636 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/MCEditSchematicReader.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/MCEditSchematicReader.java @@ -35,6 +35,8 @@ import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard; import com.sk89q.worldedit.extent.clipboard.Clipboard; +import com.sk89q.worldedit.extent.clipboard.io.legacycompat.BannerBlockCompatibilityHandler; +import com.sk89q.worldedit.extent.clipboard.io.legacycompat.BedBlockCompatibilityHandler; import com.sk89q.worldedit.extent.clipboard.io.legacycompat.EntityNBTCompatibilityHandler; import com.sk89q.worldedit.extent.clipboard.io.legacycompat.FlowerPotCompatibilityHandler; import com.sk89q.worldedit.extent.clipboard.io.legacycompat.NBTCompatibilityHandler; @@ -79,7 +81,9 @@ public class MCEditSchematicReader extends NBTSchematicReader { new SignCompatibilityHandler(), new FlowerPotCompatibilityHandler(), new NoteBlockCompatibilityHandler(), - new SkullBlockCompatibilityHandler() + new SkullBlockCompatibilityHandler(), + new BannerBlockCompatibilityHandler(), + new BedBlockCompatibilityHandler() ); private static final ImmutableList ENTITY_COMPATIBILITY_HANDLERS = ImmutableList.of( diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/legacycompat/BannerBlockCompatibilityHandler.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/legacycompat/BannerBlockCompatibilityHandler.java new file mode 100644 index 000000000..9899bac9c --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/legacycompat/BannerBlockCompatibilityHandler.java @@ -0,0 +1,168 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.extent.clipboard.io.legacycompat; + +import com.sk89q.jnbt.CompoundTag; +import com.sk89q.jnbt.CompoundTagBuilder; +import com.sk89q.jnbt.IntTag; +import com.sk89q.jnbt.ListTag; +import com.sk89q.jnbt.Tag; +import com.sk89q.worldedit.registry.state.DirectionalProperty; +import com.sk89q.worldedit.registry.state.IntegerProperty; +import com.sk89q.worldedit.registry.state.Property; +import com.sk89q.worldedit.world.block.BlockState; +import com.sk89q.worldedit.world.block.BlockStateHolder; +import com.sk89q.worldedit.world.block.BlockType; +import com.sk89q.worldedit.world.block.BlockTypes; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class BannerBlockCompatibilityHandler implements NBTCompatibilityHandler { + + private static final DirectionalProperty FacingProperty; + private static final IntegerProperty RotationProperty; + + static { + DirectionalProperty tempFacing; + IntegerProperty tempRotation; + try { + tempFacing = (DirectionalProperty) (Property) BlockTypes.WHITE_WALL_BANNER.getProperty("facing"); + tempRotation = (IntegerProperty) (Property) BlockTypes.WHITE_BANNER.getProperty("rotation"); + } catch (NullPointerException | IllegalArgumentException | ClassCastException e) { + tempFacing = null; + tempRotation = null; + } + FacingProperty = tempFacing; + RotationProperty = tempRotation; + } + + @Override + public > boolean isAffectedBlock(B block) { + return block.getBlockType() == BlockTypes.WHITE_BANNER + || block.getBlockType() == BlockTypes.WHITE_WALL_BANNER; + } + + @Override + public > B updateNBT(B block, Map values) { + Tag typeTag = values.get("Base"); + if (typeTag instanceof IntTag) { + boolean isWall = block.getBlockType() == BlockTypes.WHITE_WALL_BANNER; + String bannerType = convertBannerType(((IntTag) typeTag).getValue(), isWall); + if (bannerType != null) { + BlockType type = BlockTypes.get("minecraft:" + bannerType); + if (type != null) { + BlockState state = type.getDefaultState(); + + if (isWall) { + Property facingProp = type.getProperty("facing"); + state = state.with(facingProp, block.getState(FacingProperty)); + } else { + Property rotationProp = type.getProperty("rotation"); + state = state.with(rotationProp, block.getState(RotationProperty)); + } + + values.remove("Base"); + + Tag patternsTag = values.get("Patterns"); + if (patternsTag instanceof ListTag) { + List tempList = new ArrayList<>(); + for (Tag pattern : ((ListTag) patternsTag).getValue()) { + if (pattern instanceof CompoundTag) { + Map patternMap = ((CompoundTag) pattern).getValue(); + Tag colorTag = patternMap.get("Color"); + + CompoundTagBuilder builder = CompoundTagBuilder.create(); + builder.putAll(patternMap); + if (colorTag instanceof IntTag) { + builder.putInt("Color", 15 - ((IntTag) colorTag).getValue()); + } + tempList.add(builder.build()); + } else { + tempList.add(pattern); + } + } + values.put("Patterns", new ListTag(((ListTag) patternsTag).getType(), tempList)); + } + return (B) state; + } + } + } + return block; + } + + private static String convertBannerType(int oldType, boolean isWall) { + String color; + switch (oldType) { + case 0: + color = "black"; + break; + case 1: + color = "red"; + break; + case 2: + color = "green"; + break; + case 3: + color = "brown"; + break; + case 4: + color = "blue"; + break; + case 5: + color = "purple"; + break; + case 6: + color = "cyan"; + break; + case 7: + color = "light_gray"; + break; + case 8: + color = "gray"; + break; + case 9: + color = "pink"; + break; + case 10: + color = "lime"; + break; + case 11: + color = "yellow"; + break; + case 12: + color = "light_blue"; + break; + case 13: + color = "magenta"; + break; + case 14: + color = "orange"; + break; + case 15: + color = "white"; + break; + default: + return null; + } + return color + (isWall ? "_wall_banner" : "_banner"); + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/legacycompat/BedBlockCompatibilityHandler.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/legacycompat/BedBlockCompatibilityHandler.java new file mode 100644 index 000000000..4711f3287 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/legacycompat/BedBlockCompatibilityHandler.java @@ -0,0 +1,141 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.extent.clipboard.io.legacycompat; + +import com.sk89q.jnbt.IntTag; +import com.sk89q.jnbt.Tag; +import com.sk89q.worldedit.registry.state.DirectionalProperty; +import com.sk89q.worldedit.registry.state.EnumProperty; +import com.sk89q.worldedit.registry.state.Property; +import com.sk89q.worldedit.world.block.BlockState; +import com.sk89q.worldedit.world.block.BlockStateHolder; +import com.sk89q.worldedit.world.block.BlockType; +import com.sk89q.worldedit.world.block.BlockTypes; + +import java.util.Map; + +public class BedBlockCompatibilityHandler implements NBTCompatibilityHandler { + + private static final DirectionalProperty FacingProperty; + private static final EnumProperty PartProperty; + + static { + DirectionalProperty tempFacing; + EnumProperty tempPart; + try { + tempFacing = (DirectionalProperty) (Property) BlockTypes.RED_BED.getProperty("facing"); + tempPart = (EnumProperty) (Property) BlockTypes.RED_BED.getProperty("part"); + } catch (NullPointerException | IllegalArgumentException | ClassCastException e) { + tempFacing = null; + tempPart = null; + } + FacingProperty = tempFacing; + PartProperty = tempPart; + } + + @Override + public > boolean isAffectedBlock(B block) { + return block.getBlockType() == BlockTypes.RED_BED; + } + + @Override + public > B updateNBT(B block, Map values) { + Tag typeTag = values.get("color"); + if (typeTag instanceof IntTag) { + String bedType = convertBedType(((IntTag) typeTag).getValue()); + if (bedType != null) { + BlockType type = BlockTypes.get("minecraft:" + bedType); + if (type != null) { + BlockState state = type.getDefaultState(); + + Property facingProp = type.getProperty("facing"); + state = state.with(facingProp, block.getState(FacingProperty)); + + Property occupiedProp = type.getProperty("occupied"); + state = state.with(occupiedProp, false); + + Property partProp = type.getProperty("part"); + state = state.with(partProp, block.getState(PartProperty)); + + values.remove("color"); + return (B) state; + } + } + } + return block; + } + + private String convertBedType(int oldType) { + String color; + switch (oldType) { + case 0: + color = "white"; + break; + case 1: + color = "orange"; + break; + case 2: + color = "magenta"; + break; + case 3: + color = "light_blue"; + break; + case 4: + color = "yellow"; + break; + case 5: + color = "lime"; + break; + case 6: + color = "pink"; + break; + case 7: + color = "gray"; + break; + case 8: + color = "light_gray"; + break; + case 9: + color = "cyan"; + break; + case 10: + color = "purple"; + break; + case 11: + color = "blue"; + break; + case 12: + color = "brown"; + break; + case 13: + color = "green"; + break; + case 14: + color = "red"; + break; + case 15: + color = "black"; + break; + default: + return null; + } + return color + "_bed"; + } +}