/** Copyright (C) <2017> <coolAlias> This file is part of coolAlias' Zelda Sword Skills Minecraft Mod; as such, you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package zeldaswordskills.block; import java.util.ArrayList; import java.util.List; import java.util.Random; import net.minecraft.block.Block; import net.minecraft.block.material.Material; import net.minecraft.block.properties.PropertyBool; import net.minecraft.block.properties.PropertyEnum; import net.minecraft.block.state.BlockState; import net.minecraft.block.state.IBlockState; import net.minecraft.client.renderer.block.statemap.IStateMapper; import net.minecraft.client.renderer.block.statemap.StateMap; import net.minecraft.creativetab.CreativeTabs; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLiving.SpawnPlacementType; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Blocks; import net.minecraft.item.Item; import net.minecraft.item.ItemPickaxe; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.BlockPos; import net.minecraft.util.EnumFacing; import net.minecraft.util.IStringSerializable; import net.minecraft.world.Explosion; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; import net.minecraftforge.fml.common.eventhandler.Event.Result; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import zeldaswordskills.api.block.BlockWeight; import zeldaswordskills.api.block.IExplodable; import zeldaswordskills.api.block.ILiftable; import zeldaswordskills.api.block.ISmashable; import zeldaswordskills.creativetab.ZSSCreativeTabs; import zeldaswordskills.ref.Config; import zeldaswordskills.ref.Sounds; import zeldaswordskills.util.PlayerUtils; /** * * A block that can either only be destroyed by explosions, or can not be destroyed at all * */ public class BlockSecretStone extends Block implements IBlockItemVariant, ICustomStateMapper, IDungeonBlock, IExplodable, ILiftable, ISmashable { public static final PropertyEnum<BlockSecretStone.EnumType> VARIANT = PropertyEnum.create("variant", BlockSecretStone.EnumType.class); public static final PropertyBool UNBREAKABLE = PropertyBool.create("unbreakable"); public BlockSecretStone(Material material) { super(material); setBlockUnbreakable(); setResistance(6.0F); setStepSound(soundTypeStone); setCreativeTab(ZSSCreativeTabs.tabBlocks); setDefaultState(blockState.getBaseState().withProperty(VARIANT, BlockSecretStone.EnumType.STONE).withProperty(UNBREAKABLE, Boolean.FALSE)); } @Override public BlockWeight getLiftWeight(EntityPlayer player, ItemStack stack, IBlockState state, EnumFacing face) { return (state.getValue(UNBREAKABLE).booleanValue() || !Config.canLiftSecretStone() ? BlockWeight.IMPOSSIBLE : null); } @Override public void onLifted(World world, EntityPlayer player, ItemStack stack, BlockPos pos, IBlockState state) { NBTTagCompound tag = stack.getTagCompound(); if (tag != null) { Block block = state.getValue(VARIANT).getDroppedBlock(); tag.setInteger("blockId", Block.getIdFromBlock(block)); tag.setInteger("metadata", 0); } } @Override public void onHeldBlockPlaced(World world, ItemStack stack, BlockPos pos, IBlockState state) {} @Override public BlockWeight getSmashWeight(EntityPlayer player, ItemStack stack, IBlockState state, EnumFacing face) { return (state.getValue(UNBREAKABLE).booleanValue() ? BlockWeight.IMPOSSIBLE : BlockWeight.VERY_HEAVY); } @Override public Result onSmashed(World world, EntityPlayer player, ItemStack stack, BlockPos pos, IBlockState state, EnumFacing face) { return Result.DEFAULT; } @Override public boolean canEntityDestroy(IBlockAccess world, BlockPos pos, Entity entity) { return !world.getBlockState(pos).getValue(UNBREAKABLE).booleanValue(); } @Override public boolean canCreatureSpawn(IBlockAccess world, BlockPos pos, SpawnPlacementType type) { return false; } @Override public int getMobilityFlag() { return 2; } @Override public boolean canHarvestBlock(IBlockAccess World, BlockPos pos, EntityPlayer player) { return false; } @Override public int damageDropped(IBlockState state) { return state.getBlock().getMetaFromState(state); } @Override public Item getItemDropped(IBlockState state, Random rand, int fortune) { return Item.getItemFromBlock(state.getValue(VARIANT).getDroppedBlock()); } @Override public ArrayList<ItemStack> getDrops(IBlockAccess world, BlockPos pos, IBlockState state, int fortune) { Random rand = world instanceof World ? ((World) world).rand : RANDOM; ArrayList<ItemStack> drops = new ArrayList<ItemStack>(); drops.add(new ItemStack(getItemDropped(state, rand, fortune))); return drops; } @Override public void onBlockClicked(World world, BlockPos pos, EntityPlayer player) { if (player.getHeldItem() != null && player.getHeldItem().getItem() instanceof ItemPickaxe) { if (!world.isRemote) { world.playSoundAtEntity(player, Sounds.ITEM_BREAK, 0.25F, 1.0F / (world.rand.nextFloat() * 0.4F + 0.5F)); } else if (Config.showSecretMessage) { PlayerUtils.sendTranslatedChat(player, "chat.zss.block.secret"); } } } // TODO remove if Mojang's stupid code ever gets fixed @Override public void onBlockExploded(World world, BlockPos pos, Explosion explosion) { if (!world.getBlockState(pos).getValue(UNBREAKABLE).booleanValue()) { super.onBlockExploded(world, pos, explosion); } } @Override public float getExplosionResistance(World world, BlockPos pos, Entity entity, Explosion explosion) { IBlockState state = world.getBlockState(pos); if (state.getBlock() != this) { return state.getBlock().getExplosionResistance(world, pos, entity, explosion); } return (state.getValue(UNBREAKABLE).booleanValue() ? BlockWeight.getMaxResistance() : getExplosionResistance(entity)); } @Override public String[] getItemBlockVariants() { String[] variants = new String[BlockSecretStone.EnumType.values().length]; for (BlockSecretStone.EnumType type : BlockSecretStone.EnumType.values()) { variants[type.getMetadata()] = "minecraft:" + type.getUnlocalizedName(); } return variants; } @Override @SideOnly(Side.CLIENT) public void getSubBlocks(Item item, CreativeTabs tab, List<ItemStack> list) { BlockSecretStone.EnumType types[] = BlockSecretStone.EnumType.values(); for (int i = 0; i < types.length; ++i) { list.add(new ItemStack(item, 1, types[i].getMetadata())); list.add(new ItemStack(item, 1, types[i].getMetadata() | 0x8)); } } @Override public boolean isSameVariant(World world, BlockPos pos, IBlockState state, int meta) { IBlockState expected = getStateFromMeta(meta); return state.getValue(VARIANT) == expected.getValue(VARIANT); } @Override public IBlockState getStateFromMeta(int meta) { BlockSecretStone.EnumType type = BlockSecretStone.EnumType.byMetadata(meta); return getDefaultState().withProperty(VARIANT, type).withProperty(UNBREAKABLE, Boolean.valueOf((meta & 0x8) > 0)); } @Override public int getMetaFromState(IBlockState state) { int i = state.getValue(VARIANT).getMetadata(); if (state.getValue(UNBREAKABLE).booleanValue()) { i |= 0x8; } return i; } @Override protected BlockState createBlockState() { return new BlockState(this, VARIANT, UNBREAKABLE); } @Override @SideOnly(Side.CLIENT) public IStateMapper getCustomStateMap() { return (new StateMap.Builder()).ignore(UNBREAKABLE).build(); } /** * Helper method returns the variant's dropped block based on metadata */ public static Block getDroppedBlock(int meta) { return ZSSBlocks.secretStone.getStateFromMeta(meta).getValue(VARIANT).getDroppedBlock(); } public static enum EnumType implements IStringSerializable { STONE(0, 0, "stone"), SANDSTONE(1, 1, "sandstone"), NETHER_BRICK(2, 6, "nether_brick"), STONE_BRICK(3, 5, "stonebrick"), MOSSY_COBBLE(4, 3, "mossy_cobblestone"), ICE(5, 7, "ice"), COBBLESTONE(6, 3, "cobblestone"), END_STONE(7, 7, "end_stone"); private final int meta; private final int slab; private final String name; private final String unlocalizedName; private EnumType(int meta, int slab, String name) { this(meta, slab, name, name); } private EnumType(int meta, int slab, String name, String unlocalizedName) { this.meta = meta; this.slab = slab; this.name = name; this.unlocalizedName = unlocalizedName; } public int getMetadata() { return this.meta; } /** * Returns the block dropped when this type is broken */ public Block getDroppedBlock() { switch (this) { case STONE: return Blocks.stone; case SANDSTONE: return Blocks.sandstone; case NETHER_BRICK: return Blocks.nether_brick; case STONE_BRICK: return Blocks.stonebrick; case MOSSY_COBBLE: return Blocks.mossy_cobblestone; case ICE: return Blocks.ice; case COBBLESTONE: return Blocks.cobblestone; // return Blocks.quartz_block; case END_STONE: return Blocks.end_stone; default: return Blocks.stone; } } /** * Returns the slab of the appropriate type with default position */ public IBlockState getSlab() { return Blocks.stone_slab.getStateFromMeta(slab); } /** * Returns the stair block to use for this type */ public Block getStairBlock() { switch (meta) { case 0: case 3: return Blocks.stone_brick_stairs; case 1: return Blocks.sandstone_stairs; case 2: return Blocks.nether_brick_stairs; case 5: case 7: return Blocks.quartz_stairs; default: return Blocks.stone_stairs; } } @Override public String toString() { return this.name; } /** * Returns the EnumType associated with this metadata (bit8 is ignored) */ public static EnumType byMetadata(int meta) { return EnumType.values()[meta & 0x7]; } @Override public String getName() { return this.name; } public String getUnlocalizedName() { return this.unlocalizedName; } } }