mirror of
https://github.com/MightyPirates/OpenComputers.git
synced 2025-09-17 03:05:30 -04:00
Merge branch 'master-MC1.7.10' of github.com:MightyPirates/OpenComputers into master-MC1.8
Conflicts: src/main/scala/li/cil/oc/client/Textures.scala src/main/scala/li/cil/oc/client/gui/Assembler.scala src/main/scala/li/cil/oc/client/gui/Database.scala src/main/scala/li/cil/oc/client/gui/Manual.scala src/main/scala/li/cil/oc/client/gui/Server.scala src/main/scala/li/cil/oc/client/gui/ServerRack.scala src/main/scala/li/cil/oc/common/item/FloppyDisk.scala src/main/scala/li/cil/oc/integration/opencomputers/DriverFileSystem.scala src/main/scala/li/cil/oc/server/machine/Machine.scala
This commit is contained in:
commit
3d663fee35
@ -205,9 +205,7 @@ opencomputers {
|
||||
allowBytecode: false
|
||||
|
||||
# Whether to make the Lua 5.3 architecture available. If enabled, you
|
||||
# can reconfigure any CPU to use the Lua 5.3 architecture. This is
|
||||
# not enabled by default for the time being, because it needs some
|
||||
# more stability testing.
|
||||
# can reconfigure any CPU to use the Lua 5.3 architecture.
|
||||
enableLua53: true
|
||||
|
||||
# The sizes of the six levels of RAM, in kilobytes. This list must
|
||||
@ -853,6 +851,20 @@ opencomputers {
|
||||
# runs on. As a side effect this pretty much determines the read
|
||||
# performance of file systems.
|
||||
maxReadBuffer: 2048
|
||||
|
||||
# Number of physical platters to pretend a disk has in unmanged mode. This
|
||||
# controls seek times, in how it emulates sectors overlapping (thus sharing
|
||||
# a common head position for access).
|
||||
hddPlatterCounts: [ 2, 4, 6 ]
|
||||
|
||||
# When skipping more than this number of sectors in unmanaged mode, the
|
||||
# pause specified in sectorSeekTime will be enforced. We use this instead
|
||||
# of linear scaling for movement because those values would have to be
|
||||
# really small, which is hard to conceptualize and configure.
|
||||
sectorSeekThreshold: 128
|
||||
|
||||
# The time to pause when the head movement threshold is exceeded.
|
||||
sectorSeekTime: 0.1
|
||||
}
|
||||
|
||||
# Internet settings, security related.
|
||||
|
@ -191,6 +191,9 @@ oc:gui.Chat.WarningPower=No supported power providing mod available. Computers,
|
||||
oc:gui.Chat.WarningProjectRed=You are using a version of Project: Red that is incompatible with OpenComputers. Try updating your version of Project: Red.
|
||||
oc:gui.Chat.WarningRecipes=There were errors loading one or more recipes. Some items may be uncraftable. Please check your log file for more information.
|
||||
oc:gui.Chat.WarningSimpleComponent=An addon (yours?) using the §aSimpleComponent§f interface did §esomething wrong§f. Component logic could not be injected. Please check your log file for more information.
|
||||
oc:gui.Drive.Managed=Managed
|
||||
oc:gui.Drive.Unmanaged=Unmanaged
|
||||
oc:gui.Drive.Warning=§lWarning§r: switching modes will result in a loss of all data currently stored on the disk!
|
||||
oc:gui.Error.ComponentOverflow=Too many components connected to the computer.
|
||||
oc:gui.Error.InternalError=Internal error, please see the log file. This is probably a bug.
|
||||
oc:gui.Error.NoCPU=No CPU is installed in the computer.
|
||||
@ -272,6 +275,9 @@ oc:tooltip.Disassembler=Separates items into their original components. §lWarni
|
||||
oc:tooltip.Disk=Primitive medium that can be used to build persistent storage devices.
|
||||
oc:tooltip.DiskDrive.CC=ComputerCraft floppies are §asupported§7.
|
||||
oc:tooltip.DiskDrive=Allows reading and writing floppies. Can be installed in robots to allow inserting floppies later on.
|
||||
oc:tooltip.DiskUsage=Disk usage: %s/%s Byte
|
||||
oc:tooltip.DiskModeManaged=Mode: Managed
|
||||
oc:tooltip.DiskModeUnmanaged=Mode: Unmanaged
|
||||
oc:tooltip.Drone=Drones are light-weight, fast reconnaissance units with limited cargo space.
|
||||
oc:tooltip.DroneCase=This casing is used to build Drones in the assembler. It has room for a small amount of components and provides endstone-powered levitation.
|
||||
oc:tooltip.EEPROM=Small, programmable storage that contains the BIOS computers use to boot.
|
||||
|
@ -0,0 +1,90 @@
|
||||
--[[ Backwards compat for Lua 5.3; only loaded in 5.3 because package.loaded is
|
||||
prepopulated with the existing global bit32 in 5.2. ]]
|
||||
|
||||
local bit32 = {}
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
local function fold(init, op, ...)
|
||||
local result = init
|
||||
local args = table.pack(...)
|
||||
for i = 1, args.n do
|
||||
result = op(result, args[i])
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
local function trim(n)
|
||||
return n & 0xFFFFFFFF
|
||||
end
|
||||
|
||||
local function mask(w)
|
||||
return ~(0xFFFFFFFF << w)
|
||||
end
|
||||
|
||||
function bit32.arshift(x, disp)
|
||||
return x // (2 ^ disp)
|
||||
end
|
||||
|
||||
function bit32.band(...)
|
||||
return fold(0xFFFFFFFF, function(a, b) return a & b end, ...)
|
||||
end
|
||||
|
||||
function bit32.bnot(x)
|
||||
return ~x
|
||||
end
|
||||
|
||||
function bit32.bor(...)
|
||||
return fold(0, function(a, b) return a | b end, ...)
|
||||
end
|
||||
|
||||
function bit32.btest(...)
|
||||
return bit32.band(...) ~= 0
|
||||
end
|
||||
|
||||
function bit32.bxor(...)
|
||||
return fold(0, function(a, b) return a ~ b end, ...)
|
||||
end
|
||||
|
||||
local function fieldargs(f, w)
|
||||
w = w or 1
|
||||
assert(f >= 0, "field cannot be negative")
|
||||
assert(w > 0, "width must be positive")
|
||||
assert(f + w <= 32, "trying to access non-existent bits")
|
||||
return f, w
|
||||
end
|
||||
|
||||
function bit32.extract(n, field, width)
|
||||
local f, w = fieldargs(field, width)
|
||||
return (n >> f) & mask(w)
|
||||
end
|
||||
|
||||
function bit32.replace(n, v, field, width)
|
||||
local f, w = fieldargs(field, width)
|
||||
local m = mask(w)
|
||||
return (n & ~(m << f)) | ((v & m) << f)
|
||||
end
|
||||
|
||||
function bit32.lrotate(x, disp)
|
||||
if disp == 0 then return x
|
||||
elseif disp < 0 then return bit32.rrotate(x, -disp)
|
||||
else return trim((x << disp) | (x >> (32 - disp))) end
|
||||
end
|
||||
|
||||
function bit32.lshift(x, disp)
|
||||
return trim(x << disp)
|
||||
end
|
||||
|
||||
function bit32.rrotate(x, disp)
|
||||
if disp == 0 then return x
|
||||
elseif disp < 0 then return bit32.lrotate(x, -disp)
|
||||
else return trim((x >> disp) | (x << (32 - disp))) end
|
||||
end
|
||||
|
||||
function bit32.rshift(x, disp)
|
||||
return trim(x >> disp)
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
return bit32
|
Binary file not shown.
After Width: | Height: | Size: 208 B |
BIN
src/main/resources/assets/opencomputers/textures/gui/drive.png
Normal file
BIN
src/main/resources/assets/opencomputers/textures/gui/drive.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 326 B |
@ -112,6 +112,14 @@ object Localization {
|
||||
def Power = localizeImmediately("gui.Robot.Power")
|
||||
}
|
||||
|
||||
object Drive {
|
||||
def Managed = localizeImmediately("gui.Drive.Managed")
|
||||
|
||||
def Unmanaged = localizeImmediately("gui.Drive.Unmanaged")
|
||||
|
||||
def Warning = localizeImmediately("gui.Drive.Warning")
|
||||
}
|
||||
|
||||
object Raid {
|
||||
def Warning = localizeImmediately("gui.Raid.Warning")
|
||||
}
|
||||
@ -151,6 +159,10 @@ object Localization {
|
||||
}
|
||||
|
||||
object Tooltip {
|
||||
def DiskUsage(used: Long, capacity: Long) = localizeImmediately("tooltip.DiskUsage", used.toString, capacity.toString)
|
||||
|
||||
def DiskMode(isUnmanaged: Boolean) = localizeImmediately(if (isUnmanaged) "tooltip.DiskModeUnmanaged" else "tooltip.DiskModeManaged")
|
||||
|
||||
def Materials = localizeImmediately("tooltip.Materials")
|
||||
|
||||
def Tier(tier: Int) = localizeImmediately("tooltip.Tier", tier.toString)
|
||||
|
@ -248,10 +248,19 @@ class Settings(val config: Config) {
|
||||
OpenComputers.log.warn("Bad number of HDD sizes, ignoring.")
|
||||
Array(1024, 2048, 4096)
|
||||
}
|
||||
val hddPlatterCounts = Array(config.getIntList("filesystem.hddPlatterCounts"): _*) match {
|
||||
case Array(tier1, tier2, tier3) =>
|
||||
Array(tier1: Int, tier2: Int, tier3: Int)
|
||||
case _ =>
|
||||
OpenComputers.log.warn("Bad number of HDD platter counts, ignoring.")
|
||||
Array(2, 4, 6)
|
||||
}
|
||||
val floppySize = config.getInt("filesystem.floppySize") max 0
|
||||
val tmpSize = config.getInt("filesystem.tmpSize") max 0
|
||||
val maxHandles = config.getInt("filesystem.maxHandles") max 0
|
||||
val maxReadBuffer = config.getInt("filesystem.maxReadBuffer") max 0
|
||||
val sectorSeekThreshold = config.getInt("filesystem.sectorSeekThreshold")
|
||||
val sectorSeekTime = config.getDouble("filesystem.sectorSeekTime")
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
// internet
|
||||
|
@ -58,6 +58,8 @@ object GuiHandler extends CommonGuiHandler {
|
||||
}
|
||||
case Some(GuiType.Category.Item) =>
|
||||
Delegator.subItem(player.getCurrentEquippedItem) match {
|
||||
case Some(drive: item.traits.FileSystemLike) if id == GuiType.Drive.id =>
|
||||
new gui.Drive(player.inventory, () => player.getCurrentEquippedItem)
|
||||
case Some(database: item.UpgradeDatabase) if id == GuiType.Database.id =>
|
||||
new gui.Database(player.inventory, new DatabaseInventory {
|
||||
override def tier = database.tier
|
||||
|
@ -26,6 +26,14 @@ object PacketSender {
|
||||
pb.sendToServer()
|
||||
}
|
||||
|
||||
def sendDriveMode(unmanaged: Boolean) {
|
||||
val pb = new SimplePacketBuilder(PacketType.DriveMode)
|
||||
|
||||
pb.writeBoolean(unmanaged)
|
||||
|
||||
pb.sendToServer()
|
||||
}
|
||||
|
||||
def sendDronePower(e: Drone, power: Boolean) {
|
||||
val pb = new SimplePacketBuilder(PacketType.DronePower)
|
||||
|
||||
|
@ -28,6 +28,7 @@ object Textures {
|
||||
val Background = L("background")
|
||||
val Bar = L("bar")
|
||||
val Borders = L("borders")
|
||||
val ButtonDriveMode = L("button_drive_mode")
|
||||
val ButtonPower = L("button_power")
|
||||
val ButtonRange = L("button_range")
|
||||
val ButtonRun = L("button_run")
|
||||
@ -39,6 +40,7 @@ object Textures {
|
||||
val Database1 = L("database1")
|
||||
val Database2 = L("database2")
|
||||
val Disassembler = L("disassembler")
|
||||
val Drive = L("drive")
|
||||
val Drone = L("drone")
|
||||
val KeyboardMissing = L("keyboard_missing")
|
||||
val Manual = L("manual")
|
||||
|
@ -1,7 +1,5 @@
|
||||
package li.cil.oc.client.gui
|
||||
|
||||
import java.util
|
||||
|
||||
import li.cil.oc.Localization
|
||||
import li.cil.oc.client.Textures
|
||||
import li.cil.oc.client.gui.widget.ProgressBar
|
||||
@ -36,17 +34,13 @@ class Assembler(playerInventory: InventoryPlayer, val assembler: tileentity.Asse
|
||||
|
||||
var info: Option[(Boolean, IChatComponent, Array[IChatComponent])] = None
|
||||
|
||||
private def assemblerContainer = inventorySlots.asInstanceOf[container.Assembler]
|
||||
|
||||
protected var runButton: ImageButton = _
|
||||
|
||||
private val progress = addWidget(new ProgressBar(28, 92))
|
||||
|
||||
def add[T](list: util.List[T], value: Any) = list.add(value.asInstanceOf[T])
|
||||
private def validate = AssemblerTemplates.select(inventoryContainer.getSlot(0).getStack).map(_.validate(inventoryContainer.otherInventory))
|
||||
|
||||
private def validate = AssemblerTemplates.select(assemblerContainer.getSlot(0).getStack).map(_.validate(assemblerContainer.otherInventory))
|
||||
|
||||
private def canBuild = !assemblerContainer.isAssembling && validate.exists(_._1)
|
||||
private def canBuild = !inventoryContainer.isAssembling && validate.exists(_._1)
|
||||
|
||||
protected override def actionPerformed(button: GuiButton) {
|
||||
if (button.id == 0 && canBuild) {
|
||||
@ -62,14 +56,14 @@ class Assembler(playerInventory: InventoryPlayer, val assembler: tileentity.Asse
|
||||
|
||||
override def drawSecondaryForegroundLayer(mouseX: Int, mouseY: Int) = {
|
||||
RenderState.pushAttrib()
|
||||
if (!assemblerContainer.isAssembling) {
|
||||
if (!inventoryContainer.isAssembling) {
|
||||
val message =
|
||||
if (!assemblerContainer.getSlot(0).getHasStack) {
|
||||
if (!inventoryContainer.getSlot(0).getHasStack) {
|
||||
Localization.Assembler.InsertTemplate
|
||||
}
|
||||
else info match {
|
||||
case Some((_, value, _)) if value != null => value.getUnformattedText
|
||||
case _ if assemblerContainer.getSlot(0).getHasStack => Localization.Assembler.CollectResult
|
||||
case _ if inventoryContainer.getSlot(0).getHasStack => Localization.Assembler.CollectResult
|
||||
case _ => ""
|
||||
}
|
||||
fontRendererObj.drawString(message, 30, 94, 0x404040)
|
||||
@ -86,8 +80,8 @@ class Assembler(playerInventory: InventoryPlayer, val assembler: tileentity.Asse
|
||||
}
|
||||
else if (isPointInRegion(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))
|
||||
val timeRemaining = formatTime(inventoryContainer.assemblyRemainingTime)
|
||||
tooltip.add(Localization.Assembler.Progress(inventoryContainer.assemblyProgress, timeRemaining))
|
||||
copiedDrawHoveringText(tooltip, mouseX - guiLeft, mouseY - guiTop, fontRendererObj)
|
||||
}
|
||||
RenderState.popAttrib()
|
||||
@ -103,13 +97,11 @@ class Assembler(playerInventory: InventoryPlayer, val assembler: tileentity.Asse
|
||||
RenderState.color(1, 1, 1) // Required under Linux.
|
||||
Textures.bind(Textures.GUI.RobotAssembler)
|
||||
drawTexturedModalRect(guiLeft, guiTop, 0, 0, xSize, ySize)
|
||||
if (assemblerContainer.isAssembling) progress.level = assemblerContainer.assemblyProgress / 100.0
|
||||
if (inventoryContainer.isAssembling) progress.level = inventoryContainer.assemblyProgress / 100.0
|
||||
else progress.level = 0
|
||||
drawWidgets()
|
||||
drawInventorySlots()
|
||||
}
|
||||
|
||||
override protected def drawDisabledSlot(slot: ComponentSlot) {}
|
||||
|
||||
override def doesGuiPauseGame = false
|
||||
}
|
@ -1,7 +1,5 @@
|
||||
package li.cil.oc.client.gui
|
||||
|
||||
import java.util
|
||||
|
||||
import li.cil.oc.Localization
|
||||
import li.cil.oc.client.Textures
|
||||
import li.cil.oc.client.{PacketSender => ClientPacketSender}
|
||||
@ -16,8 +14,6 @@ import scala.collection.convert.WrapAsJava._
|
||||
class Case(playerInventory: InventoryPlayer, val computer: tileentity.Case) extends DynamicGuiContainer(new container.Case(playerInventory, computer)) {
|
||||
protected var powerButton: ImageButton = _
|
||||
|
||||
def add[T](list: util.List[T], value: Any) = list.add(value.asInstanceOf[T])
|
||||
|
||||
protected override def actionPerformed(button: GuiButton) {
|
||||
if (button.id == 0) {
|
||||
ClientPacketSender.sendComputerPower(computer, !computer.isRunning)
|
||||
@ -52,6 +48,4 @@ class Case(playerInventory: InventoryPlayer, val computer: tileentity.Case) exte
|
||||
Textures.bind(Textures.GUI.Computer)
|
||||
drawTexturedModalRect(guiLeft, guiTop, 0, 0, xSize, ySize)
|
||||
}
|
||||
|
||||
override def doesGuiPauseGame = false
|
||||
}
|
@ -14,13 +14,17 @@ import scala.collection.convert.WrapAsScala._
|
||||
// transformations that break things! Such fun. Many annoyed. And yes, this
|
||||
// is a common issue, have a look at EnderIO and Enchanting Plus. They have
|
||||
// to work around this, too.
|
||||
abstract class CustomGuiContainer(container: Container) extends GuiContainer(container) with WidgetContainer {
|
||||
abstract class CustomGuiContainer[C <: Container](val inventoryContainer: C) extends GuiContainer(inventoryContainer) with WidgetContainer {
|
||||
override def windowX = guiLeft
|
||||
|
||||
override def windowY = guiTop
|
||||
|
||||
override def windowZ = zLevel
|
||||
|
||||
override def doesGuiPauseGame = false
|
||||
|
||||
protected def add[T](list: util.List[T], value: Any) = list.add(value.asInstanceOf[T])
|
||||
|
||||
// Pretty much Scalaified copy-pasta from base-class.
|
||||
override def drawHoveringText(text: util.List[_], x: Int, y: Int, font: FontRenderer): Unit = {
|
||||
copiedDrawHoveringText(text, x, y, font)
|
||||
|
@ -6,11 +6,12 @@ import li.cil.oc.common.container
|
||||
import li.cil.oc.common.inventory.DatabaseInventory
|
||||
import li.cil.oc.util.RenderState
|
||||
import net.minecraft.entity.player.InventoryPlayer
|
||||
import net.minecraft.inventory.Slot
|
||||
|
||||
class Database(playerInventory: InventoryPlayer, val databaseInventory: DatabaseInventory) extends DynamicGuiContainer(new container.Database(playerInventory, databaseInventory)) {
|
||||
class Database(playerInventory: InventoryPlayer, val databaseInventory: DatabaseInventory) extends DynamicGuiContainer(new container.Database(playerInventory, databaseInventory)) with traits.LockedHotbar {
|
||||
ySize = 256
|
||||
|
||||
override def lockedStack = databaseInventory.container
|
||||
|
||||
override def drawSecondaryForegroundLayer(mouseX: Int, mouseY: Int) {}
|
||||
|
||||
override protected def drawGuiContainerBackgroundLayer(dt: Float, mouseX: Int, mouseY: Int) {
|
||||
@ -28,14 +29,4 @@ class Database(playerInventory: InventoryPlayer, val databaseInventory: Database
|
||||
drawTexturedModalRect(guiLeft, guiTop, 0, 0, xSize, ySize)
|
||||
}
|
||||
}
|
||||
|
||||
override def doesGuiPauseGame = false
|
||||
|
||||
protected override def handleMouseClick(slot: Slot, slotNumber: Int, button: Int, shift: Int) {
|
||||
if (slot == null || slot.getStack != databaseInventory.container) {
|
||||
super.handleMouseClick(slot, slotNumber, button, shift)
|
||||
}
|
||||
}
|
||||
|
||||
protected override def checkHotbarKeys(slot: Int) = false
|
||||
}
|
||||
|
@ -9,8 +9,6 @@ import li.cil.oc.util.RenderState
|
||||
import net.minecraft.entity.player.InventoryPlayer
|
||||
|
||||
class Disassembler(playerInventory: InventoryPlayer, val disassembler: tileentity.Disassembler) extends DynamicGuiContainer(new container.Disassembler(playerInventory, disassembler)) {
|
||||
private def disassemblerContainer = inventorySlots.asInstanceOf[container.Disassembler]
|
||||
|
||||
val progress = addWidget(new ProgressBar(18, 65))
|
||||
|
||||
override def drawSecondaryForegroundLayer(mouseX: Int, mouseY: Int) = {
|
||||
@ -23,7 +21,7 @@ class Disassembler(playerInventory: InventoryPlayer, val disassembler: tileentit
|
||||
RenderState.color(1, 1, 1)
|
||||
Textures.bind(Textures.GUI.Disassembler)
|
||||
drawTexturedModalRect(guiLeft, guiTop, 0, 0, xSize, ySize)
|
||||
progress.level = disassemblerContainer.disassemblyProgress / 100.0
|
||||
progress.level = inventoryContainer.disassemblyProgress / 100.0
|
||||
drawWidgets()
|
||||
}
|
||||
}
|
||||
|
47
src/main/scala/li/cil/oc/client/gui/Drive.scala
Normal file
47
src/main/scala/li/cil/oc/client/gui/Drive.scala
Normal file
@ -0,0 +1,47 @@
|
||||
package li.cil.oc.client.gui
|
||||
|
||||
import li.cil.oc.Localization
|
||||
import li.cil.oc.client.Textures
|
||||
import li.cil.oc.client.{PacketSender => ClientPacketSender}
|
||||
import li.cil.oc.common.item.data.DriveData
|
||||
import net.minecraft.client.gui.GuiButton
|
||||
import net.minecraft.client.gui.GuiScreen
|
||||
import net.minecraft.entity.player.InventoryPlayer
|
||||
import net.minecraft.item.ItemStack
|
||||
|
||||
class Drive(playerInventory: InventoryPlayer, val driveStack: () => ItemStack) extends GuiScreen with traits.Window {
|
||||
override val windowHeight = 85
|
||||
|
||||
override def backgroundImage = Textures.GUI.Drive
|
||||
|
||||
protected var managedButton: ImageButton = _
|
||||
protected var unmanagedButton: ImageButton = _
|
||||
|
||||
protected override def actionPerformed(button: GuiButton) {
|
||||
if (button.id == 0) {
|
||||
ClientPacketSender.sendDriveMode(false)
|
||||
}
|
||||
if (button.id == 1) {
|
||||
ClientPacketSender.sendDriveMode(true)
|
||||
}
|
||||
}
|
||||
|
||||
override def initGui(): Unit = {
|
||||
super.initGui()
|
||||
managedButton = new ImageButton(0, guiLeft + 11, guiTop + 11, 74, 18, Textures.GUI.ButtonDriveMode, text = Localization.Drive.Managed, textColor = 0x608060, canToggle = true)
|
||||
unmanagedButton = new ImageButton(1, guiLeft + 91, guiTop + 11, 74, 18, Textures.GUI.ButtonDriveMode, text = Localization.Drive.Unmanaged, textColor = 0x608060, canToggle = true)
|
||||
add(buttonList, managedButton)
|
||||
add(buttonList, unmanagedButton)
|
||||
}
|
||||
|
||||
override def updateScreen(): Unit = {
|
||||
unmanagedButton.toggled = new DriveData(driveStack()).isUnmanaged
|
||||
managedButton.toggled = !unmanagedButton.toggled
|
||||
super.updateScreen()
|
||||
}
|
||||
|
||||
override def drawScreen(mouseX: Int, mouseY: Int, dt: Float): Unit = {
|
||||
super.drawScreen(mouseX, mouseY, dt)
|
||||
fontRendererObj.drawSplitString(Localization.Drive.Warning, guiLeft + 7, guiTop + 37, xSize - 16, 0x404040)
|
||||
}
|
||||
}
|
@ -1,7 +1,5 @@
|
||||
package li.cil.oc.client.gui
|
||||
|
||||
import java.util
|
||||
|
||||
import li.cil.oc.Localization
|
||||
import li.cil.oc.client.Textures
|
||||
import li.cil.oc.client.gui.widget.ProgressBar
|
||||
@ -51,8 +49,6 @@ class Drone(playerInventory: InventoryPlayer, val drone: entity.Drone) extends D
|
||||
private val selectionsStates = 17
|
||||
private val selectionStepV = 1 / selectionsStates.toDouble
|
||||
|
||||
def add[T](list: util.List[T], value: Any) = list.add(value.asInstanceOf[T])
|
||||
|
||||
protected override def actionPerformed(button: GuiButton) {
|
||||
if (button.id == 0) {
|
||||
ClientPacketSender.sendDronePower(drone, !drone.isRunning)
|
||||
@ -61,9 +57,9 @@ class Drone(playerInventory: InventoryPlayer, val drone: entity.Drone) extends D
|
||||
|
||||
override def drawScreen(mouseX: Int, mouseY: Int, dt: Float) {
|
||||
powerButton.toggled = drone.isRunning
|
||||
bufferRenderer.dirty = drone.statusText.lines.zipWithIndex.map {
|
||||
bufferRenderer.dirty = drone.statusText.lines.zipWithIndex.exists {
|
||||
case (line, i) => buffer.set(0, i, line, vertical = false)
|
||||
}.contains(true)
|
||||
}
|
||||
super.drawScreen(mouseX, mouseY, dt)
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,7 @@ import org.lwjgl.opengl.GL11
|
||||
|
||||
import scala.collection.convert.WrapAsScala._
|
||||
|
||||
abstract class DynamicGuiContainer(container: Container) extends CustomGuiContainer(container) {
|
||||
abstract class DynamicGuiContainer[C <: Container](container: C) extends CustomGuiContainer(container) {
|
||||
protected var hoveredSlot: Option[Slot] = None
|
||||
|
||||
protected var hoveredStackNEI: Option[ItemStack] = None
|
||||
|
@ -1,7 +1,5 @@
|
||||
package li.cil.oc.client.gui
|
||||
|
||||
import java.util
|
||||
|
||||
import li.cil.oc.Localization
|
||||
import li.cil.oc.api
|
||||
import li.cil.oc.client.Textures
|
||||
@ -10,17 +8,15 @@ import li.cil.oc.client.renderer.markdown.segment.InteractiveSegment
|
||||
import li.cil.oc.client.renderer.markdown.segment.Segment
|
||||
import li.cil.oc.client.{Manual => ManualAPI}
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.gui.Gui
|
||||
import net.minecraft.client.gui.GuiButton
|
||||
import net.minecraft.client.gui.GuiScreen
|
||||
import net.minecraft.client.gui.ScaledResolution
|
||||
import org.lwjgl.input.Mouse
|
||||
import org.lwjgl.opengl.GL11
|
||||
|
||||
import scala.collection.convert.WrapAsJava._
|
||||
import scala.collection.convert.WrapAsScala._
|
||||
|
||||
class Manual extends GuiScreen {
|
||||
class Manual extends GuiScreen with traits.Window {
|
||||
final val documentMaxWidth = 230
|
||||
final val documentMaxHeight = 176
|
||||
final val scrollPosX = 244
|
||||
@ -33,10 +29,11 @@ class Manual extends GuiScreen {
|
||||
final val tabHeight = 26
|
||||
final val maxTabsPerSide = 7
|
||||
|
||||
var guiLeft = 0
|
||||
var guiTop = 0
|
||||
var xSize = 0
|
||||
var ySize = 0
|
||||
override val windowWidth = 256
|
||||
override val windowHeight = 192
|
||||
|
||||
override def backgroundImage = Textures.GUI.Manual
|
||||
|
||||
var isDragging = false
|
||||
var document: Segment = null
|
||||
var documentHeight = 0
|
||||
@ -49,8 +46,6 @@ class Manual extends GuiScreen {
|
||||
|
||||
def maxOffset = documentHeight - documentMaxHeight
|
||||
|
||||
def add[T](list: util.List[T], value: Any) = list.add(value.asInstanceOf[T])
|
||||
|
||||
def resolveLink(path: String, current: String): String =
|
||||
if (path.startsWith("/")) path
|
||||
else {
|
||||
@ -84,8 +79,6 @@ class Manual extends GuiScreen {
|
||||
}
|
||||
}
|
||||
|
||||
override def doesGuiPauseGame = false
|
||||
|
||||
override def actionPerformed(button: GuiButton): Unit = {
|
||||
if (button.id >= 0 && button.id < ManualAPI.tabs.length) {
|
||||
api.Manual.navigate(ManualAPI.tabs(button.id).path)
|
||||
@ -95,14 +88,6 @@ class Manual extends GuiScreen {
|
||||
override def initGui(): Unit = {
|
||||
super.initGui()
|
||||
|
||||
val screenSize = new ScaledResolution(mc, mc.displayWidth, mc.displayHeight)
|
||||
val guiSize = new ScaledResolution(mc, 256, 192)
|
||||
val (midX, midY) = (screenSize.getScaledWidth / 2, screenSize.getScaledHeight / 2)
|
||||
guiLeft = midX - guiSize.getScaledWidth / 2
|
||||
guiTop = midY - guiSize.getScaledHeight / 2
|
||||
xSize = guiSize.getScaledWidth
|
||||
ySize = guiSize.getScaledHeight
|
||||
|
||||
for ((tab, i) <- ManualAPI.tabs.zipWithIndex if i < maxTabsPerSide) {
|
||||
val x = guiLeft + tabPosX
|
||||
val y = guiTop + tabPosY + i * (tabHeight - 1)
|
||||
@ -116,14 +101,11 @@ class Manual extends GuiScreen {
|
||||
}
|
||||
|
||||
override def drawScreen(mouseX: Int, mouseY: Int, dt: Float): Unit = {
|
||||
Textures.bind(Textures.GUI.Manual)
|
||||
Gui.drawModalRectWithCustomSizedTexture(guiLeft, guiTop, 0, 0, xSize, ySize, 256, 192)
|
||||
super.drawScreen(mouseX, mouseY, dt)
|
||||
|
||||
scrollButton.enabled = canScroll
|
||||
scrollButton.hoverOverride = isDragging
|
||||
|
||||
super.drawScreen(mouseX, mouseY, dt)
|
||||
|
||||
for ((tab, i) <- ManualAPI.tabs.zipWithIndex if i < maxTabsPerSide) {
|
||||
val button = buttonList.get(i).asInstanceOf[ImageButton]
|
||||
GL11.glPushMatrix()
|
||||
|
@ -8,7 +8,6 @@ import li.cil.oc.common.container.ComponentSlot
|
||||
import li.cil.oc.common.tileentity
|
||||
import li.cil.oc.util.RenderState
|
||||
import net.minecraft.entity.player.InventoryPlayer
|
||||
import org.lwjgl.opengl.GL11
|
||||
|
||||
class Printer(playerInventory: InventoryPlayer, val printer: tileentity.Printer) extends DynamicGuiContainer(new container.Printer(playerInventory, printer)) {
|
||||
xSize = 176
|
||||
@ -36,8 +35,6 @@ class Printer(playerInventory: InventoryPlayer, val printer: tileentity.Printer)
|
||||
override def barTexture = Textures.GUI.PrinterProgress
|
||||
})
|
||||
|
||||
private def printerContainer = inventorySlots.asInstanceOf[container.Printer]
|
||||
|
||||
override def initGui() {
|
||||
super.initGui()
|
||||
}
|
||||
@ -50,12 +47,12 @@ class Printer(playerInventory: InventoryPlayer, val printer: tileentity.Printer)
|
||||
RenderState.pushAttrib()
|
||||
if (isPointInRegion(materialBar.x, materialBar.y, materialBar.width, materialBar.height, mouseX, mouseY)) {
|
||||
val tooltip = new java.util.ArrayList[String]
|
||||
tooltip.add(printerContainer.amountMaterial + "/" + printer.maxAmountMaterial)
|
||||
tooltip.add(inventoryContainer.amountMaterial + "/" + printer.maxAmountMaterial)
|
||||
copiedDrawHoveringText(tooltip, mouseX - guiLeft, mouseY - guiTop, fontRendererObj)
|
||||
}
|
||||
if (isPointInRegion(inkBar.x, inkBar.y, inkBar.width, inkBar.height, mouseX, mouseY)) {
|
||||
val tooltip = new java.util.ArrayList[String]
|
||||
tooltip.add(printerContainer.amountInk + "/" + printer.maxAmountInk)
|
||||
tooltip.add(inventoryContainer.amountInk + "/" + printer.maxAmountInk)
|
||||
copiedDrawHoveringText(tooltip, mouseX - guiLeft, mouseY - guiTop, fontRendererObj)
|
||||
}
|
||||
RenderState.popAttrib()
|
||||
@ -65,14 +62,12 @@ class Printer(playerInventory: InventoryPlayer, val printer: tileentity.Printer)
|
||||
RenderState.color(1, 1, 1)
|
||||
Textures.bind(Textures.GUI.Printer)
|
||||
drawTexturedModalRect(guiLeft, guiTop, 0, 0, xSize, ySize)
|
||||
materialBar.level = printerContainer.amountMaterial / printer.maxAmountMaterial.toDouble
|
||||
inkBar.level = printerContainer.amountInk / printer.maxAmountInk.toDouble
|
||||
progressBar.level = printerContainer.progress
|
||||
materialBar.level = inventoryContainer.amountMaterial / printer.maxAmountMaterial.toDouble
|
||||
inkBar.level = inventoryContainer.amountInk / printer.maxAmountInk.toDouble
|
||||
progressBar.level = inventoryContainer.progress
|
||||
drawWidgets()
|
||||
drawInventorySlots()
|
||||
}
|
||||
|
||||
override protected def drawDisabledSlot(slot: ComponentSlot) {}
|
||||
|
||||
override def doesGuiPauseGame = false
|
||||
}
|
@ -1,7 +1,5 @@
|
||||
package li.cil.oc.client.gui
|
||||
|
||||
import java.util
|
||||
|
||||
import li.cil.oc.Localization
|
||||
import li.cil.oc.Settings
|
||||
import li.cil.oc.api
|
||||
@ -77,8 +75,6 @@ class Robot(playerInventory: InventoryPlayer, val robot: tileentity.Robot) exten
|
||||
private val selectionsStates = 17
|
||||
private val selectionStepV = 1 / selectionsStates.toDouble
|
||||
|
||||
def add[T](list: util.List[T], value: Any) = list.add(value.asInstanceOf[T])
|
||||
|
||||
protected override def actionPerformed(button: GuiButton) {
|
||||
if (button.id == 0) {
|
||||
ClientPacketSender.sendComputerPower(robot, !robot.isRunning)
|
||||
|
@ -6,9 +6,10 @@ import li.cil.oc.common.container
|
||||
import li.cil.oc.common.inventory.ServerInventory
|
||||
import li.cil.oc.util.RenderState
|
||||
import net.minecraft.entity.player.InventoryPlayer
|
||||
import net.minecraft.inventory.Slot
|
||||
|
||||
class Server(playerInventory: InventoryPlayer, serverInventory: ServerInventory) extends DynamicGuiContainer(new container.Server(playerInventory, serverInventory)) {
|
||||
class Server(playerInventory: InventoryPlayer, serverInventory: ServerInventory) extends DynamicGuiContainer(new container.Server(playerInventory, serverInventory)) with traits.LockedHotbar {
|
||||
override def lockedStack = serverInventory.container
|
||||
|
||||
override def drawSecondaryForegroundLayer(mouseX: Int, mouseY: Int) {
|
||||
super.drawSecondaryForegroundLayer(mouseX, mouseY)
|
||||
fontRendererObj.drawString(
|
||||
@ -21,14 +22,4 @@ class Server(playerInventory: InventoryPlayer, serverInventory: ServerInventory)
|
||||
Textures.bind(Textures.GUI.Server)
|
||||
drawTexturedModalRect(guiLeft, guiTop, 0, 0, xSize, ySize)
|
||||
}
|
||||
|
||||
override def doesGuiPauseGame = false
|
||||
|
||||
protected override def handleMouseClick(slot: Slot, slotNumber: Int, button: Int, shift: Int) {
|
||||
if (slot == null || slot.getStack != serverInventory.container) {
|
||||
super.handleMouseClick(slot, slotNumber, button, shift)
|
||||
}
|
||||
}
|
||||
|
||||
protected override def checkHotbarKeys(slot: Int) = false
|
||||
}
|
@ -1,7 +1,5 @@
|
||||
package li.cil.oc.client.gui
|
||||
|
||||
import java.util
|
||||
|
||||
import li.cil.oc.Localization
|
||||
import li.cil.oc.Settings
|
||||
import li.cil.oc.client.Textures
|
||||
@ -35,8 +33,6 @@ class ServerRack(playerInventory: InventoryPlayer, val rack: tileentity.ServerRa
|
||||
case _ => Localization.ServerRack.None
|
||||
}
|
||||
|
||||
def add[T](list: util.List[T], value: Any) = list.add(value.asInstanceOf[T])
|
||||
|
||||
protected override def actionPerformed(button: GuiButton) {
|
||||
if (button.id >= 0 && button.id <= 3) {
|
||||
ClientPacketSender.sendServerPower(rack, button.id, !rack.isRunning(button.id))
|
||||
@ -46,7 +42,7 @@ class ServerRack(playerInventory: InventoryPlayer, val rack: tileentity.ServerRa
|
||||
val sides = EnumFacing.values.map(Option(_)) ++ Seq(None)
|
||||
val currentSide = sides.indexOf(rack.sides(number))
|
||||
val searchSides = sides.drop(currentSide + 1) ++ sides.take(currentSide + 1)
|
||||
val nextSide = searchSides.find(side => side != Option(EnumFacing.SOUTH) && (!rack.sides.contains(side) || side == None)) match {
|
||||
val nextSide = searchSides.find(side => side != Option(EnumFacing.SOUTH) && (!rack.sides.contains(side) || side.isEmpty)) match {
|
||||
case Some(side) => side
|
||||
case _ => None
|
||||
}
|
||||
|
@ -8,7 +8,6 @@ import li.cil.oc.common.tileentity
|
||||
import net.minecraft.entity.player.InventoryPlayer
|
||||
|
||||
class Switch(playerInventory: InventoryPlayer, val switch: tileentity.Switch) extends DynamicGuiContainer(new container.Switch(playerInventory, switch)) {
|
||||
private val switchContainer = inventorySlots.asInstanceOf[container.Switch]
|
||||
private val format = new DecimalFormat("#.##hz")
|
||||
|
||||
override def drawSecondaryForegroundLayer(mouseX: Int, mouseY: Int) = {
|
||||
@ -28,14 +27,14 @@ class Switch(playerInventory: InventoryPlayer, val switch: tileentity.Switch) ex
|
||||
14, 58, 0x404040)
|
||||
|
||||
fontRendererObj.drawString(
|
||||
format.format(20f / switchContainer.relayDelay),
|
||||
format.format(20f / inventoryContainer.relayDelay),
|
||||
108, 20, 0x404040)
|
||||
fontRendererObj.drawString(
|
||||
switchContainer.packetsPerCycleAvg + " / " + switchContainer.relayAmount,
|
||||
108, 39, thresholdBasedColor(switchContainer.packetsPerCycleAvg, math.ceil(switchContainer.relayAmount / 2f).toInt, switchContainer.relayAmount))
|
||||
inventoryContainer.packetsPerCycleAvg + " / " + inventoryContainer.relayAmount,
|
||||
108, 39, thresholdBasedColor(inventoryContainer.packetsPerCycleAvg, math.ceil(inventoryContainer.relayAmount / 2f).toInt, inventoryContainer.relayAmount))
|
||||
fontRendererObj.drawString(
|
||||
switchContainer.queueSize + " / " + switchContainer.maxQueueSize,
|
||||
108, 58, thresholdBasedColor(switchContainer.queueSize, switchContainer.maxQueueSize / 2, switchContainer.maxQueueSize))
|
||||
inventoryContainer.queueSize + " / " + inventoryContainer.maxQueueSize,
|
||||
108, 58, thresholdBasedColor(inventoryContainer.queueSize, inventoryContainer.maxQueueSize / 2, inventoryContainer.maxQueueSize))
|
||||
}
|
||||
|
||||
private def thresholdBasedColor(value: Int, yellow: Int, red: Int) = {
|
||||
|
@ -4,23 +4,14 @@ import li.cil.oc.Localization
|
||||
import li.cil.oc.common.container
|
||||
import li.cil.oc.common.item.TabletWrapper
|
||||
import net.minecraft.entity.player.InventoryPlayer
|
||||
import net.minecraft.inventory.Slot
|
||||
|
||||
class Tablet(playerInventory: InventoryPlayer, val tablet: TabletWrapper) extends DynamicGuiContainer(new container.Tablet(playerInventory, tablet)) {
|
||||
class Tablet(playerInventory: InventoryPlayer, val tablet: TabletWrapper) extends DynamicGuiContainer(new container.Tablet(playerInventory, tablet)) with traits.LockedHotbar {
|
||||
override def lockedStack = tablet.stack
|
||||
|
||||
override def drawSecondaryForegroundLayer(mouseX: Int, mouseY: Int) = {
|
||||
super.drawSecondaryForegroundLayer(mouseX, mouseY)
|
||||
fontRendererObj.drawString(
|
||||
Localization.localizeImmediately(tablet.getName),
|
||||
8, 6, 0x404040)
|
||||
}
|
||||
|
||||
override def doesGuiPauseGame = false
|
||||
|
||||
protected override def handleMouseClick(slot: Slot, slotNumber: Int, button: Int, shift: Int) {
|
||||
if (slot == null || slot.getStack != tablet.stack) {
|
||||
super.handleMouseClick(slot, slotNumber, button, shift)
|
||||
}
|
||||
}
|
||||
|
||||
protected override def checkHotbarKeys(slot: Int) = false
|
||||
}
|
||||
|
@ -0,0 +1,17 @@
|
||||
package li.cil.oc.client.gui.traits
|
||||
|
||||
import net.minecraft.client.gui.inventory.GuiContainer
|
||||
import net.minecraft.inventory.Slot
|
||||
import net.minecraft.item.ItemStack
|
||||
|
||||
trait LockedHotbar extends GuiContainer {
|
||||
def lockedStack: ItemStack
|
||||
|
||||
protected override def handleMouseClick(slot: Slot, slotNumber: Int, button: Int, shift: Int) {
|
||||
if (slot == null || slot.getStack != lockedStack) {
|
||||
super.handleMouseClick(slot, slotNumber, button, shift)
|
||||
}
|
||||
}
|
||||
|
||||
protected override def checkHotbarKeys(keyCode: Int) = false
|
||||
}
|
44
src/main/scala/li/cil/oc/client/gui/traits/Window.scala
Normal file
44
src/main/scala/li/cil/oc/client/gui/traits/Window.scala
Normal file
@ -0,0 +1,44 @@
|
||||
package li.cil.oc.client.gui.traits
|
||||
|
||||
import java.util
|
||||
|
||||
import net.minecraft.client.gui.Gui
|
||||
import net.minecraft.client.gui.GuiScreen
|
||||
import net.minecraft.client.gui.ScaledResolution
|
||||
import net.minecraft.util.ResourceLocation
|
||||
|
||||
trait Window extends GuiScreen {
|
||||
var guiLeft = 0
|
||||
var guiTop = 0
|
||||
var xSize = 0
|
||||
var ySize = 0
|
||||
|
||||
val windowWidth = 176
|
||||
val windowHeight = 166
|
||||
|
||||
def backgroundImage: ResourceLocation
|
||||
|
||||
protected def add[T](list: util.List[T], value: Any) = list.add(value.asInstanceOf[T])
|
||||
|
||||
override def doesGuiPauseGame = false
|
||||
|
||||
override def initGui(): Unit = {
|
||||
super.initGui()
|
||||
|
||||
val screenSize = new ScaledResolution(mc, mc.displayWidth, mc.displayHeight)
|
||||
val guiSize = new ScaledResolution(mc, windowWidth, windowHeight)
|
||||
val (midX, midY) = (screenSize.getScaledWidth / 2, screenSize.getScaledHeight / 2)
|
||||
guiLeft = midX - guiSize.getScaledWidth / 2
|
||||
guiTop = midY - guiSize.getScaledHeight / 2
|
||||
xSize = guiSize.getScaledWidth
|
||||
ySize = guiSize.getScaledHeight
|
||||
}
|
||||
|
||||
override def drawScreen(mouseX: Int, mouseY: Int, dt: Float): Unit = {
|
||||
mc.renderEngine.bindTexture(backgroundImage)
|
||||
Gui.drawModalRectWithCustomSizedTexture(guiLeft, guiTop, 0, 0, xSize, ySize, windowWidth, windowHeight)
|
||||
|
||||
super.drawScreen(mouseX, mouseY, dt)
|
||||
}
|
||||
|
||||
}
|
@ -303,8 +303,12 @@ object EventHandler {
|
||||
else false
|
||||
}
|
||||
|
||||
// This is called from the ServerThread *and* the ClientShutdownThread, which
|
||||
// can potentially happen at the same time... for whatever reason. So let's
|
||||
// synchronize what we're doing here to avoid race conditions (e.g. when
|
||||
// disposing networks, where this actually triggered an assert).
|
||||
@SubscribeEvent
|
||||
def onWorldUnload(e: WorldEvent.Unload) {
|
||||
def onWorldUnload(e: WorldEvent.Unload): Unit = this.synchronized {
|
||||
if (!e.world.isRemote) {
|
||||
e.world.loadedTileEntityList.collect {
|
||||
case te: tileentity.traits.TileEntity => te.dispose()
|
||||
|
@ -22,6 +22,7 @@ object GuiType extends ScalaEnum {
|
||||
val Database = new EnumVal { def name = "Database"; def subType = GuiType.Category.Item }
|
||||
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 Drive = new EnumVal { def name = "Drive"; def subType = GuiType.Category.Item }
|
||||
val Drone = new EnumVal { def name = "Drone"; def subType = GuiType.Category.Entity }
|
||||
val Manual = new EnumVal { def name = "Manual"; def subType = GuiType.Category.None }
|
||||
val Printer = new EnumVal { def name = "Printer"; def subType = GuiType.Category.Block }
|
||||
|
@ -59,6 +59,7 @@ object PacketType extends Enumeration {
|
||||
// Client -> Server
|
||||
ComputerPower,
|
||||
CopyToAnalyzer,
|
||||
DriveMode,
|
||||
DronePower,
|
||||
KeyDown,
|
||||
KeyUp,
|
||||
|
@ -232,7 +232,7 @@ object SaveHandler {
|
||||
// systems, to avoid deleting in-use folders here.
|
||||
System.currentTimeMillis() - file.lastModified() > TimeToHoldOntoOldSaves && {
|
||||
val list = file.list()
|
||||
list == null || list.length == 0
|
||||
list == null || list.isEmpty
|
||||
}
|
||||
})
|
||||
if (emptyDirs != null) {
|
||||
|
@ -1,32 +1,19 @@
|
||||
package li.cil.oc.common.item
|
||||
|
||||
import java.util
|
||||
|
||||
import li.cil.oc.Constants
|
||||
import li.cil.oc.Settings
|
||||
import li.cil.oc.util.Color
|
||||
import net.minecraft.client.resources.model.ModelBakery
|
||||
import net.minecraft.client.resources.model.ModelResourceLocation
|
||||
import net.minecraft.entity.player.EntityPlayer
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraftforge.fml.relauncher.Side
|
||||
import net.minecraftforge.fml.relauncher.SideOnly
|
||||
|
||||
class FloppyDisk(val parent: Delegator) extends traits.Delegate with CustomModel {
|
||||
class FloppyDisk(val parent: Delegator) extends traits.Delegate with CustomModel with traits.FileSystemLike {
|
||||
// Necessary for anonymous subclasses used for loot disks.
|
||||
override def unlocalizedName = "FloppyDisk"
|
||||
|
||||
override protected def tooltipName = None
|
||||
|
||||
override def tooltipLines(stack: ItemStack, player: EntityPlayer, tooltip: util.List[String], advanced: Boolean) = {
|
||||
if (stack.hasTagCompound && stack.getTagCompound.hasKey(Settings.namespace + "data")) {
|
||||
val nbt = stack.getTagCompound.getCompoundTag(Settings.namespace + "data")
|
||||
if (nbt.hasKey(Settings.namespace + "fs.label")) {
|
||||
tooltip.add(nbt.getString(Settings.namespace + "fs.label"))
|
||||
}
|
||||
}
|
||||
super.tooltipLines(stack, player, tooltip, advanced)
|
||||
}
|
||||
val kiloBytes = Settings.get.floppySize
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
private def modelLocationFromDyeName(name: String) = {
|
||||
|
@ -1,36 +1,12 @@
|
||||
package li.cil.oc.common.item
|
||||
|
||||
import java.util
|
||||
|
||||
import li.cil.oc.Settings
|
||||
import net.minecraft.entity.player.EntityPlayer
|
||||
import net.minecraft.item.ItemStack
|
||||
|
||||
class HardDiskDrive(val parent: Delegator, val tier: Int) extends traits.Delegate with traits.ItemTier {
|
||||
class HardDiskDrive(val parent: Delegator, val tier: Int) extends traits.Delegate with traits.ItemTier with traits.FileSystemLike {
|
||||
override val unlocalizedName = super.unlocalizedName + tier
|
||||
val kiloBytes = Settings.get.hddSizes(tier)
|
||||
|
||||
override protected def tooltipName = None
|
||||
|
||||
override def tooltipLines(stack: ItemStack, player: EntityPlayer, tooltip: util.List[String], advanced: Boolean) = {
|
||||
if (stack.hasTagCompound) {
|
||||
val nbt = stack.getTagCompound
|
||||
if (nbt.hasKey(Settings.namespace + "data")) {
|
||||
val data = nbt.getCompoundTag(Settings.namespace + "data")
|
||||
if (data.hasKey(Settings.namespace + "fs.label")) {
|
||||
tooltip.add(data.getString(Settings.namespace + "fs.label"))
|
||||
}
|
||||
if (advanced && data.hasKey("fs")) {
|
||||
val fsNbt = data.getCompoundTag("fs")
|
||||
if (fsNbt.hasKey("capacity.used")) {
|
||||
val used = fsNbt.getLong("capacity.used")
|
||||
tooltip.add(s"Disk usage: $used/${kiloBytes * 1024} Byte")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
super.tooltipLines(stack, player, tooltip, advanced)
|
||||
}
|
||||
val platterCount = Settings.get.hddPlatterCounts(tier)
|
||||
|
||||
override def displayName(stack: ItemStack) = {
|
||||
val localizedName = parent.internalGetItemStackDisplayName(stack)
|
||||
|
22
src/main/scala/li/cil/oc/common/item/data/DriveData.scala
Normal file
22
src/main/scala/li/cil/oc/common/item/data/DriveData.scala
Normal file
@ -0,0 +1,22 @@
|
||||
package li.cil.oc.common.item.data
|
||||
|
||||
import li.cil.oc.Settings
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
|
||||
class DriveData extends ItemData(null) {
|
||||
def this(stack: ItemStack) {
|
||||
this()
|
||||
load(stack)
|
||||
}
|
||||
|
||||
var isUnmanaged = false
|
||||
|
||||
override def load(nbt: NBTTagCompound) {
|
||||
isUnmanaged = nbt.getBoolean(Settings.namespace + "unmanaged")
|
||||
}
|
||||
|
||||
override def save(nbt: NBTTagCompound) {
|
||||
nbt.setBoolean(Settings.namespace + "unmanaged", isUnmanaged)
|
||||
}
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
package li.cil.oc.common.item.traits
|
||||
|
||||
import java.util
|
||||
|
||||
import li.cil.oc.Localization
|
||||
import li.cil.oc.OpenComputers
|
||||
import li.cil.oc.Settings
|
||||
import li.cil.oc.common.GuiType
|
||||
import net.minecraft.entity.player.EntityPlayer
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.world.World
|
||||
|
||||
trait FileSystemLike extends Delegate {
|
||||
override protected def tooltipName = None
|
||||
|
||||
def kiloBytes: Int
|
||||
|
||||
override def tooltipLines(stack: ItemStack, player: EntityPlayer, tooltip: util.List[String], advanced: Boolean) = {
|
||||
if (stack.hasTagCompound) {
|
||||
val nbt = stack.getTagCompound
|
||||
if (nbt.hasKey(Settings.namespace + "data")) {
|
||||
val data = nbt.getCompoundTag(Settings.namespace + "data")
|
||||
if (data.hasKey(Settings.namespace + "fs.label")) {
|
||||
tooltip.add(data.getString(Settings.namespace + "fs.label"))
|
||||
}
|
||||
if (advanced && data.hasKey("fs")) {
|
||||
val fsNbt = data.getCompoundTag("fs")
|
||||
if (fsNbt.hasKey("capacity.used")) {
|
||||
val used = fsNbt.getLong("capacity.used")
|
||||
tooltip.add(Localization.Tooltip.DiskUsage(used, kiloBytes * 1024))
|
||||
}
|
||||
}
|
||||
}
|
||||
tooltip.add(Localization.Tooltip.DiskMode(nbt.getBoolean(Settings.namespace + "unmanaged")))
|
||||
}
|
||||
super.tooltipLines(stack, player, tooltip, advanced)
|
||||
}
|
||||
|
||||
override def onItemRightClick(stack: ItemStack, world: World, player: EntityPlayer): ItemStack = {
|
||||
if (!player.isSneaking) {
|
||||
player.openGui(OpenComputers, GuiType.Drive.id, world, 0, 0, 0)
|
||||
player.swingItem()
|
||||
}
|
||||
stack
|
||||
}
|
||||
}
|
@ -10,6 +10,8 @@ import li.cil.oc.common.Slot
|
||||
import li.cil.oc.common.item.Delegator
|
||||
import li.cil.oc.common.item.FloppyDisk
|
||||
import li.cil.oc.common.item.HardDiskDrive
|
||||
import li.cil.oc.common.item.data.DriveData
|
||||
import li.cil.oc.server.component.Drive
|
||||
import li.cil.oc.server.fs.FileSystem.ItemLabel
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
@ -25,8 +27,8 @@ object DriverFileSystem extends Item {
|
||||
|
||||
override def createEnvironment(stack: ItemStack, host: EnvironmentHost) =
|
||||
Delegator.subItem(stack) match {
|
||||
case Some(hdd: HardDiskDrive) => createEnvironment(stack, hdd.kiloBytes * 1024, host, hdd.tier + 2)
|
||||
case Some(disk: FloppyDisk) => createEnvironment(stack, Settings.get.floppySize * 1024, host, 1)
|
||||
case Some(hdd: HardDiskDrive) => createEnvironment(stack, hdd.kiloBytes * 1024, hdd.platterCount, host, hdd.tier + 2)
|
||||
case Some(disk: FloppyDisk) => createEnvironment(stack, Settings.get.floppySize * 1024, 1, host, 1)
|
||||
case _ => null
|
||||
}
|
||||
|
||||
@ -43,7 +45,7 @@ object DriverFileSystem extends Item {
|
||||
case _ => 0
|
||||
}
|
||||
|
||||
private def createEnvironment(stack: ItemStack, capacity: Int, host: EnvironmentHost, speed: Int) = if (DimensionManager.getWorld(0) != null) {
|
||||
private def createEnvironment(stack: ItemStack, capacity: Int, platterCount: Int, host: EnvironmentHost, speed: Int) = if (DimensionManager.getWorld(0) != null) {
|
||||
if (stack.hasTagCompound && stack.getTagCompound.hasKey(Settings.namespace + "lootFactory")) {
|
||||
// Loot disk, create file system using factory callback.
|
||||
Loot.factories.get(stack.getTagCompound.getString(Settings.namespace + "lootFactory")) match {
|
||||
@ -61,9 +63,17 @@ object DriverFileSystem extends Item {
|
||||
// node's address as the folder name... so we generate the address here,
|
||||
// if necessary. No one will know, right? Right!?
|
||||
val address = addressFromTag(dataTag(stack))
|
||||
val label = new ReadWriteItemLabel(stack)
|
||||
val isFloppy = api.Items.get(stack) == api.Items.get(Constants.ItemName.Floppy)
|
||||
val fs = oc.api.FileSystem.fromSaveDirectory(address, capacity, Settings.get.bufferChanges)
|
||||
val environment = oc.api.FileSystem.asManagedEnvironment(fs, new ReadWriteItemLabel(stack), host, Settings.resourceDomain + ":" + (if (isFloppy) "floppy_access" else "hdd_access"), speed)
|
||||
val sound = Settings.resourceDomain + ":" + (if (isFloppy) "floppy_access" else "hdd_access")
|
||||
val drive = new DriveData(stack)
|
||||
val environment = if (drive.isUnmanaged) {
|
||||
Drive(capacity, platterCount, label, Option(host), Option(sound), speed)
|
||||
}
|
||||
else {
|
||||
val fs = oc.api.FileSystem.fromSaveDirectory(address, capacity, Settings.get.bufferChanges)
|
||||
oc.api.FileSystem.asManagedEnvironment(fs, label, host, sound, speed)
|
||||
}
|
||||
if (environment != null && environment.node != null) {
|
||||
environment.node.asInstanceOf[oc.server.network.Node].address = address
|
||||
}
|
||||
|
@ -8,6 +8,9 @@ import li.cil.oc.common.Achievement
|
||||
import li.cil.oc.common.PacketType
|
||||
import li.cil.oc.common.component.TextBuffer
|
||||
import li.cil.oc.common.entity.Drone
|
||||
import li.cil.oc.common.item.Delegator
|
||||
import li.cil.oc.common.item.data.DriveData
|
||||
import li.cil.oc.common.item.traits.FileSystemLike
|
||||
import li.cil.oc.common.tileentity._
|
||||
import li.cil.oc.common.tileentity.traits.Computer
|
||||
import li.cil.oc.common.tileentity.traits.TileEntity
|
||||
@ -38,6 +41,7 @@ object PacketHandler extends CommonPacketHandler {
|
||||
p.packetType match {
|
||||
case PacketType.ComputerPower => onComputerPower(p)
|
||||
case PacketType.CopyToAnalyzer => onCopyToAnalyzer(p)
|
||||
case PacketType.DriveMode => onDriveMode(p)
|
||||
case PacketType.DronePower => onDronePower(p)
|
||||
case PacketType.KeyDown => onKeyDown(p)
|
||||
case PacketType.KeyUp => onKeyUp(p)
|
||||
@ -83,6 +87,18 @@ object PacketHandler extends CommonPacketHandler {
|
||||
}
|
||||
}
|
||||
|
||||
def onDriveMode(p: PacketParser) = p.player match {
|
||||
case player: EntityPlayerMP =>
|
||||
Delegator.subItem(player.getCurrentEquippedItem) match {
|
||||
case Some(drive: FileSystemLike) =>
|
||||
val data = new DriveData(player.getCurrentEquippedItem)
|
||||
data.isUnmanaged = p.readBoolean()
|
||||
data.save(player.getCurrentEquippedItem)
|
||||
case _ => // Invalid packet.
|
||||
}
|
||||
case _ => // Invalid packet.
|
||||
}
|
||||
|
||||
def onDronePower(p: PacketParser) =
|
||||
p.readEntity[Drone]() match {
|
||||
case Some(drone) => p.player match {
|
||||
|
268
src/main/scala/li/cil/oc/server/component/Drive.scala
Normal file
268
src/main/scala/li/cil/oc/server/component/Drive.scala
Normal file
@ -0,0 +1,268 @@
|
||||
package li.cil.oc.server.component
|
||||
|
||||
import java.io
|
||||
import java.io.ByteArrayInputStream
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.util.zip.GZIPInputStream
|
||||
import java.util.zip.GZIPOutputStream
|
||||
|
||||
import com.google.common.io.Files
|
||||
import li.cil.oc.OpenComputers
|
||||
import li.cil.oc.Settings
|
||||
import li.cil.oc.api.Network
|
||||
import li.cil.oc.api.driver.EnvironmentHost
|
||||
import li.cil.oc.api.fs.Label
|
||||
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.Visibility
|
||||
import li.cil.oc.api.prefab
|
||||
import li.cil.oc.server.{PacketSender => ServerPacketSender}
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
import net.minecraftforge.common.DimensionManager
|
||||
|
||||
class Drive(val capacity: Int, val platterCount: Int, val label: Label, host: Option[EnvironmentHost], val sound: Option[String]) extends prefab.ManagedEnvironment {
|
||||
override val node = Network.newNode(this, Visibility.Network).
|
||||
withComponent("drive", Visibility.Neighbors).
|
||||
withConnector().
|
||||
create()
|
||||
|
||||
private def savePath = new io.File(DimensionManager.getCurrentSaveRootDirectory, Settings.savePath + node.address + ".bin")
|
||||
|
||||
private final val sectorSize = 512
|
||||
|
||||
private val data = new Array[Byte](capacity)
|
||||
|
||||
private val sectorCount = capacity / sectorSize
|
||||
|
||||
private val sectorsPerPlatter = sectorCount / platterCount
|
||||
|
||||
private var headPos = 0
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
@Callback(direct = true, doc = """function():string -- Get the current label of the drive.""")
|
||||
def getLabel(context: Context, args: Arguments): Array[AnyRef] = this.synchronized {
|
||||
if (label != null) result(label.getLabel) else null
|
||||
}
|
||||
|
||||
@Callback(doc = """function(value:string):string -- Sets the label of the drive. Returns the new value, which may be truncated.""")
|
||||
def setLabel(context: Context, args: Arguments): Array[AnyRef] = this.synchronized {
|
||||
if (label == null) throw new Exception("drive does not support labeling")
|
||||
if (args.checkAny(0) == null) label.setLabel(null)
|
||||
else label.setLabel(args.checkString(0))
|
||||
result(label.getLabel)
|
||||
}
|
||||
|
||||
@Callback(direct = true, doc = """function():number -- Returns the total capacity of the drive, in bytes.""")
|
||||
def getCapacity(context: Context, args: Arguments): Array[AnyRef] = result(capacity)
|
||||
|
||||
@Callback(direct = true, doc = """function():number -- Returns the size of a single sector on the drive, in bytes.""")
|
||||
def getSectorSize(context: Context, args: Arguments): Array[AnyRef] = result(sectorSize)
|
||||
|
||||
@Callback(direct = true, doc = """function():number -- Returns the number of platters in the drive.""")
|
||||
def getPlatterCount(context: Context, args: Arguments): Array[AnyRef] = result(platterCount)
|
||||
|
||||
def readSector(context: Context, args: Arguments): Array[AnyRef] = this.synchronized {
|
||||
val sector = moveToSector(context, checkSector(args, 0))
|
||||
diskActivity()
|
||||
val sectorData = new Array[Byte](sectorSize)
|
||||
Array.copy(data, sectorOffset(sector), sectorData, 0, sectorSize)
|
||||
result(sectorData)
|
||||
}
|
||||
|
||||
def writeSector(context: Context, args: Arguments): Array[AnyRef] = this.synchronized {
|
||||
val sectorData = args.checkByteArray(1)
|
||||
val sector = moveToSector(context, checkSector(args, 0))
|
||||
diskActivity()
|
||||
Array.copy(sectorData, 0, data, sectorOffset(sector), math.min(sectorSize, sectorData.length))
|
||||
null
|
||||
}
|
||||
|
||||
def readByte(context: Context, args: Arguments): Array[AnyRef] = this.synchronized {
|
||||
val offset = args.checkInteger(0) - 1
|
||||
moveToSector(context, checkSector(offset))
|
||||
diskActivity()
|
||||
result(data(offset))
|
||||
}
|
||||
|
||||
def writeByte(context: Context, args: Arguments): Array[AnyRef] = this.synchronized {
|
||||
val offset = args.checkInteger(0) - 1
|
||||
val value = args.checkInteger(1).toByte
|
||||
moveToSector(context, checkSector(offset))
|
||||
diskActivity()
|
||||
data(offset) = value
|
||||
null
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
override def load(nbt: NBTTagCompound) = this.synchronized {
|
||||
super.load(nbt)
|
||||
|
||||
if (node.address != null) try {
|
||||
val path = savePath
|
||||
if (path.exists()) {
|
||||
val bin = new ByteArrayInputStream(Files.toByteArray(path))
|
||||
val zin = new GZIPInputStream(bin)
|
||||
var offset = 0
|
||||
var read = 0
|
||||
while (read >= 0 && offset < data.length) {
|
||||
read = zin.read(data, offset, data.length - offset)
|
||||
offset += read
|
||||
}
|
||||
}
|
||||
}
|
||||
catch {
|
||||
case t: Throwable => OpenComputers.log.warn(s"Failed loading drive contents for '${node.address}'.", t)
|
||||
}
|
||||
|
||||
headPos = nbt.getInteger("headPos") max 0 min sectorToHeadPos(sectorCount)
|
||||
|
||||
if (label != null) {
|
||||
label.load(nbt)
|
||||
}
|
||||
}
|
||||
|
||||
override def save(nbt: NBTTagCompound) = this.synchronized {
|
||||
super.save(nbt)
|
||||
|
||||
if (node.address != null) try {
|
||||
val path = savePath
|
||||
path.getParentFile.mkdirs()
|
||||
val bos = new ByteArrayOutputStream()
|
||||
val zos = new GZIPOutputStream(bos)
|
||||
zos.write(data)
|
||||
zos.close()
|
||||
Files.write(bos.toByteArray, path)
|
||||
}
|
||||
catch {
|
||||
case t: Throwable => OpenComputers.log.warn(s"Failed saving drive contents for '${node.address}'.", t)
|
||||
}
|
||||
|
||||
nbt.setInteger("headPos", headPos)
|
||||
|
||||
if (label != null) {
|
||||
label.save(nbt)
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
private def validateSector(sector: Int) = {
|
||||
if (sector < 0 || sector >= sectorCount)
|
||||
throw new IllegalArgumentException("invalid offset, not in a usable sector")
|
||||
sector
|
||||
}
|
||||
|
||||
private def checkSector(offset: Int) = validateSector(offsetSector(offset))
|
||||
|
||||
private def checkSector(args: Arguments, n: Int) = validateSector(args.checkInteger(n) - 1)
|
||||
|
||||
private def moveToSector(context: Context, sector: Int) = {
|
||||
val newHeadPos = sectorToHeadPos(sector)
|
||||
if (headPos != newHeadPos) {
|
||||
val delta = math.abs(headPos - newHeadPos)
|
||||
if (delta > Settings.get.sectorSeekThreshold) context.pause(Settings.get.sectorSeekTime)
|
||||
headPos = newHeadPos
|
||||
}
|
||||
sector
|
||||
}
|
||||
|
||||
private def sectorToHeadPos(sector: Int) = sector % sectorsPerPlatter
|
||||
|
||||
private def sectorOffset(sector: Int) = sector * sectorSize
|
||||
|
||||
private def offsetSector(offset: Int) = offset / sectorSize
|
||||
|
||||
private def diskActivity() {
|
||||
(sound, host) match {
|
||||
case (Some(s), Some(h)) => ServerPacketSender.sendFileSystemActivity(node, h, s)
|
||||
case _ =>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object Drive {
|
||||
// I really need to come up with a way to make the call limit dynamic...
|
||||
def apply(capacity: Int, platterCount: Int, label: Label, host: Option[EnvironmentHost], sound: Option[String], speed: Int = 1): Drive = speed match {
|
||||
case 6 => new Drive(capacity, platterCount, label, host, sound) {
|
||||
@Callback(direct = true, limit = 60, doc = """function(sector:number):string -- Read the current contents of the specified sector.""")
|
||||
override def readSector(context: Context, args: Arguments): Array[AnyRef] = super.readSector(context, args)
|
||||
|
||||
@Callback(direct = true, limit = 30, doc = """function(sector:number, value:string) -- Write the specified contents to the specified sector.""")
|
||||
override def writeSector(context: Context, args: Arguments): Array[AnyRef] = super.writeSector(context, args)
|
||||
|
||||
@Callback(direct = true, limit = 128, doc = """function(offset:number):number -- Read a single byte at the specified offset.""")
|
||||
override def readByte(context: Context, args: Arguments): Array[AnyRef] = super.readByte(context, args)
|
||||
|
||||
@Callback(direct = true, limit = 64, doc = """function(offset:number, value:number) -- Write a single byte to the specified offset.""")
|
||||
override def writeByte(context: Context, args: Arguments): Array[AnyRef] = super.writeByte(context, args)
|
||||
}
|
||||
case 5 => new Drive(capacity, platterCount, label, host, sound) {
|
||||
@Callback(direct = true, limit = 50, doc = """function(sector:number):string -- Read the current contents of the specified sector.""")
|
||||
override def readSector(context: Context, args: Arguments): Array[AnyRef] = super.readSector(context, args)
|
||||
|
||||
@Callback(direct = true, limit = 25, doc = """function(sector:number, value:string) -- Write the specified contents to the specified sector.""")
|
||||
override def writeSector(context: Context, args: Arguments): Array[AnyRef] = super.writeSector(context, args)
|
||||
|
||||
@Callback(direct = true, limit = 112, doc = """function(offset:number):number -- Read a single byte at the specified offset.""")
|
||||
override def readByte(context: Context, args: Arguments): Array[AnyRef] = super.readByte(context, args)
|
||||
|
||||
@Callback(direct = true, limit = 56, doc = """function(offset:number, value:number) -- Write a single byte to the specified offset.""")
|
||||
override def writeByte(context: Context, args: Arguments): Array[AnyRef] = super.writeByte(context, args)
|
||||
}
|
||||
case 4 => new Drive(capacity, platterCount, label, host, sound) {
|
||||
@Callback(direct = true, limit = 40, doc = """function(sector:number):string -- Read the current contents of the specified sector.""")
|
||||
override def readSector(context: Context, args: Arguments): Array[AnyRef] = super.readSector(context, args)
|
||||
|
||||
@Callback(direct = true, limit = 20, doc = """function(sector:number, value:string) -- Write the specified contents to the specified sector.""")
|
||||
override def writeSector(context: Context, args: Arguments): Array[AnyRef] = super.writeSector(context, args)
|
||||
|
||||
@Callback(direct = true, limit = 96, doc = """function(offset:number):number -- Read a single byte at the specified offset.""")
|
||||
override def readByte(context: Context, args: Arguments): Array[AnyRef] = super.readByte(context, args)
|
||||
|
||||
@Callback(direct = true, limit = 48, doc = """function(offset:number, value:number) -- Write a single byte to the specified offset.""")
|
||||
override def writeByte(context: Context, args: Arguments): Array[AnyRef] = super.writeByte(context, args)
|
||||
}
|
||||
case 3 => new Drive(capacity, platterCount, label, host, sound) {
|
||||
@Callback(direct = true, limit = 30, doc = """function(sector:number):string -- Read the current contents of the specified sector.""")
|
||||
override def readSector(context: Context, args: Arguments): Array[AnyRef] = super.readSector(context, args)
|
||||
|
||||
@Callback(direct = true, limit = 15, doc = """function(sector:number, value:string) -- Write the specified contents to the specified sector.""")
|
||||
override def writeSector(context: Context, args: Arguments): Array[AnyRef] = super.writeSector(context, args)
|
||||
|
||||
@Callback(direct = true, limit = 80, doc = """function(offset:number):number -- Read a single byte at the specified offset.""")
|
||||
override def readByte(context: Context, args: Arguments): Array[AnyRef] = super.readByte(context, args)
|
||||
|
||||
@Callback(direct = true, limit = 40, doc = """function(offset:number, value:number) -- Write a single byte to the specified offset.""")
|
||||
override def writeByte(context: Context, args: Arguments): Array[AnyRef] = super.writeByte(context, args)
|
||||
}
|
||||
case 2 => new Drive(capacity, platterCount, label, host, sound) {
|
||||
@Callback(direct = true, limit = 20, doc = """function(sector:number):string -- Read the current contents of the specified sector.""")
|
||||
override def readSector(context: Context, args: Arguments): Array[AnyRef] = super.readSector(context, args)
|
||||
|
||||
@Callback(direct = true, limit = 10, doc = """function(sector:number, value:string) -- Write the specified contents to the specified sector.""")
|
||||
override def writeSector(context: Context, args: Arguments): Array[AnyRef] = super.writeSector(context, args)
|
||||
|
||||
@Callback(direct = true, limit = 64, doc = """function(offset:number):number -- Read a single byte at the specified offset.""")
|
||||
override def readByte(context: Context, args: Arguments): Array[AnyRef] = super.readByte(context, args)
|
||||
|
||||
@Callback(direct = true, limit = 32, doc = """function(offset:number, value:number) -- Write a single byte to the specified offset.""")
|
||||
override def writeByte(context: Context, args: Arguments): Array[AnyRef] = super.writeByte(context, args)
|
||||
}
|
||||
case _ => new Drive(capacity, platterCount, label, host, sound) {
|
||||
@Callback(direct = true, limit = 10, doc = """function(sector:number):string -- Read the current contents of the specified sector.""")
|
||||
override def readSector(context: Context, args: Arguments): Array[AnyRef] = super.readSector(context, args)
|
||||
|
||||
@Callback(direct = true, limit = 5, doc = """function(sector:number, value:string) -- Write the specified contents to the specified sector.""")
|
||||
override def writeSector(context: Context, args: Arguments): Array[AnyRef] = super.writeSector(context, args)
|
||||
|
||||
@Callback(direct = true, limit = 48, doc = """function(offset:number):number -- Read a single byte at the specified offset.""")
|
||||
override def readByte(context: Context, args: Arguments): Array[AnyRef] = super.readByte(context, args)
|
||||
|
||||
@Callback(direct = true, limit = 24, doc = """function(offset:number, value:number) -- Write a single byte to the specified offset.""")
|
||||
override def writeByte(context: Context, args: Arguments): Array[AnyRef] = super.writeByte(context, args)
|
||||
}
|
||||
}
|
||||
}
|
@ -33,14 +33,14 @@ class FileSystem(val fileSystem: IFileSystem, var label: Label, val host: Option
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
@Callback(direct = true, doc = """function():string -- Get the current label of the file system.""")
|
||||
@Callback(direct = true, doc = """function():string -- Get the current label of the drive.""")
|
||||
def getLabel(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||
if (label != null) result(label.getLabel) else null
|
||||
}
|
||||
|
||||
@Callback(doc = """function(value:string):string -- Sets the label of the file system. Returns the new value, which may be truncated.""")
|
||||
@Callback(doc = """function(value:string):string -- Sets the label of the drive. Returns the new value, which may be truncated.""")
|
||||
def setLabel(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||
if (label == null) throw new Exception("filesystem does not support labeling")
|
||||
if (label == null) throw new Exception("drive does not support labeling")
|
||||
if (args.checkAny(0) == null) label.setLabel(null)
|
||||
else label.setLabel(args.checkString(0))
|
||||
result(label.getLabel)
|
||||
|
@ -123,6 +123,7 @@ private[oc] object Registry extends api.detail.DriverAPI {
|
||||
case arg: java.lang.Long => arg
|
||||
case arg: java.lang.Float => arg
|
||||
case arg: java.lang.Double => arg
|
||||
case arg: java.lang.Number => Double.box(arg.doubleValue())
|
||||
case arg: java.lang.String => arg
|
||||
|
||||
case arg: Array[Boolean] => arg
|
||||
|
@ -72,7 +72,7 @@ trait Buffered extends OutputStreamFileSystem {
|
||||
}
|
||||
setLastModified(path, directory.lastModified())
|
||||
}
|
||||
if (fileRoot.list() == null || fileRoot.list().length == 0) {
|
||||
if (fileRoot.list() == null || fileRoot.list().isEmpty) {
|
||||
fileRoot.delete()
|
||||
}
|
||||
else recurse("", fileRoot)
|
||||
@ -114,7 +114,7 @@ trait Buffered extends OutputStreamFileSystem {
|
||||
}
|
||||
directory.setLastModified(lastModified(path))
|
||||
}
|
||||
if (list("") == null || list("").length == 0) {
|
||||
if (list("") == null || list("").isEmpty) {
|
||||
fileRoot.delete()
|
||||
}
|
||||
else recurse("")
|
||||
|
@ -303,13 +303,9 @@ class Machine(val host: MachineHost) extends prefab.ManagedEnvironment with mach
|
||||
signals.enqueue(new Machine.Signal(name, args.map {
|
||||
case null | Unit | None => null
|
||||
case arg: java.lang.Boolean => arg
|
||||
case arg: java.lang.Byte => Double.box(arg.doubleValue)
|
||||
case arg: java.lang.Character => Double.box(arg.toDouble)
|
||||
case arg: java.lang.Short => Double.box(arg.doubleValue)
|
||||
case arg: java.lang.Integer => Double.box(arg.doubleValue)
|
||||
case arg: java.lang.Long => Double.box(arg.doubleValue)
|
||||
case arg: java.lang.Float => Double.box(arg.doubleValue)
|
||||
case arg: java.lang.Double => arg
|
||||
case arg: java.lang.Long => arg
|
||||
case arg: java.lang.Number => Double.box(arg.doubleValue)
|
||||
case arg: java.lang.String => arg
|
||||
case arg: Array[Byte] => arg
|
||||
case arg: Map[_, _] if arg.isEmpty || arg.head._1.isInstanceOf[String] && arg.head._2.isInstanceOf[String] => arg
|
||||
@ -697,6 +693,7 @@ class Machine(val host: MachineHost) extends prefab.ManagedEnvironment with mach
|
||||
(0 until argsLength).map("arg" + _).map(argsNbt.getTag).map {
|
||||
case tag: NBTTagByte if tag.getByte == -1 => null
|
||||
case tag: NBTTagByte => Boolean.box(tag.getByte == 1)
|
||||
case tag: NBTTagLong => Long.box(tag.getLong)
|
||||
case tag: NBTTagDouble => Double.box(tag.getDouble)
|
||||
case tag: NBTTagString => tag.getString
|
||||
case tag: NBTTagByteArray => tag.getByteArray
|
||||
@ -770,6 +767,7 @@ class Machine(val host: MachineHost) extends prefab.ManagedEnvironment with mach
|
||||
s.args.zipWithIndex.foreach {
|
||||
case (null, i) => args.setByte("arg" + i, -1)
|
||||
case (arg: java.lang.Boolean, i) => args.setByte("arg" + i, if (arg) 1 else 0)
|
||||
case (arg: java.lang.Long, i) => args.setLong("arg" + i, arg)
|
||||
case (arg: java.lang.Double, i) => args.setDouble("arg" + i, arg)
|
||||
case (arg: String, i) => args.setString("arg" + i, arg)
|
||||
case (arg: Array[Byte], i) => args.setByteArray("arg" + i, arg)
|
||||
|
Loading…
x
Reference in New Issue
Block a user