/** * Copyright (c) 2011-2015, SpaceToad and the BuildCraft Team * http://www.mod-buildcraft.com * <p/> * BuildCraft is distributed under the terms of the Minecraft Mod Public * License 1.0, or MMPL. Please check the contents of the license located in * http://www.mod-buildcraft.com/MMPL-1.0.txt */ package buildcraft.core.lib.utils; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import net.minecraft.block.Block; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.inventory.IInventory; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.MathHelper; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; import cpw.mods.fml.common.network.internal.FMLProxyPacket; import net.minecraftforge.common.util.FakePlayer; import net.minecraftforge.common.util.ForgeDirection; import buildcraft.api.core.IAreaProvider; import buildcraft.api.core.Position; import buildcraft.api.power.IEngine; import buildcraft.api.power.ILaserTarget; import buildcraft.api.tiles.ITileAreaProvider; import buildcraft.api.transport.IInjectable; import buildcraft.api.transport.IPipeTile; import buildcraft.core.CompatHooks; import buildcraft.core.DefaultProps; import buildcraft.core.internal.IDropControlInventory; import buildcraft.core.internal.IFramePipeConnection; import buildcraft.core.lib.block.TileBuildCraft; import buildcraft.core.lib.engines.BlockEngineBase; import buildcraft.core.lib.inventory.ITransactor; import buildcraft.core.lib.inventory.InvUtils; import buildcraft.core.lib.inventory.Transactor; import buildcraft.core.lib.network.Packet; public final class Utils { public static final boolean CAULDRON_DETECTED; public static final XorShift128Random RANDOM = new XorShift128Random(); private static final List<ForgeDirection> directions = new ArrayList<ForgeDirection>(Arrays.asList(ForgeDirection.VALID_DIRECTIONS)); static { boolean cauldron = false; try { cauldron = Utils.class.getClassLoader().loadClass("org.spigotmc.SpigotConfig") != null; } catch (ClassNotFoundException e) { } CAULDRON_DETECTED = cauldron; } /** * Deactivate constructor */ private Utils() { } public static boolean isRegistered(Block block) { return block != null && Block.getIdFromBlock(block) >= 0; } public static boolean isRegistered(Item item) { return item != null && Item.getIdFromItem(item) >= 0; } public static boolean isRegistered(ItemStack stack) { if (stack == null) { return false; } Block block = Block.getBlockFromItem(stack.getItem()); if (block instanceof BlockEngineBase) { return isRegistered(block) && ((BlockEngineBase) block).hasEngine(stack.getItemDamage()); } return isRegistered(stack.getItem()); } /** * Tries to add the passed stack to any valid inventories around the given * coordinates. * * @param stack * @param world * @param x * @param y * @param z * @return amount used */ public static int addToRandomInventoryAround(World world, int x, int y, int z, ItemStack stack) { Collections.shuffle(directions); for (ForgeDirection orientation : directions) { Position pos = new Position(x, y, z, orientation); pos.moveForwards(1.0); TileEntity tileInventory = BlockUtils.getTileEntity(world, (int) pos.x, (int) pos.y, (int) pos.z); ITransactor transactor = Transactor.getTransactorFor(tileInventory); if (transactor != null && !(tileInventory instanceof IEngine) && !(tileInventory instanceof ILaserTarget) && transactor.add(stack, orientation.getOpposite(), false).stackSize > 0) { return transactor.add(stack, orientation.getOpposite(), true).stackSize; } } return 0; } /** * Returns the cardinal direction of the entity depending on its * rotationYaw */ public static ForgeDirection get2dOrientation(EntityLivingBase entityliving) { ForgeDirection[] orientationTable = {ForgeDirection.SOUTH, ForgeDirection.WEST, ForgeDirection.NORTH, ForgeDirection.EAST}; int orientationIndex = MathHelper.floor_double((entityliving.rotationYaw + 45.0) / 90.0) & 3; return orientationTable[orientationIndex]; } /** * Look around the tile given in parameter in all 6 position, tries to add * the items to a random injectable tile around. Will make sure that the location * from which the items are coming from (identified by the from parameter) * isn't used again so that entities doesn't go backwards. Returns true if * successful, false otherwise. */ public static int addToRandomInjectableAround(World world, int x, int y, int z, ForgeDirection from, ItemStack stack) { List<IInjectable> possiblePipes = new ArrayList<IInjectable>(); List<ForgeDirection> pipeDirections = new ArrayList<ForgeDirection>(); for (ForgeDirection side : ForgeDirection.VALID_DIRECTIONS) { if (from.getOpposite() == side) { continue; } Position pos = new Position(x, y, z, side); pos.moveForwards(1.0); TileEntity tile = BlockUtils.getTileEntity(world, (int) pos.x, (int) pos.y, (int) pos.z); if (tile instanceof IInjectable) { if (!((IInjectable) tile).canInjectItems(side.getOpposite())) { continue; } possiblePipes.add((IInjectable) tile); pipeDirections.add(side.getOpposite()); } else { IInjectable wrapper = CompatHooks.INSTANCE.getInjectableWrapper(tile, side); if (wrapper != null) { possiblePipes.add(wrapper); pipeDirections.add(side.getOpposite()); } } } if (possiblePipes.size() > 0) { int choice = RANDOM.nextInt(possiblePipes.size()); IInjectable pipeEntry = possiblePipes.get(choice); return pipeEntry.injectItem(stack, true, pipeDirections.get(choice), null); } return 0; } public static void dropTryIntoPlayerInventory(World world, int x, int y, int z, ItemStack stack, EntityPlayer player) { if (player != null && player.inventory.addItemStackToInventory(stack)) { if (player instanceof EntityPlayerMP) { ((EntityPlayerMP) player).sendContainerToPlayer(player.inventoryContainer); } } InvUtils.dropItems(world, stack, x, y, z); } public static IAreaProvider getNearbyAreaProvider(World world, int i, int j, int k) { for (TileEntity t : (List<TileEntity>) world.loadedTileEntityList) { if (t instanceof ITileAreaProvider && ((ITileAreaProvider) t).isValidFromLocation(i, j, k)) { return (IAreaProvider) t; } } return null; } public static void preDestroyBlock(World world, int i, int j, int k) { TileEntity tile = BlockUtils.getTileEntity(world, i, j, k); if (tile instanceof IInventory && !world.isRemote) { if (!(tile instanceof IDropControlInventory) || ((IDropControlInventory) tile).doDrop()) { InvUtils.dropItems(world, (IInventory) tile, i, j, k); InvUtils.wipeInventory((IInventory) tile); } } if (tile instanceof TileBuildCraft) { ((TileBuildCraft) tile).destroy(); } } public static boolean isFakePlayer(EntityPlayer player) { if (player instanceof FakePlayer) { return true; } // Tip donated by skyboy - addedToChunk must be set to false by a fake player // or it becomes a chunk-loading entity. if (!player.addedToChunk) { return true; } return false; } public static boolean checkPipesConnections(TileEntity tile1, TileEntity tile2) { if (tile1 == null || tile2 == null) { return false; } if (!(tile1 instanceof IPipeTile) && !(tile2 instanceof IPipeTile)) { return false; } ForgeDirection o = ForgeDirection.UNKNOWN; if (tile1.xCoord - 1 == tile2.xCoord) { o = ForgeDirection.WEST; } else if (tile1.xCoord + 1 == tile2.xCoord) { o = ForgeDirection.EAST; } else if (tile1.yCoord - 1 == tile2.yCoord) { o = ForgeDirection.DOWN; } else if (tile1.yCoord + 1 == tile2.yCoord) { o = ForgeDirection.UP; } else if (tile1.zCoord - 1 == tile2.zCoord) { o = ForgeDirection.NORTH; } else if (tile1.zCoord + 1 == tile2.zCoord) { o = ForgeDirection.SOUTH; } if (tile1 instanceof IPipeTile && !((IPipeTile) tile1).isPipeConnected(o)) { return false; } if (tile2 instanceof IPipeTile && !((IPipeTile) tile2).isPipeConnected(o.getOpposite())) { return false; } return true; } public static boolean checkLegacyPipesConnections(IBlockAccess blockAccess, int x1, int y1, int z1, int x2, int y2, int z2) { Block b1 = blockAccess.getBlock(x1, y1, z1); Block b2 = blockAccess.getBlock(x2, y2, z2); if (!(b1 instanceof IFramePipeConnection) && !(b2 instanceof IFramePipeConnection)) { return false; } if (b1 instanceof IFramePipeConnection && !((IFramePipeConnection) b1).isPipeConnected(blockAccess, x1, y1, z1, x2, y2, z2)) { return false; } if (b2 instanceof IFramePipeConnection && !((IFramePipeConnection) b2).isPipeConnected(blockAccess, x2, y2, z2, x1, y1, z1)) { return false; } return true; } public static boolean isPipeConnected(IBlockAccess access, int x, int y, int z, ForgeDirection dir, IPipeTile.PipeType type) { TileEntity tile = access.getTileEntity(x + dir.offsetX, y + dir.offsetY, z + dir.offsetZ); return tile instanceof IPipeTile && ((IPipeTile) tile).getPipeType() == type && ((IPipeTile) tile).isPipeConnected(dir.getOpposite()); } public static int[] createSlotArray(int first, int count) { int[] slots = new int[count]; for (int k = first; k < first + count; k++) { slots[k - first] = k; } return slots; } /** * This subprogram transforms a packet into a FML packet to be send in the * minecraft default packet mechanism. This always use BC-CORE as a * channel, and as a result, should use discriminators declared there. * * WARNING! The implementation of this subprogram relies on the internal * behavior of #FMLIndexedMessageToMessageCodec (in particular the encode * member). It is probably opening a maintenance issue and should be * replaced eventually by some more solid mechanism. */ public static FMLProxyPacket toPacket(Packet packet, int discriminator) { ByteBuf buf = Unpooled.buffer(); buf.writeByte((byte) discriminator); packet.writeData(buf); return new FMLProxyPacket(buf, DefaultProps.NET_CHANNEL_NAME + "-CORE"); } }