com.github.pelepmc.unlittorch.TorchItem.java Source code

Java tutorial

Introduction

Here is the source code for com.github.pelepmc.unlittorch.TorchItem.java

Source

/*
 * This file is part of Unlit Torch.
 *
 * Unlit Torch is free software: 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.
 *
 * Unlit Torch 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 Unlit Torch. If not, see <http://www.gnu.org/licenses/>.
 */

package com.github.pelepmc.unlittorch;

import static com.github.pelepmc.unlittorch.TorchBlock.UNLIT;
import static com.github.pelepmc.unlittorch.UnlitTorch.MOD_ID;
import static net.minecraft.init.SoundEvents.BLOCK_FIRE_AMBIENT;
import static net.minecraft.init.SoundEvents.BLOCK_LAVA_EXTINGUISH;
import static net.minecraft.util.SoundCategory.BLOCKS;
import static net.minecraftforge.items.CapabilityItemHandler.ITEM_HANDLER_CAPABILITY;

import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.resources.I18n;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.init.Blocks;
import net.minecraft.item.EnumAction;
import net.minecraft.item.Item;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ActionResult;
import net.minecraft.util.EnumActionResult;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import net.minecraftforge.event.entity.player.ItemTooltipEvent;
import net.minecraftforge.fml.common.eventhandler.EventPriority;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.IItemHandlerModifiable;

import java.util.List;

public final class TorchItem extends ItemBlock {
    public static final int LIT_METADATA = 0;
    public static final int UNLIT_METADATA = 1;

    public static final ResourceLocation IGNITING_PROPERTY_KEY = new ResourceLocation("igniting");

    TorchItem(Block block) {
        super(block);
        setHasSubtypes(true);
        addPropertyOverride(IGNITING_PROPERTY_KEY, (stack, world,
                entity) -> entity != null && entity.isHandActive() && entity.getActiveItemStack() == stack ? 1.0f
                        : 0.0f);
    }

    private static final int UPDATE_INTERVAL = 25;

    @Override
    public void onUpdate(ItemStack stack, World world, Entity entity, int slot, boolean held) {
        if (world.isRemote || world.getTotalWorldTime() % UPDATE_INTERVAL != 0)
            return;

        IItemHandler handler = entity.getCapability(ITEM_HANDLER_CAPABILITY, null);
        if (!(handler instanceof IItemHandlerModifiable))
            return;

        if (entity instanceof EntityPlayer && ((EntityPlayer) entity).capabilities.isCreativeMode)
            return;

        IItemHandlerModifiable inventory = (IItemHandlerModifiable) handler;

        if (stack.getMetadata() == LIT_METADATA && entity.isWet()) {
            for (int i = 0; i < inventory.getSlots(); i++) {
                stack = inventory.getStackInSlot(i);
                if (stack != null && stack.getItem() == this && stack.stackSize != 0) {
                    stack = stack.copy();
                    stack.setItemDamage(UNLIT_METADATA);
                    inventory.setStackInSlot(i, stack);
                }
            }
            playDousingSound(entity.worldObj, entity.posX, entity.posY + entity.getEyeHeight(), entity.posZ);
        } else if (stack.getMetadata() == UNLIT_METADATA && entity.isBurning()) {
            for (int i = 0; i < inventory.getSlots(); i++) {
                stack = inventory.getStackInSlot(i);
                if (stack != null && stack.getItem() == this && stack.stackSize != 0) {
                    stack = stack.copy();
                    stack.setItemDamage(LIT_METADATA);
                    inventory.setStackInSlot(i, stack);
                }
            }
            playIgnitingSound(entity.worldObj, entity.posX, entity.posY + entity.getEyeHeight(), entity.posZ);
        }
    }

    @Override
    public boolean onEntityItemUpdate(EntityItem entity) {
        if (entity.worldObj.isRemote)
            return false;

        ItemStack stack = entity.getEntityItem();
        if (stack.getItem() != this)
            return false;

        if (stack.getMetadata() == LIT_METADATA && entity.isWet()) {
            stack.setItemDamage(UNLIT_METADATA);
            playDousingSound(entity.worldObj, entity.posX, entity.posY + entity.getEyeHeight(), entity.posZ);
        } else if (stack.getMetadata() == UNLIT_METADATA && entity.isBurning()) {
            stack.setItemDamage(LIT_METADATA);
            playIgnitingSound(entity.worldObj, entity.posX, entity.posY + entity.getEyeHeight(), entity.posZ);
        }

        return false;
    }

    @Override
    public EnumActionResult onItemUseFirst(ItemStack stack, EntityPlayer player, World world, BlockPos position,
            EnumFacing side, float localX, float localY, float localZ, EnumHand hand) {
        if (player.isSneaking() || stack == null)
            return EnumActionResult.PASS;

        IBlockState state = world.getBlockState(position);
        if (state.getBlock() != getBlock())
            return EnumActionResult.PASS;

        if ((stack.getMetadata() == UNLIT_METADATA && !state.getValue(UNLIT))
                || (stack.getMetadata() == LIT_METADATA && state.getValue(UNLIT))) {
            player.setActiveHand(hand);
            return EnumActionResult.FAIL;
        }

        return EnumActionResult.PASS;
    }

    @Override
    public ActionResult<ItemStack> onItemRightClick(ItemStack stack, World world, EntityPlayer player,
            EnumHand hand) {
        player.setActiveHand(hand);
        return new ActionResult<>(EnumActionResult.FAIL, stack);
    }

    private static final int USE_DURATION = 72000;
    private static final int MAX_IGNITION_DELAY = 30;
    private static final int COOLDOWN_DURATION = 10;

    @Override
    public void onUsingTick(ItemStack stack, EntityLivingBase entity, int count) {
        if (count == USE_DURATION || count % MAX_IGNITION_DELAY != 0)
            return;

        World world = entity.worldObj;
        RayTraceResult result = rayTrace(world, entity, true);
        if (result == null || result.typeOfHit != RayTraceResult.Type.BLOCK)
            return;

        IBlockState state = world.getBlockState(result.getBlockPos());
        if (state.getBlock() != getBlock())
            return;

        if (stack.getMetadata() == UNLIT_METADATA && !state.getValue(UNLIT)) {
            if (entity instanceof EntityPlayer)
                ((EntityPlayer) entity).getCooldownTracker().setCooldown(this, COOLDOWN_DURATION);
            stack.setItemDamage(LIT_METADATA);
            playIgnitingSound(world, entity.posX, entity.posY + entity.getEyeHeight(), entity.posZ);
        } else if (stack.getMetadata() == LIT_METADATA && state.getValue(UNLIT)) {
            if (entity instanceof EntityPlayer)
                ((EntityPlayer) entity).getCooldownTracker().setCooldown(this, COOLDOWN_DURATION);
            BlockPos position = result.getBlockPos();
            world.setBlockState(position, state.withProperty(UNLIT, false));
            playIgnitingSound(world, position.getX() + 0.5d, position.getY() + 0.5d, position.getZ() + 0.5d);
        }
    }

    private static final float DEGREES_TO_RADIANS = (float) Math.PI / 180.0f;

    private RayTraceResult rayTrace(World world, Entity entity, boolean includeLiquids) {
        float pitch = entity.rotationPitch;
        float yaw = entity.rotationYaw;
        float scale = -MathHelper.cos(-pitch * DEGREES_TO_RADIANS);
        float unitX = MathHelper.sin(-yaw * DEGREES_TO_RADIANS - (float) Math.PI) * scale;
        float unitY = MathHelper.sin(-pitch * DEGREES_TO_RADIANS);
        float unitZ = MathHelper.cos(-yaw * DEGREES_TO_RADIANS - (float) Math.PI) * scale;
        double reach = entity instanceof EntityPlayerMP
                ? ((EntityPlayerMP) entity).interactionManager.getBlockReachDistance()
                : 5.0d;
        Vec3d start = new Vec3d(entity.posX, entity.posY + entity.getEyeHeight(), entity.posZ);
        Vec3d end = start.addVector(unitX * reach, unitY * reach, unitZ * reach);

        return world.rayTraceBlocks(start, end, includeLiquids, !includeLiquids, false);
    }

    @Override
    public int getMaxItemUseDuration(ItemStack stack) {
        return USE_DURATION;
    }

    @Override
    public EnumAction getItemUseAction(ItemStack stack) {
        return EnumAction.BLOCK;
    }

    @Override
    public int getMetadata(int damage) {
        return damage;
    }

    @SideOnly(Side.CLIENT)
    @Override
    public void getSubItems(Item item, CreativeTabs tab, List<ItemStack> items) {
        items.add(new ItemStack(this, 1, LIT_METADATA));
        items.add(new ItemStack(this, 1, UNLIT_METADATA));
    }

    private static final String LIT_UNLOCALIZED_NAME = "tile.torch"; // use minecraft's existing localization
    private static final String UNLIT_UNLOCALIZED_NAME = "tile." + MOD_ID + ".torch.unlit";

    @Override
    public String getUnlocalizedName(ItemStack stack) {
        return stack.getMetadata() == UNLIT_METADATA ? UNLIT_UNLOCALIZED_NAME : LIT_UNLOCALIZED_NAME;
    }

    private static void playDousingSound(World world, double x, double y, double z) {
        world.playSound(null, x, y, z, BLOCK_LAVA_EXTINGUISH, BLOCKS, 0.4f + (0.15f * itemRand.nextFloat()), 1.0f);
    }

    private static void playIgnitingSound(World world, double x, double y, double z) {
        world.playSound(null, x, y, z, BLOCK_FIRE_AMBIENT, BLOCKS, 0.9f + itemRand.nextFloat(), 0.6f);
    }

    private static final String TOOLTIP_KEY = "item." + MOD_ID + ".torch.tooltip.unmodded";

    @SideOnly(Side.CLIENT)
    @SubscribeEvent(priority = EventPriority.LOWEST)
    public void addTooltip(ItemTooltipEvent event) {
        if (!event.isCanceled()) {
            Item item = event.getItemStack().getItem();
            if (item instanceof ItemBlock && ((ItemBlock) item).getBlock() == Blocks.TORCH)
                event.getToolTip().add(I18n.format(TOOLTIP_KEY));
        }
    }
}