Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --Program Settings
- local programName = "Smeltery Program";
- local version = "1.0";
- local debugMode = false;
- local printMessages = true;
- -- The interval at which the main loop runs (a.k.a. how long the program sleeps).
- local loopDelay = 1;
- -- The delay between checking items. We use this to make things easier on the game/server.
- local checkDelay = 0.25;
- -- The last printed message. Used to avoid duplicates.
- local lastMessage = "";
- --Inventory sides.
- local smelteryID = "crafters_smeltery_1";
- local drainID = "tconstruct_smelterydrain_1";
- local chestID = "iron_2";
- local monitorID = "up";
- --Where the smeltery controller is in relation to the chest.
- local smelteryDirection = "NORTH";
- local innerTankSide = "UP";
- --Smelt everything containing this word (that doesn't match the blacklist).
- local smelteryKeyword = " Ore";
- --Items to not smelt (easier than putting in all the ones that work).
- local smelteryBlacklist = {"Redstone", "Diamond", "Shiny", "Lapis",
- "Coal", "Amber", "Sapphire", "Ruby", "Peridot", "Salt", "Sulfur", "Platinum", "Nikolite", "Emerald"};
- --Liquids that don't have proper names. Used for matching.
- local specialLiquids = {};
- specialLiquids["fluid.bigreactors.yellorium.still"] = "Yellorium";
- local alloys = {};
- alloys["Brass"] = {"Aluminum", "Copper"};
- alloys["Bronze"] = {"Tin", "Copper"};
- alloys["Electrum"] = {"Silver", "Gold"};
- alloys["Alumite"] = {"Obsidian", "Iron", "Aluminum"};
- alloys["Manyullyn"] = {"Cobalt", "Ardite"};
- alloys["Invar"] = {"Ferrous", "Iron"};
- alloys["Pig Iron"] = {"Emerald", "Iron", "Blood"};
- --Peripherals
- local inputChest = nil;
- local smelteryController = nil;
- local smelteryDrain = nil;
- local smelteryMonitor = nil;
- local tankSide = nil;
- --Table functions
- local function deepcopy(o, seen)
- seen = seen or {}
- if o == nil then return nil end
- if seen[o] then return seen[o] end
- local no
- if type(o) == 'table' then
- no = {}
- seen[o] = no
- for k, v in next, o, nil do
- no[deepcopy(k, seen)] = deepcopy(v, seen)
- end
- setmetatable(no, deepcopy(getmetatable(o), seen))
- else -- number, string, boolean, etc
- no = o
- end
- return no
- end
- --*Wrap peripherals*
- local function InitPeripherals()
- inputChest = peripheral.wrap(chestID);
- smelteryController = peripheral.wrap(smelteryID);
- smelteryDrain = peripheral.wrap(drainID);
- smelteryMonitor = peripheral.wrap(monitorID);
- if inputChest ~= nil and smelteryController ~= nil and smelteryDrain ~= nil then
- return true;
- end
- return false;
- end
- local function PrintMessage(message, isDebugMessage)
- if isDebugMessage == nil then isDebugMessage = false end;
- if (printMessages == true and message ~= lastMessage) and (isDebugMessage == false or (isDebugMessage == true and debugMode == true)) then
- print(message);
- lastMessage = message;
- end
- end
- local function TrimSpaces(s)
- return s:match( "^%s*(.-)%s*$" );
- --return string.gsub(s, "%s$", "");
- end
- local function MoveItem(direction, fromSlot)
- if debugMode == false then
- inputChest.pushItem(direction, fromSlot, 64);
- end
- end
- local function GetTankInfo(tank)
- local data = tank.getTankInfo("unknown");
- --print("data: "..tostring(data));
- return data;
- end
- local function TrimName(name)
- local trimmedName = name;
- trimmedName = string.gsub(trimmedName, "Ore", "");
- trimmedName = string.gsub(trimmedName, "Gravel", "");
- trimmedName = string.gsub(trimmedName, "Nether", "");
- trimmedName = string.gsub(trimmedName, "Molten", "");
- trimmedName = TrimSpaces(trimmedName);
- return trimmedName;
- end
- local function CaseInsensitiveMatch(s1, s2)
- return string.lower(TrimName(s1)) == string.lower(TrimName(s2));
- end
- local function ItemInInventory(name, inventory)
- if inventory ~= nil then
- local maxSlots = inventory.getInventorySize();
- if maxSlots ~= nil and maxSlots > 0 then
- for i=1,maxSlots,1
- do
- local item = inventory.getStackInSlot(i);
- if item ~= nil then
- local itemName = item["display_name"];
- local result = string.find(name, itemName);
- if result ~= nil then
- return true;
- end
- end
- end
- end
- end
- return false;
- end
- --Match a name to a list.
- local function MatchList(item, list)
- for k, v in pairs(list) do
- local result = string.find(item, v);
- if debugMode then
- --print("Item: "..item.." List["..k.."]: "..v);
- --print(result);
- end
- if result ~= nil then
- return true;
- end
- end
- return false;
- end
- -- Match a name to the liquids in the smeltery. If trimMolten is true, then Molten is taken out of the liquid name.
- -- This allows for strict matching (i.e. "Aluminum Ore" and "Molten Aluminum" is trimmed to "Aluminum", and checked for equality.
- local function MatchTank(name, trimMolten)
- local matchFound = false;
- if name ~= nil then
- if trimMolten == nil then trimMolten = false end;
- local data = GetTankInfo(smelteryDrain);
- for key, tank in pairs(data) do
- if tank ~= nil and tank.contents ~= nil then
- local liquidName = TrimSpaces(tank.contents.rawName);
- if trimMolten == true then
- local fixedName = false;
- for name1, fixedname in pairs(specialLiquids) do
- if liquidName == name1 then
- liquidName = fixedname;
- fixedName = true;
- break;
- end
- end
- local matchLiquid = liquidName;
- if fixedName == false then
- matchLiquid = string.gsub(liquidName, "Molten ", "");
- end
- local result = string.find(name, matchLiquid);
- if result ~= nil then
- matchFound = true;
- break;
- end
- else
- local result = string.find(name, liquidName);
- if result ~= nil then
- matchFound = true;
- break;
- end
- end
- end
- end
- --print(liquid["rawName"]) --The name of the liquid, as it is called in game
- --print(liquid["amount"]) --The current amount of the liquid in the tank
- --print(liquid["capacity"]) --The total capacity of the liquid in the tank
- --print(liquid["name"]) --The name of the liquid, as it is called in the source code
- --print(liquid["id"]) --The ID of the liquid
- end
- return matchFound;
- end
- local function OreWillAlloyInInventory(ore)
- if smelteryController ~= nil then
- local maxSlots = smelteryController.getInventorySize();
- if maxSlots ~= nil and maxSlots > 0 then
- for i=1,maxSlots,1
- do
- local item = smelteryController.getStackInSlot(i);
- if item ~= nil then
- local itemName = TrimName(item["display_name"]);
- local result = string.lower(ore) == string.lower(itemName);
- if result == true then
- return true;
- end
- end
- end
- end
- end
- return false;
- end
- local function OreWillAlloy(ore)
- local matchFound = false;
- if ore ~= nil then
- local data = GetTankInfo(smelteryDrain);
- local oreInSmeltery = {};
- for key, tank in pairs(data) do
- if tank ~= nil and tank.contents ~= nil then
- local liquidName = TrimSpaces(tank.contents.rawName);
- local fixedName = false;
- for k, fixedname in pairs(specialLiquids) do
- if liquidName == k then
- liquidName = fixedname;
- fixedName = true;
- break;
- end
- end
- local matchLiquid = liquidName;
- if fixedName == false then
- matchLiquid = TrimName(liquidName);
- end
- table.insert(oreInSmeltery, matchLiquid);
- PrintMessage("Added "..matchLiquid.." to liquids to check.", true);
- end
- end
- if smelteryController ~= nil then
- local maxSlots = smelteryController.getInventorySize();
- if maxSlots ~= nil and maxSlots > 0 then
- for i=1,maxSlots,1
- do
- local item = smelteryController.getStackInSlot(i);
- if item ~= nil then
- local itemName = TrimName(item["display_name"]);
- table.insert(oreInSmeltery, itemName);
- PrintMessage("Added "..itemName.." to items to check.", true);
- end
- end
- end
- end
- for alloyName, metals in pairs(alloys) do
- for mkey, metalName in pairs(metals) do
- --PrintMessage("["..string.lower(metalName).."]=>["..string.lower(ore).."]", true);
- if CaseInsensitiveMatch(metalName, ore) == true then
- PrintMessage(ore.." found in alloy "..alloyName..".");
- local otherMetals = deepcopy(metals);
- otherMetals[mkey] = nil;
- for lkey, val in ipairs(oreInSmeltery) do
- local matched = 0;
- local total = 0;
- for mkey2, mname in pairs(otherMetals) do
- --PrintMessage("["..string.lower(val).."]=>["..string.lower(mname).."]", true);
- if CaseInsensitiveMatch(val, mname) == true then
- PrintMessage(val.." matches "..mname..".", true);
- matched = matched + 1;
- end
- end
- total = total + 1;
- if matched >= total then
- --PrintMessage(ore.." will alloy with liquids in Smeltery. Skipping.");
- return true;
- end
- end
- end
- end
- end
- return false;
- end
- end
- local function OreInTank(name)
- return MatchTank(TrimName(name), true);
- end
- local function GetMethods(peripheralID)
- print("Checking methods for "..peripheralID);
- for i,v in ipairs(peripheral.getMethods(peripheralID))
- do print(i..". "..v)
- end
- end
- -- Get slots filled in an inventory.
- local function SlotsFilled(inventory, condenseItems)
- local slots = 0;
- if inventory ~= nil then
- if condenseItems == nil then condenseItems = false; end;
- local maxSlots = inventory.getInventorySize();
- if maxSlots ~= nil and maxSlots > 0 then
- if condenseItems == true then
- inventory.condenseItems();
- end
- for i=1,maxSlots,1
- do
- local item = inventory.getStackInSlot(i);
- if item ~= nil then
- slots = slots + 1;
- end
- end
- end
- end
- return slots;
- end
- local function InventoryEmpty(inventory, condenseItems)
- local slots = SlotsFilled(inventory, condenseItems);
- return slots == 0;
- end
- local function TankEmpty(tank)
- local data = GetTankInfo(tank);
- if data ~= nil then
- --if debugMode == true then PrintMessage(result); end;
- for k, tank in pairs(data) do
- if tank ~= nil and tank.contents ~= nil then
- return false;
- end
- end
- end
- return true;
- end
- local function InventoryFull(inventory, condenseItems)
- local maxSlots = inventory.getInventorySize();
- local slots = SlotsFilled(inventory, condenseItems);
- return slots >= maxSlots;
- end
- --The main loop of the program.
- local function ProgramLoop(delay)
- if delay == nil or delay <= 0 then
- delay = 1;
- end
- local inputEmpty = InventoryEmpty(inputChest);
- local smelteryFull = InventoryFull(smelteryController);
- if inputEmpty == false and smelteryFull == false then
- local maxSlots = inputChest.getInventorySize();
- if maxSlots ~= nil and maxSlots > 0 then
- inputChest.condenseItems();
- for i=1,maxSlots,1
- do
- local item = inputChest.getStackInSlot(i);
- if item ~= nil then
- local itemName = item["display_name"];
- local matchFound = false;
- if string.find(itemName, smelteryKeyword) ~= nil then
- if MatchList(itemName, smelteryBlacklist) == false then
- -- Check if the controller is full, then if the tank is empty or the same liquid exists.
- -- We avoid creating alloys this way.
- if InventoryFull(smelteryController) == false then
- local tankEmpty = TankEmpty(smelteryDrain);
- if tankEmpty == true then
- if InventoryEmpty(smelteryController) == true then
- PrintMessage("Tank and Controller are empty. Moving "..itemName.." to Smeltery.");
- MoveItem(smelteryDirection, i);
- matchFound = true;
- else
- if ItemInInventory(itemName, smelteryController) == true then
- PrintMessage("Same item is in Controller. Moving "..itemName.." to Smeltery.");
- MoveItem(smelteryDirection, i);
- matchFound = true;
- else
- PrintMessage("Checking for alloys...");
- if OreWillAlloy(itemName) == false then
- PrintMessage("Ore will not alloy. Moving "..itemName.." to Smeltery. [TankEmpty]");
- MoveItem(smelteryDirection, i);
- matchFound = true;
- else
- PrintMessage("Smeltery Controller contains a different item than "..itemName..". Skipping.");
- end
- end
- end
- else
- PrintMessage("Checking for alloys...");
- if OreWillAlloy(itemName) == false then
- PrintMessage("Ore will not alloy. Moving "..itemName.." to Smeltery. [TankNotEmpty]");
- MoveItem(smelteryDirection, i);
- matchFound = true;
- -- if OreInTank(itemName) == true then
- -- PrintMessage("Same item is in Tank. Moving "..itemName.." to Smeltery.");
- -- MoveItem(smelteryDirection, i);
- -- matchFound = true;
- -- else
- -- end
- else
- PrintMessage(itemName.." will alloy with other liquids if melted. Skipping.");
- end
- end
- else
- PrintMessage("Smeltery Controller is full. Skipping");
- end
- end
- end
- if checkDelay > 0 then
- os.sleep(checkDelay);
- end
- end
- end
- end
- else
- if inputEmpty == true then
- PrintMessage("Input chest is empty. Sleeping...");
- delay = delay * 3;
- elseif smelteryFull == true then
- PrintMessage("Smeltery is full.");
- end
- end
- os.sleep(delay);
- end
- -- This is where we actually start the program loop.
- local function InitProgram()
- if InitPeripherals() == true then
- print("Running "..programName.." v"..version);
- local programRunning = true;
- while programRunning == true do
- ProgramLoop(loopDelay);
- --if debugMode == false then
- --ProgramLoop(loopDelay);
- --else
- --GetChestFunctions();
- --GetMethods(drainID);
- --GetMethods(smelteryID);
- --CheckTank();
- -- local isEmpty = "true";
- -- if InventoryEmpty(smelteryController) == false then
- -- isEmpty = "false";
- -- end
- -- print("Controller empty: "..isEmpty);
- -- programRunning = false;
- -- end
- end
- print(programName.." ended.");
- else
- if inputChest == nil then print("Input Chest could not be found.") end;
- if smelteryController == nil then print("Smeltery Controller could not be found.") end;
- if smelteryDrain == nil then print("Smeltery Drain could not be found.") end;
- end
- end
- InitProgram();
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement