This commit is contained in:
Florian Nücke 2013-09-22 16:59:37 +02:00
parent 5871731b7a
commit 6bcfab2c5e
35 changed files with 235 additions and 302 deletions

View File

@ -4,9 +4,9 @@ import cpw.mods.fml.relauncher.Side
import cpw.mods.fml.relauncher.SideOnly
import net.minecraft.creativetab.CreativeTabs
object CreativeTab extends CreativeTabs(CreativeTabs.getNextID(), "OpenComputers") {
object CreativeTab extends CreativeTabs(CreativeTabs.getNextID, "OpenComputers") {
@SideOnly(Side.CLIENT)
override def getTabIconItemIndex() = Config.blockId
override def getTabIconItemIndex = Config.blockId
override def getTranslatedTabLabel() = getTabLabel()
override def getTranslatedTabLabel = getTabLabel
}

View File

@ -30,22 +30,4 @@ public interface IComputerContext {
* any parameters to pass along with the signal.
*/
boolean signal(String name, Object[] args);
/**
* Gets a component with the specified ID from the computer.
*
* The Lua state refers to components only by their ID. They may pass this ID
* along to a driver API function, so that it in turn may resolve it to the
* actual component (originally retrieved by the computer via {@see
* IItemDriver#getComponent(ItemStack)} or {@see
* IBlockDriver#getComponent(Int, Int, Int)}).
*
* This will try to convert the component to the specified type and throw an
* exception if the type does not match. It also throws an exception if there
* is no such component.
*
* @param id
* the id of the component to get.
*/
<T> T getComponent(int id);
}

View File

@ -9,14 +9,10 @@ trait IComputerContext extends IJavaComputerContext {
def signal(name: String, args: Any*): Boolean
def component[T <: AnyRef](id: Int): T
// ----------------------------------------------------------------------- //
def getWorld = world
def signal(name: String, args: Array[Object]): Boolean =
signal(name, args: _*)
override def getComponent[T >: Nothing](id: Int) = component(id)
}

View File

@ -1,12 +1,11 @@
package li.cil.oc.client
import cpw.mods.fml.common.network.Player
import li.cil.oc.common.{ PacketHandler => CommonPacketHandler }
import li.cil.oc.common.{PacketHandler => CommonPacketHandler}
import li.cil.oc.common.PacketType
import li.cil.oc.common.tileentity.TileEntityRotatable
import li.cil.oc.common.tileentity.TileEntityScreen
import net.minecraft.entity.player.EntityPlayer
import net.minecraftforge.common.ForgeDirection
import li.cil.oc.common.tileentity.TileEntityComputer
class PacketHandler extends CommonPacketHandler {
@ -29,7 +28,7 @@ class PacketHandler extends CommonPacketHandler {
}
def onScreenResolutionChange(p: PacketParser) =
p.readTileEntity[TileEntityScreen] match {
p.readTileEntity[TileEntityScreen]() match {
case None => // Invalid packet.
case Some(t) => {
val w = p.readInt()
@ -39,7 +38,7 @@ class PacketHandler extends CommonPacketHandler {
}
def onScreenSet(p: PacketParser) =
p.readTileEntity[TileEntityScreen] match {
p.readTileEntity[TileEntityScreen]() match {
case None => // Invalid packet.
case Some(t) => {
val col = p.readInt()
@ -50,7 +49,7 @@ class PacketHandler extends CommonPacketHandler {
}
def onScreenFill(p: PacketParser) =
p.readTileEntity[TileEntityScreen] match {
p.readTileEntity[TileEntityScreen]() match {
case None => // Invalid packet.
case Some(t) => {
val col = p.readInt()
@ -63,7 +62,7 @@ class PacketHandler extends CommonPacketHandler {
}
def onScreenCopy(p: PacketParser) =
p.readTileEntity[TileEntityScreen] match {
p.readTileEntity[TileEntityScreen]() match {
case None => // Invalid packet.
case Some(t) => {
val col = p.readInt()
@ -77,7 +76,7 @@ class PacketHandler extends CommonPacketHandler {
}
def onScreenBufferResponse(p: PacketParser) =
p.readTileEntity[TileEntityScreen] match {
p.readTileEntity[TileEntityScreen]() match {
case None => // Invalid packet.
case Some(t) =>
p.readUTF.split('\n').zipWithIndex.foreach {
@ -86,7 +85,7 @@ class PacketHandler extends CommonPacketHandler {
}
def onComputerStateResponse(p: PacketParser) =
p.readTileEntity[TileEntityComputer] match {
p.readTileEntity[TileEntityComputer]() match {
case None => // Invalid packet.
case Some(t) => {
t.isOn = p.readBoolean()
@ -94,7 +93,7 @@ class PacketHandler extends CommonPacketHandler {
}
def onRotatableStateResponse(p: PacketParser) =
p.readTileEntity[TileEntityRotatable] match {
p.readTileEntity[TileEntityRotatable]() match {
case None => // Invalid packet.
case Some(t) =>
t.pitch = p.readDirection()

View File

@ -2,10 +2,7 @@ package li.cil.oc.client.computer
import li.cil.oc.api.scala.IComputerContext
import li.cil.oc.common.computer.IComputer
import net.minecraft.block.Block
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
import li.cil.oc.server.computer.Driver
/**
* This is a dummy class for the client side. It does nothing, really, just
@ -20,16 +17,10 @@ class Computer(val owner: AnyRef) extends IComputerContext with IComputer {
def signal(name: String, args: Any*) = throw new NotImplementedError
def component[T <: AnyRef](id: Int) = throw new NotImplementedError
// ----------------------------------------------------------------------- //
// IComputer
// ----------------------------------------------------------------------- //
def add(component: AnyRef, driver: Driver) = false
def remove(id: Int) = false
def start() = false
def stop() = false

View File

@ -3,7 +3,6 @@ package li.cil.oc.client.gui
import org.lwjgl.opengl.GL11
import li.cil.oc.common.container.ContainerComputer
import li.cil.oc.common.tileentity.TileEntityComputer
import net.minecraft.client.gui.GuiButton
import net.minecraft.client.gui.inventory.GuiContainer
import net.minecraft.entity.player.InventoryPlayer
import net.minecraft.util.ResourceLocation
@ -31,7 +30,7 @@ class GuiComputer(inventory: InventoryPlayer, val tileEntity: TileEntityComputer
override def drawSlotInventory(slot: Slot) = {
super.drawSlotInventory(slot)
if (slot.slotNumber < 8 && !slot.getHasStack())
if (slot.slotNumber < 8 && !slot.getHasStack)
drawSlotIcon(slot, icons(slot.slotNumber))
}

View File

@ -1,7 +1,6 @@
package li.cil.oc.client.gui
import li.cil.oc.common.tileentity.TileEntityScreen
import net.minecraft.client.gui.Gui
import org.lwjgl.opengl.GL11
import net.minecraft.util.ResourceLocation
import net.minecraft.client.renderer.Tessellator
@ -53,11 +52,11 @@ class GuiScreen(val tileEntity: TileEntityScreen) extends net.minecraft.client.g
override def handleKeyboardInput() = {
// Find all keyboards next to this screen and type on them.
for (k <- neighboringKeyboards) {
if (Keyboard.getEventKeyState()) {
PacketSender.sendKeyDown(k, Keyboard.getEventCharacter())
if (Keyboard.getEventKeyState) {
PacketSender.sendKeyDown(k, Keyboard.getEventCharacter)
}
else {
PacketSender.sendKeyUp(k, Keyboard.getEventCharacter())
PacketSender.sendKeyUp(k, Keyboard.getEventCharacter)
}
}
}
@ -70,7 +69,7 @@ class GuiScreen(val tileEntity: TileEntityScreen) extends net.minecraft.client.g
setSize(w, h)
}
override def onGuiClosed = {
override def onGuiClosed() = {
super.onGuiClosed()
tileEntity.gui = None
}
@ -88,11 +87,11 @@ class GuiScreen(val tileEntity: TileEntityScreen) extends net.minecraft.client.g
override def doesGuiPauseGame = false
private def neighboringKeyboards =
(ForgeDirection.VALID_DIRECTIONS).
ForgeDirection.VALID_DIRECTIONS.
map(d => tileEntity.worldObj.getBlockTileEntity(
tileEntity.xCoord + d.offsetX,
tileEntity.yCoord + d.offsetY,
tileEntity.zCoord + d.offsetZ)).
tileEntity.xCoord + d.offsetX,
tileEntity.yCoord + d.offsetY,
tileEntity.zCoord + d.offsetZ)).
filter(_ != null).
filter(_.isInstanceOf[TileEntityKeyboard]).
map(_.asInstanceOf[TileEntityKeyboard])

View File

@ -29,11 +29,11 @@ class PacketBuilder(packetType: PacketType.Value, private val stream: ByteArrayO
def sendToServer() = PacketDispatcher.sendPacketToServer(packet)
private def packet: Packet = {
private def packet = {
val p = new Packet250CustomPayload
p.channel = "OpenComp"
p.data = stream.toByteArray
p.length = stream.size
return p
p
}
}

View File

@ -2,15 +2,12 @@ package li.cil.oc.common
import java.io.ByteArrayInputStream
import java.io.DataInputStream
import scala.reflect.runtime.universe._
import cpw.mods.fml.common.network.IPacketHandler
import cpw.mods.fml.common.network.Player
import net.minecraft.network.INetworkManager
import net.minecraft.network.packet.Packet250CustomPayload
import net.minecraft.tileentity.TileEntity
import net.minecraft.world.World
import net.minecraftforge.common.ForgeDirection
import scala.reflect.api.Universe
abstract class PacketHandler extends IPacketHandler {
/** Top level dispatcher based on packet type. */
@ -49,9 +46,10 @@ abstract class PacketHandler extends IPacketHandler {
return Some(t.asInstanceOf[T])
}
}
return None
None
}
def readDirection() = ForgeDirection.getOrientation(readInt())
}
}

View File

@ -81,7 +81,8 @@ class Proxy {
filter(_.isInstanceOf[INetworkNode]).
map(_.asInstanceOf[TileEntity with INetworkNode]).
foreach(t => NetworkAPI.
joinOrCreateNetwork(w, t.xCoord, t.yCoord, t.zCoord, t))
joinOrCreateNetwork(w, t.xCoord, t.yCoord, t.zCoord, t))
}
}
}

View File

@ -84,8 +84,8 @@ class BlockComputer(val parent: BlockMulti) extends SubBlock {
}
override def onBlockActivated(world: World, x: Int, y: Int, z: Int, player: EntityPlayer,
side: ForgeDirection, hitX: Float, hitY: Float, hitZ: Float) = {
if (!player.isSneaking()) {
side: ForgeDirection, hitX: Float, hitY: Float, hitZ: Float) = {
if (!player.isSneaking) {
// Start the computer if it isn't already running and open the GUI.
world.getBlockTileEntity(x, y, z).asInstanceOf[TileEntityComputer].turnOn()
player.openGui(OpenComputers, GuiType.Computer.id, world, x, y, z)

View File

@ -1,6 +1,5 @@
package li.cil.oc.common.block
import scala.collection.mutable.MutableList
import cpw.mods.fml.common.registry.GameRegistry
import li.cil.oc.Config
@ -19,6 +18,7 @@ import net.minecraft.tileentity.TileEntity
import net.minecraft.world.IBlockAccess
import net.minecraft.world.World
import net.minecraftforge.common.ForgeDirection
import scala.collection.mutable
/**
* Block proxy for all real block implementations.
@ -31,11 +31,11 @@ import net.minecraftforge.common.ForgeDirection
* the underlying sub block, based on the metadata. The only actual logic done
* in here is:
* - block rotation, if the block has a rotatable tile entity. In that case all
* sides are also translated into local coordinate space for the sub block
* (i.e. "up" will always be up relative to the block itself. So if it's
* rotated up may actually be west).
* sides are also translated into local coordinate space for the sub block
* (i.e. "up" will always be up relative to the block itself. So if it's
* rotated up may actually be west).
* - Component network logic for adding / removing blocks from the component
* network when they are placed / removed.
* network when they are placed / removed.
*/
class BlockMulti(id: Int) extends Block(id, Material.iron) {
setHardness(2f)
@ -46,7 +46,7 @@ class BlockMulti(id: Int) extends Block(id, Material.iron) {
// SubBlock
// ----------------------------------------------------------------------- //
val subBlocks = MutableList.empty[SubBlock]
val subBlocks = mutable.MutableList.empty[SubBlock]
def add(subBlock: SubBlock) = {
val blockId = subBlocks.length
@ -62,7 +62,7 @@ class BlockMulti(id: Int) extends Block(id, Material.iron) {
protected def subBlock(metadata: Int) =
metadata match {
case id if id >= 0 && id < subBlocks.length => Some(subBlocks(id))
case blockId if blockId >= 0 && blockId < subBlocks.length => Some(subBlocks(blockId))
case _ => None
}
@ -145,9 +145,9 @@ class BlockMulti(id: Int) extends Block(id, Material.iron) {
case None => super.getBlockTexture(world, x, y, z, side)
case Some(subBlock) => subBlock.getBlockTextureFromSide(
world, x, y, z, ForgeDirection.getOrientation(side), toLocal(world, x, y, z, ForgeDirection.getOrientation(side))) match {
case null => super.getBlockTexture(world, x, y, z, side)
case icon => icon
}
case null => super.getBlockTexture(world, x, y, z, side)
case icon => icon
}
}
override def getIcon(side: Int, metadata: Int) =
@ -212,7 +212,7 @@ class BlockMulti(id: Int) extends Block(id, Material.iron) {
def canWrench = {
if (player.getCurrentEquippedItem != null)
try {
player.getCurrentEquippedItem.getItem.asInstanceOf[{
player.getCurrentEquippedItem.getItem.asInstanceOf[ {
def canWrench(player: EntityPlayer, x: Int, y: Int, z: Int): Boolean
}].canWrench(player, x, y, z)
}
@ -228,11 +228,11 @@ class BlockMulti(id: Int) extends Block(id, Material.iron) {
if (valid.length > 1 && canWrench)
world.getBlockTileEntity(x, y, z) match {
case rotatable: TileEntityRotatable => {
if (player.isSneaking()) {
if (player.isSneaking) {
// Rotate pitch. Get the valid pitch rotations.
val validPitch = valid.collect {
case valid if valid == ForgeDirection.DOWN || valid == ForgeDirection.UP => valid
case valid if valid != ForgeDirection.UNKNOWN => ForgeDirection.NORTH
case direction if direction == ForgeDirection.DOWN || direction == ForgeDirection.UP => direction
case direction if direction != ForgeDirection.UNKNOWN => ForgeDirection.NORTH
}
// Check if there's more than one, and if so set to the next one.
if (validPitch.length > 1) {
@ -244,7 +244,7 @@ class BlockMulti(id: Int) extends Block(id, Material.iron) {
else {
// Rotate yaw. Get the valid yaw rotations.
val validYaw = valid.collect {
case valid if valid != ForgeDirection.DOWN && valid != ForgeDirection.UP && valid != ForgeDirection.UNKNOWN => valid
case direction if direction != ForgeDirection.DOWN && direction != ForgeDirection.UP && direction != ForgeDirection.UNKNOWN => direction
}
// Check if there's more than one, and if so set to the next one.
if (validYaw.length > 1) {

View File

@ -71,7 +71,7 @@ class BlockScreen(val parent: BlockMulti) extends SubBlock {
// ----------------------------------------------------------------------- //
override def onBlockActivated(world: World, x: Int, y: Int, z: Int, player: EntityPlayer,
side: ForgeDirection, hitX: Float, hitY: Float, hitZ: Float) = {
side: ForgeDirection, hitX: Float, hitY: Float, hitZ: Float) = {
player.openGui(OpenComputers, GuiType.Screen.id, world, x, y, z)
true
}

View File

@ -1,13 +1,10 @@
package li.cil.oc.common.block
import net.minecraft.item.ItemBlock
import li.cil.oc.Config
import net.minecraft.item.ItemStack
import net.minecraft.block.Block
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.world.World
import li.cil.oc.Blocks
import net.minecraftforge.common.ForgeDirection
import li.cil.oc.common.tileentity.TileEntityRotatable
/** Used to represent multiblocks when in item form. */

View File

@ -1,7 +1,5 @@
package li.cil.oc.common.components
import cpw.mods.fml.relauncher._
/**
* Environment for screen components.
*

View File

@ -2,7 +2,6 @@ package li.cil.oc.common.components
import li.cil.oc.common.util.TextBuffer
import li.cil.oc.server.components.IComponent
import li.cil.oc.server.computer.NetworkNode
import net.minecraft.nbt.NBTTagCompound
class Screen(val owner: IScreenEnvironment) extends IComponent {

View File

@ -1,7 +1,6 @@
package li.cil.oc.common.computer
import li.cil.oc.server.computer.Driver
import li.cil.oc.server.computer.NetworkNode
import net.minecraft.nbt.NBTTagCompound
/**
@ -11,35 +10,6 @@ import net.minecraft.nbt.NBTTagCompound
* the client, which does nothing at all.
*/
trait IComputer {
// ----------------------------------------------------------------------- //
/**
* Tries to add the specified component to the computer.
*
* This can fail if another component with that ID is already installed in
* the computer. This will add the component ID to the list of installed
* components and send the install signal to the computer, as well as call
* the install function of the driver.
*
* @param component the component object.
* @param driver the driver used for the component.
* @return true if the component was installed, false otherwise.
*/
def add(component: AnyRef, driver: Driver): Boolean
/**
* Tries to remove the component with the specified ID from the computer.
*
* This can fail if there is no such component installed in the computer. The
* driver's uninstall function will be called, and the uninstall signal will
* be sent to the computer.
*
* @param id the id of the component to remove.
*/
def remove(id: Int): Boolean
// ----------------------------------------------------------------------- //
/** Starts asynchronous execution of this computer if it isn't running. */
def start(): Boolean

View File

@ -22,7 +22,7 @@ abstract class GenericInventoryContainer(protected val playerInventory: Inventor
override def transferStackInSlot(player: EntityPlayer, index: Int): ItemStack = {
val slot = inventorySlots.get(index).asInstanceOf[Slot]
if (slot != null && slot.getHasStack()) {
if (slot != null && slot.getHasStack) {
// Get search range and direction for checking for merge options.
val playerInventorySize = 4 * 9
val (begin, length, direction) =
@ -35,7 +35,7 @@ abstract class GenericInventoryContainer(protected val playerInventory: Inventor
(0, otherInventory.getSizeInventory, false)
}
val stack = slot.getStack()
val stack = slot.getStack
val originalStack = stack.copy()
// TODO this won't check a slot's isItemValidForSlot value...
if (mergeItemStack(stack, begin, length, direction)) {
@ -57,7 +57,7 @@ abstract class GenericInventoryContainer(protected val playerInventory: Inventor
// else: Merge failed.
}
// else: Empty slot.
return null
null
}
/** Render player inventory at the specified coordinates. */

View File

@ -3,8 +3,6 @@ package li.cil.oc.common.tileentity
import li.cil.oc.common.computer.IComputer
import li.cil.oc.server.computer.Drivers
import net.minecraft.nbt.NBTTagCompound
import net.minecraft.nbt.NBTTagIntArray
import net.minecraft.nbt.NBTTagList
import net.minecraft.world.World
import net.minecraftforge.common.ForgeDirection

View File

@ -1,4 +1,5 @@
package li.cil.oc.common.tileentity
import li.cil.oc.api.ComponentType
import li.cil.oc.common.computer.IComputer
import li.cil.oc.server.computer.Drivers
@ -46,18 +47,20 @@ trait ItemComponentProxy extends IInventory {
def writeItemsToNBT(nbt: NBTTagCompound) = {
val list = new NBTTagList
inventory.zipWithIndex.filter { case (stack, slot) => stack != null }.
inventory.zipWithIndex.filter {
case (stack, slot) => stack != null
}.
foreach {
case (stack, slot) => {
val slotNbt = new NBTTagCompound
slotNbt.setByte("slot", slot.toByte)
val itemNbt = new NBTTagCompound
stack.writeToNBT(itemNbt)
slotNbt.setCompoundTag("item", itemNbt)
slotNbt.setInteger("id", itemComponents(slot))
list.appendTag(slotNbt)
}
case (stack, slot) => {
val slotNbt = new NBTTagCompound
slotNbt.setByte("slot", slot.toByte)
val itemNbt = new NBTTagCompound
stack.writeToNBT(itemNbt)
slotNbt.setCompoundTag("item", itemNbt)
slotNbt.setInteger("id", itemComponents(slot))
list.appendTag(slotNbt)
}
}
nbt.setTag("list", list)
}

View File

@ -3,12 +3,11 @@ package li.cil.oc.common.tileentity
import java.util.concurrent.atomic.AtomicBoolean
import li.cil.oc.api.INetworkMessage
import li.cil.oc.client.{ PacketSender => ClientPacketSender }
import li.cil.oc.client.computer.{ Computer => ClientComputer }
import li.cil.oc.server.{ PacketSender => ServerPacketSender }
import li.cil.oc.server.computer.{ Computer => ServerComputer }
import li.cil.oc.client.{PacketSender => ClientPacketSender}
import li.cil.oc.client.computer.{Computer => ClientComputer}
import li.cil.oc.server.{PacketSender => ServerPacketSender}
import li.cil.oc.server.computer.{Computer => ServerComputer}
import li.cil.oc.server.computer.IComputerEnvironment
import li.cil.oc.server.computer.NetworkNode
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.nbt.NBTTagCompound
@ -34,12 +33,12 @@ class TileEntityComputer(isClient: Boolean) extends TileEntityRotatable with ICo
computer.signal("component_removed", message.getSource.getAddress)
case Array(oldAddress: Integer) if message.getName == "network.reconnect" =>
computer.signal("component_updated", message.getSource.getAddress, oldAddress)
case Array(name: String, args @ _*) if message.getName == "signal" =>
case Array(name: String, args@_*) if message.getName == "signal" =>
computer.signal(name, args: _*)
case _ => // Ignore message.
}
override def onAddressChange = computer.signal("address_change", address)
override def onAddressChange() = computer.signal("address_change", address)
// ----------------------------------------------------------------------- //
// General
@ -54,6 +53,7 @@ class TileEntityComputer(isClient: Boolean) extends TileEntityRotatable with ICo
def isOn_=(value: Boolean) = {
computer.asInstanceOf[ClientComputer].isRunning = value
worldObj.markBlockForRenderUpdate(xCoord, yCoord, zCoord)
this
}
override def readFromNBT(nbt: NBTTagCompound) = {
@ -102,11 +102,11 @@ class TileEntityComputer(isClient: Boolean) extends TileEntityRotatable with ICo
// ----------------------------------------------------------------------- //
def onNeighborBlockChange(blockId: Int) =
(0 to 5).foreach(checkBlockChanged(_))
(0 to 5).foreach(checkBlockChanged)
def isUseableByPlayer(entityplayer: EntityPlayer) =
def isUseableByPlayer(player: EntityPlayer) =
world.getBlockTileEntity(xCoord, yCoord, zCoord) == this &&
entityplayer.getDistanceSq(xCoord + 0.5, yCoord + 0.5, zCoord + 0.5) < 64
player.getDistanceSq(xCoord + 0.5, yCoord + 0.5, zCoord + 0.5) < 64
def world = worldObj

View File

@ -1,7 +1,7 @@
package li.cil.oc.common.tileentity
import li.cil.oc.client.{ PacketSender => ClientPacketSender }
import li.cil.oc.server.{ PacketSender => ServerPacketSender }
import li.cil.oc.client.{PacketSender => ClientPacketSender}
import li.cil.oc.server.{PacketSender => ServerPacketSender}
import net.minecraft.block.Block
import net.minecraft.entity.Entity
import net.minecraft.nbt.NBTTagCompound

View File

@ -1,11 +1,10 @@
package li.cil.oc.common.tileentity
import cpw.mods.fml.relauncher._
import li.cil.oc.client.{ PacketSender => ClientPacketSender }
import li.cil.oc.client.{PacketSender => ClientPacketSender}
import li.cil.oc.client.gui.GuiScreen
import li.cil.oc.common.components.IScreenEnvironment
import li.cil.oc.common.components.Screen
import li.cil.oc.server.{ PacketSender => ServerPacketSender }
import li.cil.oc.server.{PacketSender => ServerPacketSender}
import net.minecraft.nbt.NBTTagCompound
import li.cil.oc.server.computer.NetworkNode

View File

@ -1,10 +1,9 @@
package li.cil.oc.common.util
import scala.collection.mutable._
import scala.reflect.runtime.universe._
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
import scala.collection.mutable
/**
* This singleton is responsible for caching actual item component instances,
@ -12,18 +11,18 @@ import net.minecraft.nbt.NBTTagCompound
* data.
*/
object ItemComponentCache {
private val caches = Map.empty[Int, Cache[_]]
private val caches = mutable.Map.empty[Int, Cache[_]]
def get[T](item: ItemStack) = caches.get(item.itemID) match {
case None => None
case Some(cache) => cache.asInstanceOf[Cache[T]].getComponent(item)
}
def register[T](id: Int, ctor: (NBTTagCompound) => T): Unit =
caches += id -> new Cache[T](id, ctor)
def register[T](id: Int, constructor: (NBTTagCompound) => T): Unit =
caches += id -> new Cache[T](id, constructor)
private class Cache[T](val id: Int, val ctor: (NBTTagCompound) => T) {
private val instances = WeakHashMap.empty[NBTTagCompound, T]
private class Cache[T](val id: Int, val constructor: (NBTTagCompound) => T) {
private val instances = mutable.WeakHashMap.empty[NBTTagCompound, T]
def getComponent(item: ItemStack): Option[T] =
if (item.itemID == id) {
@ -32,11 +31,12 @@ object ItemComponentCache {
case tag => tag
}
instances.get(nbt).orElse {
val component = ctor(nbt)
val component = constructor(nbt)
instances += nbt -> component
Some(component)
}
}
else throw new IllegalArgumentException("Invalid item type.")
}
}

View File

@ -92,15 +92,15 @@ class TextBuffer(var width: Int, var height: Int) {
case destx => destx.swap
}
val (dy0, dy1) = ((row + ty + h - 1) max 0 min (height - 1), (row + ty) max 0 min height) match {
case desty if (ty > 0) => desty
case desty if ty > 0 => desty
case desty => desty.swap
}
val (sx, sy) = ((if (tx > 0) -1 else 1), (if (ty > 0) -1 else 1))
val (sx, sy) = (if (tx > 0) -1 else 1, if (ty > 0) -1 else 1)
// Copy values to destination rectangle if there source is valid.
var changed = false
for (ny <- dy0 to dy1 by sy) (ny - ty) match {
for (ny <- dy0 to dy1 by sy) ny - ty match {
case oy if oy >= 0 && oy < height =>
for (nx <- dx0 to dx1 by sx) (nx - tx) match {
for (nx <- dx0 to dx1 by sx) nx - tx match {
case ox if ox >= 0 && ox < width => {
changed = changed || (buffer(ny)(nx) != buffer(oy)(ox))
buffer(ny)(nx) = buffer(oy)(ox)
@ -140,6 +140,6 @@ class TextBuffer(var width: Int, var height: Int) {
b.append('\n').appendAll(buffer(y))
}
}
b.toString
b.toString()
}
}

View File

@ -2,11 +2,9 @@ package li.cil.oc.server
import cpw.mods.fml.common.network.Player
import li.cil.oc.common.PacketBuilder
import li.cil.oc.common.PacketBuilder._
import li.cil.oc.common.{ PacketHandler => CommonPacketHandler }
import li.cil.oc.common.{PacketHandler => CommonPacketHandler}
import li.cil.oc.common.PacketType
import li.cil.oc.common.tileentity.TileEntityComputer
import li.cil.oc.common.tileentity.TileEntityKeyboard
import li.cil.oc.common.tileentity.TileEntityRotatable
import li.cil.oc.common.tileentity.TileEntityScreen
import net.minecraftforge.common.DimensionManager
@ -27,7 +25,7 @@ class PacketHandler extends CommonPacketHandler {
}
def onScreenBufferRequest(p: PacketParser) =
p.readTileEntity[TileEntityScreen] match {
p.readTileEntity[TileEntityScreen]() match {
case None => // Invalid packet.
case Some(t) => {
val pb = new PacketBuilder(PacketType.ScreenBufferResponse)
@ -40,7 +38,7 @@ class PacketHandler extends CommonPacketHandler {
}
def onComputerStateRequest(p: PacketParser) =
p.readTileEntity[TileEntityComputer] match {
p.readTileEntity[TileEntityComputer]() match {
case None => // Invalid packet.
case Some(t) => {
val pb = new PacketBuilder(PacketType.ComputerStateResponse)
@ -53,7 +51,7 @@ class PacketHandler extends CommonPacketHandler {
}
def onRotatableStateRequest(p: PacketParser) =
p.readTileEntity[TileEntityRotatable] match {
p.readTileEntity[TileEntityRotatable]() match {
case None => // Invalid packet.
case Some(t) => {
val pb = new PacketBuilder(PacketType.RotatableStateResponse)
@ -67,13 +65,13 @@ class PacketHandler extends CommonPacketHandler {
}
def onKeyDown(p: PacketParser) =
p.readTileEntity[INetworkNode] match {
p.readTileEntity[INetworkNode]() match {
case None => // Invalid packet.
case Some(n) => n.getNetwork.sendToAll(n, "tryKeyDown", p.player, char2Character(p.readChar()))
}
def onKeyUp(p: PacketParser) =
p.readTileEntity[INetworkNode] match {
p.readTileEntity[INetworkNode]() match {
case None => // Invalid packet.
case Some(n) => n.getNetwork.sendToAll(n, "tryKeyUp", p.player, char2Character(p.readChar()))
}

View File

@ -1,7 +1,6 @@
package li.cil.oc.server
import li.cil.oc.common.PacketBuilder
import li.cil.oc.common.PacketBuilder._
import li.cil.oc.common.PacketType
import li.cil.oc.common.tileentity.TileEntityRotatable
import net.minecraft.tileentity.TileEntity

View File

@ -1,6 +1,6 @@
package li.cil.oc.server
import li.cil.oc.common.{ Proxy => CommonProxy }
import li.cil.oc.common.{Proxy => CommonProxy}
class Proxy extends CommonProxy {
}

View File

@ -1,9 +1,5 @@
package li.cil.oc.server.components
import li.cil.oc.Items
import li.cil.oc.api.IItemDriver
import net.minecraft.item.ItemStack
class Disk extends IComponent {
def close() {}
}

View File

@ -7,9 +7,7 @@ import java.util.concurrent.atomic.AtomicInteger
import scala.Array.canBuildFrom
import scala.collection.JavaConversions._
import scala.collection.mutable._
import scala.io.Source
import scala.reflect.runtime.universe._
import scala.util.Random
import com.naef.jnlua._
@ -185,7 +183,7 @@ class Computer(val owner: IComputerEnvironment) extends IComputerContext with IC
stateMonitor.synchronized(state match {
case State.Stopped | State.Stopping => return
case State.DriverCall => {
assert(lua.getTop() == 2)
assert(lua.getTop == 2)
assert(lua.isThread(1))
assert(lua.isFunction(2))
println("> drivercall")
@ -205,10 +203,10 @@ class Computer(val owner: IComputerEnvironment) extends IComputerContext with IC
// Remember when we started the computer for os.clock(). We do this in the
// update because only then can we be sure the world is available.
if (timeStarted == 0)
timeStarted = owner.world.getWorldInfo().getWorldTotalTime()
timeStarted = owner.world.getWorldInfo.getWorldTotalTime
// Update world time for computer threads.
worldTime = owner.world.getWorldInfo().getWorldTotalTime()
worldTime = owner.world.getWorldInfo.getWorldTotalTime
// Update last time run to let our executor thread know it doesn't have to
// pause.
@ -229,7 +227,7 @@ class Computer(val owner: IComputerEnvironment) extends IComputerContext with IC
if (state != State.Stopped && init()) {
// Unlimit memory use while unpersisting.
val memory = lua.getTotalMemory()
val memory = lua.getTotalMemory
lua.setTotalMemory(Integer.MAX_VALUE)
try {
// Try unpersisting Lua, because that's what all of the rest depends
@ -256,19 +254,19 @@ class Computer(val owner: IComputerEnvironment) extends IComputerContext with IC
signals.addAll((0 until signalsTag.tagCount()).
map(signalsTag.tagAt(_).asInstanceOf[NBTTagCompound]).
map(signal => {
val argsTag = signal.getCompoundTag("args")
val argsLength = argsTag.getInteger("length")
new Signal(signal.getString("name"),
(0 until argsLength).map("arg" + _).map(argsTag.getTag(_)).map {
case tag: NBTTagByte => tag.data
case tag: NBTTagShort => tag.data
case tag: NBTTagInt => tag.data
case tag: NBTTagLong => tag.data
case tag: NBTTagFloat => tag.data
case tag: NBTTagDouble => tag.data
case tag: NBTTagString => tag.data
}.toArray)
}))
val argsTag = signal.getCompoundTag("args")
val argsLength = argsTag.getInteger("length")
new Signal(signal.getString("name"),
(0 until argsLength).map("arg" + _).map(argsTag.getTag).map {
case tag: NBTTagByte => tag.data
case tag: NBTTagShort => tag.data
case tag: NBTTagInt => tag.data
case tag: NBTTagLong => tag.data
case tag: NBTTagFloat => tag.data
case tag: NBTTagDouble => tag.data
case tag: NBTTagString => tag.data
}.toArray)
}))
timeStarted = nbt.getDouble("timeStarted")
@ -305,7 +303,7 @@ class Computer(val owner: IComputerEnvironment) extends IComputerContext with IC
}
// Unlimit memory while persisting.
val memory = lua.getTotalMemory()
val memory = lua.getTotalMemory
lua.setTotalMemory(Integer.MAX_VALUE)
try {
// Try persisting Lua, because that's what all of the rest depends on.
@ -360,27 +358,30 @@ class Computer(val owner: IComputerEnvironment) extends IComputerContext with IC
private def persist(): Array[Byte] = {
lua.getGlobal("persist") // ... obj persist?
if (lua.`type`(-1) == LuaType.FUNCTION) { // ... obj persist
if (lua.`type`(-1) == LuaType.FUNCTION) {
// ... obj persist
lua.pushValue(-2) // ... obj persist obj
lua.call(1, 1) // ... obj str?
if (lua.`type`(-1) == LuaType.STRING) { // ... obj str
if (lua.`type`(-1) == LuaType.STRING) {
// ... obj str
val result = lua.toByteArray(-1)
lua.pop(1) // ... obj
return result
} // ... obj :(
} // ... obj :(
lua.pop(1) // ... obj
return Array[Byte]()
Array[Byte]()
}
private def unpersist(value: Array[Byte]): Boolean = {
lua.getGlobal("unpersist") // ... unpersist?
if (lua.`type`(-1) == LuaType.FUNCTION) { // ... unpersist
if (lua.`type`(-1) == LuaType.FUNCTION) {
// ... unpersist
lua.pushByteArray(value) // ... unpersist str
lua.call(1, 1) // ... obj
return true
} // ... :(
return false
false
}
// ----------------------------------------------------------------------- //
@ -394,7 +395,7 @@ class Computer(val owner: IComputerEnvironment) extends IComputerContext with IC
LuaStateFactory.createState() match {
case None =>
lua = null; return false
case Some(state) => lua = state
case Some(value) => lua = value
}
try {
@ -404,7 +405,7 @@ class Computer(val owner: IComputerEnvironment) extends IComputerContext with IC
// Set up function used to send network messages.
lua.pushJavaFunction(new JavaFunction() {
def invoke(lua: LuaState): Int = {
return 1
1
}
})
lua.setGlobal("sendMessage")
@ -420,8 +421,8 @@ class Computer(val owner: IComputerEnvironment) extends IComputerContext with IC
// World time is in ticks, and each second has 20 ticks. Since we
// want os.clock() to return real seconds, though, we'll divide it
// accordingly.
lua.pushNumber((owner.world.getTotalWorldTime() - timeStarted) / 20.0)
return 1
lua.pushNumber((owner.world.getTotalWorldTime - timeStarted) / 20.0)
1
}
})
lua.setField(-2, "clock")
@ -434,7 +435,7 @@ class Computer(val owner: IComputerEnvironment) extends IComputerContext with IC
// starts days at 6 o'clock, so we add those six hours. Thus:
// timestamp = (time + 6000) / 1000[h] * 60[m] * 60[s] * 1000[ms]
lua.pushNumber((worldTime + 6000) * 60 * 60)
return 1
1
}
})
lua.setField(-2, "time")
@ -442,9 +443,9 @@ class Computer(val owner: IComputerEnvironment) extends IComputerContext with IC
// Date-time formatting using Java's formatting capabilities.
lua.pushJavaFunction(new JavaFunction() {
def invoke(lua: LuaState): Int = {
val calendar = Calendar.getInstance(Locale.ENGLISH);
val calendar = Calendar.getInstance(Locale.ENGLISH)
calendar.setTimeInMillis(lua.checkInteger(1))
return 1
1
}
})
lua.setField(-2, "date")
@ -456,7 +457,7 @@ class Computer(val owner: IComputerEnvironment) extends IComputerContext with IC
val t2 = lua.checkNumber(1)
val t1 = lua.checkNumber(2)
lua.pushNumber(t2 - t1)
return 1
1
}
})
lua.setField(-2, "difftime")
@ -465,7 +466,7 @@ class Computer(val owner: IComputerEnvironment) extends IComputerContext with IC
lua.pushJavaFunction(new JavaFunction() {
def invoke(lua: LuaState): Int = {
lua.pushNumber(System.currentTimeMillis() / 1000.0)
return 1
1
}
})
lua.setField(-2, "realTime")
@ -473,15 +474,15 @@ class Computer(val owner: IComputerEnvironment) extends IComputerContext with IC
// Allow the system to read how much memory it uses and has available.
lua.pushJavaFunction(new JavaFunction() {
def invoke(lua: LuaState): Int = {
lua.pushInteger(lua.getTotalMemory() - kernelMemory)
return 1
lua.pushInteger(lua.getTotalMemory - kernelMemory)
1
}
})
lua.setField(-2, "totalMemory")
lua.pushJavaFunction(new JavaFunction() {
def invoke(lua: LuaState): Int = {
lua.pushInteger(lua.getFreeMemory())
return 1
lua.pushInteger(lua.getFreeMemory)
1
}
})
lua.setField(-2, "freeMemory")
@ -497,8 +498,8 @@ class Computer(val owner: IComputerEnvironment) extends IComputerContext with IC
val random = new Random
lua.pushJavaFunction(new JavaFunction() {
def invoke(lua: LuaState): Int = {
lua.getTop() match {
case 0 => lua.pushNumber(random.nextDouble)
lua.getTop match {
case 0 => lua.pushNumber(random.nextDouble())
case 1 => {
val u = lua.checkInteger(1)
lua.checkArg(1, 1 < u, "interval is empty")
@ -512,7 +513,7 @@ class Computer(val owner: IComputerEnvironment) extends IComputerContext with IC
}
case _ => throw new IllegalArgumentException("wrong number of arguments")
}
return 1
1
}
})
lua.setField(-2, "random")
@ -521,7 +522,7 @@ class Computer(val owner: IComputerEnvironment) extends IComputerContext with IC
def invoke(lua: LuaState): Int = {
val seed = lua.checkInteger(1)
random.setSeed(seed)
return 0
0
}
})
lua.setField(-2, "randomseed")
@ -532,7 +533,7 @@ class Computer(val owner: IComputerEnvironment) extends IComputerContext with IC
// Until we get to ingame screens we log to Java's stdout.
lua.pushJavaFunction(new JavaFunction() {
def invoke(lua: LuaState): Int = {
for (i <- 1 to lua.getTop()) {
for (i <- 1 to lua.getTop) {
lua.`type`(i) match {
case LuaType.NIL => print("nil")
case LuaType.BOOLEAN => print(lua.toBoolean(i))
@ -545,7 +546,7 @@ class Computer(val owner: IComputerEnvironment) extends IComputerContext with IC
}
}
println()
return 0
0
}
})
lua.setGlobal("print")
@ -586,7 +587,7 @@ class Computer(val owner: IComputerEnvironment) extends IComputerContext with IC
def invoke(lua: LuaState): Int = {
lua.pushString(Source.fromInputStream(classOf[Computer].
getResourceAsStream("/assets/opencomputers/lua/init.lua")).mkString)
return 1
1
}
})
lua.setGlobal("init")
@ -597,7 +598,7 @@ class Computer(val owner: IComputerEnvironment) extends IComputerContext with IC
// fixed base amount of memory, regardless of the memory need of the
// underlying system (which may change across releases).
lua.gc(LuaState.GcAction.COLLECT, 0)
kernelMemory = lua.getTotalMemory() - lua.getFreeMemory()
kernelMemory = lua.getTotalMemory - lua.getFreeMemory
lua.setTotalMemory(kernelMemory + 64 * 1024)
// Clear any left-over signals from a previous run.
@ -611,13 +612,13 @@ class Computer(val owner: IComputerEnvironment) extends IComputerContext with IC
close()
}
}
return false
false
}
private def close(): Unit = stateMonitor.synchronized(
if (state != State.Stopped) {
state = State.Stopped
lua.setTotalMemory(Integer.MAX_VALUE);
lua.setTotalMemory(Integer.MAX_VALUE)
lua.close()
lua = null
kernelMemory = 0
@ -667,7 +668,7 @@ class Computer(val owner: IComputerEnvironment) extends IComputerContext with IC
// Resume the Lua state and remember the number of results we get.
val results = if (driverReturn) {
// If we were doing a driver call, continue where we left off.
assert(lua.getTop() == 2)
assert(lua.getTop == 2)
lua.resume(1, 1)
}
else signals.poll() match {
@ -780,6 +781,7 @@ class Computer(val owner: IComputerEnvironment) extends IComputerContext with IC
/** The computer is paused and waiting for the game to resume. */
val DriverReturnPaused = Value("DriverReturnPaused")
}
}
/** Singleton for requesting executors that run our Lua states. */
@ -788,19 +790,19 @@ private[computer] object Executor {
new ThreadFactory() {
private val threadNumber = new AtomicInteger(1)
private val group = System.getSecurityManager() match {
case null => Thread.currentThread().getThreadGroup()
case s => s.getThreadGroup()
private val group = System.getSecurityManager match {
case null => Thread.currentThread().getThreadGroup
case s => s.getThreadGroup
}
def newThread(r: Runnable): Thread = {
val name = "OpenComputers-" + threadNumber.getAndIncrement()
val name = "OpenComputers-" + threadNumber.getAndIncrement
val thread = new Thread(group, r, name)
if (!thread.isDaemon())
if (!thread.isDaemon)
thread.setDaemon(true)
if (thread.getPriority() != Thread.MIN_PRIORITY)
if (thread.getPriority != Thread.MIN_PRIORITY)
thread.setPriority(Thread.MIN_PRIORITY)
return thread
thread
}
})
}

View File

@ -3,8 +3,6 @@ package li.cil.oc.server.computer
import java.lang.reflect.InvocationTargetException
import scala.compat.Platform.EOL
import scala.reflect.runtime.{ universe => ru }
import scala.reflect.runtime.universe._
import com.naef.jnlua.DefaultConverter
import com.naef.jnlua.JavaFunction
@ -19,6 +17,7 @@ import li.cil.oc.api.scala.IDriver
import li.cil.oc.api.scala.IItemDriver
class ItemDriver(val instance: IItemDriver) extends Driver
class BlockDriver(val instance: IBlockDriver) extends Driver
/**
@ -51,7 +50,8 @@ abstract private[oc] class Driver {
// Get or create API table.
lua.getField(-1, apiName.get) // ... drivers api?
if (lua.isNil(-1)) { // ... drivers nil
if (lua.isNil(-1)) {
// ... drivers nil
lua.pop(1) // ... drivers
lua.newTable() // ... drivers api
lua.pushValue(-1) // ... drivers api api
@ -62,31 +62,36 @@ abstract private[oc] class Driver {
val instanceMirror = mirror.reflect(instance)
val instanceType = instanceMirror.symbol.typeSignature
val callbackSymbol = ru.typeOf[Callback].typeSymbol
for (method <- instanceType.members collect { case m if m.isMethod => m.asMethod })
for (method <- instanceType.members collect {
case m if m.isMethod => m.asMethod
}) {
method.annotations.filter(_.tpe.typeSymbol == callbackSymbol).
foreach(annotation => {
val name = annotation.javaArgs.get(newTermName("name")) match {
case Some(arg) if arg != null => arg.asInstanceOf[String]
case _ => method.name.decoded
}
lua.getField(-1, name) // ... drivers api func?
if (lua.isNil(-1)) { // ... drivers api nil
// No such entry yet.
lua.pop(1) // ... drivers api
lua.pushJavaFunction(new APIClosure(mirror, instanceMirror.reflectMethod(method), computer)) // ... drivers api func
lua.setField(-2, name) // ... drivers api
}
else { // ... drivers api func
// Entry already exists, skip it.
lua.pop(1) // ... drivers api
// Note that we can be sure it's an issue with two drivers
// colliding, because this is guaranteed to run before any user
// code had a chance to mess with the table.
OpenComputers.log.warning(String.format(
"Duplicate API entry, ignoring %s.%s of driver %s.",
apiName, name, instance.componentName))
}
})
val name = annotation.javaArgs.get(newTermName("name")) match {
case Some(arg) if arg != null => arg.asInstanceOf[String]
case _ => method.name.decoded
}
lua.getField(-1, name) // ... drivers api func?
if (lua.isNil(-1)) {
// ... drivers api nil
// No such entry yet.
lua.pop(1) // ... drivers api
lua.pushJavaFunction(new APIClosure(mirror, instanceMirror.reflectMethod(method), computer)) // ... drivers api func
lua.setField(-2, name) // ... drivers api
}
else {
// ... drivers api func
// Entry already exists, skip it.
lua.pop(1) // ... drivers api
// Note that we can be sure it's an issue with two drivers
// colliding, because this is guaranteed to run before any user
// code had a chance to mess with the table.
OpenComputers.log.warning(String.format(
"Duplicate API entry, ignoring %s.%s of driver %s.",
apiName, name, instance.componentName))
}
})
}
// ... drivers api
lua.pop(2) // ...
@ -147,11 +152,13 @@ abstract private[oc] class Driver {
// Transform error messages to only keep the actual message, to avoid
// Java/scala specific stuff to be shown on the Lua side.
case e: InvocationTargetException =>
e.getCause.printStackTrace(); throw new Throwable {
e.getCause.printStackTrace();
throw new Throwable {
override def toString = e.getCause.getMessage
}
case e: Throwable =>
e.printStackTrace(); throw new Throwable {
e.printStackTrace();
throw new Throwable {
override def toString = e.getMessage
}
}
@ -164,7 +171,7 @@ abstract private[oc] class Driver {
private def buildParameterTransformations(mirror: Mirror, method: MethodSymbol): (Array[Computer => Any], Computer => Boolean) =
if (method.paramss.length == 0 || method.paramss(0).length == 0) {
// No parameters.
(Array(), c => c.lua.getTop() == 0)
(Array(), c => c.lua.getTop == 0)
}
else {
val paramTypes = method.paramss(0).map(_.typeSignature.typeSymbol)
@ -172,11 +179,11 @@ abstract private[oc] class Driver {
if (paramTypes.length == 2 &&
paramTypes(0) == typeOf[IComputerContext].typeSymbol &&
paramTypes(1) == typeOf[Array[Any]].typeSymbol)
// Callback function that wants to handle its arguments manually.
// Convert all arguments and pack them into an array.
// Callback function that wants to handle its arguments manually.
// Convert all arguments and pack them into an array.
(Array(
c => c,
c => (1 to c.lua.getTop()).map(
c => (1 to c.lua.getTop).map(
c.lua.toJavaObject(_, classOf[Object]))), c => true)
// Normal callback. Build converters based on the method's signature.
@ -189,13 +196,13 @@ abstract private[oc] class Driver {
(paramTypes.map {
case t if t == typeOf[IComputerContext].typeSymbol =>
(c: Computer) => c
case t => {
case t => {
val clazz = mirror.runtimeClass(t.asClass)
paramIndex = paramIndex + 1
val i = paramIndex
(c: Computer) => c.lua.toJavaObject(i, clazz)
}
}.toArray, c => c.lua.getTop() == paramIndex)
}.toArray, c => c.lua.getTop == paramIndex)
}
}
@ -210,7 +217,7 @@ abstract private[oc] class Driver {
case t if t.typeSymbol == typeOf[Unit].typeSymbol => (c, v) => 0
case t if t.typeSymbol == typeOf[Array[_]].typeSymbol && checkType(mirror, t.asInstanceOf[TypeRefApi].args(0).typeSymbol) => (c, v) => {
val array = v.asInstanceOf[Array[_]]
array.foreach(c.lua.pushJavaObject(_))
array.foreach(c.lua.pushJavaObject)
array.length
}
case t if checkType(mirror, t.typeSymbol) => (c, v) => c.lua.pushJavaObject(v); 1
@ -224,4 +231,5 @@ abstract private[oc] class Driver {
else if (t.isType) DefaultConverter.isTypeSupported(mirror.runtimeClass(t.typeSignature))
else false
}
}

View File

@ -3,8 +3,8 @@ package li.cil.oc.server.computer
import scala.collection.mutable.ArrayBuffer
import li.cil.oc.api.ComponentType
import li.cil.oc.api.{ IBlockDriver => IJavaBlockDriver }
import li.cil.oc.api.{ IItemDriver => IJavaItemDriver }
import li.cil.oc.api.{IBlockDriver => IJavaBlockDriver}
import li.cil.oc.api.{IItemDriver => IJavaItemDriver}
import li.cil.oc.api.scala.IBlockDriver
import li.cil.oc.api.scala.IItemDriver
import net.minecraft.item.ItemStack
@ -49,10 +49,10 @@ private[oc] object Drivers {
}
def add(driver: IJavaBlockDriver): Unit = add(new IBlockDriver {
// IDriver
def componentName: String = driver.getComponentName
// IBlockDriver
def component(world: World, x: Int, y: Int, z: Int): Option[AnyRef] = Some(driver.getComponent(world, x, y, z))
def worksWith(world: World, x: Int, y: Int, z: Int): Boolean = driver.worksWith(world, x, y, z)
})
@ -71,11 +71,12 @@ private[oc] object Drivers {
}
def add(driver: IJavaItemDriver): Unit = add(new IItemDriver {
// IDriver
def componentName: String = driver.getComponentName
// IItemDriver
def component(item: ItemStack): Option[AnyRef] = Some(driver.getComponent(item))
def componentType(item: ItemStack): ComponentType = driver.getComponentType(item)
def worksWith(item: ItemStack): Boolean = driver.worksWith(item)
})

View File

@ -4,7 +4,6 @@ import java.io.File
import java.io.FileOutputStream
import java.nio.channels.Channels
import scala.collection.mutable.Map
import com.naef.jnlua.LuaState
import com.naef.jnlua.NativeSupport
@ -28,10 +27,10 @@ private[computer] object LuaStateFactory {
// shared libraries somewhere so that we can load them, because we cannot
// load them directly from a JAR.
{
val platform = System.getProperty("os.name").toLowerCase() match {
case name if (name.startsWith("linux")) => "linux"
case name if (name.startsWith("windows")) => "windows"
case name if (name.startsWith("mac")) => "mac"
val platform = System.getProperty("os.name").toLowerCase match {
case name if name.startsWith("linux") => "linux"
case name if name.startsWith("windows") => "windows"
case name if name.startsWith("mac") => "mac"
}
val libPath = "/assets/opencomputers/lib/" + System.getProperty("os.arch") + "/"
@ -65,7 +64,7 @@ private[computer] object LuaStateFactory {
// Copy the file contents to the temporary file.
try {
val in = Channels.newChannel(libraryUrl.openStream())
val out = new FileOutputStream(file).getChannel()
val out = new FileOutputStream(file).getChannel
out.transferFrom(in, 0, Long.MaxValue)
in.close()
out.close()
@ -80,7 +79,7 @@ private[computer] object LuaStateFactory {
}
// Remember the temporary file's location for the loader.
val libraryPath = file.getAbsolutePath()
val libraryPath = file.getAbsolutePath
// Register a custom library loader with JNLua to actually load the ones we
// just extracted.
@ -123,7 +122,7 @@ private[computer] object LuaStateFactory {
state.pushNil()
state.setGlobal("require")
return Some(state)
Some(state)
}
catch {
case ex: Throwable => {

View File

@ -1,15 +1,12 @@
package li.cil.oc.server.computer
import scala.beans.BeanProperty
import scala.collection.JavaConversions._
import scala.collection.mutable.ArrayBuffer
import scala.collection.mutable.Map
import scala.collection.mutable.MutableList
import scala.collection.mutable.Queue
import li.cil.oc.api.INetwork
import li.cil.oc.api.INetworkMessage
import li.cil.oc.api.INetworkNode
import scala.collection.mutable
/**
* Network implementation for component networks.
@ -22,8 +19,8 @@ import li.cil.oc.api.INetworkNode
* It keeps the list of nodes as a lookup table for fast id->node resolving.
* Note that it is possible for multiple nodes to have the same ID, though.
*/
class Network private (private val nodes: Map[Int, ArrayBuffer[Network.Node]]) extends INetwork {
def this(node: INetworkNode) = this(Map(node.getAddress -> ArrayBuffer(new Network.Node(node))))
class Network private(private val nodes: mutable.Map[Int, ArrayBuffer[Network.Node]]) extends INetwork {
def this(node: INetworkNode) = this(mutable.Map(node.getAddress -> ArrayBuffer(new Network.Node(node))))
/** Do not allow modification of the network while it's updating. */
private var locked = false
@ -91,7 +88,7 @@ class Network private (private val nodes: Map[Int, ArrayBuffer[Network.Node]]) e
private def send(message: Network.Message, nodes: Iterator[INetworkNode]) =
while (!message.isCanceled && nodes.hasNext) {
nodes.next.receive(message)
nodes.next().receive(message)
}
private def add(oldNode: Network.Node, node: INetworkNode) = {
@ -100,7 +97,7 @@ class Network private (private val nodes: Map[Int, ArrayBuffer[Network.Node]]) e
// Other node is not yet in a network, create internal node and add it
// to our lookup table of internal nodes.
val newNode = new Network.Node(node)
node.setAddress(findId)
node.setAddress(findId())
nodes.getOrElseUpdate(node.getAddress, new ArrayBuffer[Network.Node]) += newNode
node.setNetwork(this)
sendToAll(node, "network.connect")
@ -148,6 +145,7 @@ class Network private (private val nodes: Map[Int, ArrayBuffer[Network.Node]]) e
}
object Network {
private class Node(val data: INetworkNode) {
val edges = ArrayBuffer.empty[Edge]
@ -157,20 +155,24 @@ object Network {
edge.other(this).edges -= edge
}
// Build neighbor graphs to see if our removal resulted in a split.
val subgraphs = MutableList.empty[(Map[Int, ArrayBuffer[Node]], Queue[Node])]
val subGraphs = mutable.MutableList.empty[(mutable.Map[Int, ArrayBuffer[Node]], mutable.Queue[Node])]
for (edge <- edges) {
val other = edge.other(this)
subgraphs += ((Map(other.data.getAddress -> ArrayBuffer(other)), Queue(other.edges.map(_.other(other)): _*)))
subGraphs += ((mutable.Map(other.data.getAddress -> ArrayBuffer(other)), mutable.Queue(other.edges.map(_.other(other)): _*)))
}
// Breadth-first search to make early merges more likely.
while (!subgraphs.forall { case (_, queue) => queue.isEmpty }) {
for (subgraph <- subgraphs.filter { case (_, queue) => !queue.isEmpty }) {
val (nodes, queue) = subgraph
val node = queue.dequeue
while (!subGraphs.forall {
case (_, queue) => queue.isEmpty
}) {
for (subGraph <- subGraphs.filter {
case (_, queue) => !queue.isEmpty
}) {
val (nodes, queue) = subGraph
val node = queue.dequeue()
// See if the node is already in some other graph, in which case we
// merge this graph into the other graph.
if (!subgraphs.filter(_ != subgraph).find(otherSubgraph => {
val (otherNodes, _) = otherSubgraph
if (!subGraphs.filter(_ != subGraph).exists(otherSubGraph => {
val (otherNodes, _) = otherSubGraph
otherNodes.get(node.data.getAddress) match {
case Some(list) if list.contains(node) => {
// Merge.
@ -181,7 +183,7 @@ object Network {
}
case _ => false
}
}).isDefined) {
})) {
// Not in any other graph yet.
nodes.getOrElseUpdate(node.data.getAddress, new ArrayBuffer[Network.Node]) += node
// Add nodes this node is connected to to the queue if they're not
@ -191,10 +193,10 @@ object Network {
}
}
}
// Create new subnetworks for separated sub-networks. Skip the first one
// Create new sub networks for separated sub-networks. Skip the first one
// to re-use the originating network and avoid re-creation if there is no
// split at all.
subgraphs map (_._1) filter (!_.isEmpty) drop 1 map (new Network(_))
subGraphs map (_._1) filter (!_.isEmpty) drop 1 map (new Network(_))
}
}
@ -202,12 +204,12 @@ object Network {
def other(side: Node) = if (side == left) right else left
}
private class Message(
@BeanProperty val source: INetworkNode,
@BeanProperty val name: String,
@BeanProperty val data: Array[Object] = Array()) extends INetworkMessage {
private class Message(@BeanProperty val source: INetworkNode,
@BeanProperty val name: String,
@BeanProperty val data: Array[Object] = Array()) extends INetworkMessage {
var isCanceled = false
def cancel = isCanceled = true
def cancel() = isCanceled = true
}
}

View File

@ -3,7 +3,6 @@ package li.cil.oc.server.drivers
import li.cil.oc.Blocks
import li.cil.oc.api.scala.IBlockDriver
import li.cil.oc.common.block.BlockMulti
import li.cil.oc.common.components.Screen
import li.cil.oc.common.tileentity.TileEntityScreen
import net.minecraft.block.Block
import net.minecraft.world.World