mirror of
				https://github.com/sbrl/Minetest-WorldEditAdditions
				synced 2025-11-04 05:53:07 +01:00 
			
		
		
		
	Finish farwand implementation
This commit is contained in:
		
							parent
							
								
									6f20b31763
								
							
						
					
					
						commit
						fbf2b894e5
					
				@ -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
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
	
 | 
			
		||||
 | 
			
		||||
@ -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")
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										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", {
 | 
			
		||||
	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
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										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