package mekanism.common.tile; import io.netty.buffer.ByteBuf; import java.util.ArrayList; import java.util.EnumSet; import mekanism.api.Coord4D; import mekanism.api.MekanismConfig.general; import mekanism.api.Range4D; import mekanism.api.transmitters.TransmissionType; import mekanism.common.Mekanism; import mekanism.common.Upgrade; import mekanism.common.base.IEjector; import mekanism.common.base.IElectricMachine; import mekanism.common.base.IRedstoneControl; import mekanism.common.base.ISideConfiguration; import mekanism.common.base.IUpgradeTile; import mekanism.common.network.PacketTileEntity.TileEntityMessage; import mekanism.common.recipe.inputs.MachineInput; import mekanism.common.recipe.machines.MachineRecipe; import mekanism.common.recipe.outputs.MachineOutput; import mekanism.common.tile.component.TileComponentConfig; import mekanism.common.tile.component.TileComponentEjector; import mekanism.common.tile.component.TileComponentUpgrade; import mekanism.common.util.MekanismUtils; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.ResourceLocation; import net.minecraftforge.common.util.ForgeDirection; import cpw.mods.fml.common.Optional.Interface; import cpw.mods.fml.common.Optional.Method; import dan200.computercraft.api.peripheral.IComputerAccess; import dan200.computercraft.api.peripheral.IPeripheral; @Interface(iface = "dan200.computercraft.api.peripheral.IPeripheral", modid = "ComputerCraft") public abstract class TileEntityBasicMachine<INPUT extends MachineInput<INPUT>, OUTPUT extends MachineOutput<OUTPUT>, RECIPE extends MachineRecipe<INPUT, OUTPUT, RECIPE>> extends TileEntityNoisyElectricBlock implements IElectricMachine<INPUT, OUTPUT, RECIPE>, IPeripheral, ISideConfiguration, IUpgradeTile, IRedstoneControl { /** How much energy this machine uses per tick, un-upgraded. */ public double BASE_ENERGY_PER_TICK; /** How much energy this machine uses per tick including upgrades */ public double energyPerTick; /** How many ticks this machine has operated for. */ public int operatingTicks = 0; /** Un-upgraded ticks required to operate -- or smelt an item. */ public int BASE_TICKS_REQUIRED; /** Ticks required including upgrades */ public int ticksRequired; /** How many ticks must pass until this block's active state can sync with the client. */ public int updateDelay; /** Whether or not this block is in it's active state. */ public boolean isActive; /** The client's current active state. */ public boolean clientActive; /** The GUI texture path for this machine. */ public ResourceLocation guiLocation; /** This machine's current RedstoneControl type. */ public RedstoneControl controlType = RedstoneControl.DISABLED; /** This machine's previous amount of energy. */ public double prevEnergy; public RECIPE cachedRecipe = null; public TileComponentUpgrade upgradeComponent; public TileComponentEjector ejectorComponent; public TileComponentConfig configComponent; /** * The foundation of all machines - a simple tile entity with a facing, active state, initialized state, sound effect, and animated texture. * @param soundPath - location of the sound effect * @param name - full name of this machine * @param location - GUI texture path of this machine * @param perTick - the energy this machine consumes every tick in it's active state * @param baseTicksRequired - how many ticks it takes to run a cycle * @param maxEnergy - how much energy this machine can store */ public TileEntityBasicMachine(String soundPath, String name, ResourceLocation location, double perTick, int baseTicksRequired, double maxEnergy) { super("machine." + soundPath, name, maxEnergy); BASE_ENERGY_PER_TICK = perTick; energyPerTick = perTick; BASE_TICKS_REQUIRED = baseTicksRequired; ticksRequired = baseTicksRequired; guiLocation = location; isActive = false; } @Override public void onUpdate() { super.onUpdate(); if(worldObj.isRemote && updateDelay > 0) { updateDelay--; if(updateDelay == 0 && clientActive != isActive) { isActive = clientActive; MekanismUtils.updateBlock(worldObj, xCoord, yCoord, zCoord); } } if(!worldObj.isRemote) { if(updateDelay > 0) { updateDelay--; if(updateDelay == 0 && clientActive != isActive) { Mekanism.packetHandler.sendToReceivers(new TileEntityMessage(Coord4D.get(this), getNetworkedData(new ArrayList())), new Range4D(Coord4D.get(this))); } } } } @Override public EnumSet<ForgeDirection> getConsumingSides() { return configComponent.getSidesForData(TransmissionType.ENERGY, facing, 1); } @Override public void readFromNBT(NBTTagCompound nbtTags) { super.readFromNBT(nbtTags); operatingTicks = nbtTags.getInteger("operatingTicks"); clientActive = isActive = nbtTags.getBoolean("isActive"); controlType = RedstoneControl.values()[nbtTags.getInteger("controlType")]; } @Override public void writeToNBT(NBTTagCompound nbtTags) { super.writeToNBT(nbtTags); nbtTags.setInteger("operatingTicks", operatingTicks); nbtTags.setBoolean("isActive", isActive); nbtTags.setInteger("controlType", controlType.ordinal()); } @Override public void handlePacketData(ByteBuf dataStream) { super.handlePacketData(dataStream); operatingTicks = dataStream.readInt(); clientActive = dataStream.readBoolean(); ticksRequired = dataStream.readInt(); controlType = RedstoneControl.values()[dataStream.readInt()]; if(updateDelay == 0 && clientActive != isActive) { updateDelay = general.UPDATE_DELAY; isActive = clientActive; MekanismUtils.updateBlock(worldObj, xCoord, yCoord, zCoord); } } @Override public ArrayList getNetworkedData(ArrayList data) { super.getNetworkedData(data); data.add(operatingTicks); data.add(isActive); data.add(ticksRequired); data.add(controlType.ordinal()); return data; } /** * Gets the scaled progress level for the GUI. * @return */ public double getScaledProgress() { return ((double)operatingTicks) / ((double)ticksRequired); } @Override public boolean getActive() { return isActive; } @Override public void setActive(boolean active) { isActive = active; if(clientActive != active && updateDelay == 0) { Mekanism.packetHandler.sendToReceivers(new TileEntityMessage(Coord4D.get(this), getNetworkedData(new ArrayList())), new Range4D(Coord4D.get(this))); updateDelay = 10; clientActive = active; } } @Override public void recalculateUpgradables(Upgrade upgrade) { super.recalculateUpgradables(upgrade); switch(upgrade) { case SPEED: ticksRequired = MekanismUtils.getTicks(this, BASE_TICKS_REQUIRED); energyPerTick = MekanismUtils.getEnergyPerTick(this, BASE_ENERGY_PER_TICK); break; case ENERGY: energyPerTick = MekanismUtils.getEnergyPerTick(this, BASE_ENERGY_PER_TICK); maxEnergy = MekanismUtils.getMaxEnergy(this, BASE_MAX_ENERGY); break; default: break; } } @Override @Method(modid = "ComputerCraft") public String getType() { return getInventoryName(); } @Override @Method(modid = "ComputerCraft") public boolean equals(IPeripheral other) { return this == other; } @Override public boolean canSetFacing(int facing) { return facing != 0 && facing != 1; } @Override @Method(modid = "ComputerCraft") public void attach(IComputerAccess computer) {} @Override @Method(modid = "ComputerCraft") public void detach(IComputerAccess computer) {} @Override public int[] getAccessibleSlotsFromSide(int side) { return configComponent.getOutput(TransmissionType.ITEM, side, facing).availableSlots; } @Override public TileComponentConfig getConfig() { return configComponent; } @Override public int getOrientation() { return facing; } @Override public boolean renderUpdate() { return true; } @Override public boolean lightUpdate() { return true; } @Override public RedstoneControl getControlType() { return controlType; } @Override public void setControlType(RedstoneControl type) { controlType = type; MekanismUtils.saveChunk(this); } @Override public boolean canPulse() { return false; } @Override public TileComponentUpgrade getComponent() { return upgradeComponent; } @Override public IEjector getEjector() { return ejectorComponent; } }