diff --git a/init.lua b/init.lua index dc57adb..f7ee7bb 100755 --- a/init.lua +++ b/init.lua @@ -97,17 +97,41 @@ end -- TODO recheck if player leaving the server is not crashing it +local function try_to_pickup(player, pointed_thing) + -- TODO check if we can pick up more item + -- TODO if can't pick up any more items, then maybe move the item entity a bit? + local item = pointed_thing.ref:get_luaentity() + if item and item.on_punch then -- TODO probaly don't need this check + minetest.sound_play("dvornik_pickup", { + to_player = player:get_player_name() + --pos = player:get_pos(), + --max_hear_distance = 10 + }) + minetest.add_particle({ + pos = pointed_thing.ref:get_pos(), + expirationtime = 1, + size = 1, + texture = "tnt_smoke.png" -- TODO + }) + item:on_punch(player) + end +end + + local RANGE = 3.0 --local RADIUS = 1.0 local function trace_and_pickup(player) local p_eye_pos = player_get_eye_pos(player) + local prev_point = active_veniks[player] local to = vector.add(p_eye_pos, vector.multiply(player:get_look_dir(), RANGE)) local ray = minetest.raycast( p_eye_pos, to, true, -- point to objects false) -- point to liquids + -- First trace: find what player is looking at local pointed_thing = ray:next() + local current_point = nil while pointed_thing do if DEBUG and pointed_thing.type ~= "nothing" and not (pointed_thing.type == "object" and pointed_thing.ref == player) then local point = pointed_thing.intersection_point @@ -119,31 +143,51 @@ local function trace_and_pickup(player) -- for _, obj in pairs(minetest.get_objects_inside_radius(point, RADIUS)) do -- obj:remove() -- end - local item = pointed_thing.ref:get_luaentity() - -- TODO check if we can pick up more item - -- TODO if can't pick up any more items, then maybe move the item entity a bit? - if item.on_punch then -- TODO probaly don't need this check - minetest.sound_play("dvornik_pickup", { - to_player = player:get_player_name() - --pos = player:get_pos(), - --max_hear_distance = 10 - }) - minetest.add_particle({ - pos = pointed_thing.ref:get_pos(), - expirationtime = 1, - size = 1, - texture = "tnt_smoke.png" -- TODO - - }) - item:on_punch(player) - end + + -- Player is looking at an item: use the item position + current_point = pointed_thing.ref:get_pos() + break end + elseif pointed_thing.type == "node" then + -- move intersection point a little bit away from the block + local HEIGHT = 0.2 + -- Player is looking at a block: move a little bit away from it + current_point = vector.multiply( + vector.add(pointed_thing.intersection_point, + pointed_thing.intersection_normal), + HEIGHT) + break end pointed_thing = ray:next() end + + -- Second trace: trace from old previous position to current + if not prev_point then + prev_point = p_eye_pos + end + -- TODO maybe limit the distance between prev/current points? + if prev_point and prev_point.x and current_point and current_point.x then + local ray = minetest.raycast(prev_point, + current_point, + true, + false) + local pointed_thing = ray:next() + while pointed_thing do + if pointed_thing.type == "object" then + if pointed_thing.ref ~= player then + -- Just pick up everything that was between + -- previous and current points + try_to_pickup(player, pointed_thing) + end + end + pointed_thing = ray:next() + end + end + -- store the point for next timestep + active_veniks[player] = current_point end -local timer = 0 + minetest.register_globalstep(function(_dtime) for player, _ in pairs(active_veniks) do trace_and_pickup(player) @@ -151,6 +195,7 @@ minetest.register_globalstep(function(_dtime) end ) + minetest.register_on_leaveplayer(function(player, timed_out) deactivate_venik(player) end)