Advertisement
Tatantyler

Remote Procedure Calls

Oct 26th, 2012
676
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 3.02 KB | None | 0 0
  1. local debug = false
  2. local trustedPull = os.pullEvent
  3. local trustedPullRaw = os.pullEventRaw
  4.  
  5. function doCall(id, func, ...)
  6.     if func ~= "new" and func ~= "loadAPI"  then
  7.         local argStr = ""
  8.         for i=1, #arg-1 do
  9.             if type(arg[i]) ~= "string" then
  10.                 argStr = argStr..textutils.serialize(arg[i])..", "
  11.             else
  12.                 argStr = argStr.."\""..arg[i].."\""..", "
  13.             end
  14.         end
  15.         if type(arg[#arg]) ~= "string" then
  16.             argStr = argStr..textutils.serialize(arg[#arg])
  17.         else
  18.             argStr = argStr.."\""..arg[#arg].."\""
  19.         end
  20.         if debug then
  21.             print("return rpc."..func.."("..argStr..")")
  22.         end
  23.         local fn, err = loadstring("return rpc."..func.."("..argStr..")")
  24.         if fn then
  25.             setfenv(fn, getfenv(2))
  26.             local pcall_return = {pcall(fn)}
  27.             if pcall_return[1] then
  28.                 local returns = {}
  29.                 for i=2, #pcall_return do
  30.                     table.insert(returns, pcall_return[i])
  31.                 end
  32.                 return returns
  33.             else
  34.                 if string.find(pcall_return[2], "attempt to call nil") ~= nil then
  35.                     return {"attempt to call nil"}
  36.                 elseif string.find(pcall_return[2], "attempt to call table") ~= nil then
  37.                     return {"attempt to call table"}
  38.                 else
  39.                     return {pcall_return[2]}
  40.                 end
  41.             end
  42.         else
  43.             return {err}
  44.         end
  45.     end
  46. end
  47.  
  48. function remoteCall(remoteID, remoteFunc, ...)
  49.     local msg = textutils.serialize({"rpc", "call", remoteFunc, unpack(arg)})
  50.     rednet.send(remoteID, msg)
  51.     local event, id, func, returns = os.pullEvent("rpc_return")
  52.     returns = textutils.unserialize(returns)
  53.     if id == remoteID and func == remoteFunc then
  54.         return unpack(returns)
  55.     end
  56. end
  57.  
  58. function broadcastRemoteCall(remoteID, remoteFunc, ...)
  59.     local msg = textutils.serialize({"rpc", "call", remoteFunc, unpack(arg)})
  60.     rednet.broadcast(msg)
  61. end
  62.  
  63. function setDebug(d)
  64.     debug = d
  65. end
  66.  
  67. function new(func, body)
  68.     if func ~= "doCall" and func ~= "remoteCall" and func ~= "new" and func ~= "loadAPI" and func ~= "run" then
  69.         if type(body) == "string" then
  70.             _G["rpc"][func] = loadstring(body)
  71.         elseif type(body) == "function" then
  72.             _G["rpc"][func] = body
  73.         else
  74.             error("Invalid function passed to rpc.new")
  75.         end
  76.     end
  77. end
  78.  
  79. function loadAPI(file)
  80.     local env = {}
  81.     setmetatable(env, {__index = _G})
  82.     local func, err = loadfile(file)
  83.     if func then
  84.         setfenv(func, env)
  85.         func()
  86.         local api = {}
  87.         for i,v in pairs(env) do
  88.             api[i] = v
  89.         end
  90.         rpc[fs.getName(file)] = api
  91.         return true
  92.     else
  93.         return false, err
  94.     end
  95. end
  96.  
  97. function run()
  98.     while true do
  99.         local event, id, msg = trustedPull("rednet_message")
  100.         msg = textutils.unserialize(msg)
  101.         if type(msg) == "table" then
  102.             if msg[1] == "rpc" then
  103.                 if msg[2] == "call" then
  104.                     local args = {}
  105.                     for i=4, #msg do
  106.                         table.insert(args, msg[i])
  107.                     end
  108.                     os.queueEvent("rpc_call", msg[3], args)
  109.                     local returns = doCall(id, msg[3], unpack(args))
  110.                     rednet.send(id, textutils.serialize({"rpc", "return", msg[3], returns}))
  111.                 elseif msg[2] == "return" then
  112.                     os.queueEvent("rpc_return", id, msg[3], textutils.serialize(msg[4]))
  113.                 end
  114.             end
  115.         end
  116.     end
  117. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement