Printer block to allow printing 3d prints.

This commit is contained in:
Florian Nücke 2015-03-23 17:58:41 +01:00
parent bb3456d86e
commit 1d7b6caa6f
18 changed files with 475 additions and 9 deletions

View File

@ -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).

Binary file not shown.

After

Width:  |  Height:  |  Size: 634 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 189 B

View File

@ -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

View File

@ -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 =>

View File

@ -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")

View 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
}

View File

@ -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)

View File

@ -11,5 +11,5 @@ abstract class Widget {
def height: Int
def draw()
def draw(): Unit
}

View File

@ -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 =>

View File

@ -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 }

View File

@ -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

View 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()
}

View 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)
}
}
}
}

View File

@ -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")
}
}

View File

@ -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)
}

View 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
}

View 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
}
}
}