diff --git a/docs/_sidebar.md b/docs/_sidebar.md index f7a3d5d..1a657fa 100644 --- a/docs/_sidebar.md +++ b/docs/_sidebar.md @@ -29,3 +29,4 @@ - [Button coloring](tips/buttonColoring.md) - [Designing/Animating](tips/design.md) - [Dynamic Values](tips/dynamicvalues.md) + - [XML](tips/xml.md) diff --git a/docs/installer.lua b/docs/installer.lua new file mode 100644 index 0000000..9b56fa4 --- /dev/null +++ b/docs/installer.lua @@ -0,0 +1,487 @@ +--Basalt configurated installer +local filePath = "basalt.lua" --here you can change the file path default: basalt +if not(fs.exists(filePath))then + shell.run("pastebin run ESs1mg7P packed true "..filePath:gsub(".lua", "")) -- this is an alternative to the wget command +end +local basalt = require(filePath:gsub(".lua", "")) -- here you can change the variablename in any variablename you want default: basalt + +local maxCoWorker = 3 + +local recipeList = {} +local craftingQueue = {} +local bridge = peripheral.find("rsBridge") +local w, h = term.getSize() + +local main = basalt.createFrame() +local home = main:addFrame():setPosition(1,2):setBackground(colors.lightGray):setSize(w, h-2) +local recipes = main:addFrame():setPosition(1,2):setBackground(colors.lightGray):hide() +local log = main:addFrame():setPosition(1,2):setBackground(colors.lightGray):hide() + +local menuBar = main:addMenubar():addItem("Home"):addItem("Recipes"):addItem("Log"):setBackground(colors.gray):setSize(w, 1):setSpace(6):setScrollable():show() +menuBar:onChange(function(self) + home:hide() + recipes:hide() + log:hide() + if(self:getValue().text=="Home")then + home:show() + elseif(self:getValue().text=="Recipes")then + recipes:show() + elseif(self:getValue().text=="Log")then + log:show() + end +end) + +local function buttonVisuals(btn) + btn:onClick(basalt.schedule(function() btn:setBackground(colors.black) btn:setForeground(colors.lightGray) os.sleep(0.1) btn:setBackground(colors.gray) btn:setForeground(colors.black) end)) +end + +local coworkerCount = home:addLabel():setText(maxCoWorker):setPosition(45,2):show() +home:addLabel():setText("Co-Worker:"):setPosition(32,2):show() +buttonVisuals(home:addButton():setText(">"):setSize(1,1):setPosition(47,2):onClick(function() if(maxCoWorker<100)then maxCoWorker = maxCoWorker+1 end coworkerCount:setText(maxCoWorker) end):show()) +buttonVisuals(home:addButton():setText("<"):setSize(1,1):setPosition(43,2):onClick(function() if(maxCoWorker>1)then maxCoWorker = maxCoWorker-1 end coworkerCount:setText(maxCoWorker) end):show()) + +local logList = log:addList():setPosition(2,2):setSize(w-2,h-3):setScrollable(false):show() +local jobList = home:addList():setPosition(20,4):setSize(30,10):show() +local rList = recipes:addList():setPosition(13,2):setSize(38,16):show() + +local function logging(text) + logList:addItem(text) + if(logList:getItemCount()>h-3)then + logList:removeItem(1) + end +end + +logging("Loading autocrafter...") + +function SaveToFile() + local file = io.open("recipes", "wb") + local sel = rList:getItemIndex() + rList:clear() + for _,v in pairs(recipeList)do + if(v.useDmg)then + file:write(v.name.."|"..v.damage.."|"..v.minAmount.."|"..v.maxCraftAmount.."|true|", "\n") + else + file:write(v.name.."|"..v.damage.."|"..v.minAmount.."|"..v.maxCraftAmount.."|false|", "\n") + end + rList:addItem(v.minAmount.."x "..v.name..":"..v.damage, nil, nil, v) + end + rList:selectItem(sel) + file:close() +end + +buttonVisuals(recipes:addButton():setPosition(2,2):setText("Remove"):setSize(8,1):onClick(function() + if(rList:getValue()~=nil)then + local sel = rList:getValue().args[1] + for k,v in pairs(recipeList)do + if(v.name==sel.name)and(tonumber(v.damage)==tonumber(sel.damage))then + table.remove(recipeList, k) + logging("Removed recipe: "..v.name..":"..v.damage) + SaveToFile() + end + end + end +end)) +local changeAmn = recipes:addInput():setPosition(4,4):setSize(5,1):setInputType("number"):setForeground(colors.black):setDefaultText("32", colors.black):onChange(function(self) + local val = tonumber(self:getValue()) or 32 + if(val<0)then + self:setValue(0) + end +end) +buttonVisuals(recipes:addButton():setPosition(2,4):setSize(1,1):setText("-"):onClick(function() + local val = tonumber(changeAmn:getValue()) or 32 + if(rList:getValue()~=nil)then + local sel = rList:getValue().args[1] + if(val>0)and(sel.name~=nil)and(sel.damage~=nil)then + for k,v in pairs(recipeList)do + if(v.name==sel.name)and(tonumber(v.damage)==tonumber(sel.damage))then + v.minAmount = v.minAmount - val + if(v.minAmount < 0)then v.minAmount = 0 end + SaveToFile() + end + end + end + end +end)) +buttonVisuals(recipes:addButton():setPosition(10,4):setSize(1,1):setText("+"):onClick(function() + local val = tonumber(changeAmn:getValue()) or 32 + if(rList:getValue()~=nil)then + local sel = rList:getValue().args[1] + if(val>0)and(sel.name~=nil)and(sel.damage~=nil)then + for k,v in pairs(recipeList)do + if(v.name==sel.name)and(tonumber(v.damage)==tonumber(sel.damage))then + v.minAmount = v.minAmount + val + SaveToFile() + end + end + end + end +end)) + +buttonVisuals(recipes:addButton():setPosition(2,6):setSize(8,1):setText("Set"):onClick(function() + local val = tonumber(changeAmn:getValue()) or 32 + if(rList:getValue()~=nil)then + local sel = rList:getValue().args[1] + if(val>0)and(sel.name~=nil)and(sel.damage~=nil)then + for k,v in pairs(recipeList)do + if(v.name==sel.name)and(tonumber(v.damage)==tonumber(sel.damage))then + v.minAmount = val + SaveToFile() + end + end + end + end +end)) + +local rItemFrame = home:addFrame():setPosition(7,3):setBackground(colors.gray):setSize(27,6):setMoveable(true):setBar("Remove Item", colors.black, colors.lightGray):showBar():hide() +rItemFrame:addButton():setPosition(1,1):setAnchor("topRight"):setSize(1,1):setBackground(colors.black):setForeground(colors.lightGray):setText("x"):onClick(function() rItemFrame:hide() end):show() +rItemFrame:addLabel():setText("Item ID:"):setPosition(2,3):show() +local ritemId = rItemFrame:addInput("itemid"):setPosition(12,3):setSize(15,1):setBackground(colors.black):setForeground(colors.lightGray):setDefaultText("minecraft:stick", colors.gray):show() +rItemFrame:addButton():setPosition(-7,0):setAnchor("bottomRight"):setSize(8,1):setBackground(colors.black):setForeground(colors.lightGray):setText("Remove"):onClick(function() + local id = ritemId:getValue() + + for k,v in pairs(recipeList)do + if(v.name==id)then + table.remove(recipeList, k) + logging("Removed recipe: "..v.name..":"..v.damage) + end + end + SaveToFile() +end) + + +local aItemFrame = home:addFrame():setPosition(7,3):setBackground(colors.gray):setSize(27,12):setMoveable(true):setBar("Add Item", colors.black, colors.lightGray):showBar():hide() +aItemFrame:addLabel():setText("Item ID:"):setPosition(2,3) +aItemFrame:addLabel():setText("Damage:"):setPosition(2,5) +aItemFrame:addLabel():setText("Count:"):setPosition(2,7) +aItemFrame:addLabel():setText("Max:"):setPosition(2,9) +aItemFrame:addLabel():setText("Use Damage:"):setAnchor("bottomLeft"):setPosition(4,0) +local itemId = aItemFrame:addInput():setPosition(12,3):setSize(15,1):setBackground(colors.black):setForeground(colors.lightGray):setDefaultText("minecraft:stick", colors.gray) +local itemDamage = aItemFrame:addInput():setPosition(12,5):setSize(15,1):setBackground(colors.black):setForeground(colors.lightGray):setInputType("number"):setDefaultText("0", colors.gray) +local itemCount = aItemFrame:addInput():setPosition(12,7):setSize(15,1):setBackground(colors.black):setForeground(colors.lightGray):setInputType("number"):setDefaultText("64", colors.gray) +local itemMaxCount = aItemFrame:addInput():setPosition(12,9):setSize(15,1):setBackground(colors.black):setForeground(colors.lightGray):setInputType("number"):setDefaultText("0", colors.gray) +local useDamage = aItemFrame:addCheckbox():setAnchor("bottomLeft"):setPosition(2,0):setBackground(colors.black):setForeground(colors.lightGray):setValue(true) +aItemFrame:addButton():setAnchor("topRight"):setPosition(1,1):setSize(1,1):setBackground(colors.black):setForeground(colors.lightGray):setText("x"):onClick(function() aItemFrame:hide() end) +aItemFrame:addButton():setAnchor("bottomRight"):setPosition(-4,0):setSize(5,1):setBackground(colors.black):setForeground(colors.lightGray):setText("Add"):onClick(function() + local id = itemId:getValue() + local dmg = itemDamage:getValue() == "" and 0 or itemDamage:getValue() + local count = itemCount:getValue() == "" and 64 or itemCount:getValue() + local maxCount = itemMaxCount:getValue() == "" and 0 or itemMaxCount:getValue() + local usedamage = useDamage:getValue() or true + if(id~="")then + local itemExist = false + for k,v in pairs(recipeList)do + if(v.name==id)then + if(usedamage)then + if(v.damage==dmg)then + itemExist = true + v.minAmount = count or 64 + v.maxCraftAmount = maxCount or 0 + logging("Edited recipe: "..(count).."x "..id..":"..dmg) + end + else + itemExist = true + v.minAmount = count or 64 + v.maxCraftAmount = maxCount or 0 + logging("Edited recipe: "..(count).."x "..id..":"..dmg) + end + end + end + + if(itemExist == false)then + table.insert(recipeList, {name = id, damage = dmg or 0, minAmount = count, maxCraftAmount = maxCount or 0, useDmg = usedamage, fails = 0, timer = 0}) + logging("Added recipe: "..(count).."x "..id..":"..dmg) + end + SaveToFile() + else + logging("Please set a ID.") + end +end) + +buttonVisuals(home:addButton():setText("Add Item"):setSize(12,3):setPosition(2,6):onClick(function() aItemFrame:show() aItemFrame:setFocus() end):show()) +buttonVisuals(home:addButton():setText("Remove Item"):setSize(12,3):setPosition(2,10):onClick(function() rItemFrame:show() rItemFrame:setFocus() end):show()) + +local function StringSeperate(str, seperator) +local words = {} +local word = "" + + if(string.sub(str, str:len(), str:len())~=seperator)then + str = str..""..seperator + end + for x=1,str:len() do + local s = string.sub(str,x,x) + if(s==seperator)then + table.insert(words, word) + word = "" + else + word = word..s + end + end + return words +end + +if not(fs.exists("recipes"))then + fs.open("recipes","w").close() +end + +local f = fs.open("recipes", "r") +for line in f.readLine do + local tab = StringSeperate(line, "|") + if(tab[1]~=nil)and(tab[2]~=nil)and(tab[3]~=nil)and(tab[4]~=nil)and(tab[5]~=nil)then + logging("Registered recipe: "..tab[3].."x "..tab[1]..":"..tab[2]) + local recipe = {name=tab[1],damage=tonumber(tab[2]),minAmount=tonumber(tab[3]),maxCraftAmount=tonumber(tab[4]),fails=0,timer=0} + if(tab[5]=="true")then + recipe.useDmg=true + else + recipe.useDmg=false + end + rList:addItem(recipe.minAmount.."x "..recipe.name..":"..recipe.damage, nil, nil, recipe) + table.insert(recipeList, recipe) + end +end +f.close() + +local function findKeyWithItemName(table, itemname, damage) + for k,v in pairs(table)do + if(v.name==itemname)and(v.damage == damage)then + return k + end + end + return nil +end + +local scanChestBtn = home:addButton("scanChest"):setText("Scan Chest"):setSize(12,3):setPosition(2,2):show() +local function checkChestForNewEntrys() + scanChestBtn:setText("Scanning..") + local inventory = peripheral.find("minecraft:chest") + local items = {} + local itemAmounts = {} + local somethingChanged = false + + if(inventory~=nil)then + for x=1,inventory.size(), 1 do + local item = inventory.getItemDetail(x) + if(item~=nil)then + if(item.damage==nil)then item.damage = 0 end + table.insert(items, item) + end + os.sleep(0.1) + end + else + logging("No chest available!") + end + + if(#items > 0)then + for _,v in pairs(items)do + local key = findKeyWithItemName(itemAmounts, v.name, v.damage) + if(key~=nil)then + itemAmounts[key].count = itemAmounts[key].count + v.count + else + table.insert( itemAmounts, {name=v.name, damage=v.damage, count = v.count}) + end + end + end + + if(#itemAmounts > 0)then + for _,v in pairs(itemAmounts)do + local key = findKeyWithItemName(recipeList, v.name, v.damage) + if(key~=nil)then + if(recipeList[key].minAmount ~= v.count)then + logging("Edited recipe: "..v.name.. ":"..v.damage.." new count: "..v.count) + end + somethingChanged = true + recipeList[key].minAmount = v.count + else + table.insert( recipeList, {name=v.name, damage=v.damage, minAmount = v.count, maxCraftAmount = 0, useDmg = true, fails = 0, timer = 0}) + somethingChanged = true + logging("Registered recipe: "..v.count.."x "..v.name.. ":"..v.damage) + end + end + if(somethingChanged)then + SaveToFile() + end + end + scanChestBtn:setText("Scan Chest") + logging("Scanning chest done.") +end + +local chestScanThread = main:addThread("chestScanThread") +buttonVisuals(scanChestBtn:onClick(function() chestScanThread:start(checkChestForNewEntrys) end)) + + +local function GetAmount(itemAmount, recipe) + local amount = 0 + if(itemAmount < recipe.minAmount)then + if(recipe.maxCraftAmount > 0)then + if(recipe.minAmount-itemAmount > recipe.maxCraftAmount)then + amount = recipe.maxCraftAmount + else + amount = recipe.minAmount-itemAmount + end + else + amount = recipe.minAmount-itemAmount + end + end + return amount +end + +function GetRecipeKey(pattern) + for k,v in pairs(recipeList)do + if(v.name == pattern.name)then + if(pattern.damage==nil)then return k end + if(v.useDmg)then + if(v.damage == pattern.damage)then + return k + end + else + return k + end + end + end + return nil +end + +local function CheckCraftingRecipe(recipe) + local pattern = bridge.getItem({name=recipe.name}) + local item = {pattern=pattern, amount=0} + if(pattern~=nil)then + local storedAmount = pattern.amount + local neededItemAmount = GetAmount(storedAmount, recipe) + if(neededItemAmount > 0)then + item.amount = neededItemAmount + table.insert(craftingQueue, item) + return true + end + end + return false +end + +function RemoveRecipe(item) + local key = -1 + for k,v in pairs(recipeList)do + if(v.name == item.name)and(v.damage== item.damage)then + key = k + end + end + if(key>=0)then + table.remove(recipeList, key) + end + SaveToFile() +end + +local function FindKeyInTable(table, item) + for k,v in pairs(table)do + if(v==item)then + return k + end + end + return nil +end + +local function CheckAllRecipes() + for _,v in pairs(recipeList)do + if(type(v)=="table")then + CheckCraftingRecipe(v) + end + end +end + +local function jobCrafting(coworker, item) + if(jobList:getItem(coworker)~=nil)then + jobList:editItem(coworker, "Co-Worker "..coworker..": "..item.amountToCraft.."x "..item.item.displayName:gsub(" ", "")) + else + jobList:addItem("Co-Worker "..coworker..": "..item.amountToCraft.."x "..item.item.displayName:gsub(" ", "")) + end + +end + +local function jobDone(coworker) + if(jobList:getItem(coworker)~=nil)then + jobList:editItem(coworker, "Co-Worker "..coworker..": waiting...") + else + jobList:addItem("Co-Worker "..coworker..": waiting...") + end +end + +local coWorkerId = 1 +local function UpdateCraftingQueue() + while(#craftingQueue > 0)do + local activeCoWorkers = {} + local craftingQueuesToRemove = {} + for _,v in pairs(craftingQueue)do + if(#activeCoWorkers+1 <= maxCoWorker)then + local stack = v.pattern + local recipeKey = GetRecipeKey(stack) + + local waittimer = 0 + local multiplier = 1 + + if(recipeList[recipeKey].fails > 0)and(recipeList[recipeKey].fails <=10)then + multiplier = recipeList[recipeKey].fails + elseif(recipeList[recipeKey].fails > 10)then + multiplier = 20 + end + waittimer = multiplier * 30 + if(os.clock()>=recipeList[recipeKey].timer+waittimer)then + if not(bridge.isItemCrafting(stack.name))then + local currentItemState = {item=stack, curAmount = stack.count, amountToCraft = v.amount} + if(bridge.isItemCraftable({name=stack.name}))then + local task, errormsg = bridge.craftItem({name=stack.name, count = v.amount}) + if(task)then + logging("Sheduled Task: "..v.amount.." ("..stack.name..") "..stack.displayName:gsub(" ", "")) + jobCrafting(coWorkerId, currentItemState) + currentItemState.coWorker = coWorkerId + coWorkerId = coWorkerId + 1 + if(coWorkerId > maxCoWorker)then coWorkerId = 1 end + table.insert(activeCoWorkers, currentItemState) + recipeList[recipeKey].fails = 0 + else + logging("Error sheduling task: "..v.amount.."x ("..stack.name..") "..stack.displayName:gsub(" ", "")) + logging("Not enough materials!") + recipeList[recipeKey].fails = recipeList[recipeKey].fails + 1 + recipeList[recipeKey].timer = os.clock() + end + else + logging("Error sheduling task: "..v.amount.."x ("..stack.name..") "..stack.displayName:gsub(" ", "")) + logging("No pattern available!") + recipeList[recipeKey].fails = recipeList[recipeKey].fails + 1 + recipeList[recipeKey].timer = os.clock() + end + end + end + table.insert(craftingQueuesToRemove, v) + end + end + + if(#craftingQueuesToRemove > 0)then + for _,v in pairs(craftingQueuesToRemove)do + local id = FindKeyInTable(craftingQueue, v) + table.remove(craftingQueue, id) + end + end + + while(#activeCoWorkers > 0)do + local finishedCoworker = {} + for _,v in pairs(activeCoWorkers)do + if not(bridge.isItemCrafting(v.item.name))then + logging("Task done: "..v.amountToCraft.."x ("..v.item.name..") "..v.item.displayName:gsub(" ", "")) + table.insert(finishedCoworker, v) + end + end + if(#finishedCoworker>0)then + for _,v in pairs(finishedCoworker)do + local id = FindKeyInTable(activeCoWorkers, v) + table.remove(activeCoWorkers, id) + jobDone(v.coWorker) + end + end + os.sleep(0.75) + end + os.sleep(0.75) + end +end + +main:addThread("craftingThread"):start(function() while true do CheckAllRecipes() os.sleep(1) UpdateCraftingQueue() os.sleep(1) end end) + +logging("Autocrafter successfully loaded!") + +basalt.autoUpdate() \ No newline at end of file diff --git a/docs/objects/Animation/changeBackground.md b/docs/objects/Animation/changeBackground.md index fa38ea0..0e4bf73 100644 --- a/docs/objects/Animation/changeBackground.md +++ b/docs/objects/Animation/changeBackground.md @@ -14,7 +14,7 @@ Changes the background color while the animation is running ```lua local mainFrame = basalt.createFrame() local testButton = mainFrame:addButton("buttonToAnimate") -local aAnimation = mainFrame:addAnimation():setObject(testButton):changeBackground({colors.red, colors.yellow, colors.green}, 2):play() +local aAnimation = mainFrame:addAnimation():setObject(testButton):changeTextColor(2, 0, colors.red, colors.yellow, colors.green):play() ``` ```xml @@ -25,4 +25,4 @@ local aAnimation = mainFrame:addAnimation():setObject(testButton):changeBackgrou 2 -``` +``` \ No newline at end of file diff --git a/docs/objects/Animation/changeText.md b/docs/objects/Animation/changeText.md index e5a6019..d2bdb11 100644 --- a/docs/objects/Animation/changeText.md +++ b/docs/objects/Animation/changeText.md @@ -14,7 +14,7 @@ Changes the text while animation is running ```lua local mainFrame = basalt.createFrame() local testButton = mainFrame:addButton("buttonToAnimate") -local aAnimation = mainFrame:addAnimation():setObject(testButton):changeText({"i", "am", "groot"}, 2):play() +local aAnimation = mainFrame:addAnimation():setObject(testButton):changeText(2, 0, "i", "am", "groot"):play() ``` ```xml diff --git a/docs/objects/Animation/changeTextColor.md b/docs/objects/Animation/changeTextColor.md index 26b9153..e23c586 100644 --- a/docs/objects/Animation/changeTextColor.md +++ b/docs/objects/Animation/changeTextColor.md @@ -14,7 +14,7 @@ Changes the text color while the animation is running ```lua local mainFrame = basalt.createFrame() local testButton = mainFrame:addButton("buttonToAnimate") -local aAnimation = mainFrame:addAnimation():setObject(testButton):changeTextColor({colors.red, colors.yellow, colors.green}, 2):play() +local aAnimation = mainFrame:addAnimation():setObject(testButton):changeTextColor(2, 0, colors.red, colors.yellow, colors.green):play() ``` ```xml diff --git a/docs/objects/Button.md b/docs/objects/Button.md index 3b00e7f..b4c2a5a 100644 --- a/docs/objects/Button.md +++ b/docs/objects/Button.md @@ -24,13 +24,13 @@ end) and this would be the xml way: ```lua -local main = basalt.createFrame():addLayout("example.xml") - basalt.setVariable("buttonClick", function(self,event,button,x,y) if(event=="mouse_click")and(button==1)then basalt.debug("Left mousebutton got clicked!") end end) + +local main = basalt.createFrame():addLayout("example.xml") ``` ```xml