From e391ee435f3e82c8251bb8797c5e9b76e7ac9f72 Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Thu, 18 Feb 2021 20:19:17 +0100 Subject: Forcefully place items when minetest.place_node is used --- src/script/lua_api/l_client.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/script/lua_api/l_client.cpp') diff --git a/src/script/lua_api/l_client.cpp b/src/script/lua_api/l_client.cpp index dac2febae..abd27f7dc 100644 --- a/src/script/lua_api/l_client.cpp +++ b/src/script/lua_api/l_client.cpp @@ -440,7 +440,7 @@ int ModApiClient::l_place_node(lua_State *L) pointed.node_abovesurface = pos; pointed.node_undersurface = pos; NodeMetadata *meta = map.getNodeMetadata(pos); - g_game->nodePlacement(selected_def, selected_item, pos, pos, pointed, meta); + g_game->nodePlacement(selected_def, selected_item, pos, pos, pointed, meta, true); return 0; } -- cgit v1.2.3 From 16696823242ca3b82d932542899e77894238fa2c Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Thu, 18 Feb 2021 20:20:22 +0100 Subject: Port formspec API from waspsaliva This API is inofficial and undocumented; invalid usage causes the game to crash. Use at own risk! --- src/script/lua_api/l_client.cpp | 44 +++++++++++++++++++++++++++++++++++++++++ src/script/lua_api/l_client.h | 6 ++++++ 2 files changed, 50 insertions(+) (limited to 'src/script/lua_api/l_client.cpp') diff --git a/src/script/lua_api/l_client.cpp b/src/script/lua_api/l_client.cpp index abd27f7dc..484af2ec3 100644 --- a/src/script/lua_api/l_client.cpp +++ b/src/script/lua_api/l_client.cpp @@ -621,6 +621,48 @@ int ModApiClient::l_interact(lua_State *L) return 1; } +StringMap *table_to_stringmap(lua_State *L, int index) +{ + StringMap *m = new StringMap; + + lua_pushvalue(L, index); + lua_pushnil(L); + + while (lua_next(L, -2)) { + lua_pushvalue(L, -2); + std::basic_string key = lua_tostring(L, -1); + std::basic_string value = lua_tostring(L, -2); + (*m)[key] = value; + lua_pop(L, 2); + } + + lua_pop(L, 1); + + return m; +} + +// send_inventory_fields(formname, fields) +// Only works if the inventory form was opened beforehand. +int ModApiClient::l_send_inventory_fields(lua_State *L) +{ + std::string formname = luaL_checkstring(L, 1); + StringMap *fields = table_to_stringmap(L, 2); + + getClient(L)->sendInventoryFields(formname, *fields); + return 0; +} + +// send_nodemeta_fields(position, formname, fields) +int ModApiClient::l_send_nodemeta_fields(lua_State *L) +{ + v3s16 pos = check_v3s16(L, 1); + std::string formname = luaL_checkstring(L, 2); + StringMap *m = table_to_stringmap(L, 3); + + getClient(L)->sendNodemetaFields(pos, formname, *m); + return 0; +} + void ModApiClient::Initialize(lua_State *L, int top) { API_FCT(get_current_modname); @@ -657,4 +699,6 @@ void ModApiClient::Initialize(lua_State *L, int top) API_FCT(get_objects_inside_radius); API_FCT(make_screenshot); API_FCT(interact); + API_FCT(send_inventory_fields); + API_FCT(send_nodemeta_fields); } diff --git a/src/script/lua_api/l_client.h b/src/script/lua_api/l_client.h index 03a42e022..caf21f78e 100644 --- a/src/script/lua_api/l_client.h +++ b/src/script/lua_api/l_client.h @@ -132,6 +132,12 @@ private: // interact(action, pointed_thing) static int l_interact(lua_State *L); + // send_inventory_fields(formname, fields) + static int l_send_inventory_fields(lua_State *L); + + // send_nodemeta_fields(position, formname, fields) + static int l_send_nodemeta_fields(lua_State *L); + public: static void Initialize(lua_State *L, int top); }; -- cgit v1.2.3 From 4f613bbf5118ebe8c3610514e7f4206e930783bf Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Tue, 11 May 2021 14:07:30 +0200 Subject: Include tile definitions in get_node_def; Client-side minetest.object_refs table --- builtin/client/register.lua | 1 + builtin/common/misc_helpers.lua | 9 +++++ builtin/game/item.lua | 9 ----- doc/client_lua_api.txt | 61 +++++++++++++++++++++++++++++++++ src/client/clientenvironment.cpp | 11 +++++- src/client/game.cpp | 2 +- src/script/common/c_content.cpp | 63 ++++++++++++++++++++++++++++++----- src/script/cpp_api/s_base.cpp | 16 ++++++--- src/script/cpp_api/s_base.h | 5 +-- src/script/cpp_api/s_client.cpp | 4 +-- src/script/lua_api/l_client.cpp | 2 +- src/script/lua_api/l_clientobject.cpp | 59 ++++++++++++++++++++++++++++---- src/script/lua_api/l_clientobject.h | 2 ++ src/script/lua_api/l_localplayer.cpp | 2 +- src/serverenvironment.cpp | 8 ++--- 15 files changed, 212 insertions(+), 42 deletions(-) (limited to 'src/script/lua_api/l_client.cpp') diff --git a/builtin/client/register.lua b/builtin/client/register.lua index 835ec5002..6a6d8e13c 100644 --- a/builtin/client/register.lua +++ b/builtin/client/register.lua @@ -110,3 +110,4 @@ core.registered_on_object_hp_change, core.register_on_object_hp_change = make_re core.registered_nodes = {} core.registered_items = {} +core.object_refs = {} diff --git a/builtin/common/misc_helpers.lua b/builtin/common/misc_helpers.lua index b86d68f5f..308e2c7c7 100644 --- a/builtin/common/misc_helpers.lua +++ b/builtin/common/misc_helpers.lua @@ -785,3 +785,12 @@ end function core.is_nan(number) return number ~= number end + +function core.inventorycube(img1, img2, img3) + img2 = img2 or img1 + img3 = img3 or img1 + return "[inventorycube" + .. "{" .. img1:gsub("%^", "&") + .. "{" .. img2:gsub("%^", "&") + .. "{" .. img3:gsub("%^", "&") +end diff --git a/builtin/game/item.lua b/builtin/game/item.lua index dc0247e5f..cc0314e67 100644 --- a/builtin/game/item.lua +++ b/builtin/game/item.lua @@ -15,15 +15,6 @@ end -- Item definition helpers -- -function core.inventorycube(img1, img2, img3) - img2 = img2 or img1 - img3 = img3 or img1 - return "[inventorycube" - .. "{" .. img1:gsub("%^", "&") - .. "{" .. img2:gsub("%^", "&") - .. "{" .. img3:gsub("%^", "&") -end - function core.dir_to_facedir(dir, is6d) --account for y if requested if is6d and math.abs(dir.y) > math.abs(dir.x) and math.abs(dir.y) > math.abs(dir.z) then diff --git a/doc/client_lua_api.txt b/doc/client_lua_api.txt index 2e347ec47..e33fe0e3a 100644 --- a/doc/client_lua_api.txt +++ b/doc/client_lua_api.txt @@ -934,6 +934,8 @@ Call these functions only at load time! * Convert between two privilege representations ### Client Environment +* `minetest.object_refs` + * Map of object references, indexed by active object id * `minetest.get_player_names()` * Returns list of player names on server (nil if CSM_RF_READ_PLAYERINFO is enabled by server) * `minetest.get_objects_inside_radius(pos, radius)`: returns a list of @@ -1454,6 +1456,8 @@ It can be created via `Raycast(pos1, pos2, objects, liquids)` or ----------------- ### Definitions +* `minetest.inventorycube(img1, img2, img3)` + * Returns a string for making an image of a cube (useful as an item image) * `minetest.get_node_def(nodename)` * Returns [node definition](#node-definition) table of `nodename` * `minetest.get_item_def(itemstring)` @@ -1465,10 +1469,67 @@ It can be created via `Raycast(pos1, pos2, objects, liquids)` or {light_source=minetest.LIGHT_MAX})` * Doesnt really work yet an causes strange bugs, I'm working to make is better + +#### Tile definition + +* `"image.png"` +* `{name="image.png", animation={Tile Animation definition}}` +* `{name="image.png", backface_culling=bool, align_style="node"/"world"/"user", scale=int}` + * backface culling enabled by default for most nodes + * align style determines whether the texture will be rotated with the node + or kept aligned with its surroundings. "user" means that client + setting will be used, similar to `glasslike_framed_optional`. + Note: supported by solid nodes and nodeboxes only. + * scale is used to make texture span several (exactly `scale`) nodes, + instead of just one, in each direction. Works for world-aligned + textures only. + Note that as the effect is applied on per-mapblock basis, `16` should + be equally divisible by `scale` or you may get wrong results. +* `{name="image.png", color=ColorSpec}` + * the texture's color will be multiplied with this color. + * the tile's color overrides the owning node's color in all cases. + +##### Tile definition + + { + type = "vertical_frames", + + aspect_w = 16, + -- Width of a frame in pixels + + aspect_h = 16, + -- Height of a frame in pixels + + length = 3.0, + -- Full loop length + } + + { + type = "sheet_2d", + + frames_w = 5, + -- Width in number of frames + + frames_h = 3, + -- Height in number of frames + + frame_length = 0.5, + -- Length of a single frame + } + #### Node Definition ```lua { + tiles = {tile definition 1, def2, def3, def4, def5, def6}, + -- Textures of node; +Y, -Y, +X, -X, +Z, -Z + overlay_tiles = {tile definition 1, def2, def3, def4, def5, def6}, + -- Same as `tiles`, but these textures are drawn on top of the base + -- tiles. This is used to colorize only specific parts of the + -- texture. If the texture name is an empty string, that overlay is not + -- drawn + special_tiles = {tile definition 1, Tile definition 2}, + -- Special textures of node; used rarely. has_on_construct = bool, -- Whether the node has the on_construct callback defined has_on_destruct = bool, -- Whether the node has the on_destruct callback defined has_after_destruct = bool, -- Whether the node has the after_destruct callback defined diff --git a/src/client/clientenvironment.cpp b/src/client/clientenvironment.cpp index fd56c8f44..8e0d00bc9 100644 --- a/src/client/clientenvironment.cpp +++ b/src/client/clientenvironment.cpp @@ -352,6 +352,7 @@ void ClientEnvironment::addActiveObject(u16 id, u8 type, { ClientActiveObject* obj = ClientActiveObject::create((ActiveObjectType) type, m_client, this); + if(obj == NULL) { infostream<<"ClientEnvironment::addActiveObject(): " @@ -362,6 +363,9 @@ void ClientEnvironment::addActiveObject(u16 id, u8 type, obj->setId(id); + if (m_client->modsLoaded()) + m_client->getScript()->addObjectReference(dynamic_cast(obj)); + try { obj->initialize(init_data); @@ -394,9 +398,14 @@ void ClientEnvironment::removeActiveObject(u16 id) { // Get current attachment childs to detach them visually std::unordered_set attachment_childs; - if (auto *obj = getActiveObject(id)) + auto *obj = getActiveObject(id); + if (obj) { attachment_childs = obj->getAttachmentChildIds(); + if (m_client->modsLoaded()) + m_client->getScript()->removeObjectReference(dynamic_cast(obj)); + } + m_ao_manager.removeObject(id); // Perform a proper detach in Irrlicht diff --git a/src/client/game.cpp b/src/client/game.cpp index 104a6e374..e1f2fbe75 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -734,7 +734,7 @@ bool Game::connectToServer(const GameStartData &start_data, } else { wait_time += dtime; // Only time out if we aren't waiting for the server we started - if (!start_data.isSinglePlayer() && wait_time > 10) { + if (!start_data.local_server && !start_data.isSinglePlayer() && wait_time > 10) { *error_message = "Connection timed out."; errorstream << *error_message << std::endl; break; diff --git a/src/script/common/c_content.cpp b/src/script/common/c_content.cpp index 8543b70ce..e56d07cc6 100644 --- a/src/script/common/c_content.cpp +++ b/src/script/common/c_content.cpp @@ -515,6 +515,35 @@ TileDef read_tiledef(lua_State *L, int index, u8 drawtype) return tiledef; } +/******************************************************************************/ +void push_tiledef(lua_State *L, TileDef tiledef) +{ + lua_newtable(L); + setstringfield(L, -1, "name", tiledef.name); + setboolfield(L, -1, "backface_culling", tiledef.backface_culling); + setboolfield(L, -1, "tileable_horizontal", tiledef.tileable_horizontal); + setboolfield(L, -1, "tileable_vertical", tiledef.tileable_vertical); + std::string align_style; + switch (tiledef.align_style) { + case ALIGN_STYLE_USER_DEFINED: + align_style = "user"; + break; + case ALIGN_STYLE_WORLD: + align_style = "world"; + break; + default: + align_style = "node"; + } + setstringfield(L, -1, "align_style", align_style); + setintfield(L, -1, "scale", tiledef.scale); + if (tiledef.has_color) { + push_ARGB8(L, tiledef.color); + lua_setfield(L, -2, "color"); + } + push_animation_definition(L, tiledef.animation); + lua_setfield(L, -2, "animation"); +} + /******************************************************************************/ void read_content_features(lua_State *L, ContentFeatures &f, int index) { @@ -835,9 +864,32 @@ void push_content_features(lua_State *L, const ContentFeatures &c) std::string drawtype(ScriptApiNode::es_DrawType[(int)c.drawtype].str); std::string liquid_type(ScriptApiNode::es_LiquidType[(int)c.liquid_type].str); - /* Missing "tiles" because I don't see a usecase (at least not yet). */ + lua_newtable(L); + // tiles lua_newtable(L); + for (int i = 0; i < 6; i++) { + push_tiledef(L, c.tiledef[i]); + lua_rawseti(L, -2, i + 1); + } + lua_setfield(L, -2, "tiles"); + + // overlay_tiles + lua_newtable(L); + for (int i = 0; i < 6; i++) { + push_tiledef(L, c.tiledef_overlay[i]); + lua_rawseti(L, -2, i + 1); + } + lua_setfield(L, -2, "overlay_tiles"); + + // special_tiles + lua_newtable(L); + for (int i = 0; i < CF_SPECIAL_COUNT; i++) { + push_tiledef(L, c.tiledef_special[i]); + lua_rawseti(L, -2, i + 1); + } + lua_setfield(L, -2, "special_tiles"); + lua_pushboolean(L, c.has_on_construct); lua_setfield(L, -2, "has_on_construct"); lua_pushboolean(L, c.has_on_destruct); @@ -1886,14 +1938,7 @@ void push_pointed_thing(lua_State *L, const PointedThing &pointed, bool csm, } else if (pointed.type == POINTEDTHING_OBJECT) { lua_pushstring(L, "object"); lua_setfield(L, -2, "type"); - if (csm) { -#ifndef SERVER - ClientObjectRef::create(L, pointed.object_id); -#endif - } else { - push_objectRef(L, pointed.object_id); - } - + push_objectRef(L, pointed.object_id); lua_setfield(L, -2, "ref"); } else { lua_pushstring(L, "nothing"); diff --git a/src/script/cpp_api/s_base.cpp b/src/script/cpp_api/s_base.cpp index 1d62d8b65..867f61e0c 100644 --- a/src/script/cpp_api/s_base.cpp +++ b/src/script/cpp_api/s_base.cpp @@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "cpp_api/s_internal.h" #include "cpp_api/s_security.h" #include "lua_api/l_object.h" +#include "lua_api/l_clientobject.h" #include "common/c_converter.h" #include "server/player_sao.h" #include "filesys.h" @@ -354,13 +355,16 @@ void ScriptApiBase::setOriginFromTableRaw(int index, const char *fxn) * since we lose control over the ref and the contained pointer. */ -void ScriptApiBase::addObjectReference(ServerActiveObject *cobj) +void ScriptApiBase::addObjectReference(ActiveObject *cobj) { SCRIPTAPI_PRECHECKHEADER //infostream<<"scriptapi_add_object_reference: id="<getId()<(cobj)); + else + ObjectRef::create(L, dynamic_cast(cobj)); // Puts ObjectRef (as userdata) on stack int object = lua_gettop(L); // Get core.object_refs table @@ -375,7 +379,7 @@ void ScriptApiBase::addObjectReference(ServerActiveObject *cobj) lua_settable(L, objectstable); } -void ScriptApiBase::removeObjectReference(ServerActiveObject *cobj) +void ScriptApiBase::removeObjectReference(ActiveObject *cobj) { SCRIPTAPI_PRECHECKHEADER //infostream<<"scriptapi_rm_object_reference: id="<getId()<getId()); // Push id lua_gettable(L, objectstable); // Set object reference to NULL - ObjectRef::set_null(L); + if (m_type == ScriptingType::Client) + ClientObjectRef::set_null(L); + else + ObjectRef::set_null(L); lua_pop(L, 1); // pop object // Set object_refs[id] = nil @@ -413,7 +420,6 @@ void ScriptApiBase::objectrefGetOrCreate(lua_State *L, << ", this is probably a bug." << std::endl; } } - void ScriptApiBase::pushPlayerHPChangeReason(lua_State *L, const PlayerHPChangeReason &reason) { if (reason.hasLuaReference()) diff --git a/src/script/cpp_api/s_base.h b/src/script/cpp_api/s_base.h index 36331ad37..a7a2c7203 100644 --- a/src/script/cpp_api/s_base.h +++ b/src/script/cpp_api/s_base.h @@ -73,6 +73,7 @@ class Game; class IGameDef; class Environment; class GUIEngine; +class ActiveObject; class ServerActiveObject; struct PlayerHPChangeReason; @@ -99,8 +100,8 @@ public: RunCallbacksMode mode, const char *fxn); /* object */ - void addObjectReference(ServerActiveObject *cobj); - void removeObjectReference(ServerActiveObject *cobj); + void addObjectReference(ActiveObject *cobj); + void removeObjectReference(ActiveObject *cobj); IGameDef *getGameDef() { return m_gamedef; } Server* getServer(); diff --git a/src/script/cpp_api/s_client.cpp b/src/script/cpp_api/s_client.cpp index 2231cf573..7971e4081 100644 --- a/src/script/cpp_api/s_client.cpp +++ b/src/script/cpp_api/s_client.cpp @@ -302,7 +302,7 @@ void ScriptApiClient::on_object_properties_change(s16 id) lua_getfield(L, -1, "registered_on_object_properties_change"); // Push data - ClientObjectRef::create(L, id); + push_objectRef(L, id); // Call functions runCallbacks(1, RUN_CALLBACKS_MODE_FIRST); @@ -317,7 +317,7 @@ void ScriptApiClient::on_object_hp_change(s16 id) lua_getfield(L, -1, "registered_on_object_hp_change"); // Push data - ClientObjectRef::create(L, id); + push_objectRef(L, id); // Call functions runCallbacks(1, RUN_CALLBACKS_MODE_FIRST); diff --git a/src/script/lua_api/l_client.cpp b/src/script/lua_api/l_client.cpp index 484af2ec3..916983982 100644 --- a/src/script/lua_api/l_client.cpp +++ b/src/script/lua_api/l_client.cpp @@ -520,7 +520,7 @@ int ModApiClient::l_get_objects_inside_radius(lua_State *L) int i = 0; lua_createtable(L, objs.size(), 0); for (const auto obj : objs) { - ClientObjectRef::create(L, obj.obj); // TODO: getObjectRefOrCreate + push_objectRef(L, obj.obj->getId()); lua_rawseti(L, -2, ++i); } return 1; diff --git a/src/script/lua_api/l_clientobject.cpp b/src/script/lua_api/l_clientobject.cpp index 8a4647d45..5a1123169 100644 --- a/src/script/lua_api/l_clientobject.cpp +++ b/src/script/lua_api/l_clientobject.cpp @@ -48,6 +48,8 @@ ClientActiveObject *ClientObjectRef::get_cao(ClientObjectRef *ref) GenericCAO *ClientObjectRef::get_generic_cao(ClientObjectRef *ref, lua_State *L) { ClientActiveObject *obj = get_cao(ref); + if (! obj) + return nullptr; ClientEnvironment &env = getClient(L)->getEnv(); GenericCAO *gcao = env.getGenericCAO(obj->getId()); return gcao; @@ -57,6 +59,8 @@ int ClientObjectRef::l_get_pos(lua_State *L) { ClientObjectRef *ref = checkobject(L, 1); ClientActiveObject *cao = get_cao(ref); + if (! cao) + return 0; push_v3f(L, cao->getPosition() / BS); return 1; } @@ -65,6 +69,8 @@ int ClientObjectRef::l_get_velocity(lua_State *L) { ClientObjectRef *ref = checkobject(L, 1); GenericCAO *gcao = get_generic_cao(ref, L); + if (! gcao) + return 0; push_v3f(L, gcao->getVelocity() / BS); return 1; } @@ -73,6 +79,8 @@ int ClientObjectRef::l_get_acceleration(lua_State *L) { ClientObjectRef *ref = checkobject(L, 1); GenericCAO *gcao = get_generic_cao(ref, L); + if (! gcao) + return 0; push_v3f(L, gcao->getAcceleration() / BS); return 1; } @@ -81,6 +89,8 @@ int ClientObjectRef::l_get_rotation(lua_State *L) { ClientObjectRef *ref = checkobject(L, 1); GenericCAO *gcao = get_generic_cao(ref, L); + if (! gcao) + return 0; push_v3f(L, gcao->getRotation()); return 1; } @@ -89,6 +99,8 @@ int ClientObjectRef::l_is_player(lua_State *L) { ClientObjectRef *ref = checkobject(L, 1); GenericCAO *gcao = get_generic_cao(ref, L); + if (! gcao) + return 0; lua_pushboolean(L, gcao->isPlayer()); return 1; } @@ -97,6 +109,8 @@ int ClientObjectRef::l_is_local_player(lua_State *L) { ClientObjectRef *ref = checkobject(L, 1); GenericCAO *gcao = get_generic_cao(ref, L); + if (! gcao) + return 0; lua_pushboolean(L, gcao->isLocalPlayer()); return 1; } @@ -105,6 +119,8 @@ int ClientObjectRef::l_get_name(lua_State *L) { ClientObjectRef *ref = checkobject(L, 1); GenericCAO *gcao = get_generic_cao(ref, L); + if (! gcao) + return 0; lua_pushstring(L, gcao->getName().c_str()); return 1; } @@ -113,7 +129,12 @@ int ClientObjectRef::l_get_attach(lua_State *L) { ClientObjectRef *ref = checkobject(L, 1); GenericCAO *gcao = get_generic_cao(ref, L); - create(L, gcao->getParent()); + if (! gcao) + return 0; + ClientActiveObject *parent = gcao->getParent(); + if (! parent) + return 0; + push_objectRef(L, parent->getId()); return 1; } @@ -122,6 +143,8 @@ int ClientObjectRef::l_get_nametag(lua_State *L) log_deprecated(L,"Deprecated call to get_nametag, use get_properties().nametag instead"); ClientObjectRef *ref = checkobject(L, 1); GenericCAO *gcao = get_generic_cao(ref, L); + if (! gcao) + return 0; ObjectProperties *props = gcao->getProperties(); lua_pushstring(L, props->nametag.c_str()); return 1; @@ -132,6 +155,8 @@ int ClientObjectRef::l_get_item_textures(lua_State *L) log_deprecated(L,"Deprecated call to get_item_textures, use get_properties().textures instead"); ClientObjectRef *ref = checkobject(L, 1); GenericCAO *gcao = get_generic_cao(ref, L); + if (! gcao) + return 0; ObjectProperties *props = gcao->getProperties(); lua_newtable(L); @@ -146,6 +171,8 @@ int ClientObjectRef::l_get_max_hp(lua_State *L) log_deprecated(L,"Deprecated call to get_max_hp, use get_properties().hp_max instead"); ClientObjectRef *ref = checkobject(L, 1); GenericCAO *gcao = get_generic_cao(ref, L); + if (! gcao) + return 0; ObjectProperties *props = gcao->getProperties(); lua_pushnumber(L, props->hp_max); return 1; @@ -155,6 +182,8 @@ int ClientObjectRef::l_get_properties(lua_State *L) { ClientObjectRef *ref = checkobject(L, 1); GenericCAO *gcao = get_generic_cao(ref, L); + if (! gcao) + return 0; ObjectProperties *prop = gcao->getProperties(); push_object_properties(L, prop); return 1; @@ -164,6 +193,8 @@ int ClientObjectRef::l_set_properties(lua_State *L) { ClientObjectRef *ref = checkobject(L, 1); GenericCAO *gcao = get_generic_cao(ref, L); + if (! gcao) + return 0; ObjectProperties prop = *gcao->getProperties(); read_object_properties(L, 2, nullptr, &prop, getClient(L)->idef()); gcao->setProperties(prop); @@ -174,6 +205,8 @@ int ClientObjectRef::l_get_hp(lua_State *L) { ClientObjectRef *ref = checkobject(L, 1); GenericCAO *gcao = get_generic_cao(ref, L); + if (! gcao) + return 0; lua_pushnumber(L, gcao->getHp()); return 1; } @@ -182,6 +215,8 @@ int ClientObjectRef::l_punch(lua_State *L) { ClientObjectRef *ref = checkobject(L, 1); GenericCAO *gcao = get_generic_cao(ref, L); + if (! gcao) + return 0; PointedThing pointed(gcao->getId(), v3f(0, 0, 0), v3s16(0, 0, 0), 0); getClient(L)->interact(INTERACT_START_DIGGING, pointed); return 0; @@ -191,6 +226,8 @@ int ClientObjectRef::l_rightclick(lua_State *L) { ClientObjectRef *ref = checkobject(L, 1); GenericCAO *gcao = get_generic_cao(ref, L); + if (! gcao) + return 0; PointedThing pointed(gcao->getId(), v3f(0, 0, 0), v3s16(0, 0, 0), 0); getClient(L)->interact(INTERACT_PLACE, pointed); return 0; @@ -200,6 +237,8 @@ int ClientObjectRef::l_remove(lua_State *L) { ClientObjectRef *ref = checkobject(L, 1); ClientActiveObject *cao = get_cao(ref); + if (! cao) + return 0; getClient(L)->getEnv().removeActiveObject(cao->getId()); return 0; @@ -209,6 +248,8 @@ int ClientObjectRef::l_set_nametag_images(lua_State *L) { ClientObjectRef *ref = checkobject(L, 1); GenericCAO *gcao = get_generic_cao(ref, L); + if (! gcao) + return 0; gcao->nametag_images.clear(); if(lua_istable(L, 2)){ lua_pushnil(L); @@ -228,12 +269,10 @@ ClientObjectRef::ClientObjectRef(ClientActiveObject *object) : m_object(object) void ClientObjectRef::create(lua_State *L, ClientActiveObject *object) { - if (object) { - ClientObjectRef *o = new ClientObjectRef(object); - *(void **)(lua_newuserdata(L, sizeof(void *))) = o; - luaL_getmetatable(L, className); - lua_setmetatable(L, -2); - } + ClientObjectRef *o = new ClientObjectRef(object); + *(void **)(lua_newuserdata(L, sizeof(void *))) = o; + luaL_getmetatable(L, className); + lua_setmetatable(L, -2); } void ClientObjectRef::create(lua_State *L, s16 id) @@ -241,6 +280,12 @@ void ClientObjectRef::create(lua_State *L, s16 id) create(L, ((ClientEnvironment *)getEnv(L))->getActiveObject(id)); } +void ClientObjectRef::set_null(lua_State *L) +{ + ClientObjectRef *obj = checkobject(L, -1); + obj->m_object = nullptr; +} + int ClientObjectRef::gc_object(lua_State *L) { ClientObjectRef *obj = *(ClientObjectRef **)(lua_touserdata(L, 1)); diff --git a/src/script/lua_api/l_clientobject.h b/src/script/lua_api/l_clientobject.h index 60d10dcf6..c4c95cb41 100644 --- a/src/script/lua_api/l_clientobject.h +++ b/src/script/lua_api/l_clientobject.h @@ -35,6 +35,8 @@ public: static void create(lua_State *L, ClientActiveObject *object); static void create(lua_State *L, s16 id); + static void set_null(lua_State *L); + static ClientObjectRef *checkobject(lua_State *L, int narg); private: diff --git a/src/script/lua_api/l_localplayer.cpp b/src/script/lua_api/l_localplayer.cpp index 747657016..b8673379a 100644 --- a/src/script/lua_api/l_localplayer.cpp +++ b/src/script/lua_api/l_localplayer.cpp @@ -483,7 +483,7 @@ int LuaLocalPlayer::l_get_object(lua_State *L) ClientEnvironment &env = getClient(L)->getEnv(); ClientActiveObject *obj = env.getGenericCAO(player->getCAO()->getId()); - ClientObjectRef::create(L, obj); + push_objectRef(L, obj->getId()); return 1; } diff --git a/src/serverenvironment.cpp b/src/serverenvironment.cpp index 3d9ba132b..cd5ac0753 100644 --- a/src/serverenvironment.cpp +++ b/src/serverenvironment.cpp @@ -1170,7 +1170,7 @@ void ServerEnvironment::clearObjects(ClearObjectsMode mode) // Tell the object about removal obj->removingFromEnvironment(); // Deregister in scripting api - m_script->removeObjectReference(obj); + m_script->removeObjectReference(dynamic_cast(obj)); // Delete active object if (obj->environmentDeletes()) @@ -1736,7 +1736,7 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object, } // Register reference in scripting api (must be done before post-init) - m_script->addObjectReference(object); + m_script->addObjectReference(dynamic_cast(object)); // Post-initialize object object->addedToEnvironment(dtime_s); @@ -1826,7 +1826,7 @@ void ServerEnvironment::removeRemovedObjects() // Tell the object about removal obj->removingFromEnvironment(); // Deregister in scripting api - m_script->removeObjectReference(obj); + m_script->removeObjectReference(dynamic_cast(obj)); // Delete if (obj->environmentDeletes()) @@ -2091,7 +2091,7 @@ void ServerEnvironment::deactivateFarObjects(bool _force_delete) // Tell the object about removal obj->removingFromEnvironment(); // Deregister in scripting api - m_script->removeObjectReference(obj); + m_script->removeObjectReference(dynamic_cast(obj)); // Delete active object if (obj->environmentDeletes()) -- cgit v1.2.3