Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --[[
- --*--*--*--*--*--*--*--*--*--*--*--*--*--*--
- --* Shop Program *--
- --* https://pastebin.com/XXXXXXXX *--
- --* by: GravityCube *--
- --*--*--*--*--*--*--*--*--*--*--*--*--*--*--
- Changelog:
- 1.0.0 First release. (DynamicChestShop fork https://pastebin.com/hQihjQ3b).
- 1.1.0 Added colors for the categories.
- 1.2.0 Changed currency to CLKeys
- 1.2.1 Issue fixed with non-stackeable items.
- 1.2.2 Bigger buy and qty buttons and change of color for buttons.
- 1.2.3 Remove function fixed.
- --]]
- os.pullEvent = os.pullEventRaw
- --------------------------------------
- --> APIs <--
- --------------------------------------
- os.loadAPI("gcapi")
- os.loadAPI("configAPI")
- os.loadAPI("tableAPI")
- os.loadAPI("windowAPI")
- --------------------------------------
- --> Config <--
- --------------------------------------
- local config = configAPI.open("config.cfg")
- local mon = config:checkPeripheral("monitor", "Please enter the monitor name (enter 'search' for automatic detection): ", "monitor")
- local me = config:checkPeripheral("me_system", "Please enter the me cable name (enter 'search' for automatic detection): ", "appeng_me_tilecolorlesscable")
- local noteblock = config:checkPeripheral("noteblock", "Please enter noteblock name (enter 'search' for automatic detection): ", "music")
- local pim = config:checkPeripheral("pim", "Please enter pim name (enter 'search' for automatic detection): ", "pim")
- --------------------------------------
- --> CL KEYS <--
- --------------------------------------
- os.loadAPI("keySystem")
- keySystem.setup(pim, me)
- --------------------------------------
- --> Listed Items <--
- --------------------------------------
- local items_file = configAPI.open("items.list")
- function checkMaxSizeItems()
- local items = items_file:get("items")
- for i, item in pairs(items) do
- if not item.max_size then
- local me_item = getItemFromME(item)
- if me_item then
- items[i].max_size = me_item.maxSize
- else
- print("Item " .. item.id .. ":" .. (item.dmg or 0) .. " not found in the me_system!")
- sleep(2)
- end
- end
- end
- items_file:put("items", items)
- end
- function getItemFromME(item)
- local inventory = me.getAvailableItems()
- for k,v in pairs(inventory) do
- if v.id == tonumber(item.id) and v.dmg == (tonumber(item.dmg) or 0) then
- return inventory[k]
- end
- end
- return nil
- end
- checkMaxSizeItems()
- --------------------------------------
- --> Table Instance <--
- --------------------------------------
- local category_colors = {}
- local tableInstance = tableAPI.new(mon, (items_file:get("items") or {}), {"name", "qty", "price", "category"})
- tableInstance.custom_colors_func.category = function(mon, txt)
- local color = category_colors[txt]
- if not color then
- local i = 0
- for k,v in pairs(category_colors) do i = i + 1 end
- color = 2^(i + 1)
- category_colors[txt] = color
- mon.setTextColor(color)
- else
- mon.setTextColor(color)
- end
- end
- table.sort(tableInstance.data, function(a,b)
- if a.category == b.category then
- return a.name < b.name
- end
- return a.category < b.category
- end)
- tableInstance:draw()
- --------------------------------------
- --> Sound Monitor <--
- --------------------------------------
- tableInstance.playSound = function(self)
- noteblock.playSound("random.wood_click",1,1)
- end
- --------------------------------------
- --> Item delivery <--
- --------------------------------------
- function getStock(item)
- local id = tonumber(item.id)
- local dmg = tonumber(item.dmg) or 0
- local stock = me.countOfItemType(id, dmg)
- return stock or 0
- end
- function sendItems(item)
- local queue_qty = item.qty
- for r=1, math.floor(queue_qty/(item.max_size or 64))+1 do
- local move_qty = item.max_size or 64
- if queue_qty < move_qty then move_qty = queue_qty end
- queue_qty = queue_qty - me.extractItem({["id"] = tonumber(item.id), ["dmg"] = tonumber(item.dmg), ["qty"] = move_qty}, "up")
- end
- if delivered_qty == item.qty then
- return true
- end
- return false, delivered_qty
- end
- --------------------------------------
- --> Transaction Window <--
- --------------------------------------
- --[[
- --------------Close-
- - Name: item_name -
- - ID: id -
- - Qty: << < 1 > >> -
- - Price: $xxx -
- - Category: xxx -
- - -
- -Back-----------BUY-
- ]]--
- local TransactionWindow = {
- draw = function(self)
- self:clearButtonsMap()
- local mon = self.mon
- local max_x, max_y = mon.getSize()
- local item = self.item
- local width = ( ( 40 > ( 6 + string.len(item.name) ) ) and 40 ) or ( 6 + string.len(item.name) )
- local xi = gcapi.getCenter(max_x, width)
- local yi = gcapi.getCenter(max_y, 8)
- self.window = windowAPI.newWindow(mon, xi, yi, width, 8)
- local window = self.window
- window:setBackgroundColor(colors.white)
- window:clear()
- --** Borders
- window:setBackgroundColor(colors.cyan)
- for y=1, 8 do
- if y == 1 or y == 8 then
- window:setCursorPos(1,y)
- for x=1, width do
- window:write(" ")
- end
- end
- end
- for y=1, 8 do
- window:setCursorPos(width,y)
- window:write(" ")
- end
- for y=1, 8 do
- window:setCursorPos(1,y)
- window:write(" ")
- end
- --**Close button
- self:newButton(" X ", width-3,1,1,1, function() return true end)
- window:setBackgroundColor(colors.white)
- --**Item data
- window:setCursorPos(2,2)
- window:write("Name: " .. item.name)
- window:setCursorPos(2,3)
- window:write("ID: " .. item.id) if item.dmg then window:write(":" .. item.dmg) end
- window:setCursorPos(2,4)
- window:write("Qty: " .. item.qty .. " ")
- --** << < Arrows > >>
- local cx, cy = window:getCursorPos()
- self:newButton(" < ", cx, cy, 3, 1, function() self:updateItemQty(-1) end)
- self:newButton(" > ", cx+4, cy, 3, 1, function() self:updateItemQty(1) end)
- window:setBackgroundColor(colors.white)
- window:setCursorPos(2,5)
- window:write("Price: " .. keySystem.priceToKeys(item.price) .. " keys" .. " (Virtual price: " .. math.floor(item.price*10)/1000 .. ")")
- window:setCursorPos(2,6)
- window:write("Category: " .. item.category)
- --** Back and Buy
- self:newButton("Back", 2,8,4,1, function() return true end)
- self:newButton(" Buy ", width-5,8,5,1, function()
- local stock = getStock(item)
- if stock < item.qty then
- self:displayMessage("There is no stock for this item", nil, colors.red)
- sleep(2)
- self:draw()
- return false
- end
- local transaction_status, err = keySystem.withdraw(self.item.price, "Bought " .. item.id .. ":" .. (item.dmg or 0))
- if transaction_status then
- local text = "Thanks for your purchase!"
- self:displayMessage(text, nil, colors.lime)
- sendItems(item)
- sleep(2)
- return true
- else
- self:displayMessage(err, nil, colors.red)
- sleep(2)
- self:draw()
- return false
- end
- end)
- end,
- displayMessage = function(self, text, background_color, text_color)
- local background_color = background_color or colors.lightGray
- local text_color = text_color or colors.black
- local window = self.window
- local text = " " .. text .. " "
- window:setBackgroundColor(background_color)
- window:setTextColor(text_color)
- window:setCursorPos(gcapi.getCenter(window.width+1, text), gcapi.getCenter(window.heigth+1))
- window:write(text)
- window:setTextColor(colors.black)
- end,
- updateItemQty = function (self, diff)
- local item = self.item
- local org_qty = self.original_item["qty"]
- local new_qty = self.item["qty"] + org_qty*diff
- local stock = getStock(item)
- if new_qty > 0 and new_qty < 999 and stock >= new_qty then
- local pc = new_qty/self.item["qty"]
- item.price = item.price*pc
- item.qty = new_qty
- end
- self:draw()
- end,
- buttonListener = function (self)
- while true do
- local tEvent = {os.pullEvent()}
- if not self.window then
- return false
- end
- if tEvent[1] == "monitor_touch" then
- local x = tEvent[3]
- local y = tEvent[4]
- local ix = self.window.init_x + 1
- local iy = self.window.init_y + 1
- --if clic on the window
- if gcapi.numberBetween(x, ix, self.window.width+ix) and gcapi.numberBetween(y, iy, self.window.heigth+iy) then
- local buttonFunc = self.buttons_map[x][y]
- if buttonFunc then
- if buttonFunc() then
- return true
- end
- end
- else
- return false
- end
- end
- end
- end,
- newButton = function(self, text, xi, yi, width, heigth, func)
- local drawButton = function(color)
- self.window:setBackgroundColor(color)
- local x_string = ""
- for x=xi, width+xi-1 do
- x_string = x_string .. " "
- end
- for y=yi, heigth+yi-1 do
- self.window:setCursorPos(xi, y)
- self.window:write(x_string)
- end
- self.window:setCursorPos(xi + gcapi.getCenter(width, text), yi + gcapi.getCenter(heigth))
- self.window:write(text)
- end
- drawButton(colors.cyan)
- for x=xi, width+xi-1 do
- for y=yi, heigth+yi-1 do
- self.buttons_map[x+self.window.init_x][y+self.window.init_y] = function()
- drawButton(colors.orange)
- sleep(0.15)
- drawButton(colors.cyan)
- if func then
- return func()
- end
- end
- end
- end
- end,
- clearButtonsMap = function(self)
- local max_x, max_y = self.mon.getSize()
- for x=1, max_x do
- self.buttons_map[x] = {}
- end
- end,
- }
- function createTransactionWindow(row_data)
- local max_x, max_y = mon.getSize()
- local transactionWindow = {
- item = gcapi.deepCopy(row_data),
- original_item = row_data,
- buttons_map = {}
- }
- transactionWindow.mon = mon
- for x=1, max_x do
- transactionWindow.buttons_map[x] = {}
- end
- setmetatable(transactionWindow, {__index = TransactionWindow})
- return transactionWindow
- end
- --------------------------------------
- --> Monitor <--
- --------------------------------------
- function printTable(new_data)
- tableInstance.data = new_data
- tableInstance:draw()
- end
- function monitorListener()
- while true do
- local tEvent = {os.pullEvent()}
- local row_data, y = tableInstance:getRowOnEvent(tEvent)
- if row_data then
- tableInstance:highlight("name", row_data.name, true)
- tableInstance:draw()
- local transactionWindow = createTransactionWindow(row_data)
- transactionWindow:draw()
- transactionWindow:buttonListener()
- tableInstance:clearHighlights()
- tableInstance:draw()
- end
- end
- end
- --------------------------------------
- --> Terminal <--
- --------------------------------------
- function commandListener()
- textutils.slowPrint(".......", 6)
- while true do
- verifyPassword("pass")
- term.clear()
- term.setCursorPos(1,1)
- term.write("Available commands: ")
- term.setCursorPos(1,2)
- term.write("1. add <name> <id> <amount> <price> <category>")
- term.setCursorPos(1,3)
- term.write("2. remove <id>")
- term.setCursorPos(1,5)
- term.write("Enter command: ")
- local input = read()
- tInput = gcapi.split(input .. " ", " ")
- if tInput[1] == "add" then
- local name = tInput[2]
- local id = tInput[3]
- local qty = tonumber(tInput[4])
- local price = tonumber(tInput[5])
- local category = tInput[6]
- if id and qty and price and category then
- local items = items_file:get("items") or {}
- local s = gcapi.split(id, ":")
- table.insert(items, {["id"] = s[1], ["dmg"] = s[2], ["name"] = name, ["price"] = price, ["qty"] = qty, ["category"] = category})
- printTable(items)
- items_file:put("items", items)
- print("Item " .. name .. " added!")
- else
- print("Wrong parameters!")
- end
- end
- if tInput[1] == "remove" then
- local id0 = tInput[2]
- if id0 then
- local s = gcapi.split(id0, ":")
- local id = s[1]
- local dmg = s[2]
- local items = items_file:get("items") or {}
- local new_items = {}
- local was_deleted = false
- for _,row_data in pairs(items) do
- if row_data.id ~= id or row_data.dmg ~= dmg then
- table.insert(new_items, row_data)
- else
- was_deleted = true
- end
- end
- if was_deleted then
- printTable(new_items)
- items_file:put("items", new_items)
- print("Item (ID: " .. id ..") deleted!")
- else
- print("Item (ID: " .. id ..") not found!")
- end
- end
- end
- if tInput[1] == "terminate" then
- return true
- end
- textutils.slowPrint("....", 4)
- end
- end
- function verifyPassword(pass)
- while true do
- term.clear()
- term.setCursorPos(1,1)
- term.write("Password: ")
- local input = read("*")
- if input == pass then
- return true
- else
- term.setCursorPos(1,2)
- term.write("Incorrect password!")
- end
- end
- end
- parallel.waitForAny(commandListener, monitorListener)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement