Merge branch 'master' of github.com:MightyPirates/OpenComputers into MC1.7

Conflicts:
	src/main/scala/li/cil/oc/common/Proxy.scala
This commit is contained in:
Florian Nücke 2014-06-06 12:50:21 +02:00
commit d06285c35f
11 changed files with 122 additions and 71 deletions

View File

@ -262,7 +262,7 @@ sandbox._G = sandbox
-- These functions provide the logic for wrapping and unwrapping (when
-- pushed to user code and when pushed back to the host, respectively).
local wrapUserdata, wrapSingleUserdata, unwrapUserdata, wrappedUserdataMeta
--[[
wrappedUserdataMeta = {
-- Weak keys, clean up once a proxy is no longer referenced anywhere.
__mode="k",
@ -278,7 +278,7 @@ wrappedUserdataMeta = {
end
}
local wrappedUserdata = setmetatable({}, wrappedUserdataMeta)
]]
local function processResult(result)
wrapUserdata(result) -- needed for metamethods.
if not result[1] then -- error that should be re-thrown.
@ -307,7 +307,7 @@ local function invoke(target, direct, ...)
end
return processResult(result)
end
--[[
local function udinvoke(f, data, ...)
local args = table.pack(...)
unwrapUserdata(args)
@ -424,9 +424,6 @@ function unwrapUserdata(values)
end
unwrapRecursively(values)
end
]]
function wrapUserdata(...) return ... end
function unwrapUserdata(...) return ... end
-------------------------------------------------------------------------------

View File

@ -46,6 +46,11 @@ opencomputers {
# filled chars to appear (i.e. the block symbol that is used for cursor
# blinking for example) on less accurate hardware.
fontCharScale: 1.01
# The maximum render distance of a hologram projected by a highest tier
# hologram projector when at maximum scale. Render distance is scaled
# down with the actual scale of the hologram.
hologramRenderDistance: 64
}
# Computer related settings, concerns server performance and security.
@ -145,25 +150,45 @@ opencomputers {
# See also: `canComputersBeOwned`.
maxUsernameLength: 32
# This setting is meant for debugging errors that occur in Lua callbacks.
# Per default, if an error occurs and it has a message set, only the
# message is pushed back to Lua, and that's it. If you encounter weird
# errors or are developing an addon you'll want the stacktrace for those
# errors. Enabling this setting will log them to the game log. This is
# disabled per default to avoid spamming the log with inconsequentual
# exceptions such as IllegalArgumentExceptions and the like.
logCallbackErrors: false
# Whether to delete all contents in the /tmp file system when performing
# a 'soft' reboot (i.e. via `computer.shutdown(true)`). The tmpfs will
# always be erased when the computer is completely powered off, even if
# it crashed. This setting is purely for software-triggered reboots.
eraseTmpOnReboot: false
# Forces the use of the LuaJ fallback instead of the native libraries.
# Use this if you have (unfounded) concerns using native libraries or
# experience issues with the native library. Also used for debugging.
forceLuaJ: false
# Debugging related settings. You usually don't want to touch these
# unless asked to do so by a developer.
debug {
# Forces the use of the LuaJ fallback instead of the native libraries.
# Use this if you have concerns using native libraries or experience
# issues with the native library.
forceLuaJ: false
# This setting is meant for debugging errors that occur in Lua callbacks.
# Per default, if an error occurs and it has a message set, only the
# message is pushed back to Lua, and that's it. If you encounter weird
# errors or are developing an addon you'll want the stacktrace for those
# errors. Enabling this setting will log them to the game log. This is
# disabled per default to avoid spamming the log with inconsequentual
# exceptions such as IllegalArgumentExceptions and the like.
logCallbackErrors: false
# Disable user data support. This means any otherwise supported
# userdata (implementing the Value interface) will not be pushed
# to the Lua state.
disableUserdata: false
# Disable computer state persistence. This means that computers will
# automatically be rebooted when loaded after being unloaded, instead
# of resuming with their exection (it also means the state is not even
# saved). Only relevant when using the native library.
disablePersistence: false
# Disable memory limit enforcement. This means Lua states can
# theoretically use as much memory as they want. Only relevant when
# using the native library.
disableMemoryLimit: false
}
}
# Robot related settings, what they may do and general balancing.

View File

@ -22,6 +22,7 @@ class Settings(config: Config) {
val robotLabels = config.getBoolean("client.robotLabels")
val soundVolume = config.getDouble("client.soundVolume").toFloat max 0 min 2
val fontCharScale = config.getDouble("client.fontCharScale") max 0.5 min 2
val hologramRenderDistance = config.getDouble("client.hologramRenderDistance") max 0
// ----------------------------------------------------------------------- //
// computer
@ -47,10 +48,16 @@ class Settings(config: Config) {
val maxUsers = config.getInt("computer.maxUsers") max 0
val maxUsernameLength = config.getInt("computer.maxUsernameLength") max 0
val allowBytecode = config.getBoolean("computer.allowBytecode")
val logLuaCallbackErrors = config.getBoolean("computer.logCallbackErrors")
val eraseTmpOnReboot = config.getBoolean("computer.eraseTmpOnReboot")
val forceLuaJ = config.getBoolean("computer.forceLuaJ")
val allowUserdata = false // unstable
// ----------------------------------------------------------------------- //
// computer.debug
val logLuaCallbackErrors = config.getBoolean("computer.debug.logCallbackErrors")
val forceLuaJ = config.getBoolean("computer.debug.forceLuaJ")
val allowUserdata = !config.getBoolean("computer.debug.disableUserdata")
val allowPersistence = !config.getBoolean("computer.debug.disablePersistence")
val limitMemory = !config.getBoolean("computer.debug.disableMemoryLimit")
// ----------------------------------------------------------------------- //
// robot

View File

@ -274,6 +274,8 @@ class Hologram(var tier: Int) extends traits.Environment with SidedEnvironment w
override def shouldRenderInPass(pass: Int) = pass == 1
override def getMaxRenderDistanceSquared = scale / Settings.hologramMaxScaleByTier.max * Settings.get.hologramRenderDistance * Settings.get.hologramRenderDistance
override def getRenderBoundingBox = AxisAlignedBB.getAABBPool.getAABB(xCoord + 0.5 - 1.5 * scale, yCoord, zCoord - scale, xCoord + 0.5 + 1.5 * scale, yCoord + 0.25 + 2 * scale, zCoord + 0.5 + 1.5 * scale)
// ----------------------------------------------------------------------- //

View File

@ -9,7 +9,6 @@ import li.cil.oc.util.mods.{Mods, StargateTech2}
import net.minecraft.nbt.NBTTagCompound
import stargatetech2.api.bus.{IBusInterface, IBusDevice}
import stargatetech2.api.StargateTechAPI
import li.cil.oc.server.component.AbstractBus
// IMPORTANT: for some reason that is beyond me we cannot implement the
// IBusDevice here directly, since we'll get an error if the interface is not
@ -32,7 +31,7 @@ trait AbstractBusAware extends TileEntity with network.Environment {
if (isAbstractBusAvailable) {
if (isServer) {
installedComponents.collect {
case abstractBus: AbstractBus => abstractBus.busInterface
case abstractBus: component.AbstractBusCard => abstractBus.busInterface
}.toArray
}
else fakeInterface.map(_.asInstanceOf[IBusInterface])

View File

@ -9,7 +9,7 @@ import scala.collection.convert.WrapAsScala._
import stargatetech2.api.StargateTechAPI
import stargatetech2.api.bus._
class AbstractBus(val device: IBusDevice) extends component.ManagedComponent with IBusDriver {
class AbstractBusCard(val device: IBusDevice) extends component.ManagedComponent with IBusDriver {
val node = Network.newNode(this, Visibility.Neighbors).
withComponent("abstract_bus").
withConnector().
@ -70,7 +70,7 @@ class AbstractBus(val device: IBusDevice) extends component.ManagedComponent wit
result(address)
}
@Callback(doc = """function(address:number, data:table):boolean -- Sends data across the abstract bus.""")
@Callback(doc = """function(address:number, data:table):table -- Sends data across the abstract bus.""")
def send(context: Context, args: Arguments): Array[AnyRef] = this.synchronized {
val target = args.checkInteger(0) & 0xFFFF
val data = args.checkTable(1)

View File

@ -103,7 +103,9 @@ abstract class GraphicsCard extends component.ManagedComponent {
@Callback(direct = true)
def getPaletteColor(context: Context, args: Arguments): Array[AnyRef] = {
val index = args.checkInteger(0)
screen(s => result(s.getPaletteColor(index)))
screen(s => try result(s.getPaletteColor(index)) catch {
case _: ArrayIndexOutOfBoundsException => throw new IllegalArgumentException("invalid palette index")
})
}
@Callback
@ -111,10 +113,13 @@ abstract class GraphicsCard extends component.ManagedComponent {
val index = args.checkInteger(0)
val color = args.checkInteger(1)
context.pause(0.1)
screen(s => {
screen(s => try {
val oldColor = s.getPaletteColor(index)
s.setPaletteColor(index, color)
result(oldColor)
}
catch {
case _: ArrayIndexOutOfBoundsException => throw new IllegalArgumentException("invalid palette index")
})
}

View File

@ -28,10 +28,11 @@ class NativeLuaArchitecture(val machine: api.machine.Machine) extends Architectu
new ComponentAPI(this),
new ComputerAPI(this),
new OSAPI(this),
persistence,
new SystemAPI(this),
new UnicodeAPI(this),
new UserdataAPI(this))
new UserdataAPI(this),
// Persistence has to go last to ensure all other APIs can go into the permanent value table.
persistence)
private[machine] def invoke(f: () => Array[AnyRef]): Int = try {
f() match {
@ -125,7 +126,7 @@ class NativeLuaArchitecture(val machine: api.machine.Machine) extends Architectu
override def isInitialized = kernelMemory > 0
override def recomputeMemory() = Option(lua) match {
case Some(l) =>
case Some(l) if Settings.get.limitMemory =>
l.setTotalMemory(Int.MaxValue)
l.gc(LuaState.GcAction.COLLECT, 0)
if (kernelMemory > 0) {
@ -241,7 +242,9 @@ class NativeLuaArchitecture(val machine: api.machine.Machine) extends Architectu
new ExecutionResult.Shutdown(false)
}
else {
lua.setTotalMemory(Int.MaxValue)
if (Settings.get.limitMemory) {
lua.setTotalMemory(Int.MaxValue)
}
val error =
if (lua.isJavaObjectRaw(3)) lua.toJavaObjectRaw(3).toString
else lua.toString(3)
@ -291,7 +294,9 @@ class NativeLuaArchitecture(val machine: api.machine.Machine) extends Architectu
override def close() {
if (lua != null) {
lua.setTotalMemory(Integer.MAX_VALUE)
if (Settings.get.limitMemory) {
lua.setTotalMemory(Integer.MAX_VALUE)
}
lua.close()
}
lua = null
@ -310,7 +315,9 @@ class NativeLuaArchitecture(val machine: api.machine.Machine) extends Architectu
bootAddress = nbt.getString("bootAddress")
// Unlimit memory use while unpersisting.
lua.setTotalMemory(Integer.MAX_VALUE)
if (Settings.get.limitMemory) {
lua.setTotalMemory(Integer.MAX_VALUE)
}
try {
// Try unpersisting Lua, because that's what all of the rest depends
@ -333,7 +340,7 @@ class NativeLuaArchitecture(val machine: api.machine.Machine) extends Architectu
if (!lua.isThread(1)) {
// This shouldn't really happen, but there's a chance it does if
// the save was corrupt (maybe someone modified the Lua files).
throw new IllegalArgumentException("Invalid kernel.")
throw new LuaRuntimeException("Invalid kernel.")
}
if (state.contains(Machine.State.SynchronizedCall) || state.contains(Machine.State.SynchronizedReturn)) {
val stack =
@ -343,15 +350,16 @@ class NativeLuaArchitecture(val machine: api.machine.Machine) extends Architectu
if (!(if (state.contains(Machine.State.SynchronizedCall)) lua.isFunction(2) else lua.isTable(2))) {
// Same as with the above, should not really happen normally, but
// could for the same reasons.
throw new IllegalArgumentException("Invalid stack.")
throw new LuaRuntimeException("Invalid stack.")
}
}
kernelMemory = (nbt.getInteger("kernelMemory") * ramScale).toInt
} catch {
case e: LuaRuntimeException =>
OpenComputers.log.warning("Could not unpersist computer.\n" + e.toString + "\tat " + e.getLuaStackTrace.mkString("\n\tat "))
OpenComputers.log.warning("Could not unpersist computer.\n" + e.toString + (if (e.getLuaStackTrace.isEmpty) "" else "\tat " + e.getLuaStackTrace.mkString("\n\tat ")))
machine.stop()
machine.start()
}
// Limit memory again.
@ -364,7 +372,9 @@ class NativeLuaArchitecture(val machine: api.machine.Machine) extends Architectu
}
// Unlimit memory while persisting.
lua.setTotalMemory(Integer.MAX_VALUE)
if (Settings.get.limitMemory) {
lua.setTotalMemory(Integer.MAX_VALUE)
}
try {
// Try persisting Lua, because that's what all of the rest depends on.

View File

@ -99,43 +99,47 @@ class PersistenceAPI(owner: NativeLuaArchitecture) extends NativeLuaAPI(owner) {
}
def persist(index: Int): Array[Byte] = {
configure()
lua.getGlobal("eris") // ... eris
lua.getField(-1, "persist") // ... eris persist
if (lua.isFunction(-1)) {
lua.getField(LuaState.REGISTRYINDEX, "perms") // ... eris persist perms
lua.pushValue(index) // ... eris persist perms obj
try {
lua.call(2, 1) // ... eris str?
} catch {
case e: Throwable =>
lua.pop(1)
throw e
}
if (lua.isString(-1)) {
// ... eris str
val result = lua.toByteArray(-1)
lua.pop(2) // ...
return result
if (Settings.get.allowPersistence) {
configure()
lua.getGlobal("eris") // ... eris
lua.getField(-1, "persist") // ... eris persist
if (lua.isFunction(-1)) {
lua.getField(LuaState.REGISTRYINDEX, "perms") // ... eris persist perms
lua.pushValue(index) // ... eris persist perms obj
try {
lua.call(2, 1) // ... eris str?
} catch {
case e: Throwable =>
lua.pop(1)
throw e
}
if (lua.isString(-1)) {
// ... eris str
val result = lua.toByteArray(-1)
lua.pop(2) // ...
return result
} // ... eris :(
} // ... eris :(
} // ... eris :(
lua.pop(2) // ...
lua.pop(2) // ...
}
Array[Byte]()
}
def unpersist(value: Array[Byte]): Boolean = {
configure()
lua.getGlobal("eris") // ... eris
lua.getField(-1, "unpersist") // ... eris unpersist
if (lua.isFunction(-1)) {
lua.getField(LuaState.REGISTRYINDEX, "uperms") // ... eris persist uperms
lua.pushByteArray(value) // ... eris unpersist uperms str
lua.call(2, 1) // ... eris obj
lua.insert(-2) // ... obj eris
if (Settings.get.allowPersistence) {
configure()
lua.getGlobal("eris") // ... eris
lua.getField(-1, "unpersist") // ... eris unpersist
if (lua.isFunction(-1)) {
lua.getField(LuaState.REGISTRYINDEX, "uperms") // ... eris persist uperms
lua.pushByteArray(value) // ... eris unpersist uperms str
lua.call(2, 1) // ... eris obj
lua.insert(-2) // ... obj eris
lua.pop(1)
return true
} // ... :(
lua.pop(1)
return true
} // ... :(
lua.pop(1)
}
false
}
}

View File

@ -11,7 +11,7 @@ object AbstractBusCard extends Item {
override def worksWith(stack: ItemStack) = isOneOf(stack, api.Items.get("abstractBusCard"))
override def createEnvironment(stack: ItemStack, container: Container) = if (Mods.StargateTech2.isAvailable) container match {
case device: IBusDevice => new component.AbstractBus(device)
case device: IBusDevice => new component.AbstractBusCard(device)
case _ => null
}
else null

View File

@ -158,7 +158,9 @@ object LuaStateFactory {
if (!haveNativeLibrary) return None
try {
val state = new jnlua.LuaState(Int.MaxValue)
val state =
if (Settings.get.limitMemory) new jnlua.LuaState(Int.MaxValue)
else new jnlua.LuaState()
try {
// Load all libraries.
state.openLib(jnlua.LuaState.Library.BASE)