Skip to content

Instantly share code, notes, and snippets.

@MacChuck
Last active December 15, 2023 20:47
Show Gist options
  • Save MacChuck/780d80cbcb7b457500e0030f921ab43f to your computer and use it in GitHub Desktop.
Save MacChuck/780d80cbcb7b457500e0030f921ab43f to your computer and use it in GitHub Desktop.
Turtle Cafe
print("ID: "..os.getComputerID().." Label: "..os.getComputerLabel())
turtle = 34
os.loadAPI("touchpoint")
peripheral.find("modem", rednet.open)
mon = peripheral.wrap("top")
mon.setTextScale(.7)
monW,monH = mon.getSize()
local pageFood = touchpoint.new("top")
local pageManager = touchpoint.new("top")
local pageWait = touchpoint.new("top")
local pageAlert = touchpoint.new("top")
local t
os.startTimer(1)
function emptyFunc()
--do nothing
end
function managerScreen()
t = pageManager
t:draw()
end
function alertScreen()
pageAlert:add("No Fuel",emptyFunc,1,2,monW,2,colors.red,colors.red)
pageAlert:add("notify",emptyFunc,1,4,monW,4,colors.red,colors.red)
pageAlert:add("management",emptyFunc,1,5,monW,5,colors.red,colors.red)
t = pageAlert
t:draw()
end
function multiOrder()
rednet.send(turtle,{"Sandwich",30})
end
-- Functions for ordering food and empty function should be swapped around and reworked.
-- The default/nil behavior is to send the name of the button over rednet.
pageFood:add("Order Here",emptyFunc,2,1,monW-2,1,colors.black,colors.black)
pageFood:add("", managerScreen,monW-1,1,monW,1,colors.black,colors.black)
pageFood:add("Fried Rice", nil, 1,2,monW,2, colors.green, colors.lime)
pageFood:add("Caramel", nil, 1,3,monW,3, colors.green, colors.lime)
pageFood:add("Cheesecake", nil, 1,4,monW,4, colors.green, colors.lime)
pageFood:add("Coffee Cake", nil, 1,5,monW,5, colors.green, colors.lime)
pageFood:add("Sweet Roll", nil, 1,6,monW,6, colors.green, colors.lime)
pageFood:add("Sandwich", nil, 1,7,monW,7, colors.green, colors.lime)
pageFood:add("Sushi", nil, 1,8,monW,8, colors.green, colors.lime)
pageFood:add("Coffee", nil, 1,9,monW,9, colors.green, colors.lime)
pageFood:add("Hot Chocolate", nil, 1,10,monW,10, colors.green, colors.lime)
pageWait:add("Cooking...",emptyFunc,1,2,monW,2,colors.black,colors.black)
pageManager:add("Manager",emptyFunc,1,1,monW,1,colors.red,colors.red)
pageManager:add("Cake", nil, 1,2,monW,2, colors.green, colors.lime)
pageManager:add("Sandwich",multiOrder,1,3,monW-5,3,colors.green,colors.lime)
pageManager:add("x30",emptyFunc,monW-4,3,monW,3,colors.green,colors.green)
t = pageFood
t:draw()
function waitScreen()
t = pageWait
t:draw()
end
function menuScreen()
t = pageFood
t:draw()
end
function callButton(name)
if t.buttonList[name].func ~= nil then
t.buttonList[name].func()
else
rednet.send(turtle,name)
end
end
while true do
local event, p1, msg, proto = t:handleEvents(os.pullEvent())
if event == "button_click" then
t:flash(p1)
callButton(p1)
elseif event == "rednet_message" then
if p1 == turtle then
if msg == "cooking" then waitScreen()
elseif msg == "served" then menuScreen()
elseif msg == "lowfuel" then alertScreen()
end
end
elseif event == "timer" then
os.startTimer(10)
end
end
print("ID: "..os.getComputerID().." Label: "..os.getComputerLabel())
controlComputer = 31
peripheral.find("modem",rednet.open)
arg1,arg2 = ...
-- update function and arg check
function update()
shell.run( "rm", shell.getRunningProgram() ) -- Delete the current program
shell.run( "pastebin", "get", "BehPqTT7", shell.getRunningProgram() ) -- Update it
print("updated, please restart")
error("exiting intentionally")
end
if (arg1 ~= nil) and (string.lower(arg1) == "update") then
update()
end
os.startTimer(1)
-- Bowls and cups are using slot 16
-- Crafting uses the lower right 9 squares
-- current location and counter position
curLoc = 0
counter = "front" --left, right, front, rear
--workstation locations
--using location 0 for home to trigger and undock if needed
fridge1 = 1
fridge2 = 2
kettle = 3
pot = 4
shelf = 5
cocoa = 6
milk = 7
serve = 4
--recipes/menu
-- key / workstation, ingredients
-- workstations determine if/what shelf item should be used
menu = {}
menu["Caramel"] = {"none","caramel"}
menu["Cheesecake"] = {"none","cheesecake"}
menu["Coffee Cake"] = {"none","coffee cake"}
menu["Sandwich"] = {"crafting","bread","bacon","tomato","cabbage"}
menu["Sweet Roll"] = {"milk","bread"}
menu["Hot Chocolate"] = {"cocoa"}
menu["Coffee"] = {"kettle","coffee beans","coffee beans"}
menu["Fried Rice"] = {"pot", "rice","egg","carrot","onion"}
menu["Sushi"] = {"special","rice","salmon","salmon"}
menu["Cake"] = {"special","milk","milk","milk","sugar","egg","sugar","wheat","wheat","wheat"}
-- table copying function from
-- https://gist.github.com/tylerneylon/81333721109155b2d244
function copyTable(obj, seen)
-- Handle non-tables and previously-seen tables.
if type(obj) ~= 'table' then return obj end
if seen and seen[obj] then return seen[obj] end
-- New table; mark it as seen and copy recursively.
local s = seen or {}
local res = {}
s[obj] = res
for k, v in pairs(obj) do res[copyTable(k, s)] = copyTable(v, s) end
return setmetatable(res, getmetatable(obj))
end
function inspectName()
s,d = turtle.inspect()
if s then
return d.name
else
return ""
end
end
function home()
if inspectName():find("computer_advanced") then
-- already home
else
while turtle.down() do
-- move down to the floor
end
for i = 1,4 do
if inspectName():find("stairs") then --found counter
turtle.turnLeft() --face "right"
turtle.up() --above counter
break
elseif inspectName():find("fridge") then --found fridge
turtle.turnRight() --face "right"
break
elseif inspectName():find("computer") then
turtle.turnLeft()
break
end
turtle.turnLeft()
end
while turtle.forward() do end --move to window by computer
turtle.turnRight()
turtle.forward()
turtle.down()
end
curLoc = 0
counter = "front"
end
function unHome()
turtle.turnRight()
counter = "left"
turtle.turnRight()
counter = "rear"
turtle.up()
turtle.forward()
curLoc = 1
end
function fuelCheck()
if turtle.getFuelLevel() < 30 then
rednet.send(controlComputer,"lowfuel")
print("Insert Fuel")
while turtle.getFuelLevel() < 30 do
os.sleep(3)
turtle.select(1)
turtle.refuel()
end
rednet.send(controlComputer,"served") --reset the order screen to the default
end
end
function faceLeft()
if counter == "front" then
turtle.turnRight()
elseif counter == "rear" then
turtle.turnLeft()
elseif counter == "right" then
turtle.turnRight() turtle.turnRight()
end
counter = "left"
end
function faceRight()
if counter == "front" then
turtle.turnLeft()
elseif counter == "rear" then
turtle.turnRight()
elseif counter == "left" then
turtle.turnLeft() turtle.turnLeft()
end
counter = "right"
end
function faceWork()
if counter == "front" then
turtle.turnRight() turtle.turnRight()
elseif counter == "right" then
turtle.turnLeft()
elseif counter == "left" then
turtle.turnRight()
end
counter = "rear"
end
function faceCounter()
if counter == "rear" then
turtle.turnRight() turtle.turnRight()
elseif counter == "left" then
turtle.turnLeft()
elseif counter == "right" then
turtle.turnRight()
end
counter = "front"
end
function goTo(destination)
-- If we're in the home location, unhome before moving left to right
if curLoc == 0 then
unHome()
curLoc = 1
end
distance = curLoc - destination
if destination > curLoc then
faceLeft()
for i=1,math.abs(distance) do
turtle.forward()
end
elseif destination < curLoc then
faceRight()
for i=1,math.abs(distance) do
turtle.forward()
end
end
curLoc = destination
end
function getIngredient(item)
if item == nil then
--no item requested
return 0
end
print("looking for "..item)
fridge = peripheral.wrap("front")
size = fridge.size()
for i=1,size do
if fridge.getItemDetail(i) ~= nil then
if fridge.getItemDetail(i).displayName:lower():find(item) then
--print("Found "..item.." in slot "..i)
fridge.pushItems("front",1,64,size) --move item 1 to last slot
fridge.pushItems("front",i,64,1) --move found item to slot 1
fridge.pushItems("front",size,64,i) --move item in last slot to original slot for found item
turtle.suck(1)
return 1 --found the item and grabbed it, stop looking
end
end
end
end
function gatherIngredients(recipe)
--table to use for shorter searching of the 2nd fridge if necessary
local recipeCopy = copyTable(recipe)
turtle.select(1)
itemsFound = 1 --starting at 1 to skip workstation keyword in the count
-- fridge 1
goTo(fridge1)
faceWork()
for i = 2,#recipe do
if getIngredient(recipe[i]) then
itemsFound = itemsFound + 1
recipeCopy[i] = nil --clear this item from the 2nd fridge ingredient list
end
end
-- fridge 2
if itemsFound < #recipe then
goTo(fridge2)
faceWork()
for i = 2,#recipeCopy do
getIngredient(recipeCopy[i])
end
end
end
function potCooking(recipe)
--get dish
goTo(shelf)
faceWork()
turtle.select(16) --dish in slot 16
getIngredient("bowl")
--fill pot
goTo(pot)
faceWork()
turtle.drop() --add dish from 16
turtle.select(1)
turtle.up()
turtle.forward()
for i=1,#recipe do
turtle.select(i)
turtle.dropDown()
end
--get food
turtle.back()
turtle.down()
turtle.select(1)
repeat until(turtle.suck())
end
function kettleCooking()
--get dish
goTo(shelf)
faceWork()
turtle.select(16) --dish to slot 16
getIngredient("bottle")
--fill kettle
goTo(kettle)
faceWork()
turtle.drop() --add bottle from 16
turtle.select(1)
turtle.up()
turtle.forward()
turtle.dropDown()
k = peripheral.wrap("bottom")
k.pushItems("bottom",1,1,2) --1 item in first slot of kettle to 2nd slot
turtle.select(2) --2nd ingredient if a 2 item recipe
turtle.dropDown()
--get food
turtle.back()
turtle.down()
turtle.select(1)
repeat until(turtle.suck())
end
function useSpout(ordered)
turtle.select(1)
turtle.down()
turtle.drop()
d = peripheral.wrap("front")
repeat until(d.getItemDetail(1).displayName:find(ordered))
turtle.suck()
turtle.up()
end
function milkSpout(ordered)
goTo(milk)
faceWork()
useSpout(ordered)
end
function cocoaSpout(ordered)
--get dish
goTo(shelf)
faceWork()
turtle.select(1) --dish to slot 1
getIngredient("bottle")
goTo(cocoa)
faceWork()
useSpout(ordered)
end
function sortAndCraft(count)
grid = {16,15,14,12,11,10,8,7,6}
g = 1
for s=count,1,-1 do
turtle.select(s)
for i=1,turtle.getItemCount(s) do
turtle.transferTo(grid[g],1)
g = g + 1
end
end
turtle.select(1)
turtle.craft()
end
function craftSushi()
--find which slots the rice and fish are in
riceSlot = 0
fishSlot = 0
for i=1,4 do
if turtle.getItemCount(i) > 0 then
if turtle.getItemDetail(i).name:find("rice") then
riceSlot = i
elseif turtle.getItemDetail(i).name:find("salmon") then
fishSlot = i
end
end
end
--get the rice into slot 1
turtle.select(fishSlot)
turtle.transferTo(8)
fishSlot = 8
turtle.select(riceSlot)
turtle.transferTo(1)
-- cook the rice in slot 1
potCooking({"rice"})
-- move the fish back to slot 2
turtle.select(fishSlot)
turtle.transferTo(2)
--make the sushi
sortAndCraft(4)
--find the bowl
for i=1,16 do
if turtle.getItemCount(i) > 0 then
if turtle.getItemDetail(i).name:find("bowl") then
turtle.select(i)
break
end
end
end
--store the bowl
goTo(shelf)
faceWork()
turtle.drop()
end
function craftCake()
--BUG: not very resiliant due to being a shaped crafting recipe, should search and sort by name in the turtle to make better.
-- free up slot 1
for i = 9,1,-1 do
turtle.select(i)
turtle.transferTo(i+1)
end
--get 3 bottles
goTo(shelf)
faceWork()
turtle.select(1)
for i = 1,3 do
getIngredient("bottle")
end
--fill bottles
milkSpout("Milk")
--split sugar
turtle.select(4) turtle.transferTo(5)
turtle.select(2) turtle.transferTo(4,1)
--craft the cake
sortAndCraft(9)
--find and store the empty bottles
goTo(shelf)
faceWork()
for i=1,16 do
if turtle.getItemCount(i) > 0 then
if turtle.getItemDetail(i).name:find("bottle") then
turtle.select(i)
turtle.drop()
end
end
end
end
function serveFood()
goTo(serve)
faceCounter()
turtle.select(1) --test with crafty turtle, may need to use another slot or search
turtle.drop()
end
function cook(ordered)
rednet.send(controlComputer,"cooking")
--clear terminal before showing crafting status
term.clear()
term.setCursorPos(1,1)
-- load recipe
recipe = menu[ordered]
workstation = recipe[1]
gatherIngredients(recipe)
if workstation == "none" then
--no workstation or crafting, just serve
elseif workstation == "milk" then
milkSpout(ordered)
elseif workstation == "cocoa" then
cocoaSpout(ordered)
elseif workstation == "pot" then
potCooking(recipe)
elseif workstation == "kettle" then
kettleCooking()
elseif workstation == "crafting" then
sortAndCraft(#recipe)
elseif workstation == "special" then
if ordered == "Sushi" then
craftSushi()
elseif ordered == "Cake" then
craftCake()
end
end
serveFood()
rednet.send(controlComputer,"served")
-- check fuel after each craft
fuelCheck()
end
--Check fuel and go home on startup before doing anything else
fuelCheck()
home()
--multicraft
function multicraft(ordered,qty)
for i = 1,qty do
cook(ordered)
end
end
--launch args override
if (arg1 ~= nil) and (arg1 ~= "update") then
if (arg2 ~= nil) then
for i=1,arg2 do
cook(arg1)
end
else
cook(arg1)
end
end
while true do
local evt,sid,msg,proto = os.pullEvent()
if evt == "rednet_message" then
if sid == controlComputer then
if type(msg) == "string" then
print("Order for: "..msg)
cook(msg)
elseif type(msg) == "table" then
print("Order for: "..msg[1].." x"..msg[2])
multicraft(msg[1],msg[2])
end
end
elseif evt == "timer" then
os.startTimer(30)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment