From c4da02b65c6a1675cd708190b8d266439641b1a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Tue, 11 Feb 2014 23:35:46 +0100 Subject: [PATCH] removed mention of udp from internet cards, those were a lie; text.serialize now line breaks and indents in pretty print mode; tostringing tables with metatable that has a __tostring method in text.serialize with pretty print; corrected comment in config; explicitly putting textures and localizations into the public domain in the license info; deleting empty file system folders from disk on save to reduce clutter in /opencomputers dir; doc field of callback annotations can now be read in computers, methods in proxies are tostring'ed to the docstring; returning false from component.modem.close() when no ports are open, now --- .../cil/oc/common/tileentity/RobotProxy.scala | 6 ++-- .../li/cil/oc/common/tileentity/Screen.scala | 6 ++-- .../cil/oc/server/component/AbstractBus.scala | 12 ++++---- .../oc/server/component/BundledRedstone.scala | 6 ++-- .../oc/server/component/InternetCard.scala | 14 ++++----- .../cil/oc/server/component/NetworkCard.scala | 17 ++++++----- .../li/cil/oc/server/component/Redstone.scala | 6 ++-- .../oc/server/component/UpgradeCrafting.scala | 2 +- .../server/component/UpgradeGenerator.scala | 6 ++-- .../server/component/UpgradeNavigation.scala | 6 ++-- .../cil/oc/server/component/UpgradeSign.scala | 4 +-- .../component/WirelessNetworkCard.scala | 4 +-- .../oc/server/component/machine/Machine.scala | 13 +++++--- .../machine/NativeLuaArchitecture.scala | 24 +++++++++++++++ .../java/li/cil/oc/server/fs/Buffered.scala | 10 +++++-- .../li/cil/oc/server/network/Component.scala | 11 +++++-- src/main/resources/LICENSE | 9 +++++- .../assets/opencomputers/lang/de_DE.lang | 2 +- .../assets/opencomputers/lang/en_US.lang | 2 +- .../assets/opencomputers/lua/kernel.lua | 23 +++++++++++--- .../assets/opencomputers/lua/rom/lib/text.lua | 30 ++++++++++++++----- src/main/resources/reference.conf | 2 +- 22 files changed, 146 insertions(+), 69 deletions(-) diff --git a/src/main/java/li/cil/oc/common/tileentity/RobotProxy.scala b/src/main/java/li/cil/oc/common/tileentity/RobotProxy.scala index 4ecae3c3e..59a8e2574 100644 --- a/src/main/java/li/cil/oc/common/tileentity/RobotProxy.scala +++ b/src/main/java/li/cil/oc/common/tileentity/RobotProxy.scala @@ -46,15 +46,15 @@ class RobotProxy(val robot: Robot) extends Computer(robot.isClient) with ISidedI // ----------------------------------------------------------------------- // - @Callback + @Callback(doc = """function():boolean -- Starts the robot. Returns true if the state changed.""") def start(context: Context, args: Arguments): Array[AnyRef] = result(!computer.isPaused && computer.start()) - @Callback + @Callback(doc = """function():boolean -- Stops the robot. Returns true if the state changed.""") def stop(context: Context, args: Arguments): Array[AnyRef] = result(computer.stop()) - @Callback(direct = true) + @Callback(direct = true, doc = """function():boolean -- Returns whether the robot is running.""") def isRunning(context: Context, args: Arguments): Array[AnyRef] = result(computer.isRunning) diff --git a/src/main/java/li/cil/oc/common/tileentity/Screen.scala b/src/main/java/li/cil/oc/common/tileentity/Screen.scala index aec069e10..43012e953 100644 --- a/src/main/java/li/cil/oc/common/tileentity/Screen.scala +++ b/src/main/java/li/cil/oc/common/tileentity/Screen.scala @@ -25,10 +25,10 @@ class Screen(var tier: Int) extends Buffer with SidedEnvironment with Rotatable // ----------------------------------------------------------------------- // override protected val _buffer = new component.Buffer(this) { - @Callback + @Callback(doc = """function():boolean -- Returns whether the screen is currently on.""") def isOn(computer: Context, args: Arguments): Array[AnyRef] = result(origin.isOn) - @Callback + @Callback(doc = """function():boolean -- Turns off the screen. Returns true if it was on.""") def turnOn(computer: Context, args: Arguments): Array[AnyRef] = { if (!origin.isOn) { origin.turnOn() @@ -37,7 +37,7 @@ class Screen(var tier: Int) extends Buffer with SidedEnvironment with Rotatable else result(false, origin.isOn) } - @Callback + @Callback(doc = """function():boolean -- Turns the screen on. Returns true if it was off.""") def turnOff(computer: Context, args: Arguments): Array[AnyRef] = { if (origin.isOn) { origin.turnOff() diff --git a/src/main/java/li/cil/oc/server/component/AbstractBus.scala b/src/main/java/li/cil/oc/server/component/AbstractBus.scala index 359ba72e6..62b4c4bf2 100644 --- a/src/main/java/li/cil/oc/server/component/AbstractBus.scala +++ b/src/main/java/li/cil/oc/server/component/AbstractBus.scala @@ -54,25 +54,25 @@ class AbstractBus(val device: IBusDevice) extends ManagedComponent with IBusDriv // ----------------------------------------------------------------------- // - @Callback + @Callback(doc = """function():boolean -- Whether the local bus interface is enabled.""") def getEnabled(context: Context, args: Arguments): Array[AnyRef] = result(isEnabled) - @Callback + @Callback(doc = """function(enabled:boolean):boolean -- Sets whether the local bus interface should be enabled.""") def setEnabled(context: Context, args: Arguments): Array[AnyRef] = { isEnabled = args.checkBoolean(0) result(isEnabled) } - @Callback + @Callback(doc = """function():number -- Get the local interface address.""") def getAddress(context: Context, args: Arguments): Array[AnyRef] = result(address) - @Callback + @Callback(doc = """function(address:number):number -- Sets the local interface address.""") def setAddress(context: Context, args: Arguments): Array[AnyRef] = { address = args.checkInteger(0) & 0xFFFF result(address) } - @Callback + @Callback(doc = """function(address:number, data:table):boolean -- Sends data across the abstract bus.""") def send(context: Context, args: Arguments): Array[AnyRef] = { val target = args.checkInteger(0) & 0xFFFF val data = args.checkTable(1) @@ -84,7 +84,7 @@ class AbstractBus(val device: IBusDevice) extends ManagedComponent with IBusDriv else result(false, "not enough energy") } - @Callback(direct = true) + @Callback(direct = true, doc = """function():number -- The maximum packet size that can be sent over the bus.""") def maxPacketSize(context: Context, args: Arguments): Array[AnyRef] = result(Settings.get.maxNetworkPacketSize) // ----------------------------------------------------------------------- // diff --git a/src/main/java/li/cil/oc/server/component/BundledRedstone.scala b/src/main/java/li/cil/oc/server/component/BundledRedstone.scala index 61ea3e42c..d8325a4cb 100644 --- a/src/main/java/li/cil/oc/server/component/BundledRedstone.scala +++ b/src/main/java/li/cil/oc/server/component/BundledRedstone.scala @@ -5,21 +5,21 @@ import li.cil.oc.common.tileentity.BundledRedstoneAware class BundledRedstone(override val owner: BundledRedstoneAware) extends Redstone(owner) { - @Callback(direct = true) + @Callback(direct = true, doc = """function(side:number, color:number):number -- Get the bundled redstone input on the specified side and with the specified color.""") def getBundledInput(context: Context, args: Arguments): Array[AnyRef] = { val side = checkSide(args, 0) val color = checkColor(args, 1) result(owner.bundledInput(side, color)) } - @Callback(direct = true) + @Callback(direct = true, doc = """function(side:number, color:number):number -- Get the bundled redstone output on the specified side and with the specified color.""") def getBundledOutput(context: Context, args: Arguments): Array[AnyRef] = { val side = checkSide(args, 0) val color = checkColor(args, 1) result(owner.bundledOutput(side, color)) } - @Callback + @Callback(doc = """function(side:number, color:number, value:number):number -- Set the bundled redstone output on the specified side and with the specified color.""") def setBundledOutput(context: Context, args: Arguments): Array[AnyRef] = { val side = checkSide(args, 0) val color = checkColor(args, 1) diff --git a/src/main/java/li/cil/oc/server/component/InternetCard.scala b/src/main/java/li/cil/oc/server/component/InternetCard.scala index 8162c1c1c..538ae6bca 100644 --- a/src/main/java/li/cil/oc/server/component/InternetCard.scala +++ b/src/main/java/li/cil/oc/server/component/InternetCard.scala @@ -44,10 +44,10 @@ class InternetCard extends ManagedComponent { // ----------------------------------------------------------------------- // - @Callback(direct = true) + @Callback(direct = true, doc = """function():boolean -- Returns whether HTTP requests can be made (config setting).""") def isHttpEnabled(context: Context, args: Arguments): Array[AnyRef] = result(Settings.get.httpEnabled) - @Callback + @Callback(doc = """function():boolean -- Starts an HTTP request. If this returns true, further results will be pushed using `http_response` signals.""") def request(context: Context, args: Arguments): Array[AnyRef] = { if (owner.isEmpty || context.node.address != owner.get.node.address) { throw new IllegalArgumentException("can only be used by the owning computer") @@ -130,10 +130,10 @@ class InternetCard extends ManagedComponent { }) } - @Callback(direct = true) + @Callback(direct = true, doc = """function():boolean -- Returns whether TCP connections can be made (config setting).""") def isTcpEnabled(context: Context, args: Arguments): Array[AnyRef] = result(Settings.get.httpEnabled) - @Callback + @Callback(doc = """function(address:string[, port:number]):number -- Opens a new TCP connection. Returns the handle of the connection.""") def connect(context: Context, args: Arguments): Array[AnyRef] = { val address = args.checkString(0) val port = if (args.count > 1) args.checkInteger(1) else -1 @@ -151,7 +151,7 @@ class InternetCard extends ManagedComponent { result(handle) } - @Callback + @Callback(doc = """function(handle:number) -- Closes an open socket stream.""") def close(context: Context, args: Arguments): Array[AnyRef] = { val handle = args.checkInteger(0) connections.remove(handle) match { @@ -161,7 +161,7 @@ class InternetCard extends ManagedComponent { null } - @Callback + @Callback(doc = """function(handle:number, data:string):number -- Tries to write data to the socket stream. Returns the number of bytes written.""") def write(context: Context, args: Arguments): Array[AnyRef] = { val handle = args.checkInteger(0) val value = args.checkByteArray(1) @@ -173,7 +173,7 @@ class InternetCard extends ManagedComponent { } } - @Callback + @Callback(doc = """function(handle:number, n:number):string -- Tries to read data from the socket stream. Returns the read byte array.""") def read(context: Context, args: Arguments): Array[AnyRef] = { val handle = args.checkInteger(0) val n = math.min(Settings.get.maxReadBuffer, math.max(0, args.checkInteger(1))) diff --git a/src/main/java/li/cil/oc/server/component/NetworkCard.scala b/src/main/java/li/cil/oc/server/component/NetworkCard.scala index 04c3a4dc2..e125138f2 100644 --- a/src/main/java/li/cil/oc/server/component/NetworkCard.scala +++ b/src/main/java/li/cil/oc/server/component/NetworkCard.scala @@ -17,17 +17,18 @@ class NetworkCard extends ManagedComponent { // ----------------------------------------------------------------------- // - @Callback + @Callback(doc = """function(port:number):boolean -- Opens the specified port. Returns true if the port was opened.""") def open(context: Context, args: Arguments): Array[AnyRef] = { val port = checkPort(args.checkInteger(0)) result(openPorts.add(port)) } - @Callback + @Callback(doc = """function([port:number]):boolean -- Closes the specified port (default: all ports). Returns true if ports were closed.""") def close(context: Context, args: Arguments): Array[AnyRef] = { if (args.count == 0) { + val closed = openPorts.size > 0 openPorts.clear() - result(true) + result(closed) } else { val port = checkPort(args.checkInteger(0)) @@ -35,16 +36,16 @@ class NetworkCard extends ManagedComponent { } } - @Callback(direct = true) + @Callback(direct = true, doc = """function(port:number):boolean -- Whether the specified port is open.""") def isOpen(context: Context, args: Arguments): Array[AnyRef] = { val port = checkPort(args.checkInteger(0)) result(openPorts.contains(port)) } - @Callback(direct = true) + @Callback(direct = true, doc = """function():boolean -- Whether this is a wireless network card.""") def isWireless(context: Context, args: Arguments): Array[AnyRef] = result(false) - @Callback + @Callback(doc = """function(address:string, port:number, data...) -- Sends the specified data to the specified target.""") def send(context: Context, args: Arguments): Array[AnyRef] = { val address = args.checkString(0) val port = checkPort(args.checkInteger(1)) @@ -53,7 +54,7 @@ class NetworkCard extends ManagedComponent { result(true) } - @Callback + @Callback(doc = """function(port:number, data...) -- Broadcasts the specified data on the specified port.""") def broadcast(context: Context, args: Arguments): Array[AnyRef] = { val port = checkPort(args.checkInteger(0)) checkPacketSize(args.drop(1)) @@ -61,7 +62,7 @@ class NetworkCard extends ManagedComponent { result(true) } - @Callback(direct = true) + @Callback(direct = true, doc = """function():number -- Gets the maximum packet size (config setting).""") def maxPacketSize(context: Context, args: Arguments): Array[AnyRef] = result(Settings.get.maxNetworkPacketSize) // ----------------------------------------------------------------------- // diff --git a/src/main/java/li/cil/oc/server/component/Redstone.scala b/src/main/java/li/cil/oc/server/component/Redstone.scala index f80d0d211..1d63a7b0f 100644 --- a/src/main/java/li/cil/oc/server/component/Redstone.scala +++ b/src/main/java/li/cil/oc/server/component/Redstone.scala @@ -12,19 +12,19 @@ class Redstone(val owner: RedstoneAware) extends ManagedComponent { // ----------------------------------------------------------------------- // - @Callback(direct = true) + @Callback(direct = true, doc = """function(side:number):number -- Get the redstone input on the specified side.""") def getInput(context: Context, args: Arguments): Array[AnyRef] = { val side = checkSide(args, 0) result(owner.input(side)) } - @Callback(direct = true) + @Callback(direct = true, doc = """function(side:number):number -- Get the redstone output on the specified side.""") def getOutput(context: Context, args: Arguments): Array[AnyRef] = { val side = checkSide(args, 0) result(owner.output(side)) } - @Callback() + @Callback(doc = """function(side:number, value:number):number -- Set the redstone output on the specified side.""") def setOutput(context: Context, args: Arguments): Array[AnyRef] = { val side = checkSide(args, 0) val value = args.checkInteger(1) diff --git a/src/main/java/li/cil/oc/server/component/UpgradeCrafting.scala b/src/main/java/li/cil/oc/server/component/UpgradeCrafting.scala index 490f893ef..07e2841f0 100644 --- a/src/main/java/li/cil/oc/server/component/UpgradeCrafting.scala +++ b/src/main/java/li/cil/oc/server/component/UpgradeCrafting.scala @@ -17,7 +17,7 @@ class UpgradeCrafting(val owner: MCTileEntity) extends ManagedComponent { withComponent("crafting"). create() - @Callback + @Callback(doc = """function([count:number]):number -- Tries to craft the specified number of items in the top left area of the inventory.""") def craft(context: RobotContext, args: Arguments): Array[AnyRef] = { val count = if (args.count > 0) args.checkInteger(0) else Int.MaxValue result(CraftingInventory.craft(context, count)) diff --git a/src/main/java/li/cil/oc/server/component/UpgradeGenerator.scala b/src/main/java/li/cil/oc/server/component/UpgradeGenerator.scala index 4f23f1a7a..91f8b7b14 100644 --- a/src/main/java/li/cil/oc/server/component/UpgradeGenerator.scala +++ b/src/main/java/li/cil/oc/server/component/UpgradeGenerator.scala @@ -21,7 +21,7 @@ class UpgradeGenerator(val owner: TileEntity) extends ManagedComponent { // ----------------------------------------------------------------------- // - @Callback + @Callback(doc = """function([count:number]):boolean -- Tries to insert fuel from the selected slot into the generator's queue.""") def insert(context: RobotContext, args: Arguments): Array[AnyRef] = { val count = if (args.count > 0) args.checkInteger(0) else 64 val player = context.player @@ -48,7 +48,7 @@ class UpgradeGenerator(val owner: TileEntity) extends ManagedComponent { result(true) } - @Callback + @Callback(doc = """function():number -- Get the size of the item stack in the generator's queue.""") def count(context: Context, args: Arguments): Array[AnyRef] = { inventory match { case Some(stack) => result(stack.stackSize) @@ -56,7 +56,7 @@ class UpgradeGenerator(val owner: TileEntity) extends ManagedComponent { } } - @Callback + @Callback(doc = """function([count:number]):boolean -- Tries to remove items from the generator's queue.""") def remove(context: RobotContext, args: Arguments): Array[AnyRef] = { val count = if (args.count > 0) args.checkInteger(0) else Int.MaxValue inventory match { diff --git a/src/main/java/li/cil/oc/server/component/UpgradeNavigation.scala b/src/main/java/li/cil/oc/server/component/UpgradeNavigation.scala index 1217fc632..1ad8fb8c9 100644 --- a/src/main/java/li/cil/oc/server/component/UpgradeNavigation.scala +++ b/src/main/java/li/cil/oc/server/component/UpgradeNavigation.scala @@ -11,7 +11,7 @@ class UpgradeNavigation(val owner: TileEntity, val xCenter: Int, val zCenter: In // ----------------------------------------------------------------------- // - @Callback + @Callback(doc = """function():number, number, number -- Get the current relative position of the robot.""") def getPosition(context: Context, args: Arguments): Array[AnyRef] = { val x = owner.xCoord val y = owner.yCoord @@ -25,7 +25,7 @@ class UpgradeNavigation(val owner: TileEntity, val xCenter: Int, val zCenter: In result(Unit, "out of range") } - @Callback + @Callback(doc = """function():number -- Get the current orientation of the robot.""") def getFacing(context: Context, args: Arguments): Array[AnyRef] = { owner match { case rotatable: Rotatable => result(rotatable.facing.ordinal) @@ -33,7 +33,7 @@ class UpgradeNavigation(val owner: TileEntity, val xCenter: Int, val zCenter: In } } - @Callback + @Callback(doc = """function():number -- Get the operational range of the navigation upgrade.""") def getRange(context: Context, args: Arguments): Array[AnyRef] = { result(size / 2) } diff --git a/src/main/java/li/cil/oc/server/component/UpgradeSign.scala b/src/main/java/li/cil/oc/server/component/UpgradeSign.scala index bc6279169..41989db55 100644 --- a/src/main/java/li/cil/oc/server/component/UpgradeSign.scala +++ b/src/main/java/li/cil/oc/server/component/UpgradeSign.scala @@ -12,7 +12,7 @@ class UpgradeSign(val owner: TileEntity) extends ManagedComponent { // ----------------------------------------------------------------------- // - @Callback + @Callback(doc = """function():string -- Get the text on the sign in front of the robot.""") def getValue(context: Context, args: Arguments): Array[AnyRef] = { val facing = owner match { case rotatable: Rotatable => rotatable.facing @@ -24,7 +24,7 @@ class UpgradeSign(val owner: TileEntity) extends ManagedComponent { } } - @Callback + @Callback(doc = """function(value:string):string -- Set the text on the sign in front of the robot.""") def setValue(context: Context, args: Arguments): Array[AnyRef] = { val text = args.checkString(0).lines.padTo(4, "").map(line => if (line.length > 15) line.substring(0, 15) else line) val facing = owner match { diff --git a/src/main/java/li/cil/oc/server/component/WirelessNetworkCard.scala b/src/main/java/li/cil/oc/server/component/WirelessNetworkCard.scala index 23dd7ce07..e1a674f89 100644 --- a/src/main/java/li/cil/oc/server/component/WirelessNetworkCard.scala +++ b/src/main/java/li/cil/oc/server/component/WirelessNetworkCard.scala @@ -20,10 +20,10 @@ class WirelessNetworkCard(val owner: TileEntity) extends NetworkCard { // ----------------------------------------------------------------------- // - @Callback(direct = true) + @Callback(direct = true, doc = """function():number -- Get the signal strength (range) used when sending messages.""") def getStrength(context: Context, args: Arguments): Array[AnyRef] = result(strength) - @Callback + @Callback(doc = """function(strength:number):number -- Set the signal strength (range) used when sending messages.""") def setStrength(context: Context, args: Arguments): Array[AnyRef] = { strength = math.max(args.checkDouble(0), math.min(0, Settings.get.maxWirelessRange)) result(strength) diff --git a/src/main/java/li/cil/oc/server/component/machine/Machine.scala b/src/main/java/li/cil/oc/server/component/machine/Machine.scala index 1f53792a1..a94dce97d 100644 --- a/src/main/java/li/cil/oc/server/component/machine/Machine.scala +++ b/src/main/java/li/cil/oc/server/component/machine/Machine.scala @@ -218,9 +218,14 @@ class Machine(val owner: Machine.Owner) extends ManagedComponent with Context wi counts(method) += 1 } component.invoke(method, this, args: _*) - case _ => throw new Exception("no such component") + case _ => throw new IllegalArgumentException("no such component") } + private[component] def doc(address: String, method: String) = Option(node.network.node(address)) match { + case Some(component: server.network.Component) if component.canBeSeenFrom(node) || component == node => component.doc(method) + case _ => throw new IllegalArgumentException("no such component") + } + private[component] def addUser(name: String) { if (_users.size >= Settings.get.maxUsers) throw new Exception("too many users") @@ -248,15 +253,15 @@ class Machine(val owner: Machine.Owner) extends ManagedComponent with Context wi // ----------------------------------------------------------------------- // - @Callback + @Callback(doc = """function():boolean -- Starts the computer. Returns true if the state changed.""") def start(context: Context, args: Arguments): Array[AnyRef] = result(!isPaused && start()) - @Callback + @Callback(doc = """function():boolean -- Stops the computer. Returns true if the state changed.""") def stop(context: Context, args: Arguments): Array[AnyRef] = result(stop()) - @Callback(direct = true) + @Callback(direct = true, doc = """function():boolean -- Returns whether the computer is running.""") def isRunning(context: Context, args: Arguments): Array[AnyRef] = result(isRunning) diff --git a/src/main/java/li/cil/oc/server/component/machine/NativeLuaArchitecture.scala b/src/main/java/li/cil/oc/server/component/machine/NativeLuaArchitecture.scala index b37f1aed3..ce360f5ca 100644 --- a/src/main/java/li/cil/oc/server/component/machine/NativeLuaArchitecture.scala +++ b/src/main/java/li/cil/oc/server/component/machine/NativeLuaArchitecture.scala @@ -1,5 +1,6 @@ package li.cil.oc.server.component.machine +import com.google.common.base.Strings import com.naef.jnlua._ import java.io.{IOException, FileNotFoundException} import java.util.logging.Level @@ -528,6 +529,29 @@ class NativeLuaArchitecture(val machine: Machine) extends Architecture { }) lua.setField(-2, "invoke") + lua.pushScalaFunction(lua => { + val address = lua.checkString(1) + val method = lua.checkString(2) + try { + val doc = machine.doc(address, method) + if (Strings.isNullOrEmpty(doc)) + lua.pushNil() + else + lua.pushString(doc) + 1 + } catch { + case e: NoSuchMethodException => + lua.pushNil() + lua.pushString("no such method") + 2 + case t: Throwable => + lua.pushNil() + lua.pushString(if (t.getMessage != null) t.getMessage else t.toString) + 2 + } + }) + lua.setField(-2, "doc") + lua.setGlobal("component") initPerms() diff --git a/src/main/java/li/cil/oc/server/fs/Buffered.scala b/src/main/java/li/cil/oc/server/fs/Buffered.scala index c1de16a15..c8a8077b1 100644 --- a/src/main/java/li/cil/oc/server/fs/Buffered.scala +++ b/src/main/java/li/cil/oc/server/fs/Buffered.scala @@ -55,7 +55,10 @@ trait Buffered extends OutputStreamFileSystem { } setLastModified(path, directory.lastModified()) } - recurse("", fileRoot) + if (fileRoot.list() == null || fileRoot.list().length == 0) { + fileRoot.delete() + } + else recurse("", fileRoot) super.load(nbt) } @@ -94,6 +97,9 @@ trait Buffered extends OutputStreamFileSystem { } directory.setLastModified(lastModified(path)) } - recurse("") + if (list("") == null || list("").length == 0) { + fileRoot.delete() + } + else recurse("") } } diff --git a/src/main/java/li/cil/oc/server/network/Component.scala b/src/main/java/li/cil/oc/server/network/Component.scala index c5f2a309c..3939889aa 100644 --- a/src/main/java/li/cil/oc/server/network/Component.scala +++ b/src/main/java/li/cil/oc/server/network/Component.scala @@ -99,6 +99,11 @@ trait Component extends network.Component with Node { def methods = callbacks.keySet + def doc(name: String) = callbacks.get(name) match { + case Some(callback) => callback.doc + case _ => throw new NoSuchMethodException() + } + def invoke(method: String, context: Context, arguments: AnyRef*) = callbacks.get(method) match { case Some(callback) => hosts(method) match { @@ -173,7 +178,7 @@ object Component { val a = m.getAnnotation[network.Callback](classOf[network.Callback]) val name = if (a.value != null && a.value.trim != "") a.value else m.getName if (!callbacks.contains(name)) { - callbacks += name -> new ComponentCallback(m, a.direct, a.limit) + callbacks += name -> new ComponentCallback(m, a.direct, a.limit, a.doc) } } ) @@ -201,11 +206,11 @@ object Component { // ----------------------------------------------------------------------- // - abstract class Callback(val direct: Boolean, val limit: Int) { + abstract class Callback(val direct: Boolean, val limit: Int, val doc: String = "") { def apply(instance: Environment, context: Context, args: Arguments): Array[AnyRef] } - class ComponentCallback(val method: Method, direct: Boolean, limit: Int) extends Callback(direct, limit) { + class ComponentCallback(val method: Method, direct: Boolean, limit: Int, doc: String) extends Callback(direct, limit, doc) { override def apply(instance: Environment, context: Context, args: Arguments) = try { method.invoke(instance, context, args).asInstanceOf[Array[AnyRef]] } catch { diff --git a/src/main/resources/LICENSE b/src/main/resources/LICENSE index c17a158fd..68dd6e055 100644 --- a/src/main/resources/LICENSE +++ b/src/main/resources/LICENSE @@ -16,4 +16,11 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. \ No newline at end of file +THE SOFTWARE. + +------------------------------------------------------------------------------- + +All images / textures and localization strings (resources) are put in the +public domain. More specicially, see CC0 1.0 Universal: + + http://creativecommons.org/publicdomain/zero/1.0/ \ No newline at end of file diff --git a/src/main/resources/assets/opencomputers/lang/de_DE.lang b/src/main/resources/assets/opencomputers/lang/de_DE.lang index 9c4eba203..c9f1bc053 100644 --- a/src/main/resources/assets/opencomputers/lang/de_DE.lang +++ b/src/main/resources/assets/opencomputers/lang/de_DE.lang @@ -133,7 +133,7 @@ oc:tooltip.Disk=Sehr einfaches Speichermedium, das verwendet werden kann, um Dis oc:tooltip.DiskDrive.CC=ComputerCraft-Disketten werden §aunterstützt§7. oc:tooltip.DiskDrive=Erlaubt es, Disketten zu lesen und zu beschreiben. oc:tooltip.GraphicsCard=Erlaubt es, den angezeigten Inhalt von Bildschirmen zu ändern.[nl] Höchstauflösung: §f%sx%s§7.[nl] Maximale Farbtiefe: §f%s§7.[nl] Operationen/Tick: §f%s§7. -oc:tooltip.InternetCard=Diese Karte erlaubt es, HTTP-Anfragen zu senden und echte TCP und UDP Sockets zu verwenden. +oc:tooltip.InternetCard=Diese Karte erlaubt es, HTTP-Anfragen zu senden und echte TCP Sockets zu verwenden. oc:tooltip.IronNugget=Ein Nugget, das aus Eisen besteht, darum wird es ja auch Eisennugget genannt, duh... oc:tooltip.Keyboard=Kann an Bildschirmen befestigt werden, um auf ihnen zu tippen. oc:tooltip.Memory=Braucht ein jeder Computer, um zu starten. Je mehr vorhanden, desto komplexere Programme können ausgeführt werden. diff --git a/src/main/resources/assets/opencomputers/lang/en_US.lang b/src/main/resources/assets/opencomputers/lang/en_US.lang index 22abe2be9..b5f8195d6 100644 --- a/src/main/resources/assets/opencomputers/lang/en_US.lang +++ b/src/main/resources/assets/opencomputers/lang/en_US.lang @@ -133,7 +133,7 @@ oc:tooltip.Disk=Primitive medium that can be used to build persistent storage de oc:tooltip.DiskDrive.CC=ComputerCraft floppies are §asupported§7. oc:tooltip.DiskDrive=Allows reading and writing floppies. oc:tooltip.GraphicsCard=Used to change what's displayed on screens.[nl] Maximum resolution: §f%sx%s§7.[nl] Maximum color depth: §f%s§7.[nl] Operations/tick: §f%s§7. -oc:tooltip.InternetCard=This card allows making HTTP requests and using real TCP and UDP sockets. +oc:tooltip.InternetCard=This card allows making HTTP requests and using real TCP sockets. oc:tooltip.IronNugget=A nugget made of iron, that's why it's called an Iron Nugget, duh... oc:tooltip.Keyboard=Can be attached to screens to allow typing on them. oc:tooltip.Memory=Required to get computers to run. The more you have, the more complex the programs you can run. diff --git a/src/main/resources/assets/opencomputers/lua/kernel.lua b/src/main/resources/assets/opencomputers/lua/kernel.lua index aae4f1804..cf313eb7a 100644 --- a/src/main/resources/assets/opencomputers/lua/kernel.lua +++ b/src/main/resources/assets/opencomputers/lua/kernel.lua @@ -259,7 +259,17 @@ sandbox._G = sandbox ------------------------------------------------------------------------------- -- Start of non-standard stuff made available via package.preload. -local libcomponent = { +local libcomponent +libcomponent = { + doc = function(address, method) + checkArg(1, address, "string") + checkArg(2, method, "string") + local result, reason = component.doc(address, method) + if not result and reason then + error(reason, 2) + end + return result + end, invoke = function(address, method, ...) checkArg(1, address, "string") checkArg(2, method, "string") @@ -288,9 +298,14 @@ local libcomponent = { return nil, reason end for method, direct in pairs(methods) do - proxy[method] = function(...) - return invoke(direct, address, method, ...) - end + proxy[method] = setmetatable({}, { + __call = function(_, ...) + return invoke(direct, address, method, ...) + end, + __tostring = function() + return libcomponent.doc(address, method) or "function" + end + }) end return proxy end, diff --git a/src/main/resources/assets/opencomputers/lua/rom/lib/text.lua b/src/main/resources/assets/opencomputers/lua/rom/lib/text.lua index 98ef4d588..ebca7a9a4 100644 --- a/src/main/resources/assets/opencomputers/lua/rom/lib/text.lua +++ b/src/main/resources/assets/opencomputers/lua/rom/lib/text.lua @@ -95,7 +95,7 @@ function text.serialize(value, pretty) ["until"]=true, ["while"]=true} local id = "^[%a_][%w_]*$" local ts = {} - local function s(v) + local function s(v, l) local t = type(v) if t == "nil" then return "nil" @@ -113,6 +113,8 @@ function text.serialize(value, pretty) end elseif t == "string" then return string.format("%q", v) + elseif t == "table" and pretty and getmetatable(v) and getmetatable(v).__tostring then + return tostring(v) elseif t == "table" then if ts[v] then if pretty then @@ -122,24 +124,36 @@ function text.serialize(value, pretty) end end ts[v] = true - local i, r = 1, nil - for k, v in pairs(v) do + local f, i, r = 1, nil + if pretty then + local ks = {} + for k in pairs(v) do table.insert(ks, k) end + table.sort(ks) + local k = 0 + f = function() + k = k + 1 + return ks[k], ks[k] and v[ks[k]] or nil + end + else + f = pairs(v) + end + for k, v in f do if r then - r = r .. "," + r = r .. "," .. (pretty and ("\n" .. string.rep(" ", l)) or "") else r = "{" end local tk = type(k) if tk == "number" and k == i then i = i + 1 - r = r .. s(v) + r = r .. s(v, l + 1) else if tk == "string" and not kw[k] and string.match(k, id) then r = r .. k else - r = r .. "[" .. s(k) .. "]" + r = r .. "[" .. s(k, l + 1) .. "]" end - r = r .. "=" .. s(v) + r = r .. "=" .. s(v, l + 1) end end ts[v] = nil -- allow writing same table more than once @@ -152,7 +166,7 @@ function text.serialize(value, pretty) end end end - local result = s(value) + local result = s(value, 1) local limit = type(pretty) == "number" and pretty or 1000 if pretty and unicode.len(result) > limit then return result:sub(1, limit) .. "..." diff --git a/src/main/resources/reference.conf b/src/main/resources/reference.conf index e7fed2d10..232b759dc 100644 --- a/src/main/resources/reference.conf +++ b/src/main/resources/reference.conf @@ -101,7 +101,7 @@ opencomputers { activeGC: true # The sizes of the three tiers of RAM, in kilobytes. This list must - # contain exactly three entries, or it will be ignored. + # contain exactly five entries, or it will be ignored. ramSizes: [ 64 128