Copy paste/merge FAWE classes to this WorldEdit fork

- so certain people can look at the diff and complain about my sloppy code :(

Signed-off-by: Jesse Boyd <jessepaleg@gmail.com>
This commit is contained in:
Jesse Boyd
2018-08-13 00:03:07 +10:00
parent a920c77cb8
commit a629d15c74
994 changed files with 117583 additions and 10745 deletions

View File

@ -1,211 +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.world.block;
import static com.google.common.base.Preconditions.checkNotNull;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.StringTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.blocks.TileEntityBlock;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.registry.state.Property;
import java.util.Map;
import java.util.Objects;
import javax.annotation.Nullable;
/**
* Represents a mutable "snapshot" of a block.
*
* <p>An instance of this block contains all the information needed to
* accurately reproduce the block, provided that the instance was
* made correctly. In some implementations, it may not be possible to get a
* snapshot of blocks correctly, so, for example, the NBT data for a block
* may be missing.</p>
*
* <p>A peculiar detail of this class is that it accepts {@code -1} as a
* valid data value. This is due to legacy reasons: WorldEdit uses -1
* as a "wildcard" block value, even though a {@link Mask} would be
* more appropriate.</p>
*/
public class BaseBlock implements BlockStateHolder<BaseBlock>, TileEntityBlock {
private BlockState blockState;
@Nullable private CompoundTag nbtData;
/**
* Construct a block with a state.
*
* @param blockState The blockstate
*/
protected BaseBlock(BlockState blockState) {
this.blockState = blockState;
}
/**
* Construct a block with the given ID, data value and NBT data structure.
*
* @param state The block state
* @param nbtData NBT data, which must be provided
*/
protected BaseBlock(BlockState state, CompoundTag nbtData) {
checkNotNull(nbtData);
this.blockState = state;
this.nbtData = nbtData;
}
/**
* Create a clone of another block.
*
* @param other the other block
*/
public BaseBlock(BaseBlock other) {
this(other.toImmutableState(), other.getNbtData());
}
/**
* Gets a map of state to statevalue
*
* @return The state map
*/
@Override
public Map<Property<?>, Object> getStates() {
return this.blockState.getStates();
}
@Override
public BlockType getBlockType() {
return this.blockState.getBlockType();
}
@Override
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 property The state to get the value for
* @return The state value
*/
@Override
public <V> V getState(Property<V> property) {
return this.blockState.getState(property);
}
@Override
public boolean hasNbtData() {
return getNbtData() != null;
}
@Override
public String getNbtId() {
CompoundTag nbtData = getNbtData();
if (nbtData == null) {
return "";
}
Tag idTag = nbtData.getValue().get("id");
if (idTag instanceof StringTag) {
return ((StringTag) idTag).getValue();
} else {
return "";
}
}
@Nullable
@Override
public CompoundTag getNbtData() {
return this.nbtData;
}
@Override
public void setNbtData(@Nullable CompoundTag nbtData) {
throw new UnsupportedOperationException("This class is immutable.");
}
/**
* Checks whether the type ID and data value are equal.
*/
@Override
public boolean equals(Object o) {
if (!(o instanceof BaseBlock)) {
return false;
}
final BaseBlock otherBlock = (BaseBlock) o;
return this.toImmutableState().equals(otherBlock.toImmutableState()) && Objects.equals(getNbtData(), otherBlock.getNbtData());
}
/**
* Checks if the type is the same, and if the matched states are the same.
*
* @param o other block
* @return true if equal
*/
@Override
public boolean equalsFuzzy(BlockStateHolder o) {
return this.toImmutableState().equalsFuzzy(o);
}
@Override
public BlockState toImmutableState() {
return this.blockState;
}
@Override
public BaseBlock toBaseBlock() {
return this;
}
@Override
public BaseBlock toBaseBlock(CompoundTag compoundTag) {
if (compoundTag == null) {
return this.blockState.toBaseBlock();
} else if (compoundTag == this.nbtData) {
return this;
} else {
return new BaseBlock(this.blockState, compoundTag);
}
}
@Override
public int hashCode() {
int ret = toImmutableState().hashCode() << 3;
if (hasNbtData()) {
ret += getNbtData().hashCode();
}
return ret;
}
@Override
public String toString() {
// if (getNbtData() != null) { // TODO Maybe make some JSON serialiser to make this not awful.
// return blockState.getAsString() + " {" + String.valueOf(getNbtData()) + "}";
// } else {
return blockState.getAsString();
// }
}
}

View File

@ -19,24 +19,25 @@
package com.sk89q.worldedit.world.block;
import com.google.common.collect.ArrayTable;
import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Lists;
import com.boydti.fawe.object.string.MutableCharSequence;
import com.google.common.base.Function;
import com.google.common.collect.Maps;
import com.google.common.collect.Table;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.TileEntityBlock;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.mask.SingleBlockStateMask;
import com.sk89q.worldedit.function.pattern.FawePattern;
import com.sk89q.worldedit.registry.state.AbstractProperty;
import com.sk89q.worldedit.registry.state.Property;
import com.sk89q.worldedit.registry.state.PropertyKey;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import javax.annotation.Nullable;
import java.util.*;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* An immutable class that represents the state a block can be in.
@ -44,130 +45,252 @@ import java.util.Set;
@SuppressWarnings("unchecked")
public class BlockState implements BlockStateHolder<BlockState> {
private final BlockType blockType;
private final Map<Property<?>, Object> values;
private final boolean fuzzy;
private final int internalId;
private BaseBlock emptyBaseBlock;
// Neighbouring state table.
private Table<Property<?>, Object, BlockState> states;
private BlockState(BlockType blockType) {
this.blockType = blockType;
this.values = new LinkedHashMap<>();
this.emptyBaseBlock = new BaseBlock(this);
this.fuzzy = false;
// TODO FIXME have field for BlockType & propertyId (to avoid all the bit shifting / masking)
protected BlockState(int internalId) {
this.internalId = internalId;
}
/**
* Creates a fuzzy BlockState. This can be used for partial matching.
*
* @param blockType The block type
* @param values The block state values
* Returns a temporary BlockState for a given internal id
* @param combinedId
* @deprecated magic number
* @return BlockState
*/
private BlockState(BlockType blockType, Map<Property<?>, Object> values) {
this.blockType = blockType;
this.values = values;
this.fuzzy = true;
@Deprecated
public static BlockState get(int combinedId) {
return BlockTypes.getFromStateId(combinedId).withStateId(combinedId);
}
static Map<Map<Property<?>, Object>, BlockState> generateStateMap(BlockType blockType) {
Map<Map<Property<?>, Object>, BlockState> stateMap = new LinkedHashMap<>();
List<? extends Property> properties = blockType.getProperties();
/**
* Returns a temporary BlockState for a given type and string
* @param state String e.g. minecraft:water[level=4]
* @return BlockState
*/
public static BlockState get(String state) {
return get(null, state);
}
if (!properties.isEmpty()) {
List<List<Object>> separatedValues = Lists.newArrayList();
for (Property prop : properties) {
List<Object> vals = Lists.newArrayList();
vals.addAll(prop.getValues());
separatedValues.add(vals);
/**
* Returns a temporary BlockState for a given type and string
* - It's faster if a BlockType is provided compared to parsing the string
* @param type BlockType e.g. BlockTypes.STONE (or null)
* @param state String e.g. minecraft:water[level=4]
* @return BlockState
*/
public static BlockState get(@Nullable BlockType type, String state) {
return get(type, state, 0);
}
/**
* Returns a temporary BlockState for a given type and string
* - It's faster if a BlockType is provided compared to parsing the string
* @param type BlockType e.g. BlockTypes.STONE (or null)
* @param state String e.g. minecraft:water[level=4]
* @return BlockState
*/
public static BlockState get(@Nullable BlockType type, String state, int propId) {
int propStrStart = state.indexOf('[');
if (type == null) {
CharSequence key;
if (propStrStart == -1) {
key = state;
} else {
MutableCharSequence charSequence = MutableCharSequence.getTemporal();
charSequence.setString(state);
charSequence.setSubstring(0, propStrStart);
key = charSequence;
}
List<List<Object>> valueLists = Lists.cartesianProduct(separatedValues);
for (List<Object> valueList : valueLists) {
Map<Property<?>, Object> valueMap = Maps.newTreeMap(Comparator.comparing(Property::getName));
BlockState stateMaker = new BlockState(blockType);
for (int i = 0; i < valueList.size(); i++) {
Property<?> property = properties.get(i);
Object value = valueList.get(i);
valueMap.put(property, value);
stateMaker.setState(property, value);
type = BlockTypes.get(key);
}
if (propStrStart == -1) {
return type.getDefaultState();
}
List<? extends Property> propList = type.getProperties();
MutableCharSequence charSequence = MutableCharSequence.getTemporal();
charSequence.setString(state);
if (propList.size() == 1) {
AbstractProperty property = (AbstractProperty) propList.get(0);
String name = property.getName();
charSequence.setSubstring(propStrStart + name.length() + 2, state.length() - 1);
return type.withPropertyId(property.getIndexFor(charSequence));
}
int stateId = type.getInternalId() + (propId << BlockTypes.BIT_OFFSET);
int length = state.length();
AbstractProperty property = null;
int last = propStrStart + 1;
for (int i = last; i < length; i++) {
char c = state.charAt(i);
switch (c) {
case ']':
case ',': {
charSequence.setSubstring(last, i);
int index = property.getIndexFor(charSequence);
stateId = property.modifyIndex(stateId, index);
last = i + 1;
break;
}
stateMap.put(valueMap, stateMaker);
case '=': {
charSequence.setSubstring(last, i);
property = (AbstractProperty) type.getPropertyMap().get(charSequence);
last = i + 1;
break;
}
default:
continue;
}
}
if (stateMap.isEmpty()) {
// No properties.
stateMap.put(new LinkedHashMap<>(), new BlockState(blockType));
}
for (BlockState state : stateMap.values()) {
state.populate(stateMap);
}
return stateMap;
}
private void populate(Map<Map<Property<?>, Object>, BlockState> stateMap) {
final Table<Property<?>, Object, BlockState> states = HashBasedTable.create();
for(final Map.Entry<Property<?>, Object> entry : this.values.entrySet()) {
final Property property = entry.getKey();
property.getValues().forEach(value -> {
if(value != entry.getValue()) {
BlockState modifiedState = stateMap.get(this.withValue(property, value));
if (modifiedState != null) {
states.put(property, value, modifiedState);
} else {
System.out.println(stateMap);
WorldEdit.logger.warning("Found a null state at " + this.withValue(property, value));
}
}
});
}
this.states = states.isEmpty() ? states : ArrayTable.create(states);
}
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;
return type.withPropertyId(stateId >> BlockTypes.BIT_OFFSET);
}
@Override
public BlockType getBlockType() {
return this.blockType;
public BlockState withPropertyId(int propertyId) {
return getBlockType().withPropertyId(propertyId);
}
@Override
public Mask toMask(Extent extent) {
return new SingleBlockStateMask(extent, this);
}
@Override
public boolean apply(Extent extent, Vector get, Vector set) throws WorldEditException {
return extent.setBlock(set, this);
}
@Override
public BlockState apply(Vector position) {
return this;
}
@Deprecated
public int getInternalId() {
return this.internalId;
}
@Override
public boolean hasNbtData() {
return getNbtData() != null;
}
@Override
public String getNbtId() {
return "";
}
@Nullable
@Override
public CompoundTag getNbtData() {
return null;
}
@Override
public void setNbtData(@Nullable CompoundTag nbtData) {
throw new UnsupportedOperationException("This class is immutable.");
}
/**
* The internal id with no type information
* @return
*/
@Deprecated
@Override
public final int getInternalPropertiesId() {
return this.getInternalId() >> BlockTypes.BIT_OFFSET;
}
@Override
public final BlockTypes getBlockType() {
return BlockTypes.get(this.getInternalId() & BlockTypes.BIT_MASK);
}
@Deprecated
@Override
public final int getInternalBlockTypeId() {
return this.getInternalId() & BlockTypes.BIT_MASK;
}
@Override
public <V> BlockState with(final Property<V> property, final V value) {
if (fuzzy) {
return setState(property, value);
} else {
BlockState result = states.get(property, value);
return result == null ? this : result;
try {
int newState = ((AbstractProperty) property).modify(this.getInternalId(), value);
return newState != this.getInternalId() ? new BlockState(newState) : this;
} catch (ClassCastException e) {
throw new IllegalArgumentException("Property not found: " + property);
}
}
@Override
public <V> V getState(final Property<V> property) {
return (V) this.values.get(property);
public <V> BlockState with(final PropertyKey property, final V value) {
try {
int newState = ((AbstractProperty) getBlockType().getProperty(property)).modify(this.getInternalId(), value);
return newState != this.getInternalId() ? new BlockState(newState) : this;
} catch (ClassCastException e) {
throw new IllegalArgumentException("Property not found: " + property);
}
}
@Override
public Map<Property<?>, Object> getStates() {
return Collections.unmodifiableMap(this.values);
public final <V> V getState(final Property<V> property) {
try {
AbstractProperty ap = (AbstractProperty) property;
return (V) ap.getValue(this.getInternalId());
} catch (ClassCastException e) {
throw new IllegalArgumentException("Property not found: " + property);
}
}
@Deprecated
@Override
public final <V> V getState(final PropertyKey key) {
return getState(getBlockType().getProperty(key));
}
@Override
@Deprecated
public final Map<Property<?>, Object> getStates() {
BlockType type = this.getBlockType();
// Lazily initialize the map
Map<? extends Property, Object> map = Maps.asMap(type.getPropertiesSet(), (Function<Property, Object>) input -> getState(input));
return (Map<Property<?>, Object>) map;
}
/**
* Deprecated, use masks - not try to this fuzzy/non fuzzy state nonsense
* @return
*/
@Deprecated
public BlockState toFuzzy() {
return new BlockState(this.getBlockType(), new HashMap<>());
return this;
}
@Override
public int hashCode() {
return getInternalId();
}
@Override
public boolean equals(Object obj) {
return this == obj;
}
@Override
@Deprecated
public boolean equalsFuzzy(BlockStateHolder o) {
try {
return o.getInternalId() == this.getInternalId();
} catch (ClassCastException e) {
// Shouldn't happen unless something modifies WorldEdit
e.printStackTrace();
}
if (!getBlockType().equals(o.getBlockType())) {
return false;
}
@ -201,38 +324,37 @@ public class BlockState implements BlockStateHolder<BlockState> {
return this;
}
@Override
public BaseBlock toBaseBlock() {
if (this.fuzzy) {
throw new IllegalArgumentException("Can't create a BaseBlock from a fuzzy BlockState!");
}
return this.emptyBaseBlock;
}
@Override
public BaseBlock toBaseBlock(CompoundTag compoundTag) {
if (compoundTag == null) {
return toBaseBlock();
}
return new BaseBlock(this, compoundTag);
}
/**
* Internal method used for creating the initial BlockState.
*
* Sets a value. DO NOT USE THIS.
*
* @param property The state
* @param value The value
* @return The blockstate, for chaining
*/
private BlockState setState(final Property<?> property, final Object value) {
this.values.put(property, value);
return this;
}
@Override
public String toString() {
return getAsString();
}
}

View File

@ -19,23 +19,58 @@
package com.sk89q.worldedit.world.block;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.blocks.TileEntityBlock;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.pattern.FawePattern;
import com.sk89q.worldedit.registry.state.Property;
import com.sk89q.worldedit.registry.state.PropertyKey;
import java.util.Map;
import java.util.stream.Collectors;
public interface BlockStateHolder<T extends BlockStateHolder> {
public interface BlockStateHolder<T extends BlockStateHolder> extends FawePattern, TileEntityBlock {
/**
* Get the block type
*
* @return The type
*/
BlockType getBlockType();
BlockTypes getBlockType();
/**
* Returns a BlockState with the given state and value applied.
* Magic number (legacy uses)
* @param propertyId
* @return
*/
@Deprecated
BlockStateHolder withPropertyId(int propertyId);
/**
* Get combined id (legacy uses)
* @return
*/
@Deprecated
int getInternalId();
/**
* Get type id (legacy uses)
* @return
*/
@Deprecated
int getInternalBlockTypeId();
/**
* Get the block data (legacy uses)
* @return
*/
@Deprecated
int getInternalPropertiesId();
Mask toMask(Extent extent);
/**
* Returns a BlockStateHolder with the given state and value applied.
*
* @param property The state
* @param value The value
@ -43,6 +78,15 @@ public interface BlockStateHolder<T extends BlockStateHolder> {
*/
<V> T with(final Property<V> property, final V value);
/**
* Returns a BlockStateHolder with the given state and value applied.
*
* @param property The property key
* @param value The value
* @return The modified state, or same if could not be applied
*/
<V> BlockStateHolder with(final PropertyKey property, final V value);
/**
* Gets the value at the given state
*
@ -51,6 +95,14 @@ public interface BlockStateHolder<T extends BlockStateHolder> {
*/
<V> V getState(Property<V> property);
/**
* Gets the value at the given state
*
* @param property The state
* @return The value
*/
<V> V getState(final PropertyKey property);
/**
* Gets an immutable collection of the states.
*
@ -59,35 +111,20 @@ public interface BlockStateHolder<T extends BlockStateHolder> {
Map<Property<?>, Object> getStates();
/**
* Checks if the type is the same, and if the matched states are the same.
*
* @deprecated use masks - not try to this fuzzy/non fuzzy state nonsense
* @param o other block
* @return true if equal
*/
@Deprecated
boolean equalsFuzzy(BlockStateHolder o);
/**
* Returns an immutable {@link BlockState} from this BlockStateHolder.
* Returns an immutable BlockStateHolder from this BlockStateHolder.
*
* @return A BlockState
*/
BlockState toImmutableState();
/**
* Gets a {@link BaseBlock} from this BlockStateHolder.
*
* @return The BaseBlock
*/
BaseBlock toBaseBlock();
/**
* Gets a {@link BaseBlock} from this BlockStateHolder.
*
* @param compoundTag The NBT Data to apply
* @return The BaseBlock
*/
BaseBlock toBaseBlock(CompoundTag compoundTag);
default String getAsString() {
if (getStates().isEmpty()) {
return this.getBlockType().getId();

View File

@ -0,0 +1,5 @@
package com.sk89q.worldedit.world.block;
public class BlockStateRegistry {
}

View File

@ -19,48 +19,45 @@
package com.sk89q.worldedit.world.block;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.world.registry.BlockMaterial;
import com.sk89q.worldedit.extension.platform.Capability;
import com.sk89q.worldedit.registry.NamespacedRegistry;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BlockMaterial;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.mask.SingleBlockTypeMask;
import com.sk89q.worldedit.function.pattern.FawePattern;
import com.sk89q.worldedit.registry.state.Property;
import com.sk89q.worldedit.registry.state.PropertyKey;
import com.sk89q.worldedit.world.item.ItemType;
import com.sk89q.worldedit.world.item.ItemTypes;
import com.sk89q.worldedit.world.registry.BundledBlockData;
import com.sk89q.worldedit.world.registry.LegacyMapper;
import java.util.ArrayList;
import javax.annotation.Nullable;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.Set;
import javax.annotation.Nullable;
public interface BlockType extends FawePattern, Comparable<BlockTypes> {
public class BlockType {
public static final NamespacedRegistry<BlockType> REGISTRY = new NamespacedRegistry<>("block type");
private String id;
private BlockState defaultState;
private Map<String, ? extends Property> properties;
private BlockMaterial blockMaterial;
public BlockType(String id) {
this(id, null);
default BlockTypes getTypeEnum() {
return (BlockTypes) this;
}
public BlockType(String id, Function<BlockState, BlockState> values) {
// If it has no namespace, assume minecraft.
if (!id.contains(":")) {
id = "minecraft:" + id;
}
this.id = id;
this.defaultState = new ArrayList<>(BlockState.generateStateMap(this).values()).get(0);
if (values != null) {
this.defaultState = values.apply(this.defaultState);
}
@Deprecated
int getMaxStateId();
@Override
default boolean apply(Extent extent, Vector get, Vector set) throws WorldEditException {
return extent.setBlock(set, this.getDefaultState());
}
@Override
default BlockStateHolder apply(Vector position) {
return this.getDefaultState();
}
default Mask toMask(Extent extent) {
return new SingleBlockTypeMask(extent, this);
}
/**
@ -68,17 +65,15 @@ public class BlockType {
*
* @return The id
*/
public String getId() {
return this.id;
}
String getId();
/**
* Gets the name of this block, or the ID if the name cannot be found.
*
* @return The name, or ID
*/
public String getName() {
BundledBlockData.BlockEntry entry = BundledBlockData.getInstance().findById(this.id);
default String getName() {
BundledBlockData.BlockEntry entry = BundledBlockData.getInstance().findById(this.getId());
if (entry == null) {
return getId();
} else {
@ -86,27 +81,30 @@ public class BlockType {
}
}
@Deprecated
default BlockState withPropertyId(int internalPropertiesId) {
if (internalPropertiesId == 0) return getDefaultState();
return BlockState.get(getInternalId() + (internalPropertiesId << BlockTypes.BIT_OFFSET));
}
/**
* Gets the properties of this BlockType in a key->property mapping.
*
* @return The properties map
*/
public Map<String, ? extends Property> getPropertyMap() {
if (properties == null) {
properties = ImmutableMap.copyOf(WorldEdit.getInstance().getPlatformManager()
.queryCapability(Capability.GAME_HOOKS).getRegistries().getBlockRegistry().getProperties(this));
}
return this.properties;
}
@Deprecated
Map<String, ? extends Property> getPropertyMap();
/**
* Gets the properties of this BlockType.
*
* @return the properties
*/
public List<? extends Property> getProperties() {
return ImmutableList.copyOf(this.getPropertyMap().values());
}
@Deprecated
List<? extends Property> getProperties();
@Deprecated
Set<? extends Property> getPropertiesSet();
/**
* Gets a property by name.
@ -114,25 +112,26 @@ public class BlockType {
* @param name The name
* @return The property
*/
public <V> Property<V> getProperty(String name) {
return getPropertyMap().get(name);
}
@Deprecated
<V> Property<V> getProperty(String name);
boolean hasProperty(PropertyKey key);
<V> Property<V> getProperty(PropertyKey key);
/**
* Gets the default state of this block type.
*
* @return The default state
*/
public BlockState getDefaultState() {
return this.defaultState;
}
BlockState getDefaultState();
/**
* Gets whether this block type has an item representation.
*
* @return If it has an item
*/
public boolean hasItemType() {
default boolean hasItemType() {
return getItemType() != null;
}
@ -142,46 +141,32 @@ public class BlockType {
* @return The item representation
*/
@Nullable
public ItemType getItemType() {
return ItemTypes.get(this.id);
}
ItemType getItemType();
/**
* Get the material for this BlockType.
*
* @return The material
*/
public BlockMaterial getMaterial() {
if (this.blockMaterial == null) {
this.blockMaterial = WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.GAME_HOOKS).getRegistries().getBlockRegistry().getMaterial(this);
}
return this.blockMaterial;
BlockMaterial getMaterial();
default int getLegacyCombinedId() {
Integer combinedId = LegacyMapper.getInstance().getLegacyFromBlock(this);
return combinedId == null ? 0 : combinedId;
}
/**
* Gets the legacy ID. Needed for legacy reasons.
* The internal index of this type.
*
* DO NOT USE THIS.
* This number is not necessarily consistent across restarts.
*
* @return legacy id or 0, if unknown
* @return internal id
*/
@Deprecated
public int getLegacyId() {
int[] id = LegacyMapper.getInstance().getLegacyFromBlock(this.getDefaultState());
if (id != null) {
return id[0];
} else {
return 0;
}
}
int getInternalId();
@Override
public int hashCode() {
return this.id.hashCode();
}
boolean equals(Object obj);
@Override
public boolean equals(Object obj) {
return obj instanceof BlockType && this.id.equals(((BlockType) obj).id);
}
int hashCode();
}

View File

@ -0,0 +1,17 @@
package com.sk89q.worldedit.world.block;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
public class BlockTypeSwitch<T> implements Function<BlockType, T> {
private final T[] tasks;
protected BlockTypeSwitch(T[] tasks) {
this.tasks = tasks;
}
@Override
public T apply(BlockType blockType) {
return this.tasks[blockType.getInternalId()];
}
}

View File

@ -0,0 +1,39 @@
package com.sk89q.worldedit.world.block;
import java.util.function.Predicate;
public class BlockTypeSwitchBuilder<T> {
private final Object[] runnables;
private T defaultTask;
public BlockTypeSwitchBuilder(T defaultTask) {
this.runnables = new Object[BlockTypes.size()];
this.defaultTask = defaultTask;
}
public BlockTypeSwitchBuilder<T> add(BlockType type, T task) {
this.runnables[type.getInternalId()] = task;
return this;
}
public BlockTypeSwitchBuilder<T> add(Predicate<BlockType> predicate, T task) {
for (BlockTypes type : BlockTypes.values) {
if (predicate.test(type)) {
this.runnables[type.getInternalId()] = task;
}
}
return this;
}
public BlockTypeSwitchBuilder<T> setDefaultTask(T defaultTask) {
this.defaultTask = defaultTask;
return this;
}
public BlockTypeSwitch<T> build() {
for (int i = 0; i < runnables.length; i++) {
if (runnables[i] == null) runnables[i] = defaultTask;
}
return new BlockTypeSwitch(runnables);
}
}