-- make a copy of package.path local sSrc = fs.getDir(shell.getRunningProgram()) local sRoot = fs.combine(sSrc, "..") local sData = fs.combine(sRoot, "data") local sFont = fs.combine(sData, "fonts") local sImg = fs.combine(sData, "images") local sPage = fs.combine(sData, "pages") local basalt = require("libs/basalt") local bdf = require("libs/basalt/libraries/miniBDF") local ctx local function purchase(self, event, button, x, y) if event == "mouse_click" and button == 1 then local metadata = self:getMetadata() if metadata.id then -- TODO Open popup that tells user where to send krist to get item basalt.debug("Item: " .. ctx.products[metadata.id].displayName) end end end local function init(...) -- [Context] ctx = { gui = {}, image = {}, products = {}, theme = {}, config = {}, pages = {}, current = 1, scroll = 0, redraw = true } -- [Fonts] fontBDF = {} if fs.exists(sFont) and fs.isDir(sFont) then local fonts = fs.list(sFont) for i = 1, #fonts do local tmp = bdf.loadBDF(fs.combine(sFont, fonts[i])) local count, msg = bdf.checkFont(tmp) if count > 0 then printError("Could not load font \'" .. fonts[i] .. "\'!") for j = 1, #msg do printError(" * " .. msg[j]) end sleep(1) else fontBDF[tmp.name] = tmp end end end -- [Pages] local pages = fs.list(sPage) for i = 1, #pages do local f = fs.open(fs.combine(sPage, pages[i]), 'r') ctx.pages[pages[i]] = f.readAll() f.close() end -- [Data] (config,theme,products, etc.) local function loadStr(str, begin, env) if not begin then begin = "" end local success, result = pcall(loadstring(begin .. str, "t", env)) if success and type(result) == "table" then return result end return false end local function loadLuaFile(path, env) if fs.exists(path) and not fs.isDir(path) then local f = fs.open(path, 'r') local c = f.readAll() f.close() local result = loadStr(c, "", env) if not result then printError("Could not load \'" .. path .. "\' properly!\n" .. tostring(result)) sleep(1) end return result else printError("Could not load \'" .. path .. "\'!") sleep(0.5) end return false end -- theme local col = { white = 0x1, orange = 0x2, magenta = 0x4, lightBlue = 0x8, yellow = 0x10, lime = 0x20, pink = 0x40, grey = 0x80, lightGrey = 0x100, cyan = 0x200, purple = 0x400, blue = 0x800, brown = 0x1000, green = 0x2000, red = 0x4000, black = 0x8000 } local inferiorcol = col; inferiorcol.gray = col.grey; inferiorcol.lightGray = col.lightGrey local result = loadLuaFile(fs.combine(sPage, "theme.lua"), { colours = col, colors = inferiorcol }) if result then ctx.theme = result end -- bimg local files = fs.list(sImg) for i = 1, #files do if files[i]:sub(-4) == "bimg" then local f = fs.open(fs.combine(sImg, files[i]), 'r') local c = f.readAll() f.close() local result = loadStr(c, "return ", { colours = col, colors = inferiorcol }) if result then ctx.image[files[i] or (#ctx.image + 1)] = result end end end -- config result = loadLuaFile(fs.combine(sData, "config.lua")) if result then ctx.config = result end -- products result = loadLuaFile(fs.combine(sData, "products.lua")) if result then ctx.products = result end -- [Purchase] basalt.setVariable("purchase", purchase) return ctx end ---Saves the current proucts states into the file ---and loads them into the interface. local function updateProducts() end ---Checks if a given table has all keys inside it, building a chain with each other. ---@param ctx table The table to inspect ---@param ... any The keys to check ---@return boolean status true if all keys are there and false if not local function checkTableTree(ctx, ...) local tmp = ctx for _, key in pairs({ ... }) do if tmp[key] then tmp = tmp[key] else return false end end return true end ---Go through layout and replace stuff with our content ---@param page table The Basalt frame layout local function insertData(page, ctx) local layout = page:getLastLayout() local function repalceContent(layout) for _, object in pairs(layout) do -- Is frame? if object.addLayout then id = object:getName() -- Is frame for products? if id:find("products") then local listHeight = 1 local nW, nH = object:getSize() for i, product in pairs(ctx.products) do if product.displayName and product.price and product.description then local item = object:addFrame(tostring(i)) :setPosition(1, listHeight) :setSize(nW, 3) :setBackground(colors.gray) local offX = 0 -- Image local bimg = {} for k, v in pairs(ctx.image["missing.bimg"]) do bimg[k] = v end if product.bimg then if type(product.bimg) == "table" then bimg[1] = product.bimg elseif type(product.bimg) == "string" then bimg = fs.combine(sImg, product.bimg) end end if bimg then local img = item:addBimg() :setPosition(1, 1) :loadImage(bimg) local x, y = img:getSize() offX = x + 2 end -- Title item:addLabel() :setText(product.displayName) :setPosition(2 + offX, 1) :setSize(1, nW - (6 + offX), 1) :setBackground(colors.gray) -- Description item:addLabel() :setText(product.description) :setPosition(2 + offX, 2) :setSize(2, nW - (6 + offX), 1) :setForeground(colors.lightGray) :setBackground(colors.gray) -- Button item:addButton() :setText("BUY") :setPosition(nW - 6, 1) :setSize(7, 3) :setForeground(colors.white) :setBackground(colors.green) :setMetadata({ id = i }) :onClick(purchase) listHeight = listHeight + 4 end end object:setSize(nW, listHeight) -- Look into frame for other stuff else local subLayout = object:getLastLayout() repalceContent(subLayout) end -- Is something else we are looking for? elseif object.setText then local id = object:getName() local txt = object:getValue() if id:find("subtitle") then if checkTableTree(ctx, "config", "details", "description") then object:setText(string.format(txt, ctx.config.details.description)) end elseif id:find("title") then if checkTableTree(ctx, "config", "details", "title") then object:setText(string.format(txt, ctx.config.details.title)) end end end end end repalceContent(layout) end local function main(ctx) local base = basalt.createFrame() :setTheme(ctx.theme) :addLayout(fs.combine(sPage, "index.xml")) local sCurPage = "" parallel.waitForAny( basalt.autoUpdate, function() local menubar = base:getDeepObject("main-menubar") local displayPage = base:getDeepObject("main-content") if not (menubar or displayPage) then return printError("Content is missing in index.xml!\nMake sure the following things are there:\n * Menubar | id=\"main-menubar\"\n * Frame | id=\"main-content\"") end while true do -- Change pages local tmpPage = menubar:getItem(menubar:getItemIndex()).text if tmpPage ~= sCurPage then sCurPage = tmpPage local oldLayout = displayPage:getLastLayout() for _, v in pairs(oldLayout) do displayPage:removeObject(v) end displayPage:addLayoutFromString(ctx.pages[sCurPage:lower() .. ".xml"]) insertData(displayPage, ctx) end -- Update products if updateContent then updateContent = false end sleep() end end ) end -- INIT local noErrors = true local args = table.pack(...) xpcall(function() init(table.unpack(args, 1, args.n)) end, function(err) printError(err) noErrors = false end) -- MAIN if noErrors then xpcall(function() main(ctx) end, function(err) printError(err) end) end