Schematics: Prepend mod path to relative schematic filepaths
[oweals/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 "util/serialize.h"
26 #include "server.h"
27 #include "environment.h"
28 #include "emerge.h"
29 #include "mg_biome.h"
30 #include "mg_ore.h"
31 #include "mg_decoration.h"
32 #include "mg_schematic.h"
33 #include "mapgen_v5.h"
34 #include "mapgen_v7.h"
35 #include "filesys.h"
36 #include "settings.h"
37 #include "log.h"
38
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
89 ObjDef *get_objdef(lua_State *L, int index, ObjDefManager *objmgr);
90
91 Biome *get_or_load_biome(lua_State *L, int index,
92         BiomeManager *biomemgr);
93 Biome *read_biome_def(lua_State *L, int index, INodeDefManager *ndef);
94 size_t get_biome_list(lua_State *L, int index,
95         BiomeManager *biomemgr, std::set<u8> *biome_id_list);
96
97 Schematic *get_or_load_schematic(lua_State *L, int index,
98         SchematicManager *schemmgr, StringMap *replace_names);
99 Schematic *read_schematic_def(lua_State *L, int index,
100         INodeDefManager *ndef, StringMap *replace_names);
101 Schematic *load_schematic(lua_State *L, int index,
102         SchematicManager *schemmgr, StringMap *replace_names);
103
104 bool read_deco_simple(lua_State *L, NodeResolveInfo *nri, DecoSimple *deco);
105 bool read_deco_schematic(lua_State *L, SchematicManager *schemmgr, DecoSchematic *deco);
106
107
108 ///////////////////////////////////////////////////////////////////////////////
109
110
111 ObjDef *get_objdef(lua_State *L, int index, ObjDefManager *objmgr)
112 {
113         if (index < 0)
114                 index = lua_gettop(L) + 1 + index;
115
116         // If a number, assume this is a handle to an object def
117         if (lua_isnumber(L, index))
118                 return objmgr->get(lua_tointeger(L, index));
119
120         // If a string, assume a name is given instead
121         if (lua_isstring(L, index))
122                 return objmgr->getByName(lua_tostring(L, index));
123
124         return NULL;
125 }
126
127
128 Schematic *load_schematic(lua_State *L, int index,
129         SchematicManager *schemmgr, StringMap *replace_names)
130 {
131         if (index < 0)
132                 index = lua_gettop(L) + 1 + index;
133
134         Schematic *schem;
135
136         if (lua_istable(L, index)) {
137                 schem = read_schematic_def(L, index, schemmgr->getNodeDef(), replace_names);
138                 if (!schem) {
139                         delete schem;
140                         return NULL;
141                 }
142         } else if (lua_isnumber(L, index)) {
143                 return NULL;
144         } else if (lua_isstring(L, index)) {
145                 schem = SchematicManager::create(SCHEMATIC_NORMAL);
146
147                 std::string filepath = lua_tostring(L, index);
148                 if (!fs::IsPathAbsolute(filepath))
149                         filepath = ModApiBase::getCurrentModPath(L) + DIR_DELIM + filepath;
150
151                 if (!schem->loadSchematicFromFile(filepath.c_str(),
152                                 schemmgr->getNodeDef(), replace_names)) {
153                         delete schem;
154                         return NULL;
155                 }
156         } else {
157                 return NULL;
158         }
159
160         return schem;
161 }
162
163
164 Biome *get_or_load_biome(lua_State *L, int index, BiomeManager *biomemgr)
165 {
166         if (index < 0)
167                 index = lua_gettop(L) + 1 + index;
168
169         Biome *biome = (Biome *)get_objdef(L, index, biomemgr);
170         if (biome)
171                 return biome;
172
173         biome = read_biome_def(L, index, biomemgr->getNodeDef());
174         if (!biome)
175                 return NULL;
176
177         if (biomemgr->add(biome) == OBJDEF_INVALID_HANDLE) {
178                 delete biome;
179                 return NULL;
180         }
181
182         return biome;
183 }
184
185
186 Biome *read_biome_def(lua_State *L, int index, INodeDefManager *ndef)
187 {
188         if (!lua_istable(L, index))
189                 return NULL;
190
191         BiomeType biometype = (BiomeType)getenumfield(L, index, "type",
192                 ModApiMapgen::es_BiomeTerrainType, BIOME_NORMAL);
193         Biome *b = BiomeManager::create(biometype);
194
195         b->name            = getstringfield_default(L, index, "name", "");
196         b->depth_top       = getintfield_default(L, index, "depth_top",          1);
197         b->depth_filler    = getintfield_default(L, index, "depth_filler",       2);
198         b->depth_water_top = getintfield_default(L, index, "depth_water_top",    0);
199         b->y_min           = getintfield_default(L, index, "y_min",         -31000);
200         b->y_max           = getintfield_default(L, index, "y_max",          31000);
201         b->heat_point      = getfloatfield_default(L, index, "heat_point",     0.f);
202         b->humidity_point  = getfloatfield_default(L, index, "humidity_point", 0.f);
203         b->flags           = 0; //reserved
204
205         NodeResolveInfo *nri = new NodeResolveInfo(b);
206         std::list<std::string> &nnames = nri->nodenames;
207         nnames.push_back(getstringfield_default(L, index, "node_top",       ""));
208         nnames.push_back(getstringfield_default(L, index, "node_filler",    ""));
209         nnames.push_back(getstringfield_default(L, index, "node_stone",     ""));
210         nnames.push_back(getstringfield_default(L, index, "node_water_top", ""));
211         nnames.push_back(getstringfield_default(L, index, "node_water",     ""));
212         nnames.push_back(getstringfield_default(L, index, "node_dust",      ""));
213         ndef->pendNodeResolve(nri);
214
215         return b;
216 }
217
218
219 size_t get_biome_list(lua_State *L, int index,
220         BiomeManager *biomemgr, std::set<u8> *biome_id_list)
221 {
222         if (index < 0)
223                 index = lua_gettop(L) + 1 + index;
224
225         if (lua_isnil(L, index))
226                 return 0;
227
228         bool is_single = true;
229         if (lua_istable(L, index)) {
230                 lua_getfield(L, index, "name");
231                 is_single = !lua_isnil(L, -1);
232                 lua_pop(L, 1);
233         }
234
235         if (is_single) {
236                 Biome *biome = get_or_load_biome(L, index, biomemgr);
237                 if (!biome) {
238                         errorstream << "get_biome_list: failed to get biome" << std::endl;
239                         return 1;
240                 }
241
242                 biome_id_list->insert(biome->index);
243                 return 0;
244         }
245
246         // returns number of failed resolutions
247         size_t fail_count = 0;
248         size_t count = 0;
249
250         for (lua_pushnil(L); lua_next(L, index); lua_pop(L, 1)) {
251                 count++;
252                 Biome *biome = get_or_load_biome(L, -1, biomemgr);
253                 if (!biome) {
254                         fail_count++;
255                         errorstream << "get_biome_list: failed to load biome (index "
256                                 << count << ")" << std::endl;
257                         continue;
258                 }
259
260                 biome_id_list->insert(biome->index);
261         }
262
263         return fail_count;
264 }
265
266
267 Schematic *get_or_load_schematic(lua_State *L, int index,
268         SchematicManager *schemmgr, StringMap *replace_names)
269 {
270         if (index < 0)
271                 index = lua_gettop(L) + 1 + index;
272
273         Schematic *schem = (Schematic *)get_objdef(L, index, schemmgr);
274         if (schem)
275                 return schem;
276
277         schem = load_schematic(L, index, schemmgr, replace_names);
278         if (!schem)
279                 return NULL;
280
281         if (schemmgr->add(schem) == OBJDEF_INVALID_HANDLE) {
282                 delete schem;
283                 return NULL;
284         }
285
286         return schem;
287 }
288
289
290 Schematic *read_schematic_def(lua_State *L, int index,
291         INodeDefManager *ndef, StringMap *replace_names)
292 {
293         if (!lua_istable(L, index))
294                 return NULL;
295
296         //// Get schematic size
297         lua_getfield(L, index, "size");
298         v3s16 size = read_v3s16(L, -1);
299         lua_pop(L, 1);
300
301         //// Get schematic data
302         lua_getfield(L, index, "data");
303         luaL_checktype(L, -1, LUA_TTABLE);
304
305         int numnodes = size.X * size.Y * size.Z;
306         MapNode *schemdata = new MapNode[numnodes];
307         int i = 0;
308
309         lua_pushnil(L);
310         while (lua_next(L, -2)) {
311                 if (i >= numnodes) {
312                         i++;
313                         lua_pop(L, 1);
314                         continue;
315                 }
316
317                 // same as readnode, except param1 default is MTSCHEM_PROB_CONST
318                 lua_getfield(L, -1, "name");
319                 std::string name = luaL_checkstring(L, -1);
320                 lua_pop(L, 1);
321
322                 u8 param1;
323                 lua_getfield(L, -1, "param1");
324                 param1 = !lua_isnil(L, -1) ? lua_tonumber(L, -1) : MTSCHEM_PROB_ALWAYS;
325                 lua_pop(L, 1);
326
327                 u8 param2;
328                 lua_getfield(L, -1, "param2");
329                 param2 = !lua_isnil(L, -1) ? lua_tonumber(L, -1) : 0;
330                 lua_pop(L, 1);
331
332                 StringMap::iterator it = replace_names->find(name);
333                 if (it != replace_names->end())
334                         name = it->second;
335
336                 schemdata[i] = MapNode(ndef, name, param1, param2);
337
338                 i++;
339                 lua_pop(L, 1);
340         }
341
342         if (i != numnodes) {
343                 errorstream << "read_schematic: incorrect number of "
344                         "nodes provided in raw schematic data (got " << i <<
345                         ", expected " << numnodes << ")." << std::endl;
346                 delete schemdata;
347                 return NULL;
348         }
349
350         //// Get Y-slice probability values (if present)
351         u8 *slice_probs = new u8[size.Y];
352         for (i = 0; i != size.Y; i++)
353                 slice_probs[i] = MTSCHEM_PROB_ALWAYS;
354
355         lua_getfield(L, index, "yslice_prob");
356         if (lua_istable(L, -1)) {
357                 lua_pushnil(L);
358                 while (lua_next(L, -2)) {
359                         if (getintfield(L, -1, "ypos", i) && i >= 0 && i < size.Y) {
360                                 slice_probs[i] = getintfield_default(L, -1,
361                                         "prob", MTSCHEM_PROB_ALWAYS);
362                         }
363                         lua_pop(L, 1);
364                 }
365         }
366
367         Schematic *schem = SchematicManager::create(SCHEMATIC_NORMAL);
368
369         // Here, we read the nodes directly from the INodeDefManager - there is no
370         // need for pending node resolutions so we'll mark this schematic as updated
371         schem->flags       = SCHEM_CIDS_UPDATED;
372
373         schem->size        = size;
374         schem->schemdata   = schemdata;
375         schem->slice_probs = slice_probs;
376         return schem;
377 }
378
379
380 void read_schematic_replacements(lua_State *L, int index, StringMap *replace_names)
381 {
382         if (index < 0)
383                 index = lua_gettop(L) + 1 + index;
384
385         lua_pushnil(L);
386         while (lua_next(L, index)) {
387                 std::string replace_from;
388                 std::string replace_to;
389
390                 if (lua_istable(L, -1)) { // Old {{"x", "y"}, ...} format
391                         lua_rawgeti(L, -1, 1);
392                         replace_from = lua_tostring(L, -1);
393                         lua_pop(L, 1);
394
395                         lua_rawgeti(L, -1, 2);
396                         replace_to = lua_tostring(L, -1);
397                         lua_pop(L, 1);
398                 } else { // New {x = "y", ...} format
399                         replace_from = lua_tostring(L, -2);
400                         replace_to = lua_tostring(L, -1);
401                 }
402
403                 replace_names->insert(std::make_pair(replace_from, replace_to));
404                 lua_pop(L, 1);
405         }
406 }
407
408
409 ///////////////////////////////////////////////////////////////////////////////
410
411
412 // get_mapgen_object(objectname)
413 // returns the requested object used during map generation
414 int ModApiMapgen::l_get_mapgen_object(lua_State *L)
415 {
416         const char *mgobjstr = lua_tostring(L, 1);
417
418         int mgobjint;
419         if (!string_to_enum(es_MapgenObject, mgobjint, mgobjstr ? mgobjstr : ""))
420                 return 0;
421
422         enum MapgenObject mgobj = (MapgenObject)mgobjint;
423
424         EmergeManager *emerge = getServer(L)->getEmergeManager();
425         Mapgen *mg = emerge->getCurrentMapgen();
426         if (!mg)
427                 return 0;
428
429         size_t maplen = mg->csize.X * mg->csize.Z;
430
431         switch (mgobj) {
432         case MGOBJ_VMANIP: {
433                 MMVManip *vm = mg->vm;
434
435                 // VoxelManip object
436                 LuaVoxelManip *o = new LuaVoxelManip(vm, true);
437                 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
438                 luaL_getmetatable(L, "VoxelManip");
439                 lua_setmetatable(L, -2);
440
441                 // emerged min pos
442                 push_v3s16(L, vm->m_area.MinEdge);
443
444                 // emerged max pos
445                 push_v3s16(L, vm->m_area.MaxEdge);
446
447                 return 3;
448         }
449         case MGOBJ_HEIGHTMAP: {
450                 if (!mg->heightmap)
451                         return 0;
452
453                 lua_newtable(L);
454                 for (size_t i = 0; i != maplen; i++) {
455                         lua_pushinteger(L, mg->heightmap[i]);
456                         lua_rawseti(L, -2, i + 1);
457                 }
458
459                 return 1;
460         }
461         case MGOBJ_BIOMEMAP: {
462                 if (!mg->biomemap)
463                         return 0;
464
465                 lua_newtable(L);
466                 for (size_t i = 0; i != maplen; i++) {
467                         lua_pushinteger(L, mg->biomemap[i]);
468                         lua_rawseti(L, -2, i + 1);
469                 }
470
471                 return 1;
472         }
473         case MGOBJ_HEATMAP: { // Mapgen V7 specific objects
474         case MGOBJ_HUMIDMAP:
475                 if (strcmp(emerge->params.mg_name.c_str(), "v7"))
476                         return 0;
477
478                 MapgenV7 *mgv7 = (MapgenV7 *)mg;
479
480                 float *arr = (mgobj == MGOBJ_HEATMAP) ?
481                         mgv7->noise_heat->result : mgv7->noise_humidity->result;
482                 if (!arr)
483                         return 0;
484
485                 lua_newtable(L);
486                 for (size_t i = 0; i != maplen; i++) {
487                         lua_pushnumber(L, arr[i]);
488                         lua_rawseti(L, -2, i + 1);
489                 }
490
491                 return 1;
492         }
493         case MGOBJ_GENNOTIFY: {
494                 std::map<std::string, std::vector<v3s16> >event_map;
495                 std::map<std::string, std::vector<v3s16> >::iterator it;
496
497                 mg->gennotify.getEvents(event_map);
498
499                 lua_newtable(L);
500                 for (it = event_map.begin(); it != event_map.end(); ++it) {
501                         lua_newtable(L);
502
503                         for (size_t j = 0; j != it->second.size(); j++) {
504                                 push_v3s16(L, it->second[j]);
505                                 lua_rawseti(L, -2, j + 1);
506                         }
507
508                         lua_setfield(L, -2, it->first.c_str());
509                 }
510
511                 return 1;
512         }
513         }
514
515         return 0;
516 }
517
518
519 int ModApiMapgen::l_get_mapgen_params(lua_State *L)
520 {
521         MapgenParams *params = &getServer(L)->getEmergeManager()->params;
522
523         lua_newtable(L);
524
525         lua_pushstring(L, params->mg_name.c_str());
526         lua_setfield(L, -2, "mgname");
527
528         lua_pushinteger(L, params->seed);
529         lua_setfield(L, -2, "seed");
530
531         lua_pushinteger(L, params->water_level);
532         lua_setfield(L, -2, "water_level");
533
534         lua_pushinteger(L, params->chunksize);
535         lua_setfield(L, -2, "chunksize");
536
537         std::string flagstr = writeFlagString(params->flags, flagdesc_mapgen, (u32)-1);
538         lua_pushstring(L, flagstr.c_str());
539         lua_setfield(L, -2, "flags");
540
541         return 1;
542 }
543
544
545 // set_mapgen_params(params)
546 // set mapgen parameters
547 int ModApiMapgen::l_set_mapgen_params(lua_State *L)
548 {
549         if (!lua_istable(L, 1))
550                 return 0;
551
552         MapgenParams *params = &getServer(L)->getEmergeManager()->params;
553         u32 flags = 0, flagmask = 0;
554
555         lua_getfield(L, 1, "mgname");
556         if (lua_isstring(L, -1)) {
557                 params->mg_name = lua_tostring(L, -1);
558                 delete params->sparams;
559                 params->sparams = NULL;
560         }
561
562         lua_getfield(L, 1, "seed");
563         if (lua_isnumber(L, -1))
564                 params->seed = lua_tointeger(L, -1);
565
566         lua_getfield(L, 1, "water_level");
567         if (lua_isnumber(L, -1))
568                 params->water_level = lua_tointeger(L, -1);
569
570         warn_if_field_exists(L, 1, "flagmask",
571                 "Deprecated: flags field now includes unset flags.");
572         lua_getfield(L, 1, "flagmask");
573         if (lua_isstring(L, -1))
574                 params->flags &= ~readFlagString(lua_tostring(L, -1), flagdesc_mapgen, NULL);
575
576         if (getflagsfield(L, 1, "flags", flagdesc_mapgen, &flags, &flagmask)) {
577                 params->flags &= ~flagmask;
578                 params->flags |= flags;
579         }
580
581         return 0;
582 }
583
584
585 // set_noiseparams(name, noiseparams, set_default)
586 // set global config values for noise parameters
587 int ModApiMapgen::l_set_noiseparams(lua_State *L)
588 {
589         const char *name = luaL_checkstring(L, 1);
590
591         NoiseParams np;
592         if (!read_noiseparams(L, 2, &np))
593                 return 0;
594
595         bool set_default = lua_isboolean(L, 3) ? lua_toboolean(L, 3) : true;
596
597         g_settings->setNoiseParams(name, np, set_default);
598
599         return 0;
600 }
601
602
603 // set_gen_notify(flags, {deco_id_table})
604 int ModApiMapgen::l_set_gen_notify(lua_State *L)
605 {
606         u32 flags = 0, flagmask = 0;
607         EmergeManager *emerge = getServer(L)->getEmergeManager();
608
609         if (read_flags(L, 1, flagdesc_gennotify, &flags, &flagmask)) {
610                 emerge->gen_notify_on &= ~flagmask;
611                 emerge->gen_notify_on |= flags;
612         }
613
614         if (lua_istable(L, 2)) {
615                 lua_pushnil(L);
616                 while (lua_next(L, 2)) {
617                         if (lua_isnumber(L, -1))
618                                 emerge->gen_notify_on_deco_ids.insert(lua_tonumber(L, -1));
619                         lua_pop(L, 1);
620                 }
621         }
622
623         return 0;
624 }
625
626
627 // register_biome({lots of stuff})
628 int ModApiMapgen::l_register_biome(lua_State *L)
629 {
630         int index = 1;
631         luaL_checktype(L, index, LUA_TTABLE);
632
633         INodeDefManager *ndef = getServer(L)->getNodeDefManager();
634         BiomeManager *bmgr    = getServer(L)->getEmergeManager()->biomemgr;
635
636         Biome *biome = read_biome_def(L, index, ndef);
637         if (!biome)
638                 return 0;
639
640         ObjDefHandle handle = bmgr->add(biome);
641         if (handle == OBJDEF_INVALID_HANDLE) {
642                 delete biome;
643                 return 0;
644         }
645
646         lua_pushinteger(L, handle);
647         return 1;
648 }
649
650
651 // register_decoration({lots of stuff})
652 int ModApiMapgen::l_register_decoration(lua_State *L)
653 {
654         int index = 1;
655         luaL_checktype(L, index, LUA_TTABLE);
656
657         INodeDefManager *ndef      = getServer(L)->getNodeDefManager();
658         DecorationManager *decomgr = getServer(L)->getEmergeManager()->decomgr;
659         BiomeManager *biomemgr     = getServer(L)->getEmergeManager()->biomemgr;
660         SchematicManager *schemmgr = getServer(L)->getEmergeManager()->schemmgr;
661
662         enum DecorationType decotype = (DecorationType)getenumfield(L, index,
663                                 "deco_type", es_DecorationType, -1);
664
665         Decoration *deco = decomgr->create(decotype);
666         if (!deco) {
667                 errorstream << "register_decoration: decoration placement type "
668                         << decotype << " not implemented" << std::endl;
669                 return 0;
670         }
671
672         deco->name       = getstringfield_default(L, index, "name", "");
673         deco->fill_ratio = getfloatfield_default(L, index, "fill_ratio", 0.02);
674         deco->y_min      = getintfield_default(L, index, "y_min", -31000);
675         deco->y_max      = getintfield_default(L, index, "y_max", 31000);
676         deco->sidelen    = getintfield_default(L, index, "sidelen", 8);
677         if (deco->sidelen <= 0) {
678                 errorstream << "register_decoration: sidelen must be "
679                         "greater than 0" << std::endl;
680                 delete deco;
681                 return 0;
682         }
683
684         NodeResolveInfo *nri = new NodeResolveInfo(deco);
685
686         //// Get node name(s) to place decoration on
687         std::vector<const char *> place_on_names;
688         getstringlistfield(L, index, "place_on", place_on_names);
689         nri->nodelistinfo.push_back(NodeListInfo(place_on_names.size()));
690         for (size_t i = 0; i != place_on_names.size(); i++)
691                 nri->nodenames.push_back(place_on_names[i]);
692
693         getflagsfield(L, index, "flags", flagdesc_deco, &deco->flags, NULL);
694
695         //// Get NoiseParams to define how decoration is placed
696         lua_getfield(L, index, "noise_params");
697         if (read_noiseparams(L, -1, &deco->np))
698                 deco->flags |= DECO_USE_NOISE;
699         lua_pop(L, 1);
700
701         //// Get biomes associated with this decoration (if any)
702         lua_getfield(L, index, "biomes");
703         if (get_biome_list(L, -1, biomemgr, &deco->biomes))
704                 errorstream << "register_decoration: couldn't get all biomes " << std::endl;
705         lua_pop(L, 1);
706
707         //// Handle decoration type-specific parameters
708         bool success = false;
709         switch (decotype) {
710         case DECO_SIMPLE:
711                 success = read_deco_simple(L, nri, (DecoSimple *)deco);
712                 break;
713         case DECO_SCHEMATIC:
714                 success = read_deco_schematic(L, schemmgr, (DecoSchematic *)deco);
715                 break;
716         case DECO_LSYSTEM:
717                 break;
718         }
719
720         ndef->pendNodeResolve(nri);
721
722         if (!success) {
723                 delete deco;
724                 return 0;
725         }
726
727         ObjDefHandle handle = decomgr->add(deco);
728         if (handle == OBJDEF_INVALID_HANDLE) {
729                 delete deco;
730                 return 0;
731         }
732
733         lua_pushinteger(L, handle);
734         return 1;
735 }
736
737
738 bool read_deco_simple(lua_State *L, NodeResolveInfo *nri, DecoSimple *deco)
739 {
740         int index = 1;
741
742         deco->deco_height     = getintfield_default(L, index, "height", 1);
743         deco->deco_height_max = getintfield_default(L, index, "height_max", 0);
744         deco->nspawnby        = getintfield_default(L, index, "num_spawn_by", -1);
745
746         if (deco->deco_height <= 0) {
747                 errorstream << "register_decoration: simple decoration height"
748                         " must be greater than 0" << std::endl;
749                 return false;
750         }
751
752         std::vector<const char *> deco_names;
753         getstringlistfield(L, index, "decoration", deco_names);
754         if (deco_names.size() == 0) {
755                 errorstream << "register_decoration: no decoration nodes "
756                         "defined" << std::endl;
757                 return false;
758         }
759         nri->nodelistinfo.push_back(NodeListInfo(deco_names.size()));
760         for (size_t i = 0; i != deco_names.size(); i++)
761                 nri->nodenames.push_back(deco_names[i]);
762
763         std::vector<const char *> spawnby_names;
764         getstringlistfield(L, index, "spawn_by", spawnby_names);
765         if (deco->nspawnby != -1 && spawnby_names.size() == 0) {
766                 errorstream << "register_decoration: no spawn_by nodes defined,"
767                         " but num_spawn_by specified" << std::endl;
768                 return false;
769         }
770         nri->nodelistinfo.push_back(NodeListInfo(spawnby_names.size()));
771         for (size_t i = 0; i != spawnby_names.size(); i++)
772                 nri->nodenames.push_back(spawnby_names[i]);
773
774         return true;
775 }
776
777
778 bool read_deco_schematic(lua_State *L, SchematicManager *schemmgr, DecoSchematic *deco)
779 {
780         int index = 1;
781
782         deco->rotation = (Rotation)getenumfield(L, index, "rotation",
783                 ModApiMapgen::es_Rotation, ROTATE_0);
784
785         StringMap replace_names;
786         lua_getfield(L, index, "replacements");
787         if (lua_istable(L, -1))
788                 read_schematic_replacements(L, -1, &replace_names);
789         lua_pop(L, 1);
790
791         lua_getfield(L, index, "schematic");
792         Schematic *schem = get_or_load_schematic(L, -1, schemmgr, &replace_names);
793         lua_pop(L, 1);
794
795         deco->schematic = schem;
796         return schem != NULL;
797 }
798
799
800 // register_ore({lots of stuff})
801 int ModApiMapgen::l_register_ore(lua_State *L)
802 {
803         int index = 1;
804         luaL_checktype(L, index, LUA_TTABLE);
805
806         INodeDefManager *ndef = getServer(L)->getNodeDefManager();
807         OreManager *oremgr    = getServer(L)->getEmergeManager()->oremgr;
808
809         enum OreType oretype = (OreType)getenumfield(L, index,
810                                 "ore_type", es_OreType, ORE_SCATTER);
811         Ore *ore = oremgr->create(oretype);
812         if (!ore) {
813                 errorstream << "register_ore: ore_type " << oretype << " not implemented";
814                 return 0;
815         }
816
817         ore->name           = getstringfield_default(L, index, "name", "");
818         ore->ore_param2     = (u8)getintfield_default(L, index, "ore_param2", 0);
819         ore->clust_scarcity = getintfield_default(L, index, "clust_scarcity", 1);
820         ore->clust_num_ores = getintfield_default(L, index, "clust_num_ores", 1);
821         ore->clust_size     = getintfield_default(L, index, "clust_size", 0);
822         ore->nthresh        = getfloatfield_default(L, index, "noise_threshhold", 0);
823         ore->noise          = NULL;
824         ore->flags          = 0;
825
826         warn_if_field_exists(L, index, "height_min",
827                 "Deprecated: new name is \"y_min\".");
828         warn_if_field_exists(L, index, "height_max",
829                 "Deprecated: new name is \"y_max\".");
830
831         int ymin, ymax;
832         if (!getintfield(L, index, "y_min", ymin) &&
833                 !getintfield(L, index, "height_min", ymin))
834                 ymin = -31000;
835         if (!getintfield(L, index, "y_max", ymax) &&
836                 !getintfield(L, index, "height_max", ymax))
837                 ymax = 31000;
838         ore->y_min = ymin;
839         ore->y_max = ymax;
840
841         if (ore->clust_scarcity <= 0 || ore->clust_num_ores <= 0) {
842                 errorstream << "register_ore: clust_scarcity and clust_num_ores"
843                         "must be greater than 0" << std::endl;
844                 delete ore;
845                 return 0;
846         }
847
848         getflagsfield(L, index, "flags", flagdesc_ore, &ore->flags, NULL);
849
850         lua_getfield(L, index, "noise_params");
851         if (read_noiseparams(L, -1, &ore->np)) {
852                 ore->flags |= OREFLAG_USE_NOISE;
853         } else if (ore->NEEDS_NOISE) {
854                 errorstream << "register_ore: specified ore type requires valid "
855                         "noise parameters" << std::endl;
856                 delete ore;
857                 return 0;
858         }
859         lua_pop(L, 1);
860
861         if (oretype == ORE_VEIN) {
862                 OreVein *orevein = (OreVein *)ore;
863                 orevein->random_factor = getfloatfield_default(L, index,
864                         "random_factor", 1.f);
865         }
866
867         ObjDefHandle handle = oremgr->add(ore);
868         if (handle == OBJDEF_INVALID_HANDLE) {
869                 delete ore;
870                 return 0;
871         }
872
873         NodeResolveInfo *nri = new NodeResolveInfo(ore);
874         nri->nodenames.push_back(getstringfield_default(L, index, "ore", ""));
875
876         std::vector<const char *> wherein_names;
877         getstringlistfield(L, index, "wherein", wherein_names);
878         nri->nodelistinfo.push_back(NodeListInfo(wherein_names.size()));
879         for (size_t i = 0; i != wherein_names.size(); i++)
880                 nri->nodenames.push_back(wherein_names[i]);
881
882         ndef->pendNodeResolve(nri);
883
884         lua_pushinteger(L, handle);
885         return 1;
886 }
887
888
889 // register_schematic({schematic}, replacements={})
890 int ModApiMapgen::l_register_schematic(lua_State *L)
891 {
892         SchematicManager *schemmgr = getServer(L)->getEmergeManager()->schemmgr;
893
894         StringMap replace_names;
895         if (lua_istable(L, 2))
896                 read_schematic_replacements(L, 2, &replace_names);
897
898         Schematic *schem = load_schematic(L, 1, schemmgr, &replace_names);
899         if (!schem)
900                 return 0;
901
902         ObjDefHandle handle = schemmgr->add(schem);
903         if (handle == OBJDEF_INVALID_HANDLE) {
904                 delete schem;
905                 return 0;
906         }
907
908         lua_pushinteger(L, handle);
909         return 1;
910 }
911
912
913 // clear_registered_biomes()
914 int ModApiMapgen::l_clear_registered_biomes(lua_State *L)
915 {
916         BiomeManager *bmgr = getServer(L)->getEmergeManager()->biomemgr;
917         bmgr->clear();
918         return 0;
919 }
920
921
922 // clear_registered_decorations()
923 int ModApiMapgen::l_clear_registered_decorations(lua_State *L)
924 {
925         DecorationManager *dmgr = getServer(L)->getEmergeManager()->decomgr;
926         dmgr->clear();
927         return 0;
928 }
929
930
931 // clear_registered_ores()
932 int ModApiMapgen::l_clear_registered_ores(lua_State *L)
933 {
934         OreManager *omgr = getServer(L)->getEmergeManager()->oremgr;
935         omgr->clear();
936         return 0;
937 }
938
939
940 // clear_registered_schematics()
941 int ModApiMapgen::l_clear_registered_schematics(lua_State *L)
942 {
943         SchematicManager *smgr = getServer(L)->getEmergeManager()->schemmgr;
944         smgr->clear();
945         return 0;
946 }
947
948
949 // generate_ores(vm, p1, p2, [ore_id])
950 int ModApiMapgen::l_generate_ores(lua_State *L)
951 {
952         EmergeManager *emerge = getServer(L)->getEmergeManager();
953
954         Mapgen mg;
955         mg.seed = emerge->params.seed;
956         mg.vm   = LuaVoxelManip::checkobject(L, 1)->vm;
957         mg.ndef = getServer(L)->getNodeDefManager();
958
959         v3s16 pmin = lua_istable(L, 2) ? read_v3s16(L, 2) :
960                         mg.vm->m_area.MinEdge + v3s16(1,1,1) * MAP_BLOCKSIZE;
961         v3s16 pmax = lua_istable(L, 3) ? read_v3s16(L, 3) :
962                         mg.vm->m_area.MaxEdge - v3s16(1,1,1) * MAP_BLOCKSIZE;
963         sortBoxVerticies(pmin, pmax);
964
965         u32 blockseed = Mapgen::getBlockSeed(pmin, mg.seed);
966
967         emerge->oremgr->placeAllOres(&mg, blockseed, pmin, pmax);
968
969         return 0;
970 }
971
972
973 // generate_decorations(vm, p1, p2, [deco_id])
974 int ModApiMapgen::l_generate_decorations(lua_State *L)
975 {
976         EmergeManager *emerge = getServer(L)->getEmergeManager();
977
978         Mapgen mg;
979         mg.seed = emerge->params.seed;
980         mg.vm   = LuaVoxelManip::checkobject(L, 1)->vm;
981         mg.ndef = getServer(L)->getNodeDefManager();
982
983         v3s16 pmin = lua_istable(L, 2) ? read_v3s16(L, 2) :
984                         mg.vm->m_area.MinEdge + v3s16(1,1,1) * MAP_BLOCKSIZE;
985         v3s16 pmax = lua_istable(L, 3) ? read_v3s16(L, 3) :
986                         mg.vm->m_area.MaxEdge - v3s16(1,1,1) * MAP_BLOCKSIZE;
987         sortBoxVerticies(pmin, pmax);
988
989         u32 blockseed = Mapgen::getBlockSeed(pmin, mg.seed);
990
991         emerge->decomgr->placeAllDecos(&mg, blockseed, pmin, pmax);
992
993         return 0;
994 }
995
996
997 // create_schematic(p1, p2, probability_list, filename, y_slice_prob_list)
998 int ModApiMapgen::l_create_schematic(lua_State *L)
999 {
1000         Schematic schem;
1001
1002         Map *map = &(getEnv(L)->getMap());
1003         INodeDefManager *ndef = getServer(L)->getNodeDefManager();
1004
1005         v3s16 p1 = read_v3s16(L, 1);
1006         v3s16 p2 = read_v3s16(L, 2);
1007         sortBoxVerticies(p1, p2);
1008
1009         std::vector<std::pair<v3s16, u8> > prob_list;
1010         if (lua_istable(L, 3)) {
1011                 lua_pushnil(L);
1012                 while (lua_next(L, 3)) {
1013                         if (lua_istable(L, -1)) {
1014                                 lua_getfield(L, -1, "pos");
1015                                 v3s16 pos = read_v3s16(L, -1);
1016                                 lua_pop(L, 1);
1017
1018                                 u8 prob = getintfield_default(L, -1, "prob", MTSCHEM_PROB_ALWAYS);
1019                                 prob_list.push_back(std::make_pair(pos, prob));
1020                         }
1021
1022                         lua_pop(L, 1);
1023                 }
1024         }
1025
1026         std::vector<std::pair<s16, u8> > slice_prob_list;
1027         if (lua_istable(L, 5)) {
1028                 lua_pushnil(L);
1029                 while (lua_next(L, 5)) {
1030                         if (lua_istable(L, -1)) {
1031                                 s16 ypos = getintfield_default(L, -1, "ypos", 0);
1032                                 u8 prob  = getintfield_default(L, -1, "prob", MTSCHEM_PROB_ALWAYS);
1033                                 slice_prob_list.push_back(std::make_pair(ypos, prob));
1034                         }
1035
1036                         lua_pop(L, 1);
1037                 }
1038         }
1039
1040         const char *filename = luaL_checkstring(L, 4);
1041
1042         if (!schem.getSchematicFromMap(map, p1, p2)) {
1043                 errorstream << "create_schematic: failed to get schematic "
1044                         "from map" << std::endl;
1045                 return 0;
1046         }
1047
1048         schem.applyProbabilities(p1, &prob_list, &slice_prob_list);
1049
1050         schem.saveSchematicToFile(filename, ndef);
1051         actionstream << "create_schematic: saved schematic file '"
1052                 << filename << "'." << std::endl;
1053
1054         lua_pushboolean(L, true);
1055         return 1;
1056 }
1057
1058
1059 // place_schematic(p, schematic, rotation, replacement)
1060 int ModApiMapgen::l_place_schematic(lua_State *L)
1061 {
1062         Map *map = &(getEnv(L)->getMap());
1063         SchematicManager *schemmgr = getServer(L)->getEmergeManager()->schemmgr;
1064
1065         //// Read position
1066         v3s16 p = read_v3s16(L, 1);
1067
1068         //// Read rotation
1069         int rot = ROTATE_0;
1070         if (lua_isstring(L, 3))
1071                 string_to_enum(es_Rotation, rot, std::string(lua_tostring(L, 3)));
1072
1073         //// Read force placement
1074         bool force_placement = true;
1075         if (lua_isboolean(L, 5))
1076                 force_placement = lua_toboolean(L, 5);
1077
1078         //// Read node replacements
1079         StringMap replace_names;
1080         if (lua_istable(L, 4))
1081                 read_schematic_replacements(L, 4, &replace_names);
1082
1083         //// Read schematic
1084         Schematic *schem = get_or_load_schematic(L, 2, schemmgr, &replace_names);
1085         if (!schem) {
1086                 errorstream << "place_schematic: failed to get schematic" << std::endl;
1087                 return 0;
1088         }
1089
1090         schem->placeStructure(map, p, 0, (Rotation)rot, force_placement,
1091                 schemmgr->getNodeDef());
1092
1093         lua_pushboolean(L, true);
1094         return 1;
1095 }
1096
1097
1098 void ModApiMapgen::Initialize(lua_State *L, int top)
1099 {
1100         API_FCT(get_mapgen_object);
1101
1102         API_FCT(get_mapgen_params);
1103         API_FCT(set_mapgen_params);
1104         API_FCT(set_noiseparams);
1105         API_FCT(set_gen_notify);
1106
1107         API_FCT(register_biome);
1108         API_FCT(register_decoration);
1109         API_FCT(register_ore);
1110         API_FCT(register_schematic);
1111
1112         API_FCT(clear_registered_biomes);
1113         API_FCT(clear_registered_decorations);
1114         API_FCT(clear_registered_ores);
1115         API_FCT(clear_registered_schematics);
1116
1117         API_FCT(generate_ores);
1118         API_FCT(generate_decorations);
1119         API_FCT(create_schematic);
1120         API_FCT(place_schematic);
1121 }