package blusunrize.immersiveengineering.common.util; import blusunrize.immersiveengineering.api.ApiUtils; import blusunrize.immersiveengineering.api.DirectionalBlockPos; import blusunrize.immersiveengineering.api.Lib; import blusunrize.immersiveengineering.api.crafting.IngredientStack; import blusunrize.immersiveengineering.common.util.inventory.IIEInventory; import com.google.common.base.Charsets; import com.google.common.collect.Lists; import com.google.common.io.Resources; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonParseException; import net.minecraft.block.Block; import net.minecraft.block.BlockLiquid; import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; import net.minecraft.client.resources.I18n; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.item.EntityItem; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.init.Blocks; import net.minecraft.init.Items; import net.minecraft.inventory.Container; import net.minecraft.inventory.IInventory; import net.minecraft.inventory.InventoryCrafting; import net.minecraft.item.Item; import net.minecraft.item.ItemDye; import net.minecraft.item.ItemStack; import net.minecraft.item.crafting.CraftingManager; import net.minecraft.item.crafting.IRecipe; import net.minecraft.nbt.NBTBase; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumFacing.Axis; import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.math.Vec3d; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; import net.minecraft.world.storage.loot.*; import net.minecraft.world.storage.loot.conditions.LootCondition; import net.minecraft.world.storage.loot.conditions.LootConditionManager; import net.minecraft.world.storage.loot.functions.LootFunction; import net.minecraft.world.storage.loot.functions.LootFunctionManager; import net.minecraftforge.fluids.*; import net.minecraftforge.fluids.capability.CapabilityFluidHandler; import net.minecraftforge.fluids.capability.IFluidHandler; import net.minecraftforge.fml.common.Loader; import net.minecraftforge.fml.common.ModContainer; import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.ItemHandlerHelper; import net.minecraftforge.oredict.OreDictionary; import javax.annotation.Nullable; import java.io.IOException; import java.lang.reflect.Method; import java.net.URL; import java.text.DecimalFormat; import java.util.*; public class Utils { public static boolean compareToOreName(ItemStack stack, String oreName) { if(!ApiUtils.isExistingOreName(oreName)) return false; ItemStack comp = copyStackWithAmount(stack, 1); List<ItemStack> s = OreDictionary.getOres(oreName); for(ItemStack st:s) if(OreDictionary.itemMatches(st, comp, false)) return true; return false; } public static boolean stackMatchesObject(ItemStack stack, Object o) { return stackMatchesObject(stack, o, false); } public static boolean stackMatchesObject(ItemStack stack, Object o, boolean checkNBT) { if(o instanceof ItemStack) return OreDictionary.itemMatches((ItemStack)o, stack, false) && (!checkNBT || ((ItemStack)o).getItemDamage()==OreDictionary.WILDCARD_VALUE || Utils.compareItemNBT((ItemStack)o, stack)); else if(o instanceof Collection) { for(Object io : (Collection)o) if(io instanceof ItemStack && OreDictionary.itemMatches((ItemStack)io, stack, false) && (!checkNBT || ((ItemStack)io).getItemDamage()==OreDictionary.WILDCARD_VALUE || Utils.compareItemNBT((ItemStack)io, stack))) return true; } else if(o instanceof IngredientStack) return ((IngredientStack)o).matchesItemStack(stack); else if(o instanceof ItemStack[]) { for(ItemStack io : (ItemStack[])o) if(OreDictionary.itemMatches(io, stack, false) && (!checkNBT || io.getItemDamage()==OreDictionary.WILDCARD_VALUE || Utils.compareItemNBT(io, stack))) return true; } else if(o instanceof FluidStack) { FluidStack fs = FluidUtil.getFluidContained(stack); return fs != null && fs.containsFluid((FluidStack)o); } else if(o instanceof String) return compareToOreName(stack, (String)o); return false; } public static boolean compareItemNBT(ItemStack stack1, ItemStack stack2) { if((stack1==null) != (stack2==null)) return false; boolean empty1 = (stack1.getTagCompound()==null||stack1.getTagCompound().hasNoTags()); boolean empty2 = (stack2.getTagCompound()==null||stack2.getTagCompound().hasNoTags()); if(empty1!=empty2) return false; if(!empty1 && !stack1.getTagCompound().equals(stack2.getTagCompound())) return false; return stack1.areCapsCompatible(stack2); } public static boolean canCombineArrays(ItemStack[] stacks, ItemStack[] target) { HashSet<IngredientStack> inputSet = new HashSet(); for(ItemStack s : stacks) inputSet.add(new IngredientStack(s)); for(ItemStack t : target) { int size = t.stackSize; Iterator<IngredientStack> it = inputSet.iterator(); while(it.hasNext()) { IngredientStack in = it.next(); if(in.matchesItemStackIgnoringSize(t)) { int taken = Math.min(size, in.inputSize); size -= taken; in.inputSize -= taken; if(in.inputSize<=0) it.remove(); if(size<=0) break; } } if(size>0) return false; } return true; } public static ItemStack copyStackWithAmount(ItemStack stack, int amount) { if(stack==null) return null; ItemStack s2 = stack.copy(); s2.stackSize=amount; return s2; } public static String[] dyeNames = {"Black","Red","Green","Brown","Blue","Purple","Cyan","LightGray","Gray","Pink","Lime","Yellow","LightBlue","Magenta","Orange","White"}; public static int getDye(ItemStack stack) { if(stack==null) return -1; if(stack.getItem().equals(Items.DYE)) return stack.getItemDamage(); for(int dye=0;dye<dyeNames.length;dye++) if(compareToOreName(stack,"dye"+dyeNames[dye])) return dye; return -1; } public static boolean isDye(ItemStack stack) { if(stack==null) return false; if(stack.getItem().equals(Items.DYE)) return true; for(int dye=0;dye<dyeNames.length;dye++) if(compareToOreName(stack,"dye"+dyeNames[dye])) return true; return false; } public static FluidStack copyFluidStackWithAmount(FluidStack stack, int amount, boolean stripPressure) { if(stack==null) return null; FluidStack fs = new FluidStack(stack, amount); if(stripPressure && fs.tag!=null && fs.tag.hasKey("pressurized")) { fs.tag.removeTag("pressurized"); if(fs.tag.hasNoTags()) fs.tag = null; } return fs; } static long UUIDBase = 109406000905L; static long UUIDAdd = 01L; public static UUID generateNewUUID() { UUID uuid = new UUID(UUIDBase,UUIDAdd); UUIDAdd++; return uuid; } public static BlockPos toCC(Object object) { return ApiUtils.toBlockPos(object); } public static DirectionalBlockPos toDirCC(Object object, EnumFacing direction) { if(object instanceof BlockPos) return new DirectionalBlockPos((BlockPos)object, direction); if(object instanceof TileEntity) return new DirectionalBlockPos(((TileEntity)object).getPos(), direction); return null; } public static boolean isBlockAt(World world, BlockPos pos, Block b, int meta) { return blockstateMatches(world.getBlockState(pos), b, meta); } public static boolean blockstateMatches(IBlockState state, Block b, int meta) { if(state.getBlock().equals(b)) return meta<0||meta==OreDictionary.WILDCARD_VALUE || state.getBlock().getMetaFromState(state)==meta; return false; } public static boolean isOreBlockAt(World world, BlockPos pos, String oreName) { IBlockState state = world.getBlockState(pos); ItemStack stack = new ItemStack(state.getBlock(),1,state.getBlock().getMetaFromState(state)); return compareToOreName(stack, oreName); } public static String formatDouble(double d, String s) { DecimalFormat df = new DecimalFormat(s); return df.format(d); } public static String toScientificNotation(int value, String decimalPrecision, int useKilo) { float formatted = value>=1000000000?value/1000000000f : value>=1000000?value/1000000f: value>=useKilo?value/1000f: value; String notation = value>=1000000000?"G" : value>=1000000?"M": value>=useKilo?"K": ""; return formatDouble(formatted, "0."+decimalPrecision)+notation; } public static String toCamelCase(String s) { return s.substring(0,1).toUpperCase(Locale.ENGLISH) + s.substring(1).toLowerCase(Locale.ENGLISH); } static Method m_getHarvestLevel = null; public static String getHarvestLevelName(int lvl) { if(Loader.isModLoaded("TConstruct")) { try{ if(m_getHarvestLevel==null) { Class clazz = Class.forName("tconstruct.library.util"); if(clazz!=null) m_getHarvestLevel = clazz.getDeclaredMethod("getHarvestLevelName", int.class); } if(m_getHarvestLevel!=null) return (String)m_getHarvestLevel.invoke(null, lvl); }catch(Exception e){} } return I18n.format(Lib.DESC_INFO+"mininglvl."+Math.max(-1, Math.min(lvl, 6))); } public static String getModVersion(String modid) { for(ModContainer container : Loader.instance().getActiveModList()) if(container.getModId().equalsIgnoreCase(modid)) return container.getVersion(); return ""; } public static boolean tilePositionMatch(TileEntity tile0, TileEntity tile1) { return tile0.getPos().equals(tile1.getPos()); } public static EnumFacing rotateFacingTowardsDir(EnumFacing f, EnumFacing dir) { if(dir==EnumFacing.NORTH) return f; else if(dir==EnumFacing.SOUTH && f.getAxis()!=Axis.Y) return f.rotateY().rotateY(); else if(dir==EnumFacing.WEST && f.getAxis()!=Axis.Y) return f.rotateYCCW(); else if(dir==EnumFacing.EAST && f.getAxis()!=Axis.Y) return f.rotateY(); else if(dir==EnumFacing.DOWN && f.getAxis()!=Axis.Y) return f.rotateAround(Axis.X); else if(dir==EnumFacing.UP && f.getAxis()!=Axis.X) return f.rotateAround(Axis.X).getOpposite(); return f; } public static RayTraceResult getMovingObjectPositionFromPlayer(World world, EntityLivingBase living, boolean bool) { float f = 1.0F; float f1 = living.prevRotationPitch + (living.rotationPitch - living.prevRotationPitch) * f; float f2 = living.prevRotationYaw + (living.rotationYaw - living.prevRotationYaw) * f; double d0 = living.prevPosX + (living.posX - living.prevPosX) * (double)f; double d1 = living.prevPosY + (living.posY - living.prevPosY) * (double)f + (double)(world.isRemote ? living.getEyeHeight() - (living instanceof EntityPlayer?((EntityPlayer)living).getDefaultEyeHeight():0) : living.getEyeHeight()); // isRemote check to revert changes to ray trace position due to adding the eye height clientside and player yOffset differences double d2 = living.prevPosZ + (living.posZ - living.prevPosZ) * (double)f; Vec3d vec3 = new Vec3d(d0, d1, d2); float f3 = MathHelper.cos(-f2 * 0.017453292F - (float)Math.PI); float f4 = MathHelper.sin(-f2 * 0.017453292F - (float)Math.PI); float f5 = -MathHelper.cos(-f1 * 0.017453292F); float f6 = MathHelper.sin(-f1 * 0.017453292F); float f7 = f4 * f5; float f8 = f3 * f5; double d3 = 5.0D; if (living instanceof EntityPlayerMP) d3 = ((EntityPlayerMP)living).interactionManager.getBlockReachDistance(); Vec3d vec31 = vec3.addVector((double)f7 * d3, (double)f6 * d3, (double)f8 * d3); return world.rayTraceBlocks(vec3, vec31, bool, !bool, false); } public static boolean canBlocksSeeOther(World world, BlockPos cc0, BlockPos cc1, Vec3d pos0, Vec3d pos1) { HashSet<BlockPos> inter = rayTrace(pos0, pos1, world); Iterator<BlockPos> it = inter.iterator(); while (it.hasNext()) { BlockPos cc = it.next(); if (!cc.equals(cc0)&&!cc.equals(cc1)) return false; } return true; } public static boolean isHammer(ItemStack stack) { if(stack==null) return false; return stack.getItem().getToolClasses(stack).contains(Lib.TOOL_HAMMER); } public static Vec3d getFlowVector(World world, BlockPos pos) { IBlockState state = world.getBlockState(pos); if(state.getBlock() instanceof BlockFluidBase) return ((BlockFluidBase)state.getBlock()).getFlowVector(world, pos); else if( !(state.getBlock() instanceof BlockLiquid)) return new Vec3d(0, 0, 0); BlockLiquid block = (BlockLiquid)state.getBlock(); Vec3d vec3 = new Vec3d(0.0D, 0.0D, 0.0D); Material mat = state.getMaterial(); int i = getEffectiveFlowDecay(world, pos, mat); for(EnumFacing enumfacing : EnumFacing.Plane.HORIZONTAL) { BlockPos blockpos = pos.offset(enumfacing); int j = getEffectiveFlowDecay(world, blockpos, mat); if(j<0) { if(!world.getBlockState(blockpos).getMaterial().blocksMovement()) { j = getEffectiveFlowDecay(world, blockpos.down(), mat); if(j>=0) { int k = j - (i - 8); vec3 = vec3.addVector((double)((blockpos.getX() - pos.getX()) * k), (double)((blockpos.getY() - pos.getY()) * k), (double)((blockpos.getZ() - pos.getZ()) * k)); } } } else if(j>=0) { int l = j - i; vec3 = vec3.addVector((double)((blockpos.getX() - pos.getX()) * l), (double)((blockpos.getY() - pos.getY()) * l), (double)((blockpos.getZ() - pos.getZ()) * l)); } } if(state.getValue(BlockLiquid.LEVEL).intValue()>=8) { for(EnumFacing enumfacing1 : EnumFacing.Plane.HORIZONTAL) { BlockPos blockpos1 = pos.offset(enumfacing1); if(block.isBlockSolid(world, blockpos1, enumfacing1) || block.isBlockSolid(world, blockpos1.up(), enumfacing1)) { vec3 = vec3.normalize().addVector(0.0D, -6.0D, 0.0D); break; } } } return vec3.normalize(); } static int getEffectiveFlowDecay(IBlockAccess world, BlockPos pos, Material mat) { IBlockState state = world.getBlockState(pos); if(state.getMaterial() != mat) return -1; int l = state.getBlock().getMetaFromState(state); if (l >= 8) l = 0; return l; } public static Vec3d addVectors(Vec3d vec0, Vec3d vec1) { return vec0.addVector(vec1.xCoord,vec1.yCoord,vec1.zCoord); } public static boolean isVecInEntityHead(EntityLivingBase entity, Vec3d vec) { if(entity.height/entity.width<2)//Crude check to see if the entity is bipedal or at least upright (this should work for blazes) return false; double d = vec.yCoord-(entity.posY+entity.getEyeHeight()); return Math.abs(d) < .25; } public static NBTTagCompound getRandomFireworkExplosion(Random rand, int preType) { NBTTagCompound tag = new NBTTagCompound(); NBTTagCompound expl = new NBTTagCompound(); expl.setBoolean("Flicker", true); expl.setBoolean("Trail", true); int[] colors = new int[rand.nextInt(8) + 1]; for (int i = 0; i < colors.length; i++) { int j = rand.nextInt(11)+1; if(j>2) j++; if(j>6) j+=2; //no black, brown, light grey, grey or white colors[i] = ItemDye.DYE_COLORS[j]; } expl.setIntArray("Colors", colors); int type = preType>=0?preType: rand.nextInt(4); if(preType<0 && type==3) type = 4; expl.setByte("Type", (byte) type); NBTTagList list = new NBTTagList(); list.appendTag(expl); tag.setTag("Explosions", list); return tag; } public static FluidStack drainFluidBlock(World world, BlockPos pos, boolean doDrain) { Block b = world.getBlockState(pos).getBlock(); Fluid f = FluidRegistry.lookupFluidForBlock(b); if(f!=null) { if(b instanceof IFluidBlock) { if(((IFluidBlock)b).canDrain(world, pos)) return ((IFluidBlock) b).drain(world, pos, doDrain); else return null; } else { if(b.getMetaFromState(world.getBlockState(pos))==0) { if(doDrain) world.setBlockToAir(pos); return new FluidStack(f, 1000); } return null; } } return null; } public static Fluid getRelatedFluid(World w, BlockPos pos) { Block b = w.getBlockState(pos).getBlock(); return FluidRegistry.lookupFluidForBlock(b); } public static boolean placeFluidBlock(World world, BlockPos pos, FluidStack fluid) { if(fluid==null || fluid.getFluid()==null) return false; IBlockState state = world.getBlockState(pos); Block b = state.getBlock(); Block fluidBlock = fluid.getFluid().getBlock(); if(Blocks.WATER.equals(fluidBlock)) fluidBlock = Blocks.FLOWING_WATER; else if(Blocks.LAVA.equals(fluidBlock)) fluidBlock = Blocks.FLOWING_LAVA; boolean canPlace = b==null||b.isAir(state,world,pos)||b.isReplaceable(world,pos); if(fluidBlock!=null && canPlace && fluid.amount>=1000) { boolean placed = false; if ((fluidBlock instanceof BlockFluidBase)) { BlockFluidBase blockFluid = (BlockFluidBase)fluidBlock; placed = world.setBlockState(pos, fluidBlock.getStateFromMeta(blockFluid.getMaxRenderHeightMeta())); } else placed = world.setBlockState(pos, fluidBlock.getDefaultState()); if(placed) fluid.amount -= 1000; return placed; } return false; } // public static Collection<ItemStack> getContainersFilledWith(FluidStack fluidStack) // { // List<ItemStack> containers = new ArrayList(); // for (FluidContainerRegistry.FluidContainerData data : FluidContainerRegistry.getRegisteredFluidContainerData()) // if(data.fluid.containsFluid(fluidStack)) // containers.add(data.filledContainer); // return containers; // } // public static String nameFromStack(ItemStack stack) // { // if(stack==null) // return ""; // try // { // return GameData.getItemRegistry().getNameForObject(stack.getItem()); // } // catch (NullPointerException e) {} // return ""; // } public static IBlockState getStateFromItemStack(ItemStack stack) { if(stack==null||stack.getItem()==null) return null; Block block = getBlockFromItem(stack.getItem()); if(block!=null) return block.getStateFromMeta(stack.getItemDamage()); return null; } public static Block getBlockFromItem(Item item) { if(item==Items.CAULDRON) return Blocks.CAULDRON; return Block.getBlockFromItem(item); } public static boolean canInsertStackIntoInventory(TileEntity inventory, ItemStack stack, EnumFacing side) { if(stack!=null && inventory!=null && inventory.hasCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, side)) { IItemHandler handler = inventory.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, side); ItemStack temp = ItemHandlerHelper.insertItem(handler, stack.copy(), true); if(temp==null || temp.stackSize<stack.stackSize) return true; } return false; } public static ItemStack insertStackIntoInventory(TileEntity inventory, ItemStack stack, EnumFacing side) { if(stack!=null && inventory!=null && inventory.hasCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, side)) { IItemHandler handler = inventory.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, side); ItemStack temp = ItemHandlerHelper.insertItem(handler, stack.copy(), true); if(temp==null || temp.stackSize<stack.stackSize) return ItemHandlerHelper.insertItem(handler, stack, false); } return stack; } public static ItemStack insertStackIntoInventory(TileEntity inventory, ItemStack stack, EnumFacing side, boolean simulate) { if(inventory!=null && stack!=null && inventory.hasCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, side)) { IItemHandler handler = inventory.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, side); return ItemHandlerHelper.insertItem(handler, stack.copy(), simulate); } return stack; } public static void dropStackAtPos(World world, BlockPos pos, ItemStack stack, EnumFacing facing) { if(stack!=null) { EntityItem ei = new EntityItem(world, pos.getX()+.5,pos.getY()+.5,pos.getZ()+.5, stack.copy()); ei.motionY = 0.025000000372529D; if(facing!=null) { ei.motionX = (0.075F * facing.getFrontOffsetX()); ei.motionZ = (0.075F * facing.getFrontOffsetZ()); } world.spawnEntityInWorld(ei); } } public static void dropStackAtPos(World world, BlockPos pos, ItemStack stack) { dropStackAtPos(world, pos, stack, null); } // public static ItemStack insertStackIntoInventory(IInventory inventory, ItemStack stack, EnumFacing side) // { // if (stack == null || inventory == null) // return null; // int stackSize = stack.stackSize; // if (inventory instanceof ISidedInventory) // { // ISidedInventory sidedInv = (ISidedInventory) inventory; // int slots[] = sidedInv.getSlotsForFace(side); // if (slots == null) // return stack; // for (int i=0; i<slots.length && stack!=null; i++) // { // if (sidedInv.canInsertItem(slots[i], stack, side)) // { // ItemStack existingStack = inventory.getStackInSlot(slots[i]); // if(OreDictionary.itemMatches(existingStack, stack, true)&&Utils.compareItemNBT(stack, existingStack)) // stack = addToOccupiedSlot(sidedInv, slots[i], stack, existingStack); // } // } // for (int i=0; i<slots.length && stack!=null; i++) // if (inventory.getStackInSlot(slots[i]) == null && sidedInv.canInsertItem(slots[i], stack, side)) // stack = addToEmptyInventorySlot(sidedInv, slots[i], stack); // } // else // { // int invSize = inventory.getSizeInventory(); // for (int i=0; i<invSize && stack!=null; i++) // { // ItemStack existingStack = inventory.getStackInSlot(i); // if (OreDictionary.itemMatches(existingStack, stack, true)&&Utils.compareItemNBT(stack, existingStack)) // stack = addToOccupiedSlot(inventory, i, stack, existingStack); // } // for (int i=0; i<invSize && stack!=null; i++) // if (inventory.getStackInSlot(i) == null) // stack = addToEmptyInventorySlot(inventory, i, stack); // } // if (stack == null || stack.stackSize != stackSize) // inventory.markDirty(); // return stack; // } public static ItemStack addToEmptyInventorySlot(IInventory inventory, int slot, ItemStack stack) { if (!inventory.isItemValidForSlot(slot, stack)) { return stack; } int stackLimit = inventory.getInventoryStackLimit(); inventory.setInventorySlotContents(slot, copyStackWithAmount(stack, Math.min(stack.stackSize, stackLimit))); return stackLimit >= stack.stackSize ? null : stack.splitStack(stack.stackSize - stackLimit); } public static ItemStack addToOccupiedSlot(IInventory inventory, int slot, ItemStack stack, ItemStack existingStack) { int stackLimit = Math.min(inventory.getInventoryStackLimit(), stack.getMaxStackSize()); if (stack.stackSize + existingStack.stackSize > stackLimit) { int stackDiff = stackLimit - existingStack.stackSize; existingStack.stackSize = stackLimit; stack.stackSize -= stackDiff; inventory.setInventorySlotContents(slot, existingStack); return stack; } existingStack.stackSize += Math.min(stack.stackSize, stackLimit); inventory.setInventorySlotContents(slot, existingStack); return stackLimit >= stack.stackSize ? null : stack.splitStack(stack.stackSize - stackLimit); } // public static boolean canInsertStackIntoInventory(IInventory inventory, ItemStack stack, EnumFacing side) // { // if(stack == null || inventory == null) // return false; // if(inventory instanceof ISidedInventory) // { // ISidedInventory sidedInv = (ISidedInventory) inventory; // int slots[] = sidedInv.getSlotsForFace(side); // if(slots == null) // return false; // for(int i=0; i<slots.length && stack!=null; i++) // { // if(sidedInv.canInsertItem(slots[i], stack, side) && sidedInv.isItemValidForSlot(slots[i], stack)) // { // ItemStack existingStack = inventory.getStackInSlot(slots[i]); // if(existingStack==null) // return true; // else // if(OreDictionary.itemMatches(existingStack, stack, true)&&Utils.compareItemNBT(stack, existingStack)) // if(existingStack.stackSize+stack.stackSize<inventory.getInventoryStackLimit() && existingStack.stackSize+stack.stackSize<existingStack.getMaxStackSize()) // return true; // } // } // } // else // { // int invSize = inventory.getSizeInventory(); // for(int i=0; i<invSize && stack!=null; i++) // if(inventory.isItemValidForSlot(i, stack)) // { // ItemStack existingStack = inventory.getStackInSlot(i); // if(existingStack==null) // return true; // else // if(OreDictionary.itemMatches(existingStack, stack, true)&&Utils.compareItemNBT(stack, existingStack)) // if(existingStack.stackSize+stack.stackSize<inventory.getInventoryStackLimit() && existingStack.stackSize+stack.stackSize<existingStack.getMaxStackSize()) // return true; // } // } // return false; // } public static ItemStack fillFluidContainer(IFluidHandler handler, ItemStack containerIn, ItemStack containerOut, @Nullable EntityPlayer player) { if(containerIn==null) return null; if(containerIn.hasTagCompound() && containerIn.getTagCompound().hasNoTags()) containerIn.setTagCompound(null); ItemStack full = FluidUtil.tryFillContainer(containerIn, handler, Integer.MAX_VALUE, player, false); if(full!=null && (containerOut==null || OreDictionary.itemMatches(containerOut,full,true))) { if(containerOut != null && containerOut.stackSize + full.stackSize > containerOut.getMaxStackSize()) return null; return FluidUtil.tryFillContainer(containerIn, handler, Integer.MAX_VALUE, player, true); } return null; } public static ItemStack drainFluidContainer(IFluidHandler handler, ItemStack containerIn, ItemStack containerOut, @Nullable EntityPlayer player) { if(containerIn==null) return null; if(containerIn.hasTagCompound() && containerIn.getTagCompound().hasNoTags()) containerIn.setTagCompound(null); ItemStack empty = FluidUtil.tryEmptyContainer(containerIn, handler, Integer.MAX_VALUE, player, false); if(empty!=null && (containerOut==null || OreDictionary.itemMatches(containerOut,empty,true))) { if(containerOut != null && containerOut.stackSize + empty.stackSize > containerOut.getMaxStackSize()) return null; return FluidUtil.tryEmptyContainer(containerIn, handler, Integer.MAX_VALUE, player, true); } return null; } // public static FluidStack getFluidFromItemStack(ItemStack stack) // { // if(stack==null) // return null; // FluidStack fluid = FluidContainerRegistry.getFluidForFilledItem(stack); // if(fluid != null) // return fluid; // else if(stack.getItem() instanceof IFluidContainerItem) // return ((IFluidContainerItem)stack.getItem()).getFluid(stack); // return null; // } public static boolean isFluidRelatedItemStack(ItemStack stack) { if(stack==null) return false; return stack.hasCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, null); } public static IRecipe findRecipe(InventoryCrafting crafting, World world) { for (int i=0; i<CraftingManager.getInstance().getRecipeList().size(); i++) { IRecipe irecipe = CraftingManager.getInstance().getRecipeList().get(i); if(irecipe.matches(crafting, world)) return irecipe; } return null; } public static class InventoryCraftingFalse extends InventoryCrafting { private static final Container nullContainer = new Container() { @Override public void onCraftMatrixChanged(IInventory paramIInventory){} @Override public boolean canInteractWith(EntityPlayer p_75145_1_) { return false; } }; public InventoryCraftingFalse(int w, int h) { super(nullContainer, w, h); } public static InventoryCrafting createFilledCraftingInventory(int w, int h, ItemStack[] stacks) { InventoryCrafting invC = new Utils.InventoryCraftingFalse(w, h); for(int j = 0; j < w * h; j++) if(stacks[j] != null) invC.setInventorySlotContents(j, stacks[j].copy()); return invC; } } public static HashSet<BlockPos> rayTrace(Vec3d start, Vec3d end, World world) { HashSet<BlockPos> ret = new HashSet<BlockPos>(); HashSet<BlockPos> checked = new HashSet<BlockPos>(); // x if (start.xCoord>end.xCoord) { Vec3d tmp = start; start = end; end = tmp; } double min = start.xCoord; double dif =end.xCoord-min; double lengthAdd = Math.ceil(min)-start.xCoord; Vec3d mov = start.subtract(end); if (mov.xCoord!=0) { mov = scalarProd(mov, 1 / mov.xCoord); ray(dif, mov, start, lengthAdd, ret, world, checked, Blocks.DIAMOND_ORE); } // y if (mov.yCoord!=0) { if (start.yCoord>end.yCoord) { Vec3d tmp = start; start = end; end = tmp; } min = start.yCoord; dif = end.yCoord-min; lengthAdd = Math.ceil(min)-start.yCoord; mov = start.subtract(end); mov = scalarProd(mov, 1/mov.yCoord); ray(dif, mov, start, lengthAdd, ret, world, checked, Blocks.IRON_ORE); } // z if (mov.zCoord!=0) { if (start.zCoord>end.zCoord) { Vec3d tmp = start; start = end; end = tmp; } min = start.zCoord; dif = end.zCoord - min; lengthAdd = Math.ceil(min)-start.zCoord; mov = start.subtract(end); mov = scalarProd(mov, 1 / mov.zCoord); ray(dif, mov, start, lengthAdd, ret, world, checked, Blocks.GOLD_ORE); } return ret; } private static void ray(double dif, Vec3d mov, Vec3d start, double lengthAdd, HashSet<BlockPos> ret, World world, HashSet<BlockPos> checked, Block tmp) { //Do NOT set this to true unless for debugging. Causes blocks to be placed along the traced ray boolean place = false; double standartOff = .0625; for (int i = 0; i < dif; i++) { Vec3d pos = addVectors(start, scalarProd(mov, i + lengthAdd+standartOff)); Vec3d posNext = addVectors(start, scalarProd(mov, i + 1 + lengthAdd+standartOff)); Vec3d posPrev = addVectors(start, scalarProd(mov, i + lengthAdd-standartOff)); Vec3d posVeryPrev = addVectors(start, scalarProd(mov, i - 1 + lengthAdd-standartOff)); BlockPos blockPos = new BlockPos((int) Math.floor(pos.xCoord), (int) Math.floor(pos.yCoord), (int) Math.floor(pos.zCoord)); Block b; IBlockState state; if (!checked.contains(blockPos)&&i + lengthAdd+standartOff<dif) { state = world.getBlockState(blockPos); b = state.getBlock(); if (b.canCollideCheck(state, false) && state.collisionRayTrace(world, blockPos, pos, posNext) != null) ret.add(blockPos); // if (place) // world.setBlockState(blockPos, tmp); checked.add(blockPos); } blockPos = new BlockPos((int) Math.floor(posPrev.xCoord), (int) Math.floor(posPrev.yCoord), (int) Math.floor(posPrev.zCoord)); if (!checked.contains(blockPos)&&i + lengthAdd-standartOff<dif) { state = world.getBlockState(blockPos); b = state.getBlock(); if (b.canCollideCheck(state, false) && state.collisionRayTrace(world, blockPos, posVeryPrev, posPrev) != null) ret.add(blockPos); // if (place) // world.setBlock(blockPos.posX, blockPos.posY, blockPos.posZ, tmp); checked.add(blockPos); } } } public static Vec3d scalarProd(Vec3d v, double s) { return new Vec3d(v.xCoord*s, v.yCoord*s, v.zCoord*s); } public static BlockPos rayTraceForFirst(Vec3d start, Vec3d end, World w, Set<BlockPos> ignore) { HashSet<BlockPos> trace = rayTrace(start, end, w); for (BlockPos cc:ignore) trace.remove(cc); if (start.xCoord!=end.xCoord) trace = findMinOrMax(trace, start.xCoord>end.xCoord, 0); if (start.yCoord!=end.yCoord) trace = findMinOrMax(trace, start.yCoord>end.yCoord, 0); if (start.zCoord!=end.zCoord) trace = findMinOrMax(trace, start.zCoord>end.zCoord, 0); if (trace.size()>0) { BlockPos ret = trace.iterator().next(); return ret; } return null; } public static HashSet<BlockPos> findMinOrMax(HashSet<BlockPos> in, boolean max, int coord) { HashSet<BlockPos> ret = new HashSet<BlockPos>(); int currMinMax = max?Integer.MIN_VALUE:Integer.MAX_VALUE; //find minimum for (BlockPos cc:in) { int curr = (coord==0?cc.getX():(coord==1?cc.getY():cc.getY())); if (max^(curr<currMinMax)) currMinMax = curr; } //fill ret set for (BlockPos cc:in) { int curr = (coord==0?cc.getX():(coord==1?cc.getY():cc.getZ())); if (curr==currMinMax) ret.add(cc); } return ret; } /** * get tile entity without loading currently unloaded chunks * @return return value of {@link IBlockAccess#getTileEntity(BlockPos)} or always null if chunk is not loaded */ public static TileEntity getExistingTileEntity(World world, BlockPos pos) { if(world.isBlockLoaded(pos)) return world.getTileEntity(pos); return null; } public static ItemStack[] readInventory(NBTTagList nbt, int size) { ItemStack[] inv = new ItemStack[size]; int max = nbt.tagCount(); for (int i = 0;i<max;i++) { NBTTagCompound itemTag = nbt.getCompoundTagAt(i); int slot = itemTag.getByte("Slot") & 255; if(slot>=0 && slot<size) inv[slot] = ItemStack.loadItemStackFromNBT(itemTag); } return inv; } public static NBTTagList writeInventory(ItemStack[] inv) { NBTTagList invList = new NBTTagList(); for(int i=0; i<inv.length; i++) if(inv[i] != null) { NBTTagCompound itemTag = new NBTTagCompound(); itemTag.setByte("Slot", (byte)i); inv[i].writeToNBT(itemTag); invList.appendTag(itemTag); } return invList; } public static NBTTagList writeInventory(Collection<ItemStack> inv) { NBTTagList invList = new NBTTagList(); byte slot = 0; for(ItemStack s : inv) { if(s!=null) { NBTTagCompound itemTag = new NBTTagCompound(); itemTag.setByte("Slot", slot); s.writeToNBT(itemTag); invList.appendTag(itemTag); } slot++; } return invList; } public static ItemStack[] loadItemStacksFromNBT(NBTBase nbt) { if(nbt instanceof NBTTagCompound) { ItemStack stack = ItemStack.loadItemStackFromNBT((NBTTagCompound)nbt); return new ItemStack[]{stack}; } else if(nbt instanceof NBTTagList) { NBTTagList list = (NBTTagList)nbt; return readInventory(list, list.tagCount()); } return new ItemStack[0]; } public static void modifyInvStackSize(ItemStack[] inv, int slot, int amount) { if(slot>=0&&slot<inv.length && inv[slot]!=null) { inv[slot].stackSize += amount; if(inv[slot].stackSize<=0) inv[slot] = null; } } public static void shuffleLootItems(List<ItemStack> stacks, int slotAmount, Random rand) { List<ItemStack> list = Lists.newArrayList(); Iterator<ItemStack> iterator = stacks.iterator(); while(iterator.hasNext()) { ItemStack itemstack = iterator.next(); if(itemstack.stackSize <= 0) iterator.remove(); else if(itemstack.stackSize > 1) { list.add(itemstack); iterator.remove(); } } slotAmount = slotAmount - stacks.size(); while(slotAmount>0 && list.size()>0) { ItemStack itemstack2 = list.remove(MathHelper.getRandomIntegerInRange(rand, 0, list.size() - 1)); int i = MathHelper.getRandomIntegerInRange(rand, 1, itemstack2.stackSize / 2); itemstack2.stackSize -= i; ItemStack itemstack1 = itemstack2.copy(); itemstack1.stackSize = i; if(itemstack2.stackSize>1 && rand.nextBoolean()) list.add(itemstack2); else stacks.add(itemstack2); if(itemstack1.stackSize>1 && rand.nextBoolean()) list.add(itemstack1); else stacks.add(itemstack1); } stacks.addAll(list); Collections.shuffle(stacks, rand); } private static final Gson GSON_INSTANCE = (new GsonBuilder()).registerTypeAdapter(RandomValueRange.class, new RandomValueRange.Serializer()).registerTypeAdapter(LootPool.class, new LootPool.Serializer()).registerTypeAdapter(LootTable.class, new LootTable.Serializer()).registerTypeHierarchyAdapter(LootEntry.class, new LootEntry.Serializer()).registerTypeHierarchyAdapter(LootFunction.class, new LootFunctionManager.Serializer()).registerTypeHierarchyAdapter(LootCondition.class, new LootConditionManager.Serializer()).registerTypeHierarchyAdapter(LootContext.EntityTarget.class, new LootContext.EntityTarget.Serializer()).create(); public static LootTable loadBuiltinLootTable(ResourceLocation resource) { URL url = Utils.class.getResource("/assets/" + resource.getResourceDomain() + "/loot_tables/" + resource.getResourcePath() + ".json"); if(url==null) return LootTable.EMPTY_LOOT_TABLE; else { String s; try { s = Resources.toString(url, Charsets.UTF_8); } catch(IOException ioexception) { // IELogger.warn(("Failed to load loot table " + resource.toString() + " from " + url.toString())); ioexception.printStackTrace(); return LootTable.EMPTY_LOOT_TABLE; } try { return net.minecraftforge.common.ForgeHooks.loadLootTable(GSON_INSTANCE, resource, s, false); } catch(JsonParseException jsonparseexception) { // IELogger.error(("Failed to load loot table " + resource.toString() + " from " + url.toString())); jsonparseexception.printStackTrace(); return LootTable.EMPTY_LOOT_TABLE; } } } public static int calcRedstoneFromInventory(IIEInventory inv) { if(inv==null) return 0; else { int i=0; float f = 0.0F; for(int j=0; j<inv.getInventory().length; ++j) { ItemStack itemstack = inv.getInventory()[j]; if(itemstack!=null) { f += (float)itemstack.stackSize / (float)Math.min(inv.getSlotLimit(j), itemstack.getMaxStackSize()); ++i; } } f = f/(float)inv.getInventory().length; return MathHelper.floor_float(f * 14.0F) + (i > 0 ? 1 : 0); } } public static Map<String, Object> saveStack(ItemStack stack) { HashMap<String, Object> ret = new HashMap<>(); if(stack != null && stack.getItem() != null) { ret.put("size", stack.stackSize); ret.put("name", Item.REGISTRY.getNameForObject(stack.getItem())); ret.put("nameUnlocalized", stack.getUnlocalizedName()); ret.put("label", stack.getDisplayName()); ret.put("damage", stack.getItemDamage()); ret.put("maxDamage", stack.getMaxDamage()); ret.put("maxSize", stack.getMaxStackSize()); ret.put("hasTag", stack.hasTagCompound()); } return ret; } public static Map<String, Object> saveFluidTank(FluidTank tank) { HashMap<String, Object> ret = new HashMap<>(); if(tank != null && tank.getFluid() != null) { ret.put("name", tank.getFluid().getFluid().getUnlocalizedName()); ret.put("amount", tank.getFluidAmount()); ret.put("capacity", tank.getCapacity()); ret.put("hasTag", tank.getFluid().tag != null); } return ret; } public static Map<String, Object> saveFluidStack(FluidStack tank) { HashMap<String, Object> ret = new HashMap<>(); if(tank != null && tank.getFluid() != null) { ret.put("name", tank.getFluid().getUnlocalizedName()); ret.put("amount", tank.amount); ret.put("hasTag", tank.tag != null); } return ret; } }