From d974164204cb6640fb3a148abc62e52fd5e7bc1b Mon Sep 17 00:00:00 2001 From: Hannes Greule Date: Sun, 14 Mar 2021 20:38:11 +0100 Subject: [PATCH] Switch from PropertyKey enum to class (#971) * Switch from PropertyKey enum to class * Fix generic toArray --- .../fawe/object/pattern/PropertyPattern.java | 2 +- .../transform/BlockTransformExtent.java | 229 +++++++++--------- .../function/mask/BlockMaskBuilder.java | 10 +- .../worldedit/registry/state/PropertyKey.java | 187 +++++++------- .../registry/state/PropertyKeySet.java | 178 ++++++++++++++ .../worldedit/world/block/BlockState.java | 2 +- .../worldedit/world/block/BlockType.java | 6 +- .../world/block/BlockTypesCache.java | 4 +- 8 files changed, 409 insertions(+), 209 deletions(-) create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/registry/state/PropertyKeySet.java diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/pattern/PropertyPattern.java b/worldedit-core/src/main/java/com/boydti/fawe/object/pattern/PropertyPattern.java index 55ba7325f..f6940a57d 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/pattern/PropertyPattern.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/pattern/PropertyPattern.java @@ -200,7 +200,7 @@ public class PropertyPattern extends AbstractExtentPattern { i++; } if (charSequence.length() > 0) { - key = PropertyKey.get(charSequence); + key = PropertyKey.getByName(charSequence); } last = i + 1; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/transform/BlockTransformExtent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/transform/BlockTransformExtent.java index 80e99e72e..095c9f1a0 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/transform/BlockTransformExtent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/transform/BlockTransformExtent.java @@ -20,6 +20,7 @@ package com.sk89q.worldedit.extent.transform; import com.boydti.fawe.object.extent.ResettableExtent; +import com.google.common.collect.ImmutableMap; import com.sk89q.jnbt.ByteTag; import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.Tag; @@ -34,6 +35,7 @@ import com.sk89q.worldedit.registry.state.AbstractProperty; import com.sk89q.worldedit.registry.state.DirectionalProperty; import com.sk89q.worldedit.registry.state.Property; import com.sk89q.worldedit.registry.state.PropertyKey; +import com.sk89q.worldedit.registry.state.PropertyKeySet; import com.sk89q.worldedit.util.Direction; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; @@ -50,6 +52,7 @@ import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Set; import javax.annotation.Nullable; import static com.google.common.base.Preconditions.checkNotNull; @@ -78,6 +81,25 @@ import static org.slf4j.LoggerFactory.getLogger; */ public class BlockTransformExtent extends ResettableExtent { + private static final Set directional = PropertyKeySet.of( + PropertyKey.HALF, + PropertyKey.ROTATION, + PropertyKey.AXIS, + PropertyKey.FACING, + PropertyKey.SHAPE, + PropertyKey.NORTH, + PropertyKey.EAST, + PropertyKey.SOUTH, + PropertyKey.WEST + ); + + private static final Map directionMap = ImmutableMap.of( + NORTH, PropertyKey.NORTH, + EAST, PropertyKey.EAST, + SOUTH, PropertyKey.SOUTH, + WEST, PropertyKey.WEST + ); + private Transform transform; private Transform transformInverse; @@ -134,101 +156,103 @@ public class BlockTransformExtent extends ResettableExtent { return adapt(directional.getValues().toArray(new Direction[0])); } else { List values = property.getValues(); - switch (property.getKey()) { - case HALF: - return adapt(UP, DOWN); - case ROTATION: { - List directions = new ArrayList<>(); - for (Object value : values) { - directions.add(Direction.fromRotationIndex((Integer) value).get()); - } - return adapt(directions.toArray(new Direction[0])); + PropertyKey key = property.getKey(); + if (key == PropertyKey.HALF) { + return adapt(UP, DOWN); + } + if (key == PropertyKey.ROTATION) { + List directions = new ArrayList<>(); + for (Object value : values) { + directions.add(Direction.fromRotationIndex((Integer) value).get()); } - case AXIS: - switch (property.getValues().size()) { - case 3: - return adapt(combine(EAST, WEST), combine(UP, DOWN), combine(SOUTH, NORTH)); - case 2: - return adapt(combine(EAST, WEST), combine(SOUTH, NORTH)); - default: - getLogger(BlockTransformExtent.class).error("Invalid {} {}", property.getName(), property.getValues()); - return null; - } - case FACING: { - List directions = new ArrayList<>(); - for (Object value : values) { - directions.add(Direction.valueOf(value.toString().toUpperCase(Locale.ROOT))); - } - return adapt(directions.toArray(new Direction[0])); + return adapt(directions.toArray(new Direction[0])); + } + if (key == PropertyKey.AXIS) { + switch (property.getValues().size()) { + case 3: + return adapt(combine(EAST, WEST), combine(UP, DOWN), combine(SOUTH, NORTH)); + case 2: + return adapt(combine(EAST, WEST), combine(SOUTH, NORTH)); + default: + getLogger(BlockTransformExtent.class).error("Invalid {} {}", property.getName(), property.getValues()); + return null; } - case SHAPE: - if (values.contains("straight")) { - ArrayList result = new ArrayList<>(); - for (Object value : values) { - // [straight, inner_left, inner_right, outer_left, outer_right] - switch (value.toString()) { - case "straight": - result.add(combine(NORTH, EAST, SOUTH, WEST)); - continue; - case "inner_left": - result.add(notIndex(combine(NORTHEAST, NORTHWEST, SOUTHWEST, SOUTHEAST), property.getIndexFor("outer_right"), property.getIndexFor("outer_left"))); - continue; - case "inner_right": - result.add(notIndex(combine(NORTHEAST, NORTHWEST, SOUTHWEST, SOUTHEAST), property.getIndexFor("outer_right"), property.getIndexFor("outer_left"))); - continue; - case "outer_left": - result.add(notIndex(combine(NORTHEAST, NORTHWEST, SOUTHWEST, SOUTHEAST), property.getIndexFor("inner_left"), property.getIndexFor("inner_right"))); - continue; - case "outer_right": - result.add(notIndex(combine(NORTHEAST, NORTHWEST, SOUTHWEST, SOUTHEAST), property.getIndexFor("inner_left"), property.getIndexFor("inner_right"))); - continue; - default: - getLogger(BlockTransformExtent.class).warn("Unknown direction {}", value); - result.add(0L); - } + } + if (key == PropertyKey.FACING) { + List directions = new ArrayList<>(); + for (Object value : values) { + directions.add(Direction.valueOf(value.toString().toUpperCase(Locale.ROOT))); + } + return adapt(directions.toArray(new Direction[0])); + } + if (key == PropertyKey.SHAPE) { + if (values.contains("straight")) { + ArrayList result = new ArrayList<>(); + for (Object value : values) { + // [straight, inner_left, inner_right, outer_left, outer_right] + switch (value.toString()) { + case "straight": + result.add(combine(NORTH, EAST, SOUTH, WEST)); + continue; + case "inner_left": + result.add(notIndex(combine(NORTHEAST, NORTHWEST, SOUTHWEST, SOUTHEAST), property.getIndexFor("outer_right"), property.getIndexFor("outer_left"))); + continue; + case "inner_right": + result.add(notIndex(combine(NORTHEAST, NORTHWEST, SOUTHWEST, SOUTHEAST), property.getIndexFor("outer_right"), property.getIndexFor("outer_left"))); + continue; + case "outer_left": + result.add(notIndex(combine(NORTHEAST, NORTHWEST, SOUTHWEST, SOUTHEAST), property.getIndexFor("inner_left"), property.getIndexFor("inner_right"))); + continue; + case "outer_right": + result.add(notIndex(combine(NORTHEAST, NORTHWEST, SOUTHWEST, SOUTHEAST), property.getIndexFor("inner_left"), property.getIndexFor("inner_right"))); + continue; + default: + getLogger(BlockTransformExtent.class).warn("Unknown direction {}", value); + result.add(0L); } - return adapt(result.toArray(new Long[0])); - } else { - List directions = new ArrayList<>(); - for (Object value : values) { - switch (value.toString()) { - case "north_south": - directions.add(combine(NORTH, SOUTH)); - break; - case "east_west": - directions.add(combine(EAST, WEST)); - break; - case "ascending_east": - directions.add(combine(ASCENDING_EAST)); - break; - case "ascending_west": - directions.add(combine(ASCENDING_WEST)); - break; - case "ascending_north": - directions.add(combine(ASCENDING_NORTH)); - break; - case "ascending_south": - directions.add(combine(ASCENDING_SOUTH)); - break; - case "south_east": - directions.add(combine(SOUTHEAST)); - break; - case "south_west": - directions.add(combine(SOUTHWEST)); - break; - case "north_west": - directions.add(combine(NORTHWEST)); - break; - case "north_east": - directions.add(combine(NORTHEAST)); - break; - default: - getLogger(BlockTransformExtent.class).warn("Unknown direction {}", value); - directions.add(0L); - } - } - return adapt(directions.toArray(new Long[0])); } + return adapt(result.toArray(new Long[0])); + } else { + List directions = new ArrayList<>(); + for (Object value : values) { + switch (value.toString()) { + case "north_south": + directions.add(combine(NORTH, SOUTH)); + break; + case "east_west": + directions.add(combine(EAST, WEST)); + break; + case "ascending_east": + directions.add(combine(ASCENDING_EAST)); + break; + case "ascending_west": + directions.add(combine(ASCENDING_WEST)); + break; + case "ascending_north": + directions.add(combine(ASCENDING_NORTH)); + break; + case "ascending_south": + directions.add(combine(ASCENDING_SOUTH)); + break; + case "south_east": + directions.add(combine(SOUTHEAST)); + break; + case "south_west": + directions.add(combine(SOUTHWEST)); + break; + case "north_west": + directions.add(combine(NORTHWEST)); + break; + case "north_east": + directions.add(combine(NORTHEAST)); + break; + default: + getLogger(BlockTransformExtent.class).warn("Unknown direction {}", value); + directions.add(0L); + } + } + return adapt(directions.toArray(new Long[0])); + } } } return null; @@ -304,20 +328,7 @@ public class BlockTransformExtent extends ResettableExtent { if (property instanceof DirectionalProperty) { return true; } - switch (property.getKey()) { - case HALF: - case ROTATION: - case AXIS: - case FACING: - case SHAPE: - case NORTH: - case EAST: - case SOUTH: - case WEST: - return true; - default: - return false; - } + return directional.contains(property.getKey()); } private static BaseBlock transformBaseBlockNBT(BlockState transformed, CompoundTag tag, Transform transform) { @@ -366,10 +377,10 @@ public class BlockTransformExtent extends ResettableExtent { Object southState = tmp.getState(PropertyKey.SOUTH); Object westState = tmp.getState(PropertyKey.WEST); - tmp = tmp.with(PropertyKey.valueOf(newNorth.name().toUpperCase(Locale.ROOT)), northState); - tmp = tmp.with(PropertyKey.valueOf(newEast.name().toUpperCase(Locale.ROOT)), eastState); - tmp = tmp.with(PropertyKey.valueOf(newSouth.name().toUpperCase(Locale.ROOT)), southState); - tmp = tmp.with(PropertyKey.valueOf(newWest.name().toUpperCase(Locale.ROOT)), westState); + tmp = tmp.with(directionMap.get(newNorth), northState); + tmp = tmp.with(directionMap.get(newEast), eastState); + tmp = tmp.with(directionMap.get(newSouth), southState); + tmp = tmp.with(directionMap.get(newWest), westState); newMaskedId = tmp.getInternalId(); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockMaskBuilder.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockMaskBuilder.java index c22f52a92..3ee861303 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockMaskBuilder.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockMaskBuilder.java @@ -9,6 +9,7 @@ import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.registry.state.AbstractProperty; import com.sk89q.worldedit.registry.state.Property; import com.sk89q.worldedit.registry.state.PropertyKey; +import com.sk89q.worldedit.registry.state.PropertyKeySet; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockType; @@ -20,7 +21,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; -import java.util.EnumSet; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -152,7 +152,7 @@ public class BlockMaskBuilder { case ']': case ',': { charSequence.setSubstring(last, i); - if (key == null && PropertyKey.get(charSequence) == null) { + if (key == null && PropertyKey.getByName(charSequence) == null) { suggest(input, charSequence.toString(), type != null ? Collections.singleton(type) : blockTypeList); } if (operator == null) { @@ -220,7 +220,7 @@ public class BlockMaskBuilder { break; } if (charSequence.length() > 0 || key == null) { - key = PropertyKey.get(charSequence); + key = PropertyKey.getByName(charSequence); if (key == null) { suggest(input, charSequence.toString(), type != null ? Collections.singleton(type) : blockTypeList); } @@ -258,9 +258,9 @@ public class BlockMaskBuilder { private void suggest(String input, String property, Collection finalTypes) throws InputParseException { throw new SuggestInputParseException(input + " does not have: " + property, input, () -> { - Set keys = EnumSet.noneOf(PropertyKey.class); + Set keys = PropertyKeySet.empty(); finalTypes.forEach(t -> t.getProperties().forEach(p -> keys.add(p.getKey()))); - return keys.stream().map(PropertyKey::getId) + return keys.stream().map(PropertyKey::getName) .filter(p -> StringMan.blockStateMatches(property, p)) .sorted(StringMan.blockStateComparator(property)) .collect(Collectors.toList()); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/registry/state/PropertyKey.java b/worldedit-core/src/main/java/com/sk89q/worldedit/registry/state/PropertyKey.java index 5689e7a64..4a25ddc8a 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/registry/state/PropertyKey.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/registry/state/PropertyKey.java @@ -1,116 +1,127 @@ package com.sk89q.worldedit.registry.state; -import com.boydti.fawe.util.ReflectionUtils; +import org.jetbrains.annotations.NotNull; +import java.util.ArrayList; import java.util.HashMap; -import java.util.Locale; +import java.util.List; import java.util.Map; /** * This class will be generated at runtime - these are just example values. */ -public enum PropertyKey { - // TODO FIXME Generate this at runtime - AGE, - ATTACHED, - AXIS, - BITES, - CONDITIONAL, - DELAY, - DISARMED, - DISTANCE, - DOWN, - DRAG, - EAST, - EGGS, - ENABLED, - EXTENDED, - EYE, - FACE, - FACING, - HALF, - HAS_BOTTLE_0, - HAS_BOTTLE_1, - HAS_BOTTLE_2, - HAS_RECORD, - HATCH, - HINGE, - IN_WALL, - INSTRUMENT, - INVERTED, - LAYERS, - LEVEL, - LIT, - LOCKED, - MODE, - MOISTURE, - NORTH, - NOTE, - OCCUPIED, - OPEN, - PART, - PERSISTENT, - PICKLES, - POWER, - POWERED, - ROTATION, - SHAPE, - SHORT, - SNOWY, - SOUTH, - STAGE, - TRIGGERED, - TYPE, - UP, - WATERLOGGED, - WEST, - UNSTABLE, - LEAVES, - ATTACHMENT, - SIGNAL_FIRE, - HANGING, - HAS_BOOK, - BOTTOM; +public class PropertyKey implements Comparable { - private final String id; + // needs to be declared before constants + private static final Map keys = new HashMap<>(); + private static final List keyList = new ArrayList<>(); - PropertyKey() { - this.id = name().toLowerCase(Locale.ROOT); + // constants + public static final PropertyKey AGE = getOrCreate("age"); + public static final PropertyKey ATTACHED = getOrCreate("attached"); + public static final PropertyKey AXIS = getOrCreate("axis"); + public static final PropertyKey BITES = getOrCreate("bites"); + public static final PropertyKey CONDITIONAL = getOrCreate("conditional"); + public static final PropertyKey DELAY = getOrCreate("delay"); + public static final PropertyKey DISARMED = getOrCreate("disarmed"); + public static final PropertyKey DISTANCE = getOrCreate("distance"); + public static final PropertyKey DOWN = getOrCreate("down"); + public static final PropertyKey DRAG = getOrCreate("drag"); + public static final PropertyKey EAST = getOrCreate("east"); + public static final PropertyKey EGGS = getOrCreate("eggs"); + public static final PropertyKey ENABLED = getOrCreate("enabled"); + public static final PropertyKey EXTENDED = getOrCreate("extended"); + public static final PropertyKey EYE = getOrCreate("eye"); + public static final PropertyKey FACE = getOrCreate("face"); + public static final PropertyKey FACING = getOrCreate("facing"); + public static final PropertyKey HALF = getOrCreate("half"); + public static final PropertyKey HAS_BOTTLE_0 = getOrCreate("has_bottle_0"); + public static final PropertyKey HAS_BOTTLE_1 = getOrCreate("has_bottle_1"); + public static final PropertyKey HAS_BOTTLE_2 = getOrCreate("has_bottle_2"); + public static final PropertyKey HAS_RECORD = getOrCreate("has_record"); + public static final PropertyKey HATCH = getOrCreate("hatch"); + public static final PropertyKey HINGE = getOrCreate("hinge"); + public static final PropertyKey IN_WALL = getOrCreate("in_wall"); + public static final PropertyKey INSTRUMENT = getOrCreate("instrument"); + public static final PropertyKey INVERTED = getOrCreate("inverted"); + public static final PropertyKey LAYERS = getOrCreate("layers"); + public static final PropertyKey LEVEL = getOrCreate("level"); + public static final PropertyKey LIT = getOrCreate("lit"); + public static final PropertyKey LOCKED = getOrCreate("locked"); + public static final PropertyKey MODE = getOrCreate("mode"); + public static final PropertyKey MOISTURE = getOrCreate("moisture"); + public static final PropertyKey NORTH = getOrCreate("north"); + public static final PropertyKey NOTE = getOrCreate("note"); + public static final PropertyKey OCCUPIED = getOrCreate("occupied"); + public static final PropertyKey OPEN =getOrCreate("open"); + public static final PropertyKey PART = getOrCreate("part"); + public static final PropertyKey PERSISTENT = getOrCreate("persistent"); + public static final PropertyKey PICKLES = getOrCreate("pickles"); + public static final PropertyKey POWER = getOrCreate("power"); + public static final PropertyKey POWERED = getOrCreate("powered"); + public static final PropertyKey ROTATION = getOrCreate("rotation"); + public static final PropertyKey SHAPE = getOrCreate("shape"); + public static final PropertyKey SHORT = getOrCreate("short"); + public static final PropertyKey SNOWY = getOrCreate("snowy"); + public static final PropertyKey SOUTH = getOrCreate("south"); + public static final PropertyKey STAGE = getOrCreate("stage"); + public static final PropertyKey TRIGGERED = getOrCreate("triggered"); + public static final PropertyKey TYPE = getOrCreate("type"); + public static final PropertyKey UP = getOrCreate("up"); + public static final PropertyKey WATERLOGGED = getOrCreate("waterlogged"); + public static final PropertyKey WEST = getOrCreate("west"); + public static final PropertyKey UNSTABLE = getOrCreate("unstable"); + public static final PropertyKey LEAVES = getOrCreate("leaves"); + public static final PropertyKey ATTACHMENT = getOrCreate("attachement"); + public static final PropertyKey SIGNAL_FIRE = getOrCreate("signal_fire"); + public static final PropertyKey HANGING = getOrCreate("hanging"); + public static final PropertyKey HAS_BOOK = getOrCreate("has_book"); + public static final PropertyKey BOTTOM = getOrCreate("bottom"); + + private final String name; + private final int id; + + + private PropertyKey(String name, int ordinal) { + this.name = name; + this.id = ordinal; } - private static final Map keys = new HashMap<>(); - static { - for (PropertyKey key : values()) { - keys.put(key.name().toLowerCase(Locale.ROOT), key); - } + public static int getCount() { + return keyList.size(); } - public final String getId() { - return this.id; + public final String getName() { + return this.name; } - public static final PropertyKey get(CharSequence name) { + public static PropertyKey getByName(CharSequence name) { return keys.get(name); } + public static PropertyKey getById(int id) { + return keyList.get(id); + } + /** * Get or create the property key. * @param id The name of the property (e.g., `waterlogged`) * @return PropertyKey enum */ public static PropertyKey getOrCreate(String id) { - PropertyKey property = PropertyKey.get(id); - if (property == null) { - property = ReflectionUtils.addEnum(PropertyKey.class, id.toUpperCase(Locale.ROOT)); - if (property.getId() == null) { - try { - ReflectionUtils.setFailsafeFieldValue(PropertyKey.class.getDeclaredField("id"), property, property.name().toLowerCase()); - } catch (Throwable e) { - throw new RuntimeException("Could not register property with an id of " + id , e); - } - } - keys.put(property.name().toLowerCase(Locale.ROOT), property); - } - return property; + return keys.computeIfAbsent(id, k -> { + PropertyKey key = new PropertyKey(id, keyList.size()); + keyList.add(key); + return key; + }); + } + + public int getId() { + return id; + } + + @Override + public int compareTo(@NotNull PropertyKey o) { + return Integer.compare(this.id, o.id); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/registry/state/PropertyKeySet.java b/worldedit-core/src/main/java/com/sk89q/worldedit/registry/state/PropertyKeySet.java new file mode 100644 index 000000000..a3f36ce18 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/registry/state/PropertyKeySet.java @@ -0,0 +1,178 @@ +package com.sk89q.worldedit.registry.state; + +import org.jetbrains.annotations.NotNull; + +import java.lang.reflect.Array; +import java.util.Arrays; +import java.util.BitSet; +import java.util.Collection; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.Set; + +public class PropertyKeySet implements Set { + private final BitSet bits = new BitSet(PropertyKey.getCount()); // still resizable + + public static PropertyKeySet empty() { + return new PropertyKeySet(); + } + + public static PropertyKeySet ofCollection(Collection collection) { + PropertyKeySet set = new PropertyKeySet(); + if (collection instanceof PropertyKeySet) { + // simple copy + set.bits.or(((PropertyKeySet) collection).bits); + return set; + } + for (PropertyKey key : collection) { + set.bits.set(key.getId()); + } + return set; + } + + public static PropertyKeySet of(PropertyKey propertyKey) { + PropertyKeySet set = new PropertyKeySet(); + set.bits.set(propertyKey.getId()); + return set; + } + + public static PropertyKeySet of(PropertyKey... propertyKeys) { + return ofCollection(Arrays.asList(propertyKeys)); + } + + @Override + public int size() { + return this.bits.cardinality(); + } + + @Override + public boolean isEmpty() { + return this.bits.isEmpty(); + } + + @Override + public boolean contains(Object o) { + if (!(o instanceof PropertyKey)) return false; + return this.bits.get(((PropertyKey) o).getId()); + } + + @NotNull + @Override + public Iterator iterator() { + return new PropertyKeyIterator(); + } + + @NotNull + @Override + public Object[] toArray() { + return toArray(new Object[0]); + } + + @NotNull + @Override + public T[] toArray(@NotNull T[] a) { + T[] array = Arrays.copyOf(a, this.bits.cardinality()); + Iterator iter = iterator(); + for (int i = 0; i < array.length && iter.hasNext(); i++) { + //noinspection unchecked + array[i] = (T) iter.next(); + } + return array; + } + + @Override + public boolean add(PropertyKey propertyKey) { + if (this.bits.get(propertyKey.getId())) return false; + this.bits.set(propertyKey.getId()); + return true; + } + + @Override + public boolean remove(Object o) { + if (!(o instanceof PropertyKey)) return false; + if (!this.bits.get(((PropertyKey) o).getId())) return false; + this.bits.clear(((PropertyKey) o).getId()); + return true; + } + + @Override + public boolean containsAll(@NotNull Collection c) { + if (c instanceof PropertyKeySet) { + return ((PropertyKeySet) c).bits.intersects(this.bits); + } + for (Object o : c) { + if (!(o instanceof PropertyKey)) return false; + if (!this.bits.get(((PropertyKey) o).getId())) return false; + } + return false; + } + + @Override + public boolean addAll(@NotNull Collection c) { + int cardinality = this.bits.cardinality(); + if (c instanceof PropertyKeySet) { + this.bits.or(((PropertyKeySet) c).bits); + } else { + for (PropertyKey key : c) { + this.bits.set(key.getId()); + } + } + return cardinality != this.bits.cardinality(); // if cardinality changed, this set was changed + } + + @Override + public boolean retainAll(@NotNull Collection c) { + int cardinality = this.bits.cardinality(); + BitSet removal; + if (c instanceof PropertyKeySet) { + removal = ((PropertyKeySet) c).bits; + } else { + removal = new BitSet(this.bits.length()); + for (PropertyKey key : this) { + if (!c.contains(key)) { + removal.set(key.getId()); + } + } + } + this.bits.and(removal); + return cardinality != this.bits.cardinality(); // if cardinality changed, this set was changed + } + + @Override + public boolean removeAll(@NotNull Collection c) { + int cardinality = this.bits.cardinality(); + if (c instanceof PropertyKeySet) { + this.bits.andNot(((PropertyKeySet) c).bits); + } else { + for (Object o : c) { // mh + if (o instanceof PropertyKey) { + this.bits.clear(((PropertyKey) o).getId()); + } + } + } + return cardinality != this.bits.cardinality(); // if cardinality changed, this set was changed + } + + @Override + public void clear() { + this.bits.clear(); + } + + private class PropertyKeyIterator implements Iterator { + + private int current = bits.nextSetBit(0); + + @Override + public boolean hasNext() { + return this.current >= 0; + } + + @Override + public PropertyKey next() { + if (!hasNext()) throw new NoSuchElementException(); + PropertyKey next = PropertyKey.getById(this.current); + this.current = bits.nextSetBit(this.current + 1); + return next; + } + } +} 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 26374e495..4572cedda 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 @@ -185,7 +185,7 @@ public class BlockState implements BlockStateHolder, Pattern { stateId = property.modifyIndex(stateId, index); } else { // suggest - PropertyKey key = PropertyKey.get(charSequence); + PropertyKey key = PropertyKey.getByName(charSequence); if (key == null || !type.hasProperty(key)) { // Suggest property String input = charSequence.toString(); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockType.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockType.java index 3686d8ed9..17ed3db47 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockType.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockType.java @@ -181,13 +181,13 @@ public class BlockType implements Keyed, Pattern { } public boolean hasProperty(PropertyKey key) { - int ordinal = key.ordinal(); - return this.settings.propertiesMapArr.length > ordinal ? this.settings.propertiesMapArr[ordinal] != null : false; + int ordinal = key.getId(); + return this.settings.propertiesMapArr.length > ordinal && this.settings.propertiesMapArr[ordinal] != null; } public Property getProperty(PropertyKey key) { try { - return (Property) this.settings.propertiesMapArr[key.ordinal()]; + return (Property) this.settings.propertiesMapArr[key.getId()]; } catch (IndexOutOfBoundsException ignored) { return null; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockTypesCache.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockTypesCache.java index 880b4f290..65d633345 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockTypesCache.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockTypesCache.java @@ -59,7 +59,7 @@ public class BlockTypesCache { // Ensure the properties are registered int maxOrdinal = 0; for (String key : properties.keySet()) { - maxOrdinal = Math.max(PropertyKey.getOrCreate(key).ordinal(), maxOrdinal); + maxOrdinal = Math.max(PropertyKey.getOrCreate(key).getId(), maxOrdinal); } this.propertiesMapArr = new AbstractProperty[maxOrdinal + 1]; int prop_arr_i = 0; @@ -70,7 +70,7 @@ public class BlockTypesCache { for (Map.Entry> entry : properties.entrySet()) { PropertyKey key = PropertyKey.getOrCreate(entry.getKey()); AbstractProperty property = ((AbstractProperty) entry.getValue()).withOffset(bitOffset); - this.propertiesMapArr[key.ordinal()] = property; + this.propertiesMapArr[key.getId()] = property; this.propertiesArr[prop_arr_i++] = property; propMap.put(entry.getKey(), property);