package thaumcraft.api; import java.util.HashMap; import java.util.Iterator; import net.minecraft.block.Block; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.MathHelper; import net.minecraft.util.MovingObjectPosition; import net.minecraft.util.Vec3; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; import net.minecraftforge.common.util.ForgeDirection; import net.minecraftforge.oredict.OreDictionary; import thaumcraft.api.aspects.Aspect; import thaumcraft.api.aspects.AspectList; import thaumcraft.api.aspects.IEssentiaTransport; public class ThaumcraftApiHelper { public static AspectList cullTags(AspectList temp) { AspectList temp2 = new AspectList(); for (Aspect tag:temp.getAspects()) { if (tag!=null) temp2.add(tag, temp.getAmount(tag)); } while (temp2!=null && temp2.size()>6) { Aspect lowest = null; float low = Short.MAX_VALUE; for (Aspect tag:temp2.getAspects()) { if (tag==null) continue; float ta=temp2.getAmount(tag); if (tag.isPrimal()) { ta *= .9f; } else { if (!tag.getComponents()[0].isPrimal()) { ta *= 1.1f; if (!tag.getComponents()[0].getComponents()[0].isPrimal()) { ta *= 1.05f; } if (!tag.getComponents()[0].getComponents()[1].isPrimal()) { ta *= 1.05f; } } if (!tag.getComponents()[1].isPrimal()) { ta *= 1.1f; if (!tag.getComponents()[1].getComponents()[0].isPrimal()) { ta *= 1.05f; } if (!tag.getComponents()[1].getComponents()[1].isPrimal()) { ta *= 1.05f; } } } if (ta<low) { low = ta; lowest = tag; } } temp2.aspects.remove(lowest); } return temp2; } public static boolean areItemsEqual(ItemStack s1,ItemStack s2) { if (s1.isItemStackDamageable() && s2.isItemStackDamageable()) { return s1.getItem() == s2.getItem(); } else return s1.getItem() == s2.getItem() && s1.getItemDamage() == s2.getItemDamage(); } public static boolean isResearchComplete(String username, String researchkey) { return ThaumcraftApi.internalMethods.isResearchComplete(username, researchkey); } public static boolean hasDiscoveredAspect(String username, Aspect aspect) { return ThaumcraftApi.internalMethods.hasDiscoveredAspect(username, aspect); } public static AspectList getDiscoveredAspects(String username) { return ThaumcraftApi.internalMethods.getDiscoveredAspects(username); } public static ItemStack getStackInRowAndColumn(Object instance, int row, int column) { return ThaumcraftApi.internalMethods.getStackInRowAndColumn(instance, row, column); } public static AspectList getObjectAspects(ItemStack is) { return ThaumcraftApi.internalMethods.getObjectAspects(is); } public static AspectList getBonusObjectTags(ItemStack is,AspectList ot) { return ThaumcraftApi.internalMethods.getBonusObjectTags(is, ot); } public static AspectList generateTags(Item item, int meta) { return ThaumcraftApi.internalMethods.generateTags(item, meta); } public static boolean containsMatch(boolean strict, ItemStack[] inputs, ItemStack... targets) { for (ItemStack input : inputs) { for (ItemStack target : targets) { if (itemMatches(target, input, strict)) { return true; } } } return false; } public static boolean areItemStackTagsEqualForCrafting(ItemStack slotItem,ItemStack recipeItem) { if (recipeItem == null || slotItem == null) return false; if (recipeItem.stackTagCompound!=null && slotItem.stackTagCompound==null ) return false; if (recipeItem.stackTagCompound==null ) return true; Iterator iterator = recipeItem.stackTagCompound.func_150296_c().iterator(); while (iterator.hasNext()) { String s = (String)iterator.next(); if (slotItem.stackTagCompound.hasKey(s)) { if (!slotItem.stackTagCompound.getTag(s).toString().equals( recipeItem.stackTagCompound.getTag(s).toString())) { return false; } } else { return false; } } return true; } public static boolean itemMatches(ItemStack target, ItemStack input, boolean strict) { if (input == null && target != null || input != null && target == null) { return false; } return (target.getItem() == input.getItem() && ((target.getItemDamage() == OreDictionary.WILDCARD_VALUE && !strict) || target.getItemDamage() == input.getItemDamage())); } public static TileEntity getConnectableTile(World world, int x, int y, int z, ForgeDirection face) { TileEntity te = world.getTileEntity(x+face.offsetX, y+face.offsetY, z+face.offsetZ); if (te instanceof IEssentiaTransport && ((IEssentiaTransport)te).isConnectable(face.getOpposite())) return te; else return null; } public static TileEntity getConnectableTile(IBlockAccess world, int x, int y, int z, ForgeDirection face) { TileEntity te = world.getTileEntity(x+face.offsetX, y+face.offsetY, z+face.offsetZ); if (te instanceof IEssentiaTransport && ((IEssentiaTransport)te).isConnectable(face.getOpposite())) return te; else return null; } private static HashMap<Integer, AspectList> allAspects= new HashMap<Integer, AspectList>(); private static HashMap<Integer, AspectList> allCompoundAspects= new HashMap<Integer, AspectList>(); public static AspectList getAllAspects(int amount) { if (allAspects.get(amount)==null) { AspectList al = new AspectList(); for (Aspect aspect:Aspect.aspects.values()) { al.add(aspect, amount); } allAspects.put(amount, al); } return allAspects.get(amount); } public static AspectList getAllCompoundAspects(int amount) { if (allCompoundAspects.get(amount)==null) { AspectList al = new AspectList(); for (Aspect aspect:Aspect.getCompoundAspects()) { al.add(aspect, amount); } allCompoundAspects.put(amount, al); } return allCompoundAspects.get(amount); } /** * Use to subtract vis from a wand for most operations * Wands store vis differently so "real" vis costs need to be multiplied by 100 before calling this method * @param wand the wand itemstack * @param player the player using the wand * @param cost the cost of the operation. * @param doit actually subtract the vis from the wand if true - if false just simulate the result * @param crafting is this a crafting operation or not - if * false then things like frugal and potency will apply to the costs * @return was the vis successfully subtracted */ public static boolean consumeVisFromWand(ItemStack wand, EntityPlayer player, AspectList cost, boolean doit, boolean crafting) { return ThaumcraftApi.internalMethods.consumeVisFromWand(wand, player, cost, doit, crafting); } /** * Subtract vis for use by a crafting mechanic. Costs are calculated slightly * differently and things like the frugal enchant is ignored * Must NOT be multiplied by 100 - send the actual vis cost * @param wand the wand itemstack * @param player the player using the wand * @param cost the cost of the operation. * @param doit actually subtract the vis from the wand if true - if false just simulate the result * @return was the vis successfully subtracted */ public static boolean consumeVisFromWandCrafting(ItemStack wand, EntityPlayer player, AspectList cost, boolean doit) { return ThaumcraftApi.internalMethods.consumeVisFromWandCrafting(wand, player, cost, doit); } /** * Subtract vis from a wand the player is carrying. Works like consumeVisFromWand in that actual vis * costs should be multiplied by 100. The costs are handled like crafting however and things like * frugal don't effect them * @param player the player using the wand * @param cost the cost of the operation. * @return was the vis successfully subtracted */ public static boolean consumeVisFromInventory(EntityPlayer player, AspectList cost) { return ThaumcraftApi.internalMethods.consumeVisFromInventory(player, cost); } /** * This adds permanents or temporary warp to a player. It will automatically be synced clientside * @param player the player using the wand * @param amount how much warp to add. Negative amounts are only valid for temporary warp * @param temporary add temporary warp instead of permanent */ public static void addWarpToPlayer(EntityPlayer player, int amount, boolean temporary) { ThaumcraftApi.internalMethods.addWarpToPlayer(player, amount, temporary); } /** * This "sticky" warp to a player. Sticky warp is permanent warp that can be removed. * It will automatically be synced clientside * @param player the player using the wand * @param amount how much warp to add. Can have negative amounts. */ public static void addStickyWarpToPlayer(EntityPlayer player, int amount) { ThaumcraftApi.internalMethods.addStickyWarpToPlayer(player, amount); } public static MovingObjectPosition rayTraceIgnoringSource(World world, Vec3 v1, Vec3 v2, boolean bool1, boolean bool2, boolean bool3) { if (!Double.isNaN(v1.xCoord) && !Double.isNaN(v1.yCoord) && !Double.isNaN(v1.zCoord)) { if (!Double.isNaN(v2.xCoord) && !Double.isNaN(v2.yCoord) && !Double.isNaN(v2.zCoord)) { int i = MathHelper.floor_double(v2.xCoord); int j = MathHelper.floor_double(v2.yCoord); int k = MathHelper.floor_double(v2.zCoord); int l = MathHelper.floor_double(v1.xCoord); int i1 = MathHelper.floor_double(v1.yCoord); int j1 = MathHelper.floor_double(v1.zCoord); Block block = world.getBlock(l, i1, j1); int k1 = world.getBlockMetadata(l, i1, j1); MovingObjectPosition movingobjectposition2 = null; k1 = 200; while (k1-- >= 0) { if (Double.isNaN(v1.xCoord) || Double.isNaN(v1.yCoord) || Double.isNaN(v1.zCoord)) { return null; } if (l == i && i1 == j && j1 == k) { continue; } boolean flag6 = true; boolean flag3 = true; boolean flag4 = true; double d0 = 999.0D; double d1 = 999.0D; double d2 = 999.0D; if (i > l) { d0 = (double)l + 1.0D; } else if (i < l) { d0 = (double)l + 0.0D; } else { flag6 = false; } if (j > i1) { d1 = (double)i1 + 1.0D; } else if (j < i1) { d1 = (double)i1 + 0.0D; } else { flag3 = false; } if (k > j1) { d2 = (double)j1 + 1.0D; } else if (k < j1) { d2 = (double)j1 + 0.0D; } else { flag4 = false; } double d3 = 999.0D; double d4 = 999.0D; double d5 = 999.0D; double d6 = v2.xCoord - v1.xCoord; double d7 = v2.yCoord - v1.yCoord; double d8 = v2.zCoord - v1.zCoord; if (flag6) { d3 = (d0 - v1.xCoord) / d6; } if (flag3) { d4 = (d1 - v1.yCoord) / d7; } if (flag4) { d5 = (d2 - v1.zCoord) / d8; } boolean flag5 = false; byte b0; if (d3 < d4 && d3 < d5) { if (i > l) { b0 = 4; } else { b0 = 5; } v1.xCoord = d0; v1.yCoord += d7 * d3; v1.zCoord += d8 * d3; } else if (d4 < d5) { if (j > i1) { b0 = 0; } else { b0 = 1; } v1.xCoord += d6 * d4; v1.yCoord = d1; v1.zCoord += d8 * d4; } else { if (k > j1) { b0 = 2; } else { b0 = 3; } v1.xCoord += d6 * d5; v1.yCoord += d7 * d5; v1.zCoord = d2; } Vec3 vec32 = Vec3.createVectorHelper(v1.xCoord, v1.yCoord, v1.zCoord); l = (int)(vec32.xCoord = (double)MathHelper.floor_double(v1.xCoord)); if (b0 == 5) { --l; ++vec32.xCoord; } i1 = (int)(vec32.yCoord = (double)MathHelper.floor_double(v1.yCoord)); if (b0 == 1) { --i1; ++vec32.yCoord; } j1 = (int)(vec32.zCoord = (double)MathHelper.floor_double(v1.zCoord)); if (b0 == 3) { --j1; ++vec32.zCoord; } Block block1 = world.getBlock(l, i1, j1); int l1 = world.getBlockMetadata(l, i1, j1); if (!bool2 || block1.getCollisionBoundingBoxFromPool(world, l, i1, j1) != null) { if (block1.canCollideCheck(l1, bool1)) { MovingObjectPosition movingobjectposition1 = block1.collisionRayTrace(world, l, i1, j1, v1, v2); if (movingobjectposition1 != null) { return movingobjectposition1; } } else { movingobjectposition2 = new MovingObjectPosition(l, i1, j1, b0, v1, false); } } } return bool3 ? movingobjectposition2 : null; } else { return null; } } else { return null; } } }