Add mapgen settings to world creation dialog (#9254)
authorWuzzy <wuzzy2@mail.ru>
Tue, 12 May 2020 01:52:52 +0000 (03:52 +0200)
committerGitHub <noreply@github.com>
Tue, 12 May 2020 01:52:52 +0000 (02:52 +0100)
builtin/mainmenu/dlg_create_world.lua
doc/lua_api.txt

index f28ae69609a04b4e5021f6e494c9c0c7b07a93cc..0d977a17ca24896739a1699bf38c33fa07da21d9 100644 (file)
 
 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,6 +132,7 @@ 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")
@@ -64,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
+
+               form = form .. "tooltip[flag_mg_caves;" ..
+               fgettext("Network of tunnels and caves")
+               .. "]"
+               return form, y
+       end
 
-               "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") .. "]"
+       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 #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;" ..
+               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 minimal is installed
+       local minimal_only = ""
+       local gamelist_height = 2.3
+       if #pkgmgr.games == 1 and pkgmgr.games[1].id == "minimal" then
+               minimal_only = "box[0,0;5.8,1.7;#ff8800]" ..
+                               "textarea[0.3,0;6,1.8;;;"..
+                               fgettext("Warning: The minimal 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]" ..
+               minimal_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
@@ -163,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
 
index db13f4224eb99af62769023d9f86645d46c25260..9685e8307b65a4ec435eee2bc38d3b133e3530e7 100644 (file)
@@ -75,6 +75,10 @@ The game directory can contain the following files:
       When both `allowed_mapgens` and `disallowed_mapgens` are
       specified, `allowed_mapgens` is applied before
       `disallowed_mapgens`.
+    * `disallowed_mapgen_settings= <comma-separated mapgen settings>`
+      e.g. `disallowed_mapgen_settings = mgv5_spflags`
+      These settings are hidden for this game in the world creation
+      dialog and game start menu.
 * `minetest.conf`:
   Used to set default settings when running this game.
 * `settingtypes.txt`: