From 27316ff8c221d10b049b5ecd3c7ce18eb8e370ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Sat, 4 Jan 2014 00:20:40 +0100 Subject: [PATCH 01/16] fixed shell.setPath(), closes #53 --- assets/opencomputers/lua/rom/lib/shell.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/opencomputers/lua/rom/lib/shell.lua b/assets/opencomputers/lua/rom/lib/shell.lua index 2a2758492..da0334eed 100644 --- a/assets/opencomputers/lua/rom/lib/shell.lua +++ b/assets/opencomputers/lua/rom/lib/shell.lua @@ -84,7 +84,7 @@ end function shell.setPath(value) checkArg(1, value, "string") path = {} - for p in string:gmatch(value, "[^:]") do + for p in string.gmatch(value, "[^:]+") do p = fs.canonical(text.trim(p)) if unicode.sub(p, 1, 1) ~= "/" then p = "/" .. p From b5154843a99e91e734b2f1751a447d3a2cab7ad1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Sat, 4 Jan 2014 01:12:49 +0100 Subject: [PATCH 02/16] configurable paste shortcut, very rudimentary but better than nothing. closes #54 --- li/cil/oc/Settings.scala | 1 + li/cil/oc/client/gui/Buffer.scala | 19 +++++++++++++------ reference.conf | 6 ++++++ 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/li/cil/oc/Settings.scala b/li/cil/oc/Settings.scala index 1433aa70a..9b54b2478 100644 --- a/li/cil/oc/Settings.scala +++ b/li/cil/oc/Settings.scala @@ -22,6 +22,7 @@ class Settings(config: Config) { val maxScreenTextRenderDistance = config.getDouble("client.maxScreenTextRenderDistance") val textLinearFiltering = config.getBoolean("client.textLinearFiltering") val textAntiAlias = config.getBoolean("client.textAntiAlias") + val pasteShortcut = config.getStringList("client.pasteShortcut").toSet val rTreeDebugRenderer = false // *Not* to be configurable via config file. // ----------------------------------------------------------------------- // diff --git a/li/cil/oc/client/gui/Buffer.scala b/li/cil/oc/client/gui/Buffer.scala index a100f2274..f751d6c14 100644 --- a/li/cil/oc/client/gui/Buffer.scala +++ b/li/cil/oc/client/gui/Buffer.scala @@ -1,5 +1,6 @@ package li.cil.oc.client.gui +import li.cil.oc.Settings import li.cil.oc.client.PacketSender import li.cil.oc.client.renderer.MonospaceFontRenderer import li.cil.oc.client.renderer.gui.BufferRenderer @@ -70,12 +71,8 @@ trait Buffer extends GuiScreen { if (NEI.isInputFocused) return val code = Keyboard.getEventKey - if (code != Keyboard.KEY_ESCAPE && code != Keyboard.KEY_F11) - if (code == Keyboard.KEY_INSERT && GuiScreen.isShiftKeyDown) { - if (Keyboard.getEventKeyState) - PacketSender.sendClipboard(buffer.owner, GuiScreen.getClipboardString) - } - else if (Keyboard.getEventKeyState) { + if (code != Keyboard.KEY_ESCAPE && code != Keyboard.KEY_F11) { + if (Keyboard.getEventKeyState) { val char = Keyboard.getEventCharacter if (!pressedKeys.contains(code) || !ignoreRepeat(char, code)) { PacketSender.sendKeyDown(buffer.owner, char, code) @@ -86,6 +83,11 @@ trait Buffer extends GuiScreen { case Some(char) => PacketSender.sendKeyUp(buffer.owner, char, code) case _ => // Wasn't pressed while viewing the screen. } + + if (isPasteShortcutPressed && Keyboard.getEventKeyState) { + PacketSender.sendClipboard(buffer.owner, GuiScreen.getClipboardString) + } + } } override protected def mouseClicked(x: Int, y: Int, button: Int) { @@ -107,4 +109,9 @@ trait Buffer extends GuiScreen { code == Keyboard.KEY_LMETA || code == Keyboard.KEY_RMETA } + + private def isPasteShortcutPressed = { + val want = Settings.get.pasteShortcut.map(name => Keyboard.getKeyIndex(name.toUpperCase)).filter(_ != Keyboard.KEY_NONE) + pressedKeys.keySet.equals(want) + } } diff --git a/reference.conf b/reference.conf index 0c728e226..a3ec2c7da 100644 --- a/reference.conf +++ b/reference.conf @@ -47,6 +47,12 @@ opencomputers { # If you prefer the text on the screens to be aliased (you know, *not* # anti-aliased / smoothed) turn this option off. textAntiAlias: true + + # The keyboard shortcut that is used to send the current text in the + # clipboard to the currently opened screen (if said screen has a keyboard + # attached to it). For valid key names, please see the following list: + # https://github.com/LWJGL/lwjgl/blob/master/src/java/org/lwjgl/input/Keyboard.java#L73 + pasteShortcut: [LSHIFT, INSERT] } # Computer related settings, concerns server performance and security. From 88cd9bdad3f491f1f513188cf7f38d544cf5017b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Sat, 4 Jan 2014 01:26:07 +0100 Subject: [PATCH 03/16] adjusted gregtech recipes as discussed on forum --- assets/opencomputers/recipes/gregtech.recipes | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/assets/opencomputers/recipes/gregtech.recipes b/assets/opencomputers/recipes/gregtech.recipes index 4659ffec2..5f8c51d70 100644 --- a/assets/opencomputers/recipes/gregtech.recipes +++ b/assets/opencomputers/recipes/gregtech.recipes @@ -222,7 +222,7 @@ diskDrive { powerConverter { input: [["", "oc:circuitAdvanced", ""] - [plateAluminium, craftingGenerator, plateAluminium] + [plateAluminium, {item=Electric, subID=4}, plateAluminium] ["oc:craftingCircuitBoardPrinted", craftingToolWrench, "oc:craftingCircuitBoardPrinted"]] } powerDistributor { @@ -251,12 +251,12 @@ screen1 { [plateAluminium, plateAluminium, craftingToolScrewdriver]] } screen2 { - input: [[plateStainlessSteel, {item=dyePowder, subID=1}, craftingToolWrench] - ["oc:circuitAdvanced", {item=dyePowder, subID=2}, "oc:craftingScreenBasic"] - [plateStainlessSteel, {item=dyePowder, subID=4}, craftingToolScrewdriver]] + input: [[plateStainlessSteel, screwStainlessSteel, craftingToolWrench] + ["oc:circuitAdvanced", "oc:craftingScreenBasic", craftingMonitorTier02] + [plateStainlessSteel, screwStainlessSteel, craftingToolScrewdriver]] } screen3 { input: [[plateTitanium, "oc:craftingCircuitBoardPrinted", craftingToolWrench] - ["oc:circuitElite", "oc:circuitElite", "oc:craftingScreenAdvanced"] + ["oc:circuitElite", "oc:craftingScreenAdvanced", "oc:circuitElite"] [plateTitanium, "oc:craftingCircuitBoardPrinted", craftingToolScrewdriver]] } \ No newline at end of file From 48217254b8568c5cc97204ba2da47452b2229202 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Sat, 4 Jan 2014 03:00:54 +0100 Subject: [PATCH 04/16] fixed screen clear on multi-block rearrange (client sync); clearing screen when computer stops (where possible, i.e. where a computer.stopped message is sent by the computer) --- li/cil/oc/common/tileentity/Screen.scala | 6 +++++- li/cil/oc/server/component/GraphicsCard.scala | 17 +++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/li/cil/oc/common/tileentity/Screen.scala b/li/cil/oc/common/tileentity/Screen.scala index 2eae2aa94..e60e7b073 100644 --- a/li/cil/oc/common/tileentity/Screen.scala +++ b/li/cil/oc/common/tileentity/Screen.scala @@ -218,7 +218,11 @@ class Screen(var tier: Int) extends Buffer with SidedEnvironment with Rotatable } val buffer = screen.buffer val (w, h) = buffer.resolution - buffer.buffer.fill(0, 0, w, h, ' ') + buffer.foreground = 0xFFFFFF + buffer.background = 0x000000 + if (buffer.buffer.fill(0, 0, w, h, ' ')) { + onScreenFill(0, 0, w, h, ' ') + } } ) } diff --git a/li/cil/oc/server/component/GraphicsCard.scala b/li/cil/oc/server/component/GraphicsCard.scala index 2b9a340c0..0a82bf016 100644 --- a/li/cil/oc/server/component/GraphicsCard.scala +++ b/li/cil/oc/server/component/GraphicsCard.scala @@ -202,6 +202,23 @@ abstract class GraphicsCard extends ManagedComponent { // ----------------------------------------------------------------------- // + override def onMessage(message: Message) { + super.onMessage(message) + if (message.name == "computer.stopped" && node.isNeighborOf(message.source)) { + screenInstance match { + case Some(buffer) => buffer.synchronized { + val (w, h) = buffer.resolution + buffer.foreground = 0xFFFFFF + buffer.background = 0x000000 + if (buffer.buffer.fill(0, 0, w, h, ' ')) { + buffer.owner.onScreenFill(0, 0, w, h, ' ') + } + } + case _ => + } + } + } + override def onDisconnect(node: Node) { super.onDisconnect(node) if (node == this.node || screenAddress.exists(_ == node.address)) { From dbc3af26d2ad68673eda7a59bf13005b03e674f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Sat, 4 Jan 2014 03:15:31 +0100 Subject: [PATCH 05/16] crashing on start to show a warning when doDaylightCycle is false (since sleeps will never elapse in that mode computers won't start up) --- li/cil/oc/server/component/Computer.scala | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/li/cil/oc/server/component/Computer.scala b/li/cil/oc/server/component/Computer.scala index 833ad330e..c4fcedb65 100644 --- a/li/cil/oc/server/component/Computer.scala +++ b/li/cil/oc/server/component/Computer.scala @@ -108,7 +108,12 @@ class Computer(val owner: tileentity.Computer) extends ManagedComponent with Con def start() = state.synchronized(state.top match { case Computer.State.Stopped => - if (owner.installedMemory > 0) { + val rules = owner.world.getWorldInfo.getGameRulesInstance + if (rules.hasRule("doDaylightCycle") && !rules.getGameRuleBooleanValue("doDaylightCycle")) { + crash("computers don't work while time is frozen (gamerule doDaylightCycle is false)") + false + } + else if (owner.installedMemory > 0) { if (Settings.get.ignorePower || node.globalBuffer > cost) { init() && { switchTo(Computer.State.Starting) From 74a30f92c38719d4227913dd61b54393961693c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Sat, 4 Jan 2014 03:21:02 +0100 Subject: [PATCH 06/16] added getter for maximum packet size to network card --- li/cil/oc/server/component/NetworkCard.scala | 3 +++ 1 file changed, 3 insertions(+) diff --git a/li/cil/oc/server/component/NetworkCard.scala b/li/cil/oc/server/component/NetworkCard.scala index 3550065ac..f911b4694 100644 --- a/li/cil/oc/server/component/NetworkCard.scala +++ b/li/cil/oc/server/component/NetworkCard.scala @@ -60,6 +60,9 @@ class NetworkCard extends ManagedComponent { result(true) } + @LuaCallback(value = "maxPacketSize", direct = true) + def maxPacketSize(context: Context, args: Arguments): Array[AnyRef] = result(Settings.get.maxNetworkPacketSize) + // ----------------------------------------------------------------------- // override def onDisconnect(node: Node) { From 852a4757146a6730094b2d394af1a838e2ff1625 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Sat, 4 Jan 2014 03:46:06 +0100 Subject: [PATCH 07/16] fixed config comment --- reference.conf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/reference.conf b/reference.conf index a3ec2c7da..01ebeb380 100644 --- a/reference.conf +++ b/reference.conf @@ -496,7 +496,7 @@ opencomputers { # strength one, which means the signal reaches one block. This is # scaled up linearly, so for example to send a signal 400 blocks a # signal strength of 400 is required, costing a total of - # 400 * `wirelessCostPerRange`. In other words, the higher this value, + # 400 * `wirelessStrength`. In other words, the higher this value, # the higher the cost of wireless messages. # See also: `maxWirelessRange`. wirelessStrength: 0.05 @@ -629,7 +629,7 @@ opencomputers { # This is used to limit the search range in which to check for modems, # which may or may not lead to performance issues for ridiculous ranges - # like, you know, more than the loaded area. - # See also: `wirelessCostPerRange`. + # See also: `wirelessStrength`. maxWirelessRange: 400 # The user name to specify when executing a command via a command block. From f217556d906831edb194896e00099fbf3c635592 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Sat, 4 Jan 2014 04:00:08 +0100 Subject: [PATCH 08/16] fixed ghost characters in edit when inserting a newline (pressing enter) when the cursor blink was currently visible --- assets/opencomputers/lua/rom/bin/edit.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/assets/opencomputers/lua/rom/bin/edit.lua b/assets/opencomputers/lua/rom/bin/edit.lua index da25e663a..36326fe54 100644 --- a/assets/opencomputers/lua/rom/bin/edit.lua +++ b/assets/opencomputers/lua/rom/bin/edit.lua @@ -209,6 +209,7 @@ local function insert(value) end local function enter() + term.setCursorBlink(false) local cx, cy = term.getCursor() local cbx, cby = getCursor() local w, h = getSize() From 21d4510fb8585aa1fbb3a86c9d01a8fcb34e9f97 Mon Sep 17 00:00:00 2001 From: crafteverywhere <1196377271@qq.com> Date: Sat, 4 Jan 2014 22:53:37 +0800 Subject: [PATCH 09/16] Update zh_CN.lang --- assets/opencomputers/lang/zh_CN.lang | 1 + 1 file changed, 1 insertion(+) diff --git a/assets/opencomputers/lang/zh_CN.lang b/assets/opencomputers/lang/zh_CN.lang index 4668a57b2..7ee46d55d 100644 --- a/assets/opencomputers/lang/zh_CN.lang +++ b/assets/opencomputers/lang/zh_CN.lang @@ -69,6 +69,7 @@ oc:gui.Robot.TurnOff=关闭 oc:gui.Robot.TurnOn=开启 # Containers +oc:container.Adapter=适配器 oc:container.Case=计算机 oc:container.DiskDrive=磁盘驱动 From e67764eca32707e60fcc29878d13e1eae33be231 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Sat, 4 Jan 2014 21:02:59 +0100 Subject: [PATCH 10/16] fixed mouse clicks being off on scaled down screen gui (e.g. tier 3 gpu+screen on low game resolution) --- li/cil/oc/client/gui/Screen.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/li/cil/oc/client/gui/Screen.scala b/li/cil/oc/client/gui/Screen.scala index c33fa4a7b..0cec8d73e 100644 --- a/li/cil/oc/client/gui/Screen.scala +++ b/li/cil/oc/client/gui/Screen.scala @@ -59,8 +59,8 @@ class Screen(val screen: tileentity.Screen) extends Buffer { } private def clickOrDrag(mouseX: Int, mouseY: Int) { - val bx = (mouseX - x - bufferMargin) / MonospaceFontRenderer.fontWidth + 1 - val by = (mouseY - y - bufferMargin) / MonospaceFontRenderer.fontHeight + 1 + val bx = ((mouseX - x - bufferMargin) / scale / MonospaceFontRenderer.fontWidth).toInt + 1 + val by = ((mouseY - y - bufferMargin) / scale / MonospaceFontRenderer.fontHeight).toInt + 1 val (bw, bh) = screen.buffer.resolution if (bx > 0 && by > 0 && bx <= bw && by <= bh) { if (bx != mx || by != my) { From 1161d6b80aa0cabdb92158e4029b6f1cb854cb2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Sun, 5 Jan 2014 13:08:05 +0100 Subject: [PATCH 11/16] marked passive tile entities and manually triggering an update for their blocks on chunk/world load to connect them to the component update, since this apparently could fail when scheduling the update (see issue #46) --- li/cil/oc/common/Proxy.scala | 2 ++ li/cil/oc/common/tileentity/Cable.scala | 4 +-- li/cil/oc/common/tileentity/Capacitor.scala | 4 +-- li/cil/oc/common/tileentity/DiskDrive.scala | 4 +-- li/cil/oc/common/tileentity/Keyboard.scala | 4 +-- li/cil/oc/common/tileentity/PassiveNode.scala | 5 ++++ li/cil/oc/common/tileentity/Router.scala | 4 +-- li/cil/oc/server/network/Network.scala | 26 +++++++++++++++++++ 8 files changed, 43 insertions(+), 10 deletions(-) create mode 100644 li/cil/oc/common/tileentity/PassiveNode.scala diff --git a/li/cil/oc/common/Proxy.scala b/li/cil/oc/common/Proxy.scala index 01a18804f..f6a57a9e6 100644 --- a/li/cil/oc/common/Proxy.scala +++ b/li/cil/oc/common/Proxy.scala @@ -7,6 +7,7 @@ import li.cil.oc.server.component.Keyboard import li.cil.oc.server.driver import li.cil.oc.server.fs import li.cil.oc.server.network +import li.cil.oc.server.network.Network import li.cil.oc.util.WirelessNetwork import net.minecraftforge.common.MinecraftForge @@ -49,5 +50,6 @@ class Proxy { GameRegistry.registerPlayerTracker(Keyboard) MinecraftForge.EVENT_BUS.register(WirelessNetwork) + MinecraftForge.EVENT_BUS.register(Network) } } \ No newline at end of file diff --git a/li/cil/oc/common/tileentity/Cable.scala b/li/cil/oc/common/tileentity/Cable.scala index e71a32f56..12133da77 100644 --- a/li/cil/oc/common/tileentity/Cable.scala +++ b/li/cil/oc/common/tileentity/Cable.scala @@ -5,7 +5,7 @@ import li.cil.oc.{Blocks, api, common} import net.minecraft.entity.player.EntityPlayer import net.minecraft.nbt.NBTTagCompound -class Cable extends Environment with Analyzable { +class Cable extends Environment with Analyzable with PassiveNode { val node = api.Network.newNode(this, Visibility.None).create() def onAnalyze(stats: NBTTagCompound, player: EntityPlayer, side: Int, hitX: Float, hitY: Float, hitZ: Float) = null @@ -16,7 +16,7 @@ class Cable extends Environment with Analyzable { override def validate() { super.validate() - world.scheduleBlockUpdateFromLoad(x, y, z, Blocks.cable.parent.blockID, Int.MinValue, 0) + world.scheduleBlockUpdateFromLoad(x, y, z, Blocks.cable.parent.blockID, 0, 0) } override def getRenderBoundingBox = common.block.Cable.bounds(world, x, y, z).offset(x, y, z) diff --git a/li/cil/oc/common/tileentity/Capacitor.scala b/li/cil/oc/common/tileentity/Capacitor.scala index 33901d08b..949e99160 100644 --- a/li/cil/oc/common/tileentity/Capacitor.scala +++ b/li/cil/oc/common/tileentity/Capacitor.scala @@ -5,7 +5,7 @@ import li.cil.oc.{Blocks, Settings, api} import net.minecraftforge.common.ForgeDirection import scala.collection.convert.WrapAsScala._ -class Capacitor extends Environment { +class Capacitor extends Environment with PassiveNode { // Start with maximum theoretical capacity, gets reduced after validation. // This is done so that we don't lose energy while loading. val node = api.Network.newNode(this, Visibility.Network). @@ -16,7 +16,7 @@ class Capacitor extends Environment { override def validate() { super.validate() - world.scheduleBlockUpdateFromLoad(x, y, z, Blocks.capacitor.parent.blockID, Int.MinValue, 0) + world.scheduleBlockUpdateFromLoad(x, y, z, Blocks.capacitor.parent.blockID, 0, 0) } override def invalidate() { diff --git a/li/cil/oc/common/tileentity/DiskDrive.scala b/li/cil/oc/common/tileentity/DiskDrive.scala index 47348f33f..fc502cd96 100644 --- a/li/cil/oc/common/tileentity/DiskDrive.scala +++ b/li/cil/oc/common/tileentity/DiskDrive.scala @@ -8,7 +8,7 @@ import net.minecraft.entity.player.EntityPlayer import net.minecraft.item.ItemStack import net.minecraft.nbt.NBTTagCompound -class DiskDrive extends Environment with ComponentInventory with Rotatable with Analyzable { +class DiskDrive extends Environment with ComponentInventory with Rotatable with Analyzable with PassiveNode { val node = api.Network.newNode(this, Visibility.None).create() // ----------------------------------------------------------------------- // @@ -23,7 +23,7 @@ class DiskDrive extends Environment with ComponentInventory with Rotatable with override def validate() = { super.validate() - world.scheduleBlockUpdateFromLoad(x, y, z, Blocks.diskDrive.parent.blockID, Int.MinValue, 0) + world.scheduleBlockUpdateFromLoad(x, y, z, Blocks.diskDrive.parent.blockID, 0, 0) } // ----------------------------------------------------------------------- // diff --git a/li/cil/oc/common/tileentity/Keyboard.scala b/li/cil/oc/common/tileentity/Keyboard.scala index a90a12868..3e9af91d8 100644 --- a/li/cil/oc/common/tileentity/Keyboard.scala +++ b/li/cil/oc/common/tileentity/Keyboard.scala @@ -9,7 +9,7 @@ import net.minecraft.entity.player.EntityPlayer import net.minecraft.nbt.NBTTagCompound import net.minecraftforge.common.ForgeDirection -class Keyboard(isRemote: Boolean) extends Environment with SidedEnvironment with Analyzable with Rotatable { +class Keyboard(isRemote: Boolean) extends Environment with SidedEnvironment with Analyzable with Rotatable with PassiveNode { def this() = this(false) val keyboard = if (isRemote) null else new component.Keyboard(this) @@ -37,7 +37,7 @@ class Keyboard(isRemote: Boolean) extends Environment with SidedEnvironment with override def validate() { super.validate() - world.scheduleBlockUpdateFromLoad(x, y, z, Blocks.keyboard.parent.blockID, Int.MinValue, 0) + world.scheduleBlockUpdateFromLoad(x, y, z, Blocks.keyboard.parent.blockID, 0, 0) } override def readFromNBT(nbt: NBTTagCompound) { diff --git a/li/cil/oc/common/tileentity/PassiveNode.scala b/li/cil/oc/common/tileentity/PassiveNode.scala new file mode 100644 index 000000000..d52739acd --- /dev/null +++ b/li/cil/oc/common/tileentity/PassiveNode.scala @@ -0,0 +1,5 @@ +package li.cil.oc.common.tileentity + +// Marker for tile entities that don't tick and therefore have to be added to +// the component network manually (see Network singleton). +trait PassiveNode \ No newline at end of file diff --git a/li/cil/oc/common/tileentity/Router.scala b/li/cil/oc/common/tileentity/Router.scala index aa308f407..2ba7602d5 100644 --- a/li/cil/oc/common/tileentity/Router.scala +++ b/li/cil/oc/common/tileentity/Router.scala @@ -11,7 +11,7 @@ import net.minecraftforge.common.ForgeDirection import scala.collection.mutable @Optional.Interface(iface = "dan200.computer.api.IPeripheral", modid = "ComputerCraft") -class Router extends net.minecraft.tileentity.TileEntity with api.network.SidedEnvironment with IPeripheral { +class Router extends net.minecraft.tileentity.TileEntity with api.network.SidedEnvironment with IPeripheral with PassiveNode { private val plugs = ForgeDirection.VALID_DIRECTIONS.map(side => new Plug(side)) // ----------------------------------------------------------------------- // @@ -27,7 +27,7 @@ class Router extends net.minecraft.tileentity.TileEntity with api.network.SidedE override def validate() { super.validate() - worldObj.scheduleBlockUpdateFromLoad(xCoord, yCoord, zCoord, Blocks.router.parent.blockID, Int.MinValue, 0) + worldObj.scheduleBlockUpdateFromLoad(xCoord, yCoord, zCoord, Blocks.router.parent.blockID, 0, 0) } override def invalidate() { diff --git a/li/cil/oc/server/network/Network.scala b/li/cil/oc/server/network/Network.scala index 3b9dc8956..9ef0dafd5 100644 --- a/li/cil/oc/server/network/Network.scala +++ b/li/cil/oc/server/network/Network.scala @@ -3,11 +3,15 @@ package li.cil.oc.server.network import cpw.mods.fml.common.FMLCommonHandler import cpw.mods.fml.relauncher.Side import li.cil.oc.api.network.{Node => ImmutableNode, SidedEnvironment, Environment, Visibility} +import li.cil.oc.common.tileentity.PassiveNode import li.cil.oc.server.network.{Node => MutableNode} import li.cil.oc.{Settings, api} import net.minecraft.tileentity.TileEntity import net.minecraftforge.common.ForgeDirection +import net.minecraftforge.event.ForgeSubscribe +import net.minecraftforge.event.world.{ChunkEvent, WorldEvent} import scala.collection.JavaConverters._ +import scala.collection.convert.WrapAsScala._ import scala.collection.mutable import scala.collection.mutable.ArrayBuffer @@ -345,6 +349,28 @@ private class Network private(private val data: mutable.Map[String, Network.Vert } object Network extends api.detail.NetworkAPI { + @ForgeSubscribe + def onWorldLoad(e: WorldEvent.Load) { + val world = e.world + if (!world.isRemote) { + for (t <- world.loadedTileEntityList) t match { + case p: TileEntity with PassiveNode => p.getBlockType.updateTick(world, p.xCoord, p.yCoord, p.zCoord, world.rand) + case _ => + } + } + } + + @ForgeSubscribe + def onChunkLoad(e: ChunkEvent.Load) { + val world = e.world + if (!world.isRemote) { + for (t <- e.getChunk.chunkTileEntityMap.values) t match { + case p: TileEntity with PassiveNode => p.getBlockType.updateTick(world, p.xCoord, p.yCoord, p.zCoord, world.rand) + case _ => + } + } + } + override def joinOrCreateNetwork(tileEntity: TileEntity): Unit = if (!tileEntity.getWorldObj.isRemote) { for (side <- ForgeDirection.VALID_DIRECTIONS) { From d026b61295cd20fde25934d2cf5c3fe718f4851d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Sun, 5 Jan 2014 13:27:33 +0100 Subject: [PATCH 12/16] added setting to allow enabling bytecode loading. use this at your own risk, and only if you're aware just how exploitable this can be... closes #58 for now --- assets/opencomputers/lua/kernel.lua | 6 ++++-- li/cil/oc/Settings.scala | 1 + li/cil/oc/server/component/Computer.scala | 7 +++++++ reference.conf | 8 ++++++++ 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/assets/opencomputers/lua/kernel.lua b/assets/opencomputers/lua/kernel.lua index ff0af0d2b..d59e97f93 100644 --- a/assets/opencomputers/lua/kernel.lua +++ b/assets/opencomputers/lua/kernel.lua @@ -66,8 +66,10 @@ sandbox = { end, ipairs = ipairs, load = function(ld, source, mode, env) - assert((mode or "t") == "t", "unsupported mode") - return load(ld, source, "t", env or sandbox) + if not allowBytecode() then + mode = "t" + end + return load(ld, source, mode, env or sandbox) end, loadfile = nil, -- in lib/base.lua next = next, diff --git a/li/cil/oc/Settings.scala b/li/cil/oc/Settings.scala index 9b54b2478..51de063c4 100644 --- a/li/cil/oc/Settings.scala +++ b/li/cil/oc/Settings.scala @@ -42,6 +42,7 @@ class Settings(config: Config) { val canComputersBeOwned = config.getBoolean("computer.canComputersBeOwned") val maxUsers = config.getInt("computer.maxUsers") max 0 val maxUsernameLength = config.getInt("computer.maxUsernameLength") max 0 + val allowBytecode = config.getBoolean("computer.allowBytecode") // ----------------------------------------------------------------------- // // robot diff --git a/li/cil/oc/server/component/Computer.scala b/li/cil/oc/server/component/Computer.scala index c4fcedb65..e7271a642 100644 --- a/li/cil/oc/server/component/Computer.scala +++ b/li/cil/oc/server/component/Computer.scala @@ -965,6 +965,13 @@ class Computer(val owner: tileentity.Computer) extends ManagedComponent with Con }) lua.setGlobal("print") + // Whether bytecode may be loaded directly. + lua.pushScalaFunction(lua => { + lua.pushBoolean(Settings.get.allowBytecode) + 1 + }) + lua.setGlobal("allowBytecode") + // How long programs may run without yielding before we stop them. lua.pushNumber(Settings.get.timeout) lua.setGlobal("timeout") diff --git a/reference.conf b/reference.conf index 01ebeb380..84f59da85 100644 --- a/reference.conf +++ b/reference.conf @@ -72,6 +72,14 @@ opencomputers { # already running - they'll have to be rebooted for this to take effect. timeout: 1.0 + # Whether to allow loading precompiled bytecode via Lua's `load` function, + # or related functions (`loadfile`, `dofile`). Enable this only if you + # absolutely trust all users on your server and all Lua code you run. This + # can be a MASSIVE SECURITY RISK, since precompiled code can easily be + # used for exploits, running arbitrary code on the real server! I cannot + # stress this enough: only enable this is you know what you're doing. + allowBytecode: false + # The time in seconds to wait after a computer has been restored before it # continues to run. This is meant to allow the world around the computer # to settle, avoiding issues such as components in neighboring chunks From bd57550bd22d6e56e9aca5503b393c256688fc40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Sun, 5 Jan 2014 13:54:10 +0100 Subject: [PATCH 13/16] fixed touch coordinates on certain multiblock screen formats in combination with certain resolutions, closes #57 --- li/cil/oc/common/tileentity/Screen.scala | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/li/cil/oc/common/tileentity/Screen.scala b/li/cil/oc/common/tileentity/Screen.scala index e60e7b073..82561eee8 100644 --- a/li/cil/oc/common/tileentity/Screen.scala +++ b/li/cil/oc/common/tileentity/Screen.scala @@ -90,11 +90,12 @@ class Screen(var tier: Int) extends Buffer with SidedEnvironment with Rotatable if (ax <= border || ay <= border || ax >= width - border || ay >= height - border) { return false } - val (rx, ry) = ((ax - border) / (width - border * 2), (ay - border) / (height - border * 2)) + val (iw, ih) = (width - border * 2, height - border * 2) + val (rx, ry) = ((ax - border) / iw, (ay - border) / ih) // Make it a relative position in the displayed buffer. val (bw, bh) = origin.buffer.resolution - val (bpw, bph) = (bw * MonospaceFontRenderer.fontWidth, bh * MonospaceFontRenderer.fontHeight) + val (bpw, bph) = (bw * MonospaceFontRenderer.fontWidth / iw.toDouble, bh * MonospaceFontRenderer.fontHeight / ih.toDouble) val (brx, bry) = if (bpw > bph) { val rh = bph.toDouble / bpw.toDouble val bry = (ry - (1 - rh) * 0.5) / rh From 4b4a59258f05052ff41583efcf3603a5988b8dcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Sun, 5 Jan 2014 14:49:34 +0100 Subject: [PATCH 14/16] added a null check that may avoid #37, although I can't reproduce it and can't see how it could come to that. possibly mcpc+ related. --- li/cil/oc/server/component/GraphicsCard.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/li/cil/oc/server/component/GraphicsCard.scala b/li/cil/oc/server/component/GraphicsCard.scala index 0a82bf016..48d2390e0 100644 --- a/li/cil/oc/server/component/GraphicsCard.scala +++ b/li/cil/oc/server/component/GraphicsCard.scala @@ -33,7 +33,7 @@ abstract class GraphicsCard extends ManagedComponent { override def update() { super.update() - if (screenInstance.isEmpty && screenAddress.isDefined) { + if (node.network != null && screenInstance.isEmpty && screenAddress.isDefined) { Option(node.network.node(screenAddress.get)) match { case Some(node: Node) if node.host.isInstanceOf[Buffer] => screenInstance = Some(node.host.asInstanceOf[Buffer]) From 0f7718dcb074a9e8e8d92757e9b67950c8cc67c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Sun, 5 Jan 2014 18:18:14 +0100 Subject: [PATCH 15/16] fixed side of redstone_changed event not being translated to computer case's local side, closes #60 --- li/cil/oc/common/tileentity/Computer.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/li/cil/oc/common/tileentity/Computer.scala b/li/cil/oc/common/tileentity/Computer.scala index bba3f3f8f..927213997 100644 --- a/li/cil/oc/common/tileentity/Computer.scala +++ b/li/cil/oc/common/tileentity/Computer.scala @@ -155,7 +155,7 @@ abstract class Computer(isRemote: Boolean) extends Environment with ComponentInv override protected def onRedstoneInputChanged(side: ForgeDirection) { super.onRedstoneInputChanged(side) - computer.signal("redstone_changed", computer.address, Int.box(side.ordinal())) + computer.signal("redstone_changed", computer.address, Int.box(toLocal(side).ordinal())) } // ----------------------------------------------------------------------- // From c1e283ca8702955d144e0b50d276195070ab8aa7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Sun, 5 Jan 2014 19:12:28 +0100 Subject: [PATCH 16/16] fixed bug in term.write() that caused issues with writing long strings. could have sworn I tested this and it worked once... was probably before I added word wrapping. anyway, closes #61 --- assets/opencomputers/lua/rom/lib/term.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/opencomputers/lua/rom/lib/term.lua b/assets/opencomputers/lua/rom/lib/term.lua index f16e3c55c..acee5225d 100644 --- a/assets/opencomputers/lua/rom/lib/term.lua +++ b/assets/opencomputers/lua/rom/lib/term.lua @@ -345,7 +345,7 @@ function term.write(value, wrap) while wrap and unicode.len(line) > w - (cursorX - 1) do local partial = unicode.sub(line, 1, w - (cursorX - 1)) local wordWrapped = partial:match("(.*[^a-zA-Z0-9._])") - if wordWrapped or unicode.len(partial) > w then + if wordWrapped or unicode.len(line) > w then partial = wordWrapped or partial line = unicode.sub(line, unicode.len(partial) + 1) component.gpu.set(cursorX, cursorY, partial)