468 lines
15 KiB
Java
468 lines
15 KiB
Java
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;
|
|
}
|
|
}
|
|
}
|