From fbf2b894e5462846592df66c299baf3ba4a05ae6 Mon Sep 17 00:00:00 2001 From: Starbeamrainbowlabs Date: Sat, 13 Jun 2020 14:23:14 +0100 Subject: [PATCH] Finish farwand implementation --- worldeditadditions/utils.lua | 6 ++ worldeditadditions/utils/nodes.lua | 8 ++- worldeditadditions/utils/raycast_adv.lua | 51 +++++++++++----- worldeditadditions_farwand/init.lua | 6 ++ .../lib/chatcommand.lua | 61 +++++++++++++++++++ worldeditadditions_farwand/lib/farwand.lua | 51 +++++++++++++++- worldeditadditions_farwand/lib/settings.lua | 33 ++++++++++ 7 files changed, 196 insertions(+), 20 deletions(-) create mode 100644 worldeditadditions_farwand/lib/chatcommand.lua create mode 100644 worldeditadditions_farwand/lib/settings.lua diff --git a/worldeditadditions/utils.lua b/worldeditadditions/utils.lua index d894361..375c3b1 100644 --- a/worldeditadditions/utils.lua +++ b/worldeditadditions/utils.lua @@ -7,3 +7,9 @@ end function worldeditadditions.vector.lengthsquared(v) return v.x*v.x + v.y*v.y + v.z*v.z end + +function worldeditadditions.vector.floor(v) + v.x = math.floor(v.x) + v.y = math.floor(v.y) + v.z = math.floor(v.z) +end diff --git a/worldeditadditions/utils/nodes.lua b/worldeditadditions/utils/nodes.lua index 3161697..e15d7e3 100644 --- a/worldeditadditions/utils/nodes.lua +++ b/worldeditadditions/utils/nodes.lua @@ -65,10 +65,14 @@ end -- @param id number The content/node id to check. -- @return bool Whether the given node/content id is a liquid-ish node or not. function worldeditadditions.is_liquidlike(id) + print("[is_liquidlike]") if id == node_id_ignore then return false end - if not minetest.registered_nodes[id] then return false end - local liquidtype = minetest.registered_nodes[id].liquidtype + local node_name = minetest.get_name_from_content_id(id) + if node_name == nil or not minetest.registered_nodes[node_name] then return false end + + local liquidtype = minetest.registered_nodes[node_name].liquidtype + print("[is_liquidlike]", "id", id, "liquidtype", liquidtype) if liquidtype == nil or liquidtype == "none" then return false end -- If it's not none, then it has to be a liquid as the only other values are source and flowing diff --git a/worldeditadditions/utils/raycast_adv.lua b/worldeditadditions/utils/raycast_adv.lua index 575112f..edbeb91 100644 --- a/worldeditadditions/utils/raycast_adv.lua +++ b/worldeditadditions/utils/raycast_adv.lua @@ -14,32 +14,53 @@ function worldeditadditions.raycast(player, maxdist, skip_liquid) local player_pos = player:getpos() player_pos.y = player_pos.y + 1.5 -- Calculate from the eye position + local divisor = 5 for i = 1, maxdist do - local j = i / 10 + local j = i / divisor cur_pos.x = (look_dir.x*j) + player_pos.x cur_pos.y = (look_dir.y*j) + player_pos.y cur_pos.z = (look_dir.z*j) + player_pos.z - local found_node = false - local node = minetest.get_node_or_nil(cur_pos) - if node ~= nil then - local node_id = minetest.get_content_id(node.name) - local is_air = worldeditadditions.is_airlike(node_id) + local node_pos = { + x = math.floor(0.5+cur_pos.x), + y = math.floor(0.5+cur_pos.y), + z = math.floor(0.5+cur_pos.z) + } + + -- Don't bother if this is the same position we were looking at before + if not (node_pos.x == math.floor(0.5+look_dir.x*(j-divisor)) + and node_pos.y == math.floor(0.5+look_dir.y*(j-divisor)) + and node_pos.z == math.floor(0.5+look_dir.z*(j-divisor))) then - -- ignore = unloaded chunks, as far as I can tell - if node_id == node_id_ignore then - return nil - end + local found_node = false - if is_air == false then - if skip_liquid == true then - return cur_pos, node_id - elseif worldeditadditions.is_liquidlike(node_id) == true then - return cur_pos, node_id + local node = minetest.get_node_or_nil(node_pos) + if node ~= nil then + local node_id = minetest.get_content_id(node.name) + local is_air = worldeditadditions.is_airlike(node_id) + print("[raycast] Scanning "..worldeditadditions.vector.tostring(cur_pos)..", i: "..i..", j: "..j..", found", node.name, "is_air", is_air) + + -- ignore = unloaded chunks, as far as I can tell + if node_id == node_id_ignore then + print("[raycast] found ignore, returning nil") + return nil + end + + if is_air == false then + if skip_liquid == false then + return node_pos, node_id + else + local is_liquid = worldeditadditions.is_liquidlike(node_id) + print("[raycast] is_liquid ", is_liquid) + if is_liquid == false then + return node_pos, node_id + end + end end end + end end diff --git a/worldeditadditions_farwand/init.lua b/worldeditadditions_farwand/init.lua index 91723bc..26cc902 100644 --- a/worldeditadditions_farwand/init.lua +++ b/worldeditadditions_farwand/init.lua @@ -1,3 +1,9 @@ +worldeditadditions.farwand = { + player_data = {} +} + local modpath = minetest.get_modpath("worldeditadditions_farwand") dofile(modpath.."/lib/farwand.lua") +dofile(modpath.."/lib/chatcommand.lua") +dofile(modpath.."/lib/settings.lua") diff --git a/worldeditadditions_farwand/lib/chatcommand.lua b/worldeditadditions_farwand/lib/chatcommand.lua new file mode 100644 index 0000000..65a8c7b --- /dev/null +++ b/worldeditadditions_farwand/lib/chatcommand.lua @@ -0,0 +1,61 @@ +local farwand = worldeditadditions.farwand -- Convenience shurtcut + +local function parse_params_farwand(params_text) + if params_text == nil then + return false, "Can't parse nil value" + end + local parts = worldeditadditions.split(params_text, "%s+", false) + + local key = nil + local value = nil + + if #parts >= 1 then + key = parts[1] + end + if #parts >= 2 then + value = parts[2] + end + + return true, key, value +end + +minetest.register_chatcommand("/farwand", { + params = "skip_liquid (true|false) | maxdist ", + description = "Configures your worldeditadditions farwand tool on a per-player basis. skip_liquid configures whether liquids will be skipped when raycasting. maxdist configues the maximum distance to raycast looking for a suitable node (default: 1000, but while higher values mean that it will search further, it's not an exact number of nodes that will be searched)", + privs = { worldedit = true }, + func = function(name, params_text) + if name == nil then return end + local success, key, value = parse_params_farwand(params_text) + print("[/farwand] ", success, key, value) + if success == false then + worldedit.player_notify(name, key) + return + end + + if key == "" then + worldedit.player_notify(name, "Current settings:\n" + .."\tskip_liquid\t"..tostring(farwand.setting_get(name, "skip_liquid")).."\n" + .."\tmaxdist\t"..tostring(farwand.setting_get(name, "maxdist")).."\n" + ) + return + end + + if key == "skip_liquid" then + local skip_liquid = false + if value == "true" then skip_liquid = true end + farwand.setting_set(name, "skip_liquid", skip_liquid) + worldedit.player_notify(name, "Set skip_liquid to "..tostring(skip_liquid)..".") + elseif key == "maxdist" then + local maxdist = tonumber(value) + if maxdist == nil then + worldedit.player_notify(name, "Invalid maxdist '"..value.."' (expected number).") + return + end + farwand.setting_set(name, "maxdist", maxdist) + worldedit.player_notify(name, "Set maxdist to "..tostring(maxdist)..".") + else + worldedit.player_notify(name, "Unknown key '"..key.."' (valid values: skip_liquid, maxdist).") + return + end + end +}) diff --git a/worldeditadditions_farwand/lib/farwand.lua b/worldeditadditions_farwand/lib/farwand.lua index 85db6cf..66fe2c0 100644 --- a/worldeditadditions_farwand/lib/farwand.lua +++ b/worldeditadditions_farwand/lib/farwand.lua @@ -1,20 +1,65 @@ +local function set_pos1(name, pos) + if pos ~= nil then + print("[set_pos1]", name, "("..pos.x..", "..pos.y..", "..pos.z..")") + worldedit.pos1[name] = pos + worldedit.mark_pos1(name) + else + print("[set_pos1]", name, "nil") + end +end +local function set_pos2(name, pos) + if pos ~= nil then + print("[set_pos2]", name, "("..pos.x..", "..pos.y..", "..pos.z..")") + worldedit.pos2[name] = pos + worldedit.mark_pos2(name) + else + print("[set_pos2]", name, "nil") + end +end + +local function do_raycast(player) + if player == nil then return nil end + local player_name = player:get_player_name() + + if worldeditadditions.farwand.player_data[player_name] == nil then + worldeditadditions.farwand.player_data[player_name] = { maxdist = 1000, skip_liquid = true } + end + + local looking_pos, node_id = worldeditadditions.raycast( + player, + worldeditadditions.farwand.player_data[player_name].maxdist, + worldeditadditions.farwand.player_data[player_name].skip_liquid + ) + return looking_pos, node_id +end + minetest.register_tool(":worldeditadditions:farwand", { description = "WorldEditAdditions far-reaching wand", inventory_image = "worldeditadditions_farwand.png", on_place = function(itemstack, player, pointed_thing) - print("[farwand] on_place", player:get_player_name()) + local name = player:get_player_name() + print("[farwand] on_place", name) -- Right click when pointing at something + -- Pointed thing: https://rubenwardy.com/minetest_modding_book/lua_api.html#pointed_thing + local looking_pos, node_id = do_raycast(player) + set_pos2(name, looking_pos) end, on_use = function(itemstack, player, pointed_thing) - print("[farwand] on_use", player:get_player_name()) + local name = player:get_player_name() + print("[farwand] on_use", name) + local looking_pos, node_id = do_raycast(player) + set_pos1(name, looking_pos) -- Left click when pointing at something or nothing end, on_secondary_use = function(itemstack, player, pointed_thing) + local name = player:get_player_name() -- Right click when pointing at nothing + print("[farwand] on_secondary_use", name) - print("[farwand] on_secondary_use", player:get_player_name()) + local looking_pos, node_id = do_raycast(player) + set_pos2(name, looking_pos) end }) diff --git a/worldeditadditions_farwand/lib/settings.lua b/worldeditadditions_farwand/lib/settings.lua new file mode 100644 index 0000000..1e89a48 --- /dev/null +++ b/worldeditadditions_farwand/lib/settings.lua @@ -0,0 +1,33 @@ +--- If the settings object for the given player name doesn't exist, it is created. +-- @param name The name of the player to ensure has a settings object. +local function settings_init(name) + if worldeditadditions.farwand.player_data[name] == nil then + print("[settings_init] ", worldeditadditions.farwand.player_data) + worldeditadditions.farwand.player_data[name] = { + maxdist = 1000, + skip_liquid = true + } + end +end + +--- Gets a given farwand setting for the given player name. +-- @param string name The name of the player to get the setting for. +-- @param string setting_name The name of the setting to fetch. +-- @return any The value of the setting. +function worldeditadditions.farwand.setting_get(name, setting_name) + if setting_name == nil then return nil end + settings_init(name) + return worldeditadditions.farwand.player_data[name][setting_name] +end + +--- Sets a given farwand setting for the given player name to the given value. +-- @param string name The name of the player to set the setting for. +-- @param string setting_name The name of the setting to set. +-- @param any setting_value The value to set the setting to. +-- @return bool Whether setting the setting was successful or not. +function worldeditadditions.farwand.setting_set(name, setting_name, setting_value) + if setting_name == nil then return false end + settings_init(name) + worldeditadditions.farwand.player_data[name][setting_name] = setting_value + return true +end