]> git.lizzy.rs Git - minetest.git/blob - src/script/lua_api/l_mapgen.cpp
d30b680548e1bd9522d4f9d8625b1f2796266942
[minetest.git] / src / script / lua_api / l_mapgen.cpp
1 /*
2 Minetest
3 Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include "lua_api/l_mapgen.h"
21 #include "lua_api/l_internal.h"
22 #include "lua_api/l_vmanip.h"
23 #include "common/c_converter.h"
24 #include "common/c_content.h"
25 #include "cpp_api/s_security.h"
26 #include "util/serialize.h"
27 #include "server.h"
28 #include "environment.h"
29 #include "emerge.h"
30 #include "mg_biome.h"
31 #include "mg_ore.h"
32 #include "mg_decoration.h"
33 #include "mg_schematic.h"
34 #include "mapgen_v5.h"
35 #include "mapgen_v7.h"
36 #include "filesys.h"
37 #include "settings.h"
38 #include "log.h"
39
40 struct EnumString ModApiMapgen::es_BiomeTerrainType[] =
41 {
42         {BIOME_NORMAL, "normal"},
43         {BIOME_LIQUID, "liquid"},
44         {BIOME_NETHER, "nether"},
45         {BIOME_AETHER, "aether"},
46         {BIOME_FLAT,   "flat"},
47         {0, NULL},
48 };
49
50 struct EnumString ModApiMapgen::es_DecorationType[] =
51 {
52         {DECO_SIMPLE,    "simple"},
53         {DECO_SCHEMATIC, "schematic"},
54         {DECO_LSYSTEM,   "lsystem"},
55         {0, NULL},
56 };
57
58 struct EnumString ModApiMapgen::es_MapgenObject[] =
59 {
60         {MGOBJ_VMANIP,    "voxelmanip"},
61         {MGOBJ_HEIGHTMAP, "heightmap"},
62         {MGOBJ_BIOMEMAP,  "biomemap"},
63         {MGOBJ_HEATMAP,   "heatmap"},
64         {MGOBJ_HUMIDMAP,  "humiditymap"},
65         {MGOBJ_GENNOTIFY, "gennotify"},
66         {0, NULL},
67 };
68
69 struct EnumString ModApiMapgen::es_OreType[] =
70 {
71         {ORE_SCATTER, "scatter"},
72         {ORE_SHEET,   "sheet"},
73         {ORE_BLOB,    "blob"},
74         {ORE_VEIN,    "vein"},
75         {0, NULL},
76 };
77
78 struct EnumString ModApiMapgen::es_Rotation[] =
79 {
80         {ROTATE_0,    "0"},
81         {ROTATE_90,   "90"},
82         {ROTATE_180,  "180"},
83         {ROTATE_270,  "270"},
84         {ROTATE_RAND, "random"},
85         {0, NULL},
86 };
87
88 struct EnumString ModApiMapgen::es_SchematicFormatType[] =
89 {
90         {SCHEM_FMT_HANDLE, "handle"},
91         {SCHEM_FMT_MTS,    "mts"},
92         {SCHEM_FMT_LUA,    "lua"},
93         {0, NULL},
94 };
95
96 ObjDef *get_objdef(lua_State *L, int index, ObjDefManager *objmgr);
97
98 Biome *get_or_load_biome(lua_State *L, int index,
99         BiomeManager *biomemgr);
100 Biome *read_biome_def(lua_State *L, int index, INodeDefManager *ndef);
101 size_t get_biome_list(lua_State *L, int index,
102         BiomeManager *biomemgr, std::set<u8> *biome_id_list);
103
104 Schematic *get_or_load_schematic(lua_State *L, int index,
105         SchematicManager *schemmgr, StringMap *replace_names);
106 Schematic *load_schematic(lua_State *L, int index, INodeDefManager *ndef,
107         StringMap *replace_names);
108 Schematic *load_schematic_from_def(lua_State *L, int index,
109         INodeDefManager *ndef, StringMap *replace_names);
110 bool read_schematic_def(lua_State *L, int index,
111         Schematic *schem, std::vector<std::string> *names);
112
113 bool read_deco_simple(lua_State *L, DecoSimple *deco);
114 bool read_deco_schematic(lua_State *L, SchematicManager *schemmgr, DecoSchematic *deco);
115
116
117 ///////////////////////////////////////////////////////////////////////////////
118
119 ObjDef *get_objdef(lua_State *L, int index, ObjDefManager *objmgr)
120 {
121         if (index < 0)
122                 index = lua_gettop(L) + 1 + index;
123
124         // If a number, assume this is a handle to an object def
125         if (lua_isnumber(L, index))
126                 return objmgr->get(lua_tointeger(L, index));
127
128         // If a string, assume a name is given instead
129         if (lua_isstring(L, index))
130                 return objmgr->getByName(lua_tostring(L, index));
131
132         return NULL;
133 }
134
135 ///////////////////////////////////////////////////////////////////////////////
136
137 Schematic *get_or_load_schematic(lua_State *L, int index,
138         SchematicManager *schemmgr, StringMap *replace_names)
139 {
140         if (index < 0)
141                 index = lua_gettop(L) + 1 + index;
142
143         Schematic *schem = (Schematic *)get_objdef(L, index, schemmgr);
144         if (schem)
145                 return schem;
146
147         schem = load_schematic(L, index, schemmgr->getNodeDef(),
148                 replace_names);
149         if (!schem)
150                 return NULL;
151
152         if (schemmgr->add(schem) == OBJDEF_INVALID_HANDLE) {
153                 delete schem;
154                 return NULL;
155         }
156
157         return schem;
158 }
159
160
161 Schematic *load_schematic(lua_State *L, int index, INodeDefManager *ndef,
162         StringMap *replace_names)
163 {
164         if (index < 0)
165                 index = lua_gettop(L) + 1 + index;
166
167         Schematic *schem = NULL;
168
169         if (lua_istable(L, index)) {
170                 schem = load_schematic_from_def(L, index, ndef,
171                         replace_names);
172                 if (!schem) {
173                         delete schem;
174                         return NULL;
175                 }
176         } else if (lua_isnumber(L, index)) {
177                 return NULL;
178         } else if (lua_isstring(L, index)) {
179                 schem = SchematicManager::create(SCHEMATIC_NORMAL);
180
181                 std::string filepath = lua_tostring(L, index);
182                 if (!fs::IsPathAbsolute(filepath))
183                         filepath = ModApiBase::getCurrentModPath(L) + DIR_DELIM + filepath;
184
185                 if (!schem->loadSchematicFromFile(filepath, ndef,
186                                 replace_names)) {
187                         delete schem;
188                         return NULL;
189                 }
190         }
191
192         return schem;
193 }
194
195
196 Schematic *load_schematic_from_def(lua_State *L, int index,
197         INodeDefManager *ndef, StringMap *replace_names)
198 {
199         Schematic *schem = SchematicManager::create(SCHEMATIC_NORMAL);
200
201         if (!read_schematic_def(L, index, schem, &schem->m_nodenames)) {
202                 delete schem;
203                 return NULL;
204         }
205
206         size_t num_nodes = schem->m_nodenames.size();
207
208         schem->m_nnlistsizes.push_back(num_nodes);
209
210         if (replace_names) {
211                 for (size_t i = 0; i != num_nodes; i++) {
212                         StringMap::iterator it = replace_names->find(schem->m_nodenames[i]);
213                         if (it != replace_names->end())
214                                 schem->m_nodenames[i] = it->second;
215                 }
216         }
217
218         if (ndef)
219                 ndef->pendNodeResolve(schem);
220
221         return schem;
222 }
223
224
225 bool read_schematic_def(lua_State *L, int index,
226         Schematic *schem, std::vector<std::string> *names)
227 {
228         if (!lua_istable(L, index))
229                 return false;
230
231         //// Get schematic size
232         lua_getfield(L, index, "size");
233         v3s16 size = check_v3s16(L, -1);
234         lua_pop(L, 1);
235
236         schem->size = size;
237
238         //// Get schematic data
239         lua_getfield(L, index, "data");
240         luaL_checktype(L, -1, LUA_TTABLE);
241
242         u32 numnodes = size.X * size.Y * size.Z;
243         schem->schemdata = new MapNode[numnodes];
244
245         size_t names_base = names->size();
246         std::map<std::string, content_t> name_id_map;
247
248         u32 i = 0;
249         for (lua_pushnil(L); lua_next(L, -2); i++, lua_pop(L, 1)) {
250                 if (i >= numnodes)
251                         continue;
252
253                 //// Read name
254                 std::string name;
255                 if (!getstringfield(L, -1, "name", name))
256                         throw LuaError("Schematic data definition with missing name field");
257
258                 //// Read param1/prob
259                 u8 param1;
260                 if (!getintfield(L, -1, "param1", param1) &&
261                         !getintfield(L, -1, "prob", param1))
262                         param1 = MTSCHEM_PROB_ALWAYS_OLD;
263
264                 //// Read param2
265                 u8 param2 = getintfield_default(L, -1, "param2", 0);
266
267                 //// Find or add new nodename-to-ID mapping
268                 std::map<std::string, content_t>::iterator it = name_id_map.find(name);
269                 content_t name_index;
270                 if (it != name_id_map.end()) {
271                         name_index = it->second;
272                 } else {
273                         name_index = names->size() - names_base;
274                         name_id_map[name] = name_index;
275                         names->push_back(name);
276                 }
277
278                 //// Perform probability/force_place fixup on param1
279                 param1 >>= 1;
280                 if (getboolfield_default(L, -1, "force_place", false))
281                         param1 |= MTSCHEM_FORCE_PLACE;
282
283                 //// Actually set the node in the schematic
284                 schem->schemdata[i] = MapNode(name_index, param1, param2);
285         }
286
287         if (i != numnodes) {
288                 errorstream << "read_schematic_def: incorrect number of "
289                         "nodes provided in raw schematic data (got " << i <<
290                         ", expected " << numnodes << ")." << std::endl;
291                 return false;
292         }
293
294         //// Get Y-slice probability values (if present)
295         schem->slice_probs = new u8[size.Y];
296         for (i = 0; i != (u32) size.Y; i++)
297                 schem->slice_probs[i] = MTSCHEM_PROB_ALWAYS;
298
299         lua_getfield(L, index, "yslice_prob");
300         if (lua_istable(L, -1)) {
301                 for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
302                         u16 ypos;
303                         if (!getintfield(L, -1, "ypos", ypos) || (ypos >= size.Y) ||
304                                 !getintfield(L, -1, "prob", schem->slice_probs[ypos]))
305                                 continue;
306
307                         schem->slice_probs[ypos] >>= 1;
308                 }
309         }
310
311         return true;
312 }
313
314
315 void read_schematic_replacements(lua_State *L, int index, StringMap *replace_names)
316 {
317         if (index < 0)
318                 index = lua_gettop(L) + 1 + index;
319
320         lua_pushnil(L);
321         while (lua_next(L, index)) {
322                 std::string replace_from;
323                 std::string replace_to;
324
325                 if (lua_istable(L, -1)) { // Old {{"x", "y"}, ...} format
326                         lua_rawgeti(L, -1, 1);
327                         replace_from = lua_tostring(L, -1);
328                         lua_pop(L, 1);
329
330                         lua_rawgeti(L, -1, 2);
331                         replace_to = lua_tostring(L, -1);
332                         lua_pop(L, 1);
333                 } else { // New {x = "y", ...} format
334                         replace_from = lua_tostring(L, -2);
335                         replace_to = lua_tostring(L, -1);
336                 }
337
338                 replace_names->insert(std::make_pair(replace_from, replace_to));
339                 lua_pop(L, 1);
340         }
341 }
342
343 ///////////////////////////////////////////////////////////////////////////////
344
345 Biome *get_or_load_biome(lua_State *L, int index, BiomeManager *biomemgr)
346 {
347         if (index < 0)
348                 index = lua_gettop(L) + 1 + index;
349
350         Biome *biome = (Biome *)get_objdef(L, index, biomemgr);
351         if (biome)
352                 return biome;
353
354         biome = read_biome_def(L, index, biomemgr->getNodeDef());
355         if (!biome)
356                 return NULL;
357
358         if (biomemgr->add(biome) == OBJDEF_INVALID_HANDLE) {
359                 delete biome;
360                 return NULL;
361         }
362
363         return biome;
364 }
365
366
367 Biome *read_biome_def(lua_State *L, int index, INodeDefManager *ndef)
368 {
369         if (!lua_istable(L, index))
370                 return NULL;
371
372         BiomeType biometype = (BiomeType)getenumfield(L, index, "type",
373                 ModApiMapgen::es_BiomeTerrainType, BIOME_NORMAL);
374         Biome *b = BiomeManager::create(biometype);
375
376         b->name            = getstringfield_default(L, index, "name", "");
377         b->depth_top       = getintfield_default(L,    index, "depth_top",       0);
378         b->depth_filler    = getintfield_default(L,    index, "depth_filler",    -31000);
379         b->depth_water_top = getintfield_default(L,    index, "depth_water_top", 0);
380         b->y_min           = getintfield_default(L,    index, "y_min",           -31000);
381         b->y_max           = getintfield_default(L,    index, "y_max",           31000);
382         b->heat_point      = getfloatfield_default(L,  index, "heat_point",      0.f);
383         b->humidity_point  = getfloatfield_default(L,  index, "humidity_point",  0.f);
384         b->flags           = 0; //reserved
385
386         std::vector<std::string> &nn = b->m_nodenames;
387         nn.push_back(getstringfield_default(L, index, "node_top",         ""));
388         nn.push_back(getstringfield_default(L, index, "node_filler",      ""));
389         nn.push_back(getstringfield_default(L, index, "node_stone",       ""));
390         nn.push_back(getstringfield_default(L, index, "node_water_top",   ""));
391         nn.push_back(getstringfield_default(L, index, "node_water",       ""));
392         nn.push_back(getstringfield_default(L, index, "node_river_water", ""));
393         nn.push_back(getstringfield_default(L, index, "node_dust",        ""));
394         ndef->pendNodeResolve(b);
395
396         return b;
397 }
398
399
400 size_t get_biome_list(lua_State *L, int index,
401         BiomeManager *biomemgr, std::set<u8> *biome_id_list)
402 {
403         if (index < 0)
404                 index = lua_gettop(L) + 1 + index;
405
406         if (lua_isnil(L, index))
407                 return 0;
408
409         bool is_single = true;
410         if (lua_istable(L, index)) {
411                 lua_getfield(L, index, "name");
412                 is_single = !lua_isnil(L, -1);
413                 lua_pop(L, 1);
414         }
415
416         if (is_single) {
417                 Biome *biome = get_or_load_biome(L, index, biomemgr);
418                 if (!biome) {
419                         errorstream << "get_biome_list: failed to get biome '"
420                                 << (lua_isstring(L, index) ? lua_tostring(L, index) : "")
421                                 << "'." << std::endl;
422                         return 1;
423                 }
424
425                 biome_id_list->insert(biome->index);
426                 return 0;
427         }
428
429         // returns number of failed resolutions
430         size_t fail_count = 0;
431         size_t count = 0;
432
433         for (lua_pushnil(L); lua_next(L, index); lua_pop(L, 1)) {
434                 count++;
435                 Biome *biome = get_or_load_biome(L, -1, biomemgr);
436                 if (!biome) {
437                         fail_count++;
438                         errorstream << "get_biome_list: failed to get biome '"
439                                 << (lua_isstring(L, -1) ? lua_tostring(L, -1) : "")
440                                 << "'" << std::endl;
441                         continue;
442                 }
443
444                 biome_id_list->insert(biome->index);
445         }
446
447         return fail_count;
448 }
449
450 ///////////////////////////////////////////////////////////////////////////////
451
452 // get_mapgen_object(objectname)
453 // returns the requested object used during map generation
454 int ModApiMapgen::l_get_mapgen_object(lua_State *L)
455 {
456         const char *mgobjstr = lua_tostring(L, 1);
457
458         int mgobjint;
459         if (!string_to_enum(es_MapgenObject, mgobjint, mgobjstr ? mgobjstr : ""))
460                 return 0;
461
462         enum MapgenObject mgobj = (MapgenObject)mgobjint;
463
464         EmergeManager *emerge = getServer(L)->getEmergeManager();
465         Mapgen *mg = emerge->getCurrentMapgen();
466         if (!mg)
467                 return 0;
468
469         size_t maplen = mg->csize.X * mg->csize.Z;
470
471         switch (mgobj) {
472         case MGOBJ_VMANIP: {
473                 MMVManip *vm = mg->vm;
474
475                 // VoxelManip object
476                 LuaVoxelManip *o = new LuaVoxelManip(vm, true);
477                 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
478                 luaL_getmetatable(L, "VoxelManip");
479                 lua_setmetatable(L, -2);
480
481                 // emerged min pos
482                 push_v3s16(L, vm->m_area.MinEdge);
483
484                 // emerged max pos
485                 push_v3s16(L, vm->m_area.MaxEdge);
486
487                 return 3;
488         }
489         case MGOBJ_HEIGHTMAP: {
490                 if (!mg->heightmap)
491                         return 0;
492
493                 lua_newtable(L);
494                 for (size_t i = 0; i != maplen; i++) {
495                         lua_pushinteger(L, mg->heightmap[i]);
496                         lua_rawseti(L, -2, i + 1);
497                 }
498
499                 return 1;
500         }
501         case MGOBJ_BIOMEMAP: {
502                 if (!mg->biomemap)
503                         return 0;
504
505                 lua_newtable(L);
506                 for (size_t i = 0; i != maplen; i++) {
507                         lua_pushinteger(L, mg->biomemap[i]);
508                         lua_rawseti(L, -2, i + 1);
509                 }
510
511                 return 1;
512         }
513         case MGOBJ_HEATMAP: {
514                 if (!mg->heatmap)
515                         return 0;
516
517                 lua_newtable(L);
518                 for (size_t i = 0; i != maplen; i++) {
519                         lua_pushnumber(L, mg->heatmap[i]);
520                         lua_rawseti(L, -2, i + 1);
521                 }
522
523                 return 1;
524         }
525
526         case MGOBJ_HUMIDMAP: {
527                 if (!mg->humidmap)
528                         return 0;
529
530                 lua_newtable(L);
531                 for (size_t i = 0; i != maplen; i++) {
532                         lua_pushnumber(L, mg->humidmap[i]);
533                         lua_rawseti(L, -2, i + 1);
534                 }
535
536                 return 1;
537         }
538         case MGOBJ_GENNOTIFY: {
539                 std::map<std::string, std::vector<v3s16> >event_map;
540                 std::map<std::string, std::vector<v3s16> >::iterator it;
541
542                 mg->gennotify.getEvents(event_map);
543
544                 lua_newtable(L);
545                 for (it = event_map.begin(); it != event_map.end(); ++it) {
546                         lua_newtable(L);
547
548                         for (size_t j = 0; j != it->second.size(); j++) {
549                                 push_v3s16(L, it->second[j]);
550                                 lua_rawseti(L, -2, j + 1);
551                         }
552
553                         lua_setfield(L, -2, it->first.c_str());
554                 }
555
556                 return 1;
557         }
558         }
559
560         return 0;
561 }
562
563
564 int ModApiMapgen::l_get_mapgen_params(lua_State *L)
565 {
566         MapgenParams *params = &getServer(L)->getEmergeManager()->params;
567
568         lua_newtable(L);
569
570         lua_pushstring(L, params->mg_name.c_str());
571         lua_setfield(L, -2, "mgname");
572
573         lua_pushinteger(L, params->seed);
574         lua_setfield(L, -2, "seed");
575
576         lua_pushinteger(L, params->water_level);
577         lua_setfield(L, -2, "water_level");
578
579         lua_pushinteger(L, params->chunksize);
580         lua_setfield(L, -2, "chunksize");
581
582         std::string flagstr = writeFlagString(params->flags, flagdesc_mapgen, (u32)-1);
583         lua_pushstring(L, flagstr.c_str());
584         lua_setfield(L, -2, "flags");
585
586         return 1;
587 }
588
589
590 // set_mapgen_params(params)
591 // set mapgen parameters
592 int ModApiMapgen::l_set_mapgen_params(lua_State *L)
593 {
594         if (!lua_istable(L, 1))
595                 return 0;
596
597         MapgenParams *params = &getServer(L)->getEmergeManager()->params;
598         u32 flags = 0, flagmask = 0;
599
600         lua_getfield(L, 1, "mgname");
601         if (lua_isstring(L, -1)) {
602                 params->mg_name = lua_tostring(L, -1);
603                 delete params->sparams;
604                 params->sparams = NULL;
605         }
606
607         lua_getfield(L, 1, "seed");
608         if (lua_isnumber(L, -1))
609                 params->seed = lua_tointeger(L, -1);
610
611         lua_getfield(L, 1, "water_level");
612         if (lua_isnumber(L, -1))
613                 params->water_level = lua_tointeger(L, -1);
614
615         warn_if_field_exists(L, 1, "flagmask",
616                 "Deprecated: flags field now includes unset flags.");
617         lua_getfield(L, 1, "flagmask");
618         if (lua_isstring(L, -1))
619                 params->flags &= ~readFlagString(lua_tostring(L, -1), flagdesc_mapgen, NULL);
620
621         if (getflagsfield(L, 1, "flags", flagdesc_mapgen, &flags, &flagmask)) {
622                 params->flags &= ~flagmask;
623                 params->flags |= flags;
624         }
625
626         return 0;
627 }
628
629
630 // set_noiseparams(name, noiseparams, set_default)
631 // set global config values for noise parameters
632 int ModApiMapgen::l_set_noiseparams(lua_State *L)
633 {
634         const char *name = luaL_checkstring(L, 1);
635
636         NoiseParams np;
637         if (!read_noiseparams(L, 2, &np))
638                 return 0;
639
640         bool set_default = lua_isboolean(L, 3) ? lua_toboolean(L, 3) : true;
641
642         g_settings->setNoiseParams(name, np, set_default);
643
644         return 0;
645 }
646
647
648 // get_noiseparams(name)
649 int ModApiMapgen::l_get_noiseparams(lua_State *L)
650 {
651         std::string name = luaL_checkstring(L, 1);
652
653         NoiseParams np;
654         if (!g_settings->getNoiseParams(name, np))
655                 return 0;
656
657         push_noiseparams(L, &np);
658         return 1;
659 }
660
661
662 // set_gen_notify(flags, {deco_id_table})
663 int ModApiMapgen::l_set_gen_notify(lua_State *L)
664 {
665         u32 flags = 0, flagmask = 0;
666         EmergeManager *emerge = getServer(L)->getEmergeManager();
667
668         if (read_flags(L, 1, flagdesc_gennotify, &flags, &flagmask)) {
669                 emerge->gen_notify_on &= ~flagmask;
670                 emerge->gen_notify_on |= flags;
671         }
672
673         if (lua_istable(L, 2)) {
674                 lua_pushnil(L);
675                 while (lua_next(L, 2)) {
676                         if (lua_isnumber(L, -1))
677                                 emerge->gen_notify_on_deco_ids.insert((u32)lua_tonumber(L, -1));
678                         lua_pop(L, 1);
679                 }
680         }
681
682         return 0;
683 }
684
685
686 // get_gen_notify()
687 int ModApiMapgen::l_get_gen_notify(lua_State *L)
688 {
689         EmergeManager *emerge = getServer(L)->getEmergeManager();
690         push_flags_string(L, flagdesc_gennotify, emerge->gen_notify_on,
691                 emerge->gen_notify_on);
692
693         lua_newtable(L);
694         int i = 1;
695         for (std::set<u32>::iterator it = emerge->gen_notify_on_deco_ids.begin();
696                         it != emerge->gen_notify_on_deco_ids.end(); ++it) {
697                 lua_pushnumber(L, *it);
698                 lua_rawseti(L, -2, i);
699                 i++;
700         }
701         return 2;
702 }
703
704
705 // register_biome({lots of stuff})
706 int ModApiMapgen::l_register_biome(lua_State *L)
707 {
708         int index = 1;
709         luaL_checktype(L, index, LUA_TTABLE);
710
711         INodeDefManager *ndef = getServer(L)->getNodeDefManager();
712         BiomeManager *bmgr    = getServer(L)->getEmergeManager()->biomemgr;
713
714         Biome *biome = read_biome_def(L, index, ndef);
715         if (!biome)
716                 return 0;
717
718         ObjDefHandle handle = bmgr->add(biome);
719         if (handle == OBJDEF_INVALID_HANDLE) {
720                 delete biome;
721                 return 0;
722         }
723
724         lua_pushinteger(L, handle);
725         return 1;
726 }
727
728
729 // register_decoration({lots of stuff})
730 int ModApiMapgen::l_register_decoration(lua_State *L)
731 {
732         int index = 1;
733         luaL_checktype(L, index, LUA_TTABLE);
734
735         INodeDefManager *ndef      = getServer(L)->getNodeDefManager();
736         DecorationManager *decomgr = getServer(L)->getEmergeManager()->decomgr;
737         BiomeManager *biomemgr     = getServer(L)->getEmergeManager()->biomemgr;
738         SchematicManager *schemmgr = getServer(L)->getEmergeManager()->schemmgr;
739
740         enum DecorationType decotype = (DecorationType)getenumfield(L, index,
741                                 "deco_type", es_DecorationType, -1);
742
743         Decoration *deco = decomgr->create(decotype);
744         if (!deco) {
745                 errorstream << "register_decoration: decoration placement type "
746                         << decotype << " not implemented" << std::endl;
747                 return 0;
748         }
749
750         deco->name       = getstringfield_default(L, index, "name", "");
751         deco->fill_ratio = getfloatfield_default(L, index, "fill_ratio", 0.02);
752         deco->y_min      = getintfield_default(L, index, "y_min", -31000);
753         deco->y_max      = getintfield_default(L, index, "y_max", 31000);
754         deco->sidelen    = getintfield_default(L, index, "sidelen", 8);
755         if (deco->sidelen <= 0) {
756                 errorstream << "register_decoration: sidelen must be "
757                         "greater than 0" << std::endl;
758                 delete deco;
759                 return 0;
760         }
761
762         //// Get node name(s) to place decoration on
763         size_t nread = getstringlistfield(L, index, "place_on", &deco->m_nodenames);
764         deco->m_nnlistsizes.push_back(nread);
765
766         //// Get decoration flags
767         getflagsfield(L, index, "flags", flagdesc_deco, &deco->flags, NULL);
768
769         //// Get NoiseParams to define how decoration is placed
770         lua_getfield(L, index, "noise_params");
771         if (read_noiseparams(L, -1, &deco->np))
772                 deco->flags |= DECO_USE_NOISE;
773         lua_pop(L, 1);
774
775         //// Get biomes associated with this decoration (if any)
776         lua_getfield(L, index, "biomes");
777         if (get_biome_list(L, -1, biomemgr, &deco->biomes))
778                 errorstream << "register_decoration: couldn't get all biomes " << std::endl;
779         lua_pop(L, 1);
780
781         //// Handle decoration type-specific parameters
782         bool success = false;
783         switch (decotype) {
784         case DECO_SIMPLE:
785                 success = read_deco_simple(L, (DecoSimple *)deco);
786                 break;
787         case DECO_SCHEMATIC:
788                 success = read_deco_schematic(L, schemmgr, (DecoSchematic *)deco);
789                 break;
790         case DECO_LSYSTEM:
791                 break;
792         }
793
794         if (!success) {
795                 delete deco;
796                 return 0;
797         }
798
799         ndef->pendNodeResolve(deco);
800
801         ObjDefHandle handle = decomgr->add(deco);
802         if (handle == OBJDEF_INVALID_HANDLE) {
803                 delete deco;
804                 return 0;
805         }
806
807         lua_pushinteger(L, handle);
808         return 1;
809 }
810
811
812 bool read_deco_simple(lua_State *L, DecoSimple *deco)
813 {
814         size_t nnames;
815         int index = 1;
816
817         deco->deco_height     = getintfield_default(L, index, "height", 1);
818         deco->deco_height_max = getintfield_default(L, index, "height_max", 0);
819         deco->nspawnby        = getintfield_default(L, index, "num_spawn_by", -1);
820
821         if (deco->deco_height <= 0) {
822                 errorstream << "register_decoration: simple decoration height"
823                         " must be greater than 0" << std::endl;
824                 return false;
825         }
826
827         nnames = getstringlistfield(L, index, "decoration", &deco->m_nodenames);
828         deco->m_nnlistsizes.push_back(nnames);
829         if (nnames == 0) {
830                 errorstream << "register_decoration: no decoration nodes "
831                         "defined" << std::endl;
832                 return false;
833         }
834
835         nnames = getstringlistfield(L, index, "spawn_by", &deco->m_nodenames);
836         deco->m_nnlistsizes.push_back(nnames);
837         if (nnames == 0 && deco->nspawnby != -1) {
838                 errorstream << "register_decoration: no spawn_by nodes defined,"
839                         " but num_spawn_by specified" << std::endl;
840                 return false;
841         }
842
843         return true;
844 }
845
846
847 bool read_deco_schematic(lua_State *L, SchematicManager *schemmgr, DecoSchematic *deco)
848 {
849         int index = 1;
850
851         deco->rotation = (Rotation)getenumfield(L, index, "rotation",
852                 ModApiMapgen::es_Rotation, ROTATE_0);
853
854         StringMap replace_names;
855         lua_getfield(L, index, "replacements");
856         if (lua_istable(L, -1))
857                 read_schematic_replacements(L, -1, &replace_names);
858         lua_pop(L, 1);
859
860         lua_getfield(L, index, "schematic");
861         Schematic *schem = get_or_load_schematic(L, -1, schemmgr, &replace_names);
862         lua_pop(L, 1);
863
864         deco->schematic = schem;
865         return schem != NULL;
866 }
867
868
869 // register_ore({lots of stuff})
870 int ModApiMapgen::l_register_ore(lua_State *L)
871 {
872         int index = 1;
873         luaL_checktype(L, index, LUA_TTABLE);
874
875         INodeDefManager *ndef = getServer(L)->getNodeDefManager();
876         BiomeManager *bmgr    = getServer(L)->getEmergeManager()->biomemgr;
877         OreManager *oremgr    = getServer(L)->getEmergeManager()->oremgr;
878
879         enum OreType oretype = (OreType)getenumfield(L, index,
880                                 "ore_type", es_OreType, ORE_SCATTER);
881         Ore *ore = oremgr->create(oretype);
882         if (!ore) {
883                 errorstream << "register_ore: ore_type " << oretype << " not implemented";
884                 return 0;
885         }
886
887         ore->name           = getstringfield_default(L, index, "name", "");
888         ore->ore_param2     = (u8)getintfield_default(L, index, "ore_param2", 0);
889         ore->clust_scarcity = getintfield_default(L, index, "clust_scarcity", 1);
890         ore->clust_num_ores = getintfield_default(L, index, "clust_num_ores", 1);
891         ore->clust_size     = getintfield_default(L, index, "clust_size", 0);
892         ore->nthresh        = getfloatfield_default(L, index, "noise_threshhold", 0);
893         ore->noise          = NULL;
894         ore->flags          = 0;
895
896         //// Get y_min/y_max
897         warn_if_field_exists(L, index, "height_min",
898                 "Deprecated: new name is \"y_min\".");
899         warn_if_field_exists(L, index, "height_max",
900                 "Deprecated: new name is \"y_max\".");
901
902         int ymin, ymax;
903         if (!getintfield(L, index, "y_min", ymin) &&
904                 !getintfield(L, index, "height_min", ymin))
905                 ymin = -31000;
906         if (!getintfield(L, index, "y_max", ymax) &&
907                 !getintfield(L, index, "height_max", ymax))
908                 ymax = 31000;
909         ore->y_min = ymin;
910         ore->y_max = ymax;
911
912         if (ore->clust_scarcity <= 0 || ore->clust_num_ores <= 0) {
913                 errorstream << "register_ore: clust_scarcity and clust_num_ores"
914                         "must be greater than 0" << std::endl;
915                 delete ore;
916                 return 0;
917         }
918
919         //// Get flags
920         getflagsfield(L, index, "flags", flagdesc_ore, &ore->flags, NULL);
921
922         //// Get biomes associated with this decoration (if any)
923         lua_getfield(L, index, "biomes");
924         if (get_biome_list(L, -1, bmgr, &ore->biomes))
925                 errorstream << "register_ore: couldn't get all biomes " << std::endl;
926         lua_pop(L, 1);
927
928         //// Get noise parameters if needed
929         lua_getfield(L, index, "noise_params");
930         if (read_noiseparams(L, -1, &ore->np)) {
931                 ore->flags |= OREFLAG_USE_NOISE;
932         } else if (ore->NEEDS_NOISE) {
933                 errorstream << "register_ore: specified ore type requires valid "
934                         "noise parameters" << std::endl;
935                 delete ore;
936                 return 0;
937         }
938         lua_pop(L, 1);
939
940         if (oretype == ORE_VEIN) {
941                 OreVein *orevein = (OreVein *)ore;
942                 orevein->random_factor = getfloatfield_default(L, index,
943                         "random_factor", 1.f);
944         }
945
946         ObjDefHandle handle = oremgr->add(ore);
947         if (handle == OBJDEF_INVALID_HANDLE) {
948                 delete ore;
949                 return 0;
950         }
951
952         ore->m_nodenames.push_back(getstringfield_default(L, index, "ore", ""));
953
954         size_t nnames = getstringlistfield(L, index, "wherein", &ore->m_nodenames);
955         ore->m_nnlistsizes.push_back(nnames);
956
957         ndef->pendNodeResolve(ore);
958
959         lua_pushinteger(L, handle);
960         return 1;
961 }
962
963
964 // register_schematic({schematic}, replacements={})
965 int ModApiMapgen::l_register_schematic(lua_State *L)
966 {
967         SchematicManager *schemmgr = getServer(L)->getEmergeManager()->schemmgr;
968
969         StringMap replace_names;
970         if (lua_istable(L, 2))
971                 read_schematic_replacements(L, 2, &replace_names);
972
973         Schematic *schem = load_schematic(L, 1, schemmgr->getNodeDef(),
974                 &replace_names);
975         if (!schem)
976                 return 0;
977
978         ObjDefHandle handle = schemmgr->add(schem);
979         if (handle == OBJDEF_INVALID_HANDLE) {
980                 delete schem;
981                 return 0;
982         }
983
984         lua_pushinteger(L, handle);
985         return 1;
986 }
987
988
989 // clear_registered_biomes()
990 int ModApiMapgen::l_clear_registered_biomes(lua_State *L)
991 {
992         BiomeManager *bmgr = getServer(L)->getEmergeManager()->biomemgr;
993         bmgr->clear();
994         return 0;
995 }
996
997
998 // clear_registered_decorations()
999 int ModApiMapgen::l_clear_registered_decorations(lua_State *L)
1000 {
1001         DecorationManager *dmgr = getServer(L)->getEmergeManager()->decomgr;
1002         dmgr->clear();
1003         return 0;
1004 }
1005
1006
1007 // clear_registered_ores()
1008 int ModApiMapgen::l_clear_registered_ores(lua_State *L)
1009 {
1010         OreManager *omgr = getServer(L)->getEmergeManager()->oremgr;
1011         omgr->clear();
1012         return 0;
1013 }
1014
1015
1016 // clear_registered_schematics()
1017 int ModApiMapgen::l_clear_registered_schematics(lua_State *L)
1018 {
1019         SchematicManager *smgr = getServer(L)->getEmergeManager()->schemmgr;
1020         smgr->clear();
1021         return 0;
1022 }
1023
1024
1025 // generate_ores(vm, p1, p2, [ore_id])
1026 int ModApiMapgen::l_generate_ores(lua_State *L)
1027 {
1028         EmergeManager *emerge = getServer(L)->getEmergeManager();
1029
1030         Mapgen mg;
1031         mg.seed = emerge->params.seed;
1032         mg.vm   = LuaVoxelManip::checkobject(L, 1)->vm;
1033         mg.ndef = getServer(L)->getNodeDefManager();
1034
1035         v3s16 pmin = lua_istable(L, 2) ? check_v3s16(L, 2) :
1036                         mg.vm->m_area.MinEdge + v3s16(1,1,1) * MAP_BLOCKSIZE;
1037         v3s16 pmax = lua_istable(L, 3) ? check_v3s16(L, 3) :
1038                         mg.vm->m_area.MaxEdge - v3s16(1,1,1) * MAP_BLOCKSIZE;
1039         sortBoxVerticies(pmin, pmax);
1040
1041         u32 blockseed = Mapgen::getBlockSeed(pmin, mg.seed);
1042
1043         emerge->oremgr->placeAllOres(&mg, blockseed, pmin, pmax);
1044
1045         return 0;
1046 }
1047
1048
1049 // generate_decorations(vm, p1, p2, [deco_id])
1050 int ModApiMapgen::l_generate_decorations(lua_State *L)
1051 {
1052         EmergeManager *emerge = getServer(L)->getEmergeManager();
1053
1054         Mapgen mg;
1055         mg.seed = emerge->params.seed;
1056         mg.vm   = LuaVoxelManip::checkobject(L, 1)->vm;
1057         mg.ndef = getServer(L)->getNodeDefManager();
1058
1059         v3s16 pmin = lua_istable(L, 2) ? check_v3s16(L, 2) :
1060                         mg.vm->m_area.MinEdge + v3s16(1,1,1) * MAP_BLOCKSIZE;
1061         v3s16 pmax = lua_istable(L, 3) ? check_v3s16(L, 3) :
1062                         mg.vm->m_area.MaxEdge - v3s16(1,1,1) * MAP_BLOCKSIZE;
1063         sortBoxVerticies(pmin, pmax);
1064
1065         u32 blockseed = Mapgen::getBlockSeed(pmin, mg.seed);
1066
1067         emerge->decomgr->placeAllDecos(&mg, blockseed, pmin, pmax);
1068
1069         return 0;
1070 }
1071
1072
1073 // create_schematic(p1, p2, probability_list, filename, y_slice_prob_list)
1074 int ModApiMapgen::l_create_schematic(lua_State *L)
1075 {
1076         INodeDefManager *ndef = getServer(L)->getNodeDefManager();
1077
1078         const char *filename = luaL_checkstring(L, 4);
1079         CHECK_SECURE_PATH_OPTIONAL(L, filename);
1080
1081         Map *map = &(getEnv(L)->getMap());
1082         Schematic schem;
1083
1084         v3s16 p1 = check_v3s16(L, 1);
1085         v3s16 p2 = check_v3s16(L, 2);
1086         sortBoxVerticies(p1, p2);
1087
1088         std::vector<std::pair<v3s16, u8> > prob_list;
1089         if (lua_istable(L, 3)) {
1090                 lua_pushnil(L);
1091                 while (lua_next(L, 3)) {
1092                         if (lua_istable(L, -1)) {
1093                                 lua_getfield(L, -1, "pos");
1094                                 v3s16 pos = check_v3s16(L, -1);
1095                                 lua_pop(L, 1);
1096
1097                                 u8 prob = getintfield_default(L, -1, "prob", MTSCHEM_PROB_ALWAYS);
1098                                 prob_list.push_back(std::make_pair(pos, prob));
1099                         }
1100
1101                         lua_pop(L, 1);
1102                 }
1103         }
1104
1105         std::vector<std::pair<s16, u8> > slice_prob_list;
1106         if (lua_istable(L, 5)) {
1107                 lua_pushnil(L);
1108                 while (lua_next(L, 5)) {
1109                         if (lua_istable(L, -1)) {
1110                                 s16 ypos = getintfield_default(L, -1, "ypos", 0);
1111                                 u8 prob  = getintfield_default(L, -1, "prob", MTSCHEM_PROB_ALWAYS);
1112                                 slice_prob_list.push_back(std::make_pair(ypos, prob));
1113                         }
1114
1115                         lua_pop(L, 1);
1116                 }
1117         }
1118
1119         if (!schem.getSchematicFromMap(map, p1, p2)) {
1120                 errorstream << "create_schematic: failed to get schematic "
1121                         "from map" << std::endl;
1122                 return 0;
1123         }
1124
1125         schem.applyProbabilities(p1, &prob_list, &slice_prob_list);
1126
1127         schem.saveSchematicToFile(filename, ndef);
1128         actionstream << "create_schematic: saved schematic file '"
1129                 << filename << "'." << std::endl;
1130
1131         lua_pushboolean(L, true);
1132         return 1;
1133 }
1134
1135
1136 // place_schematic(p, schematic, rotation, replacement)
1137 int ModApiMapgen::l_place_schematic(lua_State *L)
1138 {
1139         Map *map = &(getEnv(L)->getMap());
1140         SchematicManager *schemmgr = getServer(L)->getEmergeManager()->schemmgr;
1141
1142         //// Read position
1143         v3s16 p = check_v3s16(L, 1);
1144
1145         //// Read rotation
1146         int rot = ROTATE_0;
1147         const char *enumstr = lua_tostring(L, 3);
1148         if (enumstr)
1149                 string_to_enum(es_Rotation, rot, std::string(enumstr));
1150
1151         //// Read force placement
1152         bool force_placement = true;
1153         if (lua_isboolean(L, 5))
1154                 force_placement = lua_toboolean(L, 5);
1155
1156         //// Read node replacements
1157         StringMap replace_names;
1158         if (lua_istable(L, 4))
1159                 read_schematic_replacements(L, 4, &replace_names);
1160
1161         //// Read schematic
1162         Schematic *schem = get_or_load_schematic(L, 2, schemmgr, &replace_names);
1163         if (!schem) {
1164                 errorstream << "place_schematic: failed to get schematic" << std::endl;
1165                 return 0;
1166         }
1167
1168         schem->placeStructure(map, p, 0, (Rotation)rot, force_placement);
1169
1170         lua_pushboolean(L, true);
1171         return 1;
1172 }
1173
1174 // serialize_schematic(schematic, format, options={...})
1175 int ModApiMapgen::l_serialize_schematic(lua_State *L)
1176 {
1177         SchematicManager *schemmgr = getServer(L)->getEmergeManager()->schemmgr;
1178
1179         //// Read options
1180         bool use_comments = getboolfield_default(L, 3, "lua_use_comments", false);
1181         u32 indent_spaces = getintfield_default(L, 3, "lua_num_indent_spaces", 0);
1182
1183         //// Get schematic
1184         bool was_loaded = false;
1185         Schematic *schem = (Schematic *)get_objdef(L, 1, schemmgr);
1186         if (!schem) {
1187                 schem = load_schematic(L, 1, NULL, NULL);
1188                 was_loaded = true;
1189         }
1190         if (!schem) {
1191                 errorstream << "serialize_schematic: failed to get schematic" << std::endl;
1192                 return 0;
1193         }
1194
1195         //// Read format of definition to save as
1196         int schem_format = SCHEM_FMT_MTS;
1197         const char *enumstr = lua_tostring(L, 2);
1198         if (enumstr)
1199                 string_to_enum(es_SchematicFormatType, schem_format, std::string(enumstr));
1200
1201         //// Serialize to binary string
1202         std::ostringstream os(std::ios_base::binary);
1203         switch (schem_format) {
1204         case SCHEM_FMT_MTS:
1205                 schem->serializeToMts(&os, schem->m_nodenames);
1206                 break;
1207         case SCHEM_FMT_LUA:
1208                 schem->serializeToLua(&os, schem->m_nodenames,
1209                         use_comments, indent_spaces);
1210                 break;
1211         default:
1212                 return 0;
1213         }
1214
1215         if (was_loaded)
1216                 delete schem;
1217
1218         std::string ser = os.str();
1219         lua_pushlstring(L, ser.c_str(), ser.length());
1220         return 1;
1221 }
1222
1223
1224 void ModApiMapgen::Initialize(lua_State *L, int top)
1225 {
1226         API_FCT(get_mapgen_object);
1227
1228         API_FCT(get_mapgen_params);
1229         API_FCT(set_mapgen_params);
1230         API_FCT(set_noiseparams);
1231         API_FCT(get_noiseparams);
1232         API_FCT(set_gen_notify);
1233         API_FCT(get_gen_notify);
1234
1235         API_FCT(register_biome);
1236         API_FCT(register_decoration);
1237         API_FCT(register_ore);
1238         API_FCT(register_schematic);
1239
1240         API_FCT(clear_registered_biomes);
1241         API_FCT(clear_registered_decorations);
1242         API_FCT(clear_registered_ores);
1243         API_FCT(clear_registered_schematics);
1244
1245         API_FCT(generate_ores);
1246         API_FCT(generate_decorations);
1247         API_FCT(create_schematic);
1248         API_FCT(place_schematic);
1249         API_FCT(serialize_schematic);
1250 }