From 8da984d9f9ca57c2ffc562345eb38bc00cbfbbad Mon Sep 17 00:00:00 2001 From: Matthew Miller Date: Thu, 27 Dec 2018 15:19:58 +1000 Subject: [PATCH] Fuzzier fuzzies --- .../factory/parser/DefaultBlockParser.java | 7 +- .../worldedit/world/block/BaseBlock.java | 4 +- .../worldedit/world/block/BlockState.java | 36 +---- .../world/block/FuzzyBlockState.java | 131 ++++++++++++++++++ 4 files changed, 143 insertions(+), 35 deletions(-) create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/world/block/FuzzyBlockState.java diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/DefaultBlockParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/DefaultBlockParser.java index e2093ff13..1088c3695 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/DefaultBlockParser.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/DefaultBlockParser.java @@ -43,6 +43,7 @@ import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.block.BlockTypes; +import com.sk89q.worldedit.world.block.FuzzyBlockState; import com.sk89q.worldedit.world.registry.LegacyMapper; import java.util.HashMap; @@ -268,12 +269,14 @@ public class DefaultBlockParser extends InputParser { // No wildcards allowed => eliminate them. (Start with default state) state = blockType.getDefaultState(); } else { - state = blockType.getDefaultState().toFuzzy(); + FuzzyBlockState.Builder fuzzyBuilder = FuzzyBlockState.builder(); + fuzzyBuilder.type(blockType); for (Map.Entry, Object> blockState : blockStates.entrySet()) { @SuppressWarnings("unchecked") Property objProp = (Property) blockState.getKey(); - state = state.with(objProp, blockState.getValue()); + fuzzyBuilder.withProperty(objProp, blockState.getValue()); } + state = fuzzyBuilder.build(); } state = applyProperties(state, stateProperties); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BaseBlock.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BaseBlock.java index 1810f9178..bc913f2d7 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BaseBlock.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BaseBlock.java @@ -142,7 +142,7 @@ public class BaseBlock implements BlockStateHolder, TileEntityBlock { final BaseBlock otherBlock = (BaseBlock) o; - return this.toImmutableState().equalsFuzzy(otherBlock.toImmutableState()) && Objects.equals(getNbtData(), otherBlock.getNbtData()); + return this.blockState.equalsFuzzy(otherBlock.blockState) && Objects.equals(getNbtData(), otherBlock.getNbtData()); } /** @@ -153,7 +153,7 @@ public class BaseBlock implements BlockStateHolder, TileEntityBlock { */ @Override public boolean equalsFuzzy(BlockStateHolder o) { - return this.toImmutableState().equalsFuzzy(o); + return this.blockState.equalsFuzzy(o); } @Override diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockState.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockState.java index 565b208a0..a67235d0c 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockState.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockState.java @@ -30,7 +30,6 @@ import com.sk89q.worldedit.registry.state.Property; import java.util.Collections; import java.util.Comparator; -import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; @@ -46,30 +45,16 @@ public class BlockState implements BlockStateHolder { private final BlockType blockType; private final Map, Object> values; - private final boolean fuzzy; private BaseBlock emptyBaseBlock; // Neighbouring state table. private Table, Object, BlockState> states; - private BlockState(BlockType blockType) { + BlockState(BlockType blockType) { this.blockType = blockType; this.values = new LinkedHashMap<>(); this.emptyBaseBlock = new BaseBlock(this); - this.fuzzy = false; - } - - /** - * Creates a fuzzy BlockState. This can be used for partial matching. - * - * @param blockType The block type - * @param values The block state values - */ - private BlockState(BlockType blockType, Map, Object> values) { - this.blockType = blockType; - this.values = values; - this.fuzzy = true; } static Map, Object>, BlockState> generateStateMap(BlockType blockType) { @@ -144,12 +129,8 @@ public class BlockState implements BlockStateHolder { @Override public BlockState with(final Property property, final V value) { - if (fuzzy) { - return setState(property, value); - } else { - BlockState result = states.get(property, value); - return result == null ? this : result; - } + BlockState result = states.get(property, value); + return result == null ? this : result; } @Override @@ -162,10 +143,6 @@ public class BlockState implements BlockStateHolder { return Collections.unmodifiableMap(this.values); } - public BlockState toFuzzy() { - return new BlockState(this.getBlockType(), new HashMap<>()); - } - @Override public boolean equalsFuzzy(BlockStateHolder o) { if (this == o) { @@ -207,9 +184,6 @@ public class BlockState implements BlockStateHolder { @Override public BaseBlock toBaseBlock() { - if (this.fuzzy) { - throw new IllegalArgumentException("Can't create a BaseBlock from a fuzzy BlockState!"); - } return this.emptyBaseBlock; } @@ -230,7 +204,7 @@ public class BlockState implements BlockStateHolder { * @param value The value * @return The blockstate, for chaining */ - private BlockState setState(final Property property, final Object value) { + BlockState setState(final Property property, final Object value) { this.values.put(property, value); return this; } @@ -251,6 +225,6 @@ public class BlockState implements BlockStateHolder { @Override public int hashCode() { - return Objects.hash(blockType, values, fuzzy); + return Objects.hash(blockType, values); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/FuzzyBlockState.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/FuzzyBlockState.java new file mode 100644 index 000000000..a2082270e --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/FuzzyBlockState.java @@ -0,0 +1,131 @@ +/* + * 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.world.block; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.sk89q.worldedit.registry.state.Property; + +import java.util.HashMap; +import java.util.Map; + +/** + * A Fuzzy BlockState. Used for partial matching. + * + * Immutable, construct with {@link FuzzyBlockState.Builder}. + */ +public class FuzzyBlockState extends BlockState { + + FuzzyBlockState(BlockType blockType) { + super(blockType); + } + + @SuppressWarnings("unchecked") + @Override + public BlockState toImmutableState() { + BlockState state = getBlockType().getDefaultState(); + for (Map.Entry, Object> entry : getStates().entrySet()) { + state = state.with((Property) entry.getKey(), entry.getValue()); + } + return getBlockType().getDefaultState(); + } + + /** + * Gets an instance of a builder. + * + * @return The builder + */ + public static Builder builder() { + return new Builder(); + } + + /** + * Builder for FuzzyBlockState + */ + public static class Builder { + private BlockState internalState; + private Map, Object> values = new HashMap<>(); + + /** + * The type of the Fuzzy BlockState + * + * @param type The type + * @return The builder, for chaining + */ + public Builder type(BlockType type) { + checkNotNull(type); + internalState = type.getDefaultState(); + return this; + } + + /** + * The type of the Fuzzy BlockState + * + * @param state The state + * @return The builder, for chaining + */ + public Builder type(BlockState state) { + checkNotNull(state); + internalState = state; + return this; + } + + /** + * Adds a property to the fuzzy BlockState + * + * @param property The property + * @param value The value + * @param The property type + * @return The builder, for chaining + */ + public Builder withProperty(Property property, V value) { + checkNotNull(property); + checkNotNull(value); + checkNotNull(internalState, "The type must be set before the properties!"); + values.put(property, value); + return this; + } + + /** + * Builds a FuzzyBlockState from this builder. + * + * @return The fuzzy BlockState + */ + public FuzzyBlockState build() { + checkNotNull(internalState); + FuzzyBlockState blockState = new FuzzyBlockState(internalState.getBlockType()); + for (Map.Entry, Object> entry : values.entrySet()) { + blockState.setState(entry.getKey(), entry.getValue()); + } + return blockState; + } + + /** + * Resets the builder. + * + * @return The builder, for chaining + */ + public Builder reset() { + this.internalState = null; + this.values.clear(); + return this; + } + } +}