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