blob: ec39d43d21e7ffcdabee001960d591b7b82fbf5a [file] [log] [blame] [raw]
package li.cil.oc.common.tileentity
import cpw.mods.fml.relauncher.Side
import cpw.mods.fml.relauncher.SideOnly
import li.cil.oc.api
import li.cil.oc.api.Driver
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.Analyzable
import li.cil.oc.api.network.Component
import li.cil.oc.api.network.Node
import li.cil.oc.api.network.Visibility
import li.cil.oc.common.Slot
import li.cil.oc.common.Sound
import li.cil.oc.server.{PacketSender => ServerPacketSender}
import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.util.InventoryUtils
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
class DiskDrive extends traits.Environment with traits.ComponentInventory with traits.Rotatable with Analyzable {
// Used on client side to check whether to render disk activity indicators.
var lastAccess = 0L
def filesystemNode = components(0) match {
case Some(environment) => Option(environment.node)
case _ => None
}
// ----------------------------------------------------------------------- //
// Environment
val node = api.Network.newNode(this, Visibility.Network).
withComponent("disk_drive").
create()
@Callback(doc = """function():boolean -- Checks whether some medium is currently in the drive.""")
def isEmpty(context: Context, args: Arguments): Array[AnyRef] = {
result(filesystemNode.isEmpty)
}
@Callback(doc = """function([velocity:number]):boolean -- Eject the currently present medium from the drive.""")
def eject(context: Context, args: Arguments): Array[AnyRef] = {
val velocity = args.optDouble(0, 0) max 0 min 1
val ejected = decrStackSize(0, 1)
if (ejected != null && ejected.stackSize > 0) {
val entity = InventoryUtils.spawnStackInWorld(position, ejected, Option(facing))
if (entity != null) {
val vx = facing.offsetX * velocity
val vy = facing.offsetY * velocity
val vz = facing.offsetZ * velocity
entity.addVelocity(vx, vy, vz)
}
result(true)
}
else result(false)
}
// ----------------------------------------------------------------------- //
// Analyzable
override def onAnalyze(player: EntityPlayer, side: Int, hitX: Float, hitY: Float, hitZ: Float) = filesystemNode.fold(null: Array[Node])(Array(_))
// ----------------------------------------------------------------------- //
// IInventory
override def getSizeInventory = 1
override def isItemValidForSlot(slot: Int, stack: ItemStack) = (slot, Option(Driver.driverFor(stack, getClass))) match {
case (0, Some(driver)) => driver.slot(stack) == Slot.Floppy
case _ => false
}
// ----------------------------------------------------------------------- //
// ComponentInventory
override protected def onItemAdded(slot: Int, stack: ItemStack) {
super.onItemAdded(slot, stack)
components(slot) match {
case Some(environment) => environment.node match {
case component: Component => component.setVisibility(Visibility.Network)
}
case _ =>
}
Sound.playDiskInsert(this)
if (isServer) {
ServerPacketSender.sendFloppyChange(this, stack)
}
}
override protected def onItemRemoved(slot: Int, stack: ItemStack) {
super.onItemRemoved(slot, stack)
Sound.playDiskEject(this)
if (isServer) {
ServerPacketSender.sendFloppyChange(this)
}
}
// ----------------------------------------------------------------------- //
// TileEntity
override def canUpdate = false
@SideOnly(Side.CLIENT) override
def readFromNBTForClient(nbt: NBTTagCompound) {
super.readFromNBTForClient(nbt)
if (nbt.hasKey("disk")) {
setInventorySlotContents(0, ItemStack.loadItemStackFromNBT(nbt.getCompoundTag("disk")))
}
}
override def writeToNBTForClient(nbt: NBTTagCompound) {
super.writeToNBTForClient(nbt)
items(0) match {
case Some(stack) => nbt.setNewCompoundTag("disk", stack.writeToNBT)
case _ =>
}
}
}