Skip to content

Commit

Permalink
Add proper property support
Browse files Browse the repository at this point in the history
  • Loading branch information
me4502 committed Nov 15, 2020
1 parent f2b8454 commit 8d5bf74
Show file tree
Hide file tree
Showing 5 changed files with 213 additions and 30 deletions.
Expand Up @@ -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;

Expand All @@ -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.
*
Expand Down Expand Up @@ -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());
}
Expand Down Expand Up @@ -204,7 +216,44 @@ public static Vector3i adapt(BlockVector3 vec) {
return new Vector3i(vec.getX(), vec.getY(), vec.getZ());
}

private static final Map<String, BlockState> 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<Direction>) 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.
Expand All @@ -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<org.spongepowered.api.block.BlockState> blockDataCache = new Int2ObjectOpenHashMap<>();
private static final Int2ObjectMap<org.spongepowered.api.block.BlockState> spongeBlockStateCache = new Int2ObjectOpenHashMap<>();

/**
* Create a Sponge BlockState from a WorldEdit BlockStateHolder.
Expand All @@ -242,11 +283,7 @@ public static <B extends BlockStateHolder<B>> 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));
}

}
@@ -0,0 +1,66 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* 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 <https://www.gnu.org/licenses/>.
*/

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<String, ? extends Property<?>> getProperties(BlockType blockType) {
Map<String, Property<?>> 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));
}
}
@@ -0,0 +1,75 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* 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 <https://www.gnu.org/licenses/>.
*/

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<T extends Comparable<T>> implements Property<T> {

private final StateProperty<T> property;
private final List<T> values;

public SpongePropertyAdapter(StateProperty<T> property) {
this.property = property;
this.values = ImmutableList.copyOf(property.getPossibleValues());
}

@Override
public String getName() {
return this.property.getName();
}

@Override
public List<T> getValues() {
return this.values;
}

@Nullable
@Override
public T getValueFor(String string) throws IllegalArgumentException {
Optional<T> 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();
}
}
Expand Up @@ -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;

/**
Expand All @@ -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;
}

/**
Expand Down
Expand Up @@ -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;
Expand Down Expand Up @@ -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;

Expand Down

0 comments on commit 8d5bf74

Please sign in to comment.