]> git.lizzy.rs Git - minetest.git/blob - builtin/mainmenu/dlg_create_world.lua
Mapgen Flat: Add caverns, disabled by default (#9913)
[minetest.git] / builtin / mainmenu / dlg_create_world.lua
1 --Minetest
2 --Copyright (C) 2014 sapier
3 --
4 --This program is free software; you can redistribute it and/or modify
5 --it under the terms of the GNU Lesser General Public License as published by
6 --the Free Software Foundation; either version 2.1 of the License, or
7 --(at your option) any later version.
8 --
9 --This program is distributed in the hope that it will be useful,
10 --but WITHOUT ANY WARRANTY; without even the implied warranty of
11 --MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 --GNU Lesser General Public License for more details.
13 --
14 --You should have received a copy of the GNU Lesser General Public License along
15 --with this program; if not, write to the Free Software Foundation, Inc.,
16 --51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17
18 local worldname = ""
19
20 local function table_to_flags(ftable)
21         -- Convert e.g. { jungles = true, caves = false } to "jungles,nocaves"
22         local str = {}
23         for flag, is_set in pairs(ftable) do
24                 str[#str + 1] = is_set and flag or ("no" .. flag)
25         end
26         return table.concat(str, ",")
27 end
28
29 -- Same as check_flag but returns a string
30 local function strflag(flags, flag)
31         return (flags[flag] == true) and "true" or "false"
32 end
33
34 local cb_caverns = { "caverns", fgettext("Caverns"), "caverns",
35         fgettext("Very large caverns deep in the underground") }
36 local tt_sea_rivers = fgettext("Sea level rivers")
37
38 local flag_checkboxes = {
39         v5 = {
40                 cb_caverns,
41         },
42         v7 = {
43                 cb_caverns,
44                 { "ridges", fgettext("Rivers"), "ridges", tt_sea_rivers },
45                 { "mountains", fgettext("Mountains"), "mountains" },
46                 { "floatlands", fgettext("Floatlands (experimental)"), "floatlands",
47                 fgettext("Floating landmasses in the sky") },
48         },
49         carpathian = {
50                 cb_caverns,
51                 { "rivers", fgettext("Rivers"), "rivers", tt_sea_rivers },
52         },
53         valleys = {
54                 { "altitude-chill", fgettext("Altitude chill"), "altitude_chill",
55                 fgettext("Reduces heat with altitude") },
56                 { "altitude-dry", fgettext("Altitude dry"), "altitude_dry",
57                 fgettext("Reduces humidity with altitude") },
58                 { "humid-rivers", fgettext("Humid rivers"), "humid_rivers",
59                 fgettext("Increases humidity around rivers") },
60                 { "vary-river-depth", fgettext("Vary river depth"), "vary_river_depth",
61                 fgettext("Low humidity and high heat causes shallow or dry rivers") },
62         },
63         flat = {
64                 cb_caverns,
65                 { "hills", fgettext("Hills"), "hills" },
66                 { "lakes", fgettext("Lakes"), "lakes" },
67         },
68         fractal = {
69                 { "terrain", fgettext("Additional terrain"), "terrain",
70                 fgettext("Generate non-fractal terrain: Oceans and underground") },
71         },
72         v6 = {
73                 { "trees", fgettext("Trees and jungle grass"), "trees" },
74                 { "flat", fgettext("Flat terrain"), "flat" },
75                 { "mudflow", fgettext("Mud flow"), "mudflow",
76                 fgettext("Terrain surface erosion") },
77                 -- Biome settings are in mgv6_biomes below
78         },
79 }
80
81 local mgv6_biomes = {
82         {
83                 fgettext("Temperate, Desert, Jungle, Tundra, Taiga"),
84                 {jungles = true, snowbiomes = true}
85         },
86         {
87                 fgettext("Temperate, Desert, Jungle"),
88                 {jungles = true, snowbiomes = false}
89         },
90         {
91                 fgettext("Temperate, Desert"),
92                 {jungles = false, snowbiomes = false}
93         },
94 }
95
96 local function create_world_formspec(dialogdata)
97
98         -- Error out when no games found
99         if #pkgmgr.games == 0 then
100                 return "size[12.25,3,true]" ..
101                         "box[0,0;12,2;#ff8800]" ..
102                         "textarea[0.3,0;11.7,2;;;"..
103                         fgettext("You have no games installed.") .. "\n" ..
104                         fgettext("Download one from minetest.net") .. "]" ..
105                         "button[4.75,2.5;3,0.5;world_create_cancel;" .. fgettext("Cancel") .. "]"
106         end
107
108         local mapgens = core.get_mapgen_names()
109
110         local current_seed = core.settings:get("fixed_map_seed") or ""
111         local current_mg   = core.settings:get("mg_name")
112         local gameid = core.settings:get("menu_last_game")
113
114         local flags = {
115                 main = core.settings:get_flags("mg_flags"),
116                 v5 = core.settings:get_flags("mgv5_spflags"),
117                 v6 = core.settings:get_flags("mgv6_spflags"),
118                 v7 = core.settings:get_flags("mgv7_spflags"),
119                 fractal = core.settings:get_flags("mgfractal_spflags"),
120                 carpathian = core.settings:get_flags("mgcarpathian_spflags"),
121                 valleys = core.settings:get_flags("mgvalleys_spflags"),
122                 flat = core.settings:get_flags("mgflat_spflags"),
123         }
124
125         local gameidx = 0
126         if gameid ~= nil then
127                 local _
128                 _, gameidx = pkgmgr.find_by_gameid(gameid)
129
130                 if gameidx == nil then
131                         gameidx = 0
132                 end
133         end
134
135         local game_by_gameidx = core.get_game(gameidx)
136         local disallowed_mapgen_settings = {}
137         if game_by_gameidx ~= nil then
138                 local gamepath = game_by_gameidx.path
139                 local gameconfig = Settings(gamepath.."/game.conf")
140
141                 local allowed_mapgens = (gameconfig:get("allowed_mapgens") or ""):split()
142                 for key, value in pairs(allowed_mapgens) do
143                         allowed_mapgens[key] = value:trim()
144                 end
145
146                 local disallowed_mapgens = (gameconfig:get("disallowed_mapgens") or ""):split()
147                 for key, value in pairs(disallowed_mapgens) do
148                         disallowed_mapgens[key] = value:trim()
149                 end
150
151                 if #allowed_mapgens > 0 then
152                         for i = #mapgens, 1, -1 do
153                                 if table.indexof(allowed_mapgens, mapgens[i]) == -1 then
154                                         table.remove(mapgens, i)
155                                 end
156                         end
157                 end
158
159                 if disallowed_mapgens then
160                         for i = #mapgens, 1, -1 do
161                                 if table.indexof(disallowed_mapgens, mapgens[i]) > 0 then
162                                         table.remove(mapgens, i)
163                                 end
164                         end
165                 end
166
167                 local ds = (gameconfig:get("disallowed_mapgen_settings") or ""):split()
168                 for _, value in pairs(ds) do
169                         disallowed_mapgen_settings[value:trim()] = true
170                 end
171         end
172
173         local mglist = ""
174         local selindex
175         local i = 1
176         local first_mg
177         for k,v in pairs(mapgens) do
178                 if not first_mg then
179                         first_mg = v
180                 end
181                 if current_mg == v then
182                         selindex = i
183                 end
184                 i = i + 1
185                 mglist = mglist .. v .. ","
186         end
187         if not selindex then
188                 selindex = 1
189                 current_mg = first_mg
190         end
191         mglist = mglist:sub(1, -2)
192
193         local mg_main_flags = function(mapgen, y)
194                 if mapgen == "singlenode" then
195                         return "", y
196                 end
197                 if disallowed_mapgen_settings["mg_flags"] then
198                         return "", y
199                 end
200
201                 local form = "checkbox[0," .. y .. ";flag_mg_caves;" ..
202                         fgettext("Caves") .. ";"..strflag(flags.main, "caves").."]"
203                 y = y + 0.5
204
205                 form = form .. "checkbox[0,"..y..";flag_mg_dungeons;" ..
206                         fgettext("Dungeons") .. ";"..strflag(flags.main, "dungeons").."]"
207                 y = y + 0.5
208
209                 local d_name = fgettext("Decorations")
210                 local d_tt
211                 if mapgen == "v6" then
212                         d_tt = fgettext("Structures appearing on the terrain (no effect on trees and jungle grass created by v6)")
213                 else
214                         d_tt = fgettext("Structures appearing on the terrain, typically trees and plants")
215                 end
216                 form = form .. "checkbox[0,"..y..";flag_mg_decorations;" ..
217                         d_name .. ";" ..
218                         strflag(flags.main, "decorations").."]" ..
219                         "tooltip[flag_mg_decorations;" ..
220                         d_tt ..
221                         "]"
222                 y = y + 0.5
223
224                 form = form .. "tooltip[flag_mg_caves;" ..
225                 fgettext("Network of tunnels and caves")
226                 .. "]"
227                 return form, y
228         end
229
230         local mg_specific_flags = function(mapgen, y)
231                 if not flag_checkboxes[mapgen] then
232                         return "", y
233                 end
234                 if disallowed_mapgen_settings["mg"..mapgen.."_spflags"] then
235                         return "", y
236                 end
237                 local form = ""
238                 for _,tab in pairs(flag_checkboxes[mapgen]) do
239                         local id = "flag_mg"..mapgen.."_"..tab[1]
240                         form = form .. ("checkbox[0,%f;%s;%s;%s]"):
241                                 format(y, id, tab[2], strflag(flags[mapgen], tab[3]))
242
243                         if tab[4] then
244                                 form = form .. "tooltip["..id..";"..tab[4].."]"
245                         end
246                         y = y + 0.5
247                 end
248
249                 if mapgen ~= "v6" then
250                         -- No special treatment
251                         return form, y
252                 end
253                 -- Special treatment for v6 (add biome widgets)
254
255                 -- Biome type (jungles, snowbiomes)
256                 local biometype
257                 if flags.v6.snowbiomes == true then
258                         biometype = 1
259                 elseif flags.v6.jungles == true  then
260                         biometype = 2
261                 else
262                         biometype = 3
263                 end
264                 y = y + 0.3
265
266                 form = form .. "label[0,"..(y+0.1)..";" .. fgettext("Biomes") .. "]"
267                 y = y + 0.6
268
269                 form = form .. "dropdown[0,"..y..";6.3;mgv6_biomes;"
270                 for b=1, #mgv6_biomes do
271                         form = form .. mgv6_biomes[b][1]
272                         if b < #mgv6_biomes then
273                                 form = form .. ","
274                         end
275                 end
276                 form = form .. ";" .. biometype.. "]"
277
278                 -- biomeblend
279                 y = y + 0.55
280                 form = form .. "checkbox[0,"..y..";flag_mgv6_biomeblend;" ..
281                         fgettext("Biome blending") .. ";"..strflag(flags.v6, "biomeblend").."]" ..
282                         "tooltip[flag_mgv6_biomeblend;" ..
283                         fgettext("Smooth transition between biomes") .. "]"
284
285                 return form, y
286         end
287
288         current_seed = core.formspec_escape(current_seed)
289
290         local y_start = 0.0
291         local y = y_start
292         local str_flags, str_spflags
293         local label_flags, label_spflags = "", ""
294         y = y + 0.3
295         str_flags, y = mg_main_flags(current_mg, y)
296         if str_flags ~= "" then
297                 label_flags = "label[0,"..y_start..";" .. fgettext("Mapgen flags") .. "]"
298                 y_start = y + 0.4
299         else
300                 y_start = 0.0
301         end
302         y = y_start + 0.3
303         str_spflags = mg_specific_flags(current_mg, y)
304         if str_spflags ~= "" then
305                 label_spflags = "label[0,"..y_start..";" .. fgettext("Mapgen-specific flags") .. "]"
306         end
307
308         -- Warning if only devtest is installed
309         local devtest_only = ""
310         local gamelist_height = 2.3
311         if #pkgmgr.games == 1 and pkgmgr.games[1].id == "devtest" then
312                 devtest_only = "box[0,0;5.8,1.7;#ff8800]" ..
313                                 "textarea[0.3,0;6,1.8;;;"..
314                                 fgettext("Warning: The Development Test is meant for developers.") .. "\n" ..
315                                 fgettext("Download a game, such as Minetest Game, from minetest.net") .. "]"
316                 gamelist_height = 0.5
317         end
318
319         local retval =
320                 "size[12.25,7,true]" ..
321
322                 -- Left side
323                 "container[0,0]"..
324                 "field[0.3,0.6;6,0.5;te_world_name;" ..
325                 fgettext("World name") ..
326                 ";" .. core.formspec_escape(worldname) .. "]" ..
327
328                 "field[0.3,1.7;6,0.5;te_seed;" ..
329                 fgettext("Seed") ..
330                 ";".. current_seed .. "]" ..
331
332                 "label[0,2;" .. fgettext("Mapgen") .. "]"..
333                 "dropdown[0,2.5;6.3;dd_mapgen;" .. mglist .. ";" .. selindex .. "]" ..
334
335                 "label[0,3.35;" .. fgettext("Game") .. "]"..
336                 "textlist[0,3.85;5.8,"..gamelist_height..";games;" ..
337                 pkgmgr.gamelist() .. ";" .. gameidx .. ";false]" ..
338                 "container[0,4.5]" ..
339                 devtest_only ..
340                 "container_end[]" ..
341                 "container_end[]" ..
342
343                 -- Right side
344                 "container[6.2,0]"..
345                 label_flags .. str_flags ..
346                 label_spflags .. str_spflags ..
347                 "container_end[]"..
348
349                 -- Menu buttons
350                 "button[3.25,6.5;3,0.5;world_create_confirm;" .. fgettext("Create") .. "]" ..
351                 "button[6.25,6.5;3,0.5;world_create_cancel;" .. fgettext("Cancel") .. "]"
352
353         return retval
354
355 end
356
357 local function create_world_buttonhandler(this, fields)
358
359         if fields["world_create_confirm"] or
360                 fields["key_enter"] then
361
362                 local worldname = fields["te_world_name"]
363                 local gameindex = core.get_textlist_index("games")
364
365                 if gameindex ~= nil then
366                         if worldname == "" then
367                                 local random_number = math.random(10000, 99999)
368                                 local random_world_name = "Unnamed" .. random_number
369                                 worldname = random_world_name
370                         end
371
372                         core.settings:set("fixed_map_seed", fields["te_seed"])
373
374                         local message
375                         if not menudata.worldlist:uid_exists_raw(worldname) then
376                                 core.settings:set("mg_name",fields["dd_mapgen"])
377                                 message = core.create_world(worldname,gameindex)
378                         else
379                                 message = fgettext("A world named \"$1\" already exists", worldname)
380                         end
381
382                         if message ~= nil then
383                                 gamedata.errormessage = message
384                         else
385                                 core.settings:set("menu_last_game",pkgmgr.games[gameindex].id)
386                                 if this.data.update_worldlist_filter then
387                                         menudata.worldlist:set_filtercriteria(pkgmgr.games[gameindex].id)
388                                         mm_texture.update("singleplayer", pkgmgr.games[gameindex].id)
389                                 end
390                                 menudata.worldlist:refresh()
391                                 core.settings:set("mainmenu_last_selected_world",
392                                                                         menudata.worldlist:raw_index_by_uid(worldname))
393                         end
394                 else
395                         gamedata.errormessage = fgettext("No game selected")
396                 end
397                 this:delete()
398                 return true
399         end
400
401         worldname = fields.te_world_name
402
403         if fields["games"] then
404                 local gameindex = core.get_textlist_index("games")
405                 core.settings:set("menu_last_game", pkgmgr.games[gameindex].id)
406                 return true
407         end
408
409         for k,v in pairs(fields) do
410                 local split = string.split(k, "_", nil, 3)
411                 if split and split[1] == "flag" then
412                         local setting
413                         if split[2] == "mg" then
414                                 setting = "mg_flags"
415                         else
416                                 setting = split[2].."_spflags"
417                         end
418                         -- We replaced the underscore of flag names with a dash.
419                         local flag = string.gsub(split[3], "-", "_")
420                         local ftable = core.settings:get_flags(setting)
421                         if v == "true" then
422                                 ftable[flag] = true
423                         else
424                                 ftable[flag] = false
425                         end
426                         local flags = table_to_flags(ftable)
427                         core.settings:set(setting, flags)
428                         return true
429                 end
430         end
431
432         if fields["world_create_cancel"] then
433                 this:delete()
434                 return true
435         end
436
437         if fields["mgv6_biomes"] then
438                 local entry = minetest.formspec_escape(fields["mgv6_biomes"])
439                 for b=1, #mgv6_biomes do
440                         if entry == mgv6_biomes[b][1] then
441                                 local ftable = core.settings:get_flags("mgv6_spflags")
442                                 ftable.jungles = mgv6_biomes[b][2].jungles
443                                 ftable.snowbiomes = mgv6_biomes[b][2].snowbiomes
444                                 local flags = table_to_flags(ftable)
445                                 core.settings:set("mgv6_spflags", flags)
446                                 return true
447                         end
448                 end
449         end
450
451         if fields["dd_mapgen"] then
452                 core.settings:set("mg_name", fields["dd_mapgen"])
453                 return true
454         end
455
456         return false
457 end
458
459
460 function create_create_world_dlg(update_worldlistfilter)
461         worldname = ""
462         local retval = dialog_create("sp_create_world",
463                                         create_world_formspec,
464                                         create_world_buttonhandler,
465                                         nil)
466         retval.update_worldlist_filter = update_worldlistfilter
467
468         return retval
469 end