summaryrefslogtreecommitdiff
path: root/worldedit/visualization.lua
blob: 8e27c2733dc856e50fe7d6884a3d1ae378c655d2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
worldedit = worldedit or {}

--modifies positions `pos1` and `pos2` so that each component of `pos1` is less than or equal to its corresponding conent of `pos2`, returning two new positions
worldedit.sort_pos = function(pos1, pos2)
	pos1 = {x=pos1.x, y=pos1.y, z=pos1.z}
	pos2 = {x=pos2.x, y=pos2.y, z=pos2.z}
	if pos1.x > pos2.x then
		pos2.x, pos1.x = pos1.x, pos2.x
	end
	if pos1.y > pos2.y then
		pos2.y, pos1.y = pos1.y, pos2.y
	end
	if pos1.z > pos2.z then
		pos2.z, pos1.z = pos1.z, pos2.z
	end
	return pos1, pos2
end

--determines the volume of the region defined by positions `pos1` and `pos2`, returning the volume
worldedit.volume = function(pos1, pos2)
	local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
	return (pos2.x - pos1.x + 1) * (pos2.y - pos1.y + 1) * (pos2.z - pos1.z + 1)
end

minetest.register_node("worldedit:placeholder", {
	drawtype = "airlike",
	paramtype = "light",
	sunlight_propagates = true,
	diggable = false,
	groups = {not_in_creative_inventory=1},
})

--hides all nodes in a region defined by positions `pos1` and `pos2` by non-destructively replacing them with invisible nodes, returning the number of nodes hidden
worldedit.hide = function(pos1, pos2, tenv)
	local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
	if env == nil then env = minetest.env end

	local pos = {x=pos1.x, y=0, z=0}
	local placeholder = {name="worldedit:placeholder", param1=0, param2=0}
	while pos.x <= pos2.x do
		pos.y = pos1.y
		while pos.y <= pos2.y do
			pos.z = pos1.z
			while pos.z <= pos2.z do
				local node = env:get_node(pos)
				placeholder.param1, placeholder.param2 = node.param1, node.param2 --copy node's param1 and param2
				local data = env:get_meta(pos):to_table() --obtain metadata of original node
				env:add_node(pos, placeholder) --add placeholder node
				local meta = env:get_meta(pos) --obtain placeholder meta
				meta:from_table(data) --set placeholder metadata to the original node's metadata
				meta:set_string("worldedit_placeholder", node.name)  --add the node's name
				pos.z = pos.z + 1
			end
			pos.y = pos.y + 1
		end
		pos.x = pos.x + 1
	end
	return worldedit.volume(pos1, pos2)
end

--suppresses all instances of `nodename` in a region defined by positions `pos1` and `pos2` by non-destructively replacing them with invisible nodes, returning the number of nodes suppressed
worldedit.suppress = function(pos1, pos2, nodename, tenv)
	local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
	if env == nil then env = minetest.env end

	local placeholder = {name="worldedit:placeholder", param1=0, param2=0}
	local nodes = minetest.find_nodes_in_area(pos1, pos2, nodename)
	for _, pos in ipairs(nodes) do
		local node = env:get_node(pos)
		placeholder.param1, placeholder.param2 = node.param1, node.param2 --copy node's param1 and param2
		local data = env:get_meta(pos):to_table() --obtain metadata of original node
		env:add_node(pos, placeholder) --add placeholder node
		local meta = env:get_meta(pos) --obtain placeholder meta
		meta:from_table(data) --set placeholder metadata to the original node's metadata
		meta:set_string("worldedit_placeholder", nodename)  --add the node's name
	end
	return #nodes
end

--highlights all instances of `nodename` in a region defined by positions `pos1` and `pos2` by non-destructively hiding all other nodes, returning the number of nodes found
worldedit.highlight = function(pos1, pos2, nodename, tenv)
	local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
	if env == nil then env = minetest.env end

	if minetest.registered_nodes[nodename] == nil then
		nodename = "default:" .. nodename
	end

	local pos = {x=pos1.x, y=0, z=0}
	local placeholder = {name="worldedit:placeholder", param1=0, param2=0}
	local count = 0
	while pos.x <= pos2.x do --wip: see if this can be sped up like worldedit.suppress, except with hashed found node positions and testing against the set
		pos.y = pos1.y
		while pos.y <= pos2.y do
			pos.z = pos1.z
			while pos.z <= pos2.z do
				local node = env:get_node(pos)
				if node.name == nodename then --node found
					count = count + 1
				else --hide other nodes
					placeholder.param1, placeholder.param2 = node.param1, node.param2 --copy node's param1 and param2
					local data = env:get_meta(pos):to_table() --obtain metadata of original node
					env:add_node(pos, placeholder) --add placeholder node
					local meta = env:get_meta(pos) --obtain placeholder meta
					meta:from_table(data) --set placeholder metadata to the original node's metadata
					meta:set_string("worldedit_placeholder", node.name)  --add the node's name
				end
				pos.z = pos.z + 1
			end
			pos.y = pos.y + 1
		end
		pos.x = pos.x + 1
	end
	return count
end

--restores all nodes hidden with WorldEdit functions in a region defined by positions `pos1` and `pos2`, returning the number of nodes restored
worldedit.restore = function(pos1, pos2, tenv)
	local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
	if env == nil then env = minetest.env end

	local node = {name="", param1=0, param2=0}
	local nodes = minetest.find_nodes_in_area(pos1, pos2, nodename)
	for _, pos in ipairs(nodes) do
		local currentnode = env:get_node(pos)
		node.param1, node.param2 = currentnode.param1, currentnode.param2 --copy node's param1 and param2
		local data = env:get_meta(pos):to_table() --obtain node metadata
		node.name = data.fields.worldedit_placeholder --set node name
		data.fields.worldedit_placeholder = nil --delete old nodename
		env:add_node(pos, placeholder) --add original node
		env:get_meta(pos):from_table(data) --set original node metadata
	end
	return #nodes
end