Advertisement
SwellzD

just_shop

Jun 19th, 2025 (edited)
548
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 16.32 KB | None | 0 0
  1. -- Configuration
  2. local CHEST_SIDE = "top"
  3. local MONITOR_SIDE = "right"
  4. local PLAYER_CHEST_SIDE = "back"
  5. local ADMIN_PASSWORD = "sanabi"
  6. local FIXED_PRICE_FACTOR = 0.1
  7. local BUTTON_HIGHLIGHT_TIME = 0.3
  8.  
  9. -- System settings
  10. local data = {}
  11. local monitor = peripheral.wrap(MONITOR_SIDE)
  12. local chest = peripheral.wrap(CHEST_SIDE)
  13. local playerChest = peripheral.wrap(PLAYER_CHEST_SIDE)
  14. monitor.setTextScale(0.5)
  15. local lastHighlight = 0
  16. local highlightedButton = nil
  17. local inTransaction = false
  18.  
  19. -- Sync resources with chest
  20. local function syncWithChest()
  21.     -- Reset amounts
  22.     for _, resource in pairs(data.resources) do
  23.         resource.amount = 0
  24.     end
  25.    
  26.     -- Scan chest
  27.     for slot, stack in pairs(chest.list()) do
  28.         if data.resources[stack.name] then
  29.             data.resources[stack.name].amount = data.resources[stack.name].amount + stack.count
  30.         end
  31.     end
  32. end
  33.  
  34. -- Initialize data
  35. local function initData()
  36.     data = {
  37.         resources = {
  38.             ["minecraft:iron_ingot"] = {name = "Iron", base = 1, amount = 0},
  39.             ["minecraft:gold_ingot"] = {name = "Gold", base = 1, amount = 0},
  40.             ["minecraft:diamond"] = {name = "Diamond", base = 1, amount = 0},
  41.             ["minecraft:emerald"] = {name = "Emerald", base = 1, amount = 0}
  42.         },
  43.         balance = 0,
  44.         discount = 1,
  45.         selectedItem = ""
  46.     }
  47.     syncWithChest()
  48. end
  49.  
  50. -- Calculate prices
  51. local function calculatePrices()
  52.     syncWithChest() -- Always sync before calculating
  53.    
  54.     local total = 0
  55.     for _, res in pairs(data.resources) do
  56.         total = total + res.amount
  57.     end
  58.  
  59.     local prices = {}
  60.     for id, res in pairs(data.resources) do
  61.         if res.amount == 0 then
  62.             prices[id] = {
  63.                 buy = math.huge,
  64.                 sell = res.base * FIXED_PRICE_FACTOR
  65.             }
  66.         else
  67.             local buyPrice = (total / (res.amount + 1)) * res.base
  68.             prices[id] = {
  69.                 buy = buyPrice,
  70.                 sell = buyPrice * data.discount
  71.             }
  72.         end
  73.     end
  74.     return prices
  75. end
  76.  
  77. -- Draw numeric keyboard with cancel button
  78. local function drawNumericKeyboard()
  79.     local keys = {
  80.         "7","8","9",
  81.         "4","5","6",
  82.         "1","2","3",
  83.         "0","<","OK"
  84.     }
  85.    
  86.     local w, h = monitor.getSize()
  87.     local keyWidth = 4
  88.     local keyHeight = 2
  89.     local startX = math.floor((w - 3 * keyWidth) / 2)
  90.     local startY = h - 15
  91.    
  92.     for i, key in ipairs(keys) do
  93.         local row = math.floor((i-1)/3)
  94.         local col = (i-1) % 3
  95.        
  96.         local x = startX + col * (keyWidth + 1)
  97.         local y = startY + row * (keyHeight + 1)
  98.        
  99.         monitor.setCursorPos(x, y)
  100.         monitor.write("["..key.."]")
  101.     end
  102.    
  103.     -- Cancel button at bottom
  104.     monitor.setCursorPos(math.floor(w/2)-5, h-2)
  105.     monitor.write("[ Cancel ]")
  106. end
  107.  
  108. -- Highlight button temporarily
  109. local function highlightButton(name, x, y, width)
  110.     monitor.setCursorPos(x, y)
  111.     monitor.setBackgroundColor(colors.gray)
  112.     monitor.write(string.rep(" ", width))
  113.     monitor.setCursorPos(x, y)
  114.     monitor.write(name)
  115.     monitor.setBackgroundColor(colors.black)
  116.     highlightedButton = {name = name, x = x, y = y, width = width}
  117.     lastHighlight = os.clock()
  118. end
  119.  
  120. -- Highlight key on keyboard
  121. local function highlightKey(x, y, key)
  122.     monitor.setCursorPos(x, y)
  123.     monitor.setBackgroundColor(colors.gray)
  124.     monitor.write("["..key.."]")
  125.     monitor.setBackgroundColor(colors.black)
  126. end
  127.  
  128. -- Draw UI with button highlighting
  129. local function drawUI(prices)
  130.     monitor.clear()
  131.     local w, h = monitor.getSize()
  132.    
  133.     -- Header with balance
  134.     monitor.setCursorPos(1, 1)
  135.     monitor.write("SHOP")
  136.     monitor.setCursorPos(w - 10, 1)
  137.     monitor.write("$:"..data.balance)
  138.    
  139.     -- Resources list
  140.     local y = 3
  141.     for id, res in pairs(data.resources) do
  142.         local isSelected = (id == data.selectedItem)
  143.         if isSelected then
  144.             monitor.setBackgroundColor(colors.gray)
  145.         end
  146.        
  147.         monitor.setCursorPos(1, y)
  148.         if prices[id].buy == math.huge then
  149.             monitor.write(string.format("%s: Sold out", res.name))
  150.         else
  151.             monitor.write(string.format("%s: buy %.1f", res.name, prices[id].buy))
  152.         end
  153.        
  154.         monitor.setCursorPos(1, y+1)
  155.         monitor.write(string.format("  sell: %.1f", prices[id].sell))
  156.        
  157.         if isSelected then
  158.             monitor.setBackgroundColor(colors.black)
  159.         end
  160.         y = y + 3
  161.     end
  162.    
  163.     -- Buttons with highlighting - moved down
  164.     local now = os.clock()
  165.     if highlightedButton and (now - lastHighlight < BUTTON_HIGHLIGHT_TIME) then
  166.         monitor.setCursorPos(highlightedButton.x, highlightedButton.y)
  167.         monitor.setBackgroundColor(colors.gray)
  168.         monitor.write(highlightedButton.name)
  169.         monitor.setBackgroundColor(colors.black)
  170.     else
  171.         highlightedButton = nil
  172.         -- Moved buttons down one line
  173.         monitor.setCursorPos(1, h-4)
  174.         monitor.write("[Buy] [Sell]")
  175.        
  176.         -- Admin button in bottom right corner
  177.         monitor.setCursorPos(w - 7, h-1)
  178.         monitor.write("[Admin]")
  179.     end
  180. end
  181.  
  182. -- Process transaction
  183. local function processTransaction(isBuy)
  184.     if data.selectedItem == "" then
  185.         monitor.clear()
  186.         monitor.setCursorPos(1, 1)
  187.         monitor.write("Select an item first!")
  188.         sleep(2)
  189.         return
  190.     end
  191.    
  192.     local resID = data.selectedItem
  193.     inTransaction = true
  194.    
  195.     while inTransaction do
  196.         monitor.clear()
  197.         monitor.setCursorPos(1, 1)
  198.         monitor.write(isBuy and "BUY" or "SELL")
  199.         monitor.setCursorPos(1, 2)
  200.         monitor.write("Item: "..data.resources[resID].name)
  201.        
  202.         local count = 0
  203.         local inputStr = ""
  204.         local w, h = monitor.getSize()
  205.         local startX = math.floor((w - 3 * 4) / 2)
  206.         local startY = h - 15
  207.        
  208.         -- Input amount with numeric keyboard
  209.         local inputActive = true
  210.         while inputActive do
  211.             -- Clear input area
  212.             monitor.setCursorPos(1, 3)
  213.             monitor.write("Amount: "..inputStr..string.rep(" ", 10))
  214.            
  215.             drawNumericKeyboard()
  216.            
  217.             local event, side, x, y = os.pullEvent("monitor_touch")
  218.            
  219.             -- Check if Cancel button pressed
  220.             if y >= h-3 and y <= h-1 and x >= math.floor(w/2)-5 and x <= math.floor(w/2)+5 then
  221.                 inTransaction = false
  222.                 return
  223.             end
  224.            
  225.             -- Calculate which key was pressed
  226.             local row = math.floor((y - startY) / 3)
  227.             local col = math.floor((x - startX) / 5)
  228.            
  229.             if row >= 0 and col >= 0 and row <= 3 and col <= 2 then
  230.                 local keyIndex = row * 3 + col + 1
  231.                 local keys = {"7","8","9","4","5","6","1","2","3","0","<","OK"}
  232.                
  233.                 if keyIndex >= 1 and keyIndex <= #keys then
  234.                     local key = keys[keyIndex]
  235.                    
  236.                     -- Highlight the key briefly
  237.                     highlightKey(startX + col * 5, startY + row * 3, key)
  238.                     sleep(0.1) -- Make highlight visible
  239.                    
  240.                     if key == "<" then
  241.                         inputStr = inputStr:sub(1, -2)
  242.                     elseif key == "OK" then
  243.                         count = tonumber(inputStr)
  244.                         if count and count > 0 then
  245.                             inputActive = false
  246.                         end
  247.                     else
  248.                         inputStr = inputStr .. key
  249.                     end
  250.                 end
  251.             end
  252.         end
  253.        
  254.         local prices = calculatePrices()
  255.        
  256.         if isBuy then
  257.             if prices[resID].buy == math.huge then
  258.                 monitor.clear()
  259.                 monitor.setCursorPos(1, 1)
  260.                 monitor.write("Error: item sold out!")
  261.                 sleep(2)
  262.                 return
  263.             end
  264.            
  265.             local cost = math.floor(prices[resID].buy * count)
  266.             if data.balance < cost then
  267.                 monitor.clear()
  268.                 monitor.setCursorPos(1, 1)
  269.                 monitor.write("Not enough points!")
  270.                 sleep(2)
  271.                 return
  272.             end
  273.            
  274.             -- Check stock
  275.             local available = 0
  276.             for _, stack in pairs(chest.list()) do
  277.                 if stack.name == resID then
  278.                     available = available + stack.count
  279.                 end
  280.             end
  281.            
  282.             if available < count then
  283.                 monitor.clear()
  284.                 monitor.setCursorPos(1, 1)
  285.                 monitor.write("Not enough items in shop!")
  286.                 sleep(2)
  287.                 return
  288.             end
  289.            
  290.             -- Complete purchase (move to player chest)
  291.             local moved = 0
  292.             for slot, stack in pairs(chest.list()) do
  293.                 if stack.name == resID and count > 0 then
  294.                     local toTake = math.min(count, stack.count)
  295.                     -- Move to player chest
  296.                     local transferred = chest.pushItems(peripheral.getName(playerChest), slot, toTake)
  297.                     if transferred > 0 then
  298.                         moved = moved + transferred
  299.                         count = count - transferred
  300.                         if count == 0 then break end
  301.                     end
  302.                 end
  303.             end
  304.            
  305.             if moved == 0 then
  306.                 monitor.clear()
  307.                 monitor.setCursorPos(1, 1)
  308.                 monitor.write("Error: no space in player chest!")
  309.                 sleep(2)
  310.                 return
  311.             end
  312.            
  313.             data.balance = data.balance - math.floor(prices[resID].buy * moved)
  314.            
  315.             monitor.clear()
  316.             monitor.setCursorPos(1, 1)
  317.             monitor.write("Success! Charged: "..(math.floor(prices[resID].buy * moved)))
  318.             monitor.setCursorPos(1, 2)
  319.             monitor.write("Balance: "..data.balance)
  320.             sleep(3)
  321.             inTransaction = false
  322.         else
  323.             -- Sell items
  324.             local reward = math.floor(prices[resID].sell * count)
  325.            
  326.             -- Check player inventory
  327.             local available = 0
  328.             for _, stack in pairs(playerChest.list()) do
  329.                 if stack.name == resID then
  330.                     available = available + stack.count
  331.                 end
  332.             end
  333.            
  334.             if available < count then
  335.                 monitor.clear()
  336.                 monitor.setCursorPos(1, 1)
  337.                 monitor.write("Not enough items!")
  338.                 sleep(2)
  339.                 return
  340.             end
  341.            
  342.             -- Complete sale (move to shop chest)
  343.             local moved = 0
  344.             for slot, stack in pairs(playerChest.list()) do
  345.                 if stack.name == resID and count > 0 then
  346.                     local toSell = math.min(count, stack.count)
  347.                     -- Move to shop chest
  348.                     local transferred = playerChest.pushItems(peripheral.getName(chest), slot, toSell)
  349.                     if transferred > 0 then
  350.                         moved = moved + transferred
  351.                         count = count - transferred
  352.                         if count == 0 then break end
  353.                     end
  354.                 end
  355.             end
  356.            
  357.             if moved == 0 then
  358.                 monitor.clear()
  359.                 monitor.setCursorPos(1, 1)
  360.                 monitor.write("Error: no space in shop chest!")
  361.                 sleep(2)
  362.                 return
  363.             end
  364.            
  365.             data.balance = data.balance + math.floor(prices[resID].sell * moved)
  366.            
  367.             monitor.clear()
  368.             monitor.setCursorPos(1, 1)
  369.             monitor.write("Success! Added: "..(math.floor(prices[resID].sell * moved)))
  370.             monitor.setCursorPos(1, 2)
  371.             monitor.write("Balance: "..data.balance)
  372.             sleep(3)
  373.             inTransaction = false
  374.         end
  375.     end
  376.    
  377.     syncWithChest() -- Update after transaction
  378. end
  379.  
  380. -- Admin panel
  381. local function adminPanel()
  382.     local adminActive = true
  383.     while adminActive do
  384.         monitor.clear()
  385.         monitor.setCursorPos(1, 1)
  386.         monitor.write("ADMIN PANEL")
  387.         monitor.setCursorPos(1, 2)
  388.         monitor.write("Password: ")
  389.         local inputPass = read("*")
  390.        
  391.         if inputPass ~= ADMIN_PASSWORD then
  392.             monitor.setCursorPos(1, 3)
  393.             monitor.write("Wrong password!")
  394.             sleep(2)
  395.             return
  396.         end
  397.        
  398.         local choice = 0
  399.         while choice ~= 4 do
  400.             monitor.clear()
  401.             monitor.setCursorPos(1, 1)
  402.             monitor.write("1. Add resource")
  403.             monitor.setCursorPos(1, 2)
  404.             monitor.write("2. Change discount")
  405.             monitor.setCursorPos(1, 3)
  406.             monitor.write("3. Set balance")
  407.             monitor.setCursorPos(1, 4)
  408.             monitor.write("4. Back")
  409.            
  410.             choice = tonumber(read())
  411.             if choice == 1 then
  412.                 monitor.setCursorPos(1, 5)
  413.                 monitor.write("Item ID: ")
  414.                 local id = read()
  415.                
  416.                 monitor.setCursorPos(1, 6)
  417.                 monitor.write("Name: ")
  418.                 local name = read()
  419.                
  420.                 monitor.setCursorPos(1, 7)
  421.                 monitor.write("Base price: ")
  422.                 local base = tonumber(read())
  423.                
  424.                 if id and name and base then
  425.                     data.resources[id] = {
  426.                         name = name,
  427.                         base = base,
  428.                         amount = 0
  429.                     }
  430.                     monitor.setCursorPos(1, 8)
  431.                     monitor.write("Resource added!")
  432.                     sleep(2)
  433.                 end
  434.             elseif choice == 2 then
  435.                 monitor.setCursorPos(1, 5)
  436.                 monitor.write("New discount (0.1-0.9): ")
  437.                 local discount = tonumber(read())
  438.                
  439.                 if discount and discount >= 0.1 and discount <= 0.9 then
  440.                     data.discount = discount
  441.                     monitor.setCursorPos(1, 6)
  442.                     monitor.write("Discount updated!")
  443.                     sleep(2)
  444.                 end
  445.             elseif choice == 3 then
  446.                 monitor.setCursorPos(1, 5)
  447.                 monitor.write("New balance: ")
  448.                 local newBalance = tonumber(read())
  449.                
  450.                 if newBalance then
  451.                     data.balance = newBalance
  452.                     monitor.setCursorPos(1, 6)
  453.                     monitor.write("Balance updated!")
  454.                     sleep(2)
  455.                 end
  456.             elseif choice == 4 then
  457.                 adminActive = false
  458.             end
  459.         end
  460.     end
  461. end
  462.  
  463. -- Main loop
  464. initData()
  465.  
  466. while true do
  467.     local prices = calculatePrices()
  468.     drawUI(prices)
  469.    
  470.     local event, side, x, y = os.pullEvent("monitor_touch")
  471.     local w, h = monitor.getSize()
  472.    
  473.     -- Resource selection
  474.     if y >= 3 and y <= h-5 then
  475.         local resourceY = 3
  476.         for id, res in pairs(data.resources) do
  477.             if y >= resourceY and y < resourceY + 2 then
  478.                 data.selectedItem = id
  479.                 break
  480.             end
  481.             resourceY = resourceY + 3
  482.         end
  483.     end
  484.    
  485.     -- Button handling with highlighting
  486.     if not inTransaction then
  487.         -- Buy/Sell buttons moved down to h-4
  488.         if y >= h-4 and y <= h-3 then
  489.             if x >= 1 and x <= 4 then -- Buy
  490.                 highlightButton("Buy", 1, h-4, 4)
  491.                 processTransaction(true)
  492.             elseif x >= 6 and x <= 10 then -- Sell
  493.                 highlightButton("Sell", 6, h-4, 4)
  494.                 processTransaction(false)
  495.             end
  496.         -- Admin button in bottom right corner
  497.         elseif y >= h-1 and x >= w-7 and x <= w-1 then
  498.             highlightButton("Admin", w-7, h-1, 7)
  499.             adminPanel()
  500.         end
  501.     end
  502. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement