package pneumaticCraft.common.block.tubes; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Random; import java.util.Set; import net.minecraft.block.Block; import net.minecraft.entity.Entity; import net.minecraft.entity.item.EntityItem; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.IInventory; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntityHopper; import net.minecraft.util.AxisAlignedBB; import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.Facing; import net.minecraft.util.MovingObjectPosition; import net.minecraft.util.Vec3; import net.minecraft.world.World; import net.minecraftforge.common.util.ForgeDirection; import org.lwjgl.opengl.GL11; import pneumaticCraft.client.model.IBaseModel; import pneumaticCraft.client.model.tubemodules.ModelAirGrate; import pneumaticCraft.client.render.RenderRangeLines; import pneumaticCraft.common.ai.StringFilterEntitySelector; import pneumaticCraft.common.block.pneumaticPlants.BlockPneumaticPlantBase; import pneumaticCraft.common.network.NetworkHandler; import pneumaticCraft.common.network.PacketSpawnParticle; import pneumaticCraft.common.tileentity.TileEntityHeatSink; import pneumaticCraft.lib.Names; import pneumaticCraft.lib.PneumaticValues; import pneumaticCraft.proxy.CommonProxy.EnumGuiId; public class ModuleAirGrate extends TubeModule{ private final IBaseModel model = new ModelAirGrate(); private int grateRange; private boolean vacuum; public String entityFilter = ""; private final Set<TileEntityHeatSink> heatSinks = new HashSet<TileEntityHeatSink>(); private final RenderRangeLines rangeLineRenderer = new RenderRangeLines(0x55FF0000); private int plantCheckX = Integer.MIN_VALUE; private int plantCheckZ = Integer.MIN_VALUE; public ModuleAirGrate(){ rangeLineRenderer.resetRendering(1); } private int getRange(){ float range = pressureTube.getAirHandler().getPressure(ForgeDirection.UNKNOWN) * 4; vacuum = range < 0; if(vacuum) range = -range * 4; return (int)range; } @Override public double getWidth(){ return 1; } @Override public void update(){ super.update(); World worldObj = pressureTube.world(); int xCoord = pressureTube.x(); int yCoord = pressureTube.y(); int zCoord = pressureTube.z(); Vec3 tileVec = Vec3.createVectorHelper(xCoord + 0.5D, yCoord + 0.5D, zCoord + 0.5D); if(!worldObj.isRemote) { int oldGrateRange = grateRange; grateRange = getRange(); pressureTube.getAirHandler().addAir((vacuum ? 1 : -1) * grateRange * PneumaticValues.USAGE_AIR_GRATE, ForgeDirection.UNKNOWN); if(oldGrateRange != grateRange) sendDescriptionPacket(); checkForPlantsAndFarm(worldObj, xCoord, yCoord, zCoord, grateRange); coolHeatSinks(worldObj, xCoord, yCoord, zCoord, grateRange); } else { rangeLineRenderer.update(); /* updateParticleTargets(tileVec, grateRange); for(Vec3 particleVec : particleTargets) { //if(worldObj.rand.nextInt(10) == 0) { Vec3 motionVec = particleVec.subtract(tileVec); double force = 0.1D; motionVec.xCoord *= force; motionVec.yCoord *= force; motionVec.zCoord *= force; if(vacuum) { worldObj.spawnParticle("smoke", particleVec.xCoord, particleVec.yCoord, particleVec.zCoord, -motionVec.xCoord, -motionVec.yCoord, -motionVec.zCoord); } else { worldObj.spawnParticle("smoke", tileVec.xCoord, tileVec.yCoord, tileVec.zCoord, motionVec.xCoord, motionVec.yCoord, motionVec.zCoord); } // } }*/ } AxisAlignedBB bbBox = AxisAlignedBB.getBoundingBox(xCoord - grateRange, yCoord - grateRange, zCoord - grateRange, xCoord + grateRange + 1, yCoord + grateRange + 1, zCoord + grateRange + 1); List<Entity> entities = worldObj.selectEntitiesWithinAABB(Entity.class, bbBox, new StringFilterEntitySelector().setFilter(entityFilter)); double d0 = grateRange + 0.5D; for(Entity entity : entities) { if(!entity.worldObj.isRemote && entity.getDistanceSq(xCoord + 0.5D, yCoord + 0.5D, zCoord + 0.5D) < 0.6D && entity instanceof EntityItem && !entity.isDead) { List<IInventory> inventories = new ArrayList<IInventory>(); List<Integer> sides = new ArrayList<Integer>(); for(int i = 0; i < 6; i++) { IInventory inventory = TileEntityHopper.func_145893_b(worldObj, xCoord + Facing.offsetsXForSide[i], yCoord + Facing.offsetsYForSide[i], zCoord + Facing.offsetsZForSide[i]); if(inventory != null) { inventories.add(inventory); sides.add(i); } } if(inventories.size() == 0) continue;// if there isn't a // inventory attached, // stop handling. int inventoryIndexSelected = new Random().nextInt(inventories.size()); IInventory inventory = inventories.get(inventoryIndexSelected); int side = sides.get(inventoryIndexSelected); side = Facing.oppositeSide[side]; ItemStack leftoverStack = TileEntityHopper.func_145889_a(inventory, ((EntityItem)entity).getEntityItem(), side); if(leftoverStack == null || leftoverStack.stackSize == 0) { entity.setDead(); } } else { if(!(entity instanceof EntityPlayer) || !((EntityPlayer)entity).capabilities.isCreativeMode) { Vec3 entityVec = Vec3.createVectorHelper(entity.posX, entity.posY, entity.posZ); MovingObjectPosition trace = worldObj.rayTraceBlocks(entityVec, tileVec); if(trace != null && trace.blockX == xCoord && trace.blockY == yCoord && trace.blockZ == zCoord) { double d1 = (entity.posX - xCoord - 0.5D) / d0; double d2 = (entity.posY - yCoord - 0.5D) / d0; double d3 = (entity.posZ - zCoord - 0.5D) / d0; double d4 = Math.sqrt(d1 * d1 + d2 * d2 + d3 * d3); double d5 = 1.0D - d4; if(d5 > 0.0D) { d5 *= d5; if(!vacuum) d5 *= -1; entity.motionX -= d1 / d4 * d5 * 0.1D; entity.motionY -= d2 / d4 * d5 * 0.1D; entity.motionZ -= d3 / d4 * d5 * 0.1D; } } } } } } private void checkForPlantsAndFarm(World worldObj, int x, int y, int z, int plantCheckRange){ if(grateRange > 0 && worldObj.getTotalWorldTime() % 5 == 0) { if(plantCheckX < x - plantCheckRange || plantCheckZ < z - plantCheckRange) { plantCheckX = x - plantCheckRange; plantCheckZ = z - plantCheckRange; } if(plantCheckX != x || plantCheckZ != z) { // we know that we're no plant, avoid getBlock Block b = worldObj.getBlock(plantCheckX, y, plantCheckZ); NetworkHandler.sendToAllAround(new PacketSpawnParticle("reddust", plantCheckX + 0.5, y + 0.5, plantCheckZ + 0.5, 0, 0, 0), worldObj); if(b instanceof BlockPneumaticPlantBase) { ((BlockPneumaticPlantBase)b).attemptFarmByAirGrate(worldObj, plantCheckX, y, plantCheckZ); } } if(plantCheckZ++ >= z + plantCheckRange) { plantCheckZ = z - plantCheckRange; if(plantCheckX++ >= x + plantCheckRange) { plantCheckX = x - plantCheckRange; } } } } private void coolHeatSinks(World world, int x, int y, int z, int range){ if(grateRange > 2) { int curTeIndex = (int)(world.getTotalWorldTime() % 27); x += dir.offsetX * 2; y += dir.offsetY * 2; z += dir.offsetZ * 2; TileEntity te = world.getTileEntity(x - 1 + curTeIndex % 3, y - 1 + curTeIndex / 3 % 3, z - 1 + curTeIndex / 9 % 3); if(te instanceof TileEntityHeatSink) heatSinks.add((TileEntityHeatSink)te); Iterator<TileEntityHeatSink> iterator = heatSinks.iterator(); while(iterator.hasNext()) { TileEntityHeatSink heatSink = iterator.next(); if(heatSink.isInvalid()) { iterator.remove(); } else { for(int i = 0; i < 4; i++) heatSink.onFannedByAirGrate(); } } } } @Override public void readFromNBT(NBTTagCompound tag){ super.readFromNBT(tag); vacuum = tag.getBoolean("vacuum"); grateRange = tag.getInteger("grateRange"); entityFilter = tag.getString("entityFilter"); } @Override public void writeToNBT(NBTTagCompound tag){ super.writeToNBT(tag); tag.setBoolean("vacuum", vacuum); tag.setInteger("grateRange", grateRange); tag.setString("entityFilter", entityFilter); } @Override public String getType(){ return Names.MODULE_AIR_GRATE; } @Override public IBaseModel getModel(){ return model; } @Override protected void renderModule(){ GL11.glPushMatrix(); GL11.glTranslated(0, 0, 2); rangeLineRenderer.render(); if(isFake()) { GL11.glEnable(GL11.GL_BLEND); GL11.glColor4d(1, 1, 1, 0.5); } GL11.glPopMatrix(); } @Override public void addInfo(List<String> curInfo){ curInfo.add("Status: " + EnumChatFormatting.WHITE + (grateRange == 0 ? "Idle" : vacuum ? "Attracting" : "Repelling")); curInfo.add("Range: " + EnumChatFormatting.WHITE + grateRange + " blocks"); if(!entityFilter.equals("")) curInfo.add("Entity Filter: " + EnumChatFormatting.WHITE + "\"" + entityFilter + "\""); } @Override public void addItemDescription(List<String> curInfo){ curInfo.add(EnumChatFormatting.BLUE + "Formula: Range(blocks) = 4.0 x pressure(bar),"); curInfo.add(EnumChatFormatting.BLUE + "or -16 x pressure(bar), if vacuum"); curInfo.add("This module will attract or repel any entity"); curInfo.add("within range dependant on whether it is in"); curInfo.add("vacuum or under pressure respectively."); } @Override protected EnumGuiId getGuiId(){ return EnumGuiId.AIR_GRATE_MODULE; } }