mirror of
https://github.com/MightyPirates/OpenComputers.git
synced 2025-09-13 17:28:52 -04:00
Printer block to allow printing 3d prints.
This commit is contained in:
parent
bb3456d86e
commit
1d7b6caa6f
@ -729,6 +729,11 @@ opencomputers {
|
||||
# Energy it costs to re-program an EEPROM. This is deliberately
|
||||
# expensive, to discourage frequent re-writing of EEPROMs.
|
||||
eepromWrite: 50
|
||||
|
||||
# How much energy is required per shape in a 3D print. With the
|
||||
# default of 200 for example, it will take 1600 energy to print a
|
||||
# block with 8 shapes in it.
|
||||
printerShape: 200
|
||||
}
|
||||
|
||||
# The rate at which different blocks accept external power. All of these
|
||||
@ -1011,6 +1016,12 @@ opencomputers {
|
||||
# format 'itemid@damage', were the damage is optional.
|
||||
# Examples: 'OpenComputers:case3', 'minecraft:stonebrick@1'
|
||||
assemblerBlacklist: []
|
||||
|
||||
# The maximum number of shape for a single 3D print allowed. This is for
|
||||
# the sum of shapes in both states (off and on), so e.g. with the default
|
||||
# of 32 you can use 10 shapes for the off state and 22 for the on state
|
||||
# at maximum.
|
||||
maxPrinterShapes: 32
|
||||
}
|
||||
|
||||
# Settings for mod integration (the mod previously known as OpenComponents).
|
||||
|
BIN
src/main/resources/assets/opencomputers/textures/gui/printer.png
Normal file
BIN
src/main/resources/assets/opencomputers/textures/gui/printer.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 634 B |
Binary file not shown.
After Width: | Height: | Size: 189 B |
@ -192,6 +192,7 @@ class Settings(val config: Config) {
|
||||
val chunkloaderCost = config.getDouble("power.cost.chunkloaderCost") max 0
|
||||
val pistonCost = config.getDouble("power.cost.pistonPush") max 0
|
||||
val eepromWriteCost = config.getDouble("power.cost.eepromWrite") max 0
|
||||
val printShapeCost = config.getDouble("power.cost.printerShape") max 0
|
||||
|
||||
// power.rate
|
||||
val accessPointRate = config.getDouble("power.rate.accessPoint") max 0
|
||||
@ -290,6 +291,7 @@ class Settings(val config: Config) {
|
||||
val databaseEntriesPerTier = Array(9, 25, 81) // Not configurable because of GUI design.
|
||||
val presentChance = config.getDouble("misc.presentChance") max 0 min 1
|
||||
val assemblerBlacklist = config.getStringList("misc.assemblerBlacklist")
|
||||
val maxPrintComplexity = config.getInt("misc.maxPrinterShapes")
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
// integration
|
||||
|
@ -32,6 +32,8 @@ object GuiHandler extends CommonGuiHandler {
|
||||
new gui.Disassembler(player.inventory, t)
|
||||
case t: tileentity.DiskDrive if id == GuiType.DiskDrive.id =>
|
||||
new gui.DiskDrive(player.inventory, t)
|
||||
case t: tileentity.Printer if id == GuiType.Printer.id =>
|
||||
new gui.Printer(player.inventory, t)
|
||||
case t: tileentity.Raid if id == GuiType.Raid.id =>
|
||||
new gui.Raid(player.inventory, t)
|
||||
case t: tileentity.RobotProxy if id == GuiType.Robot.id =>
|
||||
|
@ -25,6 +25,8 @@ object Textures {
|
||||
val guiDisassembler = new ResourceLocation(Settings.resourceDomain, "textures/gui/disassembler.png")
|
||||
val guiDrone = new ResourceLocation(Settings.resourceDomain, "textures/gui/drone.png")
|
||||
val guiKeyboardMissing = new ResourceLocation(Settings.resourceDomain, "textures/gui/keyboard_missing.png")
|
||||
val guiPrinter = new ResourceLocation(Settings.resourceDomain, "textures/gui/printer.png")
|
||||
val guiPrinterProgress = new ResourceLocation(Settings.resourceDomain, "textures/gui/printer_progress.png")
|
||||
val guiRaid = new ResourceLocation(Settings.resourceDomain, "textures/gui/raid.png")
|
||||
val guiRange = new ResourceLocation(Settings.resourceDomain, "textures/gui/range.png")
|
||||
val guiRobot = new ResourceLocation(Settings.resourceDomain, "textures/gui/robot.png")
|
||||
|
66
src/main/scala/li/cil/oc/client/gui/Printer.scala
Normal file
66
src/main/scala/li/cil/oc/client/gui/Printer.scala
Normal file
@ -0,0 +1,66 @@
|
||||
package li.cil.oc.client.gui
|
||||
|
||||
import li.cil.oc.Localization
|
||||
import li.cil.oc.client.Textures
|
||||
import li.cil.oc.client.gui.widget.ProgressBar
|
||||
import li.cil.oc.client.{PacketSender => ClientPacketSender}
|
||||
import li.cil.oc.common.container
|
||||
import li.cil.oc.common.container.ComponentSlot
|
||||
import li.cil.oc.common.tileentity
|
||||
import net.minecraft.entity.player.InventoryPlayer
|
||||
import net.minecraft.util.ResourceLocation
|
||||
import org.lwjgl.opengl.GL11
|
||||
|
||||
class Printer(playerInventory: InventoryPlayer, val printer: tileentity.Printer) extends DynamicGuiContainer(new container.Printer(playerInventory, printer)) {
|
||||
xSize = 176
|
||||
ySize = 166
|
||||
|
||||
private val progress = addWidget(new ProgressBar(104, 21) {
|
||||
override def width = 46
|
||||
|
||||
override def height = 46
|
||||
|
||||
override def barTexture = Textures.guiPrinterProgress
|
||||
})
|
||||
|
||||
private def assemblerContainer = inventorySlots.asInstanceOf[container.Printer]
|
||||
|
||||
override def initGui() {
|
||||
super.initGui()
|
||||
}
|
||||
|
||||
override def drawSecondaryForegroundLayer(mouseX: Int, mouseY: Int) = {
|
||||
super.drawSecondaryForegroundLayer(mouseX, mouseY)
|
||||
fontRendererObj.drawString(
|
||||
Localization.localizeImmediately(printer.getInventoryName),
|
||||
8, 6, 0x404040)
|
||||
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS) // Me lazy... prevents NEI render glitch.
|
||||
if (assemblerContainer.isAssembling && func_146978_c(progress.x, progress.y, progress.width, progress.height, mouseX, mouseY)) {
|
||||
val tooltip = new java.util.ArrayList[String]
|
||||
val timeRemaining = formatTime(assemblerContainer.assemblyRemainingTime)
|
||||
tooltip.add(Localization.Assembler.Progress(assemblerContainer.assemblyProgress, timeRemaining))
|
||||
copiedDrawHoveringText(tooltip, mouseX - guiLeft, mouseY - guiTop, fontRendererObj)
|
||||
}
|
||||
GL11.glPopAttrib()
|
||||
}
|
||||
|
||||
private def formatTime(seconds: Int) = {
|
||||
// Assembly times should not / rarely exceed one hour, so this is good enough.
|
||||
if (seconds < 60) f"0:$seconds%02d"
|
||||
else f"${seconds / 60}:${seconds % 60}%02d"
|
||||
}
|
||||
|
||||
override def drawGuiContainerBackgroundLayer(dt: Float, mouseX: Int, mouseY: Int) {
|
||||
GL11.glColor3f(1, 1, 1) // Required under Linux.
|
||||
mc.renderEngine.bindTexture(Textures.guiPrinter)
|
||||
drawTexturedModalRect(guiLeft, guiTop, 0, 0, xSize, ySize)
|
||||
if (assemblerContainer.isAssembling) progress.level = assemblerContainer.assemblyProgress / 100.0
|
||||
else progress.level = 0
|
||||
drawWidgets()
|
||||
drawInventorySlots()
|
||||
}
|
||||
|
||||
override protected def drawDisabledSlot(slot: ComponentSlot) {}
|
||||
|
||||
override def doesGuiPauseGame = false
|
||||
}
|
@ -9,6 +9,8 @@ class ProgressBar(val x: Int, val y: Int) extends Widget {
|
||||
|
||||
override def height = 12
|
||||
|
||||
def barTexture = Textures.guiBar
|
||||
|
||||
var level = 0.0
|
||||
|
||||
def draw() {
|
||||
@ -21,7 +23,7 @@ class ProgressBar(val x: Int, val y: Int) extends Widget {
|
||||
val ty = owner.windowY + y
|
||||
val w = width * level
|
||||
|
||||
Minecraft.getMinecraft.renderEngine.bindTexture(Textures.guiBar)
|
||||
Minecraft.getMinecraft.renderEngine.bindTexture(barTexture)
|
||||
val t = Tessellator.instance
|
||||
t.startDrawingQuads()
|
||||
t.addVertexWithUV(tx, ty, owner.windowZ, u0, v0)
|
||||
|
@ -11,5 +11,5 @@ abstract class Widget {
|
||||
|
||||
def height: Int
|
||||
|
||||
def draw()
|
||||
def draw(): Unit
|
||||
}
|
||||
|
@ -24,6 +24,8 @@ abstract class GuiHandler extends IGuiHandler {
|
||||
new container.Disassembler(player.inventory, t)
|
||||
case t: tileentity.DiskDrive if id == GuiType.DiskDrive.id =>
|
||||
new container.DiskDrive(player.inventory, t)
|
||||
case t: tileentity.Printer if id == GuiType.Printer.id =>
|
||||
new container.Printer(player.inventory, t)
|
||||
case t: tileentity.Raid if id == GuiType.Raid.id =>
|
||||
new container.Raid(player.inventory, t)
|
||||
case t: tileentity.RobotProxy if id == GuiType.Robot.id =>
|
||||
|
@ -21,6 +21,7 @@ object GuiType extends ScalaEnum {
|
||||
val Disassembler = new EnumVal { def name = "Disassembler"; def subType = GuiType.Category.Block }
|
||||
val DiskDrive = new EnumVal { def name = "DiskDrive"; def subType = GuiType.Category.Block }
|
||||
val Drone = new EnumVal { def name = "Drone"; def subType = GuiType.Category.Entity }
|
||||
val Printer = new EnumVal { def name = "Printer"; def subType = GuiType.Category.Block }
|
||||
val Rack = new EnumVal { def name = "Rack"; def subType = GuiType.Category.Block }
|
||||
val Raid = new EnumVal { def name = "Raid"; def subType = GuiType.Category.Block }
|
||||
val Robot = new EnumVal { def name = "Robot"; def subType = GuiType.Category.Block }
|
||||
|
@ -2,6 +2,7 @@ package li.cil.oc.common.block
|
||||
|
||||
import li.cil.oc.Settings
|
||||
import li.cil.oc.common.tileentity
|
||||
import li.cil.oc.util.ExtendedAABB
|
||||
import net.minecraft.entity.EntityLivingBase
|
||||
import net.minecraft.entity.player.EntityPlayer
|
||||
import net.minecraft.item.ItemStack
|
||||
@ -38,6 +39,10 @@ class Print(protected implicit val tileTag: ClassTag[tileentity.Print]) extends
|
||||
}
|
||||
}
|
||||
|
||||
override def setBlockBoundsForItemRender(metadata: Int): Unit = {
|
||||
setBlockBounds(ExtendedAABB.unitBounds)
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
override def hasTileEntity(metadata: Int) = true
|
||||
|
42
src/main/scala/li/cil/oc/common/block/Printer.scala
Normal file
42
src/main/scala/li/cil/oc/common/block/Printer.scala
Normal file
@ -0,0 +1,42 @@
|
||||
package li.cil.oc.common.block
|
||||
|
||||
import li.cil.oc.Settings
|
||||
import li.cil.oc.client.Textures
|
||||
import li.cil.oc.common.GuiType
|
||||
import li.cil.oc.common.tileentity
|
||||
import net.minecraft.client.renderer.texture.IIconRegister
|
||||
import net.minecraft.world.IBlockAccess
|
||||
import net.minecraft.world.World
|
||||
import net.minecraftforge.common.util.ForgeDirection
|
||||
|
||||
class Printer extends SimpleBlock with traits.SpecialBlock with traits.PowerAcceptor with traits.StateAware with traits.GUI {
|
||||
override protected def customTextures = Array(
|
||||
None,
|
||||
Some("AssemblerTop"),
|
||||
Some("AssemblerSide"),
|
||||
Some("AssemblerSide"),
|
||||
Some("AssemblerSide"),
|
||||
Some("AssemblerSide")
|
||||
)
|
||||
|
||||
override def registerBlockIcons(iconRegister: IIconRegister) = {
|
||||
super.registerBlockIcons(iconRegister)
|
||||
Textures.Assembler.iconSideAssembling = iconRegister.registerIcon(Settings.resourceDomain + ":AssemblerSideAssembling")
|
||||
Textures.Assembler.iconSideOn = iconRegister.registerIcon(Settings.resourceDomain + ":AssemblerSideOn")
|
||||
Textures.Assembler.iconTopOn = iconRegister.registerIcon(Settings.resourceDomain + ":AssemblerTopOn")
|
||||
}
|
||||
|
||||
override def isBlockSolid(world: IBlockAccess, x: Int, y: Int, z: Int, side: ForgeDirection) = side == ForgeDirection.DOWN
|
||||
|
||||
override def isSideSolid(world: IBlockAccess, x: Int, y: Int, z: Int, side: ForgeDirection) = side == ForgeDirection.DOWN
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
override def energyThroughput = Settings.get.assemblerRate
|
||||
|
||||
override def guiType = GuiType.Printer
|
||||
|
||||
override def hasTileEntity(metadata: Int) = true
|
||||
|
||||
override def createTileEntity(world: World, metadata: Int) = new tileentity.Printer()
|
||||
}
|
53
src/main/scala/li/cil/oc/common/container/Printer.scala
Normal file
53
src/main/scala/li/cil/oc/common/container/Printer.scala
Normal file
@ -0,0 +1,53 @@
|
||||
package li.cil.oc.common.container
|
||||
|
||||
import cpw.mods.fml.relauncher.Side
|
||||
import cpw.mods.fml.relauncher.SideOnly
|
||||
import li.cil.oc.common.tileentity
|
||||
import li.cil.oc.util.SideTracker
|
||||
import net.minecraft.entity.player.InventoryPlayer
|
||||
|
||||
class Printer(playerInventory: InventoryPlayer, val printer: tileentity.Printer) extends Player(playerInventory, printer) {
|
||||
addSlotToContainer(18, 19)
|
||||
addSlotToContainer(18, 51)
|
||||
addSlotToContainer(152, 35)
|
||||
|
||||
// Show the player's inventory.
|
||||
addPlayerInventorySlots(8, 84)
|
||||
|
||||
var isAssembling = false
|
||||
var assemblyProgress = 0.0
|
||||
var assemblyRemainingTime = 0
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
override def updateProgressBar(id: Int, value: Int) {
|
||||
super.updateProgressBar(id, value)
|
||||
if (id == 0) {
|
||||
isAssembling = value == 1
|
||||
}
|
||||
|
||||
if (id == 1) {
|
||||
assemblyProgress = value / 5.0
|
||||
}
|
||||
|
||||
if (id == 2) {
|
||||
assemblyRemainingTime = value
|
||||
}
|
||||
}
|
||||
|
||||
override def detectAndSendChanges() {
|
||||
super.detectAndSendChanges()
|
||||
if (SideTracker.isServer) {
|
||||
if (isAssembling != printer.isAssembling) {
|
||||
isAssembling = printer.isAssembling
|
||||
sendProgressBarUpdate(0, if (isAssembling) 1 else 0)
|
||||
}
|
||||
val timeRemaining = printer.timeRemaining
|
||||
if (math.abs(printer.progress - assemblyProgress) > 0.2 || assemblyRemainingTime != timeRemaining) {
|
||||
assemblyProgress = printer.progress
|
||||
assemblyRemainingTime = timeRemaining
|
||||
sendProgressBarUpdate(1, (assemblyProgress * 5).toInt)
|
||||
sendProgressBarUpdate(2, timeRemaining)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -26,6 +26,7 @@ object Blocks {
|
||||
GameRegistry.registerTileEntity(classOf[tileentity.PowerConverter], Settings.namespace + "power_converter")
|
||||
GameRegistry.registerTileEntity(classOf[tileentity.PowerDistributor], Settings.namespace + "power_distributor")
|
||||
GameRegistry.registerTileEntity(classOf[tileentity.Print], Settings.namespace + "print")
|
||||
GameRegistry.registerTileEntity(classOf[tileentity.Printer], Settings.namespace + "printer")
|
||||
GameRegistry.registerTileEntity(classOf[tileentity.Raid], Settings.namespace + "raid")
|
||||
GameRegistry.registerTileEntity(classOf[tileentity.Redstone], Settings.namespace + "redstone")
|
||||
GameRegistry.registerTileEntity(classOf[tileentity.RobotProxy], Settings.namespace + "robot")
|
||||
@ -85,5 +86,6 @@ object Blocks {
|
||||
|
||||
// v1.5.4
|
||||
Items.registerBlock(new Print(), "print")
|
||||
Items.registerBlock(new Printer(), "printer")
|
||||
}
|
||||
}
|
||||
|
@ -3,15 +3,16 @@ package li.cil.oc.common.tileentity
|
||||
import cpw.mods.fml.relauncher.Side
|
||||
import cpw.mods.fml.relauncher.SideOnly
|
||||
import li.cil.oc.common.item.data.PrintData
|
||||
import li.cil.oc.util.ExtendedAABB
|
||||
import li.cil.oc.util.ExtendedAABB._
|
||||
import li.cil.oc.util.ExtendedNBT._
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
import net.minecraft.util.AxisAlignedBB
|
||||
|
||||
class Print extends traits.TileEntity {
|
||||
val data = new PrintData()
|
||||
|
||||
var boundsOff = unitBounds
|
||||
var boundsOn = unitBounds
|
||||
var boundsOff = ExtendedAABB.unitBounds
|
||||
var boundsOn = ExtendedAABB.unitBounds
|
||||
var state = false
|
||||
|
||||
override def canUpdate: Boolean = false
|
||||
@ -40,9 +41,9 @@ class Print extends traits.TileEntity {
|
||||
}
|
||||
|
||||
def updateBounds(): Unit = {
|
||||
boundsOff = data.stateOff.drop(1).foldLeft(data.stateOff.headOption.fold(unitBounds)(_.bounds))((a, b) => a.func_111270_a(b.bounds))
|
||||
boundsOn = data.stateOn.drop(1).foldLeft(data.stateOn.headOption.fold(unitBounds)(_.bounds))((a, b) => a.func_111270_a(b.bounds))
|
||||
boundsOff = data.stateOff.drop(1).foldLeft(data.stateOff.headOption.fold(ExtendedAABB.unitBounds)(_.bounds))((a, b) => a.func_111270_a(b.bounds))
|
||||
if (boundsOff.volume == 0) boundsOff = ExtendedAABB.unitBounds
|
||||
boundsOn = data.stateOn.drop(1).foldLeft(data.stateOn.headOption.fold(ExtendedAABB.unitBounds)(_.bounds))((a, b) => a.func_111270_a(b.bounds))
|
||||
if (boundsOn.volume == 0) boundsOn = ExtendedAABB.unitBounds
|
||||
}
|
||||
|
||||
private def unitBounds = AxisAlignedBB.getBoundingBox(0, 0, 0, 1, 1, 1)
|
||||
}
|
||||
|
247
src/main/scala/li/cil/oc/common/tileentity/Printer.scala
Normal file
247
src/main/scala/li/cil/oc/common/tileentity/Printer.scala
Normal file
@ -0,0 +1,247 @@
|
||||
package li.cil.oc.common.tileentity
|
||||
|
||||
import java.util
|
||||
|
||||
import cpw.mods.fml.relauncher.Side
|
||||
import cpw.mods.fml.relauncher.SideOnly
|
||||
import li.cil.oc.Settings
|
||||
import li.cil.oc.api
|
||||
import li.cil.oc.api.machine.Arguments
|
||||
import li.cil.oc.api.machine.Callback
|
||||
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.util.ExtendedAABB._
|
||||
import li.cil.oc.util.ExtendedNBT._
|
||||
import li.cil.oc.util.ItemUtils
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
import net.minecraft.util.AxisAlignedBB
|
||||
import net.minecraftforge.common.util.ForgeDirection
|
||||
|
||||
class Printer extends traits.Environment with traits.PowerAcceptor with traits.Inventory with traits.Rotatable with SidedEnvironment with traits.StateAware {
|
||||
val node = api.Network.newNode(this, Visibility.Network).
|
||||
withComponent("printer3d").
|
||||
withConnector(Settings.get.bufferConverter).
|
||||
create()
|
||||
|
||||
var data = new PrintData()
|
||||
var isActive = false
|
||||
var output: Option[ItemStack] = None
|
||||
var totalRequiredEnergy = 0.0
|
||||
var requiredEnergy = 0.0
|
||||
|
||||
val slotPlastic = 0
|
||||
val slotInk = 1
|
||||
val slotOutput = 2
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
override def canConnect(side: ForgeDirection) = side != ForgeDirection.UP
|
||||
|
||||
override def sidedNode(side: ForgeDirection) = if (side != ForgeDirection.UP) node else null
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
override protected def hasConnector(side: ForgeDirection) = canConnect(side)
|
||||
|
||||
override protected def connector(side: ForgeDirection) = Option(if (side != ForgeDirection.UP) node else null)
|
||||
|
||||
override protected def energyThroughput = Settings.get.assemblerRate
|
||||
|
||||
override def currentState = {
|
||||
if (isAssembling) util.EnumSet.of(traits.State.IsWorking)
|
||||
else if (canAssemble) util.EnumSet.of(traits.State.CanWork)
|
||||
else util.EnumSet.noneOf(classOf[traits.State])
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
def canAssemble = {
|
||||
val complexity = data.stateOff.size + data.stateOn.size
|
||||
complexity > 0 && complexity <= Settings.get.maxPrintComplexity
|
||||
}
|
||||
|
||||
def isAssembling = requiredEnergy > 0
|
||||
|
||||
def progress = (1 - requiredEnergy / totalRequiredEnergy) * 100
|
||||
|
||||
def timeRemaining = (requiredEnergy / Settings.get.assemblerTickAmount / 20).toInt
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
@Callback(doc = """function() -- Resets the configuration of the printer and stop printing (current job will finish).""")
|
||||
def reset(context: Context, args: Arguments): Array[Object] = {
|
||||
data = new PrintData()
|
||||
isActive = false // Needs committing.
|
||||
null
|
||||
}
|
||||
|
||||
@Callback(doc = """function(value:string) -- Set a label for the block being printed.""")
|
||||
def setLabel(context: Context, args: Arguments): Array[Object] = {
|
||||
data.label = Option(args.optString(0, null))
|
||||
isActive = false // Needs committing.
|
||||
null
|
||||
}
|
||||
|
||||
@Callback(doc = """function():string -- Get the current label for the block being printed.""")
|
||||
def getLabel(context: Context, args: Arguments): Array[Object] = {
|
||||
result(data.label.orNull)
|
||||
}
|
||||
|
||||
@Callback(doc = """function(value:string) -- Set a tooltip for the block being printed.""")
|
||||
def setTooltip(context: Context, args: Arguments): Array[Object] = {
|
||||
data.tooltip = Option(args.optString(0, null))
|
||||
isActive = false // Needs committing.
|
||||
null
|
||||
}
|
||||
|
||||
@Callback(doc = """function():string -- Get the current tooltip for the block being printed.""")
|
||||
def getTooltip(context: Context, args: Arguments): Array[Object] = {
|
||||
result(data.tooltip.orNull)
|
||||
}
|
||||
|
||||
@Callback(doc = """function(minX:number, minY:number, minZ:number, maxX:number, maxY:number, maxZ:number, texture:string[, state:boolean=false]) -- Adds a shape to the printers configuration, optionally specifying whether it is for the off or on state.""")
|
||||
def addShape(context: Context, args: Arguments): Array[Object] = {
|
||||
if (data.stateOff.size + data.stateOn.size >= Settings.get.maxPrintComplexity) {
|
||||
return result(null, "model too complex")
|
||||
}
|
||||
val minX = (args.checkInteger(0) max 0 min 16) / 16f
|
||||
val minY = (args.checkInteger(1) max 0 min 16) / 16f
|
||||
val minZ = (args.checkInteger(2) max 0 min 16) / 16f
|
||||
val maxX = (args.checkInteger(3) max 0 min 16) / 16f
|
||||
val maxY = (args.checkInteger(4) max 0 min 16) / 16f
|
||||
val maxZ = (args.checkInteger(5) max 0 min 16) / 16f
|
||||
val texture = args.checkString(6)
|
||||
val state = args.optBoolean(7, false)
|
||||
|
||||
if (minX == maxX) throw new IllegalArgumentException("empty block")
|
||||
if (minY == maxY) throw new IllegalArgumentException("empty block")
|
||||
if (minZ == maxZ) throw new IllegalArgumentException("empty block")
|
||||
|
||||
val list = if (state) data.stateOn else data.stateOff
|
||||
list += new PrintData.Shape(AxisAlignedBB.getBoundingBox(
|
||||
math.min(minX, maxX),
|
||||
math.min(minY, maxY),
|
||||
math.min(minZ, maxZ),
|
||||
math.max(maxX, minX),
|
||||
math.max(maxY, minY),
|
||||
math.max(maxZ, minZ)), texture)
|
||||
isActive = false // Needs committing.
|
||||
|
||||
result(true)
|
||||
}
|
||||
|
||||
@Callback(doc = """function():number -- Get the number of shapes in the current configuration.""")
|
||||
def getShapeCount(context: Context, args: Arguments): Array[Object] = result(data.stateOff.size + data.stateOn.size)
|
||||
|
||||
@Callback(doc = """function():number -- Get the maximum allowed number of shapes.""")
|
||||
def getMaxShapeCount(context: Context, args: Arguments): Array[Object] = result(Settings.get.maxPrintComplexity)
|
||||
|
||||
@Callback(doc = """function():boolean -- Commit and begin printing the current configuration.""")
|
||||
def commit(context: Context, args: Arguments): Array[Object] = {
|
||||
if (!canAssemble) {
|
||||
return result(null, "model invalid")
|
||||
}
|
||||
isActive = true
|
||||
result(true)
|
||||
}
|
||||
|
||||
@Callback(doc = """function(): string, number or boolean -- The current state of the printer, `busy' or `idle', followed by the progress or model validity, respectively.""")
|
||||
def status(context: Context, args: Arguments): Array[Object] = {
|
||||
if (isAssembling) result("busy", progress)
|
||||
else if (canAssemble) result("idle", true)
|
||||
else result("idle", false)
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
override def canUpdate = isServer
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
override def updateEntity() {
|
||||
super.updateEntity()
|
||||
|
||||
if (world.getTotalWorldTime % Settings.get.tickFrequency == 0) {
|
||||
if (isActive && output.isEmpty) {
|
||||
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)
|
||||
val totalShapes = data.stateOn.size + data.stateOff.size
|
||||
// TODO Consume plastic (totalVolume) and ink (totalSurface).
|
||||
totalRequiredEnergy = totalShapes * Settings.get.printShapeCost
|
||||
requiredEnergy = totalRequiredEnergy
|
||||
output = Option(data.createItemStack())
|
||||
// ServerPacketSender.sendRobotAssembling(this, assembling = true)
|
||||
}
|
||||
|
||||
if (output.isDefined) {
|
||||
val want = math.max(1, math.min(requiredEnergy, Settings.get.assemblerTickAmount * Settings.get.tickFrequency))
|
||||
val success = Settings.get.ignorePower || node.tryChangeBuffer(-want)
|
||||
if (success) {
|
||||
requiredEnergy -= want
|
||||
}
|
||||
if (requiredEnergy <= 0) {
|
||||
val result = getStackInSlot(slotOutput)
|
||||
if (result == null) {
|
||||
setInventorySlotContents(slotOutput, output.get)
|
||||
}
|
||||
else if (output.get.isItemEqual(result) && ItemStack.areItemStackTagsEqual(output.get, result) && result.stackSize < result.getMaxStackSize) {
|
||||
result.stackSize += 1
|
||||
markDirty()
|
||||
}
|
||||
else {
|
||||
return
|
||||
}
|
||||
requiredEnergy = 0
|
||||
output = None
|
||||
}
|
||||
// ServerPacketSender.sendRobotAssembling(this, success && output.isDefined)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override def readFromNBTForServer(nbt: NBTTagCompound) {
|
||||
super.readFromNBTForServer(nbt)
|
||||
data.load(nbt.getCompoundTag("data"))
|
||||
isActive = nbt.getBoolean(Settings.namespace + "active")
|
||||
if (nbt.hasKey(Settings.namespace + "output")) {
|
||||
output = Option(ItemUtils.loadStack(nbt.getCompoundTag(Settings.namespace + "output")))
|
||||
}
|
||||
totalRequiredEnergy = nbt.getDouble(Settings.namespace + "total")
|
||||
requiredEnergy = nbt.getDouble(Settings.namespace + "remaining")
|
||||
}
|
||||
|
||||
override def writeToNBTForServer(nbt: NBTTagCompound) {
|
||||
super.writeToNBTForServer(nbt)
|
||||
nbt.setNewCompoundTag("data", data.save)
|
||||
nbt.setBoolean(Settings.namespace + "active", isActive)
|
||||
output.foreach(stack => nbt.setNewCompoundTag(Settings.namespace + "output", stack.writeToNBT))
|
||||
nbt.setDouble(Settings.namespace + "total", totalRequiredEnergy)
|
||||
nbt.setDouble(Settings.namespace + "remaining", requiredEnergy)
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT) override
|
||||
def readFromNBTForClient(nbt: NBTTagCompound) {
|
||||
super.readFromNBTForClient(nbt)
|
||||
requiredEnergy = nbt.getDouble("remaining")
|
||||
}
|
||||
|
||||
override def writeToNBTForClient(nbt: NBTTagCompound) {
|
||||
super.writeToNBTForClient(nbt)
|
||||
nbt.setDouble("remaining", requiredEnergy)
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
override def getSizeInventory = 3
|
||||
|
||||
override def getInventoryStackLimit = 64
|
||||
|
||||
override def isItemValidForSlot(slot: Int, stack: ItemStack) =
|
||||
if (slot == 0)
|
||||
true // TODO Plastic
|
||||
else if (slot == 1)
|
||||
true // TODO Color
|
||||
else false
|
||||
}
|
28
src/main/scala/li/cil/oc/util/ExtendedAABB.scala
Normal file
28
src/main/scala/li/cil/oc/util/ExtendedAABB.scala
Normal file
@ -0,0 +1,28 @@
|
||||
package li.cil.oc.util
|
||||
|
||||
import net.minecraft.util.AxisAlignedBB
|
||||
|
||||
import scala.language.implicitConversions
|
||||
|
||||
object ExtendedAABB {
|
||||
implicit def extendedAABB(bounds: AxisAlignedBB): ExtendedAABB = new ExtendedAABB(bounds)
|
||||
|
||||
def unitBounds = AxisAlignedBB.getBoundingBox(0, 0, 0, 1, 1, 1)
|
||||
|
||||
class ExtendedAABB(val bounds: AxisAlignedBB) {
|
||||
def volume: Int = {
|
||||
val sx = ((bounds.maxX - bounds.minX) * 16).round.toInt
|
||||
val sy = ((bounds.maxY - bounds.minY) * 16).round.toInt
|
||||
val sz = ((bounds.maxZ - bounds.minZ) * 16).round.toInt
|
||||
sx * sy * sz
|
||||
}
|
||||
|
||||
def surface: Int = {
|
||||
val sx = ((bounds.maxX - bounds.minX) * 16).round.toInt
|
||||
val sy = ((bounds.maxY - bounds.minY) * 16).round.toInt
|
||||
val sz = ((bounds.maxZ - bounds.minZ) * 16).round.toInt
|
||||
sx * sy * 2 + sx * sz * 2 + sy * sz * 2
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user