mirror of
https://github.com/sbrl/Minetest-WorldEditAdditions.git
synced 2024-11-26 09:03:01 +00:00
Add //count
This commit is contained in:
parent
f0dc2f5a3c
commit
f3a8c1dd64
8 changed files with 144 additions and 25 deletions
|
@ -6,15 +6,19 @@
|
||||||
-- @author Starbeamrainbowlabs
|
-- @author Starbeamrainbowlabs
|
||||||
|
|
||||||
worldeditadditions = {}
|
worldeditadditions = {}
|
||||||
|
worldeditadditions.modpath = minetest.get_modpath("worldeditadditions")
|
||||||
|
dofile(worldeditadditions.modpath.."/utils/strings.lua")
|
||||||
|
dofile(worldeditadditions.modpath.."/utils/numbers.lua")
|
||||||
|
|
||||||
dofile(minetest.get_modpath("worldeditadditions") .. "/utils.lua")
|
dofile(worldeditadditions.modpath.."/utils.lua")
|
||||||
dofile(minetest.get_modpath("worldeditadditions") .. "/lib/floodfill.lua")
|
dofile(worldeditadditions.modpath.."/lib/floodfill.lua")
|
||||||
dofile(minetest.get_modpath("worldeditadditions") .. "/lib/overlay.lua")
|
dofile(worldeditadditions.modpath.."/lib/overlay.lua")
|
||||||
dofile(minetest.get_modpath("worldeditadditions") .. "/lib/ellipsoid.lua")
|
dofile(worldeditadditions.modpath.."/lib/ellipsoid.lua")
|
||||||
dofile(minetest.get_modpath("worldeditadditions") .. "/lib/torus.lua")
|
dofile(worldeditadditions.modpath.."/lib/torus.lua")
|
||||||
dofile(minetest.get_modpath("worldeditadditions") .. "/lib/maze2d.lua")
|
dofile(worldeditadditions.modpath.."/lib/walls.lua")
|
||||||
dofile(minetest.get_modpath("worldeditadditions") .. "/lib/maze3d.lua")
|
dofile(worldeditadditions.modpath.."/lib/maze2d.lua")
|
||||||
|
dofile(worldeditadditions.modpath.."/lib/maze3d.lua")
|
||||||
|
|
||||||
dofile(minetest.get_modpath("worldeditadditions") .. "/lib/walls.lua")
|
dofile(worldeditadditions.modpath.."/lib/count.lua")
|
||||||
|
|
||||||
dofile(minetest.get_modpath("worldeditadditions") .. "/lib/bonemeal.lua")
|
dofile(worldeditadditions.modpath.."/lib/bonemeal.lua")
|
||||||
|
|
48
worldeditadditions/lib/count.lua
Normal file
48
worldeditadditions/lib/count.lua
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
--- Counts the nodes in a given area.
|
||||||
|
-- @module worldeditadditions.count
|
||||||
|
|
||||||
|
-- ██████ ██████ ██ ██ ███ ██ ████████
|
||||||
|
-- ██ ██ ██ ██ ██ ████ ██ ██
|
||||||
|
-- ██ ██ ██ ██ ██ ██ ██ ██ ██
|
||||||
|
-- ██ ██ ██ ██ ██ ██ ██ ██ ██
|
||||||
|
-- ██████ ██████ ██████ ██ ████ ██
|
||||||
|
function worldeditadditions.count(pos1, pos2)
|
||||||
|
pos1, pos2 = worldedit.sort_pos(pos1, pos2)
|
||||||
|
-- pos2 will always have the highest co-ordinates now
|
||||||
|
|
||||||
|
-- Fetch the nodes in the specified area
|
||||||
|
local manip, area = worldedit.manip_helpers.init(pos1, pos2)
|
||||||
|
local data = manip:get_data()
|
||||||
|
|
||||||
|
-- z y x is the preferred loop order (because CPU cache I'd guess, since then we're iterating linearly through the data array)
|
||||||
|
local counts = {}
|
||||||
|
for z = pos2.z, pos1.z, -1 do
|
||||||
|
for y = pos2.y, pos1.y, -1 do
|
||||||
|
for x = pos2.x, pos1.x, -1 do
|
||||||
|
local next = data[area:index(x, y, z)]
|
||||||
|
if not counts[next] then
|
||||||
|
counts[next] = 0
|
||||||
|
end
|
||||||
|
counts[next] = counts[next] + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local total = worldedit.volume(pos1, pos2)
|
||||||
|
|
||||||
|
local results = {}
|
||||||
|
for node_name, count in pairs(counts) do
|
||||||
|
table.insert(results, {
|
||||||
|
count,
|
||||||
|
tostring(worldeditadditions.round((count / total) * 100, 2)).."%",
|
||||||
|
minetest.get_name_from_content_id(node_name)
|
||||||
|
})
|
||||||
|
end
|
||||||
|
table.sort(results, function(a, b) return a[1] < b[1] end)
|
||||||
|
|
||||||
|
-- Save the modified nodes back to disk & return
|
||||||
|
-- No need to save - this function doesn't actually change anything
|
||||||
|
-- worldedit.manip_helpers.finish(manip, data)
|
||||||
|
|
||||||
|
return true, results, total
|
||||||
|
end
|
|
@ -1,7 +1,5 @@
|
||||||
local we_c = worldeditadditions_commands
|
|
||||||
|
|
||||||
-- From http://lua-users.org/wiki/SimpleRound
|
-- From http://lua-users.org/wiki/SimpleRound
|
||||||
function we_c.round(num, numDecimalPlaces)
|
function worldeditadditions.round(num, numDecimalPlaces)
|
||||||
local mult = 10^(numDecimalPlaces or 0)
|
local mult = 10^(numDecimalPlaces or 0)
|
||||||
return math.floor(num * mult + 0.5) / mult
|
return math.floor(num * mult + 0.5) / mult
|
||||||
end
|
end
|
|
@ -1,9 +1,6 @@
|
||||||
-- Licence: GPLv2 (MPL-2.0 is compatible, so we can use this here)
|
-- Licence: GPLv2 (MPL-2.0 is compatible, so we can use this here)
|
||||||
-- Source: https://stackoverflow.com/a/43582076/1460422
|
-- Source: https://stackoverflow.com/a/43582076/1460422
|
||||||
|
|
||||||
local we_c = worldeditadditions_commands
|
|
||||||
|
|
||||||
|
|
||||||
-- gsplit: iterate over substrings in a string separated by a pattern
|
-- gsplit: iterate over substrings in a string separated by a pattern
|
||||||
--
|
--
|
||||||
-- Parameters:
|
-- Parameters:
|
||||||
|
@ -18,7 +15,7 @@ local we_c = worldeditadditions_commands
|
||||||
-- for substr in gsplit(text, pattern, plain) do
|
-- for substr in gsplit(text, pattern, plain) do
|
||||||
-- doSomething(substr)
|
-- doSomething(substr)
|
||||||
-- end
|
-- end
|
||||||
function we_c.gsplit(text, pattern, plain)
|
function worldeditadditions.gsplit(text, pattern, plain)
|
||||||
local splitStart, length = 1, #text
|
local splitStart, length = 1, #text
|
||||||
return function ()
|
return function ()
|
||||||
if splitStart then
|
if splitStart then
|
||||||
|
@ -54,10 +51,49 @@ end
|
||||||
-- string, not a Lua pattern
|
-- string, not a Lua pattern
|
||||||
--
|
--
|
||||||
-- Returns: table (a sequence table containing the substrings)
|
-- Returns: table (a sequence table containing the substrings)
|
||||||
function we_c.split(text, pattern, plain)
|
function worldeditadditions.split(text, pattern, plain)
|
||||||
local ret = {}
|
local ret = {}
|
||||||
for match in we_c.gsplit(text, pattern, plain) do
|
for match in worldeditadditions.gsplit(text, pattern, plain) do
|
||||||
table.insert(ret, match)
|
table.insert(ret, match)
|
||||||
end
|
end
|
||||||
return ret
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Pads str to length len with char from right
|
||||||
|
-- @source https://snipplr.com/view/13092/strlpad--pad-string-to-the-left
|
||||||
|
function worldeditadditions.str_padend(str, len, char)
|
||||||
|
if char == nil then char = ' ' end
|
||||||
|
return str .. string.rep(char, len - #str)
|
||||||
|
end
|
||||||
|
--- Pads str to length len with char from left
|
||||||
|
-- Adapted from the above
|
||||||
|
function worldeditadditions.str_padstart(str, len, char)
|
||||||
|
if char == nil then char = ' ' end
|
||||||
|
return string.rep(char, len - #str) .. str
|
||||||
|
end
|
||||||
|
|
||||||
|
function worldeditadditions.make_ascii_table(data)
|
||||||
|
local extra_padding = 2
|
||||||
|
local result = {}
|
||||||
|
local max_lengths = {}
|
||||||
|
for y = 1, #data, 1 do
|
||||||
|
for x = 1, #data[y], 1 do
|
||||||
|
if not max_lengths[x] then
|
||||||
|
max_lengths[x] = 0
|
||||||
|
end
|
||||||
|
max_lengths[x] = math.max(max_lengths[x], #tostring(data[y][x]) + extra_padding)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for _key, row in ipairs(data) do
|
||||||
|
local row_result = {}
|
||||||
|
for i = 1, #row, 1 do
|
||||||
|
row_result[#row_result + 1] = worldeditadditions.str_padend(tostring(row[i]), max_lengths[i], " ")
|
||||||
|
end
|
||||||
|
result[#result+1] = table.concat(row_result, "")
|
||||||
|
end
|
||||||
|
|
||||||
|
-- TODO: Add multi-column support here
|
||||||
|
return table.concat(result, "\n")
|
||||||
|
end
|
|
@ -15,7 +15,7 @@ worldedit.register_command("bonemeal", {
|
||||||
params_text = "1"
|
params_text = "1"
|
||||||
end
|
end
|
||||||
|
|
||||||
local parts = we_c.split(params_text, "%s+", false)
|
local parts = worldeditadditions.split(params_text, "%s+", false)
|
||||||
|
|
||||||
local strength = 1
|
local strength = 1
|
||||||
local chance = 1
|
local chance = 1
|
||||||
|
@ -52,7 +52,7 @@ worldedit.register_command("bonemeal", {
|
||||||
-- nodes_bonemealed is an error message here because success == false
|
-- nodes_bonemealed is an error message here because success == false
|
||||||
return success, nodes_bonemealed
|
return success, nodes_bonemealed
|
||||||
end
|
end
|
||||||
local percentage = we_c.round((nodes_bonemealed / candidates)*100, 2)
|
local percentage = worldeditadditions.round((nodes_bonemealed / candidates)*100, 2)
|
||||||
local time_taken = os.clock() - start_time
|
local time_taken = os.clock() - start_time
|
||||||
|
|
||||||
minetest.log("action", name .. " used //bonemeal at "..worldeditadditions.vector.tostring(worldedit.pos1[name]).." - "..worldeditadditions.vector.tostring(worldedit.pos2[name])..", bonemealing " .. nodes_bonemealed.." nodes (out of "..candidates.." nodes) at strength "..strength.." in "..time_taken.."s")
|
minetest.log("action", name .. " used //bonemeal at "..worldeditadditions.vector.tostring(worldedit.pos1[name]).." - "..worldeditadditions.vector.tostring(worldedit.pos2[name])..", bonemealing " .. nodes_bonemealed.." nodes (out of "..candidates.." nodes) at strength "..strength.." in "..time_taken.."s")
|
||||||
|
|
35
worldeditadditions_commands/commands/count.lua
Normal file
35
worldeditadditions_commands/commands/count.lua
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
local we_c = worldeditadditions_commands
|
||||||
|
|
||||||
|
-- ██████ ██████ ██ ██ ███ ██ ████████
|
||||||
|
-- ██ ██ ██ ██ ██ ████ ██ ██
|
||||||
|
-- ██ ██ ██ ██ ██ ██ ██ ██ ██
|
||||||
|
-- ██ ██ ██ ██ ██ ██ ██ ██ ██
|
||||||
|
-- ██████ ██████ ██████ ██ ████ ██
|
||||||
|
worldedit.register_command("count", {
|
||||||
|
params = "",
|
||||||
|
description = "Counts all the nodes in the defined region.",
|
||||||
|
privs = { worldedit = true },
|
||||||
|
require_pos = 2,
|
||||||
|
parse = function(params_text)
|
||||||
|
return true
|
||||||
|
end,
|
||||||
|
nodes_needed = function(name)
|
||||||
|
-- We don't actually modify anything, but without returning a
|
||||||
|
-- number here safe_region doesn't work
|
||||||
|
return worldedit.volume(worldedit.pos1[name], worldedit.pos2[name])
|
||||||
|
end,
|
||||||
|
func = function(name)
|
||||||
|
local start_time = os.clock()
|
||||||
|
|
||||||
|
local success, counts, total = worldeditadditions.count(worldedit.pos1[name], worldedit.pos2[name], target_node)
|
||||||
|
local result = worldeditadditions.make_ascii_table(counts).."\n"..
|
||||||
|
string.rep("=", 6 + #tostring(total) + 6).."\n"..
|
||||||
|
"Total "..total.." nodes\n"
|
||||||
|
|
||||||
|
local time_taken = os.clock() - start_time
|
||||||
|
|
||||||
|
|
||||||
|
minetest.log("action", name.." used //count at "..worldeditadditions.vector.tostring(worldedit.pos1[name]).." - "..worldeditadditions.vector.tostring(worldedit.pos1[name])..", counting "..total.." nodes in "..time_taken.."s")
|
||||||
|
return true, result
|
||||||
|
end
|
||||||
|
})
|
|
@ -11,7 +11,7 @@ local function parse_params_maze(params_text, is_3d)
|
||||||
return false, "No arguments specified"
|
return false, "No arguments specified"
|
||||||
end
|
end
|
||||||
|
|
||||||
local parts = we_c.split(params_text, "%s+", false)
|
local parts = worldeditadditions.split(params_text, "%s+", false)
|
||||||
|
|
||||||
local replace_node = parts[1]
|
local replace_node = parts[1]
|
||||||
local seed = os.time()
|
local seed = os.time()
|
||||||
|
|
|
@ -10,9 +10,6 @@ local we_c = worldeditadditions_commands
|
||||||
|
|
||||||
we_c.modpath = minetest.get_modpath("worldeditadditions_commands")
|
we_c.modpath = minetest.get_modpath("worldeditadditions_commands")
|
||||||
|
|
||||||
dofile(we_c.modpath.."/utils/strings.lua")
|
|
||||||
dofile(we_c.modpath.."/utils/numbers.lua")
|
|
||||||
|
|
||||||
dofile(we_c.modpath.."/multi.lua")
|
dofile(we_c.modpath.."/multi.lua")
|
||||||
|
|
||||||
-- We no longer need our own implementation of safe_region thanks to @sfan5's
|
-- We no longer need our own implementation of safe_region thanks to @sfan5's
|
||||||
|
@ -24,9 +21,10 @@ dofile(we_c.modpath.."/commands/floodfill.lua")
|
||||||
dofile(we_c.modpath.."/commands/overlay.lua")
|
dofile(we_c.modpath.."/commands/overlay.lua")
|
||||||
dofile(we_c.modpath.."/commands/ellipsoid.lua")
|
dofile(we_c.modpath.."/commands/ellipsoid.lua")
|
||||||
dofile(we_c.modpath.."/commands/torus.lua")
|
dofile(we_c.modpath.."/commands/torus.lua")
|
||||||
|
dofile(we_c.modpath.."/commands/walls.lua")
|
||||||
dofile(we_c.modpath.."/commands/maze.lua")
|
dofile(we_c.modpath.."/commands/maze.lua")
|
||||||
|
|
||||||
dofile(we_c.modpath.."/commands/walls.lua")
|
dofile(we_c.modpath.."/commands/count.lua")
|
||||||
|
|
||||||
-- Don't registry the //bonemeal command if the bonemeal mod isn't present
|
-- Don't registry the //bonemeal command if the bonemeal mod isn't present
|
||||||
if minetest.get_modpath("bonemeal") then
|
if minetest.get_modpath("bonemeal") then
|
||||||
|
|
Loading…
Reference in a new issue