Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Filenames = {}
- Filenames.configFolder = "config"
- Filenames.tankContents = Filenames.configFolder.."/tank_contents.json"
- Filenames.potionTypes = Filenames.configFolder.."/potion_types.json"
- Filenames.fuelItems = Filenames.configFolder.."/blaze_fuels.txt"
- ItemNames = {
- redstone = "minecraft:redstone",
- glowstone = "minecraft:glowstone_dust",
- gunpowder = "minecraft:gunpowder",
- dragonBreath = "minecraft:dragon_breath",
- netherwart = "minecraft:nether_wart",
- bottle = "minecraft:glass_bottle"
- }
- term.clear()
- term.setCursorPos(1,1)
- term.setTextColor(colors.white)
- if not fs.exists(Filenames.potionTypes) then
- print("Downloading potion types config...")
- shell.run("pastebin","get","YBSC0sGp",Filenames.potionTypes)
- end
- UNKNOWN = "unknown"
- string.startsWith = function(self,str)
- return self:find("^"..str)
- end
- string.split = function(self,sep)
- if sep == nil then
- sep = "%s"
- end
- local t = {}
- for str in self:gmatch("([^"..sep.."]+)") do
- table.insert(t,str)
- end
- return t
- end
- table.contains = function(self,value)
- for _, v in ipairs(self) do
- if v == value then
- return true
- end
- end
- return false
- end
- PotionTypes = {
- definitions=nil,
- aliases={},
- initialize=function()
- print("Initializing potion definitions...")
- PotionTypes.definitions = {}
- PotionTypes.aliases = {}
- local potionTypes = {}
- if not pcall(function()
- local h = fs.open(Filenames.potionTypes,"r")
- local data = h.readAll()
- h.close()
- potionTypes = textutils.unserializeJSON(data)
- end) then
- --failed to decode file and load potion types
- clearTerm()
- printError("An error occurred while reading potion types config")
- return false
- end
- for typeName,typeData in pairs(potionTypes) do
- PotionTypes.addDefinition(typeName,PotionDefinition:new(typeData))
- end
- return true
- end,
- addDefinition=function(name,definition)
- PotionTypes.definitions[name] = definition
- for _,displayName in ipairs(definition.names) do
- PotionTypes.aliases[string.lower(displayName)] = name
- end
- end,
- getInternalName=function(name)
- if name == nil then return nil end
- name = string.lower(name)
- if PotionTypes.definitions[name] ~= nil then return name end
- if PotionTypes.aliases[name] ~= nil then return PotionTypes.aliases[name] end
- end,
- getDefinition=function(name)
- local internalName = PotionTypes.getInternalName(name)
- if internalName == nil then return nil end
- return PotionTypes.definitions[internalName]
- end
- }
- PotionModifiers = {
- normal="Normal",
- extended="Extended",
- levelTwo="Level II",
- getList=function()
- return {
- PotionModifiers.normal,
- PotionModifiers.extended,
- PotionModifiers.levelTwo
- }
- end,
- isValid=function(value)
- return PotionModifiers.getModifier(value) ~= nil
- end,
- getModifier=function(value)
- if type(value) == "number" then return PotionModifiers.getList()[value] end
- value = string.lower(value)
- if value == string.lower(PotionModifiers.normal) then return PotionModifiers.normal end
- if value == string.lower(PotionModifiers.extended) then return PotionModifiers.extended end
- if value == string.lower(PotionModifiers.levelTwo) then return PotionModifiers.levelTwo end
- if value == "l2" then return PotionModifiers.levelTwo end
- if value == "level ii" then return PotionModifiers.levelTwo end
- if value == "ext" then return PotionModifiers.extended end
- return nil
- end,
- getItem=function(modifier)
- if modifier == PotionModifiers.extended then
- return ItemNames.redstone
- elseif modifier == PotionModifiers.levelTwo then
- return ItemNames.glowstone
- end
- return nil
- end
- }
- PotionStyles = {
- normal="Normal",
- splash="Splash",
- lingering="Lingering",
- getList=function()
- return {
- PotionStyles.normal,
- PotionStyles.splash,
- PotionStyles.lingering
- }
- end,
- isValid=function(value)
- return PotionStyles.getStyle(value) ~= nil
- end,
- getStyle=function(value)
- if type(value) == "number" then return PotionStyles.getList()[value] end
- value = string.lower(value)
- if value == string.lower(PotionStyles.normal) then return PotionStyles.normal end
- if value == string.lower(PotionStyles.splash) then return PotionStyles.splash end
- if value == string.lower(PotionStyles.lingering) then return PotionStyles.lingering end
- return nil
- end,
- getItem=function(style)
- if style == PotionStyles.splash then
- return ItemNames.gunpowder
- elseif style == PotionStyles.lingering then
- return ItemNames.dragonBreath
- end
- return nil
- end
- }
- PotionDefinition = {
- new=function(self,data)
- local o = {}
- setmetatable(o,self)
- self.__index = self
- o.names = List:new(data.names)
- o.recipes = RecipeList:new()
- for _,recipeData in ipairs(data.recipes) do
- o.recipes:addRecipe(Recipe:new(recipeData))
- end
- return o
- end
- }
- RecipeList = {
- new=function(self)
- local o = {}
- setmetatable(o,self)
- self.__index = self
- return o
- end,
- addRecipe=function(self,recipe)
- self:insert(recipe)
- end,
- --- Gets a list of recipes and the number of times each should be crafted
- --
- -- first return is a bool for whether or not the desired qty can be satisfied
- --
- -- second return is the list of recipes and quantities
- getCraftPlan=function(self,qty)
- local plan = List:new()
- for _,recipe in ipairs(self) do
- local maxCrafts = recipe:getMaxCrafts(qty)
- if maxCrafts > 0 then
- qty = qty - maxCrafts
- plan:insert({maxCrafts,recipe})
- if qty == 0 then
- break
- end
- end
- end
- return qty == 0, plan
- end,
- insert=table.insert,
- remove=table.remove,
- contains=table.contains
- }
- Recipe = {
- new=function(self,items)
- local o = {}
- o.items = List:new(items)
- setmetatable(o,self)
- self.__index = self
- return o
- end,
- getMaxCrafts=function(self,targetQty)
- local maxCrafts = targetQty
- for _,itemName in ipairs(self.items) do
- local available = Inventories.getItemCount(itemName)
- if available == 0 then return 0 end
- if maxCrafts == nil or available < maxCrafts then maxCrafts = available end
- end
- return maxCrafts
- end,
- checkMissingItems=function(self,qty,missingItems)
- for _,itemName in ipairs(self.items) do
- Inventories.checkMissingItem(itemName,qty,missingItems)
- end
- end
- }
- Potion = {
- new=function(self,type,modifier,style)
- local contents = {}
- contents.type = type
- contents.modifier = modifier or PotionStyles.normal
- contents.style = style or PotionStyles.normal
- setmetatable(contents,self)
- self.__index = self
- return contents
- end,
- matches=function(self,def)
- if def == nil then return false end
- if self.type ~= def.type then return false end
- if self.type == UNKNOWN then return true end
- return self.modifier == def.modifier and self.style == def.style
- end,
- canCreate=function(self,def)
- if def == nil or self.type == UNKNOWN then return false end
- if self.type ~= def.type then return false end
- if self.modifier ~= def.modifier then
- if def.modifier == PotionModifiers.normal then return false end
- if self.modifier ~= PotionModifiers.normal then return false end
- end
- if self.style ~= def.style then
- if def.style == PotionModifiers.normal then return false end
- if self.modifier ~= PotionModifiers.normal then return false end
- end
- return true
- end,
- isUnknown=function(self)
- return self.type == UNKNOWN
- end,
- getDisplayName=function(self)
- local fullPotionName = "Potion of "..PotionTypes.getDefinition(self.type).names[1]
- if self.style ~= PotionStyles.normal then
- fullPotionName = self.style.." "..fullPotionName
- end
- if self.modifier == PotionModifiers.extended then
- fullPotionName = PotionModifiers.extended.." "..fullPotionName
- elseif self.modifier == PotionModifiers.levelTwo then
- fullPotionName = fullPotionName.." II"
- end
- return fullPotionName
- end,
- getSaveObject=function(self)
- return {
- type=self.type,
- modifier=self.modifier,
- style=self.style
- }
- end
- }
- List = {
- new=function(self,t)
- local list = t or {}
- setmetatable(list,self)
- self.__index = self
- return list
- end,
- insert=table.insert,
- remove=table.remove,
- contains=table.contains
- }
- StorageTanks = {
- list={},
- findStorage=function(potion)
- local matchingTanks = List:new()
- local unknownTanks = List:new()
- local emptyTanks = List:new()
- for tankName,tank in pairs(StorageTanks.list) do
- if tank:hasContents() then
- if tank:contentsMatch(potion) then
- matchingTanks:insert(tank)
- elseif tank:isUnknown() then
- unknownTanks:insert(tank)
- end
- else
- emptyTanks:insert(tank)
- end
- end
- return matchingTanks, unknownTanks, emptyTanks
- end,
- writeTankContents=function()
- local saveData = {}
- for name,tank in pairs(StorageTanks.list) do
- if tank:hasContents(true) and not tank:isUnknown(true) then
- saveData[name] = tank.contents:getSaveObject()
- end
- end
- saveData = textutils.serializeJSON(saveData)
- local h = fs.open(Filenames.tankContents,"w")
- h.write(saveData)
- h.close()
- return true
- end,
- initializeTankContents=function()
- print("Initializing tank contents...")
- if fs.exists(Filenames.tankContents) then
- local h = fs.open(Filenames.tankContents,"r")
- local saveData = h.readAll()
- h.close()
- saveData = textutils.unserializeJSON(saveData)
- for name,tank in pairs(StorageTanks.list) do
- if tank:hasContents(true) then
- if saveData[name] ~= nil then
- tank:setContents(Potion:new(saveData[name].type,saveData[name].modifier,saveData[name].style),true)
- else
- tank:setContents(Potion:new(UNKNOWN),true)
- end
- else
- tank:setContents(nil,true)
- end
- end
- else
- for _,tank in pairs(StorageTanks.list) do
- if tank:hasContents(true) then
- tank:setContents(Potion:new(UNKNOWN),true)
- else
- tank:setContents(nil,true)
- end
- end
- end
- end,
- storePotion=function(potion)
- while true do
- local matchingTanks, unknownTanks, emptyTanks = StorageTanks.findStorage(potion)
- local basin = Peripherals.basin
- if #matchingTanks > 0 then
- for _,t in ipairs(matchingTanks) do
- if t.pullFluid(basin.name) > 0 then
- if not basin:hasFluid() then
- return true
- end
- end
- end
- end
- if #unknownTanks > 0 then
- for _,t in ipairs(unknownTanks) do
- if t.pullFluid(basin.name) > 0 then
- t:setContents(potion)
- if not basin:hasFluid() then
- return true
- end
- end
- end
- end
- if #emptyTanks > 0 then
- for _,t in ipairs(emptyTanks) do
- if t.pullFluid(basin.name) > 0 then
- t:setContents(potion)
- if not basin:hasFluid() then
- return true
- end
- end
- end
- end
- if not Issues.cannotStorePotion() then return false end
- end
- end,
- outputPotion=function(potion,qty,outputtingInfinite)
- if outputtingInfinite == nil then outputtingInfinite = false end
- qty = qty * 1000
- local qtyOutput = 0
- while qtyOutput < qty do
- local tank = StorageTanks.findTank(potion)
- if tank ~= nil then
- local amountPushed = tank.pushFluid(Peripherals.workbench.name,qty)
- if amountPushed == 0 then
- if not Issues.cannotOutputPotion() then
- return false
- end
- else
- qtyOutput = qtyOutput + amountPushed
- tank:hasContents()
- end
- else
- if not Crafting.craft(potion,1) then
- return false
- end
- end
- end
- return true
- end,
- outputInfinitePotion=function(potion)
- local infiniteOutputCancelled = false
- parallel.waitForAll(function()
- parallel.waitForAny(function()
- while not infiniteOutputCancelled do
- local _,key = waitForKey()
- if key == keys.backspace then
- infiniteOutputCancelled = true
- print("Cancelling infinite output...")
- end
- end
- end,function()
- while not infiniteOutputCancelled do
- sleep(5)
- end
- end)
- end,function()
- while not infiniteOutputCancelled do
- if not StorageTanks.outputPotion(potion,1,true) then
- infiniteOutputCancelled = true
- print("Cancelling infinite output...")
- break
- end
- end
- end)
- end,
- findTank=function(potion)
- for name,tank in pairs(StorageTanks.list) do
- if tank:contentsMatch(potion) then
- return tank
- end
- end
- return nil
- end
- }
- StorageTank = {
- new=function(self,peripheralName)
- perip = peripheral.wrap(peripheralName)
- perip.name = peripheralName
- perip.contents=nil
- setmetatable(perip,self)
- self.__index = self
- return perip
- end,
- hasContents=function(self,preventWrite)
- if preventWrite == nil then preventWrite = false end
- if #self.tanks() == 0 then
- if self.contents ~= nil then
- self:setContents(nil,preventWrite)
- end
- return false
- else
- if self.contents == nil then
- self:setContents(Potion:new(UNKNOWN),preventWrite)
- end
- return true
- end
- end,
- isUnknown=function(self,preventWrite)
- if preventWrite == nil then preventWrite = false end
- if self.contents == nil then
- if #self.tanks() ~= 0 then
- self:setContents(Potion:new(UNKNOWN),preventWrite)
- return true
- end
- return false
- else
- if #self.tanks() == 0 then
- self.contents = nil
- self:setContents(nil,preventWrite)
- return false
- end
- return self.contents:isUnknown()
- end
- end,
- contentsMatch=function(self,potionDef)
- if self.contents == nil then
- return potionDef == nil
- elseif potionDef == nil then
- return false
- end
- return self.contents:matches(potionDef)
- end,
- setContents=function(self,potionDef,preventWrite)
- if preventWrite == nil then preventWrite = false end
- self.contents = potionDef
- if not preventWrite then
- StorageTanks:writeTankContents()
- end
- end,
- getContentsName=function(self)
- if self.contents == nil then return "Empty" end
- if self.contents.type == UNKNOWN then return "Unknown contents" end
- return self.contents:getDisplayName()
- end
- }
- Inventories = {
- list=List:new(),
- indexedItems={},
- indexInventories=function()
- local totalSlots = 0
- for _,inv in ipairs(Inventories.list) do
- totalSlots = totalSlots + inv.size()
- end
- Inventories.indexedItems = {}
- local currentSlot = 1
- clearTerm()
- for _,inv in ipairs(Inventories.list) do
- local inventorySize = inv.size()
- for slot=1, inventorySize do
- term.setCursorPos(1,1)
- term.write("Indexing Inventories... Slot "..currentSlot.." of "..totalSlots)
- local itemDetail = inv.getItemDetail(slot)
- if itemDetail ~= nil then
- if not Inventories.hasItem(itemDetail.name) then
- Inventories.indexedItems[itemDetail.name] = IndexedItem:new(itemDetail.name)
- end
- Inventories.indexedItems[itemDetail.name]:addLocation(ItemLocation:new(inv,slot,itemDetail.count))
- end
- currentSlot = currentSlot + 1
- end
- end
- clearTerm()
- end,
- hasItem=function(itemName)
- return Inventories.indexedItems[itemName] ~= nil
- end,
- getItemCount=function(itemName)
- if Inventories.indexedItems[itemName] == nil then return 0 end
- return Inventories.indexedItems[itemName].total
- end,
- getItemLocations=function(itemName)
- if not Inventories.hasItem(itemName) then return nil end
- return Inventories.indexedItems[itemName].locations
- end,
- checkMissingItem=function(itemName,qty,missingItems)
- local count = Inventories.getItemCount(itemName)
- if count < qty then
- missingItems:insert({itemName,qty - count})
- end
- end,
- --- Returns true if the operation was successful
- --
- -- Can trigger issue if item is not found, after which user can add more items or cancel the operation
- take=function(itemName,toInventory,qty)
- if Inventories.getItemCount(itemName) < qty then
- if not Issues.itemMissingInInventory(itemName,qty) then
- return false
- end
- end
- while qty > 0 do
- local satisfied, remainingQty = Inventories.indexedItems[itemName]:take(toInventory,qty)
- if not satisfied then
- qty = remainingQty
- if not Issues.itemMissingInInventory(itemName,qty) then
- return false
- end
- else
- qty = 0
- end
- end
- return true
- end
- }
- IndexedItem={
- new=function(self,name)
- local o = {}
- o.name = name
- o.total = 0
- o.locations = List:new()
- setmetatable(o,self)
- self.__index = self
- return o
- end,
- addLocation=function(self,location)
- self.locations:insert(location)
- self.total = self.total + location.stackSize
- end,
- --- Takes an item from the index
- --
- -- first return is true if the qty was satisfied, otherwise false
- --
- -- second return is the remaining qty that was not satisfied
- take=function(self,toInventory,qty)
- qty = qty or 1
- if self.total == 0 or #self.locations == 0 then return false end
- if qty > self.total then return false end
- while qty > 0 and self.total > 0 do
- local moveCount = toInventory.pullItems(self.locations[1].inventory.name,self.locations[1].slot,qty)
- if moveCount > 0 then
- qty = qty - moveCount
- self.locations[1].stackSize = self.locations[1].stackSize - moveCount
- self.total = self.total - moveCount
- self:validateFirstLocation()
- else
- if self:validateFirstLocation() then
- --stored location is still valid
- --destination must have an issue
- break
- end
- end
- end
- return qty == 0, qty
- end,
- --- returns true if location still exists after being validated, else false
- validateFirstLocation=function(self)
- local count, difference = self.locations[1]:validateCount(self.name)
- if difference ~= 0 then
- self.total = self.total + difference
- end
- if count == 0 then
- self.locations:remove(1)
- return false
- end
- return true
- end
- }
- ItemLocation={
- new=function(self,inventory,slot,stackSize)
- local o = {}
- o.inventory = inventory
- o.slot = slot
- o.stackSize = stackSize
- setmetatable(o,self)
- self.__index = self
- return o
- end,
- --- checks the location to validate that the expected item still exists, and updates the stored qty if it differs
- --
- -- first return is the count of the item that exists in the stack
- --
- -- second return is the difference between the actual and the stored value
- validateCount=function(self,itemName)
- local detail = self.inventory.getItemDetail(self.slot)
- if detail == nil then return 0, -1 * self.stackSize end
- if detail.name ~= itemName then return 0, -1 * self.stackSize end
- local diff = detail.count - self.stackSize
- if diff ~= 0 then self.stackSize = detail.count end
- return detail.count, diff
- end
- }
- Peripherals={
- waterTank=nil,
- basin=nil,
- spout=nil,
- depot=nil,
- workbench=nil,
- deployer=nil,
- wrapPeripherals=function()
- while true do
- Peripherals.waterTank = nil
- StorageTanks.list = {}
- Peripherals.basin = nil
- Inventories.list = List:new()
- Monitors.list = List:new()
- Peripherals.spout = nil
- Peripherals.depot = nil
- Peripherals.workbench = nil
- local foundTanks = false
- local sideNames = List:new({"top","front","left","right","back","bottom"})
- for _,name in ipairs(peripheral.getNames()) do
- if not sideNames:contains(name) then
- local ptype = peripheral.getType(name)
- local perip = peripheral.wrap(name)
- perip.name = name
- if ptype == "create:fluid_tank" or ptype == "thermal:fluid_cell" then
- local tanks = perip.tanks()
- if #tanks > 0 and tanks[1].name == "minecraft:water" then
- Peripherals.waterTank = perip
- else
- perip = StorageTank:new(name)
- StorageTanks.list[name] = perip
- foundTanks = true
- end
- elseif ptype == "thermal:tinker_bench" then
- Peripherals.workbench = perip
- elseif ptype == "create:basin" then
- Peripherals.basin = Basin:new(name)
- elseif ptype == "monitor" then
- Monitors.list:insert(perip)
- elseif ptype == "create:spout" then
- Peripherals.spout = perip
- elseif ptype == "create:depot" then
- Peripherals.depot = perip
- elseif ptype == "create:deployer" then
- Peripherals.deployer = perip
- else
- if perip.pullItems ~= nil then
- Inventories.list:insert(perip)
- end
- end
- end
- end
- local messages = List:new()
- if Peripherals.waterTank == nil then
- messages:insert("No water tank found")
- end
- if not foundTanks then
- messages:insert("No storage tanks found")
- end
- if Peripherals.basin == nil then
- messages:insert("No Basin found")
- end
- if #Inventories.list == 0 then
- messages:insert("No item inventories found")
- end
- if #messages > 0 then
- Monitors.error("Could not find necessary peripherals")
- clearTerm()
- printError("Could not find necessary peripherals")
- for _,msg in ipairs(messages) do
- printError("- "..msg)
- end
- printLine()
- print("Press X to quit. Press any other key to retry.")
- local _, key = waitForKey()
- if key == keys.x then
- return false
- end
- else
- return true
- end
- end
- end
- }
- Basin={
- new=function(self,peripheralName)
- local basin = peripheral.wrap(peripheralName)
- basin.name = peripheralName
- setmetatable(basin,self)
- self.__index = self
- return basin
- end,
- hasWater=function(self)
- if not self:hasFluid() then return false end
- if #self.tanks() > 0 then
- return self.tanks()[1].name == "minecraft:water"
- end
- return self.tanks()[3].name == "minecraft:water"
- end,
- hasFluid=function(self)
- if #self.tanks() > 0 then
- return true
- end
- if self.tanks()[3] ~= nil then
- return true
- end
- return false
- end,
- hasItem=function(self)
- return self.getItemDetail(1) ~= nil
- end,
- insertItem=function(self,itemName)
- if self:hasItem() then
- if not Issues.itemStuckInBasin() then
- return false
- end
- end
- if not Inventories.take(itemName,self,1) then
- return false
- end
- return true
- end
- }
- Monitors = {
- lineNum=1,
- list=List:new(),
- setLineNum=function(lineNum)
- if #Monitors.list > 0 then
- for _,v in ipairs(Monitors.list) do
- v.setCursorPos(1,lineNum)
- end
- Monitors.lineNum=lineNum
- end
- end,
- clear=function()
- if #Monitors.list > 0 then
- for _,v in ipairs(Monitors.list) do
- v.clear()
- v.setCursorPos(1,1)
- end
- Monitors.lineNum=1
- end
- end,
- clearLine=function(line)
- line = line or Monitors.lineNum
- if #Monitors.list > 0 then
- for _,v in ipairs(Monitors.list) do
- v.setCursorPos(1,line)
- v.clearLine()
- end
- Monitors.lineNum=line
- end
- end,
- write=function(text,line)
- if #Monitors.list > 0 then
- for _,v in ipairs(Monitors.list) do
- if line ~= nil then
- v.setCursorPos(1,line)
- else
- v.setCursorPos(1,Monitors.lineNum)
- end
- v.clearLine()
- v.write(text)
- end
- if line == nil then
- Monitors.lineNum = Monitors.lineNum+1
- end
- end
- end,
- error=function(text)
- if #Monitors.list > 0 then
- for _,v in ipairs(Monitors.list) do
- v.setTextColor(colors.red)
- v.setCursorPos(1,Monitors.lineNum)
- v.write(text)
- v.setTextColor(colors.white)
- end
- Monitors.lineNum = Monitors.lineNum+1
- end
- end,
- back=function()
- if #Monitors.list > 0 then
- if Monitors.lineNum > 1 then
- Monitors.lineNum = Monitors.lineNum-1
- end
- for _,mon in ipairs(Monitors.list) do
- mon.setCursorPos(1,Monitors.lineNum)
- end
- end
- end
- }
- function clearTerm()
- term.clear()
- term.setCursorPos(1,1)
- end
- function printError(text)
- term.setTextColor(colors.red)
- print(text)
- term.setTextColor(colors.white)
- end
- function printInstruction(text)
- term.setTextColor(colors.lightBlue)
- print(text)
- term.setTextColor(colors.white)
- end
- function printLine()
- print()
- end
- function waitForKey()
- local event, key = os.pullEvent("key")
- sleep(.5)
- return event, key
- end
- Crafting = {
- fuels=nil,
- craft=function(potion,qty,craftingInfinite)
- local cancelled = false
- if craftingInfinite == nil then craftingInfinite = false end
- local craftPlan = nil
- while true do
- local result, missing, recipes = Crafting.canCraftPotion(potion,qty)
- if not result then
- if not Issues.multipleItemsMissing(missing) then
- return false
- end
- else
- craftPlan = recipes
- break
- end
- end
- clearTerm()
- local remainingQty = qty
- local fullPotionName = potion:getDisplayName()
- Crafting.setRedstone(true)
- for _,recipePlan in ipairs(craftPlan) do
- local recipeCount = recipePlan[1]
- local recipe = recipePlan[2]
- for i=1, recipeCount do
- Monitors.clear()
- clearTerm()
- if craftingInfinite then
- Monitors.write("Crafting infinite")
- print("Crafting infinite "..fullPotionName)
- printInstruction("Press backspace to stop crafting")
- else
- Monitors.write("Crafting "..(qty-remainingQty+1).." of "..qty)
- print("Crafting "..(qty-remainingQty+1).." of "..qty)
- print(fullPotionName)
- end
- Monitors.write(fullPotionName)
- if not Crafting.refillWater() then
- cancelled = true
- break
- end
- if not Crafting.mix(ItemNames.netherwart) then
- cancelled = true
- break
- end
- for _,itemName in ipairs(recipe.items) do
- if not Crafting.mix(itemName) then
- cancelled = true
- break
- end
- end
- local modItem = PotionModifiers.getItem(potion.modifier)
- if modItem ~= nil then
- if not Crafting.mix(modItem) then
- cancelled = true
- break
- end
- end
- local styleItem = PotionStyles.getItem(potion.style)
- if styleItem ~= nil then
- if not Crafting.mix(styleItem) then
- cancelled = true
- break
- end
- end
- if not StorageTanks.storePotion(potion) then
- cancelled = true
- break
- end
- remainingQty = remainingQty - 1
- end
- if cancelled then break end
- end
- Monitors.clear()
- clearTerm()
- Crafting.setRedstone(false)
- return not cancelled
- end,
- craftInfinite=function(potion)
- local infiniteCraftingCancelled = false
- parallel.waitForAll(function()
- parallel.waitForAny(function()
- while not infiniteCraftingCancelled do
- local _,key = waitForKey()
- if key == keys.backspace then
- infiniteCraftingCancelled = true
- print("Cancelling infinite crafting...")
- end
- end
- end,function()
- while not infiniteCraftingCancelled do
- sleep(5)
- end
- end)
- end,function()
- while not infiniteCraftingCancelled do
- if not Crafting.craft(potion,1,true) then
- infiniteCraftingCancelled = true
- print("Cancelling infinite crafting...")
- break
- end
- end
- end)
- end,
- canCraftPotion=function(potion,qty)
- local potionDef = PotionTypes.getDefinition(potion.type)
- if potionDef == nil then
- printError(potion.type)
- end
- local missingItems = List:new()
- Inventories.checkMissingItem(ItemNames.netherwart,qty,missingItems)
- local modItem = PotionModifiers.getItem(potion.modifier)
- if modItem ~= nil then
- Inventories.checkMissingItem(modItem,qty,missingItems)
- end
- local styleItem = PotionStyles.getItem(potion.style)
- if styleItem ~= nil then
- Inventories.checkMissingItem(styleItem,qty,missingItems)
- end
- local canCraft, craftPlan = potionDef.recipes:getCraftPlan(qty)
- if not canCraft then
- potionDef.recipes[1]:checkMissingItems(qty,missingItems)
- end
- if #missingItems > 0 then
- return false, missingItems, nil
- end
- return true, nil, craftPlan
- end,
- refillWater=function()
- local basin = Peripherals.basin
- if basin:hasFluid() then
- if basin:hasWater() then return true end
- Issues.fluidStuckInBasin()
- end
- basin.pullFluid(Peripherals.waterTank.name)
- return true
- end,
- mix=function(itemName)
- if Peripherals.basin:hasItem() then
- Issues.itemStuckInBasin()
- end
- if Peripherals.basin:insertItem(itemName) then
- while true do
- sleep(1)
- if not Peripherals.basin:hasItem() then
- break
- end
- end
- else
- return false
- end
- return true
- end,
- setRedstone=function(on)
- for _,side in ipairs(redstone.getSides()) do
- redstone.setOutput(side,on)
- end
- end,
- getRedstone=function()
- return redstone.getOutput(redstone.getSides()[1])
- end,
- initializeFuels=function()
- print("Initializing fuel types")
- Crafting.fuels = List:new()
- local h = nil
- if not pcall(function()
- if fs.exists(Filenames.fuelItems) then
- h = fs.open(Filenames.fuelItems,"r")
- local l = h.readLine()
- while l ~= nil do
- Crafting.fuels:insert(l)
- l = h.readLine()
- end
- h.close()
- h = nil
- end
- end) then
- if h ~= nil then h.close() end
- end
- if #Crafting.fuels == 0 then
- Crafting.fuels = List:new({
- "minecraft:charcoal",
- "minecraft:charcoal_block",
- "minecraft:coal",
- "minecraft:coal_block",
- "create:blaze_cake"
- })
- h = fs.open(Filenames.fuelItems,"w")
- for _,itemName in ipairs(Crafting.fuels) do
- h.writeLine(itemName)
- end
- h.close()
- end
- end
- }
- Issues = {
- itemStuckInBasin=function()
- Monitors.error("Item stuck in Basin!")
- printError("An item is stuck in the basin")
- while true do
- sleep(10)
- if not Peripherals.basin:hasItem() then
- Monitors.back()
- Monitors.clearLine()
- clearTerm()
- return
- end
- end
- end,
- fluidStuckInBasin=function()
- Monitors.error("Fluid stuck in Basin!")
- printError("Fluid is stuck in the basin")
- while true do
- sleep(10)
- if not Peripherals.basin:hasFluid() then
- Monitors.back()
- Monitors.clearLine()
- clearTerm()
- return true
- end
- end
- end,
- missingBlazeFuel=function()
- Monitors.error("Could not find fuel for blaze!")
- while true do
- clearTerm()
- printError("Could not find fuel for blaze!")
- printInstruction("Press X to cancel")
- printInstruction("Press any other key after adding fuel")
- local _,key = waitForKey()
- if key == keys.x then
- clearTerm()
- Monitors.clear()
- return false
- end
- Inventories.indexInventories()
- for _,name in ipairs(Crafting.fuels) do
- if Inventories.hasItem(name) then
- clearTerm()
- Monitors.clear()
- return true
- end
- end
- end
- end,
- itemMissingInInventory=function(itemName,qty)
- Monitors.error("Item could not be found in inventory!")
- while true do
- clearTerm()
- printError("Item could not be found in inventory!")
- print("Item: "..itemName)
- print("Needed quantity: "..qty)
- printInstruction("Press X to cancel")
- printInstruction("Press any other key after adding item")
- local _,key = waitForKey()
- if key == keys.x then
- clearTerm()
- Monitors.clear()
- return false
- end
- Inventories.indexInventories()
- if Inventories.getItemCount(itemName) > 0 then
- clearTerm()
- Monitors.back()
- Monitors.clearLine()
- return true
- end
- end
- end,
- multipleItemsMissing=function(missingItems)
- Monitors.error("Insufficient items in inventory!")
- clearTerm()
- printError("The following items could not be found:")
- for _,itemData in ipairs(missingItems) do
- print(" "..itemData[2].."x "..itemData[1])
- end
- printInstruction("Press x to cancel")
- printInstruction("Press any other key after adding items")
- local _,key = waitForKey()
- if key == keys.x then
- clearTerm()
- Monitors.clear()
- return false
- end
- Monitors.back()
- Monitors.clearLine()
- clearTerm()
- Inventories.indexInventories()
- return true
- end,
- cannotStorePotion=function()
- Monitors.error("Potion in Basin could not be stored!")
- clearTerm()
- printError("Potion in the Basin could not be stored")
- printInstruction("Please empty an existing storage tank")
- print("Adding additional storage tanks during runtime")
- print("is not currently supported.")
- printLine()
- printInstruction("Press x to cancel")
- printInstruction("Press any other key to try again")
- local _,key = waitForKey()
- if key == keys.x then
- Monitors.clear()
- clearTerm()
- return false
- end
- Monitors.back()
- Monitors.clearLine()
- term.clear()
- return true
- end,
- cannotOutputPotion=function()
- Monitors.error("Potion could not be put in Tinker's Bench!")
- clearTerm()
- printError("Potion could not be output to Tinker's Bench")
- printInstruction("Please empty bench or ensure it does not contain")
- printInstruction("an incompatible fluid")
- printLine()
- printInstruction("Press x to cancel")
- printInstruction("Press any other key to try again")
- local bench = Peripherals.workbench
- local startingAmount = bench.tanks()[1].amount
- local cancelled = false
- parallel.waitForAny(function()
- while true do
- local t = bench.tanks()[1]
- if t == nil then
- break
- elseif t.amount < startingAmount then
- break
- end
- sleep(2)
- end
- end,function()
- local _,key = waitForKey()
- if key == keys.x then
- Monitors.clear()
- clearTerm()
- cancelled = true
- end
- end)
- Monitors.back()
- Monitors.clearLine()
- term.clear()
- return not cancelled
- end
- }
- CommandLine = {
- commands={
- craft={
- desc="Crafts the specified potion",
- usage="craft,<potionType>,<modifier>,<style>,<qty>"
- },
- help={
- desc="Displays this screen",
- usage="help"
- },
- list={
- desc={
- "Prints a list of the connected storage",
- "tanks along with their current contents"
- },
- usage="list"
- },
- exit={
- desc="Quits the program",
- usage="exit"
- }
- },
- read=function()
- while true do
- Monitors.clear()
- Monitors.write("Waiting for input...")
- clearTerm()
- printInstruction("Please enter command (use help for more info)")
- local com = tostring(read()):split(",")
- Monitors.clear()
- if #com > 0 then
- if com[1] == "craft" then
- CommandLine.craft(com[2],com[3],com[4],com[5])
- elseif com[1] == "output" then
- CommandLine.output(com[2],com[3],com[4],com[5])
- elseif com[1] == "bottle" then
- elseif com[1] == "list" then
- CommandLine.list()
- elseif com[1] == "help" then
- CommandLine.help()
- elseif com[1] == "index" then
- Inventories.indexInventories()
- elseif com[1] == "exit" then
- return
- end
- end
- end
- end,
- craft=function(potionName,modifier,style,qty)
- local potionType = CommandLine.validatePotionType(potionName)
- if potionType == nil then return end
- modifier = CommandLine.validateModifier(modifier)
- if modifier == nil then return end
- style = CommandLine.validateStyle(style)
- if style == nil then return end
- qty = CommandLine.validateQty(qty,"buckets")
- if qty == nil then return end
- if type(qty) == "string" and qty == "infinite" then
- Crafting.craftInfinite(Potion:new(potionType,modifier,style))
- else
- if not Crafting.craft(Potion:new(potionType,modifier,style),qty) then
- print("Crafting aborted")
- sleep(3)
- end
- end
- end,
- output=function(potionName,modifier,style,qty)
- if Peripherals.workbench == nil then
- printError("Tinker's Workbench not found")
- waitForKey()
- return
- end
- local potionType = CommandLine.validatePotionType(potionName)
- if potionType == nil then return end
- modifier = CommandLine.validateModifier(modifier)
- if modifier == nil then return end
- style = CommandLine.validateStyle(style)
- if style == nil then return end
- qty = CommandLine.validateQty(qty,"buckets")
- if qty == nil then return end
- if type(qty) == "string" and qty == "infinite" then
- StorageTanks.outputInfinitePotion(Potion:new(potionType,modifier,style))
- else
- if not StorageTanks.outputPotion(Potion:new(potionType,modifier,style),qty) then
- print("Outputting potion aborted")
- sleep(3)
- end
- end
- end,
- list=function()
- clearTerm()
- local i = 1
- for _,tank in pairs(StorageTanks.list) do
- print("Tank "..i..": "..tank:getContentsName())
- i = i + 1
- end
- printInstruction("Press any key to continue")
- waitForKey()
- end,
- help=function()
- clearTerm()
- for commandName,data in pairs(CommandLine.commands) do
- term.setTextColor(colors.lightBlue)
- term.write(commandName)
- term.setTextColor(colors.white)
- if type(data.desc) == "string" then
- print(data.desc)
- else
- for _,line in ipairs(data.desc) do
- print(line)
- end
- end
- print("Usage: "..data.usage)
- end
- printInstruction("Press any key to continue")
- waitForKey()
- end,
- validatePotionType=function(potionName)
- local potionType = nil
- if potionName ~= nil then
- potionType = PotionTypes.getInternalName(potionName)
- if potionType == nil then
- printError("Invalid potion name provided")
- printInstruction("Press any key to continue")
- waitForKey()
- end
- else
- potionType = CommandLine.promptPotionType()
- end
- return potionType
- end,
- promptPotionType=function()
- clearTerm()
- local names = List:new()
- for internalName,_ in pairs(PotionTypes.definitions) do
- names:insert(internalName)
- end
- while true do
- printInstruction("Which potion type do you want?")
- for i,internalName in ipairs(names) do
- print(" "..i..") "..PotionTypes.definitions[internalName].names[1])
- end
- printError(" "..(#names+1)..") Cancel")
- local i = tonumber(read())
- if i < 1 or i > #names+1 then
- printError("Invalid value provided")
- elseif i == #names+1 then
- return nil
- else
- return names[i]
- end
- end
- end,
- validateModifier=function(modifier)
- if modifier ~= nil then
- modifier = PotionModifiers.getModifier(modifier)
- if modifier == nil then
- printError("Invalid value provided for potion modifier")
- printInstruction("Press any key to continue")
- waitForKey()
- return nil
- end
- return modifier
- end
- return CommandLine.promptModifier()
- end,
- promptModifier=function()
- clearTerm()
- local mods = PotionModifiers.getList()
- while true do
- printInstruction("Which modifier do you want?")
- for m=1, #mods do
- print(" "..m..") "..mods[m])
- end
- printError(" "..(#mods+1)..") Cancel")
- local i = tonumber(read())
- if i == nil or i < 1 or i > #mods+1 then
- printError("Invalid value provided")
- elseif i == #mods+1 then
- return nil
- else
- return mods[i]
- end
- end
- end,
- validateStyle=function(style)
- if style ~= nil then
- style = PotionStyles.getStyle(style)
- if style == nil then
- printError("Invalid value provided for potion style")
- printInstruction("Press any key to continue")
- waitForKey()
- return nil
- end
- return style
- end
- return CommandLine.promptStyle()
- end,
- promptStyle=function()
- clearTerm()
- local mods = PotionStyles.getList()
- while true do
- printInstruction("Which style do you want?")
- for m=1, #mods do
- print(" "..m..") "..mods[m])
- end
- printError(" "..(#mods+1)..") Cancel")
- local i = tonumber(read())
- if i == nil or i < 1 or i > #mods+1 then
- printError("Invalid value provided")
- elseif i == #mods+1 then
- return nil
- else
- return mods[i]
- end
- end
- end,
- validateQty=function(qty,type)
- if qty ~= nil then
- if qty == "infinite" then
- return qty
- end
- qty = tonumber(qty)
- if qty == nil or qty < 1 then
- printError("Invalid value provided for number of "..type)
- printInstruction("Press any key to continue")
- waitForKey()
- end
- return qty
- end
- return CommandLine.promptQty(type)
- end,
- promptQty=function(qtyType)
- clearTerm()
- while true do
- printInstruction("How many "..qtyType.." do you want?")
- printInstruction("Enter \"infinite\" to keep producing forever")
- printError("Enter \"cancel\" to quit")
- local i = read()
- if i == "cancel" then
- return nil
- elseif i == "infinite" then
- return -1
- else
- i = tonumber(i)
- if i == nil or i <= 0 then
- printError("Invalid value provided")
- else
- return i
- end
- end
- end
- end
- }
- function run()
- if not Peripherals.wrapPeripherals() then
- return
- end
- Monitors.clear()
- clearTerm()
- --if Peripherals.deployer ~= nil then
- -- Crafting.initializeFuels()
- --end
- StorageTanks.initializeTankContents()
- if not PotionTypes.initialize() then
- return
- end
- Inventories.indexInventories()
- CommandLine.read()
- end
- run()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement