state stuff

This commit is contained in:
kashike 2018-07-05 16:16:52 -07:00 committed by Matthew Miller
parent 40a665a509
commit ee6af8ee76
15 changed files with 99 additions and 218 deletions

View File

@ -22,14 +22,13 @@
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.StringTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.registry.state.Property;
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 com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.world.registry.LegacyMapper;
import com.sk89q.worldedit.registry.state.State;
import com.sk89q.worldedit.registry.state.value.StateValue;
import java.util.Map;
import java.util.Objects;
@ -131,7 +130,7 @@ public int getData() {
* @return The state map
*/
@Override
public Map<State, StateValue> getStates() {
public Map<Property<?>, Object> getStates() {
return this.blockState.getStates();
}
@ -141,19 +140,19 @@ public BlockType getBlockType() {
}
@Override
public BaseBlock with(State state, StateValue value) {
return new BaseBlock(this.blockState.with(state, value), getNbtData());
public <V> BaseBlock with(Property<V> property, V value) {
return new BaseBlock(this.blockState.with(property, value), getNbtData());
}
/**
* Gets the State for this Block.
*
* @param state The state to get the value for
* @param property The state to get the value for
* @return The state value
*/
@Override
public StateValue getState(State state) {
return this.blockState.getState(state);
public <V> V getState(Property<V> property) {
return this.blockState.getState(property);
}
@Override

View File

@ -44,8 +44,7 @@
import com.sk89q.worldedit.util.HandSide;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.registry.BundledBlockData;
import com.sk89q.worldedit.registry.state.State;
import com.sk89q.worldedit.registry.state.value.StateValue;
import com.sk89q.worldedit.registry.state.Property;
import java.util.HashMap;
import java.util.Map;
@ -163,16 +162,16 @@ private static BlockState applyProperties(BlockState state, String[] stateProper
throw new NoMatchException("Bad state format in " + parseableData);
}
State stateKey = BundledBlockData.getInstance().findById(state.getBlockType().getId()).states.get(parts[0]);
if (stateKey == null) {
Property propertyKey = BundledBlockData.getInstance().findById(state.getBlockType().getId()).states.get(parts[0]);
if (propertyKey == null) {
throw new NoMatchException("Unknown state " + parts[0] + " for block " + state.getBlockType().getName());
}
StateValue value = stateKey.getValueFor(parts[1]);
Object value = propertyKey.getValueFor(parts[1]);
if (value == null) {
throw new NoMatchException("Unknown value " + parts[1] + " for state " + parts[0]);
}
state = state.with(stateKey, value);
state = state.with(propertyKey, value);
} catch (NoMatchException e) {
throw e; // Pass-through
} catch (Exception e) {
@ -186,7 +185,7 @@ private static BlockState applyProperties(BlockState state, String[] stateProper
private BlockStateHolder parseLogic(String input, ParserContext context) throws InputParseException {
BlockType blockType;
Map<State, StateValue> blockStates = new HashMap<>();
Map<Property<?>, Object> blockStates = new HashMap<>();
String[] blockAndExtraData = input.trim().split("\\|");
blockAndExtraData[0] = woolMapper(blockAndExtraData[0]);
Matcher matcher = blockStatePattern.matcher(blockAndExtraData[0]);

View File

@ -32,8 +32,8 @@
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.math.transform.Transform;
import com.sk89q.worldedit.registry.state.DirectionalState;
import com.sk89q.worldedit.registry.state.State;
import com.sk89q.worldedit.registry.state.DirectionalProperty;
import com.sk89q.worldedit.registry.state.Property;
import com.sk89q.worldedit.registry.state.value.DirectionalStateValue;
import java.util.Map;
@ -128,20 +128,20 @@ private static <T extends BlockStateHolder> T transform(T block, Transform trans
checkNotNull(block);
checkNotNull(transform);
Map<String, ? extends State> states = WorldEdit.getInstance().getPlatformManager()
Map<String, ? extends Property> states = WorldEdit.getInstance().getPlatformManager()
.queryCapability(Capability.GAME_HOOKS).getRegistries().getBlockRegistry().getStates(block);
if (states == null) {
return changedBlock;
}
for (State state : states.values()) {
if (state instanceof DirectionalState) {
DirectionalStateValue value = (DirectionalStateValue) block.getState(state);
if (value != null && value.getData() != null) {
DirectionalStateValue newValue = getNewStateValue((DirectionalState) state, transform, value.getDirection());
for (Property property : states.values()) {
if (property instanceof DirectionalProperty) {
DirectionalStateValue value = (DirectionalStateValue) block.getState(property);
if (value != null) {
DirectionalStateValue newValue = getNewStateValue((DirectionalProperty) property, transform, value.getDirection());
if (newValue != null) {
changedBlock.with(state, newValue);
changedBlock.with(property, newValue);
}
}
}
@ -159,7 +159,7 @@ private static <T extends BlockStateHolder> T transform(T block, Transform trans
* @return a new state or null if none could be found
*/
@Nullable
private static DirectionalStateValue getNewStateValue(DirectionalState state, Transform transform, Vector oldDirection) {
private static DirectionalStateValue getNewStateValue(DirectionalProperty state, Transform transform, Vector oldDirection) {
Vector newDirection = transform.apply(oldDirection).subtract(transform.apply(Vector.ZERO)).normalize();
DirectionalStateValue newValue = null;
double closest = -2;

View File

@ -17,36 +17,31 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.registry.state.value;
package com.sk89q.worldedit.registry.state;
import java.util.Objects;
import static com.google.common.base.Preconditions.checkState;
public class SimpleStateValue implements StateValue {
public abstract class AbstractProperty<T> implements Property<T> {
private String data;
private String name;
@Override
public boolean isSet() {
return data != null;
public AbstractProperty() {
}
public AbstractProperty(final String name) {
this.name = name;
}
@Override
public void set(String data) {
this.data = data;
public String getName() {
return this.name;
}
@Override
public String getData() {
return this.data;
}
@Override
public boolean equals(Object obj) {
return obj instanceof StateValue && Objects.equals(((StateValue) obj).getData(), getData());
}
@Override
public int hashCode() {
return this.data.hashCode();
/**
* Internal method for name setting post-deserialise. Do not use.
*/
public void setName(final String name) {
checkState(this.name == null, "name already set");
this.name = name;
}
}

View File

@ -23,9 +23,17 @@
import java.util.List;
public class DirectionalState extends SimpleState<DirectionalStateValue> {
import javax.annotation.Nullable;
public DirectionalState(List<DirectionalStateValue> values) {
super(values);
public class DirectionalProperty extends AbstractProperty<DirectionalStateValue> {
@Override
public List<DirectionalStateValue> getValues() {
return null;
}
@Nullable
@Override
public DirectionalStateValue getValueFor(final String string) {
return null;
}
}

View File

@ -19,8 +19,6 @@
package com.sk89q.worldedit.registry.state;
import com.sk89q.worldedit.registry.state.value.SimpleStateValue;
import java.util.List;
import javax.annotation.Nullable;
@ -31,7 +29,7 @@
* <p>Example states include "variant" (indicating material or type) and
* "facing" (indicating orientation).</p>
*/
public interface State<T extends SimpleStateValue> {
public interface Property<T> {
/**
* Returns the name of this state.

View File

@ -1,66 +0,0 @@
/*
* 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 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 <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.registry.state;
import com.sk89q.worldedit.registry.state.value.SimpleStateValue;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import javax.annotation.Nullable;
public class SimpleState<T extends SimpleStateValue> implements State<T> {
private String name;
private List<T> values;
/**
* Creates a state with values
*
* @param values The values
*/
public SimpleState(List<T> values) {
this.name = "Unknown";
this.values = values;
}
/**
* Internal method for name setting post-deserialise. Do not use.
*/
public void setName(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
@Override
public List<T> getValues() {
return Collections.unmodifiableList(values);
}
@Nullable
@Override
public T getValueFor(String string) {
return values.stream().filter(value -> Objects.equals(value.getData(), string)).findFirst().orElse(null);
}
}

View File

@ -21,7 +21,7 @@
import com.sk89q.worldedit.Vector;
public class DirectionalStateValue extends SimpleStateValue {
public class DirectionalStateValue {
public Vector getDirection() {
return new Vector(); // TODO

View File

@ -1,49 +0,0 @@
/*
* 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 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 <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.registry.state.value;
import javax.annotation.Nullable;
/**
* Describes a possible value for a {@code State}.
*/
public interface StateValue {
/**
* Return whether this state is set on the given block.
*
* @return true if this value is set
*/
boolean isSet();
/**
* Set the state to the given value.
*/
void set(String data);
/**
* Returns the data associated with this value.
*
* @return The data, otherwise null
*/
@Nullable
String getData();
}

View File

@ -23,8 +23,7 @@
import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Maps;
import com.google.common.collect.Table;
import com.sk89q.worldedit.registry.state.State;
import com.sk89q.worldedit.registry.state.value.StateValue;
import com.sk89q.worldedit.registry.state.Property;
import java.util.ArrayList;
import java.util.Collections;
@ -39,11 +38,11 @@
public class BlockState implements BlockStateHolder<BlockState> {
private final BlockType blockType;
private final Map<State, StateValue> values;
private final Map<Property<?>, Object> values;
private final boolean fuzzy;
// Neighbouring state table.
private Table<State, StateValue, BlockState> states;
private Table<Property<?>, Object, BlockState> states;
BlockState(BlockType blockType) {
this.blockType = blockType;
@ -57,21 +56,21 @@ public class BlockState implements BlockStateHolder<BlockState> {
* @param blockType The block type
* @param values The block state values
*/
public BlockState(BlockType blockType, Map<State, StateValue> values) {
public BlockState(BlockType blockType, Map<Property<?>, Object> values) {
this.blockType = blockType;
this.values = values;
this.fuzzy = true;
}
public void populate(Map<Map<State, StateValue>, BlockState> stateMap) {
final Table<State, StateValue, BlockState> states = HashBasedTable.create();
public void populate(Map<Map<Property<?>, Object>, BlockState> stateMap) {
final Table<Property<?>, Object, BlockState> states = HashBasedTable.create();
for(final Map.Entry<State, StateValue> entry : this.values.entrySet()) {
final State state = entry.getKey();
for(final Map.Entry<Property<?>, Object> entry : this.values.entrySet()) {
final Property property = entry.getKey();
state.getValues().forEach(value -> {
property.getValues().forEach(value -> {
if(value != entry.getValue()) {
states.put(state, (StateValue) value, stateMap.get(this.withValue(state, (StateValue) value)));
states.put(property, value, stateMap.get(this.withValue(property, value)));
}
});
}
@ -79,8 +78,8 @@ public void populate(Map<Map<State, StateValue>, BlockState> stateMap) {
this.states = states.isEmpty() ? states : ArrayTable.create(states);
}
private Map<State, StateValue> withValue(final State property, final StateValue value) {
final Map<State, StateValue> values = Maps.newHashMap(this.values);
private <V> Map<Property<?>, Object> withValue(final Property<V> property, final V value) {
final Map<Property<?>, Object> values = Maps.newHashMap(this.values);
values.put(property, value);
return values;
}
@ -91,22 +90,22 @@ public BlockType getBlockType() {
}
@Override
public BlockState with(State state, StateValue value) {
public <V> BlockState with(final Property<V> property, final V value) {
if (fuzzy) {
return setState(state, value);
return setState(property, value);
} else {
BlockState result = states.get(state, value);
BlockState result = states.get(property, value);
return result == null ? this : result;
}
}
@Override
public StateValue getState(State state) {
return this.values.get(state);
public <V> V getState(final Property<V> property) {
return (V) this.values.get(property);
}
@Override
public Map<State, StateValue> getStates() {
public Map<Property<?>, Object> getStates() {
return Collections.unmodifiableMap(this.values);
}
@ -120,20 +119,20 @@ public boolean equalsFuzzy(BlockStateHolder o) {
return false;
}
List<State> differingStates = new ArrayList<>();
List<Property> differingProperties = new ArrayList<>();
for (Object state : o.getStates().keySet()) {
if (getState((State) state) == null) {
differingStates.add((State) state);
if (getState((Property) state) == null) {
differingProperties.add((Property) state);
}
}
for (State state : getStates().keySet()) {
if (o.getState(state) == null) {
differingStates.add(state);
for (Property property : getStates().keySet()) {
if (o.getState(property) == null) {
differingProperties.add(property);
}
}
for (State state : differingStates) {
if (!getState(state).equals(o.getState(state))) {
for (Property property : differingProperties) {
if (!getState(property).equals(o.getState(property))) {
return false;
}
}
@ -151,12 +150,12 @@ public BlockState toImmutableState() {
*
* Sets a value. DO NOT USE THIS.
*
* @param state The state
* @param property The state
* @param value The value
* @return The blockstate, for chaining
*/
private BlockState setState(State state, StateValue value) {
this.values.put(state, value);
private <V> BlockState setState(final Property<V> property, final V value) {
this.values.put(property, value);
return this;
}
}

View File

@ -19,8 +19,7 @@
package com.sk89q.worldedit.world.block;
import com.sk89q.worldedit.registry.state.State;
import com.sk89q.worldedit.registry.state.value.StateValue;
import com.sk89q.worldedit.registry.state.Property;
import java.util.Map;
@ -36,26 +35,26 @@ public interface BlockStateHolder<T extends BlockStateHolder> {
/**
* Returns a BlockState with the given state and value applied.
*
* @param state The state
* @param property The state
* @param value The value
* @return The modified state, or same if could not be applied
*/
T with(State state, StateValue value);
<V> T with(final Property<V> property, final V value);
/**
* Gets the value at the given state
*
* @param state The state
* @param property The state
* @return The value
*/
StateValue getState(State state);
<V> V getState(Property<V> property);
/**
* Gets an immutable collection of the states.
*
* @return The states
*/
Map<State, StateValue> getStates();
Map<Property<?>, Object> getStates();
/**
* Checks if the type is the same, and if the matched states are the same.

View File

@ -22,7 +22,7 @@
import com.sk89q.worldedit.blocks.BlockMaterial;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.registry.state.State;
import com.sk89q.worldedit.registry.state.Property;
import java.util.Map;
@ -58,6 +58,6 @@ public interface BlockRegistry {
* @return a map of states where the key is the state's ID
*/
@Nullable
Map<String, ? extends State> getStates(BlockStateHolder block);
Map<String, ? extends Property> getStates(BlockStateHolder block);
}

View File

@ -25,9 +25,9 @@
import com.google.gson.reflect.TypeToken;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.blocks.BlockMaterial;
import com.sk89q.worldedit.registry.state.Property;
import com.sk89q.worldedit.util.gson.VectorAdapter;
import com.sk89q.worldedit.registry.state.SimpleState;
import com.sk89q.worldedit.registry.state.State;
import com.sk89q.worldedit.registry.state.AbstractProperty;
import javax.annotation.Nullable;
import java.io.IOException;
@ -128,7 +128,7 @@ public BlockMaterial getMaterialById(String id) {
* @return the block's states, or null if no information is available
*/
@Nullable
public Map<String, ? extends State> getStatesById(String id) {
public Map<String, ? extends Property> getStatesById(String id) {
BlockEntry entry = findById(id);
if (entry != null) {
return entry.states;
@ -151,11 +151,11 @@ public static class BlockEntry {
private String unlocalizedName;
public String localizedName;
private List<String> aliases;
public Map<String, SimpleState> states = new HashMap<>();
public Map<String, AbstractProperty> states = new HashMap<>();
private SimpleBlockMaterial material = new SimpleBlockMaterial();
void postDeserialization() {
for (Map.Entry<String, SimpleState> state : states.entrySet()) {
for (Map.Entry<String, AbstractProperty> state : states.entrySet()) {
state.getValue().setName(state.getKey());
}
}

View File

@ -20,10 +20,10 @@
package com.sk89q.worldedit.world.registry;
import com.sk89q.worldedit.blocks.BlockMaterial;
import com.sk89q.worldedit.registry.state.Property;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.registry.state.State;
import java.util.Map;
@ -49,7 +49,7 @@ public BlockMaterial getMaterial(String id) {
@Nullable
@Override
public Map<String, ? extends State> getStates(BlockStateHolder block) {
public Map<String, ? extends Property> getStates(BlockStateHolder block) {
return BundledBlockData.getInstance().getStatesById(block.getBlockType().getId());
}

View File

@ -27,6 +27,7 @@
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BaseItemStack;
import com.sk89q.worldedit.registry.state.Property;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.item.ItemTypes;
import com.sk89q.worldedit.entity.BaseEntity;
@ -35,8 +36,6 @@
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.world.AbstractWorld;
import com.sk89q.worldedit.world.biome.BaseBiome;
import com.sk89q.worldedit.registry.state.State;
import com.sk89q.worldedit.registry.state.value.StateValue;
import org.spongepowered.api.Sponge;
import org.spongepowered.api.block.BlockSnapshot;
import org.spongepowered.api.block.BlockState;
@ -116,7 +115,7 @@ public String getName() {
protected BlockState getBlockState(BlockStateHolder<?> block) {
if (block instanceof com.sk89q.worldedit.world.block.BlockState) {
BlockState state = Sponge.getRegistry().getType(BlockType.class, block.getBlockType().getId()).orElse(BlockTypes.AIR).getDefaultState();
for (Map.Entry<State, StateValue> entry : block.getStates().entrySet()) {
for (Map.Entry<Property<?>, Object> entry : block.getStates().entrySet()) {
// TODO Convert across states
}
return state;