Advertisement
nagoL2015

shopv2

Oct 27th, 2018
93
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 26.60 KB | None | 0 0
  1.  
  2. --  00      0000 0000    000000   0000000   00    00      00000   00    00    0000    0000000
  3. --  00      0000000000  00000000  00000000  00    00     000000   00    00   000000   00000000         8888
  4. --  00      00  00  00  00    00  00    00  000  000    00        00    00  00    00  00    00        888888
  5. --  00  00  00  00  00  00    00  00    00   000000     00        00    00  00    00  00    00       88    88
  6. --  00 00   00  00  00  00000000  00000000    0000       00000    00000000  00    00  00000000       88    88
  7. --  0000    00  00  00  00000000  0000000     0000        00000   00000000  00    00  0000000      888888888888
  8. --  000     00  00  00  00    00  00 000     000000           00  00    00  00    00  00           888888888888
  9. --  0000    00  00  00  00    00  00  000   000  000          00  00    00  00    00  00           888 v0.2 888
  10. --  00 00   00  00  00  00    00  00   000  00    00     000000   00    00   000000   00           888888888888
  11. --  00  00  00  00  00  00    00  00    00  00    00     00000    00    00    0000    00            8888888888
  12.  
  13. -- kMarx (Krist Markets) Shop Program v0.2 - Created by HydroNitrogen - purpose environment: KristPay on SwitchCraft 2
  14. -- https://energetic.pw/computercraft/kmarx | energetic.pw/kmarx
  15.  
  16. -- ### LICENCE, RIGHTS and TERMS ###
  17. -- Anyone is allowed to use this program on any kristpay enabled server, given that they comply with the usage policy below.
  18. -- Anyone is allowed to make modifications for their personal needs.
  19. -- Nobody is allowed to sell, distribute or publish this program or parts of it in any way, modified or unmodified.
  20. -- Nobody can hold me, the author, responsible for any damage this program may cause, including but not limited to theft/loss of krist, items, blocks etc...
  21. --
  22. -- ### USAGE POLICY ###
  23. -- Anyone using this shop program must either:
  24. -- 1. Share a royalty (percentage) of more than 10% of sales (rounded down in your favour) with the creator of the program (HydroNitrogen).
  25. -- 2. Have a permanent display of credits on the main shop monitor.
  26. -- You can choose either 1, 2 or both options via the configuration file that the shop uses.
  27.  
  28. local success, error = pcall(function()
  29.   local dataFile = "/shopData.lua"
  30.  
  31.   if not fs.exists("k.lua") then shell.run("pastebin", "run 4ddNhMYd") end
  32.  
  33.   local w = require("w")
  34.   local r = require("r")
  35.   local k = require("k")
  36.   local jua = require("jua")
  37.   os.loadAPI("json.lua")
  38.   local await = jua.await
  39.  
  40.   r.init(jua)
  41.   w.init(jua)
  42.   k.init(jua, json, w, r)
  43.  
  44.   if not fs.exists("blittle.lua") then shell.run("pastebin", "get ujchRSnU blittle.lua") end
  45.   os.loadAPI("blittle.lua")
  46.  
  47.   local mon = peripheral.find("monitor") -- Do you error here? Then you haven't connected a monitor properly.
  48.   mon.setTextScale(.5)
  49.   local xm, ym = mon.getSize()
  50.  
  51.   local chestContent = {}
  52.   local stockLevels = {}
  53.   local lookupTable = {}
  54.   local chest
  55.  
  56.   local monMaxX, monMaxY = mon.getSize()
  57.  
  58.   local function getData(file)
  59.     print("[info] Getting data from file")
  60.     if not fs.exists(file) then error("There's no data file! The shop needs a data file!") end
  61.     local h = fs.open(file, "r")
  62.     local unserialized = textutils.unserialize(h.readAll()) -- Do you error here? Then your data file is probably corrupt.
  63.     if unserialized == nil then error("[error] Could not serialize shop data file!") end
  64.     h.close()
  65.     return unserialized
  66.   end
  67.  
  68.   if not fs.exists(dataFile) then shell.run("wget", "https://energetic.pw/computercraft/kmarx/assets/v0.2/shopData.lua " .. dataFile) end
  69.   local shopData = getData(dataFile)
  70.  
  71.   local function makeDataSafe()
  72.     shopData.config.name = string.sub(shopData.config.name, 1, 128)
  73.     shopData.config.owner = string.sub(shopData.config.owner, 1, 64)
  74.     shopData.config.krist.privatekey = string.sub(shopData.config.krist.privatekey, 1, 512)
  75.     shopData.config.krist.domainname = string.sub(shopData.config.krist.domainname, 1, 32)
  76.     shopData.config.messages.overpaid = string.sub(shopData.config.messages.overpaid, 1, 192)
  77.     shopData.config.messages.underpaid = string.sub(shopData.config.messages.underpaid, 1, 192)
  78.     shopData.config.messages.outofstock = string.sub(shopData.config.messages.outofstock, 1, 192)
  79.     shopData.config.messages.unknownitem = string.sub(shopData.config.messages.unknownitem, 1, 192)
  80.   end
  81.  
  82.   makeDataSafe()
  83.  
  84.   local function saveConfig()
  85.     if not fs.exists("/shopData-old.lua") then
  86.       fs.copy(dataFile, "/shopData-old.lua")
  87.     end
  88.     local serialized = textutils.serialize(shopData)
  89.     local handle = fs.open(dataFile, "w")
  90.     handle.write(serialized)
  91.     handle.flush()
  92.     handle.close()
  93.     print("[info] Config file updated and saved.")
  94.   end
  95.  
  96.   local function updateConfigTo2()
  97.     shopData.config.krist.iskristwalletformat = false
  98.     shopData.config.redstoneside = "top"
  99.     shopData.iv = 2
  100.  
  101.     --UNCOMMENT the following line if you want to have your config file automatically updated. [ NOT RECOMMENDED ]
  102.     --saveConfig()
  103.   end
  104.  
  105.   local logoImage
  106.   if not fs.exists(shopData.layout.logo.location) then shell.run("wget", "https://energetic.pw/computercraft/kmarx/assets/v0.2/shopLogo.lua " .. shopData.layout.logo.location) end
  107.  
  108.   local function wrapChest()
  109.     chest = peripheral.wrap(shopData.config.chestside)
  110.   end
  111.  
  112.   local function getStock()
  113.     print("[info] Getting chest content")
  114.     chestContent = chest.list()
  115.  
  116.     for c = 0, #shopData.stock do
  117.       stockLevels[shopData.stock[c].name .. ":" .. shopData.stock[c].damage] = 0
  118.     end
  119.  
  120.     print("[info] Populating lookup table")
  121.     for c = 0, #shopData.stock do
  122.       lookupTable[shopData.stock[c].meta] = { ["longname"] = shopData.stock[c].name .. ":" .. shopData.stock[c].damage, ["index"] = c }
  123.     end
  124.  
  125.     print("[info] Listing stock")
  126.     for c = 1, chest.size() do
  127.       if chestContent[c] ~= nil and stockLevels[chestContent[c].name .. ":" .. chestContent[c].damage] ~= nil then
  128.         stockLevels[chestContent[c].name .. ":" .. chestContent[c].damage] = stockLevels[chestContent[c].name .. ":" .. chestContent[c].damage] + chestContent[c].count
  129.       end
  130.     end
  131.   end
  132.  
  133.   local function replaceStuff(input)
  134.     if input == "domainname" then
  135.       return shopData.config.krist.domainname
  136.     elseif input == "shopname" then
  137.       return shopData.config.name
  138.     elseif input == "shopowner" then
  139.       return shopData.config.owner
  140.     elseif input == "kristaddress" then
  141.       return shopData.config.krist.address
  142.     elseif input == "kristname" then
  143.       return shopData.config.krist.name
  144.     end
  145.     return "*"
  146.   end
  147.  
  148.   local function clearLines(y1, y2, colour, terminal)
  149.     local x0, y0 = terminal.getCursorPos()
  150.     local colour0 = terminal.getBackgroundColour()
  151.     terminal.setBackgroundColor(colour)
  152.     for y = y1, y2 do
  153.       terminal.setCursorPos(1, y)
  154.       terminal.clearLine()
  155.     end
  156.     terminal.setCursorPos(x0, y0)
  157.     terminal.setBackgroundColor(colour0)
  158.   end
  159.  
  160.   local function drawShopItem(index, yoff)
  161.     clearLines(yoff, yoff + shopData.layout.table.size.row - 1, shopData.layout.colours.table.content.row[index % 2], mon)
  162.  
  163.     mon.setCursorPos(monMaxX * shopData.layout.columnoffset.name, yoff + math.floor(shopData.layout.table.size.row / 2.1 ))
  164.     mon.setTextColor(shopData.layout.colours.table.content.name[index % 2])
  165.     mon.setBackgroundColor(shopData.layout.colours.table.content.row[index % 2])
  166.     mon.write(shopData.stock[index].displayname)
  167.  
  168.     mon.setCursorPos(monMaxX * shopData.layout.columnoffset.stock, yoff + math.floor(shopData.layout.table.size.row / 2.1 ))
  169.     if stockLevels[shopData.stock[index].name .. ":" .. shopData.stock[index].damage] > 0 then
  170.       mon.setTextColor(shopData.layout.colours.table.content.stockfull[index % 2])
  171.     else
  172.       mon.setTextColor(shopData.layout.colours.table.content.stockempty[index % 2])
  173.     end
  174.     mon.setBackgroundColor(shopData.layout.colours.table.content.row[index % 2])
  175.     mon.write(string.format("%.0f", stockLevels[shopData.stock[index].name .. ":" .. shopData.stock[index].damage]) .. shopData.layout.table.suffix.stock)
  176.  
  177.     mon.setCursorPos(monMaxX * shopData.layout.columnoffset.price, yoff + math.floor(shopData.layout.table.size.row / 2.1 ))
  178.     mon.setTextColor(shopData.layout.colours.table.content.price[index % 2])
  179.     mon.setBackgroundColor(shopData.layout.colours.table.content.row[index % 2])
  180.     mon.write(shopData.stock[index].price .. shopData.layout.table.suffix.currency)
  181.  
  182.     mon.setCursorPos(monMaxX * shopData.layout.columnoffset.meta, yoff + math.floor(shopData.layout.table.size.row / 2.1 ))
  183.     mon.setTextColor(shopData.layout.colours.table.content.meta[index % 2])
  184.     mon.setBackgroundColor(shopData.layout.colours.table.content.row[index % 2])
  185.     mon.write(shopData.stock[index].meta .. string.gsub(shopData.layout.table.suffix.meta, "{(.-)}", replaceStuff))
  186.   end
  187.  
  188.   local function drawHeader(yoff)
  189.     local ysize = #shopData.layout.header.text + shopData.layout.header.spacing
  190.  
  191.     clearLines(yoff, yoff + ysize, shopData.layout.colours.header.background, mon)
  192.     for i = 1,#shopData.layout.header.text do
  193.       mon.setCursorPos(shopData.layout.header.indent + 1, yoff + shopData.layout.header.spacing + i - 1)
  194.       mon.setTextColor(shopData.layout.colours.header.text)
  195.       mon.setBackgroundColor(shopData.layout.colours.header.background)
  196.       mon.write(string.gsub(shopData.layout.header.text[i], "{(.-)}", replaceStuff))
  197.     end
  198.   end
  199.  
  200.   local function drawFooter()
  201.     local ysize = #shopData.layout.footer.text + shopData.layout.footer.spacing
  202.     local ystart = monMaxY - ysize
  203.  
  204.     clearLines(ystart, monMaxY, shopData.layout.colours.footer.background, mon)
  205.     for i = 1,#shopData.layout.footer.text do
  206.       mon.setCursorPos(shopData.layout.footer.indent + 1, ystart + shopData.layout.footer.spacing + i - 1)
  207.       mon.setTextColor(shopData.layout.colours.footer.text)
  208.       mon.setBackgroundColor(shopData.layout.colours.footer.background)
  209.       mon.write(string.gsub(shopData.layout.footer.text[i], "{(.-)}", replaceStuff))
  210.     end
  211.   end
  212.  
  213.   local function drawTableHeader(yoff)
  214.     local ysize = shopData.layout.table.size.header
  215.  
  216.     clearLines(yoff, yoff + ysize - 1, shopData.layout.colours.table.header.row, mon)
  217.     mon.setCursorPos(monMaxX * shopData.layout.columnoffset.name, yoff + math.floor(shopData.layout.table.size.header / 2.1 ))
  218.     mon.setTextColor(shopData.layout.colours.table.header.name)
  219.     mon.setBackgroundColor(shopData.layout.colours.table.header.row)
  220.     mon.write(shopData.layout.table.columnname.name)
  221.  
  222.     mon.setCursorPos(monMaxX * shopData.layout.columnoffset.stock, yoff + math.floor(shopData.layout.table.size.header / 2.1 ))
  223.     mon.setBackgroundColor(shopData.layout.colours.table.header.row)
  224.     mon.write(shopData.layout.table.columnname.stock)
  225.  
  226.     mon.setCursorPos(monMaxX * shopData.layout.columnoffset.price, yoff + math.floor(shopData.layout.table.size.header / 2.1 ))
  227.     mon.setTextColor(shopData.layout.colours.table.header.price)
  228.     mon.setBackgroundColor(shopData.layout.colours.table.header.row)
  229.     mon.write(shopData.layout.table.columnname.price)
  230.  
  231.     mon.setCursorPos(monMaxX * shopData.layout.columnoffset.meta, yoff + math.floor(shopData.layout.table.size.header / 2.1 ))
  232.     mon.setTextColor(shopData.layout.colours.table.header.meta)
  233.     mon.setBackgroundColor(shopData.layout.colours.table.header.row)
  234.     mon.write(shopData.layout.table.columnname.meta)
  235.   end
  236.  
  237.   local function drawTableContent(yoff)
  238.     for i = 0, #shopData.stock do
  239.       drawShopItem(i, yOffset["tableContents"][i])
  240.       yOffset["tableContents"][i] = yoff
  241.       yoff = yoff + shopData.layout.table.size.row
  242.     end
  243.   end
  244.  
  245.   local function drawTableFooter(yoff)
  246.     local ysize = shopData.layout.table.size.footer
  247.  
  248.     clearLines(yoff, yoff + ysize - 1, shopData.layout.colours.table.footer.row, mon)
  249.     mon.setCursorPos(monMaxX * shopData.layout.columnoffset.name, yoff + math.floor(shopData.layout.table.size.footer / 2.1 ))
  250.     mon.setTextColor(shopData.layout.colours.table.footer.name)
  251.     mon.setBackgroundColor(shopData.layout.colours.table.footer.row)
  252.     mon.write(shopData.layout.table.columnname.name)
  253.  
  254.     mon.setCursorPos(monMaxX * shopData.layout.columnoffset.stock, yoff + math.floor(shopData.layout.table.size.footer / 2.1 ))
  255.     mon.setBackgroundColor(shopData.layout.colours.table.footer.row)
  256.     mon.write(shopData.layout.table.columnname.stock)
  257.  
  258.     mon.setCursorPos(monMaxX * shopData.layout.columnoffset.price, yoff + math.floor(shopData.layout.table.size.footer / 2.1 ))
  259.     mon.setTextColor(shopData.layout.colours.table.footer.price)
  260.     mon.setBackgroundColor(shopData.layout.colours.table.footer.row)
  261.     mon.write(shopData.layout.table.columnname.price)
  262.  
  263.     mon.setCursorPos(monMaxX * shopData.layout.columnoffset.meta, yoff + math.floor(shopData.layout.table.size.footer / 2.1 ))
  264.     mon.setTextColor(shopData.layout.colours.table.footer.meta)
  265.     mon.setBackgroundColor(shopData.layout.colours.table.footer.row)
  266.     mon.write(shopData.layout.table.columnname.meta)
  267.   end
  268.  
  269.   local function drawLogo(yoff)
  270.     blittle.draw(logoImage, 1, yoff + 1, mon)
  271.   end
  272.  
  273.   local function drawCredits(y)
  274.     local creditsText
  275.     if monMaxX >= 86 then
  276.       creditsText = "kMarx shop program - v0.2 - Created by HydroNitrogen - more info on energetic.pw/kmarx"
  277.     elseif monMaxX >= 71 then
  278.       creditsText = "kMarx shop program v0.2 - Created by HydroNitrogen - energetic.pw/kmarx"
  279.     elseif monMaxX >= 55 then
  280.       creditsText = "kMarx shop v0.2 - by HydroNitrogen - energetic.pw/kmarx"
  281.     elseif monMaxX >= 48 then
  282.       creditsText = "kMarx v0.2 by HydroNitrogen - energetic.pw/kmarx"
  283.     elseif monMaxX >= 31 then
  284.       creditsText = "kMarx v0.2 - energetic.pw/kmarx"
  285.     elseif monMaxX >= 18 then
  286.       creditsText = "energetic.pw/kmarx"
  287.     else
  288.       creditsText = "kMarx"
  289.     end
  290.     mon.setCursorPos(math.ceil((monMaxX / 2) - (creditsText:len() / 2)) + 1, y)
  291.     mon.setBackgroundColor(colours.yellow)
  292.     mon.setTextColor(colours.black)
  293.     mon.clearLine()
  294.     mon.write(creditsText)
  295.   end
  296.  
  297.   local yOffset = { ["default"] = 1}
  298.  
  299.   local function drawShopGui()
  300.     mon.setBackgroundColor(shopData.layout.colours.empty)
  301.     mon.clear()
  302.     local yoff = 1
  303.  
  304.     if shopData.layout.credits.forceVisible or shopData.config.krist.royaltyrate <= .1 then
  305.       drawCredits(yoff)
  306.       yoff = yoff + 1
  307.     end
  308.  
  309.     if shopData.layout.visible.logo then
  310.       logoImage = blittle.shrink(paintutils.loadImage(shopData.layout.logo.location), shopData.layout.colours.logo.background)
  311.       drawLogo(yoff)
  312.       yOffset["logo"] = yoff
  313.       yoff = yoff + shopData.layout.logo.verticalSize
  314.     end
  315.  
  316.     if shopData.layout.visible.header then
  317.       drawHeader(yoff)
  318.       yOffset["header"] = yoff
  319.       yoff = yoff + shopData.layout.header.spacing * 2 + #shopData.layout.header.text
  320.     end
  321.  
  322.     if shopData.layout.visible.table.header then
  323.       drawTableHeader(yoff)
  324.       yOffset["tableHeader"] = yoff
  325.       yoff = yoff + shopData.layout.table.size.header
  326.     end
  327.  
  328.     yOffset["tableContents"] = {}
  329.     for i = 0, #shopData.stock do
  330.       drawShopItem(i, yoff)
  331.       yOffset["tableContents"][i] = yoff
  332.       yoff = yoff + shopData.layout.table.size.row
  333.     end
  334.  
  335.     if shopData.layout.visible.table.footer then
  336.       yOffset["tableFooter"] = yoff
  337.       drawTableFooter(yoff)
  338.       yoff = yoff + shopData.layout.table.size.footer
  339.     end
  340.  
  341.     if shopData.layout.visible.footer then
  342.       drawFooter()
  343.     end
  344.   end
  345.  
  346.   local function updateStock()
  347.     print("[info] Updated stock levels")
  348.     chestContent = chest.list()
  349.     stockLevels = {}
  350.  
  351.     for c = 0, #shopData.stock do
  352.       stockLevels[shopData.stock[c].name .. ":" .. shopData.stock[c].damage] = 0
  353.     end
  354.  
  355.     for c = 1, chest.size() do
  356.       if chestContent[c] ~= nil and stockLevels[chestContent[c].name .. ":" .. chestContent[c].damage] ~= nil then
  357.         stockLevels[chestContent[c].name .. ":" .. chestContent[c].damage] = stockLevels[chestContent[c].name .. ":" .. chestContent[c].damage] + chestContent[c].count
  358.       end
  359.     end
  360.  
  361.     for i = 0, #shopData.stock do
  362.       drawShopItem(i, yOffset["tableContents"][i])
  363.     end
  364.   end
  365.  
  366.   local function dispense(item, amount)
  367.     print("[info] Dispensing " .. amount .. " of " .. item)
  368.     local amountToDispense = amount
  369.  
  370.     for c = 1, chest.size() do
  371.       if chestContent[c] ~= nil and (chestContent[c].name .. ":" .. chestContent[c].damage) == item then
  372.         local dispensed = chest.drop(c, amountToDispense, shopData.config.dispensedirection)
  373.         amountToDispense = amountToDispense - dispensed
  374.         if amountToDispense == 0 then return end
  375.       end
  376.     end
  377.   end
  378.  
  379.   local function drawShutdownGUI()
  380.     mon.setBackgroundColor(colours.grey)
  381.     mon.setTextColor(colours.lightGrey)
  382.     mon.clear()
  383.     local shutDownMsg = "Shop has been shut down manually."
  384.     mon.setCursorPos(math.ceil((xm/ 2) - (shutDownMsg:len() / 2)) + 1, ym / 2)
  385.     mon.write(shutDownMsg)
  386.   end
  387.  
  388.   local function drawStartupGUI()
  389.     mon.setBackgroundColor(colours.blue)
  390.     mon.setTextColor(colours.white)
  391.     mon.clear()
  392.     local startUpMsg = "Starting kMarx shop..."
  393.     mon.setCursorPos(math.ceil((xm/ 2) - (startUpMsg:len() / 2)) + 1, ym / 2)
  394.     mon.write(startUpMsg)
  395.   end
  396.  
  397.   local function dCChar(rr)
  398.     local cChar = "?"
  399.     if rr <= 0 then cChar = "."
  400.     elseif rr > 0 and rr <= .05 then cChar = ":"
  401.     elseif rr > .05 and rr <= .1 then cChar = "-"
  402.     elseif rr > .1 then cChar = "=" end
  403.     mon.setBackgroundColour(shopData.layout.colours.footer.background)
  404.     mon.setTextColour(shopData.layout.colours.footer.text)
  405.     mon.setCursorPos(monMaxX, monMaxY)
  406.     mon.write(cChar)
  407.   end
  408.  
  409.   local redstoneHeartbeatStatus = false
  410.   local function toggleRedstone()
  411.     redstoneHeartbeatStatus = not redstoneHeartbeatStatus
  412.     redstone.setOutput(shopData.config.redstoneside, redstoneHeartbeatStatus)
  413.   end
  414.  
  415.   local wssuccess, ws
  416.   local royaltyDestination = "kMarx.kst"
  417.   local internalVersion = "0.2"
  418.   local integerVersion = 2
  419.   local updateFetch = "https://energetic.pw/computercraft/kmarx/assets/versioncheck"
  420.   local privatekey
  421.  
  422.   if shopData.config.krist.iskristwalletformat then
  423.     privatekey = k.toKristWalletFormat(shopData.config.krist.privatekey)
  424.   else
  425.     privatekey = shopData.config.krist.privatekey
  426.   end
  427.  
  428.   local function notifyToUpdate()
  429.     local headers = { [ "User-Agent" ] = "kMarx-client (v" .. internalVersion .. ")" }
  430.     if http.checkURL("https://energetic.pw/computercraft/kmarx/assets/versioncheck") then
  431.       local handle = http.get("https://energetic.pw/computercraft/kmarx/assets/versioncheck", headers)
  432.       if handle == nil then
  433.         printError("[warning] Could not check for updates.")
  434.       else
  435.         local rawResult = handle.readAll()
  436.         handle.close()
  437.         local result = {}
  438.         local success = pcall(function() result = textutils.unserialize(rawResult) end)
  439.         if not success or result == nil then
  440.           printError("[warning] Could not check for updates.")
  441.         else
  442.           if result.status ~= nil and result.status == "success" then
  443.             if result.versions.current.integerVersion == integerVersion then
  444.               print("[info] Shop is up to date!")
  445.             elseif result.versions.current.integerVersion ~= integerVersion then
  446.               printError("[info] Shop version is outdated!")
  447.               print("[info] Visit energetic.pw/kmarx")
  448.             end
  449.           else
  450.             printError("[warning] Could not check for updates.")
  451.           end
  452.         end
  453.       end
  454.     else
  455.       printError("[warning] Could not check for updates.")
  456.     end
  457.   end
  458.  
  459.   local function handleTransaction(data)
  460.     local transaction = data.transaction
  461.     local metadata = nil
  462.  
  463.     local success, error = pcall(function() metadata = k.parseMeta(transaction.metadata) end)
  464.  
  465.     if not success then
  466.       printError("[error] could not parse metadata!!")
  467.     elseif metadata ~= nil and metadata.name ~= nil and metadata.domain == shopData.config.krist.domainname then -- filter out only our shop payments
  468.  
  469.       if metadata.meta["return"] == nil then metadata.meta["return"] = transaction.from end
  470.       if metadata.meta["username"] == nil then metadata.meta["username"] = transaction.from end
  471.  
  472.       if lookupTable[metadata.name] ~= nil then
  473.         print("[info] Transaction to shop made! Received " .. transaction.value .. " from " .. transaction.from)
  474.         if stockLevels[lookupTable[metadata.name].longname] > 0 then
  475.           --we have stock - DISPENSE & REFUND THE CHANGE
  476.           local amountToDispense = math.min( math.floor( transaction.value / shopData.stock[lookupTable[metadata.name].index].price ), stockLevels[lookupTable[metadata.name].longname])
  477.           local amountToRefund = transaction.value - ( amountToDispense * shopData.stock[lookupTable[metadata.name].index].price )
  478.           local amountToRoyalty = math.floor( ( transaction.value - amountToRefund ) * shopData.config.krist.royaltyrate )
  479.  
  480.           if amountToDispense == 0 then
  481.             -- no items dispensed, because user underpaid, refunding
  482.             print("[info] Underpaid, refunding customer")
  483.             local success = await(k.makeTransaction, shopData.config.krist.privatekey, metadata.meta["return"], amountToRefund, string.gsub(shopData.config.messages.underpaid, "{buyer}", metadata.meta.username))
  484.             assert(success, "[warning] Couldn't refund customer!!")
  485.           elseif amountToDispense > 0 then
  486.             -- dispensing items for the user
  487.             dispense(lookupTable[metadata.name].longname, amountToDispense)
  488.             updateStock()
  489.  
  490.             if amountToRoyalty > 0 then
  491.               local success = await(k.makeTransaction, shopData.config.krist.privatekey, royaltyDestination, amountToRoyalty, "kMarx Royalties;" .. table.concat({ "iv=" .. internalVersion, "rr=" .. shopData.config.krist.royaltyrate, "so=" .. shopData.config.owner }, ";"))
  492.               assert(success, "[warning] Could not pay royalties!")
  493.             end
  494.  
  495.             if amountToRefund > 0 then
  496.               -- items dispensed, returning overpay
  497.               print("[info] Item has been dispensed, returning change")
  498.               local success = await(k.makeTransaction, shopData.config.krist.privatekey, metadata.meta["return"], amountToRefund, string.gsub(shopData.config.messages.overpaid, "{buyer}", metadata.meta.username))
  499.               assert(success, "[warning] Couldn't refund customer!!")
  500.             end
  501.           end
  502.         else
  503.           -- we're out of stock - REFUND
  504.           print("[info] We're out of stock, refunding customer")
  505.           local success = await(k.makeTransaction, shopData.config.krist.privatekey, metadata.meta["return"], transaction.value, string.gsub(shopData.config.messages.outofstock, "{buyer}", metadata.meta.username))
  506.           assert(success, "[warning] Couldn't refund customer!!")
  507.         end
  508.       else
  509.         -- we don't sell this item - REFUND
  510.         print("[info] Unknown item, refunding customer")
  511.         local success = await(k.makeTransaction, shopData.config.krist.privatekey, metadata.meta["return"], transaction.value, string.gsub(shopData.config.messages.unknownitem, "{buyer}", metadata.meta.username))
  512.         assert(success, "[warning] Couldn't refund customer!!")
  513.       end
  514.     end
  515.   end
  516.  
  517.   jua.on("terminate", function()
  518.     print("[stop] Terminating")
  519.     drawShutdownGUI()
  520.     local success = pcall(function() ws.close() end)
  521.     if not success then
  522.       printError("Warning: Could not close websocket. Rebooting is strongly recommended!")
  523.     else
  524.       print("[stop] Websocket succesfully closed.")
  525.     end
  526.     jua.stop()
  527.     printError("[stop] Terminated.")
  528.   end)
  529.  
  530.   local function openWebsocket()
  531.     wssuccess, ws = await(k.connect, shopData.config.krist.privatekey)
  532.     if not wssuccess then
  533.       error("Failed to connect to websocket! Please reboot and try again.")
  534.     end
  535.  
  536.     local success = await(ws.subscribe, "transactions", handleTransaction)
  537.     if not success then
  538.       error("Failed to subscribe to websocket! Please reboot and try again.")
  539.     end
  540.  
  541.     print("[info] Connections to krist made!")
  542.   end
  543.  
  544.   jua.go(function()
  545.     term.setCursorPos(1,1)
  546.     term.setBackgroundColor(colors.black)
  547.     term.clear()
  548.  
  549.     term.setTextColor(colours.black)
  550.     term.setBackgroundColor(colors.white)
  551.     term.clearLine()
  552.     print(" kMarx shop - energetic.pw/kmarx")
  553.     term.clearLine()
  554.     print(" Created by HydroNitrogen")
  555.     term.clearLine()
  556.     print(" version 0.2 - 2018-04-09")
  557.  
  558.     drawStartupGUI()
  559.  
  560.     term.setBackgroundColor(colors.black)
  561.     term.setTextColor(colours.white)
  562.     print("...")
  563.  
  564.     if shopData.iv == nil or shopData.iv < 2 then
  565.       printError("[warning] Config file is outdated!")
  566.       updateConfigTo2()
  567.     end
  568.  
  569.     wrapChest()
  570.     getStock()
  571.  
  572.     openWebsocket()
  573.  
  574.     print("[info] Drawing shop GUI")
  575.     drawShopGui()
  576.  
  577.     jua.setInterval(updateStock, shopData.config.updatestockinterval)
  578.     jua.setTimeout(function() dCChar(shopData.config.krist.royaltyrate) end, 30)
  579.     jua.setInterval(toggleRedstone, 3)
  580.  
  581.     notifyToUpdate()
  582.   end)
  583. end)
  584.  
  585. local function centerWrite(t, text)
  586.   local xm, xy = t.getSize()
  587.   local x, y = t.getCursorPos()
  588.   t.clearLine()
  589.   t.setCursorPos(math.ceil((xm/ 2) - (text:len() / 2)) + 1, y)
  590.   t.write(text)
  591. end
  592.  
  593. local function displayError(error)
  594.   local mon = peripheral.find("monitor")
  595.   mon.setTextScale(1)
  596.   local xm, ym = mon.getSize()
  597.   if xm < 26 or ym < 10 then
  598.     mon.setTextScale(.5)
  599.     xm, xy = mon.getSize()
  600.   end
  601.  
  602.   mon.setBackgroundColor(colours.white)
  603.   mon.setTextScale(1)
  604.   mon.clear()
  605.  
  606.   mon.setBackgroundColor(colours.red)
  607.   mon.setTextColor(colours.white)
  608.   mon.setCursorPos(1,1)
  609.   mon.clearLine()
  610.   mon.setCursorPos(1,2)
  611.   centerWrite(mon, "MEDIC NEEDED!")
  612.   mon.setCursorPos(1,3)
  613.   centerWrite(mon, "Shop has stopped working!")
  614.   mon.setCursorPos(1,4)
  615.   mon.clearLine()
  616.  
  617.   mon.setBackgroundColor(colours.white)
  618.   mon.setTextColor(colours.grey)
  619.   mon.setCursorPos(1, math.floor(0.5 * ym))
  620.   mon.write("Error details:")
  621.   mon.setCursorPos(1, math.floor(0.5 * ym) + 1)
  622.   mon.write(error)
  623.  
  624.   mon.setTextColor(colours.black)
  625.   mon.setCursorPos(1, math.floor(0.9 * ym))
  626.   centerWrite(mon, "Auto reboot in 15 seconds")
  627. end
  628.  
  629. if not success then
  630.   pcall(function() displayError(error) end)
  631.   term.setTextColor(colours.white)
  632.   term.setBackgroundColor(colours.black)
  633.   term.setCursorPos(1,1)
  634.   term.clear()
  635.   printError("FATAL ERROR OF DEATH IN SHOP")
  636.   printError("Shop stopped working.")
  637.   printError("\nInformation about your error:")
  638.   print(error)
  639.   print("\nShop will reboot in 15 seconds!")
  640.   os.sleep(15)
  641.   os.reboot()
  642. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement