SHARE
TWEET

Quest Server

Oeed Oct 24th, 2014 (edited) 2,162 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. --  Hideously Smashed Together by Compilr, a Hideous Smash-Stuff-Togetherer, (c) 2014 oeed  --
  2.  
  3. --  This file REALLLLLLLY isn't suitable to be used for anything other than being executed --
  4.  
  5. --  To extract all the files, run: "<filename> --extract" in the Shell --
  6. local files = {["Views"]={["toolbar.view"]="{\
  7.  [\"Width\"]=\"100%\",\
  8.  [\"Height\"]=3,\
  9.  [\"Type\"]=\"View\",\
  10.  [\"BackgroundColour\"]=128,\
  11.  [\"Children\"]={\
  12.    [1]={\
  13.      [\"Y\"]=2,\
  14.      [\"X\"]=2,\
  15.      [\"Name\"]=\"GoStopButton\",\
  16.      [\"Type\"]=\"Button\",\
  17.      [\"Text\"]=\">\",\
  18.      [\"BackgroundColour\"]=1,\
  19.      [\"TextColour\"]=128\
  20.    },\
  21.    [2]={\
  22.      [\"Y\"]=2,\
  23.      [\"X\"]=\"100%,-23\",\
  24.      [\"Name\"]=\"LogButton\",\
  25.      [\"Type\"]=\"Button\",\
  26.      [\"Text\"]=\"Log\",\
  27.      [\"BackgroundColour\"]=1,\
  28.      [\"TextColour\"]=128,\
  29.      [\"Toggle\"]=false\
  30.    },\
  31.    [3]={\
  32.      [\"Y\"]=2,\
  33.      [\"X\"]=\"100%,-17\",\
  34.      [\"Name\"]=\"SettingsButton\",\
  35.      [\"Type\"]=\"Button\",\
  36.      [\"Text\"]=\"Settings\",\
  37.      [\"BackgroundColour\"]=1,\
  38.      [\"TextColour\"]=128,\
  39.      [\"Toggle\"]=false\
  40.    },\
  41.    [4]={\
  42.      [\"Y\"]=2,\
  43.      [\"X\"]=\"100%,-6\",\
  44.      [\"Name\"]=\"QuitButton\",\
  45.      [\"Type\"]=\"Button\",\
  46.      [\"Text\"]=\"Quit\",\
  47.      [\"BackgroundColour\"]=1,\
  48.      [\"TextColour\"]=128\
  49.    },\
  50.    [5]={\
  51.      [\"Y\"]=2,\
  52.      [\"X\"]=6,\
  53.      [\"Name\"]=\"StatusLabel\",\
  54.      [\"Type\"]=\"Label\",\
  55.      [\"Text\"]=\"Stopped\",\
  56.      [\"TextColour\"]=1\
  57.    },\
  58.  },\
  59. }",["main.view"]="{\
  60.  [\"Children\"]={\
  61.    [1]={\
  62.      [\"Y\"]=1,\
  63.      [\"X\"]=1,\
  64.      [\"Name\"]=\"Toolbar\",\
  65.      [\"Type\"]=\"View\",\
  66.      [\"InheritView\"]=\"toolbar\"\
  67.    },\
  68.    [2]={\
  69.      [\"X\"]=1,\
  70.      [\"Y\"]=4,\
  71.      [\"Name\"]=\"SettingsView\",\
  72.      [\"Type\"]=\"SettingsView\",\
  73.      [\"Width\"]=\"100%\",\
  74.      [\"Height\"]=\"100%,-3\",\
  75.      [\"Visible\"]=false,\
  76.      [\"InheritView\"]=\"settings\"\
  77.    },\
  78.    [3]={\
  79.      [\"X\"]=1,\
  80.      [\"Y\"]=4,\
  81.      [\"Name\"]=\"LogView\",\
  82.      [\"Type\"]=\"LogView\",\
  83.      [\"Width\"]=\"100%\",\
  84.      [\"Height\"]=\"100%,-3\",\
  85.      [\"Visible\"]=false\
  86.    },\
  87.  },\
  88.  [\"BackgroundColour\"]=1,\
  89.  [\"ToolBarColour\"]=128,\
  90.  [\"ToolBarTextColour\"]=1\
  91. }",["nomodem.view"]="{\
  92.  [\"Children\"]={\
  93.    [1]={\
  94.      [\"Y\"]=\"50%,-2\",\
  95.      [\"X\"]=1,\
  96.      [\"Width\"]=\"100%\",\
  97.      [\"Type\"]=\"Label\",\
  98.      [\"Text\"]=\"No Modem Attached!\",\
  99.      [\"TextColour\"]=16384,\
  100.      [\"Align\"]=\"Center\"\
  101.    },\
  102.    [2]={\
  103.      [\"Y\"]=\"50%\",\
  104.      [\"X\"]=\"10%\",\
  105.      [\"Width\"]=\"80%\",\
  106.      [\"Type\"]=\"Label\",\
  107.      [\"Text\"]=\"Please attach a wireless modem to use Quest Server.\",\
  108.      [\"Align\"]=\"Center\"\
  109.    },\
  110.    [3]={\
  111.      [\"Y\"]=\"100%,-1\",\
  112.      [\"X\"]=\"100%,-6\",\
  113.      [\"Name\"]=\"QuitButton\",\
  114.      [\"Type\"]=\"Button\",\
  115.      [\"Text\"]=\"Quit\",\
  116.    },\
  117.  },\
  118.  [\"BackgroundColour\"]=1,\
  119.  [\"ToolBarColour\"]=128,\
  120.  [\"ToolBarTextColour\"]=1\
  121. }",["settings.view"]="{\
  122.  [\"Children\"]={\
  123.    [1]={\
  124.      [\"Y\"]=2,\
  125.      [\"X\"]=3,\
  126.      [\"Type\"]=\"Label\",\
  127.      [\"Text\"]=\"Server Address\",\
  128.      [\"TextColour\"]=128\
  129.    },\
  130.    [2]={\
  131.      [\"Y\"]=2,\
  132.      [\"X\"]=19,\
  133.      [\"Type\"]=\"Label\",\
  134.      [\"Text\"]=\"wifi://\",\
  135.      [\"TextColour\"]=256\
  136.    },\
  137.    [3]={\
  138.      [\"Y\"]=2,\
  139.      [\"X\"]=26,\
  140.      [\"Width\"]=20,\
  141.      [\"Name\"]=\"AddressTextBox\",\
  142.      [\"Type\"]=\"TextBox\",\
  143.      [\"Placeholder\"]=\"e.g. basesite\",\
  144.    },\
  145.    [4]={\
  146.      [\"Y\"]=5,\
  147.      [\"X\"]=3,\
  148.      [\"Width\"]=\"100%,-4\",\
  149.      [\"Type\"]=\"Label\",\
  150.      [\"Text\"]=\"Ok... so maybe there aren't that many settings. But hey, at least it's easy to use.\",\
  151.      [\"TextColour\"]=256\
  152.    },\
  153.    [5]={\
  154.      [\"Y\"]=9,\
  155.      [\"X\"]=3,\
  156.      [\"Type\"]=\"Label\",\
  157.      [\"Text\"]=\"Quest Server v1.0.0\",\
  158.    },\
  159.    [6]={\
  160.      [\"Y\"]=11,\
  161.      [\"X\"]=3,\
  162.      [\"Width\"]=\"100%,-4\",\
  163.      [\"Type\"]=\"Label\",\
  164.      [\"Text\"]=\"Quest and Quest Server were made by oeed using Bedrock, the source of all awesomeness. If you find a bug or have any questions give me a PM or post on the forum topic.\",\
  165.      [\"TextColour\"]=128\
  166.    },\
  167.  },\
  168. }",},["README.md"]="Quest-Server\
  169. ============\
  170. \
  171. A wireless modem based CCML server for Quest",["startup"]="local bedrockPath='' if OneOS then OneOS.LoadAPI('/System/API/Bedrock.lua', false)elseif fs.exists(bedrockPath..'/Bedrock')then os.loadAPI(bedrockPath..'/Bedrock')else if http then print('Downloading Bedrock...')local h=http.get('http://pastebin.com/raw.php?i=0MgKNqpN')if h then local f=fs.open(bedrockPath..'/Bedrock','w')f.write(h.readAll())f.close()h.close()os.loadAPI(bedrockPath..'/Bedrock')else error('Failed to download Bedrock. Is your internet working?') end else error('This program needs to download Bedrock to work. Please enable HTTP.') end end if Bedrock then Bedrock.BasePath = bedrockPath Bedrock.ProgramPath = shell.getRunningProgram() end\
  172. \
  173. local program = Bedrock:Initialise()\
  174. \
  175. os.loadAPI(program.ProgramPath .. '/APIs/Peripheral')\
  176. os.loadAPI(program.ProgramPath .. '/APIs/Wireless')\
  177. \
  178. local serverRunning = false\
  179. \
  180. local messageLevel = {\
  181.         Info    = 'Info',\
  182.         Success = 'Success',\
  183.         Warning = 'Warning',\
  184.         Error   = 'Error',\
  185. }\
  186. \
  187. local function logMsg(msg, level)\
  188.         level = level or messageLevel.Info\
  189.         program:GetObject('LogView'):AddItem('[' .. level .. '] '..msg, level)\
  190. end\
  191. \
  192. local defaultSettings = {\
  193.         address = nil\
  194. }\
  195. \
  196. local settings = {}\
  197. \
  198. local function saveSettings()\
  199.         logMsg('Saving settings.')\
  200.         local f = fs.open('.QuestServer.settings', 'w')\
  201.         settings.address = program:GetObject('AddressTextBox').Text\
  202.         if f then\
  203.                 f.write(textutils.serialize(settings))\
  204.                 f.close()\
  205.         end\
  206. end\
  207. \
  208. local function loadSettings()\
  209.         logMsg('Loading settings.')\
  210.         local f = fs.open('.QuestServer.settings', 'r')\
  211.         if f then\
  212.                 settings = textutils.unserialize(f.readAll())\
  213.                 f.close()\
  214.         else\
  215.                 logMsg('No settings file, using default.', messageLevel.Warning)\
  216.                 settings = defaultSettings\
  217.                 saveSettings()\
  218.         end\
  219. \
  220.         program:GetObject('AddressTextBox').Text = settings.address or ''\
  221. end\
  222. \
  223. local function switchView(name)\
  224.         local viewNames = {\
  225.                 'Settings',\
  226.                 'Log',\
  227.         }\
  228. \
  229.         for i, v in ipairs(viewNames) do\
  230.                 if name == v then\
  231.                         program:GetObject(v .. 'View').Visible = true\
  232.                         program:GetObject(v .. 'Button').Toggle = true\
  233.                 else\
  234.                         program:GetObject(v .. 'View').Visible = false\
  235.                         program:GetObject(v .. 'Button').Toggle = false\
  236.                 end\
  237.         end\
  238. \
  239.         program:SetActiveObject()\
  240. end\
  241. \
  242. local availableTimer = nil\
  243. \
  244. local startServer = nil\
  245. local stopServer = nil\
  246. \
  247. local function checkNameAvailable(name)\
  248.         logMsg('Checking address clashes: '..name)\
  249.         if name:match(\"%W\") then\
  250.                 logMsg('Invalid address!', messageLevel.Error)\
  251.                 stopServer('Invalid Address')\
  252.                 switchView('Settings')\
  253.         else\
  254.                 Wireless.SendMessage(Wireless.Channels.QuestServerNameAvailable, name)\
  255.                 availableTimer = program:StartTimer(function()\
  256.                         if availableTimer and name == settings.address then\
  257.                                 logMsg('No address clashes found!', messageLevel.Success)\
  258.                                 availableTimer = nil\
  259.                                 startServer(true)\
  260.                         end\
  261.                 end, 1)\
  262.         end\
  263. end\
  264. \
  265. function stopServer(reason)\
  266.         logMsg('Stopping server: ' .. reason or 'Stopped', messageLevel.Warning)\
  267.         serverRunning = false\
  268.         program:GetObject('GoStopButton').Text = '>'\
  269.         program:GetObject('StatusLabel').Text = reason or 'Stopped'\
  270. end\
  271. \
  272. function startServer(available)\
  273.         logMsg('Starting server...')\
  274.         if settings.address and #settings.address > 0 then\
  275.                 if available then\
  276.                         logMsg('Server started!', messageLevel.Success)\
  277.                         serverRunning = true\
  278.                         program:GetObject('GoStopButton').Text = 'x'\
  279.                         program:GetObject('StatusLabel').Text = 'Running'\
  280.                 else\
  281.                         program:GetObject('StatusLabel').Text = 'Checking Name'\
  282.                         checkNameAvailable(settings.address)\
  283.                 end\
  284.         else\
  285.                 logMsg('Server could not start, address not set!', messageLevel.Error)\
  286.                 stopServer('Address Not Set')\
  287.                 switchView('Settings')\
  288.         end\
  289. end\
  290. \
  291. program.OnKeyChar = function(self, event, keychar)\
  292.         if keychar == '\\\\' then\
  293.                 os.reboot()\
  294.         end\
  295. end\
  296. \
  297. program:RegisterEvent('modem_message', function(self, event, side, channel, replyChannel, message, distance)\
  298.         Wireless.HandleMessage(event, side, channel, replyChannel, message, distance)\
  299. end)\
  300. \
  301. local function split(str, pat)\
  302.   local t = {}\
  303.   local fpat = \"(.-)\" .. pat\
  304.   local last_end = 1\
  305.   local s, e, cap = str:find(fpat, 1)\
  306.   while s do\
  307.      if s ~= 1 or cap ~= \"\" then\
  308.          table.insert(t,cap)\
  309.      end\
  310.      last_end = e+1\
  311.      s, e, cap = str:find(fpat, last_end)\
  312.   end\
  313.   if last_end <= #str then\
  314.      cap = str:sub(last_end)\
  315.      table.insert(t, cap)\
  316.   end\
  317.   return t\
  318. end\
  319. \
  320. local function findLast(haystack, needle)\
  321.    local i=haystack:match(\".*\"..needle..\"()\")\
  322.    if i==nil then return nil else return i-1 end\
  323. end\
  324. \
  325. local hex_to_char = function(x)\
  326.  return string.char(tonumber(x, 16))\
  327. end\
  328. \
  329. local function urlUnencode( str )\
  330.         -- essentially reverses textutils.urlDecode\
  331.    if str then\
  332.        str = string.gsub(str, \"+\", \" \")\
  333.        str = string.gsub(str, \"\\r\\n\", \"\\n\")\
  334.        term.setTextColor(colors.black)\
  335.        str = str:gsub(\"%%(%x%x)\", hex_to_char)\
  336.    end\
  337.    return str    \
  338. end\
  339. \
  340. local function urlComponents(url)\
  341.         if url then\
  342.                 urlUnencode(textutils.urlEncode(url))\
  343.                 local components = {}\
  344.                 local parts = split(url, '[\\\\/]+')\
  345.                 if url:find('://') and parts[1]:sub(#parts[1]) == ':' then\
  346.                         components.protocol = parts[1]:sub(1, #parts[1]-1)\
  347.                         components.sansprotocol = url:sub(#components.protocol + 4)\
  348.                         components.host = parts[2]\
  349.                         components.fullhost = components.protocol .. '://' .. parts[2] .. '/'\
  350.                         components.filename = fs.getName(url)\
  351.                         components.filepath = url:sub(#components.fullhost)\
  352.                         if components.filename == components.host then\
  353.                                 components.filename = ''\
  354.                         end\
  355.                         components.base = url:sub(1, findLast(url, '/'))\
  356.                         components.get = {}\
  357.                         components.filepathsansget = components.sansprotocol\
  358.                         if url:find('?') then\
  359.                                 local start = url:find('?')\
  360.                                 components.filepathsansget = url:sub(#components.protocol + 4, start - 1)\
  361.                                 local getString = url:sub(start + 1)\
  362.                                 local values = split(getString, '&')\
  363.                                 for i, v in ipairs(values) do\
  364.                                         local keyvalue = split(v, '=')\
  365.                                         components.get[keyvalue[1]] =  urlUnencode(keyvalue[2])\
  366.                                 end\
  367.                         end\
  368.                         return components\
  369.                 end\
  370.         end\
  371. end\
  372. \
  373. local function resolveFile(path)\
  374.         local parts = split(path, '[\\\\/]+')\
  375.         local realPath = '/Server Files'\
  376.         if #parts == 0 then\
  377.                 parts = {''}\
  378.         end\
  379.         for i, v in ipairs(parts) do\
  380.                 local tmpPath\
  381.                 if #v == 0 then\
  382.                         tmpPath = realPath\
  383.                 else\
  384.                         tmpPath = realPath .. '/' ..v\
  385.                 end\
  386.                 if fs.exists(tmpPath) then\
  387.                         if fs.isDir(tmpPath) and i == #parts then\
  388.                                 local attempts = {\
  389.                                         tmpPath .. '/index.ccml',\
  390.                                         tmpPath .. '/index.html',\
  391.                                 }\
  392. \
  393.                                 for i2, v2 in ipairs(attempts) do\
  394.                                         if fs.exists(v2) then\
  395.                                                 return v2\
  396.                                         end\
  397.                                 end\
  398.                                 return nil\
  399.                         end\
  400.                         realPath = tmpPath\
  401.                 else\
  402.                         return nil\
  403.                 end\
  404.         end\
  405.         return realPath\
  406. end\
  407. \
  408. Wireless.Responder = function(event, side, channel, replyChannel, message, distance)\
  409.         if channel == Wireless.Channels.QuestServerRequest and serverRunning then\
  410.                 if message.content:find('wifi://') == 1 then\
  411.                         local parts = urlComponents(message.content)\
  412.                         if parts.host and parts.host == settings.address then\
  413.                                 local path = resolveFile(parts.filepath)\
  414.                                 local content\
  415.                                 if path then\
  416.                                         local f = fs.open(path, 'r')\
  417.                                         if f then\
  418.                                                 content = f.readAll()\
  419.                                                 logMsg('File request successful: '..message.content, messageLevel.Success)\
  420.                                         end\
  421.                                 end\
  422.                                 if not content then\
  423.                                         logMsg('File request failed: '..message.content, messageLevel.Warning)\
  424.                                 end\
  425.                                 Wireless.SendMessage(replyChannel, {url = message.content, content = content}, nil, message.messageID)\
  426.                         end\
  427.                 end\
  428.         elseif channel == Wireless.Channels.QuestServerNameAvailable then\
  429.                 if message.content == settings.address then\
  430.                         logMsg('External address clash request clashed with this server: '..message.content, messageLevel.Warning)\
  431.                         Wireless.SendMessage(replyChannel, 'IN_USE', nil, message.messageID)\
  432.                 end\
  433.         elseif channel == Wireless.Channels.QuestServerNameAvailableReply and running then\
  434.                 availableTimer = nil\
  435.                 logMsg('Address clash request failed, address in use: '..message.content, messageLevel.Error)\
  436.                 stopServer('Address In Use')\
  437.                 switchView('Settings')\
  438.         end\
  439. end\
  440. \
  441. local debounce = nil\
  442. \
  443. program.OnTimer = function(self, event, timer)\
  444.         if timer == debounce then\
  445.                 saveSettings()\
  446.         end\
  447. end\
  448. \
  449. program:Run(function()\
  450.         if Wireless.Present() then\
  451.                 program:LoadView('main')\
  452. \
  453.                 if not fs.exists('/Server Files/') then\
  454.                         fs.makeDir('/Server Files/')\
  455.                         local f = fs.open('/Server Files/index.ccml', 'w')\
  456.                         if f then\
  457.                                 f.write([[<!DOCTYPE ccml>\
  458. <html>\
  459.    <head>\
  460.        <title>Welcome to your Quest Server Website!</title>\
  461.    </head>\
  462. \
  463.    <body>\
  464.        <br>\
  465.        <h colour=\"green\">Welcome to your Quest Server Website!</h>\
  466.        <br>\
  467.        <center>\
  468.                 <p width=\"46\" align=\"center\">\
  469.                     The files for this website are stored in the /Server Files/ folder on the server.\
  470.                 </p>\
  471.                 <br>\
  472.                 <p width=\"46\" align=\"center\">\
  473.                     If you haven't made a Quest web page before you should look for the CCML tutorial on the ComputerCraft forums.\
  474.                 </p>\
  475.        </center>\
  476.    </body>\
  477. </html>]])\
  478.                                 f.close()\
  479.                         end\
  480.                 end\
  481. \
  482.                 loadSettings()\
  483.                 Wireless.Initialise()\
  484. \
  485.                 switchView('Log')\
  486.                 startServer()\
  487. \
  488.                 program:GetObject('SettingsButton').OnClick = function(self, event, side, x, y)\
  489.                         switchView('Settings')\
  490.                 end\
  491. \
  492.                 program:GetObject('LogButton').OnClick = function(self, event, side, x, y)\
  493.                         switchView('Log')\
  494.                 end\
  495. \
  496.                 program:GetObject('GoStopButton').OnClick = function(self, event, side, x, y)\
  497.                         if serverRunning then\
  498.                                 stopServer()\
  499.                         else\
  500.                                 startServer()\
  501.                         end\
  502.                 end\
  503. \
  504.                 program:GetObject('AddressTextBox').OnChange = function(self, event, keychar)\
  505.                         if settings.address ~= program:GetObject('AddressTextBox').Text then\
  506.                                 stopServer('Address Changed')\
  507.                                 debounce = os.startTimer(1)\
  508.                         end\
  509.                 end\
  510. \
  511.         else\
  512.                 program:LoadView('nomodem')\
  513.         end\
  514. \
  515.         program:GetObject('QuitButton').OnClick = function(self, event, side, x, y)\
  516.                 term.setBackgroundColour(colours.black)\
  517.                 term.setTextColor(colours.white)\
  518.                 term.clear()\
  519.                 term.setCursorPos(1, 1)\
  520.                 print('Thanks for using Quest Server by oeed')\
  521.                 program:Quit()\
  522.         end\
  523. end)",["Objects"]={["SettingsView.lua"]="Inherit = 'View'",["LogView.lua"]="Inherit = 'View'\
  524. Log = nil\
  525. \
  526. SaveLog = function(self)\
  527.         local str = table.concat(self.Log, '\\n')\
  528.         local f = fs.open('QuestServer.log', 'w')\
  529.         if f then\
  530.                 f.write(str)\
  531.                 f.close()\
  532.         end\
  533. end\
  534. \
  535. AddItem = function(self, str, level)\
  536.         local messageColours = {\
  537.                 Info    = colours.blue,\
  538.                 Success = colours.green,\
  539.                 Warning = colours.orange,\
  540.                 Error   = colours.red,\
  541.         }\
  542.         table.insert(self.Log, str)\
  543. \
  544.         local y = 1\
  545. \
  546.         for i, v in ipairs(self.Children) do\
  547.                 y = y + v.Height\
  548.         end\
  549. \
  550.         self:AddObject({\
  551.                 X = 1,\
  552.                 Y = y,\
  553.                 Width = \"100%\",\
  554.                 Type = 'Label',\
  555.                 Text = str,\
  556.                 TextColour = messageColours[level]\
  557.         })\
  558.         \
  559.         self:SaveLog()\
  560. end\
  561. \
  562. OnLoad = function(self)\
  563.         self.Log = {}\
  564. end",},["APIs"]={["Peripheral"]="GetPeripheral = function(_type)\
  565.         for i, p in ipairs(GetPeripherals()) do\
  566.                 if p.Type == _type then\
  567.                         return p\
  568.                 end\
  569.         end\
  570. end\
  571. \
  572. Call = function(type, ...)\
  573.         local tArgs = {...}\
  574.         local p = GetPeripheral(type)\
  575.         peripheral.call(p.Side, unpack(tArgs))\
  576. end\
  577. \
  578. local getNames = peripheral.getNames or function()\
  579.         local tResults = {}\
  580.         for n,sSide in ipairs( rs.getSides() ) do\
  581.                 if peripheral.isPresent( sSide ) then\
  582.                         table.insert( tResults, sSide )\
  583.                         local isWireless = false\
  584.                         if pcall(function()isWireless = peripheral.call(sSide, 'isWireless') end) then\
  585.                                 isWireless = true\
  586.                         end     \
  587.                         if peripheral.getType( sSide ) == \"modem\" and not isWireless then\
  588.                                 local tRemote = peripheral.call( sSide, \"getNamesRemote\" )\
  589.                                 for n,sName in ipairs( tRemote ) do\
  590.                                         table.insert( tResults, sName )\
  591.                                 end\
  592.                         end\
  593.                 end\
  594.         end\
  595.         return tResults\
  596. end\
  597. \
  598. GetPeripherals = function(filterType)\
  599.         local peripherals = {}\
  600.         for i, side in ipairs(getNames()) do\
  601.                 local name = peripheral.getType(side):gsub(\"^%l\", string.upper)\
  602.                 local code = string.upper(side:sub(1,1))\
  603.                 if side:find('_') then\
  604.                         code = side:sub(side:find('_')+1)\
  605.                 end\
  606. \
  607.                 local dupe = false\
  608.                 for i, v in ipairs(peripherals) do\
  609.                         if v[1] == name .. ' ' .. code then\
  610.                                 dupe = true\
  611.                         end\
  612.                 end\
  613. \
  614.                 if not dupe then\
  615.                         local _type = peripheral.getType(side)\
  616.                         local formattedType = _type:sub(1, 1):upper() .. _type:sub(2, -1)\
  617.                         local isWireless = false\
  618.                         if _type == 'modem' then\
  619.                                 if not pcall(function()isWireless = peripheral.call(side, 'isWireless') end) then\
  620.                                         isWireless = true\
  621.                                 end     \
  622.                                 if isWireless then\
  623.                                         _type = 'wireless_modem'\
  624.                                         formattedType = 'Wireless Modem'\
  625.                                         name = 'W '..name\
  626.                                 end\
  627.                         end\
  628.                         if not filterType or _type == filterType then\
  629.                                 table.insert(peripherals, {Name = name:sub(1,8) .. ' '..code, Fullname = name .. ' ('..side:sub(1, 1):upper() .. side:sub(2, -1)..')', Side = side, Type = _type, Wireless = isWireless, FormattedType = formattedType})\
  630.                         end\
  631.                 end\
  632.         end\
  633.         return peripherals\
  634. end\
  635. \
  636. GetSide = function(side)\
  637.         for i, p in ipairs(GetPeripherals()) do\
  638.                 if p.Side == side then\
  639.                         return p\
  640.                 end\
  641.         end\
  642. end\
  643. \
  644. PresentNamed = function(name)\
  645.         return peripheral.isPresent(name)\
  646. end\
  647. \
  648. CallType = function(type, ...)\
  649.         local tArgs = {...}\
  650.         local p = GetPeripheral(type)\
  651.         return peripheral.call(p.Side, unpack(tArgs))\
  652. end\
  653. \
  654. CallNamed = function(name, ...)\
  655.         local tArgs = {...}\
  656.         return peripheral.call(name, unpack(tArgs))\
  657. end\
  658. \
  659. GetInfo = function(p)\
  660.         local info = {}\
  661.         local buttons = {}\
  662.         if p.Type == 'computer' then\
  663.                 local id = peripheral.call(p.Side:lower(),'getID')\
  664.                 if id then\
  665.                         info = {\
  666.                                 ID = tostring(id)\
  667.                         }\
  668.                 else\
  669.                         info = {}\
  670.                 end\
  671.         elseif p.Type == 'drive' then\
  672.                 local discType = 'No Disc'\
  673.                 local discID = nil\
  674.                 local mountPath = nil\
  675.                 local discLabel = nil\
  676.                 local songName = nil\
  677.                 if peripheral.call(p.Side:lower(), 'isDiskPresent') then\
  678.                         if peripheral.call(p.Side:lower(), 'hasData') then\
  679.                                 discType = 'Data'\
  680.                                 discID = peripheral.call(p.Side:lower(), 'getDiskID')\
  681.                                 if discID then\
  682.                                         discID = tostring(discID)\
  683.                                 else\
  684.                                         discID = 'None'\
  685.                                 end\
  686.                                 mountPath = '/'..peripheral.call(p.Side:lower(), 'getMountPath')..'/'\
  687.                                 discLabel = peripheral.call(p.Side:lower(), 'getDiskLabel')\
  688.                         else\
  689.                                 discType = 'Audio'\
  690.                                 songName = peripheral.call(p.Side:lower(), 'getAudioTitle')\
  691.                         end\
  692.                 end\
  693.                 if mountPath then\
  694.                         table.insert(buttons, {Text = 'View Files', OnClick = function(self, event, side, x, y)GoToPath(mountPath)end})\
  695.                 elseif discType == 'Audio' then\
  696.                         table.insert(buttons, {Text = 'Play', OnClick = function(self, event, side, x, y)\
  697.                                 if self.Text == 'Play' then\
  698.                                         disk.playAudio(p.Side:lower())\
  699.                                         self.Text = 'Stop'\
  700.                                 else\
  701.                                         disk.stopAudio(p.Side:lower())\
  702.                                         self.Text = 'Play'\
  703.                                 end\
  704.                         end})\
  705.                 else\
  706.                         diskOpenButton = nil\
  707.                 end\
  708.                 if discType ~= 'No Disc' then\
  709.                         table.insert(buttons, {Text = 'Eject', OnClick = function(self, event, side, x, y)disk.eject(p.Side:lower()) sleep(0) RefreshFiles() end})\
  710.                 end\
  711. \
  712.                 info = {\
  713.                         ['Disc Type'] = discType,\
  714.                         ['Disc Label'] = discLabel,\
  715.                         ['Song Title'] = songName,\
  716.                         ['Disc ID'] = discID,\
  717.                         ['Mount Path'] = mountPath\
  718.                 }\
  719.         elseif p.Type == 'printer' then\
  720.                 local pageSize = 'No Loaded Page'\
  721.                 local _, err = pcall(function() return tostring(peripheral.call(p.Side:lower(), 'getPgaeSize')) end)\
  722.                 if not err then\
  723.                         pageSize = tostring(peripheral.call(p.Side:lower(), 'getPageSize'))\
  724.                 end\
  725.                 info = {\
  726.                         ['Paper Level'] = tostring(peripheral.call(p.Side:lower(), 'getPaperLevel')),\
  727.                         ['Paper Size'] = pageSize,\
  728.                         ['Ink Level'] = tostring(peripheral.call(p.Side:lower(), 'getInkLevel'))\
  729.                 }\
  730.         elseif p.Type == 'modem' then\
  731.                 info = {\
  732.                         ['Connected Peripherals'] = tostring(#peripheral.call(p.Side:lower(), 'getNamesRemote'))\
  733.                 }\
  734.         elseif p.Type == 'monitor' then\
  735.                 local w, h = peripheral.call(p.Side:lower(), 'getSize')\
  736.                 local screenType = 'Black and White'\
  737.                 if peripheral.call(p.Side:lower(), 'isColour') then\
  738.                         screenType = 'Colour'\
  739.                 end\
  740.                 local buttonTitle = 'Use as Screen'\
  741.                 if OneOS.Settings:GetValues()['Monitor'] == p.Side:lower() then\
  742.                         buttonTitle = 'Use Computer Screen'\
  743.                 end\
  744.                 table.insert(buttons, {Text = buttonTitle, OnClick = function(self, event, side, x, y)\
  745.                                 self.Bedrock:DisplayAlertWindow('Reboot Required', \"To change screen you'll need to reboot your computer.\", {'Reboot', 'Cancel'}, function(value)\
  746.                                         if value == 'Reboot' then\
  747.                                                 if buttonTitle == 'Use Computer Screen' then\
  748.                                                         OneOS.Settings:SetValue('Monitor', nil)\
  749.                                                 else\
  750.                                                         OneOS.Settings:SetValue('Monitor', p.Side:lower())\
  751.                                                 end\
  752.                                                 OneOS.Reboot()\
  753.                                         end\
  754.                                 end)\
  755.                         end\
  756.                 })\
  757.                 info = {\
  758.                         ['Type'] = screenType,\
  759.                         ['Width'] = tostring(w),\
  760.                         ['Height'] = tostring(h),\
  761.                 }\
  762.         end\
  763.         info.Buttons = buttons\
  764.         return info\
  765. end",["Wireless"]="--This is just the OneOS Wireless API\
  766. \
  767. --OneOS uses channels between 4200 and 4300, avoid use where possible\
  768. \
  769. Channels = {\
  770.         Ignored = 4299,\
  771.         Ping = 4200,\
  772.         PingReply = 4201,\
  773.         QuestServerRequest = 4250,\
  774.         QuestServerRequestReply = 4251,\
  775.         QuestServerNameAvailable = 4252,\
  776.         QuestServerNameAvailableReply = 4253,\
  777. }\
  778. \
  779. local function isOpen(channel)\
  780.         return Peripheral.CallType('wireless_modem', 'isOpen', channel)\
  781. end\
  782. \
  783. local function open(channel)\
  784.         if not isOpen(channel) then\
  785.                 Peripheral.CallType('wireless_modem', 'open', channel)\
  786.         end\
  787. end\
  788. \
  789. Open = open\
  790. \
  791. local function close(channel)\
  792.         Peripheral.CallType('wireless_modem', 'close', channel)\
  793. end\
  794. \
  795. local function closeAll()\
  796.         Peripheral.CallType('wireless_modem', 'closeAll')\
  797. end\
  798. \
  799. local function transmit(channel, replyChannel, message)\
  800.         Peripheral.CallType('wireless_modem', 'transmit', channel, replyChannel, textutils.serialize(message))\
  801. end\
  802. \
  803. function Present()\
  804.         if Peripheral.GetPeripheral('wireless_modem') == nil then\
  805.                 return false\
  806.         else\
  807.                 return true\
  808.         end\
  809. end\
  810. \
  811. local function FormatMessage(message, messageID, destinationID)\
  812.         return {\
  813.                 content = textutils.serialize(message),\
  814.                 senderID = os.getComputerID(),\
  815.                 senderName = os.getComputerLabel(),\
  816.                 channel = channel,\
  817.                 replyChannel = reply,\
  818.                 messageID = messageID or math.random(10000),\
  819.                 destinationID = destinationID\
  820.         }\
  821. end\
  822. \
  823. local Timeout = function(func, time)\
  824.         time = time or 1\
  825.         parallel.waitForAny(func, function()\
  826.                 sleep(time)\
  827.                 --log('Timeout!'..time)\
  828.         end)\
  829. end\
  830. \
  831. RecieveMessage = function(_channel, messageID, timeout)\
  832.         open(_channel)\
  833.         local done = false\
  834.         local event, side, channel, replyChannel, message = nil\
  835.         Timeout(function()\
  836.                 while not done do\
  837.                         event, side, channel, replyChannel, message = os.pullEvent('modem_message')\
  838.                         if channel ~= _channel then\
  839.                                 event, side, channel, replyChannel, message = nil\
  840.                         else\
  841.                                 message = textutils.unserialize(message)\
  842.                                 message.content = textutils.unserialize(message.content)\
  843.                                 if messageID and messageID ~= message.messageID or (message.destinationID ~= nil and message.destinationID ~= os.getComputerID()) then\
  844.                                         event, side, channel, replyChannel, message = nil\
  845.                                 else\
  846.                                         done = true\
  847.                                 end\
  848.                         end\
  849.                 end\
  850.         end,\
  851.         timeout)\
  852.         return event, side, channel, replyChannel, message\
  853. end\
  854. \
  855. Initialise = function()\
  856.         if Present() then\
  857.                 for i, c in pairs(Channels) do\
  858.                         open(c)\
  859.                 end\
  860.         end\
  861. end\
  862. \
  863. HandleMessage = function(event, side, channel, replyChannel, message, distance)\
  864.         message = textutils.unserialize(message)\
  865.         message.content = textutils.unserialize(message.content)\
  866. \
  867.         if channel == Channels.Ping then\
  868.                 if message.content == 'Ping!' then\
  869.                         SendMessage(replyChannel, 'Pong!', nil, message.messageID)\
  870.                 end\
  871.         elseif message.destinationID ~= nil and message.destinationID ~= os.getComputerID() then\
  872.         elseif Wireless.Responder then\
  873.                 Wireless.Responder(event, side, channel, replyChannel, message, distance)\
  874.         end\
  875. end\
  876. \
  877. SendMessage = function(channel, message, reply, messageID, destinationID)\
  878.         reply = reply or channel + 1\
  879.         open(channel)\
  880.         open(reply)\
  881.         local _message = FormatMessage(message, messageID, destinationID)\
  882.         transmit(channel, reply, _message)\
  883.         return _message\
  884. end\
  885. \
  886. Ping = function()\
  887.         local message = SendMessage(Channels.Ping, 'Ping!', Channels.PingReply)\
  888.         RecieveMessage(Channels.PingReply, message.messageID)\
  889. end",},}
  890.  
  891. local function run(tArgs)
  892.  
  893.   local fnFile, err = loadstring(files['startup'], 'startup')
  894.   if err then
  895.     error(err)
  896.   end
  897.  
  898.   local function split(str, pat)
  899.      local t = {}
  900.      local fpat = "(.-)" .. pat
  901.      local last_end = 1
  902.      local s, e, cap = str:find(fpat, 1)
  903.      while s do
  904.         if s ~= 1 or cap ~= "" then
  905.      table.insert(t,cap)
  906.         end
  907.         last_end = e+1
  908.         s, e, cap = str:find(fpat, last_end)
  909.      end
  910.      if last_end <= #str then
  911.         cap = str:sub(last_end)
  912.         table.insert(t, cap)
  913.      end
  914.      return t
  915.   end
  916.  
  917.   local function resolveTreeForPath(path, single)
  918.     local _files = files
  919.     local parts = split(path, '/')
  920.     if parts then
  921.       for i, v in ipairs(parts) do
  922.         if #v > 0 then
  923.           if _files[v] then
  924.             _files = _files[v]
  925.           else
  926.             _files = nil
  927.             break
  928.           end
  929.         end
  930.       end
  931.     elseif #path > 0 and path ~= '/' then
  932.       _files = _files[path]
  933.     end
  934.     if not single or type(_files) == 'string' then
  935.       return _files
  936.     end
  937.   end
  938.  
  939.   local oldFs = fs
  940.   local env
  941.   env = {
  942.     fs = {
  943.       list = function(path)
  944.               local list = {}
  945.               if fs.exists(path) then
  946.             list = fs.list(path)
  947.               end
  948.         for k, v in pairs(resolveTreeForPath(path)) do
  949.           if not fs.exists(path .. '/' ..k) then
  950.             table.insert(list, k)
  951.           end
  952.         end
  953.         return list
  954.       end,
  955.  
  956.       exists = function(path)
  957.         if fs.exists(path) then
  958.           return true
  959.         elseif resolveTreeForPath(path) then
  960.           return true
  961.         else
  962.           return false
  963.         end
  964.       end,
  965.  
  966.       isDir = function(path)
  967.         if fs.isDir(path) then
  968.           return true
  969.         else
  970.           local tree = resolveTreeForPath(path)
  971.           if tree and type(tree) == 'table' then
  972.             return true
  973.           else
  974.             return false
  975.           end
  976.         end
  977.       end,
  978.  
  979.       isReadOnly = function(path)
  980.         if not fs.isReadOnly(path) then
  981.           return false
  982.         else
  983.           return true
  984.         end
  985.       end,
  986.  
  987.       getName = fs.getName,
  988.  
  989.       getSize = fs.getSize,
  990.  
  991.       getFreespace = fs.getFreespace,
  992.  
  993.       makeDir = fs.makeDir,
  994.  
  995.       move = fs.move,
  996.  
  997.       copy = fs.copy,
  998.  
  999.       delete = fs.delete,
  1000.  
  1001.       combine = fs.combine,
  1002.  
  1003.       open = function(path, mode)
  1004.         if fs.exists(path) then
  1005.           return fs.open(path, mode)
  1006.         elseif type(resolveTreeForPath(path)) == 'string' then
  1007.           local handle = {close = function()end}
  1008.           if mode == 'r' then
  1009.             local content = resolveTreeForPath(path)
  1010.             handle.readAll = function()
  1011.               return content
  1012.             end
  1013.  
  1014.             local line = 1
  1015.             local lines = split(content, '\n')
  1016.             handle.readLine = function()
  1017.               if line > #lines then
  1018.                 return nil
  1019.               else
  1020.                 return lines[line]
  1021.               end
  1022.               line = line + 1
  1023.             end
  1024.                       return handle
  1025.           else
  1026.             error('Cannot write to read-only file (compilr archived).')
  1027.           end
  1028.         else
  1029.           return fs.open(path, mode)
  1030.         end
  1031.       end
  1032.     },
  1033.  
  1034.     loadfile = function( _sFile )
  1035.         local file = env.fs.open( _sFile, "r" )
  1036.         if file then
  1037.             local func, err = loadstring( file.readAll(), fs.getName( _sFile ) )
  1038.             file.close()
  1039.             return func, err
  1040.         end
  1041.         return nil, "File not found: ".._sFile
  1042.     end,
  1043.  
  1044.     dofile = function( _sFile )
  1045.         local fnFile, e = env.loadfile( _sFile )
  1046.         if fnFile then
  1047.             setfenv( fnFile, getfenv(2) )
  1048.             return fnFile()
  1049.         else
  1050.             error( e, 2 )
  1051.         end
  1052.     end
  1053.   }
  1054.  
  1055.   setmetatable( env, { __index = _G } )
  1056.  
  1057.   local tAPIsLoading = {}
  1058.   env.os.loadAPI = function( _sPath )
  1059.       local sName = fs.getName( _sPath )
  1060.       if tAPIsLoading[sName] == true then
  1061.           printError( "API "..sName.." is already being loaded" )
  1062.           return false
  1063.       end
  1064.       tAPIsLoading[sName] = true
  1065.          
  1066.       local tEnv = {}
  1067.       setmetatable( tEnv, { __index = env } )
  1068.       local fnAPI, err = env.loadfile( _sPath )
  1069.       if fnAPI then
  1070.           setfenv( fnAPI, tEnv )
  1071.           fnAPI()
  1072.       else
  1073.           printError( err )
  1074.           tAPIsLoading[sName] = nil
  1075.           return false
  1076.       end
  1077.      
  1078.       local tAPI = {}
  1079.       for k,v in pairs( tEnv ) do
  1080.           tAPI[k] =  v
  1081.       end
  1082.      
  1083.       env[sName] = tAPI    
  1084.       tAPIsLoading[sName] = nil
  1085.       return true
  1086.   end
  1087.  
  1088.   env.shell = shell
  1089.  
  1090.   setfenv( fnFile, env )
  1091.   fnFile(unpack(tArgs))
  1092. end
  1093.  
  1094. local function extract()
  1095.     local function node(path, tree)
  1096.         if type(tree) == 'table' then
  1097.             fs.makeDir(path)
  1098.             for k, v in pairs(tree) do
  1099.                 node(path .. '/' .. k, v)
  1100.             end
  1101.         else
  1102.             local f = fs.open(path, 'w')
  1103.             if f then
  1104.                 f.write(tree)
  1105.                 f.close()
  1106.             end
  1107.         end
  1108.     end
  1109.     node('', files)
  1110. end
  1111.  
  1112. local tArgs = {...}
  1113. if #tArgs == 1 and tArgs[1] == '--extract' then
  1114.   extract()
  1115. else
  1116.   run(tArgs)
  1117. end
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Not a member of Pastebin yet?
Sign Up, it unlocks many cool features!
 
Top