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.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.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.InternalError=Internal error, please see the log file. This is probably a bug.
oc:gui.Error.NoCPU=No CPU is installed in the computer.

View File

@ -117,7 +117,7 @@ end
function network.tcp.close(channel)
if internal.tcp.channels[channel] 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
internal.tcp.channels[channel] = {next = internal.tcp.freeCh}
internal.tcp.freeCh = channel

View File

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

View File

@ -3,6 +3,11 @@
# priority (i.e. included recipes simply replace the current definition for all
# 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("hardmode.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 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 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),
"DaKaTotal" ->(0.5, 0.7, 1.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().

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.RobotData
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.integration.Mods
import li.cil.oc.integration.util
@ -116,6 +117,9 @@ object EventHandler {
if (!Settings.get.pureIgnorePower && Settings.get.ignorePower) {
player.addChatMessage(Localization.Chat.WarningPower)
}
if (Recipes.hadErrors) {
player.addChatMessage(Localization.Chat.WarningRecipes)
}
ServerPacketSender.sendPetVisibility(None, Some(player))
// Do update check in local games and for OPs.
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 {
val list = mutable.LinkedHashMap.empty[ItemStack, String]
val oreDictEntries = mutable.LinkedHashMap.empty[String, ItemStack]
var hadErrors = false
def addBlock(instance: Block, name: String, oreDict: String = null) = {
Items.registerBlock(instance, name)
@ -211,43 +212,55 @@ object Recipes {
private def addRecipe(output: ItemStack, list: Config, name: String) = try {
if (list.hasPath(name)) {
val recipe = list.getConfig(name)
val recipeType = tryGetType(recipe)
try {
recipeType match {
case "shaped" => addShapedRecipe(output, recipe)
case "shapeless" => addShapelessRecipe(output, recipe)
case "furnace" => addFurnaceRecipe(output, recipe)
/* TODO GregTech
case "gt_assembler" =>
if (Mods.GregTech.isAvailable) {
addGTAssemblingMachineRecipe(output, recipe)
val value = list.getValue(name)
value.valueType match {
case ConfigValueType.OBJECT =>
val recipe = list.getConfig(name)
val recipeType = tryGetType(recipe)
try {
recipeType match {
case "shaped" => addShapedRecipe(output, recipe)
case "shapeless" => addShapelessRecipe(output, recipe)
case "furnace" => addFurnaceRecipe(output, recipe)
/* TODO GregTech
case "gt_assembler" =>
if (Mods.GregTech.isAvailable) {
addGTAssemblingMachineRecipe(output, recipe)
}
else {
OpenComputers.log.error(s"Skipping GregTech assembler recipe for '$name' because GregTech is not present, you will not be able to craft this item.")
hadErrors = true
}
*/
case 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'.")
hadErrors = true
}
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(s"Failed adding recipe for '$name', you will not be able to craft this item! The error was: Invalid recipe type '$other'.")
}
catch {
case e: RecipeException =>
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)
}
}
catch {
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}")
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 {
OpenComputers.log.info(s"No recipe for '$name', you will not be able to craft this item.")
hide(output)
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).")
hadErrors = true
}
}
catch {
case e: Throwable =>
OpenComputers.log.error(s"Failed adding recipe for '$name', you will not be able to craft this item!", e)
hide(output)
OpenComputers.log.error(s"Failed adding recipe for '$name', you will not be able to craft this item.", e)
hadErrors = true
}
private def addShapedRecipe(output: ItemStack, recipe: Config) {
@ -276,7 +289,6 @@ object Recipes {
if (input.size > 0 && output.stackSize > 0) {
GameRegistry.addRecipe(new ExtendedShapedOreRecipe(output, shape ++ input: _*))
}
else hide(output)
}
private def addShapelessRecipe(output: ItemStack, recipe: Config) {
@ -289,7 +301,6 @@ object Recipes {
if (input.size > 0 && output.stackSize > 0) {
GameRegistry.addRecipe(new ExtendedShapelessOreRecipe(output, input: _*))
}
else hide(output)
}
/* TODO GregTech

View File

@ -1,13 +1,5 @@
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.NamedBlock
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.ResultWrapper._
import net.minecraft.world.World
import net.minecraftforge.common.util.ForgeDirection
import scala.collection.convert.WrapAsScala._
object DriverExportBus extends driver.Block {
type ExportBusTile = appeng.api.parts.IPartHost
@ -98,11 +87,15 @@ object DriverExportBus extends driver.Block {
case 4 => 96
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)
var didSomething = false
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 =
if (export.getInstalledUpgrades(Upgrades.FUZZY) > 0)
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.vec.Cuboid6
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.api.Items
import li.cil.oc.client.renderer.block.Print
import li.cil.oc.common.block.Print
import li.cil.oc.common.item.data.PrintData
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.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.RenderBlocks
import net.minecraft.client.renderer.RenderGlobal
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.init.Blocks
@ -34,18 +25,58 @@ import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
import net.minecraft.util.MovingObjectPosition
import net.minecraft.util.Vec3
import net.minecraftforge.common.util.ForgeDirection
import org.lwjgl.opengl.GL11
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 data = new PrintData()
var boundsOff = ExtendedAABB.unitBounds
var boundsOn = ExtendedAABB.unitBounds
var state = false
var toggling = false // avoid infinite loops when updating neighbors
original.foreach(print => {
facing = print.facing
@ -74,8 +105,24 @@ class PrintPart(val original: Option[tileentity.Print] = None) extends SimpleBlo
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 strongPowerLevel(side: Int): Int = weakPowerLevel(side)
@ -96,22 +143,29 @@ class PrintPart(val original: Option[tileentity.Print] = None) extends SimpleBlo
def toggleState(): Unit = {
if (canToggle) {
toggling = true
state = !state
world.playSoundEffect(x + 0.5, y + 0.5, z + 0.5, "random.click", 0.3F, if (state) 0.6F else 0.5F)
world.notifyBlocksOfNeighborChange(x, y, z, tile.getBlockType)
world.markBlockForUpdate(x, y, z)
if (!world.isRemote) sendDescUpdate()
tile.partList.foreach {
case print: PrintPart if print != this => print.onNeighborChanged()
// Update slot info in tile... kinda meh, but works.
tile match {
case slotted: TSlottedTile =>
for (i <- 0 until slotted.v_partMap.length) {
if (slotted.v_partMap(i) == this)
slotted.v_partMap(i) = null
}
tile.bindPart(this)
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) {
scheduleTick(simpleBlock.tickRate(world))
}
toggling = false
}
}
def canToggle = {
def canToggle = !toggling && world != null && !world.isRemote && {
val toggled = new PrintPart()
toggled.facing = facing
toggled.data = data
@ -177,22 +231,33 @@ class PrintPart(val original: Option[tileentity.Print] = None) extends SimpleBlo
true
}
override def onPartChanged(part: TMultiPart): Unit = {
super.onPartChanged(part)
checkRedstone()
}
override def onNeighborChanged(): Unit = {
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 {
case print: PrintPart => powered || (print.state && print.data.emitRedstone)
case _ => powered
})
val newMaxValue = 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()
}
}
if (inner) 15 else ForgeDirection.VALID_DIRECTIONS.map(computeInput).max
}
protected def computeInput(side: ForgeDirection) = {
protected def computeInput(side: ForgeDirection): Int = {
val blockPos = BlockPosition(x, y, z).offset(side)
if (!world.blockExists(blockPos)) 0
else {

View File

@ -71,20 +71,30 @@ object ItemUtils {
}
def getIngredients(stack: ItemStack): Array[ItemStack] = try {
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) => 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 &&
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).
!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.
if (ingredients.exists(ingredient => ingredient.isItemEqual(stack))) {
return Array.empty