blob: c6819563ca3018774f9544ba87d7738f89ec16b0 [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.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 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))
}
}