From bdbdeab0053d9ebbaffea17effeba777b710d390 Mon Sep 17 00:00:00 2001 From: sapier Date: Sat, 23 Feb 2013 18:06:57 +0000 Subject: split scriptapi.cpp Remerge some files in order to reduce number of additional files Make necessary changes for split, rename files, reorganize some bits --- src/scriptapi.cpp | 7717 ++++++----------------------------------------------- 1 file changed, 823 insertions(+), 6894 deletions(-) (limited to 'src/scriptapi.cpp') diff --git a/src/scriptapi.cpp b/src/scriptapi.cpp index 7aa148fd6..ef8a1454a 100644 --- a/src/scriptapi.cpp +++ b/src/scriptapi.cpp @@ -27,89 +27,27 @@ extern "C" { #include } -#include "log.h" -#include "server.h" -#include "porting.h" -#include "filesys.h" -#include "serverobject.h" -#include "script.h" -#include "object_properties.h" -#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 -#include "nodemetadata.h" -#include "mapblock.h" // For getNodeBlockPos -#include "content_nodemeta.h" -#include "tool.h" -#include "daynightratio.h" -#include "noise.h" // PseudoRandom for LuaPseudoRandom -#include "util/pointedthing.h" +#include "main.h" // For g_settings +#include "biome.h" +#include "script.h" #include "rollback.h" -#include "treegen.h" - -static void stackDump(lua_State *L, std::ostream &o) -{ - int i; - int top = lua_gettop(L); - for (i = 1; i <= top; i++) { /* repeat for each level */ - int t = lua_type(L, i); - switch (t) { - - case LUA_TSTRING: /* strings */ - o<<"\""<= 30){ - dstream<<"Stack is over 30:"< &result) { - std::string result = default_; - getstringfield(L, table, fieldname, result); - return result; + result.clear(); + lua_pushnil(L); + if(index < 0) + index -= 1; + while(lua_next(L, index) != 0){ + // key at index -2 and value at index -1 + std::string key = luaL_checkstring(L, -2); + bool value = lua_toboolean(L, -1); + if(value) + result.insert(key); + // removes value, keeps key for next iteration + lua_pop(L, 1); + } } -static int getintfield_default(lua_State *L, int table, - const char *fieldname, int default_) +static void get_auth_handler(lua_State *L) { - int result = default_; - getintfield(L, table, fieldname, result); - return result; + lua_getglobal(L, "minetest"); + lua_getfield(L, -1, "registered_auth_handler"); + if(lua_isnil(L, -1)){ + lua_pop(L, 1); + lua_getfield(L, -1, "builtin_auth_handler"); + } + if(lua_type(L, -1) != LUA_TTABLE) + throw LuaError(L, "Authentication handler table not valid"); } -static float getfloatfield_default(lua_State *L, int table, - const char *fieldname, float default_) +bool scriptapi_get_auth(lua_State *L, const std::string &playername, + std::string *dst_password, std::set *dst_privs) { - float result = default_; - getfloatfield(L, table, fieldname, result); - return result; -} + realitycheck(L); + assert(lua_checkstack(L, 20)); + StackUnroller stack_unroller(L); -static bool getboolfield_default(lua_State *L, int table, - const char *fieldname, bool default_) -{ - bool result = default_; - getboolfield(L, table, fieldname, result); - return result; -} + get_auth_handler(L); + lua_getfield(L, -1, "get_auth"); + if(lua_type(L, -1) != LUA_TFUNCTION) + throw LuaError(L, "Authentication handler missing get_auth"); + lua_pushstring(L, playername.c_str()); + if(lua_pcall(L, 1, 1, 0)) + script_error(L, "error: %s", lua_tostring(L, -1)); -struct EnumString -{ - int num; - const char *str; -}; + // nil = login not allowed + if(lua_isnil(L, -1)) + return false; + luaL_checktype(L, -1, LUA_TTABLE); -static bool string_to_enum(const EnumString *spec, int &result, - const std::string &str) -{ - const EnumString *esp = spec; - while(esp->str){ - if(str == std::string(esp->str)){ - result = esp->num; - return true; - } - esp++; - } - return false; -} + std::string password; + bool found = getstringfield(L, -1, "password", password); + if(!found) + throw LuaError(L, "Authentication handler didn't return password"); + if(dst_password) + *dst_password = password; -/*static bool enum_to_string(const EnumString *spec, std::string &result, - int num) -{ - const EnumString *esp = spec; - while(esp){ - if(num == esp->num){ - result = esp->str; - return true; - } - esp++; - } - return false; -}*/ + lua_getfield(L, -1, "privileges"); + if(!lua_istable(L, -1)) + throw LuaError(L, + "Authentication handler didn't return privilege table"); + if(dst_privs) + read_privileges(L, -1, *dst_privs); + lua_pop(L, 1); -static int getenumfield(lua_State *L, int table, - const char *fieldname, const EnumString *spec, int default_) -{ - int result = default_; - string_to_enum(spec, result, - getstringfield_default(L, table, fieldname, "")); - return result; + return true; } -static void setintfield(lua_State *L, int table, - const char *fieldname, int value) +void scriptapi_create_auth(lua_State *L, const std::string &playername, + const std::string &password) { - lua_pushinteger(L, value); - if(table < 0) - table -= 1; - lua_setfield(L, table, fieldname); -} + realitycheck(L); + assert(lua_checkstack(L, 20)); + StackUnroller stack_unroller(L); -static void setfloatfield(lua_State *L, int table, - const char *fieldname, float value) -{ - lua_pushnumber(L, value); - if(table < 0) - table -= 1; - lua_setfield(L, table, fieldname); + get_auth_handler(L); + lua_getfield(L, -1, "create_auth"); + if(lua_type(L, -1) != LUA_TFUNCTION) + throw LuaError(L, "Authentication handler missing create_auth"); + lua_pushstring(L, playername.c_str()); + lua_pushstring(L, password.c_str()); + if(lua_pcall(L, 2, 0, 0)) + script_error(L, "error: %s", lua_tostring(L, -1)); } -static void setboolfield(lua_State *L, int table, - const char *fieldname, bool value) +bool scriptapi_set_password(lua_State *L, const std::string &playername, + const std::string &password) { - lua_pushboolean(L, value); - if(table < 0) - table -= 1; - lua_setfield(L, table, fieldname); -} + realitycheck(L); + assert(lua_checkstack(L, 20)); + StackUnroller stack_unroller(L); -static void warn_if_field_exists(lua_State *L, int table, - const char *fieldname, const std::string &message) -{ - lua_getfield(L, table, fieldname); - if(!lua_isnil(L, -1)){ - infostream< &result) { - {TAT_NONE, "none"}, - {TAT_VERTICAL_FRAMES, "vertical_frames"}, - {0, NULL}, -}; + if (!lua_istable(L,index)) + return; + result.clear(); + lua_pushnil(L); + if(index < 0) + index -= 1; + while(lua_next(L, index) != 0){ + // key at index -2 and value at index -1 + std::string name = luaL_checkstring(L, -2); + int rating = luaL_checkinteger(L, -1); + result[name] = rating; + // removes value, keeps key for next iteration + lua_pop(L, 1); + } +} struct EnumString es_BiomeTerrainType[] = { @@ -447,5969 +241,303 @@ struct EnumString es_BiomeTerrainType[] = {0, NULL}, }; +/*****************************************************************************/ +/* Parameters */ +/*****************************************************************************/ /* - C struct <-> Lua table converter functions + DigParams */ -static void push_v3f(lua_State *L, v3f p) +static void set_dig_params(lua_State *L, int table, + const DigParams ¶ms) { - lua_newtable(L); - lua_pushnumber(L, p.X); - lua_setfield(L, -2, "x"); - lua_pushnumber(L, p.Y); - lua_setfield(L, -2, "y"); - lua_pushnumber(L, p.Z); - lua_setfield(L, -2, "z"); + setboolfield(L, table, "diggable", params.diggable); + setfloatfield(L, table, "time", params.time); + setintfield(L, table, "wear", params.wear); } -static v2s16 read_v2s16(lua_State *L, int index) +static void push_dig_params(lua_State *L, + const DigParams ¶ms) { - v2s16 p; - luaL_checktype(L, index, LUA_TTABLE); - lua_getfield(L, index, "x"); - p.X = lua_tonumber(L, -1); - lua_pop(L, 1); - lua_getfield(L, index, "y"); - p.Y = lua_tonumber(L, -1); - lua_pop(L, 1); - return p; + lua_newtable(L); + set_dig_params(L, -1, params); } -static v2f read_v2f(lua_State *L, int index) +/* + HitParams +*/ + +static void set_hit_params(lua_State *L, int table, + const HitParams ¶ms) { - v2f p; - luaL_checktype(L, index, LUA_TTABLE); - lua_getfield(L, index, "x"); - p.X = lua_tonumber(L, -1); - lua_pop(L, 1); - lua_getfield(L, index, "y"); - p.Y = lua_tonumber(L, -1); - lua_pop(L, 1); - return p; + setintfield(L, table, "hp", params.hp); + setintfield(L, table, "wear", params.wear); } -static v3f read_v3f(lua_State *L, int index) -{ - v3f pos; - luaL_checktype(L, index, LUA_TTABLE); - lua_getfield(L, index, "x"); - pos.X = lua_tonumber(L, -1); - lua_pop(L, 1); - lua_getfield(L, index, "y"); - pos.Y = lua_tonumber(L, -1); - lua_pop(L, 1); - lua_getfield(L, index, "z"); - pos.Z = lua_tonumber(L, -1); - lua_pop(L, 1); - return pos; -} - -static v3f check_v3f(lua_State *L, int index) -{ - v3f pos; - luaL_checktype(L, index, LUA_TTABLE); - lua_getfield(L, index, "x"); - pos.X = luaL_checknumber(L, -1); - lua_pop(L, 1); - lua_getfield(L, index, "y"); - pos.Y = luaL_checknumber(L, -1); - lua_pop(L, 1); - lua_getfield(L, index, "z"); - pos.Z = luaL_checknumber(L, -1); - lua_pop(L, 1); - return pos; -} - -static void pushFloatPos(lua_State *L, v3f p) -{ - p /= BS; - push_v3f(L, p); -} - -static v3f checkFloatPos(lua_State *L, int index) -{ - return check_v3f(L, index) * BS; -} - -static void push_v3s16(lua_State *L, v3s16 p) -{ - lua_newtable(L); - lua_pushnumber(L, p.X); - lua_setfield(L, -2, "x"); - lua_pushnumber(L, p.Y); - lua_setfield(L, -2, "y"); - lua_pushnumber(L, p.Z); - lua_setfield(L, -2, "z"); -} - -static v3s16 read_v3s16(lua_State *L, int index) -{ - // Correct rounding at <0 - v3f pf = read_v3f(L, index); - return floatToInt(pf, 1.0); -} - -static v3s16 check_v3s16(lua_State *L, int index) -{ - // Correct rounding at <0 - v3f pf = check_v3f(L, index); - return floatToInt(pf, 1.0); -} - -static void pushnode(lua_State *L, const MapNode &n, INodeDefManager *ndef) +static void push_hit_params(lua_State *L, + const HitParams ¶ms) { lua_newtable(L); - lua_pushstring(L, ndef->get(n).name.c_str()); - lua_setfield(L, -2, "name"); - lua_pushnumber(L, n.getParam1()); - lua_setfield(L, -2, "param1"); - lua_pushnumber(L, n.getParam2()); - lua_setfield(L, -2, "param2"); -} - -static MapNode readnode(lua_State *L, int index, INodeDefManager *ndef) -{ - lua_getfield(L, index, "name"); - const char *name = luaL_checkstring(L, -1); - lua_pop(L, 1); - u8 param1; - lua_getfield(L, index, "param1"); - if(lua_isnil(L, -1)) - param1 = 0; - else - param1 = lua_tonumber(L, -1); - lua_pop(L, 1); - u8 param2; - lua_getfield(L, index, "param2"); - if(lua_isnil(L, -1)) - param2 = 0; - else - param2 = lua_tonumber(L, -1); - lua_pop(L, 1); - return MapNode(ndef, name, param1, param2); -} - -static video::SColor readARGB8(lua_State *L, int index) -{ - video::SColor color; - luaL_checktype(L, index, LUA_TTABLE); - lua_getfield(L, index, "a"); - if(lua_isnumber(L, -1)) - color.setAlpha(lua_tonumber(L, -1)); - lua_pop(L, 1); - lua_getfield(L, index, "r"); - color.setRed(lua_tonumber(L, -1)); - lua_pop(L, 1); - lua_getfield(L, index, "g"); - color.setGreen(lua_tonumber(L, -1)); - lua_pop(L, 1); - lua_getfield(L, index, "b"); - color.setBlue(lua_tonumber(L, -1)); - lua_pop(L, 1); - return color; + set_hit_params(L, -1, params); } -static aabb3f read_aabb3f(lua_State *L, int index, f32 scale) -{ - aabb3f box; - if(lua_istable(L, index)){ - lua_rawgeti(L, index, 1); - box.MinEdge.X = lua_tonumber(L, -1) * scale; - lua_pop(L, 1); - lua_rawgeti(L, index, 2); - box.MinEdge.Y = lua_tonumber(L, -1) * scale; - lua_pop(L, 1); - lua_rawgeti(L, index, 3); - box.MinEdge.Z = lua_tonumber(L, -1) * scale; - lua_pop(L, 1); - lua_rawgeti(L, index, 4); - box.MaxEdge.X = lua_tonumber(L, -1) * scale; - lua_pop(L, 1); - lua_rawgeti(L, index, 5); - box.MaxEdge.Y = lua_tonumber(L, -1) * scale; - lua_pop(L, 1); - lua_rawgeti(L, index, 6); - box.MaxEdge.Z = lua_tonumber(L, -1) * scale; - lua_pop(L, 1); - } - return box; -} +/* + ServerSoundParams +*/ -static std::vector read_aabb3f_vector(lua_State *L, int index, f32 scale) +static void read_server_sound_params(lua_State *L, int index, + ServerSoundParams ¶ms) { - std::vector boxes; + if(index < 0) + index = lua_gettop(L) + 1 + index; + // Clear + params = ServerSoundParams(); if(lua_istable(L, index)){ - int n = lua_objlen(L, index); - // Check if it's a single box or a list of boxes - bool possibly_single_box = (n == 6); - for(int i = 1; i <= n && possibly_single_box; i++){ - lua_rawgeti(L, index, i); - if(!lua_isnumber(L, -1)) - possibly_single_box = false; - lua_pop(L, 1); + getfloatfield(L, index, "gain", params.gain); + getstringfield(L, index, "to_player", params.to_player); + lua_getfield(L, index, "pos"); + if(!lua_isnil(L, -1)){ + v3f p = read_v3f(L, -1)*BS; + params.pos = p; + params.type = ServerSoundParams::SSP_POSITIONAL; } - if(possibly_single_box){ - // Read a single box - boxes.push_back(read_aabb3f(L, index, scale)); - } else { - // Read a list of boxes - for(int i = 1; i <= n; i++){ - lua_rawgeti(L, index, i); - boxes.push_back(read_aabb3f(L, -1, scale)); - lua_pop(L, 1); + lua_pop(L, 1); + lua_getfield(L, index, "object"); + if(!lua_isnil(L, -1)){ + ObjectRef *ref = ObjectRef::checkobject(L, -1); + ServerActiveObject *sao = ObjectRef::getobject(ref); + if(sao){ + params.object = sao->getId(); + params.type = ServerSoundParams::SSP_OBJECT; } } - } - return boxes; -} - -static NodeBox read_nodebox(lua_State *L, int index) -{ - NodeBox nodebox; - if(lua_istable(L, -1)){ - nodebox.type = (NodeBoxType)getenumfield(L, index, "type", - es_NodeBoxType, NODEBOX_REGULAR); - - lua_getfield(L, index, "fixed"); - if(lua_istable(L, -1)) - nodebox.fixed = read_aabb3f_vector(L, -1, BS); - lua_pop(L, 1); - - lua_getfield(L, index, "wall_top"); - if(lua_istable(L, -1)) - nodebox.wall_top = read_aabb3f(L, -1, BS); - lua_pop(L, 1); - - lua_getfield(L, index, "wall_bottom"); - if(lua_istable(L, -1)) - nodebox.wall_bottom = read_aabb3f(L, -1, BS); - lua_pop(L, 1); - - lua_getfield(L, index, "wall_side"); - if(lua_istable(L, -1)) - nodebox.wall_side = read_aabb3f(L, -1, BS); lua_pop(L, 1); + params.max_hear_distance = BS*getfloatfield_default(L, index, + "max_hear_distance", params.max_hear_distance/BS); + getboolfield(L, index, "loop", params.loop); } - return nodebox; } -/* - NoiseParams -*/ -static NoiseParams *read_noiseparams(lua_State *L, int index) -{ - if (index < 0) - index = lua_gettop(L) + 1 + index; - - if (!lua_istable(L, index)) - return NULL; - - NoiseParams *np = new NoiseParams; - - np->offset = getfloatfield_default(L, index, "offset", 0.0); - np->scale = getfloatfield_default(L, index, "scale", 0.0); - lua_getfield(L, index, "spread"); - np->spread = read_v3f(L, -1); - np->seed = getintfield_default(L, index, "seed", 0); - np->octaves = getintfield_default(L, index, "octaves", 0); - np->persist = getfloatfield_default(L, index, "persist", 0.0); - - return np; -} +/*****************************************************************************/ +/* callbacks */ +/*****************************************************************************/ -/* - Groups -*/ -static void read_groups(lua_State *L, int index, - std::map &result) +// Push the list of callbacks (a lua table). +// Then push nargs arguments. +// Then call this function, which +// - runs the callbacks +// - removes the table and arguments from the lua stack +// - pushes the return value, computed depending on mode +void scriptapi_run_callbacks(lua_State *L, int nargs, + RunCallbacksMode mode) { - if (!lua_istable(L,index)) - return; - result.clear(); + // Insert the return value into the lua stack, below the table + assert(lua_gettop(L) >= nargs + 1); lua_pushnil(L); - if(index < 0) - index -= 1; - while(lua_next(L, index) != 0){ - // key at index -2 and value at index -1 - std::string name = luaL_checkstring(L, -2); - int rating = luaL_checkinteger(L, -1); - result[name] = rating; - // removes value, keeps key for next iteration - lua_pop(L, 1); - } -} + lua_insert(L, -(nargs + 1) - 1); + // Stack now looks like this: + // ... ... -/* - Privileges -*/ -static void read_privileges(lua_State *L, int index, - std::set &result) -{ - result.clear(); + int rv = lua_gettop(L) - nargs - 1; + int table = rv + 1; + int arg = table + 1; + + luaL_checktype(L, table, LUA_TTABLE); + + // Foreach lua_pushnil(L); - if(index < 0) - index -= 1; - while(lua_next(L, index) != 0){ + bool first_loop = true; + while(lua_next(L, table) != 0){ // key at index -2 and value at index -1 - std::string key = luaL_checkstring(L, -2); - bool value = lua_toboolean(L, -1); - if(value) - result.insert(key); - // removes value, keeps key for next iteration - lua_pop(L, 1); - } -} - -/* - ToolCapabilities -*/ + luaL_checktype(L, -1, LUA_TFUNCTION); + // Call function + for(int i = 0; i < nargs; i++) + lua_pushvalue(L, arg+i); + if(lua_pcall(L, nargs, 1, 0)) + script_error(L, "error: %s", lua_tostring(L, -1)); -static ToolCapabilities read_tool_capabilities( - lua_State *L, int table) -{ - ToolCapabilities toolcap; - getfloatfield(L, table, "full_punch_interval", toolcap.full_punch_interval); - getintfield(L, table, "max_drop_level", toolcap.max_drop_level); - lua_getfield(L, table, "groupcaps"); - if(lua_istable(L, -1)){ - int table_groupcaps = lua_gettop(L); - lua_pushnil(L); - while(lua_next(L, table_groupcaps) != 0){ - // key at index -2 and value at index -1 - std::string groupname = luaL_checkstring(L, -2); - if(lua_istable(L, -1)){ - int table_groupcap = lua_gettop(L); - // This will be created - ToolGroupCap groupcap; - // Read simple parameters - getintfield(L, table_groupcap, "maxlevel", groupcap.maxlevel); - getintfield(L, table_groupcap, "uses", groupcap.uses); - // DEPRECATED: maxwear - float maxwear = 0; - if(getfloatfield(L, table_groupcap, "maxwear", maxwear)){ - if(maxwear != 0) - groupcap.uses = 1.0/maxwear; - else - groupcap.uses = 0; - infostream<::const_iterator - i = toolcap.groupcaps.begin(); i != toolcap.groupcaps.end(); i++){ - // Create groupcap table - lua_newtable(L); - const std::string &name = i->first; - const ToolGroupCap &groupcap = i->second; - // Create subtable "times" - lua_newtable(L); - for(std::map::const_iterator - i = groupcap.times.begin(); i != groupcap.times.end(); i++){ - int rating = i->first; - float time = i->second; - lua_pushinteger(L, rating); - lua_pushnumber(L, time); - lua_settable(L, -3); + // Remove stuff from stack, leaving only the return value + lua_settop(L, rv); + + // Fix return value in case no callbacks were called + if(first_loop){ + if(mode == RUN_CALLBACKS_MODE_AND || + mode == RUN_CALLBACKS_MODE_AND_SC){ + lua_pop(L, 1); + lua_pushboolean(L, true); + } + else if(mode == RUN_CALLBACKS_MODE_OR || + mode == RUN_CALLBACKS_MODE_OR_SC){ + lua_pop(L, 1); + lua_pushboolean(L, false); } - // Set subtable "times" - lua_setfield(L, -2, "times"); - // Set simple parameters - setintfield(L, -1, "maxlevel", groupcap.maxlevel); - setintfield(L, -1, "uses", groupcap.uses); - // Insert groupcap table into groupcaps table - lua_setfield(L, -2, name.c_str()); } - // Set groupcaps table - lua_setfield(L, -2, "groupcaps"); } -static void push_tool_capabilities(lua_State *L, - const ToolCapabilities &prop) -{ - lua_newtable(L); - set_tool_capabilities(L, -1, prop); -} - -/* - DigParams -*/ - -static void set_dig_params(lua_State *L, int table, - const DigParams ¶ms) +bool scriptapi_on_chat_message(lua_State *L, const std::string &name, + const std::string &message) { - setboolfield(L, table, "diggable", params.diggable); - setfloatfield(L, table, "time", params.time); - setintfield(L, table, "wear", params.wear); -} - -static void push_dig_params(lua_State *L, - const DigParams ¶ms) -{ - lua_newtable(L); - set_dig_params(L, -1, params); -} - -/* - HitParams -*/ - -static void set_hit_params(lua_State *L, int table, - const HitParams ¶ms) -{ - setintfield(L, table, "hp", params.hp); - setintfield(L, table, "wear", params.wear); -} - -static void push_hit_params(lua_State *L, - const HitParams ¶ms) -{ - lua_newtable(L); - set_hit_params(L, -1, params); -} - -/* - PointedThing -*/ - -static void push_pointed_thing(lua_State *L, const PointedThing& pointed) -{ - lua_newtable(L); - if(pointed.type == POINTEDTHING_NODE) - { - lua_pushstring(L, "node"); - lua_setfield(L, -2, "type"); - push_v3s16(L, pointed.node_undersurface); - lua_setfield(L, -2, "under"); - push_v3s16(L, pointed.node_abovesurface); - lua_setfield(L, -2, "above"); - } - else if(pointed.type == POINTEDTHING_OBJECT) - { - lua_pushstring(L, "object"); - lua_setfield(L, -2, "type"); - objectref_get(L, pointed.object_id); - lua_setfield(L, -2, "ref"); - } - else - { - lua_pushstring(L, "nothing"); - lua_setfield(L, -2, "type"); - } -} - -/* - SimpleSoundSpec -*/ - -static void read_soundspec(lua_State *L, int index, SimpleSoundSpec &spec) -{ - if(index < 0) - index = lua_gettop(L) + 1 + index; - if(lua_isnil(L, index)){ - } else if(lua_istable(L, index)){ - getstringfield(L, index, "name", spec.name); - getfloatfield(L, index, "gain", spec.gain); - } else if(lua_isstring(L, index)){ - spec.name = lua_tostring(L, index); - } -} - -/* - ObjectProperties -*/ - -static void read_object_properties(lua_State *L, int index, - ObjectProperties *prop) -{ - if(index < 0) - index = lua_gettop(L) + 1 + index; - if(!lua_istable(L, index)) - return; - - prop->hp_max = getintfield_default(L, -1, "hp_max", 10); - - getboolfield(L, -1, "physical", prop->physical); - - getfloatfield(L, -1, "weight", prop->weight); - - lua_getfield(L, -1, "collisionbox"); - if(lua_istable(L, -1)) - prop->collisionbox = read_aabb3f(L, -1, 1.0); - 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)) - prop->visual_size = read_v2f(L, -1); - lua_pop(L, 1); - - lua_getfield(L, -1, "textures"); - if(lua_istable(L, -1)){ - prop->textures.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->textures.push_back(lua_tostring(L, -1)); - else - prop->textures.push_back(""); - // removes value, keeps key for next iteration - lua_pop(L, 1); - } - } - 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)) - prop->spritediv = read_v2s16(L, -1); - lua_pop(L, 1); - - lua_getfield(L, -1, "initial_sprite_basepos"); - 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); -} - -/* - ItemDefinition -*/ - -static ItemDefinition read_item_definition(lua_State *L, int index, - ItemDefinition default_def = ItemDefinition()) -{ - if(index < 0) - index = lua_gettop(L) + 1 + index; - - // Read the item definition - ItemDefinition def = default_def; - - def.type = (ItemType)getenumfield(L, index, "type", - es_ItemType, ITEM_NONE); - getstringfield(L, index, "name", def.name); - getstringfield(L, index, "description", def.description); - getstringfield(L, index, "inventory_image", def.inventory_image); - getstringfield(L, index, "wield_image", def.wield_image); - - lua_getfield(L, index, "wield_scale"); - if(lua_istable(L, -1)){ - def.wield_scale = check_v3f(L, -1); - } - lua_pop(L, 1); - - def.stack_max = getintfield_default(L, index, "stack_max", def.stack_max); - if(def.stack_max == 0) - def.stack_max = 1; - - lua_getfield(L, index, "on_use"); - def.usable = lua_isfunction(L, -1); - lua_pop(L, 1); - - getboolfield(L, index, "liquids_pointable", def.liquids_pointable); - - 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( - read_tool_capabilities(L, -1)); - } - - // If name is "" (hand), ensure there are ToolCapabilities - // because it will be looked up there whenever any other item has - // no ToolCapabilities - if(def.name == "" && def.tool_capabilities == NULL){ - def.tool_capabilities = new ToolCapabilities(); - } - - lua_getfield(L, index, "groups"); - read_groups(L, -1, def.groups); - lua_pop(L, 1); - - // Client shall immediately place this node when player places the item. - // Server will update the precise end result a moment later. - // "" = no prediction - getstringfield(L, index, "node_placement_prediction", - def.node_placement_prediction); - - return def; -} - -/* - TileDef -*/ - -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 - if(lua_isstring(L, index)){ - // "default_lava.png" - tiledef.name = lua_tostring(L, index); - } - else if(lua_istable(L, index)) - { - // {name="default_lava.png", animation={}} - tiledef.name = ""; - getstringfield(L, index, "name", tiledef.name); - getstringfield(L, index, "image", tiledef.name); // MaterialSpec compat. - tiledef.backface_culling = getboolfield_default( - L, index, "backface_culling", true); - // animation = {} - lua_getfield(L, index, "animation"); - if(lua_istable(L, -1)){ - // {type="vertical_frames", aspect_w=16, aspect_h=16, length=2.0} - tiledef.animation.type = (TileAnimationType) - getenumfield(L, -1, "type", es_TileAnimationType, - TAT_NONE); - tiledef.animation.aspect_w = - getintfield_default(L, -1, "aspect_w", 16); - tiledef.animation.aspect_h = - getintfield_default(L, -1, "aspect_h", 16); - tiledef.animation.length = - getfloatfield_default(L, -1, "length", 1.0); - } - lua_pop(L, 1); - } - - return tiledef; -} - -/* - ContentFeatures -*/ - -static ContentFeatures read_content_features(lua_State *L, int index) -{ - if(index < 0) - 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; - lua_pop(L, 1); - lua_getfield(L, index, "on_destruct"); - if(!lua_isnil(L, -1)) f.has_on_destruct = true; - lua_pop(L, 1); - lua_getfield(L, index, "after_destruct"); - if(!lua_isnil(L, -1)) f.has_after_destruct = true; - lua_pop(L, 1); - - lua_getfield(L, index, "on_rightclick"); - f.rightclickable = lua_isfunction(L, -1); - lua_pop(L, 1); - - /* Name */ - getstringfield(L, index, "name", f.name); - - /* Groups */ - lua_getfield(L, index, "groups"); - read_groups(L, -1, f.groups); - lua_pop(L, 1); - - /* Visual definition */ - - 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 - if(lua_isnil(L, -1)){ - lua_pop(L, 1); - warn_if_field_exists(L, index, "tile_images", - "Deprecated; new name is \"tiles\"."); - lua_getfield(L, index, "tile_images"); - } - if(lua_istable(L, -1)){ - int table = lua_gettop(L); - lua_pushnil(L); - int i = 0; - while(lua_next(L, table) != 0){ - // Read tiledef from value - f.tiledef[i] = read_tiledef(L, -1); - // removes value, keeps key for next iteration - lua_pop(L, 1); - i++; - if(i==6){ - lua_pop(L, 1); - break; - } - } - // Copy last value to all remaining textures - if(i >= 1){ - TileDef lasttile = f.tiledef[i-1]; - while(i < 6){ - f.tiledef[i] = lasttile; - i++; - } - } - } - lua_pop(L, 1); - - // special_tiles = {} - lua_getfield(L, index, "special_tiles"); - // If nil, try the deprecated name "special_materials" instead - if(lua_isnil(L, -1)){ - lua_pop(L, 1); - warn_if_field_exists(L, index, "special_materials", - "Deprecated; new name is \"special_tiles\"."); - lua_getfield(L, index, "special_materials"); - } - if(lua_istable(L, -1)){ - int table = lua_gettop(L); - lua_pushnil(L); - int i = 0; - while(lua_next(L, table) != 0){ - // Read tiledef from value - f.tiledef_special[i] = read_tiledef(L, -1); - // removes value, keeps key for next iteration - lua_pop(L, 1); - i++; - if(i==6){ - lua_pop(L, 1); - break; - } - } - } - lua_pop(L, 1); - - 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); - lua_pop(L, 1); - - f.param_type = (ContentParamType)getenumfield(L, index, "paramtype", - es_ContentParamType, CPT_NONE); - f.param_type_2 = (ContentParamType2)getenumfield(L, index, "paramtype2", - es_ContentParamType2, CPT2_NONE); - - // Warn about some deprecated fields - warn_if_field_exists(L, index, "wall_mounted", - "deprecated: use paramtype2 = 'wallmounted'"); - warn_if_field_exists(L, index, "light_propagates", - "deprecated: determined from paramtype"); - warn_if_field_exists(L, index, "dug_item", - "deprecated: use 'drop' field"); - warn_if_field_exists(L, index, "extra_dug_item", - "deprecated: use 'drop' field"); - warn_if_field_exists(L, index, "extra_dug_item_rarity", - "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); - getboolfield(L, index, "sunlight_propagates", f.sunlight_propagates); - // This is used for collision detection. - // Also for general solidness queries. - getboolfield(L, index, "walkable", f.walkable); - // Player can point to these - getboolfield(L, index, "pointable", f.pointable); - // Player can dig these - getboolfield(L, index, "diggable", f.diggable); - // Player can climb these - getboolfield(L, index, "climbable", f.climbable); - // Player can build on these - getboolfield(L, index, "buildable_to", f.buildable_to); - // Whether the node is non-liquid, source liquid or flowing liquid - f.liquid_type = (LiquidType)getenumfield(L, index, "liquidtype", - es_LiquidType, LIQUID_NONE); - // If the content is liquid, this is the flowing version of the liquid. - getstringfield(L, index, "liquid_alternative_flowing", - f.liquid_alternative_flowing); - // If the content is liquid, this is the source version of the liquid. - getstringfield(L, index, "liquid_alternative_source", - f.liquid_alternative_source); - // Viscosity for fluid flow, ranging from 1 to 7, with - // 1 giving almost instantaneous propagation and 7 being - // 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); - lua_pop(L, 1); - - lua_getfield(L, index, "selection_box"); - if(lua_istable(L, -1)) - f.selection_box = read_nodebox(L, -1); - lua_pop(L, 1); - - // Set to true if paramtype used to be 'facedir_simple' - 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)){ - lua_getfield(L, -1, "footstep"); - read_soundspec(L, -1, f.sound_footstep); - lua_pop(L, 1); - lua_getfield(L, -1, "dig"); - read_soundspec(L, -1, f.sound_dig); - lua_pop(L, 1); - lua_getfield(L, -1, "dug"); - read_soundspec(L, -1, f.sound_dug); - lua_pop(L, 1); - } - lua_pop(L, 1); - - return f; -} - -/* - Inventory stuff -*/ - -static ItemStack read_item(lua_State *L, int index); -static std::vector read_items(lua_State *L, int index); -// creates a table of ItemStacks -static void push_items(lua_State *L, const std::vector &items); - -static void inventory_set_list_from_lua(Inventory *inv, const char *name, - lua_State *L, int tableindex, int forcesize=-1) -{ - if(tableindex < 0) - tableindex = lua_gettop(L) + 1 + tableindex; - // If nil, delete list - if(lua_isnil(L, tableindex)){ - inv->deleteList(name); - return; - } - // Otherwise set list - std::vector items = read_items(L, tableindex); - int listsize = (forcesize != -1) ? forcesize : items.size(); - InventoryList *invlist = inv->addList(name, listsize); - int index = 0; - for(std::vector::const_iterator - i = items.begin(); i != items.end(); i++){ - if(forcesize != -1 && index == forcesize) - break; - invlist->changeItem(index, *i); - index++; - } - while(forcesize != -1 && index < forcesize){ - invlist->deleteItem(index); - index++; - } -} - -static void inventory_get_list_to_lua(Inventory *inv, const char *name, - lua_State *L) -{ - InventoryList *invlist = inv->getList(name); - if(invlist == NULL){ - lua_pushnil(L); - return; - } - std::vector items; - for(u32 i=0; igetSize(); i++) - items.push_back(invlist->getItem(i)); - push_items(L, items); -} - -/* - Helpful macros for userdata classes -*/ - -#define method(class, name) {#name, class::l_##name} - -/* - LuaItemStack -*/ - -class LuaItemStack -{ -private: - ItemStack m_stack; - - static const char className[]; - static const luaL_reg methods[]; - - // Exported functions - - // garbage collector - static int gc_object(lua_State *L) - { - LuaItemStack *o = *(LuaItemStack **)(lua_touserdata(L, 1)); - delete o; - return 0; - } - - // is_empty(self) -> true/false - static int l_is_empty(lua_State *L) - { - LuaItemStack *o = checkobject(L, 1); - ItemStack &item = o->m_stack; - lua_pushboolean(L, item.empty()); - return 1; - } - - // get_name(self) -> string - static int l_get_name(lua_State *L) - { - LuaItemStack *o = checkobject(L, 1); - ItemStack &item = o->m_stack; - lua_pushstring(L, item.name.c_str()); - return 1; - } - - // get_count(self) -> number - static int l_get_count(lua_State *L) - { - LuaItemStack *o = checkobject(L, 1); - ItemStack &item = o->m_stack; - lua_pushinteger(L, item.count); - return 1; - } - - // get_wear(self) -> number - static int l_get_wear(lua_State *L) - { - LuaItemStack *o = checkobject(L, 1); - ItemStack &item = o->m_stack; - lua_pushinteger(L, item.wear); - return 1; - } - - // get_metadata(self) -> string - static int l_get_metadata(lua_State *L) - { - LuaItemStack *o = checkobject(L, 1); - ItemStack &item = o->m_stack; - lua_pushlstring(L, item.metadata.c_str(), item.metadata.size()); - return 1; - } - - // clear(self) -> true - static int l_clear(lua_State *L) - { - LuaItemStack *o = checkobject(L, 1); - o->m_stack.clear(); - lua_pushboolean(L, true); - return 1; - } - - // replace(self, itemstack or itemstring or table or nil) -> true - static int l_replace(lua_State *L) - { - LuaItemStack *o = checkobject(L, 1); - o->m_stack = read_item(L, 2); - lua_pushboolean(L, true); - return 1; - } - - // to_string(self) -> string - static int l_to_string(lua_State *L) - { - LuaItemStack *o = checkobject(L, 1); - std::string itemstring = o->m_stack.getItemString(); - lua_pushstring(L, itemstring.c_str()); - return 1; - } - - // to_table(self) -> table or nil - static int l_to_table(lua_State *L) - { - LuaItemStack *o = checkobject(L, 1); - const ItemStack &item = o->m_stack; - if(item.empty()) - { - lua_pushnil(L); - } - else - { - lua_newtable(L); - lua_pushstring(L, item.name.c_str()); - lua_setfield(L, -2, "name"); - lua_pushinteger(L, item.count); - lua_setfield(L, -2, "count"); - lua_pushinteger(L, item.wear); - lua_setfield(L, -2, "wear"); - lua_pushlstring(L, item.metadata.c_str(), item.metadata.size()); - lua_setfield(L, -2, "metadata"); - } - return 1; - } - - // get_stack_max(self) -> number - static int l_get_stack_max(lua_State *L) - { - LuaItemStack *o = checkobject(L, 1); - ItemStack &item = o->m_stack; - lua_pushinteger(L, item.getStackMax(get_server(L)->idef())); - return 1; - } - - // get_free_space(self) -> number - static int l_get_free_space(lua_State *L) - { - LuaItemStack *o = checkobject(L, 1); - ItemStack &item = o->m_stack; - lua_pushinteger(L, item.freeSpace(get_server(L)->idef())); - return 1; - } - - // is_known(self) -> true/false - // Checks if the item is defined. - static int l_is_known(lua_State *L) - { - LuaItemStack *o = checkobject(L, 1); - ItemStack &item = o->m_stack; - bool is_known = item.isKnown(get_server(L)->idef()); - lua_pushboolean(L, is_known); - return 1; - } - - // get_definition(self) -> table - // Returns the item definition table from minetest.registered_items, - // or a fallback one (name="unknown") - static int l_get_definition(lua_State *L) - { - LuaItemStack *o = checkobject(L, 1); - ItemStack &item = o->m_stack; - - // Get minetest.registered_items[name] - lua_getglobal(L, "minetest"); - lua_getfield(L, -1, "registered_items"); - luaL_checktype(L, -1, LUA_TTABLE); - lua_getfield(L, -1, item.name.c_str()); - if(lua_isnil(L, -1)) - { - lua_pop(L, 1); - lua_getfield(L, -1, "unknown"); - } - return 1; - } - - // get_tool_capabilities(self) -> table - // Returns the effective tool digging properties. - // Returns those of the hand ("") if this item has none associated. - static int l_get_tool_capabilities(lua_State *L) - { - LuaItemStack *o = checkobject(L, 1); - ItemStack &item = o->m_stack; - const ToolCapabilities &prop = - item.getToolCapabilities(get_server(L)->idef()); - push_tool_capabilities(L, prop); - return 1; - } - - // add_wear(self, amount) -> true/false - // The range for "amount" is [0,65535]. Wear is only added if the item - // is a tool. Adding wear might destroy the item. - // Returns true if the item is (or was) a tool. - static int l_add_wear(lua_State *L) - { - LuaItemStack *o = checkobject(L, 1); - ItemStack &item = o->m_stack; - int amount = lua_tointeger(L, 2); - bool result = item.addWear(amount, get_server(L)->idef()); - lua_pushboolean(L, result); - return 1; - } - - // add_item(self, itemstack or itemstring or table or nil) -> itemstack - // Returns leftover item stack - static int l_add_item(lua_State *L) - { - LuaItemStack *o = checkobject(L, 1); - ItemStack &item = o->m_stack; - ItemStack newitem = read_item(L, 2); - ItemStack leftover = item.addItem(newitem, get_server(L)->idef()); - create(L, leftover); - return 1; - } - - // item_fits(self, itemstack or itemstring or table or nil) -> true/false, itemstack - // First return value is true iff the new item fits fully into the stack - // Second return value is the would-be-left-over item stack - static int l_item_fits(lua_State *L) - { - LuaItemStack *o = checkobject(L, 1); - ItemStack &item = o->m_stack; - ItemStack newitem = read_item(L, 2); - ItemStack restitem; - bool fits = item.itemFits(newitem, &restitem, get_server(L)->idef()); - lua_pushboolean(L, fits); // first return value - create(L, restitem); // second return value - return 2; - } - - // take_item(self, takecount=1) -> itemstack - static int l_take_item(lua_State *L) - { - LuaItemStack *o = checkobject(L, 1); - ItemStack &item = o->m_stack; - u32 takecount = 1; - if(!lua_isnone(L, 2)) - takecount = luaL_checkinteger(L, 2); - ItemStack taken = item.takeItem(takecount); - create(L, taken); - return 1; - } - - // peek_item(self, peekcount=1) -> itemstack - static int l_peek_item(lua_State *L) - { - LuaItemStack *o = checkobject(L, 1); - ItemStack &item = o->m_stack; - u32 peekcount = 1; - if(!lua_isnone(L, 2)) - peekcount = lua_tointeger(L, 2); - ItemStack peekaboo = item.peekItem(peekcount); - create(L, peekaboo); - return 1; - } - -public: - LuaItemStack(const ItemStack &item): - m_stack(item) - { - } - - ~LuaItemStack() - { - } - - const ItemStack& getItem() const - { - return m_stack; - } - ItemStack& getItem() - { - 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) - { - ItemStack item = read_item(L, 1); - LuaItemStack *o = new LuaItemStack(item); - *(void **)(lua_newuserdata(L, sizeof(void *))) = o; - luaL_getmetatable(L, className); - lua_setmetatable(L, -2); - return 1; - } - // Not callable from Lua - static int create(lua_State *L, const ItemStack &item) - { - LuaItemStack *o = new LuaItemStack(item); - *(void **)(lua_newuserdata(L, sizeof(void *))) = o; - luaL_getmetatable(L, className); - lua_setmetatable(L, -2); - return 1; - } - - static LuaItemStack* checkobject(lua_State *L, int narg) - { - luaL_checktype(L, narg, LUA_TUSERDATA); - void *ud = luaL_checkudata(L, narg, className); - if(!ud) luaL_typerror(L, narg, className); - return *(LuaItemStack**)ud; // unbox pointer - } - - static void Register(lua_State *L) - { - lua_newtable(L); - int methodtable = lua_gettop(L); - luaL_newmetatable(L, className); - int metatable = lua_gettop(L); - - lua_pushliteral(L, "__metatable"); - lua_pushvalue(L, methodtable); - lua_settable(L, metatable); // hide metatable from Lua getmetatable() - - lua_pushliteral(L, "__index"); - lua_pushvalue(L, methodtable); - lua_settable(L, metatable); - - lua_pushliteral(L, "__gc"); - lua_pushcfunction(L, gc_object); - lua_settable(L, metatable); - - lua_pop(L, 1); // drop metatable - - luaL_openlib(L, 0, methods, 0); // fill methodtable - lua_pop(L, 1); // drop methodtable - - // Can be created from Lua (LuaItemStack(itemstack or itemstring or table or nil)) - lua_register(L, className, create_object); - } -}; -const char LuaItemStack::className[] = "ItemStack"; -const luaL_reg LuaItemStack::methods[] = { - method(LuaItemStack, is_empty), - method(LuaItemStack, get_name), - method(LuaItemStack, get_count), - method(LuaItemStack, get_wear), - method(LuaItemStack, get_metadata), - method(LuaItemStack, clear), - method(LuaItemStack, replace), - method(LuaItemStack, to_string), - method(LuaItemStack, to_table), - method(LuaItemStack, get_stack_max), - method(LuaItemStack, get_free_space), - method(LuaItemStack, is_known), - method(LuaItemStack, get_definition), - method(LuaItemStack, get_tool_capabilities), - method(LuaItemStack, add_wear), - method(LuaItemStack, add_item), - method(LuaItemStack, item_fits), - method(LuaItemStack, take_item), - method(LuaItemStack, peek_item), - {0,0} -}; - -static ItemStack read_item(lua_State *L, int index) -{ - if(index < 0) - index = lua_gettop(L) + 1 + index; - - if(lua_isnil(L, index)) - { - return ItemStack(); - } - else if(lua_isuserdata(L, index)) - { - // Convert from LuaItemStack - LuaItemStack *o = LuaItemStack::checkobject(L, index); - return o->getItem(); - } - else if(lua_isstring(L, index)) - { - // Convert from itemstring - std::string itemstring = lua_tostring(L, index); - IItemDefManager *idef = get_server(L)->idef(); - try - { - ItemStack item; - item.deSerialize(itemstring, idef); - return item; - } - catch(SerializationError &e) - { - infostream<<"WARNING: unable to create item from itemstring" - <<": "<idef(); - std::string name = getstringfield_default(L, index, "name", ""); - int count = getintfield_default(L, index, "count", 1); - int wear = getintfield_default(L, index, "wear", 0); - std::string metadata = getstringfield_default(L, index, "metadata", ""); - return ItemStack(name, count, wear, metadata, idef); - } - else - { - throw LuaError(L, "Expecting itemstack, itemstring, table or nil"); - } -} - -static std::vector read_items(lua_State *L, int index) -{ - if(index < 0) - index = lua_gettop(L) + 1 + index; - - std::vector items; - luaL_checktype(L, index, LUA_TTABLE); - lua_pushnil(L); - while(lua_next(L, index) != 0){ - // key at index -2 and value at index -1 - items.push_back(read_item(L, -1)); - // removes value, keeps key for next iteration - lua_pop(L, 1); - } - return items; -} - -// creates a table of ItemStacks -static void push_items(lua_State *L, const std::vector &items) -{ - // Get the table insert function - lua_getglobal(L, "table"); - lua_getfield(L, -1, "insert"); - int table_insert = lua_gettop(L); - // Create and fill table - lua_newtable(L); - int table = lua_gettop(L); - for(u32 i=0; igetInventory(ref->m_loc); - } - - static InventoryList* getlist(lua_State *L, InvRef *ref, - const char *listname) - { - Inventory *inv = getinv(L, ref); - if(!inv) - return NULL; - return inv->getList(listname); - } - - static void reportInventoryChange(lua_State *L, InvRef *ref) - { - // 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)); - delete o; - return 0; - } - - // is_empty(self, listname) -> true/false - static int l_is_empty(lua_State *L) - { - InvRef *ref = checkobject(L, 1); - const char *listname = luaL_checkstring(L, 2); - InventoryList *list = getlist(L, ref, listname); - if(list && list->getUsedSlots() > 0){ - lua_pushboolean(L, false); - } else { - lua_pushboolean(L, true); - } - return 1; - } - - // get_size(self, listname) - static int l_get_size(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->getSize()); - } else { - lua_pushinteger(L, 0); - } - 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) - { - InvRef *ref = checkobject(L, 1); - const char *listname = luaL_checkstring(L, 2); - int newsize = luaL_checknumber(L, 3); - Inventory *inv = getinv(L, ref); - if(newsize == 0){ - inv->deleteList(listname); - reportInventoryChange(L, ref); - return 0; - } - InventoryList *list = inv->getList(listname); - if(list){ - list->setSize(newsize); - } else { - list = inv->addList(listname, newsize); - } - reportInventoryChange(L, ref); - 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) - { - InvRef *ref = checkobject(L, 1); - const char *listname = luaL_checkstring(L, 2); - int i = luaL_checknumber(L, 3) - 1; - InventoryList *list = getlist(L, ref, listname); - ItemStack item; - if(list != NULL && i >= 0 && i < (int) list->getSize()) - item = list->getItem(i); - LuaItemStack::create(L, item); - return 1; - } - - // set_stack(self, listname, i, stack) -> true/false - static int l_set_stack(lua_State *L) - { - InvRef *ref = checkobject(L, 1); - const char *listname = luaL_checkstring(L, 2); - int i = luaL_checknumber(L, 3) - 1; - ItemStack newitem = read_item(L, 4); - InventoryList *list = getlist(L, ref, listname); - if(list != NULL && i >= 0 && i < (int) list->getSize()){ - list->changeItem(i, newitem); - reportInventoryChange(L, ref); - lua_pushboolean(L, true); - } else { - lua_pushboolean(L, false); - } - return 1; - } - - // get_list(self, listname) -> list or nil - static int l_get_list(lua_State *L) - { - InvRef *ref = checkobject(L, 1); - const char *listname = luaL_checkstring(L, 2); - Inventory *inv = getinv(L, ref); - inventory_get_list_to_lua(inv, listname, L); - return 1; - } - - // set_list(self, listname, list) - static int l_set_list(lua_State *L) - { - InvRef *ref = checkobject(L, 1); - const char *listname = luaL_checkstring(L, 2); - Inventory *inv = getinv(L, ref); - InventoryList *list = inv->getList(listname); - if(list) - inventory_set_list_from_lua(inv, listname, L, 3, - list->getSize()); - else - inventory_set_list_from_lua(inv, listname, L, 3); - reportInventoryChange(L, ref); - return 0; - } - - // add_item(self, listname, itemstack or itemstring or table or nil) -> itemstack - // Returns the leftover stack - static int l_add_item(lua_State *L) - { - InvRef *ref = checkobject(L, 1); - const char *listname = luaL_checkstring(L, 2); - ItemStack item = read_item(L, 3); - InventoryList *list = getlist(L, ref, listname); - if(list){ - ItemStack leftover = list->addItem(item); - if(leftover.count != item.count) - reportInventoryChange(L, ref); - LuaItemStack::create(L, leftover); - } else { - LuaItemStack::create(L, item); - } - return 1; - } - - // room_for_item(self, listname, itemstack or itemstring or table or nil) -> true/false - // Returns true if the item completely fits into the list - static int l_room_for_item(lua_State *L) - { - InvRef *ref = checkobject(L, 1); - const char *listname = luaL_checkstring(L, 2); - ItemStack item = read_item(L, 3); - InventoryList *list = getlist(L, ref, listname); - if(list){ - lua_pushboolean(L, list->roomForItem(item)); - } else { - lua_pushboolean(L, false); - } - return 1; - } - - // contains_item(self, listname, itemstack or itemstring or table or nil) -> true/false - // Returns true if the list contains the given count of the given item name - static int l_contains_item(lua_State *L) - { - InvRef *ref = checkobject(L, 1); - const char *listname = luaL_checkstring(L, 2); - ItemStack item = read_item(L, 3); - InventoryList *list = getlist(L, ref, listname); - if(list){ - lua_pushboolean(L, list->containsItem(item)); - } else { - lua_pushboolean(L, false); - } - return 1; - } - - // remove_item(self, listname, itemstack or itemstring or table or nil) -> itemstack - // Returns the items that were actually removed - static int l_remove_item(lua_State *L) - { - InvRef *ref = checkobject(L, 1); - const char *listname = luaL_checkstring(L, 2); - ItemStack item = read_item(L, 3); - InventoryList *list = getlist(L, ref, listname); - if(list){ - ItemStack removed = list->removeItem(item); - if(!removed.empty()) - reportInventoryChange(L, ref); - LuaItemStack::create(L, removed); - } else { - LuaItemStack::create(L, ItemStack()); - } - 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) - { - } - - ~InvRef() - { - } - - // Creates an InvRef and leaves it on top of stack - // Not callable from Lua; all references are created on the C side. - static void create(lua_State *L, const InventoryLocation &loc) - { - InvRef *o = new InvRef(loc); - *(void **)(lua_newuserdata(L, sizeof(void *))) = o; - luaL_getmetatable(L, className); - lua_setmetatable(L, -2); - } - static void createPlayer(lua_State *L, Player *player) - { - InventoryLocation loc; - loc.setPlayer(player->getName()); - create(L, loc); - } - static void createNodeMeta(lua_State *L, v3s16 p) - { - InventoryLocation loc; - loc.setNodeMeta(p); - create(L, loc); - } - - static void Register(lua_State *L) - { - lua_newtable(L); - int methodtable = lua_gettop(L); - luaL_newmetatable(L, className); - int metatable = lua_gettop(L); - - lua_pushliteral(L, "__metatable"); - lua_pushvalue(L, methodtable); - lua_settable(L, metatable); // hide metatable from Lua getmetatable() - - lua_pushliteral(L, "__index"); - lua_pushvalue(L, methodtable); - lua_settable(L, metatable); - - lua_pushliteral(L, "__gc"); - lua_pushcfunction(L, gc_object); - lua_settable(L, metatable); - - lua_pop(L, 1); // drop metatable - - luaL_openlib(L, 0, methods, 0); // fill methodtable - lua_pop(L, 1); // drop methodtable - - // Cannot be created from Lua - //lua_register(L, className, create_object); - } -}; -const char InvRef::className[] = "InvRef"; -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), - method(InvRef, set_list), - method(InvRef, add_item), - method(InvRef, room_for_item), - method(InvRef, contains_item), - method(InvRef, remove_item), - method(InvRef, get_location), - {0,0} -}; - -/* - NodeMetaRef -*/ - -class NodeMetaRef -{ -private: - v3s16 m_p; - ServerEnvironment *m_env; - - static const char className[]; - static const luaL_reg methods[]; - - static NodeMetaRef *checkobject(lua_State *L, int narg) - { - luaL_checktype(L, narg, LUA_TUSERDATA); - void *ud = luaL_checkudata(L, narg, className); - 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); - if(meta == NULL && auto_create) - { - meta = new NodeMetadata(ref->m_env->getGameDef()); - ref->m_env->getMap().setNodeMetadata(ref->m_p, meta); - } - return meta; - } - - static void reportMetadataChange(NodeMetaRef *ref) - { - // NOTE: This same code is in rollback_interface.cpp - // Inform other things that the metadata has changed - v3s16 blockpos = getNodeBlockPos(ref->m_p); - MapEditEvent event; - event.type = MEET_BLOCK_NODE_METADATA_CHANGED; - event.p = blockpos; - ref->m_env->getMap().dispatchEvent(&event); - // Set the block to be saved - MapBlock *block = ref->m_env->getMap().getBlockNoCreateNoEx(blockpos); - if(block) - 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)); - delete o; - return 0; - } - - // get_string(self, name) - static int l_get_string(lua_State *L) - { - NodeMetaRef *ref = checkobject(L, 1); - std::string name = luaL_checkstring(L, 2); - - NodeMetadata *meta = getmeta(ref, false); - if(meta == NULL){ - lua_pushlstring(L, "", 0); - return 1; - } - std::string str = meta->getString(name); - lua_pushlstring(L, str.c_str(), str.size()); - return 1; - } - - // set_string(self, name, var) - static int l_set_string(lua_State *L) - { - NodeMetaRef *ref = checkobject(L, 1); - std::string name = luaL_checkstring(L, 2); - size_t len = 0; - const char *s = lua_tolstring(L, 3, &len); - std::string str(s, len); - - NodeMetadata *meta = getmeta(ref, !str.empty()); - if(meta == NULL || str == meta->getString(name)) - return 0; - meta->setString(name, str); - reportMetadataChange(ref); - return 0; - } - - // get_int(self, name) - static int l_get_int(lua_State *L) - { - NodeMetaRef *ref = checkobject(L, 1); - std::string name = lua_tostring(L, 2); - - NodeMetadata *meta = getmeta(ref, false); - if(meta == NULL){ - lua_pushnumber(L, 0); - return 1; - } - std::string str = meta->getString(name); - lua_pushnumber(L, stoi(str)); - return 1; - } - - // set_int(self, name, var) - static int l_set_int(lua_State *L) - { - NodeMetaRef *ref = checkobject(L, 1); - std::string name = lua_tostring(L, 2); - int a = lua_tointeger(L, 3); - std::string str = itos(a); - - NodeMetadata *meta = getmeta(ref, true); - if(meta == NULL || str == meta->getString(name)) - return 0; - meta->setString(name, str); - reportMetadataChange(ref); - return 0; - } - - // get_float(self, name) - static int l_get_float(lua_State *L) - { - NodeMetaRef *ref = checkobject(L, 1); - std::string name = lua_tostring(L, 2); - - NodeMetadata *meta = getmeta(ref, false); - if(meta == NULL){ - lua_pushnumber(L, 0); - return 1; - } - std::string str = meta->getString(name); - lua_pushnumber(L, stof(str)); - return 1; - } - - // set_float(self, name, var) - static int l_set_float(lua_State *L) - { - NodeMetaRef *ref = checkobject(L, 1); - std::string name = lua_tostring(L, 2); - float a = lua_tonumber(L, 3); - std::string str = ftos(a); - - NodeMetadata *meta = getmeta(ref, true); - if(meta == NULL || str == meta->getString(name)) - return 0; - meta->setString(name, str); - reportMetadataChange(ref); - return 0; - } - - // get_inventory(self) - static int l_get_inventory(lua_State *L) - { - NodeMetaRef *ref = checkobject(L, 1); - getmeta(ref, true); // try to ensure the metadata exists - InvRef::createNodeMeta(L, ref->m_p); - return 1; - } - - // to_table(self) - static int l_to_table(lua_State *L) - { - NodeMetaRef *ref = checkobject(L, 1); - - NodeMetadata *meta = getmeta(ref, true); - if(meta == NULL){ - lua_pushnil(L); - return 1; - } - lua_newtable(L); - // fields - lua_newtable(L); - { - std::map fields = meta->getStrings(); - for(std::map::const_iterator - i = fields.begin(); i != fields.end(); i++){ - const std::string &name = i->first; - const std::string &value = i->second; - lua_pushlstring(L, name.c_str(), name.size()); - lua_pushlstring(L, value.c_str(), value.size()); - lua_settable(L, -3); - } - } - lua_setfield(L, -2, "fields"); - // inventory - lua_newtable(L); - Inventory *inv = meta->getInventory(); - if(inv){ - std::vector lists = inv->getLists(); - for(std::vector::const_iterator - i = lists.begin(); i != lists.end(); i++){ - inventory_get_list_to_lua(inv, (*i)->getName().c_str(), L); - lua_setfield(L, -2, (*i)->getName().c_str()); - } - } - lua_setfield(L, -2, "inventory"); - return 1; - } - - // from_table(self, table) - static int l_from_table(lua_State *L) - { - NodeMetaRef *ref = checkobject(L, 1); - int base = 2; - - if(lua_isnil(L, base)){ - // No metadata - ref->m_env->getMap().removeNodeMetadata(ref->m_p); - lua_pushboolean(L, true); - return 1; - } - - // Has metadata; clear old one first - ref->m_env->getMap().removeNodeMetadata(ref->m_p); - // Create new metadata - NodeMetadata *meta = getmeta(ref, true); - // Set fields - lua_getfield(L, base, "fields"); - int fieldstable = lua_gettop(L); - lua_pushnil(L); - while(lua_next(L, fieldstable) != 0){ - // key at index -2 and value at index -1 - std::string name = lua_tostring(L, -2); - size_t cl; - const char *cs = lua_tolstring(L, -1, &cl); - std::string value(cs, cl); - meta->setString(name, value); - lua_pop(L, 1); // removes value, keeps key for next iteration - } - // Set inventory - Inventory *inv = meta->getInventory(); - lua_getfield(L, base, "inventory"); - int inventorytable = lua_gettop(L); - lua_pushnil(L); - while(lua_next(L, inventorytable) != 0){ - // key at index -2 and value at index -1 - std::string name = lua_tostring(L, -2); - inventory_set_list_from_lua(inv, name.c_str(), L, -1); - lua_pop(L, 1); // removes value, keeps key for next iteration - } - reportMetadataChange(ref); - lua_pushboolean(L, true); - return 1; - } - -public: - NodeMetaRef(v3s16 p, ServerEnvironment *env): - m_p(p), - m_env(env) - { - } - - ~NodeMetaRef() - { - } - - // Creates an NodeMetaRef and leaves it on top of stack - // Not callable from Lua; all references are created on the C side. - static void create(lua_State *L, v3s16 p, ServerEnvironment *env) - { - NodeMetaRef *o = new NodeMetaRef(p, env); - //infostream<<"NodeMetaRef::create: o="<m_object; - return co; - } -private: - static LuaEntitySAO* getluaobject(ObjectRef *ref) - { - ServerActiveObject *obj = getobject(ref); - if(obj == NULL) - return NULL; - if(obj->getType() != ACTIVEOBJECT_TYPE_LUAENTITY) - return NULL; - return (LuaEntitySAO*)obj; - } - - static PlayerSAO* getplayersao(ObjectRef *ref) - { - ServerActiveObject *obj = getobject(ref); - if(obj == NULL) - return NULL; - if(obj->getType() != ACTIVEOBJECT_TYPE_PLAYER) - return NULL; - return (PlayerSAO*)obj; - } - - static Player* getplayer(ObjectRef *ref) - { - PlayerSAO *playersao = getplayersao(ref); - if(playersao == NULL) - return NULL; - return playersao->getPlayer(); - } - - // Exported functions - - // garbage collector - static int gc_object(lua_State *L) { - ObjectRef *o = *(ObjectRef **)(lua_touserdata(L, 1)); - //infostream<<"ObjectRef::gc_object: o="<setPos(pos); - return 0; - } - - // moveto(self, pos, continuous=false) - static int l_moveto(lua_State *L) - { - ObjectRef *ref = checkobject(L, 1); - //LuaEntitySAO *co = getluaobject(ref); - ServerActiveObject *co = getobject(ref); - if(co == NULL) return 0; - // pos - v3f pos = checkFloatPos(L, 2); - // continuous - bool continuous = lua_toboolean(L, 3); - // Do it - co->moveTo(pos, continuous); - return 0; - } - - // punch(self, puncher, time_from_last_punch, tool_capabilities, dir) - static int l_punch(lua_State *L) - { - ObjectRef *ref = checkobject(L, 1); - ObjectRef *puncher_ref = checkobject(L, 2); - ServerActiveObject *co = getobject(ref); - ServerActiveObject *puncher = getobject(puncher_ref); - if(co == NULL) return 0; - if(puncher == NULL) return 0; - 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, 3)) - time_from_last_punch = lua_tonumber(L, 3); - ToolCapabilities toolcap = read_tool_capabilities(L, 4); - dir.normalize(); - // Do it - co->punch(dir, &toolcap, puncher, time_from_last_punch); - return 0; - } - - // right_click(self, clicker); clicker = an another ObjectRef - static int l_right_click(lua_State *L) - { - ObjectRef *ref = checkobject(L, 1); - ObjectRef *ref2 = checkobject(L, 2); - ServerActiveObject *co = getobject(ref); - ServerActiveObject *co2 = getobject(ref2); - if(co == NULL) return 0; - if(co2 == NULL) return 0; - // Do it - co->rightClick(co2); - return 0; - } - - // set_hp(self, hp) - // hp = number of hitpoints (2 * number of hearts) - // returns: nil - static int l_set_hp(lua_State *L) - { - ObjectRef *ref = checkobject(L, 1); - luaL_checknumber(L, 2); - ServerActiveObject *co = getobject(ref); - if(co == NULL) return 0; - int hp = lua_tonumber(L, 2); - /*infostream<<"ObjectRef::l_set_hp(): id="<getId() - <<" hp="<setHP(hp); - // Return - return 0; - } - - // get_hp(self) - // returns: number of hitpoints (2 * number of hearts) - // 0 if not applicable to this type of object - static int l_get_hp(lua_State *L) - { - ObjectRef *ref = checkobject(L, 1); - ServerActiveObject *co = getobject(ref); - if(co == NULL){ - // Default hp is 1 - lua_pushnumber(L, 1); - return 1; - } - int hp = co->getHP(); - /*infostream<<"ObjectRef::l_get_hp(): id="<getId() - <<" hp="<getInventoryLocation(); - if(get_server(L)->getInventory(loc) != NULL) - InvRef::create(L, loc); - else - lua_pushnil(L); // An object may have no inventory (nil) - return 1; - } - - // get_wield_list(self) - static int l_get_wield_list(lua_State *L) - { - ObjectRef *ref = checkobject(L, 1); - ServerActiveObject *co = getobject(ref); - if(co == NULL) return 0; - // Do it - lua_pushstring(L, co->getWieldList().c_str()); - return 1; - } - - // get_wield_index(self) - static int l_get_wield_index(lua_State *L) - { - ObjectRef *ref = checkobject(L, 1); - ServerActiveObject *co = getobject(ref); - if(co == NULL) return 0; - // Do it - lua_pushinteger(L, co->getWieldIndex() + 1); - return 1; - } - - // get_wielded_item(self) - static int l_get_wielded_item(lua_State *L) - { - ObjectRef *ref = checkobject(L, 1); - ServerActiveObject *co = getobject(ref); - if(co == NULL){ - // Empty ItemStack - LuaItemStack::create(L, ItemStack()); - return 1; - } - // Do it - LuaItemStack::create(L, co->getWieldedItem()); - return 1; - } - - // set_wielded_item(self, itemstack or itemstring or table or nil) - static int l_set_wielded_item(lua_State *L) - { - ObjectRef *ref = checkobject(L, 1); - ServerActiveObject *co = getobject(ref); - if(co == NULL) return 0; - // Do it - ItemStack item = read_item(L, 2); - bool success = co->setWieldedItem(item); - lua_pushboolean(L, success); - return 1; - } - - // set_armor_groups(self, groups) - static int l_set_armor_groups(lua_State *L) - { - ObjectRef *ref = checkobject(L, 1); - ServerActiveObject *co = getobject(ref); - if(co == NULL) return 0; - // Do it - ItemGroupList groups; - read_groups(L, 2, groups); - co->setArmorGroups(groups); - 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) - { - ObjectRef *ref = checkobject(L, 1); - ServerActiveObject *co = getobject(ref); - if(co == NULL) return 0; - ObjectProperties *prop = co->accessObjectProperties(); - if(!prop) - return 0; - read_object_properties(L, 2, prop); - co->notifyObjectPropertiesModified(); - return 0; - } - - /* LuaEntitySAO-only */ - - // setvelocity(self, {x=num, y=num, z=num}) - static int l_setvelocity(lua_State *L) - { - ObjectRef *ref = checkobject(L, 1); - LuaEntitySAO *co = getluaobject(ref); - if(co == NULL) return 0; - v3f pos = checkFloatPos(L, 2); - // Do it - co->setVelocity(pos); - return 0; - } - - // getvelocity(self) - static int l_getvelocity(lua_State *L) - { - ObjectRef *ref = checkobject(L, 1); - LuaEntitySAO *co = getluaobject(ref); - if(co == NULL) return 0; - // Do it - v3f v = co->getVelocity(); - pushFloatPos(L, v); - return 1; - } - - // setacceleration(self, {x=num, y=num, z=num}) - static int l_setacceleration(lua_State *L) - { - ObjectRef *ref = checkobject(L, 1); - LuaEntitySAO *co = getluaobject(ref); - if(co == NULL) return 0; - // pos - v3f pos = checkFloatPos(L, 2); - // Do it - co->setAcceleration(pos); - return 0; - } - - // getacceleration(self) - static int l_getacceleration(lua_State *L) - { - ObjectRef *ref = checkobject(L, 1); - LuaEntitySAO *co = getluaobject(ref); - if(co == NULL) return 0; - // Do it - v3f v = co->getAcceleration(); - pushFloatPos(L, v); - return 1; - } - - // setyaw(self, radians) - static int l_setyaw(lua_State *L) - { - ObjectRef *ref = checkobject(L, 1); - LuaEntitySAO *co = getluaobject(ref); - if(co == NULL) return 0; - float yaw = luaL_checknumber(L, 2) * core::RADTODEG; - // Do it - co->setYaw(yaw); - return 0; - } - - // getyaw(self) - static int l_getyaw(lua_State *L) - { - ObjectRef *ref = checkobject(L, 1); - LuaEntitySAO *co = getluaobject(ref); - if(co == NULL) return 0; - // Do it - float yaw = co->getYaw() * core::DEGTORAD; - lua_pushnumber(L, yaw); - return 1; - } - - // settexturemod(self, mod) - static int l_settexturemod(lua_State *L) - { - ObjectRef *ref = checkobject(L, 1); - LuaEntitySAO *co = getluaobject(ref); - if(co == NULL) return 0; - // Do it - std::string mod = luaL_checkstring(L, 2); - 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) - { - ObjectRef *ref = checkobject(L, 1); - LuaEntitySAO *co = getluaobject(ref); - if(co == NULL) return 0; - // Do it - v2s16 p(0,0); - if(!lua_isnil(L, 2)) - p = read_v2s16(L, 2); - int num_frames = 1; - if(!lua_isnil(L, 3)) - num_frames = lua_tonumber(L, 3); - float framelength = 0.2; - if(!lua_isnil(L, 4)) - framelength = lua_tonumber(L, 4); - bool select_horiz_by_yawpitch = false; - if(!lua_isnil(L, 5)) - select_horiz_by_yawpitch = lua_toboolean(L, 5); - co->setSprite(p, num_frames, framelength, select_horiz_by_yawpitch); - return 0; - } - - // DEPRECATED - // get_entity_name(self) - static int l_get_entity_name(lua_State *L) - { - ObjectRef *ref = checkobject(L, 1); - LuaEntitySAO *co = getluaobject(ref); - if(co == NULL) return 0; - // Do it - std::string name = co->getName(); - lua_pushstring(L, name.c_str()); - return 1; - } - - // get_luaentity(self) - static int l_get_luaentity(lua_State *L) - { - ObjectRef *ref = checkobject(L, 1); - LuaEntitySAO *co = getluaobject(ref); - if(co == NULL) return 0; - // Do it - luaentity_get(L, co->getId()); - return 1; - } - - /* Player-only */ - - // is_player(self) - static int l_is_player(lua_State *L) - { - ObjectRef *ref = checkobject(L, 1); - Player *player = getplayer(ref); - lua_pushboolean(L, (player != NULL)); - return 1; - } - - // get_player_name(self) - static int l_get_player_name(lua_State *L) - { - ObjectRef *ref = checkobject(L, 1); - Player *player = getplayer(ref); - if(player == NULL){ - lua_pushlstring(L, "", 0); - return 1; - } - // Do it - lua_pushstring(L, player->getName()); - return 1; - } - - // get_look_dir(self) - static int l_get_look_dir(lua_State *L) - { - ObjectRef *ref = checkobject(L, 1); - Player *player = getplayer(ref); - if(player == NULL) return 0; - // Do it - float pitch = player->getRadPitch(); - float yaw = player->getRadYaw(); - v3f v(cos(pitch)*cos(yaw), sin(pitch), cos(pitch)*sin(yaw)); - push_v3f(L, v); - return 1; - } - - // get_look_pitch(self) - static int l_get_look_pitch(lua_State *L) - { - ObjectRef *ref = checkobject(L, 1); - Player *player = getplayer(ref); - if(player == NULL) return 0; - // Do it - lua_pushnumber(L, player->getRadPitch()); - return 1; - } - - // get_look_yaw(self) - static int l_get_look_yaw(lua_State *L) - { - ObjectRef *ref = checkobject(L, 1); - Player *player = getplayer(ref); - if(player == NULL) return 0; - // Do it - lua_pushnumber(L, player->getRadYaw()); - return 1; - } - - // set_inventory_formspec(self, formspec) - static int l_set_inventory_formspec(lua_State *L) - { - ObjectRef *ref = checkobject(L, 1); - Player *player = getplayer(ref); - if(player == NULL) return 0; - std::string formspec = luaL_checkstring(L, 2); - - player->inventory_formspec = formspec; - get_server(L)->reportInventoryFormspecModified(player->getName()); - lua_pushboolean(L, true); - return 1; - } - - // get_inventory_formspec(self) -> formspec - static int l_get_inventory_formspec(lua_State *L) - { - ObjectRef *ref = checkobject(L, 1); - Player *player = getplayer(ref); - if(player == NULL) return 0; - - std::string formspec = player->inventory_formspec; - 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) - { - //infostream<<"ObjectRef created for id="<getId()<getId() == 0){ - ObjectRef::create(L, cobj); - } else { - objectref_get(L, cobj->getId()); - } -} - -class LuaPerlinNoise -{ -private: - int seed; - int octaves; - float persistence; - float scale; - static const char className[]; - static const luaL_reg methods[]; - - // Exported functions - - // garbage collector - static int gc_object(lua_State *L) - { - LuaPerlinNoise *o = *(LuaPerlinNoise **)(lua_touserdata(L, 1)); - delete o; - return 0; - } - - static int l_get2d(lua_State *L) - { - LuaPerlinNoise *o = checkobject(L, 1); - v2f pos2d = read_v2f(L,2); - lua_Number val = noise2d_perlin(pos2d.X/o->scale, pos2d.Y/o->scale, o->seed, o->octaves, o->persistence); - lua_pushnumber(L, val); - return 1; - } - static int l_get3d(lua_State *L) - { - LuaPerlinNoise *o = checkobject(L, 1); - v3f pos3d = read_v3f(L,2); - lua_Number val = noise3d_perlin(pos3d.X/o->scale, pos3d.Y/o->scale, pos3d.Z/o->scale, o->seed, o->octaves, o->persistence); - lua_pushnumber(L, val); - return 1; - } - -public: - LuaPerlinNoise(int a_seed, int a_octaves, float a_persistence, - float a_scale): - seed(a_seed), - octaves(a_octaves), - persistence(a_persistence), - scale(a_scale) - { - } - - ~LuaPerlinNoise() - { - } - - // LuaPerlinNoise(seed, octaves, persistence, scale) - // Creates an LuaPerlinNoise and leaves it on top of stack - static int create_object(lua_State *L) - { - int seed = luaL_checkint(L, 1); - int octaves = luaL_checkint(L, 2); - 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); - lua_setmetatable(L, -2); - return 1; - } - - static LuaPerlinNoise* checkobject(lua_State *L, int narg) - { - luaL_checktype(L, narg, LUA_TUSERDATA); - void *ud = luaL_checkudata(L, narg, className); - if(!ud) luaL_typerror(L, narg, className); - return *(LuaPerlinNoise**)ud; // unbox pointer - } - - static void Register(lua_State *L) - { - lua_newtable(L); - int methodtable = lua_gettop(L); - luaL_newmetatable(L, className); - int metatable = lua_gettop(L); - - lua_pushliteral(L, "__metatable"); - lua_pushvalue(L, methodtable); - lua_settable(L, metatable); // hide metatable from Lua getmetatable() - - lua_pushliteral(L, "__index"); - lua_pushvalue(L, methodtable); - lua_settable(L, metatable); - - lua_pushliteral(L, "__gc"); - lua_pushcfunction(L, gc_object); - lua_settable(L, metatable); - - lua_pop(L, 1); // drop metatable - - luaL_openlib(L, 0, methods, 0); // fill methodtable - lua_pop(L, 1); // drop methodtable - - // Can be created from Lua (PerlinNoise(seed, octaves, persistence) - lua_register(L, className, create_object); - } -}; -const char LuaPerlinNoise::className[] = "PerlinNoise"; -const luaL_reg LuaPerlinNoise::methods[] = { - method(LuaPerlinNoise, get2d), - method(LuaPerlinNoise, get3d), - {0,0} -}; - -/* - PerlinNoiseMap - */ -class LuaPerlinNoiseMap -{ -private: - Noise *noise; - static const char className[]; - static const luaL_reg methods[]; - - static int gc_object(lua_State *L) - { - LuaPerlinNoiseMap *o = *(LuaPerlinNoiseMap **)(lua_touserdata(L, 1)); - delete o; - return 0; - } - - static int l_get2dMap(lua_State *L) - { - int i = 0; - - LuaPerlinNoiseMap *o = checkobject(L, 1); - v2f p = read_v2f(L, 2); - - Noise *n = o->noise; - n->perlinMap2D(p.X, p.Y); - - lua_newtable(L); - for (int y = 0; y != n->sy; y++) { - lua_newtable(L); - for (int x = 0; x != n->sx; x++) { - float noiseval = n->np->offset + n->np->scale * n->result[i++]; - lua_pushnumber(L, noiseval); - lua_rawseti(L, -2, x + 1); - } - lua_rawseti(L, -2, y + 1); - } - return 1; - } - - static int l_get3dMap(lua_State *L) - { - int i = 0; - - LuaPerlinNoiseMap *o = checkobject(L, 1); - v3f p = read_v3f(L, 2); - - Noise *n = o->noise; - n->perlinMap3D(p.X, p.Y, p.Z); - - lua_newtable(L); - for (int z = 0; z != n->sz; z++) { - lua_newtable(L); - for (int y = 0; y != n->sy; y++) { - lua_newtable(L); - for (int x = 0; x != n->sx; x++) { - lua_pushnumber(L, n->np->offset + n->np->scale * n->result[i++]); - lua_rawseti(L, -2, x + 1); - } - lua_rawseti(L, -2, y + 1); - } - lua_rawseti(L, -2, z + 1); - } - return 1; - } - -public: - LuaPerlinNoiseMap(NoiseParams *np, int seed, v3s16 size) { - noise = new Noise(np, seed, size.X, size.Y, size.Z); - } - - ~LuaPerlinNoiseMap() - { - delete noise->np; - delete noise; - } - - // LuaPerlinNoiseMap(np, size) - // Creates an LuaPerlinNoiseMap and leaves it on top of stack - static int create_object(lua_State *L) - { - NoiseParams *np = read_noiseparams(L, 1); - if (!np) - return 0; - v3s16 size = read_v3s16(L, 2); - - LuaPerlinNoiseMap *o = new LuaPerlinNoiseMap(np, 0, size); - *(void **)(lua_newuserdata(L, sizeof(void *))) = o; - luaL_getmetatable(L, className); - lua_setmetatable(L, -2); - return 1; - } - - static LuaPerlinNoiseMap *checkobject(lua_State *L, int narg) - { - luaL_checktype(L, narg, LUA_TUSERDATA); - - void *ud = luaL_checkudata(L, narg, className); - if (!ud) - luaL_typerror(L, narg, className); - - return *(LuaPerlinNoiseMap **)ud; // unbox pointer - } - - static void Register(lua_State *L) - { - lua_newtable(L); - int methodtable = lua_gettop(L); - luaL_newmetatable(L, className); - int metatable = lua_gettop(L); - - lua_pushliteral(L, "__metatable"); - lua_pushvalue(L, methodtable); - lua_settable(L, metatable); // hide metatable from Lua getmetatable() - - lua_pushliteral(L, "__index"); - lua_pushvalue(L, methodtable); - lua_settable(L, metatable); - - lua_pushliteral(L, "__gc"); - lua_pushcfunction(L, gc_object); - lua_settable(L, metatable); - - lua_pop(L, 1); // drop metatable - - luaL_openlib(L, 0, methods, 0); // fill methodtable - lua_pop(L, 1); // drop methodtable - - // Can be created from Lua (PerlinNoiseMap(np, size) - lua_register(L, className, create_object); - } -}; -const char LuaPerlinNoiseMap::className[] = "PerlinNoiseMap"; -const luaL_reg LuaPerlinNoiseMap::methods[] = { - method(LuaPerlinNoiseMap, get2dMap), - method(LuaPerlinNoiseMap, get3dMap), - {0,0} -}; - -/* - NodeTimerRef -*/ - -class NodeTimerRef -{ -private: - v3s16 m_p; - ServerEnvironment *m_env; - - static const char className[]; - static const luaL_reg methods[]; - - static int gc_object(lua_State *L) { - NodeTimerRef *o = *(NodeTimerRef **)(lua_touserdata(L, 1)); - delete o; - return 0; - } - - static NodeTimerRef *checkobject(lua_State *L, int narg) - { - luaL_checktype(L, narg, LUA_TUSERDATA); - void *ud = luaL_checkudata(L, narg, className); - if(!ud) luaL_typerror(L, narg, className); - return *(NodeTimerRef**)ud; // unbox pointer - } - - static int l_set(lua_State *L) - { - NodeTimerRef *o = checkobject(L, 1); - ServerEnvironment *env = o->m_env; - if(env == NULL) return 0; - f32 t = luaL_checknumber(L,2); - f32 e = luaL_checknumber(L,3); - env->getMap().setNodeTimer(o->m_p,NodeTimer(t,e)); - return 0; - } - - static int l_start(lua_State *L) - { - NodeTimerRef *o = checkobject(L, 1); - ServerEnvironment *env = o->m_env; - if(env == NULL) return 0; - f32 t = luaL_checknumber(L,2); - env->getMap().setNodeTimer(o->m_p,NodeTimer(t,0)); - return 0; - } - - static int l_stop(lua_State *L) - { - NodeTimerRef *o = checkobject(L, 1); - ServerEnvironment *env = o->m_env; - if(env == NULL) return 0; - env->getMap().removeNodeTimer(o->m_p); - return 0; - } - - static int l_is_started(lua_State *L) - { - NodeTimerRef *o = checkobject(L, 1); - ServerEnvironment *env = o->m_env; - if(env == NULL) return 0; - - NodeTimer t = env->getMap().getNodeTimer(o->m_p); - lua_pushboolean(L,(t.timeout != 0)); - return 1; - } - - static int l_get_timeout(lua_State *L) - { - NodeTimerRef *o = checkobject(L, 1); - ServerEnvironment *env = o->m_env; - if(env == NULL) return 0; - - NodeTimer t = env->getMap().getNodeTimer(o->m_p); - lua_pushnumber(L,t.timeout); - return 1; - } - - static int l_get_elapsed(lua_State *L) - { - NodeTimerRef *o = checkobject(L, 1); - ServerEnvironment *env = o->m_env; - if(env == NULL) return 0; - - NodeTimer t = env->getMap().getNodeTimer(o->m_p); - lua_pushnumber(L,t.elapsed); - return 1; - } - -public: - NodeTimerRef(v3s16 p, ServerEnvironment *env): - m_p(p), - m_env(env) - { - } - - ~NodeTimerRef() - { - } - - // Creates an NodeTimerRef and leaves it on top of stack - // Not callable from Lua; all references are created on the C side. - static void create(lua_State *L, v3s16 p, ServerEnvironment *env) - { - NodeTimerRef *o = new NodeTimerRef(p, env); - *(void **)(lua_newuserdata(L, sizeof(void *))) = o; - luaL_getmetatable(L, className); - lua_setmetatable(L, -2); - } - - static void set_null(lua_State *L) - { - NodeTimerRef *o = checkobject(L, -1); - o->m_env = NULL; - } - - static void Register(lua_State *L) - { - lua_newtable(L); - int methodtable = lua_gettop(L); - luaL_newmetatable(L, className); - int metatable = lua_gettop(L); - - lua_pushliteral(L, "__metatable"); - lua_pushvalue(L, methodtable); - lua_settable(L, metatable); // hide metatable from Lua getmetatable() - - lua_pushliteral(L, "__index"); - lua_pushvalue(L, methodtable); - lua_settable(L, metatable); - - lua_pushliteral(L, "__gc"); - lua_pushcfunction(L, gc_object); - lua_settable(L, metatable); - - lua_pop(L, 1); // drop metatable - - luaL_openlib(L, 0, methods, 0); // fill methodtable - lua_pop(L, 1); // drop methodtable - - // Cannot be created from Lua - //lua_register(L, className, create_object); - } -}; -const char NodeTimerRef::className[] = "NodeTimerRef"; -const luaL_reg NodeTimerRef::methods[] = { - method(NodeTimerRef, start), - method(NodeTimerRef, set), - method(NodeTimerRef, stop), - method(NodeTimerRef, is_started), - method(NodeTimerRef, get_timeout), - method(NodeTimerRef, get_elapsed), - {0,0} -}; - -/* - EnvRef -*/ - -class EnvRef -{ -private: - ServerEnvironment *m_env; - - static const char className[]; - static const luaL_reg methods[]; - - static int gc_object(lua_State *L) { - EnvRef *o = *(EnvRef **)(lua_touserdata(L, 1)); - delete o; - return 0; - } - - static EnvRef *checkobject(lua_State *L, int narg) - { - luaL_checktype(L, narg, LUA_TUSERDATA); - void *ud = luaL_checkudata(L, narg, className); - if(!ud) luaL_typerror(L, narg, className); - return *(EnvRef**)ud; // unbox pointer - } - - // Exported functions - - // EnvRef:set_node(pos, node) - // pos = {x=num, y=num, z=num} - static int l_set_node(lua_State *L) - { - EnvRef *o = checkobject(L, 1); - ServerEnvironment *env = o->m_env; - if(env == NULL) return 0; - INodeDefManager *ndef = env->getGameDef()->ndef(); - // parameters - v3s16 pos = read_v3s16(L, 2); - MapNode n = readnode(L, 3, ndef); - // Do it - bool succeeded = env->setNode(pos, n); - lua_pushboolean(L, succeeded); - return 1; - } - - static int l_add_node(lua_State *L) - { - return l_set_node(L); - } - - // EnvRef:remove_node(pos) - // pos = {x=num, y=num, z=num} - static int l_remove_node(lua_State *L) - { - EnvRef *o = checkobject(L, 1); - ServerEnvironment *env = o->m_env; - if(env == NULL) return 0; - INodeDefManager *ndef = env->getGameDef()->ndef(); - // parameters - v3s16 pos = read_v3s16(L, 2); - // Do it - bool succeeded = env->removeNode(pos); - lua_pushboolean(L, succeeded); - return 1; - } - - // EnvRef:get_node(pos) - // pos = {x=num, y=num, z=num} - static int l_get_node(lua_State *L) - { - EnvRef *o = checkobject(L, 1); - ServerEnvironment *env = o->m_env; - if(env == NULL) return 0; - // pos - v3s16 pos = read_v3s16(L, 2); - // Do it - MapNode n = env->getMap().getNodeNoEx(pos); - // Return node - pushnode(L, n, env->getGameDef()->ndef()); - return 1; - } - - // EnvRef:get_node_or_nil(pos) - // pos = {x=num, y=num, z=num} - static int l_get_node_or_nil(lua_State *L) - { - EnvRef *o = checkobject(L, 1); - ServerEnvironment *env = o->m_env; - if(env == NULL) return 0; - // pos - v3s16 pos = read_v3s16(L, 2); - // Do it - try{ - MapNode n = env->getMap().getNode(pos); - // Return node - pushnode(L, n, env->getGameDef()->ndef()); - return 1; - } catch(InvalidPositionException &e) - { - lua_pushnil(L); - return 1; - } - } - - // EnvRef:get_node_light(pos, timeofday) - // pos = {x=num, y=num, z=num} - // timeofday: nil = current time, 0 = night, 0.5 = day - static int l_get_node_light(lua_State *L) - { - EnvRef *o = checkobject(L, 1); - ServerEnvironment *env = o->m_env; - if(env == NULL) return 0; - // Do it - v3s16 pos = read_v3s16(L, 2); - u32 time_of_day = env->getTimeOfDay(); - 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, true); - MapNode n = env->getMap().getNodeNoEx(pos); - try{ - MapNode n = env->getMap().getNode(pos); - INodeDefManager *ndef = env->getGameDef()->ndef(); - lua_pushinteger(L, n.getLightBlend(dnr, ndef)); - return 1; - } catch(InvalidPositionException &e) - { - lua_pushnil(L); - return 1; - } - } - - // EnvRef:place_node(pos, node) - // pos = {x=num, y=num, z=num} - static int l_place_node(lua_State *L) - { - EnvRef *o = checkobject(L, 1); - ServerEnvironment *env = o->m_env; - if(env == NULL) return 0; - v3s16 pos = read_v3s16(L, 2); - MapNode n = readnode(L, 3, env->getGameDef()->ndef()); - - // Don't attempt to load non-loaded area as of now - MapNode n_old = env->getMap().getNodeNoEx(pos); - if(n_old.getContent() == CONTENT_IGNORE){ - lua_pushboolean(L, false); - return 1; - } - // Create item to place - INodeDefManager *ndef = get_server(L)->ndef(); - IItemDefManager *idef = get_server(L)->idef(); - ItemStack item(ndef->get(n).name, 1, 0, "", idef); - // Make pointed position - PointedThing pointed; - pointed.type = POINTEDTHING_NODE; - pointed.node_abovesurface = pos; - pointed.node_undersurface = pos + v3s16(0,-1,0); - // Place it with a NULL placer (appears in Lua as a non-functional - // ObjectRef) - bool success = scriptapi_item_on_place(L, item, NULL, pointed); - lua_pushboolean(L, success); - return 1; - } - - // EnvRef:dig_node(pos) - // pos = {x=num, y=num, z=num} - static int l_dig_node(lua_State *L) - { - EnvRef *o = checkobject(L, 1); - ServerEnvironment *env = o->m_env; - if(env == NULL) return 0; - v3s16 pos = read_v3s16(L, 2); - - // Don't attempt to load non-loaded area as of now - MapNode n = env->getMap().getNodeNoEx(pos); - if(n.getContent() == CONTENT_IGNORE){ - lua_pushboolean(L, false); - return 1; - } - // Dig it out with a NULL digger (appears in Lua as a - // non-functional ObjectRef) - bool success = scriptapi_node_on_dig(L, pos, n, NULL); - lua_pushboolean(L, success); - return 1; - } - - // EnvRef:punch_node(pos) - // pos = {x=num, y=num, z=num} - static int l_punch_node(lua_State *L) - { - EnvRef *o = checkobject(L, 1); - ServerEnvironment *env = o->m_env; - if(env == NULL) return 0; - v3s16 pos = read_v3s16(L, 2); - - // Don't attempt to load non-loaded area as of now - MapNode n = env->getMap().getNodeNoEx(pos); - if(n.getContent() == CONTENT_IGNORE){ - lua_pushboolean(L, false); - return 1; - } - // Punch it with a NULL puncher (appears in Lua as a non-functional - // ObjectRef) - bool success = scriptapi_node_on_punch(L, pos, n, NULL); - lua_pushboolean(L, success); - return 1; - } - - // EnvRef:get_meta(pos) - static int l_get_meta(lua_State *L) - { - //infostream<<"EnvRef::l_get_meta()"<m_env; - if(env == NULL) return 0; - // Do it - v3s16 p = read_v3s16(L, 2); - NodeMetaRef::create(L, p, env); - return 1; - } - - // EnvRef:get_node_timer(pos) - static int l_get_node_timer(lua_State *L) - { - EnvRef *o = checkobject(L, 1); - ServerEnvironment *env = o->m_env; - if(env == NULL) return 0; - // Do it - v3s16 p = read_v3s16(L, 2); - NodeTimerRef::create(L, p, env); - return 1; - } - - // EnvRef:add_entity(pos, entityname) -> ObjectRef or nil - // pos = {x=num, y=num, z=num} - static int l_add_entity(lua_State *L) - { - //infostream<<"EnvRef::l_add_entity()"<m_env; - if(env == NULL) return 0; - // pos - v3f pos = checkFloatPos(L, 2); - // content - const char *name = luaL_checkstring(L, 3); - // Do it - ServerActiveObject *obj = new LuaEntitySAO(env, pos, name, ""); - int objectid = env->addActiveObject(obj); - // If failed to add, return nothing (reads as nil) - if(objectid == 0) - return 0; - // Return ObjectRef - objectref_get_or_create(L, obj); - return 1; - } - - // EnvRef:add_item(pos, itemstack or itemstring or table) -> ObjectRef or nil - // pos = {x=num, y=num, z=num} - static int l_add_item(lua_State *L) - { - //infostream<<"EnvRef::l_add_item()"<m_env; - if(env == NULL) return 0; - // pos - v3f pos = checkFloatPos(L, 2); - // item - ItemStack item = read_item(L, 3); - if(item.empty() || !item.isKnown(get_server(L)->idef())) - return 0; - // Use minetest.spawn_item to spawn a __builtin:item - lua_getglobal(L, "minetest"); - lua_getfield(L, -1, "spawn_item"); - if(lua_isnil(L, -1)) - return 0; - lua_pushvalue(L, 2); - lua_pushstring(L, item.getItemString().c_str()); - if(lua_pcall(L, 2, 1, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); - return 1; - /*lua_pushvalue(L, 1); - lua_pushstring(L, "__builtin:item"); - lua_pushstring(L, item.getItemString().c_str()); - return l_add_entity(L);*/ - /*// Do it - ServerActiveObject *obj = createItemSAO(env, pos, item.getItemString()); - int objectid = env->addActiveObject(obj); - // If failed to add, return nothing (reads as nil) - if(objectid == 0) - return 0; - // Return ObjectRef - objectref_get_or_create(L, obj); - return 1;*/ - } - - // EnvRef:add_rat(pos) - // pos = {x=num, y=num, z=num} - static int l_add_rat(lua_State *L) - { - infostream<<"EnvRef::l_add_rat(): C++ mobs have been removed." - <<" Doing nothing."<m_env; - if(env == NULL) return 0; - // Do it - const char *name = luaL_checkstring(L, 2); - Player *player = env->getPlayer(name); - if(player == NULL){ - lua_pushnil(L); - return 1; - } - PlayerSAO *sao = player->getPlayerSAO(); - if(sao == NULL){ - lua_pushnil(L); - return 1; - } - // Put player on stack - objectref_get_or_create(L, sao); - return 1; - } - - // EnvRef:get_objects_inside_radius(pos, radius) - static int l_get_objects_inside_radius(lua_State *L) - { - // Get the table insert function - lua_getglobal(L, "table"); - lua_getfield(L, -1, "insert"); - int table_insert = lua_gettop(L); - // Get environemnt - EnvRef *o = checkobject(L, 1); - ServerEnvironment *env = o->m_env; - if(env == NULL) return 0; - // Do it - v3f pos = checkFloatPos(L, 2); - float radius = luaL_checknumber(L, 3) * BS; - std::set ids = env->getObjectsInsideRadius(pos, radius); - lua_newtable(L); - int table = lua_gettop(L); - for(std::set::const_iterator - i = ids.begin(); i != ids.end(); i++){ - ServerActiveObject *obj = env->getActiveObject(*i); - // Insert object reference into table - lua_pushvalue(L, table_insert); - lua_pushvalue(L, table); - objectref_get_or_create(L, obj); - if(lua_pcall(L, 2, 0, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); - } - return 1; - } - - // EnvRef:set_timeofday(val) - // val = 0...1 - static int l_set_timeofday(lua_State *L) - { - EnvRef *o = checkobject(L, 1); - ServerEnvironment *env = o->m_env; - if(env == NULL) return 0; - // Do it - float timeofday_f = luaL_checknumber(L, 2); - assert(timeofday_f >= 0.0 && timeofday_f <= 1.0); - int timeofday_mh = (int)(timeofday_f * 24000.0); - // This should be set directly in the environment but currently - // such changes aren't immediately sent to the clients, so call - // the server instead. - //env->setTimeOfDay(timeofday_mh); - get_server(L)->setTimeOfDay(timeofday_mh); - return 0; - } - - // EnvRef:get_timeofday() -> 0...1 - static int l_get_timeofday(lua_State *L) - { - EnvRef *o = checkobject(L, 1); - ServerEnvironment *env = o->m_env; - if(env == NULL) return 0; - // Do it - int timeofday_mh = env->getTimeOfDay(); - float timeofday_f = (float)timeofday_mh / 24000.0; - lua_pushnumber(L, timeofday_f); - return 1; - } - - - // EnvRef:find_node_near(pos, radius, nodenames) -> pos or nil - // nodenames: eg. {"ignore", "group:tree"} or "default:dirt" - static int l_find_node_near(lua_State *L) - { - EnvRef *o = checkobject(L, 1); - ServerEnvironment *env = o->m_env; - if(env == NULL) return 0; - INodeDefManager *ndef = get_server(L)->ndef(); - v3s16 pos = read_v3s16(L, 2); - int radius = luaL_checkinteger(L, 3); - std::set filter; - if(lua_istable(L, 4)){ - int table = 4; - lua_pushnil(L); - while(lua_next(L, table) != 0){ - // key at index -2 and value at index -1 - luaL_checktype(L, -1, LUA_TSTRING); - ndef->getIds(lua_tostring(L, -1), filter); - // removes value, keeps key for next iteration - lua_pop(L, 1); - } - } else if(lua_isstring(L, 4)){ - ndef->getIds(lua_tostring(L, 4), filter); - } - - for(int d=1; d<=radius; d++){ - core::list list; - getFacePositions(list, d); - for(core::list::Iterator i = list.begin(); - i != list.end(); i++){ - v3s16 p = pos + (*i); - content_t c = env->getMap().getNodeNoEx(p).getContent(); - if(filter.count(c) != 0){ - push_v3s16(L, p); - return 1; - } - } - } - return 0; - } - - // EnvRef:find_nodes_in_area(minp, maxp, nodenames) -> list of positions - // nodenames: eg. {"ignore", "group:tree"} or "default:dirt" - static int l_find_nodes_in_area(lua_State *L) - { - EnvRef *o = checkobject(L, 1); - ServerEnvironment *env = o->m_env; - if(env == NULL) return 0; - INodeDefManager *ndef = get_server(L)->ndef(); - v3s16 minp = read_v3s16(L, 2); - v3s16 maxp = read_v3s16(L, 3); - std::set filter; - if(lua_istable(L, 4)){ - int table = 4; - lua_pushnil(L); - while(lua_next(L, table) != 0){ - // key at index -2 and value at index -1 - luaL_checktype(L, -1, LUA_TSTRING); - ndef->getIds(lua_tostring(L, -1), filter); - // removes value, keeps key for next iteration - lua_pop(L, 1); - } - } else if(lua_isstring(L, 4)){ - ndef->getIds(lua_tostring(L, 4), filter); - } - - // Get the table insert function - 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++) - for(s16 y=minp.Y; y<=maxp.Y; y++) - for(s16 z=minp.Z; z<=maxp.Z; z++) - { - v3s16 p(x,y,z); - content_t c = env->getMap().getNodeNoEx(p).getContent(); - if(filter.count(c) != 0){ - lua_pushvalue(L, table_insert); - lua_pushvalue(L, table); - push_v3s16(L, p); - if(lua_pcall(L, 2, 0, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); - } - } - return 1; - } - - // EnvRef:get_perlin(seeddiff, octaves, persistence, scale) - // returns world-specific PerlinNoise - static int l_get_perlin(lua_State *L) - { - EnvRef *o = checkobject(L, 1); - ServerEnvironment *env = o->m_env; - if(env == NULL) return 0; - - int seeddiff = luaL_checkint(L, 2); - int octaves = luaL_checkint(L, 3); - 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; - luaL_getmetatable(L, "PerlinNoise"); - lua_setmetatable(L, -2); - return 1; - } - - // EnvRef:get_perlin_map(noiseparams, size) - // returns world-specific PerlinNoiseMap - static int l_get_perlin_map(lua_State *L) - { - EnvRef *o = checkobject(L, 1); - ServerEnvironment *env = o->m_env; - if (env == NULL) - return 0; - - NoiseParams *np = read_noiseparams(L, 2); - if (!np) - return 0; - v3s16 size = read_v3s16(L, 3); - - int seed = (int)(env->getServerMap().getSeed()); - LuaPerlinNoiseMap *n = new LuaPerlinNoiseMap(np, seed, size); - *(void **)(lua_newuserdata(L, sizeof(void *))) = n; - luaL_getmetatable(L, "PerlinNoiseMap"); - lua_setmetatable(L, -2); - return 1; - } - - // EnvRef:clear_objects() - // clear all objects in the environment - static int l_clear_objects(lua_State *L) - { - EnvRef *o = checkobject(L, 1); - o->m_env->clearAllObjects(); - 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); - } - getintfield(L, 3, "seed", tree_def.seed); - } - else - return 0; - treegen::spawn_ltree (env, p0, ndef, tree_def); - return 1; - } - -public: - EnvRef(ServerEnvironment *env): - m_env(env) - { - //infostream<<"EnvRef created"< get next value - static int l_next(lua_State *L) - { - LuaPseudoRandom *o = checkobject(L, 1); - int min = 0; - int max = 32767; - lua_settop(L, 3); // Fill 2 and 3 with nil if they don't exist - if(!lua_isnil(L, 2)) - min = luaL_checkinteger(L, 2); - if(!lua_isnil(L, 3)) - max = luaL_checkinteger(L, 3); - if(max < min){ - errorstream<<"PseudoRandom.next(): max="< 32767/5) - throw LuaError(L, "PseudoRandom.next() max-min is not 32767 and is > 32768/5. This is disallowed due to the bad random distribution the implementation would otherwise make."); - PseudoRandom &pseudo = o->m_pseudo; - int val = pseudo.next(); - val = (val % (max-min+1)) + min; - lua_pushinteger(L, val); - return 1; - } - -public: - LuaPseudoRandom(int seed): - m_pseudo(seed) - { - } - - ~LuaPseudoRandom() - { - } - - const PseudoRandom& getItem() const - { - return m_pseudo; - } - PseudoRandom& getItem() - { - return m_pseudo; - } - - // LuaPseudoRandom(seed) - // Creates an LuaPseudoRandom and leaves it on top of stack - static int create_object(lua_State *L) - { - int seed = luaL_checknumber(L, 1); - LuaPseudoRandom *o = new LuaPseudoRandom(seed); - *(void **)(lua_newuserdata(L, sizeof(void *))) = o; - luaL_getmetatable(L, className); - lua_setmetatable(L, -2); - return 1; - } - - static LuaPseudoRandom* checkobject(lua_State *L, int narg) - { - luaL_checktype(L, narg, LUA_TUSERDATA); - void *ud = luaL_checkudata(L, narg, className); - if(!ud) luaL_typerror(L, narg, className); - return *(LuaPseudoRandom**)ud; // unbox pointer - } - - static void Register(lua_State *L) - { - lua_newtable(L); - int methodtable = lua_gettop(L); - luaL_newmetatable(L, className); - int metatable = lua_gettop(L); - - lua_pushliteral(L, "__metatable"); - lua_pushvalue(L, methodtable); - lua_settable(L, metatable); // hide metatable from Lua getmetatable() - - lua_pushliteral(L, "__index"); - lua_pushvalue(L, methodtable); - lua_settable(L, metatable); - - lua_pushliteral(L, "__gc"); - lua_pushcfunction(L, gc_object); - lua_settable(L, metatable); - - lua_pop(L, 1); // drop metatable - - luaL_openlib(L, 0, methods, 0); // fill methodtable - lua_pop(L, 1); // drop methodtable - - // Can be created from Lua (LuaPseudoRandom(seed)) - lua_register(L, className, create_object); - } -}; -const char LuaPseudoRandom::className[] = "PseudoRandom"; -const luaL_reg LuaPseudoRandom::methods[] = { - method(LuaPseudoRandom, next), - {0,0} -}; - - - -/* - LuaABM -*/ - -class LuaABM : public ActiveBlockModifier -{ -private: - lua_State *m_lua; - int m_id; - - std::set m_trigger_contents; - std::set m_required_neighbors; - float m_trigger_interval; - u32 m_trigger_chance; -public: - LuaABM(lua_State *L, int id, - const std::set &trigger_contents, - const std::set &required_neighbors, - float trigger_interval, u32 trigger_chance): - m_lua(L), - m_id(id), - m_trigger_contents(trigger_contents), - m_required_neighbors(required_neighbors), - m_trigger_interval(trigger_interval), - m_trigger_chance(trigger_chance) - { - } - virtual std::set getTriggerContents() - { - return m_trigger_contents; - } - virtual std::set getRequiredNeighbors() - { - return m_required_neighbors; - } - virtual float getTriggerInterval() - { - return m_trigger_interval; - } - virtual u32 getTriggerChance() - { - return m_trigger_chance; - } - virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n, - 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); - - // Get minetest.registered_abms - lua_getglobal(L, "minetest"); - lua_getfield(L, -1, "registered_abms"); - luaL_checktype(L, -1, LUA_TTABLE); - int registered_abms = lua_gettop(L); - - // Get minetest.registered_abms[m_id] - lua_pushnumber(L, m_id); - 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"); - luaL_checktype(L, -1, LUA_TFUNCTION); - push_v3s16(L, p); - pushnode(L, n, env->getGameDef()->ndef()); - lua_pushnumber(L, active_object_count); - lua_pushnumber(L, active_object_count_wider); - if(lua_pcall(L, 4, 0, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); - } -}; - -/* - ServerSoundParams -*/ - -static void read_server_sound_params(lua_State *L, int index, - ServerSoundParams ¶ms) -{ - if(index < 0) - index = lua_gettop(L) + 1 + index; - // Clear - params = ServerSoundParams(); - if(lua_istable(L, index)){ - getfloatfield(L, index, "gain", params.gain); - getstringfield(L, index, "to_player", params.to_player); - lua_getfield(L, index, "pos"); - if(!lua_isnil(L, -1)){ - v3f p = read_v3f(L, -1)*BS; - params.pos = p; - params.type = ServerSoundParams::SSP_POSITIONAL; - } - lua_pop(L, 1); - lua_getfield(L, index, "object"); - if(!lua_isnil(L, -1)){ - ObjectRef *ref = ObjectRef::checkobject(L, -1); - ServerActiveObject *sao = ObjectRef::getobject(ref); - if(sao){ - params.object = sao->getId(); - params.type = ServerSoundParams::SSP_OBJECT; - } - } - lua_pop(L, 1); - params.max_hear_distance = BS*getfloatfield_default(L, index, - "max_hear_distance", params.max_hear_distance/BS); - getboolfield(L, index, "loop", params.loop); - } -} - -/* - Global functions -*/ - -// debug(text) -// Writes a line to dstream -static int l_debug(lua_State *L) -{ - std::string text = lua_tostring(L, 1); - dstream << text << std::endl; - return 0; -} - -// log([level,] text) -// Writes a line to the logger. -// The one-argument version logs to infostream. -// The two-argument version accept a log level: error, action, info, or verbose. -static int l_log(lua_State *L) -{ - std::string text; - LogMessageLevel level = LMT_INFO; - if(lua_isnone(L, 2)) - { - text = lua_tostring(L, 1); - } - else - { - std::string levelname = luaL_checkstring(L, 1); - text = luaL_checkstring(L, 2); - if(levelname == "error") - level = LMT_ERROR; - else if(levelname == "action") - level = LMT_ACTION; - else if(levelname == "verbose") - level = LMT_VERBOSE; - } - log_printline(level, text); - return 0; -} - -// request_shutdown() -static int l_request_shutdown(lua_State *L) -{ - get_server(L)->requestShutdown(); - return 0; -} - -// get_server_status() -static int l_get_server_status(lua_State *L) -{ - lua_pushstring(L, wide_to_narrow(get_server(L)->getStatusString()).c_str()); - 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) -{ - luaL_checktype(L, 1, LUA_TTABLE); - int table = 1; - - // Get the writable item and node definition managers from the server - IWritableItemDefManager *idef = - get_server(L)->getWritableItemDefManager(); - IWritableNodeDefManager *ndef = - get_server(L)->getWritableNodeDefManager(); - - // Check if name is defined - std::string name; - lua_getfield(L, table, "name"); - if(lua_isstring(L, -1)){ - name = lua_tostring(L, -1); - verbosestream<<"register_item_raw: "<registerItem(def); - - // Read the node definition (content features) and register it - if(def.type == ITEM_NODE) - { - ContentFeatures f = read_content_features(L, table); - ndef->set(f.name, f); - } - - return 0; /* number of results */ -} - -// register_alias_raw(name, convert_to_name) -static int l_register_alias_raw(lua_State *L) -{ - std::string name = luaL_checkstring(L, 1); - std::string convert_to = luaL_checkstring(L, 2); - - // 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 */ -} - -// helper for register_craft -static bool read_craft_recipe_shaped(lua_State *L, int index, - int &width, std::vector &recipe) -{ - if(index < 0) - index = lua_gettop(L) + 1 + index; - - if(!lua_istable(L, index)) - return false; - - lua_pushnil(L); - int rowcount = 0; - while(lua_next(L, index) != 0){ - int colcount = 0; - // key at index -2 and value at index -1 - if(!lua_istable(L, -1)) - return false; - int table2 = lua_gettop(L); - lua_pushnil(L); - while(lua_next(L, table2) != 0){ - // key at index -2 and value at index -1 - if(!lua_isstring(L, -1)) - return false; - recipe.push_back(lua_tostring(L, -1)); - // removes value, keeps key for next iteration - lua_pop(L, 1); - colcount++; - } - if(rowcount == 0){ - width = colcount; - } else { - if(colcount != width) - return false; - } - // removes value, keeps key for next iteration - lua_pop(L, 1); - rowcount++; - } - return width != 0; -} - -// helper for register_craft -static bool read_craft_recipe_shapeless(lua_State *L, int index, - std::vector &recipe) -{ - if(index < 0) - index = lua_gettop(L) + 1 + index; - - if(!lua_istable(L, index)) - return false; - - lua_pushnil(L); - while(lua_next(L, index) != 0){ - // key at index -2 and value at index -1 - if(!lua_isstring(L, -1)) - return false; - recipe.push_back(lua_tostring(L, -1)); - // removes value, keeps key for next iteration - lua_pop(L, 1); - } - return true; -} - -// helper for register_craft -static bool read_craft_replacements(lua_State *L, int index, - CraftReplacements &replacements) -{ - if(index < 0) - index = lua_gettop(L) + 1 + index; - - if(!lua_istable(L, index)) - return false; - - lua_pushnil(L); - while(lua_next(L, index) != 0){ - // key at index -2 and value at index -1 - if(!lua_istable(L, -1)) - return false; - lua_rawgeti(L, -1, 1); - if(!lua_isstring(L, -1)) - return false; - std::string replace_from = lua_tostring(L, -1); - lua_pop(L, 1); - lua_rawgeti(L, -1, 2); - if(!lua_isstring(L, -1)) - return false; - std::string replace_to = lua_tostring(L, -1); - lua_pop(L, 1); - replacements.pairs.push_back( - std::make_pair(replace_from, replace_to)); - // removes value, keeps key for next iteration - lua_pop(L, 1); - } - return true; -} -// register_craft({output=item, recipe={{item00,item10},{item01,item11}}) -static int l_register_craft(lua_State *L) -{ - //infostream<<"register_craft"<getWritableCraftDefManager(); - - std::string type = getstringfield_default(L, table, "type", "shaped"); - - /* - CraftDefinitionShaped - */ - if(type == "shaped"){ - std::string output = getstringfield_default(L, table, "output", ""); - if(output == "") - throw LuaError(L, "Crafting definition is missing an output"); - - int width = 0; - std::vector recipe; - lua_getfield(L, table, "recipe"); - if(lua_isnil(L, -1)) - throw LuaError(L, "Crafting definition is missing a recipe" - " (output=\"" + output + "\")"); - if(!read_craft_recipe_shaped(L, -1, width, recipe)) - throw LuaError(L, "Invalid crafting recipe" - " (output=\"" + output + "\")"); - - CraftReplacements replacements; - lua_getfield(L, table, "replacements"); - if(!lua_isnil(L, -1)) - { - if(!read_craft_replacements(L, -1, replacements)) - throw LuaError(L, "Invalid replacements" - " (output=\"" + output + "\")"); - } - - CraftDefinition *def = new CraftDefinitionShaped( - output, width, recipe, replacements); - craftdef->registerCraft(def); - } - /* - CraftDefinitionShapeless - */ - else if(type == "shapeless"){ - std::string output = getstringfield_default(L, table, "output", ""); - if(output == "") - throw LuaError(L, "Crafting definition (shapeless)" - " is missing an output"); - - std::vector recipe; - lua_getfield(L, table, "recipe"); - if(lua_isnil(L, -1)) - throw LuaError(L, "Crafting definition (shapeless)" - " is missing a recipe" - " (output=\"" + output + "\")"); - if(!read_craft_recipe_shapeless(L, -1, recipe)) - throw LuaError(L, "Invalid crafting recipe" - " (output=\"" + output + "\")"); - - CraftReplacements replacements; - lua_getfield(L, table, "replacements"); - if(!lua_isnil(L, -1)) - { - if(!read_craft_replacements(L, -1, replacements)) - throw LuaError(L, "Invalid replacements" - " (output=\"" + output + "\")"); - } - - CraftDefinition *def = new CraftDefinitionShapeless( - output, recipe, replacements); - craftdef->registerCraft(def); - } - /* - CraftDefinitionToolRepair - */ - else if(type == "toolrepair"){ - float additional_wear = getfloatfield_default(L, table, - "additional_wear", 0.0); - - CraftDefinition *def = new CraftDefinitionToolRepair( - additional_wear); - craftdef->registerCraft(def); - } - /* - CraftDefinitionCooking - */ - else if(type == "cooking"){ - std::string output = getstringfield_default(L, table, "output", ""); - if(output == "") - throw LuaError(L, "Crafting definition (cooking)" - " is missing an output"); - - std::string recipe = getstringfield_default(L, table, "recipe", ""); - if(recipe == "") - throw LuaError(L, "Crafting definition (cooking)" - " is missing a recipe" - " (output=\"" + output + "\")"); - - float cooktime = getfloatfield_default(L, table, "cooktime", 3.0); - - CraftReplacements replacements; - lua_getfield(L, table, "replacements"); - if(!lua_isnil(L, -1)) - { - if(!read_craft_replacements(L, -1, replacements)) - throw LuaError(L, "Invalid replacements" - " (cooking output=\"" + output + "\")"); - } - - CraftDefinition *def = new CraftDefinitionCooking( - output, recipe, cooktime, replacements); - craftdef->registerCraft(def); - } - /* - CraftDefinitionFuel - */ - else if(type == "fuel"){ - std::string recipe = getstringfield_default(L, table, "recipe", ""); - if(recipe == "") - throw LuaError(L, "Crafting definition (fuel)" - " is missing a recipe"); - - float burntime = getfloatfield_default(L, table, "burntime", 1.0); - - CraftReplacements replacements; - lua_getfield(L, table, "replacements"); - if(!lua_isnil(L, -1)) - { - if(!read_craft_replacements(L, -1, replacements)) - throw LuaError(L, "Invalid replacements" - " (fuel recipe=\"" + recipe + "\")"); - } - - CraftDefinition *def = new CraftDefinitionFuel( - recipe, burntime, replacements); - craftdef->registerCraft(def); - } - else - { - throw LuaError(L, "Unknown crafting definition type: \"" + type + "\""); - } - - lua_pop(L, 1); - return 0; /* number of results */ -} - -// setting_set(name, value) -static int l_setting_set(lua_State *L) -{ - const char *name = luaL_checkstring(L, 1); - const char *value = luaL_checkstring(L, 2); - g_settings->set(name, value); - return 0; -} - -// setting_get(name) -static int l_setting_get(lua_State *L) -{ - const char *name = luaL_checkstring(L, 1); - try{ - std::string value = g_settings->get(name); - lua_pushstring(L, value.c_str()); - } catch(SettingNotFoundException &e){ - lua_pushnil(L); - } - return 1; -} - -// setting_getbool(name) -static int l_setting_getbool(lua_State *L) -{ - const char *name = luaL_checkstring(L, 1); - try{ - bool value = g_settings->getBool(name); - lua_pushboolean(L, value); - } catch(SettingNotFoundException &e){ - lua_pushnil(L); - } - return 1; -} - -// setting_save() -static int l_setting_save(lua_State *L) -{ - get_server(L)->saveConfig(); - return 0; -} - -// chat_send_all(text) -static int l_chat_send_all(lua_State *L) -{ - const char *text = luaL_checkstring(L, 1); - // Get server from registry - Server *server = get_server(L); - // Send - server->notifyPlayers(narrow_to_wide(text)); - return 0; -} - -// chat_send_player(name, text) -static int l_chat_send_player(lua_State *L) -{ - const char *name = luaL_checkstring(L, 1); - const char *text = luaL_checkstring(L, 2); - // Get server from registry - Server *server = get_server(L); - // Send - server->notifyPlayer(name, narrow_to_wide(text)); - return 0; -} - -// get_player_privs(name, text) -static int l_get_player_privs(lua_State *L) -{ - const char *name = luaL_checkstring(L, 1); - // Get server from registry - Server *server = get_server(L); - // Do it - lua_newtable(L); - int table = lua_gettop(L); - std::set privs_s = server->getPlayerEffectivePrivs(name); - for(std::set::const_iterator - i = privs_s.begin(); i != privs_s.end(); i++){ - lua_pushboolean(L, true); - lua_setfield(L, table, i->c_str()); - } - lua_pushvalue(L, table); - 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) -{ - InventoryLocation loc; - - std::string type = checkstringfield(L, 1, "type"); - if(type == "player"){ - std::string name = checkstringfield(L, 1, "name"); - loc.setPlayer(name); - } else if(type == "node"){ - lua_getfield(L, 1, "pos"); - v3s16 pos = check_v3s16(L, -1); - loc.setNodeMeta(pos); - } else if(type == "detached"){ - std::string name = checkstringfield(L, 1, "name"); - loc.setDetached(name); - } - - if(get_server(L)->getInventory(loc) != NULL) - InvRef::create(L, loc); - else - lua_pushnil(L); - return 1; -} - -// create_detached_inventory_raw(name) -static int l_create_detached_inventory_raw(lua_State *L) -{ - const char *name = luaL_checkstring(L, 1); - if(get_server(L)->createDetachedInventory(name) != NULL){ - InventoryLocation loc; - loc.setDetached(name); - InvRef::create(L, loc); - }else{ - lua_pushnil(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) -{ - std::map groups; - read_groups(L, 1, groups); - ToolCapabilities tp = read_tool_capabilities(L, 2); - if(lua_isnoneornil(L, 3)) - push_dig_params(L, getDigParams(groups, &tp)); - else - push_dig_params(L, getDigParams(groups, &tp, - luaL_checknumber(L, 3))); - return 1; -} - -// get_hit_params(groups, tool_capabilities[, time_from_last_punch]) -static int l_get_hit_params(lua_State *L) -{ - std::map groups; - read_groups(L, 1, groups); - ToolCapabilities tp = read_tool_capabilities(L, 2); - if(lua_isnoneornil(L, 3)) - push_hit_params(L, getHitParams(groups, &tp)); - else - push_hit_params(L, getHitParams(groups, &tp, - luaL_checknumber(L, 3))); - return 1; -} - -// get_current_modname() -static int l_get_current_modname(lua_State *L) -{ - lua_getfield(L, LUA_REGISTRYINDEX, "minetest_current_modname"); - return 1; -} - -// get_modpath(modname) -static int l_get_modpath(lua_State *L) -{ - std::string modname = luaL_checkstring(L, 1); - // Do it - if(modname == "__builtin"){ - std::string path = get_server(L)->getBuiltinLuaPath(); - lua_pushstring(L, path.c_str()); - return 1; - } - const ModSpec *mod = get_server(L)->getModSpec(modname); - if(!mod){ - lua_pushnil(L); - return 1; - } - lua_pushstring(L, mod->path.c_str()); - return 1; -} - -// get_modnames() -// the returned list is sorted alphabetically for you -static int l_get_modnames(lua_State *L) -{ - // Get a list of mods - core::list mods_unsorted, mods_sorted; - get_server(L)->getModNames(mods_unsorted); - - // Take unsorted items from mods_unsorted and sort them into - // mods_sorted; not great performance but the number of mods on a - // server will likely be small. - for(core::list::Iterator i = mods_unsorted.begin(); - i != mods_unsorted.end(); i++) - { - bool added = false; - for(core::list::Iterator x = mods_sorted.begin(); - x != mods_unsorted.end(); x++) - { - // I doubt anybody using Minetest will be using - // anything not ASCII based :) - if((*i).compare(*x) <= 0) - { - mods_sorted.insert_before(x, *i); - added = true; - break; - } - } - if(!added) - mods_sorted.push_back(*i); - } - - // Get the table insertion function from Lua. - lua_getglobal(L, "table"); - lua_getfield(L, -1, "insert"); - int insertion_func = lua_gettop(L); - - // Package them up for Lua - lua_newtable(L); - int new_table = lua_gettop(L); - core::list::Iterator i = mods_sorted.begin(); - while(i != mods_sorted.end()) - { - lua_pushvalue(L, insertion_func); - lua_pushvalue(L, new_table); - lua_pushstring(L, (*i).c_str()); - if(lua_pcall(L, 2, 0, 0) != 0) - { - script_error(L, "error: %s", lua_tostring(L, -1)); - } - i++; - } - return 1; -} - -// get_worldpath() -static int l_get_worldpath(lua_State *L) -{ - std::string worldpath = get_server(L)->getWorldPath(); - lua_pushstring(L, worldpath.c_str()); - return 1; -} - -// sound_play(spec, parameters) -static int l_sound_play(lua_State *L) -{ - SimpleSoundSpec spec; - read_soundspec(L, 1, spec); - ServerSoundParams params; - read_server_sound_params(L, 2, params); - s32 handle = get_server(L)->playSound(spec, params); - lua_pushinteger(L, handle); - return 1; -} - -// sound_stop(handle) -static int l_sound_stop(lua_State *L) -{ - int handle = luaL_checkinteger(L, 1); - get_server(L)->stopSound(handle); - return 0; -} - -// is_singleplayer() -static int l_is_singleplayer(lua_State *L) -{ - lua_pushboolean(L, get_server(L)->isSingleplayer()); - return 1; -} - -// get_password_hash(name, raw_password) -static int l_get_password_hash(lua_State *L) -{ - std::string name = luaL_checkstring(L, 1); - std::string raw_password = luaL_checkstring(L, 2); - std::string hash = translatePassword(name, - narrow_to_wide(raw_password)); - lua_pushstring(L, hash.c_str()); - return 1; -} - -// notify_authentication_modified(name) -static int l_notify_authentication_modified(lua_State *L) -{ - std::string name = ""; - if(lua_isstring(L, 1)) - name = lua_tostring(L, 1); - get_server(L)->reportPrivsModified(name); - return 0; -} - -// get_craft_result(input) -static int l_get_craft_result(lua_State *L) -{ - int input_i = 1; - std::string method_s = getstringfield_default(L, input_i, "method", "normal"); - enum CraftMethod method = (CraftMethod)getenumfield(L, input_i, "method", - es_CraftMethod, CRAFT_METHOD_NORMAL); - int width = 1; - lua_getfield(L, input_i, "width"); - if(lua_isnumber(L, -1)) - width = luaL_checkinteger(L, -1); - lua_pop(L, 1); - 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); - CraftOutput output; - bool got = cdef->getCraftResult(input, output, true, gdef); - lua_newtable(L); // output table - if(got){ - ItemStack item; - item.deSerialize(output.item, gdef->idef()); - LuaItemStack::create(L, item); - lua_setfield(L, -2, "item"); - setintfield(L, -1, "time", output.time); - } else { - LuaItemStack::create(L, ItemStack()); - lua_setfield(L, -2, "item"); - setintfield(L, -1, "time", 0); - } - lua_newtable(L); // decremented input table - lua_pushstring(L, method_s.c_str()); - lua_setfield(L, -2, "method"); - lua_pushinteger(L, width); - lua_setfield(L, -2, "width"); - push_items(L, input.items); - lua_setfield(L, -2, "items"); - return 2; -} - -// get_craft_recipe(result item) -static int l_get_craft_recipe(lua_State *L) -{ - int k = 0; - 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; - CraftOutput output(o_item,0); - bool got = cdef->getCraftRecipe(input, output, gdef); - lua_newtable(L); // output table - if(got){ - lua_newtable(L); - for(std::vector::const_iterator - i = input.items.begin(); - i != input.items.end(); i++, k++) - { - if (i->empty()) - { - continue; - } - sprintf(tmp,"%d",k); - lua_pushstring(L,tmp); - lua_pushstring(L,i->name.c_str()); - lua_settable(L, -3); - } - lua_setfield(L, -2, "items"); - setintfield(L, -1, "width", input.width); - switch (input.method) { - case CRAFT_METHOD_NORMAL: - lua_pushstring(L,"normal"); - break; - case CRAFT_METHOD_COOKING: - lua_pushstring(L,"cooking"); - break; - case CRAFT_METHOD_FUEL: - lua_pushstring(L,"fuel"); - break; - default: - lua_pushstring(L,"unknown"); - } - lua_setfield(L, -2, "type"); - } else { - lua_pushnil(L); - lua_setfield(L, -2, "items"); - setintfield(L, -1, "width", 0); - } - return 1; -} - -// rollback_get_last_node_actor(p, range, seconds) -> actor, p, seconds -static int l_rollback_get_last_node_actor(lua_State *L) -{ - v3s16 p = read_v3s16(L, 1); - int range = luaL_checknumber(L, 2); - int seconds = luaL_checknumber(L, 3); - Server *server = get_server(L); - IRollbackManager *rollback = server->getRollbackManager(); - v3s16 act_p; - int act_seconds = 0; - std::string actor = rollback->getLastNodeActor(p, range, seconds, &act_p, &act_seconds); - lua_pushstring(L, actor.c_str()); - push_v3s16(L, act_p); - lua_pushnumber(L, act_seconds); - return 3; -} - -// rollback_revert_actions_by(actor, seconds) -> bool, log messages -static int l_rollback_revert_actions_by(lua_State *L) -{ - std::string actor = luaL_checkstring(L, 1); - int seconds = luaL_checknumber(L, 2); - Server *server = get_server(L); - IRollbackManager *rollback = server->getRollbackManager(); - std::list actions = rollback->getRevertActions(actor, seconds); - std::list log; - bool success = server->rollbackRevertActions(actions, &log); - // Push boolean result - lua_pushboolean(L, success); - // Get the table insert function and push the log table - lua_getglobal(L, "table"); - lua_getfield(L, -1, "insert"); - int table_insert = lua_gettop(L); - lua_newtable(L); - int table = lua_gettop(L); - for(std::list::const_iterator i = log.begin(); - i != log.end(); i++) - { - lua_pushvalue(L, table_insert); - lua_pushvalue(L, table); - lua_pushstring(L, i->c_str()); - if(lua_pcall(L, 2, 0, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); - } - lua_remove(L, -2); // Remove table - lua_remove(L, -2); // Remove insert - return 2; -} - -static const struct luaL_Reg minetest_f [] = { - {"debug", l_debug}, - {"log", l_log}, - {"request_shutdown", l_request_shutdown}, - {"get_server_status", l_get_server_status}, - {"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}, - {"setting_save",l_setting_save}, - {"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}, - {"get_modpath", l_get_modpath}, - {"get_modnames", l_get_modnames}, - {"get_worldpath", l_get_worldpath}, - {"sound_play", l_sound_play}, - {"sound_stop", l_sound_stop}, - {"is_singleplayer", l_is_singleplayer}, - {"get_password_hash", l_get_password_hash}, - {"notify_authentication_modified", l_notify_authentication_modified}, - {"get_craft_result", l_get_craft_result}, - {"get_craft_recipe", l_get_craft_recipe}, - {"rollback_get_last_node_actor", l_rollback_get_last_node_actor}, - {"rollback_revert_actions_by", l_rollback_revert_actions_by}, - {NULL, NULL} -}; - -/* - Main export function -*/ - -void scriptapi_export(lua_State *L, Server *server) -{ - realitycheck(L); - assert(lua_checkstack(L, 20)); - verbosestream<<"scriptapi_export()"< trigger_contents; - lua_getfield(L, current_abm, "nodenames"); - if(lua_istable(L, -1)){ - int table = lua_gettop(L); - lua_pushnil(L); - while(lua_next(L, table) != 0){ - // key at index -2 and value at index -1 - luaL_checktype(L, -1, LUA_TSTRING); - trigger_contents.insert(lua_tostring(L, -1)); - // removes value, keeps key for next iteration - lua_pop(L, 1); - } - } else if(lua_isstring(L, -1)){ - trigger_contents.insert(lua_tostring(L, -1)); - } - lua_pop(L, 1); - - std::set required_neighbors; - lua_getfield(L, current_abm, "neighbors"); - if(lua_istable(L, -1)){ - int table = lua_gettop(L); - lua_pushnil(L); - while(lua_next(L, table) != 0){ - // key at index -2 and value at index -1 - luaL_checktype(L, -1, LUA_TSTRING); - required_neighbors.insert(lua_tostring(L, -1)); - // removes value, keeps key for next iteration - lua_pop(L, 1); - } - } else if(lua_isstring(L, -1)){ - required_neighbors.insert(lua_tostring(L, -1)); - } - lua_pop(L, 1); - - float trigger_interval = 10.0; - getfloatfield(L, current_abm, "interval", trigger_interval); - - int trigger_chance = 50; - getintfield(L, current_abm, "chance", trigger_chance); - - LuaABM *abm = new LuaABM(L, id, trigger_contents, - required_neighbors, trigger_interval, trigger_chance); - - env->addActiveBlockModifier(abm); - - // removes value, keeps key for next iteration - lua_pop(L, 1); - } - } - lua_pop(L, 1); -} - -#if 0 -// Dump stack top with the dump2 function -static void dump2(lua_State *L, const char *name) -{ - // Dump object (debug) - lua_getglobal(L, "dump2"); - luaL_checktype(L, -1, LUA_TFUNCTION); - lua_pushvalue(L, -2); // Get previous stack top as first parameter - lua_pushstring(L, name); - if(lua_pcall(L, 2, 0, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); -} -#endif - -/* - object_reference -*/ - -void scriptapi_add_object_reference(lua_State *L, ServerActiveObject *cobj) -{ - realitycheck(L); - assert(lua_checkstack(L, 20)); - //infostream<<"scriptapi_add_object_reference: id="<getId()<getId()); // Push id - lua_pushvalue(L, object); // Copy object to top of stack - lua_settable(L, objectstable); -} - -void scriptapi_rm_object_reference(lua_State *L, ServerActiveObject *cobj) -{ - realitycheck(L); - assert(lua_checkstack(L, 20)); - //infostream<<"scriptapi_rm_object_reference: id="<getId()<getId()); // Push id - lua_gettable(L, objectstable); - // Set object reference to NULL - ObjectRef::set_null(L); - lua_pop(L, 1); // pop object - - // Set object_refs[id] = nil - lua_pushnumber(L, cobj->getId()); // Push id - lua_pushnil(L); - lua_settable(L, objectstable); -} - -/* - misc -*/ - -// What scriptapi_run_callbacks does with the return values of callbacks. -// Regardless of the mode, if only one callback is defined, -// its return value is the total return value. -// Modes only affect the case where 0 or >= 2 callbacks are defined. -enum RunCallbacksMode -{ - // Returns the return value of the first callback - // Returns nil if list of callbacks is empty - RUN_CALLBACKS_MODE_FIRST, - // Returns the return value of the last callback - // Returns nil if list of callbacks is empty - RUN_CALLBACKS_MODE_LAST, - // If any callback returns a false value, the first such is returned - // Otherwise, the first callback's return value (trueish) is returned - // Returns true if list of callbacks is empty - RUN_CALLBACKS_MODE_AND, - // Like above, but stops calling callbacks (short circuit) - // after seeing the first false value - RUN_CALLBACKS_MODE_AND_SC, - // If any callback returns a true value, the first such is returned - // Otherwise, the first callback's return value (falseish) is returned - // Returns false if list of callbacks is empty - RUN_CALLBACKS_MODE_OR, - // Like above, but stops calling callbacks (short circuit) - // after seeing the first true value - RUN_CALLBACKS_MODE_OR_SC, - // Note: "a true value" and "a false value" refer to values that - // are converted by lua_toboolean to true or false, respectively. -}; - -// Push the list of callbacks (a lua table). -// Then push nargs arguments. -// Then call this function, which -// - runs the callbacks -// - removes the table and arguments from the lua stack -// - pushes the return value, computed depending on mode -static void scriptapi_run_callbacks(lua_State *L, int nargs, - RunCallbacksMode mode) -{ - // Insert the return value into the lua stack, below the table - assert(lua_gettop(L) >= nargs + 1); - lua_pushnil(L); - lua_insert(L, -(nargs + 1) - 1); - // Stack now looks like this: - // ...
... - - int rv = lua_gettop(L) - nargs - 1; - int table = rv + 1; - int arg = table + 1; - - luaL_checktype(L, table, LUA_TTABLE); - - // Foreach - lua_pushnil(L); - bool first_loop = true; - while(lua_next(L, table) != 0){ - // key at index -2 and value at index -1 - luaL_checktype(L, -1, LUA_TFUNCTION); - // Call function - for(int i = 0; i < nargs; i++) - lua_pushvalue(L, arg+i); - if(lua_pcall(L, nargs, 1, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); - - // Move return value to designated space in stack - // Or pop it - if(first_loop){ - // Result of first callback is always moved - lua_replace(L, rv); - first_loop = false; - } else { - // Otherwise, what happens depends on the mode - if(mode == RUN_CALLBACKS_MODE_FIRST) - lua_pop(L, 1); - else if(mode == RUN_CALLBACKS_MODE_LAST) - lua_replace(L, rv); - else if(mode == RUN_CALLBACKS_MODE_AND || - mode == RUN_CALLBACKS_MODE_AND_SC){ - 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((bool)lua_toboolean(L, rv) == false && - (bool)lua_toboolean(L, -1) == true) - lua_replace(L, rv); - else - lua_pop(L, 1); - } - else - assert(0); - } - - // Handle short circuit modes - if(mode == RUN_CALLBACKS_MODE_AND_SC && - (bool)lua_toboolean(L, rv) == false) - break; - else if(mode == RUN_CALLBACKS_MODE_OR_SC && - (bool)lua_toboolean(L, rv) == true) - break; - - // value removed, keep key for next iteration - } - - // Remove stuff from stack, leaving only the return value - lua_settop(L, rv); - - // Fix return value in case no callbacks were called - if(first_loop){ - if(mode == RUN_CALLBACKS_MODE_AND || - mode == RUN_CALLBACKS_MODE_AND_SC){ - lua_pop(L, 1); - lua_pushboolean(L, true); - } - else if(mode == RUN_CALLBACKS_MODE_OR || - mode == RUN_CALLBACKS_MODE_OR_SC){ - lua_pop(L, 1); - lua_pushboolean(L, false); - } - } -} - -bool scriptapi_on_chat_message(lua_State *L, const std::string &name, - const std::string &message) -{ - realitycheck(L); - assert(lua_checkstack(L, 20)); - StackUnroller stack_unroller(L); - - // Get minetest.registered_on_chat_messages - lua_getglobal(L, "minetest"); - lua_getfield(L, -1, "registered_on_chat_messages"); - // Call callbacks - lua_pushstring(L, name.c_str()); - lua_pushstring(L, message.c_str()); - scriptapi_run_callbacks(L, 2, RUN_CALLBACKS_MODE_OR_SC); - bool ate = lua_toboolean(L, -1); - 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); - assert(lua_checkstack(L, 20)); - StackUnroller stack_unroller(L); - - // Get minetest.registered_on_newplayers - lua_getglobal(L, "minetest"); - lua_getfield(L, -1, "registered_on_newplayers"); - // Call callbacks - objectref_get_or_create(L, player); - scriptapi_run_callbacks(L, 1, RUN_CALLBACKS_MODE_FIRST); -} - -void scriptapi_on_dieplayer(lua_State *L, ServerActiveObject *player) -{ - realitycheck(L); - assert(lua_checkstack(L, 20)); - StackUnroller stack_unroller(L); - - // Get minetest.registered_on_dieplayers - lua_getglobal(L, "minetest"); - lua_getfield(L, -1, "registered_on_dieplayers"); - // Call callbacks - objectref_get_or_create(L, player); - scriptapi_run_callbacks(L, 1, RUN_CALLBACKS_MODE_FIRST); -} - -bool scriptapi_on_respawnplayer(lua_State *L, ServerActiveObject *player) -{ - realitycheck(L); - assert(lua_checkstack(L, 20)); - StackUnroller stack_unroller(L); - - // Get minetest.registered_on_respawnplayers - lua_getglobal(L, "minetest"); - lua_getfield(L, -1, "registered_on_respawnplayers"); - // Call callbacks - objectref_get_or_create(L, player); - scriptapi_run_callbacks(L, 1, RUN_CALLBACKS_MODE_OR); - bool positioning_handled_by_some = lua_toboolean(L, -1); - return positioning_handled_by_some; -} - -void scriptapi_on_joinplayer(lua_State *L, ServerActiveObject *player) -{ - realitycheck(L); - assert(lua_checkstack(L, 20)); - StackUnroller stack_unroller(L); - - // Get minetest.registered_on_joinplayers - lua_getglobal(L, "minetest"); - lua_getfield(L, -1, "registered_on_joinplayers"); - // Call callbacks - objectref_get_or_create(L, player); - scriptapi_run_callbacks(L, 1, RUN_CALLBACKS_MODE_FIRST); -} - -void scriptapi_on_leaveplayer(lua_State *L, ServerActiveObject *player) -{ - realitycheck(L); - assert(lua_checkstack(L, 20)); - StackUnroller stack_unroller(L); - - // Get minetest.registered_on_leaveplayers - lua_getglobal(L, "minetest"); - lua_getfield(L, -1, "registered_on_leaveplayers"); - // Call callbacks - objectref_get_or_create(L, player); - scriptapi_run_callbacks(L, 1, RUN_CALLBACKS_MODE_FIRST); -} - -static void get_auth_handler(lua_State *L) -{ - lua_getglobal(L, "minetest"); - lua_getfield(L, -1, "registered_auth_handler"); - if(lua_isnil(L, -1)){ - lua_pop(L, 1); - lua_getfield(L, -1, "builtin_auth_handler"); - } - if(lua_type(L, -1) != LUA_TTABLE) - throw LuaError(L, "Authentication handler table not valid"); -} - -bool scriptapi_get_auth(lua_State *L, const std::string &playername, - std::string *dst_password, std::set *dst_privs) -{ - 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) - throw LuaError(L, "Authentication handler missing get_auth"); - 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) - throw LuaError(L, "Authentication handler didn't return password"); - if(dst_password) - *dst_password = password; - - lua_getfield(L, -1, "privileges"); - if(!lua_istable(L, -1)) - throw LuaError(L, - "Authentication handler didn't return privilege table"); - if(dst_privs) - read_privileges(L, -1, *dst_privs); - lua_pop(L, 1); - - return true; -} - -void scriptapi_create_auth(lua_State *L, const std::string &playername, - const std::string &password) -{ - 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) - throw LuaError(L, "Authentication handler missing create_auth"); - lua_pushstring(L, playername.c_str()); - lua_pushstring(L, password.c_str()); - if(lua_pcall(L, 2, 0, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); -} - -bool scriptapi_set_password(lua_State *L, const std::string &playername, - const std::string &password) -{ - 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) - throw LuaError(L, "Authentication handler missing set_password"); - lua_pushstring(L, playername.c_str()); - lua_pushstring(L, password.c_str()); - if(lua_pcall(L, 2, 1, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); - return lua_toboolean(L, -1); -} - -/* - player -*/ - -void scriptapi_on_player_receive_fields(lua_State *L, - ServerActiveObject *player, - const std::string &formname, - const std::map &fields) -{ - realitycheck(L); - assert(lua_checkstack(L, 20)); - StackUnroller stack_unroller(L); + realitycheck(L); + assert(lua_checkstack(L, 20)); + StackUnroller stack_unroller(L); // Get minetest.registered_on_chat_messages lua_getglobal(L, "minetest"); - lua_getfield(L, -1, "registered_on_player_receive_fields"); + lua_getfield(L, -1, "registered_on_chat_messages"); // Call callbacks - // param 1 - objectref_get_or_create(L, player); - // param 2 - lua_pushstring(L, formname.c_str()); - // param 3 - lua_newtable(L); - for(std::map::const_iterator - i = fields.begin(); i != fields.end(); i++){ - const std::string &name = i->first; - const std::string &value = i->second; - lua_pushstring(L, name.c_str()); - lua_pushlstring(L, value.c_str(), value.size()); - lua_settable(L, -3); - } - scriptapi_run_callbacks(L, 3, RUN_CALLBACKS_MODE_OR_SC); -} - -/* - item callbacks and node callbacks -*/ - -// Retrieves minetest.registered_items[name][callbackname] -// If that is nil or on error, return false and stack is unchanged -// If that is a function, returns true and pushes the -// function onto the stack -// If minetest.registered_items[name] doesn't exist, minetest.nodedef_default -// is tried instead so unknown items can still be manipulated to some degree -static bool get_item_callback(lua_State *L, - const char *name, const char *callbackname) -{ - lua_getglobal(L, "minetest"); - lua_getfield(L, -1, "registered_items"); - lua_remove(L, -2); - luaL_checktype(L, -1, LUA_TTABLE); - lua_getfield(L, -1, name); - lua_remove(L, -2); - // Should be a table - if(lua_type(L, -1) != LUA_TTABLE) - { - // Report error and clean up - errorstream<<"Item \""<ndef(); - - // Push callback function on stack - if(!get_item_callback(L, ndef->get(node).name.c_str(), "on_punch")) - return false; - - // Call function - push_v3s16(L, p); - pushnode(L, node, ndef); - objectref_get_or_create(L, puncher); - if(lua_pcall(L, 3, 0, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); - return true; + // 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); } -bool scriptapi_node_on_dig(lua_State *L, v3s16 p, MapNode node, - ServerActiveObject *digger) +void scriptapi_on_newplayer(lua_State *L, ServerActiveObject *player) { realitycheck(L); assert(lua_checkstack(L, 20)); StackUnroller stack_unroller(L); - INodeDefManager *ndef = get_server(L)->ndef(); - - // Push callback function on stack - if(!get_item_callback(L, ndef->get(node).name.c_str(), "on_dig")) - return false; - - // Call function - push_v3s16(L, p); - pushnode(L, node, ndef); - objectref_get_or_create(L, digger); - if(lua_pcall(L, 3, 0, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); - return true; + // Get minetest.registered_on_newplayers + lua_getglobal(L, "minetest"); + lua_getfield(L, -1, "registered_on_newplayers"); + // Call callbacks + objectref_get_or_create(L, player); + scriptapi_run_callbacks(L, 1, RUN_CALLBACKS_MODE_FIRST); } -void scriptapi_node_on_construct(lua_State *L, v3s16 p, MapNode node) +void scriptapi_on_dieplayer(lua_State *L, ServerActiveObject *player) { realitycheck(L); assert(lua_checkstack(L, 20)); StackUnroller stack_unroller(L); - INodeDefManager *ndef = get_server(L)->ndef(); - - // Push callback function on stack - if(!get_item_callback(L, ndef->get(node).name.c_str(), "on_construct")) - return; - - // Call function - push_v3s16(L, p); - if(lua_pcall(L, 1, 0, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); + // Get minetest.registered_on_dieplayers + lua_getglobal(L, "minetest"); + lua_getfield(L, -1, "registered_on_dieplayers"); + // Call callbacks + objectref_get_or_create(L, player); + scriptapi_run_callbacks(L, 1, RUN_CALLBACKS_MODE_FIRST); } -void scriptapi_node_on_destruct(lua_State *L, v3s16 p, MapNode node) +bool scriptapi_on_respawnplayer(lua_State *L, ServerActiveObject *player) { realitycheck(L); assert(lua_checkstack(L, 20)); StackUnroller stack_unroller(L); - INodeDefManager *ndef = get_server(L)->ndef(); - - // Push callback function on stack - if(!get_item_callback(L, ndef->get(node).name.c_str(), "on_destruct")) - return; - - // Call function - push_v3s16(L, p); - if(lua_pcall(L, 1, 0, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); + // Get minetest.registered_on_respawnplayers + lua_getglobal(L, "minetest"); + lua_getfield(L, -1, "registered_on_respawnplayers"); + // Call callbacks + objectref_get_or_create(L, player); + scriptapi_run_callbacks(L, 1, RUN_CALLBACKS_MODE_OR); + bool positioning_handled_by_some = lua_toboolean(L, -1); + return positioning_handled_by_some; } -void scriptapi_node_after_destruct(lua_State *L, v3s16 p, MapNode node) +void scriptapi_on_joinplayer(lua_State *L, ServerActiveObject *player) { realitycheck(L); assert(lua_checkstack(L, 20)); StackUnroller stack_unroller(L); - INodeDefManager *ndef = get_server(L)->ndef(); - - // Push callback function on stack - if(!get_item_callback(L, ndef->get(node).name.c_str(), "after_destruct")) - return; - - // Call function - push_v3s16(L, p); - pushnode(L, node, ndef); - if(lua_pcall(L, 2, 0, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); + // Get minetest.registered_on_joinplayers + lua_getglobal(L, "minetest"); + lua_getfield(L, -1, "registered_on_joinplayers"); + // Call callbacks + objectref_get_or_create(L, player); + scriptapi_run_callbacks(L, 1, RUN_CALLBACKS_MODE_FIRST); } -bool scriptapi_node_on_timer(lua_State *L, v3s16 p, MapNode node, f32 dtime) +void scriptapi_on_leaveplayer(lua_State *L, ServerActiveObject *player) { realitycheck(L); assert(lua_checkstack(L, 20)); StackUnroller stack_unroller(L); - INodeDefManager *ndef = get_server(L)->ndef(); - - // Push callback function on stack - if(!get_item_callback(L, ndef->get(node).name.c_str(), "on_timer")) - return false; - - // Call function - push_v3s16(L, p); - lua_pushnumber(L,dtime); - if(lua_pcall(L, 2, 1, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); - if((bool)lua_isboolean(L,-1) && (bool)lua_toboolean(L,-1) == true) - return true; - - return false; + // Get minetest.registered_on_leaveplayers + lua_getglobal(L, "minetest"); + lua_getfield(L, -1, "registered_on_leaveplayers"); + // Call callbacks + objectref_get_or_create(L, player); + scriptapi_run_callbacks(L, 1, RUN_CALLBACKS_MODE_FIRST); } -void scriptapi_node_on_receive_fields(lua_State *L, v3s16 p, +/* + player +*/ +void scriptapi_on_player_receive_fields(lua_State *L, + ServerActiveObject *player, const std::string &formname, - const std::map &fields, - ServerActiveObject *sender) + const std::map &fields) { realitycheck(L); assert(lua_checkstack(L, 20)); 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) - return; - - // Push callback function on stack - if(!get_item_callback(L, ndef->get(node).name.c_str(), "on_receive_fields")) - return; - - // Call function + // Get minetest.registered_on_chat_messages + lua_getglobal(L, "minetest"); + lua_getfield(L, -1, "registered_on_player_receive_fields"); + // Call callbacks // param 1 - push_v3s16(L, p); + objectref_get_or_create(L, player); // param 2 lua_pushstring(L, formname.c_str()); // param 3 @@ -6422,784 +550,585 @@ void scriptapi_node_on_receive_fields(lua_State *L, v3s16 p, lua_pushlstring(L, value.c_str(), value.size()); lua_settable(L, -3); } - // param 4 - objectref_get_or_create(L, sender); - if(lua_pcall(L, 4, 0, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); + scriptapi_run_callbacks(L, 3, RUN_CALLBACKS_MODE_OR_SC); } +/*****************************************************************************/ +/* Api functions */ +/*****************************************************************************/ -/* - Node metadata inventory callbacks -*/ +// debug(text) +// Writes a line to dstream +static int l_debug(lua_State *L) +{ + std::string text = lua_tostring(L, 1); + dstream << text << std::endl; + return 0; +} -// Return number of accepted items to be moved -int scriptapi_nodemeta_inventory_allow_move(lua_State *L, v3s16 p, - const std::string &from_list, int from_index, - const std::string &to_list, int to_index, - int count, ServerActiveObject *player) +// log([level,] text) +// Writes a line to the logger. +// The one-argument version logs to infostream. +// The two-argument version accept a log level: error, action, info, or verbose. +static int l_log(lua_State *L) { - realitycheck(L); - assert(lua_checkstack(L, 20)); - StackUnroller stack_unroller(L); + std::string text; + LogMessageLevel level = LMT_INFO; + if(lua_isnone(L, 2)) + { + text = lua_tostring(L, 1); + } + else + { + std::string levelname = luaL_checkstring(L, 1); + text = luaL_checkstring(L, 2); + if(levelname == "error") + level = LMT_ERROR; + else if(levelname == "action") + level = LMT_ACTION; + else if(levelname == "verbose") + level = LMT_VERBOSE; + } + log_printline(level, text); + return 0; +} + +// request_shutdown() +static int l_request_shutdown(lua_State *L) +{ + get_server(L)->requestShutdown(); + return 0; +} + +// get_server_status() +static int l_get_server_status(lua_State *L) +{ + lua_pushstring(L, wide_to_narrow(get_server(L)->getStatusString()).c_str()); + return 1; +} - INodeDefManager *ndef = get_server(L)->ndef(); +// 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"); - // 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) + BiomeDefManager *bmgr = get_server(L)->getBiomeDef(); + if (!bmgr) { + verbosestream << "register_biome_groups: BiomeDefManager not active" << std::endl; return 0; + } - // Push callback function on stack - if(!get_item_callback(L, ndef->get(node).name.c_str(), - "allow_metadata_inventory_move")) - return count; + 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); - // function(pos, from_list, from_index, to_list, to_index, count, player) - // pos - push_v3s16(L, p); - // from_list - lua_pushstring(L, from_list.c_str()); - // from_index - lua_pushinteger(L, from_index + 1); - // to_list - lua_pushstring(L, to_list.c_str()); - // to_index - lua_pushinteger(L, to_index + 1); - // count - lua_pushinteger(L, count); - // player - objectref_get_or_create(L, player); - if(lua_pcall(L, 7, 1, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); - if(!lua_isnumber(L, -1)) - throw LuaError(L, "allow_metadata_inventory_move should return a number"); - return luaL_checkinteger(L, -1); + return 0; } -// Return number of accepted items to be put -int scriptapi_nodemeta_inventory_allow_put(lua_State *L, v3s16 p, - const std::string &listname, int index, ItemStack &stack, - ServerActiveObject *player) +// register_biome({lots of stuff}) +static int l_register_biome(lua_State *L) { - realitycheck(L); - assert(lua_checkstack(L, 20)); - StackUnroller stack_unroller(L); - - INodeDefManager *ndef = get_server(L)->ndef(); + luaL_checktype(L, 1, LUA_TTABLE); + int index = 1, groupid; + std::string nodename; - // 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) + IWritableNodeDefManager *ndef = get_server(L)->getWritableNodeDefManager(); + BiomeDefManager *bmgr = get_server(L)->getBiomeDef(); + if (!bmgr) { + verbosestream << "register_biome: BiomeDefManager not active" << std::endl; return 0; + } - // Push callback function on stack - if(!get_item_callback(L, ndef->get(node).name.c_str(), - "allow_metadata_inventory_put")) - return stack.count; + groupid = getintfield_default(L, index, "group_id", 0); - // Call function(pos, listname, index, stack, player) - // pos - push_v3s16(L, p); - // listname - lua_pushstring(L, listname.c_str()); - // index - lua_pushinteger(L, index + 1); - // stack - LuaItemStack::create(L, stack); - // player - objectref_get_or_create(L, player); - if(lua_pcall(L, 5, 1, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); - if(!lua_isnumber(L, -1)) - throw LuaError(L, "allow_metadata_inventory_put should return a number"); - return luaL_checkinteger(L, -1); + 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; } -// Return number of accepted items to be taken -int scriptapi_nodemeta_inventory_allow_take(lua_State *L, v3s16 p, - const std::string &listname, int index, ItemStack &stack, - ServerActiveObject *player) -{ - realitycheck(L); - assert(lua_checkstack(L, 20)); - 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) - return 0; +// setting_set(name, value) +static int l_setting_set(lua_State *L) +{ + const char *name = luaL_checkstring(L, 1); + const char *value = luaL_checkstring(L, 2); + g_settings->set(name, value); + return 0; +} - // Push callback function on stack - if(!get_item_callback(L, ndef->get(node).name.c_str(), - "allow_metadata_inventory_take")) - return stack.count; +// setting_get(name) +static int l_setting_get(lua_State *L) +{ + const char *name = luaL_checkstring(L, 1); + try{ + std::string value = g_settings->get(name); + lua_pushstring(L, value.c_str()); + } catch(SettingNotFoundException &e){ + lua_pushnil(L); + } + return 1; +} - // Call function(pos, listname, index, count, player) - // pos - push_v3s16(L, p); - // listname - lua_pushstring(L, listname.c_str()); - // index - lua_pushinteger(L, index + 1); - // stack - LuaItemStack::create(L, stack); - // player - objectref_get_or_create(L, player); - if(lua_pcall(L, 5, 1, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); - if(!lua_isnumber(L, -1)) - throw LuaError(L, "allow_metadata_inventory_take should return a number"); - return luaL_checkinteger(L, -1); +// setting_getbool(name) +static int l_setting_getbool(lua_State *L) +{ + const char *name = luaL_checkstring(L, 1); + try{ + bool value = g_settings->getBool(name); + lua_pushboolean(L, value); + } catch(SettingNotFoundException &e){ + lua_pushnil(L); + } + return 1; } -// Report moved items -void scriptapi_nodemeta_inventory_on_move(lua_State *L, v3s16 p, - const std::string &from_list, int from_index, - const std::string &to_list, int to_index, - int count, ServerActiveObject *player) +// setting_save() +static int l_setting_save(lua_State *L) { - realitycheck(L); - assert(lua_checkstack(L, 20)); - 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) - return; - - // Push callback function on stack - if(!get_item_callback(L, ndef->get(node).name.c_str(), - "on_metadata_inventory_move")) - return; - - // function(pos, from_list, from_index, to_list, to_index, count, player) - // pos - push_v3s16(L, p); - // from_list - lua_pushstring(L, from_list.c_str()); - // from_index - lua_pushinteger(L, from_index + 1); - // to_list - lua_pushstring(L, to_list.c_str()); - // to_index - lua_pushinteger(L, to_index + 1); - // count - lua_pushinteger(L, count); - // player - objectref_get_or_create(L, player); - if(lua_pcall(L, 7, 0, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); + get_server(L)->saveConfig(); + return 0; } -// Report put items -void scriptapi_nodemeta_inventory_on_put(lua_State *L, v3s16 p, - const std::string &listname, int index, ItemStack &stack, - ServerActiveObject *player) +// chat_send_all(text) +static int l_chat_send_all(lua_State *L) { - realitycheck(L); - assert(lua_checkstack(L, 20)); - 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) - return; - - // Push callback function on stack - if(!get_item_callback(L, ndef->get(node).name.c_str(), - "on_metadata_inventory_put")) - return; - - // Call function(pos, listname, index, stack, player) - // pos - push_v3s16(L, p); - // listname - lua_pushstring(L, listname.c_str()); - // index - lua_pushinteger(L, index + 1); - // stack - LuaItemStack::create(L, stack); - // player - objectref_get_or_create(L, player); - if(lua_pcall(L, 5, 0, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); + const char *text = luaL_checkstring(L, 1); + // Get server from registry + Server *server = get_server(L); + // Send + server->notifyPlayers(narrow_to_wide(text)); + return 0; } -// Report taken items -void scriptapi_nodemeta_inventory_on_take(lua_State *L, v3s16 p, - const std::string &listname, int index, ItemStack &stack, - ServerActiveObject *player) +// chat_send_player(name, text) +static int l_chat_send_player(lua_State *L) { - realitycheck(L); - assert(lua_checkstack(L, 20)); - 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) - return; + const char *name = luaL_checkstring(L, 1); + const char *text = luaL_checkstring(L, 2); + // Get server from registry + Server *server = get_server(L); + // Send + server->notifyPlayer(name, narrow_to_wide(text)); + return 0; +} - // Push callback function on stack - if(!get_item_callback(L, ndef->get(node).name.c_str(), - "on_metadata_inventory_take")) - return; +// get_player_privs(name, text) +static int l_get_player_privs(lua_State *L) +{ + const char *name = luaL_checkstring(L, 1); + // Get server from registry + Server *server = get_server(L); + // Do it + lua_newtable(L); + int table = lua_gettop(L); + std::set privs_s = server->getPlayerEffectivePrivs(name); + for(std::set::const_iterator + i = privs_s.begin(); i != privs_s.end(); i++){ + lua_pushboolean(L, true); + lua_setfield(L, table, i->c_str()); + } + lua_pushvalue(L, table); + return 1; +} - // Call function(pos, listname, index, stack, player) - // pos - push_v3s16(L, p); - // listname - lua_pushstring(L, listname.c_str()); - // index - lua_pushinteger(L, index + 1); - // stack - LuaItemStack::create(L, stack); - // player - objectref_get_or_create(L, player); - if(lua_pcall(L, 5, 0, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); +// get_ban_list() +static int l_get_ban_list(lua_State *L) +{ + lua_pushstring(L, get_server(L)->getBanDescription("").c_str()); + return 1; } -/* - Detached inventory callbacks -*/ +// 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; +} -// Retrieves minetest.detached_inventories[name][callbackname] -// If that is nil or on error, return false and stack is unchanged -// If that is a function, returns true and pushes the -// function onto the stack -static bool get_detached_inventory_callback(lua_State *L, - const std::string &name, const char *callbackname) +// ban_player() +static int l_ban_player(lua_State *L) { - lua_getglobal(L, "minetest"); - lua_getfield(L, -1, "detached_inventories"); - lua_remove(L, -2); - luaL_checktype(L, -1, LUA_TTABLE); - lua_getfield(L, -1, name.c_str()); - lua_remove(L, -2); - // Should be a table - if(lua_type(L, -1) != LUA_TTABLE) - { - errorstream<<"Item \""<getPlayer(name); + if(player == NULL) { - return true; + lua_pushboolean(L, false); // no such player + return 1; } - else if(lua_isnil(L, -1)) + try { - lua_pop(L, 1); - return false; + 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); } - else + catch(con::PeerNotFoundException) // unlikely { - errorstream<<"Detached inventory \""<unsetIpBanned(ip_or_name); + lua_pushboolean(L, true); + return 1; } -// Return number of accepted items to be put -int scriptapi_detached_inventory_allow_put(lua_State *L, - const std::string &name, - const std::string &listname, int index, ItemStack &stack, - ServerActiveObject *player) +// show_formspec(playername,formname,formspec) +static int l_show_formspec(lua_State *L) { - realitycheck(L); - assert(lua_checkstack(L, 20)); - StackUnroller stack_unroller(L); - - // Push callback function on stack - if(!get_detached_inventory_callback(L, name, "allow_put")) - return stack.count; // All will be accepted + const char *playername = luaL_checkstring(L, 1); + const char *formname = luaL_checkstring(L, 2); + const char *formspec = luaL_checkstring(L, 3); - // Call function(inv, listname, index, stack, player) - // inv - InventoryLocation loc; - loc.setDetached(name); - InvRef::create(L, loc); - // listname - lua_pushstring(L, listname.c_str()); - // index - lua_pushinteger(L, index + 1); - // stack - LuaItemStack::create(L, stack); - // player - objectref_get_or_create(L, player); - if(lua_pcall(L, 5, 1, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); - if(!lua_isnumber(L, -1)) - throw LuaError(L, "allow_put should return a number"); - return luaL_checkinteger(L, -1); + if(get_server(L)->showFormspec(playername,formspec,formname)) + { + lua_pushboolean(L, true); + }else{ + lua_pushboolean(L, false); + } + return 1; } -// Return number of accepted items to be taken -int scriptapi_detached_inventory_allow_take(lua_State *L, - const std::string &name, - const std::string &listname, int index, ItemStack &stack, - ServerActiveObject *player) +// get_dig_params(groups, tool_capabilities[, time_from_last_punch]) +static int l_get_dig_params(lua_State *L) { - realitycheck(L); - assert(lua_checkstack(L, 20)); - StackUnroller stack_unroller(L); - - // Push callback function on stack - if(!get_detached_inventory_callback(L, name, "allow_take")) - return stack.count; // All will be accepted - - // Call function(inv, listname, index, stack, player) - // inv - InventoryLocation loc; - loc.setDetached(name); - InvRef::create(L, loc); - // listname - lua_pushstring(L, listname.c_str()); - // index - lua_pushinteger(L, index + 1); - // stack - LuaItemStack::create(L, stack); - // player - objectref_get_or_create(L, player); - if(lua_pcall(L, 5, 1, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); - if(!lua_isnumber(L, -1)) - throw LuaError(L, "allow_take should return a number"); - return luaL_checkinteger(L, -1); + std::map groups; + read_groups(L, 1, groups); + ToolCapabilities tp = read_tool_capabilities(L, 2); + if(lua_isnoneornil(L, 3)) + push_dig_params(L, getDigParams(groups, &tp)); + else + push_dig_params(L, getDigParams(groups, &tp, + luaL_checknumber(L, 3))); + return 1; } -// Report moved items -void scriptapi_detached_inventory_on_move(lua_State *L, - const std::string &name, - const std::string &from_list, int from_index, - const std::string &to_list, int to_index, - int count, ServerActiveObject *player) +// get_hit_params(groups, tool_capabilities[, time_from_last_punch]) +static int l_get_hit_params(lua_State *L) { - realitycheck(L); - assert(lua_checkstack(L, 20)); - StackUnroller stack_unroller(L); + std::map groups; + read_groups(L, 1, groups); + ToolCapabilities tp = read_tool_capabilities(L, 2); + if(lua_isnoneornil(L, 3)) + push_hit_params(L, getHitParams(groups, &tp)); + else + push_hit_params(L, getHitParams(groups, &tp, + luaL_checknumber(L, 3))); + return 1; +} - // Push callback function on stack - if(!get_detached_inventory_callback(L, name, "on_move")) - return; +// get_current_modname() +static int l_get_current_modname(lua_State *L) +{ + lua_getfield(L, LUA_REGISTRYINDEX, "minetest_current_modname"); + return 1; +} - // function(inv, from_list, from_index, to_list, to_index, count, player) - // inv - InventoryLocation loc; - loc.setDetached(name); - InvRef::create(L, loc); - // from_list - lua_pushstring(L, from_list.c_str()); - // from_index - lua_pushinteger(L, from_index + 1); - // to_list - lua_pushstring(L, to_list.c_str()); - // to_index - lua_pushinteger(L, to_index + 1); - // count - lua_pushinteger(L, count); - // player - objectref_get_or_create(L, player); - if(lua_pcall(L, 7, 0, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); +// get_modpath(modname) +static int l_get_modpath(lua_State *L) +{ + std::string modname = luaL_checkstring(L, 1); + // Do it + if(modname == "__builtin"){ + std::string path = get_server(L)->getBuiltinLuaPath(); + lua_pushstring(L, path.c_str()); + return 1; + } + const ModSpec *mod = get_server(L)->getModSpec(modname); + if(!mod){ + lua_pushnil(L); + return 1; + } + lua_pushstring(L, mod->path.c_str()); + return 1; } -// Report put items -void scriptapi_detached_inventory_on_put(lua_State *L, - const std::string &name, - const std::string &listname, int index, ItemStack &stack, - ServerActiveObject *player) +// get_modnames() +// the returned list is sorted alphabetically for you +static int l_get_modnames(lua_State *L) { - realitycheck(L); - assert(lua_checkstack(L, 20)); - StackUnroller stack_unroller(L); + // Get a list of mods + core::list mods_unsorted, mods_sorted; + get_server(L)->getModNames(mods_unsorted); - // Push callback function on stack - if(!get_detached_inventory_callback(L, name, "on_put")) - return; + // Take unsorted items from mods_unsorted and sort them into + // mods_sorted; not great performance but the number of mods on a + // server will likely be small. + for(core::list::Iterator i = mods_unsorted.begin(); + i != mods_unsorted.end(); i++) + { + bool added = false; + for(core::list::Iterator x = mods_sorted.begin(); + x != mods_unsorted.end(); x++) + { + // I doubt anybody using Minetest will be using + // anything not ASCII based :) + if((*i).compare(*x) <= 0) + { + mods_sorted.insert_before(x, *i); + added = true; + break; + } + } + if(!added) + mods_sorted.push_back(*i); + } - // Call function(inv, listname, index, stack, player) - // inv - InventoryLocation loc; - loc.setDetached(name); - InvRef::create(L, loc); - // listname - lua_pushstring(L, listname.c_str()); - // index - lua_pushinteger(L, index + 1); - // stack - LuaItemStack::create(L, stack); - // player - objectref_get_or_create(L, player); - if(lua_pcall(L, 5, 0, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); + // Get the table insertion function from Lua. + lua_getglobal(L, "table"); + lua_getfield(L, -1, "insert"); + int insertion_func = lua_gettop(L); + + // Package them up for Lua + lua_newtable(L); + int new_table = lua_gettop(L); + core::list::Iterator i = mods_sorted.begin(); + while(i != mods_sorted.end()) + { + lua_pushvalue(L, insertion_func); + lua_pushvalue(L, new_table); + lua_pushstring(L, (*i).c_str()); + if(lua_pcall(L, 2, 0, 0) != 0) + { + script_error(L, "error: %s", lua_tostring(L, -1)); + } + i++; + } + return 1; } -// Report taken items -void scriptapi_detached_inventory_on_take(lua_State *L, - const std::string &name, - const std::string &listname, int index, ItemStack &stack, - ServerActiveObject *player) +// get_worldpath() +static int l_get_worldpath(lua_State *L) { - realitycheck(L); - assert(lua_checkstack(L, 20)); - StackUnroller stack_unroller(L); - - // Push callback function on stack - if(!get_detached_inventory_callback(L, name, "on_take")) - return; - - // Call function(inv, listname, index, stack, player) - // inv - InventoryLocation loc; - loc.setDetached(name); - InvRef::create(L, loc); - // listname - lua_pushstring(L, listname.c_str()); - // index - lua_pushinteger(L, index + 1); - // stack - LuaItemStack::create(L, stack); - // player - objectref_get_or_create(L, player); - if(lua_pcall(L, 5, 0, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); + std::string worldpath = get_server(L)->getWorldPath(); + lua_pushstring(L, worldpath.c_str()); + return 1; } -/* - environment -*/ - -void scriptapi_environment_step(lua_State *L, float dtime) +// sound_play(spec, parameters) +static int l_sound_play(lua_State *L) { - realitycheck(L); - assert(lua_checkstack(L, 20)); - //infostream<<"scriptapi_environment_step"<playSound(spec, params); + lua_pushinteger(L, handle); + return 1; } -void scriptapi_environment_on_generated(lua_State *L, v3s16 minp, v3s16 maxp, - u32 blockseed) +// sound_stop(handle) +static int l_sound_stop(lua_State *L) { - realitycheck(L); - assert(lua_checkstack(L, 20)); - //infostream<<"scriptapi_environment_on_generated"<stopSound(handle); + return 0; } -/* - luaentity -*/ - -bool scriptapi_luaentity_add(lua_State *L, u16 id, const char *name) +// is_singleplayer() +static int l_is_singleplayer(lua_State *L) { - realitycheck(L); - assert(lua_checkstack(L, 20)); - verbosestream<<"scriptapi_luaentity_add: id="<isSingleplayer()); + return 1; } -void scriptapi_luaentity_activate(lua_State *L, u16 id, - const std::string &staticdata, u32 dtime_s) +// get_password_hash(name, raw_password) +static int l_get_password_hash(lua_State *L) { - realitycheck(L); - assert(lua_checkstack(L, 20)); - verbosestream<<"scriptapi_luaentity_activate: id="<reportPrivsModified(name); + return 0; } -std::string scriptapi_luaentity_get_staticdata(lua_State *L, u16 id) +// rollback_get_last_node_actor(p, range, seconds) -> actor, p, seconds +static int l_rollback_get_last_node_actor(lua_State *L) { - realitycheck(L); - assert(lua_checkstack(L, 20)); - //infostream<<"scriptapi_luaentity_get_staticdata: id="<getRollbackManager(); + v3s16 act_p; + int act_seconds = 0; + std::string actor = rollback->getLastNodeActor(p, range, seconds, &act_p, &act_seconds); + lua_pushstring(L, actor.c_str()); + push_v3s16(L, act_p); + lua_pushnumber(L, act_seconds); + return 3; } -void scriptapi_luaentity_get_properties(lua_State *L, u16 id, - ObjectProperties *prop) +// rollback_revert_actions_by(actor, seconds) -> bool, log messages +static int l_rollback_revert_actions_by(lua_State *L) { - realitycheck(L); - assert(lua_checkstack(L, 20)); - //infostream<<"scriptapi_luaentity_get_properties: id="<hp_max = 10; - - /* Read stuff */ - - prop->hp_max = getintfield_default(L, -1, "hp_max", 10); - - getboolfield(L, -1, "physical", prop->physical); - - getfloatfield(L, -1, "weight", prop->weight); - - lua_getfield(L, -1, "collisionbox"); - if(lua_istable(L, -1)) - prop->collisionbox = read_aabb3f(L, -1, 1.0); - lua_pop(L, 1); - - getstringfield(L, -1, "visual", prop->visual); + std::string actor = luaL_checkstring(L, 1); + int seconds = luaL_checknumber(L, 2); + Server *server = get_server(L); + IRollbackManager *rollback = server->getRollbackManager(); + std::list actions = rollback->getRevertActions(actor, seconds); + std::list log; + bool success = server->rollbackRevertActions(actions, &log); + // Push boolean result + lua_pushboolean(L, success); + // Get the table insert function and push the log table + lua_getglobal(L, "table"); + lua_getfield(L, -1, "insert"); + int table_insert = lua_gettop(L); + lua_newtable(L); + int table = lua_gettop(L); + for(std::list::const_iterator i = log.begin(); + i != log.end(); i++) + { + lua_pushvalue(L, table_insert); + lua_pushvalue(L, table); + lua_pushstring(L, i->c_str()); + if(lua_pcall(L, 2, 0, 0)) + script_error(L, "error: %s", lua_tostring(L, -1)); + } + lua_remove(L, -2); // Remove table + lua_remove(L, -2); // Remove insert + return 2; +} - getstringfield(L, -1, "mesh", prop->mesh); +static const struct luaL_Reg minetest_f [] = { + {"debug", l_debug}, + {"log", l_log}, + {"request_shutdown", l_request_shutdown}, + {"get_server_status", l_get_server_status}, + {"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}, + {"setting_save",l_setting_save}, + {"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}, + {"get_modpath", l_get_modpath}, + {"get_modnames", l_get_modnames}, + {"get_worldpath", l_get_worldpath}, + {"sound_play", l_sound_play}, + {"sound_stop", l_sound_stop}, + {"is_singleplayer", l_is_singleplayer}, + {"get_password_hash", l_get_password_hash}, + {"notify_authentication_modified", l_notify_authentication_modified}, + {"get_craft_result", l_get_craft_result}, + {"get_craft_recipe", l_get_craft_recipe}, + {"rollback_get_last_node_actor", l_rollback_get_last_node_actor}, + {"rollback_revert_actions_by", l_rollback_revert_actions_by}, + {NULL, NULL} +}; - // 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); - lua_pop(L, 1); -} +/* + Main export function +*/ -void scriptapi_luaentity_step(lua_State *L, u16 id, float dtime) +void scriptapi_export(lua_State *L, Server *server) { realitycheck(L); assert(lua_checkstack(L, 20)); - //infostream<<"scriptapi_luaentity_step: id="< Date: Mon, 4 Mar 2013 01:55:16 +0100 Subject: Added method to get all registered recipes for item(node) --- src/scriptapi.cpp | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) (limited to 'src/scriptapi.cpp') diff --git a/src/scriptapi.cpp b/src/scriptapi.cpp index ef8a1454a..074a2eb0d 100644 --- a/src/scriptapi.cpp +++ b/src/scriptapi.cpp @@ -1000,6 +1000,79 @@ static int l_notify_authentication_modified(lua_State *L) return 0; } +// get_craft_recipes(result item) +static int l_get_all_craft_recipes(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; + CraftOutput output(o_item,0); + std::vector recipes_list = cdef->getCraftRecipes(output, gdef); + if (recipes_list.empty()) + { + lua_pushnil(L); + return 1; + } + // Get the table insert function + lua_getglobal(L, "table"); + lua_getfield(L, -1, "insert"); + int table_insert = lua_gettop(L); + lua_newtable(L); + int table = lua_gettop(L); + for(std::vector::const_iterator + i = recipes_list.begin(); + i != recipes_list.end(); i++) + { + CraftOutput tmpout; + tmpout.item = ""; + tmpout.time = 0; + CraftDefinition *def = *i; + tmpout = def->getOutput(input, gdef); + if(tmpout.item.substr(0,output.item.length()) == output.item) + { + input = def->getInput(output, gdef); + lua_pushvalue(L, table_insert); + lua_pushvalue(L, table); + lua_newtable(L); + int k = 0; + lua_newtable(L); + for(std::vector::const_iterator + i = input.items.begin(); + i != input.items.end(); i++, k++) + { + if (i->empty()) continue; + sprintf(tmp,"%d",k); + lua_pushstring(L,tmp); + lua_pushstring(L,i->name.c_str()); + lua_settable(L, -3); + } + lua_setfield(L, -2, "items"); + setintfield(L, -1, "width", input.width); + switch (input.method) + { + case CRAFT_METHOD_NORMAL: + lua_pushstring(L,"normal"); + break; + case CRAFT_METHOD_COOKING: + lua_pushstring(L,"cooking"); + break; + case CRAFT_METHOD_FUEL: + lua_pushstring(L,"fuel"); + break; + default: + lua_pushstring(L,"unknown"); + } + lua_setfield(L, -2, "type"); + if(lua_pcall(L, 2, 0, 0)) + script_error(L, "error: %s", lua_tostring(L, -1)); + } + } + return 1; +} + // rollback_get_last_node_actor(p, range, seconds) -> actor, p, seconds static int l_rollback_get_last_node_actor(lua_State *L) { @@ -1086,6 +1159,7 @@ static const struct luaL_Reg minetest_f [] = { {"notify_authentication_modified", l_notify_authentication_modified}, {"get_craft_result", l_get_craft_result}, {"get_craft_recipe", l_get_craft_recipe}, + {"get_all_craft_recipes", l_get_all_craft_recipes}, {"rollback_get_last_node_actor", l_rollback_get_last_node_actor}, {"rollback_revert_actions_by", l_rollback_revert_actions_by}, {NULL, NULL} -- cgit v1.2.3 From 6a1670dbc31cc0e44178bbd9ad34ff0d5981a060 Mon Sep 17 00:00:00 2001 From: Ilya Zhuravlev Date: Thu, 20 Dec 2012 21:19:49 +0400 Subject: Migrate to STL containers/algorithms. --- src/scriptapi.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'src/scriptapi.cpp') diff --git a/src/scriptapi.cpp b/src/scriptapi.cpp index 074a2eb0d..04af4eb22 100644 --- a/src/scriptapi.cpp +++ b/src/scriptapi.cpp @@ -895,24 +895,24 @@ static int l_get_modpath(lua_State *L) static int l_get_modnames(lua_State *L) { // Get a list of mods - core::list mods_unsorted, mods_sorted; + std::list mods_unsorted, mods_sorted; get_server(L)->getModNames(mods_unsorted); // Take unsorted items from mods_unsorted and sort them into // mods_sorted; not great performance but the number of mods on a // server will likely be small. - for(core::list::Iterator i = mods_unsorted.begin(); - i != mods_unsorted.end(); i++) + for(std::list::iterator i = mods_unsorted.begin(); + i != mods_unsorted.end(); ++i) { bool added = false; - for(core::list::Iterator x = mods_sorted.begin(); - x != mods_unsorted.end(); x++) + for(std::list::iterator x = mods_sorted.begin(); + x != mods_unsorted.end(); ++x) { // I doubt anybody using Minetest will be using // anything not ASCII based :) if((*i).compare(*x) <= 0) { - mods_sorted.insert_before(x, *i); + mods_sorted.insert(x, *i); added = true; break; } @@ -929,7 +929,7 @@ static int l_get_modnames(lua_State *L) // Package them up for Lua lua_newtable(L); int new_table = lua_gettop(L); - core::list::Iterator i = mods_sorted.begin(); + std::list::iterator i = mods_sorted.begin(); while(i != mods_sorted.end()) { lua_pushvalue(L, insertion_func); @@ -939,7 +939,7 @@ static int l_get_modnames(lua_State *L) { script_error(L, "error: %s", lua_tostring(L, -1)); } - i++; + ++i; } return 1; } -- cgit v1.2.3 From eb90c3d92dac8a04019ccca875a9162739ddd7f1 Mon Sep 17 00:00:00 2001 From: sapier Date: Thu, 7 Mar 2013 23:22:54 +0000 Subject: Move l_get_all_craft_recipes to scriptapi_craft --- src/scriptapi.cpp | 73 ------------------------------------------------------- 1 file changed, 73 deletions(-) (limited to 'src/scriptapi.cpp') diff --git a/src/scriptapi.cpp b/src/scriptapi.cpp index 04af4eb22..f95f5a29d 100644 --- a/src/scriptapi.cpp +++ b/src/scriptapi.cpp @@ -1000,79 +1000,6 @@ static int l_notify_authentication_modified(lua_State *L) return 0; } -// get_craft_recipes(result item) -static int l_get_all_craft_recipes(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; - CraftOutput output(o_item,0); - std::vector recipes_list = cdef->getCraftRecipes(output, gdef); - if (recipes_list.empty()) - { - lua_pushnil(L); - return 1; - } - // Get the table insert function - lua_getglobal(L, "table"); - lua_getfield(L, -1, "insert"); - int table_insert = lua_gettop(L); - lua_newtable(L); - int table = lua_gettop(L); - for(std::vector::const_iterator - i = recipes_list.begin(); - i != recipes_list.end(); i++) - { - CraftOutput tmpout; - tmpout.item = ""; - tmpout.time = 0; - CraftDefinition *def = *i; - tmpout = def->getOutput(input, gdef); - if(tmpout.item.substr(0,output.item.length()) == output.item) - { - input = def->getInput(output, gdef); - lua_pushvalue(L, table_insert); - lua_pushvalue(L, table); - lua_newtable(L); - int k = 0; - lua_newtable(L); - for(std::vector::const_iterator - i = input.items.begin(); - i != input.items.end(); i++, k++) - { - if (i->empty()) continue; - sprintf(tmp,"%d",k); - lua_pushstring(L,tmp); - lua_pushstring(L,i->name.c_str()); - lua_settable(L, -3); - } - lua_setfield(L, -2, "items"); - setintfield(L, -1, "width", input.width); - switch (input.method) - { - case CRAFT_METHOD_NORMAL: - lua_pushstring(L,"normal"); - break; - case CRAFT_METHOD_COOKING: - lua_pushstring(L,"cooking"); - break; - case CRAFT_METHOD_FUEL: - lua_pushstring(L,"fuel"); - break; - default: - lua_pushstring(L,"unknown"); - } - lua_setfield(L, -2, "type"); - if(lua_pcall(L, 2, 0, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); - } - } - return 1; -} - // rollback_get_last_node_actor(p, range, seconds) -> actor, p, seconds static int l_rollback_get_last_node_actor(lua_State *L) { -- cgit v1.2.3 From 66750dc88e3b1001e2141dd965345ae51095e0bb Mon Sep 17 00:00:00 2001 From: sapier Date: Thu, 14 Mar 2013 00:24:07 +0000 Subject: fix typo invalid for loop end --- src/scriptapi.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/scriptapi.cpp') diff --git a/src/scriptapi.cpp b/src/scriptapi.cpp index f95f5a29d..13696eabf 100644 --- a/src/scriptapi.cpp +++ b/src/scriptapi.cpp @@ -906,7 +906,7 @@ static int l_get_modnames(lua_State *L) { bool added = false; for(std::list::iterator x = mods_sorted.begin(); - x != mods_unsorted.end(); ++x) + x != mods_sorted.end(); ++x) { // I doubt anybody using Minetest will be using // anything not ASCII based :) -- cgit v1.2.3 From e1ff5b13619666e5b987ecf4faaf294400ffd979 Mon Sep 17 00:00:00 2001 From: Jeija Date: Wed, 23 Jan 2013 18:32:02 +0100 Subject: Allow spawning particles from the server, from lua Spawn single particles or make use of ParticleSpawner for many randomly spawned particles. Accessible in Lua using minetest.spawn_particle and minetest.add_particlespawner. Increase Protocol Version to 17. Conflicts: src/clientserver.h --- src/scriptapi.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/scriptapi.cpp') diff --git a/src/scriptapi.cpp b/src/scriptapi.cpp index 13696eabf..29494ff69 100644 --- a/src/scriptapi.cpp +++ b/src/scriptapi.cpp @@ -44,6 +44,7 @@ extern "C" { #include "scriptapi_item.h" #include "scriptapi_content.h" #include "scriptapi_craft.h" +#include "scriptapi_particles.h" /*****************************************************************************/ /* Mod related */ @@ -1089,6 +1090,9 @@ static const struct luaL_Reg minetest_f [] = { {"get_all_craft_recipes", l_get_all_craft_recipes}, {"rollback_get_last_node_actor", l_rollback_get_last_node_actor}, {"rollback_revert_actions_by", l_rollback_revert_actions_by}, + {"add_particle", l_add_particle}, + {"add_particlespawner", l_add_particlespawner}, + {"delete_particlespawner", l_delete_particlespawner}, {NULL, NULL} }; -- cgit v1.2.3 From 57cbb8bfd8daaa1b8b1aa876723ff6355d21f7fc Mon Sep 17 00:00:00 2001 From: kwolekr Date: Sun, 24 Mar 2013 01:43:38 -0400 Subject: Add Ore infrastructure and l_register_ore() --- src/scriptapi.cpp | 46 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) (limited to 'src/scriptapi.cpp') diff --git a/src/scriptapi.cpp b/src/scriptapi.cpp index 29494ff69..ddffbb0b7 100644 --- a/src/scriptapi.cpp +++ b/src/scriptapi.cpp @@ -30,6 +30,7 @@ extern "C" { #include "settings.h" // For accessing g_settings #include "main.h" // For g_settings #include "biome.h" +#include "emerge.h" #include "script.h" #include "rollback.h" @@ -242,6 +243,14 @@ struct EnumString es_BiomeTerrainType[] = {0, NULL}, }; +struct EnumString es_OreType[] = +{ + {ORE_SCATTER, "scatter"}, + {ORE_SHEET, "sheet"}, + {ORE_CLAYLIKE, "claylike"}, + {0, NULL}, +}; + /*****************************************************************************/ /* Parameters */ /*****************************************************************************/ @@ -612,8 +621,6 @@ 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) { @@ -686,6 +693,40 @@ static int l_register_biome(lua_State *L) } +static int l_register_ore(lua_State *L) +{ + int index = 1; + luaL_checktype(L, index, LUA_TTABLE); + + IWritableNodeDefManager *ndef = get_server(L)->getWritableNodeDefManager(); + EmergeManager *emerge = get_server(L)->getEmergeManager(); + + enum OreType oretype = (OreType)getenumfield(L, index, + "ore_type", es_OreType, ORE_SCATTER); + Ore *ore = createOre(oretype); + + ore->ore_name = getstringfield_default(L, index, "ore", ""); + ore->wherein_name = getstringfield_default(L, index, "wherein", ""); + ore->clust_scarcity = getintfield_default(L, index, "clust_scarcity", 0); + ore->clust_num_ores = getintfield_default(L, index, "clust_num_ores", 0); + ore->clust_size = getintfield_default(L, index, "clust_size", 0); + ore->height_min = getintfield_default(L, index, "height_min", 0); + ore->height_max = getintfield_default(L, index, "height_max", 0); + ore->nthresh = getfloatfield_default(L, index, "noise_threshhold", 0.); + + lua_getfield(L, index, "noise_params"); + ore->np = read_noiseparams(L, -1); + lua_pop(L, 1); + + ore->noise = NULL; + + emerge->ores.push_back(ore); + + verbosestream << "register_ore: ore '" << ore->ore_name + << "' registered" << std::endl; + return 0; +} + // setting_set(name, value) static int l_setting_set(lua_State *L) @@ -1060,6 +1101,7 @@ static const struct luaL_Reg minetest_f [] = { {"register_craft", l_register_craft}, {"register_biome", l_register_biome}, {"register_biome_groups", l_register_biome_groups}, + {"register_ore", l_register_ore}, {"setting_set", l_setting_set}, {"setting_get", l_setting_get}, {"setting_getbool", l_setting_getbool}, -- cgit v1.2.3 From 0e07a7157f4865c26b4d7d0ba6fb12f1de59373c Mon Sep 17 00:00:00 2001 From: kwolekr Date: Sun, 24 Mar 2013 15:29:23 -0400 Subject: Add more error checking to l_register_ore --- src/scriptapi.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'src/scriptapi.cpp') diff --git a/src/scriptapi.cpp b/src/scriptapi.cpp index ddffbb0b7..80abffa2b 100644 --- a/src/scriptapi.cpp +++ b/src/scriptapi.cpp @@ -704,11 +704,16 @@ static int l_register_ore(lua_State *L) enum OreType oretype = (OreType)getenumfield(L, index, "ore_type", es_OreType, ORE_SCATTER); Ore *ore = createOre(oretype); + if (!ore) { + errorstream << "register_ore: ore_type " + << oretype << " not implemented"; + return 0; + } ore->ore_name = getstringfield_default(L, index, "ore", ""); ore->wherein_name = getstringfield_default(L, index, "wherein", ""); - ore->clust_scarcity = getintfield_default(L, index, "clust_scarcity", 0); - ore->clust_num_ores = getintfield_default(L, index, "clust_num_ores", 0); + 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); ore->height_min = getintfield_default(L, index, "height_min", 0); ore->height_max = getintfield_default(L, index, "height_max", 0); @@ -720,6 +725,13 @@ static int l_register_ore(lua_State *L) ore->noise = NULL; + if (ore->clust_scarcity <= 0 || ore->clust_num_ores <= 0) { + errorstream << "register_ore: clust_scarcity and clust_num_ores" + "must be greater than 0"; + delete ore; + return 0; + } + emerge->ores.push_back(ore); verbosestream << "register_ore: ore '" << ore->ore_name -- cgit v1.2.3