diff --git a/README.md b/README.md index 5771250..7136f76 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ By [PilzAdam](https://github.com/PilzAdam), [texmex](https://github.com/tacotexmex/), [hybriddog](https://github.com/hybriddog/). ## Description -This mod adds Minecraft like drop/pick up of items to Minetest. +A highly configurable mod providing item magnet and in-world node drops ## Licensing LGPLv2.1/CC BY-SA 3.0. Particle code from WCILA mod by Aurailus, originally licensed MIT. @@ -31,6 +31,8 @@ developed by [PilzAdam](https://github.com/PilzAdam/item_drop). items between these radii are flying to the player for `item_drop.magnet_time` seconds, after this time, they're picked or stop flying. + * Enable manual item pickups by mouse only if `item_drop.mouse_pickup` is + `true` (true by default) * Plays a sound when the items are picked up with the gain level set to `item_drop.pickup_sound_gain` (default 0.2) * Requires a key to be pressed in order to pick items if diff --git a/init.lua b/init.lua index 2f3318f..2e3f9eb 100644 --- a/init.lua +++ b/init.lua @@ -1,5 +1,27 @@ local load_time_start = minetest.get_us_time() -pickup_radius = tonumber(minetest.settings:get("item_pickup_radius")) + +-- Functions which can be overridden by mods +item_drop = { + -- This function is executed before picking up an item or making it fly to + -- the player. If it does not return true, the item is ignored. + -- It is also executed before collecting the item after it flew to + -- the player and did not reach him/her for magnet_time seconds. + can_pickup = function(entity, player) + if entity.item_drop_picked then + -- Ignore items where picking has already failed + return false + end + return true + end, + + -- before_collect and after_collect are executed before and after an item + -- is collected by a player + before_collect = function(entity, pos, player) + end, + after_collect = function(entity, pos, player) + entity.item_drop_picked = true + end, +} if minetest.settings:get_bool("item_drop.enable_item_pickup") ~= false and minetest.settings:get_bool("enable_item_pickup") ~= false then @@ -9,7 +31,8 @@ minetest.settings:get_bool("enable_item_pickup") ~= false then local pickup_particle = minetest.settings:get_bool("item_drop.pickup_particle") ~= false local pickup_radius = tonumber( - minetest.settings:get("item_drop.pickup_radius")) or 0.75 + minetest.settings:get("item_drop.pickup_radius")) or + tonumber(minetest.settings:get("item_pickup_radius")) or 0.75 local magnet_radius = tonumber( minetest.settings:get("item_drop.magnet_radius")) or -1 local magnet_time = tonumber( @@ -30,6 +53,11 @@ minetest.settings:get_bool("enable_item_pickup") ~= false then pickup_age = math.min(pickup_age, 0) end end + local mouse_pickup = minetest.settings:get_bool( + "item_drop.mouse_pickup") ~= false + if not mouse_pickup then + minetest.registered_entities["__builtin:item"].pointable = false + end local magnet_mode = magnet_radius > pickup_radius local zero_velocity_mode = pickup_age == -1 @@ -53,6 +81,7 @@ minetest.settings:get_bool("enable_item_pickup") ~= false then -- adds the item to the inventory and removes the object local function collect_item(ent, pos, player) + item_drop.before_collect(ent, pos, player) minetest.sound_play("item_drop_pickup", { pos = pos, gain = pickup_gain, @@ -94,6 +123,7 @@ minetest.settings:get_bool("enable_item_pickup") ~= false then end end ent:on_punch(player) + item_drop.after_collect(ent, pos, player) end -- opt_get_ent gets the object's luaentity if it can be collected @@ -139,7 +169,8 @@ minetest.settings:get_bool("enable_item_pickup") ~= false then end local item = ItemStack(ent.itemstring) if inv - and inv:room_for_item("main", item) then + and inv:room_for_item("main", item) + and can_pickup(ent, player) then collect_item(ent, object:get_pos(), player) else -- the acceleration will be reset by the object's on_step @@ -224,7 +255,8 @@ minetest.settings:get_bool("enable_item_pickup") ~= false then for i = 1,#objectlist do local object = objectlist[i] local ent = opt_get_ent(object) - if ent then + if ent + and item_drop.can_pickup(ent, player) then if not inv then inv = player:get_inventory() if not inv then @@ -242,10 +274,13 @@ minetest.settings:get_bool("enable_item_pickup") ~= false then flying_item = vector.distance(pos, pos2) > pickup_radius end if not flying_item then - -- collect one item at a time to avoid the loud pop + -- The item is near enough to pick it collect_item(ent, pos, player) + -- Collect one item at a time to avoid the loud pop return true end + -- The item is not too far a way but near enough to be + -- magnetised, make it fly to the player local vel = vector.multiply(vector.subtract(pos, pos2), 3) vel.y = vel.y + 0.6 object:set_velocity(vel) @@ -294,8 +329,9 @@ and not minetest.settings:get_bool("creative_mode") then name = item:get_name() end - if name == "" then - -- Sometimes nothing should be dropped + -- Sometimes nothing should be dropped + if name == "" + or not minetest.registered_nodes[name] then count = 0 end diff --git a/screenshot.png b/screenshot.png new file mode 100644 index 0000000..1313e40 Binary files /dev/null and b/screenshot.png differ diff --git a/settingtypes.txt b/settingtypes.txt index 0bf3684..4896788 100644 --- a/settingtypes.txt +++ b/settingtypes.txt @@ -33,3 +33,6 @@ item_drop.magnet_time (Magnet time) float 5.0 #Time delay in seconds after autopicking an item if it's dropped by a player item_drop.pickup_age (Pickup age) float 0.5 + +#Enable manual item pickups by mouse +item_drop.mouse_pickup (Mouse pickup) bool true