package mods.railcraft.api.carts; import com.mojang.authlib.GameProfile; import java.util.ArrayList; import java.util.List; import java.util.UUID; import net.minecraft.entity.item.EntityMinecart; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemMinecart; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.AxisAlignedBB; import net.minecraft.world.World; import net.minecraftforge.common.util.ForgeDirection; import mods.railcraft.api.core.items.IMinecartItem; import net.minecraft.block.BlockRailBase; import net.minecraft.world.WorldServer; import net.minecraftforge.common.util.FakePlayerFactory; public abstract class CartTools { private static final GameProfile railcraftProfile = new GameProfile(UUID.nameUUIDFromBytes("[Railcraft]".getBytes()), "[Railcraft]"); public static ILinkageManager linkageManager; /** * Returns an instance of ILinkageManager. * * Will return null if Railcraft is not installed. * * @param world The World, may be required in the future * @return an instance of ILinkageManager */ public static ILinkageManager getLinkageManager(World world) { return linkageManager; } /** * Sets a carts owner. * * The is really only needed by the bukkit ports. * * @param cart * @param owner */ public static void setCartOwner(EntityMinecart cart, EntityPlayer owner) { setCartOwner(cart, owner.getGameProfile()); } /** * Sets a carts owner. * * The is really only needed by the bukkit ports. * * @param cart * @param owner */ public static void setCartOwner(EntityMinecart cart, GameProfile owner) { if (!cart.worldObj.isRemote) { NBTTagCompound data = cart.getEntityData(); if (owner.getName() != null) data.setString("owner", owner.getName()); if (owner.getId() != null) data.setString("ownerId", owner.getId().toString()); } } /** * Gets a carts owner. (player.username) * * The is really only needed by the bukkit ports. * * @param cart * @return */ public static GameProfile getCartOwner(EntityMinecart cart) { NBTTagCompound data = cart.getEntityData(); String ownerName = "[Unknown]"; if (data.hasKey("owner")) ownerName = data.getString("owner"); UUID ownerId = null; if (data.hasKey("ownerId")) ownerId = UUID.fromString(data.getString("ownerId")); return new GameProfile(ownerId, ownerName); } /** * Does the cart have a owner? * * The is really only needed by the bukkit ports. * * @param cart * @return */ public static boolean doesCartHaveOwner(EntityMinecart cart) { NBTTagCompound data = cart.getEntityData(); return data.hasKey("owner"); } /** * Spawns a new cart entity using the provided item. * * The backing item must implement <code>IMinecartItem</code> and/or extend * <code>ItemMinecart</code>. * * Generally Forge requires all cart items to extend ItemMinecart. * * @param owner The player name that should used as the owner * @param cart An ItemStack containing a cart item, will not be changed by * the function * @param world The World object * @param x x-Coord * @param y y-Coord * @param z z-Coord * @return the cart placed or null if failed * @see IMinecartItem, ItemMinecart */ public static EntityMinecart placeCart(GameProfile owner, ItemStack cart, WorldServer world, int x, int y, int z) { if (cart == null) return null; cart = cart.copy(); if (cart.getItem() instanceof IMinecartItem) { IMinecartItem mi = (IMinecartItem) cart.getItem(); return mi.placeCart(owner, cart, world, x, y, z); } else if (cart.getItem() instanceof ItemMinecart) try { boolean placed = cart.getItem().onItemUse(cart, FakePlayerFactory.get(world, railcraftProfile),world, x, y, z , 0, 0, 0, 0); if (placed) { List<EntityMinecart> carts = getMinecartsAt(world, x, y, z, 0.3f); if (carts.size() > 0) { setCartOwner(carts.get(0), owner); return carts.get(0); } } } catch (Exception e) { return null; } return null; } /** * Offers an item stack to linked carts or drops it if no one wants it. * * @param cart * @param stack */ public static void offerOrDropItem(EntityMinecart cart, ItemStack stack) { EntityMinecart link_A = getLinkageManager(cart.worldObj).getLinkedCartA(cart); EntityMinecart link_B = getLinkageManager(cart.worldObj).getLinkedCartB(cart); if (stack != null && stack.stackSize > 0 && link_A instanceof IItemTransfer) stack = ((IItemTransfer) link_A).offerItem(cart, stack); if (stack != null && stack.stackSize > 0 && link_B instanceof IItemTransfer) stack = ((IItemTransfer) link_B).offerItem(cart, stack); if (stack != null && stack.stackSize > 0) cart.entityDropItem(stack, 1); } public static boolean isMinecartOnRailAt(World world, int i, int j, int k, float sensitivity) { return isMinecartOnRailAt(world, i, j, k, sensitivity, null, true); } public static boolean isMinecartOnRailAt(World world, int i, int j, int k, float sensitivity, Class<? extends EntityMinecart> type, boolean subclass) { if (BlockRailBase.func_150049_b_(world, i, j, k)) return isMinecartAt(world, i, j, k, sensitivity, type, subclass); return false; } public static boolean isMinecartOnAnySide(World world, int i, int j, int k, float sensitivity) { return isMinecartOnAnySide(world, i, j, k, sensitivity, null, true); } public static boolean isMinecartOnAnySide(World world, int i, int j, int k, float sensitivity, Class<? extends EntityMinecart> type, boolean subclass) { List<EntityMinecart> list = new ArrayList<EntityMinecart>(); for (int side = 0; side < 6; side++) { list.addAll(getMinecartsOnSide(world, i, j, k, sensitivity, ForgeDirection.getOrientation(side))); } if (type == null) return !list.isEmpty(); else for (EntityMinecart cart : list) { if ((subclass && type.isInstance(cart)) || cart.getClass() == type) return true; } return false; } public static boolean isMinecartAt(World world, int i, int j, int k, float sensitivity) { return isMinecartAt(world, i, j, k, sensitivity, null, true); } public static boolean isMinecartAt(World world, int i, int j, int k, float sensitivity, Class<? extends EntityMinecart> type, boolean subclass) { List<EntityMinecart> list = getMinecartsAt(world, i, j, k, sensitivity); if (type == null) return !list.isEmpty(); else for (EntityMinecart cart : list) { if ((subclass && type.isInstance(cart)) || cart.getClass() == type) return true; } return false; } public static List<EntityMinecart> getMinecartsOnAllSides(World world, int i, int j, int k, float sensitivity) { List<EntityMinecart> carts = new ArrayList<EntityMinecart>(); for (int side = 0; side < 6; side++) { carts.addAll(getMinecartsOnSide(world, i, j, k, sensitivity, ForgeDirection.getOrientation(side))); } return carts; } public static List<EntityMinecart> getMinecartsOnAllSides(World world, int i, int j, int k, float sensitivity, Class<? extends EntityMinecart> type, boolean subclass) { List<EntityMinecart> list = new ArrayList<EntityMinecart>(); List<EntityMinecart> carts = new ArrayList<EntityMinecart>(); for (int side = 0; side < 6; side++) { list.addAll(getMinecartsOnSide(world, i, j, k, sensitivity, ForgeDirection.getOrientation(side))); } for (EntityMinecart cart : list) { if ((subclass && type.isInstance(cart)) || cart.getClass() == type) carts.add(cart); } return carts; } private static int getYOnSide(int y, ForgeDirection side) { switch (side) { case UP: return y + 1; case DOWN: return y - 1; default: return y; } } private static int getXOnSide(int x, ForgeDirection side) { switch (side) { case EAST: return x + 1; case WEST: return x - 1; default: return x; } } private static int getZOnSide(int z, ForgeDirection side) { switch (side) { case NORTH: return z - 1; case SOUTH: return z + 1; default: return z; } } public static List<EntityMinecart> getMinecartsOnSide(World world, int i, int j, int k, float sensitivity, ForgeDirection side) { return getMinecartsAt(world, getXOnSide(i, side), getYOnSide(j, side), getZOnSide(k, side), sensitivity); } public static boolean isMinecartOnSide(World world, int i, int j, int k, float sensitivity, ForgeDirection side) { return getMinecartOnSide(world, i, j, k, sensitivity, side) != null; } public static EntityMinecart getMinecartOnSide(World world, int i, int j, int k, float sensitivity, ForgeDirection side) { for (EntityMinecart cart : getMinecartsOnSide(world, i, j, k, sensitivity, side)) { return cart; } return null; } public static boolean isMinecartOnSide(World world, int i, int j, int k, float sensitivity, ForgeDirection side, Class<? extends EntityMinecart> type, boolean subclass) { return getMinecartOnSide(world, i, j, k, sensitivity, side, type, subclass) != null; } public static <T extends EntityMinecart> T getMinecartOnSide(World world, int i, int j, int k, float sensitivity, ForgeDirection side, Class<T> type, boolean subclass) { for (EntityMinecart cart : getMinecartsOnSide(world, i, j, k, sensitivity, side)) { if (type == null || (subclass && type.isInstance(cart)) || cart.getClass() == type) return (T) cart; } return null; } /** * * @param world * @param i * @param j * @param k * @param sensitivity Controls the size of the search box, ranges from * (-inf, 0.49]. * @return */ public static List<EntityMinecart> getMinecartsAt(World world, int i, int j, int k, float sensitivity) { sensitivity = Math.min(sensitivity, 0.49f); List entities = world.getEntitiesWithinAABB(EntityMinecart.class, AxisAlignedBB.getBoundingBox(i + sensitivity, j + sensitivity, k + sensitivity, i + 1 - sensitivity, j + 1 - sensitivity, k + 1 - sensitivity)); List<EntityMinecart> carts = new ArrayList<EntityMinecart>(); for (Object o : entities) { EntityMinecart cart = (EntityMinecart) o; if (!cart.isDead) carts.add((EntityMinecart) o); } return carts; } public static List<EntityMinecart> getMinecartsIn(World world, int i1, int j1, int k1, int i2, int j2, int k2) { List entities = world.getEntitiesWithinAABB(EntityMinecart.class, AxisAlignedBB.getBoundingBox(i1, j1, k1, i2, j2, k2)); List<EntityMinecart> carts = new ArrayList<EntityMinecart>(); for (Object o : entities) { EntityMinecart cart = (EntityMinecart) o; if (!cart.isDead) carts.add((EntityMinecart) o); } return carts; } /** * Returns the cart's "speed". It is not capped by the carts max speed, it * instead returns the cart's "potential" speed. Used by collision and * linkage logic. Do not use this to determine how fast a cart is currently * moving. * * @param cart * @return speed */ public static double getCartSpeedUncapped(EntityMinecart cart) { return Math.sqrt(cart.motionX * cart.motionX + cart.motionZ * cart.motionZ); } public static boolean cartVelocityIsLessThan(EntityMinecart cart, float vel) { return Math.abs(cart.motionX) < vel && Math.abs(cart.motionZ) < vel; } }