blob: 309e8480ae1537bcdfc14210728cb81c5bffd696 [file] [log] [blame] [raw]
package li.cil.oc.util
import java.util.Random
import li.cil.oc.Constants
import li.cil.oc.OpenComputers
import li.cil.oc.api
import li.cil.oc.common.Tier
import net.minecraft.item.ItemBucket
import net.minecraft.item.ItemStack
import net.minecraft.item.crafting.CraftingManager
import net.minecraft.item.crafting.IRecipe
import net.minecraft.item.crafting.ShapedRecipes
import net.minecraft.item.crafting.ShapelessRecipes
import net.minecraft.nbt.NBTTagCompound
import net.minecraftforge.oredict.ShapedOreRecipe
import net.minecraftforge.oredict.ShapelessOreRecipe
import scala.collection.convert.WrapAsScala._
import scala.collection.mutable
object ItemUtils {
def caseTier(stack: ItemStack) = {
val descriptor = api.Items.get(stack)
if (descriptor == api.Items.get(Constants.BlockName.CaseTier1)) Tier.One
else if (descriptor == api.Items.get(Constants.BlockName.CaseTier2)) Tier.Two
else if (descriptor == api.Items.get(Constants.BlockName.CaseTier3)) Tier.Three
else if (descriptor == api.Items.get(Constants.BlockName.CaseCreative)) Tier.Four
else if (descriptor == api.Items.get(Constants.ItemName.MicrocontrollerCaseTier1)) Tier.One
else if (descriptor == api.Items.get(Constants.ItemName.MicrocontrollerCaseTier2)) Tier.Two
else if (descriptor == api.Items.get(Constants.ItemName.MicrocontrollerCaseCreative)) Tier.Four
else if (descriptor == api.Items.get(Constants.ItemName.DroneCaseTier1)) Tier.One
else if (descriptor == api.Items.get(Constants.ItemName.DroneCaseTier2)) Tier.Two
else if (descriptor == api.Items.get(Constants.ItemName.DroneCaseCreative)) Tier.Four
else if (descriptor == api.Items.get(Constants.ItemName.ServerTier1)) Tier.One
else if (descriptor == api.Items.get(Constants.ItemName.ServerTier2)) Tier.Two
else if (descriptor == api.Items.get(Constants.ItemName.ServerTier3)) Tier.Three
else if (descriptor == api.Items.get(Constants.ItemName.ServerCreative)) Tier.Four
else if (descriptor == api.Items.get(Constants.ItemName.TabletCaseTier1)) Tier.One
else if (descriptor == api.Items.get(Constants.ItemName.TabletCaseTier2)) Tier.Two
else if (descriptor == api.Items.get(Constants.ItemName.TabletCaseCreative)) Tier.Four
else Tier.None
}
def caseNameWithTierSuffix(name: String, tier: Int) = name + (if (tier == Tier.Four) "Creative" else (tier + 1).toString)
def loadStack(nbt: NBTTagCompound) = ItemStack.loadItemStackFromNBT(nbt)
def getIngredients(stack: ItemStack): Array[ItemStack] = try {
def getFilteredInputs(inputs: Iterable[ItemStack], outputSize: Double) = inputs.filter(input =>
input != null &&
input.getItem != null &&
math.floor(input.stackSize / outputSize) > 0 &&
// Strip out buckets, because those are returned when crafting, and
// we have no way of returning the fluid only (and I can't be arsed
// to make it output fluids into fluiducts or such, sorry).
!input.getItem.isInstanceOf[ItemBucket]).toArray
def getOutputSize(recipe: IRecipe): Double =
if (recipe != null && recipe.getRecipeOutput != null)
recipe.getRecipeOutput.stackSize
else
Double.PositiveInfinity
val recipes = CraftingManager.getInstance.getRecipeList.map(_.asInstanceOf[IRecipe])
val recipe = recipes.find(recipe => recipe.getRecipeOutput != null && recipe.getRecipeOutput.isItemEqual(stack))
val count = recipe.fold(0)(_.getRecipeOutput.stackSize)
val ingredients = recipe match {
case Some(recipe: ShapedRecipes) => getFilteredInputs(recipe.recipeItems.toIterable, getOutputSize(recipe))
case Some(recipe: ShapelessRecipes) => getFilteredInputs(recipe.recipeItems.map(_.asInstanceOf[ItemStack]), getOutputSize(recipe))
case Some(recipe: ShapedOreRecipe) => getFilteredInputs(resolveOreDictEntries(recipe.getInput), getOutputSize(recipe))
case Some(recipe: ShapelessOreRecipe) => getFilteredInputs(resolveOreDictEntries(recipe.getInput), getOutputSize(recipe))
case _ => Array.empty[ItemStack]
}
// Avoid positive feedback loops.
if (ingredients.exists(ingredient => ingredient.isItemEqual(stack))) {
return Array.empty[ItemStack]
}
// Merge equal items for size division by output size.
val merged = mutable.ArrayBuffer.empty[ItemStack]
for (ingredient <- ingredients) {
merged.find(_.isItemEqual(ingredient)) match {
case Some(entry) => entry.stackSize += ingredient.stackSize
case _ => merged += ingredient.copy()
}
}
merged.foreach(_.stackSize /= count)
// Split items up again to 'disassemble them individually'.
val distinct = mutable.ArrayBuffer.empty[ItemStack]
for (ingredient <- merged) {
val size = ingredient.stackSize max 1
ingredient.stackSize = 1
for (i <- 0 until size) {
distinct += ingredient.copy()
}
}
distinct.toArray
}
catch {
case t: Throwable =>
OpenComputers.log.warn("Whoops, something went wrong when trying to figure out an item's parts.", t)
Array.empty[ItemStack]
}
private lazy val rng = new Random()
private def resolveOreDictEntries[T](entries: Iterable[T]) = entries.collect {
case stack: ItemStack => stack
case list: java.util.ArrayList[ItemStack]@unchecked if !list.isEmpty => list.get(rng.nextInt(list.size))
}
}