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