Advertisement
Guest User

Untitled

a guest
Jul 25th, 2016
73
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 34.29 KB | None | 0 0
  1.     --tankmon tppi fix
  2.     --   Edited by bot190 to support CC 1.73 and OpenPeripheralCore 0.5.0
  3.     --   Tank monitoring program edited by Morphik08
  4.     --    Original program by Forgotten_Boy
  5.     --    Hardware detector program by Sharidan
  6.     --      Requires OpenPeripherals (OP). Tested with version 3.0.
  7.     --      Supports iron & steel Railcraft tanks, Open Block tanks, Ender Tanks, AE ExtraCells tanks,
  8.     --    TConstruct tanks, Extra Utilities Drums, Mekanism Dynamic Tanks.
  9.     --      Also supports multiple tanks, and tanks attached with modems.
  10.     --      If I missed any tanks, let me know. I will add it to the list.
  11.     --[[
  12.      Setup:
  13.      - Place an Advanced Computer with wireless modem and with tankmon on it adjacent to a tank.  Run "tankmon".
  14.      - Setup another Advanced Computer with wireless modem and with tankmon on it adjacent to an advanced monitor and/or terminal glass bridge.  Run "tankmon".
  15.      - Your monitor should now show the contents of the tank.  Add as many tanks as you like and the server will simply add them to the display.
  16.      - The size of the monitor or locations of the modems don't matter, place them anywhere on the computer.  The monitor can be resized while tankmon is running.
  17.      
  18.      Optional Setup:
  19.      - Place an Advanced Computer with wired and wireless modems with lan cables connecting all tanks with lan modems attached to tanks and to computer.  Run "tankmon".
  20.      - Setup another Advanced Computer with wireless modem and with tankmon on it adjacent to an advanced monitor and/or terminal glass bridge.  Run "tankmon".
  21.      - Your monitor should now show the contents of the tanks.  Add as many tanks as you like and the server will simply add them to the display.
  22.      - The size of the monitor or locations of the modems don't matter, place them anywhere on the computer.  The monitor can be resized while tankmon is running.
  23.      
  24.      Advanced usage:
  25.      - On the client, you can use tankmon to trigger a redstone signal when the tank reaches a certain threshold (specified as 0 to 100, a percentage).  For example:
  26.      tankmon 100 left
  27.      tankmon 0 top
  28.      The first example will send redstone output on the left when the tank is full.  The second example will send redstone output on the top when the tank is empty.
  29.     --]]
  30.      
  31.     -- Variable definitions
  32.     local valve, monitor, screenw, screenh
  33.     local serverID = nil
  34.     local clients = {}
  35.     local args = {...}
  36.     local redLimit, redside, on
  37.     local sides = {"left", "right", "top", "bottom", "front", "back"};
  38.     local tankTypes = {"tile.basicblock.dynamic_valve_name", "rcirontankvalvetile", "rcsteeltankvalvetile", "openblocks_tank", "drum", "ender_tank", "cofh_thermalexpansion_tank", "net_minecraft_src_buildcraft_factory_tiletank", "tileentitycertustank", "tconstruct_lavatank"};
  39.     local scale = .5 --Scale for monitor text
  40.     local skipEmpty = true --Skip showing empty tanks
  41.     local count = 0 --Counter for tanks
  42.      
  43.     ----------------------------------------------------
  44.     -- Terminal Bridge Glasses Variable definitions
  45.     ----------------------------------------------------
  46.     local bridge = {}
  47.     bridge["TankText"] = {}
  48.     bridge["TankBackground"] = {}
  49.     bridge["TankTexture"] = {}
  50.     -------------------------------------------------------
  51.     -- Terminal Bridge Glasses display variable definitions
  52.     -- Feel free to alter these to your liking
  53.     -------------------------------------------------------
  54.     bridge["BackgroundColor"] = 0x000000 --Background Bar color
  55.     bridge["TextColor"] = 0x33B5E5 --Text color
  56.     bridge["TextScale"] = 1 --Text Scale
  57.     bridge["ExtendBackground"] = true --Extend Black background behind text
  58.     bridge["BarWidth"] = 25 --Tank bar width
  59.     bridge["BarHeight"] = 50 --Tank bar height
  60.     bridge["XOffset"] = 5 --X Offset for displaying info
  61.     bridge["YOffset"] = 50 --Y Offset for displaying info
  62.     bridge["XSpacing"] = 5 --Space between columns
  63.     bridge["YSpacing"] = 5 --Space between rows
  64.     bridge["Alpha"] = 1 --Alpha value of bar background
  65.     bridge["LinesAmt"] = 3 --Number of text lines after tank bar
  66.     bridge["MaxCols"] = 3 --Max Number of cols to display per page
  67.     bridge["MaxRows"] = 3 --Max Number of rows to display per page
  68.     -------------------------------------------------------
  69.     -- Which row to start with. This will be changed to
  70.     -- automatically change based on user input in chat
  71.     -- command box.
  72.     -------------------------------------------------------
  73.     bridge["StartRow"] = 0 --Min Row to display
  74.     -------------------------------------------------------
  75.     -- Altering these does nothing
  76.     -------------------------------------------------------
  77.     bridge["CurrentRow"] = 1 --Current Row
  78.     bridge["CurrentCol"] = 1 --Current Col
  79.      
  80.     ----------------------------------------------------
  81.     -- Function definitions
  82.     ----------------------------------------------------
  83.     local liquidNameColors = {
  84.                    {"water", colors.blue, "Water" },
  85.                    {"lava", colors.orange, "Lava" },
  86.                    {"liquidforce", colors.yellow, "Liquid Force" },
  87.                    {"turpentine", colors.brown, "Turpentine" },
  88.                    {"poison", colors.purple, "Poison" },
  89.                    {"latex", colors.white, "Latex" },
  90.                    {"ardite.molten", colors.orange, "Molten Ardite" },
  91.                    {"gold.molten", colors.yellow, "Molten Gold" },
  92.                    {"blood", colors.orange, "Blood" },
  93.                    {"copper.molten", colors.orange, "Molten Copper" },
  94.                    {"obsidian.molten", colors.gray, "Molten Obsidian" },
  95.                    {"bop.honey", colors.yellow, "Honey" },
  96.                    {"sap", colors.brown, "Sap" },
  97.                    {"liquidnitrogen", colors.cyan, "Liquid Nitrogen" },
  98.                    {"iron.molten", colors.gray, "Molten Iron" },
  99.                    {"bop.liquidpoison", colors.purple, "Liquid Poison" },
  100.                    {"alumite.molten", colors.orange, "Molten Ardite" },
  101.                    {"cobalt.molten", colors.cyan, "Molten Cobalt" },
  102.                    {"bop.springwater", colors.blue, "Spring Water" },
  103.                    {"glowstone", colors.yellow, "Energized Glowstone" },
  104.                    {"resin", colors.brown, "Resin" },
  105.                    {"emerald.liquid", colors.lime, "Liquified Emerald" },
  106.                    {"pinkslime", colors.pink, "Pink Slime" },
  107.                    {"redstone", colors.red, "Redstone" },
  108.                    {"xpjuice", colors.lime, "Liquid XP" },
  109.                    {"oil", colors.gray, "Oil" },
  110.                    {"aluminum.molten", colors.lightGray, "Molten Aluminum" },
  111.                    {"manyullyn.molten", colors.purple, "Molten Manyullyn" },
  112.                    {"stone.seared", colors.gray, "Seared Stone" },
  113.                    {"creosote", colors.green, "Creosote Oil" },
  114.                    {"sludge", colors.brown, "Sludge" },
  115.                    {"bioethanol", colors.lime, "Ethanol" },
  116.                    {"acid", colors.lime, "Acid" },
  117.                    {"biomass", colors.lime, "Biomass" },
  118.                    {"immibis.liquidxp", colors.lime, "Liquid XP" },
  119.                    {"electrum.molten", colors.yellow, "Molten Electrum" },
  120.                    {"sewage", colors.brown, "Sewage" },
  121.                    {"slime.blue", colors.cyan, "Liquid Blueslime" },
  122.                    {"tin.molten", colors.lightGray, "Molten Tin" },
  123.                    {"aluminumbrass.molten", colors.orange, "Molten Aluminum Brass" },
  124.                    {"milk", colors.white, "Milk" },
  125.                    {"fuel", colors.lime, "Fuel" },
  126.                    {"biofuel", colors.green, "Biofuel" },
  127.                    {"chocolatemilk", colors.brown, "Chocolate Milk" },
  128.                    {"glass.molten", colors.lightGray, "Molten Glass" },
  129.                    {"cryotheum", colors.cyan, "Gelid Cryotheum" },
  130.                    {"pyrotheum", colors.orange, "Blazing Pyrotheum" },
  131.                    {"pinkslime", colors.pink, "Pink Slime" },
  132.                    {"platinum.molten", colors.cyan, "Molten Platinum" },
  133.                    {"coal", colors.gray, "Liquifacted Coal" },
  134.                    {"lead.molten", colors.gray, "Molten Lead" },
  135.                    {"mushroomsoup", colors.brown, "Mushroom Soup" },
  136.                    {"silver.molten", colors.lightGray, "Molten Silver" },
  137.                    {"nickel.molten", colors.cyan, "Molten Nickel" },
  138.                    {"ender", colors.green, "Resonant Ender" },
  139.                    {"invar.molten", colors.lightGray, "Molten Invar" },
  140.                    {"glue", colors.white, "Glue" },
  141.                    {"meat", colors.pink, "Meat" },
  142.                    {"steel.molten", colors.gray, "Molten Steel" },
  143.                    {"bronze.molten", colors.brown, "Molten Bronze" }
  144.                    }
  145.      
  146.     function cls()
  147.        term.clear()
  148.        term.setCursorPos(1,1)
  149.        term.setCursorBlink(false)
  150.     end
  151.     function clm()
  152.        if monitor then
  153.           monitor.setBackgroundColor(colors.black)
  154.           monitor.setTextScale(scale)
  155.           monitor.clear()
  156.           monitor.setCursorPos(1,1)
  157.           monitor.setCursorBlink(false)
  158.        end
  159.     end
  160.     function clb()
  161.        if bridge["peripheral"] then
  162.           bridge["peripheral"].clear()
  163.        end
  164.     end
  165.      
  166.     function table.merge(tbl1, tbl2)
  167.        for k,v in ipairs(tbl2) do
  168.           table.insert(tbl1, v)
  169.        end
  170.        return tbl1
  171.     end
  172.      
  173.     function split(str, wordNum)
  174.        local splitString = {}
  175.        for tmp in str:gmatch("%w+") do
  176.           table.insert(splitString, tmp)
  177.        end
  178.        return splitString[wordNum] or ""
  179.     end
  180.      
  181.     local function getLiquidColor(liquid)
  182.        for c, color in pairs (liquidNameColors) do
  183.           if (liquid == color[1]) or (liquid == color[3]) then
  184.              return color[2]
  185.           end
  186.        end
  187.        return colors.white;
  188.     end
  189.      
  190.     local function getDeviceSide(deviceType)
  191.             for i,side in pairs(sides) do
  192.                     if (peripheral.isPresent(side)) then
  193.                             if (peripheral.getType(side)) == string.lower(deviceType) then
  194.                                     return side;
  195.                             end
  196.                     end
  197.             end
  198.     end
  199.      
  200.     function hardwareDetector(...)
  201.       local self = {}
  202.       -- Initialize internal hardware list
  203.       self._devList = {}
  204.      
  205.       -- Internal worker function
  206.       -- Checks a boolean value and returns the
  207.       -- corresponding supplied value
  208.       local function iif(bool, resultTrue, resultFalse)
  209.         if (bool) then
  210.           return resultTrue;
  211.         else
  212.           return resultFalse;
  213.         end
  214.       end
  215.       local function split(str, pat)
  216.         local t = {}
  217.         local fpat = "(.-)" .. pat
  218.         local last_end = 1
  219.         local s, e, cap = str:find(fpat, 1)
  220.         while s do
  221.           if s ~= 1 or cap ~= "" then
  222.             table.insert(t,cap)
  223.           end
  224.           last_end = e+1
  225.           s, e, cap = str:find(fpat, last_end)
  226.         end -- while
  227.         if last_end <= #str then
  228.           cap = str:sub(last_end)
  229.           table.insert(t, cap)
  230.         end
  231.         return t
  232.       end
  233.       local function splitType(str)
  234.         local typ, adv = str, nil
  235.         local r = split(str, ":")
  236.         if (#r == 2) then
  237.           typ = r[1]
  238.           adv = r[2]
  239.         end
  240.         return typ, adv;
  241.       end
  242.       local function wrapID(value)
  243.         if (value == nil) then
  244.           return "offline"
  245.         else
  246.           return tostring(value)
  247.         end
  248.       end
  249.       local function addDevice(label, devType, remote)
  250.         local lcdt = string.lower(devType)
  251.         local adv = "n/a";
  252.         local pCall = function() end;
  253.         if (remote) then
  254.           pCall = function(label, method)
  255.             return remote.callRemote(label, method)
  256.           end;
  257.         else
  258.           pCall = function(label, method)
  259.             return peripheral.call(label, method)
  260.           end;
  261.         end
  262.         if (lcdt == "modem") then
  263.           adv = iif(pCall(label, "isWireless"), "wireless", "cable")
  264.         elseif (lcdt == "monitor") then
  265.           adv = iif(pCall(label, "isColor"), "advanced", "normal")
  266.         elseif (lcdt == "computer" or lcdt == "turtle") then
  267.           adv = tostring(wrapID(pCall(label, "getID")))
  268.         elseif (lcdt == "drive") then
  269.           if (disk.isPresent(label)) then
  270.             if (disk.hasData(label)) then
  271.               adv = "floppy";
  272.             elseif (disk.hasAudio(label)) then
  273.               adv = "music";
  274.             else
  275.               adv = "unknown";
  276.             end
  277.           else
  278.             adv = "empty"
  279.           end
  280.         end
  281.         table.insert(self._devList, {label, devType, adv});
  282.         if (lcdt == "modem" and string.lower(adv) == "cable") then
  283.           return true;
  284.         end
  285.       end
  286.      
  287.       -- Detects all connected peripherals
  288.       function self.detect()
  289.         self._devList = {};
  290.         local sides = rs.getSides();
  291.         local remoteSide = {};
  292.         for i, side in pairs(sides) do
  293.           local devType = peripheral.getType(side);
  294.           if (devType) then
  295.             if (addDevice(side, devType)) then
  296.               table.insert(remoteSide, side);
  297.             end
  298.           end -- if
  299.         end -- for-do
  300.        
  301.         if (#remoteSide > 0) then
  302.           -- There was a cable modem attached, so we need to loop through all remote peripherals too
  303.           for r = 1, #remoteSide do
  304.             local rp = peripheral.wrap(remoteSide[r]);
  305.             local lst = rp.getNamesRemote()
  306.             for r = 1, #lst do
  307.               local name = lst[r]
  308.               local devType = rp.getTypeRemote(name);
  309.               if (devType) then
  310.                 addDevice(name, devType, rp);
  311.               end
  312.             end
  313.           end -- for r
  314.         end
  315.       end
  316.      
  317.       -- Returns a tuple of the first matching peripheral
  318.       function self.find(...)
  319.         local args={...}
  320.         if (#args > 0) then
  321.           local idx = 0;
  322.           for i, sideType in pairs(self._devList) do
  323.             for a = 1, #args do
  324.               local findType = args[a];
  325.               if (type(findType) == "string") then
  326.                 local typ, adv = splitType(findType);
  327.                 if (string.lower(typ) == string.lower(self._devList[i][2])) then
  328.                   if (adv) then
  329.                     if (string.lower(adv) == string.lower(self._devList[i][3])) then
  330.                       -- We found a device of this type
  331.                       idx = i;
  332.                     end
  333.                   else
  334.                     -- We found a device of this type
  335.                     idx = i;
  336.                   end
  337.                   if (idx > 0) then
  338.                     return tostring(self._devList[idx][1]), tostring(self._devList[idx][2]), tostring(self._devList[idx][3])
  339.                   end
  340.                 end
  341.               end
  342.             end
  343.           end
  344.           return nil;
  345.         else
  346.           error("No device type specified.", 0)
  347.         end
  348.       end
  349.      
  350.       -- Returns a complete list of peripherals
  351.       function self.getAll()
  352.         return self._devList;
  353.       end
  354.      
  355.       -- Returns a list of all matching peripherals
  356.       function self.getList(...)
  357.           local args={...}
  358.           local results = {}
  359.           if (#args > 0) then
  360.              for i, sideType in pairs(self._devList) do
  361.                 for a = 1, #args do
  362.                    local findType = args[a];
  363.                    if (type(findType) == "string") then
  364.                       if (string.lower(findType) == string.lower(self._devList[i][2])) then
  365.                          -- We found a device of this type
  366.                          table.insert(results, {tostring(self._devList[i][1]), tostring(self._devList[i][2]), tostring(self._devList[i][3])})
  367.                       end
  368.                    elseif (type(findType) == "table") then
  369.                       for i2, entry in pairs(findType) do
  370.                          if (type(entry) == "string") then
  371.                             if (string.lower(entry) == string.lower(self._devList[i][2])) then
  372.                                -- We found a device of this type
  373.                                table.insert(results, {tostring(self._devList[i][1]), tostring(self._devList[i][2]), tostring(self._devList[i][3])})
  374.                             end
  375.                          end
  376.                       end
  377.                    end
  378.                 end
  379.              end
  380.              return results;
  381.           else
  382.              error("No device type specified.", 0);
  383.           end
  384.        end
  385.      
  386.       -- Determines if the device is remote or not
  387.       function self.isRemote(dev)
  388.         if (type(dev) == "string") then
  389.           local sides = rs.getSides();
  390.           for i, s in pairs(sides) do
  391.             if (string.lower(dev) == string.lower(s)) then
  392.               return nil;
  393.             end
  394.           end
  395.           return true;
  396.         else
  397.           error("Device connect string expected.", 0);
  398.         end
  399.       end
  400.      
  401.       -- Internal calls, don't mess with these
  402.       self.detect()
  403.      
  404.       local args = {...};
  405.       if (#args > 0) then
  406.         return self.find(...);
  407.       else
  408.         -- If no parameters were passed,
  409.         -- return the hardware object
  410.         return self;
  411.       end
  412.     end
  413.      
  414.     local function showLevel(count,total,filled,color,label,rawLabel, amt, threshold, signal)
  415.        if (monitor) then
  416.           local screenw, screenh = monitor.getSize()
  417.           --total = total + 1
  418.           if (not screenw) then
  419.              return nil;
  420.              -- monitor has been broken
  421.           end
  422.      
  423.           local starty = screenh -  math.floor((screenh * filled))
  424.           local width  = math.ceil(screenw / total)
  425.           local offset = math.ceil((screenw / total) * (count-1))
  426.           local amtw = string.len(amt)
  427.           local thresholdy = (threshold and ( screenh - ((threshold / 100) * screenh)))
  428.            
  429.           if (count == total) then
  430.           --  the final column should use up the remaining space.  A hack!
  431.              width = screenw - offset
  432.           end
  433.      
  434.           if (thresholdy and thresholdy < 1) then
  435.              thresholdy = 1
  436.           else
  437.              if (thresholdy and thresholdy > screenh) then
  438.                 thresholdy = screenh
  439.              end
  440.           end
  441.           restoreTo = term.current()
  442.           term.redirect(monitor)
  443.           for c=starty, screenh + 1, 1 do
  444.              for line=0, width, 1 do
  445.                 paintutils.drawPixel(line + offset, c, color)
  446.              end
  447.           end
  448.           if (thresholdy) then
  449.              local thresholdColor = color
  450.              for line=0, width, 1 do
  451.                 thresholdColor = color
  452.                 if (signal) then
  453.                    thresholdColor = colors.red
  454.                 else
  455.                    -- makes a dotted line when there is no redstone signal
  456.                    if (line % 2 == 0) then
  457.                       thresholdColor = colors.red
  458.                    else
  459.                       thresholdColor = color
  460.                    end
  461.                 end
  462.                 paintutils.drawPixel(line + offset, thresholdy, thresholdColor)
  463.              end
  464.           end
  465.      
  466.           --truncate the label to the width of the bar.
  467.           monLabel = string.sub(rawLabel, 1, math.max((width - 1), 0))
  468.      
  469.           monitor.setBackgroundColor(color)
  470.           if (color == colors.white) then
  471.              monitor.setTextColor(colors.black)
  472.           end
  473.            
  474.           labely = math.min((starty + 1), screenh - 1)
  475.           monitor.setCursorPos(offset + 1, labely)
  476.           monitor.setTextScale(scale)
  477.           write(monLabel)
  478.            
  479.           if (amtw <= width) then
  480.              amty = math.min(labely + 1, screenh)
  481.              monitor.setCursorPos(offset + 1, amty)
  482.              write(amt)
  483.           end
  484.           monitor.setTextColor(colors.white)
  485.           term.redirect(restoreTo)
  486.        end
  487.        if (bridge["peripheral"]) then
  488.           --Maximum length string can be
  489.           local cutoffPoint = math.ceil(bridge["BarWidth"] / (8*bridge["TextScale"]))
  490.      
  491.           bridge["CurrentRow"] = math.floor((count+bridge["MaxCols"]-1)/bridge["MaxCols"])
  492.           bridge["CurrentCol"] = ((count+bridge["MaxCols"]-1) - bridge["CurrentRow"]*bridge["MaxCols"]) + 1
  493.          
  494.           if (bridge["CurrentRow"] > bridge["StartRow"]) and (bridge["CurrentRow"] <= (bridge["StartRow"] + bridge["MaxRows"])) then
  495.              --Heigth including extra lines below tank display
  496.              local fullHeight = bridge["BarHeight"]+((8*bridge["TextScale"])*(bridge["LinesAmt"]))
  497.              --X and Y coords for tank displays
  498.              local x = bridge["XOffset"] + ((bridge["BarWidth"] + bridge["XSpacing"]) * (bridge["CurrentCol"]-1))
  499.              local y = bridge["YOffset"] + ((fullHeight+bridge["YSpacing"])*(bridge["CurrentRow"]-bridge["StartRow"]-1))
  500.              --Draw tank background using liquid texture
  501.              if bridge["ExtendBackground"] then
  502.                 bridge["TankBackground"][count] = bridge["peripheral"].addBox(x,y,bridge["BarWidth"],fullHeight,bridge["BackgroundColor"],bridge["Alpha"])
  503.              else
  504.                 bridge["TankBackground"][count] = bridge["peripheral"].addBox(x,y,bridge["BarWidth"],bridge["BarHeight"],bridge["BackgroundColor"],bridge["Alpha"])
  505.              end
  506.              bridge["TankTexture"][count] = bridge["peripheral"].addLiquid(x+1,y+1+math.ceil(bridge["BarHeight"]-(bridge["BarHeight"] * filled)),bridge["BarWidth"]-2,(bridge["BarHeight"] * filled)-2,label)
  507.              --Display info to bridge
  508.              bridge["TankText"][count] = bridge["TankText"][count] or {}
  509.              for i=0,(bridge["LinesAmt"]-1) do
  510.                 bridge["TankText"][count][i] = bridge["peripheral"].addText((x+2), (bridge["BarHeight"]+y+((8*bridge["TextScale"])*i)),"",bridge["TextColor"])
  511.                 bridge["TankText"][count][i].setScale(scale)
  512.              end
  513.              bridge["TankText"][count][0].setText(string.sub(split(rawLabel,1), 1, cutoffPoint))
  514.              bridge["TankText"][count][1].setText(string.sub(split(rawLabel,2), 1, cutoffPoint))
  515.              bridge["TankText"][count][2].setText(string.sub(tostring(math.floor(filled*100)).."%", 1, cutoffPoint))
  516.           end
  517.        end
  518.     end
  519.      
  520.     local function tankStats(tank)
  521.             if(tank) then
  522.           local name = tank["contents"]["name"] or nil
  523.           local rawName = tank["contents"]["rawName"] or nil
  524.                     local amt = tank["contents"]["amount"]
  525.                     local size = tank["capacity"]
  526.                     local filled = (amt and 1 / (size / amt)) or 0
  527.           local threshold = tank["contents"]["redLimit"] or -1
  528.           local signalOn = tank["contents"]["on"] or false
  529.                     return name, rawName, amt, size, filled, threshold, signalOn
  530.             else
  531.                     return nil;
  532.             end
  533.     end
  534.      
  535.     local function tableCount(t)
  536.             local total=0
  537.             for k,v in pairs (t) do
  538.                     total = total + 1
  539.             end
  540.             return total
  541.     end
  542.      
  543.     function printTable(tt, indent)
  544.        print(tableToString(tt, indent))
  545.     end
  546.      
  547.     function tableToString (tt, indent, done)
  548.       done = done or {}
  549.       indent = indent or 0
  550.       if type(tt) == "table" then
  551.         local sb = {}
  552.         for key, value in pairs (tt) do
  553.           table.insert(sb, string.rep (" ", indent)) -- indent it
  554.           if type (value) == "table" and not done [value] then
  555.             done [value] = true
  556.             table.insert(sb, "{\n");
  557.             table.insert(sb, tableToString (value, indent + 2, done))
  558.             table.insert(sb, string.rep (" ", indent)) -- indent it
  559.             table.insert(sb, "}\n");
  560.           elseif "number" == type(key) then
  561.             table.insert(sb, string.format("\"%s\"\n", tostring(value)))
  562.           else
  563.             table.insert(sb, string.format("%s = \"%s\"\n", tostring (key), tostring(value)))
  564.            end
  565.         end
  566.         return table.concat(sb)
  567.       else
  568.         return tt .. "\n"
  569.       end
  570.     end
  571.      
  572.     function table.contains(tbl, element)
  573.       for _, value in pairs(tbl) do
  574.         if value == element then
  575.           return true
  576.         end
  577.       end
  578.       return false
  579.     end
  580.      
  581.     local function findTank(tbl)
  582.        if type(tbl) == "table" then
  583.           for index,value in pairs(tbl) do
  584.              if type(value) == "table" then
  585.                 if value["capacity"] then
  586.                    return tbl
  587.                 else
  588.                    return findTank(value)
  589.                 end
  590.              end
  591.           end
  592.        else
  593.           return nil
  594.        end
  595.     end
  596.     local function findTanks(tbl)
  597.        local tblTemp = {}
  598.        if type(tbl) == "table" then
  599.           for index,value in pairs(tbl) do
  600.              if type(value) == "table" then
  601.                 if value["capacity"] then
  602.                    table.insert(tblTemp, value)
  603.                 else
  604.                    table.insert(tblTemp, findTank(value))
  605.                 end
  606.              end
  607.           end
  608.        end
  609.        return tblTemp
  610.     end
  611.     local function updateDisplay()
  612.        --printTable(findTanks(clients))
  613.     --end
  614.     --local function tmp()
  615.             local count = 1
  616.        local lstTanks = {}
  617.        local total = 0
  618.      
  619.        clm()
  620.        clb()
  621.      
  622.        if tableCount(clients) > 0 then
  623.           local i = 1
  624.           for ix,client in pairs (clients) do
  625.              local tanks = findTanks(client)
  626.              table.merge(lstTanks, tanks)
  627.              if (i <= 15) then
  628.                 term.setCursorPos(1,6+i)
  629.                 term.clearLine()
  630.                 print("Client "..i.." # of Tanks: "..tostring(#tanks))
  631.              end
  632.              i = i + 1
  633.           end
  634.           total = #lstTanks
  635.           term.setCursorPos(1,6)
  636.           term.clearLine()
  637.           print("Total # of Tanks: "..tostring(total))
  638.           for _,tankInfo in pairs (lstTanks) do
  639.                 local name, rawName, amt, size, filled, threshold, signalOn = tankStats(tankInfo)
  640.                 local color = getLiquidColor(rawName)
  641.                 local unit = ""
  642.                 local amount = math.max(amt or 0, 0)
  643.                 --print("Name: "..tostring(name))
  644.                 --print("Raw Name: "..tostring(rawName))
  645.                 --print("color: "..tostring(color))
  646.                 --print("amt: "..tostring(amt))
  647.                 --print("size: "..tostring(size))
  648.                 --print("filled: "..tostring(filled))
  649.        
  650.                 if not (name) and (skipEmpty) then total = total - 1 end
  651.                 if name or (not (name) and not (skipEmpty)) then
  652.                    if (amount > 1000000) then
  653.                       unit="M"
  654.                       amount=string.format("%.2f", math.floor(amt / 1000) / 1000)
  655.                       --unit="K Buckets"
  656.                       --amount=string.format("%i", math.floor(amt / 1000) / 1000)
  657.                    else
  658.                       if(amount > 0) then
  659.                          unit="K"
  660.                          amount=string.format("%.2f", amt / 1000)
  661.                          --unit=" Buckets"
  662.                          --amount=string.format("%i", amt / 1000)
  663.                       else
  664.                          amount = ""
  665.                       end
  666.                    end
  667.                    amount = amount..unit
  668.                    showLevel(count, total, filled, color, name or "Empty", rawName or "Empty", amount, threshold, signalOn)
  669.                    count = count + 1    
  670.                 --end
  671.              end
  672.           end
  673.        end
  674.        return nil;
  675.     end
  676.      
  677.     local function broadcast ()
  678.             cls()
  679.             print("_____________ tankmon Server started __________")
  680.             print("Broadcasting that tank display is available...")
  681.             print("Hold Ctrl+T to Terminate.")
  682.             while true do
  683.                     rednet.broadcast(os.getComputerID())
  684.                     term.setCursorPos(1, 5)
  685.                     term.clearLine()
  686.                     write("Connected tankmon clients: " .. tableCount(clients))
  687.                     sleep(7)
  688.             end
  689.     end
  690.      
  691.     local function receive()
  692.       while true do
  693.         local senderID, message, distance = rednet.receive()
  694.         if (message) then
  695.                     local data = textutils.unserialize(message)
  696.                     clients[senderID] = data
  697.         end
  698.       end
  699.     end
  700.      
  701.     local function display()
  702.             while true do
  703.           updateDisplay()
  704.           sleep(1.5)
  705.             end
  706.     end
  707.      
  708.     local function connect()
  709.             cls()
  710.        print("Looking for a tankmon server in range...")
  711.             while true do
  712.                     local senderID, message, distance = rednet.receive()
  713.                     serverID = senderID
  714.           print()
  715.           print("Connected to server " ..tostring(serverID)..".")
  716.           sleep(3)
  717.       end  
  718.     end
  719.      
  720.     local function publishTank()
  721.        while true do
  722.           if (serverID) then
  723.              local hw = hardwareDetector()
  724.              lstTanks = hw.getList(tankTypes)
  725.              if (type(lstTanks) == "table") then
  726.                 if (#lstTanks > 0) then
  727.                    local info = {}
  728.                    for i, tank in pairs(lstTanks) do
  729.                       if not tank[1]["capacity"] then
  730.                          lstTanks[i][1] = peripheral.wrap(lstTanks[i][1]).getTankInfo("unknown")[1]
  731.                       end
  732.                    end
  733.                    cls()
  734.                    print("** Sending out tank information **")
  735.                    print("Number of tanks: "..#lstTanks)
  736.                    for i, tank in pairs(lstTanks) do
  737.                       if tank[1]["contents"] then
  738.                           -- establish whether redstone signal should be sent
  739.                           local name, rawName, amt, size, filled, threshold, signalOn = tankStats(tank[1])
  740.                           on = false
  741.                           pctFilled = filled * 100
  742.                           if (filled and redLimit and redLimit==0 and filled==0) then
  743.                              on = true
  744.                           else
  745.                              if(filled and redLimit and filled <= redLimit) then
  746.                                 on=true
  747.                              end
  748.                           end
  749.                           if(redside) then
  750.                              rs.setOutput(redside, on)
  751.                           end
  752.                           -- use rednet to update the server with this tank's info.
  753.                           tank[1]["redLimit"] = redLimit
  754.                           tank[1]["on"] = on
  755.                           table.insert(info, tank[1])
  756.                           if (redLimit and redside) then
  757.                              print("Redstone signal on: " .. tostring(on))
  758.                           end
  759.                           if (i <= 12) then
  760.                              term.setCursorPos(1,3 + i)
  761.                              term.clearLine()
  762.                              if tank[1]["contents"]["amount"] then
  763.                                 write("** Tank "..i.." contains: " .. tostring(tank[1]["contents"]["amount"]).."mB of "..tostring(tank[1]["name"]))
  764.                              else
  765.                                 write("** Tank "..i.." is empty.")
  766.                              end
  767.                           end
  768.                         end
  769.                    end
  770.                    if (redLimit and redside) then
  771.                       print("Redstone threshold: " .. tostring(redLimit))
  772.                       print("Redstone output side: " .. tostring(redside))
  773.                    end
  774.                    rednet.send(serverID, textutils.serialize(info), false)
  775.                 end
  776.              end
  777.                     end
  778.                     sleep(math.random(1,5))
  779.       end
  780.     end
  781.      
  782.     -------------------------------------------------------
  783.     -- Hardware setup and detection
  784.     -------------------------------------------------------
  785.     local hw = hardwareDetector()
  786.     local screenSide, _, _ = hw.find("monitor:advanced");
  787.     local bridgeSide, _, _ = hw.find("openperipheral_glassesbridge");
  788.     local modemSide, _, _ = hardwareDetector("modem:wireless")
  789.     lstTanks = hw.getList(tankTypes)
  790.      
  791.     if (modemSide) then
  792.         local modem = peripheral.wrap(modemSide)
  793.     else
  794.         error("A wireless modem must be attached to this computer.")
  795.     end
  796.      
  797.     if (#lstTanks > 0) and (bridgeSide or screenSide) then
  798.         error("Either a screen or a tank valve can be connected, not both.")
  799.     end
  800.      
  801.     if (screenSide) then
  802.        monitor = peripheral.wrap(screenSide)
  803.             if(not monitor.isColor()) then
  804.                     error("The attached monitor must be Advanced.  Get some gold!")
  805.             end
  806.        screenw, screenh = monitor.getSize()
  807.             clm()
  808.     end
  809.     if (bridgeSide) then
  810.        bridge["peripheral"] = peripheral.wrap(bridgeSide)
  811.        clb()
  812.     end
  813.      
  814.     ---------------------------------------
  815.     --the Main
  816.     ---------------------------------------
  817.      
  818.     rednet.open(modemSide)
  819.     if (#lstTanks > 0) then
  820.         -- client mode
  821.             redLimit = args[1]
  822.             redside = args[2]
  823.             if (redLimit and not redside) then
  824.                     print("A threshold and redstone side must both be present.")
  825.                     print("e.g. tankmon 100 top")
  826.                     error()
  827.             end
  828.             if (redLimit) then
  829.                     redLimit = tonumber(redLimit)
  830.                     print("")
  831.                     print("Tank will send redstone signal at or below " .. tostring(redLimit) .. "% on side " .. redside)
  832.             end
  833.             -- clear outstanding redstone signals.
  834.             for i,side in pairs(sides) do
  835.                     rs.setOutput(side, false)
  836.             end
  837.        parallel.waitForAll(connect, publishTank)
  838.     else
  839.         -- server mode
  840.         parallel.waitForAll(broadcast, receive, display)
  841.     end
  842.     rednet.close(modemSide)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement