blob: a6f9919d3f17c9f12da3f7b0c119d12516b8b658 [file] [log] [blame] [raw]
package li.cil.oc.common.tileentity
import java.util.UUID
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.Driver
import li.cil.oc.api.network.Analyzable
import li.cil.oc.api.network.Visibility
import li.cil.oc.common.Slot
import li.cil.oc.server.component.FileSystem
import li.cil.oc.server.{PacketSender => ServerPacketSender}
import li.cil.oc.util.ExtendedNBT._
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
class Raid extends traits.Environment with traits.Inventory with traits.Rotatable with Analyzable {
val node = api.Network.newNode(this, Visibility.None).create()
var filesystem: Option[FileSystem] = None
// Used on client side to check whether to render disk activity indicators.
var lastAccess = 0L
// For client side rendering.
val presence = Array.fill(getSizeInventory)(false)
// ----------------------------------------------------------------------- //
override def onAnalyze(player: EntityPlayer, side: Int, hitX: Float, hitY: Float, hitZ: Float) = Array(filesystem.map(_.node).orNull)
override def canUpdate = false
// ----------------------------------------------------------------------- //
override def getSizeInventory = 3
override def getInventoryStackLimit = 1
override def isItemValidForSlot(slot: Int, stack: ItemStack) = Option(Driver.driverFor(stack, getClass)) match {
case Some(driver) => driver.slot(stack) == Slot.HDD
case _ => false
}
override protected def onItemAdded(slot: Int, stack: ItemStack) {
super.onItemAdded(slot, stack)
if (isServer) this.synchronized {
ServerPacketSender.sendRaidChange(this)
tryCreateRaid(UUID.randomUUID().toString)
}
}
override protected def onItemRemoved(slot: Int, stack: ItemStack) {
super.onItemRemoved(slot, stack)
if (isServer) this.synchronized {
ServerPacketSender.sendRaidChange(this)
filesystem.foreach(fs => {
fs.fileSystem.close()
fs.fileSystem.list("/").foreach(fs.fileSystem.delete)
fs.save(new NBTTagCompound()) // Flush buffered fs.
fs.node.remove()
filesystem = None
})
}
}
private def tryCreateRaid(id: String) {
if (items.count(_.isDefined) == items.length) {
val fs = api.FileSystem.asManagedEnvironment(
api.FileSystem.fromSaveDirectory(id, wipeDisksAndComputeSpace, Settings.get.bufferChanges),
"raid", this, Settings.resourceDomain + ":hdd_access").
asInstanceOf[FileSystem]
val nbtToSetAddress = new NBTTagCompound()
nbtToSetAddress.setString("address", id)
fs.node.load(nbtToSetAddress)
fs.node.setVisibility(Visibility.Network)
// Ensure we're in a network before connecting the raid fs.
api.Network.joinNewNetwork(node)
node.connect(fs.node)
filesystem = Option(fs)
}
}
private def wipeDisksAndComputeSpace = items.foldLeft(0L) {
case (acc, Some(hdd)) => acc + (Option(api.Driver.driverFor(hdd)) match {
case Some(driver) => driver.createEnvironment(hdd, this) match {
case fs: FileSystem =>
val nbt = driver.dataTag(hdd)
fs.load(nbt)
fs.fileSystem.close()
fs.fileSystem.list("/").foreach(fs.fileSystem.delete)
fs.save(nbt)
fs.fileSystem.spaceTotal.toInt
case _ => 0L // Ignore.
}
case _ => 0L
})
case (acc, None) => acc
}
// ----------------------------------------------------------------------- //
override def readFromNBT(nbt: NBTTagCompound) {
super.readFromNBT(nbt)
if (nbt.hasKey(Settings.namespace + "fs")) {
val tag = nbt.getCompoundTag(Settings.namespace + "fs")
tryCreateRaid(tag.getCompoundTag("node").getString("address"))
filesystem.foreach(fs => fs.load(tag))
}
}
override def writeToNBT(nbt: NBTTagCompound) {
super.writeToNBT(nbt)
filesystem.foreach(fs => nbt.setNewCompoundTag(Settings.namespace + "fs", fs.save))
}
@SideOnly(Side.CLIENT) override
def readFromNBTForClient(nbt: NBTTagCompound) {
super.readFromNBTForClient(nbt)
nbt.getByteArray("presence").
map(_ != 0).
copyToArray(presence)
}
override def writeToNBTForClient(nbt: NBTTagCompound) {
super.writeToNBTForClient(nbt)
nbt.setTag("presence", items.map(_.isDefined))
}
}