package shedar.mods.ic2.nuclearcontrol.tileentities;
import ic2.core.network.NetworkManager;
import ic2.api.energy.EnergyNet;
import ic2.api.energy.event.EnergyTileLoadEvent;
import ic2.api.energy.event.EnergyTileUnloadEvent;
import ic2.api.energy.tile.IEnergyConductor;
import ic2.api.item.IC2Items;
import ic2.api.network.INetworkClientTileEntityEventListener;
import ic2.api.network.INetworkDataProvider;
import ic2.api.network.INetworkUpdateListener;
import ic2.api.tile.IWrenchable;
import ic2.core.IC2;
import java.util.List;
import java.util.Vector;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Facing;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.util.Constants;
import net.minecraftforge.common.util.ForgeDirection;
import shedar.mods.ic2.nuclearcontrol.IC2NuclearControl;
import shedar.mods.ic2.nuclearcontrol.ISlotItemFilter;
import shedar.mods.ic2.nuclearcontrol.crossmod.EnergyStorageData;
import shedar.mods.ic2.nuclearcontrol.crossmod.ic2.IC2Type;
import shedar.mods.ic2.nuclearcontrol.utils.BlockDamages;
import cpw.mods.fml.common.FMLCommonHandler;
public class TileEntityAverageCounter extends TileEntity implements
IEnergyConductor, IWrenchable, INetworkClientTileEntityEventListener,
IInventory, ISlotItemFilter, INetworkDataProvider,
INetworkUpdateListener {
private static final int BASE_PACKET_SIZE = 32;
protected static final int DATA_POINTS = 11 * 20;
private boolean init;
private ItemStack inventory[];
// check out shedar.mods.ic2.nuclearcontrol.crossmod.EnergyStorageData
private byte prevPowerType;
public byte powerType;
// private double prevTotal;
private short prevFacing;
public short facing;
protected double[] data;
protected int index;
protected int updateTicker;
protected int tickRate;
protected short prevPeriod;
public short period;
protected int clientAverage = -1;
private double lastReceivedPower = 0; //#blameclassic
public int packetSize;
private boolean addedToEnergyNet;
public TileEntityAverageCounter() {
super();
inventory = new ItemStack[1];// transformers upgrade
addedToEnergyNet = false;
packetSize = BASE_PACKET_SIZE;
prevFacing = facing = 0;
data = new double[DATA_POINTS];
index = 0;
tickRate = 20;
updateTicker = tickRate;
prevPeriod = period = 1;
powerType = EnergyStorageData.TARGET_TYPE_IC2;
}
protected void initData() {
init = true;
}
@Override
public short getFacing() {
return (short) Facing.oppositeSide[facing];
}
@Override
public void setFacing(short f) {
if (addedToEnergyNet) {
EnergyTileUnloadEvent event = new EnergyTileUnloadEvent(this);
MinecraftForge.EVENT_BUS.post(event);
}
setSide((short) Facing.oppositeSide[f]);
addedToEnergyNet = false;
if (FMLCommonHandler.instance().getEffectiveSide().isServer()) {
EnergyTileLoadEvent event = new EnergyTileLoadEvent(this);
MinecraftForge.EVENT_BUS.post(event);
addedToEnergyNet = true;
}
}
private void setSide(short f) {
facing = f;
if(init && prevFacing != f)
((NetworkManager)IC2.network.get()).updateTileEntityField(this, "facing");
prevFacing = f;
}
private void setPeriod(short p) {
period = p;
if (prevPeriod != p) {
IC2.network.get().updateTileEntityField(this, "period");
}
prevPeriod = p;
}
public void setPowerType(byte p) {
powerType = p;
if (prevPowerType != p) {
IC2.network.get().updateTileEntityField(this, "powerType");
}
prevPowerType = p;
}
@Override
public void updateEntity() {
if (!init) {
initData();
markDirty();
}
if (FMLCommonHandler.instance().getEffectiveSide().isClient())
return;
if (!worldObj.isRemote){
if (!addedToEnergyNet){
EnergyTileLoadEvent event = new EnergyTileLoadEvent(this);
MinecraftForge.EVENT_BUS.post(event);
addedToEnergyNet = true;
}
index = (index + 1) % DATA_POINTS;
data[index] = 0;
this.getAverage();
double total = EnergyNet.instance.getTotalEnergyEmitted(this);
if(IC2NuclearControl.instance.crossIc2.getType() == IC2Type.SPEIGER){
double realTotal = total - lastReceivedPower;
lastReceivedPower = total;
data[index] = realTotal;
}else
data[index] = total;
this.setPowerType((byte)EnergyStorageData.TARGET_TYPE_IC2);
}
super.updateEntity();
}
@Override
public void readFromNBT(NBTTagCompound nbttagcompound) {
super.readFromNBT(nbttagcompound);
facing = nbttagcompound.getShort("facing");
index = nbttagcompound.getInteger("dataIndex");
updateTicker = nbttagcompound.getInteger("updateTicker");
prevPeriod = period = nbttagcompound.getShort("period");
powerType = nbttagcompound.getByte("powerType");
for (int i = 0; i < DATA_POINTS; i++)
data[i] = nbttagcompound.getLong("point-" + i);
NBTTagList nbttaglist = nbttagcompound.getTagList("Items",
Constants.NBT.TAG_COMPOUND);
inventory = new ItemStack[getSizeInventory()];
for (int i = 0; i < nbttaglist.tagCount(); i++) {
NBTTagCompound compound = nbttaglist
.getCompoundTagAt(i);
byte slotNum = compound.getByte("Slot");
if (slotNum >= 0 && slotNum < inventory.length) {
inventory[slotNum] = ItemStack.loadItemStackFromNBT(compound);
}
}
markDirty();
}
@Override
public void onNetworkUpdate(String field) {
if (field.equals("facing") && prevFacing != facing) {
worldObj.markBlockForUpdate(xCoord, yCoord, zCoord);
prevFacing = facing;
}
}
@Override
public void invalidate() {
if (!worldObj.isRemote && addedToEnergyNet) {
EnergyTileUnloadEvent event = new EnergyTileUnloadEvent(this);
MinecraftForge.EVENT_BUS.post(event);
addedToEnergyNet = false;
}
super.invalidate();
}
@Override
public void writeToNBT(NBTTagCompound nbttagcompound) {
super.writeToNBT(nbttagcompound);
nbttagcompound.setShort("facing", facing);
nbttagcompound.setInteger("dataIndex", index);
nbttagcompound.setInteger("updateTicker", updateTicker);
nbttagcompound.setShort("period", period);
nbttagcompound.setByte("powerType", powerType);
for (int i = 0; i < DATA_POINTS; i++)
nbttagcompound.setLong("point-" + i, (long) data[i]);
NBTTagList nbttaglist = new NBTTagList();
for (int i = 0; i < inventory.length; i++) {
if (inventory[i] != null) {
NBTTagCompound compound = new NBTTagCompound();
compound.setByte("Slot", (byte) i);
inventory[i].writeToNBT(compound);
nbttaglist.appendTag(compound);
}
}
nbttagcompound.setTag("Items", nbttaglist);
}
@Override
public int getSizeInventory() {
return inventory.length;
}
@Override
public ItemStack getStackInSlot(int slotNum) {
return inventory[slotNum];
}
@Override
public ItemStack decrStackSize(int slotNum, int amount) {
if (inventory[slotNum] != null) {
if (inventory[slotNum].stackSize <= amount) {
ItemStack itemStack = inventory[slotNum];
inventory[slotNum] = null;
markDirty();
return itemStack;
}
ItemStack taken = inventory[slotNum].splitStack(amount);
if (inventory[slotNum].stackSize == 0) {
inventory[slotNum] = null;
}
markDirty();
return taken;
}
return null;
}
@Override
public ItemStack getStackInSlotOnClosing(int var1) {
return null;
}
@Override
public void setInventorySlotContents(int slotNum, ItemStack itemStack) {
inventory[slotNum] = itemStack;
if (itemStack != null && itemStack.stackSize > getInventoryStackLimit()) {
itemStack.stackSize = getInventoryStackLimit();
}
markDirty();
}
@Override
public String getInventoryName() {
return "block.RemoteThermo";
}
@Override
public int getInventoryStackLimit() {
return 64;
}
@Override
public boolean isUseableByPlayer(EntityPlayer player) {
return worldObj.getTileEntity(xCoord, yCoord, zCoord) == this && player.getDistanceSq(xCoord + 0.5D, yCoord + 0.5D, zCoord + 0.5D) <= 64D;
}
@Override
public void openInventory() {}
@Override
public void closeInventory() {}
@Override
public void markDirty() {
super.markDirty();
int upgradeCountTransormer = 0;
ItemStack itemStack = inventory[0];
if (itemStack != null && itemStack.isItemEqual(IC2Items.getItem("transformerUpgrade")))
upgradeCountTransormer = itemStack.stackSize;
upgradeCountTransormer = Math.min(upgradeCountTransormer, 4);
if (worldObj != null && !worldObj.isRemote) {
packetSize = BASE_PACKET_SIZE * (int) Math.pow(4D, upgradeCountTransormer);
if (addedToEnergyNet) {
EnergyTileUnloadEvent event = new EnergyTileUnloadEvent(this);
MinecraftForge.EVENT_BUS.post(event);
}
addedToEnergyNet = false;
EnergyTileLoadEvent event = new EnergyTileLoadEvent(this);
MinecraftForge.EVENT_BUS.post(event);
addedToEnergyNet = true;
}
}
@Override
public boolean acceptsEnergyFrom(TileEntity emitter, ForgeDirection direction) {
return direction.ordinal() == getFacing();
}
@Override
public boolean emitsEnergyTo(TileEntity receiver, ForgeDirection direction) {
return direction.ordinal() != getFacing();
}
@Override
public boolean isItemValid(int slotIndex, ItemStack itemstack) {
return itemstack.isItemEqual(IC2Items.getItem("transformerUpgrade"));
}
@Override
public boolean wrenchCanSetFacing(EntityPlayer entityPlayer, int face) {
return getFacing() != face;
};
@Override
public boolean wrenchCanRemove(EntityPlayer entityPlayer) {
return true;
}
@Override
public float getWrenchDropRate() {
return 1;
}
@Override
public List<String> getNetworkedFields() {
Vector<String> vector = new Vector<String>(3);
vector.add("facing");
vector.add("period");
vector.add("powerType");
return vector;
}
public void setClientAverage(int value) {
clientAverage = value;
}
public int getClientAverage(){
if (clientAverage == -1)
return getAverage();
return clientAverage;
}
protected int getAverage(){
int start = DATA_POINTS + index - period * 20;
double sum = 0;
for (int i = 0; i < period * 20; i++)
sum += data[(start + i) % DATA_POINTS];
clientAverage = (int) Math.round(sum / period / 20);
return clientAverage;
}
@Override
public void onNetworkEvent(EntityPlayer player, int event) {
if (event == 0){
for (int i = 0; i < DATA_POINTS; i++)
data[i] = 0;
updateTicker = tickRate;
index = 0;
}else
setPeriod((short) event);
}
@Override
public ItemStack getWrenchDrop(EntityPlayer entityPlayer) {
return new ItemStack(IC2NuclearControl.blockNuclearControlMain, 1, BlockDamages.DAMAGE_AVERAGE_COUNTER);
}
@Override
public double getConductionLoss() {
return 0.025D;
}
@Override
public double getInsulationEnergyAbsorption() {
return 16384;
}
@Override
public double getInsulationBreakdownEnergy() {
return packetSize + 1;
}
@Override
public double getConductorBreakdownEnergy() {
return packetSize + 1;
}
@Override
public void removeInsulation(){
}
@Override
public void removeConductor(){
worldObj.setBlock(xCoord, yCoord, zCoord, Blocks.air, 0, 3);
worldObj.createExplosion(null, xCoord, yCoord, zCoord, 0.8F, false);
}
@Override
public boolean hasCustomInventoryName() {
return false;
}
@Override
public boolean isItemValidForSlot(int slot, ItemStack itemstack) {
return isItemValid(slot, itemstack);
}
}