diff --git a/builtin/builtin.lua b/builtin/builtin.lua index bf9fdc1e5..10acd0f52 100644 --- a/builtin/builtin.lua +++ b/builtin/builtin.lua @@ -13,6 +13,7 @@ math.randomseed(os.time()) dofile(minetest.get_modpath("__builtin").."/misc_helpers.lua") dofile(minetest.get_modpath("__builtin").."/item.lua") dofile(minetest.get_modpath("__builtin").."/misc_register.lua") +dofile(minetest.get_modpath("__builtin").."/item_entity.lua") dofile(minetest.get_modpath("__builtin").."/deprecated.lua") dofile(minetest.get_modpath("__builtin").."/misc.lua") dofile(minetest.get_modpath("__builtin").."/privileges.lua") diff --git a/builtin/item.lua b/builtin/item.lua index 3abf30a6d..678a5cdac 100644 --- a/builtin/item.lua +++ b/builtin/item.lua @@ -192,7 +192,17 @@ function minetest.item_place(itemstack, placer, pointed_thing) end function minetest.item_drop(itemstack, dropper, pos) - minetest.env:add_item(pos, itemstack) + if dropper.get_player_name then + local v = dropper:get_look_dir() + local p = {x=pos.x+v.x, y=pos.y+1.5+v.y, z=pos.z+v.z} + local obj = minetest.env:add_item(p, itemstack) + v.x = v.x*2 + v.y = v.y*2 + 1 + v.z = v.z*2 + obj:setvelocity(v) + else + minetest.env:add_item(pos, itemstack) + end return "" end @@ -377,4 +387,3 @@ minetest.noneitemdef_default = { -- This is used for the hand and unknown items on_use = nil, } - diff --git a/builtin/item_entity.lua b/builtin/item_entity.lua new file mode 100644 index 000000000..8468ebedf --- /dev/null +++ b/builtin/item_entity.lua @@ -0,0 +1,90 @@ +-- Minetest: builtin/item_entity.lua + +function minetest.spawn_item(pos, item) + -- Take item in any format + local stack = ItemStack(item) + local obj = minetest.env:add_entity(pos, "__builtin:item") + obj:get_luaentity():set_item(stack:to_string()) + return obj +end + +minetest.register_entity("__builtin:item", { + initial_properties = { + hp_max = 1, + physical = true, + collisionbox = {-0.25,-0.25,-0.25, 0.25,0.25,0.25}, + visual = "sprite", + visual_size = {x=0.5, y=0.5}, + textures = {""}, + spritediv = {x=1, y=1}, + initial_sprite_basepos = {x=0, y=0}, + is_visible = false, + }, + + itemstring = '', + physical_state = true, + + set_item = function(self, itemstring) + self.itemstring = itemstring + local stack = ItemStack(itemstring) + local itemtable = stack:to_table() + local itemname = nil + if itemtable then + itemname = stack:to_table().name + end + local item_texture = nil + if minetest.registered_items[itemname] then + item_texture = minetest.registered_items[itemname].inventory_image + end + item_texture = item_texture or "unknown_item.png" + self.object:set_properties({ + textures = {item_texture}, + is_visible = true, + }) + end, + + get_staticdata = function(self) + return self.itemstring + end, + + on_activate = function(self, staticdata) + self.itemstring = staticdata + self.object:set_armor_groups({immortal=1}) + self.object:setvelocity({x=0, y=2, z=0}) + self.object:setacceleration({x=0, y=-10, z=0}) + self:set_item(self.itemstring) + end, + + on_step = function(self, dtime) + local p = self.object:getpos() + p.y = p.y - 0.3 + local nn = minetest.env:get_node(p).name + if minetest.registered_nodes[nn].walkable then + if self.physical_state then + self.object:setvelocity({x=0,y=0,z=0}) + self.object:setacceleration({x=0, y=0, z=0}) + self.physical_state = false + self.object:set_properties({ + physical = false + }) + end + else + if not self.physical_state then + self.object:setvelocity({x=0,y=0,z=0}) + self.object:setacceleration({x=0, y=-10, z=0}) + self.physical_state = true + self.object:set_properties({ + physical = true + }) + end + end + end, + + on_punch = function(self, hitter) + if self.itemstring ~= '' then + hitter:get_inventory():add_item("main", self.itemstring) + end + self.object:remove() + end, +}) + diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 798ea607c..36c004fa3 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -637,15 +637,18 @@ methods: ^ Returns nil for unloaded area - get_node_light(pos, timeofday) -> 0...15 or nil ^ timeofday: nil = current time, 0 = night, 0.5 = day -- add_entity(pos, name): Returns ObjectRef or nil if failed -- add_item(pos, itemstring) -- add_rat(pos) -- add_firefly(pos) +- add_entity(pos, name): Spawn Lua-defined entity at position + ^ Returns ObjectRef, or nil if failed +- add_item(pos, itemstring): Spawn item + ^ Returns ObjectRef, or nil if failed - get_meta(pos) -- Get a NodeMetaRef at that position - get_player_by_name(name) -- Get an ObjectRef to a player - get_objects_inside_radius(pos, radius) - set_timeofday(val): val: 0...1; 0 = midnight, 0.5 = midday - get_timeofday() +Deprecated: +- add_rat(pos): Add C++ rat object (no-op) +- add_firefly(pos): Add C++ firefly object (no-op) NodeMetaRef (this stuff is subject to change in a future version) methods: diff --git a/src/content_cao.cpp b/src/content_cao.cpp index 2a9c8a91a..1241e0002 100644 --- a/src/content_cao.cpp +++ b/src/content_cao.cpp @@ -1068,6 +1068,11 @@ public: bool do_interpolate = readU8(is); bool is_end_position = readU8(is); float update_interval = readF1000(is); + + // Place us a bit higher if we're physical, to not sink into + // the ground due to sucky collision detection... + if(m_prop.physical) + m_position += v3f(0,0.002,0); if(do_interpolate){ if(!m_prop.physical) diff --git a/src/scriptapi.cpp b/src/scriptapi.cpp index f8fca00c7..a45c27de6 100644 --- a/src/scriptapi.cpp +++ b/src/scriptapi.cpp @@ -3042,7 +3042,21 @@ private: ItemStack item = read_item(L, 3); if(item.empty() || !item.isKnown(get_server(L)->idef())) return 0; - // Do it + // 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) @@ -3050,7 +3064,7 @@ private: return 0; // Return ObjectRef objectref_get_or_create(L, obj); - return 1; + return 1;*/ } // EnvRef:add_rat(pos)