aboutsummaryrefslogtreecommitdiff
path: root/builtin/mainmenu
diff options
context:
space:
mode:
Diffstat (limited to 'builtin/mainmenu')
-rw-r--r--builtin/mainmenu/async_event.lua32
-rw-r--r--builtin/mainmenu/dlg_config_world.lua95
-rw-r--r--builtin/mainmenu/dlg_contentstore.lua313
-rw-r--r--builtin/mainmenu/dlg_create_world.lua341
-rw-r--r--builtin/mainmenu/init.lua4
-rw-r--r--builtin/mainmenu/tab_credits.lua11
-rw-r--r--builtin/mainmenu/tab_local.lua65
7 files changed, 578 insertions, 283 deletions
diff --git a/builtin/mainmenu/async_event.lua b/builtin/mainmenu/async_event.lua
new file mode 100644
index 000000000..04bfb78d6
--- /dev/null
+++ b/builtin/mainmenu/async_event.lua
@@ -0,0 +1,32 @@
+
+core.async_jobs = {}
+
+local function handle_job(jobid, serialized_retval)
+ local retval = core.deserialize(serialized_retval)
+ assert(type(core.async_jobs[jobid]) == "function")
+ core.async_jobs[jobid](retval)
+ core.async_jobs[jobid] = nil
+end
+
+core.async_event_handler = handle_job
+
+function core.handle_async(func, parameter, callback)
+ -- Serialize function
+ local serialized_func = string.dump(func)
+
+ assert(serialized_func ~= nil)
+
+ -- Serialize parameters
+ local serialized_param = core.serialize(parameter)
+
+ if serialized_param == nil then
+ return false
+ end
+
+ local jobid = core.do_async_callback(serialized_func, serialized_param)
+
+ core.async_jobs[jobid] = callback
+
+ return true
+end
+
diff --git a/builtin/mainmenu/dlg_config_world.lua b/builtin/mainmenu/dlg_config_world.lua
index 97218df9c..2cf70c9c9 100644
--- a/builtin/mainmenu/dlg_config_world.lua
+++ b/builtin/mainmenu/dlg_config_world.lua
@@ -23,7 +23,49 @@ local function modname_valid(name)
return not name:find("[^a-z0-9_]")
end
+local function init_data(data)
+ data.list = filterlist.create(
+ pkgmgr.preparemodlist,
+ pkgmgr.comparemod,
+ function(element, uid)
+ if element.name == uid then
+ return true
+ end
+ end,
+ function(element, criteria)
+ if criteria.hide_game and
+ element.is_game_content then
+ return false
+ end
+
+ if criteria.hide_modpackcontents and
+ element.modpack ~= nil then
+ return false
+ end
+ return true
+ end,
+ {
+ worldpath = data.worldspec.path,
+ gameid = data.worldspec.gameid
+ })
+
+ if data.selected_mod > data.list:size() then
+ data.selected_mod = 0
+ end
+
+ data.list:set_filtercriteria({
+ hide_game = data.hide_gamemods,
+ hide_modpackcontents = data.hide_modpackcontents
+ })
+ data.list:add_sort_mechanism("alphabetic", sort_mod_list)
+ data.list:set_sortmode("alphabetic")
+end
+
local function get_formspec(data)
+ if not data.list then
+ init_data(data)
+ end
+
local mod = data.list:get_list()[data.selected_mod] or {name = ""}
local retval =
@@ -85,11 +127,14 @@ local function get_formspec(data)
end
end
end
+
retval = retval ..
"button[3.25,7;2.5,0.5;btn_config_world_save;" ..
fgettext("Save") .. "]" ..
"button[5.75,7;2.5,0.5;btn_config_world_cancel;" ..
- fgettext("Cancel") .. "]"
+ fgettext("Cancel") .. "]" ..
+ "button[9,7;2.5,0.5;btn_config_world_cdb;" ..
+ fgettext("Find More Mods") .. "]"
if mod.name ~= "" and not mod.is_game_content then
if mod.is_modpack then
@@ -198,6 +243,16 @@ local function handle_buttons(this, fields)
return true
end
+ if fields.btn_config_world_cdb then
+ this.data.list = nil
+
+ local dlg = create_store_dlg("mod")
+ dlg:set_parent(this)
+ this:hide()
+ dlg:show()
+ return true
+ end
+
if fields.btn_enable_all_mods then
local list = this.data.list:get_raw_list()
@@ -247,43 +302,5 @@ function create_configure_world_dlg(worldidx)
return
end
- dlg.data.list = filterlist.create(
- pkgmgr.preparemodlist,
- pkgmgr.comparemod,
- function(element, uid)
- if element.name == uid then
- return true
- end
- end,
- function(element, criteria)
- if criteria.hide_game and
- element.is_game_content then
- return false
- end
-
- if criteria.hide_modpackcontents and
- element.modpack ~= nil then
- return false
- end
- return true
- end,
- {
- worldpath = dlg.data.worldspec.path,
- gameid = dlg.data.worldspec.gameid
- }
- )
-
-
- if dlg.data.selected_mod > dlg.data.list:size() then
- dlg.data.selected_mod = 0
- end
-
- dlg.data.list:set_filtercriteria({
- hide_game = dlg.data.hide_gamemods,
- hide_modpackcontents = dlg.data.hide_modpackcontents
- })
- dlg.data.list:add_sort_mechanism("alphabetic", sort_mod_list)
- dlg.data.list:set_sortmode("alphabetic")
-
return dlg
end
diff --git a/builtin/mainmenu/dlg_contentstore.lua b/builtin/mainmenu/dlg_contentstore.lua
index 3bc5f60bb..01c42be0b 100644
--- a/builtin/mainmenu/dlg_contentstore.lua
+++ b/builtin/mainmenu/dlg_contentstore.lua
@@ -1,5 +1,5 @@
--Minetest
---Copyright (C) 2018 rubenwardy
+--Copyright (C) 2018-20 rubenwardy
--
--This program is free software; you can redistribute it and/or modify
--it under the terms of the GNU Lesser General Public License as published by
@@ -15,8 +15,17 @@
--with this program; if not, write to the Free Software Foundation, Inc.,
--51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+if not minetest.get_http_api then
+ function create_store_dlg()
+ return messagebox("store",
+ fgettext("ContentDB is not available when Minetest was compiled without cURL"))
+ end
+ return
+end
+
local store = { packages = {}, packages_full = {} }
-local package_dialog = {}
+
+local http = minetest.get_http_api()
-- Screenshot
local screenshot_dir = core.get_cache_path() .. DIR_DELIM .. "cdb"
@@ -44,19 +53,15 @@ local filter_types_type = {
}
-
-
local function download_package(param)
if core.download_file(param.package.url, param.filename) then
return {
- package = param.package,
filename = param.filename,
successful = true,
}
else
core.log("error", "downloading " .. dump(param.package.url) .. " failed")
return {
- package = param.package,
successful = false,
}
end
@@ -70,9 +75,9 @@ local function start_install(calling_dialog, package)
local function callback(result)
if result.successful then
- local path, msg = pkgmgr.install(result.package.type,
- result.filename, result.package.name,
- result.package.path)
+ local path, msg = pkgmgr.install(package.type,
+ result.filename, package.name,
+ package.path)
if not path then
gamedata.errormessage = msg
else
@@ -80,33 +85,33 @@ local function start_install(calling_dialog, package)
local conf_path
local name_is_title = false
- if result.package.type == "mod" then
+ if package.type == "mod" then
local actual_type = pkgmgr.get_folder_type(path)
if actual_type.type == "modpack" then
conf_path = path .. DIR_DELIM .. "modpack.conf"
else
conf_path = path .. DIR_DELIM .. "mod.conf"
end
- elseif result.package.type == "game" then
+ elseif package.type == "game" then
conf_path = path .. DIR_DELIM .. "game.conf"
name_is_title = true
- elseif result.package.type == "txp" then
+ elseif package.type == "txp" then
conf_path = path .. DIR_DELIM .. "texture_pack.conf"
end
if conf_path then
local conf = Settings(conf_path)
if name_is_title then
- conf:set("name", result.package.title)
+ conf:set("name", package.title)
else
- conf:set("title", result.package.title)
- conf:set("name", result.package.name)
+ conf:set("title", package.title)
+ conf:set("name", package.name)
end
if not conf:get("description") then
- conf:set("description", result.package.short_description)
+ conf:set("description", package.short_description)
end
- conf:set("author", result.package.author)
- conf:set("release", result.package.release)
+ conf:set("author", package.author)
+ conf:set("release", package.release)
conf:write()
end
end
@@ -115,37 +120,22 @@ local function start_install(calling_dialog, package)
gamedata.errormessage = fgettext("Failed to download $1", package.name)
end
- if gamedata.errormessage == nil then
- core.button_handler({btn_hidden_close_download=result})
- else
- core.button_handler({btn_hidden_close_download={successful=false}})
- end
+ package.downloading = false
+ ui.update()
end
+ package.downloading = true
+
if not core.handle_async(download_package, params, callback) then
core.log("error", "ERROR: async event failed")
gamedata.errormessage = fgettext("Failed to download $1", package.name)
+ return
end
+end
- local new_dlg = dialog_create("store_downloading",
- function(data)
- return "size[7,2]label[0.25,0.75;" ..
- fgettext("Downloading and installing $1, please wait...", data.title) .. "]"
- end,
- function(this,fields)
- if fields["btn_hidden_close_download"] ~= nil then
- this:delete()
- return true
- end
-
- return false
- end,
- nil)
-
- new_dlg:set_parent(calling_dialog)
- new_dlg.data.title = package.title
- calling_dialog:hide()
- new_dlg:show()
+local function get_file_extension(path)
+ local parts = path:split(".")
+ return parts[#parts]
end
local function get_screenshot(package)
@@ -156,8 +146,9 @@ local function get_screenshot(package)
end
-- Get tmp screenshot path
+ local ext = get_file_extension(package.thumbnail)
local filepath = screenshot_dir .. DIR_DELIM ..
- package.type .. "-" .. package.author .. "-" .. package.name .. ".png"
+ ("%s-%s-%s.%s"):format(package.type, package.author, package.name, ext)
-- Return if already downloaded
local file = io.open(filepath, "r")
@@ -195,84 +186,12 @@ local function get_screenshot(package)
return defaulttexturedir .. "loading_screenshot.png"
end
-
-
-function package_dialog.get_formspec()
- local package = package_dialog.package
-
- store.update_paths()
-
- local formspec = {
- "size[9,4;true]",
- "image[0,1;4.5,3;", core.formspec_escape(get_screenshot(package)), ']',
- "label[3.8,1;",
- minetest.colorize(mt_color_green, core.formspec_escape(package.title)), "\n",
- minetest.colorize('#BFBFBF', "by " .. core.formspec_escape(package.author)), "]",
- "textarea[4,2;5.3,2;;;", core.formspec_escape(package.short_description), "]",
- "button[0,0;2,1;back;", fgettext("Back"), "]",
- }
-
- if not package.path then
- formspec[#formspec + 1] = "button[7,0;2,1;install;"
- formspec[#formspec + 1] = fgettext("Install")
- formspec[#formspec + 1] = "]"
- elseif package.installed_release < package.release then
- -- The install_ action also handles updating
- formspec[#formspec + 1] = "button[7,0;2,1;install;"
- formspec[#formspec + 1] = fgettext("Update")
- formspec[#formspec + 1] = "]"
- formspec[#formspec + 1] = "button[5,0;2,1;uninstall;"
- formspec[#formspec + 1] = fgettext("Uninstall")
- formspec[#formspec + 1] = "]"
- else
- formspec[#formspec + 1] = "button[7,0;2,1;uninstall;"
- formspec[#formspec + 1] = fgettext("Uninstall")
- formspec[#formspec + 1] = "]"
- end
-
- return table.concat(formspec, "")
-end
-
-function package_dialog.handle_submit(this, fields)
- if fields.back then
- this:delete()
- return true
- end
-
- if fields.install then
- start_install(this, package_dialog.package)
- return true
- end
-
- if fields.uninstall then
- local dlg_delmod = create_delete_content_dlg(package_dialog.package)
- dlg_delmod:set_parent(this)
- this:hide()
- dlg_delmod:show()
- return true
- end
-
- return false
-end
-
-function package_dialog.create(package)
- package_dialog.package = package
- return dialog_create("package_view",
- package_dialog.get_formspec,
- package_dialog.handle_submit,
- nil)
-end
-
function store.load()
- local tmpdir = os.tempfolder()
- local target = tmpdir .. DIR_DELIM .. "packages.json"
-
- assert(core.create_dir(tmpdir))
-
- local base_url = core.settings:get("contentdb_url")
+ local version = core.get_version()
+ local base_url = core.settings:get("contentdb_url")
local url = base_url ..
"/api/packages/?type=mod&type=game&type=txp&protocol_version=" ..
- core.get_max_supp_proto()
+ core.get_max_supp_proto() .. "&engine_version=" .. version.string
for _, item in pairs(core.settings:get("contentdb_flag_blacklist"):split(",")) do
item = item:trim()
@@ -281,31 +200,29 @@ function store.load()
end
end
- core.download_file(url, target)
+ local timeout = tonumber(minetest.settings:get("curl_file_download_timeout"))
+ local response = http.fetch_sync({ url = url, timeout = timeout })
+ if not response.succeeded then
+ return
+ end
- local file = io.open(target, "r")
- if file then
- store.packages_full = core.parse_json(file:read("*all")) or {}
- file:close()
+ store.packages_full = core.parse_json(response.data) or {}
- for _, package in pairs(store.packages_full) do
- package.url = base_url .. "/packages/" ..
+ for _, package in pairs(store.packages_full) do
+ package.url = base_url .. "/packages/" ..
package.author .. "/" .. package.name ..
"/releases/" .. package.release .. "/download/"
- local name_len = #package.name
- if package.type == "game" and name_len > 5 and package.name:sub(name_len - 4) == "_game" then
- package.id = package.author:lower() .. "/" .. package.name:sub(1, name_len - 5)
- else
- package.id = package.author:lower() .. "/" .. package.name
- end
+ local name_len = #package.name
+ if package.type == "game" and name_len > 5 and package.name:sub(name_len - 4) == "_game" then
+ package.id = package.author:lower() .. "/" .. package.name:sub(1, name_len - 5)
+ else
+ package.id = package.author:lower() .. "/" .. package.name
end
-
- store.packages = store.packages_full
- store.loaded = true
end
- core.delete_dir(tmpdir)
+ store.packages = store.packages_full
+ store.loaded = true
end
function store.update_paths()
@@ -395,34 +312,35 @@ function store.get_formspec(dlgdata)
cur_page = 1
end
+ local W = 15.75
+ local H = 9.5
+
local formspec
if #store.packages_full > 0 then
formspec = {
- "size[12,7;true]",
+ "formspec_version[3]",
+ "size[15.75,9.5]",
"position[0.5,0.55]",
- "field[0.2,0.1;7.8,1;search_string;;",
- core.formspec_escape(search_string), "]",
+ "container[0.375,0.375]",
+ "field[0,0;10.225,0.8;search_string;;", core.formspec_escape(search_string), "]",
"field_close_on_enter[search_string;false]",
- "button[7.7,-0.2;2,1;search;",
- fgettext("Search"), "]",
- "dropdown[9.7,-0.1;2.4;type;",
- table.concat(filter_types_titles, ","),
- ";", filter_type, "]",
- -- "textlist[0,1;2.4,5.6;a;",
- -- table.concat(taglist, ","), "]",
+ "button[10.225,0;2,0.8;search;", fgettext("Search"), "]",
+ "dropdown[12.6,0;2.4,0.8;type;", table.concat(filter_types_titles, ","), ";", filter_type, "]",
+ "container_end[]",
-- Page nav buttons
- "container[0,",
- num_per_page + 1.5, "]",
- "button[-0.1,0;3,1;back;",
- fgettext("Back to Main Menu"), "]",
- "button[7.1,0;1,1;pstart;<<]",
- "button[8.1,0;1,1;pback;<]",
- "label[9.2,0.2;",
- tonumber(cur_page), " / ",
- tonumber(dlgdata.pagemax), "]",
- "button[10.1,0;1,1;pnext;>]",
- "button[11.1,0;1,1;pend;>>]",
+ "container[0,", H - 0.8 - 0.375, "]",
+ "button[0.375,0;4,0.8;back;", fgettext("Back to Main Menu"), "]",
+
+ "container[", W - 0.375 - 0.8*4 - 2, ",0]",
+ "image_button[0,0;0.8,0.8;", core.formspec_escape(defaulttexturedir), "start_icon.png;pstart;]",
+ "image_button[0.8,0;0.8,0.8;", core.formspec_escape(defaulttexturedir), "prev_icon.png;pback;]",
+ "style[pagenum;border=false]",
+ "button[1.6,0;2,0.8;pagenum;", tonumber(cur_page), " / ", tonumber(dlgdata.pagemax), "]",
+ "image_button[3.6,0;0.8,0.8;", core.formspec_escape(defaulttexturedir), "next_icon.png;pnext;]",
+ "image_button[4.4,0;0.8,0.8;", core.formspec_escape(defaulttexturedir), "end_icon.png;pend;]",
+ "container_end[]",
+
"container_end[]",
}
@@ -433,73 +351,84 @@ function store.get_formspec(dlgdata)
end
else
formspec = {
- "size[12,7;true]",
+ "size[12,7]",
"position[0.5,0.55]",
"label[4,3;", fgettext("No packages could be retrieved"), "]",
- "button[-0.1,",
- num_per_page + 1.5,
- ";3,1;back;",
- fgettext("Back to Main Menu"), "]",
+ "container[0,", H - 0.8 - 0.375, "]",
+ "button[0,0;4,0.8;back;", fgettext("Back to Main Menu"), "]",
+ "container_end[]",
}
end
local start_idx = (cur_page - 1) * num_per_page + 1
for i=start_idx, math.min(#store.packages, start_idx+num_per_page-1) do
local package = store.packages[i]
- formspec[#formspec + 1] = "container[0.5,"
- formspec[#formspec + 1] = (i - start_idx) * 1.1 + 1
+ formspec[#formspec + 1] = "container[0.375,"
+ formspec[#formspec + 1] = (i - start_idx) * 1.375 + (2*0.375 + 0.8)
formspec[#formspec + 1] = "]"
-- image
- formspec[#formspec + 1] = "image[-0.4,0;1.5,1;"
+ formspec[#formspec + 1] = "image[0,0;1.5,1;"
formspec[#formspec + 1] = core.formspec_escape(get_screenshot(package))
formspec[#formspec + 1] = "]"
-- title
- formspec[#formspec + 1] = "label[1,-0.1;"
+ formspec[#formspec + 1] = "label[1.875,0.1;"
formspec[#formspec + 1] = core.formspec_escape(
minetest.colorize(mt_color_green, package.title) ..
minetest.colorize("#BFBFBF", " by " .. package.author))
formspec[#formspec + 1] = "]"
- -- description
- if package.path and package.installed_release < package.release then
- formspec[#formspec + 1] = "textarea[1.25,0.3;7.5,1;;;"
- else
- formspec[#formspec + 1] = "textarea[1.25,0.3;9,1;;;"
- end
- formspec[#formspec + 1] = core.formspec_escape(package.short_description)
- formspec[#formspec + 1] = "]"
-
-- buttons
- if not package.path then
- formspec[#formspec + 1] = "button[9.9,0;1.5,1;install_"
+ local description_width = W - 0.375*5 - 1 - 2*1.5
+ formspec[#formspec + 1] = "container["
+ formspec[#formspec + 1] = W - 0.375*2
+ formspec[#formspec + 1] = ",0.1]"
+
+ if package.downloading then
+ formspec[#formspec + 1] = "style[download;border=false]"
+
+ formspec[#formspec + 1] = "button[-3.5,0;2,0.8;download;"
+ formspec[#formspec + 1] = fgettext("Downloading...")
+ formspec[#formspec + 1] = "]"
+ elseif not package.path then
+ formspec[#formspec + 1] = "button[-3,0;1.5,0.8;install_"
formspec[#formspec + 1] = tostring(i)
formspec[#formspec + 1] = ";"
formspec[#formspec + 1] = fgettext("Install")
formspec[#formspec + 1] = "]"
else
if package.installed_release < package.release then
+ description_width = description_width - 1.5
+
-- The install_ action also handles updating
- formspec[#formspec + 1] = "button[8.4,0;1.5,1;install_"
+ formspec[#formspec + 1] = "button[-4.5,0;1.5,0.8;install_"
formspec[#formspec + 1] = tostring(i)
formspec[#formspec + 1] = ";"
formspec[#formspec + 1] = fgettext("Update")
formspec[#formspec + 1] = "]"
end
- formspec[#formspec + 1] = "button[9.9,0;1.5,1;uninstall_"
+ formspec[#formspec + 1] = "button[-3,0;1.5,0.8;uninstall_"
formspec[#formspec + 1] = tostring(i)
formspec[#formspec + 1] = ";"
formspec[#formspec + 1] = fgettext("Uninstall")
formspec[#formspec + 1] = "]"
end
- --formspec[#formspec + 1] = "button[9.9,0;1.5,1;view_"
- --formspec[#formspec + 1] = tostring(i)
- --formspec[#formspec + 1] = ";"
- --formspec[#formspec + 1] = fgettext("View")
- --formspec[#formspec + 1] = "]"
+ formspec[#formspec + 1] = "button[-1.5,0;1.5,0.8;view_"
+ formspec[#formspec + 1] = tostring(i)
+ formspec[#formspec + 1] = ";"
+ formspec[#formspec + 1] = fgettext("View")
+ formspec[#formspec + 1] = "]"
+ formspec[#formspec + 1] = "container_end[]"
+
+ -- description
+ formspec[#formspec + 1] = "textarea[1.855,0.3;"
+ formspec[#formspec + 1] = tostring(description_width)
+ formspec[#formspec + 1] = ",0.8;;;"
+ formspec[#formspec + 1] = core.formspec_escape(package.short_description)
+ formspec[#formspec + 1] = "]"
formspec[#formspec + 1] = "container_end[]"
end
@@ -576,10 +505,9 @@ function store.handle_submit(this, fields)
end
if fields["view_" .. i] then
- local dlg = package_dialog.create(package)
- dlg:set_parent(this)
- this:hide()
- dlg:show()
+ local url = ("%s/packages/%s?protocol_version=%d"):format(
+ core.settings:get("contentdb_url"), package.id, core.get_max_supp_proto())
+ core.open_url(url)
return true
end
end
@@ -594,6 +522,17 @@ function create_store_dlg(type)
search_string = ""
cur_page = 1
+
+ if type then
+ -- table.indexof does not work on tables that contain `nil`
+ for i, v in pairs(filter_types_type) do
+ if v == type then
+ filter_type = i
+ break
+ end
+ end
+ end
+
store.filter_packages(search_string)
return dialog_create("store",
diff --git a/builtin/mainmenu/dlg_create_world.lua b/builtin/mainmenu/dlg_create_world.lua
index 31d41d693..36df23cce 100644
--- a/builtin/mainmenu/dlg_create_world.lua
+++ b/builtin/mainmenu/dlg_create_world.lua
@@ -17,13 +17,110 @@
local worldname = ""
+local function table_to_flags(ftable)
+ -- Convert e.g. { jungles = true, caves = false } to "jungles,nocaves"
+ local str = {}
+ for flag, is_set in pairs(ftable) do
+ str[#str + 1] = is_set and flag or ("no" .. flag)
+ end
+ return table.concat(str, ",")
+end
+
+-- Same as check_flag but returns a string
+local function strflag(flags, flag)
+ return (flags[flag] == true) and "true" or "false"
+end
+
+local cb_caverns = { "caverns", fgettext("Caverns"), "caverns",
+ fgettext("Very large caverns deep in the underground") }
+local tt_sea_rivers = fgettext("Sea level rivers")
+
+local flag_checkboxes = {
+ v5 = {
+ cb_caverns,
+ },
+ v7 = {
+ cb_caverns,
+ { "ridges", fgettext("Rivers"), "ridges", tt_sea_rivers },
+ { "mountains", fgettext("Mountains"), "mountains" },
+ { "floatlands", fgettext("Floatlands (experimental)"), "floatlands",
+ fgettext("Floating landmasses in the sky") },
+ },
+ carpathian = {
+ cb_caverns,
+ { "rivers", fgettext("Rivers"), "rivers", tt_sea_rivers },
+ },
+ valleys = {
+ { "altitude-chill", fgettext("Altitude chill"), "altitude_chill",
+ fgettext("Reduces heat with altitude") },
+ { "altitude-dry", fgettext("Altitude dry"), "altitude_dry",
+ fgettext("Reduces humidity with altitude") },
+ { "humid-rivers", fgettext("Humid rivers"), "humid_rivers",
+ fgettext("Increases humidity around rivers") },
+ { "vary-river-depth", fgettext("Vary river depth"), "vary_river_depth",
+ fgettext("Low humidity and high heat causes shallow or dry rivers") },
+ },
+ flat = {
+ { "hills", fgettext("Hills"), "hills" },
+ { "lakes", fgettext("Lakes"), "lakes" },
+ },
+ fractal = {
+ { "terrain", fgettext("Additional terrain"), "terrain",
+ fgettext("Generate non-fractal terrain: Oceans and underground") },
+ },
+ v6 = {
+ { "trees", fgettext("Trees and jungle grass"), "trees" },
+ { "flat", fgettext("Flat terrain"), "flat" },
+ { "mudflow", fgettext("Mud flow"), "mudflow",
+ fgettext("Terrain surface erosion") },
+ -- Biome settings are in mgv6_biomes below
+ },
+}
+
+local mgv6_biomes = {
+ {
+ fgettext("Temperate, Desert, Jungle, Tundra, Taiga"),
+ {jungles = true, snowbiomes = true}
+ },
+ {
+ fgettext("Temperate, Desert, Jungle"),
+ {jungles = true, snowbiomes = false}
+ },
+ {
+ fgettext("Temperate, Desert"),
+ {jungles = false, snowbiomes = false}
+ },
+}
+
local function create_world_formspec(dialogdata)
+
+ -- Error out when no games found
+ if #pkgmgr.games == 0 then
+ return "size[12.25,3,true]" ..
+ "box[0,0;12,2;#ff8800]" ..
+ "textarea[0.3,0;11.7,2;;;"..
+ fgettext("You have no games installed.") .. "\n" ..
+ fgettext("Download one from minetest.net") .. "]" ..
+ "button[4.75,2.5;3,0.5;world_create_cancel;" .. fgettext("Cancel") .. "]"
+ end
+
local mapgens = core.get_mapgen_names()
local current_seed = core.settings:get("fixed_map_seed") or ""
local current_mg = core.settings:get("mg_name")
local gameid = core.settings:get("menu_last_game")
+ local flags = {
+ main = core.settings:get_flags("mg_flags"),
+ v5 = core.settings:get_flags("mgv5_spflags"),
+ v6 = core.settings:get_flags("mgv6_spflags"),
+ v7 = core.settings:get_flags("mgv7_spflags"),
+ fractal = core.settings:get_flags("mgfractal_spflags"),
+ carpathian = core.settings:get_flags("mgcarpathian_spflags"),
+ valleys = core.settings:get_flags("mgvalleys_spflags"),
+ flat = core.settings:get_flags("mgflat_spflags"),
+ }
+
local gameidx = 0
if gameid ~= nil then
local _
@@ -35,15 +132,29 @@ local function create_world_formspec(dialogdata)
end
local game_by_gameidx = core.get_game(gameidx)
+ local disallowed_mapgen_settings = {}
if game_by_gameidx ~= nil then
local gamepath = game_by_gameidx.path
local gameconfig = Settings(gamepath.."/game.conf")
+ local allowed_mapgens = (gameconfig:get("allowed_mapgens") or ""):split()
+ for key, value in pairs(allowed_mapgens) do
+ allowed_mapgens[key] = value:trim()
+ end
+
local disallowed_mapgens = (gameconfig:get("disallowed_mapgens") or ""):split()
for key, value in pairs(disallowed_mapgens) do
disallowed_mapgens[key] = value:trim()
end
+ if #allowed_mapgens > 0 then
+ for i = #mapgens, 1, -1 do
+ if table.indexof(allowed_mapgens, mapgens[i]) == -1 then
+ table.remove(mapgens, i)
+ end
+ end
+ end
+
if disallowed_mapgens then
for i = #mapgens, 1, -1 do
if table.indexof(disallowed_mapgens, mapgens[i]) > 0 then
@@ -51,49 +162,193 @@ local function create_world_formspec(dialogdata)
end
end
end
+
+ local ds = (gameconfig:get("disallowed_mapgen_settings") or ""):split()
+ for _, value in pairs(ds) do
+ disallowed_mapgen_settings[value:trim()] = true
+ end
end
local mglist = ""
- local selindex = 1
+ local selindex
local i = 1
+ local first_mg
for k,v in pairs(mapgens) do
+ if not first_mg then
+ first_mg = v
+ end
if current_mg == v then
selindex = i
end
i = i + 1
mglist = mglist .. v .. ","
end
+ if not selindex then
+ selindex = 1
+ current_mg = first_mg
+ end
mglist = mglist:sub(1, -2)
- current_seed = core.formspec_escape(current_seed)
- local retval =
- "size[11.5,6.5,true]" ..
- "label[2,0;" .. fgettext("World name") .. "]"..
- "field[4.5,0.4;6,0.5;te_world_name;;" .. minetest.formspec_escape(worldname) .. "]" ..
+ local mg_main_flags = function(mapgen, y)
+ if mapgen == "singlenode" then
+ return "", y
+ end
+ if disallowed_mapgen_settings["mg_flags"] then
+ return "", y
+ end
- "label[2,1;" .. fgettext("Seed") .. "]"..
- "field[4.5,1.4;6,0.5;te_seed;;".. current_seed .. "]" ..
+ local form = "checkbox[0," .. y .. ";flag_mg_caves;" ..
+ fgettext("Caves") .. ";"..strflag(flags.main, "caves").."]"
+ y = y + 0.5
- "label[2,2;" .. fgettext("Mapgen") .. "]"..
- "dropdown[4.2,2;6.3;dd_mapgen;" .. mglist .. ";" .. selindex .. "]" ..
+ form = form .. "checkbox[0,"..y..";flag_mg_dungeons;" ..
+ fgettext("Dungeons") .. ";"..strflag(flags.main, "dungeons").."]"
+ y = y + 0.5
- "label[2,3;" .. fgettext("Game") .. "]"..
- "textlist[4.2,3;5.8,2.3;games;" .. pkgmgr.gamelist() ..
- ";" .. gameidx .. ";true]" ..
+ local d_name = fgettext("Decorations")
+ local d_tt
+ if mapgen == "v6" then
+ d_tt = fgettext("Structures appearing on the terrain (no effect on trees and jungle grass created by v6)")
+ else
+ d_tt = fgettext("Structures appearing on the terrain, typically trees and plants")
+ end
+ form = form .. "checkbox[0,"..y..";flag_mg_decorations;" ..
+ d_name .. ";" ..
+ strflag(flags.main, "decorations").."]" ..
+ "tooltip[flag_mg_decorations;" ..
+ d_tt ..
+ "]"
+ y = y + 0.5
- "button[3.25,6;2.5,0.5;world_create_confirm;" .. fgettext("Create") .. "]" ..
- "button[5.75,6;2.5,0.5;world_create_cancel;" .. fgettext("Cancel") .. "]"
+ form = form .. "tooltip[flag_mg_caves;" ..
+ fgettext("Network of tunnels and caves")
+ .. "]"
+ return form, y
+ end
- if #pkgmgr.games == 0 then
- retval = retval .. "box[2,4;8,1;#ff8800]label[2.25,4;" ..
- fgettext("You have no games installed.") .. "]label[2.25,4.4;" ..
- fgettext("Download one from minetest.net") .. "]"
- elseif #pkgmgr.games == 1 and pkgmgr.games[1].id == "minimal" then
- retval = retval .. "box[1.75,4;8.7,1;#ff8800]label[2,4;" ..
- fgettext("Warning: The minimal development test is meant for developers.") .. "]label[2,4.4;" ..
+ local mg_specific_flags = function(mapgen, y)
+ if not flag_checkboxes[mapgen] then
+ return "", y
+ end
+ if disallowed_mapgen_settings["mg"..mapgen.."_spflags"] then
+ return "", y
+ end
+ local form = ""
+ for _,tab in pairs(flag_checkboxes[mapgen]) do
+ local id = "flag_mg"..mapgen.."_"..tab[1]
+ form = form .. ("checkbox[0,%f;%s;%s;%s]"):
+ format(y, id, tab[2], strflag(flags[mapgen], tab[3]))
+
+ if tab[4] then
+ form = form .. "tooltip["..id..";"..tab[4].."]"
+ end
+ y = y + 0.5
+ end
+
+ if mapgen ~= "v6" then
+ -- No special treatment
+ return form, y
+ end
+ -- Special treatment for v6 (add biome widgets)
+
+ -- Biome type (jungles, snowbiomes)
+ local biometype
+ if flags.v6.snowbiomes == true then
+ biometype = 1
+ elseif flags.v6.jungles == true then
+ biometype = 2
+ else
+ biometype = 3
+ end
+ y = y + 0.3
+
+ form = form .. "label[0,"..(y+0.1)..";" .. fgettext("Biomes") .. "]"
+ y = y + 0.6
+
+ form = form .. "dropdown[0,"..y..";6.3;mgv6_biomes;"
+ for b=1, #mgv6_biomes do
+ form = form .. mgv6_biomes[b][1]
+ if b < #mgv6_biomes then
+ form = form .. ","
+ end
+ end
+ form = form .. ";" .. biometype.. "]"
+
+ -- biomeblend
+ y = y + 0.55
+ form = form .. "checkbox[0,"..y..";flag_mgv6_biomeblend;" ..
+ fgettext("Biome blending") .. ";"..strflag(flags.v6, "biomeblend").."]" ..
+ "tooltip[flag_mgv6_biomeblend;" ..
+ fgettext("Smooth transition between biomes") .. "]"
+
+ return form, y
+ end
+
+ current_seed = core.formspec_escape(current_seed)
+
+ local y_start = 0.0
+ local y = y_start
+ local str_flags, str_spflags
+ local label_flags, label_spflags = "", ""
+ y = y + 0.3
+ str_flags, y = mg_main_flags(current_mg, y)
+ if str_flags ~= "" then
+ label_flags = "label[0,"..y_start..";" .. fgettext("Mapgen flags") .. "]"
+ y_start = y + 0.4
+ else
+ y_start = 0.0
+ end
+ y = y_start + 0.3
+ str_spflags = mg_specific_flags(current_mg, y)
+ if str_spflags ~= "" then
+ label_spflags = "label[0,"..y_start..";" .. fgettext("Mapgen-specific flags") .. "]"
+ end
+
+ -- Warning if only devtest is installed
+ local devtest_only = ""
+ local gamelist_height = 2.3
+ if #pkgmgr.games == 1 and pkgmgr.games[1].id == "devtest" then
+ devtest_only = "box[0,0;5.8,1.7;#ff8800]" ..
+ "textarea[0.3,0;6,1.8;;;"..
+ fgettext("Warning: The Development Test is meant for developers.") .. "\n" ..
fgettext("Download a game, such as Minetest Game, from minetest.net") .. "]"
+ gamelist_height = 0.5
end
+ local retval =
+ "size[12.25,7,true]" ..
+
+ -- Left side
+ "container[0,0]"..
+ "field[0.3,0.6;6,0.5;te_world_name;" ..
+ fgettext("World name") ..
+ ";" .. core.formspec_escape(worldname) .. "]" ..
+
+ "field[0.3,1.7;6,0.5;te_seed;" ..
+ fgettext("Seed") ..
+ ";".. current_seed .. "]" ..
+
+ "label[0,2;" .. fgettext("Mapgen") .. "]"..
+ "dropdown[0,2.5;6.3;dd_mapgen;" .. mglist .. ";" .. selindex .. "]" ..
+
+ "label[0,3.35;" .. fgettext("Game") .. "]"..
+ "textlist[0,3.85;5.8,"..gamelist_height..";games;" ..
+ pkgmgr.gamelist() .. ";" .. gameidx .. ";false]" ..
+ "container[0,4.5]" ..
+ devtest_only ..
+ "container_end[]" ..
+ "container_end[]" ..
+
+ -- Right side
+ "container[6.2,0]"..
+ label_flags .. str_flags ..
+ label_spflags .. str_spflags ..
+ "container_end[]"..
+
+ -- Menu buttons
+ "button[3.25,6.5;3,0.5;world_create_confirm;" .. fgettext("Create") .. "]" ..
+ "button[6.25,6.5;3,0.5;world_create_cancel;" .. fgettext("Cancel") .. "]"
+
return retval
end
@@ -150,11 +405,53 @@ local function create_world_buttonhandler(this, fields)
return true
end
+ for k,v in pairs(fields) do
+ local split = string.split(k, "_", nil, 3)
+ if split and split[1] == "flag" then
+ local setting
+ if split[2] == "mg" then
+ setting = "mg_flags"
+ else
+ setting = split[2].."_spflags"
+ end
+ -- We replaced the underscore of flag names with a dash.
+ local flag = string.gsub(split[3], "-", "_")
+ local ftable = core.settings:get_flags(setting)
+ if v == "true" then
+ ftable[flag] = true
+ else
+ ftable[flag] = false
+ end
+ local flags = table_to_flags(ftable)
+ core.settings:set(setting, flags)
+ return true
+ end
+ end
+
if fields["world_create_cancel"] then
this:delete()
return true
end
+ if fields["mgv6_biomes"] then
+ local entry = minetest.formspec_escape(fields["mgv6_biomes"])
+ for b=1, #mgv6_biomes do
+ if entry == mgv6_biomes[b][1] then
+ local ftable = core.settings:get_flags("mgv6_spflags")
+ ftable.jungles = mgv6_biomes[b][2].jungles
+ ftable.snowbiomes = mgv6_biomes[b][2].snowbiomes
+ local flags = table_to_flags(ftable)
+ core.settings:set("mgv6_spflags", flags)
+ return true
+ end
+ end
+ end
+
+ if fields["dd_mapgen"] then
+ core.settings:set("mg_name", fields["dd_mapgen"])
+ return true
+ end
+
return false
end
diff --git a/builtin/mainmenu/init.lua b/builtin/mainmenu/init.lua
index 130c3e73c..c17e79270 100644
--- a/builtin/mainmenu/init.lua
+++ b/builtin/mainmenu/init.lua
@@ -20,20 +20,18 @@ mt_color_blue = "#6389FF"
mt_color_green = "#72FF63"
mt_color_dark_green = "#25C191"
---for all other colors ask sfan5 to complete his work!
-
local menupath = core.get_mainmenu_path()
local basepath = core.get_builtin_path()
local menustyle = core.settings:get("main_menu_style")
defaulttexturedir = core.get_texturepath_share() .. DIR_DELIM .. "base" ..
DIR_DELIM .. "pack" .. DIR_DELIM
-dofile(basepath .. "common" .. DIR_DELIM .. "async_event.lua")
dofile(basepath .. "common" .. DIR_DELIM .. "filterlist.lua")
dofile(basepath .. "fstk" .. DIR_DELIM .. "buttonbar.lua")
dofile(basepath .. "fstk" .. DIR_DELIM .. "dialog.lua")
dofile(basepath .. "fstk" .. DIR_DELIM .. "tabview.lua")
dofile(basepath .. "fstk" .. DIR_DELIM .. "ui.lua")
+dofile(menupath .. DIR_DELIM .. "async_event.lua")
dofile(menupath .. DIR_DELIM .. "common.lua")
dofile(menupath .. DIR_DELIM .. "pkgmgr.lua")
dofile(menupath .. DIR_DELIM .. "textures.lua")
diff --git a/builtin/mainmenu/tab_credits.lua b/builtin/mainmenu/tab_credits.lua
index 962d2a3b4..c2b7e503a 100644
--- a/builtin/mainmenu/tab_credits.lua
+++ b/builtin/mainmenu/tab_credits.lua
@@ -101,8 +101,8 @@ return {
local logofile = defaulttexturedir .. "logo.png"
local version = core.get_version()
return "image[0.5,1;" .. core.formspec_escape(logofile) .. "]" ..
- "label[0.5,3.2;" .. version.project .. " " .. version.string .. "]" ..
- "label[0.5,3.5;http://minetest.net]" ..
+ "label[0.5,2.8;" .. version.project .. " " .. version.string .. "]" ..
+ "button[0.5,3;2,2;homepage;minetest.net]" ..
"tablecolumns[color;text]" ..
"tableoptions[background=#00000000;highlight=#00000000;border=false]" ..
"table[3.5,-0.25;8.5,6.05;list_credits;" ..
@@ -115,5 +115,10 @@ return {
"#FFFF00," .. fgettext("Previous Contributors") .. ",," ..
buildCreditList(previous_contributors) .. "," ..
";1]"
- end
+ end,
+ cbf_button_handler = function(this, fields, name, tabdata)
+ if fields.homepage then
+ core.open_url("https://www.minetest.net")
+ end
+ end,
}
diff --git a/builtin/mainmenu/tab_local.lua b/builtin/mainmenu/tab_local.lua
index 0969bccfb..a21cf12b1 100644
--- a/builtin/mainmenu/tab_local.lua
+++ b/builtin/mainmenu/tab_local.lua
@@ -35,6 +35,15 @@ if enable_gamebar then
end
local function game_buttonbar_button_handler(fields)
+ if fields.game_open_cdb then
+ local maintab = ui.find_by_name("maintab")
+ local dlg = create_store_dlg("game")
+ dlg:set_parent(maintab)
+ maintab:hide()
+ dlg:show()
+ return true
+ end
+
for key,value in pairs(fields) do
for j=1,#pkgmgr.games,1 do
if ("game_btnbar_" .. pkgmgr.games[j].id == key) then
@@ -87,6 +96,9 @@ if enable_gamebar then
end
btnbar:add_button(btn_name, text, image, tooltip)
end
+
+ local plus_image = core.formspec_escape(defaulttexturedir .. "plus.png")
+ btnbar:add_button("game_open_cdb", "", plus_image, fgettext("Install games from ContentDB"))
end
else
function current_game()
@@ -207,40 +219,35 @@ local function main_button_handler(this, fields, name, tabdata)
local selected = core.get_textlist_index("sp_worlds")
gamedata.selected_world = menudata.worldlist:get_raw_index(selected)
- if core.settings:get_bool("enable_server") then
- if selected ~= nil and gamedata.selected_world ~= 0 then
- gamedata.playername = fields["te_playername"]
- gamedata.password = fields["te_passwd"]
- gamedata.port = fields["te_serverport"]
- gamedata.address = ""
-
- core.settings:set("port",gamedata.port)
- if fields["te_serveraddr"] ~= nil then
- core.settings:set("bind_address",fields["te_serveraddr"])
- end
+ if selected == nil or gamedata.selected_world == 0 then
+ gamedata.errormessage =
+ fgettext("No world created or selected!")
+ return true
+ end
- --update last game
- local world = menudata.worldlist:get_raw_element(gamedata.selected_world)
- if world then
- local game = pkgmgr.find_by_gameid(world.gameid)
- core.settings:set("menu_last_game", game.id)
- end
+ -- Update last game
+ local world = menudata.worldlist:get_raw_element(gamedata.selected_world)
+ if world then
+ local game = pkgmgr.find_by_gameid(world.gameid)
+ core.settings:set("menu_last_game", game.id)
+ end
- core.start()
- else
- gamedata.errormessage =
- fgettext("No world created or selected!")
+ if core.settings:get_bool("enable_server") then
+ gamedata.playername = fields["te_playername"]
+ gamedata.password = fields["te_passwd"]
+ gamedata.port = fields["te_serverport"]
+ gamedata.address = ""
+
+ core.settings:set("port",gamedata.port)
+ if fields["te_serveraddr"] ~= nil then
+ core.settings:set("bind_address",fields["te_serveraddr"])
end
else
- if selected ~= nil and gamedata.selected_world ~= 0 then
- gamedata.singleplayer = true
- core.start()
- else
- gamedata.errormessage =
- fgettext("No world created or selected!")
- end
- return true
+ gamedata.singleplayer = true
end
+
+ core.start()
+ return true
end
if fields["world_create"] ~= nil then