blob: 664e9698d798ae6d20d6dfaeca7bc09c15747832 [file] [log] [blame] [raw]
package mekanism.common.tile;
import mekanism.api.Coord4D;
import mekanism.api.MekanismConfig.general;
import mekanism.api.energy.ICableOutputter;
import mekanism.api.energy.IStrictEnergyStorage;
import mekanism.api.lasers.ILaserReceptor;
import mekanism.common.LaserManager;
import mekanism.common.LaserManager.LaserInfo;
import mekanism.common.Mekanism;
import mekanism.common.base.IRedstoneControl;
import mekanism.common.integration.IComputerIntegration;
import mekanism.common.network.PacketTileEntity.TileEntityMessage;
import mekanism.common.util.LangUtils;
import mekanism.common.util.MekanismUtils;
import net.minecraftforge.common.util.ForgeDirection;
import net.minecraft.block.Block;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.MathHelper;
import net.minecraft.util.MovingObjectPosition;
import io.netty.buffer.ByteBuf;
import java.util.ArrayList;
public class LaserAmplifierTileEntity extends ContainerTileEntity implements ILaserReceptor, IRedstoneControl, ICableOutputter, IStrictEnergyStorage, IComputerIntegration
{
public static final double MAX_ENERGY = 5E9;
public double collectedEnergy = 0;
public double lastFired = 0;
public double minThreshold = 0;
public double maxThreshold = 5E9;
public int ticks = 0;
public int time = 0;
public RedstoneControl controlType = RedstoneControl.DISABLED;
public boolean on = false;
public Coord4D digging;
public double diggingProgress;
public boolean emittingRedstone;
public int currentRedstoneLevel;
public RedstoneOutput outputMode = RedstoneOutput.OFF;
public LaserAmplifierTileEntity()
{
super("LaserAmplifier");
inventory = new ItemStack[0];
}
@Override
public void receiveLaserEnergy(double energy, ForgeDirection side)
{
setEnergy(getEnergy() + energy);
}
@Override
public boolean canLasersDig()
{
return false;
}
@Override
public void onUpdate()
{
if(worldObj.isRemote)
{
if(on)
{
MovingObjectPosition mop = LaserManager.fireLaserClient(this, ForgeDirection.getOrientation(facing), lastFired, worldObj);
Coord4D hitCoord = mop == null ? null : new Coord4D(mop.blockX, mop.blockY, mop.blockZ, worldObj.provider.dimensionId);
if(hitCoord == null || !hitCoord.equals(digging))
{
digging = hitCoord;
diggingProgress = 0;
}
if(hitCoord != null)
{
Block blockHit = hitCoord.getBlock(worldObj);
TileEntity tileHit = hitCoord.getTileEntity(worldObj);
float hardness = blockHit.getBlockHardness(worldObj, hitCoord.xCoord, hitCoord.yCoord, hitCoord.zCoord);
if(!(hardness < 0 || (tileHit instanceof ILaserReceptor && !((ILaserReceptor)tileHit).canLasersDig())))
{
diggingProgress += lastFired;
if(diggingProgress < hardness*general.laserEnergyNeededPerHardness)
{
Mekanism.proxy.addHitEffects(hitCoord, mop);
}
}
}
}
}
else {
boolean prevRedstone = emittingRedstone;
emittingRedstone = false;
if(ticks < time)
{
ticks++;
}
else {
ticks = 0;
}
if(toFire() > 0)
{
double firing = toFire();
if(!on || firing != lastFired)
{
on = true;
lastFired = firing;
Mekanism.packetHandler.sendToAllAround(new TileEntityMessage(Coord4D.get(this), getNetworkedData(new ArrayList())), Coord4D.get(this).getTargetPoint(50D));
}
LaserInfo info = LaserManager.fireLaser(this, ForgeDirection.getOrientation(facing), firing, worldObj);
Coord4D hitCoord = info.movingPos == null ? null : new Coord4D(info.movingPos.blockX, info.movingPos.blockY, info.movingPos.blockZ, worldObj.provider.dimensionId);
if(hitCoord == null || !hitCoord.equals(digging))
{
digging = hitCoord;
diggingProgress = 0;
}
if(hitCoord != null)
{
Block blockHit = hitCoord.getBlock(worldObj);
TileEntity tileHit = hitCoord.getTileEntity(worldObj);
float hardness = blockHit.getBlockHardness(worldObj, hitCoord.xCoord, hitCoord.yCoord, hitCoord.zCoord);
if(!(hardness < 0 || (tileHit instanceof ILaserReceptor && !((ILaserReceptor)tileHit).canLasersDig())))
{
diggingProgress += firing;
if(diggingProgress >= hardness*general.laserEnergyNeededPerHardness)
{
LaserManager.breakBlock(hitCoord, true, worldObj);
diggingProgress = 0;
}
}
}
emittingRedstone = info.foundEntity;
setEnergy(getEnergy() - firing);
}
else if(on)
{
on = false;
diggingProgress = 0;
Mekanism.packetHandler.sendToAllAround(new TileEntityMessage(Coord4D.get(this), getNetworkedData(new ArrayList())), Coord4D.get(this).getTargetPoint(50D));
}
if(outputMode != RedstoneOutput.ENTITY_DETECTION)
{
emittingRedstone = false;
}
int newRedstoneLevel = getRedstoneLevel();
if(newRedstoneLevel != currentRedstoneLevel)
{
markDirty();
currentRedstoneLevel = newRedstoneLevel;
}
if(emittingRedstone != prevRedstone)
{
worldObj.notifyBlocksOfNeighborChange(xCoord, yCoord, zCoord, getBlockType());
}
}
}
@Override
public void setEnergy(double energy)
{
collectedEnergy = Math.max(0, Math.min(energy, MAX_ENERGY));
}
@Override
public double getEnergy()
{
return collectedEnergy;
}
public boolean shouldFire()
{
return collectedEnergy >= minThreshold && ticks >= time && MekanismUtils.canFunction(this);
}
public double toFire()
{
return shouldFire() ? Math.min(collectedEnergy, maxThreshold) : 0;
}
public int getRedstoneLevel()
{
if(outputMode != RedstoneOutput.ENERGY_CONTENTS)
{
return 0;
}
double fractionFull = getEnergy()/getMaxEnergy();
return MathHelper.floor_float((float)(fractionFull * 14F)) + (fractionFull > 0 ? 1 : 0);
}
@Override
public ArrayList getNetworkedData(ArrayList data)
{
super.getNetworkedData(data);
data.add(Boolean.valueOf(on));
data.add(Double.valueOf(minThreshold));
data.add(Double.valueOf(maxThreshold));
data.add(Integer.valueOf(time));
data.add(Double.valueOf(collectedEnergy));
data.add(Double.valueOf(lastFired));
data.add(Integer.valueOf(controlType.ordinal()));
data.add(Boolean.valueOf(emittingRedstone));
data.add(Integer.valueOf(outputMode.ordinal()));
return data;
}
@Override
public void handlePacketData(ByteBuf dataStream)
{
if(!worldObj.isRemote)
{
switch(dataStream.readInt())
{
case 0:
minThreshold = Math.min(MAX_ENERGY, MekanismUtils.convertToJoules(dataStream.readDouble()));
break;
case 1:
maxThreshold = Math.min(MAX_ENERGY, MekanismUtils.convertToJoules(dataStream.readDouble()));
break;
case 2:
time = dataStream.readInt();
break;
case 3:
outputMode = RedstoneOutput.values()[outputMode.ordinal() == RedstoneOutput.values().length-1 ? 0 : outputMode.ordinal()+1];
break;
}
return;
}
super.handlePacketData(dataStream);
if(worldObj.isRemote)
{
on = dataStream.readBoolean();
minThreshold = dataStream.readDouble();
maxThreshold = dataStream.readDouble();
time = dataStream.readInt();
collectedEnergy = dataStream.readDouble();
lastFired = dataStream.readDouble();
controlType = RedstoneControl.values()[dataStream.readInt()];
emittingRedstone = dataStream.readBoolean();
outputMode = RedstoneOutput.values()[dataStream.readInt()];
}
}
@Override
public void readFromNBT(NBTTagCompound nbtTags)
{
super.readFromNBT(nbtTags);
on = nbtTags.getBoolean("on");
minThreshold = nbtTags.getDouble("minThreshold");
maxThreshold = nbtTags.getDouble("maxThreshold");
time = nbtTags.getInteger("time");
collectedEnergy = nbtTags.getDouble("collectedEnergy");
lastFired = nbtTags.getDouble("lastFired");
controlType = RedstoneControl.values()[nbtTags.getInteger("controlType")];
outputMode = RedstoneOutput.values()[nbtTags.getInteger("outputMode")];
}
@Override
public void writeToNBT(NBTTagCompound nbtTags)
{
super.writeToNBT(nbtTags);
nbtTags.setBoolean("on", on);
nbtTags.setDouble("minThreshold", minThreshold);
nbtTags.setDouble("maxThreshold", maxThreshold);
nbtTags.setInteger("time", time);
nbtTags.setDouble("collectedEnergy", collectedEnergy);
nbtTags.setDouble("lastFired", lastFired);
nbtTags.setInteger("controlType", controlType.ordinal());
nbtTags.setInteger("outputMode", outputMode.ordinal());
}
@Override
public RedstoneControl getControlType()
{
return controlType;
}
@Override
public void setControlType(RedstoneControl type)
{
controlType = type;
}
@Override
public boolean canPulse()
{
return true;
}
@Override
public boolean canOutputTo(ForgeDirection side)
{
return true;
}
@Override
public double getMaxEnergy()
{
return MAX_ENERGY;
}
private static final String[] methods = new String[] {"getEnergy", "getMaxEnergy"};
@Override
public String[] getMethods()
{
return methods;
}
@Override
public Object[] invoke(int method, Object[] arguments) throws Exception
{
switch(method)
{
case 0:
return new Object[] {getEnergy()};
case 1:
return new Object[] {getMaxEnergy()};
default:
throw new NoSuchMethodException();
}
}
public static enum RedstoneOutput
{
OFF("off"),
ENTITY_DETECTION("entityDetection"),
ENERGY_CONTENTS("energyContents");
private String unlocalizedName;
private RedstoneOutput(String name)
{
unlocalizedName = name;
}
public String getName()
{
return LangUtils.localize("gui." + unlocalizedName);
}
}
}