Polish RA, make it usable.
This commit is contained in:
parent
262c0b5408
commit
6825a05778
14 changed files with 771 additions and 289 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1,3 +1,4 @@
|
|||
u2c.py
|
||||
push.sh
|
||||
version
|
||||
.env
|
||||
|
|
|
|||
|
|
@ -9,7 +9,8 @@ g(
|
|||
g(
|
||||
g(
|
||||
'Sa=XbandSb=XbxWSc=XlshiftSd=unpackSe=2^32SYf(g,h)Si=g/2^hSj=i%1Ui-j+j*eVSYk(l,m)Sn=l/2^mUn-n%1VSo={0x6a09e667Tbb67ae85T3c6ef372Ta54ff53aT510e527fT9b05688cT1f83d9abT5be0cd19}Sp={0x428a2f98T71374491Tb5c0fbcfTe9b5dba5T3956c25bT59f111f1T923f82a4Tab1c5ed5Td807aa98T12835b01T243185beT550c7dc3T72be5d74T80deb1feT9bdc06a7Tc19bf174Te49b69c1Tefbe4786T0fc19dc6T240ca1ccT2de92c6fT4a7484aaT5cb0a9dcT76f988daT983e5152Ta831c66dTb00327c8Tbf597fc7Tc6e00bf3Td5a79147T06ca6351T14292967T27b70a85T2e1b2138T4d2c6dfcT53380d13T650a7354T766a0abbT81c2c92eT92722c85Ta2bfe8a1Ta81a664bTc24b8b70Tc76c51a3Td192e819Td6990624Tf40e3585T106aa070T19a4c116T1e376c08T2748774cT34b0bcb5T391c0cb3T4ed8aa4aT5b9cca4fT682e6ff3T748f82eeT78a5636fT84c87814T8cc70208T90befffaTa4506cebTbef9a3f7Tc67178f2}SYq(r,q)if e-1-r[1]<q then r[2]=r[2]+1;r[1]=q-(e-1-r[1])-1 else r[1]=r[1]+qVUrVSYs(t)Su=#t;t[#t+1]=0x80;while#t%64~=56Zt[#t+1]=0VSv=q({0,0},u*8)fWw=2,1,-1Zt[#t+1]=a(k(a(v[w]TFF000000),24)TFF)t[#t+1]=a(k(a(v[w]TFF0000),16)TFF)t[#t+1]=a(k(a(v[w]TFF00),8)TFF)t[#t+1]=a(v[w]TFF)VUtVSYx(y,w)Uc(y[w]W0,24)+c(y[w+1]W0,16)+c(y[w+2]W0,8)+(y[w+3]W0)VSYz(t,w,A)SB={}fWC=1,16ZB[C]=x(t,w+(C-1)*4)VfWC=17,64ZSD=B[C-15]SE=b(b(f(B[C-15],7),f(B[C-15],18)),k(B[C-15],3))SF=b(b(f(B[C-2],17),f(B[C-2],19)),k(B[C-2],10))B[C]=(B[C-16]+E+B[C-7]+F)%eVSG,h,H,I,J,j,K,L=d(A)fWC=1,64ZSM=b(b(f(J,6),f(J,11)),f(J,25))SN=b(a(J,j),a(Xbnot(J),K))SO=(L+M+N+p[C]+B[C])%eSP=b(b(f(G,2),f(G,13)),f(G,22))SQ=b(b(a(G,h),a(G,H)),a(h,H))SR=(P+Q)%e;L,K,j,J,I,H,h,G=K,j,J,(I+O)%e,H,h,G,(O+R)%eVA[1]=(A[1]+G)%e;A[2]=(A[2]+h)%e;A[3]=(A[3]+H)%e;A[4]=(A[4]+I)%e;A[5]=(A[5]+J)%e;A[6]=(A[6]+j)%e;A[7]=(A[7]+K)%e;A[8]=(A[8]+L)%eUAVUY(t)t=t W""t=type(t)=="string"and{t:byte(1,-1)}Wt;t=s(t)SA={d(o)}fWw=1,#t,64ZA=z(t,w,A)VU("%08x"):rep(8):format(d(A))V',
|
||||
"S", " local "), "T", ",0x"), "U", " return "), "V", " end "), "W", "or "), "X", "bit32."), "Y", "function "), "Z",
|
||||
"S", " local "), "T", ",0x"), "U", " return "), "V", " end "), "W", "or "), "X", "bit32."), "Y",
|
||||
"function "), "Z",
|
||||
" do "))()
|
||||
|
||||
local aead = require("lib.plc.aead_chacha_poly")
|
||||
|
|
@ -151,8 +152,10 @@ local VERSION = "\1"
|
|||
local KDF_ID = "\1"
|
||||
local AAD = "SiSS RA rev1|chacha20poly1305"
|
||||
|
||||
local function u32be(n) return string.char(bit32.band(bit32.rshift(n, 24), 255), bit32.band(bit32.rshift(n, 16), 255),
|
||||
bit32.band(bit32.rshift(n, 8), 255), bit32.band(n, 255)) end
|
||||
local function u32be(n)
|
||||
return string.char(bit32.band(bit32.rshift(n, 24), 255), bit32.band(bit32.rshift(n, 16), 255),
|
||||
bit32.band(bit32.rshift(n, 8), 255), bit32.band(n, 255))
|
||||
end
|
||||
local function u16be(n) return string.char(bit32.band(bit32.rshift(n, 8), 255), bit32.band(n, 255)) end
|
||||
local function pack_params(iter)
|
||||
return u32be(iter) .. u16be(32)
|
||||
80
src/lib/encryption.lua
Normal file
80
src/lib/encryption.lua
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
local g = string.gsub
|
||||
|
||||
sha256 = loadstring(g(
|
||||
g(
|
||||
g(
|
||||
g(
|
||||
g(
|
||||
g(
|
||||
g(
|
||||
g(
|
||||
'Sa=XbandSb=XbxWSc=XlshiftSd=unpackSe=2^32SYf(g,h)Si=g/2^hSj=i%1Ui-j+j*eVSYk(l,m)Sn=l/2^mUn-n%1VSo={0x6a09e667Tbb67ae85T3c6ef372Ta54ff53aT510e527fT9b05688cT1f83d9abT5be0cd19}Sp={0x428a2f98T71374491Tb5c0fbcfTe9b5dba5T3956c25bT59f111f1T923f82a4Tab1c5ed5Td807aa98T12835b01T243185beT550c7dc3T72be5d74T80deb1feT9bdc06a7Tc19bf174Te49b69c1Tefbe4786T0fc19dc6T240ca1ccT2de92c6fT4a7484aaT5cb0a9dcT76f988daT983e5152Ta831c66dTb00327c8Tbf597fc7Tc6e00bf3Td5a79147T06ca6351T14292967T27b70a85T2e1b2138T4d2c6dfcT53380d13T650a7354T766a0abbT81c2c92eT92722c85Ta2bfe8a1Ta81a664bTc24b8b70Tc76c51a3Td192e819Td6990624Tf40e3585T106aa070T19a4c116T1e376c08T2748774cT34b0bcb5T391c0cb3T4ed8aa4aT5b9cca4fT682e6ff3T748f82eeT78a5636fT84c87814T8cc70208T90befffaTa4506cebTbef9a3f7Tc67178f2}SYq(r,q)if e-1-r[1]<q then r[2]=r[2]+1;r[1]=q-(e-1-r[1])-1 else r[1]=r[1]+qVUrVSYs(t)Su=#t;t[#t+1]=0x80;while#t%64~=56Zt[#t+1]=0VSv=q({0,0},u*8)fWw=2,1,-1Zt[#t+1]=a(k(a(v[w]TFF000000),24)TFF)t[#t+1]=a(k(a(v[w]TFF0000),16)TFF)t[#t+1]=a(k(a(v[w]TFF00),8)TFF)t[#t+1]=a(v[w]TFF)VUtVSYx(y,w)Uc(y[w]W0,24)+c(y[w+1]W0,16)+c(y[w+2]W0,8)+(y[w+3]W0)VSYz(t,w,A)SB={}fWC=1,16ZB[C]=x(t,w+(C-1)*4)VfWC=17,64ZSD=B[C-15]SE=b(b(f(B[C-15],7),f(B[C-15],18)),k(B[C-15],3))SF=b(b(f(B[C-2],17),f(B[C-2],19)),k(B[C-2],10))B[C]=(B[C-16]+E+B[C-7]+F)%eVSG,h,H,I,J,j,K,L=d(A)fWC=1,64ZSM=b(b(f(J,6),f(J,11)),f(J,25))SN=b(a(J,j),a(Xbnot(J),K))SO=(L+M+N+p[C]+B[C])%eSP=b(b(f(G,2),f(G,13)),f(G,22))SQ=b(b(a(G,h),a(G,H)),a(h,H))SR=(P+Q)%e;L,K,j,J,I,H,h,G=K,j,J,(I+O)%e,H,h,G,(O+R)%eVA[1]=(A[1]+G)%e;A[2]=(A[2]+h)%e;A[3]=(A[3]+H)%e;A[4]=(A[4]+I)%e;A[5]=(A[5]+J)%e;A[6]=(A[6]+j)%e;A[7]=(A[7]+K)%e;A[8]=(A[8]+L)%eUAVUY(t)t=t W""t=type(t)=="string"and{t:byte(1,-1)}Wt;t=s(t)SA={d(o)}fWw=1,#t,64ZA=z(t,w,A)VU("%08x"):rep(8):format(d(A))V',
|
||||
"S", " local "), "T", ",0x"), "U", " return "), "V", " end "), "W", "or "), "X", "bit32."), "Y",
|
||||
"function "), "Z",
|
||||
" do "))()
|
||||
|
||||
local chacha20 = require("lib.chacha20")
|
||||
|
||||
local function hex_to_bytes(hex)
|
||||
return (hex:gsub("..", function(cc)
|
||||
return string.char(tonumber(cc, 16))
|
||||
end))
|
||||
end
|
||||
|
||||
-- hash a human string into a 32-byte key
|
||||
---@param key string
|
||||
---@return string -- 32 bytes
|
||||
local function hashKey(key)
|
||||
return hex_to_bytes(sha256(key)) -- MUST return raw bytes
|
||||
end
|
||||
|
||||
-- generate secure random bytes
|
||||
local function random_bytes(n)
|
||||
local t = {}
|
||||
for i = 1, n do
|
||||
t[i] = string.char(math.random(0, 255))
|
||||
end
|
||||
return table.concat(t)
|
||||
end
|
||||
|
||||
---@param hashed_key string -- 32 bytes
|
||||
---@param plaintext string
|
||||
---@return string -- nonce || ciphertext
|
||||
local function encrypt(hashed_key, plaintext)
|
||||
assert(#hashed_key == 32, "key must be 32 bytes")
|
||||
|
||||
local nonce = random_bytes(24) -- XChaCha20 nonce
|
||||
local counter = 0
|
||||
|
||||
local ciphertext = chacha20.xchacha20_encrypt(
|
||||
hashed_key,
|
||||
counter,
|
||||
nonce,
|
||||
plaintext
|
||||
)
|
||||
|
||||
-- prepend nonce so it can be used for decryption
|
||||
return nonce .. ciphertext
|
||||
end
|
||||
|
||||
---@param hashed_key string
|
||||
---@param data string -- nonce || ciphertext
|
||||
---@return string plaintext
|
||||
local function decrypt(hashed_key, data)
|
||||
local nonce = data:sub(1, 24)
|
||||
local ciphertext = data:sub(25)
|
||||
local counter = 0
|
||||
|
||||
return chacha20.xchacha20_encrypt(
|
||||
hashed_key,
|
||||
counter,
|
||||
nonce,
|
||||
ciphertext
|
||||
)
|
||||
end
|
||||
|
||||
return {
|
||||
hashKey = hashKey,
|
||||
encrypt = encrypt,
|
||||
decrypt = decrypt
|
||||
}
|
||||
24
src/main.lua
24
src/main.lua
|
|
@ -2,28 +2,38 @@
|
|||
---@field port number
|
||||
---@field password string
|
||||
|
||||
---@class ConectionRemote : InnerRemote
|
||||
---@field remote string
|
||||
|
||||
---@class Remote
|
||||
---@field ender_storage string
|
||||
---@field modem string
|
||||
---@field remotes table<string, InnerRemote>
|
||||
---@field remotes table<string, InnerRemote>|nil
|
||||
---@field connection InnerRemote|nil
|
||||
|
||||
---@class Chatbox
|
||||
---@field players table<string, string>
|
||||
---@field prefix string|nil
|
||||
|
||||
---@class Config
|
||||
---@field inventories string[]
|
||||
---@field inventories string[]|nil
|
||||
---@field import string[]|nil
|
||||
---@field chatbox Chatbox|nil
|
||||
---@field remote Remote
|
||||
---@field remote Remote|nil
|
||||
|
||||
local inv = require("modules.inv")
|
||||
local config = require("../config") ---@type Config
|
||||
|
||||
local inv;
|
||||
|
||||
if config.inventories == nil and config.remote.connection then
|
||||
inv = require("modules.inv_ra")
|
||||
else
|
||||
inv = require("modules.inv")
|
||||
end
|
||||
local ui = require("modules.ui")
|
||||
local chatbox = require("modules.chatbox")
|
||||
local ra = require("modules.ra")
|
||||
|
||||
local config = require("../config") ---@type Config
|
||||
|
||||
local function importMechanism()
|
||||
if config.import == nil then
|
||||
|
|
@ -55,4 +65,6 @@ local function importMechanism()
|
|||
end
|
||||
|
||||
inv.sync()
|
||||
parallel.waitForAll(inv.getAIL().run, chatbox.run, ra.run, ui.run, importMechanism, inv.detectPlayerInsert)
|
||||
parallel.waitForAll(inv.run(), chatbox.run, ra.run,
|
||||
ui.run,
|
||||
importMechanism, inv.detectPlayerInsert)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
local config = require("../../config") ---@type Config
|
||||
local inv = require("modules.inv")
|
||||
local inv;
|
||||
|
||||
if config.inventories == nil and config.remote.connection then
|
||||
inv = require("modules.inv_ra")
|
||||
else
|
||||
inv = require("modules.inv")
|
||||
end
|
||||
local function levDist(s, t)
|
||||
local n = #s
|
||||
local m = #t
|
||||
|
|
@ -176,7 +181,7 @@ function run()
|
|||
---@type ccTweaked.peripheral.Inventory
|
||||
local peripInventory = perip.getInventory()
|
||||
|
||||
local best = findBest(inv.getAIL().listNames(), args[2])
|
||||
local best = findBest(inv.listNames(), args[2])
|
||||
|
||||
local itemName = ""
|
||||
|
||||
|
|
|
|||
|
|
@ -25,16 +25,7 @@ local function sync()
|
|||
end
|
||||
end
|
||||
|
||||
ail = abstractInventoryLib(foundInventories, true, {
|
||||
--[[cache = true,
|
||||
optimal = true,
|
||||
unoptimal = true,
|
||||
api = true,
|
||||
defrag = true,
|
||||
redirect = function (e)
|
||||
print(e)
|
||||
end,]]
|
||||
})
|
||||
ail = abstractInventoryLib(foundInventories, true, {})
|
||||
|
||||
print("Synced.");
|
||||
end
|
||||
|
|
@ -166,6 +157,7 @@ local function getTurtleInventory()
|
|||
end
|
||||
|
||||
local function detectPlayerInsert()
|
||||
if turtle then
|
||||
previousInventory = getTurtleInventory()
|
||||
|
||||
while true do
|
||||
|
|
@ -193,17 +185,32 @@ local function detectPlayerInsert()
|
|||
previousInventory = currentInventory
|
||||
end
|
||||
end
|
||||
|
||||
local function getAIL()
|
||||
return ail
|
||||
end
|
||||
|
||||
local function run()
|
||||
return ail.run
|
||||
end
|
||||
|
||||
local function listNames()
|
||||
return ail.listNames()
|
||||
end
|
||||
|
||||
local function listItemAmounts()
|
||||
return ail.listItemAmounts()
|
||||
end
|
||||
|
||||
local function getItem(z)
|
||||
return ail.getItem(z)
|
||||
end
|
||||
|
||||
return {
|
||||
detectPlayerInsert = detectPlayerInsert,
|
||||
sendItemAwayMultiple = sendItemAwayMultiple,
|
||||
sendItemToSelf = sendItemToSelf,
|
||||
getTurtleInventory = getTurtleInventory,
|
||||
listItemAmounts = listItemAmounts,
|
||||
listNames = listNames,
|
||||
getItem = getItem,
|
||||
sync = sync,
|
||||
getAIL = getAIL,
|
||||
run = run
|
||||
}
|
||||
|
|
|
|||
171
src/modules/inv_ra.lua
Normal file
171
src/modules/inv_ra.lua
Normal file
|
|
@ -0,0 +1,171 @@
|
|||
local previousInventory = {}
|
||||
---@type ccTweaked.peripheral.WiredModem
|
||||
local modem = peripheral.find("modem");
|
||||
local turtleId = modem.getNameLocal()
|
||||
local turtleMoveAllowed = true
|
||||
local config = require("../../config") ---@type Config
|
||||
|
||||
local ra = require("tiny_ra_library")
|
||||
|
||||
local function sync()
|
||||
print("inv_ra does not require syncing (it is already synced!)")
|
||||
end
|
||||
|
||||
---@param itemName string
|
||||
---@param perip ccTweaked.peripheral.Inventory|string|nil
|
||||
---@param maxAmount number|nil
|
||||
local function sendItemToSelf(itemName, perip, maxAmount)
|
||||
local enderstorage = peripheral.wrap(config.remote.ender_storage);
|
||||
if enderstorage == nil then return end
|
||||
turtleMoveAllowed = false
|
||||
|
||||
local id = turtleId;
|
||||
|
||||
ra.withdraw(itemName, maxAmount, true) -- make sure to wait so we can push to turtle once waited
|
||||
|
||||
if type(perip) == "string" then
|
||||
id = perip
|
||||
end
|
||||
|
||||
for key, _ in pairs(enderstorage.list()) do
|
||||
enderstorage.pushItems(id, key)
|
||||
end
|
||||
|
||||
sleep(0.2)
|
||||
turtleMoveAllowed = true
|
||||
end
|
||||
|
||||
---@param slots ccTweaked.turtle.turtleSlot[]
|
||||
---@param perip ccTweaked.peripheral.Inventory|nil
|
||||
---@param id string|nil
|
||||
---@param maxAmount number|nil
|
||||
local function sendItemAwayMultiple(slots, perip, id, maxAmount)
|
||||
if perip == nil then
|
||||
perip = turtle
|
||||
end
|
||||
local srcId = id or turtleId
|
||||
|
||||
if srcId == nil then return end
|
||||
|
||||
local itemsInSlots = {}
|
||||
for _, slot in ipairs(slots) do
|
||||
local item = perip.getItemDetail(slot)
|
||||
if item then
|
||||
itemsInSlots[slot] = item
|
||||
end
|
||||
end
|
||||
|
||||
local enderstorage = peripheral.wrap(config.remote.ender_storage);
|
||||
if enderstorage == nil then return end
|
||||
local totalMoved = 0
|
||||
local remaining = maxAmount or math.huge
|
||||
|
||||
if remaining <= 0 then
|
||||
return 0
|
||||
end
|
||||
|
||||
for _, slot in ipairs(slots) do
|
||||
if remaining <= 0 then break end
|
||||
|
||||
local toSend = math.min(64, remaining)
|
||||
|
||||
local ok, pulled = pcall(function()
|
||||
return enderstorage.pullItems(srcId, slot, toSend)
|
||||
end)
|
||||
|
||||
if ok and pulled and pulled > 0 then
|
||||
totalMoved = totalMoved + pulled
|
||||
remaining = remaining - pulled
|
||||
end
|
||||
end
|
||||
|
||||
local numItems = 0
|
||||
for _, _ in pairs(itemsInSlots) do
|
||||
numItems = numItems + 1
|
||||
end
|
||||
|
||||
if numItems > 0 then
|
||||
os.queueEvent("update_ui")
|
||||
end
|
||||
|
||||
local keys = {}
|
||||
|
||||
for key, _ in pairs(enderstorage.list()) do
|
||||
if key ~= nil then
|
||||
table.insert(keys, key)
|
||||
end
|
||||
end
|
||||
|
||||
ra.depositBySlots(keys, nil, false)
|
||||
return totalMoved
|
||||
end
|
||||
|
||||
local function getTurtleInventory()
|
||||
local inventory = {}
|
||||
for slot = 1, 16 do
|
||||
local item = turtle.getItemDetail(slot, false)
|
||||
inventory[slot] = item
|
||||
end
|
||||
return inventory
|
||||
end
|
||||
|
||||
local function detectPlayerInsert()
|
||||
if turtle then
|
||||
previousInventory = getTurtleInventory()
|
||||
|
||||
while true do
|
||||
os.pullEvent("turtle_inventory")
|
||||
|
||||
local currentInventory = getTurtleInventory()
|
||||
|
||||
if turtleMoveAllowed then
|
||||
local newlyAddedSlots = {}
|
||||
|
||||
for slot = 1, 16 do
|
||||
local prev = previousInventory[slot]
|
||||
local curr = currentInventory[slot]
|
||||
|
||||
if not prev and curr then
|
||||
table.insert(newlyAddedSlots, slot)
|
||||
end
|
||||
end
|
||||
|
||||
if #newlyAddedSlots > 0 then
|
||||
sendItemAwayMultiple(newlyAddedSlots)
|
||||
end
|
||||
end
|
||||
|
||||
previousInventory = currentInventory
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function run()
|
||||
return function()
|
||||
ra.init(peripheral.wrap(config.remote.modem), config.remote.connection.port, config.remote.connection.password)
|
||||
end
|
||||
end
|
||||
|
||||
local function listNames()
|
||||
return ra.listNames()
|
||||
end
|
||||
|
||||
local function listItemAmounts()
|
||||
return ra.listItemAmounts()
|
||||
end
|
||||
|
||||
local function getItem(z)
|
||||
return ra.getItem(z)
|
||||
end
|
||||
|
||||
return {
|
||||
detectPlayerInsert = detectPlayerInsert,
|
||||
sendItemAwayMultiple = sendItemAwayMultiple,
|
||||
sendItemToSelf = sendItemToSelf,
|
||||
getTurtleInventory = getTurtleInventory,
|
||||
listItemAmounts = listItemAmounts,
|
||||
listNames = listNames,
|
||||
getItem = getItem,
|
||||
sync = sync,
|
||||
run = run
|
||||
}
|
||||
|
|
@ -1,6 +1,12 @@
|
|||
local inv = require("modules.inv");
|
||||
local config = require("../../config") ---@type Config
|
||||
local hmac = require("lib.hmac-pbkdf2-aead")
|
||||
if config.inventories == nil and config.remote.connection then
|
||||
inv = require("modules.inv_ra")
|
||||
else
|
||||
inv = require("modules.inv")
|
||||
end
|
||||
|
||||
|
||||
local encryption = require("lib.encryption")
|
||||
---@class RemoteAccess
|
||||
---@field type string
|
||||
---@field data RemoteAccessData
|
||||
|
|
@ -10,13 +16,34 @@ local hmac = require("lib.hmac-pbkdf2-aead")
|
|||
---@field amount number|nil
|
||||
---@field slots number[]|nil
|
||||
|
||||
|
||||
|
||||
local function sendResponse(modem, port, hashedPassword, id, ok, data, err)
|
||||
modem.transmit(
|
||||
port,
|
||||
port,
|
||||
encryption.encrypt(hashedPassword,
|
||||
textutils.serialiseJSON({
|
||||
type = "response",
|
||||
id = id,
|
||||
ok = ok,
|
||||
data = data,
|
||||
error = err
|
||||
})
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
local function run()
|
||||
if config.remote == nil then return end
|
||||
if config.remote == nil or config.remote.remotes == nil then return end
|
||||
|
||||
local modem = peripheral.wrap(config.remote.modem)
|
||||
if not modem then return end
|
||||
|
||||
for _, remote in pairs(config.remote.remotes) do
|
||||
local remotes = config.remote.remotes or { config.remote.connection }
|
||||
|
||||
for _, remote in pairs(remotes) do
|
||||
if not modem.isOpen(remote.port) then
|
||||
modem.open(remote.port)
|
||||
end
|
||||
|
|
@ -28,10 +55,11 @@ local function run()
|
|||
while true do
|
||||
local _, _, channel, _, message, _ = os.pullEvent("modem_message")
|
||||
|
||||
for color, remote in pairs(config.remote.remotes) do
|
||||
for color, remote in pairs(remotes) do
|
||||
if remote.port == channel then
|
||||
local hashed = encryption.hashKey(remote.password)
|
||||
local err, data = pcall(function()
|
||||
return hmac.decrypt_with_password(remote.password, message)
|
||||
return encryption.decrypt(hashed, message)
|
||||
end)
|
||||
|
||||
if not data then return end
|
||||
|
|
@ -51,8 +79,17 @@ local function run()
|
|||
colors[parts[3]]
|
||||
)
|
||||
if json.type == "withdraw" then
|
||||
inv.sendItemToSelf(json.data.itemName, config.remote.ender_storage, json.data.amount)
|
||||
local ok, err = pcall(function()
|
||||
inv.sendItemToSelf(
|
||||
json.data.itemName,
|
||||
config.remote.ender_storage,
|
||||
json.data.amount
|
||||
)
|
||||
end)
|
||||
|
||||
sendResponse(modem, remote.port, hashed, json.id, ok, nil, err)
|
||||
elseif json.type == "deposit" then
|
||||
local ok, err = pcall(function()
|
||||
if json.data.itemName then
|
||||
local move = {}
|
||||
for s, i in pairs(ender_storage.list()) do
|
||||
|
|
@ -60,14 +97,64 @@ local function run()
|
|||
table.insert(move, s)
|
||||
end
|
||||
end
|
||||
inv.sendItemAwayMultiple(move, ender_storage, config.remote.ender_storage, json.data.amount)
|
||||
inv.sendItemAwayMultiple(
|
||||
move,
|
||||
ender_storage,
|
||||
config.remote.ender_storage,
|
||||
json.data.amount
|
||||
)
|
||||
elseif json.data.slots then
|
||||
if type(json.data.slots) ~= 'table' then
|
||||
return
|
||||
inv.sendItemAwayMultiple(
|
||||
json.data.slots,
|
||||
ender_storage,
|
||||
config.remote.ender_storage,
|
||||
json.data.amount
|
||||
)
|
||||
end
|
||||
end)
|
||||
|
||||
inv.sendItemAwayMultiple(json.data.slots, ender_storage, config.remote.ender_storage, json.data.amount)
|
||||
end
|
||||
sendResponse(modem, remote.port, hashed, json.id, ok, nil, err)
|
||||
elseif json.type == "list_names" then
|
||||
local ok, result = pcall(function()
|
||||
return inv.listNames()
|
||||
end)
|
||||
sendResponse(
|
||||
modem,
|
||||
remote.port,
|
||||
hashed,
|
||||
json.id,
|
||||
ok,
|
||||
ok and result or nil,
|
||||
not ok and result or nil
|
||||
)
|
||||
elseif json.type == "list_item_amounts" then
|
||||
local ok, result = pcall(function()
|
||||
return inv.listItemAmounts()
|
||||
end)
|
||||
|
||||
sendResponse(
|
||||
modem,
|
||||
remote.port,
|
||||
hashed,
|
||||
json.id,
|
||||
ok,
|
||||
ok and result or nil,
|
||||
not ok and result or nil
|
||||
)
|
||||
elseif json.type == "get_item" then
|
||||
local ok, result = pcall(function()
|
||||
return inv.getItem(json.data.index)
|
||||
end)
|
||||
|
||||
sendResponse(
|
||||
modem,
|
||||
remote.port,
|
||||
hashed,
|
||||
json.id,
|
||||
ok,
|
||||
ok and result or nil,
|
||||
not ok and result or nil
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,4 +1,11 @@
|
|||
local inv = require("modules.inv");
|
||||
local config = require("../../config") ---@type Config
|
||||
local inv;
|
||||
if config.inventories == nil and config.remote.connection then
|
||||
inv = require("modules.inv_ra")
|
||||
else
|
||||
inv = require("modules.inv")
|
||||
end
|
||||
|
||||
local PrimeUI = require("lib.primeui").PrimeUI;
|
||||
local function is_beta(ver)
|
||||
if ver:match("^[0-9a-f]+$") and #ver >= 8 then
|
||||
|
|
@ -12,9 +19,18 @@ local function run()
|
|||
local win = term.current();
|
||||
local w, h = term.getSize()
|
||||
|
||||
local items = inv.listItemAmounts()
|
||||
local x = 0
|
||||
|
||||
local function getFiltered()
|
||||
local filtered = {}
|
||||
for name, count in pairs(inv.getAIL().listItemAmounts()) do
|
||||
|
||||
x = x + 1
|
||||
if x % 3 == 0 then
|
||||
items = inv.listItemAmounts()
|
||||
end
|
||||
|
||||
for name, count in pairs(items) do
|
||||
if search == "" or string.find(name:lower(), search:lower(), 1, true) then
|
||||
table.insert(filtered, { name = name, count = count })
|
||||
end
|
||||
|
|
@ -40,8 +56,7 @@ local function run()
|
|||
end,
|
||||
function(option)
|
||||
local z = option:match("^(%S+)")
|
||||
|
||||
if inv.getAIL().getItem(z) then
|
||||
if inv.getItem(z) then
|
||||
inv.sendItemToSelf(z)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
198
src/tiny_ra_library.lua
Normal file
198
src/tiny_ra_library.lua
Normal file
|
|
@ -0,0 +1,198 @@
|
|||
local encryption = require("lib.encryption")
|
||||
|
||||
---@type string
|
||||
local password
|
||||
---@type number
|
||||
local port
|
||||
|
||||
---@type string
|
||||
local hashedPassword
|
||||
---@type ccTweaked.peripheral.Modem
|
||||
local modem
|
||||
local function sendRequest(reqType, data, wait)
|
||||
if wait == nil then
|
||||
wait = true
|
||||
end
|
||||
local id = tostring(math.random(1, 1e9))
|
||||
|
||||
modem.transmit(
|
||||
port,
|
||||
port,
|
||||
encryption.encrypt(hashedPassword,
|
||||
textutils.serialiseJSON({
|
||||
type = reqType,
|
||||
id = id,
|
||||
data = data
|
||||
})
|
||||
)
|
||||
)
|
||||
|
||||
if wait then
|
||||
-- wait for response
|
||||
while true do
|
||||
local event, side, senderChannel, replyChannel, message = os.pullEvent("modem_message")
|
||||
local ok, decrypted = pcall(encryption.decrypt, hashedPassword, message)
|
||||
if not ok then goto continue end
|
||||
|
||||
local resp = textutils.unserialiseJSON(decrypted)
|
||||
if resp and resp.type == "response" and resp.id == id then
|
||||
return resp.ok, resp.data or resp.error
|
||||
end
|
||||
|
||||
::continue::
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function init(modemI, portI, passwordI)
|
||||
port = portI
|
||||
password = passwordI
|
||||
hashedPassword = encryption.hashKey(passwordI)
|
||||
modem = modemI
|
||||
|
||||
modem.open(port)
|
||||
end
|
||||
|
||||
|
||||
---@param wait boolean|nil
|
||||
local function listNames(wait)
|
||||
if not port or not modem or not password then
|
||||
error("tiny_ra_library: init was never ran")
|
||||
end
|
||||
if wait == nil then
|
||||
wait = true
|
||||
end
|
||||
|
||||
local ok, data = sendRequest("list_names", nil, wait)
|
||||
if wait then
|
||||
if not ok then
|
||||
error("Failed to list names: " .. tostring(data))
|
||||
end
|
||||
return data
|
||||
end
|
||||
end
|
||||
|
||||
---@param itemName string
|
||||
---@param count number|nil
|
||||
---@param wait boolean|nil
|
||||
local function withdraw(itemName, count, wait)
|
||||
if not port or not modem or not password then
|
||||
error("tiny_ra_library: init was never ran")
|
||||
end
|
||||
|
||||
if wait == nil then
|
||||
wait = true
|
||||
end
|
||||
|
||||
local ok, data = sendRequest("withdraw", {
|
||||
itemName = itemName,
|
||||
count = count
|
||||
}, wait)
|
||||
if wait then
|
||||
if not ok then
|
||||
error("Failed to withdraw: " .. tostring(data))
|
||||
end
|
||||
return data
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
---@param slots number[]
|
||||
---@param count number|nil
|
||||
---@param wait boolean|nil
|
||||
local function depositBySlots(slots, count, wait)
|
||||
if not port or not modem or not password then
|
||||
error("tiny_ra_library: init was never ran")
|
||||
end
|
||||
|
||||
if wait == nil then
|
||||
wait = true
|
||||
end
|
||||
|
||||
local data = {
|
||||
slots = slots
|
||||
}
|
||||
|
||||
if count then
|
||||
data["count"] = count
|
||||
end
|
||||
|
||||
local ok, response = sendRequest("deposit", data, wait)
|
||||
|
||||
if wait then
|
||||
if not ok then
|
||||
error("Failed to deposit by slots: " .. tostring(response))
|
||||
end
|
||||
return response
|
||||
end
|
||||
end
|
||||
|
||||
---@param wait boolean|nil
|
||||
local function listItemAmounts(wait)
|
||||
if wait == nil then
|
||||
wait = true
|
||||
end
|
||||
local ok, response = sendRequest("list_item_amounts", nil, wait)
|
||||
|
||||
if wait then
|
||||
if not ok then
|
||||
error("Failed to list names: " .. tostring(response))
|
||||
end
|
||||
return response
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
---@param itemName string
|
||||
---@param wait boolean|nil
|
||||
local function getItem(itemName, wait)
|
||||
if wait == nil then
|
||||
wait = true
|
||||
end
|
||||
local ok, data = sendRequest("get_item", { index = itemName }, wait)
|
||||
if wait then
|
||||
if not ok then
|
||||
error("Failed to list names: " .. tostring(data))
|
||||
end
|
||||
return data
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
---@param itemName string
|
||||
---@param count number|nil
|
||||
---@param wait boolean|nil
|
||||
local function depositByItemName(itemName, count, wait)
|
||||
if not port or not modem or not password then
|
||||
error("tiny_ra_library: init was never ran")
|
||||
end
|
||||
|
||||
local data = {
|
||||
itemName = itemName
|
||||
}
|
||||
|
||||
if count then
|
||||
data["count"] = count
|
||||
end
|
||||
|
||||
local ok, response = sendRequest("deposit", data, wait)
|
||||
|
||||
if wait then
|
||||
if not ok then
|
||||
error("Failed to list names: " .. tostring(response))
|
||||
end
|
||||
return response
|
||||
end
|
||||
end
|
||||
|
||||
return {
|
||||
init = init,
|
||||
|
||||
listItemAmounts = listItemAmounts,
|
||||
getItem = getItem,
|
||||
listNames = listNames,
|
||||
|
||||
withdraw = withdraw,
|
||||
depositByItemName = depositByItemName,
|
||||
depositBySlots = depositBySlots
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
Loading…
Add table
Add a link
Reference in a new issue