neovariable2
Description
A collection of all my ComputerCraft programs and the APIs they use. This is mostly just to get them the fuck off of pastebin, and also to ensure that API owners don't change things to break my precious programs...!
Installation
Copy one of these commands into your ComputerCraft terminal:
wget:
wget https://raw.githubusercontent.com/LDDestroier/CC/master/neovariable2.lua neovariable2Archive:
wget https://cc.shobie.xyz/cc/get/gh-LDDestroier-CC-neovariable2 neovariable2
Quick Install:
wget https://cc.shobie.xyz/cc/get/gh-LDDestroier-CC-neovariable2 neovariable2
Usage
Run: neovariable2
Tags
Source
View Original SourceCode Preview
--[[
NewVariable 2 (WIP) by LDDestroier
Get with:
wget https://raw.githubusercontent.com/LDDestroier/CC/master/neovariable2.lua
To Do:
+ asymmetrical encryption (actually forget that, functions wouldn't work out)
+ work on stability
+ steal underpants
--]]
local tArg = {...}
local mode = tArg[1] -- "server" or "demo", otherwise works as API
if not peripheral.find("modem") then
ccemux.attach("top", "wireless_modem")
end
local makeMT = function(indexFunc, newindexFunc)
local output = {}
local _output = output
output = {}
local mt = {
__index = function(t, k)
if indexFunc then
return indexFunc(_output, k)
else
return _output[k]
end
end,
__newindex = function(t, k, v)
if newindexFunc then
_output[k] = newindexFunc(_output, k, v)
else
_output[k] = v
end
end
}
setmetatable(output, mt)
return output
end
-- information about the API
local nv = {
dir = { -- all DIRECTORIES will end with "/"
main = "neovariable", -- main directory where all neovariable stuff are
privateID = "private", -- private computer ID, protect with your life
publicID = "public", -- public computer ID, is shared all the time
config = "config", -- config options
api = "api/" -- where APIs are stored
},
envKey = 1, -- determines which environment to use
environment = {}, -- stores multiple environments
privateID = nil, -- every computer should have a secret, individual "ID"
publicID = nil, -- every computer should also have a public key
channel = 1002, -- modem channel
}
-- functions that are put in the api for use
local API = {}
for k,v in pairs(nv.dir) do
if k ~= "main" then
nv.dir[k] = fs.combine(nv.dir.main, v)
end
if (not fs.exists(v)) and v:sub(-1, -1) == "/" then
fs.makeDir(nv.dir[k])
end
end
local getID = function(path)
if fs.exists(path) then
local file = fs.open(path, "r")
local contents = file.readAll()
file.close()
return contents
else
return false
end
end
local makeNewID = function(path, _id)
local file = fs.open(path, "w")
if _id then
file.write(_id)
else
local id = ""
for i = 1, 256 do
id = id .. string.char(math.random(11, 127))
end
file.write(id)
end
file.close()
return id
end
nv.privateID, nv.publicID = getID(nv.dir.privateID), getID(nv.dir.publicID)
if not nv.privateID then
nv.privateID = makeNewID(nv.dir.privateID)
end
if not nv.publicID then
nv.publicID = makeNewID(nv.dir.publicID)
end
local getModem = function()
local m = peripheral.find("modem")
if m then
if not m.isOpen(nv.channel) then
m.open(nv.channel)
end
end
return m
end
local modem = getModem()
local send = function(envKey, cID, command, recipient, tbl, key, value)
modem.transmit(nv.channel, nv.channel, {
envKey = envKey,
command = command,
t = tbl,
k = key,
v = value,
publicID = nv.publicID,
cID = cID or math.random(1, 2^30),
recipient = recipient
})
end
-- easy way to view values
local debugErrorScreen = function(value)
term.setBackgroundColor(colors.black)
term.setTextColor(colors.white)
term.clear()
term.setCursorPos(1,1)
print(textutils.serialize(value))
term.setCursorPos(1, 18)
error()
end
local rawReceive = function(valueType, timeout)
local evt, tID
if timeout then
tID = os.startTimer(timeout)
end
repeat
evt = {os.pullEvent()}
until (
evt[1] == "modem_message" and type(evt[5]) == valueType
) or (
evt[1] == "timer" and evt[2] == tID
)
return evt[5]
end
local receive = function(envKey, cID, timeout)
local output
repeat
output = rawReceive("table", timeout)
until (output or {}).cID == cID or output == nil
return output
end
-- runs a neovariable server, and sets envList to the list of environments used
API.runServer = function( envList, verbose )
local evt, msg
while true do
repeat
repeat
evt = {os.pullEvent("modem_message")}
until type(evt[5]) == "table"
until evt[5].cID ~= nil
msg = evt[5]
if msg.command == "find" then
if verbose then print("got 'find' request") end
send(nil, msg.cID, "find_response", msg.publicID, nv.publicID)
elseif msg.command == "set" or msg.command == "get" then
if ( -- check the types of all the input
msg.envKey ~= nil and
type(msg.publicID) == "string" and
msg.k ~= nil and
msg.recipient == nv.publicID
) then
nv.environment[msg.publicID] = nv.environment[msg.publicID] or {}
nv.environment[msg.publicID][msg.envKey] = nv.environment[msg.publicID][msg.envKey] or {}
if msg.command == "set" then
if msg.v ~= nil then
if verbose then print("[" .. tostring(msg.envKey) .. "] " .. tostring(msg.k) .. " = " .. tostring(msg.v)) end
nv.environment[msg.publicID][msg.envKey][msg.k] = msg.v
end
elseif msg.command == "get" then
if verbose then print("[" .. tostring(msg.envKey) .. "] " .. tostring(msg.k)) end
send(msg.envKey, msg.cID, "get_response", msg.publicID, nv.environment[msg.publicID][msg.envKey][msg.k])
end
end
end
envList = nv.environment
end
end
API.findServer = function(getList, timeout)
timeout = tonumber(timeout) or 1
local cID = math.random(1, 2^30)
send(nil, cID, "find")
if getList then
local servers = {}
parallel.waitForAny(
function()
while true do
servers[#servers+1] = receive(nil, cID).publicID
end
end,
function()
sleep(timeout)
end
)
return servers
else
return (receive(nil, cID, timeout) or {}).publicID
end
end
API.newEnvironment = function(server, envKey)
assert(type(server) == "string", "server ID must be a string")
assert(envKey ~= nil, "envKey must not be nil")
return makeMT(
function(t, k)
local cID = math.random(1, 2^30)
send(envKey, cID, "get", server, t, k)
local response = receive(envKey, cID, 3)
if response then
return response.t
else
return nil, "no response"
end
end,
function(t, k, v)
local cID = math.random(1, 2^30)
send(envKey, cID, "set", server, t, k, v)
end
)
end
if mode == "server" then
API.runServer(nil, true)
elseif mode == "demo" then
local server = API.findServer(false, 1)
if server then
print("found server")
local noo = API.newEnvironment(server, 1)
local yoo = API.newEnvironment(server, 2)
print("made envs")
noo.hi = "what"
yoo.he = "bumbo"
print("set")
local var = noo.hi
local ver = yoo.he
print("get")
print("noo.hi = " .. tostring(noo.hi))
print("yoo.he = " .. tostring(yoo.he))
else
print("no neovariable server")
end
else
return API
end