diff --git a/README.md b/README.md new file mode 100644 index 0000000..aab4082 --- /dev/null +++ b/README.md @@ -0,0 +1,26 @@ + +# Screenshots + +- Meta menu: + +![Meta menu](screenshots/meta.png) + +- Server list: + +![Servers menu](screenshots/servers.png) + +- Content menu: + +![Content menu](screenshots/content.png) + +- ContentDB menu: + +![ContentDB menu](screenshots/contentdb.png) + +- Settings menu: + +![Settings menu](screenshots/settings.png) + +- Credits menu: + +![Credits menu](screenshots/credits.png) diff --git a/imfs.lua b/imfs.lua index 5585972..e153ed6 100644 --- a/imfs.lua +++ b/imfs.lua @@ -373,7 +373,7 @@ fs_hypertext.__index = fs_hypertext setmetatable(fs_hypertext, { __call = function(_, x, y, w, h, txt) local e = {x = x, y = y, w = w, h = h, txt = txt, _styles = {}} - e.__id = "_"..minetest.get_us_time().."_"..math.random(1, 100000) + e.__id = new_id() setmetatable(e, fs_hypertext) table.insert(ctx, e) return e @@ -747,7 +747,7 @@ fs_scrollbar.__index = fs_scrollbar setmetatable(fs_scrollbar, { __call = function(_, x, y, w, h, orientation, value) local e = {x = x, y = y, w = w, h = h, orientation = orientation or "vertical", value = value or "", _styles = {}} - e.__id = "_"..minetest.get_us_time().."_"..math.random(1, 100000) + e.__id = new_id() setmetatable(e, fs_scrollbar) ctx[#ctx +1] = e return e diff --git a/init.lua b/init.lua index f1ccfed..475e4c8 100644 --- a/init.lua +++ b/init.lua @@ -259,7 +259,7 @@ function show_online_content_menu(content) show_type = imfs.state("all"), content_shown = imfs.state(), page = imfs.state(1), - current_package = imfs.state(), + detail = imfs.state(), }) end diff --git a/screenshots/content.png b/screenshots/content.png new file mode 100644 index 0000000..433a98c Binary files /dev/null and b/screenshots/content.png differ diff --git a/screenshots/contentdb.png b/screenshots/contentdb.png new file mode 100644 index 0000000..a816ae4 Binary files /dev/null and b/screenshots/contentdb.png differ diff --git a/screenshots/credits.png b/screenshots/credits.png new file mode 100644 index 0000000..8a21255 Binary files /dev/null and b/screenshots/credits.png differ diff --git a/screenshots/meta.png b/screenshots/meta.png new file mode 100644 index 0000000..57afa8d Binary files /dev/null and b/screenshots/meta.png differ diff --git a/screenshots/servers.png b/screenshots/servers.png new file mode 100644 index 0000000..e672d16 Binary files /dev/null and b/screenshots/servers.png differ diff --git a/screenshots/settings.png b/screenshots/settings.png new file mode 100644 index 0000000..a5b7938 Binary files /dev/null and b/screenshots/settings.png differ diff --git a/views/online_content.lua b/views/online_content.lua index 0580f55..5b76c89 100644 --- a/views/online_content.lua +++ b/views/online_content.lua @@ -35,7 +35,11 @@ return function(state) imfs.row(0.15, 0.05, "100% - 0.3", "100% - 0.13") local show_type = state.show_type() imfs.button(0, 0, "1x", "100%", "All") - :style(show_type == "all" and style_borderless_alt or style_borderless) + :style( + show_type == "all" + and style_borderless_alt + or style_borderless + ) :style("hovered", style_borderless_hovered) :style("pressed", style_borderless_hovered) :onclick(function() @@ -52,7 +56,11 @@ return function(state) end) imfs.box(0, 0, 0.1, "100%", theme.styles.container.border_color) imfs.button(0, 0, "1x", "100%", "Games") - :style(show_type == "games" and style_borderless_alt or style_borderless) + :style( + show_type == "games" + and style_borderless_alt + or style_borderless + ) :style("hovered", style_borderless_hovered) :style("pressed", style_borderless_hovered) :onclick(function() @@ -69,7 +77,11 @@ return function(state) end) imfs.box(0, 0, 0.1, "100%", theme.styles.container.border_color) imfs.button(0, 0, "1x", "100%", "Mods") - :style(show_type == "mods" and style_borderless_alt or style_borderless) + :style( + show_type == "mods" + and style_borderless_alt + or style_borderless + ) :style("hovered", style_borderless_hovered) :style("pressed", style_borderless_hovered) :onclick(function() @@ -86,7 +98,11 @@ return function(state) end) imfs.box(0, 0, 0.1, "100%", theme.styles.container.border_color) imfs.button(0, 0, "1x", "100%", "Texture Packs") - :style(show_type == "texturepacks" and style_borderless_alt or style_borderless) + :style( + show_type == "texturepacks" + and style_borderless_alt + or style_borderless + ) :style("hovered", style_borderless_hovered) :style("pressed", style_borderless_hovered) :onclick(function() @@ -157,75 +173,83 @@ return function(state) return imfs.end_() end - local content = state.content_shown() - local num_per_page = math.floor((size.x + 0.5) / 5.5) * math.floor((size.y - 1.05) / 3.5) - local excess_x = (size.x + 0.5) % 5.5 - local excess_y = (size.y - 1.05) % 3.5 - imfs.scroll_container(0, 1.05, "100%", "100% - 1.55", "horizontal", 0, "") - :scrollbar(function() - imfs.scrollbar(0, size.y - 0.5, size.x, 0.5, "horizontal", state.page()) - :options({ - min = 1, - max = math.ceil(state.num_content / num_per_page), - smallstep = 1 - }) - :onchange(function(action, value) - if action == "CHG" then - state.page(value) - end - end) - end) - - local x = 0 - local y = 0 - local start = (state.page() - 1) * num_per_page - local i = start - local idx = start - while idx < start + num_per_page do - i = i + 1 - local pkg = content[i] - if not pkg then break end + if state.detail() then + imfs.button(1, 2, 3, 0.75, "Back") + :onclick(function() + state.detail(false) + end) + else + local content = state.content_shown() + local num_per_page = + math.floor((size.x + 0.5) / 5.5) * math.floor((size.y - 1.05) / 3.5) + local excess_x = (size.x + 0.5) % 5.5 + local excess_y = (size.y - 1.05) % 3.5 + imfs.scroll_container(0, 1.05, "100%", "100% - 1.55", "horizontal", 0, "") + :scrollbar(function() + imfs.scrollbar(0, size.y - 0.5, size.x, 0.5, "horizontal", state.page()) + :options({ + min = 1, + max = math.ceil(state.num_content / num_per_page), + smallstep = 1 + }) + :onchange(function(action, value) + if action == "CHG" then + state.page(value) + end + end) + end) - if not package.is_installed(pkg.type, pkg.name) then - idx = idx + 1 + local x = 0 + local y = 0 + local start = (state.page() - 1) * num_per_page + local i = start + local idx = start + while idx < start + num_per_page do + i = i + 1 + local pkg = content[i] + if not pkg then break end - imfs.group(x + excess_x / 2, y + excess_y / 2, 5, 3) - imfs.image(0, 0, "100%", "100%", package.screenshot(pkg)) - imfs.box(0, 0, "100%", "100%", "#000a") - imfs.hypertext(0.1, 0.1, "100% - 0.2", "100% - 0.2", string.format( - [[ - by %s - %s]], - core.hypertext_escape(pkg.title or pkg.name), - pkg.author, - pkg.short_description - )) - :style(".scrollbar", { - size = "0" - }) - imfs.button(0, 0, "100%", "100%") - :styles(styles_no_background) - :style("hovered", { - bgimg = "[fill:1x1:0,0:#fff", - bgcolor = "#0004" - }) - :style("pressed", { - bgimg = "[fill:1x1:0,0:#fff", - bgcolor = "#0004" - }) - :onclick(function() - - end) - imfs.group_end() - x = x + 5.5 - if x + 5 > size.x then - x = 0 - y = y + 3.5 + if not package.is_installed(pkg.type, pkg.name) then + idx = idx + 1 + + imfs.group(x + excess_x / 2, y + excess_y / 2, 5, 3) + imfs.image(0, 0, "100%", "100%", package.screenshot(pkg)) + imfs.box(0, 0, "100%", "100%", "#000a") + imfs.hypertext(0.1, 0.1, "100% - 0.2", "100% - 0.2", string.format( + [[ + by %s + %s]], + core.hypertext_escape(pkg.title or pkg.name), + pkg.author, + pkg.short_description + )) + :style(".scrollbar", { + size = "0" + }) + imfs.button(0, 0, "100%", "100%") + :styles(styles_no_background) + :style("hovered", { + bgimg = "[fill:1x1:0,0:#fff", + bgcolor = "#0004" + }) + :style("pressed", { + bgimg = "[fill:1x1:0,0:#fff", + bgcolor = "#0004" + }) + :onclick(function() + state.detail(pkg) + end) + imfs.group_end() + x = x + 5.5 + if x + 5 > size.x then + x = 0 + y = y + 3.5 + end end end - end - - imfs.scroll_container_end() + + imfs.scroll_container_end() + end return imfs.end_() end diff --git a/views/servers.lua b/views/servers.lua index 9d3f984..318cb8f 100644 --- a/views/servers.lua +++ b/views/servers.lua @@ -127,6 +127,17 @@ local function refresh_server_list(state) nil, function(result) local list = table.copy(state.favorite_servers) + local num_servers = #result + local i = 0 + while i < num_servers do + i = i + 1 + -- Drop incompatible servers. You can't join them, + -- so showing them is rather pointless. + if (result[i].proto_max or version.proto_min) < version.proto_min then + table.remove(result, i) + num_servers = num_servers - 1 + end + end table.insert_all(list, result) state.servers = list if state.search ~= "" then @@ -280,109 +291,99 @@ return function(state) imfs.scope("servers") local height = size.y * 0.8 local i = 0 - local idx = state.scroll_pos() - while true do - -- We must use a while loop here because we skip incompatible servers, - -- and we have no way of knowing how many there will be until we iterate. - if i > math.ceil(height / 0.5) then break end - + for idx = state.scroll_pos(), state.scroll_pos() + height / 0.5 do local x = list[idx] -- End early if we've run out of list. if not x then break end - -- Skip incompatible servers. You can't join them, - -- so showing them is rather pointless. - if (x.proto_max or version.proto_min) >= version.proto_min then - local ping_lvl = 0 - local lag = (x.lag or 0) * 1000 + (x.ping or 0) * 250 - if lag <= 125 then - ping_lvl = 4 - elseif lag <= 175 then - ping_lvl = 3 - elseif lag <= 250 then - ping_lvl = 2 - elseif lag <= 400 then - ping_lvl = 1 + local ping_lvl = 0 + local lag = (x.lag or 0) * 1000 + (x.ping or 0) * 250 + if lag <= 125 then + ping_lvl = 4 + elseif lag <= 175 then + ping_lvl = 3 + elseif lag <= 250 then + ping_lvl = 2 + elseif lag <= 400 then + ping_lvl = 1 + end + + local name = x.name and x.name:trim() or "" + if name == "" then + name = core.colorize(theme.styles.text_color_muted, x.address..":"..x.port) + end + + imfs.button(0, i * 0.5, "100%", 0.5) + :style({ + border = false, + bgimg = "[fill:1x1:0,0:#fff", + bgimg_middle = 0, + bgcolor = i % 2 == 1 and theme.styles.container.bg_color or theme.styles.container.bg_color_alt, + }) + :style("hovered", { + border = false, + bgimg = "[fill:1x1:0,0:#fff", + bgimg_middle = 0, + }) + :style("pressed", { + border = false, + bgimg = "[fill:1x1:0,0:#fff", + bgimg_middle = 0, + }) + :onclick(function() + state.detail(x) + end) + imfs.row(0.1, i * 0.5, "100% - 0.65", 0.5) + if x.favorite then + imfs.image(0, 0, 0.5, 0.5, theme.icon("menu_servers_favorite")) + :tooltip("Favorite server", enable_tooltips) end - + local name = x.name and x.name:trim() or "" if name == "" then name = core.colorize("#888", x.address..":"..x.port) end + -- We use an arealabel to ensure that the name will be clipped + -- if it is inordinately long, rather than overflowing onto + -- other thigs. + imfs.arealabel(0, 0.125, "1x", 0.375, name) - imfs.button(0, i * 0.5, "100%", 0.5) - :style({ - border = false, - bgimg = "[fill:1x1:0,0:#fff", - bgimg_middle = 0, - bgcolor = i % 2 == 1 and theme.styles.container.bg_color or theme.styles.container.bg_color_alt, - }) - :style("hovered", { - border = false, - bgimg = "[fill:1x1:0,0:#fff", - bgimg_middle = 0, - }) - :style("pressed", { - border = false, - bgimg = "[fill:1x1:0,0:#fff", - bgimg_middle = 0, - }) - :onclick(function() - state.detail(x) - end) - imfs.row(0.1, i * 0.5, "100% - 0.65", 0.5) - if x.favorite then - imfs.image(0, 0, 0.5, 0.5, theme.icon("menu_servers_favorite")) - :tooltip("Favorite server", enable_tooltips) - end + if x.pvp == false then + imfs.image(0, 0, 0.5, 0.5, theme.icon("menu_servers_peaceful")) + :tooltip("Peaceful", enable_tooltips) + end - local name = x.name and x.name:trim() or "" - if name == "" then - name = core.colorize("#888", x.address..":"..x.port) - end - -- We use an arealabel to ensure that the name will be clipped - -- if it is inordinately long, rather than overflowing onto - -- other thigs. - imfs.arealabel(0, 0.125, "1x", 0.375, name) - - if x.pvp == false then - imfs.image(0, 0, 0.5, 0.5, theme.icon("menu_servers_peaceful")) - :tooltip("Peaceful", enable_tooltips) - end - - if x.creative then - imfs.image(0, 0, 0.5, 0.5, theme.icon("menu_servers_creative")) - :tooltip("Creative", enable_tooltips) - end - - if x.clients then - local clients = x.clients..( - x.clients_max and "/"..x.clients_max or "" - ) - local color = "#aaa" - if x.clients > 0 and x.clients_max then - local percent = x.clients /x.clients_max - if percent < 0.75 then - color = "#638b67" - elseif percent < 1 then - color = "#a69174" - else - color = "#9d5b5b" - end + if x.creative then + imfs.image(0, 0, 0.5, 0.5, theme.icon("menu_servers_creative")) + :tooltip("Creative", enable_tooltips) + end + + if x.clients then + local clients = x.clients..( + x.clients_max and "/"..x.clients_max or "" + ) + local color = "#aaa" + if x.clients > 0 and x.clients_max then + local percent = x.clients /x.clients_max + if percent < 0.75 then + color = "#638b67" + elseif percent < 1 then + color = "#a69174" + else + color = "#9d5b5b" end - imfs.hypertext(0, 0, 1, 0.5, ""..core.hypertext_escape(clients)) - end - - if x.ping or x.lag then - imfs.image(0, 0, 0.5, 0.5, theme.icon("menu_servers_icon_ping_"..ping_lvl)) - :tooltip("Ping: "..math.floor(lag), enable_tooltips) end + imfs.hypertext(0, 0, 1, 0.5, ""..core.hypertext_escape(clients)) + end - imfs.row_end() - - i = i + 1 - end - idx = idx + 1 + if x.ping or x.lag then + imfs.image(0, 0, 0.5, 0.5, theme.icon("menu_servers_icon_ping_"..ping_lvl)) + :tooltip("Ping: "..math.floor(lag), enable_tooltips) + end + + imfs.row_end() + + i = i + 1 end imfs.scope_end() @@ -467,7 +468,7 @@ return function(state) end if joining == true then - imfs.hypertext(0, 0, "100%", 0.75, "Connecting to server...") + imfs.hypertext(0, 0, "100%", 0.75, "Joining server...") imfs.group(0, 0, "100%", 1.05) imfs.image(0, 0.3, "100%", "100% - 0.3", theme.get_background_image("field")) imfs.label(0.2, 0.125, "Address") @@ -489,7 +490,7 @@ return function(state) end) imfs.group_end() else - imfs.hypertext(0, 0, "100%", 0.75, "Connecting to "..core.hypertext_escape(joining.name or joining.address..":"..joining.port).."...") + imfs.hypertext(0, 0, "100%", 0.75, "Joining "..core.hypertext_escape(joining.name or joining.address..":"..joining.port).."...") end theme.field(0, 0, "100%", 0.75, "Username", state.username) diff --git a/views/settings.lua b/views/settings.lua index 8e9ac9b..fd2232a 100644 --- a/views/settings.lua +++ b/views/settings.lua @@ -42,14 +42,24 @@ local function search_settings(state, search) return state.settings, state.categories end + local words = search:lower():trim():split(" ") + local out = {} for category, settings in pairs(state.settings) do for i = 1, #settings do - if settings[i].name:find(search, 1, true) then - if not out[category] then - out[category] = {settings[i]} - else - table.insert(out[category], settings[i]) + for j = 1, #words do + local passed = true + if not (settings[i].readable_name:lower():find(words[j], 1, true) + or settings[i].name:find(words[j], 1, true)) then + passed = false + end + + if passed then + if not out[category] then + out[category] = {settings[i]} + else + table.insert(out[category], settings[i]) + end end end end