Java tutorial
/******************************************************************************* * 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.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) Math.pow(2.0D, (double) (2 * baseTier + 3)); // 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 adjustedMaxInput; } // 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; } }