diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeAdapter.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeAdapter.java index 22f6fea5c6..851b121df6 100644 --- a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeAdapter.java +++ b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeAdapter.java @@ -19,31 +19,41 @@ package com.sk89q.worldedit.sponge; -import com.sk89q.worldedit.WorldEdit; -import com.sk89q.worldedit.extension.input.InputParseException; -import com.sk89q.worldedit.extension.input.ParserContext; +import com.google.common.collect.ImmutableList; import com.sk89q.worldedit.internal.block.BlockStateIdAccess; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.Vector3; +import com.sk89q.worldedit.registry.state.BooleanProperty; +import com.sk89q.worldedit.registry.state.DirectionalProperty; +import com.sk89q.worldedit.registry.state.EnumProperty; +import com.sk89q.worldedit.registry.state.IntegerProperty; +import com.sk89q.worldedit.registry.state.Property; import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.biome.BiomeTypes; 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 it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.Sponge; import org.spongepowered.api.entity.living.player.Player; import org.spongepowered.api.entity.living.player.server.ServerPlayer; +import org.spongepowered.api.state.BooleanStateProperty; +import org.spongepowered.api.state.EnumStateProperty; +import org.spongepowered.api.state.IntegerStateProperty; +import org.spongepowered.api.state.StateProperty; +import org.spongepowered.api.util.Direction; import org.spongepowered.api.world.ServerLocation; +import org.spongepowered.api.world.schematic.PaletteTypes; import org.spongepowered.api.world.server.ServerWorld; import org.spongepowered.math.vector.Vector3d; import org.spongepowered.math.vector.Vector3i; -import java.util.HashMap; -import java.util.Map; +import java.util.stream.Collectors; import static com.google.common.base.Preconditions.checkNotNull; @@ -55,12 +65,6 @@ public class SpongeAdapter { private SpongeAdapter() { } - private static final ParserContext TO_BLOCK_CONTEXT = new ParserContext(); - - static { - TO_BLOCK_CONTEXT.setRestricted(false); - } - /** * Create a WorldEdit world from a Sponge world. * @@ -113,6 +117,14 @@ public static ServerWorld adapt(World world) { } } + public static BlockType adapt(org.spongepowered.api.block.BlockType blockType) { + return BlockTypes.get(blockType.getKey().getFormatted()); + } + + public static org.spongepowered.api.block.BlockType adapt(BlockType blockType) { + return Sponge.getRegistry().getCatalogRegistry().get(org.spongepowered.api.block.BlockType.class, ResourceKey.resolve(blockType.getId())).orElse(null); + } + public static BiomeType adapt(org.spongepowered.api.world.biome.BiomeType biomeType) { return BiomeTypes.get(biomeType.getKey().getFormatted()); } @@ -204,7 +216,44 @@ public static Vector3i adapt(BlockVector3 vec) { return new Vector3i(vec.getX(), vec.getY(), vec.getZ()); } - private static final Map blockStateStringCache = new HashMap<>(); + public static com.sk89q.worldedit.util.Direction adapt(Direction direction) { + if (direction == null) { + return null; + } + switch (direction) { + case NORTH: return com.sk89q.worldedit.util.Direction.NORTH; + case SOUTH: return com.sk89q.worldedit.util.Direction.SOUTH; + case WEST: return com.sk89q.worldedit.util.Direction.WEST; + case EAST: return com.sk89q.worldedit.util.Direction.EAST; + case DOWN: return com.sk89q.worldedit.util.Direction.DOWN; + case UP: + default: + return com.sk89q.worldedit.util.Direction.UP; + } + } + + @SuppressWarnings("unchecked") + public static Property adaptProperty(StateProperty property) { + if (property instanceof BooleanStateProperty) { + return new BooleanProperty(property.getName(), ImmutableList.copyOf(((BooleanStateProperty) property).getPossibleValues())); + } + if (property instanceof IntegerStateProperty) { + return new IntegerProperty(property.getName(), ImmutableList.copyOf(((IntegerStateProperty) property).getPossibleValues())); + } + if (property instanceof EnumStateProperty) { + if (property.getPossibleValues().stream().anyMatch(ent -> ent instanceof Direction)) { + return new DirectionalProperty(property.getName(), ((EnumStateProperty) property).getPossibleValues() + .stream() + .map(SpongeAdapter::adapt) + .collect(Collectors.toList())); + } else { + return new EnumProperty(property.getName(), ((EnumStateProperty) property).getPossibleValues().stream() + .map(Enum::name) + .collect(Collectors.toList())); + } + } + return new SpongePropertyAdapter<>(property); + } /** * Create a WorldEdit BlockState from a Sponge BlockState. @@ -215,18 +264,10 @@ public static Vector3i adapt(BlockVector3 vec) { public static BlockState adapt(org.spongepowered.api.block.BlockState blockState) { checkNotNull(blockState); - // TODO Support properties - return blockStateStringCache.computeIfAbsent(blockState.getType().getKey().toString(), input -> { - try { - return WorldEdit.getInstance().getBlockFactory().parseFromInput(input, TO_BLOCK_CONTEXT).toImmutableState(); - } catch (InputParseException e) { - e.printStackTrace(); - return null; - } - }); + return BlockStateIdAccess.getBlockStateById(PaletteTypes.GLOBAL_BLOCKS.get().create().getOrAssign(blockState)); } - private static final Int2ObjectMap blockDataCache = new Int2ObjectOpenHashMap<>(); + private static final Int2ObjectMap spongeBlockStateCache = new Int2ObjectOpenHashMap<>(); /** * Create a Sponge BlockState from a WorldEdit BlockStateHolder. @@ -242,11 +283,7 @@ public static > org.spongepowered.api.block.BlockS cacheKey = block.hashCode(); } - // TODO Support properties - return blockDataCache.computeIfAbsent(cacheKey, input -> Sponge.getRegistry().getCatalogRegistry().get( - org.spongepowered.api.block.BlockState.class, - ResourceKey.resolve(block.getBlockType().getId()) - ).orElse(null)); + return spongeBlockStateCache.computeIfAbsent(cacheKey, input -> PaletteTypes.GLOBAL_BLOCKS.get().create().get(input).orElse(null)); } } diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeBlockRegistry.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeBlockRegistry.java new file mode 100644 index 0000000000..bd58b5d159 --- /dev/null +++ b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeBlockRegistry.java @@ -0,0 +1,66 @@ +/* + * 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 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.sponge; + +import com.sk89q.worldedit.registry.state.Property; +import com.sk89q.worldedit.util.formatting.text.Component; +import com.sk89q.worldedit.world.block.BlockState; +import com.sk89q.worldedit.world.block.BlockType; +import com.sk89q.worldedit.world.registry.BundledBlockRegistry; +import org.spongepowered.api.state.StateProperty; +import org.spongepowered.api.world.schematic.PaletteTypes; + +import java.util.Locale; +import java.util.Map; +import java.util.OptionalInt; +import java.util.TreeMap; +import javax.annotation.Nullable; + +public class SpongeBlockRegistry extends BundledBlockRegistry { + + @Override + public Component getRichName(BlockType blockType) { + return SpongeTextAdapter.convert(SpongeAdapter.adapt(blockType).asComponent()); + } + + @Nullable + @Override + public Map> getProperties(BlockType blockType) { + Map> map = new TreeMap<>(); + org.spongepowered.api.block.BlockType type = SpongeAdapter.adapt(blockType); + for (StateProperty stateProperty : type.getStateProperties()) { + map.put(stateProperty.getName(), SpongeAdapter.adaptProperty(stateProperty)); + } + return map; + } + + @Override + public OptionalInt getInternalBlockStateId(BlockState state) { + // TODO Fixup when string parsing exists. This is pretty messy. + org.spongepowered.api.block.BlockType spongeType = SpongeAdapter.adapt(state.getBlockType()); + org.spongepowered.api.block.BlockState workingState = spongeType.getDefaultState(); + for (Property property : state.getBlockType().getProperties()) { + StateProperty spongeProp = spongeType.getStatePropertyByName(property.getName()).get(); + Object val = spongeProp.parseValue(state.getState(property).toString().toLowerCase(Locale.ENGLISH)).get(); + workingState = (org.spongepowered.api.block.BlockState) workingState.withStateProperty(spongeProp, (Comparable) val).get(); + } + return OptionalInt.of(PaletteTypes.GLOBAL_BLOCKS.get().create().getOrAssign(workingState)); + } +} diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongePropertyAdapter.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongePropertyAdapter.java new file mode 100644 index 0000000000..9b8dbf56e3 --- /dev/null +++ b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongePropertyAdapter.java @@ -0,0 +1,75 @@ +/* + * 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 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.sponge; + +import com.google.common.collect.ImmutableList; +import com.sk89q.worldedit.registry.state.Property; +import org.spongepowered.api.state.StateProperty; + +import java.util.List; +import java.util.Optional; +import javax.annotation.Nullable; + +import static com.google.common.base.Preconditions.checkArgument; + +public class SpongePropertyAdapter> implements Property { + + private final StateProperty property; + private final List values; + + public SpongePropertyAdapter(StateProperty property) { + this.property = property; + this.values = ImmutableList.copyOf(property.getPossibleValues()); + } + + @Override + public String getName() { + return this.property.getName(); + } + + @Override + public List getValues() { + return this.values; + } + + @Nullable + @Override + public T getValueFor(String string) throws IllegalArgumentException { + Optional val = property.parseValue(string); + checkArgument(val.isPresent(), "%s has no value for %s", getName(), string); + return val.get(); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + return getName().equals(((Property) o).getName()); + } + + @Override + public int hashCode() { + return property.getName().hashCode(); + } +} diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeRegistries.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeRegistries.java index 47b83250e2..d385958875 100644 --- a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeRegistries.java +++ b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeRegistries.java @@ -20,6 +20,7 @@ package com.sk89q.worldedit.sponge; import com.sk89q.worldedit.world.registry.BiomeRegistry; +import com.sk89q.worldedit.world.registry.BlockRegistry; import com.sk89q.worldedit.world.registry.BundledRegistries; /** @@ -29,10 +30,16 @@ class SpongeRegistries extends BundledRegistries { private static final SpongeRegistries INSTANCE = new SpongeRegistries(); private final BiomeRegistry biomeRegistry = new SpongeBiomeRegistry(); + private final BlockRegistry blockRegistry = new SpongeBlockRegistry(); @Override public BiomeRegistry getBiomeRegistry() { - return biomeRegistry; + return this.biomeRegistry; + } + + @Override + public BlockRegistry getBlockRegistry() { + return this.blockRegistry; } /** diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeWorldEdit.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeWorldEdit.java index b87100b79a..48a950e626 100644 --- a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeWorldEdit.java +++ b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeWorldEdit.java @@ -32,7 +32,6 @@ import com.sk89q.worldedit.sponge.adapter.SpongeImplAdapter; import com.sk89q.worldedit.sponge.adapter.SpongeImplLoader; import com.sk89q.worldedit.sponge.config.SpongeConfiguration; -import com.sk89q.worldedit.world.World; import net.kyori.adventure.audience.Audience; //import org.bstats.sponge.Metrics2; import org.slf4j.Logger; @@ -60,7 +59,6 @@ import org.spongepowered.api.item.inventory.ItemStack; import org.spongepowered.api.scheduler.Task; import org.spongepowered.api.world.ServerLocation; -import org.spongepowered.api.world.server.ServerWorld; import org.spongepowered.plugin.PluginContainer; import org.spongepowered.plugin.jvm.Plugin;