mirror of
https://github.com/sbrl/Minetest-WorldEditAdditions.git
synced 2024-11-27 09:33:52 +01:00
Finish farwand implementation
This commit is contained in:
parent
6f20b31763
commit
fbf2b894e5
@ -7,3 +7,9 @@ end
|
|||||||
function worldeditadditions.vector.lengthsquared(v)
|
function worldeditadditions.vector.lengthsquared(v)
|
||||||
return v.x*v.x + v.y*v.y + v.z*v.z
|
return v.x*v.x + v.y*v.y + v.z*v.z
|
||||||
end
|
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
|
||||||
|
@ -65,10 +65,14 @@ end
|
|||||||
-- @param id number The content/node id to check.
|
-- @param id number The content/node id to check.
|
||||||
-- @return bool Whether the given node/content id is a liquid-ish node or not.
|
-- @return bool Whether the given node/content id is a liquid-ish node or not.
|
||||||
function worldeditadditions.is_liquidlike(id)
|
function worldeditadditions.is_liquidlike(id)
|
||||||
|
print("[is_liquidlike]")
|
||||||
if id == node_id_ignore then return false end
|
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 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
|
-- If it's not none, then it has to be a liquid as the only other values are source and flowing
|
||||||
|
@ -14,32 +14,53 @@ function worldeditadditions.raycast(player, maxdist, skip_liquid)
|
|||||||
local player_pos = player:getpos()
|
local player_pos = player:getpos()
|
||||||
player_pos.y = player_pos.y + 1.5 -- Calculate from the eye position
|
player_pos.y = player_pos.y + 1.5 -- Calculate from the eye position
|
||||||
|
|
||||||
|
local divisor = 5
|
||||||
for i = 1, maxdist do
|
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.x = (look_dir.x*j) + player_pos.x
|
||||||
cur_pos.y = (look_dir.y*j) + player_pos.y
|
cur_pos.y = (look_dir.y*j) + player_pos.y
|
||||||
cur_pos.z = (look_dir.z*j) + player_pos.z
|
cur_pos.z = (look_dir.z*j) + player_pos.z
|
||||||
|
|
||||||
local found_node = false
|
|
||||||
|
|
||||||
local node = minetest.get_node_or_nil(cur_pos)
|
local node_pos = {
|
||||||
if node ~= nil then
|
x = math.floor(0.5+cur_pos.x),
|
||||||
local node_id = minetest.get_content_id(node.name)
|
y = math.floor(0.5+cur_pos.y),
|
||||||
local is_air = worldeditadditions.is_airlike(node_id)
|
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
|
local found_node = false
|
||||||
if node_id == node_id_ignore then
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
if is_air == false then
|
local node = minetest.get_node_or_nil(node_pos)
|
||||||
if skip_liquid == true then
|
if node ~= nil then
|
||||||
return cur_pos, node_id
|
local node_id = minetest.get_content_id(node.name)
|
||||||
elseif worldeditadditions.is_liquidlike(node_id) == true then
|
local is_air = worldeditadditions.is_airlike(node_id)
|
||||||
return cur_pos, 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
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1,3 +1,9 @@
|
|||||||
|
worldeditadditions.farwand = {
|
||||||
|
player_data = {}
|
||||||
|
}
|
||||||
|
|
||||||
local modpath = minetest.get_modpath("worldeditadditions_farwand")
|
local modpath = minetest.get_modpath("worldeditadditions_farwand")
|
||||||
|
|
||||||
dofile(modpath.."/lib/farwand.lua")
|
dofile(modpath.."/lib/farwand.lua")
|
||||||
|
dofile(modpath.."/lib/chatcommand.lua")
|
||||||
|
dofile(modpath.."/lib/settings.lua")
|
||||||
|
61
worldeditadditions_farwand/lib/chatcommand.lua
Normal file
61
worldeditadditions_farwand/lib/chatcommand.lua
Normal file
@ -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 <number>",
|
||||||
|
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
|
||||||
|
})
|
@ -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", {
|
minetest.register_tool(":worldeditadditions:farwand", {
|
||||||
description = "WorldEditAdditions far-reaching wand",
|
description = "WorldEditAdditions far-reaching wand",
|
||||||
inventory_image = "worldeditadditions_farwand.png",
|
inventory_image = "worldeditadditions_farwand.png",
|
||||||
|
|
||||||
on_place = function(itemstack, player, pointed_thing)
|
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
|
-- 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,
|
end,
|
||||||
|
|
||||||
on_use = function(itemstack, player, pointed_thing)
|
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
|
-- Left click when pointing at something or nothing
|
||||||
end,
|
end,
|
||||||
|
|
||||||
on_secondary_use = function(itemstack, player, pointed_thing)
|
on_secondary_use = function(itemstack, player, pointed_thing)
|
||||||
|
local name = player:get_player_name()
|
||||||
-- Right click when pointing at nothing
|
-- 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
|
end
|
||||||
})
|
})
|
||||||
|
33
worldeditadditions_farwand/lib/settings.lua
Normal file
33
worldeditadditions_farwand/lib/settings.lua
Normal file
@ -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
|
Loading…
Reference in New Issue
Block a user