Package tconstruct.smeltery.logic

Source Code of tconstruct.smeltery.logic.CastingBlockLogic

package tconstruct.smeltery.logic;

import cpw.mods.fml.common.eventhandler.Event;
import mantle.blocks.abstracts.InventoryLogic;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.inventory.*;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.*;
import net.minecraft.network.play.server.S35PacketUpdateTileEntity;
import net.minecraft.world.World;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.util.ForgeDirection;
import net.minecraftforge.fluids.*;
import tconstruct.TConstruct;
import tconstruct.library.crafting.*;
import tconstruct.library.event.*;
import tconstruct.library.tools.AbilityHelper;
import tconstruct.library.util.IPattern;

public abstract class CastingBlockLogic extends InventoryLogic implements IFluidTank, IFluidHandler, ISidedInventory
{
    public FluidStack liquid;
    protected int castingDelay = 0;
    protected int renderOffset = 0;
    protected int capacity = 0;
    protected boolean needsUpdate;
    protected boolean init = true;
    protected int tick;
    protected final LiquidCasting liquidCasting;

    public CastingBlockLogic(LiquidCasting casting)
    {
        // input slot and output slot, 1 item in it max
        super(2, 1);
        this.liquidCasting = casting;
    }

    public int updateCapacity () // Only used to initialize
    {
        ItemStack inv = inventory[0];
        int ret = TConstruct.ingotLiquidValue;
        int rec = liquidCasting.getCastingAmount(this.liquid, inv);

        if (rec > 0)
            ret = rec;
        else
        {
            if (inv != null && inv.getItem() instanceof IPattern)
            {
                int cost = ((IPattern) inv.getItem()).getPatternCost(inv);
                if (cost > 0)
                    ret *= ((IPattern) inv.getItem()).getPatternCost(inv) * 0.5;
            }
        }

        return ret;
    }

    public int updateCapacity (int capacity)
    {
        int ret = TConstruct.ingotLiquidValue;

        if (capacity > 0)
            ret = capacity;
        else
        {
            ItemStack inv = inventory[0];

            if (inv != null && inv.getItem() instanceof IPattern)
            {
                int cost = ((IPattern) inv.getItem()).getPatternCost(inv);
                if (cost > 0)
                    ret *= cost * 0.5;
            }
        }

        return ret;
    }

    /* FluidHandler stuff. Mostly delegated to Tank stuff */
    @Override
    public int fill (ForgeDirection from, FluidStack resource, boolean doFill)
    {
        return fill(resource, doFill);
    }

    @Override
    public FluidStack drain (ForgeDirection from, FluidStack resource, boolean doDrain)
    {
        // only same liquid
        if (liquid != null && liquid.getFluid() != resource.getFluid())
            return null;

        return drain(resource.amount, doDrain);
    }

    @Override
    public FluidStack drain (ForgeDirection from, int maxDrain, boolean doDrain)
    {
        return drain(maxDrain, doDrain);
    }

    @Override
    public boolean canFill (ForgeDirection from, Fluid fluid)
    {
        if(fluid == null)
            return false;
        return fill(from, new FluidStack(fluid, 1), false) > 0;
    }

    @Override
    public boolean canDrain (ForgeDirection from, Fluid fluid)
    {
        if(fluid == null)
            return false;
       
        FluidStack drained = drain(from, new FluidStack(fluid, 1), false);
        return drained != null && drained.amount > 0;
    }

    /* Tank stuff */
    @Override
    public FluidTankInfo[] getTankInfo (ForgeDirection from)
    {
        return new FluidTankInfo[] { getInfo() };
    }

    @Override
    public FluidStack getFluid ()
    {
        return liquid == null ? null : liquid.copy();
    }

    @Override
    public int getFluidAmount ()
    {
        return liquid != null ? liquid.amount : 0;
    }

    /** Returns the current amount of the liquid FOR RENDERING */
    public int getLiquidAmount ()
    {
        return liquid.amount - renderOffset;
    }

    @Override
    public int getCapacity ()
    {
        return this.capacity;
    }

    @Override
    public FluidTankInfo getInfo ()
    {
        return new FluidTankInfo(this);
    }

    /**
     * Create and return the casting event here. It'll be fired automatically.
     */
    public abstract SmelteryCastEvent getCastingEvent (CastingRecipe recipe, FluidStack metal);

    @Override
    public int fill (FluidStack resource, boolean doFill)
    {
        if (resource == null)
            return 0;

        if (this.liquid == null)
        {
            CastingRecipe recipe = liquidCasting.getCastingRecipe(resource, inventory[0]);
            if (recipe == null)
                return 0;

            SmelteryCastEvent event = getCastingEvent(recipe, resource);
            MinecraftForge.EVENT_BUS.post(event);

            if (event.getResult() == Event.Result.DENY)
                return 0;

            this.capacity = updateCapacity(recipe.castingMetal.amount);

            if (inventory[1] == null)
            {
                FluidStack copyLiquid = resource.copy();

                if (copyLiquid.amount > this.capacity)
                {
                    copyLiquid.amount = this.capacity;
                }

                if (doFill)
                {
                    if (copyLiquid.amount == this.capacity)
                    {
                        castingDelay = recipe.coolTime;
                    }
                    renderOffset = copyLiquid.amount;
                    worldObj.func_147479_m(xCoord, yCoord, zCoord);
                    this.liquid = copyLiquid;
                    needsUpdate = true;
                }
                return copyLiquid.amount;
            }
            else
            {
                return 0;
            }
        }
        else if (resource.isFluidEqual(this.liquid))
        {
            if (resource.amount + this.liquid.amount >= this.capacity) // Start timer here
            {
                int roomInTank = this.capacity - liquid.amount;
                if (doFill && roomInTank > 0)
                {
                    renderOffset = roomInTank;
                    castingDelay = liquidCasting.getCastingDelay(this.liquid, inventory[0]);
                    this.liquid.amount = this.capacity;
                    worldObj.func_147479_m(xCoord, yCoord, zCoord);
                    needsUpdate = true;
                }
                return roomInTank;
            }

            else
            {
                if (doFill)
                {
                    renderOffset += resource.amount;
                    this.liquid.amount += resource.amount;
                    worldObj.func_147479_m(xCoord, yCoord, zCoord);
                    needsUpdate = true;
                }
                return resource.amount;
            }
        }

        else
        {
            return 0;
        }
    }

    @Override
    public FluidStack drain (int maxDrain, boolean doDrain)
    {
        if (liquid == null || liquid.fluidID <= 0 || castingDelay > 0)
            return null;
        if (liquid.amount <= 0)
            return null;

        int used = maxDrain;
        if (liquid.amount < used)
            used = liquid.amount;

        if (doDrain)
        {
            liquid.amount -= used;
        }

        FluidStack drained = liquid.copy();
        drained.amount = used;

        renderOffset = 0;

        // Reset liquid if emptied
        if (liquid.amount <= 0)
            liquid = null;

        if (doDrain)
            FluidEvent.fireEvent(new FluidEvent.FluidDrainingEvent(drained, this.worldObj, this.xCoord, this.yCoord, this.zCoord, this, used));

        return drained;
    }

    /* Inventory, inserting/extracting */

    public void interact(EntityPlayer player)
    {
        // only server side
        //if(worldObj.isRemote)
            //return;

        // can't interact with liquid inside
        // todo: maybe let it interact with a bucket or tank!
        if(liquid != null)
            return;

        // put stuff in?
        if(!isStackInSlot(0) && !isStackInSlot(1))
        {
            ItemStack stack = player.inventory.decrStackSize(player.inventory.currentItem, stackSizeLimit);
            SmelteryEvent.ItemInsertedIntoCasting event = new SmelteryEvent.ItemInsertedIntoCasting(this, xCoord, yCoord, zCoord, stack, player);
            MinecraftForge.EVENT_BUS.post(event);
            if(!event.isCanceled())
                setInventorySlotContents(0, event.item);
            else
                player.inventory.addItemStackToInventory(stack); // should never return false, since the itemstack was taken from the inventory
        }
        // take stuff out.
        else
        {
            int slot = 0;
            // output-slot has higher priority
            if(isStackInSlot(1))
                slot = 1;

            // Additional Info: Only 1 item can only be put into the casting block usually, however recipies
            // can have multiple blocks as output (compressed gravel -> brownstone for example)
            // we therefore spill the whole contents on extraction

            SmelteryEvent.ItemRemovedFromCasting event = new SmelteryEvent.ItemRemovedFromCasting(this, xCoord, yCoord, zCoord, getStackInSlot(slot), player);
            MinecraftForge.EVENT_BUS.post(event);

            // try to transfer thes tack to the player inventory
            ItemStack output = event.item;
            if(!player.inventory.addItemStackToInventory(output))
            {
                // drop the rest as an item
                AbilityHelper.spawnItemAtPlayer(player, output);
            }
            // added to inventory, update inventory
            else
                player.inventory.markDirty();

            // remove inventory contents, since we spilled the full contents of the slot
            inventory[slot] = null;
        }
    }

    @Override
    public ItemStack decrStackSize (int slot, int quantity)
    {
        ItemStack stack = super.decrStackSize(slot, quantity);
        worldObj.func_147479_m(xCoord, yCoord, zCoord);
        return stack;
    }

    @Override
    public int[] getAccessibleSlotsFromSide (int side)
    {
        return new int[] { 0, 1 };
    }

    @Override
    public boolean canInsertItem (int slot, ItemStack itemstack, int side)
    {
        // can't insert if there's liquid in it
        if (liquid != null)
            return false;

        // only into input slot
        return slot == 0;
    }

    @Override
    public boolean canExtractItem (int slot, ItemStack itemstack, int side)
    {
        // only output slot
        return slot == 1;
    }

    /* We don't have a gui or anything */
    @Override
    public Container getGuiContainer (InventoryPlayer inventoryplayer, World world, int x, int y, int z)
    {
        return null;
    }

    @Override
    protected String getDefaultName ()
    {
        return null;
    }

    @Override
    public String getInventoryName ()
    {
        return null;
    }

    @Override
    public String getInvName ()
    {
        return null;
    }

    @Override
    public boolean hasCustomInventoryName ()
    {
        return false;
    }

    @Override
    public void openInventory ()
    {

    }

    @Override
    public void closeInventory ()
    {

    }

    /* NBT, Updating */
    @Override
    public void markDirty () // Isn't actually called?
    {
        super.markDirty();
        worldObj.func_147479_m(xCoord, yCoord, zCoord);
        needsUpdate = true;
    }

    @Override
    public void updateEntity ()
    {
        if (castingDelay > 0)
        {
            castingDelay--;
            if (castingDelay == 0)
                castLiquid();
        }
        if (renderOffset > 0)
        {
            //renderOffset -= Math.max(renderOffset/3, 6);
            renderOffset -= 6;
            if(renderOffset < 0)
                renderOffset = 0;
            worldObj.func_147479_m(xCoord, yCoord, zCoord);
        }

        tick++;
        if (tick % 20 == 0)
        {
            tick = 0;
            if (needsUpdate)
                worldObj.markBlockForUpdate(xCoord, yCoord, zCoord);
        }
    }

    /**
     * Create and return the casting event here. It'll be fired automatically.
     */
    public abstract SmelteryCastedEvent getCastedEvent (CastingRecipe recipe, ItemStack result);

    public void castLiquid ()
    {
        CastingRecipe recipe = liquidCasting.getCastingRecipe(liquid, inventory[0]);
        if (recipe != null)
        {
            SmelteryCastedEvent event = getCastedEvent(recipe, recipe.getResult());
            MinecraftForge.EVENT_BUS.post(event);

            inventory[1] = event.output;
            if (event.consumeCast)
                inventory[0] = null;

            // if we just created a cast, move it to the first slot so we can use it directly afterwards
            if (event.output != null && event.output.getItem() instanceof IPattern)
            {
                inventory[1] = inventory[0];
                inventory[0] = event.output;
            }

            liquid = null;
            worldObj.markBlockForUpdate(xCoord, yCoord, zCoord);
        }
    }

    @Override
    public void readFromNBT (NBTTagCompound tags)
    {
        super.readFromNBT(tags);
        readCustomNBT(tags);
    }

    public void readCustomNBT (NBTTagCompound tags)
    {
        if (tags.getBoolean("hasLiquid"))
        {
            this.liquid = FluidStack.loadFluidStackFromNBT(tags.getCompoundTag("Fluid"));
        }
        else
            this.liquid = null;

        if (tags.getBoolean("Initialized"))
            this.capacity = tags.getInteger("Capacity");
        else
            this.capacity = updateCapacity();
        this.castingDelay = tags.getInteger("castingDelay");
        this.renderOffset = tags.getInteger("RenderOffset");
    }

    @Override
    public void writeToNBT (NBTTagCompound tags)
    {
        super.writeToNBT(tags);
        writeCustomNBT(tags);
    }

    public void writeCustomNBT (NBTTagCompound tags)
    {
        tags.setBoolean("hasLiquid", liquid != null);
        if (liquid != null)
        {
            NBTTagCompound nbt = new NBTTagCompound();
            liquid.writeToNBT(nbt);
            tags.setTag("Fluid", nbt);
        }
        tags.setBoolean("Initialized", init);
        tags.setInteger("Capacity", capacity);
        tags.setInteger("castingDelay", castingDelay);
        tags.setInteger("RenderOffset", renderOffset);
    }

    /* Packets */
    @Override
    public Packet getDescriptionPacket ()
    {
        NBTTagCompound tag = new NBTTagCompound();
        writeToNBT(tag);
        return new S35PacketUpdateTileEntity(xCoord, yCoord, zCoord, 1, tag);
    }

    @Override
    public void onDataPacket (NetworkManager net, S35PacketUpdateTileEntity packet)
    {
        readFromNBT(packet.func_148857_g());
        worldObj.func_147479_m(xCoord, yCoord, zCoord);
    }
}
TOP

Related Classes of tconstruct.smeltery.logic.CastingBlockLogic

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.