Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- Configuration
- local CHEST_SIDE = "top"
- local MONITOR_SIDE = "right"
- local PLAYER_CHEST_SIDE = "back"
- local ADMIN_PASSWORD = "sanabi"
- local FIXED_PRICE_FACTOR = 0.1
- local BUTTON_HIGHLIGHT_TIME = 0.3
- -- System settings
- local data = {}
- local monitor = peripheral.wrap(MONITOR_SIDE)
- local chest = peripheral.wrap(CHEST_SIDE)
- local playerChest = peripheral.wrap(PLAYER_CHEST_SIDE)
- monitor.setTextScale(0.5)
- local lastHighlight = 0
- local highlightedButton = nil
- local inTransaction = false
- -- Sync resources with chest
- local function syncWithChest()
- -- Reset amounts
- for _, resource in pairs(data.resources) do
- resource.amount = 0
- end
- -- Scan chest
- for slot, stack in pairs(chest.list()) do
- if data.resources[stack.name] then
- data.resources[stack.name].amount = data.resources[stack.name].amount + stack.count
- end
- end
- end
- -- Initialize data
- local function initData()
- data = {
- resources = {
- ["minecraft:iron_ingot"] = {name = "Iron", base = 1, amount = 0},
- ["minecraft:gold_ingot"] = {name = "Gold", base = 1, amount = 0},
- ["minecraft:diamond"] = {name = "Diamond", base = 1, amount = 0},
- ["minecraft:emerald"] = {name = "Emerald", base = 1, amount = 0}
- },
- balance = 0,
- discount = 1,
- selectedItem = ""
- }
- syncWithChest()
- end
- -- Calculate prices
- local function calculatePrices()
- syncWithChest() -- Always sync before calculating
- local total = 0
- for _, res in pairs(data.resources) do
- total = total + res.amount
- end
- local prices = {}
- for id, res in pairs(data.resources) do
- if res.amount == 0 then
- prices[id] = {
- buy = math.huge,
- sell = res.base * FIXED_PRICE_FACTOR
- }
- else
- local buyPrice = (total / (res.amount + 1)) * res.base
- prices[id] = {
- buy = buyPrice,
- sell = buyPrice * data.discount
- }
- end
- end
- return prices
- end
- -- Draw numeric keyboard with cancel button
- local function drawNumericKeyboard()
- local keys = {
- "7","8","9",
- "4","5","6",
- "1","2","3",
- "0","<","OK"
- }
- local w, h = monitor.getSize()
- local keyWidth = 4
- local keyHeight = 2
- local startX = math.floor((w - 3 * keyWidth) / 2)
- local startY = h - 15
- for i, key in ipairs(keys) do
- local row = math.floor((i-1)/3)
- local col = (i-1) % 3
- local x = startX + col * (keyWidth + 1)
- local y = startY + row * (keyHeight + 1)
- monitor.setCursorPos(x, y)
- monitor.write("["..key.."]")
- end
- -- Cancel button at bottom
- monitor.setCursorPos(math.floor(w/2)-5, h-2)
- monitor.write("[ Cancel ]")
- end
- -- Highlight button temporarily
- local function highlightButton(name, x, y, width)
- monitor.setCursorPos(x, y)
- monitor.setBackgroundColor(colors.gray)
- monitor.write(string.rep(" ", width))
- monitor.setCursorPos(x, y)
- monitor.write(name)
- monitor.setBackgroundColor(colors.black)
- highlightedButton = {name = name, x = x, y = y, width = width}
- lastHighlight = os.clock()
- end
- -- Highlight key on keyboard
- local function highlightKey(x, y, key)
- monitor.setCursorPos(x, y)
- monitor.setBackgroundColor(colors.gray)
- monitor.write("["..key.."]")
- monitor.setBackgroundColor(colors.black)
- end
- -- Draw UI with button highlighting
- local function drawUI(prices)
- monitor.clear()
- local w, h = monitor.getSize()
- -- Header with balance
- monitor.setCursorPos(1, 1)
- monitor.write("SHOP")
- monitor.setCursorPos(w - 10, 1)
- monitor.write("$:"..data.balance)
- -- Resources list
- local y = 3
- for id, res in pairs(data.resources) do
- local isSelected = (id == data.selectedItem)
- if isSelected then
- monitor.setBackgroundColor(colors.gray)
- end
- monitor.setCursorPos(1, y)
- if prices[id].buy == math.huge then
- monitor.write(string.format("%s: Sold out", res.name))
- else
- monitor.write(string.format("%s: buy %.1f", res.name, prices[id].buy))
- end
- monitor.setCursorPos(1, y+1)
- monitor.write(string.format(" sell: %.1f", prices[id].sell))
- if isSelected then
- monitor.setBackgroundColor(colors.black)
- end
- y = y + 3
- end
- -- Buttons with highlighting - moved down
- local now = os.clock()
- if highlightedButton and (now - lastHighlight < BUTTON_HIGHLIGHT_TIME) then
- monitor.setCursorPos(highlightedButton.x, highlightedButton.y)
- monitor.setBackgroundColor(colors.gray)
- monitor.write(highlightedButton.name)
- monitor.setBackgroundColor(colors.black)
- else
- highlightedButton = nil
- -- Moved buttons down one line
- monitor.setCursorPos(1, h-4)
- monitor.write("[Buy] [Sell]")
- -- Admin button in bottom right corner
- monitor.setCursorPos(w - 7, h-1)
- monitor.write("[Admin]")
- end
- end
- -- Process transaction
- local function processTransaction(isBuy)
- if data.selectedItem == "" then
- monitor.clear()
- monitor.setCursorPos(1, 1)
- monitor.write("Select an item first!")
- sleep(2)
- return
- end
- local resID = data.selectedItem
- inTransaction = true
- while inTransaction do
- monitor.clear()
- monitor.setCursorPos(1, 1)
- monitor.write(isBuy and "BUY" or "SELL")
- monitor.setCursorPos(1, 2)
- monitor.write("Item: "..data.resources[resID].name)
- local count = 0
- local inputStr = ""
- local w, h = monitor.getSize()
- local startX = math.floor((w - 3 * 4) / 2)
- local startY = h - 15
- -- Input amount with numeric keyboard
- local inputActive = true
- while inputActive do
- -- Clear input area
- monitor.setCursorPos(1, 3)
- monitor.write("Amount: "..inputStr..string.rep(" ", 10))
- drawNumericKeyboard()
- local event, side, x, y = os.pullEvent("monitor_touch")
- -- Check if Cancel button pressed
- if y >= h-3 and y <= h-1 and x >= math.floor(w/2)-5 and x <= math.floor(w/2)+5 then
- inTransaction = false
- return
- end
- -- Calculate which key was pressed
- local row = math.floor((y - startY) / 3)
- local col = math.floor((x - startX) / 5)
- if row >= 0 and col >= 0 and row <= 3 and col <= 2 then
- local keyIndex = row * 3 + col + 1
- local keys = {"7","8","9","4","5","6","1","2","3","0","<","OK"}
- if keyIndex >= 1 and keyIndex <= #keys then
- local key = keys[keyIndex]
- -- Highlight the key briefly
- highlightKey(startX + col * 5, startY + row * 3, key)
- sleep(0.1) -- Make highlight visible
- if key == "<" then
- inputStr = inputStr:sub(1, -2)
- elseif key == "OK" then
- count = tonumber(inputStr)
- if count and count > 0 then
- inputActive = false
- end
- else
- inputStr = inputStr .. key
- end
- end
- end
- end
- local prices = calculatePrices()
- if isBuy then
- if prices[resID].buy == math.huge then
- monitor.clear()
- monitor.setCursorPos(1, 1)
- monitor.write("Error: item sold out!")
- sleep(2)
- return
- end
- local cost = math.floor(prices[resID].buy * count)
- if data.balance < cost then
- monitor.clear()
- monitor.setCursorPos(1, 1)
- monitor.write("Not enough points!")
- sleep(2)
- return
- end
- -- Check stock
- local available = 0
- for _, stack in pairs(chest.list()) do
- if stack.name == resID then
- available = available + stack.count
- end
- end
- if available < count then
- monitor.clear()
- monitor.setCursorPos(1, 1)
- monitor.write("Not enough items in shop!")
- sleep(2)
- return
- end
- -- Complete purchase (move to player chest)
- local moved = 0
- for slot, stack in pairs(chest.list()) do
- if stack.name == resID and count > 0 then
- local toTake = math.min(count, stack.count)
- -- Move to player chest
- local transferred = chest.pushItems(peripheral.getName(playerChest), slot, toTake)
- if transferred > 0 then
- moved = moved + transferred
- count = count - transferred
- if count == 0 then break end
- end
- end
- end
- if moved == 0 then
- monitor.clear()
- monitor.setCursorPos(1, 1)
- monitor.write("Error: no space in player chest!")
- sleep(2)
- return
- end
- data.balance = data.balance - math.floor(prices[resID].buy * moved)
- monitor.clear()
- monitor.setCursorPos(1, 1)
- monitor.write("Success! Charged: "..(math.floor(prices[resID].buy * moved)))
- monitor.setCursorPos(1, 2)
- monitor.write("Balance: "..data.balance)
- sleep(3)
- inTransaction = false
- else
- -- Sell items
- local reward = math.floor(prices[resID].sell * count)
- -- Check player inventory
- local available = 0
- for _, stack in pairs(playerChest.list()) do
- if stack.name == resID then
- available = available + stack.count
- end
- end
- if available < count then
- monitor.clear()
- monitor.setCursorPos(1, 1)
- monitor.write("Not enough items!")
- sleep(2)
- return
- end
- -- Complete sale (move to shop chest)
- local moved = 0
- for slot, stack in pairs(playerChest.list()) do
- if stack.name == resID and count > 0 then
- local toSell = math.min(count, stack.count)
- -- Move to shop chest
- local transferred = playerChest.pushItems(peripheral.getName(chest), slot, toSell)
- if transferred > 0 then
- moved = moved + transferred
- count = count - transferred
- if count == 0 then break end
- end
- end
- end
- if moved == 0 then
- monitor.clear()
- monitor.setCursorPos(1, 1)
- monitor.write("Error: no space in shop chest!")
- sleep(2)
- return
- end
- data.balance = data.balance + math.floor(prices[resID].sell * moved)
- monitor.clear()
- monitor.setCursorPos(1, 1)
- monitor.write("Success! Added: "..(math.floor(prices[resID].sell * moved)))
- monitor.setCursorPos(1, 2)
- monitor.write("Balance: "..data.balance)
- sleep(3)
- inTransaction = false
- end
- end
- syncWithChest() -- Update after transaction
- end
- -- Admin panel
- local function adminPanel()
- local adminActive = true
- while adminActive do
- monitor.clear()
- monitor.setCursorPos(1, 1)
- monitor.write("ADMIN PANEL")
- monitor.setCursorPos(1, 2)
- monitor.write("Password: ")
- local inputPass = read("*")
- if inputPass ~= ADMIN_PASSWORD then
- monitor.setCursorPos(1, 3)
- monitor.write("Wrong password!")
- sleep(2)
- return
- end
- local choice = 0
- while choice ~= 4 do
- monitor.clear()
- monitor.setCursorPos(1, 1)
- monitor.write("1. Add resource")
- monitor.setCursorPos(1, 2)
- monitor.write("2. Change discount")
- monitor.setCursorPos(1, 3)
- monitor.write("3. Set balance")
- monitor.setCursorPos(1, 4)
- monitor.write("4. Back")
- choice = tonumber(read())
- if choice == 1 then
- monitor.setCursorPos(1, 5)
- monitor.write("Item ID: ")
- local id = read()
- monitor.setCursorPos(1, 6)
- monitor.write("Name: ")
- local name = read()
- monitor.setCursorPos(1, 7)
- monitor.write("Base price: ")
- local base = tonumber(read())
- if id and name and base then
- data.resources[id] = {
- name = name,
- base = base,
- amount = 0
- }
- monitor.setCursorPos(1, 8)
- monitor.write("Resource added!")
- sleep(2)
- end
- elseif choice == 2 then
- monitor.setCursorPos(1, 5)
- monitor.write("New discount (0.1-0.9): ")
- local discount = tonumber(read())
- if discount and discount >= 0.1 and discount <= 0.9 then
- data.discount = discount
- monitor.setCursorPos(1, 6)
- monitor.write("Discount updated!")
- sleep(2)
- end
- elseif choice == 3 then
- monitor.setCursorPos(1, 5)
- monitor.write("New balance: ")
- local newBalance = tonumber(read())
- if newBalance then
- data.balance = newBalance
- monitor.setCursorPos(1, 6)
- monitor.write("Balance updated!")
- sleep(2)
- end
- elseif choice == 4 then
- adminActive = false
- end
- end
- end
- end
- -- Main loop
- initData()
- while true do
- local prices = calculatePrices()
- drawUI(prices)
- local event, side, x, y = os.pullEvent("monitor_touch")
- local w, h = monitor.getSize()
- -- Resource selection
- if y >= 3 and y <= h-5 then
- local resourceY = 3
- for id, res in pairs(data.resources) do
- if y >= resourceY and y < resourceY + 2 then
- data.selectedItem = id
- break
- end
- resourceY = resourceY + 3
- end
- end
- -- Button handling with highlighting
- if not inTransaction then
- -- Buy/Sell buttons moved down to h-4
- if y >= h-4 and y <= h-3 then
- if x >= 1 and x <= 4 then -- Buy
- highlightButton("Buy", 1, h-4, 4)
- processTransaction(true)
- elseif x >= 6 and x <= 10 then -- Sell
- highlightButton("Sell", 6, h-4, 4)
- processTransaction(false)
- end
- -- Admin button in bottom right corner
- elseif y >= h-1 and x >= w-7 and x <= w-1 then
- highlightButton("Admin", w-7, h-1, 7)
- adminPanel()
- end
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement