From 657bc7dcdf9a81256a5d84b034537ebfe1e2ea96 Mon Sep 17 00:00:00 2001 From: Kubuxu Date: Sat, 30 May 2015 13:32:50 +0200 Subject: [PATCH] Added DataCard. --- .../assets/opencomputers/lang/en_US.lang | 1 + .../lua/component/data/.autorun.lua | 31 +++++++ .../lua/component/data/bin/deflate.lua | 25 ++++++ .../lua/component/data/bin/inflate.lua | 25 ++++++ .../lua/component/data/bin/sha256.lua | 27 ++++++ .../lua/component/data/lib/data.lua | 45 ++++++++++ src/main/scala/li/cil/oc/Constants.scala | 1 + .../scala/li/cil/oc/common/init/Items.scala | 6 +- .../li/cil/oc/common/item/DataCard.scala | 3 + .../opencomputers/DriverDataCard.scala | 19 ++++ .../opencomputers/ModOpenComputers.scala | 1 + .../li/cil/oc/server/component/DataCard.scala | 87 +++++++++++++++++++ 12 files changed, 269 insertions(+), 2 deletions(-) create mode 100644 src/main/resources/assets/opencomputers/lua/component/data/.autorun.lua create mode 100644 src/main/resources/assets/opencomputers/lua/component/data/bin/deflate.lua create mode 100644 src/main/resources/assets/opencomputers/lua/component/data/bin/inflate.lua create mode 100644 src/main/resources/assets/opencomputers/lua/component/data/bin/sha256.lua create mode 100644 src/main/resources/assets/opencomputers/lua/component/data/lib/data.lua create mode 100644 src/main/scala/li/cil/oc/common/item/DataCard.scala create mode 100644 src/main/scala/li/cil/oc/integration/opencomputers/DriverDataCard.scala create mode 100644 src/main/scala/li/cil/oc/server/component/DataCard.scala diff --git a/src/main/resources/assets/opencomputers/lang/en_US.lang b/src/main/resources/assets/opencomputers/lang/en_US.lang index c31a753a4..1628b5052 100644 --- a/src/main/resources/assets/opencomputers/lang/en_US.lang +++ b/src/main/resources/assets/opencomputers/lang/en_US.lang @@ -59,6 +59,7 @@ item.oc.CPU0.name=Central Processing Unit (CPU) (Tier 1) item.oc.CPU1.name=Central Processing Unit (CPU) (Tier 2) item.oc.CPU2.name=Central Processing Unit (CPU) (Tier 3) item.oc.CuttingWire.name=Cutting Wire +item.oc.DataCard.name=Data Card item.oc.DebugCard.name=Debug Card item.oc.Debugger.name=Network Debugger item.oc.Disk.name=Disk Platter diff --git a/src/main/resources/assets/opencomputers/lua/component/data/.autorun.lua b/src/main/resources/assets/opencomputers/lua/component/data/.autorun.lua new file mode 100644 index 000000000..9aff88263 --- /dev/null +++ b/src/main/resources/assets/opencomputers/lua/component/data/.autorun.lua @@ -0,0 +1,31 @@ +local event = require("event") +local fs = require("filesystem") +local process = require("process") + +local proxy = ... + +-- Install symlinks if they don't already exist. +local links = {} +local fsroot = fs.path(process.running()) +local function inject(path) + for file in fs.list(fs.concat(fsroot, path)) do + local source = fs.concat(fsroot, path, file) + local target = fs.concat(path, file) + if fs.link(source, target) then + table.insert(links, target) + end + end +end +inject("lib") +inject("bin") +inject("usr/man") + +-- Delete symlinks on removal. +event.listen("component_removed", function(_, address) + if address == proxy.address then + for _, link in ipairs(links) do + fs.remove(link) + end + return false -- remove listener + end +end) \ No newline at end of file diff --git a/src/main/resources/assets/opencomputers/lua/component/data/bin/deflate.lua b/src/main/resources/assets/opencomputers/lua/component/data/bin/deflate.lua new file mode 100644 index 000000000..0ba356e3a --- /dev/null +++ b/src/main/resources/assets/opencomputers/lua/component/data/bin/deflate.lua @@ -0,0 +1,25 @@ +local shell = require("shell") +local data = require("data") + +local args = shell.parse(...) +if #args == 0 then + local read = "" + repeat + local current = io.read("*a") + read = read .. current + until current ~= "" + io.write(data.deflate(read)) +else + local read = "" + local file, reason = io.open(shell.resolve(args[1])) + if not file then + io.stderr:write(tostring(reason) .. "\n") + os.exit(false) + end + repeat + local current = file:read("*a") + read = read .. current + until current ~= "" + file:close() + io.write(data.deflate(read)) +end diff --git a/src/main/resources/assets/opencomputers/lua/component/data/bin/inflate.lua b/src/main/resources/assets/opencomputers/lua/component/data/bin/inflate.lua new file mode 100644 index 000000000..c78fd7287 --- /dev/null +++ b/src/main/resources/assets/opencomputers/lua/component/data/bin/inflate.lua @@ -0,0 +1,25 @@ +local shell = require("shell") +local data = require("data") + +local args = shell.parse(...) +if #args == 0 then + local read = "" + repeat + local current = io.read("*a") + read = read .. current + until current ~= "" + io.write(data.inflate(read)) +else + local read = "" + local file, reason = io.open(shell.resolve(args[1])) + if not file then + io.stderr:write(tostring(reason) .. "\n") + os.exit(false) + end + repeat + local current = file:read("*a") + read = read .. current + until current ~= "" + file:close() + io.write(data.inflate(read)) +end diff --git a/src/main/resources/assets/opencomputers/lua/component/data/bin/sha256.lua b/src/main/resources/assets/opencomputers/lua/component/data/bin/sha256.lua new file mode 100644 index 000000000..d31506197 --- /dev/null +++ b/src/main/resources/assets/opencomputers/lua/component/data/bin/sha256.lua @@ -0,0 +1,27 @@ +local shell = require("shell") +local data = require("data") + +local args = shell.parse(...) +if #args == 0 then + local read = "" + repeat + local current = io.read("*a") + read = read .. current + until current ~= "" + io.write(data.toHex(data.sha256(read))) +else + for i = 1, #args do + local read = "" + local file, reason = io.open(shell.resolve(args[i])) + if not file then + io.stderr:write(tostring(reason) .. "\n") + os.exit(false) + end + repeat + local current = file:read("*a") + read = read .. current + until current ~= "" + file:close() + io.write(args[i].. "\t".. data.toHex(data.sha256(read))) + end +end diff --git a/src/main/resources/assets/opencomputers/lua/component/data/lib/data.lua b/src/main/resources/assets/opencomputers/lua/component/data/lib/data.lua new file mode 100644 index 000000000..2afc0f0e4 --- /dev/null +++ b/src/main/resources/assets/opencomputers/lua/component/data/lib/data.lua @@ -0,0 +1,45 @@ +local component = require("component") + + +local data = {} +------------------------------------------------------------------------------- +-- Converts binary data into hexadecimal string. +function data.toHex(data) + return (data:gsub('.', function (c) + return string.format('%02X', string.byte(c)) + end)) +end + +-- Converts hexadecimal string into binary data. +function data.fromHex(hex) + return (data:gsub('..', function (cc) + return string.char(tonumber(cc, 16)) + end)) +end + +-- Applies base64 encoding. +function data.encode64(data) + return component.data.encode64(data) +end + +-- Applies base64 decoding. +function data.decode64(data) + return component.data.decode64(data) +end + +-- Returns raw/binary SHA2-256 hash of data. Common form of presenting SHA is hexadecimal string, see data.toHex. +function data.sha256(data) + return component.data.sha256(data) +end + +-- Applies DEFLATE compression. +function data.deflate(data) + return component.data.deflate(data) +end + +-- Applies INFLATE decompression. +function data.inflate(data) + return component.data.inflate(data) +end + +return data \ No newline at end of file diff --git a/src/main/scala/li/cil/oc/Constants.scala b/src/main/scala/li/cil/oc/Constants.scala index be261a68d..1b52ce623 100644 --- a/src/main/scala/li/cil/oc/Constants.scala +++ b/src/main/scala/li/cil/oc/Constants.scala @@ -79,6 +79,7 @@ object Constants { final val DatabaseUpgradeTier1 = "databaseUpgrade1" final val DatabaseUpgradeTier2 = "databaseUpgrade2" final val DatabaseUpgradeTier3 = "databaseUpgrade3" + final val DataCard = "dataCard" final val DebugCard = "debugCard" final val Debugger = "debugger" final val Disk = "disk" diff --git a/src/main/scala/li/cil/oc/common/init/Items.scala b/src/main/scala/li/cil/oc/common/init/Items.scala index 3fd66423c..d5d324422 100644 --- a/src/main/scala/li/cil/oc/common/init/Items.scala +++ b/src/main/scala/li/cil/oc/common/init/Items.scala @@ -14,8 +14,7 @@ import li.cil.oc.common.Loot import li.cil.oc.common.Tier import li.cil.oc.common.block.SimpleBlock import li.cil.oc.common.item -import li.cil.oc.common.item.Delegator -import li.cil.oc.common.item.UpgradeLeash +import li.cil.oc.common.item.{DataCard, Delegator, UpgradeLeash} import li.cil.oc.common.item.data.DroneData import li.cil.oc.common.item.data.HoverBootsData import li.cil.oc.common.item.data.MicrocontrollerData @@ -538,5 +537,8 @@ object Items extends ItemAPI { // 1.5.12 registerItem(new item.APU(multi, Tier.Three), Constants.ItemName.APUCreative) + + // 1.5.13 + Recipes.addSubItem(new DataCard(multi), Constants.ItemName.DataCard, "oc:dataCard") } } diff --git a/src/main/scala/li/cil/oc/common/item/DataCard.scala b/src/main/scala/li/cil/oc/common/item/DataCard.scala new file mode 100644 index 000000000..61127695f --- /dev/null +++ b/src/main/scala/li/cil/oc/common/item/DataCard.scala @@ -0,0 +1,3 @@ +package li.cil.oc.common.item + +class DataCard(val parent: Delegator) extends traits.Delegate \ No newline at end of file diff --git a/src/main/scala/li/cil/oc/integration/opencomputers/DriverDataCard.scala b/src/main/scala/li/cil/oc/integration/opencomputers/DriverDataCard.scala new file mode 100644 index 000000000..c4c954c2c --- /dev/null +++ b/src/main/scala/li/cil/oc/integration/opencomputers/DriverDataCard.scala @@ -0,0 +1,19 @@ +package li.cil.oc.integration.opencomputers + +import li.cil.oc.common.Slot +import li.cil.oc.server.component +import li.cil.oc.{Constants, api} +import li.cil.oc.api.driver.{EnvironmentHost, EnvironmentAware} +import net.minecraft.item.ItemStack + + +object DriverDataCard extends Item with EnvironmentAware{ + override def worksWith(stack: ItemStack) = isOneOf(stack, + api.Items.get(Constants.ItemName.DataCard)) + + override def createEnvironment(stack: ItemStack, host: EnvironmentHost) = new component.DataCard + + override def slot(stack: ItemStack) = Slot.Card + + override def providedEnvironment(stack: ItemStack) = classOf[component.DataCard] +} diff --git a/src/main/scala/li/cil/oc/integration/opencomputers/ModOpenComputers.scala b/src/main/scala/li/cil/oc/integration/opencomputers/ModOpenComputers.scala index 423cd12d6..9283c4a51 100644 --- a/src/main/scala/li/cil/oc/integration/opencomputers/ModOpenComputers.scala +++ b/src/main/scala/li/cil/oc/integration/opencomputers/ModOpenComputers.scala @@ -93,6 +93,7 @@ object ModOpenComputers extends ModProxy { api.Driver.add(DriverAPU) api.Driver.add(DriverComponentBus) api.Driver.add(DriverCPU) + api.Driver.add(DriverDataCard) api.Driver.add(DriverDebugCard) api.Driver.add(DriverEEPROM) api.Driver.add(DriverFileSystem) diff --git a/src/main/scala/li/cil/oc/server/component/DataCard.scala b/src/main/scala/li/cil/oc/server/component/DataCard.scala new file mode 100644 index 000000000..b366ee40c --- /dev/null +++ b/src/main/scala/li/cil/oc/server/component/DataCard.scala @@ -0,0 +1,87 @@ +package li.cil.oc.server.component + +import java.security.MessageDigest +import java.util.zip.{InflaterOutputStream, DeflaterOutputStream} + +import li.cil.oc.util.ExtendedNBT._ +import li.cil.oc.{Settings, OpenComputers, api} +import li.cil.oc.api.machine.{Arguments, Context, Callback} +import li.cil.oc.api.network.{Node, Visibility} +import li.cil.oc.api.{Network, prefab} +import net.minecraft.nbt.NBTTagCompound +import org.apache.commons.codec.binary.Base64 +import org.apache.commons.io.output.ByteArrayOutputStream + +class DataCard extends prefab.ManagedEnvironment{ + override val node = Network.newNode(this, Visibility.Neighbors). + withComponent("data", Visibility.Neighbors). + withConnector(). + create() + + val romData = Option(api.FileSystem.asManagedEnvironment(api.FileSystem. + fromClass(OpenComputers.getClass, Settings.resourceDomain, "lua/component/data"), "data")) + + @Callback(direct = true, doc = """function(data:string):string -- Applies base64 encoding to the data.""") + def encode64(context: Context, args: Arguments): Array[AnyRef] = { + result(Base64.encodeBase64(args.checkByteArray(0))) + } + + @Callback(direct = true, doc = """function(data:string):string -- Applies base64 decoding to the data.""") + def decode64(context: Context, args: Arguments): Array[AnyRef] = { + result(Base64.decodeBase64(args.checkByteArray(0))) + } + + @Callback(direct = true, doc = """function(data:string):string -- Applies deflate compression to the data.""") + def deflate(context: Context, args: Arguments): Array[AnyRef] = { + val baos = new ByteArrayOutputStream(512) + val deos = new DeflaterOutputStream(baos) + deos.write(args.checkByteArray(0)) + deos.finish() + result(baos.toByteArray) + } + + @Callback(direct = true, doc = """function(data:string):string -- Applies inflate decompression to the data.""") + def inflate(context: Context, args: Arguments): Array[AnyRef] = { + val baos = new ByteArrayOutputStream(512) + val inos = new InflaterOutputStream(baos) + inos.write(args.checkByteArray(0)) + inos.finish() + result(baos.toByteArray) + } + + @Callback(direct = true, doc = """function(data:string):string -- Computes SHA2-256 hash of the data.""") + def sha256(context: Context, args: Arguments): Array[AnyRef] = { + result(Helper.sha256(args.checkByteArray(0))) + } + + private object Helper { + val sha256asher = MessageDigest.getInstance("SHA-256") + def sha256(data: Array[Byte]) = sha256asher.clone.asInstanceOf[MessageDigest].digest(data) + } + + // ----------------------------------------------------------------------- // + + override def onConnect(node: Node) { + super.onConnect(node) + if (node.isNeighborOf(this.node)) { + romData.foreach(fs => node.connect(fs.node)) + } + } + + override def onDisconnect(node: Node) { + super.onDisconnect(node) + if (node == this.node) { + romData.foreach(_.node.remove()) + } + } + + override def load(nbt: NBTTagCompound) { + super.load(nbt) + romData.foreach(_.load(nbt.getCompoundTag("romData"))) + } + + override def save(nbt: NBTTagCompound) { + super.save(nbt) + romData.foreach(fs => nbt.setNewCompoundTag("romData", fs.save)) + } +}