diff --git a/init.lua b/init.lua index 04cfcd9..39f8e81 100644 --- a/init.lua +++ b/init.lua @@ -1,4 +1,7 @@ local MODNAME = core.get_current_modname() +local MODPATH = core.get_modpath(MODNAME) + +local util = dofile(MODPATH .. DIR_DELIM .. "util.lua") local api = {} _G[MODNAME] = api @@ -8,21 +11,41 @@ api.e = {} local function create_shared_environment(player_name) - local me = core.get_player_by_name(player_name) local magic_keys = { me = function() return core.get_player_by_name(player_name) end, my_pos = function() - local pos = here + local me = core.get_player_by_name(player_name) + local pos = vector.zero() -- FIXME use last command position if me:is_player() then pos = me:get_pos() end return pos end, - this_obj = function() + point = function() + local me = core.get_player_by_name(player_name) + local pointed_thing = util.raycast_crosshair(me, 200, true, false) + if pointed_thing then + return pointed_thing.intersection_point + end + return me:get_pos() end, - this_node = function() + this_obj = function() + local me = core.get_player_by_name(player_name) + local pointed_thing = util.raycast_crosshair_to_object(me, 200) + if pointed_thing then + return pointed_thing.ref + end + return nil + end, + this_node_pos = function() + local me = core.get_player_by_name(player_name) + local pointed_thing = util.raycast_crosshair(me, 200, false, false) + if pointed_thing then + return pointed_thing.under + end + return vector.round(me:get_pos()) end, } diff --git a/util.lua b/util.lua new file mode 100644 index 0000000..71b9e37 --- /dev/null +++ b/util.lua @@ -0,0 +1,78 @@ + +-- get actual eye_pos of the player (including eye_offset) +local function player_get_eye_pos(player) + local p_pos = player:get_pos() + local p_eye_height = player:get_properties().eye_height + p_pos.y = p_pos.y + p_eye_height + local p_eye_pos = p_pos + local p_eye_offset = vector.multiply(player:get_eye_offset(), 0.1) + local yaw = player:get_look_horizontal() + p_eye_pos = vector.add(p_eye_pos, vector.rotate_around_axis(p_eye_offset, {x=0,y=1,z=0}, yaw)) + return p_eye_pos +end + + +-- return first thing player is pointing at +local function raycast_crosshair(player, range, point_to_objects, point_to_liquids) + local p_eye_pos = player_get_eye_pos(player) + local to = vector.add(p_eye_pos, vector.multiply(player:get_look_dir(), range)) + local ray = core.raycast(p_eye_pos, to, point_to_objects, point_to_liquids) + local pointed_thing = ray:next() + while pointed_thing do + if pointed_thing.type == "object" and pointed_thing.ref == player then + -- exclude the player themselves from the raycast + pointed_thing = ray:next() + else + return pointed_thing + end + end + -- FIXME return "nothing" pointed thing? + return nil +end + + +-- return first object +local function raycast_crosshair_to_object(player, range) + local p_eye_pos = player_get_eye_pos(player) + local to = vector.add(p_eye_pos, vector.multiply(player:get_look_dir(), range)) + local ray = core.raycast(p_eye_pos, to, point_to_objects, point_to_liquids) + local pointed_thing = ray:next() + while pointed_thing do + if pointed_thing.type == "object" then + if pointed_thing.ref ~= player then + return pointed_thing + end + end + pointed_thing = ray:next() + end + -- FIXME return "nothing" pointed thing? + return nil +end + + + + +-- get position and thing that player is pointing at or nil +local function get_pointed_position(player, range, point_to_objects, point_to_liquids) + local pointed_thing = raycast_crosshair(player, range, point_to_objects, point_to_liquids) + local pointed_pos = nil + if pointed_thing then + if pointed_thing.type == "node" then + -- middle between "above" and "under" + pointed_pos = vector.multiply(vector.add(pointed_thing.above, pointed_thing.under), 0.5) + elseif pointed_thing.type == "object" then + -- TODO point at the middle of collision box? (or not, ground may be better) + pointed_pos = pointed_thing.ref:get_pos() + end + end + return pointed_pos, pointed_thing +end + + +local util = { + player_get_eye_pos = player_get_eye_pos, + raycast_crosshair = raycast_crosshair, + raycast_crosshair_to_object = raycast_crosshair_to_object, + get_pointed_position = get_pointed_position, +} +return util