X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Fscriptapi.cpp;h=ec3d34676672decfdcca5db0d2a5f9b7665bd7f2;hb=318669327e84d8fc7498e32c5bacfad658d8ba87;hp=a6eaabf97459e99dbd6c51d4b0e39fa4682ac75c;hpb=548da26ddc1e38bffbc05c5577fe9a60476f8e71;p=oweals%2Fminetest.git diff --git a/src/scriptapi.cpp b/src/scriptapi.cpp index a6eaabf97..ec3d34676 100644 --- a/src/scriptapi.cpp +++ b/src/scriptapi.cpp @@ -37,6 +37,7 @@ extern "C" { #include "content_sao.h" // For LuaEntitySAO and PlayerSAO #include "itemdef.h" #include "nodedef.h" +#include "biome.h" #include "craftdef.h" #include "main.h" // For g_settings #include "settings.h" // For accessing g_settings @@ -48,6 +49,7 @@ extern "C" { #include "noise.h" // PseudoRandom for LuaPseudoRandom #include "util/pointedthing.h" #include "rollback.h" +#include "treegen.h" static void stackDump(lua_State *L, std::ostream &o) { @@ -435,6 +437,16 @@ struct EnumString es_TileAnimationType[] = {0, NULL}, }; +struct EnumString es_BiomeTerrainType[] = +{ + {BIOME_TERRAIN_NORMAL, "normal"}, + {BIOME_TERRAIN_LIQUID, "liquid"}, + {BIOME_TERRAIN_NETHER, "nether"}, + {BIOME_TERRAIN_AETHER, "aether"}, + {BIOME_TERRAIN_FLAT, "flat"}, + {0, NULL}, +}; + /* C struct <-> Lua table converter functions */ @@ -936,6 +948,8 @@ static void read_object_properties(lua_State *L, int index, lua_pop(L, 1); getstringfield(L, -1, "visual", prop->visual); + + getstringfield(L, -1, "mesh", prop->mesh); lua_getfield(L, -1, "visual_size"); if(lua_istable(L, -1)) @@ -958,6 +972,23 @@ static void read_object_properties(lua_State *L, int index, } } lua_pop(L, 1); + + lua_getfield(L, -1, "colors"); + if(lua_istable(L, -1)){ + prop->colors.clear(); + int table = lua_gettop(L); + lua_pushnil(L); + while(lua_next(L, table) != 0){ + // key at index -2 and value at index -1 + if(lua_isstring(L, -1)) + prop->colors.push_back(readARGB8(L, -1)); + else + prop->colors.push_back(video::SColor(255, 255, 255, 255)); + // removes value, keeps key for next iteration + lua_pop(L, 1); + } + } + lua_pop(L, 1); lua_getfield(L, -1, "spritediv"); if(lua_istable(L, -1)) @@ -968,7 +999,7 @@ static void read_object_properties(lua_State *L, int index, if(lua_istable(L, -1)) prop->initial_sprite_basepos = read_v2s16(L, -1); lua_pop(L, 1); - + getboolfield(L, -1, "is_visible", prop->is_visible); getboolfield(L, -1, "makes_footstep_sound", prop->makes_footstep_sound); getfloatfield(L, -1, "automatic_rotate", prop->automatic_rotate); @@ -1012,7 +1043,7 @@ static ItemDefinition read_item_definition(lua_State *L, int index, warn_if_field_exists(L, index, "tool_digging_properties", "deprecated: use tool_capabilities"); - + lua_getfield(L, index, "tool_capabilities"); if(lua_istable(L, -1)){ def.tool_capabilities = new ToolCapabilities( @@ -1047,7 +1078,7 @@ static TileDef read_tiledef(lua_State *L, int index) { if(index < 0) index = lua_gettop(L) + 1 + index; - + TileDef tiledef; // key at index -2 and value at index @@ -1093,7 +1124,7 @@ static ContentFeatures read_content_features(lua_State *L, int index) index = lua_gettop(L) + 1 + index; ContentFeatures f; - + /* Cache existence of some callbacks */ lua_getfield(L, index, "on_construct"); if(!lua_isnil(L, -1)) f.has_on_construct = true; @@ -1118,7 +1149,7 @@ static ContentFeatures read_content_features(lua_State *L, int index) f.drawtype = (NodeDrawType)getenumfield(L, index, "drawtype", es_DrawType, NDT_NORMAL); getfloatfield(L, index, "visual_scale", f.visual_scale); - + // tiles = {} lua_getfield(L, index, "tiles"); // If nil, try the deprecated name "tile_images" instead @@ -1153,7 +1184,7 @@ static ContentFeatures read_content_features(lua_State *L, int index) } } lua_pop(L, 1); - + // special_tiles = {} lua_getfield(L, index, "special_tiles"); // If nil, try the deprecated name "special_materials" instead @@ -1184,7 +1215,7 @@ static ContentFeatures read_content_features(lua_State *L, int index) f.alpha = getintfield_default(L, index, "alpha", 255); /* Other stuff */ - + lua_getfield(L, index, "post_effect_color"); if(!lua_isnil(L, -1)) f.post_effect_color = readARGB8(L, -1); @@ -1208,7 +1239,7 @@ static ContentFeatures read_content_features(lua_State *L, int index) "deprecated: use 'drop' field"); warn_if_field_exists(L, index, "metadata_name", "deprecated: use on_add and metadata callbacks"); - + // True for all ground-like things like stone and mud, false for eg. trees getboolfield(L, index, "is_ground_content", f.is_ground_content); f.light_propagates = (f.param_type == CPT_LIGHT); @@ -1238,12 +1269,13 @@ static ContentFeatures read_content_features(lua_State *L, int index) // the slowest possible f.liquid_viscosity = getintfield_default(L, index, "liquid_viscosity", f.liquid_viscosity); + getboolfield(L, index, "liquid_renewable", f.liquid_renewable); // Amount of light the node emits f.light_source = getintfield_default(L, index, "light_source", f.light_source); f.damage_per_second = getintfield_default(L, index, "damage_per_second", f.damage_per_second); - + lua_getfield(L, index, "node_box"); if(lua_istable(L, -1)) f.node_box = read_nodebox(L, -1); @@ -1258,7 +1290,7 @@ static ContentFeatures read_content_features(lua_State *L, int index) getboolfield(L, index, "legacy_facedir_simple", f.legacy_facedir_simple); // Set to true if wall_mounted used to be set to true getboolfield(L, index, "legacy_wallmounted", f.legacy_wallmounted); - + // Sound table lua_getfield(L, index, "sounds"); if(lua_istable(L, -1)){ @@ -1347,7 +1379,7 @@ private: static const luaL_reg methods[]; // Exported functions - + // garbage collector static int gc_object(lua_State *L) { @@ -1600,7 +1632,7 @@ public: { return m_stack; } - + // LuaItemStack(itemstack or itemstring or table or nil) // Creates an LuaItemStack and leaves it on top of stack static int create_object(lua_State *L) @@ -1789,7 +1821,7 @@ private: if(!ud) luaL_typerror(L, narg, className); return *(InvRef**)ud; // unbox pointer } - + static Inventory* getinv(lua_State *L, InvRef *ref) { return get_server(L)->getInventory(ref->m_loc); @@ -1809,9 +1841,9 @@ private: // Inform other things that the inventory has changed get_server(L)->setInventoryModified(ref->m_loc); } - + // Exported functions - + // garbage collector static int gc_object(lua_State *L) { InvRef *o = *(InvRef **)(lua_touserdata(L, 1)); @@ -1847,6 +1879,20 @@ private: return 1; } + // get_width(self, listname) + static int l_get_width(lua_State *L) + { + InvRef *ref = checkobject(L, 1); + const char *listname = luaL_checkstring(L, 2); + InventoryList *list = getlist(L, ref, listname); + if(list){ + lua_pushinteger(L, list->getWidth()); + } else { + lua_pushinteger(L, 0); + } + return 1; + } + // set_size(self, listname, size) static int l_set_size(lua_State *L) { @@ -1869,6 +1915,23 @@ private: return 0; } + // set_width(self, listname, size) + static int l_set_width(lua_State *L) + { + InvRef *ref = checkobject(L, 1); + const char *listname = luaL_checkstring(L, 2); + int newwidth = luaL_checknumber(L, 3); + Inventory *inv = getinv(L, ref); + InventoryList *list = inv->getList(listname); + if(list){ + list->setWidth(newwidth); + } else { + return 0; + } + reportInventoryChange(L, ref); + return 0; + } + // get_stack(self, listname, i) -> itemstack static int l_get_stack(lua_State *L) { @@ -1997,6 +2060,43 @@ private: return 1; } + // get_location() -> location (like minetest.get_inventory(location)) + static int l_get_location(lua_State *L) + { + InvRef *ref = checkobject(L, 1); + const InventoryLocation &loc = ref->m_loc; + switch(loc.type){ + case InventoryLocation::PLAYER: + lua_newtable(L); + lua_pushstring(L, "player"); + lua_setfield(L, -2, "type"); + lua_pushstring(L, loc.name.c_str()); + lua_setfield(L, -2, "name"); + return 1; + case InventoryLocation::NODEMETA: + lua_newtable(L); + lua_pushstring(L, "nodemeta"); + lua_setfield(L, -2, "type"); + push_v3s16(L, loc.p); + lua_setfield(L, -2, "name"); + return 1; + case InventoryLocation::DETACHED: + lua_newtable(L); + lua_pushstring(L, "detached"); + lua_setfield(L, -2, "type"); + lua_pushstring(L, loc.name.c_str()); + lua_setfield(L, -2, "name"); + return 1; + case InventoryLocation::UNDEFINED: + case InventoryLocation::CURRENT_PLAYER: + break; + } + lua_newtable(L); + lua_pushstring(L, "undefined"); + lua_setfield(L, -2, "type"); + return 1; + } + public: InvRef(const InventoryLocation &loc): m_loc(loc) @@ -2062,6 +2162,8 @@ const luaL_reg InvRef::methods[] = { method(InvRef, is_empty), method(InvRef, get_size), method(InvRef, set_size), + method(InvRef, get_width), + method(InvRef, set_width), method(InvRef, get_stack), method(InvRef, set_stack), method(InvRef, get_list), @@ -2070,6 +2172,7 @@ const luaL_reg InvRef::methods[] = { method(InvRef, room_for_item), method(InvRef, contains_item), method(InvRef, remove_item), + method(InvRef, get_location), {0,0} }; @@ -2093,7 +2196,7 @@ private: if(!ud) luaL_typerror(L, narg, className); return *(NodeMetaRef**)ud; // unbox pointer } - + static NodeMetadata* getmeta(NodeMetaRef *ref, bool auto_create) { NodeMetadata *meta = ref->m_env->getMap().getNodeMetadata(ref->m_p); @@ -2120,9 +2223,9 @@ private: block->raiseModified(MOD_STATE_WRITE_NEEDED, "NodeMetaRef::reportMetadataChange"); } - + // Exported functions - + // garbage collector static int gc_object(lua_State *L) { NodeMetaRef *o = *(NodeMetaRef **)(lua_touserdata(L, 1)); @@ -2235,7 +2338,7 @@ private: InvRef::createNodeMeta(L, ref->m_p); return 1; } - + // to_table(self) static int l_to_table(lua_State *L) { @@ -2281,7 +2384,7 @@ private: { NodeMetaRef *ref = checkobject(L, 1); int base = 2; - + if(lua_isnil(L, base)){ // No metadata ref->m_env->getMap().removeNodeMetadata(ref->m_p); @@ -2405,7 +2508,7 @@ public: if(!ud) luaL_typerror(L, narg, className); return *(ObjectRef**)ud; // unbox pointer } - + static ServerActiveObject* getobject(ObjectRef *ref) { ServerActiveObject *co = ref->m_object; @@ -2421,7 +2524,7 @@ private: return NULL; return (LuaEntitySAO*)obj; } - + static PlayerSAO* getplayersao(ObjectRef *ref) { ServerActiveObject *obj = getobject(ref); @@ -2431,7 +2534,7 @@ private: return NULL; return (PlayerSAO*)obj; } - + static Player* getplayer(ObjectRef *ref) { PlayerSAO *playersao = getplayersao(ref); @@ -2439,9 +2542,9 @@ private: return NULL; return playersao->getPlayer(); } - + // Exported functions - + // garbage collector static int gc_object(lua_State *L) { ObjectRef *o = *(ObjectRef **)(lua_touserdata(L, 1)); @@ -2460,7 +2563,7 @@ private: co->m_removed = true; return 0; } - + // getpos(self) // returns: {x=num, y=num, z=num} static int l_getpos(lua_State *L) @@ -2478,7 +2581,7 @@ private: lua_setfield(L, -2, "z"); return 1; } - + // setpos(self, pos) static int l_setpos(lua_State *L) { @@ -2492,7 +2595,7 @@ private: co->setPos(pos); return 0; } - + // moveto(self, pos, continuous=false) static int l_moveto(lua_State *L) { @@ -2509,7 +2612,7 @@ private: return 0; } - // punch(self, puncher, tool_capabilities, direction, time_from_last_punch) + // punch(self, puncher, time_from_last_punch, tool_capabilities, dir) static int l_punch(lua_State *L) { ObjectRef *ref = checkobject(L, 1); @@ -2518,13 +2621,18 @@ private: ServerActiveObject *puncher = getobject(puncher_ref); if(co == NULL) return 0; if(puncher == NULL) return 0; - ToolCapabilities toolcap = read_tool_capabilities(L, 3); - v3f dir = read_v3f(L, 4); + v3f dir; + if(lua_type(L, 5) != LUA_TTABLE) + dir = co->getBasePosition() - puncher->getBasePosition(); + else + dir = read_v3f(L, 5); float time_from_last_punch = 1000000; - if(lua_isnumber(L, 5)) - time_from_last_punch = lua_tonumber(L, 5); + if(lua_isnumber(L, 3)) + time_from_last_punch = lua_tonumber(L, 3); + ToolCapabilities toolcap = read_tool_capabilities(L, 4); + dir.normalize(); // Do it - puncher->punch(dir, &toolcap, puncher, time_from_last_punch); + co->punch(dir, &toolcap, puncher, time_from_last_punch); return 0; } @@ -2658,6 +2766,80 @@ private: return 0; } + // set_animation(self, frame_range, frame_speed, frame_blend) + static int l_set_animation(lua_State *L) + { + ObjectRef *ref = checkobject(L, 1); + ServerActiveObject *co = getobject(ref); + if(co == NULL) return 0; + // Do it + v2f frames = v2f(1, 1); + if(!lua_isnil(L, 2)) + frames = read_v2f(L, 2); + float frame_speed = 15; + if(!lua_isnil(L, 3)) + frame_speed = lua_tonumber(L, 3); + float frame_blend = 0; + if(!lua_isnil(L, 4)) + frame_blend = lua_tonumber(L, 4); + co->setAnimation(frames, frame_speed, frame_blend); + return 0; + } + + // set_bone_position(self, std::string bone, v3f position, v3f rotation) + static int l_set_bone_position(lua_State *L) + { + ObjectRef *ref = checkobject(L, 1); + ServerActiveObject *co = getobject(ref); + if(co == NULL) return 0; + // Do it + std::string bone = ""; + if(!lua_isnil(L, 2)) + bone = lua_tostring(L, 2); + v3f position = v3f(0, 0, 0); + if(!lua_isnil(L, 3)) + position = read_v3f(L, 3); + v3f rotation = v3f(0, 0, 0); + if(!lua_isnil(L, 4)) + rotation = read_v3f(L, 4); + co->setBonePosition(bone, position, rotation); + return 0; + } + + // set_attach(self, parent, bone, position, rotation) + static int l_set_attach(lua_State *L) + { + ObjectRef *ref = checkobject(L, 1); + ObjectRef *parent_ref = checkobject(L, 2); + ServerActiveObject *co = getobject(ref); + ServerActiveObject *parent = getobject(parent_ref); + if(co == NULL) return 0; + if(parent == NULL) return 0; + // Do it + std::string bone = ""; + if(!lua_isnil(L, 3)) + bone = lua_tostring(L, 3); + v3f position = v3f(0, 0, 0); + if(!lua_isnil(L, 4)) + position = read_v3f(L, 4); + v3f rotation = v3f(0, 0, 0); + if(!lua_isnil(L, 5)) + rotation = read_v3f(L, 5); + co->setAttachment(parent->getId(), bone, position, rotation); + return 0; + } + + // set_detach(self) + static int l_set_detach(lua_State *L) + { + ObjectRef *ref = checkobject(L, 1); + ServerActiveObject *co = getobject(ref); + if(co == NULL) return 0; + // Do it + co->setAttachment(0, "", v3f(0,0,0), v3f(0,0,0)); + return 0; + } + // set_properties(self, properties) static int l_set_properties(lua_State *L) { @@ -2685,7 +2867,7 @@ private: co->setVelocity(pos); return 0; } - + // getvelocity(self) static int l_getvelocity(lua_State *L) { @@ -2697,7 +2879,7 @@ private: pushFloatPos(L, v); return 1; } - + // setacceleration(self, {x=num, y=num, z=num}) static int l_setacceleration(lua_State *L) { @@ -2710,7 +2892,7 @@ private: co->setAcceleration(pos); return 0; } - + // getacceleration(self) static int l_getacceleration(lua_State *L) { @@ -2722,7 +2904,7 @@ private: pushFloatPos(L, v); return 1; } - + // setyaw(self, radians) static int l_setyaw(lua_State *L) { @@ -2734,7 +2916,7 @@ private: co->setYaw(yaw); return 0; } - + // getyaw(self) static int l_getyaw(lua_State *L) { @@ -2746,7 +2928,7 @@ private: lua_pushnumber(L, yaw); return 1; } - + // settexturemod(self, mod) static int l_settexturemod(lua_State *L) { @@ -2758,7 +2940,7 @@ private: co->setTextureMod(mod); return 0; } - + // setsprite(self, p={x=0,y=0}, num_frames=1, framelength=0.2, // select_horiz_by_yawpitch=false) static int l_setsprite(lua_State *L) @@ -2795,7 +2977,7 @@ private: lua_pushstring(L, name.c_str()); return 1; } - + // get_luaentity(self) static int l_get_luaentity(lua_State *L) { @@ -2806,7 +2988,7 @@ private: luaentity_get(L, co->getId()); return 1; } - + /* Player-only */ // is_player(self) @@ -2817,7 +2999,7 @@ private: lua_pushboolean(L, (player != NULL)); return 1; } - + // get_player_name(self) static int l_get_player_name(lua_State *L) { @@ -2831,7 +3013,7 @@ private: lua_pushstring(L, player->getName()); return 1; } - + // get_look_dir(self) static int l_get_look_dir(lua_State *L) { @@ -2893,7 +3075,54 @@ private: lua_pushlstring(L, formspec.c_str(), formspec.size()); return 1; } - + + // get_player_control(self) + static int l_get_player_control(lua_State *L) + { + ObjectRef *ref = checkobject(L, 1); + Player *player = getplayer(ref); + if(player == NULL){ + lua_pushlstring(L, "", 0); + return 1; + } + // Do it + PlayerControl control = player->getPlayerControl(); + lua_newtable(L); + lua_pushboolean(L, control.up); + lua_setfield(L, -2, "up"); + lua_pushboolean(L, control.down); + lua_setfield(L, -2, "down"); + lua_pushboolean(L, control.left); + lua_setfield(L, -2, "left"); + lua_pushboolean(L, control.right); + lua_setfield(L, -2, "right"); + lua_pushboolean(L, control.jump); + lua_setfield(L, -2, "jump"); + lua_pushboolean(L, control.aux1); + lua_setfield(L, -2, "aux1"); + lua_pushboolean(L, control.sneak); + lua_setfield(L, -2, "sneak"); + lua_pushboolean(L, control.LMB); + lua_setfield(L, -2, "LMB"); + lua_pushboolean(L, control.RMB); + lua_setfield(L, -2, "RMB"); + return 1; + } + + // get_player_control_bits(self) + static int l_get_player_control_bits(lua_State *L) + { + ObjectRef *ref = checkobject(L, 1); + Player *player = getplayer(ref); + if(player == NULL){ + lua_pushlstring(L, "", 0); + return 1; + } + // Do it + lua_pushnumber(L, player->keyPressed); + return 1; + } + public: ObjectRef(ServerActiveObject *object): m_object(object) @@ -2926,7 +3155,7 @@ public: ObjectRef *o = checkobject(L, -1); o->m_object = NULL; } - + static void Register(lua_State *L) { lua_newtable(L); @@ -2972,6 +3201,10 @@ const luaL_reg ObjectRef::methods[] = { method(ObjectRef, get_wielded_item), method(ObjectRef, set_wielded_item), method(ObjectRef, set_armor_groups), + method(ObjectRef, set_animation), + method(ObjectRef, set_bone_position), + method(ObjectRef, set_attach), + method(ObjectRef, set_detach), method(ObjectRef, set_properties), // LuaEntitySAO-only method(ObjectRef, setvelocity), @@ -2992,6 +3225,8 @@ const luaL_reg ObjectRef::methods[] = { method(ObjectRef, get_look_yaw), method(ObjectRef, set_inventory_formspec), method(ObjectRef, get_inventory_formspec), + method(ObjectRef, get_player_control), + method(ObjectRef, get_player_control_bits), {0,0} }; @@ -3016,8 +3251,8 @@ class LuaPerlinNoise private: int seed; int octaves; - double persistence; - double scale; + float persistence; + float scale; static const char className[]; static const luaL_reg methods[]; @@ -3049,8 +3284,8 @@ private: } public: - LuaPerlinNoise(int a_seed, int a_octaves, double a_persistence, - double a_scale): + LuaPerlinNoise(int a_seed, int a_octaves, float a_persistence, + float a_scale): seed(a_seed), octaves(a_octaves), persistence(a_persistence), @@ -3068,8 +3303,8 @@ public: { int seed = luaL_checkint(L, 1); int octaves = luaL_checkint(L, 2); - double persistence = luaL_checknumber(L, 3); - double scale = luaL_checknumber(L, 4); + float persistence = luaL_checknumber(L, 3); + float scale = luaL_checknumber(L, 4); LuaPerlinNoise *o = new LuaPerlinNoise(seed, octaves, persistence, scale); *(void **)(lua_newuserdata(L, sizeof(void *))) = o; luaL_getmetatable(L, className); @@ -3146,7 +3381,7 @@ private: if(!ud) luaL_typerror(L, narg, className); return *(NodeTimerRef**)ud; // unbox pointer } - + static int l_set(lua_State *L) { NodeTimerRef *o = checkobject(L, 1); @@ -3157,7 +3392,7 @@ private: env->getMap().setNodeTimer(o->m_p,NodeTimer(t,e)); return 0; } - + static int l_start(lua_State *L) { NodeTimerRef *o = checkobject(L, 1); @@ -3167,7 +3402,7 @@ private: env->getMap().setNodeTimer(o->m_p,NodeTimer(t,0)); return 0; } - + static int l_stop(lua_State *L) { NodeTimerRef *o = checkobject(L, 1); @@ -3176,7 +3411,7 @@ private: env->getMap().removeNodeTimer(o->m_p); return 0; } - + static int l_is_started(lua_State *L) { NodeTimerRef *o = checkobject(L, 1); @@ -3187,7 +3422,7 @@ private: lua_pushboolean(L,(t.timeout != 0)); return 1; } - + static int l_get_timeout(lua_State *L) { NodeTimerRef *o = checkobject(L, 1); @@ -3198,7 +3433,7 @@ private: lua_pushnumber(L,t.timeout); return 1; } - + static int l_get_elapsed(lua_State *L) { NodeTimerRef *o = checkobject(L, 1); @@ -3236,7 +3471,7 @@ public: NodeTimerRef *o = checkobject(L, -1); o->m_env = NULL; } - + static void Register(lua_State *L) { lua_newtable(L); @@ -3301,7 +3536,7 @@ private: if(!ud) luaL_typerror(L, narg, className); return *(EnvRef**)ud; // unbox pointer } - + // Exported functions // EnvRef:set_node(pos, node) @@ -3316,20 +3551,7 @@ private: v3s16 pos = read_v3s16(L, 2); MapNode n = readnode(L, 3, ndef); // Do it - MapNode n_old = env->getMap().getNodeNoEx(pos); - // Call destructor - if(ndef->get(n_old).has_on_destruct) - scriptapi_node_on_destruct(L, pos, n_old); - // Replace node - bool succeeded = env->getMap().addNodeWithEvent(pos, n); - if(succeeded){ - // Call post-destructor - if(ndef->get(n_old).has_after_destruct) - scriptapi_node_after_destruct(L, pos, n_old); - // Call constructor - if(ndef->get(n).has_on_construct) - scriptapi_node_on_construct(L, pos, n); - } + bool succeeded = env->setNode(pos, n); lua_pushboolean(L, succeeded); return 1; } @@ -3350,20 +3572,8 @@ private: // parameters v3s16 pos = read_v3s16(L, 2); // Do it - MapNode n_old = env->getMap().getNodeNoEx(pos); - // Call destructor - if(ndef->get(n_old).has_on_destruct) - scriptapi_node_on_destruct(L, pos, n_old); - // Replace with air - // This is slightly optimized compared to addNodeWithEvent(air) - bool succeeded = env->getMap().removeNodeWithEvent(pos); - if(succeeded){ - // Call post-destructor - if(ndef->get(n_old).has_after_destruct) - scriptapi_node_after_destruct(L, pos, n_old); - } + bool succeeded = env->removeNode(pos); lua_pushboolean(L, succeeded); - // Air doesn't require constructor return 1; } @@ -3419,7 +3629,7 @@ private: if(lua_isnumber(L, 3)) time_of_day = 24000.0 * lua_tonumber(L, 3); time_of_day %= 24000; - u32 dnr = time_to_daynight_ratio(time_of_day); + u32 dnr = time_to_daynight_ratio(time_of_day, true); MapNode n = env->getMap().getNodeNoEx(pos); try{ MapNode n = env->getMap().getNode(pos); @@ -3770,7 +3980,7 @@ private: lua_getglobal(L, "table"); lua_getfield(L, -1, "insert"); int table_insert = lua_gettop(L); - + lua_newtable(L); int table = lua_gettop(L); for(s16 x=minp.X; x<=maxp.X; x++) @@ -3800,8 +4010,8 @@ private: int seeddiff = luaL_checkint(L, 2); int octaves = luaL_checkint(L, 3); - double persistence = luaL_checknumber(L, 4); - double scale = luaL_checknumber(L, 5); + float persistence = luaL_checknumber(L, 4); + float scale = luaL_checknumber(L, 5); LuaPerlinNoise *n = new LuaPerlinNoise(seeddiff + int(env->getServerMap().getSeed()), octaves, persistence, scale); *(void **)(lua_newuserdata(L, sizeof(void *))) = n; @@ -3819,6 +4029,54 @@ private: return 0; } + static int l_spawn_tree(lua_State *L) + { + EnvRef *o = checkobject(L, 1); + ServerEnvironment *env = o->m_env; + if(env == NULL) return 0; + v3s16 p0 = read_v3s16(L, 2); + + treegen::TreeDef tree_def; + std::string trunk,leaves,fruit; + INodeDefManager *ndef = env->getGameDef()->ndef(); + + if(lua_istable(L, 3)) + { + getstringfield(L, 3, "axiom", tree_def.initial_axiom); + getstringfield(L, 3, "rules_a", tree_def.rules_a); + getstringfield(L, 3, "rules_b", tree_def.rules_b); + getstringfield(L, 3, "rules_c", tree_def.rules_c); + getstringfield(L, 3, "rules_d", tree_def.rules_d); + getstringfield(L, 3, "trunk", trunk); + tree_def.trunknode=ndef->getId(trunk); + getstringfield(L, 3, "leaves", leaves); + tree_def.leavesnode=ndef->getId(leaves); + tree_def.leaves2_chance=0; + getstringfield(L, 3, "leaves2", leaves); + if (leaves !="") + { + tree_def.leaves2node=ndef->getId(leaves); + getintfield(L, 3, "leaves2_chance", tree_def.leaves2_chance); + } + getintfield(L, 3, "angle", tree_def.angle); + getintfield(L, 3, "iterations", tree_def.iterations); + getintfield(L, 3, "random_level", tree_def.iterations_random_level); + getstringfield(L, 3, "trunk_type", tree_def.trunk_type); + getboolfield(L, 3, "thin_branches", tree_def.thin_branches); + tree_def.fruit_chance=0; + getstringfield(L, 3, "fruit", fruit); + if (fruit != "") + { + tree_def.fruitnode=ndef->getId(fruit); + getintfield(L, 3, "fruit_chance",tree_def.fruit_chance); + } + } + else + return 0; + treegen::spawn_ltree (env, p0, ndef, tree_def); + return 1; + } + public: EnvRef(ServerEnvironment *env): m_env(env) @@ -3847,7 +4105,7 @@ public: EnvRef *o = checkobject(L, -1); o->m_env = NULL; } - + static void Register(lua_State *L) { lua_newtable(L); @@ -3900,7 +4158,10 @@ const luaL_reg EnvRef::methods[] = { method(EnvRef, find_node_near), method(EnvRef, find_nodes_in_area), method(EnvRef, get_perlin), + //method{EnvRef, get_perlin_map_2d}, + //method{EnvRef, get_perlin_map_3d}, method(EnvRef, clear_objects), + method(EnvRef, spawn_tree), {0,0} }; @@ -3918,7 +4179,7 @@ private: static const luaL_reg methods[]; // Exported functions - + // garbage collector static int gc_object(lua_State *L) { @@ -3969,7 +4230,7 @@ public: { return m_pseudo; } - + // LuaPseudoRandom(seed) // Creates an LuaPseudoRandom and leaves it on top of stack static int create_object(lua_State *L) @@ -4073,7 +4334,7 @@ public: u32 active_object_count, u32 active_object_count_wider) { lua_State *L = m_lua; - + realitycheck(L); assert(lua_checkstack(L, 20)); StackUnroller stack_unroller(L); @@ -4089,7 +4350,7 @@ public: lua_gettable(L, registered_abms); if(lua_isnil(L, -1)) assert(0); - + // Call action luaL_checktype(L, -1, LUA_TTABLE); lua_getfield(L, -1, "action"); @@ -4194,6 +4455,84 @@ static int l_get_server_status(lua_State *L) return 1; } +// register_biome_groups({frequencies}) +static int l_register_biome_groups(lua_State *L) +{ + luaL_checktype(L, 1, LUA_TTABLE); + int index = 1; + if (!lua_istable(L, index)) + throw LuaError(L, "register_biome_groups: parameter is not a table"); + + BiomeDefManager *bmgr = get_server(L)->getBiomeDef(); + if (!bmgr) { + verbosestream << "register_biome_groups: BiomeDefManager not active" << std::endl; + return 0; + } + + lua_pushnil(L); + for (int i = 1; lua_next(L, index) != 0; i++) { + bmgr->addBiomeGroup(lua_tonumber(L, -1)); + lua_pop(L, 1); + } + lua_pop(L, 1); + + return 0; +} + +// register_biome({lots of stuff}) +static int l_register_biome(lua_State *L) +{ + luaL_checktype(L, 1, LUA_TTABLE); + int index = 1, groupid; + std::string nodename; + + IWritableNodeDefManager *ndef = get_server(L)->getWritableNodeDefManager(); + BiomeDefManager *bmgr = get_server(L)->getBiomeDef(); + if (!bmgr) { + verbosestream << "register_biome: BiomeDefManager not active" << std::endl; + return 0; + } + + groupid = getintfield_default(L, index, "group_id", 0); + + enum BiomeTerrainType terrain = (BiomeTerrainType)getenumfield(L, index, + "terrain_type", es_BiomeTerrainType, BIOME_TERRAIN_NORMAL); + Biome *b = bmgr->createBiome(terrain); + + b->name = getstringfield_default(L, index, "name", ""); + + if (getstringfield(L, index, "node_top", nodename)) + b->n_top = MapNode(ndef->getId(nodename)); + else + b->n_top = MapNode(CONTENT_IGNORE); + + if (getstringfield(L, index, "node_filler", nodename)) + b->n_filler = MapNode(ndef->getId(nodename)); + else + b->n_filler = b->n_top; + + b->ntopnodes = getintfield_default(L, index, "num_top_nodes", 0); + + b->height_min = getintfield_default(L, index, "height_min", 0); + b->height_max = getintfield_default(L, index, "height_max", 0); + b->heat_min = getfloatfield_default(L, index, "heat_min", 0.); + b->heat_max = getfloatfield_default(L, index, "heat_max", 0.); + b->humidity_min = getfloatfield_default(L, index, "humidity_min", 0.); + b->humidity_max = getfloatfield_default(L, index, "humidity_max", 0.); + + b->np = new NoiseParams; // should read an entire NoiseParams later on... + getfloatfield(L, index, "scale", b->np->scale); + getfloatfield(L, index, "offset", b->np->offset); + + b->groupid = (s8)groupid; + b->flags = 0; //reserved + + bmgr->addBiome(b); + + verbosestream << "register_biome: " << b->name << std::endl; + return 0; +} + // register_item_raw({lots of stuff}) static int l_register_item_raw(lua_State *L) { @@ -4233,7 +4572,7 @@ static int l_register_item_raw(lua_State *L) else def.node_placement_prediction = ""; } - + // Register item definition idef->registerItem(def); @@ -4256,9 +4595,9 @@ static int l_register_alias_raw(lua_State *L) // Get the writable item definition manager from the server IWritableItemDefManager *idef = get_server(L)->getWritableItemDefManager(); - + idef->registerAlias(name, convert_to); - + return 0; /* number of results */ } @@ -4367,7 +4706,7 @@ static int l_register_craft(lua_State *L) // Get the writable craft definition manager from the server IWritableCraftDefManager *craftdef = get_server(L)->getWritableCraftDefManager(); - + std::string type = getstringfield_default(L, table, "type", "shaped"); /* @@ -4584,6 +4923,56 @@ static int l_get_player_privs(lua_State *L) return 1; } +// get_ban_list() +static int l_get_ban_list(lua_State *L) +{ + lua_pushstring(L, get_server(L)->getBanDescription("").c_str()); + return 1; +} + +// get_ban_description() +static int l_get_ban_description(lua_State *L) +{ + const char * ip_or_name = luaL_checkstring(L, 1); + lua_pushstring(L, get_server(L)->getBanDescription(std::string(ip_or_name)).c_str()); + return 1; +} + +// ban_player() +static int l_ban_player(lua_State *L) +{ + const char * name = luaL_checkstring(L, 1); + Player *player = get_env(L)->getPlayer(name); + if(player == NULL) + { + lua_pushboolean(L, false); // no such player + return 1; + } + try + { + Address addr = get_server(L)->getPeerAddress(get_env(L)->getPlayer(name)->peer_id); + std::string ip_str = addr.serializeString(); + get_server(L)->setIpBanned(ip_str, name); + } + catch(con::PeerNotFoundException) // unlikely + { + dstream << __FUNCTION_NAME << ": peer was not found" << std::endl; + lua_pushboolean(L, false); // error + return 1; + } + lua_pushboolean(L, true); + return 1; +} + +// unban_player_or_ip() +static int l_unban_player_of_ip(lua_State *L) +{ + const char * ip_or_name = luaL_checkstring(L, 1); + get_server(L)->unsetIpBanned(ip_or_name); + lua_pushboolean(L, true); + return 1; +} + // get_inventory(location) static int l_get_inventory(lua_State *L) { @@ -4601,7 +4990,7 @@ static int l_get_inventory(lua_State *L) std::string name = checkstringfield(L, 1, "name"); loc.setDetached(name); } - + if(get_server(L)->getInventory(loc) != NULL) InvRef::create(L, loc); else @@ -4623,6 +5012,22 @@ static int l_create_detached_inventory_raw(lua_State *L) return 1; } +// show_formspec(playername,formname,formspec) +static int l_show_formspec(lua_State *L) +{ + const char *playername = luaL_checkstring(L, 1); + const char *formname = luaL_checkstring(L, 2); + const char *formspec = luaL_checkstring(L, 3); + + if(get_server(L)->showFormspec(playername,formspec,formname)) + { + lua_pushboolean(L, true); + }else{ + lua_pushboolean(L, false); + } + return 1; +} + // get_dig_params(groups, tool_capabilities[, time_from_last_punch]) static int l_get_dig_params(lua_State *L) { @@ -4802,7 +5207,7 @@ static int l_get_craft_result(lua_State *L) lua_getfield(L, input_i, "items"); std::vector items = read_items(L, -1); lua_pop(L, 1); // items - + IGameDef *gdef = get_server(L); ICraftDefManager *cdef = gdef->cdef(); CraftInput input(method, width, items); @@ -4837,7 +5242,7 @@ static int l_get_craft_recipe(lua_State *L) char tmp[20]; int input_i = 1; std::string o_item = luaL_checkstring(L,input_i); - + IGameDef *gdef = get_server(L); ICraftDefManager *cdef = gdef->cdef(); CraftInput input; @@ -4940,14 +5345,21 @@ static const struct luaL_Reg minetest_f [] = { {"register_item_raw", l_register_item_raw}, {"register_alias_raw", l_register_alias_raw}, {"register_craft", l_register_craft}, + {"register_biome", l_register_biome}, + {"register_biome_groups", l_register_biome_groups}, {"setting_set", l_setting_set}, {"setting_get", l_setting_get}, {"setting_getbool", l_setting_getbool}, {"chat_send_all", l_chat_send_all}, {"chat_send_player", l_chat_send_player}, {"get_player_privs", l_get_player_privs}, + {"get_ban_list", l_get_ban_list}, + {"get_ban_description", l_get_ban_description}, + {"ban_player", l_ban_player}, + {"unban_player_or_ip", l_unban_player_of_ip}, {"get_inventory", l_get_inventory}, {"create_detached_inventory_raw", l_create_detached_inventory_raw}, + {"show_formspec", l_show_formspec}, {"get_dig_params", l_get_dig_params}, {"get_hit_params", l_get_hit_params}, {"get_current_modname", l_get_current_modname}, @@ -4985,7 +5397,7 @@ void scriptapi_export(lua_State *L, Server *server) lua_newtable(L); luaL_register(L, NULL, minetest_f); lua_setglobal(L, "minetest"); - + // Get the main minetest table lua_getglobal(L, "minetest"); @@ -5018,7 +5430,7 @@ bool scriptapi_loadmod(lua_State *L, const std::string &scriptpath, <<"Only chararacters [a-z0-9_] are allowed."<addActiveBlockModifier(abm); // removes value, keeps key for next iteration @@ -5157,7 +5569,7 @@ void scriptapi_add_object_reference(lua_State *L, ServerActiveObject *cobj) lua_getfield(L, -1, "object_refs"); luaL_checktype(L, -1, LUA_TTABLE); int objectstable = lua_gettop(L); - + // object_refs[id] = object lua_pushnumber(L, cobj->getId()); // Push id lua_pushvalue(L, object); // Copy object to top of stack @@ -5176,7 +5588,7 @@ void scriptapi_rm_object_reference(lua_State *L, ServerActiveObject *cobj) lua_getfield(L, -1, "object_refs"); luaL_checktype(L, -1, LUA_TTABLE); int objectstable = lua_gettop(L); - + // Get object_refs[id] lua_pushnumber(L, cobj->getId()); // Push id lua_gettable(L, objectstable); @@ -5272,16 +5684,16 @@ static void scriptapi_run_callbacks(lua_State *L, int nargs, lua_replace(L, rv); else if(mode == RUN_CALLBACKS_MODE_AND || mode == RUN_CALLBACKS_MODE_AND_SC){ - if(lua_toboolean(L, rv) == true && - lua_toboolean(L, -1) == false) + if((bool)lua_toboolean(L, rv) == true && + (bool)lua_toboolean(L, -1) == false) lua_replace(L, rv); else lua_pop(L, 1); } else if(mode == RUN_CALLBACKS_MODE_OR || mode == RUN_CALLBACKS_MODE_OR_SC){ - if(lua_toboolean(L, rv) == false && - lua_toboolean(L, -1) == true) + if((bool)lua_toboolean(L, rv) == false && + (bool)lua_toboolean(L, -1) == true) lua_replace(L, rv); else lua_pop(L, 1); @@ -5292,10 +5704,10 @@ static void scriptapi_run_callbacks(lua_State *L, int nargs, // Handle short circuit modes if(mode == RUN_CALLBACKS_MODE_AND_SC && - lua_toboolean(L, rv) == false) + (bool)lua_toboolean(L, rv) == false) break; else if(mode == RUN_CALLBACKS_MODE_OR_SC && - lua_toboolean(L, rv) == true) + (bool)lua_toboolean(L, rv) == true) break; // value removed, keep key for next iteration @@ -5337,6 +5749,19 @@ bool scriptapi_on_chat_message(lua_State *L, const std::string &name, return ate; } +void scriptapi_on_shutdown(lua_State *L) +{ + realitycheck(L); + assert(lua_checkstack(L, 20)); + StackUnroller stack_unroller(L); + + // Get registered shutdown hooks + lua_getglobal(L, "minetest"); + lua_getfield(L, -1, "registered_on_shutdown"); + // Call callbacks + scriptapi_run_callbacks(L, 0, RUN_CALLBACKS_MODE_FIRST); +} + void scriptapi_on_newplayer(lua_State *L, ServerActiveObject *player) { realitycheck(L); @@ -5427,7 +5852,7 @@ bool scriptapi_get_auth(lua_State *L, const std::string &playername, realitycheck(L); assert(lua_checkstack(L, 20)); StackUnroller stack_unroller(L); - + get_auth_handler(L); lua_getfield(L, -1, "get_auth"); if(lua_type(L, -1) != LUA_TFUNCTION) @@ -5435,12 +5860,12 @@ bool scriptapi_get_auth(lua_State *L, const std::string &playername, lua_pushstring(L, playername.c_str()); if(lua_pcall(L, 1, 1, 0)) script_error(L, "error: %s", lua_tostring(L, -1)); - + // nil = login not allowed if(lua_isnil(L, -1)) return false; luaL_checktype(L, -1, LUA_TTABLE); - + std::string password; bool found = getstringfield(L, -1, "password", password); if(!found) @@ -5455,7 +5880,7 @@ bool scriptapi_get_auth(lua_State *L, const std::string &playername, if(dst_privs) read_privileges(L, -1, *dst_privs); lua_pop(L, 1); - + return true; } @@ -5465,7 +5890,7 @@ void scriptapi_create_auth(lua_State *L, const std::string &playername, realitycheck(L); assert(lua_checkstack(L, 20)); StackUnroller stack_unroller(L); - + get_auth_handler(L); lua_getfield(L, -1, "create_auth"); if(lua_type(L, -1) != LUA_TFUNCTION) @@ -5482,7 +5907,7 @@ bool scriptapi_set_password(lua_State *L, const std::string &playername, realitycheck(L); assert(lua_checkstack(L, 20)); StackUnroller stack_unroller(L); - + get_auth_handler(L); lua_getfield(L, -1, "set_password"); if(lua_type(L, -1) != LUA_TFUNCTION) @@ -5498,7 +5923,7 @@ bool scriptapi_set_password(lua_State *L, const std::string &playername, player */ -void scriptapi_on_player_receive_fields(lua_State *L, +void scriptapi_on_player_receive_fields(lua_State *L, ServerActiveObject *player, const std::string &formname, const std::map &fields) @@ -5763,9 +6188,9 @@ bool scriptapi_node_on_timer(lua_State *L, v3s16 p, MapNode node, f32 dtime) lua_pushnumber(L,dtime); if(lua_pcall(L, 2, 1, 0)) script_error(L, "error: %s", lua_tostring(L, -1)); - if(lua_isboolean(L,-1) && lua_toboolean(L,-1) == true) + if((bool)lua_isboolean(L,-1) && (bool)lua_toboolean(L,-1) == true) return true; - + return false; } @@ -5779,7 +6204,7 @@ void scriptapi_node_on_receive_fields(lua_State *L, v3s16 p, StackUnroller stack_unroller(L); INodeDefManager *ndef = get_server(L)->ndef(); - + // If node doesn't exist, we don't know what callback to call MapNode node = get_env(L)->getMap().getNodeNoEx(p); if(node.getContent() == CONTENT_IGNORE) @@ -6347,7 +6772,7 @@ bool scriptapi_luaentity_add(lua_State *L, u16 id, const char *name) verbosestream<<"scriptapi_luaentity_add: id="<hp_max = 10; - + /* Read stuff */ - + prop->hp_max = getintfield_default(L, -1, "hp_max", 10); getboolfield(L, -1, "physical", prop->physical); @@ -6494,10 +6920,12 @@ void scriptapi_luaentity_get_properties(lua_State *L, u16 id, lua_pop(L, 1); getstringfield(L, -1, "visual", prop->visual); - + + getstringfield(L, -1, "mesh", prop->mesh); + // Deprecated: read object properties directly read_object_properties(L, -1, prop); - + // Read initial_properties lua_getfield(L, -1, "initial_properties"); read_object_properties(L, -1, prop);