Add new flags for /placeschem: -r and -f

This commit is contained in:
Wuzzy 2023-12-23 23:26:02 +01:00
parent 28ede3cc26
commit a3d561ddf8

128
init.lua
View File

@ -1407,43 +1407,105 @@ local function add_suffix(schem)
return schem_full, schem_lua
end
-- [chatcommand] Place schematic
minetest.register_chatcommand("placeschem", {
description = S("Place schematic at the position specified or the current player position (loaded from @1). “-c” will clear the area first", export_path_trunc),
privs = {server = true},
params = S("<schematic name>[.mts] [-c] [<x> <y> <z>]"),
func = function(name, param)
local schem, clear, p = string.match(param, "^([^ ]+) +(%-c) *(.*)$")
if not schem then
schem, p = string.match(param, "^([^ ]+) *(.*)$")
parse_command_arguments = function(arguments, relative_pos)
if not relative_pos then
relative_pos = vector.zero()
end
clear = clear == "-c"
local ppos = minetest.get_player_by_name(name):get_pos()
local pos
if p and p ~= "" then
local pp = string.split(p, " ")
local nums = {}
local arglist = string.split(arguments, " ")
local flags = {
clear = false,
force_placement = false,
rotate = "0",
}
local coords = {}
local axes = { "x", "y", "z" }
for a=1, #axes do
local axis = axes[a]
local parsed
if minetest.parse_relative_number then
parsed = minetest.parse_relative_number(pp[a], ppos[axis])
else
parsed = tonumber(ppos[axis])
local coord_index = 1
local previous_arg = nil
local parsing_flags = true
for a=1, #arglist do
local arg = arglist[a]
local relnum
if coord_index <= 4 then
relnum = minetest.parse_relative_number(arg, relative_pos[axes[coord_index]])
end
if not parsed then
if previous_arg == "-r" then
if arg == "0" or arg == "90" or arg == "180" or arg == "270" or arg == "random" then
flags.rotate = arg
else
return false, S("Incorrect angle after “-r” flag. Allowed are “0”, “90”, “180”, “270” or “random”.")
end
elseif relnum then
if coord_index > 3 then
-- Too many coordinates!
return false
end
table.insert(nums, parsed)
end
pos = vector.new(nums[1], nums[2], nums[3])
parsing_flags = false
table.insert(coords, relnum)
coord_index = coord_index + 1
else
pos = ppos
if parsing_flags then
if previous_arg == "-r" then
-- Error: Flag after "-r"
return false
end
if arg == "-c" then
flags.clear = true
elseif arg == "-f" then
flags.force_placement = true
elseif arg == "-r" then
flags.rotate = "pending"
else
-- Error: Unknown flag
return false, S("Unknown flag “@1”. Use “/help placeschem” for a list of flags.", arg)
end
else
-- Error: Something non-coordinate like-found in coordinate section
return false
end
end
previous_arg = arg
end
if #coords == 0 then
coords = nil
elseif #coords == 3 then
coords = { x = coords[1], y = coords[2], z = coords[3] }
else
return false
end
if flags.rotate == "pending" then
return false, S("No angle specified after “-r” flag.")
end
return flags, coords
end
local flag_info = S("“-c”: clear area before placing; “-r <angle>”: set rotation to 0, 90, 180, 270 or random; “-f”: also replace nodes other than air and ignore")
-- [chatcommand] Place schematic
minetest.register_chatcommand("placeschem", {
description = S("Place schematic at the position specified or the current player position (loaded from @1). Available flags: @2.",
export_path_trunc,
flag_info),
privs = {server = true},
params = S("<schematic name>[.mts] [<flags>] [<x> <y> <z>]"),
func = function(name, param)
local schem, arguments = string.match(param, "^([^ ]+) *(.*)$")
if not schem then
return false
end
local ppos
local player = minetest.get_player_by_name(name)
if player and player:is_player() then
ppos = player:get_pos()
end
local flags, extra_info = parse_command_arguments(arguments, ppos)
if flags == false then
return false, extra_info
end
local pos = extra_info
if not pos then
pos = table.copy(ppos)
end
pos = vector.round(pos)
if not schem then
@ -1459,9 +1521,9 @@ minetest.register_chatcommand("placeschem", {
-- files when we reload. minetest.read_schematic circumvents that.
local schematic = minetest.read_schematic(schem_path, {})
if schematic then
if clear then
if flags.clear then
-- Clear same size for X and Z because
-- because schematic is randomly rotated
-- because schematic may be rotated
local max_xz = math.max(schematic.size.x, schematic.size.z)
local posses = {}
for z=pos.z, pos.z+max_xz-1 do
@ -1474,13 +1536,13 @@ minetest.register_chatcommand("placeschem", {
minetest.bulk_set_node(posses, {name="air"})
end
minetest.log("action", "[schemedit] Placing schematic '"..schem.."' at: "..minetest.pos_to_string(pos))
success = minetest.place_schematic(pos, schematic, "random", nil, false)
success = minetest.place_schematic(pos, schematic, flags.rotate, nil, flags.force_placement)
end
else
-- Legacy support for Minetest versions that do not have minetest.read_schematic.
-- Note: "-c" is ignored here.
minetest.log("action", "[schemedit] Placing schematic '"..schem.."' at: "..minetest.pos_to_string(pos))
success = minetest.place_schematic(schem_path, schematic, "random", nil, false)
success = minetest.place_schematic(schem_path, schematic, flags.rotate, nil, flags.force_placement)
end
if success == nil then