Advertisement
fatboychummy

Modu rewritten

Dec 26th, 2018
494
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 16.67 KB | None | 0 0
  1. --[[
  2.   0.01
  3.   [re]Started a new thing!
  4. ]]
  5.  
  6.  
  7. -----------------------------------The one variable you may need to change:-----------------------------------
  8. local parserOverride = false      -- Location of your personal parser.  Uses the default parser if unspecified
  9. --------------------------------------------------------------------------------------------------------------
  10.  
  11. --The below are all updated automatically, and you shouldn't have to worry about them too much
  12. --However, if you've stored modules in different folders, you can change the data here to match that.
  13. local dataLocation = false        -- Location of data, defaults to "/data/"
  14. local modulesLocation = false     -- Location of modules, defaults to "/data/modules/"
  15. local customFileName = false      -- Location of 'customization' file, defaults to "/data/custom.modu"
  16. local dynaName = false            -- Location of DynaStore, defaults to "/data/dyna.modu"
  17. local parser = false              -- Updated at runtime, depending on what is required.
  18. local manipulatorOverride = false -- [Not currently working!]If you require a specific manipulator, change this value to the name of the manipulator on the network
  19. local detectionMethod = false     -- The event listened for.  Updated when parser is updated.
  20. local capture = false             -- The captured event for chat recorders.  Updated when parser is updated.
  21. local player = false              -- The player to capture
  22.  
  23. local version = 001               -- Version number
  24. local chests = {}                 -- All chest names stored in a table.
  25. local allitems = {}               -- All items stored in a table (fast cache :tm:).
  26. local chestCache = {}             -- NOT REQUIRED, DELET DELET DELET?
  27. local modules = {}                -- Modules, stored as a table.
  28. local manipFuncs = {}             -- Manipulator functions returned
  29.  
  30. local dynaStore = false           -- DynaStore data
  31. local custom = {}                 -- Used for accessing teh shitz 'n gigglez
  32.  
  33. local functionsNeeded = {
  34.   manipulator = {
  35.     "tell",
  36.     "getInventory",
  37.     "getEnder",
  38.     "getName",
  39.     "capture",
  40.     "clearCaptures",
  41.   }
  42. }
  43.  
  44.  
  45.  
  46. local function dCopy(a,b)
  47.   --DeepCopy
  48.   assert(type(a) == "table","copy: first input is not a table.")
  49.   for k,v in pairs(a) do
  50.     if type(v) == "table" then
  51.       b[k] = {}--If table, recursive copy
  52.       dCopy(a[k],b[k])
  53.     else
  54.       b[k] = v
  55.     end
  56.   end
  57. end
  58.  
  59. local function tell(stuff)
  60.   local lines = {}
  61.   if stuff:len() > 100 then
  62.     local o = 1
  63.     for i = 1,stuff:len(),100 do
  64.       lines[o] = stuff:sub(i,i+99)
  65.       o = o + 1
  66.     end
  67.   else
  68.     lines[1] = stuff
  69.   end
  70.  
  71.   --Loop through and check for newlines
  72.   local function newLineRemover()
  73.     for i = 1,#lines do
  74.       for o = 1,#lines[i] do
  75.         local c = lines[i]
  76.         if string.sub(c,o,o) == '\n' then
  77.           lines[i] = c:sub(1,o-1)
  78.           table.insert(lines,i+1,c:sub(o+1))
  79.           return true
  80.         end
  81.       end
  82.     end
  83.     return false
  84.   end
  85.  
  86.   while newLineRemover() do end
  87.  
  88.  
  89.   for i = 1,#lines do
  90.     local a,b = pcall(manipFuncs.tell,lines[i])
  91.     if not a then
  92.       if b == "Terminated" then
  93.         os.queueEvent("terminate")
  94.       end
  95.       printError("Your chat-recorder is either missing or not bound properly.")
  96.       term.setTextColor(colors.yellow)
  97.       print(b)
  98.       term.setTextColor(colors.gray)
  99.       for i = 1,#lines do
  100.         print(lines[i])
  101.       end
  102.       term.setTextColor(colors.white)
  103.     end
  104.   end
  105. end
  106.  
  107. local function doErr(func,cont)
  108.   local err = "ERR:" .. tostring(func) .. ": " .. tostring(cont)
  109.   printError(err)
  110.   tell(err)
  111.   error()
  112. end
  113.  
  114. local function overWriteMain(variable,equals)
  115.   --Checks for instances of "local" as first word
  116.   --on a line.  If so, checks variable
  117.   --if == variable, update it to be equal to
  118.   -- "equals"
  119.   --Assumes only major variables (variables at 'root' level)
  120.   local declaration = "local " .. variable
  121.   local find = "^" .. declaration
  122.   local h = fs.open(shell.getRunningProgram(),"r")
  123.   --If open...
  124.   if h then
  125.  
  126.     --load lines of program into data
  127.     local data = {}
  128.     local line = h.readLine()
  129.     local o = 0
  130.     repeat
  131.       o = o + 1
  132.       data[o] = line
  133.       line = h.readLine()
  134.     until not line
  135.     h.close()
  136.  
  137.  
  138.  
  139.     --search through the data for the variable.
  140.     o = -1 --if o == -1 after searching, failed.
  141.     for i = 1,#data do
  142.       if data[i]:match("^local ") then
  143.         local a = data[i]:gmatch("%w+")
  144.         a()
  145.         local var = a()
  146.         a = nil
  147.         --if the variable we found is named "variable" then
  148.         if var == variable then
  149.           -- we found our variable
  150.           o = i
  151.           break
  152.         end
  153.       end
  154.     end
  155.     if o == -1 then
  156.       doErr("overWriteMain","Failed to find variable " .. tostring(variable))
  157.       return false
  158.     else
  159.       declaration = declaration .. " = "
  160.       if type(equals) == "string" then
  161.         declaration = declaration .. "\"" .. equals .. "\""
  162.       elseif type(equals) == "table" then
  163.         declaration = declaration .. textutils.serialize(equals)
  164.       elseif type(equals) == "number" or type(equals) == "boolean" then
  165.         declaration = declaration .. tostring(equals)
  166.       else
  167.         doErr("overWriteMain","Unsupported type (" .. type(equals) .. ")")
  168.         return false
  169.       end
  170.       data[o] = declaration
  171.       local h = fs.open(shell.getRunningProgram(),"w")
  172.       if h then
  173.         for i = 1,#data do
  174.           h.writeLine(data[i])
  175.         end
  176.         h.close()
  177.         return true
  178.       else
  179.         doErr("overWriteMain","No handle (2)")
  180.         return false
  181.       end
  182.     end
  183.   else
  184.     doErr("overWriteMain","No handle (1).")
  185.     return false
  186.   end
  187. end
  188.  
  189.  
  190. local function makeCustomFile()
  191.   local h = fs.open(customFileName,"w")
  192.   local function ao(d)
  193.     h.writeLine(d)
  194.   end
  195.   ao("return {")
  196.   ao("  ")
  197.   ao("}")
  198.   h.close()
  199. end
  200.  
  201. local function makeDyna()
  202.   local h = fs.open(dynaName,"w")
  203.   local function ao(d)
  204.     h.writeLine(d)
  205.   end
  206.   ao("{")
  207.   ao("  ")
  208.   ao("}")
  209.   h.close()
  210. end
  211.  
  212. --Check if the setup is valid (Function will overwrite variables for faster startup times.)
  213. local function checkSetup()
  214.   -----------------------------this boio checks variables and updates them.
  215.   local function check()
  216.     local f = true
  217.     if dataLocation then
  218.       print("Data Location is specified, checking.")
  219.       if type(dataLocation) == "string" then
  220.         assert(dataLocation:match("^/.+/$"),"Cannot run; variable dataLocation: expected absolute path to folder. (Must start and end in '/').")
  221.         print("dataLocation is valid.")
  222.       else
  223.         doErr("checkSetup","Cannot run; variable dataLocation is of incorrect type.")
  224.       end
  225.     else
  226.       f = false
  227.       print("dataLocation is false.")
  228.       overWriteMain("dataLocation","/data/")
  229.       print("updated")
  230.     end
  231.     if modulesLocation then
  232.       if type(modulesLocation) == "string" then
  233.         assert(modulesLocation:match("^/.+/$"),"Cannot run; variable modulesLocation: expected absolute path to folder. (Must start and end in '/').")
  234.         print("modulesLocation is valid.")
  235.       else
  236.         doErr("checkSetup","Cannot run; variable modulesLocation is of incorrect type.")
  237.       end
  238.     else
  239.       f = false
  240.       print("modulesLocation is false.")
  241.       overWriteMain("modulesLocation","/data/modules/")
  242.       print("updated")
  243.     end
  244.     if customFileName then
  245.       if type(customFileName) == "string" then
  246.         assert(customFileName:match("^/.+%.modu$"),"Cannot run; variable customFileName: expected absolute path to file, ending with file-extension '.modu'.")
  247.         print("customFileName is valid.")
  248.       else
  249.         doErr("checkSetup","Cannot run; variable customFileName is of incorrect type.")
  250.       end
  251.     else
  252.       f = false
  253.       print("customFileName is false.")
  254.       overWriteMain("customFileName","/data/custom.modu")
  255.       print("updated")
  256.     end
  257.     if dynaName then
  258.       if type(dynaName) == "string" then
  259.         assert(dynaName:match("^.+%.modu$"),"Cannot run; variable dynaName:")
  260.         print("dynaName is valid.")
  261.       else
  262.         doErr("checkSetup","Cannot run; variable dynaName is of incorrect type.")
  263.       end
  264.     else
  265.       f = false
  266.       print("dynaName is false.")
  267.       overWriteMain("dynaName","/data/dyna.modu")
  268.       print("updated")
  269.     end
  270.  
  271.     --Check for directories.
  272.     if f then
  273.       if fs.isDir(dataLocation) then
  274.         print("Data directory exists")
  275.       else
  276.         f = false
  277.         fs.makeDir(dataLocation)
  278.         print("Made directory " .. tostring(dataLocation))
  279.       end
  280.  
  281.       if fs.isDir(modulesLocation) then
  282.         print("Modules directory exists")
  283.       else
  284.         f = false
  285.         fs.makeDir(modulesLocation)
  286.         print("Made directory " .. tostring(modulesLocation))
  287.       end
  288.       --Check for files.
  289.       if fs.exists(customFileName) then
  290.         print("Customization file exists")
  291.       else
  292.         f = false
  293.         makeCustomFile()
  294.         print("Made file " .. tostring(customFileName))
  295.       end
  296.  
  297.       if fs.exists(dynaName) then
  298.         print("Dynastore file exists")
  299.       else
  300.         f = false
  301.         makeDyna()
  302.         print("Made file " .. tostring(dynaName))
  303.       end
  304.     end
  305.     return f
  306.   end
  307.  
  308.   --Check if the thing was invalid, or valid.
  309.   local vars = {"dataLocation","modulesLocation","customFileName","dynaName"}
  310.   if not dataLocation or not modulesLocation or not customFileName or not dynaName then
  311.     print("Setup is invalid (First run?)")
  312.     check()
  313.     print("Setup should be valid.  Rebooting.")
  314.     os.sleep(3)
  315.     os.reboot()
  316.   else
  317.     if not check() then
  318.       print("Setup was invalid, rebooting now.")
  319.       os.sleep(3)
  320.       os.reboot()
  321.     end
  322.     print("Setup is valid.")
  323.   end
  324. end
  325.  
  326. local function findFunctionsInPeripherals(ttab)
  327.   local tab = {}
  328.   dCopy(ttab,tab)
  329.  
  330.   --[[
  331.     {
  332.       peripheralType = {
  333.         "peripheralFunc1",
  334.         "peripheralFunc2",
  335.         overridePeripheral = "peripheralFunc5",
  336.       },
  337.       peripheralType2 = {
  338.         "peripheralFunc3",
  339.         "peripheralFunc4",
  340.       }
  341.     }
  342.   ]]
  343.   local perip = {}
  344.  
  345.  
  346.   local function getPeriphs(tp)
  347.     local all = peripheral.getNames()
  348.     local perips = {}
  349.     for i = 1,#all do
  350.       if all[i]:find(tp) then
  351.         perips[#perips+1] = peripheral.wrap(all[i])
  352.       end
  353.     end
  354.     return perips
  355.   end
  356.  
  357.   for k,v in pairs(tab) do
  358.     --[[
  359.       each k: peripheralType
  360.       each v: table of peripheralFuncs
  361.     ]]
  362.     assert(type(v) == "table","ERR:findFunctionsInPeripherals: Expected table, index " .. tostring(k))
  363.     local pers = getPeriphs(k)
  364.     if pers then
  365.       for k2,v2 in pairs(v) do
  366.         --[[
  367.           each k2: number index or string override
  368.           each v2: peripheralFunctionName
  369.         ]]
  370.         local grabbed = false
  371.         if type(k2) == "number" then
  372.           --No override
  373.           for i = 1,#pers do
  374.             --[[
  375.               each i: peripheral of type k
  376.             ]]
  377.             for k3,v3 in pairs(pers[i]) do
  378.               --[[
  379.                 each k3: peripheralFunctionName of peripheral of type k
  380.                 each v3: peripheralFunction of peripheral of type k
  381.               ]]
  382.               if k3 == v2 then
  383.                 perip[k3] = v3
  384.                 tab[k][k2] = nil
  385.                 grabbed = true
  386.                 break
  387.               end
  388.             end
  389.             if grabbed then break end
  390.           end
  391.         elseif type(k2) == "string" then
  392.           --Override
  393.           if peripheral.isPresent(k2) then
  394.             local ps = peripheral.wrap(k2)
  395.             for k3,v3 in pairs(ps) do
  396.               --[[
  397.                 each k3: peripheralFunctionName of peripheral of type k
  398.                 each v3: peripheralFunction of peripheral of type k
  399.               ]]
  400.               if k3 == v2 then
  401.                 perip[k3] = v3
  402.                 tab[k][k2] = nil
  403.                 break
  404.               end
  405.             end
  406.           end
  407.         else
  408.           doErr("findFunctionsInPeripherals","Unexpected error ID 1")
  409.         end
  410.       end
  411.     end
  412.   end
  413.  
  414.   for k,v in pairs(tab) do
  415.     local notThere = true
  416.     for k2,v2 in pairs(v) do
  417.       notThere = false
  418.       break
  419.     end
  420.     if notThere then
  421.       tab[k] = nil
  422.     end
  423.   end
  424.  
  425.   return perip,tab
  426. end
  427.  
  428.  
  429. --Check if the function table is empty or not; if it isn't, return failure.
  430. local function checkFuncTable(tab)
  431.   for k,v in pairs(tab) do
  432.     return false,k,v
  433.   end
  434.   return true
  435. end
  436.  
  437.  
  438. --Save contents of dynaStore
  439. local function saveDyna()
  440.   local h = fs.open(dataLocation..dynaName,"w")
  441.   if h then
  442.     h.write(textutils.serialize(dynaStore))
  443.     h.close()
  444.   end
  445. end
  446.  
  447.  
  448. --Load dynaStore
  449. local function loadDyna()
  450.   local h = fs.open(dataLocation..dynaName,"r")
  451.   if h then
  452.     dynaStore = textutils.unserialize(h.readAll())
  453.     h.close()
  454.   else
  455.     dynaStore = false
  456.   end
  457. end
  458.  
  459.  
  460. --Properly load dynaStore, then check and load all the modules.
  461. local function prepareDyna()
  462.   loadDyna()
  463.   if not dynaStore then loadDyna() end
  464.   if not dynaStore then dynaStore = {} end
  465.   local tmods = fs.list(modulesLocation)
  466.   for i = 1,#tmods do
  467.     local h = fs.open(modulesLocation..tmods[i],"r")
  468.     h.readLine()
  469.     local no = h.readLine()
  470.     h.close()
  471.     custom.modules[tmods[i]] = textutils.unserialize(no)
  472.     if not dynaStore[tmods[i]] then
  473.       dynaStore[tmods[i]] = {}
  474.     end
  475.   end
  476. end
  477.  
  478.  
  479. -- Prepare the parser.
  480. local function prepareParserModule()
  481.   capture = "^modu"     -- CHAT: 'modu get item 43 bla bla'
  482.   if custom.capture then
  483.     capture = custom.capture
  484.   end
  485.   player = manipFuncs.getName()
  486.   if custom.player then
  487.     player = custom.player
  488.   end
  489.   -- Clear captures
  490.   manipFuncs.clearCaptures()
  491.  
  492.   if parserOverride then            -- If the parser override was set to some string location, then...
  493.     assert(type(parserOverride) == "string","variable error: parserOverride: Expected string")
  494.     assert(fs.exists(parserOverride),"variable error: parserOverride: File does not exist.  Make sure you write the FULL path.")
  495.     parser,detectionMethod = dofile(parserOverride)  -- Get the parser data
  496.  
  497.  
  498.   else
  499.     -- Set the parser to be "default"
  500.     parser = function(tt)
  501.       --
  502.       local plyr = tt[4]
  503.       local msg = tt[2]
  504.       local command = {}
  505.       if plyr == player then
  506.         for word in msg:gmatch("%w+") do
  507.           command[#command + 1] = word
  508.         end
  509.       end
  510.  
  511.       local major = command[2]
  512.       return major,command
  513.     end
  514.  
  515.     -- Set captures
  516.     manipFuncs.capture(capture)
  517.     print("Captures ready.")
  518.     -- Set the detectionMethod to be "default"
  519.     detectionMethod = "chat_capture"
  520.   end
  521. end
  522.  
  523.  
  524. -- Runs a module.
  525. local function run()
  526.  
  527. end
  528.  
  529. local function getChests()
  530.   local a = peripheral.getNames()
  531.   chests = {}
  532.   for i = 1,#a do
  533.     if a[i]:find("chest") or a[i]:find("shulker") then
  534.       chests[#chests+1] = a[i]
  535.     end
  536.   end
  537. end
  538.  
  539.  
  540.  
  541. local function main()
  542.   checkSetup()                                                                                                -- Check if the setup is okay
  543.   getChests()                                                                                                 -- Discover chests
  544.   prepareDyna()                                                                                               -- Prepare the dynaStore
  545.   local df
  546.   manipFuncs,df = findFunctionsInPeripherals(functionsNeeded)                                                 -- Locate functions needed in peripherals.
  547.   local a,b,c = checkFuncTable(df)                                                                            -- Check if any functions were missing.
  548.   assert(a,"Could not find one of the required peripherals (" .. tostring(b) .. ", " .. tostring(c) ..")")    -- Print the missing peripheral and function
  549.   prepareParserModule()                                                                                       -- Prepare the parser
  550.  
  551.   if not capture then
  552.     tell("Modu is listening for " .. tostring(detectionMethod) .. " events.")
  553.   end
  554.   tell("Modu is listening for commands with the following prefix:")
  555.   tell(capture)
  556.   tell("Modu is watching for player " .. tostring(player) .. ".")
  557.   --Loop
  558.   while true do
  559.     local ev = {os.pullEvent(detectionMethod)}
  560.     local module,tbl = parser(ev)
  561.     if module then
  562.       tell(module)
  563.       tell(textutils.serialize(tbl))
  564.     end
  565.   end
  566. end
  567.  
  568. local a,err = pcall(main)
  569.  
  570. if not a then
  571.   if err == "Terminated" then
  572.     tell("Modu has been terminated")
  573.     return
  574.   end
  575.   tell("Modu has stopped with error "..err.."... Rebooting.")
  576.   os.sleep(2)
  577.   os.reboot()
  578. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement