Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,218 +1,187 @@
package gregtech.api.capability.impl;

import gnu.trove.list.TIntList;
import gnu.trove.list.array.TIntArrayList;
import java.util.List;
import java.util.ArrayList;
import gregtech.api.GTValues;
import gregtech.api.capability.GregtechCapabilities;
import gregtech.api.capability.IElectricItem;
import gregtech.api.capability.IEnergyContainer;
import gregtech.api.capability.impl.EnergyContainerHandler.IEnergyChangeListener;
import gregtech.api.metatileentity.MTETrait;
import gregtech.api.metatileentity.MetaTileEntity;
import gregtech.api.util.GTUtility;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.items.IItemHandlerModifiable;

import java.util.BitSet;
public class EnergyContainerBatteryBuffer extends EnergyContainerHandler {

public class EnergyContainerBatteryBuffer extends MTETrait implements IEnergyContainer {

private final BitSet batterySlotsUsedThisTick = new BitSet();
private final int tier;
private long amps = 0;
private long lastEnergyInputPerSec = 0;
private long lastEnergyOutputPerSec = 0;
private long energyInputPerSec = 0;
private long energyOutputPerSec = 0;

public EnergyContainerBatteryBuffer(MetaTileEntity metaTileEntity, int tier) {
super(metaTileEntity);

public EnergyContainerBatteryBuffer(MetaTileEntity metaTileEntity, int tier, int inventorySize) {
super(metaTileEntity, GTValues.V[tier] * inventorySize * 32L, GTValues.V[tier], inventorySize * 2L, GTValues.V[tier], inventorySize);
this.tier = tier;
}

@Override
public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage) {
long usedAmps = 0;
amperage -= amps;
if(amperage <= 0)
if (amperage <= 0 || voltage <= 0)
return 0;

List<IElectricItem> batteries = getNonFullBatteries();
long maxAmps = batteries.size() * 2L - amps;
long usedAmps = Math.min(maxAmps, amperage);
if (maxAmps <= 0)
return 0;

if (side == null || inputsEnergy(side)) {
if (voltage > getInputVoltage()) {
GTUtility.doOvervoltageExplosion(metaTileEntity, voltage);
return Math.min(amperage, getInputAmperage() - amps);
}
IItemHandlerModifiable inventory = getInventory();
for (int i = 0; i < inventory.getSlots(); i++) {
if (batterySlotsUsedThisTick.get(i)) continue;
ItemStack batteryStack = inventory.getStackInSlot(i);
IElectricItem electricItem = getBatteryContainer(batteryStack);
if (electricItem == null) continue;
if (chargeItemWithVoltage(electricItem, voltage, getTier(), true)) {
chargeItemWithVoltage(electricItem, voltage, getTier(), false);
inventory.setStackInSlot(i, batteryStack);
this.batterySlotsUsedThisTick.set(i);
if(++usedAmps == amperage) break;
}
return usedAmps;
}
}
if (usedAmps > 0L) {
notifyEnergyListener(false);
}
amps += usedAmps;
energyInputPerSec += voltage * usedAmps;
return usedAmps;
}

@Override
public long getInputPerSec() {
return lastEnergyInputPerSec;
}
//Prioritizes as many packets as available from the buffer
long internalAmps = Math.min(maxAmps, Math.max(0, getInternalStorage() / voltage));

@Override
public long getOutputPerSec() {
return lastEnergyOutputPerSec;
}
usedAmps = Math.min(usedAmps, maxAmps - internalAmps);
amps += usedAmps;
energyInputPerSec += usedAmps * voltage;

private static boolean chargeItemWithVoltage(IElectricItem electricItem, long voltage, int tier, boolean simulate) {
long charged = electricItem.charge(voltage, tier, false, simulate);
return charged > 0;
}
long energy = (usedAmps + internalAmps) * voltage;
long distributed = energy / batteries.size();

for (IElectricItem electricItem : batteries) {
energy -= electricItem.charge(Math.min(distributed, GTValues.V[electricItem.getTier()] * 2L), getTier(), true, false);
}

private static long chargeItem(IElectricItem electricItem, long amount, int tier, boolean discharge) {
if (!discharge) {
return electricItem.charge(amount, tier, false, false);
} else {
return electricItem.discharge(amount, tier, true, true, false);
//Remove energy used and then transfer overflow energy into the internal buffer
setEnergyStored(getInternalStorage() - internalAmps * voltage + energy);
return usedAmps;
}
return 0;
}

@Override
public void update() {
amps = 0;
if (!metaTileEntity.getWorld().isRemote) {
if (metaTileEntity.getOffsetTimer() % 20 == 0) {
lastEnergyInputPerSec = energyInputPerSec;
lastEnergyOutputPerSec = energyOutputPerSec;
energyInputPerSec = 0;
energyOutputPerSec = 0;
}
this.batterySlotsUsedThisTick.clear();
EnumFacing outFacing = metaTileEntity.getFrontFacing();
TileEntity tileEntity = metaTileEntity.getWorld().getTileEntity(metaTileEntity.getPos().offset(outFacing));
if (tileEntity == null) {
return;
}
IEnergyContainer energyContainer = tileEntity.getCapability(GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER, outFacing.getOpposite());
if (energyContainer == null) {
return;
}
if (metaTileEntity.getWorld().isRemote) {
return;
}
if (metaTileEntity.getOffsetTimer() % 20 == 0) {
lastEnergyInputPerSec = energyInputPerSec;
lastEnergyOutputPerSec = energyOutputPerSec;
energyInputPerSec = 0;
energyOutputPerSec = 0;
}

EnumFacing outFacing = metaTileEntity.getFrontFacing();
TileEntity tileEntity = metaTileEntity.getWorld().getTileEntity(metaTileEntity.getPos().offset(outFacing));
if (tileEntity == null) {
return;
}
IEnergyContainer energyContainer = tileEntity.getCapability(GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER, outFacing.getOpposite());
if (energyContainer == null) {
return;
}

IItemHandlerModifiable inventory = getInventory();
long voltage = getOutputVoltage();
long maxAmperage = 0L;
TIntList slotsList = new TIntArrayList();
for (int i = 0; i < inventory.getSlots(); i++) {
ItemStack batteryStack = inventory.getStackInSlot(i);
IElectricItem electricItem = getBatteryContainer(batteryStack);
if (electricItem == null) continue;
if (electricItem.discharge(voltage, getTier(), true, true, true) == voltage) {
slotsList.add(i);
maxAmperage++;
}
long voltage = getOutputVoltage();
List<IElectricItem> batteries = getNonEmptyBatteries();
if (batteries.size() > 0) {
//Prioritize as many packets as available of energy created
long internalAmps = Math.abs(Math.min(0, getInternalStorage() / voltage));
long genAmps = Math.max(0, batteries.size() - internalAmps);
long outAmps = 0L;

if (genAmps > 0) {
outAmps = energyContainer.acceptEnergyFromNetwork(outFacing.getOpposite(), voltage, genAmps);
if (outAmps == 0 && internalAmps == 0)
return;
energyOutputPerSec += outAmps * voltage;
}
if (maxAmperage == 0) return;
long amperageUsed = energyContainer.acceptEnergyFromNetwork(outFacing.getOpposite(), voltage, maxAmperage);
if (amperageUsed == 0) return;
energyOutputPerSec += amperageUsed * voltage;
for (int i : slotsList.toArray()) {
ItemStack batteryStack = inventory.getStackInSlot(i);
IElectricItem electricItem = getBatteryContainer(batteryStack);
if (electricItem == null) continue;
electricItem.discharge(voltage, getTier(), true, true, false);
inventory.setStackInSlot(i, batteryStack);
if (--amperageUsed == 0) break;

long energy = (outAmps + internalAmps) * voltage;
long distributed = energy / batteries.size();

for (IElectricItem electricItem : batteries) {
energy -= electricItem.discharge(distributed, getTier(), false, true, false);
}
notifyEnergyListener(false);

//Subtract energy created out of thin air from the buffer
setEnergyStored(getInternalStorage() + internalAmps * voltage - energy);
}
}

@Override
public long getEnergyCapacity() {
long energyCapacity = 0L;
private long getInternalStorage() {
return energyStored;
}

private List<IElectricItem> getNonFullBatteries() {
IItemHandlerModifiable inventory = getInventory();
List<IElectricItem> batteries = new ArrayList<>();
for (int i = 0; i < inventory.getSlots(); i++) {
ItemStack batteryStack = inventory.getStackInSlot(i);
IElectricItem electricItem = getBatteryContainer(batteryStack);
if (electricItem == null) continue;
energyCapacity += electricItem.getMaxCharge();
if (electricItem.getCharge() < electricItem.getMaxCharge()) {
batteries.add(electricItem);
}
}
return energyCapacity;
return batteries;
}

@Override
public long getEnergyStored() {
long energyStored = 0L;
private List<IElectricItem> getNonEmptyBatteries() {
IItemHandlerModifiable inventory = getInventory();
List<IElectricItem> batteries = new ArrayList<>();
for (int i = 0; i < inventory.getSlots(); i++) {
ItemStack batteryStack = inventory.getStackInSlot(i);
IElectricItem electricItem = getBatteryContainer(batteryStack);
if (electricItem == null) continue;
energyStored += electricItem.getCharge();
if (electricItem.canProvideChargeExternally() && electricItem.getCharge() > 0) {
batteries.add(electricItem);
}
}
return energyStored;
return batteries;
}

@Override
public long getInputAmperage() {
long inputAmperage = 0L;
public long getEnergyCapacity() {
long energyCapacity = 0L;
IItemHandlerModifiable inventory = getInventory();
for (int i = 0; i < inventory.getSlots(); i++) {
ItemStack batteryStack = inventory.getStackInSlot(i);
IElectricItem electricItem = getBatteryContainer(batteryStack);
if (electricItem == null) continue;
inputAmperage++;
energyCapacity += electricItem.getMaxCharge();
}
return inputAmperage;
}

public IElectricItem getBatteryContainer(ItemStack itemStack) {
IElectricItem electricItem = itemStack.getCapability(GregtechCapabilities.CAPABILITY_ELECTRIC_ITEM, null);
if (electricItem != null && getTier() >= electricItem.getTier() &&
electricItem.canProvideChargeExternally())
return electricItem;
return null;
return energyCapacity;
}

@Override
public long changeEnergy(long energyToAdd) {
boolean isDischarge = energyToAdd < 0L;
energyToAdd = Math.abs(energyToAdd);
long initialEnergyToAdd = energyToAdd;
public long getEnergyStored() {
long energyStored = 0L;
IItemHandlerModifiable inventory = getInventory();
for (int i = 0; i < inventory.getSlots(); i++) {
ItemStack batteryStack = inventory.getStackInSlot(i);
IElectricItem electricItem = getBatteryContainer(batteryStack);
if (electricItem == null) continue;
long charged = chargeItem(electricItem, energyToAdd, getTier(), isDischarge);
energyToAdd -= charged;
if (energyToAdd == 0L) break;
energyStored += electricItem.getCharge();
}
long energyAdded = initialEnergyToAdd - energyToAdd;
if (energyAdded > 0L) {
return energyStored;
}

@Override
public void setEnergyStored(long energyStored) {
this.energyStored = energyStored;
if (!metaTileEntity.getWorld().isRemote) {
metaTileEntity.markDirty();
notifyEnergyListener(false);
}
energyInputPerSec += energyAdded;
return energyAdded;
}

@Override
public void deserializeNBT(NBTTagCompound compound) {
super.deserializeNBT(compound);
notifyEnergyListener(true);
public IElectricItem getBatteryContainer(ItemStack itemStack) {
IElectricItem electricItem = itemStack.getCapability(GregtechCapabilities.CAPABILITY_ELECTRIC_ITEM, null);
if (electricItem != null && getTier() >= electricItem.getTier())
return electricItem;
return null;
}

public void notifyEnergyListener(boolean isInitialChange) {
Expand All @@ -221,21 +190,6 @@ public void notifyEnergyListener(boolean isInitialChange) {
}
}

@Override
public long getInputVoltage() {
return GTValues.V[getTier()];
}

@Override
public long getOutputVoltage() {
return getInputVoltage();
}

@Override
public long getOutputAmperage() {
return getInputAmperage();
}

@Override
public boolean inputsEnergy(EnumFacing side) {
return getMetaTileEntity().getFrontFacing() != side;
Expand All @@ -251,19 +205,6 @@ public String getName() {
return "BatteryEnergyContainer";
}

@Override
public int getNetworkID() {
return TraitNetworkIds.TRAIT_ID_ENERGY_CONTAINER;
}

@Override
public <T> T getCapability(Capability<T> capability) {
if (capability == GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER) {
return GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER.cast(this);
}
return null;
}

protected IItemHandlerModifiable getInventory() {
return metaTileEntity.getImportItems();
}
Expand Down
Loading