]> git.lizzy.rs Git - dragonfireclient.git/blobdiff - src/script/lua_api/luaapi.cpp
Fix my name.
[dragonfireclient.git] / src / script / lua_api / luaapi.cpp
index b75304b3abfc253ce78bba0a75e07fc0f6a565ab..26fb0c318ddf5e0a877c8dcf70d9a1219312bb3e 100644 (file)
@@ -43,6 +43,24 @@ struct EnumString ModApiBasic::es_OreType[] =
        {0, NULL},
 };
 
+struct EnumString ModApiBasic::es_DecorationType[] =
+{
+       {DECO_SIMPLE,    "simple"},
+       {DECO_SCHEMATIC, "schematic"},
+       {DECO_LSYSTEM,   "lsystem"},
+       {0, NULL},
+};
+
+struct EnumString ModApiBasic::es_Rotation[] =
+{
+       {ROTATE_0,    "0"},
+       {ROTATE_90,   "90"},
+       {ROTATE_180,  "180"},
+       {ROTATE_270,  "270"},
+       {ROTATE_RAND, "random"},
+       {0, NULL},
+};
+
 
 ModApiBasic::ModApiBasic() : ModApiBase() {
 }
@@ -72,7 +90,7 @@ bool ModApiBasic::Initialize(lua_State* L,int top) {
        retval &= API_FCT(get_ban_list);
        retval &= API_FCT(get_ban_description);
        retval &= API_FCT(ban_player);
-       retval &= API_FCT(unban_player_of_ip);
+       retval &= API_FCT(unban_player_or_ip);
        retval &= API_FCT(get_password_hash);
        retval &= API_FCT(notify_authentication_modified);
 
@@ -92,17 +110,38 @@ bool ModApiBasic::Initialize(lua_State* L,int top) {
        retval &= API_FCT(rollback_revert_actions_by);
 
        retval &= API_FCT(register_ore);
+       retval &= API_FCT(register_decoration);
+       retval &= API_FCT(create_schematic);
+       retval &= API_FCT(place_schematic);
 
        return retval;
 }
 
-// debug(text)
+// debug(...)
 // Writes a line to dstream
 int ModApiBasic::l_debug(lua_State *L)
 {
        NO_MAP_LOCK_REQUIRED;
-       std::string text = lua_tostring(L, 1);
-       dstream << text << std::endl;
+       // Handle multiple parameters to behave like standard lua print()
+       int n = lua_gettop(L);
+       lua_getglobal(L, "tostring");
+       for(int i = 1; i <= n; i++){
+               /*
+                       Call tostring(i-th argument).
+                       This is what print() does, and it behaves a bit
+                       differently from directly calling lua_tostring.
+               */
+               lua_pushvalue(L, -1);  /* function to be called */
+               lua_pushvalue(L, i);   /* value to print */
+               lua_call(L, 1, 1);
+               const char *s = lua_tostring(L, -1);
+               if(i>1)
+                       dstream << "\t";
+               if(s)
+                       dstream << s;
+               lua_pop(L, 1);
+       }
+       dstream << std::endl;
        return 0;
 }
 
@@ -162,30 +201,42 @@ int ModApiBasic::l_register_biome(lua_State *L)
        }
 
        enum BiomeTerrainType terrain = (BiomeTerrainType)getenumfield(L, index,
-       "terrain_type", es_BiomeTerrainType, BIOME_TERRAIN_NORMAL);
+                               "terrain_type", es_BiomeTerrainType, BIOME_TERRAIN_NORMAL);
        Biome *b = bmgr->createBiome(terrain);
 
-       b->name = getstringfield_default(L, index, "name", "");
-       b->top_nodename = getstringfield_default(L, index, "top_node", "");
-       b->top_depth = getintfield_default(L, index, "top_depth", 0);
-       b->filler_nodename = getstringfield_default(L, index, "filler_node", "");
-       b->filler_height = getintfield_default(L, index, "filler_height", 0);
-       b->height_min = getintfield_default(L, index, "height_min", 0);
-       b->height_max = getintfield_default(L, index, "height_max", 0);
-       b->heat_point = getfloatfield_default(L, index, "heat_point", 0.);
+       b->name         = getstringfield_default(L, index, "name",
+                                                                                               "<no name>");
+       b->nname_top    = getstringfield_default(L, index, "node_top",
+                                                                                               "mapgen_dirt_with_grass");
+       b->nname_filler = getstringfield_default(L, index, "node_filler",
+                                                                                               "mapgen_dirt");
+       b->nname_water  = getstringfield_default(L, index, "node_water",
+                                                                                               "mapgen_water_source");
+       b->nname_dust   = getstringfield_default(L, index, "node_dust",
+                                                                                               "air");
+       b->nname_dust_water = getstringfield_default(L, index, "node_dust_water",
+                                                                                               "mapgen_water_source");
+       
+       b->depth_top      = getintfield_default(L, index, "depth_top",    1);
+       b->depth_filler   = getintfield_default(L, index, "depth_filler", 3);
+       b->height_min     = getintfield_default(L, index, "height_min",   0);
+       b->height_max     = getintfield_default(L, index, "height_max",   0);
+       b->heat_point     = getfloatfield_default(L, index, "heat_point",     0.);
        b->humidity_point = getfloatfield_default(L, index, "humidity_point", 0.);
 
-       b->flags = 0; //reserved
-       b->c_top = CONTENT_IGNORE;
-       b->c_filler = CONTENT_IGNORE;
+       b->flags        = 0; //reserved
+       b->c_top        = CONTENT_IGNORE;
+       b->c_filler     = CONTENT_IGNORE;
+       b->c_water      = CONTENT_IGNORE;
+       b->c_dust       = CONTENT_IGNORE;
+       b->c_dust_water = CONTENT_IGNORE;
+       
+       verbosestream << "register_biome: " << b->name << std::endl;
        bmgr->addBiome(b);
 
-       verbosestream << "register_biome: " << b->name << std::endl;
        return 0;
 }
 
-
-
 // setting_set(name, value)
 int ModApiBasic::l_setting_set(lua_State *L)
 {
@@ -353,7 +404,7 @@ int ModApiBasic::l_ban_player(lua_State *L)
 }
 
 // unban_player_or_ip()
-int ModApiBasic::l_unban_player_of_ip(lua_State *L)
+int ModApiBasic::l_unban_player_or_ip(lua_State *L)
 {
        NO_MAP_LOCK_REQUIRED;
        const char * ip_or_name = luaL_checkstring(L, 1);
@@ -621,7 +672,6 @@ int ModApiBasic::l_register_ore(lua_State *L)
 
        ore->ore_name       = getstringfield_default(L, index, "ore", "");
        ore->ore_param2     = (u8)getintfield_default(L, index, "ore_param2", 0);
-       ore->wherein_name   = getstringfield_default(L, index, "wherein", "");
        ore->clust_scarcity = getintfield_default(L, index, "clust_scarcity", 1);
        ore->clust_num_ores = getintfield_default(L, index, "clust_num_ores", 1);
        ore->clust_size     = getintfield_default(L, index, "clust_size", 0);
@@ -630,6 +680,21 @@ int ModApiBasic::l_register_ore(lua_State *L)
        ore->flags          = getflagsfield(L, index, "flags", flagdesc_ore);
        ore->nthresh        = getfloatfield_default(L, index, "noise_threshhold", 0.);
 
+       lua_getfield(L, index, "wherein");
+       if (lua_istable(L, -1)) {
+               int  i = lua_gettop(L);
+               lua_pushnil(L);
+               while(lua_next(L, i) != 0) {
+                       ore->wherein_names.push_back(lua_tostring(L, -1));
+                       lua_pop(L, 1);
+               }
+       } else if (lua_isstring(L, -1)) {
+               ore->wherein_names.push_back(lua_tostring(L, -1));
+       } else {
+               ore->wherein_names.push_back("");
+       }
+       lua_pop(L, 1);
+
        lua_getfield(L, index, "noise_params");
        ore->np = read_noiseparams(L, -1);
        lua_pop(L, 1);
@@ -650,4 +715,241 @@ int ModApiBasic::l_register_ore(lua_State *L)
        return 0;
 }
 
+// register_decoration({lots of stuff})
+int ModApiBasic::l_register_decoration(lua_State *L)
+{
+       int index = 1;
+       luaL_checktype(L, index, LUA_TTABLE);
+
+       EmergeManager *emerge = getServer(L)->getEmergeManager();
+       BiomeDefManager *bdef = emerge->biomedef;
+
+       enum DecorationType decotype = (DecorationType)getenumfield(L, index,
+                               "deco_type", es_DecorationType, -1);
+       if (decotype == -1) {
+               errorstream << "register_decoration: unrecognized "
+                       "decoration placement type";
+               return 0;
+       }
+       
+       Decoration *deco = createDecoration(decotype);
+       if (!deco) {
+               errorstream << "register_decoration: decoration placement type "
+                       << decotype << " not implemented";
+               return 0;
+       }
+
+       deco->c_place_on    = CONTENT_IGNORE;
+       deco->place_on_name = getstringfield_default(L, index, "place_on", "ignore");
+       deco->fill_ratio    = getfloatfield_default(L, index, "fill_ratio", 0.02);
+       deco->sidelen       = getintfield_default(L, index, "sidelen", 8);
+       if (deco->sidelen <= 0) {
+               errorstream << "register_decoration: sidelen must be "
+                       "greater than 0" << std::endl;
+               delete deco;
+               return 0;
+       }
+       
+       lua_getfield(L, index, "noise_params");
+       deco->np = read_noiseparams(L, -1);
+       lua_pop(L, 1);
+       
+       lua_getfield(L, index, "biomes");
+       if (lua_istable(L, -1)) {
+               lua_pushnil(L);
+               while (lua_next(L, -2)) {
+                       const char *s = lua_tostring(L, -1);
+                       u8 biomeid = bdef->getBiomeIdByName(s);
+                       if (biomeid)
+                               deco->biomes.insert(biomeid);
+
+                       lua_pop(L, 1);
+               }
+               lua_pop(L, 1);
+       }
+       
+       switch (decotype) {
+               case DECO_SIMPLE: {
+                       DecoSimple *dsimple = (DecoSimple *)deco;
+                       dsimple->c_deco     = CONTENT_IGNORE;
+                       dsimple->c_spawnby  = CONTENT_IGNORE;
+                       dsimple->spawnby_name    = getstringfield_default(L, index, "spawn_by", "air");
+                       dsimple->deco_height     = getintfield_default(L, index, "height", 1);
+                       dsimple->deco_height_max = getintfield_default(L, index, "height_max", 0);
+                       dsimple->nspawnby        = getintfield_default(L, index, "num_spawn_by", -1);
+                       
+                       lua_getfield(L, index, "decoration");
+                       if (lua_istable(L, -1)) {
+                               lua_pushnil(L);
+                               while (lua_next(L, -2)) {
+                                       const char *s = lua_tostring(L, -1);
+                                       std::string str(s);
+                                       dsimple->decolist_names.push_back(str);
+
+                                       lua_pop(L, 1);
+                               }
+                       } else if (lua_isstring(L, -1)) {
+                               dsimple->deco_name = std::string(lua_tostring(L, -1));
+                       } else {
+                               dsimple->deco_name = std::string("air");
+                       }
+                       lua_pop(L, 1);
+                       
+                       if (dsimple->deco_height <= 0) {
+                               errorstream << "register_decoration: simple decoration height"
+                                       " must be greater than 0" << std::endl;
+                               delete dsimple;
+                               return 0;
+                       }
+
+                       break; }
+               case DECO_SCHEMATIC: {
+                       DecoSchematic *dschem = (DecoSchematic *)deco;
+                       dschem->flags    = getflagsfield(L, index, "flags", flagdesc_deco_schematic);
+                       dschem->rotation = (Rotation)getenumfield(L, index,
+                                                               "rotation", es_Rotation, ROTATE_0);
+
+                       lua_getfield(L, index, "replacements");
+                       if (lua_istable(L, -1)) {
+                               int i = lua_gettop(L);
+                               lua_pushnil(L);
+                               while (lua_next(L, i) != 0) {
+                                       // key at index -2 and value at index -1
+                                       lua_rawgeti(L, -1, 1);
+                                       std::string replace_from = lua_tostring(L, -1);
+                                       lua_pop(L, 1);
+                                       lua_rawgeti(L, -1, 2);
+                                       std::string replace_to = lua_tostring(L, -1);
+                                       lua_pop(L, 1);
+                                       dschem->replacements[replace_from] = replace_to;
+                                       // removes value, keeps key for next iteration
+                                       lua_pop(L, 1);
+                               }
+                       }
+                       lua_pop(L, 1);
+
+                       lua_getfield(L, index, "schematic");
+                       if (!read_schematic(L, -1, dschem, getServer(L))) {
+                               delete dschem;
+                               return 0;
+                       }
+                       lua_pop(L, -1);
+                       
+                       if (!dschem->filename.empty() && !dschem->loadSchematicFile()) {
+                               errorstream << "register_decoration: failed to load schematic file '"
+                                       << dschem->filename << "'" << std::endl;
+                               delete dschem;
+                               return 0;
+                       }
+                       break; }
+               case DECO_LSYSTEM: {
+                       //DecoLSystem *decolsystem = (DecoLSystem *)deco;
+               
+                       break; }
+       }
+
+       emerge->decorations.push_back(deco);
+
+       verbosestream << "register_decoration: decoration '" << deco->getName()
+               << "' registered" << std::endl;
+       return 0;
+}
+
+// create_schematic(p1, p2, probability_list, filename)
+int ModApiBasic::l_create_schematic(lua_State *L)
+{
+       DecoSchematic dschem;
+
+       Map *map = &(getEnv(L)->getMap());
+       INodeDefManager *ndef = getServer(L)->getNodeDefManager();
+
+       v3s16 p1 = read_v3s16(L, 1);
+       v3s16 p2 = read_v3s16(L, 2);
+       sortBoxVerticies(p1, p2);
+       
+       std::vector<std::pair<v3s16, u8> > probability_list;
+       if (lua_istable(L, 3)) {
+               lua_pushnil(L);
+               while (lua_next(L, 3)) {
+                       if (lua_istable(L, -1)) {
+                               lua_getfield(L, -1, "pos");
+                               v3s16 pos = read_v3s16(L, -1);
+                               lua_pop(L, 1);
+                               
+                               u8 prob = getintfield_default(L, -1, "prob", 0xFF);
+                               probability_list.push_back(std::make_pair(pos, prob));
+                       }
+
+                       lua_pop(L, 1);
+               }
+       }
+       
+       dschem.filename = std::string(lua_tostring(L, 4));
+
+       if (!dschem.getSchematicFromMap(map, p1, p2)) {
+               errorstream << "create_schematic: failed to get schematic "
+                       "from map" << std::endl;
+               return 0;
+       }
+       
+       dschem.applyProbabilities(&probability_list, p1);
+       
+       dschem.saveSchematicFile(ndef);
+       actionstream << "create_schematic: saved schematic file '"
+               << dschem.filename << "'." << std::endl;
+
+       return 1;
+}
+
+
+// place_schematic(p, schematic, rotation, replacement)
+int ModApiBasic::l_place_schematic(lua_State *L)
+{
+       DecoSchematic dschem;
+
+       Map *map = &(getEnv(L)->getMap());
+       INodeDefManager *ndef = getServer(L)->getNodeDefManager();
+
+       v3s16 p = read_v3s16(L, 1);
+       if (!read_schematic(L, 2, &dschem, getServer(L)))
+               return 0;
+               
+       Rotation rot = ROTATE_0;
+       if (lua_isstring(L, 3))
+               string_to_enum(es_Rotation, (int &)rot, std::string(lua_tostring(L, 3)));
+               
+       dschem.rotation = rot;
+
+       if (lua_istable(L, 4)) {
+               int index = 4;
+               lua_pushnil(L);
+               while (lua_next(L, index) != 0) {
+                       // key at index -2 and value at index -1
+                       lua_rawgeti(L, -1, 1);
+                       std::string replace_from = lua_tostring(L, -1);
+                       lua_pop(L, 1);
+                       lua_rawgeti(L, -1, 2);
+                       std::string replace_to = lua_tostring(L, -1);
+                       lua_pop(L, 1);
+                       dschem.replacements[replace_from] = replace_to;
+                       // removes value, keeps key for next iteration
+                       lua_pop(L, 1);
+               }
+       }
+
+       if (!dschem.filename.empty()) {
+               if (!dschem.loadSchematicFile()) {
+                       errorstream << "place_schematic: failed to load schematic file '"
+                               << dschem.filename << "'" << std::endl;
+                       return 0;
+               }
+               dschem.resolveNodeNames(ndef);
+       }
+       
+       dschem.placeStructure(map, p);
+
+       return 1;
+}
+
+
 ModApiBasic modapibasic_prototype;