diff --git a/core/apis/nameDB.lua b/core/apis/nameDB.lua index c068c14..7216f95 100644 --- a/core/apis/nameDB.lua +++ b/core/apis/nameDB.lua @@ -1,38 +1,57 @@ local JSON = require('json') local TableDB = require('tableDB') +local Util = require('util') local fs = _G.fs -local NAME_DIR = '/packages/core/etc/names' +local CORE_DIR = '/packages/core/etc/names' +local USER_DIR = '/usr/etc/names' local nameDB = TableDB() -function nameDB:load() +function nameDB:loadDirectory(directory) + if fs.exists(directory) then + local files = fs.list(directory) + table.sort(files) - local files = fs.list(NAME_DIR) - table.sort(files) + for _,file in ipairs(files) do + local mod = file:match('(%S+).json') + if mod then + local blocks = JSON.decodeFromFile(fs.combine(directory, file)) - for _,file in ipairs(files) do - local mod = file:match('(%S+).json') - local blocks = JSON.decodeFromFile(fs.combine(NAME_DIR, file)) + if not blocks then + error('Unable to read ' .. fs.combine(directory, file)) + end - if not blocks then - error('Unable to read ' .. fs.combine(NAME_DIR, file)) - end + for strId, block in pairs(blocks) do + strId = string.format('%s:%s', mod, strId) + if type(block.name) == 'string' then + self.data[strId .. ':0'] = block.name + else + for nid,name in pairs(block.name) do + self.data[strId .. ':' .. (nid-1)] = name + end + end + end - for strId, block in pairs(blocks) do - strId = string.format('%s:%s', mod, strId) - if type(block.name) == 'string' then - self.data[strId .. ':0'] = block.name - else - for nid,name in pairs(block.name) do - self.data[strId .. ':' .. (nid-1)] = name + elseif file:match('(%S+).db') then + local names = Util.readTable(fs.combine(directory, file)) + if not names then + error('Unable to read ' .. fs.combine(directory, file)) + end + for key,name in pairs(names) do + self.data[key] = name end end end end end +function nameDB:load() + self:loadDirectory(CORE_DIR) + self:loadDirectory(USER_DIR) +end + function nameDB:getName(strId) return self.data[strId] or strId end diff --git a/milo/apis/craft2.lua b/milo/apis/craft2.lua index 68173d2..35cc0c7 100644 --- a/milo/apis/craft2.lua +++ b/milo/apis/craft2.lua @@ -11,6 +11,7 @@ local Craft = { STATUS_SUCCESS = 'success', RECIPES_DIR = 'packages/core/etc/recipes', + USER_DIR = 'usr/etc/recipes', USER_RECIPES = 'usr/config/recipes.db', MACHINE_LOOKUP = 'usr/config/machine_crafting.db', } @@ -414,10 +415,11 @@ function Craft.loadRecipes() Util.merge(Craft.recipes, (Util.readTable(fs.combine(Craft.RECIPES_DIR, 'minecraft.db')) or { }).recipes) - local config = Util.readTable('usr/config/recipeBooks.db') or { } - for _, book in pairs(config) do - local recipeFile = Util.readTable(book) - Util.merge(Craft.recipes, recipeFile.recipes) + if fs.exists(Craft.USER_DIR) then + for _, file in pairs(fs.list(Craft.USER_DIR)) do + local recipeFile = Util.readTable(fs.combine(Craft.USER_DIR, file)) + Util.merge(Craft.recipes, recipeFile.recipes) + end end local recipes = Util.readTable(Craft.USER_RECIPES) or { } diff --git a/recipeBook/etc/apps.db b/recipeBook/etc/apps.db new file mode 100644 index 0000000..9a6ec4f --- /dev/null +++ b/recipeBook/etc/apps.db @@ -0,0 +1,7 @@ +{ + [ "9fb1092f32d4fcbf9e061ffd718d4ec689c6c95e" ] = { + title = "Recipes", + category = "Apps", + run = "recipeBook", + }, +} diff --git a/recipeBook/etc/recipeBook.db b/recipeBook/etc/recipeBook.db new file mode 100644 index 0000000..d18ef02 --- /dev/null +++ b/recipeBook/etc/recipeBook.db @@ -0,0 +1,20 @@ +{ + { + url = "https://pastebin.com/raw/dMCDeCie", + version = "MC 1.8+", + localName = "appliedenergistics2", + name = "Applied Energistics", + }, + { + url = "https://pastebin.com/raw/Y6bQMUeE", + version = "MC 1.8+", + localName = "botania", + name = "Botania", + }, + { + url = "https://pastebin.com/raw/YPWgiFFW", + version = "MC 1.8+", + localName = "computercraft", + name = "Computercraft", + }, +} \ No newline at end of file diff --git a/recipeBook/recipeBook.lua b/recipeBook/recipeBook.lua index 7d36ec2..d929a9b 100644 --- a/recipeBook/recipeBook.lua +++ b/recipeBook/recipeBook.lua @@ -1,39 +1,34 @@ -_G.requireInjector(_ENV) - local Ansi = require('ansi') local UI = require('ui') local Util = require('util') -local colors = _G.colors -local fs = _G.fs +local colors = _G.colors +local fs = _G.fs +local textutils = _G.textutils -local RECIPES_DIR = 'usr/etc/recipes' +local RECIPES_DIR = 'usr/etc/recipes' +local NAMES_DIR = 'usr/etc/names' +local RECIPE_BOOKS = 'packages/recipeBook/etc/recipeBook.db' + +local db = Util.readTable(RECIPE_BOOKS) local function getRecipeBooks() local books = { } - local files = fs.list(RECIPES_DIR) - table.sort(files) - Util.removeByValue(files, 'minecraft.db') - - for _,file in ipairs(files) do - local path = fs.combine(RECIPES_DIR, file) - local recipeFile = Util.readTable(path) - if recipeFile then - table.insert(books, { - path = path, - name = recipeFile.name, - version = recipeFile.version, - }) - end + if not fs.exists(RECIPES_DIR) then + fs.makeDir(RECIPES_DIR) end - local config = Util.readTable('usr/config/recipeBooks.db') or { } - for _, book in pairs(config) do - local b = Util.find(books, 'path', book) - if b then - b.enabled = true - end + for _,book in pairs(db) do + local path = fs.combine(RECIPES_DIR, book.localName .. '.db') + table.insert(books, { + recipePath = path, + namePath = fs.combine(NAMES_DIR, book.localName .. '.db'), + name = book.name, + url = book.url, + version = book.version, + enabled = fs.exists(path), + }) end return books @@ -43,10 +38,15 @@ local page = UI.Page { info = UI.Window { x = 2, ex = -2, y = 2, ey = 5, button = UI.Button { - ex = -1, y = 3, width = 9, + ex = -1, y = 3, width = 10, text = 'Enable', event = 'grid_select', - } + }, + addButton = UI.Button { + ex = -12, y = 3, width = 10, + text = 'Add Book', + event = 'add_book', + }, }, grid = UI.ScrollingGrid { y = 6, @@ -60,10 +60,39 @@ local page = UI.Page { sortColumn = 'name', autospace = true, }, - accelerators = { - q = 'quit', - space = 'grid_select', + add = UI.SlideOut { + backgroundColor = colors.cyan, + titleBar = UI.TitleBar { + title = 'Add a new book', + }, + form = UI.Form { + x = 2, ex = -2, y = 2, ey = -1, + [1] = UI.TextEntry { + formLabel = 'Name', formKey = 'name', + shadowText = 'Friendly name', + limit = 64, + required = true, + }, + [2] = UI.TextEntry { + formLabel = 'Version', formKey = 'version', + shadowText = 'Mod version', + limit = 10, + }, + [3] = UI.TextEntry { + formLabel = 'URL', formKey = 'url', + shadowText = 'URL for recipes', + limit = 128, + required = true, + }, + [4] = UI.TextEntry { + formLabel = 'File name', formKey = 'localName', + shadowText = 'Short name for saving file', + limit = 20, + required = true, + }, + }, }, + notification = UI.Notification { }, } function page.info:draw() @@ -79,6 +108,7 @@ function page.info:draw() self.button.text = book.enabled and 'Disable' or 'Enable' self.button:draw() + self.addButton:draw() end end @@ -89,25 +119,55 @@ function page.grid:getRowTextColor(row, selected) return selected and colors.lightGray or colors.gray end -function page:save() - local t = { } - - for _, book in pairs(self.grid.values) do - if book.enabled then - table.insert(t, book.path) +function page:save(book, enable) + if enable then + self.notification:info('Downloading...') + self:sync() + local s = pcall(function() + local recipes = Util.download(book.url) + if recipes then + recipes = textutils.unserialize(recipes) + local names = { } + for k,v in pairs(recipes.recipes) do + names[k] = v.displayName + v.displayName = nil + end + Util.writeTable(book.namePath, names) + Util.writeTable(book.recipePath, recipes) + end + book.enabled = true + self.notification:success('Download complete') + end) + if not s then + self.notification:error('Download failed') end + else + fs.delete(book.recipePath) + fs.delete(book.namePath) + book.enabled = false end - - Util.writeTable('usr/config/recipeBooks.db', t) end function page:eventHandler(event) if event.type == 'grid_select' then local book = self.grid:getSelected() - book.enabled = not book.enabled + self:save(book, not book.enabled) self.info:draw() self.grid:draw() - self:save() + + elseif event.type == 'add_book' then + self.add.form:setValues({ }) + self.add:show() + + elseif event.type == 'form_complete' then + self.add:hide() + table.insert(db, self.add.form.values) + Util.writeTable(RECIPE_BOOKS, db) + self.grid:setValues(getRecipeBooks()) + self.grid:draw() + + elseif event.type == 'form_cancel' then + self.add:hide() elseif event.type == 'grid_focus_row' then self.info:draw()