package mekanism.common.tile; import io.netty.buffer.ByteBuf; import java.util.ArrayList; import java.util.List; import mekanism.api.Coord4D; import mekanism.api.MekanismConfig.general; import mekanism.api.lasers.ILaserReceptor; import mekanism.api.util.StackUtils; import mekanism.common.LaserManager; import mekanism.common.LaserManager.LaserInfo; import mekanism.common.Mekanism; import mekanism.common.capabilities.Capabilities; import mekanism.common.network.PacketTileEntity.TileEntityMessage; import mekanism.common.security.ISecurityTile; import mekanism.common.tile.component.TileComponentSecurity; import mekanism.common.util.InventoryUtils; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.item.EntityItem; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.RayTraceResult; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.fml.common.FMLCommonHandler; public class TileEntityLaserTractorBeam extends TileEntityContainerBlock implements ILaserReceptor, ISecurityTile { public static final double MAX_ENERGY = 5E9; public double collectedEnergy = 0; public double lastFired = 0; public boolean on = false; public Coord4D digging; public double diggingProgress; public static int[] availableSlotIDs = InventoryUtils.getIntRange(0, 26); public TileComponentSecurity securityComponent = new TileComponentSecurity(this); public TileEntityLaserTractorBeam() { super("LaserTractorBeam"); inventory = new ItemStack[27]; } @Override public void receiveLaserEnergy(double energy, EnumFacing side) { setEnergy(getEnergy() + energy); } @Override public boolean canLasersDig() { return false; } @Override public void onUpdate() { if(worldObj.isRemote) { if(on) { RayTraceResult mop = LaserManager.fireLaserClient(this, facing, lastFired, worldObj); Coord4D hitCoord = mop == null ? null : new Coord4D(mop, worldObj); if(hitCoord == null || !hitCoord.equals(digging)) { digging = hitCoord; diggingProgress = 0; } if(hitCoord != null) { IBlockState blockHit = hitCoord.getBlockState(worldObj); TileEntity tileHit = hitCoord.getTileEntity(worldObj); float hardness = blockHit.getBlockHardness(worldObj, hitCoord.getPos()); if(!(hardness < 0 || (LaserManager.isReceptor(tileHit, mop.sideHit) && !(LaserManager.getReceptor(tileHit, mop.sideHit).canLasersDig())))) { diggingProgress += lastFired; if(diggingProgress < hardness * general.laserEnergyNeededPerHardness) { Mekanism.proxy.addHitEffects(hitCoord, mop); } } } } } else { if(collectedEnergy > 0) { double firing = collectedEnergy; if(!on || firing != lastFired) { on = true; lastFired = firing; Mekanism.packetHandler.sendToAllAround(new TileEntityMessage(Coord4D.get(this), getNetworkedData(new ArrayList<Object>())), Coord4D.get(this).getTargetPoint(50D)); } LaserInfo info = LaserManager.fireLaser(this, facing, firing, worldObj); Coord4D hitCoord = info.movingPos == null ? null : new Coord4D(info.movingPos, worldObj); if(hitCoord == null || !hitCoord.equals(digging)) { digging = hitCoord; diggingProgress = 0; } if(hitCoord != null) { IBlockState blockHit = hitCoord.getBlockState(worldObj); TileEntity tileHit = hitCoord.getTileEntity(worldObj); float hardness = blockHit.getBlockHardness(worldObj, hitCoord.getPos()); if(!(hardness < 0 || (LaserManager.isReceptor(tileHit, info.movingPos.sideHit) && !(LaserManager.getReceptor(tileHit, info.movingPos.sideHit).canLasersDig())))) { diggingProgress += firing; if(diggingProgress >= hardness * general.laserEnergyNeededPerHardness) { List<ItemStack> drops = LaserManager.breakBlock(hitCoord, false, worldObj); if(drops != null) receiveDrops(drops); diggingProgress = 0; } } } setEnergy(getEnergy() - firing); } else if(on) { on = false; diggingProgress = 0; Mekanism.packetHandler.sendToAllAround(new TileEntityMessage(Coord4D.get(this), getNetworkedData(new ArrayList<Object>())), Coord4D.get(this).getTargetPoint(50D)); } } } public void setEnergy(double energy) { collectedEnergy = Math.max(0, Math.min(energy, MAX_ENERGY)); } public double getEnergy() { return collectedEnergy; } public void receiveDrops(List<ItemStack> drops) { outer: for(ItemStack drop : drops) { for(int i = 0; i < inventory.length; i++) { if(inventory[i] == null) { inventory[i] = drop; continue outer; } ItemStack slot = inventory[i]; if(StackUtils.equalsWildcardWithNBT(slot, drop)) { int change = Math.min(drop.stackSize, slot.getMaxStackSize() - slot.stackSize); slot.stackSize += change; drop.stackSize -= change; if(drop.stackSize <= 0) continue outer; } } dropItem(drop); } } public void dropItem(ItemStack stack) { EntityItem item = new EntityItem(worldObj, getPos().getX() + 0.5, getPos().getY() + 1, getPos().getZ() + 0.5, stack); item.motionX = worldObj.rand.nextGaussian() * 0.05; item.motionY = worldObj.rand.nextGaussian() * 0.05 + 0.2; item.motionZ = worldObj.rand.nextGaussian() * 0.05; item.setPickupDelay(10); worldObj.spawnEntityInWorld(item); } @Override public boolean canInsertItem(int i, ItemStack itemStack, EnumFacing side) { return false; } @Override public int[] getSlotsForFace(EnumFacing side) { return availableSlotIDs; } @Override public ArrayList<Object> getNetworkedData(ArrayList<Object> data) { super.getNetworkedData(data); data.add(on); data.add(collectedEnergy); data.add(lastFired); return data; } @Override public void handlePacketData(ByteBuf dataStream) { super.handlePacketData(dataStream); if(FMLCommonHandler.instance().getEffectiveSide().isClient()) { on = dataStream.readBoolean(); collectedEnergy = dataStream.readDouble(); lastFired = dataStream.readDouble(); } } @Override public TileComponentSecurity getSecurity() { return securityComponent; } @Override public boolean hasCapability(Capability<?> capability, EnumFacing side) { return capability == Capabilities.LASER_RECEPTOR_CAPABILITY || super.hasCapability(capability, side); } @Override public <T> T getCapability(Capability<T> capability, EnumFacing side) { if(capability == Capabilities.LASER_RECEPTOR_CAPABILITY) { return (T)this; } return super.getCapability(capability, side); } }