package org.halvors.electrometrics.common.tile.machine;
import cofh.api.energy.IEnergyReceiver;
import cpw.mods.fml.common.network.ByteBufUtils;
import io.netty.buffer.ByteBuf;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraftforge.common.util.ForgeDirection;
import org.halvors.electrometrics.common.base.IElectricTier;
import org.halvors.electrometrics.common.base.MachineType;
import org.halvors.electrometrics.common.base.Tier;
import org.halvors.electrometrics.common.base.tile.ITileActiveState;
import org.halvors.electrometrics.common.base.tile.ITileNetworkable;
import org.halvors.electrometrics.common.base.tile.ITileOwnable;
import org.halvors.electrometrics.common.network.NetworkHandler;
import org.halvors.electrometrics.common.network.packet.PacketTileEntity;
import org.halvors.electrometrics.common.util.MachineUtils;
import org.halvors.electrometrics.common.util.PlayerUtils;
import java.util.EnumSet;
import java.util.List;
import java.util.UUID;
/**
* This is the TileEntity of the Electricity Meter which provides a simple way to keep count of the electricity you use.
* Especially suitable for pay-by-use applications where a player buys electricity from another player on multiplayer worlds.
*
* @author halvors
*/
public class TileEntityElectricityMeter extends TileEntityElectricityProvider implements ITileNetworkable, ITileActiveState, IElectricTier, ITileOwnable {
// Whether or not this TileEntity's block is in it's active state.
private boolean isActive;
// The UUID of the player owning this.
private UUID ownerUUID;
// The name of the player owning this.
private String ownerName;
// The tier of this TileEntity.
private Tier.Electric electricTier;
// The amount of energy that has passed thru.
private double electricityCount;
private double electricityUsage;
private double electricityUsageLastTick;
public TileEntityElectricityMeter() {
this(MachineType.BASIC_ELECTRICITY_METER, Tier.Electric.BASIC);
}
public TileEntityElectricityMeter(MachineType machineType, Tier.Electric electricTier) {
super(machineType, electricTier.getCapacity(), electricTier.getMaxTransfer());
this.electricTier = electricTier;
}
@Override
public void readFromNBT(NBTTagCompound nbtTagCompound) {
super.readFromNBT(nbtTagCompound);
isActive = nbtTagCompound.getBoolean("isActive");
if (nbtTagCompound.hasKey("ownerUUIDM") && nbtTagCompound.hasKey("ownerUUIDL")) {
ownerUUID = new UUID(nbtTagCompound.getLong("ownerUUIDM"), nbtTagCompound.getLong("ownerUUIDL"));
}
if (nbtTagCompound.hasKey("ownerName")) {
ownerName = nbtTagCompound.getString("ownerName");
}
electricTier = Tier.Electric.values()[nbtTagCompound.getInteger("electricTier")];
electricityCount = nbtTagCompound.getDouble("electricityCount");
}
@Override
public void writeToNBT(NBTTagCompound nbtTagCompound) {
super.writeToNBT(nbtTagCompound);
nbtTagCompound.setBoolean("isActive", isActive);
if (ownerUUID != null) {
nbtTagCompound.setLong("ownerUUIDM", ownerUUID.getMostSignificantBits());
nbtTagCompound.setLong("ownerUUIDL", ownerUUID.getLeastSignificantBits());
}
if (ownerName != null) {
nbtTagCompound.setString("ownerName", ownerName);
}
nbtTagCompound.setInteger("electricTier", electricTier.ordinal());
nbtTagCompound.setDouble("electricityCount", electricityCount);
}
@Override
public void handlePacketData(ByteBuf dataStream) throws Exception {
super.handlePacketData(dataStream);
isActive = dataStream.readBoolean();
long ownerUUIDMostSignificantBits = dataStream.readLong();
long ownerUUIDLeastSignificantBits = dataStream.readLong();
if (ownerUUIDMostSignificantBits != 0 && ownerUUIDLeastSignificantBits != 0) {
ownerUUID = new UUID(ownerUUIDMostSignificantBits, ownerUUIDLeastSignificantBits);
}
String ownerNameText = ByteBufUtils.readUTF8String(dataStream);
if (!ownerNameText.isEmpty()) {
ownerName = ownerNameText;
}
electricTier = Tier.Electric.values()[dataStream.readInt()];
electricityCount = dataStream.readDouble();
// Re-render the block.
worldObj.markBlockForRenderUpdate(xCoord, yCoord, zCoord);
// Update potentially connected redstone blocks.
worldObj.notifyBlocksOfNeighborChange(xCoord, yCoord, zCoord, getBlockType());
}
@Override
public List<Object> getPacketData(List<Object> objects) {
super.getPacketData(objects);
objects.add(isActive);
objects.add(ownerUUID != null ? ownerUUID.getMostSignificantBits() : 0);
objects.add(ownerUUID != null ? ownerUUID.getLeastSignificantBits() : 0);
objects.add(ownerName != null ? ownerName : "");
objects.add(electricTier.ordinal());
objects.add(electricityCount);
return objects;
}
@Override
public int extractEnergy(ForgeDirection from, int maxExtract, boolean simulate) {
if (getExtractingDirections().contains(from)) {
// Add the amount of energy we're extracting to the counter, and set the block as active.
if (!simulate) {// && storage.extractEnergy(maxExtract, true) > 0) {
setActive(true);
setElectricityCount(maxExtract); // Adding the maxExtract value to the electricityCount.
setElectricityUsage((electricityUsageLastTick + maxExtract) / 2); // Calculating the average energy usage.
setElectricityUsageLastTick(maxExtract); // Update the last tick value to be used next tick.
}
}
return super.extractEnergy(from, maxExtract, simulate);
}
@Override
protected EnumSet<ForgeDirection> getReceivingDirections() {
EnumSet<ForgeDirection> directions = EnumSet.allOf(ForgeDirection.class);
directions.removeAll(getExtractingDirections());
directions.remove(ForgeDirection.UNKNOWN);
return directions;
}
@Override
protected EnumSet<ForgeDirection> getExtractingDirections() {
return EnumSet.of(ForgeDirection.getOrientation(facing).getRotation(ForgeDirection.UP));
}
@Override
protected void distributeEnergy() {
for (ForgeDirection direction : getExtractingDirections()) {
TileEntity tileEntity = worldObj.getTileEntity(xCoord + direction.offsetX, yCoord + direction.offsetY, zCoord + direction.offsetZ);
if (tileEntity != null) {
if (tileEntity instanceof IEnergyReceiver) {
int actualEnergyAmount = extractEnergy(direction, getExtract(), true);
if (!MachineUtils.canFunction(this) || actualEnergyAmount <= 0) {
setActive(false);
}
}
} else {
setActive(false);
}
}
super.distributeEnergy();
}
@Override
public boolean isActive() {
return isActive;
}
@Override
public void setActive(boolean isActive) {
this.isActive = isActive;
if (!worldObj.isRemote) {
NetworkHandler.sendToReceivers(new PacketTileEntity(this), this);
}
}
@Override
public Tier.Electric getElectricTier() {
return electricTier;
}
@Override
public void setElectricTier(Tier.Electric electricTier) {
this.electricTier = electricTier;
}
@Override
public boolean hasOwner() {
return ownerUUID != null && ownerName != null;
}
@Override
public boolean isOwner(EntityPlayer player) {
return hasOwner() && ownerUUID.equals(player.getPersistentID());
}
@Override
public EntityPlayer getOwner() {
return PlayerUtils.getPlayerFromUUID(ownerUUID);
}
@Override
public String getOwnerName() {
return ownerName;
}
@Override
public void setOwner(EntityPlayer player) {
this.ownerUUID = player.getPersistentID();
this.ownerName = player.getDisplayName();
}
/**
* Returns the amount of energy that this block has totally received.
*/
public double getElectricityCount() {
return electricityCount;
}
/**
* Sets the amount of energy that this block has totally received.
*/
public void setElectricityCount(double electricityCount) {
this.electricityCount = electricityCount;
}
/**
* Returns the amount of energy on average drained from this block.
*/
public double getElectricityUsage() {
return electricityUsage;
}
/**
* Sets the amount of energy on average drained from this block.
*/
public void setElectricityUsage(double electricityUsage) {
this.electricityUsage = electricityUsage;
}
/**
* Returns the amount of energy on average drained from this block.
*/
public double getElectricityUsageLastTick() {
return electricityUsageLastTick;
}
/**
* Sets the amount of energy on average drained from this block.
*/
public void setElectricityUsageLastTick(double electricityUsageLastTick) {
this.electricityUsageLastTick = electricityUsageLastTick;
}
}