Advertisement
LaughingLeader

ComputerCraft Smeltery Program

Jun 15th, 2016
143
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 14.49 KB | None | 0 0
  1. --Program Settings
  2. local programName = "Smeltery Program";
  3. local version = "1.0";
  4. local debugMode = false;
  5. local printMessages = true;
  6. -- The interval at which the main loop runs (a.k.a. how long the program sleeps).
  7. local loopDelay = 1;
  8. -- The delay between checking items. We use this to make things easier on the game/server.
  9. local checkDelay = 0.25;
  10.  
  11. -- The last printed message. Used to avoid duplicates.
  12. local lastMessage = "";
  13.  
  14. --Inventory sides.
  15. local smelteryID = "crafters_smeltery_1";
  16. local drainID = "tconstruct_smelterydrain_1";
  17. local chestID = "iron_2";
  18. local monitorID = "up";
  19.  
  20. --Where the smeltery controller is in relation to the chest.
  21. local smelteryDirection = "NORTH";
  22. local innerTankSide = "UP";
  23.  
  24. --Smelt everything containing this word (that doesn't match the blacklist).
  25. local smelteryKeyword = " Ore";
  26. --Items to not smelt (easier than putting in all the ones that work).
  27. local smelteryBlacklist = {"Redstone", "Diamond", "Shiny", "Lapis",
  28. "Coal", "Amber", "Sapphire", "Ruby", "Peridot", "Salt", "Sulfur", "Platinum", "Nikolite", "Emerald"};
  29. --Liquids that don't have proper names. Used for matching.
  30. local specialLiquids = {};
  31. specialLiquids["fluid.bigreactors.yellorium.still"] = "Yellorium";
  32.  
  33. local alloys = {};
  34. alloys["Brass"]     = {"Aluminum", "Copper"};
  35. alloys["Bronze"]    = {"Tin", "Copper"};
  36. alloys["Electrum"]  = {"Silver", "Gold"};
  37. alloys["Alumite"]   = {"Obsidian", "Iron", "Aluminum"};
  38. alloys["Manyullyn"] = {"Cobalt", "Ardite"};
  39. alloys["Invar"]     = {"Ferrous", "Iron"};
  40. alloys["Pig Iron"]  = {"Emerald", "Iron", "Blood"};
  41.  
  42. --Peripherals
  43. local inputChest = nil;
  44. local smelteryController = nil;
  45. local smelteryDrain = nil;
  46. local smelteryMonitor = nil;
  47.  
  48. local tankSide = nil;
  49.  
  50. --Table functions
  51. local function deepcopy(o, seen)
  52.   seen = seen or {}
  53.   if o == nil then return nil end
  54.   if seen[o] then return seen[o] end
  55.  
  56.   local no
  57.   if type(o) == 'table' then
  58.     no = {}
  59.     seen[o] = no
  60.  
  61.     for k, v in next, o, nil do
  62.       no[deepcopy(k, seen)] = deepcopy(v, seen)
  63.     end
  64.     setmetatable(no, deepcopy(getmetatable(o), seen))
  65.   else -- number, string, boolean, etc
  66.     no = o
  67.   end
  68.   return no
  69. end
  70.  
  71. --*Wrap peripherals*
  72. local function InitPeripherals()
  73.     inputChest = peripheral.wrap(chestID);
  74.     smelteryController = peripheral.wrap(smelteryID);
  75.     smelteryDrain = peripheral.wrap(drainID);
  76.     smelteryMonitor = peripheral.wrap(monitorID);
  77.    
  78.     if inputChest ~= nil and smelteryController ~= nil and smelteryDrain ~= nil then
  79.         return true;
  80.     end
  81.    
  82.     return false;
  83. end
  84.  
  85. local function PrintMessage(message, isDebugMessage)
  86.     if isDebugMessage == nil then isDebugMessage = false end;
  87.    
  88.     if (printMessages == true and message ~= lastMessage) and (isDebugMessage == false or (isDebugMessage == true and debugMode == true)) then
  89.         print(message);
  90.         lastMessage = message;
  91.     end
  92. end
  93.  
  94. local function TrimSpaces(s)
  95.     return s:match( "^%s*(.-)%s*$" );
  96.     --return string.gsub(s, "%s$", "");
  97. end
  98.  
  99. local function MoveItem(direction, fromSlot)
  100.     if debugMode == false then
  101.         inputChest.pushItem(direction, fromSlot, 64);
  102.     end
  103. end
  104.  
  105. local function GetTankInfo(tank)
  106.     local data = tank.getTankInfo("unknown");
  107.     --print("data: "..tostring(data));
  108.     return data;
  109. end
  110.  
  111. local function TrimName(name)
  112.     local trimmedName = name;
  113.     trimmedName = string.gsub(trimmedName, "Ore", "");
  114.     trimmedName = string.gsub(trimmedName, "Gravel", "");
  115.     trimmedName = string.gsub(trimmedName, "Nether", "");
  116.     trimmedName = string.gsub(trimmedName, "Molten", "");
  117.     trimmedName = TrimSpaces(trimmedName);
  118.     return trimmedName;
  119. end
  120.  
  121. local function CaseInsensitiveMatch(s1, s2)
  122.     return string.lower(TrimName(s1)) == string.lower(TrimName(s2));
  123. end
  124.  
  125. local function ItemInInventory(name, inventory)
  126.     if inventory ~= nil then
  127.    
  128.         local maxSlots = inventory.getInventorySize();
  129.        
  130.         if maxSlots ~= nil and maxSlots > 0 then
  131.        
  132.             for i=1,maxSlots,1
  133.             do
  134.                 local item = inventory.getStackInSlot(i);
  135.                 if item ~= nil then
  136.                     local itemName = item["display_name"];
  137.                     local result = string.find(name, itemName);
  138.                     if result ~= nil then
  139.                         return true;
  140.                     end
  141.                 end
  142.             end
  143.         end
  144.        
  145.     end
  146.    
  147.     return false;
  148. end
  149.  
  150. --Match a name to a list.
  151. local function MatchList(item, list)
  152.     for k, v in pairs(list) do
  153.    
  154.         local result = string.find(item, v);
  155.         if debugMode then
  156.             --print("Item: "..item.." List["..k.."]: "..v);
  157.             --print(result);
  158.         end
  159.        
  160.         if result ~= nil then
  161.             return true;
  162.         end
  163.     end
  164.    
  165.     return false;
  166. end
  167.  
  168. -- Match a name to the liquids in the smeltery. If trimMolten is true, then Molten is taken out of the liquid name.
  169. -- This allows for strict matching (i.e. "Aluminum Ore" and "Molten Aluminum" is trimmed to "Aluminum", and checked for equality.
  170. local function MatchTank(name, trimMolten)
  171.     local matchFound = false;
  172.     if name ~= nil then
  173.         if trimMolten == nil then trimMolten = false end;
  174.        
  175.         local data = GetTankInfo(smelteryDrain);
  176.        
  177.         for key, tank in pairs(data) do
  178.             if tank ~= nil and tank.contents ~= nil then
  179.                 local liquidName = TrimSpaces(tank.contents.rawName);
  180.                
  181.                 if trimMolten == true then
  182.                    
  183.                     local fixedName = false;
  184.                    
  185.                     for name1, fixedname in pairs(specialLiquids) do
  186.                         if liquidName == name1 then
  187.                             liquidName = fixedname;
  188.                             fixedName = true;
  189.                             break;
  190.                         end
  191.                     end
  192.                    
  193.                     local matchLiquid = liquidName;
  194.                     if fixedName == false then
  195.                         matchLiquid = string.gsub(liquidName, "Molten ", "");
  196.                     end
  197.                    
  198.                     local result = string.find(name, matchLiquid);
  199.                     if result ~= nil then
  200.                         matchFound = true;
  201.                         break;
  202.                     end
  203.                    
  204.                 else
  205.                     local result = string.find(name, liquidName);
  206.                     if result ~= nil then
  207.                         matchFound = true;
  208.                         break;
  209.                     end
  210.                 end
  211.             end
  212.         end
  213.  
  214.             --print(liquid["rawName"])  --The name of the liquid, as it is called in game
  215.             --print(liquid["amount"])  --The current amount of the liquid in the tank
  216.             --print(liquid["capacity"])  --The total capacity of the liquid in the tank
  217.             --print(liquid["name"])  --The name of the liquid, as it is called in the source code
  218.             --print(liquid["id"])  --The ID of the liquid
  219.     end
  220.    
  221.     return matchFound;
  222. end
  223.  
  224. local function OreWillAlloyInInventory(ore)
  225.     if smelteryController ~= nil then
  226.        
  227.         local maxSlots = smelteryController.getInventorySize();
  228.        
  229.         if maxSlots ~= nil and maxSlots > 0 then
  230.        
  231.             for i=1,maxSlots,1
  232.             do
  233.                 local item = smelteryController.getStackInSlot(i);
  234.                 if item ~= nil then
  235.                     local itemName = TrimName(item["display_name"]);
  236.                     local result = string.lower(ore) == string.lower(itemName);
  237.                     if result == true then
  238.                         return true;
  239.                     end
  240.                 end
  241.             end
  242.         end
  243.        
  244.     end
  245.    
  246.     return false;
  247.  
  248. end
  249.  
  250. local function OreWillAlloy(ore)
  251.     local matchFound = false;
  252.     if ore ~= nil then
  253.        
  254.         local data = GetTankInfo(smelteryDrain);
  255.         local oreInSmeltery = {};
  256.        
  257.         for key, tank in pairs(data) do
  258.             if tank ~= nil and tank.contents ~= nil then
  259.                 local liquidName = TrimSpaces(tank.contents.rawName);
  260.                
  261.                 local fixedName = false;
  262.                    
  263.                 for k, fixedname in pairs(specialLiquids) do
  264.                     if liquidName == k then
  265.                         liquidName = fixedname;
  266.                         fixedName = true;
  267.                         break;
  268.                     end
  269.                 end
  270.                
  271.                 local matchLiquid = liquidName;
  272.                 if fixedName == false then
  273.                     matchLiquid = TrimName(liquidName);
  274.                 end
  275.                
  276.                 table.insert(oreInSmeltery, matchLiquid);
  277.                
  278.                 PrintMessage("Added "..matchLiquid.." to liquids to check.", true);
  279.             end
  280.         end
  281.        
  282.         if smelteryController ~= nil then
  283.            
  284.             local maxSlots = smelteryController.getInventorySize();
  285.            
  286.             if maxSlots ~= nil and maxSlots > 0 then
  287.            
  288.                 for i=1,maxSlots,1
  289.                 do
  290.                     local item = smelteryController.getStackInSlot(i);
  291.                     if item ~= nil then
  292.                         local itemName = TrimName(item["display_name"]);
  293.                         table.insert(oreInSmeltery, itemName);
  294.                        
  295.                         PrintMessage("Added "..itemName.." to items to check.", true);
  296.                     end
  297.                 end
  298.             end
  299.            
  300.         end
  301.        
  302.         for alloyName, metals in pairs(alloys) do
  303.             for mkey, metalName in pairs(metals) do
  304.                 --PrintMessage("["..string.lower(metalName).."]=>["..string.lower(ore).."]", true);
  305.                 if CaseInsensitiveMatch(metalName, ore) == true then
  306.                    
  307.                     PrintMessage(ore.." found in alloy "..alloyName..".");
  308.                    
  309.                     local otherMetals = deepcopy(metals);
  310.                     otherMetals[mkey] = nil;
  311.                    
  312.                     for lkey, val in ipairs(oreInSmeltery) do
  313.                         local matched = 0;
  314.                         local total = 0;
  315.                        
  316.                         for mkey2, mname in pairs(otherMetals) do
  317.                             --PrintMessage("["..string.lower(val).."]=>["..string.lower(mname).."]", true);
  318.                             if CaseInsensitiveMatch(val, mname) == true then
  319.                                 PrintMessage(val.." matches "..mname..".", true);
  320.                                 matched = matched + 1;
  321.                             end
  322.                         end
  323.                        
  324.                         total = total + 1;
  325.                        
  326.                         if matched >= total then
  327.                             --PrintMessage(ore.." will alloy with liquids in Smeltery. Skipping.");
  328.                             return true;
  329.                         end
  330.                     end
  331.                 end
  332.             end
  333.         end
  334.            
  335.         return false;
  336.     end
  337. end
  338.  
  339. local function OreInTank(name)
  340.     return MatchTank(TrimName(name), true);
  341. end
  342.  
  343. local function GetMethods(peripheralID)
  344.     print("Checking methods for "..peripheralID);
  345.     for i,v in ipairs(peripheral.getMethods(peripheralID))
  346.       do print(i..". "..v)
  347.     end
  348. end
  349.  
  350. -- Get slots filled in an inventory.
  351. local function SlotsFilled(inventory, condenseItems)
  352.     local slots = 0;
  353.     if inventory ~= nil then
  354.         if condenseItems == nil then condenseItems = false; end;
  355.        
  356.         local maxSlots = inventory.getInventorySize();
  357.        
  358.         if maxSlots ~= nil and maxSlots > 0 then
  359.             if condenseItems == true then
  360.                 inventory.condenseItems();
  361.             end
  362.            
  363.             for i=1,maxSlots,1
  364.             do
  365.                 local item = inventory.getStackInSlot(i);
  366.                 if item ~= nil then
  367.                     slots = slots + 1;
  368.                 end
  369.             end
  370.         end
  371.        
  372.     end
  373.     return slots;
  374. end
  375.  
  376. local function InventoryEmpty(inventory, condenseItems)
  377.     local slots = SlotsFilled(inventory, condenseItems);
  378.     return slots == 0;
  379. end
  380.  
  381. local function TankEmpty(tank)
  382.  
  383.     local data = GetTankInfo(tank);
  384.    
  385.     if data ~= nil then
  386.         --if debugMode == true then PrintMessage(result); end;
  387.         for k, tank in pairs(data) do
  388.             if tank ~= nil and tank.contents ~= nil then
  389.                 return false;
  390.             end
  391.         end
  392.     end
  393.    
  394.     return true;
  395. end
  396.  
  397. local function InventoryFull(inventory, condenseItems)
  398.     local maxSlots = inventory.getInventorySize();
  399.     local slots = SlotsFilled(inventory, condenseItems);
  400.    
  401.     return slots >= maxSlots;
  402. end
  403.  
  404. --The main loop of the program.
  405. local function ProgramLoop(delay)
  406.     if delay == nil or delay <= 0 then
  407.         delay = 1;
  408.     end
  409.    
  410.     local inputEmpty = InventoryEmpty(inputChest);
  411.     local smelteryFull = InventoryFull(smelteryController);
  412.    
  413.     if inputEmpty == false and smelteryFull == false then
  414.    
  415.         local maxSlots = inputChest.getInventorySize();
  416.    
  417.         if maxSlots ~= nil and maxSlots > 0 then
  418.  
  419.             inputChest.condenseItems();
  420.  
  421.             for i=1,maxSlots,1
  422.             do
  423.                 local item = inputChest.getStackInSlot(i);
  424.                 if item ~= nil then
  425.                     local itemName = item["display_name"];
  426.                     local matchFound = false;
  427.                    
  428.                     if string.find(itemName, smelteryKeyword) ~= nil then
  429.                         if MatchList(itemName, smelteryBlacklist) == false then
  430.                             -- Check if the controller is full, then if the tank is empty or the same liquid exists.
  431.                             -- We avoid creating alloys this way.
  432.                             if InventoryFull(smelteryController) == false then
  433.                                 local tankEmpty = TankEmpty(smelteryDrain);
  434.                                 if tankEmpty == true then
  435.                                     if InventoryEmpty(smelteryController) == true then
  436.                                         PrintMessage("Tank and Controller are empty. Moving "..itemName.." to Smeltery.");
  437.                                         MoveItem(smelteryDirection, i);
  438.                                         matchFound = true;
  439.                                     else
  440.                                         if ItemInInventory(itemName, smelteryController) == true then
  441.                                             PrintMessage("Same item is in Controller. Moving "..itemName.." to Smeltery.");
  442.                                             MoveItem(smelteryDirection, i);
  443.                                             matchFound = true;
  444.                                         else
  445.                                             PrintMessage("Checking for alloys...");
  446.                                             if OreWillAlloy(itemName) == false then
  447.                                                 PrintMessage("Ore will not alloy. Moving "..itemName.." to Smeltery. [TankEmpty]");
  448.                                                 MoveItem(smelteryDirection, i);
  449.                                                 matchFound = true;
  450.                                             else
  451.                                                 PrintMessage("Smeltery Controller contains a different item than "..itemName..". Skipping.");
  452.                                             end
  453.                                         end
  454.                                     end
  455.                                 else
  456.                                     PrintMessage("Checking for alloys...");
  457.                                     if OreWillAlloy(itemName) == false then
  458.                                         PrintMessage("Ore will not alloy. Moving "..itemName.." to Smeltery. [TankNotEmpty]");
  459.                                         MoveItem(smelteryDirection, i);
  460.                                         matchFound = true;
  461.                                         -- if OreInTank(itemName) == true then
  462.                                             -- PrintMessage("Same item is in Tank. Moving "..itemName.." to Smeltery.");
  463.                                             -- MoveItem(smelteryDirection, i);
  464.                                             -- matchFound = true;
  465.                                         -- else
  466.                                            
  467.                                            
  468.                                         -- end
  469.                                     else
  470.                                         PrintMessage(itemName.." will alloy with other liquids if melted. Skipping.");
  471.                                     end
  472.                                    
  473.                                 end
  474.                             else
  475.                                 PrintMessage("Smeltery Controller is full. Skipping");
  476.                             end
  477.                         end
  478.                     end
  479.                    
  480.                     if checkDelay > 0 then
  481.                         os.sleep(checkDelay);
  482.                     end
  483.                 end
  484.             end
  485.         end
  486.     else
  487.         if inputEmpty == true then
  488.             PrintMessage("Input chest is empty. Sleeping...");
  489.             delay = delay * 3;
  490.         elseif smelteryFull == true then
  491.             PrintMessage("Smeltery is full.");
  492.         end
  493.     end
  494.    
  495.     os.sleep(delay);
  496. end
  497.  
  498. -- This is where we actually start the program loop.
  499. local function InitProgram()
  500.     if InitPeripherals() == true then
  501.        
  502.         print("Running "..programName.." v"..version);
  503.        
  504.         local programRunning = true;
  505.        
  506.         while programRunning == true do
  507.  
  508.             ProgramLoop(loopDelay);
  509.            
  510.             --if debugMode == false then
  511.                 --ProgramLoop(loopDelay);
  512.                
  513.             --else
  514.                 --GetChestFunctions();
  515.                 --GetMethods(drainID);
  516.                 --GetMethods(smelteryID);
  517.                 --CheckTank();
  518.                
  519.                 -- local isEmpty = "true";
  520.                 -- if InventoryEmpty(smelteryController) == false then
  521.                     -- isEmpty = "false";
  522.                 -- end
  523.                
  524.                 -- print("Controller empty: "..isEmpty);
  525.                 -- programRunning = false;
  526.             -- end
  527.         end
  528.  
  529.         print(programName.." ended.");
  530.     else
  531.         if inputChest == nil then print("Input Chest could not be found.") end;
  532.         if smelteryController == nil then print("Smeltery Controller could not be found.") end;
  533.         if smelteryDrain == nil then print("Smeltery Drain could not be found.") end;
  534.     end
  535. end
  536.  
  537. InitProgram();
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement