package choonster.testmod3.block;
import choonster.testmod3.util.OreDictUtils;
import net.minecraft.block.material.MapColor;
import net.minecraft.block.material.Material;
import net.minecraft.block.properties.IProperty;
import net.minecraft.block.properties.PropertyEnum;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.EnumDyeColor;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.IStringSerializable;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import javax.annotation.Nullable;
import java.util.Collection;
import java.util.Iterator;
import java.util.Optional;
import java.util.function.Predicate;
/**
* A slab that uses vanilla's dye colours.
* <p>
* Test for this thread:
* http://www.minecraftforum.net/forums/mapping-and-modding/minecraft-mods/modification-development/2597500-how-do-you-create-a-halfslab
*
* @author Choonster
*/
public abstract class BlockColouredSlab extends BlockSlabTestMod3<EnumDyeColor, BlockColouredSlab.EnumColourGroup, BlockColouredSlab> {
/**
* Create a coloured slab block.
*
* @param material The Material of this slab
* @param colourGroup This slab's colour group
* @param slabGroup The group this slab belongs to
*/
public BlockColouredSlab(Material material, EnumColourGroup colourGroup, SlabGroup<EnumDyeColor, EnumColourGroup, BlockColouredSlab> slabGroup) {
super(material, slabGroup, colourGroup);
}
@SuppressWarnings("deprecation")
@Override
public MapColor getMapColor(IBlockState state) {
return state.getValue(getVariantProperty()).getMapColor();
}
@Override
public String getUnlocalizedName(int meta) {
return getUnlocalizedName() + "." + getVariant(meta).getUnlocalizedName();
}
/**
* Get the metadata value for the specified colour
*
* @param colour The colour
* @return The metadata value
*/
@Override
public int getMetadata(EnumDyeColor colour) {
return variants.getOffsetMetadata(colour);
}
/**
* Get the colour for the specified metadata value
*
* @param meta The metadata value
* @return The colour
*/
@Override
protected EnumDyeColor getVariant(int meta) {
return variants.byOffsetMetadata(meta);
}
@Override
public boolean recolorBlock(World world, BlockPos pos, EnumFacing side, EnumDyeColor colour) {
final IBlockState currentState = world.getBlockState(pos);
return variants.isColourInGroup(colour) &&
currentState.getValue(getVariantProperty()) != colour &&
world.setBlockState(pos, currentState.withProperty(getVariantProperty(), colour));
}
@Override
public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumHand hand, EnumFacing side, float hitX, float hitY, float hitZ) {
final ItemStack heldItem = playerIn.getHeldItem(hand);
if (!heldItem.isEmpty()) {
final Optional<EnumDyeColor> dyeColour = OreDictUtils.INSTANCE.getDyeColour(heldItem);
if (dyeColour.isPresent()) {
final boolean success = recolorBlock(worldIn, pos, side, dyeColour.get());
if (success) {
heldItem.shrink(1);
return true;
}
}
}
return false;
}
@Override
public Comparable<?> getTypeForItem(ItemStack stack) {
return variants.byOffsetMetadata(stack.getMetadata());
}
/**
* A group of {@link EnumDyeColor} values.
*/
public enum EnumColourGroup implements Iterable<EnumDyeColor>, IStringSerializable {
LOW("low", colour -> colour.getMetadata() < 8, 0),
HIGH("high", colour -> colour.getMetadata() >= 8, 8);
/**
* The property with this group's colours as the allowed values
*/
public final IProperty<EnumDyeColor> property;
/**
* The offset to subtract from each colour's metadata value
*/
private final int metaOffset;
/**
* The name of this group
*/
private final String name;
/**
* The colours in this group
*/
private final Collection<EnumDyeColor> values;
/**
* Create a colour group
*
* @param name The name of this group
* @param colourFilter A filter to obtain the colours in this group
* @param metaOffset The offset to subtract from each colour's metadata value
*/
EnumColourGroup(String name, Predicate<EnumDyeColor> colourFilter, int metaOffset) {
this.name = name;
this.property = PropertyEnum.create("colour", EnumDyeColor.class, colourFilter::test);
this.metaOffset = metaOffset;
this.values = this.property.getAllowedValues();
}
/**
* Get the metadata value of the specified colour with this group's offset.
*
* @param colour The colour
* @return The offset metadata value
*/
public int getOffsetMetadata(EnumDyeColor colour) {
return colour.getMetadata() - metaOffset;
}
/**
* Get the colour of the specified metadata value with this group's offset
*
* @param meta The offset metadata value
* @return The colour
*/
public EnumDyeColor byOffsetMetadata(int meta) {
return EnumDyeColor.byMetadata(meta + metaOffset);
}
/**
* Returns an iterator over elements of type {@code T}.
*
* @return an Iterator.
*/
@Override
public Iterator<EnumDyeColor> iterator() {
return values.iterator();
}
@Override
public String getName() {
return name;
}
/**
* Is the specified colour in this group?
*
* @param colour The colour
* @return True if the colour is in this group
*/
public boolean isColourInGroup(EnumDyeColor colour) {
return values.contains(colour);
}
/**
* Get the first group containing the specified colour.
*
* @param colour The colour
* @return A group containing the colour, or null if there isn't one
*/
@Nullable
public static EnumColourGroup getGroupForColour(EnumDyeColor colour) {
for (final EnumColourGroup colourGroup : values()) {
if (colourGroup.isColourInGroup(colour)) {
return colourGroup;
}
}
return null;
}
}
public static class ColouredSlabGroup {
public final SlabGroup<EnumDyeColor, EnumColourGroup, BlockColouredSlab> low;
public final SlabGroup<EnumDyeColor, EnumColourGroup, BlockColouredSlab> high;
/**
* Create a coloured slab group.
*
* @param groupName The group's name
* @param material The Material of the slabs
*/
public ColouredSlabGroup(String groupName, Material material) {
low = createGroup(groupName, material, EnumColourGroup.LOW);
high = createGroup(groupName, material, EnumColourGroup.HIGH);
}
/**
* Create a slab group.
*
* @param groupName The group's name
* @param material The Material of the slabs
* @param colourGroup The colour group
* @return The slab group
*/
private SlabGroup<EnumDyeColor, EnumColourGroup, BlockColouredSlab> createGroup(String groupName, Material material, EnumColourGroup colourGroup) {
return new SlabGroup<EnumDyeColor, EnumColourGroup, BlockColouredSlab>(groupName, material, colourGroup) {
@Override
public BlockColouredSlab createSlab(final Material material, final boolean isDouble, final EnumColourGroup colourGroup) {
return new BlockColouredSlab(material, colourGroup, this) {
@Override
public boolean isDouble() {
return isDouble;
}
@Override
public IProperty<EnumDyeColor> getVariantProperty() {
return colourGroup.property;
}
};
}
};
}
/**
* Get the slab group for the specified colour group.
*
* @param colourGroup The colour group
* @return The slab group
*/
public SlabGroup<EnumDyeColor, EnumColourGroup, BlockColouredSlab> getSlabGroupByColourGroup(EnumColourGroup colourGroup) {
return colourGroup == EnumColourGroup.LOW ? low : high;
}
}
}