854 lines
27 KiB
Java
Executable file
854 lines
27 KiB
Java
Executable file
/*******************************************************************************
|
|
* Copyright (c) 2012-2013 Yancarlo Ramsey and CJ Bowman
|
|
* Licensed as open source with restrictions. Please see attached LICENSE.txt.
|
|
******************************************************************************/
|
|
package com.kaijin.AdvPowerMan.tileentities;
|
|
|
|
import ic2.api.Direction;
|
|
import ic2.api.item.ElectricItem;
|
|
import ic2.api.item.IElectricItem;
|
|
import ic2.api.tile.IEnergyStorage;
|
|
import ic2.api.energy.EnergyNet;
|
|
import ic2.api.energy.event.EnergyTileLoadEvent;
|
|
import ic2.api.energy.tile.IEnergySink;
|
|
import ic2.core.IC2;
|
|
import ic2.core.network.NetworkManager;
|
|
import io.netty.buffer.ByteBuf;
|
|
|
|
import java.io.DataInputStream;
|
|
import java.io.DataOutputStream;
|
|
import java.io.IOException;
|
|
|
|
import com.kaijin.AdvPowerMan.AdvancedPowerManagement;
|
|
import com.kaijin.AdvPowerMan.Info;
|
|
import com.kaijin.AdvPowerMan.MovingAverage;
|
|
import com.kaijin.AdvPowerMan.Utils;
|
|
|
|
import net.minecraft.inventory.IInventory;
|
|
import net.minecraft.inventory.ISidedInventory;
|
|
import net.minecraft.item.Item;
|
|
import net.minecraft.item.ItemStack;
|
|
import net.minecraft.nbt.NBTTagCompound;
|
|
import net.minecraft.nbt.NBTTagList;
|
|
import net.minecraft.network.Packet;
|
|
import net.minecraft.network.PacketBuffer;
|
|
import net.minecraft.tileentity.TileEntity;
|
|
import net.minecraftforge.common.util.Constants;
|
|
import net.minecraftforge.common.util.ForgeDirection;
|
|
import net.minecraftforge.common.MinecraftForge;
|
|
import cpw.mods.fml.relauncher.Side;
|
|
import cpw.mods.fml.relauncher.SideOnly;
|
|
|
|
public class TEChargingBench extends TECommonBench implements IEnergySink, IEnergyStorage, IInventory, ISidedInventory{
|
|
// Base values
|
|
public int baseMaxInput;
|
|
public int baseStorage;
|
|
|
|
// Adjustable values that need communicating via container
|
|
public int adjustedMaxInput;
|
|
public int adjustedStorage;
|
|
|
|
public int currentEnergy;
|
|
// For outside texture display
|
|
public int chargeLevel;
|
|
|
|
public float drainFactor;
|
|
public float chargeFactor;
|
|
|
|
protected int energyReceived = 0;
|
|
public MovingAverage inputTracker = new MovingAverage(12);
|
|
|
|
public int ticksRequired = 0;
|
|
public int energyRequired = 0;
|
|
|
|
private static final int[] ChargingBenchSideInput = {Info.CB_SLOT_INPUT};
|
|
private static final int[] ChargingBenchSideOutput = {Info.CB_SLOT_OUTPUT};
|
|
private static final int[] ChargingBenchSideInOut = {Info.CB_SLOT_INPUT, Info.CB_SLOT_OUTPUT};
|
|
private static final int[] ChargingBenchSidePower = {Info.CB_SLOT_POWER_SOURCE};
|
|
|
|
public TEChargingBench() // Default constructor used only when loading tile
|
|
// entity from world save
|
|
{
|
|
super();
|
|
// Do nothing else; Creating the inventory array and loading previous
|
|
// values will be handled in NBT read method momentarily.
|
|
}
|
|
|
|
public TEChargingBench(int i) // Constructor used when placing a new tile
|
|
// entity, to set up correct parameters
|
|
{
|
|
super();
|
|
contents = new ItemStack[19];
|
|
|
|
// base tier = what we're passed, so 1, 2 or 3
|
|
baseTier = i;
|
|
initializeBaseValues();
|
|
|
|
// setup Adjusted variables to = defaults, we'll be adjusting them in
|
|
// entityUpdate
|
|
adjustedMaxInput = baseMaxInput;
|
|
adjustedStorage = baseStorage;
|
|
|
|
powerTier = baseTier;
|
|
|
|
drainFactor = 1.0F;
|
|
chargeFactor = 1.0F;
|
|
}
|
|
|
|
protected void initializeBaseValues(){
|
|
// if (ChargingBench.isDebugging)
|
|
// System.out.println("Initializing - BaseTier: " + baseTier);
|
|
|
|
// Max Input math = 32 for tier 1, 128 for tier 2, 512 for tier 3
|
|
baseMaxInput = (int) EnergyNet.instance.getPowerFromTier(baseTier);
|
|
// if (ChargingBench.isDebugging) System.out.println("BaseMaxInput: " +
|
|
// baseMaxInput);
|
|
|
|
switch(baseTier){
|
|
case 1:
|
|
baseStorage = 40000;
|
|
break;
|
|
case 2:
|
|
baseStorage = 600000;
|
|
break;
|
|
case 3:
|
|
baseStorage = 10000000;
|
|
break;
|
|
default:
|
|
baseStorage = 0;
|
|
}
|
|
// if (ChargingBench.isDebugging) System.out.println("BaseStorage: " +
|
|
// baseStorage);
|
|
}
|
|
|
|
/**
|
|
* Called to upgrade (or downgrade) a charging bench to a certain tier.
|
|
*
|
|
* @param newTier
|
|
* The tier to replace the charging bench with, based on the
|
|
* component item used
|
|
* @return the original tier of the charging bench, for creating the correct
|
|
* component item
|
|
*/
|
|
public int swapBenchComponents(int newTier){
|
|
int oldTier = baseTier;
|
|
baseTier = newTier;
|
|
worldObj.setBlockMetadataWithNotify(xCoord, yCoord, zCoord, Info.CB_META + newTier - 1, 3);
|
|
initializeBaseValues();
|
|
doUpgradeEffects();
|
|
chargeLevel = gaugeEnergyScaled(12);
|
|
worldObj.markBlockForUpdate(xCoord, yCoord, zCoord);
|
|
return oldTier;
|
|
}
|
|
|
|
// IC2 API stuff
|
|
|
|
// IEnergySink
|
|
|
|
@Override
|
|
public void setStored(int energy){
|
|
// What uses this?
|
|
}
|
|
|
|
@Override
|
|
public int addEnergy(int amount){
|
|
// Returning our current energy value always, we do not implement this
|
|
// function
|
|
return currentEnergy;
|
|
}
|
|
|
|
@Override
|
|
public int getSinkTier(){
|
|
return powerTier;
|
|
}
|
|
|
|
// IEnergyStorage
|
|
|
|
/**
|
|
* Get the amount of energy currently stored in the block.
|
|
*
|
|
* @return Energy stored in the block
|
|
*/
|
|
@Override
|
|
public int getStored(){
|
|
return currentEnergy;
|
|
}
|
|
|
|
/**
|
|
* Get the maximum amount of energy the block can store.
|
|
*
|
|
* @return Maximum energy stored
|
|
*/
|
|
@Override
|
|
public int getCapacity(){
|
|
return adjustedStorage;
|
|
}
|
|
|
|
/**
|
|
* Get the block's energy output.
|
|
*
|
|
* @return Energy output in EU/t
|
|
*/
|
|
@Override
|
|
public int getOutput(){
|
|
return 0;
|
|
}
|
|
|
|
// End IC2 API
|
|
|
|
@Override
|
|
public int getGuiID(){
|
|
return Info.GUI_ID_CHARGING_BENCH;
|
|
}
|
|
|
|
/**
|
|
* This will cause the block to drop anything inside it, create a new item
|
|
* in the world of its type, invalidate the tile entity, remove itself from
|
|
* the IC2 EnergyNet and clear the block space (set it to air)
|
|
*/
|
|
@Override
|
|
protected void selfDestroy(){
|
|
dropContents();
|
|
ItemStack stack = new ItemStack(AdvancedPowerManagement.blockAdvPwrMan, 1, Info.CB_META + baseTier - 1);
|
|
dropItem(stack);
|
|
worldObj.setBlockToAir(xCoord, yCoord, zCoord);
|
|
this.invalidate();
|
|
}
|
|
|
|
public void doUpgradeEffects(){
|
|
// Count our upgrades
|
|
ItemStack stack;
|
|
int ocCount = 0;
|
|
int tfCount = 0;
|
|
int esCount = 0;
|
|
for(int i = Info.CB_SLOT_UPGRADE; i < Info.CB_SLOT_UPGRADE + 4; ++i){
|
|
stack = contents[i];
|
|
if(stack != null){
|
|
if(stack.isItemEqual(Info.ic2overclockerUpg)){
|
|
ocCount += stack.stackSize;
|
|
}else if(stack.isItemEqual(Info.ic2storageUpg)){
|
|
esCount += stack.stackSize;
|
|
}else if(stack.isItemEqual(Info.ic2transformerUpg)){
|
|
tfCount += stack.stackSize;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Cap upgrades at sane quantities that won't result in negative energy
|
|
// storage from integer overflows and such.
|
|
if(ocCount > 20)
|
|
ocCount = 20;
|
|
if(esCount > 64)
|
|
esCount = 64;
|
|
if(tfCount > 3)
|
|
tfCount = 3;
|
|
|
|
// Overclockers:
|
|
chargeFactor = (float) Math.pow(1.3F, ocCount); // 30% more power
|
|
// transferred to an
|
|
// item per overclocker,
|
|
// exponential.
|
|
drainFactor = (float) Math.pow(1.5F, ocCount); // 50% more power drained
|
|
// per overclocker,
|
|
// exponential. Yes, you
|
|
// waste power, that's
|
|
// how OCs work.
|
|
|
|
// Transformers:
|
|
powerTier = baseTier + tfCount; // Allows better energy storage items to
|
|
// be plugged into the battery slot of
|
|
// lower tier benches.
|
|
if(powerTier > 3)
|
|
powerTier = 3;
|
|
|
|
adjustedMaxInput = (int) Math.pow(2.0D, (double) (2 * (baseTier + tfCount) + 3));
|
|
if(adjustedMaxInput > 2048)
|
|
adjustedMaxInput = 2048; // You can feed EV in with 1-4 TF upgrades,
|
|
// if you so desire.
|
|
|
|
// Energy Storage:
|
|
switch(baseTier){
|
|
case 1:
|
|
adjustedStorage = baseStorage + esCount * 10000; // LV: 25%
|
|
// additional
|
|
// storage per
|
|
// upgrade
|
|
// (10,000).
|
|
break;
|
|
case 2:
|
|
adjustedStorage = baseStorage + esCount * 60000; // MV: 10%
|
|
// additional
|
|
// storage per
|
|
// upgrade
|
|
// (60,000).
|
|
break;
|
|
case 3:
|
|
adjustedStorage = baseStorage + esCount * 500000; // HV: 5%
|
|
// additional
|
|
// storage per
|
|
// upgrade
|
|
// (500,000).
|
|
break;
|
|
default:
|
|
adjustedStorage = baseStorage; // This shouldn't ever happen, but
|
|
// just in case, it shouldn't crash
|
|
// it - storage upgrades just won't
|
|
// work.
|
|
}
|
|
if(currentEnergy > adjustedStorage)
|
|
currentEnergy = adjustedStorage; // If storage has decreased, lose
|
|
// any excess energy.
|
|
}
|
|
|
|
public boolean isItemValid(int slot, ItemStack stack){
|
|
// Decide if the item is a valid IC2 electrical item
|
|
if(stack != null && stack.getItem() instanceof IElectricItem){
|
|
IElectricItem item = (IElectricItem) (stack.getItem());
|
|
// Is the item appropriate for this slot?
|
|
if(slot == Info.CB_SLOT_POWER_SOURCE && item.canProvideEnergy(stack) && item.getTier(stack) <= powerTier)
|
|
return true;
|
|
if(slot >= Info.CB_SLOT_CHARGING && slot < Info.CB_SLOT_CHARGING + 12 && item.getTier(stack) <= baseTier)
|
|
return true;
|
|
if(slot >= Info.CB_SLOT_UPGRADE
|
|
&& slot < Info.CB_SLOT_UPGRADE + 4
|
|
&& (stack.isItemEqual(Info.ic2overclockerUpg) || stack.isItemEqual(Info.ic2transformerUpg) || stack
|
|
.isItemEqual(Info.ic2storageUpg)))
|
|
return true;
|
|
if(slot == Info.CB_SLOT_INPUT && item.getTier(stack) <= baseTier)
|
|
return true;
|
|
if(slot == Info.CB_SLOT_OUTPUT)
|
|
return true; // GUI won't allow placement of items here, but if
|
|
// the bench or an external machine does, it
|
|
// should at least let it sit there as long as
|
|
// it's an electrical item.
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Reads a tile entity from NBT.
|
|
*/
|
|
@Override
|
|
public void readFromNBT(NBTTagCompound nbttagcompound){
|
|
super.readFromNBT(nbttagcompound);
|
|
|
|
if(Info.isDebugging)
|
|
System.out.println("CB ID: " + nbttagcompound.getString("id"));
|
|
|
|
baseTier = nbttagcompound.getInteger("baseTier");
|
|
currentEnergy = nbttagcompound.getInteger("currentEnergy");
|
|
// if (ChargingBench.isDebugging)
|
|
// System.out.println("ReadNBT.CurrentEergy: " + currentEnergy);
|
|
|
|
// Our inventory
|
|
contents = new ItemStack[Info.CB_INVENTORY_SIZE];
|
|
NBTTagList nbttaglist = nbttagcompound.getTagList("Items", Constants.NBT.TAG_COMPOUND);
|
|
for(int i = 0; i < nbttaglist.tagCount(); ++i){
|
|
NBTTagCompound nbttagcompound1 = (NBTTagCompound) nbttaglist.getCompoundTagAt(i);
|
|
int j = nbttagcompound1.getByte("Slot") & 255;
|
|
|
|
if(j >= 0 && j < contents.length){
|
|
contents[j] = ItemStack.loadItemStackFromNBT(nbttagcompound1);
|
|
}
|
|
}
|
|
|
|
// We can calculate these, no need to save/load them.
|
|
initializeBaseValues();
|
|
doUpgradeEffects();
|
|
}
|
|
|
|
/**
|
|
* Writes a tile entity to NBT.
|
|
*/
|
|
@Override
|
|
public void writeToNBT(NBTTagCompound nbttagcompound){
|
|
super.writeToNBT(nbttagcompound);
|
|
|
|
nbttagcompound.setInteger("baseTier", baseTier);
|
|
nbttagcompound.setInteger("currentEnergy", currentEnergy);
|
|
// if (ChargingBench.isDebugging)
|
|
// System.out.println("WriteNBT.CurrentEergy: " + currentEnergy);
|
|
|
|
// Our inventory
|
|
NBTTagList nbttaglist = new NBTTagList();
|
|
for(int i = 0; i < contents.length; ++i){
|
|
if(contents[i] != null){
|
|
// if (ChargingBench.isDebugging)
|
|
// System.out.println("WriteNBT contents[" + i + "] stack tag: "
|
|
// + contents[i].stackTagCompound);
|
|
NBTTagCompound nbttagcompound1 = new NBTTagCompound();
|
|
nbttagcompound1.setByte("Slot", (byte) i);
|
|
contents[i].writeToNBT(nbttagcompound1);
|
|
nbttaglist.appendTag(nbttagcompound1);
|
|
}
|
|
}
|
|
nbttagcompound.setTag("Items", nbttaglist);
|
|
}
|
|
|
|
@Override
|
|
public void updateEntity() // TODO Marked for easy access
|
|
{
|
|
if(AdvancedPowerManagement.proxy.isClient()){
|
|
return;
|
|
}
|
|
|
|
if(!initialized && worldObj != null){
|
|
EnergyTileLoadEvent loadEvent = new EnergyTileLoadEvent(this);
|
|
MinecraftForge.EVENT_BUS.post(loadEvent);
|
|
// EnergyNet.getForWorld(worldObj).addTileEntity(this);
|
|
initialized = true;
|
|
}
|
|
|
|
inputTracker.tick(energyReceived);
|
|
energyReceived = 0;
|
|
ticksRequired = 0;
|
|
energyRequired = 0;
|
|
|
|
boolean lastWorkState = doingWork;
|
|
doingWork = false;
|
|
|
|
// Work done every tick
|
|
drainPowerSource();
|
|
chargeItems();
|
|
moveOutputItems();
|
|
acceptInputItems();
|
|
|
|
// Determine if and how completion time will be affected by lack of
|
|
// energy and input rate
|
|
if(energyRequired > currentEnergy){
|
|
final int deficit = energyRequired - currentEnergy;
|
|
final float avg = inputTracker.getAverage();
|
|
if(avg >= 1.0F){
|
|
final int time = (int) Math.ceil(((float) deficit) / avg);
|
|
if(time > ticksRequired)
|
|
ticksRequired = time;
|
|
}else
|
|
ticksRequired = -1;
|
|
}
|
|
|
|
// Trigger this only when charge level passes where it would need to
|
|
// update the client texture
|
|
int oldChargeLevel = chargeLevel;
|
|
chargeLevel = gaugeEnergyScaled(12);
|
|
if(oldChargeLevel != chargeLevel || lastWorkState != doingWork){
|
|
// if (ChargingBench.isDebugging)
|
|
// System.out.println("TE oldChargeLevel: " + oldChargeLevel +
|
|
// " chargeLevel: " + chargeLevel);
|
|
worldObj.markBlockForUpdate(xCoord, yCoord, zCoord);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Looks in the power item slot to see if it can pull in EU from a valid
|
|
* item in that slot. If so, pull in as much EU as the item allows to be
|
|
* transferred per tick up to the maximum energy transfer rate based on our
|
|
* tier, limited also by the maximum energy storage capacity. ie. do not
|
|
* pull in more than we have room for
|
|
*
|
|
* @return
|
|
*/
|
|
private void drainPowerSource(){
|
|
double chargeReturned = 0;
|
|
|
|
ItemStack stack = getStackInSlot(Info.CB_SLOT_POWER_SOURCE);
|
|
if(stack != null && stack.getItem() instanceof IElectricItem && currentEnergy < adjustedStorage){
|
|
IElectricItem powerSource = (IElectricItem) (stack.getItem());
|
|
|
|
Item emptyItem = powerSource.getEmptyItem(stack);
|
|
int chargedItemID = Item.getIdFromItem(powerSource.getChargedItem(stack));
|
|
|
|
if(Item.getIdFromItem(stack.getItem()) == chargedItemID){
|
|
if(powerSource.getTier(stack) <= powerTier && powerSource.canProvideEnergy(stack)){
|
|
double itemTransferLimit = powerSource.getTransferLimit(stack);
|
|
double energyNeeded = adjustedStorage - currentEnergy;
|
|
|
|
// Test if the amount of energy we have room for is greater
|
|
// than what the item can transfer per tick.
|
|
if(energyNeeded > itemTransferLimit){
|
|
// If so, request the max it can transfer per tick.
|
|
energyNeeded = itemTransferLimit;
|
|
// If we need less than it can transfer per tick,
|
|
// request only what we have room for so we don't waste
|
|
// power.
|
|
}
|
|
|
|
if(energyNeeded > 0){
|
|
chargeReturned = ElectricItem.manager.discharge(stack, energyNeeded, powerTier, false, false, false);
|
|
// Add the energy we received to our current energy
|
|
// level,
|
|
currentEnergy += chargeReturned;
|
|
if(chargeReturned > 0)
|
|
doingWork = true;
|
|
// and make sure that we didn't go over. If we somehow
|
|
// did, drop the excess.
|
|
if(currentEnergy > adjustedStorage)
|
|
currentEnergy = adjustedStorage;
|
|
}
|
|
}
|
|
|
|
// Workaround for buggy IC2 API .discharge that automatically
|
|
// switches stack to emptyItemID but leaves a stackTagCompound
|
|
// on it, so it can't be stacked with never-used empties
|
|
if(chargedItemID != Item.getIdFromItem(emptyItem) && ElectricItem.manager.discharge(stack, 1, powerTier, false, true, true) == 0){
|
|
// if (ChargingBench.isDebugging)
|
|
// System.out.println("Switching to emptyItemID: " +
|
|
// emptyItemID + " from stack.itemID: " + stack.itemID +
|
|
// " - chargedItemID: " + chargedItemID);
|
|
setInventorySlotContents(Info.CB_SLOT_POWER_SOURCE, new ItemStack(emptyItem, 1, 0));
|
|
// ItemStack newStack = new ItemStack(emptyItemID, 1, 0);
|
|
// contents[ChargingBench.slotPowerSource] = newStack;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Look through all of the items in our main inventory and determine the
|
|
* current charge level, maximum charge level and maximum base charge rate
|
|
* for each item. Increase maximum charge rate for each item based on
|
|
* overclockers as appropriate, then, starting with the first slot in the
|
|
* main inventory, transfer one tick worth of energy from our internal
|
|
* storage to the item. Continue doing this for all items in the inventory
|
|
* until we reach the end of the main inventory or run out of internal EU
|
|
* storage.
|
|
*/
|
|
private void chargeItems(){
|
|
for(int i = Info.CB_SLOT_CHARGING; i < Info.CB_SLOT_CHARGING + 12; i++){
|
|
ItemStack stack = contents[i];
|
|
if(stack != null && stack.getItem() instanceof IElectricItem && stack.stackSize == 1){
|
|
IElectricItem item = (IElectricItem) (stack.getItem());
|
|
if(item.getTier(stack) <= baseTier){
|
|
double itemTransferLimit = item.getTransferLimit(stack);
|
|
if(itemTransferLimit == 0)
|
|
itemTransferLimit = baseMaxInput;
|
|
int adjustedTransferLimit = (int) Math.ceil(chargeFactor * itemTransferLimit);
|
|
double amountNeeded;
|
|
double missing;
|
|
int consumption;
|
|
if(Item.getIdFromItem(item.getChargedItem(stack)) != Item.getIdFromItem(item.getEmptyItem(stack)) || stack.isStackable()){
|
|
// Running stack.copy() on every item every tick would
|
|
// be a horrible thing for performance, but the
|
|
// workaround is needed
|
|
// for ElectricItem.charge adding stackTagCompounds for
|
|
// charge level to EmptyItemID batteries even when run
|
|
// in simulate mode.
|
|
// Limiting its use by what is hopefully a broad enough
|
|
// test to catch all cases where it's necessary in order
|
|
// to avoid problems.
|
|
// Using it for any item types listed as stackable and
|
|
// for any items where the charged and empty item IDs
|
|
// differ.
|
|
final ItemStack stackCopy = stack.copy();
|
|
amountNeeded = ElectricItem.manager.charge(stackCopy, adjustedTransferLimit, baseTier, true, true);
|
|
if(amountNeeded == adjustedTransferLimit){
|
|
missing = ElectricItem.manager.charge(stackCopy, item.getMaxCharge(stackCopy), baseTier, true, true);
|
|
}else
|
|
missing = amountNeeded;
|
|
}else{
|
|
amountNeeded = ElectricItem.manager.charge(stack, adjustedTransferLimit, baseTier, true, true);
|
|
if(amountNeeded == adjustedTransferLimit){
|
|
missing = ElectricItem.manager.charge(stack, item.getMaxCharge(stack), baseTier, true, true);
|
|
}else
|
|
missing = amountNeeded;
|
|
}
|
|
|
|
// How long will this item take and how much will it drain?
|
|
final int eta = (int) Math.ceil(((float) missing) / ((float) adjustedTransferLimit));
|
|
if(ticksRequired < eta)
|
|
ticksRequired = eta;
|
|
energyRequired += (int) Math.ceil((drainFactor / chargeFactor) * missing);
|
|
|
|
int adjustedEnergyUse = (int) Math.ceil((drainFactor / chargeFactor) * amountNeeded);
|
|
if(adjustedEnergyUse > 0 && currentEnergy > 0){
|
|
if(adjustedEnergyUse > currentEnergy){
|
|
// Allow that last trickle of energy to be
|
|
// transferred out of the bench
|
|
adjustedTransferLimit = (adjustedTransferLimit * currentEnergy) / adjustedEnergyUse;
|
|
adjustedEnergyUse = currentEnergy;
|
|
}
|
|
// We don't need to do this with the current API, it's
|
|
// switching the ItemID for us. Just make sure we don't
|
|
// try to charge stacked batteries, as mentioned above!
|
|
// int chargedItemID = item.getChargedItemId();
|
|
// if (stack.itemID != chargedItemID)
|
|
// {
|
|
// setInventorySlotContents(i, new
|
|
// ItemStack(chargedItemID, 1, 0));
|
|
// }
|
|
ElectricItem.manager.charge(contents[i], adjustedTransferLimit, baseTier, true, false);
|
|
currentEnergy -= adjustedEnergyUse;
|
|
if(currentEnergy < 0)
|
|
currentEnergy = 0;
|
|
doingWork = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* First, check the output slot to see if it's empty. If so, look to see if
|
|
* there are any fully charged items in the main inventory. Move the first
|
|
* fully charged item to the output slot.
|
|
*/
|
|
private void moveOutputItems(){
|
|
ItemStack stack = contents[Info.CB_SLOT_OUTPUT];
|
|
if(stack == null){
|
|
// Output slot is empty. Try to find a fully charged item to move
|
|
// there.
|
|
for(int slot = Info.CB_SLOT_CHARGING; slot < Info.CB_SLOT_CHARGING + 12; ++slot){
|
|
ItemStack currentStack = contents[slot];
|
|
if(currentStack != null && currentStack.getItem() instanceof IElectricItem){
|
|
// Test if the item is fully charged (cannot accept any more
|
|
// power).
|
|
if(ElectricItem.manager.charge(currentStack.copy(), 1, baseTier, false, true) == 0){
|
|
contents[Info.CB_SLOT_OUTPUT] = currentStack;
|
|
contents[slot] = null;
|
|
this.markDirty();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check to see if there are any items in the input slot. If so, check to
|
|
* see if there are any free charging slots. If so, move one from the input
|
|
* slot to a free charging slot. Do not move more than one, if the stack
|
|
* contains more.
|
|
*/
|
|
private void acceptInputItems(){
|
|
ItemStack stack = contents[Info.CB_SLOT_INPUT];
|
|
if(stack != null && stack.getItem() instanceof IElectricItem){
|
|
// Input slot contains something electrical. If possible, move one
|
|
// of it into the charging area.
|
|
IElectricItem item = (IElectricItem) (stack.getItem());
|
|
for(int slot = Info.CB_SLOT_CHARGING; slot < Info.CB_SLOT_CHARGING + 12; ++slot){
|
|
if(contents[slot] == null){
|
|
// Grab one unit from input and move it to the selected
|
|
// slot.
|
|
contents[slot] = decrStackSize(Info.CB_SLOT_INPUT, 1);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public int gaugeEnergyScaled(int gaugeSize){
|
|
if(currentEnergy <= 0){
|
|
return 0;
|
|
}
|
|
|
|
int result = currentEnergy * gaugeSize / adjustedStorage;
|
|
if(result > gaugeSize)
|
|
result = gaugeSize;
|
|
|
|
return result;
|
|
}
|
|
|
|
// Networking stuff
|
|
|
|
@SideOnly(Side.CLIENT)
|
|
@Override
|
|
public void receiveDescriptionData(int packetID, ByteBuf stream){
|
|
final int a;
|
|
final boolean b;
|
|
// try
|
|
// {
|
|
a = stream.readInt();
|
|
b = stream.readBoolean();
|
|
/*
|
|
* } catch (IOException e) { logDescPacketError(e); return; }
|
|
*/
|
|
chargeLevel = a;
|
|
doingWork = b;
|
|
worldObj.markBlockForUpdate(xCoord, yCoord, zCoord);
|
|
}
|
|
|
|
@Override
|
|
public Packet getDescriptionPacket(){
|
|
return createDescPacket();
|
|
}
|
|
|
|
@Override
|
|
protected void addUniqueDescriptionData(ByteBuf data) throws IOException{
|
|
data.writeInt(chargeLevel);
|
|
data.writeBoolean(doingWork);
|
|
}
|
|
|
|
// ISidedInventory
|
|
|
|
/*
|
|
* @Override public int getStartInventorySide(ForgeDirection side) { switch
|
|
* (side) { case UP: return Info.CB_SLOT_INPUT; case DOWN: return
|
|
* Info.CB_SLOT_OUTPUT; default: return Info.CB_SLOT_POWER_SOURCE; } }
|
|
*
|
|
* @Override public int getSizeInventorySide(ForgeDirection side) { // Each
|
|
* side accesses a single slot return 1; }
|
|
*/
|
|
|
|
@Override
|
|
public int[] getAccessibleSlotsFromSide(int side){
|
|
switch(side){
|
|
// Correct values for top and bottom sides: 0 = bottom, 1 = top
|
|
case 0:
|
|
// return ChargingBenchSideOutput;
|
|
case 1:
|
|
// return ChargingBenchSideInput;
|
|
return ChargingBenchSideInOut;
|
|
default:
|
|
return ChargingBenchSidePower;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean isItemValidForSlot(int i, ItemStack stack){
|
|
// Decide if the item is a valid IC2 electrical item
|
|
if(i == Info.CB_SLOT_POWER_SOURCE)
|
|
return Utils.isItemDrainable(stack, powerTier);
|
|
if(i == Info.CB_SLOT_INPUT)
|
|
return Utils.isItemChargeable(stack, powerTier);
|
|
// Info.CB_SLOT_OUTPUT ?
|
|
return false;
|
|
}
|
|
|
|
// Returns true if automation can insert the given item in the given slot
|
|
// from the given side. Args: Slot, item, side
|
|
@Override
|
|
public boolean canInsertItem(int i, ItemStack itemstack, int j) // canInsertItem
|
|
{
|
|
if(i == Info.CB_SLOT_INPUT || i == Info.CB_SLOT_POWER_SOURCE)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
// Returns true if automation can extract the given item in the given slot
|
|
// from the given side. Args: Slot, item, side
|
|
@Override
|
|
public boolean canExtractItem(int i, ItemStack itemstack, int j) // canExtractItem
|
|
{
|
|
if(i == Info.CB_SLOT_OUTPUT || i == Info.CB_SLOT_POWER_SOURCE)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
// IInventory
|
|
|
|
@Override
|
|
public int getSizeInventory(){
|
|
// Only input/output slots are accessible to machines
|
|
return 3;
|
|
}
|
|
|
|
@Override
|
|
public String getInventoryName(){
|
|
switch(baseTier){
|
|
case 1:
|
|
return Info.KEY_BLOCK_NAMES[0] + Info.KEY_NAME_SUFFIX;
|
|
case 3:
|
|
return Info.KEY_BLOCK_NAMES[1] + Info.KEY_NAME_SUFFIX;
|
|
case 4:
|
|
return Info.KEY_BLOCK_NAMES[2] + Info.KEY_NAME_SUFFIX;
|
|
}
|
|
return "";
|
|
}
|
|
|
|
@Override
|
|
public void markDirty(int slot){
|
|
if(slot == Info.CB_SLOT_INPUT || slot == Info.CB_SLOT_OUTPUT){
|
|
// Move item from input to output if not valid. (Wrong tier or not
|
|
// electric item.)
|
|
if(contents[Info.CB_SLOT_INPUT] != null && contents[Info.CB_SLOT_OUTPUT] == null){
|
|
if(!isItemValid(Info.CB_SLOT_INPUT, contents[Info.CB_SLOT_INPUT])){
|
|
contents[Info.CB_SLOT_OUTPUT] = contents[Info.CB_SLOT_INPUT];
|
|
contents[Info.CB_SLOT_INPUT] = null;
|
|
}
|
|
}
|
|
}else if(slot >= Info.CB_SLOT_UPGRADE && slot < Info.CB_SLOT_UPGRADE + 4){
|
|
// One of the upgrade slots was touched, so we need to recalculate.
|
|
doUpgradeEffects();
|
|
}else if(slot >= Info.CB_SLOT_CHARGING && slot < Info.CB_SLOT_CHARGING + 12){
|
|
// Make sure it's not fully charged already? Not sure, full items
|
|
// will be output in updateEntity
|
|
|
|
}else if(slot == Info.CB_SLOT_POWER_SOURCE){
|
|
// Perhaps eject the item if it's not valid? No, just leave it
|
|
// alone.
|
|
// If machinery added it the player can figure out the problem by
|
|
// trying to remove and replace it and realizing it won't fit.
|
|
}
|
|
super.markDirty();
|
|
}
|
|
|
|
@Override
|
|
public void markDirty(){
|
|
// We're not sure what called this or what slot was altered, so make
|
|
// sure the upgrade effects are correct just in case and then pass the
|
|
// call on.
|
|
doUpgradeEffects();
|
|
super.markDirty();
|
|
}
|
|
|
|
@Override
|
|
public boolean acceptsEnergyFrom(TileEntity emitter, ForgeDirection direction){
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public double getOutputEnergyUnitsPerTick(){
|
|
return 0;
|
|
}
|
|
|
|
@Override
|
|
public boolean isTeleporterCompatible(ForgeDirection side){
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public double getDemandedEnergy(){
|
|
// return (currentEnergy < adjustedStorage &&
|
|
// !receivingRedstoneSignal());
|
|
if(!receivingRedstoneSignal()){
|
|
return adjustedStorage - currentEnergy;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
@Override
|
|
public double injectEnergy(ForgeDirection directionFrom, double amount, double voltage){
|
|
int surplus = 0;
|
|
if(AdvancedPowerManagement.proxy.isServer()){
|
|
// if supply is greater than the max we can take per tick
|
|
if(amount > adjustedMaxInput){
|
|
// If the supplied EU is over the baseMaxInput, we're getting
|
|
// supplied higher than acceptable current. Pop ourselves off
|
|
// into the world and return all but 1 EU, or if the supply
|
|
// somehow was 1EU, return zero to keep IC2 from spitting out
|
|
// massive errors in the log
|
|
selfDestroy();
|
|
if(amount <= 1)
|
|
return 0;
|
|
else
|
|
return amount - 1;
|
|
}else{
|
|
if(currentEnergy > adjustedStorage)
|
|
currentEnergy = adjustedStorage;
|
|
currentEnergy += amount;
|
|
energyReceived += amount;
|
|
// check if our current energy level is now over the max energy
|
|
// level
|
|
if(currentEnergy > adjustedStorage){
|
|
// if so, our surplus to return is equal to that amount over
|
|
surplus = currentEnergy - adjustedStorage;
|
|
// and set our current energy level TO our max energy level
|
|
currentEnergy = adjustedStorage;
|
|
energyReceived -= surplus;
|
|
}
|
|
// surplus may be zero or greater here
|
|
}
|
|
}
|
|
return surplus;
|
|
}
|
|
}
|