From ab785eb3acd2dbabb46ae6726d1b15c58bff4a13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Mon, 4 Nov 2013 20:53:31 +0100 Subject: [PATCH] forbid access to string metatable for sandbox; minor restructuring of libraries (mostly sorting by name); saving managed environments attached to an adapter. this is not very reliable, sadly, since there are way too many ways neighbors can change outside our control (chunks only partially loaded, types removed across games due to other mod changes, mods that move blocks such as RIM, ...); making some effort to re-attach peripherals using their previous address; removed connection code on chunk load in network manager, since this is also handled by the check in the tile entities' update function --- assets/opencomputers/lua/kernel.lua | 9 ++- assets/opencomputers/lua/rom/bin/df.lua | 4 +- assets/opencomputers/lua/rom/lib/event.lua | 62 ++++++++--------- .../opencomputers/lua/rom/lib/filesystem.lua | 30 +++----- assets/opencomputers/lua/rom/lib/io.lua | 40 +++++------ assets/opencomputers/lua/rom/lib/keyboard.lua | 27 ++++---- assets/opencomputers/lua/rom/lib/redstone.lua | 25 ------- assets/opencomputers/lua/rom/lib/shell.lua | 7 +- assets/opencomputers/lua/rom/lib/sides.lua | 17 +++++ assets/opencomputers/lua/rom/lib/term.lua | 13 ++-- li/cil/oc/common/Proxy.scala | 6 +- li/cil/oc/common/tileentity/Adapter.scala | 68 ++++++++++++------- li/cil/oc/server/component/Computer.scala | 28 ++++++-- li/cil/oc/server/component/Peripheral.scala | 38 ++++++++++- li/cil/oc/server/network/Component.scala | 6 +- li/cil/oc/server/network/Network.scala | 8 --- 16 files changed, 220 insertions(+), 168 deletions(-) delete mode 100644 assets/opencomputers/lua/rom/lib/redstone.lua create mode 100644 assets/opencomputers/lua/rom/lib/sides.lua diff --git a/assets/opencomputers/lua/kernel.lua b/assets/opencomputers/lua/kernel.lua index 4acb88dff..cffd2a82f 100644 --- a/assets/opencomputers/lua/kernel.lua +++ b/assets/opencomputers/lua/kernel.lua @@ -57,7 +57,10 @@ sandbox = { dofile = nil, -- in lib/base.lua error = error, _G = nil, -- see below - getmetatable = getmetatable, + getmetatable = function(t) + if type(t) == "string" then return nil end + return getmetatable(t) + end, ipairs = ipairs, load = function(ld, source, mode, env) assert((mode or "t") == "t", "unsupported mode") @@ -143,8 +146,8 @@ sandbox = { uchar = string.uchar, trim = function(s) -- from http://lua-users.org/wiki/StringTrim - local from = s:match("^%s*()") - return from > #s and "" or s:match(".*%S", from) + local from = string.match(s, "^%s*()") + return from > #s and "" or string.match(s, ".*%S", from) end }, diff --git a/assets/opencomputers/lua/rom/bin/df.lua b/assets/opencomputers/lua/rom/bin/df.lua index a85b4cfb0..dbc692a91 100644 --- a/assets/opencomputers/lua/rom/bin/df.lua +++ b/assets/opencomputers/lua/rom/bin/df.lua @@ -22,9 +22,9 @@ for path, proxy in pairs(mounts) do local used, total = proxy.spaceUsed(), proxy.spaceTotal() local available, percent if total == "unlimited" then - used = "N/A" + used = used or "N/A" available = "unlimited" - percent = 0 + percent = "0%" else available = total - used percent = used / total diff --git a/assets/opencomputers/lua/rom/lib/event.lua b/assets/opencomputers/lua/rom/lib/event.lua index 93ad1b2a3..b37e91c38 100644 --- a/assets/opencomputers/lua/rom/lib/event.lua +++ b/assets/opencomputers/lua/rom/lib/event.lua @@ -1,4 +1,4 @@ -local listeners, timers = {}, {} +local event, listeners, timers = {}, {}, {} local function matches(signal, name, filter) if name and not (type(signal[1]) == "string" and signal[1]:match(name)) @@ -58,7 +58,14 @@ end ------------------------------------------------------------------------------- -event = {} +function event.cancel(timerId) + checkArg(1, timerId, "number") + if timers[timerId] then + timers[timerId] = nil + return true + end + return false +end --[[ Error handler for ALL event callbacks. If this throws an error or is not, set the computer will immediately shut down. ]] @@ -103,36 +110,6 @@ function event.listen(name, callback) return true end -------------------------------------------------------------------------------- - -function event.cancel(timerId) - checkArg(1, timerId, "number") - if timers[timerId] then - timers[timerId] = nil - return true - end - return false -end - -function event.timer(interval, callback, times) - checkArg(1, interval, "number") - checkArg(2, callback, "function") - checkArg(3, times, "number", "nil") - local id - repeat - id = math.floor(math.random(1, 0x7FFFFFFF)) - until not timers[id] - timers[id] = { - interval = interval, - after = os.uptime() + interval, - callback = callback, - times = times or 1 - } - return id -end - -------------------------------------------------------------------------------- - function event.pull(...) local args = table.pack(...) local seconds, name, filter @@ -182,3 +159,24 @@ function event.shouldInterrupt() keyboard.isAltDown() and keyboard.isKeyDown(keyboard.keys.c) end + +function event.timer(interval, callback, times) + checkArg(1, interval, "number") + checkArg(2, callback, "function") + checkArg(3, times, "number", "nil") + local id + repeat + id = math.floor(math.random(1, 0x7FFFFFFF)) + until not timers[id] + timers[id] = { + interval = interval, + after = os.uptime() + interval, + callback = callback, + times = times or 1 + } + return id +end + +------------------------------------------------------------------------------- + +_G.event = event diff --git a/assets/opencomputers/lua/rom/lib/filesystem.lua b/assets/opencomputers/lua/rom/lib/filesystem.lua index 19ad6024b..485892405 100644 --- a/assets/opencomputers/lua/rom/lib/filesystem.lua +++ b/assets/opencomputers/lua/rom/lib/filesystem.lua @@ -1,3 +1,4 @@ +local filesystem, fileStream = {}, {} local isAutorunEnabled = true local mtab = {children={}} @@ -58,8 +59,6 @@ end ------------------------------------------------------------------------------- -filesystem = {} - function filesystem.autorun(enabled) if enabled ~= nil then checkArg(1, enabled, "boolean") @@ -204,8 +203,6 @@ function filesystem.umount(fsOrPath) return result end -------------------------------------------------------------------------------- - function filesystem.exists(path) local node, rest = findNode(path) if not rest then -- virtual directory @@ -269,8 +266,6 @@ function filesystem.list(path) end end -------------------------------------------------------------------------------- - function filesystem.makeDirectory(path) local node, rest = findNode(path) if node.fs and rest then @@ -336,10 +331,6 @@ function filesystem.copy(fromPath, toPath) return true end -------------------------------------------------------------------------------- - -local fileStream = {} - function fileStream:close() self.fs.close(self.handle) self.handle = nil @@ -366,8 +357,6 @@ function fileStream:write(str) return self.fs.write(self.handle, str) end -------------------------------------------------------------------------------- - function filesystem.open(path, mode) checkArg(1, path, "string") mode = tostring(mode or "r") @@ -407,24 +396,20 @@ end ------------------------------------------------------------------------------- -fs = filesystem - -------------------------------------------------------------------------------- - local function onComponentAdded(_, address, componentType) if componentType == "filesystem" then local proxy = component.proxy(address) if proxy then local name = address:sub(1, 3) - while fs.exists(fs.concat("/mnt", name)) and + while filesystem.exists(filesystem.concat("/mnt", name)) and name:len() < address:len() -- just to be on the safe side do name = address:sub(1, name:len() + 1) end - name = fs.concat("/mnt", name) - fs.mount(proxy, name) + name = filesystem.concat("/mnt", name) + filesystem.mount(proxy, name) if isAutorunEnabled then - shell.execute(fs.concat(name, "autorun"), proxy) + shell.execute(filesystem.concat(name, "autorun"), proxy) end end end @@ -432,10 +417,13 @@ end local function onComponentRemoved(_, address, componentType) if componentType == "filesystem" then - fs.umount(address) + filesystem.umount(address) end end +_G.filesystem = filesystem +_G.fs = filesystem + return function() event.listen("component_added", onComponentAdded) event.listen("component_removed", onComponentRemoved) diff --git a/assets/opencomputers/lua/rom/lib/io.lua b/assets/opencomputers/lua/rom/lib/io.lua index e4ffb6a82..72cfc41c7 100644 --- a/assets/opencomputers/lua/rom/lib/io.lua +++ b/assets/opencomputers/lua/rom/lib/io.lua @@ -1,4 +1,19 @@ -local file = {} +local io, file = {}, {} + +function file.new(mode, stream, nogc) + local result = { + mode = mode or "r", + stream = stream, + buffer = "", + bufferSize = math.max(128, math.min(8 * 1024, os.freeMemory() / 8)), + bufferMode = "full" + } + local metatable = { + __index = file, + __metatable = "file" + } + return setmetatable(result, metatable) +end function file:close() if self.mode ~= "r" and self.mode ~= "rb" then @@ -252,23 +267,6 @@ end ------------------------------------------------------------------------------- -function file.new(mode, stream, nogc) - local result = { - mode = mode or "r", - stream = stream, - buffer = "", - bufferSize = math.max(128, math.min(8 * 1024, os.freeMemory() / 8)), - bufferMode = "full" - } - local metatable = { - __index = file, - __metatable = "file" - } - return setmetatable(result, metatable) -end - -------------------------------------------------------------------------------- - local stdinStream = {handle="stdin"} local stdoutStream = {handle="stdout"} local stdinHistory = {} @@ -302,8 +300,6 @@ stdoutStream.seek = badFileDescriptor ------------------------------------------------------------------------------- -io = {} - io.stdin = file.new("r", stdinStream, true) io.stdout = file.new("w", stdoutStream, true) io.stderr = io.stdout @@ -420,3 +416,7 @@ end function io.write(...) return io.output():write(...) end + +------------------------------------------------------------------------------- + +_G.io = io diff --git a/assets/opencomputers/lua/rom/lib/keyboard.lua b/assets/opencomputers/lua/rom/lib/keyboard.lua index d3694b968..c22e8db5e 100644 --- a/assets/opencomputers/lua/rom/lib/keyboard.lua +++ b/assets/opencomputers/lua/rom/lib/keyboard.lua @@ -1,9 +1,4 @@ -local pressedChars = {} -local pressedCodes = {} - -------------------------------------------------------------------------------- - -keyboard = {} +local keyboard, pressedChars, pressedCodes = {}, {}, {} keyboard.keys = { ["1"] = 0x02, @@ -140,10 +135,20 @@ for k, v in pairs(keyboard.keys) do keyboard.keys[v] = k end +------------------------------------------------------------------------------- + +function keyboard.isAltDown() + return (pressedCodes[keyboard.keys.lmenu] or pressedCodes[keyboard.keys.rmenu]) ~= nil +end + function keyboard.isControl(char) return type(char) == "number" and (char < 0x20 or (char >= 0x7F and char <= 0x9F)) end +function keyboard.isControlDown() + return (pressedCodes[keyboard.keys.lcontrol] or pressedCodes[keyboard.keys.rcontrol]) ~= nil +end + function keyboard.isKeyDown(charOrCode) checkArg(1, charOrCode, "string", "number") if type(charOrCode) == "string" then @@ -153,14 +158,6 @@ function keyboard.isKeyDown(charOrCode) end end -function keyboard.isControlDown() - return (pressedCodes[keyboard.keys.lcontrol] or pressedCodes[keyboard.keys.rcontrol]) ~= nil -end - -function keyboard.isAltDown() - return (pressedCodes[keyboard.keys.lmenu] or pressedCodes[keyboard.keys.rmenu]) ~= nil -end - function keyboard.isShiftDown() return (pressedCodes[keyboard.keys.lshift] or pressedCodes[keyboard.keys.rshift]) ~= nil end @@ -188,6 +185,8 @@ local function onComponentUnavailable(_, componentType) end end +_G.keyboard = keyboard + return function() event.listen("key_down", onKeyDown) event.listen("key_up", onKeyUp) diff --git a/assets/opencomputers/lua/rom/lib/redstone.lua b/assets/opencomputers/lua/rom/lib/redstone.lua deleted file mode 100644 index bbb6d5853..000000000 --- a/assets/opencomputers/lua/rom/lib/redstone.lua +++ /dev/null @@ -1,25 +0,0 @@ -local function stringToSide(side) - if type(side) == "string" and rs.sides[side] then - return rs.sides[side] - end - return side -end - -------------------------------------------------------------------------------- - -redstone = {} -rs = redstone - -rs.sides = { - [0] = "bottom", - [1] = "top", - [2] = "back", - [3] = "front", - [4] = "right", - [5] = "left" -} -for k, v in pairs(rs.sides) do - rs.sides[v] = k -end -rs.sides.up = rs.sides.top -rs.sides.down = rs.sides.bottom diff --git a/assets/opencomputers/lua/rom/lib/shell.lua b/assets/opencomputers/lua/rom/lib/shell.lua index 0133ca955..7ed94557c 100644 --- a/assets/opencomputers/lua/rom/lib/shell.lua +++ b/assets/opencomputers/lua/rom/lib/shell.lua @@ -1,3 +1,4 @@ +local shell = {} local cwd = "/" local path = {"/bin/", "/usr/bin/", "/home/bin/"} local aliases = {dir="ls", move="mv", rename="mv", copy="cp", del="rm", @@ -48,8 +49,6 @@ end ------------------------------------------------------------------------------- -shell = {} - function shell.alias(alias, ...) checkArg(1, alias, "string") local result = aliases[alias] @@ -170,3 +169,7 @@ function shell.which(program) return nil, "program not found" end end + +------------------------------------------------------------------------------- + +_G.shell = shell diff --git a/assets/opencomputers/lua/rom/lib/sides.lua b/assets/opencomputers/lua/rom/lib/sides.lua new file mode 100644 index 000000000..7b884fe20 --- /dev/null +++ b/assets/opencomputers/lua/rom/lib/sides.lua @@ -0,0 +1,17 @@ +local sides = { + [0] = "bottom", + [1] = "top", + [2] = "back", + [3] = "front", + [4] = "right", + [5] = "left" +} +for k, v in pairs(sides) do + sides[v] = k +end +sides.up = sides.top +sides.down = sides.bottom + +------------------------------------------------------------------------------- + +_G.sides = sides diff --git a/assets/opencomputers/lua/rom/lib/term.lua b/assets/opencomputers/lua/rom/lib/term.lua index a83614a6c..61bfeafb5 100644 --- a/assets/opencomputers/lua/rom/lib/term.lua +++ b/assets/opencomputers/lua/rom/lib/term.lua @@ -1,3 +1,4 @@ +local term = {} local gpuAvailable, screenAvailable = false, false local cursorX, cursorY = 1, 1 local cursorBlink = nil @@ -17,12 +18,6 @@ end ------------------------------------------------------------------------------- -term = {} - -function term.isAvailable() - return gpuAvailable and screenAvailable -end - function term.clear() if term.isAvailable() then local w, h = gpu().getResolution() @@ -75,7 +70,9 @@ function term.cursorBlink(enabled) return cursorBlink ~= nil end -------------------------------------------------------------------------------- +function term.isAvailable() + return gpuAvailable and screenAvailable +end function term.read(history) checkArg(1, history, "table", "nil") @@ -379,6 +376,8 @@ local function onComponentUnavailable(_, componentType) end end +_G.term = term + return function() event.listen("component_available", onComponentAvailable) event.listen("component_unavailable", onComponentUnavailable) diff --git a/li/cil/oc/common/Proxy.scala b/li/cil/oc/common/Proxy.scala index 8d27a8e9f..b49213707 100644 --- a/li/cil/oc/common/Proxy.scala +++ b/li/cil/oc/common/Proxy.scala @@ -21,14 +21,14 @@ class Proxy { Blocks.init() Items.init() + api.Driver.add(driver.CommandBlock) api.Driver.add(driver.FileSystem) api.Driver.add(driver.GraphicsCard) api.Driver.add(driver.Memory) api.Driver.add(driver.NetworkCard) - api.Driver.add(driver.RedstoneCard) - api.Driver.add(driver.CommandBlock) - api.Driver.add(driver.PowerSupply) api.Driver.add(driver.Peripheral) + api.Driver.add(driver.PowerSupply) + api.Driver.add(driver.RedstoneCard) MinecraftForge.EVENT_BUS.register(Computer) MinecraftForge.EVENT_BUS.register(network.Network) diff --git a/li/cil/oc/common/tileentity/Adapter.scala b/li/cil/oc/common/tileentity/Adapter.scala index baf941319..06dbef2f5 100644 --- a/li/cil/oc/common/tileentity/Adapter.scala +++ b/li/cil/oc/common/tileentity/Adapter.scala @@ -4,22 +4,19 @@ import dan200.computer.api.{ILuaContext, IComputerAccess, IPeripheral} import li.cil.oc.api import li.cil.oc.api.Network import li.cil.oc.api.network._ -import li.cil.oc.server import li.cil.oc.server.driver -import net.minecraft.nbt.{NBTTagString, NBTTagList, NBTTagCompound} +import net.minecraft.nbt.{NBTTagList, NBTTagCompound} import net.minecraftforge.common.ForgeDirection import scala.Some import scala.collection.convert.WrapAsScala._ import scala.collection.mutable -// TODO persist managed environments of attached blocks somehow... - class Adapter extends Rotatable with Environment with IPeripheral { val node = api.Network.newNode(this, Visibility.Network).create() private val blocks = Array.fill[Option[(ManagedEnvironment, api.driver.Block)]](6)(None) - private val blocksAddresses = Array.fill[String](6)(java.util.UUID.randomUUID.toString) + private val blocksData = Array.fill[Option[BlockData]](6)(None) // ----------------------------------------------------------------------- // @@ -39,27 +36,33 @@ class Adapter extends Rotatable with Environment with IPeripheral { val (x, y, z) = (xCoord + d.offsetX, yCoord + d.offsetY, zCoord + d.offsetZ) driver.Registry.driverFor(worldObj, x, y, z) match { case Some(newDriver) => blocks(d.ordinal()) match { - case Some((environment, driver)) => + case Some((oldEnvironment, driver)) => if (newDriver != driver) { // This is... odd. Maybe moved by some other mod? - node.disconnect(environment.node) - val newEnvironment = newDriver.createEnvironment(worldObj, x, y, z) - newEnvironment.node.asInstanceOf[server.network.Node].address = blocksAddresses(d.ordinal()) - node.connect(newEnvironment.node) - blocks(d.ordinal()) = Some((newEnvironment, newDriver)) + node.disconnect(oldEnvironment.node) + val environment = newDriver.createEnvironment(worldObj, x, y, z) + blocks(d.ordinal()) = Some((environment, newDriver)) + blocksData(d.ordinal()) = Some(new BlockData(environment.getClass.getName, new NBTTagCompound())) + node.connect(environment.node) } // else: the more things change, the more they stay the same. case _ => // A challenger appears. val environment = newDriver.createEnvironment(worldObj, x, y, z) - environment.node.asInstanceOf[server.network.Node].address = blocksAddresses(d.ordinal()) - node.connect(environment.node) blocks(d.ordinal()) = Some((environment, newDriver)) + blocksData(d.ordinal()) match { + case Some(data) if data.name == environment.getClass.getName => + environment.load(data.data) + case _ => + } + blocksData(d.ordinal()) = Some(new BlockData(environment.getClass.getName, new NBTTagCompound())) + node.connect(environment.node) } case _ => blocks(d.ordinal()) match { case Some((environment, driver)) => // We had something there, but it's gone now... - blocks(d.ordinal()) = None node.disconnect(environment.node) + environment.save(blocksData(d.ordinal()).get.data) + blocks(d.ordinal()) = None case _ => // Nothing before, nothing now. } } @@ -108,13 +111,16 @@ class Adapter extends Rotatable with Environment with IPeripheral { super.readFromNBT(nbt) node.load(nbt) - val addressesNbt = nbt.getTagList("oc.adapter.addresses") - (0 until (addressesNbt.tagCount min blocksAddresses.length)). - map(addressesNbt.tagAt). - map(_.asInstanceOf[NBTTagString].data). + val blocksNbt = nbt.getTagList("oc.adapter.blocks") + (0 until (blocksNbt.tagCount min blocksData.length)). + map(blocksNbt.tagAt). + map(_.asInstanceOf[NBTTagCompound]). zipWithIndex. foreach { - case (a, i) => blocksAddresses(i) = a + case (blockNbt, i) => + if (blockNbt.hasKey("name") && blockNbt.hasKey("data")) { + blocksData(i) = Some(new BlockData(blockNbt.getString("name"), blockNbt.getCompoundTag("data"))) + } } } @@ -122,11 +128,22 @@ class Adapter extends Rotatable with Environment with IPeripheral { super.writeToNBT(nbt) node.save(nbt) - val addressesNbt = new NBTTagList() - for (i <- 0 until blocksAddresses.length) { - addressesNbt.appendTag(new NBTTagString(null, blocksAddresses(i))) + val blocksNbt = new NBTTagList() + for (i <- 0 until blocks.length) { + val blockNbt = new NBTTagCompound() + blocksData(i) match { + case Some(data) => + blocks(i) match { + case Some((environment, _)) => environment.save(data.data) + case _ => + } + blockNbt.setString("name", data.name) + blockNbt.setCompoundTag("data", data.data) + case _ => + } + blocksNbt.appendTag(blockNbt) } - nbt.setTag("oc.adapter.addresses", addressesNbt) + nbt.setTag("oc.adapter.blocks", blocksNbt) } // ----------------------------------------------------------------------- // @@ -183,4 +200,9 @@ class Adapter extends Rotatable with Environment with IPeripheral { throw new IllegalArgumentException("bad argument #%d (number in [1, 65535] expected)".format(index + 1)) port } + + // ----------------------------------------------------------------------- // + + private class BlockData(val name: String, val data: NBTTagCompound) + } diff --git a/li/cil/oc/server/component/Computer.scala b/li/cil/oc/server/component/Computer.scala index 7a46d731e..2763aeb1c 100644 --- a/li/cil/oc/server/component/Computer.scala +++ b/li/cil/oc/server/component/Computer.scala @@ -187,12 +187,29 @@ class Computer(val owner: Computer.Environment) extends Persistable with Runnabl for (component <- addedComponents) { if (component.canBeSeenFrom(owner.node)) { components += component.address -> component.name - signal("component_added", component.address, component.name) + // Skip the signal if we're not initialized yet, since we'd generate a + // duplicate in the startup script otherwise. + if (kernelMemory > 0) + signal("component_added", component.address, component.name) } } addedComponents.clear() } + private def verifyComponents() { + val invalid = mutable.Set.empty[String] + for ((address, name) <- components) { + if (owner.node.network.node(address) == null) { + OpenComputers.log.warning("A component of type " + name + " disappeared!") + signal("component_removed", address, name) + invalid += address + } + } + for (address <- invalid) { + components -= address + } + } + def update() { // Add components that were added since the last update to the actual list // of components if we can see them. We use this delayed approach to avoid @@ -205,8 +222,11 @@ class Computer(val owner: Computer.Environment) extends Persistable with Runnabl processAddedComponents() // Are we waiting for the world to settle? - if (lastUpdate == 0 && System.currentTimeMillis() < sleepUntil) - return + if (lastUpdate == 0) + if (System.currentTimeMillis() < sleepUntil) + return + else + verifyComponents() // Update last time run to let our executor thread know it doesn't have to // pause. @@ -1021,7 +1041,7 @@ class Computer(val owner: Computer.Environment) extends Persistable with Runnabl 0 } else { - System.nanoTime() - cpuStart + System.nanoTime() - cpuStart } cpuTime += runtime diff --git a/li/cil/oc/server/component/Peripheral.scala b/li/cil/oc/server/component/Peripheral.scala index 687f57f1f..4a2e6ea4d 100644 --- a/li/cil/oc/server/component/Peripheral.scala +++ b/li/cil/oc/server/component/Peripheral.scala @@ -3,6 +3,8 @@ package li.cil.oc.server.component import dan200.computer.api.{IMount, IWritableMount, IComputerAccess, IPeripheral} import li.cil.oc.api import li.cil.oc.api.network._ +import li.cil.oc.server.network.{Node => MutableNode} +import net.minecraft.nbt.{NBTTagString, NBTTagCompound} import scala.collection.convert.WrapAsScala._ import scala.collection.mutable @@ -13,6 +15,9 @@ class Peripheral(peripheral: IPeripheral) extends ManagedComponent with ICompute private val mounts = mutable.Map.empty[String, ManagedEnvironment] + // Used to restore mounts to their previous addresses after save/load. + private val mountAddresses = mutable.Map.empty[String, String] + // ----------------------------------------------------------------------- // @LuaCallback(value = "getType", asynchronous = true) @@ -53,6 +58,31 @@ class Peripheral(peripheral: IPeripheral) extends ManagedComponent with ICompute // ----------------------------------------------------------------------- // + override def load(nbt: NBTTagCompound) { + super.load(nbt) + + if (nbt.hasKey("oc.peripheral.addresses")) { + val addressesNbt = nbt.getCompoundTag("oc.peripheral.addresses") + for (tag <- addressesNbt.getTags) tag match { + case addressNbt: NBTTagString => + mountAddresses += addressNbt.getName -> addressNbt.data + case _ => + } + } + } + + override def save(nbt: NBTTagCompound) { + super.save(nbt) + + val addressesNbt = new NBTTagCompound() + for ((location, env) <- mounts) { + addressesNbt.setString(location, env.node.address) + } + nbt.setCompoundTag("oc.peripheral.addresses", addressesNbt) + } + + // ----------------------------------------------------------------------- // + def getID = -1 def getAttachmentName = node.address @@ -71,6 +101,10 @@ class Peripheral(peripheral: IPeripheral) extends ManagedComponent with ICompute if (!mounts.contains(desiredLocation)) { val env = api.FileSystem.asManagedEnvironment(fs, desiredLocation) env.node.asInstanceOf[Component].setVisibility(Visibility.Network) + if (mountAddresses.contains(desiredLocation)) { + env.node.asInstanceOf[MutableNode].address = mountAddresses(desiredLocation) + mountAddresses -= desiredLocation + } node.connect(env.node) mounts += desiredLocation -> env desiredLocation @@ -79,7 +113,9 @@ class Peripheral(peripheral: IPeripheral) extends ManagedComponent with ICompute def unmount(location: String) { mounts.remove(location) match { - case Some(env) => env.node.remove() + case Some(env) => + mountAddresses -= location + env.node.remove() case _ => } } diff --git a/li/cil/oc/server/network/Component.scala b/li/cil/oc/server/network/Component.scala index 66ba5bc40..948c61555 100644 --- a/li/cil/oc/server/network/Component.scala +++ b/li/cil/oc/server/network/Component.scala @@ -84,13 +84,13 @@ trait Component extends api.network.Component with Persistable { override def load(nbt: NBTTagCompound) { super.load(nbt) - if (nbt.hasKey("visibility")) - visibility_ = Visibility.values()(nbt.getInteger("visibility")) + if (nbt.hasKey("oc.component.visibility")) + visibility_ = Visibility.values()(nbt.getInteger("oc.component.visibility")) } override def save(nbt: NBTTagCompound) { super.save(nbt) - nbt.setInteger("visibility", visibility_.ordinal()) + nbt.setInteger("oc.component.visibility", visibility_.ordinal()) } } diff --git a/li/cil/oc/server/network/Network.scala b/li/cil/oc/server/network/Network.scala index 38913aba2..fa2d3f477 100644 --- a/li/cil/oc/server/network/Network.scala +++ b/li/cil/oc/server/network/Network.scala @@ -332,10 +332,6 @@ object Network extends api.detail.NetworkAPI { def onChunkUnload(e: ChunkEvent.Unload) = onUnload(e.world, e.getChunk.chunkTileEntityMap.values.asScala.map(_.asInstanceOf[TileEntity])) - @ForgeSubscribe - def onChunkLoad(e: ChunkEvent.Load) = - onLoad(e.world, e.getChunk.chunkTileEntityMap.values.asScala.map(_.asInstanceOf[TileEntity])) - private def onUnload(w: World, tileEntities: Iterable[TileEntity]) = if (!w.isRemote) { // TODO add a more efficient batch remove operation? something along the lines of if #remove > #nodes*factor remove all, re-add remaining? tileEntities. @@ -344,10 +340,6 @@ object Network extends api.detail.NetworkAPI { foreach(t => t.node.remove()) } - private def onLoad(w: World, tileEntities: Iterable[TileEntity]) = if (!w.isRemote) { - tileEntities.foreach(t => joinOrCreateNetwork(w, t.xCoord, t.yCoord, t.zCoord)) - } - // ----------------------------------------------------------------------- // private class Vertex(val data: MutableNode) {