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
|
u2c.py
|
||||||
push.sh
|
push.sh
|
||||||
version
|
version
|
||||||
|
.env
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,16 @@
|
||||||
local g = string.gsub
|
local g = string.gsub
|
||||||
|
|
||||||
sha256 = loadstring(g(
|
sha256 = loadstring(g(
|
||||||
g(
|
g(
|
||||||
g(
|
g(
|
||||||
g(
|
g(
|
||||||
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',
|
'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 "))()
|
" do "))()
|
||||||
|
|
||||||
local aead = require("lib.plc.aead_chacha_poly")
|
local aead = require("lib.plc.aead_chacha_poly")
|
||||||
|
|
@ -27,9 +28,9 @@ local function b64u_encode(bin)
|
||||||
out[#out + 1] = b64abc:sub(bit32.band(bit32.rshift(triple, 18), 63) + 1, bit32.band(bit32.rshift(triple, 18), 63) + 1)
|
out[#out + 1] = b64abc:sub(bit32.band(bit32.rshift(triple, 18), 63) + 1, bit32.band(bit32.rshift(triple, 18), 63) + 1)
|
||||||
out[#out + 1] = b64abc:sub(bit32.band(bit32.rshift(triple, 12), 63) + 1, bit32.band(bit32.rshift(triple, 12), 63) + 1)
|
out[#out + 1] = b64abc:sub(bit32.band(bit32.rshift(triple, 12), 63) + 1, bit32.band(bit32.rshift(triple, 12), 63) + 1)
|
||||||
out[#out + 1] = i + 1 <= n and
|
out[#out + 1] = i + 1 <= n and
|
||||||
b64abc:sub(bit32.band(bit32.rshift(triple, 6), 63) + 1, bit32.band(bit32.rshift(triple, 6), 63) + 1) or ''
|
b64abc:sub(bit32.band(bit32.rshift(triple, 6), 63) + 1, bit32.band(bit32.rshift(triple, 6), 63) + 1) or ''
|
||||||
out[#out + 1] = i + 2 <= n and
|
out[#out + 1] = i + 2 <= n and
|
||||||
b64abc:sub(bit32.band(bit32.rshift(triple, 0), 63) + 1, bit32.band(bit32.rshift(triple, 0), 63) + 1) or ''
|
b64abc:sub(bit32.band(bit32.rshift(triple, 0), 63) + 1, bit32.band(bit32.rshift(triple, 0), 63) + 1) or ''
|
||||||
i = i + 3
|
i = i + 3
|
||||||
end
|
end
|
||||||
return table.concat(out)
|
return table.concat(out)
|
||||||
|
|
@ -151,8 +152,10 @@ local VERSION = "\1"
|
||||||
local KDF_ID = "\1"
|
local KDF_ID = "\1"
|
||||||
local AAD = "SiSS RA rev1|chacha20poly1305"
|
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),
|
local function u32be(n)
|
||||||
bit32.band(bit32.rshift(n, 8), 255), bit32.band(n, 255)) end
|
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 u16be(n) return string.char(bit32.band(bit32.rshift(n, 8), 255), bit32.band(n, 255)) end
|
||||||
local function pack_params(iter)
|
local function pack_params(iter)
|
||||||
return u32be(iter) .. u16be(32)
|
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 port number
|
||||||
---@field password string
|
---@field password string
|
||||||
|
|
||||||
|
---@class ConectionRemote : InnerRemote
|
||||||
|
---@field remote string
|
||||||
|
|
||||||
---@class Remote
|
---@class Remote
|
||||||
---@field ender_storage string
|
---@field ender_storage string
|
||||||
---@field modem string
|
---@field modem string
|
||||||
---@field remotes table<string, InnerRemote>
|
---@field remotes table<string, InnerRemote>|nil
|
||||||
|
---@field connection InnerRemote|nil
|
||||||
|
|
||||||
---@class Chatbox
|
---@class Chatbox
|
||||||
---@field players table<string, string>
|
---@field players table<string, string>
|
||||||
---@field prefix string|nil
|
---@field prefix string|nil
|
||||||
|
|
||||||
---@class Config
|
---@class Config
|
||||||
---@field inventories string[]
|
---@field inventories string[]|nil
|
||||||
---@field import string[]|nil
|
---@field import string[]|nil
|
||||||
---@field chatbox Chatbox|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 ui = require("modules.ui")
|
||||||
local chatbox = require("modules.chatbox")
|
local chatbox = require("modules.chatbox")
|
||||||
local ra = require("modules.ra")
|
local ra = require("modules.ra")
|
||||||
|
|
||||||
local config = require("../config") ---@type Config
|
|
||||||
|
|
||||||
local function importMechanism()
|
local function importMechanism()
|
||||||
if config.import == nil then
|
if config.import == nil then
|
||||||
|
|
@ -55,4 +65,6 @@ local function importMechanism()
|
||||||
end
|
end
|
||||||
|
|
||||||
inv.sync()
|
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 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 function levDist(s, t)
|
||||||
local n = #s
|
local n = #s
|
||||||
local m = #t
|
local m = #t
|
||||||
|
|
@ -176,7 +181,7 @@ function run()
|
||||||
---@type ccTweaked.peripheral.Inventory
|
---@type ccTweaked.peripheral.Inventory
|
||||||
local peripInventory = perip.getInventory()
|
local peripInventory = perip.getInventory()
|
||||||
|
|
||||||
local best = findBest(inv.getAIL().listNames(), args[2])
|
local best = findBest(inv.listNames(), args[2])
|
||||||
|
|
||||||
local itemName = ""
|
local itemName = ""
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,85 +13,76 @@ local peripherals = peripheral.getNames();
|
||||||
local ail = nil
|
local ail = nil
|
||||||
|
|
||||||
local function sync()
|
local function sync()
|
||||||
print("Syncing..")
|
print("Syncing..")
|
||||||
---@type string[]
|
---@type string[]
|
||||||
local foundInventories = {}
|
local foundInventories = {}
|
||||||
|
|
||||||
for _, invPattern in ipairs(config.inventories) do
|
for _, invPattern in ipairs(config.inventories) do
|
||||||
for _, inv in ipairs(peripherals) do
|
for _, inv in ipairs(peripherals) do
|
||||||
if string.find(inv, invPattern) then
|
if string.find(inv, invPattern) then
|
||||||
table.insert(foundInventories, inv)
|
table.insert(foundInventories, inv)
|
||||||
end
|
end
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
ail = abstractInventoryLib(foundInventories, true, {
|
ail = abstractInventoryLib(foundInventories, true, {})
|
||||||
--[[cache = true,
|
|
||||||
optimal = true,
|
|
||||||
unoptimal = true,
|
|
||||||
api = true,
|
|
||||||
defrag = true,
|
|
||||||
redirect = function (e)
|
|
||||||
print(e)
|
|
||||||
end,]]
|
|
||||||
})
|
|
||||||
|
|
||||||
print("Synced.");
|
print("Synced.");
|
||||||
end
|
end
|
||||||
---@param itemName string
|
---@param itemName string
|
||||||
---@param perip ccTweaked.peripheral.Inventory|string|nil
|
---@param perip ccTweaked.peripheral.Inventory|string|nil
|
||||||
---@param maxAmount number|nil
|
---@param maxAmount number|nil
|
||||||
local function sendItemToSelf(itemName, perip, maxAmount)
|
local function sendItemToSelf(itemName, perip, maxAmount)
|
||||||
if perip == nil then
|
if perip == nil then
|
||||||
perip = turtleId
|
perip = turtleId
|
||||||
end
|
end
|
||||||
turtleMoveAllowed = false
|
turtleMoveAllowed = false
|
||||||
|
|
||||||
local remaining = maxAmount or 64
|
local remaining = maxAmount or 64
|
||||||
local total = 0
|
local total = 0
|
||||||
|
|
||||||
if remaining <= 0 then
|
if remaining <= 0 then
|
||||||
turtleMoveAllowed = true
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
if #ail.listNBT(itemName) ~= 0 then
|
|
||||||
local nbtList = ail.listNBT(itemName)
|
|
||||||
local chosenNBT = nil
|
|
||||||
if nbtList and #nbtList > 0 then
|
|
||||||
chosenNBT = nbtList[math.random(1, #nbtList)]
|
|
||||||
end
|
|
||||||
|
|
||||||
if chosenNBT == "NONE" then
|
|
||||||
chosenNBT = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
while remaining > 0 do
|
|
||||||
local toSend = math.min(64, remaining)
|
|
||||||
|
|
||||||
local ok, moved = pcall(function()
|
|
||||||
ail.performTransfer()
|
|
||||||
|
|
||||||
local amount = ail.pushItems(perip, itemName, toSend, nil, chosenNBT, {
|
|
||||||
["allowBadTransfers"] = true,
|
|
||||||
["optimal"] = false
|
|
||||||
})
|
|
||||||
|
|
||||||
ail.performTransfer()
|
|
||||||
|
|
||||||
return amount
|
|
||||||
end)
|
|
||||||
total = total + moved
|
|
||||||
if ok and moved and moved > 0 then
|
|
||||||
remaining = remaining - moved
|
|
||||||
else
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
turtleMoveAllowed = true
|
turtleMoveAllowed = true
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
return total
|
if #ail.listNBT(itemName) ~= 0 then
|
||||||
|
local nbtList = ail.listNBT(itemName)
|
||||||
|
local chosenNBT = nil
|
||||||
|
if nbtList and #nbtList > 0 then
|
||||||
|
chosenNBT = nbtList[math.random(1, #nbtList)]
|
||||||
|
end
|
||||||
|
|
||||||
|
if chosenNBT == "NONE" then
|
||||||
|
chosenNBT = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
while remaining > 0 do
|
||||||
|
local toSend = math.min(64, remaining)
|
||||||
|
|
||||||
|
local ok, moved = pcall(function()
|
||||||
|
ail.performTransfer()
|
||||||
|
|
||||||
|
local amount = ail.pushItems(perip, itemName, toSend, nil, chosenNBT, {
|
||||||
|
["allowBadTransfers"] = true,
|
||||||
|
["optimal"] = false
|
||||||
|
})
|
||||||
|
|
||||||
|
ail.performTransfer()
|
||||||
|
|
||||||
|
return amount
|
||||||
|
end)
|
||||||
|
total = total + moved
|
||||||
|
if ok and moved and moved > 0 then
|
||||||
|
remaining = remaining - moved
|
||||||
|
else
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
turtleMoveAllowed = true
|
||||||
|
|
||||||
|
return total
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param slots ccTweaked.turtle.turtleSlot[]
|
---@param slots ccTweaked.turtle.turtleSlot[]
|
||||||
|
|
@ -99,111 +90,127 @@ end
|
||||||
---@param id string|nil
|
---@param id string|nil
|
||||||
---@param maxAmount number|nil
|
---@param maxAmount number|nil
|
||||||
local function sendItemAwayMultiple(slots, perip, id, maxAmount)
|
local function sendItemAwayMultiple(slots, perip, id, maxAmount)
|
||||||
if perip == nil then
|
if perip == nil then
|
||||||
perip = turtle
|
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 srcId = id or turtleId
|
end
|
||||||
|
|
||||||
if srcId == nil then return end
|
local totalMoved = 0
|
||||||
|
local remaining = maxAmount or math.huge
|
||||||
|
|
||||||
local itemsInSlots = {}
|
if remaining <= 0 then
|
||||||
for _, slot in ipairs(slots) do
|
return 0
|
||||||
local item = perip.getItemDetail(slot)
|
end
|
||||||
if item then
|
|
||||||
itemsInSlots[slot] = item
|
for _, slot in ipairs(slots) do
|
||||||
end
|
if remaining <= 0 then break end
|
||||||
|
|
||||||
|
local toSend = math.min(64, remaining)
|
||||||
|
|
||||||
|
local ok, pulled = pcall(function()
|
||||||
|
ail.performTransfer()
|
||||||
|
|
||||||
|
local moved = ail.pullItems(srcId, slot, toSend, nil, nil, {
|
||||||
|
["allowBadTransfers"] = true,
|
||||||
|
["optimal"] = false
|
||||||
|
})
|
||||||
|
|
||||||
|
ail.performTransfer()
|
||||||
|
return moved
|
||||||
|
end)
|
||||||
|
|
||||||
|
if ok and pulled and pulled > 0 then
|
||||||
|
totalMoved = totalMoved + pulled
|
||||||
|
remaining = remaining - pulled
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
local totalMoved = 0
|
local numItems = 0
|
||||||
local remaining = maxAmount or math.huge
|
for _, _ in pairs(itemsInSlots) do
|
||||||
|
numItems = numItems + 1
|
||||||
|
end
|
||||||
|
|
||||||
if remaining <= 0 then
|
if numItems > 0 then
|
||||||
return 0
|
os.queueEvent("update_ui")
|
||||||
end
|
end
|
||||||
|
|
||||||
for _, slot in ipairs(slots) do
|
return totalMoved
|
||||||
if remaining <= 0 then break end
|
|
||||||
|
|
||||||
local toSend = math.min(64, remaining)
|
|
||||||
|
|
||||||
local ok, pulled = pcall(function()
|
|
||||||
ail.performTransfer()
|
|
||||||
|
|
||||||
local moved = ail.pullItems(srcId, slot, toSend, nil, nil, {
|
|
||||||
["allowBadTransfers"] = true,
|
|
||||||
["optimal"] = false
|
|
||||||
})
|
|
||||||
|
|
||||||
ail.performTransfer()
|
|
||||||
return moved
|
|
||||||
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
|
|
||||||
|
|
||||||
return totalMoved
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local function getTurtleInventory()
|
local function getTurtleInventory()
|
||||||
local inventory = {}
|
local inventory = {}
|
||||||
for slot = 1, 16 do
|
for slot = 1, 16 do
|
||||||
local item = turtle.getItemDetail(slot, false)
|
local item = turtle.getItemDetail(slot, false)
|
||||||
inventory[slot] = item
|
inventory[slot] = item
|
||||||
end
|
end
|
||||||
return inventory
|
return inventory
|
||||||
end
|
end
|
||||||
|
|
||||||
local function detectPlayerInsert()
|
local function detectPlayerInsert()
|
||||||
|
if turtle then
|
||||||
previousInventory = getTurtleInventory()
|
previousInventory = getTurtleInventory()
|
||||||
|
|
||||||
while true do
|
while true do
|
||||||
os.pullEvent("turtle_inventory")
|
os.pullEvent("turtle_inventory")
|
||||||
|
|
||||||
local currentInventory = getTurtleInventory()
|
local currentInventory = getTurtleInventory()
|
||||||
|
|
||||||
if turtleMoveAllowed then
|
if turtleMoveAllowed then
|
||||||
local newlyAddedSlots = {}
|
local newlyAddedSlots = {}
|
||||||
|
|
||||||
for slot = 1, 16 do
|
for slot = 1, 16 do
|
||||||
local prev = previousInventory[slot]
|
local prev = previousInventory[slot]
|
||||||
local curr = currentInventory[slot]
|
local curr = currentInventory[slot]
|
||||||
|
|
||||||
if not prev and curr then
|
if not prev and curr then
|
||||||
table.insert(newlyAddedSlots, slot)
|
table.insert(newlyAddedSlots, slot)
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
if #newlyAddedSlots > 0 then
|
|
||||||
sendItemAwayMultiple(newlyAddedSlots)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
previousInventory = currentInventory
|
if #newlyAddedSlots > 0 then
|
||||||
|
sendItemAwayMultiple(newlyAddedSlots)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
previousInventory = currentInventory
|
||||||
end
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function getAIL()
|
local function run()
|
||||||
return ail
|
return ail.run
|
||||||
end
|
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 {
|
return {
|
||||||
detectPlayerInsert = detectPlayerInsert,
|
detectPlayerInsert = detectPlayerInsert,
|
||||||
sendItemAwayMultiple = sendItemAwayMultiple,
|
sendItemAwayMultiple = sendItemAwayMultiple,
|
||||||
sendItemToSelf = sendItemToSelf,
|
sendItemToSelf = sendItemToSelf,
|
||||||
getTurtleInventory = getTurtleInventory,
|
getTurtleInventory = getTurtleInventory,
|
||||||
sync = sync,
|
listItemAmounts = listItemAmounts,
|
||||||
getAIL = getAIL,
|
listNames = listNames,
|
||||||
|
getItem = getItem,
|
||||||
|
sync = sync,
|
||||||
|
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 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
|
---@class RemoteAccess
|
||||||
---@field type string
|
---@field type string
|
||||||
---@field data RemoteAccessData
|
---@field data RemoteAccessData
|
||||||
|
|
@ -10,13 +16,34 @@ local hmac = require("lib.hmac-pbkdf2-aead")
|
||||||
---@field amount number|nil
|
---@field amount number|nil
|
||||||
---@field slots 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()
|
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)
|
local modem = peripheral.wrap(config.remote.modem)
|
||||||
if not modem then return end
|
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
|
if not modem.isOpen(remote.port) then
|
||||||
modem.open(remote.port)
|
modem.open(remote.port)
|
||||||
end
|
end
|
||||||
|
|
@ -28,10 +55,11 @@ local function run()
|
||||||
while true do
|
while true do
|
||||||
local _, _, channel, _, message, _ = os.pullEvent("modem_message")
|
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
|
if remote.port == channel then
|
||||||
|
local hashed = encryption.hashKey(remote.password)
|
||||||
local err, data = pcall(function()
|
local err, data = pcall(function()
|
||||||
return hmac.decrypt_with_password(remote.password, message)
|
return encryption.decrypt(hashed, message)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
if not data then return end
|
if not data then return end
|
||||||
|
|
@ -51,23 +79,82 @@ local function run()
|
||||||
colors[parts[3]]
|
colors[parts[3]]
|
||||||
)
|
)
|
||||||
if json.type == "withdraw" then
|
if json.type == "withdraw" then
|
||||||
inv.sendItemToSelf(json.data.itemName, config.remote.ender_storage, json.data.amount)
|
local ok, err = pcall(function()
|
||||||
elseif json.type == "deposit" then
|
inv.sendItemToSelf(
|
||||||
if json.data.itemName then
|
json.data.itemName,
|
||||||
local move = {}
|
config.remote.ender_storage,
|
||||||
for s, i in pairs(ender_storage.list()) do
|
json.data.amount
|
||||||
if i.name == json.data.itemName then
|
)
|
||||||
table.insert(move, s)
|
end)
|
||||||
end
|
|
||||||
end
|
|
||||||
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
|
|
||||||
end
|
|
||||||
|
|
||||||
inv.sendItemAwayMultiple(json.data.slots, ender_storage, config.remote.ender_storage, json.data.amount)
|
sendResponse(modem, remote.port, hashed, json.id, ok, nil, err)
|
||||||
end
|
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
|
||||||
|
if i.name == json.data.itemName then
|
||||||
|
table.insert(move, s)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
inv.sendItemAwayMultiple(
|
||||||
|
move,
|
||||||
|
ender_storage,
|
||||||
|
config.remote.ender_storage,
|
||||||
|
json.data.amount
|
||||||
|
)
|
||||||
|
elseif json.data.slots then
|
||||||
|
inv.sendItemAwayMultiple(
|
||||||
|
json.data.slots,
|
||||||
|
ender_storage,
|
||||||
|
config.remote.ender_storage,
|
||||||
|
json.data.amount
|
||||||
|
)
|
||||||
|
end
|
||||||
|
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
|
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 PrimeUI = require("lib.primeui").PrimeUI;
|
||||||
local function is_beta(ver)
|
local function is_beta(ver)
|
||||||
if ver:match("^[0-9a-f]+$") and #ver >= 8 then
|
if ver:match("^[0-9a-f]+$") and #ver >= 8 then
|
||||||
|
|
@ -12,9 +19,18 @@ local function run()
|
||||||
local win = term.current();
|
local win = term.current();
|
||||||
local w, h = term.getSize()
|
local w, h = term.getSize()
|
||||||
|
|
||||||
|
local items = inv.listItemAmounts()
|
||||||
|
local x = 0
|
||||||
|
|
||||||
local function getFiltered()
|
local function getFiltered()
|
||||||
local filtered = {}
|
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
|
if search == "" or string.find(name:lower(), search:lower(), 1, true) then
|
||||||
table.insert(filtered, { name = name, count = count })
|
table.insert(filtered, { name = name, count = count })
|
||||||
end
|
end
|
||||||
|
|
@ -25,7 +41,7 @@ local function run()
|
||||||
|
|
||||||
for i, filter in ipairs(filtered) do
|
for i, filter in ipairs(filtered) do
|
||||||
refiltered[i] = filter.name ..
|
refiltered[i] = filter.name ..
|
||||||
string.rep(" ", w - (2 + #filter.name + #tostring(filter.count))) .. tostring(filter.count)
|
string.rep(" ", w - (2 + #filter.name + #tostring(filter.count))) .. tostring(filter.count)
|
||||||
end
|
end
|
||||||
return refiltered
|
return refiltered
|
||||||
end
|
end
|
||||||
|
|
@ -40,8 +56,7 @@ local function run()
|
||||||
end,
|
end,
|
||||||
function(option)
|
function(option)
|
||||||
local z = option:match("^(%S+)")
|
local z = option:match("^(%S+)")
|
||||||
|
if inv.getItem(z) then
|
||||||
if inv.getAIL().getItem(z) then
|
|
||||||
inv.sendItemToSelf(z)
|
inv.sendItemToSelf(z)
|
||||||
end
|
end
|
||||||
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