Moved NEI integration.

Fixed potential derpery when robots use some vanilla blocks.
Removed unnecessary mod interaction classes.
This commit is contained in:
Florian Nücke 2014-10-13 16:20:33 +02:00
parent 1f08bbb345
commit 8e6c97efcb
10 changed files with 202 additions and 208 deletions

View File

@ -9,7 +9,7 @@ import cpw.mods.fml.common.registry.GameRegistry
import li.cil.oc._
import li.cil.oc.common.block.SimpleBlock
import li.cil.oc.common.init.Items
import li.cil.oc.integration.util.GregTech
import li.cil.oc.integration.Mods
import li.cil.oc.integration.util.NEI
import li.cil.oc.util.Color
import net.minecraft.block.Block
@ -130,33 +130,40 @@ object Recipes {
case "shaped" => addShapedRecipe(output, recipe)
case "shapeless" => addShapelessRecipe(output, recipe)
case "furnace" => addFurnaceRecipe(output, recipe)
case "gt_assembler" => addGTAssemblingMachineRecipe(output, recipe)
case "gt_assembler" =>
if (Mods.GregTech.isAvailable) {
addGTAssemblingMachineRecipe(output, recipe)
}
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!")
hide(output)
}
case other =>
OpenComputers.log.warn("Failed adding recipe for '" + name + "', you will not be able to craft this item! The error was: Invalid recipe type '" + 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'.")
hide(output)
}
}
catch {
case e: RecipeException =>
OpenComputers.log.warn("Failed adding " + recipeType + " recipe for '" + name + "', you will not be able to craft this item! The error was: " + e.getMessage)
OpenComputers.log.warn(s"Failed adding $recipeType recipe for '$name', you will not be able to craft this item! The error was: ${e.getMessage}")
hide(output)
}
}
else {
OpenComputers.log.info("No recipe for '" + name + "', you will not be able to craft this item.")
OpenComputers.log.info(s"No recipe for '$name', you will not be able to craft this item.")
hide(output)
}
}
catch {
case e: Throwable =>
OpenComputers.log.error("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)
}
private def addShapedRecipe(output: ItemStack, recipe: Config) {
val rows = recipe.getList("input").unwrapped().map {
case row: java.util.List[AnyRef]@unchecked => row.map(parseIngredient)
case other => throw new RecipeException("Invalid row entry for shaped recipe (not a list: " + other + ").")
case other => throw new RecipeException(s"Invalid row entry for shaped recipe (not a list: $other).")
}
output.stackSize = tryGetCount(recipe)
@ -203,17 +210,17 @@ object Recipes {
case null => Array.empty[ItemStack]
case stack: ItemStack => Array(stack)
case name: String => Array(OreDictionary.getOres(name): _*)
case other => throw new RecipeException("Invalid ingredient type: " + other + ".")
case other => throw new RecipeException(s"Invalid ingredient type: $other.")
}
output.stackSize = tryGetCount(recipe)
if (inputs.size < 1 || inputs.size > 2) {
throw new RecipeException("Invalid recipe length: " + inputs.size + ", should be 1 or 2.")
throw new RecipeException(s"Invalid recipe length: ${inputs.size}, should be 1 or 2.")
}
val inputCount = recipe.getIntList("count")
if (inputCount.size() != inputs.size) {
throw new RecipeException("Ingredient and input count mismatch: " + inputs.size + " != " + inputCount.size + ".")
throw new RecipeException(s"Ingredient and input count mismatch: ${inputs.size} != ${inputCount.size}.")
}
val eu = recipe.getInt("eu")
@ -226,9 +233,9 @@ object Recipes {
for (input1 <- inputs(0)) {
if (inputs(1) != null) {
for (input2 <- inputs(1))
GregTech.addAssemblerRecipe(input1, input2, output, duration, eu)
gregtech.api.GregTech_API.sRecipeAdder.addAssemblerRecipe(input1, input2, output, duration, eu)
}
else GregTech.addAssemblerRecipe(input1, null, output, duration, eu)
else gregtech.api.GregTech_API.sRecipeAdder.addAssemblerRecipe(input1, null, output, duration, eu)
}
}
}
@ -253,7 +260,7 @@ object Recipes {
if (map.contains("oreDict")) {
map.get("oreDict") match {
case value: String => value
case other => throw new RecipeException("Invalid name in recipe (not a string: " + other + ").")
case other => throw new RecipeException(s"Invalid name in recipe (not a string: $other).")
}
}
else if (map.contains("item")) {
@ -261,10 +268,10 @@ object Recipes {
case name: String =>
findItem(name) match {
case Some(item: Item) => new ItemStack(item, 1, tryGetId(map))
case _ => throw new RecipeException("No item found with name '" + name + "'.")
case _ => throw new RecipeException(s"No item found with name '$name'.")
}
case id: Number => new ItemStack(validateItemId(id), 1, tryGetId(map))
case other => throw new RecipeException("Invalid item name in recipe (not a string: " + other + ").")
case other => throw new RecipeException(s"Invalid item name in recipe (not a string: $other).")
}
}
else if (map.contains("block")) {
@ -272,10 +279,10 @@ object Recipes {
case name: String =>
findBlock(name) match {
case Some(block: Block) => new ItemStack(block, 1, tryGetId(map))
case _ => throw new RecipeException("No block found with name '" + name + "'.")
case _ => throw new RecipeException(s"No block found with name '$name'.")
}
case id: Number => new ItemStack(validateBlockId(id), 1, tryGetId(map))
case other => throw new RecipeException("Invalid block name (not a string: " + other + ").")
case other => throw new RecipeException(s"Invalid block name (not a string: $other).")
}
}
else throw new RecipeException("Invalid ingredient type (no oreDict, item or block entry).")
@ -288,11 +295,11 @@ object Recipes {
case _ =>
findBlock(name) match {
case Some(block: Block) => new ItemStack(block, 1, 0)
case _ => throw new RecipeException("No ore dictionary entry, item or block found for ingredient with name '" + name + "'.")
case _ => throw new RecipeException(s"No ore dictionary entry, item or block found for ingredient with name '$name'.")
}
}
}
case other => throw new RecipeException("Invalid ingredient type (not a map or string): " + other)
case other => throw new RecipeException(s"Invalid ingredient type (not a map or string): $other")
}
private def findItem(name: String) = Item.itemRegistry.find {
@ -320,14 +327,14 @@ object Recipes {
private def validateBlockId(id: Number) = {
val index = id.intValue
val block = Block.getBlockById(index)
if (block == null) throw new RecipeException("Invalid block ID: " + index)
if (block == null) throw new RecipeException(s"Invalid block ID: $index")
block
}
private def validateItemId(id: Number) = {
val index = id.intValue
val item = Item.getItemById(index)
if (item == null) throw new RecipeException("Invalid item ID: " + index)
if (item == null) throw new RecipeException(s"Invalid item ID: $index")
item
}

View File

@ -0,0 +1,109 @@
package li.cil.oc.integration.nei
import java.util
import codechicken.lib.gui.GuiDraw
import codechicken.nei.PositionedStack
import codechicken.nei.recipe.GuiRecipe
import codechicken.nei.recipe.IUsageHandler
import com.google.common.base.Strings
import li.cil.oc.api.driver.EnvironmentAware
import li.cil.oc.server.driver.Registry
import li.cil.oc.server.machine.Callbacks
import net.minecraft.client.gui.inventory.GuiContainer
import net.minecraft.inventory.Container
import net.minecraft.item.ItemStack
import net.minecraft.util.EnumChatFormatting
import scala.collection.convert.WrapAsScala._
class DocumentationHandler(val pages: Option[Array[String]]) extends IUsageHandler {
def this() = this(None)
private val DocPattern = """^function(\([^)]*\)[^-]*) -- (.*)$""".r
private val VexPattern = """^function(\([^)]*\)[^-]*); (.*)$""".r
private def wrap(line: String, width: Int) = GuiDraw.fontRenderer.listFormattedStringToWidth(line, width)
override def getUsageHandler(input: String, ingredients: AnyRef*): IUsageHandler = {
if (input == "item") {
ingredients.collect {
case stack: ItemStack if stack.getItem != null =>
def getCallbacks(env: Class[_]) = if (env != null) {
Callbacks.fromClass(env).map {
case (name, callback) =>
val doc = callback.annotation.doc
if (Strings.isNullOrEmpty(doc)) name
else {
val (signature, documentation) = doc match {
case DocPattern(head, tail) => (name + head, tail)
case VexPattern(head, tail) => (name + head, tail)
case _ => (name, doc)
}
wrap(signature, 160).map(EnumChatFormatting.BLACK.toString + _).mkString("\n") +
EnumChatFormatting.RESET + "\n" +
wrap(documentation, 152).map(" " + _).mkString("\n")
}
}
}
else Seq.empty
val callbacks = Option(Registry.driverFor(stack)) match {
case Some(driver: EnvironmentAware) =>
getCallbacks(driver.providedEnvironment(stack))
case _ => Registry.blocks.collect {
case driver: EnvironmentAware => driver.providedEnvironment(stack)
}.filter(_ != null).map(getCallbacks).flatten
}
if (callbacks.size > 0) {
val fullDocumentation = callbacks.toArray.sorted.mkString("\n\n")
val pages = fullDocumentation.lines.grouped(12).map(_.mkString("\n")).toArray
return new DocumentationHandler(Option(pages))
}
}
}
this
}
override def getRecipeName = "OpenComputers API"
override def recipiesPerPage = 1
override def numRecipes = pages.fold(0)(_.length)
override def drawBackground(recipe: Int) {}
override def drawForeground(recipe: Int) {
pages match {
case Some(data) =>
for ((text, line) <- data(recipe).lines.zipWithIndex) {
GuiDraw.drawString(text, 4, 4 + line * 10, 0x333333, false)
}
case _ =>
}
}
override def getIngredientStacks(recipe: Int) = new util.ArrayList[PositionedStack]()
override def getOtherStacks(recipe: Int) = new util.ArrayList[PositionedStack]()
override def getResultStack(recipe: Int) = null
override def onUpdate() {}
override def hasOverlay(gui: GuiContainer, container: Container, recipe: Int) = false
override def getOverlayHandler(gui: GuiContainer, recipe: Int) = null
override def getOverlayRenderer(gui: GuiContainer, recipe: Int) = null
override def handleTooltip(gui: GuiRecipe, tooltip: util.List[String], recipe: Int) = tooltip
override def handleItemTooltip(gui: GuiRecipe, stack: ItemStack, tooltip: util.List[String], recipe: Int) = tooltip
override def keyTyped(gui: GuiRecipe, char: Char, code: Int, recipe: Int) = false
override def mouseClicked(gui: GuiRecipe, x: Int, y: Int) = false
}

View File

@ -0,0 +1,22 @@
package li.cil.oc.integration.nei
import codechicken.nei.api.API
import codechicken.nei.api.IConfigureNEI
import cpw.mods.fml.relauncher.Side
import cpw.mods.fml.relauncher.SideOnly
import li.cil.oc.integration.util.NEI
import net.minecraft.item.ItemStack
@SideOnly(Side.CLIENT)
class NEIOpenComputersConfig extends IConfigureNEI {
override def getName = "OpenComputers"
override def getVersion = "1.0.0"
override def loadConfig() {
API.registerUsageHandler(new DocumentationHandler())
for (block <- NEI.hiddenBlocks) {
API.hideItem(new ItemStack(block))
}
}
}

View File

@ -2,13 +2,14 @@ package li.cil.oc.integration.ue
import cpw.mods.fml.common.eventhandler.SubscribeEvent
import li.cil.oc.api.event.RobotUsedToolEvent
import li.cil.oc.integration.util.UniversalElectricity
import net.minecraftforge.common.util.ForgeDirection
import universalelectricity.compatibility.Compatibility
object EventHandlerUniversalElectricity {
@SubscribeEvent
def onRobotApplyDamageRate(e: RobotUsedToolEvent.ApplyDamageRate) {
if (UniversalElectricity.isEnergyItem(e.toolAfterUse)) {
val damage = UniversalElectricity.getEnergyInItem(e.toolBeforeUse) - UniversalElectricity.getEnergyInItem(e.toolAfterUse)
if (Compatibility.isHandler(e.toolAfterUse, ForgeDirection.UNKNOWN)) {
val damage = Compatibility.getEnergyItem(e.toolBeforeUse) - Compatibility.getEnergyItem(e.toolAfterUse)
if (damage > 0) {
val actualDamage = damage * e.getDamageRate
val repairedDamage =
@ -16,7 +17,7 @@ object EventHandlerUniversalElectricity {
damage - math.floor(actualDamage).toLong
else
damage - math.ceil(actualDamage).toLong
UniversalElectricity.chargeItem(e.toolAfterUse, repairedDamage)
Compatibility.chargeItem(e.toolAfterUse, repairedDamage, true)
}
}
}

View File

@ -1,25 +0,0 @@
package li.cil.oc.integration.util
import net.minecraft.item.ItemStack
object GregTech {
private val (recipeAdder, addAssemblerRecipe) = try {
val api = Class.forName("gregtech.api.GregTech_API")
val recipeAdder = api.getField("sRecipeAdder").get(null)
val addAssemblerRecipe = recipeAdder.getClass.getMethod("addAssemblerRecipe", classOf[ItemStack], classOf[ItemStack], classOf[ItemStack], classOf[Int], classOf[Int])
(Option(recipeAdder), Option(addAssemblerRecipe))
}
catch {
case _: Throwable => (None, None)
}
def available = recipeAdder.isDefined && addAssemblerRecipe.isDefined
def addAssemblerRecipe(input1: ItemStack, input2: ItemStack, output: ItemStack, duration: Int, euPerTick: Int) {
(recipeAdder, addAssemblerRecipe) match {
case (Some(instance), Some(method)) => method.invoke(instance, input1, input2, output, Int.box(duration), Int.box(euPerTick))
case _ =>
}
}
}

View File

@ -1,20 +0,0 @@
package li.cil.oc.integration.util
import li.cil.oc.integration.Mods
import net.minecraft.item.ItemStack
object IndustrialCraft2 {
private lazy val miningLaser = try {
val clazz = Class.forName("ic2.core.Ic2Items")
val field = clazz.getField("miningLaser")
Option(field.get(null).asInstanceOf[ItemStack])
}
catch {
case _: Throwable => None
}
def isMiningLaser(stack: ItemStack) = stack != null && Mods.IndustrialCraft2API.isAvailable && (miningLaser match {
case Some(laser) => laser.getItem == stack.getItem
case _ => false
})
}

View File

@ -1,28 +1,11 @@
package li.cil.oc.integration.util
import java.util
import codechicken.lib.gui.GuiDraw
import codechicken.nei.LayoutManager
import codechicken.nei.PositionedStack
import codechicken.nei.api.API
import codechicken.nei.api.IConfigureNEI
import codechicken.nei.recipe.GuiRecipe
import codechicken.nei.recipe.IUsageHandler
import com.google.common.base.Strings
import cpw.mods.fml.relauncher.Side
import cpw.mods.fml.relauncher.SideOnly
import li.cil.oc.api.driver.EnvironmentAware
import li.cil.oc.integration.Mods
import li.cil.oc.server.driver.Registry
import li.cil.oc.server.machine.Callbacks
import net.minecraft.block.Block
import net.minecraft.client.gui.inventory.GuiContainer
import net.minecraft.inventory.Container
import net.minecraft.item.ItemStack
import net.minecraft.util.EnumChatFormatting
import scala.collection.convert.WrapAsScala._
import scala.collection.mutable
object NEI {
@ -45,107 +28,3 @@ object NEI {
def hide(block: Block): Unit = if (Mods.NotEnoughItems.isAvailable) hiddenBlocks += block
}
@SideOnly(Side.CLIENT)
class NEIOpenComputersConfig extends IConfigureNEI {
override def getName = "OpenComputers"
override def getVersion = "1.0.0"
override def loadConfig() {
API.registerUsageHandler(new DocumentationHandler())
for (block <- NEI.hiddenBlocks) {
API.hideItem(new ItemStack(block))
}
}
}
class DocumentationHandler(val pages: Option[Array[String]]) extends IUsageHandler {
def this() = this(None)
private val DocPattern = """^function(\([^)]*\)[^-]*) -- (.*)$""".r
private val VexPattern = """^function(\([^)]*\)[^-]*); (.*)$""".r
private def wrap(line: String, width: Int) = GuiDraw.fontRenderer.listFormattedStringToWidth(line, width)
override def getUsageHandler(input: String, ingredients: AnyRef*): IUsageHandler = {
if (input == "item") {
ingredients.collect {
case stack: ItemStack if stack.getItem != null =>
def getCallbacks(env: Class[_]) = if (env != null) {
Callbacks.fromClass(env).map {
case (name, callback) =>
val doc = callback.annotation.doc
if (Strings.isNullOrEmpty(doc)) name
else {
val (signature, documentation) = doc match {
case DocPattern(head, tail) => (name + head, tail)
case VexPattern(head, tail) => (name + head, tail)
case _ => (name, doc)
}
wrap(signature, 160).map(EnumChatFormatting.BLACK.toString + _).mkString("\n") +
EnumChatFormatting.RESET + "\n" +
wrap(documentation, 152).map(" " + _).mkString("\n")
}
}
}
else Seq.empty
val callbacks = Option(Registry.driverFor(stack)) match {
case Some(driver: EnvironmentAware) =>
getCallbacks(driver.providedEnvironment(stack))
case _ => Registry.blocks.collect {
case driver: EnvironmentAware => driver.providedEnvironment(stack)
}.filter(_ != null).map(getCallbacks).flatten
}
if (callbacks.size > 0) {
val fullDocumentation = callbacks.toArray.sorted.mkString("\n\n")
val pages = fullDocumentation.lines.grouped(12).map(_.mkString("\n")).toArray
return new DocumentationHandler(Option(pages))
}
}
}
this
}
override def getRecipeName = "OpenComputers API"
override def recipiesPerPage = 1
override def numRecipes = pages.fold(0)(_.length)
override def drawBackground(recipe: Int) {}
override def drawForeground(recipe: Int) {
pages match {
case Some(data) =>
for ((text, line) <- data(recipe).lines.zipWithIndex) {
GuiDraw.drawString(text, 4, 4 + line * 10, 0x333333, false)
}
case _ =>
}
}
override def getIngredientStacks(recipe: Int) = new util.ArrayList[PositionedStack]()
override def getOtherStacks(recipe: Int) = new util.ArrayList[PositionedStack]()
override def getResultStack(recipe: Int) = null
override def onUpdate() {}
override def hasOverlay(gui: GuiContainer, container: Container, recipe: Int) = false
override def getOverlayHandler(gui: GuiContainer, recipe: Int) = null
override def getOverlayRenderer(gui: GuiContainer, recipe: Int) = null
override def handleTooltip(gui: GuiRecipe, tooltip: util.List[String], recipe: Int) = tooltip
override def handleItemTooltip(gui: GuiRecipe, stack: ItemStack, tooltip: util.List[String], recipe: Int) = tooltip
override def keyTyped(gui: GuiRecipe, char: Char, code: Int, recipe: Int) = false
override def mouseClicked(gui: GuiRecipe, x: Int, y: Int) = false
}

View File

@ -1,13 +0,0 @@
package li.cil.oc.integration.util
import net.minecraft.item.ItemStack
import net.minecraftforge.common.util.ForgeDirection
import universalelectricity.compatibility.Compatibility
object UniversalElectricity {
def isEnergyItem(stack: ItemStack) = Compatibility.isHandler(stack.getItem, ForgeDirection.UNKNOWN)
def getEnergyInItem(stack: ItemStack) = Compatibility.getEnergyItem(stack)
def chargeItem(stack: ItemStack, value: Double) = Compatibility.chargeItem(stack, value, true)
}

View File

@ -10,19 +10,27 @@ object WirelessRedstone {
def isAvailable = systems.size > 0
def addReceiver(rs: RedstoneWireless) {
systems.foreach(_.addReceiver(rs))
systems.foreach(system => try system.addReceiver(rs) catch {
case _: Throwable => // Ignore
})
}
def removeReceiver(rs: RedstoneWireless) {
systems.foreach(_.removeReceiver(rs))
systems.foreach(system => try system.removeReceiver(rs) catch {
case _: Throwable => // Ignore
})
}
def updateOutput(rs: RedstoneWireless) {
systems.foreach(_.updateOutput(rs))
systems.foreach(system => try system.updateOutput(rs) catch {
case _: Throwable => // Ignore
})
}
def removeTransmitter(rs: RedstoneWireless) {
systems.foreach(_.removeTransmitter(rs))
systems.foreach(system => try system.removeTransmitter(rs) catch {
case _: Throwable => // Ignore
})
}
def getInput(rs: RedstoneWireless) = systems.exists(_.getInput(rs))

View File

@ -18,15 +18,19 @@ import net.minecraft.entity.Entity
import net.minecraft.entity.EntityLivingBase
import net.minecraft.entity.IMerchant
import net.minecraft.entity.item.EntityItem
import net.minecraft.entity.item.EntityMinecartHopper
import net.minecraft.entity.passive.EntityHorse
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.entity.player.EntityPlayer.EnumStatus
import net.minecraft.init.Blocks
import net.minecraft.init.Items
import net.minecraft.inventory.IInventory
import net.minecraft.item.ItemBlock
import net.minecraft.item.ItemStack
import net.minecraft.network.NetHandlerPlayServer
import net.minecraft.potion.PotionEffect
import net.minecraft.server.MinecraftServer
import net.minecraft.tileentity._
import net.minecraft.util._
import net.minecraft.world.WorldServer
import net.minecraftforge.common.ForgeHooks
@ -489,4 +493,26 @@ class Player(val robot: tileentity.Robot) extends FakePlayer(robot.world.asInsta
override def sleepInBedAt(x: Int, y: Int, z: Int) = EnumStatus.OTHER_PROBLEM
override def addChatMessage(message: IChatComponent) {}
override def displayGUIWorkbench(x: Int, y: Int, z: Int) {}
override def displayGUIEnchantment(x: Int, y: Int, z: Int, idk: String) {}
override def displayGUIAnvil(x: Int, y: Int, z: Int) {}
override def displayGUIChest(inventory: IInventory) {}
override def displayGUIHopperMinecart(cart: EntityMinecartHopper) {}
override def displayGUIHorse(horse: EntityHorse, inventory: IInventory) {}
override def func_146104_a(tileEntity: TileEntityBeacon) {}
override def func_146098_a(tileEntity: TileEntityBrewingStand) {}
override def func_146102_a(tileEntity: TileEntityDispenser) {}
override def func_146101_a(tileEntity: TileEntityFurnace) {}
override def func_146093_a(tileEntity: TileEntityHopper) {}
}