MrCyberdragon

Ipeni Shop for 1.16

Jun 17th, 2021
754
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. --[[
  2.  
  3. CC BY-SA License
  4.  
  5. Copyright (c) 2020 ipeni
  6.  
  7. reusers may distribute, remix, adapt, and build upon the material in any medium or format, so long as attribution is given to the creator. This license allows for commercial use. If you remix, adapt, or build upon the material, you must license the modified material under identical terms.
  8. --]]
  9.  
  10. disk = nil
  11. monitor = nil
  12. modem = nil
  13. wiredModem = nil
  14. monitorSide = nil
  15. itemPrices =  {}
  16.  
  17. t = nil
  18.  
  19. currentUser = nil
  20. playerBalance = 0
  21. cart = 0
  22. cost = 0
  23.  
  24. items = {}
  25.  
  26. function checkForFloppy()
  27.     while true do
  28.         local e, s, sC, rC, m, dist = os.pullEvent()
  29.         if e == "disk" and not fs.exists("disk/user.txt") then
  30.             currentUser = {}
  31.             local newUser = generateId()
  32.             write("Creating User File...")
  33.             userFile = fs.open("disk/user.txt", "w")
  34.             print("writing to balances file...")
  35.             --Create user file on inserted disk
  36.             userFile.writeLine(newUser)
  37.             userFile.close()
  38.             --Read balances file and initialized newly created user
  39.             balances = fs.open("balances.txt", "r")
  40.             serialized = textutils.unserialise(balances.readAll())
  41.             balances.close()
  42.             serialized[newUser] = 0
  43.             --Open balances file in write mode and insert the new data
  44.             balances = fs.open("balances.txt", "w")
  45.             balances.write(textutils.serialise(serialized))
  46.             balances.close()
  47.             write("User file created.")
  48.             reDrawItems(true)
  49.         elseif e == "disk" and fs.exists("disk/user.txt") then
  50.             userfile = fs.open("disk/user.txt", "r")
  51.             user = userfile.readAll()
  52.             balances = fs.open("balances.txt", "r")
  53.             balTable = textutils.unserialise(balances.readAll())
  54.             playerBalance = balTable[user]
  55.             currentUser = user
  56.             reDrawItems(true)
  57.         elseif e == "disk_eject" then
  58.             write("Thanks for shopping, come again")
  59.             --Reset all store parameters
  60.             currentUser = nil
  61.             playerBalance = 0
  62.             cart = 0
  63.             activePage = 1
  64.             reDrawItems(true)
  65.         end
  66.     end
  67. end
  68.  
  69. --Generates new User ID, not impossible for duplicated but unlikely, if it becomes problematic we can add an extra character or add a check to regenerate until its unique
  70. function generateId()
  71.     local random = math.random
  72.     local template = "xxxxxxxx"
  73.     local id =
  74.         string.gsub(
  75.         template,
  76.         "[xy]",
  77.         function(c)
  78.             write("Checking User Card...")
  79.             local v = (c == "x") and random(0, 0xf) or random(8, 0xb)
  80.             sleep(0.5)
  81.             return string.format("%x", v)
  82.         end
  83.     )
  84.     return id
  85. end
  86.  
  87. --Waits for messaged from the ATM
  88. function listenForBalanceUpdate()
  89.     while true do
  90.         local e, s, sC, rC, m, dist = os.pullEvent("modem_message")
  91.         if m["request"] == "balance_update" then
  92.             print("updating balance for " .. m["user"])
  93.             file = fs.open("balances.txt", "r")
  94.             balances = textutils.unserialise(file.readAll())
  95.             balances[m["user"]] = tonumber(balances[m["user"]]) + tonumber(m["balance"])
  96.             newBalances = fs.open("balances.txt", "w")
  97.             newBalances.write(textutils.serialize(balances))
  98.             newBalances.close()
  99.         end
  100.     end
  101. end
  102.  
  103. function write(str)
  104.     monitor.clear()
  105.     monitor.setCursorPos(1, 1)
  106.     monitor.write(str)
  107. end
  108.  
  109. function listenForTouch()
  110.     while true do
  111.         local e, p1 = t:handleEvents(os.pullEvent())
  112.         if e == "button_click" and t.buttonList[p1].func ~= nil then
  113.             t.buttonList[p1].func()
  114.         end
  115.     end
  116. end
  117.  
  118. function init()
  119.     if not fs.exists("balances.txt") then
  120.         file = fs.open("balances.txt", "w")
  121.         file.writeLine("{}")
  122.         file.close()
  123.     end
  124.     parallel.waitForAll(checkForFloppy, listenForBalanceUpdate, listenForNewItems, listenForTouch, readCommands)
  125. end
  126.  
  127. function initializePeripherals()
  128.     print("Initializing...")
  129.     if not fs.exists("buttons.lua") then
  130.         shell.run("pastebin", "get", "pFHeia96", "buttons.lua")
  131.         os.loadAPI("./buttons.lua")
  132.     else
  133.         os.loadAPI("./buttons.lua")
  134.     end
  135.        
  136.     for k,v in ipairs(peripheral.getNames()) do
  137.         type = peripheral.getType(v)
  138.         if type == "monitor" then
  139.             monitor = peripheral.wrap(v)
  140.             monitor.setTextScale(0.75)
  141.             monitor.write("Please Insert User disk")
  142.             monitorSide = v
  143.             t = buttons.new(monitorSide)
  144.         elseif type == "modem" then
  145.             tempModem = peripheral.wrap(v)
  146.             if tempModem.isWireless() then
  147.                 modem = peripheral.wrap(v)
  148.                 modem.open(404)
  149.             else
  150.                 wiredModem = peripheral.wrap(v)
  151.                 modemNames = wiredModem.getNamesRemote()
  152.                 for x,y in ipairs(modemNames) do
  153.                     if y:match("drive",1,true) then
  154.                         disk = peripheral.wrap(y)
  155.                         break
  156.                     end
  157.                 end
  158.             end
  159.         end
  160.     end
  161.     if modem == nil or disk == nil then
  162.         print("please connect a modem and disk drive to this computer")
  163.         sleep(3)
  164.         initializePeripherals()
  165.     elseif monitor == nil then
  166.         print("please connect a monitor to this computer")
  167.         sleep(3)
  168.         initializePeripherals()
  169.     elseif modem ~= nil and monitor ~= nil and disk ~= nil then
  170.         init()
  171.     end
  172. end
  173.  
  174. function updateCartLabel(oldName, value, operator, stock)
  175.     if cart > stock or cart + value > stock and operator == "add" then
  176.         return false
  177.     end
  178.     if operator == "subtract" and cart - value >= 0 then
  179.         t:rename(oldName, "Cart: " .. cart - value)
  180.         cart = cart - value
  181.         t:draw()
  182.         return true
  183.     elseif operator == "add" and cart <= 64 and cart + value <= 64 then
  184.         t:rename(oldName, "Cart: " .. cart + value)
  185.         cart = cart + value
  186.         t:draw()
  187.         return true
  188.     end
  189.     return false
  190. end
  191.  
  192. function updateCostLabel(oldName, itemName)
  193.     cost = cart * itemPrices[itemName]
  194.     t:rename(oldName, "Cost: " .. cost)
  195.     t:draw()
  196. end
  197.  
  198.  
  199. function sendPurchase(item, amount, stock)
  200.     if playerBalance < amount then
  201.         monitor.clear()
  202.         monitor.setCursorPos(1, 1)
  203.         write("Not enought funds, please deposit at the ATM, redirecting...")
  204.         cart = 0
  205.         sleep(3)
  206.         reDrawItems()
  207.         return
  208.     else
  209.         modem.transmit(420, 404, {request = "get_item", name = item, amount = amount})
  210.         cart = 0
  211.         items[item]["count"] = stock - amount
  212.         file = fs.open("balances.txt", "r")
  213.         balances = textutils.unserialise(file.readAll())
  214.         user = tostring(currentUser)
  215.         balances[user] = tonumber(balances[user]) - (tonumber(amount) * itemPrices[item])
  216.         playerBalance = balances[user]
  217.         newBalances = fs.open("balances.txt", "w")
  218.         newBalances.write(textutils.serialize(balances))
  219.         newBalances.close()
  220.         monitor.clear()
  221.         monitor.setCursorPos(1, 1)
  222.         monitor.write("Thank you for your purchase")
  223.         sleep(2)
  224.         reDrawItems()
  225.     end
  226. end
  227.  
  228. function openProductPage(name)
  229.     stock = items[name]["count"]
  230.     local x, y = monitor.getSize()
  231.     xmin = math.ceil(x / 2 - 5)
  232.     xmax = math.ceil((x / 2) + 5)
  233.     ymin = math.ceil(y / 3)
  234.     ymax = math.ceil((y / 3) + 2)
  235.     t = buttons.new(monitorSide)
  236.     t:add(name .. " - Stock: " .. stock .. " - Price: " .. itemPrices[name], nil, x - x + 1, ymin, x - 1, ymax, colors.black, colors.white)
  237.     t:add(
  238.         "Purchase",
  239.         function()
  240.             sendPurchase(name, cart, stock)
  241.         end,
  242.         x / 5 * 2 + 1,
  243.         y - 6,
  244.         x / 5 * 3,
  245.         y - 1,
  246.         colors.green,
  247.         colors.black
  248.     )
  249.     cost = cart * itemPrices[name]
  250.     t:add("Cart: " .. cart, nil, x - x + 1, ymin + 3, x - 1, ymax + 3, colors.black, colors.white)
  251.     t:add("Cost: " .. cost, nil, x - x + 1, ymin + 6, x - 1, ymax + 6, colors.black, colors.white)
  252.     t:add(
  253.         "+1",
  254.         function()
  255.             if updateCartLabel("Cart: " .. cart, 1, "add", stock) then
  256.                 updateCostLabel("Cost: " .. cost, name)
  257.             end
  258.         end,
  259.         math.ceil(x / 3 - 5),
  260.         math.ceil(ymin + 10),
  261.         math.ceil(x / 3 + 5),
  262.         math.ceil(ymax + 10),
  263.         colors.green,
  264.         colors.black
  265.     )
  266.     t:add(
  267.         "+5",
  268.         function()
  269.             if updateCartLabel("Cart: " .. cart, 5, "add", stock) then
  270.                 updateCostLabel("Cost: " .. cost, name)
  271.             end
  272.         end,
  273.         math.ceil(x / 3 - 5),
  274.         math.ceil(ymin + 13),
  275.         math.ceil(x / 3 + 5),
  276.         math.ceil(ymax + 13),
  277.         colors.blue,
  278.         colors.black
  279.     )
  280.     t:add(
  281.         "+10",
  282.         function()
  283.             if updateCartLabel("Cart: " .. cart, 10, "add", stock) then
  284.             updateCostLabel("Cost: " .. cost, name)
  285.             end
  286.         end,
  287.         math.ceil(x / 3 - 5),
  288.         math.ceil(ymin + 16),
  289.         math.ceil(x / 3 + 5),
  290.         math.ceil(ymax + 16),
  291.         colors.green,
  292.         colors.black
  293.     )
  294.     t:add(
  295.         "-1",
  296.         function()
  297.             if updateCartLabel("Cart: " .. cart, 1, "subtract", stock) then
  298.             updateCostLabel("Cost: " .. cost, name)
  299.             end
  300.         end,
  301.         math.ceil((x / 3) * 2 - 5),
  302.         math.ceil(ymin + 10),
  303.         math.ceil((x / 3) * 2 + 5),
  304.         math.ceil(ymax + 10),
  305.         colors.green,
  306.         colors.black
  307.     )
  308.     t:add(
  309.         "-5",
  310.         function()
  311.             if updateCartLabel("Cart: " .. cart, 5, "subtract", stock) then
  312.             updateCostLabel("Cost: " .. cost, name)
  313.             end
  314.         end,
  315.         math.ceil((x / 3) * 2 - 5),
  316.         math.ceil(ymin + 13),
  317.         math.ceil((x / 3) * 2 + 5),
  318.         math.ceil(ymax + 13),
  319.         colors.blue,
  320.         colors.black
  321.     )
  322.     t:add(
  323.         "-10",
  324.         function()
  325.             if updateCartLabel("Cart: " .. cart, 10, "subtract", stock) then
  326.             updateCostLabel("Cost: " .. cost, name)
  327.             end
  328.         end,
  329.         math.ceil((x / 3) * 2 - 5),
  330.         math.ceil(ymin + 16),
  331.         math.ceil((x / 3) * 2 + 5),
  332.         math.ceil(ymax + 16),
  333.         colors.green,
  334.         colors.black
  335.     )
  336.     t:add(
  337.         "back",
  338.         function()
  339.             reDrawItems()
  340.         end,
  341.         1,
  342.         1,
  343.         10,
  344.         3,
  345.         colors.red,
  346.         colors.white
  347.     )
  348.     t:add("Balance: " .. playerBalance, nil, x - 20, 1, x - 1, 10, colors.green, colors.black)
  349.     t:draw()
  350. end
  351.  
  352. activePage = 1
  353. pageCount = 1
  354. pages = {}
  355.  
  356. function reDrawItems(reload)
  357.     reload = reload or false
  358.     if items == nil or t == nil or tablelength(items) < 1 then
  359.         write("items or monitor yet to be initialized")
  360.         return
  361.     end
  362.     if currentUser == nil then
  363.         write("Please insert your user card...")
  364.         return
  365.     end
  366.     t = buttons.new(monitorSide)
  367.     if reload then
  368.         pages = {}
  369.  
  370.         index = 0
  371.         page = 1
  372.         pages[page] = {}
  373.         tempItems = {}
  374.         for k, v in pairs(items) do
  375.             name = ""
  376.             if string.find(k, ":") then
  377.                 name = string.match(tostring(k), ":(.*)")
  378.             else
  379.                 name = k
  380.             end
  381.             table.insert(tempItems, {name = name})
  382.             pages[page] = tempItems
  383.             if 20 / index == 1 then
  384.                 tempItems = {}
  385.                 index = 0
  386.                 page = page + 1
  387.                 pageCount = page
  388.             else
  389.                 index = index + 1
  390.             end
  391.         end
  392.     end
  393.         column = 20
  394.         row = 1
  395.         columnTwo = 1
  396.         indexTwo = 0
  397.         for k, v in ipairs(pages[activePage]) do
  398.             t:add(
  399.                 v.name,
  400.                 function()
  401.                     openProductPage(v.name)
  402.                 end,
  403.                 column - 18,
  404.                 row * 3 - 1,
  405.                 column - 2,
  406.                 row * 3,
  407.                 colors.red,
  408.                 colors.lime
  409.             )
  410.             if 6 / indexTwo == 1 then
  411.                 column = (columnTwo + 1) * 20
  412.                 columnTwo = columnTwo + 1
  413.                 row = 1
  414.                 indexTwo = 0
  415.             else
  416.                 indexTwo = indexTwo + 1
  417.                 row = row + 1
  418.             end
  419.         end
  420.         local x, y = monitor.getSize()
  421.         if activePage + 1 <= pageCount then
  422.             t:add(
  423.                 "Next ->",
  424.                 function()
  425.                     if activePage + 1 <= pageCount then
  426.                         activePage = activePage + 1
  427.                     end
  428.                     reDrawItems()
  429.                 end,
  430.                 2,
  431.                 30,
  432.                 15,
  433.                 35,
  434.                 colors.red,
  435.                 colors.green
  436.             )
  437.         end
  438.         if activePage - 1 >= 1 then
  439.             t:add(
  440.                 "Back <-",
  441.                 function()
  442.                     if activePage + 1 >= 1 then
  443.                         activePage = activePage - 1
  444.                     end
  445.                     reDrawItems()
  446.                 end,
  447.                 20,
  448.                 30,
  449.                 35,
  450.                 35,
  451.                 colors.red,
  452.                 colors.green
  453.             )
  454.         end
  455.     t:draw()
  456. end
  457.  
  458. function listenForNewItems()
  459.     if tablelength(items) < 1 then
  460.         sendRebootToTurtles()
  461.         sleep(3)
  462.         sendFileToTurtles("turtles.lua")
  463.     end
  464.     while true do
  465.         local e, s, sC, rC, m, dist = os.pullEvent("modem_message")
  466.         if(m["request"] == "init") then
  467.             pricesFile = nil
  468.             if not fs.exists("prices.txt") then
  469.                 pricesFile = fs.open("prices.txt", "w")
  470.                 pricesFile.writeLine("{}")
  471.                 pricesFile.close()
  472.             end
  473.             pricesFile = fs.open("prices.txt", "r")
  474.             prices = textutils.unserialise(pricesFile.readAll())
  475.             for k,v in pairs(m["data"]) do
  476.                 items[k] = v
  477.                 if(prices[k] == nil) then
  478.                     prices[k] = 1
  479.                 end
  480.             end
  481.             pricesFile = fs.open("prices.txt", "w")
  482.             newPrices = textutils.serialise(prices)
  483.             itemPrices = prices
  484.             pricesFile.write(newPrices)
  485.             pricesFile.close()
  486.             reDrawItems(true)
  487.         elseif m["request"] == "balance_request" then
  488.             local balancesFile = fs.open("balances.txt", "r")
  489.             local balances = textutils.unserialise(balancesFile.readAll())
  490.             balancesFile.close()
  491.             local balance = balances[m["user"]]
  492.             modem.transmit(6969,404, { request = "balance_transmission", balance = balance})
  493.         end
  494.     end
  495. end
  496.  
  497. function readCommands()
  498.     while true do
  499.         if itemPrices == nil then
  500.             return
  501.         end
  502.         print("Waiting for command")
  503.         sInput = read()
  504.         if sInput == "changePrice" then
  505.             print("Type an item name...")
  506.             sInput = read()
  507.             matches = {}
  508.             for k,v in pairs(itemPrices) do
  509.                 if k:match(sInput,1, true) then
  510.                     table.insert(matches, k)
  511.                 end
  512.             end
  513.             length = tablelength(matches)
  514.             if length == 0 then
  515.                 print("no matches")
  516.             elseif length == 1 then
  517.                 print("what would you like to set the price to?")
  518.                 sInput = read()
  519.                 name = matches[1]
  520.                 itemPrices[name] = tonumber(sInput)
  521.                 savePrices(itemPrices)
  522.             else
  523.                 for k,v in ipairs(matches) do
  524.                     print(k..": Matched "..v)
  525.                 end
  526.                 print("please select 1 by index provided")
  527.                 sInput = read()
  528.                 name = matches[tonumber(sInput)]
  529.                 print("what would you like to set the price to?")
  530.                 sInput = read()
  531.                 itemPrices[name] = tonumber(sInput)
  532.                 savePrices(itemPrices)
  533.             end
  534.             sleep(2)
  535.         elseif sInput == "help" then
  536.             print("Available commands are changePrice, sendReboot, and sendFile")
  537.             sleep(2)
  538.         elseif sInput == "sendFile" then
  539.             print("Please provide file name..")
  540.             sInput = read()
  541.             sendFileToTurtles(sInput)
  542.             sleep(2)
  543.         elseif sInput == "sendReboot" then
  544.             print("Rebooting turtles...")
  545.             sendRebootToTurtles()
  546.             print("Please send the turtles a file onces reboot has completed")
  547.             sleep(2)
  548.         end
  549.     end
  550. end
  551.  
  552. function sendFileToTurtles(fileName)
  553.     if not fs.exists("turtles.lua") then
  554.         shell.run("pastebin","get","7JRHhjUe","turtles.lua")
  555.     end
  556.     data = {}
  557.     data["request_name"] = "slave"
  558.     file = fs.open(fileName, "r")
  559.     data["file"] = file.readAll()
  560.     modem.transmit(420, 69, data)
  561. end
  562.  
  563. function sendRebootToTurtles()
  564.     data = {}
  565.     data["request"] = "reboot"
  566.     modem.transmit(420,69,data)
  567. end
  568.  
  569.  
  570.  
  571. function savePrices(prices)
  572.     newPrices = textutils.serialise(prices)
  573.     file = fs.open("prices.txt", "w")
  574.     file.write(newPrices)
  575.     file.close()
  576. end
  577.  
  578. function tablelength(T)
  579.   local count = 0
  580.   for _ in pairs(T) do count = count + 1 end
  581.   return count
  582. end
  583.  
  584. initializePeripherals()
  585.  
RAW Paste Data