diff --git a/src/main/resources/application.conf b/src/main/resources/application.conf index 699d64d80..a6ae0505f 100644 --- a/src/main/resources/application.conf +++ b/src/main/resources/application.conf @@ -908,6 +908,46 @@ opencomputers { relayAmountUpgrade: 1 } + # 3D printer related stuff. + printer { + # The maximum number of shape for a state of a 3D print allowed. This is + # for the individual states (off and on), so it is possible to have up to + # this many shapes *per state* (the reasoning being that only one state + # will ever be visible at a time). + maxShapes: 24 + + # How much of the material used to print a model is refunded when using + # the model to refuel a printer. This the value the original material + # cost is multiplied with, so 1 is a full refund, 0 disables the + # functionality (won't be able to put prints into the material input). + recycleRate: 0.75 + + # Whether Chamelium is edible or not. When eaten, it gives a (short) + # invisibility buff, and (slightly longer) blindness debuff. + chameliumEdible: true + + # The maximum light level a printed block can emit. This defaults to + # a value similar to that of a redstone torch, because by default the + # material prints are made of contains redstone, but no glowstone. + # Prints' light level can further be boosted by crafting them with + # glowstone dust. This is merely the maximum light level that can be + # achieved directly when printing them. + maxBaseLightLevel: 8 + + # The extra material cost involved for printing a model with a customized + # redstone output, i.e. something in [1, 14]. + customRedstoneCost: 300 + + # The amount by which a printers material buffer gets filled for a single + # chamelium. Tweak this if you think printing is too cheap or expensive. + materialValue: 2000 + + # The amount by which a printers ink buffer gets filled for a single + # cartridge. Tweak this if you think printing is too cheap or expensive. + # Note: the amount a single dye adds is this divided by 10. + inkValue: 50000 + } + # Other settings that you might find useful to tweak. misc { # The maximum width of multi-block screens, in blocks. @@ -1029,30 +1069,6 @@ opencomputers { # avoid issues with computers timing out, but can also lead to higher # server load. AGAIN, USE WITH CARE! threadPriority: -1 - - # The maximum number of shape for a state of a 3D print allowed. This is - # for the individual states (off and on), so it is possible to have up to - # this many shapes *per state* (the reasoning being that only one state - # will ever be visible at a time). - maxPrinterShapes: 24 - - # How much of the material used to print a model is refunded when using - # the model to refuel a printer. This the value the original material - # cost is multiplied with, so 1 is a full refund, 0 disables the - # functionality (won't be able to put prints into the material input). - printRecycleRate: 0.75 - - # Whether Chamelium is edible or not. When eaten, it gives a (short) - # invisibility buff, and (slightly longer) blindness debuff. - chameliumEdible: true - - # The maximum light level a printed block can emit. This defaults to - # a value similar to that of a redstone torch, because by default the - # material prints are made of contains redstone, but no glowstone. - # Prints' light level can further be boosted by crafting them with - # glowstone dust. This is merely the maximum light level that can be - # achieved directly when printing them. - maxPrintLightLevel: 8 } # Settings for mod integration (the mod previously known as OpenComponents). diff --git a/src/main/scala/li/cil/oc/Settings.scala b/src/main/scala/li/cil/oc/Settings.scala index 122fc4a3e..9baf49ed9 100644 --- a/src/main/scala/li/cil/oc/Settings.scala +++ b/src/main/scala/li/cil/oc/Settings.scala @@ -294,10 +294,16 @@ class Settings(val config: Config) { val presentChance = config.getDouble("misc.presentChance") max 0 min 1 val assemblerBlacklist = config.getStringList("misc.assemblerBlacklist") val threadPriority = config.getInt("misc.threadPriority") - val maxPrintComplexity = config.getInt("misc.maxPrinterShapes") - val printRecycleRate = config.getDouble("misc.printRecycleRate") - val chameliumEdible = config.getBoolean("misc.chameliumEdible") - val maxPrintLightLevel = config.getInt("misc.maxPrintLightLevel") max 0 min 15 + + // ----------------------------------------------------------------------- // + // printer + val maxPrintComplexity = config.getInt("printer.maxShapes") + val printRecycleRate = config.getDouble("printer.recycleRate") + val chameliumEdible = config.getBoolean("printer.chameliumEdible") + val maxPrintLightLevel = config.getInt("printer.maxBaseLightLevel") max 0 min 15 + val printCustomRedstone = config.getInt("printer.customRedstoneCost") max 0 + val printMaterialValue = config.getInt("printer.materialValue") max 0 + val printInkValue = config.getInt("printer.inkValue") max 0 // ----------------------------------------------------------------------- // // integration diff --git a/src/main/scala/li/cil/oc/common/item/Delegate.scala b/src/main/scala/li/cil/oc/common/item/Delegate.scala index cae96216c..85163c0f6 100644 --- a/src/main/scala/li/cil/oc/common/item/Delegate.scala +++ b/src/main/scala/li/cil/oc/common/item/Delegate.scala @@ -67,6 +67,10 @@ trait Delegate { def color(stack: ItemStack, pass: Int) = 0xFFFFFF + def getContainerItem(stack: ItemStack): ItemStack = null + + def hasContainerItem(stack: ItemStack): Boolean = false + def displayName(stack: ItemStack): Option[String] = None @SideOnly(Side.CLIENT) diff --git a/src/main/scala/li/cil/oc/common/item/Delegator.scala b/src/main/scala/li/cil/oc/common/item/Delegator.scala index 6d9677ad4..2a29da281 100644 --- a/src/main/scala/li/cil/oc/common/item/Delegator.scala +++ b/src/main/scala/li/cil/oc/common/item/Delegator.scala @@ -94,6 +94,18 @@ class Delegator extends Item { case _ => super.getColorFromItemStack(stack, pass) } + override def getContainerItem(stack: ItemStack): ItemStack = + Delegator.subItem(stack) match { + case Some(subItem) => subItem.getContainerItem(stack) + case _ => super.getContainerItem(stack) + } + + override def hasContainerItem(stack: ItemStack): Boolean = + Delegator.subItem(stack) match { + case Some(subItem) => subItem.hasContainerItem(stack) + case _ => super.hasContainerItem(stack) + } + override def getChestGenBase(chest: ChestGenHooks, rnd: Random, original: WeightedRandomChestContent) = original override def doesSneakBypassUse(world: World, pos: BlockPos, player: EntityPlayer) = { diff --git a/src/main/scala/li/cil/oc/common/item/InkCartridge.scala b/src/main/scala/li/cil/oc/common/item/InkCartridge.scala index 363af10c2..8563ab588 100644 --- a/src/main/scala/li/cil/oc/common/item/InkCartridge.scala +++ b/src/main/scala/li/cil/oc/common/item/InkCartridge.scala @@ -1,5 +1,17 @@ package li.cil.oc.common.item +import li.cil.oc.api +import net.minecraft.item.ItemStack + class InkCartridge(val parent: Delegator) extends Delegate { override def maxStackSize = 1 + + override def getContainerItem(stack: ItemStack): ItemStack = { + if (api.Items.get(stack) == api.Items.get("inkCartridge")) + api.Items.get("inkCartridgeEmpty").createItemStack(1) + else + super.getContainerItem(stack) + } + + override def hasContainerItem(stack: ItemStack): Boolean = true } diff --git a/src/main/scala/li/cil/oc/common/item/data/PrintData.scala b/src/main/scala/li/cil/oc/common/item/data/PrintData.scala index 5587db9ee..9c8d5de60 100644 --- a/src/main/scala/li/cil/oc/common/item/data/PrintData.scala +++ b/src/main/scala/li/cil/oc/common/item/data/PrintData.scala @@ -1,7 +1,10 @@ package li.cil.oc.common.item.data import li.cil.oc.Constants +import li.cil.oc.Settings import li.cil.oc.api +import li.cil.oc.util.Color +import li.cil.oc.util.ExtendedAABB._ import li.cil.oc.util.ExtendedNBT._ import net.minecraft.item.ItemStack import net.minecraft.nbt.NBTTagCompound @@ -103,6 +106,46 @@ object PrintData { volume } + def computeCosts(data: PrintData) = { + val totalVolume = data.stateOn.foldLeft(0)((acc, shape) => acc + shape.bounds.volume) + data.stateOff.foldLeft(0)((acc, shape) => acc + shape.bounds.volume) + val totalSurface = data.stateOn.foldLeft(0)((acc, shape) => acc + shape.bounds.surface) + data.stateOff.foldLeft(0)((acc, shape) => acc + shape.bounds.surface) + + if (totalVolume > 0) { + val baseMaterialRequired = (totalVolume / 2) max 1 + val materialRequired = + if (data.redstoneLevel > 0 && data.redstoneLevel < 15) baseMaterialRequired + Settings.get.printCustomRedstone + else baseMaterialRequired + val inkRequired = (totalSurface / 6) max 1 + + Option((materialRequired, inkRequired)) + } + else None + } + + private val materialPerItem = Settings.get.printMaterialValue + private val inkPerCartridge = Settings.get.printInkValue + + def materialValue(stack: ItemStack) = { + if (api.Items.get(stack) == api.Items.get("chamelium")) + materialPerItem + else if (api.Items.get(stack) == api.Items.get("print")) { + val data = new PrintData(stack) + computeCosts(data) match { + case Some((materialRequired, inkRequired)) => (materialRequired * Settings.get.printRecycleRate).toInt + case _ => 0 + } + } + else 0 + } + + def inkValue(stack: ItemStack) = { + if (api.Items.get(stack) == api.Items.get("inkCartridge")) + inkPerCartridge + else if (Color.isDye(stack)) + inkPerCartridge / 10 + else 0 + } + def nbtToShape(nbt: NBTTagCompound): Shape = { val aabb = if (nbt.hasKey("minX")) { diff --git a/src/main/scala/li/cil/oc/common/tileentity/Printer.scala b/src/main/scala/li/cil/oc/common/tileentity/Printer.scala index 285facf1e..622cd561f 100644 --- a/src/main/scala/li/cil/oc/common/tileentity/Printer.scala +++ b/src/main/scala/li/cil/oc/common/tileentity/Printer.scala @@ -10,7 +10,6 @@ import li.cil.oc.api.machine.Context import li.cil.oc.api.network._ import li.cil.oc.common.item.data.PrintData import li.cil.oc.server.{PacketSender => ServerPacketSender} -import li.cil.oc.util.ExtendedAABB._ import li.cil.oc.util.ExtendedNBT._ import li.cil.oc.util.ItemUtils import net.minecraft.inventory.ISidedInventory @@ -39,9 +38,6 @@ class Printer extends traits.Environment with traits.Inventory with traits.Rotat var totalRequiredEnergy = 0.0 var requiredEnergy = 0.0 - val materialPerItem = 2000 - val inkPerCartridge = 50000 - val slotMaterial = 0 val slotInk = 1 val slotOutput = 2 @@ -201,34 +197,6 @@ class Printer extends traits.Environment with traits.Inventory with traits.Rotat // ----------------------------------------------------------------------- // - def computeCosts(data: PrintData) = { - val totalVolume = data.stateOn.foldLeft(0)((acc, shape) => acc + shape.bounds.volume) + data.stateOff.foldLeft(0)((acc, shape) => acc + shape.bounds.volume) - val totalSurface = data.stateOn.foldLeft(0)((acc, shape) => acc + shape.bounds.surface) + data.stateOff.foldLeft(0)((acc, shape) => acc + shape.bounds.surface) - - if (totalVolume > 0) { - val materialRequired = (totalVolume / 2) max 1 - val inkRequired = (totalSurface / 6) max 1 - - Option((materialRequired, inkRequired)) - } - else None - } - - def materialValue(stack: ItemStack) = { - if (api.Items.get(stack) == api.Items.get("chamelium")) - materialPerItem - else if (api.Items.get(stack) == api.Items.get("print")) { - val data = new PrintData(stack) - computeCosts(data) match { - case Some((materialRequired, inkRequired)) => (materialRequired * Settings.get.printRecycleRate).toInt - case _ => 0 - } - } - else 0 - } - - // ----------------------------------------------------------------------- // - override def canUpdate = isServer override def updateEntity() { @@ -241,7 +209,7 @@ class Printer extends traits.Environment with traits.Inventory with traits.Rotat } if (isActive && output.isEmpty && canMergeOutput) { - computeCosts(data) match { + PrintData.computeCosts(data) match { case Some((materialRequired, inkRequired)) => totalRequiredEnergy = Settings.get.printCost requiredEnergy = totalRequiredEnergy @@ -282,7 +250,7 @@ class Printer extends traits.Environment with traits.Inventory with traits.Rotat ServerPacketSender.sendPrinting(this, have > 0.5 && output.isDefined) } - val inputValue = materialValue(getStackInSlot(slotMaterial)) + val inputValue = PrintData.materialValue(getStackInSlot(slotMaterial)) if (inputValue > 0 && maxAmountMaterial - amountMaterial >= inputValue) { val material = decrStackSize(slotMaterial, 1) if (material != null) { @@ -290,10 +258,14 @@ class Printer extends traits.Environment with traits.Inventory with traits.Rotat } } - if (maxAmountInk - amountInk >= inkPerCartridge) { - if (api.Items.get(getStackInSlot(slotInk)) == api.Items.get("inkCartridge")) { - setInventorySlotContents(slotInk, api.Items.get("inkCartridgeEmpty").createItemStack(1)) - amountInk += inkPerCartridge + val inkValue = PrintData.inkValue(getStackInSlot(slotInk)) + if (inkValue > 0 && maxAmountInk - amountInk >= inkValue) { + val material = decrStackSize(slotInk, 1) + if (material != null) { + amountInk += inkValue + if (material.getItem.hasContainerItem(material)) { + setInventorySlotContents(slotInk, material.getItem.getContainerItem(material)) + } } } } @@ -345,9 +317,9 @@ class Printer extends traits.Environment with traits.Inventory with traits.Rotat override def isItemValidForSlot(slot: Int, stack: ItemStack) = if (slot == slotMaterial) - materialValue(stack) > 0 + PrintData.materialValue(stack) > 0 else if (slot == slotInk) - api.Items.get(stack) == api.Items.get("inkCartridge") + PrintData.inkValue(stack) > 0 else false // ----------------------------------------------------------------------- //