Added a rack mountable version of the disk drive.

This commit is contained in:
Florian Nücke 2015-11-21 19:39:24 +01:00
parent 98e71bdc14
commit cb7f7821c7
31 changed files with 372 additions and 143 deletions

Binary file not shown.

Binary file not shown.

View File

@ -1,7 +1,13 @@
package li.cil.oc.api;
import com.typesafe.config.Config;
import li.cil.oc.api.detail.*;
import li.cil.oc.api.detail.DriverAPI;
import li.cil.oc.api.detail.FileSystemAPI;
import li.cil.oc.api.detail.ItemAPI;
import li.cil.oc.api.detail.MachineAPI;
import li.cil.oc.api.detail.ManualAPI;
import li.cil.oc.api.detail.NanomachinesAPI;
import li.cil.oc.api.detail.NetworkAPI;
/**
* Central reference for the API.
@ -14,6 +20,24 @@ public class API {
public static final String ID_OWNER = "OpenComputers|Core";
public static final String VERSION = "6.0.0-alpha";
// ----------------------------------------------------------------------- //
/**
* The loaded config.
*/
public static Config config = null;
/**
* Whether OpenComputers uses power.
* <p/>
* This is set in the init phase, so do not rely it before the post-init phase.
*/
public static boolean isPowerEnabled = false;
// ----------------------------------------------------------------------- //
// Prefer using the static methods in the respective classes in this package
// over accessing these instances directly.
public static DriverAPI driver = null;
public static FileSystemAPI fileSystem = null;
public static ItemAPI items = null;
@ -22,5 +46,8 @@ public class API {
public static NanomachinesAPI nanomachines = null;
public static NetworkAPI network = null;
public static Config config = null;
// ----------------------------------------------------------------------- //
private API() {
}
}

View File

@ -68,6 +68,7 @@ item.oc.DataCard2.name=Data Card (Tier 3)
item.oc.DebugCard.name=Debug Card
item.oc.Debugger.name=Network Debugger
item.oc.Disk.name=Disk Platter
item.oc.DiskDriveMountable.name=Disk Drive
item.oc.Drone.name=Drone
item.oc.DroneCase0.name=Drone Case (Tier 1)
item.oc.DroneCase1.name=Drone Case (Tier 2)
@ -279,6 +280,7 @@ 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.DiskDriveMountable=Provides the same functionality as a normal disk drive, but must be installed in a rack.
oc:tooltip.DiskUsage=Disk usage: %s/%s Byte
oc:tooltip.DiskModeManaged=Mode: Managed
oc:tooltip.DiskModeUnmanaged=Mode: Unmanaged

View File

@ -83,6 +83,11 @@ tabletCase2 {
["oc:circuitChip2", "oc:materialCircuitBoardPrinted", ingotGold]]
}
diskDriveMountable {
input: [[obsidian, "oc:circuitChip1", obsidian]
[fenceIron, "oc:diskDrive", fenceIron]
[obsidian, "oc:materialCircuitBoardPrinted", obsidian]]
}
server1 {
input: [[obsidian, "oc:ram4", obsidian]
["oc:circuitChip1", "oc:circuitChip2", "oc:circuitChip1"]

Binary file not shown.

After

Width:  |  Height:  |  Size: 490 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 481 B

View File

@ -88,6 +88,7 @@ object Constants {
final val DebugCard = "debugCard"
final val Debugger = "debugger"
final val Disk = "disk"
final val DiskDriveMountable = "diskDriveMountable"
final val Drone = "drone"
final val DroneCaseCreative = "droneCaseCreative"
final val DroneCaseTier1 = "droneCase1"

View File

@ -21,7 +21,7 @@ object GuiHandler extends CommonGuiHandler {
override def getClientGuiElement(id: Int, player: EntityPlayer, world: World, x: Int, y: Int, z: Int): AnyRef = {
GuiType.Categories.get(id) match {
case Some(GuiType.Category.Block) =>
world.getTileEntity(x, y, z) match {
world.getTileEntity(x, GuiType.extractY(y), z) match {
case t: tileentity.Adapter if id == GuiType.Adapter.id =>
new gui.Adapter(player.inventory, t)
case t: tileentity.Assembler if id == GuiType.Assembler.id =>
@ -46,8 +46,8 @@ object GuiHandler extends CommonGuiHandler {
new gui.Robot(player.inventory, t.robot)
case t: tileentity.Screen if id == GuiType.Screen.id =>
new gui.Screen(t.origin.buffer, t.tier > 0, () => t.origin.hasKeyboard, () => t.origin.buffer.isRenderingEnabled)
case t: tileentity.Rack if GuiType.ServerInRack.exists(e => e.id == id) =>
val slot = GuiType.ServerInRack.indexWhere(e => e.id == id)
case t: tileentity.Rack if id == GuiType.ServerInRack.id =>
val slot = GuiType.extractSlot(y)
new gui.Server(player.inventory, new ServerInventory {
override def container = t.getStackInSlot(slot)

View File

@ -59,11 +59,12 @@ object Textures {
val blockRaidFrontActivity = new ResourceLocation(Settings.resourceDomain, "textures/blocks/RaidFrontActivity.png")
val blockRobot = new ResourceLocation(Settings.resourceDomain, "textures/blocks/robot.png")
val blockScreenUpIndicator = new ResourceLocation(Settings.resourceDomain, "textures/blocks/screen/up_indicator.png")
val blockServerFrontOn = new ResourceLocation(Settings.resourceDomain, "textures/blocks/ServerFrontOn.png")
val blockServerFrontError = new ResourceLocation(Settings.resourceDomain, "textures/blocks/ServerFrontError.png")
val blockServerFrontActivity = new ResourceLocation(Settings.resourceDomain, "textures/blocks/ServerFrontActivity.png")
val blockTerminalServerFrontOn = new ResourceLocation(Settings.resourceDomain, "textures/blocks/TerminalServerFrontOn.png")
val blockTerminalServerFrontPresence = new ResourceLocation(Settings.resourceDomain, "textures/blocks/TerminalServerFrontPresence.png")
val blockRackDiskDriveActivity = new ResourceLocation(Settings.resourceDomain, "textures/blocks/DiskDriveMountableActivity.png")
val blockRackServerOn = new ResourceLocation(Settings.resourceDomain, "textures/blocks/ServerFrontOn.png")
val blockRackServerError = new ResourceLocation(Settings.resourceDomain, "textures/blocks/ServerFrontError.png")
val blockRackServerActivity = new ResourceLocation(Settings.resourceDomain, "textures/blocks/ServerFrontActivity.png")
val blockRackTerminalServerOn = new ResourceLocation(Settings.resourceDomain, "textures/blocks/TerminalServerFrontOn.png")
val blockRackTerminalServerPresence = new ResourceLocation(Settings.resourceDomain, "textures/blocks/TerminalServerFrontPresence.png")
val upgradeCrafting = new ResourceLocation(Settings.resourceDomain, "textures/model/UpgradeCrafting.png")
val upgradeGenerator = new ResourceLocation(Settings.resourceDomain, "textures/model/UpgradeGenerator.png")
@ -97,6 +98,7 @@ object Textures {
object Rack {
val icons = Array.fill[IIcon](6)(null)
var diskDrive: IIcon = _
var server: IIcon = _
var terminal: IIcon = _
}
@ -146,7 +148,7 @@ object Textures {
tm.bindTexture(blockHologram)
tm.bindTexture(blockMicrocontrollerFrontLight)
tm.bindTexture(blockMicrocontrollerFrontOn)
tm.bindTexture(blockServerFrontOn)
tm.bindTexture(blockRackServerOn)
tm.bindTexture(blockRobot)
tm.bindTexture(blockScreenUpIndicator)

View File

@ -36,10 +36,16 @@ object RackRenderer extends TileEntitySpecialRenderer {
// Note: we manually sync the rack inventory for this to work.
for (i <- 0 until rack.getSizeInventory) {
if (rack.getStackInSlot(i) != null) {
GL11.glPushMatrix()
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS)
val v0 = vOffset + i * vSize
val v1 = vOffset + (i + 1) * vSize
val event = new RackMountableRenderEvent.TileEntity(rack, i, rack.lastData(i), v0, v1)
MinecraftForge.EVENT_BUS.post(event)
GL11.glPopAttrib()
GL11.glPopMatrix()
}
}

View File

@ -12,7 +12,7 @@ abstract class GuiHandler extends IGuiHandler {
override def getServerGuiElement(id: Int, player: EntityPlayer, world: World, x: Int, y: Int, z: Int): AnyRef = {
GuiType.Categories.get(id) match {
case Some(GuiType.Category.Block) =>
world.getTileEntity(x, y, z) match {
world.getTileEntity(x, GuiType.extractY(y), z) match {
case t: tileentity.Adapter if id == GuiType.Adapter.id =>
new container.Adapter(player.inventory, t)
case t: tileentity.Assembler if id == GuiType.Assembler.id =>
@ -35,8 +35,8 @@ abstract class GuiHandler extends IGuiHandler {
new container.Robot(player.inventory, t.robot)
case t: tileentity.Rack if id == GuiType.Rack.id =>
new container.Rack(player.inventory, t)
case t: tileentity.Rack if GuiType.ServerInRack.exists(e => e.id == id) =>
val slot = GuiType.ServerInRack.indexWhere(e => e.id == id)
case t: tileentity.Rack if id == GuiType.ServerInRack.id =>
val slot = GuiType.extractSlot(y)
val server = t.getMountable(slot).asInstanceOf[Server]
new container.Server(player.inventory, server, Option(server))
case t: tileentity.Switch if id == GuiType.Switch.id =>

View File

@ -30,12 +30,7 @@ object GuiType extends ScalaEnum {
val Robot = new EnumVal { def name = "Robot"; def subType = GuiType.Category.Block }
val Screen = new EnumVal { def name = "Screen"; def subType = GuiType.Category.Block }
val Server = new EnumVal { def name = "Server"; def subType = GuiType.Category.Item }
val ServerInRack = Array(
new EnumVal { val slot = 0; def name = "ServerInRack"; def subType = GuiType.Category.Block },
new EnumVal { val slot = 1; def name = "ServerInRack"; def subType = GuiType.Category.Block },
new EnumVal { val slot = 2; def name = "ServerInRack"; def subType = GuiType.Category.Block },
new EnumVal { val slot = 3; def name = "ServerInRack"; def subType = GuiType.Category.Block }
)
val ServerInRack = new EnumVal { def name = "ServerInRack"; def subType = GuiType.Category.Block }
val Switch = new EnumVal { def name = "Switch"; def subType = GuiType.Category.Block }
val Tablet = new EnumVal { def name = "Tablet"; def subType = GuiType.Category.Item }
val TabletInner = new EnumVal { def name = "TabletInner"; def subType = GuiType.Category.Item }
@ -50,4 +45,10 @@ object GuiType extends ScalaEnum {
val Entity = new EnumVal { def name = "Entity" }
val Item = new EnumVal { def name = "Item" }
}
def embedSlot(y: Int, slot: Int) = (y & 0x00FFFFFF) | (slot << 6)
def extractY(value: Int) = value & 0x00FFFFFF
def extractSlot(value: Int) = (value >>> 6) & 0xFF
}

View File

@ -29,6 +29,7 @@ class Rack extends RedstoneAware with traits.SpecialBlock with traits.PowerAccep
override def registerBlockIcons(iconRegister: IIconRegister) = {
super.registerBlockIcons(iconRegister)
System.arraycopy(icons, 0, Textures.Rack.icons, 0, icons.length)
Textures.Rack.diskDrive = iconRegister.registerIcon(Settings.resourceDomain + ":" + "DiskDriveMountable")
Textures.Rack.server = iconRegister.registerIcon(Settings.resourceDomain + ":" + "ServerFront")
Textures.Rack.terminal = iconRegister.registerIcon(Settings.resourceDomain + ":" + "TerminalServerFront")
}

View File

@ -1,92 +0,0 @@
package li.cil.oc.common.component
import cpw.mods.fml.relauncher.Side
import cpw.mods.fml.relauncher.SideOnly
import li.cil.oc.Constants
import li.cil.oc.Settings
import li.cil.oc.api
import li.cil.oc.api.internal.Keyboard.UsabilityChecker
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.Tier
import li.cil.oc.common.item
import li.cil.oc.common.item.Delegator
import li.cil.oc.common.tileentity
import li.cil.oc.util.ExtendedNBT._
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.nbt.NBTTagCompound
import net.minecraft.nbt.NBTTagString
import net.minecraftforge.common.util.Constants.NBT
import scala.collection.mutable
//class Terminal(val rack: tileentity.Rack, val number: Int) {
// val buffer = {
// val screenItem = api.Items.get(Constants.BlockName.ScreenTier1).createItemStack(1)
// val buffer = api.Driver.driverFor(screenItem, rack.getClass).createEnvironment(screenItem, rack).asInstanceOf[api.component.TextBuffer]
// val (maxWidth, maxHeight) = Settings.screenResolutionsByTier(Tier.Three)
// buffer.setMaximumResolution(maxWidth, maxHeight)
// buffer.setMaximumColorDepth(Settings.screenDepthsByTier(Tier.Three))
// buffer
// }
//
// val keyboard = {
// val keyboardItem = api.Items.get(Constants.BlockName.Keyboard).createItemStack(1)
// val keyboard = api.Driver.driverFor(keyboardItem, rack.getClass).createEnvironment(keyboardItem, rack).asInstanceOf[api.component.Keyboard]
// keyboard.setUsableOverride(new UsabilityChecker {
// override def isUsableByPlayer(keyboard: api.component.Keyboard, player: EntityPlayer) = {
// val stack = player.getHeldItem
// Delegator.subItem(stack) match {
// case Some(t: item.Terminal) if stack.hasTagCompound => keys.contains(stack.getTagCompound.getString(Settings.namespace + "key"))
// case _ => false
// }
// }
// })
// keyboard
// }
//
// if (buffer.node != null) {
// buffer.node.asInstanceOf[Component].setVisibility(Visibility.Neighbors)
// keyboard.node.asInstanceOf[Component].setVisibility(Visibility.Neighbors)
// }
//
// val keys = mutable.ListBuffer.empty[String]
//
// def connect(node: Node) {
// if (keys.size > 0) {
// node.connect(buffer.node)
// node.connect(keyboard.node)
// buffer.node.connect(keyboard.node)
// }
// }
//
// // ----------------------------------------------------------------------- //
//
// def load(nbt: NBTTagCompound) {
// buffer.load(nbt.getCompoundTag(Settings.namespace + "buffer"))
// keyboard.load(nbt.getCompoundTag(Settings.namespace + "keyboard"))
// // Compatibility for previous dev versions where there was only one term.
// if (nbt.hasKey(Settings.namespace + "key")) {
// keys += nbt.getString(Settings.namespace + "key")
// }
// nbt.getTagList(Settings.namespace + "keys", NBT.TAG_STRING).foreach((tag: NBTTagString) => keys += tag.func_150285_a_())
// }
//
// def save(nbt: NBTTagCompound) {
// nbt.setNewCompoundTag(Settings.namespace + "buffer", buffer.save)
// nbt.setNewCompoundTag(Settings.namespace + "keyboard", keyboard.save)
// nbt.setNewTagList(Settings.namespace + "keys", keys)
// }
//
// @SideOnly(Side.CLIENT)
// def readFromNBTForClient(nbt: NBTTagCompound) {
// buffer.load(nbt)
// nbt.getTagList("keys", NBT.TAG_STRING).foreach((tag: NBTTagString) => keys += tag.func_150285_a_())
// }
//
// def writeToNBTForClient(nbt: NBTTagCompound) {
// buffer.save(nbt)
// nbt.setNewTagList("keys", keys)
// }
//}

View File

@ -7,6 +7,7 @@ import li.cil.oc.api.internal.Rack
import li.cil.oc.common.tileentity.Case
import li.cil.oc.common.tileentity.DiskDrive
import li.cil.oc.common.tileentity.Raid
import li.cil.oc.server.component.DiskDriveMountable
import li.cil.oc.server.component.Server
object FileSystemAccessHandler {
@ -22,6 +23,12 @@ object FileSystemAccessHandler {
server.lastAccess = System.currentTimeMillis()
t.markChanged(slot)
}
case diskDrive: DiskDriveMountable =>
val containsNode = diskDrive.filesystemNode.contains(e.getNode)
if (containsNode) {
diskDrive.lastAccess = System.currentTimeMillis()
t.markChanged(slot)
}
case _ =>
}
}

View File

@ -6,10 +6,20 @@ import li.cil.oc.api
import li.cil.oc.api.event.RackMountableRenderEvent
import li.cil.oc.client.Textures
import li.cil.oc.client.renderer.tileentity.RenderUtil
import li.cil.oc.util.BlockPosition
import li.cil.oc.util.ExtendedWorld._
import li.cil.oc.util.RenderState
import net.minecraft.client.renderer.OpenGlHelper
import net.minecraft.client.renderer.entity.RenderItem
import net.minecraft.client.renderer.entity.RenderManager
import net.minecraft.entity.item.EntityItem
import net.minecraft.item.ItemStack
import net.minecraftforge.common.util.Constants.NBT
import org.lwjgl.opengl.GL11
object RackMountableRenderHandler {
lazy val DiskDriveMountable = api.Items.get(Constants.ItemName.DiskDriveMountable)
lazy val Servers = Array(
api.Items.get(Constants.ItemName.ServerTier1),
api.Items.get(Constants.ItemName.ServerTier2),
@ -21,19 +31,52 @@ object RackMountableRenderHandler {
@SubscribeEvent
def onRackMountableRendering(e: RackMountableRenderEvent.TileEntity): Unit = {
if (e.data != null && Servers.contains(api.Items.get(e.rack.getStackInSlot(e.mountable)))) {
if (e.data != null && DiskDriveMountable == api.Items.get(e.rack.getStackInSlot(e.mountable))) {
// Disk drive.
if (e.data.hasKey("disk")) {
val stack = ItemStack.loadItemStackFromNBT(e.data.getCompoundTag("disk"))
if (stack != null) {
GL11.glPushMatrix()
GL11.glScalef(1, -1, 1)
GL11.glTranslatef(10 / 16f, -(3.5f + e.mountable * 3f) / 16f, 1 / 16f)
GL11.glRotatef(90, -1, 0, 0)
val brightness = e.rack.world.getLightBrightnessForSkyBlocks(BlockPosition(e.rack).offset(e.rack.facing), 0)
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, brightness % 65536, brightness / 65536)
// This is very 'meh', but item frames do it like this, too!
val entity = new EntityItem(e.rack.world, 0, 0, 0, stack)
entity.hoverStart = 0
RenderItem.renderInFrame = true
RenderManager.instance.renderEntityWithPosYaw(entity, 0, 0, 0, 0, 0)
RenderItem.renderInFrame = false
GL11.glPopMatrix()
}
}
if (System.currentTimeMillis() - e.data.getLong("lastAccess") < 400 && e.rack.world.rand.nextDouble() > 0.1) {
RenderState.disableLighting()
RenderState.makeItBlend()
e.renderOverlay(Textures.blockRackDiskDriveActivity)
RenderState.enableLighting()
}
}
else if (e.data != null && Servers.contains(api.Items.get(e.rack.getStackInSlot(e.mountable)))) {
// Server.
RenderState.disableLighting()
RenderState.makeItBlend()
if (e.data.getBoolean("isRunning")) {
e.renderOverlay(Textures.blockServerFrontOn)
e.renderOverlay(Textures.blockRackServerOn)
}
if (e.data.getBoolean("hasErrored") && RenderUtil.shouldShowErrorLight(e.rack.hashCode * (e.mountable + 1))) {
e.renderOverlay(Textures.blockServerFrontError)
e.renderOverlay(Textures.blockRackServerError)
}
if (System.currentTimeMillis() - e.data.getLong("lastAccess") < 400 && e.rack.world.rand.nextDouble() > 0.1) {
e.renderOverlay(Textures.blockServerFrontActivity)
e.renderOverlay(Textures.blockRackServerActivity)
}
RenderState.enableLighting()
@ -43,13 +86,13 @@ object RackMountableRenderHandler {
RenderState.disableLighting()
RenderState.makeItBlend()
e.renderOverlay(Textures.blockTerminalServerFrontOn)
e.renderOverlay(Textures.blockRackTerminalServerOn)
val countConnected = e.data.getTagList("keys", NBT.TAG_STRING).tagCount()
if (countConnected > 0) {
val u0 = 7 / 16f
val u1 = u0 + (2 * countConnected - 1) / 16f
e.renderOverlay(Textures.blockTerminalServerFrontPresence, u0, u1)
e.renderOverlay(Textures.blockRackTerminalServerPresence, u0, u1)
}
RenderState.enableLighting()
@ -58,7 +101,11 @@ object RackMountableRenderHandler {
@SubscribeEvent
def onRackMountableRendering(e: RackMountableRenderEvent.Block): Unit = {
if (Servers.contains(api.Items.get(e.rack.getStackInSlot(e.mountable)))) {
if (DiskDriveMountable == api.Items.get(e.rack.getStackInSlot(e.mountable))) {
// Disk drive.
e.setFrontTextureOverride(Textures.Rack.diskDrive)
}
else if (Servers.contains(api.Items.get(e.rack.getStackInSlot(e.mountable)))) {
// Server.
e.setFrontTextureOverride(Textures.Rack.server)
}

View File

@ -531,6 +531,7 @@ object Items extends ItemAPI {
// 1.6.0
Recipes.addSubItem(new item.TerminalServer(multi), Constants.ItemName.TerminalServer, "oc:terminalServer")
Recipes.addSubItem(new item.DiskDriveMountable(multi), Constants.ItemName.DiskDriveMountable, "oc:diskDriveMountable")
// Register aliases.
for ((k, v) <- aliases) {

View File

@ -13,7 +13,6 @@ import li.cil.oc.api.driver.item.Chargeable
import li.cil.oc.api.event.RobotRenderEvent.MountPoint
import li.cil.oc.api.internal.Robot
import li.cil.oc.client.renderer.item.UpgradeRenderer
import li.cil.oc.common.tileentity
import li.cil.oc.util.BlockPosition
import net.minecraft.client.renderer.texture.IIconRegister
import net.minecraft.creativetab.CreativeTabs
@ -123,14 +122,13 @@ class Delegator extends Item with driver.item.UpgradeRenderer with Chargeable {
override def getChestGenBase(chest: ChestGenHooks, rnd: Random, original: WeightedRandomChestContent) = original
override def doesSneakBypassUse(world: World, x: Int, y: Int, z: Int, player: EntityPlayer) = {
world.getTileEntity(x, y, z) match {
case drive: tileentity.DiskDrive => true
// ----------------------------------------------------------------------- //
override def doesSneakBypassUse(world: World, x: Int, y: Int, z: Int, player: EntityPlayer) =
Delegator.subItem(player.getHeldItem) match {
case Some(subItem) => subItem.doesSneakBypassUse(BlockPosition(x, y, z, world), player)
case _ => super.doesSneakBypassUse(world, x, y, z, player)
}
}
// ----------------------------------------------------------------------- //
override def onItemUseFirst(stack: ItemStack, player: EntityPlayer, world: World, x: Int, y: Int, z: Int, side: Int, hitX: Float, hitY: Float, hitZ: Float): Boolean =
Delegator.subItem(stack) match {

View File

@ -0,0 +1,3 @@
package li.cil.oc.common.item
class DiskDriveMountable(val parent: Delegator) extends traits.Delegate

View File

@ -3,7 +3,9 @@ package li.cil.oc.common.item
import cpw.mods.fml.relauncher.Side
import cpw.mods.fml.relauncher.SideOnly
import li.cil.oc.Settings
import li.cil.oc.util.BlockPosition
import li.cil.oc.util.Color
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.item.ItemStack
class FloppyDisk(val parent: Delegator) extends traits.Delegate with traits.FileSystemLike {
@ -28,4 +30,6 @@ class FloppyDisk(val parent: Delegator) extends traits.Delegate with traits.File
icons(index) = iconRegister.registerIcon(baseTextureName + color)
}
}
override def doesSneakBypassUse(position: BlockPosition, player: EntityPlayer): Boolean = true
}

View File

@ -43,6 +43,8 @@ trait Delegate {
// ----------------------------------------------------------------------- //
def doesSneakBypassUse(position: BlockPosition, player: EntityPlayer) = false
def onItemUseFirst(stack: ItemStack, player: EntityPlayer, position: BlockPosition, side: Int, hitX: Float, hitY: Float, hitZ: Float): Boolean = false
def onItemUse(stack: ItemStack, player: EntityPlayer, position: BlockPosition, side: Int, hitX: Float, hitY: Float, hitZ: Float): Boolean = false

View File

@ -21,10 +21,6 @@ import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
class DiskDrive extends traits.Environment with traits.ComponentInventory with traits.Rotatable with Analyzable {
val node = api.Network.newNode(this, Visibility.Network).
withComponent("disk_drive").
create()
// Used on client side to check whether to render disk activity indicators.
var lastAccess = 0L
@ -34,6 +30,11 @@ class DiskDrive extends traits.Environment with traits.ComponentInventory with t
}
// ----------------------------------------------------------------------- //
// 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] = {
@ -58,12 +59,12 @@ class DiskDrive extends traits.Environment with traits.ComponentInventory with t
}
// ----------------------------------------------------------------------- //
// Analyzable
override def onAnalyze(player: EntityPlayer, side: Int, hitX: Float, hitY: Float, hitZ: Float) = filesystemNode.fold(null: Array[Node])(Array(_))
override def canUpdate = false
// ----------------------------------------------------------------------- //
// IInventory
override def getSizeInventory = 1
@ -72,6 +73,9 @@ class DiskDrive extends traits.Environment with traits.ComponentInventory with t
case _ => false
}
// ----------------------------------------------------------------------- //
// ComponentInventory
override protected def onItemAdded(slot: Int, stack: ItemStack) {
super.onItemAdded(slot, stack)
components(slot) match {
@ -95,20 +99,23 @@ class DiskDrive extends traits.Environment with traits.ComponentInventory with t
}
// ----------------------------------------------------------------------- //
// TileEntity
override def canUpdate = false
@SideOnly(Side.CLIENT) override
def readFromNBTForClient(nbt: NBTTagCompound) {
super.readFromNBTForClient(nbt)
items(0) match {
case Some(stack) => nbt.setNewCompoundTag("disk", stack.writeToNBT)
case _ =>
if (nbt.hasKey("disk")) {
setInventorySlotContents(0, ItemStack.loadItemStackFromNBT(nbt.getCompoundTag("disk")))
}
}
override def writeToNBTForClient(nbt: NBTTagCompound) {
super.writeToNBTForClient(nbt)
if (nbt.hasKey("disk")) {
setInventorySlotContents(0, ItemStack.loadItemStackFromNBT(nbt.getCompoundTag("disk")))
items(0) match {
case Some(stack) => nbt.setNewCompoundTag("disk", stack.writeToNBT)
case _ =>
}
}
}

View File

@ -21,8 +21,8 @@ trait ComponentInventory extends Environment with Inventory with inventory.Compo
// Cache changes to inventory slots on the client side to avoid recreating
// components when we don't have to and the slots are just cleared by MC
// temporarily.
private val pendingRemovalsActual = mutable.ArrayBuffer.fill(getSizeInventory)(None: Option[ItemStack])
private val pendingAddsActual = mutable.ArrayBuffer.fill(getSizeInventory)(None: Option[ItemStack])
private lazy val pendingRemovalsActual = mutable.ArrayBuffer.fill(getSizeInventory)(None: Option[ItemStack])
private lazy val pendingAddsActual = mutable.ArrayBuffer.fill(getSizeInventory)(None: Option[ItemStack])
private var updateScheduled = false
def pendingRemovals = {
adjustSize(pendingRemovalsActual)

View File

@ -0,0 +1,32 @@
package li.cil.oc.integration.opencomputers
import li.cil.oc.Constants
import li.cil.oc.api
import li.cil.oc.api.driver.item.HostAware
import li.cil.oc.api.network.EnvironmentHost
import li.cil.oc.api.network.ManagedEnvironment
import li.cil.oc.common.Slot
import li.cil.oc.common.tileentity
import li.cil.oc.server.component
import li.cil.oc.util.ExtendedInventory._
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
object DriverDiskDriveMountable extends Item with HostAware {
override def worksWith(stack: ItemStack): Boolean = isOneOf(stack,
api.Items.get(Constants.ItemName.DiskDriveMountable))
override def createEnvironment(stack: ItemStack, host: EnvironmentHost): ManagedEnvironment = host match {
case rack: tileentity.Rack => new component.DiskDriveMountable(rack, rack.indexOf(stack))
case _ => null // Welp.
}
override def slot(stack: ItemStack): String = Slot.RackMountable
override def dataTag(stack: ItemStack): NBTTagCompound = {
if (!stack.hasTagCompound) {
stack.setTagCompound(new NBTTagCompound())
}
stack.getTagCompound
}
}

View File

@ -125,6 +125,7 @@ object ModOpenComputers extends ModProxy {
api.Driver.add(DriverScreen)
api.Driver.add(DriverTransposer)
api.Driver.add(DriverDiskDriveMountable)
api.Driver.add(DriverServer)
api.Driver.add(DriverTerminalServer)

View File

@ -100,10 +100,10 @@ object PacketSender {
}
// Avoid spamming the network with disk activity notices.
val fileSystemAccessTimeouts = mutable.WeakHashMap.empty[EnvironmentHost, mutable.Map[String, Long]]
val fileSystemAccessTimeouts = mutable.WeakHashMap.empty[Node, mutable.Map[String, Long]]
def sendFileSystemActivity(node: Node, host: EnvironmentHost, name: String) = fileSystemAccessTimeouts.synchronized {
fileSystemAccessTimeouts.get(host) match {
fileSystemAccessTimeouts.get(node) match {
case Some(hostTimeouts) if hostTimeouts.getOrElse(name, 0L) > System.currentTimeMillis() => // Cooldown.
case _ =>
val event = host match {
@ -112,7 +112,7 @@ object PacketSender {
}
MinecraftForge.EVENT_BUS.post(event)
if (!event.isCanceled) {
fileSystemAccessTimeouts.getOrElseUpdate(host, mutable.Map.empty) += name -> (System.currentTimeMillis() + 500)
fileSystemAccessTimeouts.getOrElseUpdate(node, mutable.Map.empty) += name -> (System.currentTimeMillis() + 500)
val pb = new SimplePacketBuilder(PacketType.FileSystemActivity)

View File

@ -0,0 +1,172 @@
package li.cil.oc.server.component
import java.util
import li.cil.oc.api
import li.cil.oc.api.Driver
import li.cil.oc.api.component.RackBusConnectable
import li.cil.oc.api.component.RackMountable
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.EnvironmentHost
import li.cil.oc.api.network.Node
import li.cil.oc.api.network.Visibility
import li.cil.oc.api.prefab
import li.cil.oc.common.Slot
import li.cil.oc.common.Sound
import li.cil.oc.common.inventory.ComponentInventory
import li.cil.oc.common.inventory.ItemStackInventory
import li.cil.oc.common.tileentity
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
import net.minecraftforge.common.util.ForgeDirection
class DiskDriveMountable(val rack: tileentity.Rack, val slot: Int) extends prefab.ManagedEnvironment with ItemStackInventory with ComponentInventory with RackMountable with Analyzable {
// Stored for filling data packet when queried.
var lastAccess = 0L
def filesystemNode = components(0) match {
case Some(environment) => Option(environment.node)
case _ => None
}
// ----------------------------------------------------------------------- //
// Environment
override 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(rack.position, ejected, Option(rack.facing))
if (entity != null) {
val vx = rack.facing.offsetX * velocity
val vy = rack.facing.offsetY * velocity
val vz = rack.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(_))
// ----------------------------------------------------------------------- //
// ItemStackInventory
override def host: EnvironmentHost = rack
// ----------------------------------------------------------------------- //
// IInventory
override def getSizeInventory: Int = 1
override def isItemValidForSlot(slot: Int, stack: ItemStack): Boolean = (slot, Option(Driver.driverFor(stack))) match {
case (0, Some(driver)) => driver.slot(stack) == Slot.Floppy
case _ => false
}
override def isUseableByPlayer(player: EntityPlayer): Boolean = rack.isUseableByPlayer(player)
// ----------------------------------------------------------------------- //
// ComponentInventory
override def container: ItemStack = rack.getStackInSlot(slot)
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(rack)
if (rack.isServer) {
rack.markChanged(this.slot)
}
}
override protected def onItemRemoved(slot: Int, stack: ItemStack) {
super.onItemRemoved(slot, stack)
Sound.playDiskEject(rack)
if (rack.isServer) {
rack.markChanged(this.slot)
}
}
// ----------------------------------------------------------------------- //
// ManagedEnvironment
override def canUpdate: Boolean = false
// ----------------------------------------------------------------------- //
// Persistable
override def load(nbt: NBTTagCompound) {
super[ManagedEnvironment].load(nbt)
super[ComponentInventory].load(nbt)
connectComponents()
}
override def save(nbt: NBTTagCompound) {
super[ManagedEnvironment].save(nbt)
super[ComponentInventory].save(nbt)
}
// ----------------------------------------------------------------------- //
// RackMountable
override def getData: NBTTagCompound = {
val nbt = new NBTTagCompound()
nbt.setLong("lastAccess", lastAccess)
nbt.setTag("disk", toNbt(getStackInSlot(0)))
nbt
}
override def getConnectableCount: Int = 0
override def getConnectableAt(index: Int): RackBusConnectable = null
override def onActivate(player: EntityPlayer, side: ForgeDirection, hitX: Float, hitY: Float, hitZ: Float): Boolean = {
if (player.isSneaking) {
val isDiskInDrive = getStackInSlot(0) != null
val isHoldingDisk = isItemValidForSlot(0, player.getHeldItem)
if (isDiskInDrive) {
if (rack.isServer) {
InventoryUtils.dropSlot(rack.position, this, 0, 1, Option(rack.facing))
}
}
if (isHoldingDisk) {
// Insert the disk.
setInventorySlotContents(0, player.inventory.decrStackSize(player.inventory.currentItem, 1))
}
isDiskInDrive || isHoldingDisk
}
else false
}
// ----------------------------------------------------------------------- //
// StateAware
override def getCurrentState: util.EnumSet[api.util.StateAware.State] = util.EnumSet.noneOf(classOf[api.util.StateAware.State])
}

View File

@ -163,7 +163,7 @@ class Server(val rack: tileentity.Rack, val slot: Int) extends Environment with
}
}
else {
player.openGui(OpenComputers, GuiType.ServerInRack(slot).id, world, rack.x, rack.y, rack.z)
player.openGui(OpenComputers, GuiType.ServerInRack.id, world, rack.x, GuiType.embedSlot(rack.y, slot), rack.z)
}
}
true

View File

@ -28,6 +28,8 @@ object ExtendedWorld {
def getTileEntity(host: EnvironmentHost): TileEntity = getTileEntity(BlockPosition(host))
def isAirBlock(position: BlockPosition) = world.isAirBlock(position.x, position.y, position.z)
def getLightBrightnessForSkyBlocks(position: BlockPosition, minBrightness: Int) = world.getLightBrightnessForSkyBlocks(position.x, position.y, position.z, minBrightness)
}
class ExtendedWorld(override val world: World) extends ExtendedBlockAccess(world) {