diff --git a/worldedit-bukkit/src/test/java/com/sk89q/worldedit/bukkit/ItemRegistryTest.java b/worldedit-bukkit/src/test/java/com/sk89q/worldedit/bukkit/ItemRegistryTest.java new file mode 100644 index 000000000..6ce44288b --- /dev/null +++ b/worldedit-bukkit/src/test/java/com/sk89q/worldedit/bukkit/ItemRegistryTest.java @@ -0,0 +1,40 @@ +/* + * 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.bukkit; + +import com.sk89q.worldedit.world.item.ItemType; +import com.sk89q.worldedit.world.item.ItemTypes; +import org.bukkit.Material; +import org.junit.jupiter.api.Test; + +public class ItemRegistryTest { + + @Test + public void testTreeTypeMapping() { + for (Material material : Material.values()) { + if (material.isItem() && !material.isLegacy()) { + ItemType.REGISTRY.register(material.getKey().toString(), new ItemType(material.getKey().toString())); + System.out.println(material.getKey().toString()); + } + } + System.out.println(ItemType.REGISTRY.getKnownNamespaces().toString()); + } + +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/RegistryConverter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/RegistryConverter.java index c42dd5ea4..83999afa1 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/RegistryConverter.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/RegistryConverter.java @@ -21,7 +21,6 @@ package com.sk89q.worldedit.command.argument; import com.google.common.collect.ImmutableList; import com.sk89q.worldedit.command.util.SuggestionHelper; -import com.sk89q.worldedit.registry.IRegistry; import com.sk89q.worldedit.registry.Keyed; import com.sk89q.worldedit.registry.Registry; import com.sk89q.worldedit.util.formatting.text.Component; @@ -29,7 +28,6 @@ import com.sk89q.worldedit.util.formatting.text.TextComponent; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BlockCategory; import com.sk89q.worldedit.world.block.BlockType; -import com.sk89q.worldedit.world.block.BlockTypes; import com.sk89q.worldedit.world.entity.EntityType; import com.sk89q.worldedit.world.fluid.FluidCategory; import com.sk89q.worldedit.world.fluid.FluidType; @@ -75,7 +73,7 @@ public final class RegistryConverter implements ArgumentConvert private static RegistryConverter from(Class registryType) { try { Field registryField = registryType.getDeclaredField("REGISTRY"); - IRegistry registry = (IRegistry) registryField.get(null); + Registry registry = (Registry) registryField.get(null); return new RegistryConverter<>(registry); } catch (NoSuchFieldException e) { throw new IllegalArgumentException("Not a registry-backed type: " + registryType.getName()); @@ -84,10 +82,10 @@ public final class RegistryConverter implements ArgumentConvert } } - private final IRegistry registry; + private final Registry registry; private final TextComponent choices; - private RegistryConverter(IRegistry registry) { + private RegistryConverter(Registry registry) { this.registry = registry; this.choices = TextComponent.of("any " + registry.getName()); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/SuggestionHelper.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/SuggestionHelper.java index 0be89351b..7d0be8e9a 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/SuggestionHelper.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/SuggestionHelper.java @@ -19,7 +19,6 @@ package com.sk89q.worldedit.command.util; -import com.sk89q.worldedit.registry.IRegistry; import com.sk89q.worldedit.registry.Keyed; import com.sk89q.worldedit.registry.NamespacedRegistry; import com.sk89q.worldedit.registry.Registry; @@ -139,7 +138,7 @@ public final class SuggestionHelper { return Stream.empty(); } - public static Stream getRegistrySuggestions(IRegistry registry, String input) { + public static Stream getRegistrySuggestions(Registry registry, String input) { if (registry instanceof NamespacedRegistry) { return getNamespacedRegistrySuggestions(((NamespacedRegistry) registry), input); } @@ -172,4 +171,4 @@ public final class SuggestionHelper { Predicate search = byPrefix(input.toLowerCase(Locale.ROOT)); return registry.keySet().stream().filter(search); } -} \ No newline at end of file +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/registry/IRegistry.java b/worldedit-core/src/main/java/com/sk89q/worldedit/registry/IRegistry.java deleted file mode 100644 index a8e7c094c..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/registry/IRegistry.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.sk89q.worldedit.registry; - -import javax.annotation.Nullable; - -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -import java.util.Locale; -import java.util.Set; -import java.util.stream.Stream; - -import static com.google.common.base.Preconditions.checkState; -import static java.util.Objects.requireNonNull; -import static org.enginehub.piston.converter.SuggestionHelper.limitByPrefix; - -public interface IRegistry extends Iterable { - String getName(); - - V get(final String key); - - Set keySet(); - - Collection values(); - - @Override - default Iterator iterator() { - return values().iterator(); - } - - default Stream getSuggestions(String input) { - return limitByPrefix(keySet().stream(), input).stream(); - } -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/registry/NamespacedRegistry.java b/worldedit-core/src/main/java/com/sk89q/worldedit/registry/NamespacedRegistry.java index b5e83ff17..c6bd40ca3 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/registry/NamespacedRegistry.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/registry/NamespacedRegistry.java @@ -19,8 +19,6 @@ package com.sk89q.worldedit.registry; -import com.google.common.collect.Maps; - import static com.google.common.base.Preconditions.checkState; import static java.util.Objects.requireNonNull; import static org.enginehub.piston.converter.SuggestionHelper.byPrefix; @@ -30,7 +28,6 @@ import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Locale; -import java.util.Map; import java.util.Set; import java.util.function.Predicate; import java.util.stream.Stream; @@ -43,20 +40,12 @@ public final class NamespacedRegistry extends Registry { private final List values = new ArrayList<>(); private int lastInternalId = 0; - public NamespacedRegistry(final String name, Map map) { - this(name, map, MINECRAFT_NAMESPACE); - } - public NamespacedRegistry(final String name) { this(name, MINECRAFT_NAMESPACE); } public NamespacedRegistry(final String name, final String defaultNamespace) { - this(name, Maps.newHashMap(), defaultNamespace); - } - - public NamespacedRegistry(final String name, Map map, final String defaultNamespace) { - super(name, map); + super(name); this.defaultNamespace = defaultNamespace; } @@ -71,19 +60,13 @@ public final class NamespacedRegistry extends Registry { requireNonNull(key, "key"); final int i = key.indexOf(':'); checkState(i > 0, "key is not namespaced"); - final V existing = super.get(key); - if (existing != null) { - throw new UnsupportedOperationException("Replacing existing registrations is not supported"); - } if (value instanceof RegistryItem) { ((RegistryItem) value).setInternalId(lastInternalId++); } values.add(value); - super.register(key, value); - if (key.startsWith(defaultNamespace)) { - super.register(key.substring(i + 1), value); - } - return value; + final V registered = super.register(key, value); + knownNamespaces.add(key.substring(0, i)); + return registered; } public V getByInternalId(int index) { @@ -123,7 +106,6 @@ public final class NamespacedRegistry extends Registry { return key; } - @Override public Stream getSuggestions(String input) { if (input.isEmpty() || input.equals(":")) { final Set namespaces = getKnownNamespaces(); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/registry/Registry.java b/worldedit-core/src/main/java/com/sk89q/worldedit/registry/Registry.java index 56bd0b831..e77a04659 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/registry/Registry.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/registry/Registry.java @@ -19,29 +19,24 @@ package com.sk89q.worldedit.registry; -import com.google.common.collect.Maps; - import static com.google.common.base.Preconditions.checkState; import static java.util.Objects.requireNonNull; -import javax.annotation.Nullable; import java.util.Collection; import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; import java.util.Locale; import java.util.Map; import java.util.Set; +import javax.annotation.Nullable; -public class Registry implements IRegistry { - private final Map map; +public class Registry implements Iterable { + private final Map map = new HashMap<>(); private final String name; - public Registry(String name, Map map) { - this.name = name; - this.map = map; - } - public Registry(final String name) { - this(name, Maps.newHashMap()); + this.name = name; } public String getName() { @@ -75,4 +70,9 @@ public class Registry implements IRegistry { return Collections.unmodifiableCollection(this.map.values()); } + @Override + public Iterator iterator() { + return this.map.values().iterator(); + } + } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockTypes.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockTypes.java index 98684f1d2..54892c15c 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockTypes.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockTypes.java @@ -27,9 +27,6 @@ import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.extension.input.InputParseException; import com.sk89q.worldedit.extension.platform.Capability; import com.sk89q.worldedit.extension.platform.Platform; -import com.sk89q.worldedit.registry.IRegistry; -import com.sk89q.worldedit.registry.NamespacedRegistry; -import com.sk89q.worldedit.registry.Registry; import com.sk89q.worldedit.registry.state.AbstractProperty; import com.sk89q.worldedit.registry.state.Property; import com.sk89q.worldedit.registry.state.PropertyKey; @@ -49,7 +46,6 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Locale; import java.util.Map; -import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; diff --git a/worldedit-core/src/test/java/com/sk89q/worldedit/util/VariedVectorsProvider.java b/worldedit-core/src/test/java/com/sk89q/worldedit/util/VariedVectorsProvider.java new file mode 100644 index 000000000..10a835392 --- /dev/null +++ b/worldedit-core/src/test/java/com/sk89q/worldedit/util/VariedVectorsProvider.java @@ -0,0 +1,133 @@ +/* + * 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.util; + +import com.google.common.collect.AbstractIterator; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Streams; +import com.sk89q.worldedit.math.BlockVector3; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.ArgumentsProvider; +import org.junit.jupiter.params.provider.ArgumentsSource; +import org.junit.jupiter.params.support.AnnotationConsumer; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.util.Iterator; +import java.util.Set; +import java.util.stream.Stream; + +/** + * Argument provider for various vectors. + */ +public final class VariedVectorsProvider implements ArgumentsProvider, AnnotationConsumer { + + @Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD }) + @Retention(RetentionPolicy.RUNTIME) + @Documented + @ArgumentsSource(VariedVectorsProvider.class) + @ParameterizedTest(name = ParameterizedTest.ARGUMENTS_PLACEHOLDER) + public @interface Test { + + /** + * If {@code true}, provide a non-matching vector from + * the existing vectors set as well. This will nearly + * square the number of tests executed, since it will + * test every non-matching vector. + */ + boolean provideNonMatching() default false; + + } + + private static final int WORLD_XZ_MINMAX = 30_000_000; + private static final long WORLD_Y_MAX = Integer.MAX_VALUE; + private static final long WORLD_Y_MIN = Integer.MIN_VALUE; + + // For better coverage assurance, increase these values for a local Gradle run. + // Don't do it for IntelliJ, it'll probably run out of memory. + private static final int DIVISIONS_XZ = Integer.getInteger("variedvecs.divisions.xz", 5); + private static final int DIVISIONS_Y = Integer.getInteger("variedvecs.divisions.y", 5); + + private static final int XZ_STEP = (WORLD_XZ_MINMAX * 2) / DIVISIONS_XZ; + private static final long Y_STEP = (WORLD_Y_MAX * 2) / DIVISIONS_Y; + + private static final Set ALWAYS_INCLUDE = + ImmutableSet.of(BlockVector3.ZERO, BlockVector3.ONE, + BlockVector3.at(-WORLD_XZ_MINMAX, 0, -WORLD_XZ_MINMAX), + BlockVector3.at(WORLD_XZ_MINMAX, 0, WORLD_XZ_MINMAX), + BlockVector3.at(-WORLD_XZ_MINMAX, WORLD_Y_MAX, -WORLD_XZ_MINMAX), + BlockVector3.at(WORLD_XZ_MINMAX, WORLD_Y_MAX, WORLD_XZ_MINMAX)); + + private boolean provideNonMatching; + + @Override + public void accept(Test test) { + provideNonMatching = test.provideNonMatching(); + } + + @Override + public Stream provideArguments(ExtensionContext context) { + if (provideNonMatching) { + return makeVectorsStream() + .flatMap(vec -> makeVectorsStream().filter(v -> !v.equals(vec)) + .map(v -> Arguments.of(vec, v))); + } + return makeVectorsStream().map(Arguments::of); + } + + public static Stream makeVectorsStream() { + return Stream.concat( + ALWAYS_INCLUDE.stream(), + Streams.stream(generateVectors()).filter(v -> !ALWAYS_INCLUDE.contains(v)) + ); + } + + private static Iterator generateVectors() { + return new AbstractIterator() { + + private int x = -WORLD_XZ_MINMAX + 1; + private int z = -WORLD_XZ_MINMAX + 1; + private long y = WORLD_Y_MAX; + + @Override + protected BlockVector3 computeNext() { + if (x > WORLD_XZ_MINMAX) { + return endOfData(); + } + BlockVector3 newVector = BlockVector3.at(x, (int) y, z); + y += Y_STEP; + if (y > WORLD_Y_MAX) { + y = 0; + z += XZ_STEP; + if (z > WORLD_XZ_MINMAX) { + z = -WORLD_XZ_MINMAX; + x += XZ_STEP; + } + } + return newVector; + } + }; + } +} diff --git a/worldedit-core/src/test/java/com/sk89q/worldedit/util/eventbus/EventBusTest.java b/worldedit-core/src/test/java/com/sk89q/worldedit/util/eventbus/EventBusTest.java new file mode 100644 index 000000000..3e85c6fee --- /dev/null +++ b/worldedit-core/src/test/java/com/sk89q/worldedit/util/eventbus/EventBusTest.java @@ -0,0 +1,71 @@ +/* + * 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.util.eventbus; + +import static java.util.Arrays.asList; +import static java.util.Collections.singletonList; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.ArrayList; +import java.util.List; +import org.junit.jupiter.api.Test; + +public class EventBusTest { + + private static final class Event { + + } + + private static final class Subscriber { + + private final List events = new ArrayList<>(); + + @Subscribe + public void onEvent(Event event) { + events.add(event); + } + + } + + private EventBus eventBus = new EventBus(); + + @Test + public void testRegister() { + Subscriber subscriber = new Subscriber(); + eventBus.register(subscriber); + Event e1 = new Event(); + eventBus.post(e1); + Event e2 = new Event(); + eventBus.post(e2); + assertEquals(asList(e1, e2), subscriber.events); + } + + @Test + public void testUnregister() { + Subscriber subscriber = new Subscriber(); + eventBus.register(subscriber); + Event e1 = new Event(); + eventBus.post(e1); + eventBus.unregister(subscriber); + Event e2 = new Event(); + eventBus.post(e2); + assertEquals(singletonList(e1), subscriber.events); + } +}