Merge branch 'master-MC1.7.10' of github.com:MightyPirates/OpenComputers into master-MC1.8

Conflicts:
	src/main/scala/li/cil/oc/common/block/Print.scala
	src/main/scala/li/cil/oc/common/recipe/Recipes.scala
This commit is contained in:
Florian Nücke 2015-04-05 01:11:43 +02:00
commit f85a7ec3dd
11 changed files with 178 additions and 82 deletions

View File

@ -173,6 +173,7 @@ oc:gui.Chat.WarningLuaFallback=Native Lua libraries are not available, computers
oc:gui.Chat.WarningPower=No supported power providing mod available. Computers, screens and all other components will §lnot§f require energy. Install one of the following mods to enable power: BuildCraft, Electrical Age, IndustrialCraft2, Mekanism or Thermal Expansion. Disable power in the config to suppress this warning. oc:gui.Chat.WarningPower=No supported power providing mod available. Computers, screens and all other components will §lnot§f require energy. Install one of the following mods to enable power: BuildCraft, Electrical Age, IndustrialCraft2, Mekanism or Thermal Expansion. Disable power in the config to suppress this warning.
oc:gui.Chat.TextureName=§7Texture name is §a%s§f. oc:gui.Chat.TextureName=§7Texture name is §a%s§f.
oc:gui.Chat.WarningProjectRed=You are using a version of Project: Red that is incompatible with OpenComputers. Try updating your version of Project: Red. oc:gui.Chat.WarningProjectRed=You are using a version of Project: Red that is incompatible with OpenComputers. Try updating your version of Project: Red.
oc:gui.Chat.WarningRecipes=There were errors loading one or more recipes. Some items may be uncraftable. Please check your log file for more information.
oc:gui.Error.ComponentOverflow=Too many components connected to the computer. oc:gui.Error.ComponentOverflow=Too many components connected to the computer.
oc:gui.Error.InternalError=Internal error, please see the log file. This is probably a bug. oc:gui.Error.InternalError=Internal error, please see the log file. This is probably a bug.
oc:gui.Error.NoCPU=No CPU is installed in the computer. oc:gui.Error.NoCPU=No CPU is installed in the computer.

View File

@ -117,7 +117,7 @@ end
function network.tcp.close(channel) function network.tcp.close(channel)
if internal.tcp.channels[channel] then if internal.tcp.channels[channel] then
if internal.tcp.channels[channel].open or internal.tcp.channels[channel].waiting then if internal.tcp.channels[channel].open or internal.tcp.channels[channel].waiting then
driver.send(addr, "TC".. string.char(math.floor(internal.tcp.channels[channel].remote/256))..string.char(internal.tcp.channels[channel].remote%256)) driver.send(internal.tcp.channels[channel].addr, "TC".. string.char(math.floor(internal.tcp.channels[channel].remote/256))..string.char(internal.tcp.channels[channel].remote%256))
end end
internal.tcp.channels[channel] = {next = internal.tcp.freeCh} internal.tcp.channels[channel] = {next = internal.tcp.freeCh}
internal.tcp.freeCh = channel internal.tcp.freeCh = channel

View File

@ -314,6 +314,8 @@ nuggetIron {
input: ingotIron input: ingotIron
output: 9 output: 9
} }
cuttingWire = false
acid = false
ingotIron { ingotIron {
input: [[nuggetIron, nuggetIron, nuggetIron], input: [[nuggetIron, nuggetIron, nuggetIron],
[nuggetIron, nuggetIron, nuggetIron], [nuggetIron, nuggetIron, nuggetIron],
@ -424,6 +426,7 @@ rawCircuitBoard {
type: shapeless type: shapeless
input: [nuggetGold, clay, dyeGreen] input: [nuggetGold, clay, dyeGreen]
} }
circuitBoard = false
printedCircuitBoard { printedCircuitBoard {
type: furnace type: furnace
input: "oc:materialCircuitBoardRaw" input: "oc:materialCircuitBoardRaw"

View File

@ -3,6 +3,11 @@
# priority (i.e. included recipes simply replace the current definition for all # priority (i.e. included recipes simply replace the current definition for all
# already known recipes). # already known recipes).
# To disable a recipe, assign a boolean value to it. For example, to disable
# the recipe for the transistor: `transistor = false`. This will disable the
# recipe and hide the item in the creative tab and NEI. If you assign `true`,
# the recipe will still be disabled, but not hidden in the creative tab/NEI.
include file("default.recipes") include file("default.recipes")
#include file("hardmode.recipes") #include file("hardmode.recipes")
#include file("gregtech.recipes") #include file("gregtech.recipes")

View File

@ -83,6 +83,8 @@ object Localization {
def WarningFingerprint(event: FMLFingerprintViolationEvent) = new ChatComponentText("§aOpenComputers§f: ").appendSibling(localizeLater("gui.Chat.WarningFingerprint", event.expectedFingerprint, event.fingerprints.toArray.mkString(", "))) def WarningFingerprint(event: FMLFingerprintViolationEvent) = new ChatComponentText("§aOpenComputers§f: ").appendSibling(localizeLater("gui.Chat.WarningFingerprint", event.expectedFingerprint, event.fingerprints.toArray.mkString(", ")))
def WarningRecipes = new ChatComponentText("§aOpenComputers§f: ").appendSibling(localizeLater("gui.Chat.WarningRecipes"))
def InfoNewVersion(version: String) = new ChatComponentText("§aOpenComputers§f: ").appendSibling(localizeLater("gui.Chat.NewVersion", version)) def InfoNewVersion(version: String) = new ChatComponentText("§aOpenComputers§f: ").appendSibling(localizeLater("gui.Chat.NewVersion", version))
def TextureName(name: String) = new ChatComponentText("§aOpenComputers§f: ").appendSibling(localizeLater("gui.Chat.TextureName", name)) def TextureName(name: String) = new ChatComponentText("§aOpenComputers§f: ").appendSibling(localizeLater("gui.Chat.TextureName", name))

View File

@ -28,7 +28,8 @@ object PetRenderer {
"Jodarion" ->(1.0, 0.0, 0.0), "Jodarion" ->(1.0, 0.0, 0.0),
"DaKaTotal" ->(0.5, 0.7, 1.0), "DaKaTotal" ->(0.5, 0.7, 1.0),
"MichiyoRavencroft" ->(1.0, 0.0, 0.0), "MichiyoRavencroft" ->(1.0, 0.0, 0.0),
"Vexatos" ->(0.18, 0.95, 0.922) "Vexatos" ->(0.18, 0.95, 0.922),
"StoneNomad" ->(0.8, 0.77, 0.75)
) )
private val petLocations = com.google.common.cache.CacheBuilder.newBuilder(). private val petLocations = com.google.common.cache.CacheBuilder.newBuilder().

View File

@ -10,6 +10,7 @@ import li.cil.oc.client.{PacketSender => ClientPacketSender}
import li.cil.oc.common.item.data.MicrocontrollerData import li.cil.oc.common.item.data.MicrocontrollerData
import li.cil.oc.common.item.data.RobotData import li.cil.oc.common.item.data.RobotData
import li.cil.oc.common.item.data.TabletData import li.cil.oc.common.item.data.TabletData
import li.cil.oc.common.recipe.Recipes
import li.cil.oc.common.tileentity.Robot import li.cil.oc.common.tileentity.Robot
import li.cil.oc.integration.Mods import li.cil.oc.integration.Mods
import li.cil.oc.integration.util import li.cil.oc.integration.util
@ -116,6 +117,9 @@ object EventHandler {
if (!Settings.get.pureIgnorePower && Settings.get.ignorePower) { if (!Settings.get.pureIgnorePower && Settings.get.ignorePower) {
player.addChatMessage(Localization.Chat.WarningPower) player.addChatMessage(Localization.Chat.WarningPower)
} }
if (Recipes.hadErrors) {
player.addChatMessage(Localization.Chat.WarningRecipes)
}
ServerPacketSender.sendPetVisibility(None, Some(player)) ServerPacketSender.sendPetVisibility(None, Some(player))
// Do update check in local games and for OPs. // Do update check in local games and for OPs.
if (!Mods.VersionChecker.isAvailable && (!MinecraftServer.getServer.isDedicatedServer || MinecraftServer.getServer.getConfigurationManager.canSendCommands(player.getGameProfile))) { if (!Mods.VersionChecker.isAvailable && (!MinecraftServer.getServer.isDedicatedServer || MinecraftServer.getServer.getConfigurationManager.canSendCommands(player.getGameProfile))) {

View File

@ -31,6 +31,7 @@ import scala.collection.mutable
object Recipes { object Recipes {
val list = mutable.LinkedHashMap.empty[ItemStack, String] val list = mutable.LinkedHashMap.empty[ItemStack, String]
val oreDictEntries = mutable.LinkedHashMap.empty[String, ItemStack] val oreDictEntries = mutable.LinkedHashMap.empty[String, ItemStack]
var hadErrors = false
def addBlock(instance: Block, name: String, oreDict: String = null) = { def addBlock(instance: Block, name: String, oreDict: String = null) = {
Items.registerBlock(instance, name) Items.registerBlock(instance, name)
@ -211,6 +212,9 @@ object Recipes {
private def addRecipe(output: ItemStack, list: Config, name: String) = try { private def addRecipe(output: ItemStack, list: Config, name: String) = try {
if (list.hasPath(name)) { if (list.hasPath(name)) {
val value = list.getValue(name)
value.valueType match {
case ConfigValueType.OBJECT =>
val recipe = list.getConfig(name) val recipe = list.getConfig(name)
val recipeType = tryGetType(recipe) val recipeType = tryGetType(recipe)
try { try {
@ -224,30 +228,39 @@ object Recipes {
addGTAssemblingMachineRecipe(output, recipe) addGTAssemblingMachineRecipe(output, recipe)
} }
else { else {
OpenComputers.log.warn(s"Skipping GregTech assembler recipe for '$name' because GregTech is not present, you will not be able to craft this item!") OpenComputers.log.error(s"Skipping GregTech assembler recipe for '$name' because GregTech is not present, you will not be able to craft this item.")
hide(output) hadErrors = true
} }
*/ */
case other => case other =>
OpenComputers.log.warn(s"Failed adding recipe for '$name', you will not be able to craft this item! The error was: Invalid recipe type '$other'.") OpenComputers.log.error(s"Failed adding recipe for '$name', you will not be able to craft this item. The error was: Invalid recipe type '$other'.")
hide(output) hadErrors = true
} }
} }
catch { catch {
case e: RecipeException => case e: RecipeException =>
OpenComputers.log.warn(s"Failed adding $recipeType recipe for '$name', you will not be able to craft this item! The error was: ${e.getMessage}") OpenComputers.log.error(s"Failed adding $recipeType recipe for '$name', you will not be able to craft this item! The error was: ${e.getMessage}")
hadErrors = true
}
case ConfigValueType.BOOLEAN =>
// Explicitly disabled, keep in NEI if true.
if (!value.unwrapped.asInstanceOf[Boolean]) {
hide(output) hide(output)
} }
case _ =>
OpenComputers.log.error(s"Failed adding recipe for '$name', you will not be able to craft this item. The error was: Invalid value for recipe.")
hadErrors = true
}
} }
else { else {
OpenComputers.log.info(s"No recipe for '$name', you will not be able to craft this item.") OpenComputers.log.warn(s"No recipe for '$name', you will not be able to craft this item. To suppress this warning, disable the recipe (assign `false` to it).")
hide(output) hadErrors = true
} }
} }
catch { catch {
case e: Throwable => case e: Throwable =>
OpenComputers.log.error(s"Failed adding recipe for '$name', you will not be able to craft this item!", e) OpenComputers.log.error(s"Failed adding recipe for '$name', you will not be able to craft this item.", e)
hide(output) hadErrors = true
} }
private def addShapedRecipe(output: ItemStack, recipe: Config) { private def addShapedRecipe(output: ItemStack, recipe: Config) {
@ -276,7 +289,6 @@ object Recipes {
if (input.size > 0 && output.stackSize > 0) { if (input.size > 0 && output.stackSize > 0) {
GameRegistry.addRecipe(new ExtendedShapedOreRecipe(output, shape ++ input: _*)) GameRegistry.addRecipe(new ExtendedShapedOreRecipe(output, shape ++ input: _*))
} }
else hide(output)
} }
private def addShapelessRecipe(output: ItemStack, recipe: Config) { private def addShapelessRecipe(output: ItemStack, recipe: Config) {
@ -289,7 +301,6 @@ object Recipes {
if (input.size > 0 && output.stackSize > 0) { if (input.size > 0 && output.stackSize > 0) {
GameRegistry.addRecipe(new ExtendedShapelessOreRecipe(output, input: _*)) GameRegistry.addRecipe(new ExtendedShapelessOreRecipe(output, input: _*))
} }
else hide(output)
} }
/* TODO GregTech /* TODO GregTech

View File

@ -1,13 +1,5 @@
package li.cil.oc.integration.appeng package li.cil.oc.integration.appeng
import appeng.api.config.Actionable
import appeng.api.config.FuzzyMode
import appeng.api.config.Settings
import appeng.api.config.Upgrades
import appeng.api.networking.security.MachineSource
import appeng.parts.automation.PartExportBus
import appeng.util.Platform
import appeng.util.item.AEItemStack
import li.cil.oc.api.driver import li.cil.oc.api.driver
import li.cil.oc.api.driver.NamedBlock import li.cil.oc.api.driver.NamedBlock
import li.cil.oc.api.internal.Database import li.cil.oc.api.internal.Database
@ -21,9 +13,6 @@ import li.cil.oc.util.ExtendedArguments._
import li.cil.oc.util.InventoryUtils import li.cil.oc.util.InventoryUtils
import li.cil.oc.util.ResultWrapper._ import li.cil.oc.util.ResultWrapper._
import net.minecraft.world.World import net.minecraft.world.World
import net.minecraftforge.common.util.ForgeDirection
import scala.collection.convert.WrapAsScala._
object DriverExportBus extends driver.Block { object DriverExportBus extends driver.Block {
type ExportBusTile = appeng.api.parts.IPartHost type ExportBusTile = appeng.api.parts.IPartHost
@ -98,11 +87,15 @@ object DriverExportBus extends driver.Block {
case 4 => 96 case 4 => 96
case _ => 1 case _ => 1
} }
val fuzzyMode = export.getConfigManager.getSetting(Settings.FUZZY_MODE).asInstanceOf[FuzzyMode] // We need reflection here to avoid compiling against the return type,
// which has changed in rv2-beta-20 or so.
val fuzzyMode = export.getConfigManager.
getClass.getMethod("getSetting", classOf[Enum[_]]).
invoke(export.getConfigManager, Settings.FUZZY_MODE).asInstanceOf[FuzzyMode]
val source = new MachineSource(export) val source = new MachineSource(export)
var didSomething = false var didSomething = false
for (slot <- 0 until config.getSizeInventory if count > 0) { for (slot <- 0 until config.getSizeInventory if count > 0) {
val filter = AEItemStack.create(config.getStackInSlot(slot)) val filter = AEApi.instance.storage.createItemStack(config.getStackInSlot(slot))
val stacks = val stacks =
if (export.getInstalledUpgrades(Upgrades.FUZZY) > 0) if (export.getInstalledUpgrades(Upgrades.FUZZY) > 0)
itemStorage.getStorageList.findFuzzy(filter, fuzzyMode).toSeq itemStorage.getStorageList.findFuzzy(filter, fuzzyMode).toSeq
@ -137,4 +130,5 @@ object DriverExportBus extends driver.Block {
} }
} }
} }
} }

View File

@ -7,14 +7,8 @@ import codechicken.lib.data.MCDataOutput
import codechicken.lib.raytracer.ExtendedMOP import codechicken.lib.raytracer.ExtendedMOP
import codechicken.lib.vec.Cuboid6 import codechicken.lib.vec.Cuboid6
import codechicken.lib.vec.Vector3 import codechicken.lib.vec.Vector3
import codechicken.multipart.IRedstonePart
import codechicken.multipart.TCuboidPart
import codechicken.multipart.TNormalOcclusion
import cpw.mods.fml.relauncher.Side
import cpw.mods.fml.relauncher.SideOnly
import li.cil.oc.Settings import li.cil.oc.Settings
import li.cil.oc.api.Items import li.cil.oc.api.Items
import li.cil.oc.client.renderer.block.Print
import li.cil.oc.common.block.Print import li.cil.oc.common.block.Print
import li.cil.oc.common.item.data.PrintData import li.cil.oc.common.item.data.PrintData
import li.cil.oc.common.tileentity import li.cil.oc.common.tileentity
@ -23,10 +17,7 @@ import li.cil.oc.util.BlockPosition
import li.cil.oc.util.ExtendedAABB import li.cil.oc.util.ExtendedAABB
import li.cil.oc.util.ExtendedAABB._ import li.cil.oc.util.ExtendedAABB._
import li.cil.oc.util.ExtendedNBT._ import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.util.ExtendedWorld._
import mods.immibis.redlogic.api.wiring.IRedstoneEmitter
import net.minecraft.client.renderer.OpenGlHelper import net.minecraft.client.renderer.OpenGlHelper
import net.minecraft.client.renderer.RenderBlocks
import net.minecraft.client.renderer.RenderGlobal import net.minecraft.client.renderer.RenderGlobal
import net.minecraft.entity.player.EntityPlayer import net.minecraft.entity.player.EntityPlayer
import net.minecraft.init.Blocks import net.minecraft.init.Blocks
@ -34,18 +25,58 @@ import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound import net.minecraft.nbt.NBTTagCompound
import net.minecraft.util.MovingObjectPosition import net.minecraft.util.MovingObjectPosition
import net.minecraft.util.Vec3 import net.minecraft.util.Vec3
import net.minecraftforge.common.util.ForgeDirection
import org.lwjgl.opengl.GL11 import org.lwjgl.opengl.GL11
import scala.collection.convert.WrapAsJava._ import scala.collection.convert.WrapAsJava._
import scala.collection.convert.WrapAsScala._
class PrintPart(val original: Option[tileentity.Print] = None) extends SimpleBlockPart with TCuboidPart with TNormalOcclusion with IRedstonePart { object PrintPart {
private val q0 = 0 / 16f
private val q1 = 4 / 16f
private val q2 = 12 / 16f
private val q3 = 16 / 16f
val slotBounds = Array(
new Cuboid6(q1, q0, q1, q2, q1, q2),
new Cuboid6(q1, q2, q1, q2, q3, q2),
new Cuboid6(q1, q1, q0, q2, q2, q1),
new Cuboid6(q1, q1, q2, q2, q2, q3),
new Cuboid6(q0, q1, q1, q1, q2, q2),
new Cuboid6(q2, q1, q1, q3, q2, q2),
new Cuboid6(q1, q1, q1, q2, q2, q2),
new Cuboid6(q0, q0, q0, q1, q1, q1),
new Cuboid6(q0, q2, q0, q1, q3, q1),
new Cuboid6(q0, q0, q2, q1, q1, q3),
new Cuboid6(q0, q2, q2, q1, q3, q3),
new Cuboid6(q2, q0, q0, q3, q1, q1),
new Cuboid6(q2, q2, q0, q3, q3, q1),
new Cuboid6(q2, q0, q2, q3, q1, q3),
new Cuboid6(q2, q2, q2, q3, q3, q3),
new Cuboid6(q0, q1, q0, q1, q2, q1),
new Cuboid6(q0, q1, q2, q1, q2, q3),
new Cuboid6(q2, q1, q0, q3, q2, q1),
new Cuboid6(q2, q1, q2, q3, q2, q3),
new Cuboid6(q0, q0, q1, q1, q1, q2),
new Cuboid6(q2, q0, q1, q3, q1, q2),
new Cuboid6(q0, q2, q1, q1, q3, q2),
new Cuboid6(q2, q2, q1, q3, q3, q2),
new Cuboid6(q1, q0, q0, q2, q1, q1),
new Cuboid6(q1, q2, q0, q2, q3, q1),
new Cuboid6(q1, q0, q2, q2, q1, q3),
new Cuboid6(q1, q2, q2, q2, q3, q3)
)
}
class PrintPart(val original: Option[tileentity.Print] = None) extends SimpleBlockPart with TCuboidPart with TNormalOcclusion with IRedstonePart with TSlottedPart with TEdgePart with TFacePart {
var facing = ForgeDirection.SOUTH var facing = ForgeDirection.SOUTH
var data = new PrintData() var data = new PrintData()
var boundsOff = ExtendedAABB.unitBounds var boundsOff = ExtendedAABB.unitBounds
var boundsOn = ExtendedAABB.unitBounds var boundsOn = ExtendedAABB.unitBounds
var state = false var state = false
var toggling = false // avoid infinite loops when updating neighbors
original.foreach(print => { original.foreach(print => {
facing = print.facing facing = print.facing
@ -74,8 +105,24 @@ class PrintPart(val original: Option[tileentity.Print] = None) extends SimpleBlo
override def getRenderBounds = getBounds override def getRenderBounds = getBounds
override def getSlotMask: Int = {
var mask = 0
val boxes = getOcclusionBoxes
for (slot <- PartMap.values) {
val bounds = PrintPart.slotBounds(slot.i)
if (boxes.exists(_.intersects(bounds))) {
mask |= slot.mask
}
}
mask
}
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //
override def conductsRedstone: Boolean = data.emitRedstone && state
override def redstoneConductionMap: Int = if (data.emitRedstone && state) 0xFF else 0
override def canConnectRedstone(side: Int): Boolean = true override def canConnectRedstone(side: Int): Boolean = true
override def strongPowerLevel(side: Int): Int = weakPowerLevel(side) override def strongPowerLevel(side: Int): Int = weakPowerLevel(side)
@ -96,22 +143,29 @@ class PrintPart(val original: Option[tileentity.Print] = None) extends SimpleBlo
def toggleState(): Unit = { def toggleState(): Unit = {
if (canToggle) { if (canToggle) {
toggling = true
state = !state state = !state
world.playSoundEffect(x + 0.5, y + 0.5, z + 0.5, "random.click", 0.3F, if (state) 0.6F else 0.5F) // Update slot info in tile... kinda meh, but works.
world.notifyBlocksOfNeighborChange(x, y, z, tile.getBlockType) tile match {
world.markBlockForUpdate(x, y, z) case slotted: TSlottedTile =>
if (!world.isRemote) sendDescUpdate() for (i <- 0 until slotted.v_partMap.length) {
tile.partList.foreach { if (slotted.v_partMap(i) == this)
case print: PrintPart if print != this => print.onNeighborChanged() slotted.v_partMap(i) = null
}
tile.bindPart(this)
case _ => case _ =>
} }
world.playSoundEffect(x + 0.5, y + 0.5, z + 0.5, "random.click", 0.3F, if (state) 0.6F else 0.5F)
tile.notifyPartChange(this)
sendDescUpdate()
if (state && data.isButtonMode) { if (state && data.isButtonMode) {
scheduleTick(simpleBlock.tickRate(world)) scheduleTick(simpleBlock.tickRate(world))
} }
toggling = false
} }
} }
def canToggle = { def canToggle = !toggling && world != null && !world.isRemote && {
val toggled = new PrintPart() val toggled = new PrintPart()
toggled.facing = facing toggled.facing = facing
toggled.data = data toggled.data = data
@ -177,22 +231,33 @@ class PrintPart(val original: Option[tileentity.Print] = None) extends SimpleBlo
true true
} }
override def onPartChanged(part: TMultiPart): Unit = {
super.onPartChanged(part)
checkRedstone()
}
override def onNeighborChanged(): Unit = { override def onNeighborChanged(): Unit = {
super.onNeighborChanged() super.onNeighborChanged()
checkRedstone()
}
protected def checkRedstone(): Unit = {
val newMaxValue = computeInput()
val newState = newMaxValue > 1 // Fixes oddities in cycling updates.
if (!data.emitRedstone && data.stateOn.size > 0 && state != newState) {
toggleState()
}
}
protected def computeInput(): Int = {
val inner = tile.partList.foldLeft(false)((powered, part) => part match { val inner = tile.partList.foldLeft(false)((powered, part) => part match {
case print: PrintPart => powered || (print.state && print.data.emitRedstone) case print: PrintPart => powered || (print.state && print.data.emitRedstone)
case _ => powered case _ => powered
}) })
val newMaxValue = if (inner) 15 else ForgeDirection.VALID_DIRECTIONS.map(computeInput).max if (inner) 15 else ForgeDirection.VALID_DIRECTIONS.map(computeInput).max
if (!data.emitRedstone && data.stateOn.size > 0) {
val newState = newMaxValue > 0
if (state != newState) {
toggleState()
}
}
} }
protected def computeInput(side: ForgeDirection) = { protected def computeInput(side: ForgeDirection): Int = {
val blockPos = BlockPosition(x, y, z).offset(side) val blockPos = BlockPosition(x, y, z).offset(side)
if (!world.blockExists(blockPos)) 0 if (!world.blockExists(blockPos)) 0
else { else {

View File

@ -71,20 +71,30 @@ object ItemUtils {
} }
def getIngredients(stack: ItemStack): Array[ItemStack] = try { def getIngredients(stack: ItemStack): Array[ItemStack] = try {
val recipes = CraftingManager.getInstance.getRecipeList.map(_.asInstanceOf[IRecipe]) def getFilteredInputs(inputs: Iterable[ItemStack], outputSize: Double) = inputs.filter(input =>
val recipe = recipes.find(recipe => recipe.getRecipeOutput != null && recipe.getRecipeOutput.isItemEqual(stack)) input != null &&
val count = recipe.fold(0)(_.getRecipeOutput.stackSize) input.getItem != null &&
val ingredients = (recipe match { math.floor(input.stackSize / outputSize) > 0 &&
case Some(recipe: ShapedRecipes) => recipe.recipeItems.toIterable
case Some(recipe: ShapelessRecipes) => recipe.recipeItems.map(_.asInstanceOf[ItemStack])
case Some(recipe: ShapedOreRecipe) => resolveOreDictEntries(recipe.getInput)
case Some(recipe: ShapelessOreRecipe) => resolveOreDictEntries(recipe.getInput)
case _ => Iterable.empty
}).filter(ingredient => ingredient != null &&
// Strip out buckets, because those are returned when crafting, and // 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 // 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). // to make it output fluids into fluiducts or such, sorry).
!ingredient.getItem.isInstanceOf[ItemBucket]).toArray !input.getItem.isInstanceOf[ItemBucket]).toArray
def getOutputSize(recipe: IRecipe) =
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
}
// Avoid positive feedback loops. // Avoid positive feedback loops.
if (ingredients.exists(ingredient => ingredient.isItemEqual(stack))) { if (ingredients.exists(ingredient => ingredient.isItemEqual(stack))) {
return Array.empty return Array.empty