base mod created
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
package net.minecraft.block.state;
|
||||
|
||||
public enum BlockFaceShape
|
||||
{
|
||||
SOLID,
|
||||
BOWL,
|
||||
CENTER_SMALL,
|
||||
MIDDLE_POLE_THIN,
|
||||
CENTER,
|
||||
MIDDLE_POLE,
|
||||
CENTER_BIG,
|
||||
MIDDLE_POLE_THICK,
|
||||
UNDEFINED;
|
||||
}
|
||||
@@ -0,0 +1,235 @@
|
||||
package net.minecraft.block.state;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import java.util.List;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockPistonBase;
|
||||
import net.minecraft.block.material.EnumPushReaction;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class BlockPistonStructureHelper
|
||||
{
|
||||
private final World world;
|
||||
private final BlockPos pistonPos;
|
||||
private final BlockPos blockToMove;
|
||||
private final EnumFacing moveDirection;
|
||||
/** This is a List<BlockPos> of all blocks that will be moved by the piston. */
|
||||
private final List<BlockPos> toMove = Lists.<BlockPos>newArrayList();
|
||||
/** This is a List<BlockPos> of blocks that will be destroyed when a piston attempts to move them. */
|
||||
private final List<BlockPos> toDestroy = Lists.<BlockPos>newArrayList();
|
||||
|
||||
public BlockPistonStructureHelper(World worldIn, BlockPos posIn, EnumFacing pistonFacing, boolean extending)
|
||||
{
|
||||
this.world = worldIn;
|
||||
this.pistonPos = posIn;
|
||||
|
||||
if (extending)
|
||||
{
|
||||
this.moveDirection = pistonFacing;
|
||||
this.blockToMove = posIn.offset(pistonFacing);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.moveDirection = pistonFacing.getOpposite();
|
||||
this.blockToMove = posIn.offset(pistonFacing, 2);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean canMove()
|
||||
{
|
||||
this.toMove.clear();
|
||||
this.toDestroy.clear();
|
||||
IBlockState iblockstate = this.world.getBlockState(this.blockToMove);
|
||||
|
||||
if (!BlockPistonBase.canPush(iblockstate, this.world, this.blockToMove, this.moveDirection, false, this.moveDirection))
|
||||
{
|
||||
if (iblockstate.getMobilityFlag() == EnumPushReaction.DESTROY)
|
||||
{
|
||||
this.toDestroy.add(this.blockToMove);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (!this.addBlockLine(this.blockToMove, this.moveDirection))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < this.toMove.size(); ++i)
|
||||
{
|
||||
BlockPos blockpos = this.toMove.get(i);
|
||||
|
||||
if (this.world.getBlockState(blockpos).getBlock().isStickyBlock(this.world.getBlockState(blockpos)) && !this.addBranchingBlocks(blockpos))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean addBlockLine(BlockPos origin, EnumFacing p_177251_2_)
|
||||
{
|
||||
IBlockState iblockstate = this.world.getBlockState(origin);
|
||||
Block block = iblockstate.getBlock();
|
||||
|
||||
if (iblockstate.getBlock().isAir(iblockstate, this.world, origin))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (!BlockPistonBase.canPush(iblockstate, this.world, origin, this.moveDirection, false, p_177251_2_))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (origin.equals(this.pistonPos))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (this.toMove.contains(origin))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
int i = 1;
|
||||
|
||||
if (i + this.toMove.size() > 12)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (block.isStickyBlock(iblockstate))
|
||||
{
|
||||
BlockPos blockpos = origin.offset(this.moveDirection.getOpposite(), i);
|
||||
iblockstate = this.world.getBlockState(blockpos);
|
||||
block = iblockstate.getBlock();
|
||||
|
||||
if (iblockstate.getBlock().isAir(iblockstate, this.world, blockpos) || !BlockPistonBase.canPush(iblockstate, this.world, blockpos, this.moveDirection, false, this.moveDirection.getOpposite()) || blockpos.equals(this.pistonPos))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
++i;
|
||||
|
||||
if (i + this.toMove.size() > 12)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int i1 = 0;
|
||||
|
||||
for (int j = i - 1; j >= 0; --j)
|
||||
{
|
||||
this.toMove.add(origin.offset(this.moveDirection.getOpposite(), j));
|
||||
++i1;
|
||||
}
|
||||
|
||||
int j1 = 1;
|
||||
|
||||
while (true)
|
||||
{
|
||||
BlockPos blockpos1 = origin.offset(this.moveDirection, j1);
|
||||
int k = this.toMove.indexOf(blockpos1);
|
||||
|
||||
if (k > -1)
|
||||
{
|
||||
this.reorderListAtCollision(i1, k);
|
||||
|
||||
for (int l = 0; l <= k + i1; ++l)
|
||||
{
|
||||
BlockPos blockpos2 = this.toMove.get(l);
|
||||
|
||||
if (this.world.getBlockState(blockpos2).getBlock().isStickyBlock(this.world.getBlockState(blockpos2)) && !this.addBranchingBlocks(blockpos2))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
iblockstate = this.world.getBlockState(blockpos1);
|
||||
|
||||
if (iblockstate.getBlock().isAir(iblockstate, this.world, blockpos1))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!BlockPistonBase.canPush(iblockstate, this.world, blockpos1, this.moveDirection, true, this.moveDirection) || blockpos1.equals(this.pistonPos))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (iblockstate.getMobilityFlag() == EnumPushReaction.DESTROY)
|
||||
{
|
||||
this.toDestroy.add(blockpos1);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this.toMove.size() >= 12)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
this.toMove.add(blockpos1);
|
||||
++i1;
|
||||
++j1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void reorderListAtCollision(int p_177255_1_, int p_177255_2_)
|
||||
{
|
||||
List<BlockPos> list = Lists.<BlockPos>newArrayList();
|
||||
List<BlockPos> list1 = Lists.<BlockPos>newArrayList();
|
||||
List<BlockPos> list2 = Lists.<BlockPos>newArrayList();
|
||||
list.addAll(this.toMove.subList(0, p_177255_2_));
|
||||
list1.addAll(this.toMove.subList(this.toMove.size() - p_177255_1_, this.toMove.size()));
|
||||
list2.addAll(this.toMove.subList(p_177255_2_, this.toMove.size() - p_177255_1_));
|
||||
this.toMove.clear();
|
||||
this.toMove.addAll(list);
|
||||
this.toMove.addAll(list1);
|
||||
this.toMove.addAll(list2);
|
||||
}
|
||||
|
||||
private boolean addBranchingBlocks(BlockPos fromPos)
|
||||
{
|
||||
for (EnumFacing enumfacing : EnumFacing.values())
|
||||
{
|
||||
if (enumfacing.getAxis() != this.moveDirection.getAxis() && !this.addBlockLine(fromPos.offset(enumfacing), enumfacing))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a List<BlockPos> of all the blocks that are being moved by the piston.
|
||||
*/
|
||||
public List<BlockPos> getBlocksToMove()
|
||||
{
|
||||
return this.toMove;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an List<BlockPos> of all the blocks that are being destroyed by the piston.
|
||||
*/
|
||||
public List<BlockPos> getBlocksToDestroy()
|
||||
{
|
||||
return this.toDestroy;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package net.minecraft.block.state;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.collect.Iterables;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map.Entry;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.properties.IProperty;
|
||||
|
||||
public abstract class BlockStateBase implements IBlockState
|
||||
{
|
||||
private static final Joiner COMMA_JOINER = Joiner.on(',');
|
||||
private static final Function < Entry < IProperty<?>, Comparable<? >> , String > MAP_ENTRY_TO_STRING = new Function < Entry < IProperty<?>, Comparable<? >> , String > ()
|
||||
{
|
||||
@Nullable
|
||||
public String apply(@Nullable Entry < IProperty<?>, Comparable<? >> p_apply_1_)
|
||||
{
|
||||
if (p_apply_1_ == null)
|
||||
{
|
||||
return "<NULL>";
|
||||
}
|
||||
else
|
||||
{
|
||||
IProperty<?> iproperty = (IProperty)p_apply_1_.getKey();
|
||||
return iproperty.getName() + "=" + this.getPropertyName(iproperty, p_apply_1_.getValue());
|
||||
}
|
||||
}
|
||||
private <T extends Comparable<T>> String getPropertyName(IProperty<T> property, Comparable<?> entry)
|
||||
{
|
||||
return property.getName((T)entry);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a version of this BlockState with the given property cycled to the next value in order. If the property
|
||||
* was at the highest possible value, it is set to the lowest one instead.
|
||||
*/
|
||||
public <T extends Comparable<T>> IBlockState cycleProperty(IProperty<T> property)
|
||||
{
|
||||
return this.withProperty(property, cyclePropertyValue(property.getAllowedValues(), this.getValue(property)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method for cycleProperty.
|
||||
*/
|
||||
protected static <T> T cyclePropertyValue(Collection<T> values, T currentValue)
|
||||
{
|
||||
Iterator<T> iterator = values.iterator();
|
||||
|
||||
while (iterator.hasNext())
|
||||
{
|
||||
if (iterator.next().equals(currentValue))
|
||||
{
|
||||
if (iterator.hasNext())
|
||||
{
|
||||
return iterator.next();
|
||||
}
|
||||
|
||||
return values.iterator().next();
|
||||
}
|
||||
}
|
||||
|
||||
return iterator.next();
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder stringbuilder = new StringBuilder();
|
||||
stringbuilder.append(Block.REGISTRY.getNameForObject(this.getBlock()));
|
||||
|
||||
if (!this.getProperties().isEmpty())
|
||||
{
|
||||
stringbuilder.append("[");
|
||||
COMMA_JOINER.appendTo(stringbuilder, Iterables.transform(this.getProperties().entrySet(), MAP_ENTRY_TO_STRING));
|
||||
stringbuilder.append("]");
|
||||
}
|
||||
|
||||
return stringbuilder.toString();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public com.google.common.collect.ImmutableTable<IProperty<?>, Comparable<?>, IBlockState> getPropertyValueTable()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,610 @@
|
||||
package net.minecraft.block.state;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.MoreObjects;
|
||||
import com.google.common.collect.HashBasedTable;
|
||||
import com.google.common.collect.ImmutableCollection;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSortedMap;
|
||||
import com.google.common.collect.ImmutableTable;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Table;
|
||||
import com.google.common.collect.UnmodifiableIterator;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.material.EnumPushReaction;
|
||||
import net.minecraft.block.material.MapColor;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.block.properties.IProperty;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.util.EnumBlockRenderType;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.MapPopulator;
|
||||
import net.minecraft.util.Mirror;
|
||||
import net.minecraft.util.Rotation;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Cartesian;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
|
||||
public class BlockStateContainer
|
||||
{
|
||||
private static final Pattern NAME_PATTERN = Pattern.compile("^[a-z0-9_]+$");
|
||||
private static final Function < IProperty<?>, String > GET_NAME_FUNC = new Function < IProperty<?>, String > ()
|
||||
{
|
||||
@Nullable
|
||||
public String apply(@Nullable IProperty<?> p_apply_1_)
|
||||
{
|
||||
return p_apply_1_ == null ? "<NULL>" : p_apply_1_.getName();
|
||||
}
|
||||
};
|
||||
private final Block block;
|
||||
private final ImmutableSortedMap < String, IProperty<? >> properties;
|
||||
private final ImmutableList<IBlockState> validStates;
|
||||
|
||||
public BlockStateContainer(Block blockIn, IProperty<?>... properties)
|
||||
{
|
||||
this(blockIn, properties, null);
|
||||
}
|
||||
|
||||
protected StateImplementation createState(Block block, ImmutableMap<IProperty<?>, Comparable<?>> properties, @Nullable ImmutableMap<net.minecraftforge.common.property.IUnlistedProperty<?>, java.util.Optional<?>> unlistedProperties)
|
||||
{
|
||||
return new StateImplementation(block, properties);
|
||||
}
|
||||
|
||||
protected BlockStateContainer(Block blockIn, IProperty<?>[] properties, ImmutableMap<net.minecraftforge.common.property.IUnlistedProperty<?>, java.util.Optional<?>> unlistedProperties)
|
||||
{
|
||||
this.block = blockIn;
|
||||
Map < String, IProperty<? >> map = Maps. < String, IProperty<? >> newHashMap();
|
||||
|
||||
for (IProperty<?> iproperty : properties)
|
||||
{
|
||||
validateProperty(blockIn, iproperty);
|
||||
map.put(iproperty.getName(), iproperty);
|
||||
}
|
||||
|
||||
this.properties = ImmutableSortedMap.copyOf(map);
|
||||
Map < Map < IProperty<?>, Comparable<? >> , BlockStateContainer.StateImplementation > map2 = Maps. < Map < IProperty<?>, Comparable<? >> , BlockStateContainer.StateImplementation > newLinkedHashMap();
|
||||
List<BlockStateContainer.StateImplementation> list1 = Lists.<BlockStateContainer.StateImplementation>newArrayList();
|
||||
|
||||
for (List < Comparable<? >> list : Cartesian.cartesianProduct(this.getAllowedValues()))
|
||||
{
|
||||
Map < IProperty<?>, Comparable<? >> map1 = MapPopulator. < IProperty<?>, Comparable<? >> createMap(this.properties.values(), list);
|
||||
BlockStateContainer.StateImplementation blockstatecontainer$stateimplementation = createState(blockIn, ImmutableMap.copyOf(map1), unlistedProperties);
|
||||
map2.put(map1, blockstatecontainer$stateimplementation);
|
||||
list1.add(blockstatecontainer$stateimplementation);
|
||||
}
|
||||
|
||||
for (BlockStateContainer.StateImplementation blockstatecontainer$stateimplementation1 : list1)
|
||||
{
|
||||
blockstatecontainer$stateimplementation1.buildPropertyValueTable(map2);
|
||||
}
|
||||
|
||||
this.validStates = ImmutableList.<IBlockState>copyOf(list1);
|
||||
}
|
||||
|
||||
public static <T extends Comparable<T>> String validateProperty(Block block, IProperty<T> property)
|
||||
{
|
||||
String s = property.getName();
|
||||
|
||||
if (!NAME_PATTERN.matcher(s).matches())
|
||||
{
|
||||
throw new IllegalArgumentException("Block: " + block.getClass() + " has invalidly named property: " + s);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (T t : property.getAllowedValues())
|
||||
{
|
||||
String s1 = property.getName(t);
|
||||
|
||||
if (!NAME_PATTERN.matcher(s1).matches())
|
||||
{
|
||||
throw new IllegalArgumentException("Block: " + block.getClass() + " has property: " + s + " with invalidly named value: " + s1);
|
||||
}
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
public ImmutableList<IBlockState> getValidStates()
|
||||
{
|
||||
return this.validStates;
|
||||
}
|
||||
|
||||
private List < Iterable < Comparable<? >>> getAllowedValues()
|
||||
{
|
||||
List < Iterable < Comparable<? >>> list = Lists. < Iterable < Comparable<? >>> newArrayList();
|
||||
ImmutableCollection < IProperty<? >> immutablecollection = this.properties.values();
|
||||
UnmodifiableIterator unmodifiableiterator = immutablecollection.iterator();
|
||||
|
||||
while (unmodifiableiterator.hasNext())
|
||||
{
|
||||
IProperty<?> iproperty = (IProperty)unmodifiableiterator.next();
|
||||
list.add(((IProperty)iproperty).getAllowedValues());
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public IBlockState getBaseState()
|
||||
{
|
||||
return (IBlockState)this.validStates.get(0);
|
||||
}
|
||||
|
||||
public Block getBlock()
|
||||
{
|
||||
return this.block;
|
||||
}
|
||||
|
||||
public Collection < IProperty<? >> getProperties()
|
||||
{
|
||||
return this.properties.values();
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return MoreObjects.toStringHelper(this).add("block", Block.REGISTRY.getNameForObject(this.block)).add("properties", Iterables.transform(this.properties.values(), GET_NAME_FUNC)).toString();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public IProperty<?> getProperty(String propertyName)
|
||||
{
|
||||
return (IProperty)this.properties.get(propertyName);
|
||||
}
|
||||
|
||||
public static class StateImplementation extends BlockStateBase
|
||||
{
|
||||
private final Block block;
|
||||
private final ImmutableMap < IProperty<?>, Comparable<? >> properties;
|
||||
protected ImmutableTable < IProperty<?>, Comparable<?>, IBlockState > propertyValueTable;
|
||||
|
||||
protected StateImplementation(Block blockIn, ImmutableMap < IProperty<?>, Comparable<? >> propertiesIn)
|
||||
{
|
||||
this.block = blockIn;
|
||||
this.properties = propertiesIn;
|
||||
}
|
||||
|
||||
protected StateImplementation(Block blockIn, ImmutableMap<IProperty<?>, Comparable<?>> propertiesIn, ImmutableTable<IProperty<?>, Comparable<?>, IBlockState> propertyValueTable)
|
||||
{
|
||||
this.block = blockIn;
|
||||
this.properties = propertiesIn;
|
||||
this.propertyValueTable = propertyValueTable;
|
||||
}
|
||||
|
||||
public Collection < IProperty<? >> getPropertyKeys()
|
||||
{
|
||||
return Collections. < IProperty<? >> unmodifiableCollection(this.properties.keySet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the given Property for this BlockState
|
||||
*/
|
||||
public <T extends Comparable<T>> T getValue(IProperty<T> property)
|
||||
{
|
||||
Comparable<?> comparable = (Comparable)this.properties.get(property);
|
||||
|
||||
if (comparable == null)
|
||||
{
|
||||
throw new IllegalArgumentException("Cannot get property " + property + " as it does not exist in " + this.block.getBlockState());
|
||||
}
|
||||
else
|
||||
{
|
||||
return (T)(property.getValueClass().cast(comparable));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a version of this BlockState with the given Property now set to the given value
|
||||
*/
|
||||
public <T extends Comparable<T>, V extends T> IBlockState withProperty(IProperty<T> property, V value)
|
||||
{
|
||||
Comparable<?> comparable = (Comparable)this.properties.get(property);
|
||||
|
||||
if (comparable == null)
|
||||
{
|
||||
throw new IllegalArgumentException("Cannot set property " + property + " as it does not exist in " + this.block.getBlockState());
|
||||
}
|
||||
else if (comparable == value)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
else
|
||||
{
|
||||
IBlockState iblockstate = (IBlockState)this.propertyValueTable.get(property, value);
|
||||
|
||||
if (iblockstate == null)
|
||||
{
|
||||
throw new IllegalArgumentException("Cannot set property " + property + " to " + value + " on block " + Block.REGISTRY.getNameForObject(this.block) + ", it is not an allowed value");
|
||||
}
|
||||
else
|
||||
{
|
||||
return iblockstate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ImmutableMap < IProperty<?>, Comparable<? >> getProperties()
|
||||
{
|
||||
return this.properties;
|
||||
}
|
||||
|
||||
public Block getBlock()
|
||||
{
|
||||
return this.block;
|
||||
}
|
||||
|
||||
public boolean equals(Object p_equals_1_)
|
||||
{
|
||||
return this == p_equals_1_;
|
||||
}
|
||||
|
||||
public int hashCode()
|
||||
{
|
||||
return this.properties.hashCode();
|
||||
}
|
||||
|
||||
public void buildPropertyValueTable(Map < Map < IProperty<?>, Comparable<? >> , BlockStateContainer.StateImplementation > map)
|
||||
{
|
||||
if (this.propertyValueTable != null)
|
||||
{
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
else
|
||||
{
|
||||
Table < IProperty<?>, Comparable<?>, IBlockState > table = HashBasedTable. < IProperty<?>, Comparable<?>, IBlockState > create();
|
||||
UnmodifiableIterator unmodifiableiterator = this.properties.entrySet().iterator();
|
||||
|
||||
while (unmodifiableiterator.hasNext())
|
||||
{
|
||||
Entry < IProperty<?>, Comparable<? >> entry = (Entry)unmodifiableiterator.next();
|
||||
IProperty<?> iproperty = (IProperty)entry.getKey();
|
||||
|
||||
for (Comparable<?> comparable : iproperty.getAllowedValues())
|
||||
{
|
||||
if (comparable != entry.getValue())
|
||||
{
|
||||
table.put(iproperty, comparable, map.get(this.getPropertiesWithValue(iproperty, comparable)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.propertyValueTable = ImmutableTable.copyOf(table);
|
||||
}
|
||||
}
|
||||
|
||||
private Map < IProperty<?>, Comparable<? >> getPropertiesWithValue(IProperty<?> property, Comparable<?> value)
|
||||
{
|
||||
Map < IProperty<?>, Comparable<? >> map = Maps. < IProperty<?>, Comparable<? >> newHashMap(this.properties);
|
||||
map.put(property, value);
|
||||
return map;
|
||||
}
|
||||
|
||||
public Material getMaterial()
|
||||
{
|
||||
return this.block.getMaterial(this);
|
||||
}
|
||||
|
||||
public boolean isFullBlock()
|
||||
{
|
||||
return this.block.isFullBlock(this);
|
||||
}
|
||||
|
||||
public boolean canEntitySpawn(Entity entityIn)
|
||||
{
|
||||
return this.block.canEntitySpawn(this, entityIn);
|
||||
}
|
||||
|
||||
public int getLightOpacity()
|
||||
{
|
||||
return this.block.getLightOpacity(this);
|
||||
}
|
||||
|
||||
public int getLightValue()
|
||||
{
|
||||
return this.block.getLightValue(this);
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public boolean isTranslucent()
|
||||
{
|
||||
return this.block.isTranslucent(this);
|
||||
}
|
||||
|
||||
public boolean useNeighborBrightness()
|
||||
{
|
||||
return this.block.getUseNeighborBrightness(this);
|
||||
}
|
||||
|
||||
public MapColor getMapColor(IBlockAccess p_185909_1_, BlockPos p_185909_2_)
|
||||
{
|
||||
return this.block.getMapColor(this, p_185909_1_, p_185909_2_);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the blockstate with the given rotation. If inapplicable, returns itself.
|
||||
*/
|
||||
public IBlockState withRotation(Rotation rot)
|
||||
{
|
||||
return this.block.withRotation(this, rot);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the blockstate mirrored in the given way. If inapplicable, returns itself.
|
||||
*/
|
||||
public IBlockState withMirror(Mirror mirrorIn)
|
||||
{
|
||||
return this.block.withMirror(this, mirrorIn);
|
||||
}
|
||||
|
||||
public boolean isFullCube()
|
||||
{
|
||||
return this.block.isFullCube(this);
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public boolean hasCustomBreakingProgress()
|
||||
{
|
||||
return this.block.hasCustomBreakingProgress(this);
|
||||
}
|
||||
|
||||
public EnumBlockRenderType getRenderType()
|
||||
{
|
||||
return this.block.getRenderType(this);
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public int getPackedLightmapCoords(IBlockAccess source, BlockPos pos)
|
||||
{
|
||||
return this.block.getPackedLightmapCoords(this, source, pos);
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public float getAmbientOcclusionLightValue()
|
||||
{
|
||||
return this.block.getAmbientOcclusionLightValue(this);
|
||||
}
|
||||
|
||||
public boolean isBlockNormalCube()
|
||||
{
|
||||
return this.block.isBlockNormalCube(this);
|
||||
}
|
||||
|
||||
public boolean isNormalCube()
|
||||
{
|
||||
return this.block.isNormalCube(this);
|
||||
}
|
||||
|
||||
public boolean canProvidePower()
|
||||
{
|
||||
return this.block.canProvidePower(this);
|
||||
}
|
||||
|
||||
public int getWeakPower(IBlockAccess blockAccess, BlockPos pos, EnumFacing side)
|
||||
{
|
||||
return this.block.getWeakPower(this, blockAccess, pos, side);
|
||||
}
|
||||
|
||||
public boolean hasComparatorInputOverride()
|
||||
{
|
||||
return this.block.hasComparatorInputOverride(this);
|
||||
}
|
||||
|
||||
public int getComparatorInputOverride(World worldIn, BlockPos pos)
|
||||
{
|
||||
return this.block.getComparatorInputOverride(this, worldIn, pos);
|
||||
}
|
||||
|
||||
public float getBlockHardness(World worldIn, BlockPos pos)
|
||||
{
|
||||
return this.block.getBlockHardness(this, worldIn, pos);
|
||||
}
|
||||
|
||||
public float getPlayerRelativeBlockHardness(EntityPlayer player, World worldIn, BlockPos pos)
|
||||
{
|
||||
return this.block.getPlayerRelativeBlockHardness(this, player, worldIn, pos);
|
||||
}
|
||||
|
||||
public int getStrongPower(IBlockAccess blockAccess, BlockPos pos, EnumFacing side)
|
||||
{
|
||||
return this.block.getStrongPower(this, blockAccess, pos, side);
|
||||
}
|
||||
|
||||
public EnumPushReaction getMobilityFlag()
|
||||
{
|
||||
return this.block.getMobilityFlag(this);
|
||||
}
|
||||
|
||||
public IBlockState getActualState(IBlockAccess blockAccess, BlockPos pos)
|
||||
{
|
||||
return this.block.getActualState(this, blockAccess, pos);
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public AxisAlignedBB getSelectedBoundingBox(World worldIn, BlockPos pos)
|
||||
{
|
||||
return this.block.getSelectedBoundingBox(this, worldIn, pos);
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public boolean shouldSideBeRendered(IBlockAccess blockAccess, BlockPos pos, EnumFacing facing)
|
||||
{
|
||||
return this.block.shouldSideBeRendered(this, blockAccess, pos, facing);
|
||||
}
|
||||
|
||||
public boolean isOpaqueCube()
|
||||
{
|
||||
return this.block.isOpaqueCube(this);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public AxisAlignedBB getCollisionBoundingBox(IBlockAccess worldIn, BlockPos pos)
|
||||
{
|
||||
return this.block.getCollisionBoundingBox(this, worldIn, pos);
|
||||
}
|
||||
|
||||
public void addCollisionBoxToList(World worldIn, BlockPos pos, AxisAlignedBB entityBox, List<AxisAlignedBB> collidingBoxes, @Nullable Entity entityIn, boolean p_185908_6_)
|
||||
{
|
||||
this.block.addCollisionBoxToList(this, worldIn, pos, entityBox, collidingBoxes, entityIn, p_185908_6_);
|
||||
}
|
||||
|
||||
public AxisAlignedBB getBoundingBox(IBlockAccess blockAccess, BlockPos pos)
|
||||
{
|
||||
return this.block.getBoundingBox(this, blockAccess, pos);
|
||||
}
|
||||
|
||||
public RayTraceResult collisionRayTrace(World worldIn, BlockPos pos, Vec3d start, Vec3d end)
|
||||
{
|
||||
return this.block.collisionRayTrace(this, worldIn, pos, start, end);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the block is solid enough on the top side to support other blocks, like redstone
|
||||
* components.
|
||||
*/
|
||||
public boolean isTopSolid()
|
||||
{
|
||||
return this.block.isTopSolid(this);
|
||||
}
|
||||
|
||||
public Vec3d getOffset(IBlockAccess access, BlockPos pos)
|
||||
{
|
||||
return this.block.getOffset(this, access, pos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called on both Client and Server when World#addBlockEvent is called. On the Server, this may perform
|
||||
* additional changes to the world, like pistons replacing the block with an extended base. On the client,
|
||||
* the update may involve replacing tile entities, playing sounds, or performing other visual actions to
|
||||
* reflect the server side changes.
|
||||
*/
|
||||
public boolean onBlockEventReceived(World worldIn, BlockPos pos, int id, int param)
|
||||
{
|
||||
return this.block.eventReceived(this, worldIn, pos, id, param);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a neighboring block was changed and marks that this state should perform any checks during a
|
||||
* neighbor change. Cases may include when redstone power is updated, cactus blocks popping off due to a
|
||||
* neighboring solid block, etc.
|
||||
*/
|
||||
public void neighborChanged(World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos)
|
||||
{
|
||||
this.block.neighborChanged(this, worldIn, pos, blockIn, fromPos);
|
||||
}
|
||||
|
||||
public boolean causesSuffocation()
|
||||
{
|
||||
return this.block.causesSuffocation(this);
|
||||
}
|
||||
|
||||
public BlockFaceShape getBlockFaceShape(IBlockAccess worldIn, BlockPos pos, EnumFacing facing)
|
||||
{
|
||||
return this.block.getBlockFaceShape(worldIn, this, pos, facing);
|
||||
}
|
||||
|
||||
//Forge Start
|
||||
@Override
|
||||
public ImmutableTable<IProperty<?>, Comparable<?>, IBlockState> getPropertyValueTable()
|
||||
{
|
||||
return propertyValueTable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLightOpacity(IBlockAccess world, BlockPos pos)
|
||||
{
|
||||
return this.block.getLightOpacity(this, world, pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLightValue(IBlockAccess world, BlockPos pos)
|
||||
{
|
||||
return this.block.getLightValue(this, world, pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSideSolid(IBlockAccess world, BlockPos pos, EnumFacing side)
|
||||
{
|
||||
return this.block.isSideSolid(this, world, pos, side);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean doesSideBlockChestOpening(IBlockAccess world, BlockPos pos, EnumFacing side)
|
||||
{
|
||||
return this.block.doesSideBlockChestOpening(this, world, pos, side);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean doesSideBlockRendering(IBlockAccess world, BlockPos pos, EnumFacing side)
|
||||
{
|
||||
return this.block.doesSideBlockRendering(this, world, pos, side);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Forge added class to make building things easier.
|
||||
* Will return an instance of BlockStateContainer appropriate for
|
||||
* the list of properties passed in.
|
||||
*
|
||||
* Example usage:
|
||||
*
|
||||
* protected BlockStateContainer createBlockState()
|
||||
* {
|
||||
* return (new BlockStateContainer.Builder(this)).add(FACING).add(SOME_UNLISTED).build();
|
||||
* }
|
||||
*
|
||||
*/
|
||||
public static class Builder
|
||||
{
|
||||
private final Block block;
|
||||
private final List<IProperty<?>> listed = Lists.newArrayList();
|
||||
private final List<net.minecraftforge.common.property.IUnlistedProperty<?>> unlisted = Lists.newArrayList();
|
||||
|
||||
public Builder(Block block)
|
||||
{
|
||||
this.block = block;
|
||||
}
|
||||
|
||||
public Builder add(IProperty<?>... props)
|
||||
{
|
||||
for (IProperty<?> prop : props)
|
||||
this.listed.add(prop);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder add(net.minecraftforge.common.property.IUnlistedProperty<?>... props)
|
||||
{
|
||||
for (net.minecraftforge.common.property.IUnlistedProperty<?> prop : props)
|
||||
this.unlisted.add(prop);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BlockStateContainer build()
|
||||
{
|
||||
IProperty<?>[] listed = new IProperty[this.listed.size()];
|
||||
listed = this.listed.toArray(listed);
|
||||
if (this.unlisted.size() == 0)
|
||||
return new BlockStateContainer(this.block, listed);
|
||||
|
||||
net.minecraftforge.common.property.IUnlistedProperty<?>[] unlisted = new net.minecraftforge.common.property.IUnlistedProperty[this.unlisted.size()];
|
||||
unlisted = this.unlisted.toArray(unlisted);
|
||||
|
||||
return new net.minecraftforge.common.property.ExtendedBlockState(this.block, listed, unlisted);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package net.minecraft.block.state;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class BlockWorldState
|
||||
{
|
||||
private final World world;
|
||||
private final BlockPos pos;
|
||||
private final boolean forceLoad;
|
||||
private IBlockState state;
|
||||
private TileEntity tileEntity;
|
||||
private boolean tileEntityInitialized;
|
||||
|
||||
public BlockWorldState(World worldIn, BlockPos posIn, boolean forceLoadIn)
|
||||
{
|
||||
this.world = worldIn;
|
||||
this.pos = posIn;
|
||||
this.forceLoad = forceLoadIn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the block state as currently held, or (if it has not gotten it from the world) loads it from the world.
|
||||
* This will only look up the state from the world if {@link #forceLoad} is true or the block position is loaded.
|
||||
*/
|
||||
public IBlockState getBlockState()
|
||||
{
|
||||
if (this.state == null && (this.forceLoad || this.world.isBlockLoaded(this.pos)))
|
||||
{
|
||||
this.state = this.world.getBlockState(this.pos);
|
||||
}
|
||||
|
||||
return this.state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the tile entity as currently held, or (if it has not gotten it from the world) loads it from the world.
|
||||
*/
|
||||
@Nullable
|
||||
public TileEntity getTileEntity()
|
||||
{
|
||||
if (this.tileEntity == null && !this.tileEntityInitialized)
|
||||
{
|
||||
this.tileEntity = this.world.getTileEntity(this.pos);
|
||||
this.tileEntityInitialized = true;
|
||||
}
|
||||
|
||||
return this.tileEntity;
|
||||
}
|
||||
|
||||
public BlockPos getPos()
|
||||
{
|
||||
return this.pos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link Predicate} that will match when the given {@link IBlockState} predicate matches.
|
||||
*/
|
||||
public static Predicate<BlockWorldState> hasState(final Predicate<IBlockState> predicatesIn)
|
||||
{
|
||||
return new Predicate<BlockWorldState>()
|
||||
{
|
||||
public boolean apply(@Nullable BlockWorldState p_apply_1_)
|
||||
{
|
||||
return p_apply_1_ != null && predicatesIn.apply(p_apply_1_.getBlockState());
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package net.minecraft.block.state;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public interface IBlockBehaviors
|
||||
{
|
||||
/**
|
||||
* Called on both Client and Server when World#addBlockEvent is called. On the Server, this may perform additional
|
||||
* changes to the world, like pistons replacing the block with an extended base. On the client, the update may
|
||||
* involve replacing tile entities, playing sounds, or performing other visual actions to reflect the server side
|
||||
* changes.
|
||||
*/
|
||||
boolean onBlockEventReceived(World worldIn, BlockPos pos, int id, int param);
|
||||
|
||||
/**
|
||||
* Called when a neighboring block was changed and marks that this state should perform any checks during a neighbor
|
||||
* change. Cases may include when redstone power is updated, cactus blocks popping off due to a neighboring solid
|
||||
* block, etc.
|
||||
*/
|
||||
void neighborChanged(World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos);
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
package net.minecraft.block.state;
|
||||
|
||||
import java.util.List;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.block.material.EnumPushReaction;
|
||||
import net.minecraft.block.material.MapColor;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.util.EnumBlockRenderType;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.Mirror;
|
||||
import net.minecraft.util.Rotation;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
|
||||
public interface IBlockProperties
|
||||
{
|
||||
Material getMaterial();
|
||||
|
||||
boolean isFullBlock();
|
||||
|
||||
boolean canEntitySpawn(Entity entityIn);
|
||||
|
||||
@Deprecated //Forge location aware version below
|
||||
int getLightOpacity();
|
||||
int getLightOpacity(IBlockAccess world, BlockPos pos);
|
||||
|
||||
@Deprecated //Forge location aware version below
|
||||
int getLightValue();
|
||||
int getLightValue(IBlockAccess world, BlockPos pos);
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
boolean isTranslucent();
|
||||
|
||||
boolean useNeighborBrightness();
|
||||
|
||||
MapColor getMapColor(IBlockAccess p_185909_1_, BlockPos p_185909_2_);
|
||||
|
||||
/**
|
||||
* Returns the blockstate with the given rotation. If inapplicable, returns itself.
|
||||
*/
|
||||
IBlockState withRotation(Rotation rot);
|
||||
|
||||
/**
|
||||
* Returns the blockstate mirrored in the given way. If inapplicable, returns itself.
|
||||
*/
|
||||
IBlockState withMirror(Mirror mirrorIn);
|
||||
|
||||
boolean isFullCube();
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
boolean hasCustomBreakingProgress();
|
||||
|
||||
EnumBlockRenderType getRenderType();
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
int getPackedLightmapCoords(IBlockAccess source, BlockPos pos);
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
float getAmbientOcclusionLightValue();
|
||||
|
||||
boolean isBlockNormalCube();
|
||||
|
||||
boolean isNormalCube();
|
||||
|
||||
boolean canProvidePower();
|
||||
|
||||
int getWeakPower(IBlockAccess blockAccess, BlockPos pos, EnumFacing side);
|
||||
|
||||
boolean hasComparatorInputOverride();
|
||||
|
||||
int getComparatorInputOverride(World worldIn, BlockPos pos);
|
||||
|
||||
float getBlockHardness(World worldIn, BlockPos pos);
|
||||
|
||||
float getPlayerRelativeBlockHardness(EntityPlayer player, World worldIn, BlockPos pos);
|
||||
|
||||
int getStrongPower(IBlockAccess blockAccess, BlockPos pos, EnumFacing side);
|
||||
|
||||
EnumPushReaction getMobilityFlag();
|
||||
|
||||
IBlockState getActualState(IBlockAccess blockAccess, BlockPos pos);
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
AxisAlignedBB getSelectedBoundingBox(World worldIn, BlockPos pos);
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
boolean shouldSideBeRendered(IBlockAccess blockAccess, BlockPos pos, EnumFacing facing);
|
||||
|
||||
boolean isOpaqueCube();
|
||||
|
||||
@Nullable
|
||||
AxisAlignedBB getCollisionBoundingBox(IBlockAccess worldIn, BlockPos pos);
|
||||
|
||||
void addCollisionBoxToList(World worldIn, BlockPos pos, AxisAlignedBB entityBox, List<AxisAlignedBB> collidingBoxes, @Nullable Entity entityIn, boolean p_185908_6_);
|
||||
|
||||
AxisAlignedBB getBoundingBox(IBlockAccess blockAccess, BlockPos pos);
|
||||
|
||||
RayTraceResult collisionRayTrace(World worldIn, BlockPos pos, Vec3d start, Vec3d end);
|
||||
|
||||
/**
|
||||
* Determines if the block is solid enough on the top side to support other blocks, like redstone components.
|
||||
*/
|
||||
@Deprecated // Forge: Use isSideSolid(IBlockAccess, BlockPos, EnumFacing.UP) instead
|
||||
boolean isTopSolid();
|
||||
|
||||
//Forge added functions
|
||||
boolean doesSideBlockRendering(IBlockAccess world, BlockPos pos, EnumFacing side);
|
||||
boolean isSideSolid(IBlockAccess world, BlockPos pos, EnumFacing side);
|
||||
boolean doesSideBlockChestOpening(IBlockAccess world, BlockPos pos, EnumFacing side);
|
||||
|
||||
Vec3d getOffset(IBlockAccess access, BlockPos pos);
|
||||
|
||||
boolean causesSuffocation();
|
||||
|
||||
BlockFaceShape getBlockFaceShape(IBlockAccess worldIn, BlockPos pos, EnumFacing facing);
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package net.minecraft.block.state;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import java.util.Collection;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.properties.IProperty;
|
||||
|
||||
public interface IBlockState extends IBlockBehaviors, IBlockProperties
|
||||
{
|
||||
Collection < IProperty<? >> getPropertyKeys();
|
||||
|
||||
/**
|
||||
* Get the value of the given Property for this BlockState
|
||||
*/
|
||||
<T extends Comparable<T>> T getValue(IProperty<T> property);
|
||||
|
||||
/**
|
||||
* Get a version of this BlockState with the given Property now set to the given value
|
||||
*/
|
||||
<T extends Comparable<T>, V extends T> IBlockState withProperty(IProperty<T> property, V value);
|
||||
|
||||
/**
|
||||
* Create a version of this BlockState with the given property cycled to the next value in order. If the property
|
||||
* was at the highest possible value, it is set to the lowest one instead.
|
||||
*/
|
||||
<T extends Comparable<T>> IBlockState cycleProperty(IProperty<T> property);
|
||||
|
||||
ImmutableMap < IProperty<?>, Comparable<? >> getProperties();
|
||||
|
||||
Block getBlock();
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
// Auto generated package-info by MCP
|
||||
@ParametersAreNonnullByDefault
|
||||
@MethodsReturnNonnullByDefault
|
||||
package net.minecraft.block.state;
|
||||
|
||||
import mcp.MethodsReturnNonnullByDefault;
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
@@ -0,0 +1,26 @@
|
||||
package net.minecraft.block.state.pattern;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
|
||||
public class BlockMatcher implements Predicate<IBlockState>
|
||||
{
|
||||
private final Block block;
|
||||
|
||||
private BlockMatcher(Block blockType)
|
||||
{
|
||||
this.block = blockType;
|
||||
}
|
||||
|
||||
public static BlockMatcher forBlock(Block blockType)
|
||||
{
|
||||
return new BlockMatcher(blockType);
|
||||
}
|
||||
|
||||
public boolean apply(@Nullable IBlockState p_apply_1_)
|
||||
{
|
||||
return p_apply_1_ != null && p_apply_1_.getBlock() == this.block;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package net.minecraft.block.state.pattern;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
|
||||
public class BlockMaterialMatcher implements Predicate<IBlockState>
|
||||
{
|
||||
private final Material material;
|
||||
|
||||
private BlockMaterialMatcher(Material materialIn)
|
||||
{
|
||||
this.material = materialIn;
|
||||
}
|
||||
|
||||
public static BlockMaterialMatcher forMaterial(Material materialIn)
|
||||
{
|
||||
return new BlockMaterialMatcher(materialIn);
|
||||
}
|
||||
|
||||
public boolean apply(@Nullable IBlockState p_apply_1_)
|
||||
{
|
||||
return p_apply_1_ != null && p_apply_1_.getMaterial() == this.material;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,216 @@
|
||||
package net.minecraft.block.state.pattern;
|
||||
|
||||
import com.google.common.base.MoreObjects;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.block.state.BlockWorldState;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3i;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class BlockPattern
|
||||
{
|
||||
private final Predicate<BlockWorldState>[][][] blockMatches;
|
||||
private final int fingerLength;
|
||||
private final int thumbLength;
|
||||
private final int palmLength;
|
||||
|
||||
public BlockPattern(Predicate<BlockWorldState>[][][] predicatesIn)
|
||||
{
|
||||
this.blockMatches = predicatesIn;
|
||||
this.fingerLength = predicatesIn.length;
|
||||
|
||||
if (this.fingerLength > 0)
|
||||
{
|
||||
this.thumbLength = predicatesIn[0].length;
|
||||
|
||||
if (this.thumbLength > 0)
|
||||
{
|
||||
this.palmLength = predicatesIn[0][0].length;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.palmLength = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.thumbLength = 0;
|
||||
this.palmLength = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public int getFingerLength()
|
||||
{
|
||||
return this.fingerLength;
|
||||
}
|
||||
|
||||
public int getThumbLength()
|
||||
{
|
||||
return this.thumbLength;
|
||||
}
|
||||
|
||||
public int getPalmLength()
|
||||
{
|
||||
return this.palmLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* checks that the given pattern & rotation is at the block co-ordinates.
|
||||
*/
|
||||
@Nullable
|
||||
private BlockPattern.PatternHelper checkPatternAt(BlockPos pos, EnumFacing finger, EnumFacing thumb, LoadingCache<BlockPos, BlockWorldState> lcache)
|
||||
{
|
||||
for (int i = 0; i < this.palmLength; ++i)
|
||||
{
|
||||
for (int j = 0; j < this.thumbLength; ++j)
|
||||
{
|
||||
for (int k = 0; k < this.fingerLength; ++k)
|
||||
{
|
||||
if (!this.blockMatches[k][j][i].apply(lcache.getUnchecked(translateOffset(pos, finger, thumb, i, j, k))))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new BlockPattern.PatternHelper(pos, finger, thumb, lcache, this.palmLength, this.thumbLength, this.fingerLength);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates whether the given world position matches the pattern. Warning, fairly heavy function. @return a
|
||||
* BlockPattern.PatternHelper if found, null otherwise.
|
||||
*/
|
||||
@Nullable
|
||||
public BlockPattern.PatternHelper match(World worldIn, BlockPos pos)
|
||||
{
|
||||
LoadingCache<BlockPos, BlockWorldState> loadingcache = createLoadingCache(worldIn, false);
|
||||
int i = Math.max(Math.max(this.palmLength, this.thumbLength), this.fingerLength);
|
||||
|
||||
for (BlockPos blockpos : BlockPos.getAllInBox(pos, pos.add(i - 1, i - 1, i - 1)))
|
||||
{
|
||||
for (EnumFacing enumfacing : EnumFacing.values())
|
||||
{
|
||||
for (EnumFacing enumfacing1 : EnumFacing.values())
|
||||
{
|
||||
if (enumfacing1 != enumfacing && enumfacing1 != enumfacing.getOpposite())
|
||||
{
|
||||
BlockPattern.PatternHelper blockpattern$patternhelper = this.checkPatternAt(blockpos, enumfacing, enumfacing1, loadingcache);
|
||||
|
||||
if (blockpattern$patternhelper != null)
|
||||
{
|
||||
return blockpattern$patternhelper;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static LoadingCache<BlockPos, BlockWorldState> createLoadingCache(World worldIn, boolean forceLoadIn)
|
||||
{
|
||||
return CacheBuilder.newBuilder().<BlockPos, BlockWorldState>build(new BlockPattern.CacheLoader(worldIn, forceLoadIn));
|
||||
}
|
||||
|
||||
/**
|
||||
* Offsets the position of pos in the direction of finger and thumb facing by offset amounts, follows the right-hand
|
||||
* rule for cross products (finger, thumb, palm) @return A new BlockPos offset in the facing directions
|
||||
*/
|
||||
protected static BlockPos translateOffset(BlockPos pos, EnumFacing finger, EnumFacing thumb, int palmOffset, int thumbOffset, int fingerOffset)
|
||||
{
|
||||
if (finger != thumb && finger != thumb.getOpposite())
|
||||
{
|
||||
Vec3i vec3i = new Vec3i(finger.getFrontOffsetX(), finger.getFrontOffsetY(), finger.getFrontOffsetZ());
|
||||
Vec3i vec3i1 = new Vec3i(thumb.getFrontOffsetX(), thumb.getFrontOffsetY(), thumb.getFrontOffsetZ());
|
||||
Vec3i vec3i2 = vec3i.crossProduct(vec3i1);
|
||||
return pos.add(vec3i1.getX() * -thumbOffset + vec3i2.getX() * palmOffset + vec3i.getX() * fingerOffset, vec3i1.getY() * -thumbOffset + vec3i2.getY() * palmOffset + vec3i.getY() * fingerOffset, vec3i1.getZ() * -thumbOffset + vec3i2.getZ() * palmOffset + vec3i.getZ() * fingerOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalArgumentException("Invalid forwards & up combination");
|
||||
}
|
||||
}
|
||||
|
||||
static class CacheLoader extends com.google.common.cache.CacheLoader<BlockPos, BlockWorldState>
|
||||
{
|
||||
private final World world;
|
||||
private final boolean forceLoad;
|
||||
|
||||
public CacheLoader(World worldIn, boolean forceLoadIn)
|
||||
{
|
||||
this.world = worldIn;
|
||||
this.forceLoad = forceLoadIn;
|
||||
}
|
||||
|
||||
public BlockWorldState load(BlockPos p_load_1_) throws Exception
|
||||
{
|
||||
return new BlockWorldState(this.world, p_load_1_, this.forceLoad);
|
||||
}
|
||||
}
|
||||
|
||||
public static class PatternHelper
|
||||
{
|
||||
private final BlockPos frontTopLeft;
|
||||
private final EnumFacing forwards;
|
||||
private final EnumFacing up;
|
||||
private final LoadingCache<BlockPos, BlockWorldState> lcache;
|
||||
private final int width;
|
||||
private final int height;
|
||||
private final int depth;
|
||||
|
||||
public PatternHelper(BlockPos posIn, EnumFacing fingerIn, EnumFacing thumbIn, LoadingCache<BlockPos, BlockWorldState> lcacheIn, int widthIn, int heightIn, int depthIn)
|
||||
{
|
||||
this.frontTopLeft = posIn;
|
||||
this.forwards = fingerIn;
|
||||
this.up = thumbIn;
|
||||
this.lcache = lcacheIn;
|
||||
this.width = widthIn;
|
||||
this.height = heightIn;
|
||||
this.depth = depthIn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the BlockPos of the Pattern
|
||||
*/
|
||||
public BlockPos getFrontTopLeft()
|
||||
{
|
||||
return this.frontTopLeft;
|
||||
}
|
||||
|
||||
public EnumFacing getForwards()
|
||||
{
|
||||
return this.forwards;
|
||||
}
|
||||
|
||||
public EnumFacing getUp()
|
||||
{
|
||||
return this.up;
|
||||
}
|
||||
|
||||
public int getWidth()
|
||||
{
|
||||
return this.width;
|
||||
}
|
||||
|
||||
public int getHeight()
|
||||
{
|
||||
return this.height;
|
||||
}
|
||||
|
||||
public BlockWorldState translateOffset(int palmOffset, int thumbOffset, int fingerOffset)
|
||||
{
|
||||
return this.lcache.getUnchecked(BlockPattern.translateOffset(this.frontTopLeft, this.getForwards(), this.getUp(), palmOffset, thumbOffset, fingerOffset));
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return MoreObjects.toStringHelper(this).add("up", this.up).add("forwards", this.forwards).add("frontTopLeft", this.frontTopLeft).toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package net.minecraft.block.state.pattern;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Maps;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.properties.IProperty;
|
||||
import net.minecraft.block.state.BlockStateContainer;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
|
||||
public class BlockStateMatcher implements Predicate<IBlockState>
|
||||
{
|
||||
public static final Predicate<IBlockState> ANY = new Predicate<IBlockState>()
|
||||
{
|
||||
public boolean apply(@Nullable IBlockState p_apply_1_)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
private final BlockStateContainer blockstate;
|
||||
private final Map < IProperty<?>, Predicate<? >> propertyPredicates = Maps. < IProperty<?>, Predicate<? >> newHashMap();
|
||||
|
||||
private BlockStateMatcher(BlockStateContainer blockStateIn)
|
||||
{
|
||||
this.blockstate = blockStateIn;
|
||||
}
|
||||
|
||||
public static BlockStateMatcher forBlock(Block blockIn)
|
||||
{
|
||||
return new BlockStateMatcher(blockIn.getBlockState());
|
||||
}
|
||||
|
||||
public boolean apply(@Nullable IBlockState p_apply_1_)
|
||||
{
|
||||
if (p_apply_1_ != null && p_apply_1_.getBlock().equals(this.blockstate.getBlock()))
|
||||
{
|
||||
if (this.propertyPredicates.isEmpty())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (Entry < IProperty<?>, Predicate<? >> entry : this.propertyPredicates.entrySet())
|
||||
{
|
||||
if (!this.matches(p_apply_1_, (IProperty)entry.getKey(), (Predicate)entry.getValue()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected <T extends Comparable<T>> boolean matches(IBlockState blockState, IProperty<T> property, Predicate<T> predicate)
|
||||
{
|
||||
return predicate.apply(blockState.getValue(property));
|
||||
}
|
||||
|
||||
public <V extends Comparable<V>> BlockStateMatcher where(IProperty<V> property, Predicate <? extends V > is)
|
||||
{
|
||||
if (!this.blockstate.getProperties().contains(property))
|
||||
{
|
||||
throw new IllegalArgumentException(this.blockstate + " cannot support property " + property);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.propertyPredicates.put(property, is);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
package net.minecraft.block.state.pattern;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import net.minecraft.block.state.BlockWorldState;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
public class FactoryBlockPattern
|
||||
{
|
||||
private static final Joiner COMMA_JOIN = Joiner.on(",");
|
||||
private final List<String[]> depth = Lists.<String[]>newArrayList();
|
||||
private final Map<Character, Predicate<BlockWorldState>> symbolMap = Maps.<Character, Predicate<BlockWorldState>>newHashMap();
|
||||
private int aisleHeight;
|
||||
private int rowWidth;
|
||||
|
||||
private FactoryBlockPattern()
|
||||
{
|
||||
this.symbolMap.put(' ', Predicates.alwaysTrue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a single aisle to this pattern, going in the z axis. (so multiple calls to this will increase the z-size by
|
||||
* 1)
|
||||
*/
|
||||
public FactoryBlockPattern aisle(String... aisle)
|
||||
{
|
||||
if (!ArrayUtils.isEmpty((Object[])aisle) && !StringUtils.isEmpty(aisle[0]))
|
||||
{
|
||||
if (this.depth.isEmpty())
|
||||
{
|
||||
this.aisleHeight = aisle.length;
|
||||
this.rowWidth = aisle[0].length();
|
||||
}
|
||||
|
||||
if (aisle.length != this.aisleHeight)
|
||||
{
|
||||
throw new IllegalArgumentException("Expected aisle with height of " + this.aisleHeight + ", but was given one with a height of " + aisle.length + ")");
|
||||
}
|
||||
else
|
||||
{
|
||||
for (String s : aisle)
|
||||
{
|
||||
if (s.length() != this.rowWidth)
|
||||
{
|
||||
throw new IllegalArgumentException("Not all rows in the given aisle are the correct width (expected " + this.rowWidth + ", found one with " + s.length() + ")");
|
||||
}
|
||||
|
||||
for (char c0 : s.toCharArray())
|
||||
{
|
||||
if (!this.symbolMap.containsKey(Character.valueOf(c0)))
|
||||
{
|
||||
this.symbolMap.put(Character.valueOf(c0), null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.depth.add(aisle);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalArgumentException("Empty pattern for aisle");
|
||||
}
|
||||
}
|
||||
|
||||
public static FactoryBlockPattern start()
|
||||
{
|
||||
return new FactoryBlockPattern();
|
||||
}
|
||||
|
||||
public FactoryBlockPattern where(char symbol, Predicate<BlockWorldState> blockMatcher)
|
||||
{
|
||||
this.symbolMap.put(Character.valueOf(symbol), blockMatcher);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BlockPattern build()
|
||||
{
|
||||
return new BlockPattern(this.makePredicateArray());
|
||||
}
|
||||
|
||||
private Predicate<BlockWorldState>[][][] makePredicateArray()
|
||||
{
|
||||
this.checkMissingPredicates();
|
||||
Predicate<BlockWorldState>[][][] predicate = (Predicate[][][])((Predicate[][][])Array.newInstance(Predicate.class, this.depth.size(), this.aisleHeight, this.rowWidth));
|
||||
|
||||
for (int i = 0; i < this.depth.size(); ++i)
|
||||
{
|
||||
for (int j = 0; j < this.aisleHeight; ++j)
|
||||
{
|
||||
for (int k = 0; k < this.rowWidth; ++k)
|
||||
{
|
||||
predicate[i][j][k] = this.symbolMap.get(Character.valueOf(((String[])this.depth.get(i))[j].charAt(k)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return predicate;
|
||||
}
|
||||
|
||||
private void checkMissingPredicates()
|
||||
{
|
||||
List<Character> list = Lists.<Character>newArrayList();
|
||||
|
||||
for (Entry<Character, Predicate<BlockWorldState>> entry : this.symbolMap.entrySet())
|
||||
{
|
||||
if (entry.getValue() == null)
|
||||
{
|
||||
list.add(entry.getKey());
|
||||
}
|
||||
}
|
||||
|
||||
if (!list.isEmpty())
|
||||
{
|
||||
throw new IllegalStateException("Predicates for character(s) " + COMMA_JOIN.join(list) + " are missing");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
// Auto generated package-info by MCP
|
||||
@ParametersAreNonnullByDefault
|
||||
@MethodsReturnNonnullByDefault
|
||||
package net.minecraft.block.state.pattern;
|
||||
|
||||
import mcp.MethodsReturnNonnullByDefault;
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
Reference in New Issue
Block a user