package gtclassic.api.helpers; import java.util.List; import javax.annotation.Nullable; import gtclassic.common.tile.GTTileMagicEnergyAbsorber; import gtclassic.common.util.GTIBlockFilters; import gtclassic.common.util.GTIFilters; import ic2.core.RotationList; import ic2.core.block.base.tile.TileEntityMachine; import ic2.core.fluid.IC2Tank; import ic2.core.inventory.filters.CommonFilters; import ic2.core.inventory.filters.IFilter; import ic2.core.inventory.transport.IItemTransporter; import ic2.core.inventory.transport.TransporterManager; import ic2.core.item.armor.electric.ItemArmorQuantumSuit; import ic2.core.util.helpers.AabbUtil; import ic2.core.util.math.MathUtil; import net.minecraft.block.Block; import net.minecraft.block.BlockEndPortalFrame; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.IProjectile; import net.minecraft.entity.item.EntityArmorStand; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.projectile.EntityArrow; import net.minecraft.init.Blocks; import net.minecraft.init.SoundEvents; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; import net.minecraft.util.SoundCategory; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; import net.minecraftforge.fluids.FluidUtil; import net.minecraftforge.fluids.capability.IFluidHandler; /** * NEVER INCLUDE THIS FILE IN YOUR MOD!!! Just a few Utility Functions I use. */ public class GTUtility { /** * Checks to see if a player is fully equipped in quantum gear * * @param entity - usually the player in this case * @return */ public static boolean hasFullQuantumSuit(EntityLivingBase entity) { if (!(entity instanceof EntityPlayer)) { return false; } EntityPlayer player = (EntityPlayer) entity; for (int i = 0; i < 4; i++) { if (!(player.inventory.armorInventory.get(i).getItem() instanceof ItemArmorQuantumSuit)) { return false; } } return true; } /** * Pushes entities away from target within an area, code adapted from * EE/ProjectE. */ public static void repelEntitiesInAABBFromPoint(World world, AxisAlignedBB boundingbox, double x, double y, double z) { List<Entity> list = world.getEntitiesWithinAABB(Entity.class, boundingbox); if (list.isEmpty()) { return; } for (Entity entity : list) { if ((entity instanceof EntityLiving) || (entity instanceof IProjectile)) { if (entity instanceof EntityArrow && ((EntityArrow) entity).onGround) { continue; } if (entity instanceof EntityArmorStand) { continue; } Vec3d p = new Vec3d(x, y, z); Vec3d t = new Vec3d(entity.posX, entity.posY, entity.posZ); double distance = p.distanceTo(t) + 0.1D; Vec3d r = new Vec3d(t.x - p.x, t.y - p.y, t.z - p.z); entity.motionX += r.x / 1.5D / distance; entity.motionY += r.y / 1.5D / distance; entity.motionZ += r.z / 1.5D / distance; } } } /** * Import ItemStacks from another tile into a TileEntityMachine. * * @param machine - the TileEntityMachine to import into. * @param side - the EnumFacing side to try pull into. * @param filter - the IFilter to filter items */ public static void importFromSideIntoMachine(TileEntityMachine machine, EnumFacing side, IFilter filter) { BlockPos importPos = machine.getPos().offset(side); if (!machine.getWorld().isBlockLoaded(importPos)) { return; } IItemTransporter slave = TransporterManager.manager.getTransporter(machine.getWorld().getTileEntity(importPos), true); IItemTransporter controller = TransporterManager.manager.getTransporter(machine, true); if (slave != null && controller != null) { int limit = controller.getSizeInventory(side); for (int i = 0; i < limit; ++i) { ItemStack stack = slave.removeItem(filter, side.getOpposite(), 1, false); if (stack.isEmpty()) { break; } ItemStack added = controller.addItem(stack, side, true); if (added.getCount() <= 0) { break; } slave.removeItem(new GTIFilters.BetterBasicItemFilter(added), side.getOpposite(), 1, true); } } } /** Simpler version that automatically imports any item **/ public static void importFromSideIntoMachine(TileEntityMachine machine, EnumFacing side) { importFromSideIntoMachine(machine, side, CommonFilters.Anything); } /** * Import a FluidStack from another tile into a TileEntityMachine tank. * * @param machine - The TileEntityMachine which has the tank, provides World and * BlockPos data. * @param tank - the IC2Tank to try to import into. * @param side - the EnumFacing to try to import fluids from. * @param amount - the amount of fluid to transfer */ public static void importFluidFromSideToMachine(TileEntityMachine machine, IC2Tank tank, EnumFacing side, int amount) { BlockPos importPos = machine.getPos().offset(side); if (!machine.getWorld().isBlockLoaded(importPos)) { return; } IFluidHandler fluidTile = FluidUtil.getFluidHandler(machine.getWorld(), importPos, side.getOpposite()); if (fluidTile != null && tank.getFluidAmount() < tank.getCapacity()) { FluidUtil.tryFluidTransfer(tank, fluidTile, amount, true); } } /** * Export ItemStacks from a TileEntityMachine to another tile. * * @param machine - The TileEntityMachine to export from. * @param side - the EnumFacing side to export out of. * @param slots - the slots you want to export from, use other constructor if * you want all slots. */ public static void exportFromMachineToSide(TileEntityMachine machine, EnumFacing side, int... slots) { BlockPos exportPos = machine.getPos().offset(side); if (!machine.getWorld().isBlockLoaded(exportPos)) { return; } IItemTransporter slave = TransporterManager.manager.getTransporter(machine.getWorld().getTileEntity(exportPos), false); if (slave != null) { for (int i : slots) { int added = slave.addItem(machine.getStackInSlot(i).copy(), side.getOpposite(), true).getCount(); if (added > 0) { machine.getStackInSlot(i).shrink(added); break; } } } } /** Simpier version that automatically exports from every possible slot **/ public static void exportFromMachineToSide(TileEntityMachine machine, EnumFacing side) { exportFromMachineToSide(machine, side, MathUtil.fromTo(0, machine.inventory.size())); } /** * Export a FluidStack from a TileEntityMachine tank to another tile. * * @param machine - The TileEntityMachine which has the tank, provides World and * BlockPos data. * @param tank - the IC2Tank to try to export from. * @param side - the EnumFacing to try to export fluids out of. * @param amount - the amount of fluid to transfer */ public static void exportFluidFromMachineToSide(TileEntityMachine machine, IC2Tank tank, EnumFacing side, int amount) { BlockPos exportPos = machine.getPos().offset(side); if (!machine.getWorld().isBlockLoaded(exportPos)) { return; } IFluidHandler fluidTile = FluidUtil.getFluidHandler(machine.getWorld(), exportPos, side.getOpposite()); boolean canExport = tank.getFluid() != null && fluidTile != null; if (canExport) { FluidUtil.tryFluidTransfer(fluidTile, tank, amount, true); } } public static boolean tryResetStrongholdPortal(World world, BlockPos pos) { List<BlockPos> portalBlockPos = AabbUtil.getTargets(world, pos, 5, new GTIBlockFilters.EndPortalFilter(), false, false, RotationList.ALL); if (portalBlockPos.isEmpty()) { return false; } BlockPos selectedPos = portalBlockPos.get(world.rand.nextInt(portalBlockPos.size() - 1)); IBlockState nearbyState = world.getBlockState(selectedPos); if (resetEndPortalFrame(world, selectedPos, nearbyState)) { boolean found = false; for (BlockPos portalPos : portalBlockPos) { if (world.getBlockState(portalPos).getBlock() == Blocks.END_PORTAL) { world.setBlockToAir(portalPos); world.removeTileEntity(portalPos); found = true; } } return found; } return false; } public static boolean resetEndPortalFrame(World world, BlockPos pos, IBlockState portalFrameState) { if (portalFrameState.getBlock() == Blocks.END_PORTAL_FRAME && portalFrameState.getValue(BlockEndPortalFrame.EYE).booleanValue()) { world.setBlockState(pos, portalFrameState.withProperty(BlockEndPortalFrame.EYE, false)); world.playSound((EntityPlayer) null, pos, SoundEvents.BLOCK_END_PORTAL_FRAME_FILL, SoundCategory.BLOCKS, 0.5F, 0.5F + world.rand.nextFloat()); return true; } return false; } public static boolean tryExplodeOtherAbsorbers(World world, BlockPos checkPos) { Iterable<BlockPos> surroundingPos = BlockPos.getAllInBox(checkPos.offset(EnumFacing.SOUTH, 4).offset(EnumFacing.WEST, 4), checkPos.offset(EnumFacing.NORTH, 4).offset(EnumFacing.EAST, 4)); for (BlockPos absorberPos : surroundingPos) { if (absorberPos.equals(checkPos)) { continue; } TileEntity tile = world.getTileEntity(absorberPos); if (tile instanceof GTTileMagicEnergyAbsorber) { GTTileMagicEnergyAbsorber absorber = (GTTileMagicEnergyAbsorber) tile; if (absorber.portalMode && absorber.isAbovePortal) { world.setBlockToAir(absorberPos); world.removeTileEntity(absorberPos); world.createExplosion(null, absorberPos.getX(), absorberPos.getY(), absorberPos.getZ(), 8.0F, true); return true; } } } return false; } /** * A way to update surrounding blocks. this does not update the original block! * * @param world - The world to update in * @param pos - the block pos the update should originate * @param blockType - block type which can be null * @param sides - the list of sides to iterate an update */ public static void updateNeighbors(World world, BlockPos pos, @Nullable Block blockType, RotationList sides) { if (blockType == null) { blockType = Blocks.AIR; } for (EnumFacing side : sides) { BlockPos newPos = pos.offset(side); if (world.isBlockLoaded(newPos)) { world.neighborChanged(newPos, blockType, pos); } } } /** * A way to update surrounding blocks and also their surrounding blocks. this * does not update the original block! * * @param world - The world to update in * @param pos - the block pos the update should originate * @param blockType - block type which can be null * @param sides - the list of sides to iterate an update */ public static void updateNeighborhood(World world, BlockPos pos, @Nullable Block blockType, RotationList sides) { for (EnumFacing side : sides) { if (world.isBlockLoaded(pos.offset(side))) { GTUtility.updateNeighbors(world, pos.offset(side), blockType, (side.getAxis().isHorizontal() ? RotationList.HORIZONTAL.remove(side.rotateY()) : RotationList.ALL).remove(side.getOpposite())); } } } }