Compare commits
8 Commits
341014f94a
...
new_schems
Author | SHA1 | Date | |
---|---|---|---|
d42ac33d62 | |||
5b19c17117 | |||
4de0eb489f | |||
adc6e00423 | |||
5c06ae59ef | |||
3c5f6b9665 | |||
e387a57e15 | |||
f43bc5278e |
15
.github/workflows/check.yml
vendored
@ -1,15 +0,0 @@
|
|||||||
name: "Check"
|
|
||||||
on: [push, pull_request]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
lint:
|
|
||||||
name: "Luacheck"
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- name: apt
|
|
||||||
run: sudo apt-get install -y luarocks
|
|
||||||
- name: luacheck install
|
|
||||||
run: luarocks install --local luacheck
|
|
||||||
- name: luacheck run
|
|
||||||
run: $HOME/.luarocks/bin/luacheck ./
|
|
11
.github/workflows/test.yml
vendored
@ -1,11 +0,0 @@
|
|||||||
name: "Test"
|
|
||||||
on: [push, pull_request]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
test:
|
|
||||||
name: "Unittests"
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- name: Run tests
|
|
||||||
run: MINETEST_VER=latest ./.util/run_tests.sh
|
|
@ -1,7 +0,0 @@
|
|||||||
read_globals = {"minetest", "vector", "VoxelArea", "ItemStack",
|
|
||||||
"table",
|
|
||||||
"unified_inventory", "sfinv", "smart_inventory", "inventory_plus"
|
|
||||||
}
|
|
||||||
globals = {"worldedit"}
|
|
||||||
-- Ignore these errors until someone decides to fix them
|
|
||||||
ignore = {"212", "213", "411", "412", "421", "422", "431", "432", "631"}
|
|
@ -1,30 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
tempdir=/tmp/mt
|
|
||||||
confpath=$tempdir/minetest.conf
|
|
||||||
worldpath=$tempdir/world
|
|
||||||
|
|
||||||
use_docker=y
|
|
||||||
[ -x ../../bin/minetestserver ] && use_docker=
|
|
||||||
|
|
||||||
rm -rf $tempdir
|
|
||||||
mkdir -p $worldpath
|
|
||||||
# the docker image doesn't have devtest
|
|
||||||
[ -n "$use_docker" ] || printf '%s\n' gameid=devtest >$worldpath/world.mt
|
|
||||||
printf '%s\n' mg_name=singlenode '[end_of_params]' >$worldpath/map_meta.txt
|
|
||||||
printf '%s\n' worldedit_run_tests=true max_forceloaded_blocks=9999 >$confpath
|
|
||||||
|
|
||||||
if [ -n "$use_docker" ]; then
|
|
||||||
chmod -R 777 $tempdir
|
|
||||||
docker run --rm -i \
|
|
||||||
-v $confpath:/etc/minetest/minetest.conf \
|
|
||||||
-v $tempdir:/var/lib/minetest/.minetest \
|
|
||||||
-v "$PWD/worldedit":/var/lib/minetest/.minetest/world/worldmods/worldedit \
|
|
||||||
registry.gitlab.com/minetest/minetest/server:${MINETEST_VER}
|
|
||||||
else
|
|
||||||
mkdir $worldpath/worldmods
|
|
||||||
ln -s "$PWD/worldedit" $worldpath/worldmods/worldedit
|
|
||||||
../../bin/minetestserver --config $confpath --world $worldpath --logfile /dev/null
|
|
||||||
fi
|
|
||||||
|
|
||||||
test -f $worldpath/tests_ok || exit 1
|
|
||||||
exit 0
|
|
@ -23,7 +23,7 @@ There is a nice installation guide over at the [Minetest Wiki](http://wiki.minet
|
|||||||
8. You should have a mod selection screen. Select the one named something like `Minetest-WorldEdit` by left clicking once and press the **Enable Modpack** button.
|
8. You should have a mod selection screen. Select the one named something like `Minetest-WorldEdit` by left clicking once and press the **Enable Modpack** button.
|
||||||
9. Press the **Save** button. You can now use WorldEdit in that world. Repeat steps 7 to 9 to enable WorldEdit for other worlds too.
|
9. Press the **Save** button. You can now use WorldEdit in that world. Repeat steps 7 to 9 to enable WorldEdit for other worlds too.
|
||||||
|
|
||||||
If you are having trouble, try asking for help in the [IRC channel](https://web.libera.chat/#minetest) (faster but may not always have helpers online)
|
If you are having trouble, try asking for help in the [IRC channel](https://webchat.freenode.net/?channels=#minetest) (faster but may not always have helpers online)
|
||||||
or ask on the [forum topic](https://forum.minetest.net/viewtopic.php?id=572) (slower but more likely to get help).
|
or ask on the [forum topic](https://forum.minetest.net/viewtopic.php?id=572) (slower but more likely to get help).
|
||||||
|
|
||||||
Usage
|
Usage
|
||||||
|
@ -1,3 +1,2 @@
|
|||||||
name = Minetest-WorldEdit
|
name = Minetest-WorldEdit
|
||||||
description = WorldEdit is an in-game world editor. Use it to repair griefing, or just create awesome buildings in seconds.
|
description = WorldEdit is an in-game world editor. Use it to repair griefing, or just create awesome buildings in seconds.
|
||||||
min_minetest_version = 5.0
|
|
||||||
|
@ -31,7 +31,7 @@ function worldedit.luatransform(pos1, pos2, code)
|
|||||||
|
|
||||||
worldedit.keep_loaded(pos1, pos2)
|
worldedit.keep_loaded(pos1, pos2)
|
||||||
|
|
||||||
local pos = vector.new(pos1.x, 0, 0)
|
local pos = {x=pos1.x, y=0, z=0}
|
||||||
while pos.x <= pos2.x do
|
while pos.x <= pos2.x do
|
||||||
pos.y = pos1.y
|
pos.y = pos1.y
|
||||||
while pos.y <= pos2.y do
|
while pos.y <= pos2.y do
|
||||||
|
@ -5,8 +5,8 @@
|
|||||||
-- `pos1` is less than or equal to the corresponding component of `pos2`.
|
-- `pos1` is less than or equal to the corresponding component of `pos2`.
|
||||||
-- Returns the new positions.
|
-- Returns the new positions.
|
||||||
function worldedit.sort_pos(pos1, pos2)
|
function worldedit.sort_pos(pos1, pos2)
|
||||||
pos1 = vector.new(pos1.x, pos1.y, pos1.z)
|
pos1 = {x=pos1.x, y=pos1.y, z=pos1.z}
|
||||||
pos2 = vector.new(pos2.x, pos2.y, pos2.z)
|
pos2 = {x=pos2.x, y=pos2.y, z=pos2.z}
|
||||||
if pos1.x > pos2.x then
|
if pos1.x > pos2.x then
|
||||||
pos2.x, pos1.x = pos1.x, pos2.x
|
pos2.x, pos1.x = pos1.x, pos2.x
|
||||||
end
|
end
|
||||||
|
@ -24,14 +24,11 @@ function worldedit.metasave(pos1, pos2, filename)
|
|||||||
return count
|
return count
|
||||||
end
|
end
|
||||||
|
|
||||||
function worldedit.metaload(originpos, file_name)
|
function worldedit.metaload(originpos, filename)
|
||||||
deprecated("load")
|
deprecated("load")
|
||||||
local file_path = minetest.get_worldpath() ..
|
filename = minetest.get_worldpath() .. "/schems/" .. file .. ".wem"
|
||||||
"/schems/" .. file_name .. ".wem"
|
local file, err = io.open(filename, "wb")
|
||||||
local file, err = io.open(file_path, "wb")
|
if err then return 0 end
|
||||||
if err then
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
local data = file:read("*a")
|
local data = file:read("*a")
|
||||||
return worldedit.deserialize(originpos, data)
|
return worldedit.deserialize(originpos, data)
|
||||||
end
|
end
|
||||||
|
@ -38,7 +38,3 @@ if minetest.settings:get_bool("log_mods") then
|
|||||||
print("[WorldEdit] Loaded!")
|
print("[WorldEdit] Loaded!")
|
||||||
end
|
end
|
||||||
|
|
||||||
if minetest.settings:get_bool("worldedit_run_tests") then
|
|
||||||
dofile(path .. "/test.lua")
|
|
||||||
minetest.after(0, worldedit.run_tests)
|
|
||||||
end
|
|
||||||
|
@ -101,7 +101,7 @@ end
|
|||||||
local function deferred_execution(next_one, finished)
|
local function deferred_execution(next_one, finished)
|
||||||
-- Allocate 100% of server step for execution (might lag a little)
|
-- Allocate 100% of server step for execution (might lag a little)
|
||||||
local allocated_usecs =
|
local allocated_usecs =
|
||||||
tonumber(minetest.settings:get("dedicated_server_step"):split(" ")[1]) * 1000000
|
tonumber(minetest.settings:get("dedicated_server_step")) * 1000000
|
||||||
local function f()
|
local function f()
|
||||||
local deadline = minetest.get_us_time() + allocated_usecs
|
local deadline = minetest.get_us_time() + allocated_usecs
|
||||||
repeat
|
repeat
|
||||||
@ -128,7 +128,7 @@ function worldedit.stack2(pos1, pos2, direction, amount, finished)
|
|||||||
direction = table.copy(direction)
|
direction = table.copy(direction)
|
||||||
|
|
||||||
local i = 0
|
local i = 0
|
||||||
local translated = vector.new()
|
local translated = {x=0, y=0, z=0}
|
||||||
local function step()
|
local function step()
|
||||||
translated.x = translated.x + direction.x
|
translated.x = translated.x + direction.x
|
||||||
translated.y = translated.y + direction.y
|
translated.y = translated.y + direction.y
|
||||||
@ -155,7 +155,7 @@ function worldedit.copy(pos1, pos2, axis, amount)
|
|||||||
-- Decide if we need to copy stuff backwards (only applies to metadata)
|
-- Decide if we need to copy stuff backwards (only applies to metadata)
|
||||||
local backwards = amount > 0 and amount < (pos2[axis] - pos1[axis] + 1)
|
local backwards = amount > 0 and amount < (pos2[axis] - pos1[axis] + 1)
|
||||||
|
|
||||||
local off = vector.new()
|
local off = {x=0, y=0, z=0}
|
||||||
off[axis] = amount
|
off[axis] = amount
|
||||||
return worldedit.copy2(pos1, pos2, off, backwards)
|
return worldedit.copy2(pos1, pos2, off, backwards)
|
||||||
end
|
end
|
||||||
@ -170,7 +170,7 @@ function worldedit.copy2(pos1, pos2, off, meta_backwards)
|
|||||||
local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
|
local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
|
||||||
|
|
||||||
local src_manip, src_area = mh.init(pos1, pos2)
|
local src_manip, src_area = mh.init(pos1, pos2)
|
||||||
local src_stride = vector.new(1, src_area.ystride, src_area.zstride)
|
local src_stride = {x=1, y=src_area.ystride, z=src_area.zstride}
|
||||||
local src_offset = vector.subtract(pos1, src_area.MinEdge)
|
local src_offset = vector.subtract(pos1, src_area.MinEdge)
|
||||||
|
|
||||||
local dpos1 = vector.add(pos1, off)
|
local dpos1 = vector.add(pos1, off)
|
||||||
@ -178,7 +178,7 @@ function worldedit.copy2(pos1, pos2, off, meta_backwards)
|
|||||||
local dim = vector.add(vector.subtract(pos2, pos1), 1)
|
local dim = vector.add(vector.subtract(pos2, pos1), 1)
|
||||||
|
|
||||||
local dst_manip, dst_area = mh.init(dpos1, dpos2)
|
local dst_manip, dst_area = mh.init(dpos1, dpos2)
|
||||||
local dst_stride = vector.new(1, dst_area.ystride, dst_area.zstride)
|
local dst_stride = {x=1, y=dst_area.ystride, z=dst_area.zstride}
|
||||||
local dst_offset = vector.subtract(dpos1, dst_area.MinEdge)
|
local dst_offset = vector.subtract(dpos1, dst_area.MinEdge)
|
||||||
|
|
||||||
local function do_copy(src_data, dst_data)
|
local function do_copy(src_data, dst_data)
|
||||||
@ -217,6 +217,8 @@ function worldedit.copy2(pos1, pos2, off, meta_backwards)
|
|||||||
dst_manip:set_param2_data(dst_data)
|
dst_manip:set_param2_data(dst_data)
|
||||||
|
|
||||||
mh.finish(dst_manip)
|
mh.finish(dst_manip)
|
||||||
|
src_data = nil
|
||||||
|
dst_data = nil
|
||||||
|
|
||||||
-- Copy metadata
|
-- Copy metadata
|
||||||
local get_meta = minetest.get_meta
|
local get_meta = minetest.get_meta
|
||||||
@ -224,7 +226,7 @@ function worldedit.copy2(pos1, pos2, off, meta_backwards)
|
|||||||
for z = dim.z-1, 0, -1 do
|
for z = dim.z-1, 0, -1 do
|
||||||
for y = dim.y-1, 0, -1 do
|
for y = dim.y-1, 0, -1 do
|
||||||
for x = dim.x-1, 0, -1 do
|
for x = dim.x-1, 0, -1 do
|
||||||
local pos = vector.new(pos1.x+x, pos1.y+y, pos1.z+z)
|
local pos = {x=pos1.x+x, y=pos1.y+y, z=pos1.z+z}
|
||||||
local meta = get_meta(pos):to_table()
|
local meta = get_meta(pos):to_table()
|
||||||
pos = vector.add(pos, off)
|
pos = vector.add(pos, off)
|
||||||
get_meta(pos):from_table(meta)
|
get_meta(pos):from_table(meta)
|
||||||
@ -235,7 +237,7 @@ function worldedit.copy2(pos1, pos2, off, meta_backwards)
|
|||||||
for z = 0, dim.z-1 do
|
for z = 0, dim.z-1 do
|
||||||
for y = 0, dim.y-1 do
|
for y = 0, dim.y-1 do
|
||||||
for x = 0, dim.x-1 do
|
for x = 0, dim.x-1 do
|
||||||
local pos = vector.new(pos1.x+x, pos1.y+y, pos1.z+z)
|
local pos = {x=pos1.x+x, y=pos1.y+y, z=pos1.z+z}
|
||||||
local meta = get_meta(pos):to_table()
|
local meta = get_meta(pos):to_table()
|
||||||
pos = vector.add(pos, off)
|
pos = vector.add(pos, off)
|
||||||
get_meta(pos):from_table(meta)
|
get_meta(pos):from_table(meta)
|
||||||
@ -284,21 +286,21 @@ function worldedit.move(pos1, pos2, axis, amount)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Copy stuff to new location
|
-- Copy stuff to new location
|
||||||
local off = vector.new()
|
local off = {x=0, y=0, z=0}
|
||||||
off[axis] = amount
|
off[axis] = amount
|
||||||
worldedit.copy2(pos1, pos2, off, backwards)
|
worldedit.copy2(pos1, pos2, off, backwards)
|
||||||
-- Nuke old area
|
-- Nuke old area
|
||||||
if not overlap then
|
if not overlap then
|
||||||
nuke_area(vector.new(), dim)
|
nuke_area({x=0, y=0, z=0}, dim)
|
||||||
else
|
else
|
||||||
-- Source and destination region are overlapping, which means we can't
|
-- Source and destination region are overlapping, which means we can't
|
||||||
-- blindly delete the [pos1, pos2] area
|
-- blindly delete the [pos1, pos2] area
|
||||||
local leftover = vector.new(dim) -- size of the leftover slice
|
local leftover = vector.new(dim) -- size of the leftover slice
|
||||||
leftover[axis] = math.abs(amount)
|
leftover[axis] = math.abs(amount)
|
||||||
if amount > 0 then
|
if amount > 0 then
|
||||||
nuke_area(vector.new(), leftover)
|
nuke_area({x=0, y=0, z=0}, leftover)
|
||||||
else
|
else
|
||||||
local top = vector.new() -- offset of the leftover slice from pos1
|
local top = {x=0, y=0, z=0} -- offset of the leftover slice from pos1
|
||||||
top[axis] = dim[axis] - math.abs(amount)
|
top[axis] = dim[axis] - math.abs(amount)
|
||||||
nuke_area(top, leftover)
|
nuke_area(top, leftover)
|
||||||
end
|
end
|
||||||
@ -356,7 +358,7 @@ function worldedit.stretch(pos1, pos2, stretch_x, stretch_y, stretch_z)
|
|||||||
for i = 1, stretch_x * stretch_y * stretch_z do
|
for i = 1, stretch_x * stretch_y * stretch_z do
|
||||||
nodes[i] = placeholder_node
|
nodes[i] = placeholder_node
|
||||||
end
|
end
|
||||||
local schematic = {size=vector.new(stretch_x, stretch_y, stretch_z), data=nodes}
|
local schematic = {size={x=stretch_x, y=stretch_y, z=stretch_z}, data=nodes}
|
||||||
|
|
||||||
local size_x, size_y, size_z = stretch_x - 1, stretch_y - 1, stretch_z - 1
|
local size_x, size_y, size_z = stretch_x - 1, stretch_y - 1, stretch_z - 1
|
||||||
|
|
||||||
@ -367,8 +369,8 @@ function worldedit.stretch(pos1, pos2, stretch_x, stretch_y, stretch_z)
|
|||||||
}
|
}
|
||||||
worldedit.keep_loaded(pos1, new_pos2)
|
worldedit.keep_loaded(pos1, new_pos2)
|
||||||
|
|
||||||
local pos = vector.new(pos2.x, 0, 0)
|
local pos = {x=pos2.x, y=0, z=0}
|
||||||
local big_pos = vector.new()
|
local big_pos = {x=0, y=0, z=0}
|
||||||
while pos.x >= pos1.x do
|
while pos.x >= pos1.x do
|
||||||
pos.y = pos2.y
|
pos.y = pos2.y
|
||||||
while pos.y >= pos1.y do
|
while pos.y >= pos1.y do
|
||||||
@ -434,16 +436,16 @@ function worldedit.transpose(pos1, pos2, axis1, axis2)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Calculate the new position 2 after transposition
|
-- Calculate the new position 2 after transposition
|
||||||
local new_pos2 = vector.new(pos2)
|
local new_pos2 = {x=pos2.x, y=pos2.y, z=pos2.z}
|
||||||
new_pos2[axis1] = pos1[axis1] + extent2
|
new_pos2[axis1] = pos1[axis1] + extent2
|
||||||
new_pos2[axis2] = pos1[axis2] + extent1
|
new_pos2[axis2] = pos1[axis2] + extent1
|
||||||
|
|
||||||
local upper_bound = vector.new(pos2)
|
local upper_bound = {x=pos2.x, y=pos2.y, z=pos2.z}
|
||||||
if upper_bound[axis1] < new_pos2[axis1] then upper_bound[axis1] = new_pos2[axis1] end
|
if upper_bound[axis1] < new_pos2[axis1] then upper_bound[axis1] = new_pos2[axis1] end
|
||||||
if upper_bound[axis2] < new_pos2[axis2] then upper_bound[axis2] = new_pos2[axis2] end
|
if upper_bound[axis2] < new_pos2[axis2] then upper_bound[axis2] = new_pos2[axis2] end
|
||||||
worldedit.keep_loaded(pos1, upper_bound)
|
worldedit.keep_loaded(pos1, upper_bound)
|
||||||
|
|
||||||
local pos = vector.new(pos1.x, 0, 0)
|
local pos = {x=pos1.x, y=0, z=0}
|
||||||
local get_node, get_meta, set_node = minetest.get_node,
|
local get_node, get_meta, set_node = minetest.get_node,
|
||||||
minetest.get_meta, minetest.set_node
|
minetest.get_meta, minetest.set_node
|
||||||
while pos.x <= pos2.x do
|
while pos.x <= pos2.x do
|
||||||
@ -483,7 +485,7 @@ function worldedit.flip(pos1, pos2, axis)
|
|||||||
worldedit.keep_loaded(pos1, pos2)
|
worldedit.keep_loaded(pos1, pos2)
|
||||||
|
|
||||||
--- TODO: Flip the region slice by slice along the flip axis using schematic method.
|
--- TODO: Flip the region slice by slice along the flip axis using schematic method.
|
||||||
local pos = vector.new(pos1.x, 0, 0)
|
local pos = {x=pos1.x, y=0, z=0}
|
||||||
local start = pos1[axis] + pos2[axis]
|
local start = pos1[axis] + pos2[axis]
|
||||||
pos2[axis] = pos1[axis] + math.floor((pos2[axis] - pos1[axis]) / 2)
|
pos2[axis] = pos1[axis] + math.floor((pos2[axis] - pos1[axis]) / 2)
|
||||||
local get_node, get_meta, set_node = minetest.get_node,
|
local get_node, get_meta, set_node = minetest.get_node,
|
||||||
@ -582,7 +584,7 @@ function worldedit.orient(pos1, pos2, angle)
|
|||||||
|
|
||||||
local count = 0
|
local count = 0
|
||||||
local get_node, swap_node = minetest.get_node, minetest.swap_node
|
local get_node, swap_node = minetest.get_node, minetest.swap_node
|
||||||
local pos = vector.new(pos1.x, 0, 0)
|
local pos = {x=pos1.x, y=0, z=0}
|
||||||
while pos.x <= pos2.x do
|
while pos.x <= pos2.x do
|
||||||
pos.y = pos1.y
|
pos.y = pos1.y
|
||||||
while pos.y <= pos2.y do
|
while pos.y <= pos2.y do
|
||||||
@ -648,12 +650,13 @@ function worldedit.clear_objects(pos1, pos2)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Offset positions to include full nodes (positions are in the center of nodes)
|
-- Offset positions to include full nodes (positions are in the center of nodes)
|
||||||
pos1 = vector.add(pos1, -0.5)
|
local pos1x, pos1y, pos1z = pos1.x - 0.5, pos1.y - 0.5, pos1.z - 0.5
|
||||||
pos2 = vector.add(pos2, 0.5)
|
local pos2x, pos2y, pos2z = pos2.x + 0.5, pos2.y + 0.5, pos2.z + 0.5
|
||||||
|
|
||||||
local count = 0
|
local count = 0
|
||||||
if minetest.get_objects_in_area then
|
if minetest.get_objects_in_area then
|
||||||
local objects = minetest.get_objects_in_area(pos1, pos2)
|
local objects = minetest.get_objects_in_area({x=pos1x, y=pos1y, z=pos1z},
|
||||||
|
{x=pos2x, y=pos2y, z=pos2z})
|
||||||
|
|
||||||
for _, obj in pairs(objects) do
|
for _, obj in pairs(objects) do
|
||||||
if should_delete(obj) then
|
if should_delete(obj) then
|
||||||
@ -667,22 +670,21 @@ function worldedit.clear_objects(pos1, pos2)
|
|||||||
-- Fallback implementation via get_objects_inside_radius
|
-- Fallback implementation via get_objects_inside_radius
|
||||||
-- Center of region
|
-- Center of region
|
||||||
local center = {
|
local center = {
|
||||||
x = pos1.x + ((pos2.x - pos1.x) / 2),
|
x = pos1x + ((pos2x - pos1x) / 2),
|
||||||
y = pos1.y + ((pos2.y - pos1.y) / 2),
|
y = pos1y + ((pos2y - pos1y) / 2),
|
||||||
z = pos1.z + ((pos2.z - pos1.z) / 2)
|
z = pos1z + ((pos2z - pos1z) / 2)
|
||||||
}
|
}
|
||||||
-- Bounding sphere radius
|
-- Bounding sphere radius
|
||||||
local radius = math.sqrt(
|
local radius = math.sqrt(
|
||||||
(center.x - pos1.x) ^ 2 +
|
(center.x - pos1x) ^ 2 +
|
||||||
(center.y - pos1.y) ^ 2 +
|
(center.y - pos1y) ^ 2 +
|
||||||
(center.z - pos1.z) ^ 2)
|
(center.z - pos1z) ^ 2)
|
||||||
local objects = minetest.get_objects_inside_radius(center, radius)
|
for _, obj in pairs(minetest.get_objects_inside_radius(center, radius)) do
|
||||||
for _, obj in pairs(objects) do
|
|
||||||
if should_delete(obj) then
|
if should_delete(obj) then
|
||||||
local pos = obj:get_pos()
|
local pos = obj:get_pos()
|
||||||
if pos.x >= pos1.x and pos.x <= pos2.x and
|
if pos.x >= pos1x and pos.x <= pos2x and
|
||||||
pos.y >= pos1.y and pos.y <= pos2.y and
|
pos.y >= pos1y and pos.y <= pos2y and
|
||||||
pos.z >= pos1.z and pos.z <= pos2.z then
|
pos.z >= pos1z and pos.z <= pos2z then
|
||||||
-- Inside region
|
-- Inside region
|
||||||
obj:remove()
|
obj:remove()
|
||||||
count = count + 1
|
count = count + 1
|
||||||
|
@ -20,7 +20,7 @@ function worldedit.cube(pos, width, height, length, node_name, hollow)
|
|||||||
|
|
||||||
-- Add cube
|
-- Add cube
|
||||||
local node_id = minetest.get_content_id(node_name)
|
local node_id = minetest.get_content_id(node_name)
|
||||||
local stride = vector.new(1, area.ystride, area.zstride)
|
local stride = {x=1, y=area.ystride, z=area.zstride}
|
||||||
local offset = vector.subtract(basepos, area.MinEdge)
|
local offset = vector.subtract(basepos, area.MinEdge)
|
||||||
local count = 0
|
local count = 0
|
||||||
|
|
||||||
@ -149,7 +149,7 @@ function worldedit.cylinder(pos, axis, length, radius1, radius2, node_name, holl
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Handle negative lengths
|
-- Handle negative lengths
|
||||||
local current_pos = vector.new(pos)
|
local current_pos = {x=pos.x, y=pos.y, z=pos.z}
|
||||||
if length < 0 then
|
if length < 0 then
|
||||||
length = -length
|
length = -length
|
||||||
current_pos[axis] = current_pos[axis] - length
|
current_pos[axis] = current_pos[axis] - length
|
||||||
@ -162,7 +162,7 @@ function worldedit.cylinder(pos, axis, length, radius1, radius2, node_name, holl
|
|||||||
|
|
||||||
-- Add desired shape (anything inbetween cylinder & cone)
|
-- Add desired shape (anything inbetween cylinder & cone)
|
||||||
local node_id = minetest.get_content_id(node_name)
|
local node_id = minetest.get_content_id(node_name)
|
||||||
local stride = vector.new(1, area.ystride, area.zstride)
|
local stride = {x=1, y=area.ystride, z=area.zstride}
|
||||||
local offset = {
|
local offset = {
|
||||||
x = current_pos.x - area.MinEdge.x,
|
x = current_pos.x - area.MinEdge.x,
|
||||||
y = current_pos.y - area.MinEdge.y,
|
y = current_pos.y - area.MinEdge.y,
|
||||||
@ -225,7 +225,7 @@ function worldedit.pyramid(pos, axis, height, node_name, hollow)
|
|||||||
|
|
||||||
-- Add pyramid
|
-- Add pyramid
|
||||||
local node_id = minetest.get_content_id(node_name)
|
local node_id = minetest.get_content_id(node_name)
|
||||||
local stride = vector.new(1, area.ystride, area.zstride)
|
local stride = {x=1, y=area.ystride, z=area.zstride}
|
||||||
local offset = {
|
local offset = {
|
||||||
x = pos.x - area.MinEdge.x,
|
x = pos.x - area.MinEdge.x,
|
||||||
y = pos.y - area.MinEdge.y,
|
y = pos.y - area.MinEdge.y,
|
||||||
@ -242,8 +242,8 @@ function worldedit.pyramid(pos, axis, height, node_name, hollow)
|
|||||||
for index3 = -size, size do
|
for index3 = -size, size do
|
||||||
local i = new_index2 + (index3 + offset[other2]) * stride[other2]
|
local i = new_index2 + (index3 + offset[other2]) * stride[other2]
|
||||||
if (not hollow or size - math.abs(index2) < 2 or size - math.abs(index3) < 2) then
|
if (not hollow or size - math.abs(index2) < 2 or size - math.abs(index3) < 2) then
|
||||||
data[i] = node_id
|
data[i] = node_id
|
||||||
count = count + 1
|
count = count + 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -271,7 +271,7 @@ function worldedit.spiral(pos, length, height, spacer, node_name)
|
|||||||
|
|
||||||
-- Set up variables
|
-- Set up variables
|
||||||
local node_id = minetest.get_content_id(node_name)
|
local node_id = minetest.get_content_id(node_name)
|
||||||
local stride = vector.new(1, area.ystride, area.zstride)
|
local stride = {x=1, y=area.ystride, z=area.zstride}
|
||||||
local offset_x, offset_y, offset_z = pos.x - area.MinEdge.x, pos.y - area.MinEdge.y, pos.z - area.MinEdge.z
|
local offset_x, offset_y, offset_z = pos.x - area.MinEdge.x, pos.y - area.MinEdge.y, pos.z - area.MinEdge.z
|
||||||
local i = offset_z * stride.z + offset_y * stride.y + offset_x + 1
|
local i = offset_z * stride.z + offset_y * stride.y + offset_x + 1
|
||||||
|
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
--- Schematic serialization and deserialiation.
|
--- Schematic serialization and deserialiation.
|
||||||
-- @module worldedit.serialization
|
-- @module worldedit.serialization
|
||||||
|
|
||||||
worldedit.LATEST_SERIALIZATION_VERSION = 5
|
worldedit.LATEST_SERIALIZATION_VERSION = 6
|
||||||
local LATEST_SERIALIZATION_HEADER = worldedit.LATEST_SERIALIZATION_VERSION .. ":"
|
|
||||||
|
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
Serialization version history:
|
Serialization version history:
|
||||||
@ -15,6 +13,7 @@ Serialization version history:
|
|||||||
`name`, `param1`, `param2`, and `meta` fields.
|
`name`, `param1`, `param2`, and `meta` fields.
|
||||||
5: Added header and made `param1`, `param2`, and `meta` fields optional.
|
5: Added header and made `param1`, `param2`, and `meta` fields optional.
|
||||||
Header format: <Version>,<ExtraHeaderField1>,...:<Content>
|
Header format: <Version>,<ExtraHeaderField1>,...:<Content>
|
||||||
|
6: Much more complicated but also better format
|
||||||
--]]
|
--]]
|
||||||
|
|
||||||
|
|
||||||
@ -66,17 +65,105 @@ function worldedit.serialize(pos1, pos2)
|
|||||||
has_meta[hash_node_position(meta_positions[i])] = true
|
has_meta[hash_node_position(meta_positions[i])] = true
|
||||||
end
|
end
|
||||||
|
|
||||||
local pos = vector.new(pos1.x, 0, 0)
|
-- Decide axis of saved rows
|
||||||
|
local dim = vector.add(vector.subtract(pos2, pos1), 1)
|
||||||
|
local axis
|
||||||
|
if dim.x * dim.y < math.min(dim.y * dim.z, dim.x * dim.z) then
|
||||||
|
axis = "z"
|
||||||
|
elseif dim.x * dim.z < math.min(dim.x * dim.y, dim.y * dim.z) then
|
||||||
|
axis = "y"
|
||||||
|
elseif dim.y * dim.z < math.min(dim.x * dim.y, dim.x * dim.z) then
|
||||||
|
axis = "x"
|
||||||
|
else
|
||||||
|
axis = "x" -- X or Z are usually most efficient
|
||||||
|
end
|
||||||
|
local other1, other2 = worldedit.get_axis_others(axis)
|
||||||
|
|
||||||
|
-- Helper functions (1)
|
||||||
|
local MATCH_DIST = 8
|
||||||
|
local function match_init(array, first_value)
|
||||||
|
array[1] = first_value
|
||||||
|
return {first_value}
|
||||||
|
end
|
||||||
|
local function match_try(cache, prev_pushed, value)
|
||||||
|
local i = #cache
|
||||||
|
while i >= 1 do
|
||||||
|
if cache[i] == value then
|
||||||
|
local ret = -(#cache - i + 1)
|
||||||
|
local was_value = type(prev_pushed) ~= "number" or prev_pushed >= 0
|
||||||
|
return ret, (was_value and ret == -1) or prev_pushed == ret
|
||||||
|
end
|
||||||
|
i = i - 1
|
||||||
|
end
|
||||||
|
return nil, false
|
||||||
|
end
|
||||||
|
local function match_push(cache, match, value)
|
||||||
|
if match ~= nil then -- don't advance cache
|
||||||
|
return match
|
||||||
|
end
|
||||||
|
local idx = #cache + 1
|
||||||
|
cache[idx] = value
|
||||||
|
if idx > MATCH_DIST then
|
||||||
|
table.remove(cache, 1)
|
||||||
|
end
|
||||||
|
return value
|
||||||
|
end
|
||||||
|
-- Helper functions (2)
|
||||||
|
local function cur_new(pos, pos1)
|
||||||
|
return {
|
||||||
|
a = axis,
|
||||||
|
p = {pos.x - pos1.x, pos.y - pos1.y, pos.z - pos1.z},
|
||||||
|
c = 1,
|
||||||
|
data = {},
|
||||||
|
param1 = {},
|
||||||
|
param2 = {},
|
||||||
|
meta = {},
|
||||||
|
}
|
||||||
|
end
|
||||||
|
local function is_emptyish(t)
|
||||||
|
-- returns true if <t> contains only one element and that one element is == 0
|
||||||
|
local seen = false
|
||||||
|
for _, value in pairs(t) do
|
||||||
|
if not seen then
|
||||||
|
if value ~= 0 then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
seen = true
|
||||||
|
else
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
local function cur_finish(result, cur)
|
||||||
|
if is_emptyish(cur.param1) then
|
||||||
|
cur.param1 = nil
|
||||||
|
end
|
||||||
|
if is_emptyish(cur.param2) then
|
||||||
|
cur.param2 = nil
|
||||||
|
end
|
||||||
|
if next(cur.meta) == nil then
|
||||||
|
cur.meta = nil
|
||||||
|
end
|
||||||
|
result[#result + 1] = cur
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Serialize stuff
|
||||||
|
local pos = {}
|
||||||
local count = 0
|
local count = 0
|
||||||
local result = {}
|
local result = {}
|
||||||
while pos.x <= pos2.x do
|
local cur
|
||||||
pos.y = pos1.y
|
local cache_data, cache_param1, cache_param2
|
||||||
while pos.y <= pos2.y do
|
local prev_data, prev_param1, prev_param2
|
||||||
pos.z = pos1.z
|
pos[other1] = pos1[other1]
|
||||||
while pos.z <= pos2.z do
|
while pos[other1] <= pos2[other1] do
|
||||||
|
pos[other2] = pos1[other2]
|
||||||
|
while pos[other2] <= pos2[other2] do
|
||||||
|
pos[axis] = pos1[axis]
|
||||||
|
while pos[axis] <= pos2[axis] do
|
||||||
|
|
||||||
local node = get_node(pos)
|
local node = get_node(pos)
|
||||||
if node.name ~= "air" and node.name ~= "ignore" then
|
if node.name ~= "air" and node.name ~= "ignore" then
|
||||||
count = count + 1
|
|
||||||
|
|
||||||
local meta
|
local meta
|
||||||
if has_meta[hash_node_position(pos)] then
|
if has_meta[hash_node_position(pos)] then
|
||||||
@ -93,36 +180,76 @@ function worldedit.serialize(pos1, pos2)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
result[count] = {
|
if cur == nil then -- Start a new row
|
||||||
x = pos.x - pos1.x,
|
cur = cur_new(pos, pos1, axis, other1, other2)
|
||||||
y = pos.y - pos1.y,
|
|
||||||
z = pos.z - pos1.z,
|
cache_data = match_init(cur.data, node.name)
|
||||||
name = node.name,
|
cache_param1 = match_init(cur.param1, node.param1)
|
||||||
param1 = node.param1 ~= 0 and node.param1 or nil,
|
cache_param2 = match_init(cur.param2, node.param2)
|
||||||
param2 = node.param2 ~= 0 and node.param2 or nil,
|
prev_data = cur.data[1]
|
||||||
meta = meta,
|
prev_param1 = cur.param1[1]
|
||||||
}
|
prev_param2 = cur.param2[1]
|
||||||
|
|
||||||
|
cur.meta[1] = meta
|
||||||
|
else -- Append to existing row
|
||||||
|
local next_c = cur.c + 1
|
||||||
|
cur.c = next_c
|
||||||
|
local value, m, can_omit
|
||||||
|
|
||||||
|
value = node.name
|
||||||
|
m, can_omit = match_try(cache_data, prev_data, node.name)
|
||||||
|
if not can_omit then
|
||||||
|
prev_data = match_push(cache_data, m, value)
|
||||||
|
cur.data[next_c] = prev_data
|
||||||
|
end
|
||||||
|
|
||||||
|
value = node.param1
|
||||||
|
m, can_omit = match_try(cache_param1, prev_param1, value)
|
||||||
|
if not can_omit then
|
||||||
|
prev_param1 = match_push(cache_param1, m, value)
|
||||||
|
cur.param1[next_c] = prev_param1
|
||||||
|
end
|
||||||
|
|
||||||
|
value = node.param2
|
||||||
|
m, can_omit = match_try(cache_param2, prev_param2, value)
|
||||||
|
if not can_omit then
|
||||||
|
prev_param2 = match_push(cache_param2, m, value)
|
||||||
|
cur.param2[next_c] = prev_param2
|
||||||
|
end
|
||||||
|
|
||||||
|
cur.meta[next_c] = meta
|
||||||
|
end
|
||||||
|
count = count + 1
|
||||||
|
else
|
||||||
|
if cur ~= nil then -- Finish row
|
||||||
|
cur_finish(result, cur)
|
||||||
|
cur = nil
|
||||||
|
end
|
||||||
end
|
end
|
||||||
pos.z = pos.z + 1
|
pos[axis] = pos[axis] + 1
|
||||||
|
|
||||||
end
|
end
|
||||||
pos.y = pos.y + 1
|
if cur ~= nil then -- Finish leftover row
|
||||||
|
cur_finish(result, cur)
|
||||||
|
cur = nil
|
||||||
|
end
|
||||||
|
pos[other2] = pos[other2] + 1
|
||||||
end
|
end
|
||||||
pos.x = pos.x + 1
|
pos[other1] = pos[other1] + 1
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Serialize entries
|
-- Serialize entries
|
||||||
result = minetest.serialize(result)
|
result = minetest.serialize(result)
|
||||||
return LATEST_SERIALIZATION_HEADER .. result, count
|
return tonumber(worldedit.LATEST_SERIALIZATION_VERSION) .. "," ..
|
||||||
|
string.format("%d,%d,%d:", dim.x, dim.y, dim.z) .. result, count
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Contains code based on [table.save/table.load](http://lua-users.org/wiki/SaveTableToFile)
|
||||||
|
-- by ChillCode, available under the MIT license.
|
||||||
local function deserialize_workaround(content)
|
local function deserialize_workaround(content)
|
||||||
local nodes, err
|
local nodes
|
||||||
if not minetest.global_exists("jit") then
|
if not minetest.global_exists("jit") then
|
||||||
nodes, err = minetest.deserialize(content, true)
|
nodes = minetest.deserialize(content, true)
|
||||||
elseif not content:match("^%s*return%s*{") then
|
|
||||||
-- The data doesn't look like we expect it to so we can't apply the workaround.
|
|
||||||
-- hope for the best
|
|
||||||
minetest.log("warning", "WorldEdit: deserializing data but can't apply LuaJIT workaround")
|
|
||||||
nodes, err = minetest.deserialize(content, true)
|
|
||||||
else
|
else
|
||||||
-- XXX: This is a filthy hack that works surprisingly well
|
-- XXX: This is a filthy hack that works surprisingly well
|
||||||
-- in LuaJIT, `minetest.deserialize` will fail due to the register limit
|
-- in LuaJIT, `minetest.deserialize` will fail due to the register limit
|
||||||
@ -132,35 +259,25 @@ local function deserialize_workaround(content)
|
|||||||
local escaped = content:gsub("\\\\", "@@"):gsub("\\\"", "@@"):gsub("(\"[^\"]*\")", function(s) return string.rep("@", #s) end)
|
local escaped = content:gsub("\\\\", "@@"):gsub("\\\"", "@@"):gsub("(\"[^\"]*\")", function(s) return string.rep("@", #s) end)
|
||||||
local startpos, startpos1 = 1, 1
|
local startpos, startpos1 = 1, 1
|
||||||
local endpos
|
local endpos
|
||||||
local entry
|
|
||||||
while true do -- go through each individual node entry (except the last)
|
while true do -- go through each individual node entry (except the last)
|
||||||
startpos, endpos = escaped:find("}%s*,%s*{", startpos)
|
startpos, endpos = escaped:find("},%s*{", startpos)
|
||||||
if not startpos then
|
if not startpos then
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
local current = content:sub(startpos1, startpos)
|
local current = content:sub(startpos1, startpos)
|
||||||
entry, err = minetest.deserialize("return " .. current, true)
|
local entry = minetest.deserialize("return " .. current, true)
|
||||||
if not entry then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
table.insert(nodes, entry)
|
table.insert(nodes, entry)
|
||||||
startpos, startpos1 = endpos, endpos
|
startpos, startpos1 = endpos, endpos
|
||||||
end
|
end
|
||||||
if not err then
|
local entry = minetest.deserialize("return " .. content:sub(startpos1), true) -- process the last entry
|
||||||
entry = minetest.deserialize("return " .. content:sub(startpos1), true) -- process the last entry
|
table.insert(nodes, entry)
|
||||||
table.insert(nodes, entry)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if err then
|
|
||||||
minetest.log("warning", "WorldEdit: deserialize: " .. err)
|
|
||||||
end
|
end
|
||||||
return nodes
|
return nodes
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Loads the schematic in `value` into a node list in the latest format.
|
--- Loads the schematic in `value` into a node list in the latest format.
|
||||||
-- @return A node list in the latest format, or nil on failure.
|
-- @return A node list in the latest format, or nil on failure.
|
||||||
local function load_schematic(value)
|
local function legacy_load_schematic(version, header, content)
|
||||||
local version, _, content = worldedit.read_header(value)
|
|
||||||
local nodes = {}
|
local nodes = {}
|
||||||
if version == 1 or version == 2 then -- Original flat table format
|
if version == 1 or version == 2 then -- Original flat table format
|
||||||
local tables = minetest.deserialize(content, true)
|
local tables = minetest.deserialize(content, true)
|
||||||
@ -202,6 +319,8 @@ local function load_schematic(value)
|
|||||||
end
|
end
|
||||||
elseif version == 4 or version == 5 then -- Nested table format
|
elseif version == 4 or version == 5 then -- Nested table format
|
||||||
nodes = deserialize_workaround(content)
|
nodes = deserialize_workaround(content)
|
||||||
|
elseif version >= 6 then
|
||||||
|
error("legacy_load_schematic called for non-legacy schematic")
|
||||||
else
|
else
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
@ -214,14 +333,29 @@ end
|
|||||||
-- @return High corner position.
|
-- @return High corner position.
|
||||||
-- @return The number of nodes.
|
-- @return The number of nodes.
|
||||||
function worldedit.allocate(origin_pos, value)
|
function worldedit.allocate(origin_pos, value)
|
||||||
local nodes = load_schematic(value)
|
local version, header, content = worldedit.read_header(value)
|
||||||
if not nodes or #nodes == 0 then return nil end
|
if version == 6 then
|
||||||
return worldedit.allocate_with_nodes(origin_pos, nodes)
|
local content = deserialize_workaround(content)
|
||||||
|
local pos2 = {
|
||||||
|
x = origin_pos.x + tonumber(header[1]) - 1,
|
||||||
|
y = origin_pos.y + tonumber(header[2]) - 1,
|
||||||
|
z = origin_pos.z + tonumber(header[3]) - 1,
|
||||||
|
}
|
||||||
|
local count = 0
|
||||||
|
for _, row in ipairs(content) do
|
||||||
|
count = count + row.c
|
||||||
|
end
|
||||||
|
return origin_pos, pos2, count
|
||||||
|
else
|
||||||
|
local nodes = legacy_load_schematic(version, header, content)
|
||||||
|
if not nodes or #nodes == 0 then return nil end
|
||||||
|
return worldedit.legacy_allocate_with_nodes(origin_pos, nodes)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Internal
|
-- Internal
|
||||||
function worldedit.allocate_with_nodes(origin_pos, nodes)
|
function worldedit.legacy_allocate_with_nodes(origin_pos, nodes)
|
||||||
local huge = math.huge
|
local huge = math.huge
|
||||||
local pos1x, pos1y, pos1z = huge, huge, huge
|
local pos1x, pos1y, pos1z = huge, huge, huge
|
||||||
local pos2x, pos2y, pos2z = -huge, -huge, -huge
|
local pos2x, pos2y, pos2z = -huge, -huge, -huge
|
||||||
@ -235,30 +369,119 @@ function worldedit.allocate_with_nodes(origin_pos, nodes)
|
|||||||
if y > pos2y then pos2y = y end
|
if y > pos2y then pos2y = y end
|
||||||
if z > pos2z then pos2z = z end
|
if z > pos2z then pos2z = z end
|
||||||
end
|
end
|
||||||
return vector.new(pos1x, pos1y, pos1z), vector.new(pos2x, pos2y, pos2z), #nodes
|
local pos1 = {x=pos1x, y=pos1y, z=pos1z}
|
||||||
|
local pos2 = {x=pos2x, y=pos2y, z=pos2z}
|
||||||
|
return pos1, pos2, #nodes
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Loads the nodes represented by string `value` at position `origin_pos`.
|
--- Loads the nodes represented by string `value` at position `origin_pos`.
|
||||||
-- @return The number of nodes deserialized.
|
-- @return The number of nodes deserialized.
|
||||||
function worldedit.deserialize(origin_pos, value)
|
function worldedit.deserialize(origin_pos, value)
|
||||||
local nodes = load_schematic(value)
|
local version, header, content = worldedit.read_header(value)
|
||||||
if not nodes then return nil end
|
if version == 6 then
|
||||||
if #nodes == 0 then return #nodes end
|
local content = deserialize_workaround(content)
|
||||||
|
local pos2 = {
|
||||||
|
x = origin_pos.x + tonumber(header[1]) - 1,
|
||||||
|
y = origin_pos.y + tonumber(header[2]) - 1,
|
||||||
|
z = origin_pos.z + tonumber(header[3]) - 1,
|
||||||
|
}
|
||||||
|
worldedit.keep_loaded(origin_pos, pos2)
|
||||||
|
|
||||||
local pos1, pos2 = worldedit.allocate_with_nodes(origin_pos, nodes)
|
return worldedit.deserialize_with_content(origin_pos, content)
|
||||||
worldedit.keep_loaded(pos1, pos2)
|
else
|
||||||
|
local nodes = legacy_load_schematic(version, header, content)
|
||||||
|
if not nodes or #nodes == 0 then return nil end
|
||||||
|
|
||||||
local origin_x, origin_y, origin_z = origin_pos.x, origin_pos.y, origin_pos.z
|
local pos1, pos2 = worldedit.legacy_allocate_with_nodes(origin_pos, nodes)
|
||||||
local add_node, get_meta = minetest.add_node, minetest.get_meta
|
worldedit.keep_loaded(pos1, pos2)
|
||||||
for i, entry in ipairs(nodes) do
|
|
||||||
entry.x, entry.y, entry.z = origin_x + entry.x, origin_y + entry.y, origin_z + entry.z
|
local origin_x, origin_y, origin_z = origin_pos.x, origin_pos.y, origin_pos.z
|
||||||
-- Entry acts as both position and node
|
local count = 0
|
||||||
add_node(entry, entry)
|
local add_node, get_meta = minetest.add_node, minetest.get_meta
|
||||||
if entry.meta then
|
for i, entry in ipairs(nodes) do
|
||||||
get_meta(entry):from_table(entry.meta)
|
entry.x, entry.y, entry.z = origin_x + entry.x, origin_y + entry.y, origin_z + entry.z
|
||||||
|
-- Entry acts as both position and node
|
||||||
|
add_node(entry, entry)
|
||||||
|
if entry.meta then
|
||||||
|
get_meta(entry):from_table(entry.meta)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
return #nodes
|
||||||
end
|
end
|
||||||
return #nodes
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Internal
|
||||||
|
function worldedit.deserialize_with_content(origin_pos, content)
|
||||||
|
-- Helper functions
|
||||||
|
local function resolve_refs(array)
|
||||||
|
-- find (and cache) highest index
|
||||||
|
local max_i = 1
|
||||||
|
for i, _ in pairs(array) do
|
||||||
|
if i > max_i then max_i = i end
|
||||||
|
end
|
||||||
|
array.max_i = max_i
|
||||||
|
-- resolve references
|
||||||
|
local cache = {}
|
||||||
|
for i = 1, max_i do
|
||||||
|
local v = array[i]
|
||||||
|
if v ~= nil then
|
||||||
|
if type(v) == "number" and v < 0 then -- is a reference
|
||||||
|
array[i] = cache[#cache + v + 1]
|
||||||
|
else
|
||||||
|
cache[#cache + 1] = v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local function read_in_array(array, idx)
|
||||||
|
if idx > array.max_i then
|
||||||
|
return array[array.max_i]
|
||||||
|
end
|
||||||
|
-- go backwards until we find something
|
||||||
|
repeat
|
||||||
|
local v = array[idx]
|
||||||
|
if v ~= nil then
|
||||||
|
return v
|
||||||
|
end
|
||||||
|
idx = idx - 1
|
||||||
|
until idx == 0
|
||||||
|
assert(false)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Actually deserialize
|
||||||
|
local count = 0
|
||||||
|
local entry = {}
|
||||||
|
local add_node, get_meta = minetest.add_node, minetest.get_meta
|
||||||
|
for _, row in ipairs(content) do
|
||||||
|
local axis = row.a
|
||||||
|
local pos = {
|
||||||
|
x = origin_pos.x + row.p[1],
|
||||||
|
y = origin_pos.y + row.p[2],
|
||||||
|
z = origin_pos.z + row.p[3],
|
||||||
|
}
|
||||||
|
if row.param1 == nil then row.param1 = {0} end
|
||||||
|
if row.param2 == nil then row.param2 = {0} end
|
||||||
|
if row.meta == nil then row.meta = {} end
|
||||||
|
resolve_refs(row.data)
|
||||||
|
resolve_refs(row.param1)
|
||||||
|
resolve_refs(row.param2)
|
||||||
|
|
||||||
|
for i = 1, row.c do
|
||||||
|
entry.name = read_in_array(row.data, i)
|
||||||
|
entry.param1 = read_in_array(row.param1, i)
|
||||||
|
entry.param2 = read_in_array(row.param2, i)
|
||||||
|
add_node(pos, entry)
|
||||||
|
|
||||||
|
local meta = row.meta[i]
|
||||||
|
if meta then
|
||||||
|
get_meta(pos):from_table(meta)
|
||||||
|
end
|
||||||
|
|
||||||
|
pos[axis] = pos[axis] + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
count = count + row.c
|
||||||
|
end
|
||||||
|
return count
|
||||||
|
end
|
||||||
|
@ -1,602 +0,0 @@
|
|||||||
---------------------
|
|
||||||
-- Helpers
|
|
||||||
---------------------
|
|
||||||
|
|
||||||
local vec = vector.new
|
|
||||||
local vecw = function(axis, n, base)
|
|
||||||
local ret = vec(base)
|
|
||||||
ret[axis] = n
|
|
||||||
return ret
|
|
||||||
end
|
|
||||||
local pos2str = minetest.pos_to_string
|
|
||||||
local get_node = minetest.get_node
|
|
||||||
local set_node = minetest.set_node
|
|
||||||
|
|
||||||
---------------------
|
|
||||||
-- Nodes
|
|
||||||
---------------------
|
|
||||||
local air = "air"
|
|
||||||
local testnode1
|
|
||||||
local testnode2
|
|
||||||
local testnode3
|
|
||||||
-- Loads nodenames to use for tests
|
|
||||||
local function init_nodes()
|
|
||||||
testnode1 = minetest.registered_aliases["mapgen_stone"]
|
|
||||||
testnode2 = minetest.registered_aliases["mapgen_dirt"]
|
|
||||||
testnode3 = minetest.registered_aliases["mapgen_cobble"] or minetest.registered_aliases["mapgen_dirt_with_grass"]
|
|
||||||
assert(testnode1 and testnode2 and testnode3)
|
|
||||||
end
|
|
||||||
-- Writes repeating pattern into given area
|
|
||||||
local function place_pattern(pos1, pos2, pattern)
|
|
||||||
local pos = vec()
|
|
||||||
local node = {name=""}
|
|
||||||
local i = 1
|
|
||||||
for z = pos1.z, pos2.z do
|
|
||||||
pos.z = z
|
|
||||||
for y = pos1.y, pos2.y do
|
|
||||||
pos.y = y
|
|
||||||
for x = pos1.x, pos2.x do
|
|
||||||
pos.x = x
|
|
||||||
node.name = pattern[i]
|
|
||||||
set_node(pos, node)
|
|
||||||
i = i % #pattern + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
---------------------
|
|
||||||
-- Area management
|
|
||||||
---------------------
|
|
||||||
assert(minetest.get_mapgen_setting("mg_name") == "singlenode")
|
|
||||||
local area = {}
|
|
||||||
do
|
|
||||||
local areamin, areamax
|
|
||||||
local off
|
|
||||||
local c_air = minetest.get_content_id(air)
|
|
||||||
local vbuffer = {}
|
|
||||||
-- Assign a new area for use, will emerge and then call ready()
|
|
||||||
area.assign = function(min, max, ready)
|
|
||||||
areamin = min
|
|
||||||
areamax = max
|
|
||||||
minetest.emerge_area(min, max, function(bpos, action, remaining)
|
|
||||||
assert(action ~= minetest.EMERGE_ERRORED)
|
|
||||||
if remaining > 0 then return end
|
|
||||||
minetest.after(0, function()
|
|
||||||
area.clear()
|
|
||||||
ready()
|
|
||||||
end)
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
-- Reset area contents and state
|
|
||||||
area.clear = function()
|
|
||||||
local vmanip = minetest.get_voxel_manip(areamin, areamax)
|
|
||||||
local vpos1, vpos2 = vmanip:get_emerged_area()
|
|
||||||
local vcount = (vpos2.x - vpos1.x + 1) * (vpos2.y - vpos1.y + 1) * (vpos2.z - vpos1.z + 1)
|
|
||||||
if #vbuffer ~= vcount then
|
|
||||||
vbuffer = {}
|
|
||||||
for i = 1, vcount do
|
|
||||||
vbuffer[i] = c_air
|
|
||||||
end
|
|
||||||
end
|
|
||||||
vmanip:set_data(vbuffer)
|
|
||||||
vmanip:write_to_map()
|
|
||||||
off = vec(0, 0, 0)
|
|
||||||
end
|
|
||||||
-- Returns an usable area [pos1, pos2] that does not overlap previous ones
|
|
||||||
area.get = function(sizex, sizey, sizez)
|
|
||||||
local size
|
|
||||||
if sizey == nil and sizez == nil then
|
|
||||||
size = vector.new(sizex, sizex, sizex)
|
|
||||||
else
|
|
||||||
size = vector.new(sizex, sizey, sizez)
|
|
||||||
end
|
|
||||||
local pos1 = vector.add(areamin, off)
|
|
||||||
local pos2 = vector.subtract(vector.add(pos1, size), 1)
|
|
||||||
if pos2.x > areamax.x or pos2.y > areamax.y or pos2.z > areamax.z then
|
|
||||||
error("Internal failure: out of space")
|
|
||||||
end
|
|
||||||
off = vector.add(off, size)
|
|
||||||
return pos1, pos2
|
|
||||||
end
|
|
||||||
-- Returns an axis and count (= n) relative to the last-requested area that is unoccupied
|
|
||||||
area.dir = function(n)
|
|
||||||
local pos1 = vector.add(areamin, off)
|
|
||||||
if pos1.x + n <= areamax.x then
|
|
||||||
off.x = off.x + n
|
|
||||||
return "x", n
|
|
||||||
elseif pos1.x + n <= areamax.y then
|
|
||||||
off.y = off.y + n
|
|
||||||
return "y", n
|
|
||||||
elseif pos1.z + n <= areamax.z then
|
|
||||||
off.z = off.z + n
|
|
||||||
return "z", n
|
|
||||||
end
|
|
||||||
error("Internal failure: out of space")
|
|
||||||
end
|
|
||||||
-- Returns [XYZ] margin (list of pos pairs) of n around last-requested area
|
|
||||||
-- (may actually be larger but doesn't matter)
|
|
||||||
area.margin = function(n)
|
|
||||||
local pos1, pos2 = area.get(n)
|
|
||||||
return {
|
|
||||||
{ vec(areamin.x, areamin.y, pos1.z), pos2 }, -- X/Y
|
|
||||||
{ vec(areamin.x, pos1.y, areamin.z), pos2 }, -- X/Z
|
|
||||||
{ vec(pos1.x, areamin.y, areamin.z), pos2 }, -- Y/Z
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-- Split an existing area into two non-overlapping [pos1, half1], [half2, pos2] parts; returns half1, half2
|
|
||||||
area.split = function(pos1, pos2)
|
|
||||||
local axis
|
|
||||||
if pos2.x - pos1.x >= 1 then
|
|
||||||
axis = "x"
|
|
||||||
elseif pos2.y - pos1.y >= 1 then
|
|
||||||
axis = "y"
|
|
||||||
elseif pos2.z - pos1.z >= 1 then
|
|
||||||
axis = "z"
|
|
||||||
else
|
|
||||||
error("Internal failure: area too small to split")
|
|
||||||
end
|
|
||||||
local hspan = math.floor((pos2[axis] - pos1[axis] + 1) / 2)
|
|
||||||
local half1 = vecw(axis, pos1[axis] + hspan - 1, pos2)
|
|
||||||
local half2 = vecw(axis, pos1[axis] + hspan, pos2)
|
|
||||||
return half1, half2
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
---------------------
|
|
||||||
-- Checks
|
|
||||||
---------------------
|
|
||||||
local check = {}
|
|
||||||
-- Check that all nodes in [pos1, pos2] are the node(s) specified
|
|
||||||
check.filled = function(pos1, pos2, nodes)
|
|
||||||
if type(nodes) == "string" then
|
|
||||||
nodes = { nodes }
|
|
||||||
end
|
|
||||||
local _, counts = minetest.find_nodes_in_area(pos1, pos2, nodes)
|
|
||||||
local total = worldedit.volume(pos1, pos2)
|
|
||||||
local sum = 0
|
|
||||||
for _, n in pairs(counts) do
|
|
||||||
sum = sum + n
|
|
||||||
end
|
|
||||||
if sum ~= total then
|
|
||||||
error((total - sum) .. " " .. table.concat(nodes, ",") .. " nodes missing in " ..
|
|
||||||
pos2str(pos1) .. " -> " .. pos2str(pos2))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-- Check that none of the nodes in [pos1, pos2] are the node(s) specified
|
|
||||||
check.not_filled = function(pos1, pos2, nodes)
|
|
||||||
if type(nodes) == "string" then
|
|
||||||
nodes = { nodes }
|
|
||||||
end
|
|
||||||
local _, counts = minetest.find_nodes_in_area(pos1, pos2, nodes)
|
|
||||||
for nodename, n in pairs(counts) do
|
|
||||||
if n ~= 0 then
|
|
||||||
error(counts[nodename] .. " " .. nodename .. " nodes found in " ..
|
|
||||||
pos2str(pos1) .. " -> " .. pos2str(pos2))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-- Check that all of the areas are only made of node(s) specified
|
|
||||||
check.filled2 = function(list, nodes)
|
|
||||||
for _, pos in ipairs(list) do
|
|
||||||
check.filled(pos[1], pos[2], nodes)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-- Check that none of the areas contain the node(s) specified
|
|
||||||
check.not_filled2 = function(list, nodes)
|
|
||||||
for _, pos in ipairs(list) do
|
|
||||||
check.not_filled(pos[1], pos[2], nodes)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-- Checks presence of a repeating pattern in [pos1, po2] (cf. place_pattern)
|
|
||||||
check.pattern = function(pos1, pos2, pattern)
|
|
||||||
local pos = vec()
|
|
||||||
local i = 1
|
|
||||||
for z = pos1.z, pos2.z do
|
|
||||||
pos.z = z
|
|
||||||
for y = pos1.y, pos2.y do
|
|
||||||
pos.y = y
|
|
||||||
for x = pos1.x, pos2.x do
|
|
||||||
pos.x = x
|
|
||||||
local node = get_node(pos)
|
|
||||||
if node.name ~= pattern[i] then
|
|
||||||
error(pattern[i] .. " not found at " .. pos2str(pos) .. " (i=" .. i .. ")")
|
|
||||||
end
|
|
||||||
i = i % #pattern + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
---------------------
|
|
||||||
-- The actual tests
|
|
||||||
---------------------
|
|
||||||
local tests = {}
|
|
||||||
local function register_test(name, func, opts)
|
|
||||||
assert(type(name) == "string")
|
|
||||||
assert(func == nil or type(func) == "function")
|
|
||||||
if not opts then
|
|
||||||
opts = {}
|
|
||||||
else
|
|
||||||
opts = table.copy(opts)
|
|
||||||
end
|
|
||||||
opts.name = name
|
|
||||||
opts.func = func
|
|
||||||
table.insert(tests, opts)
|
|
||||||
end
|
|
||||||
-- How this works:
|
|
||||||
-- register_test registers a test with a name and function
|
|
||||||
-- The function should return if the test passes or otherwise cause a Lua error
|
|
||||||
-- The basic structure is: get areas + do operations + check results
|
|
||||||
-- Helpers:
|
|
||||||
-- area.get must be used to retrieve areas that can be operated on (these will be cleared before each test)
|
|
||||||
-- check.filled / check.not_filled can be used to check the result
|
|
||||||
-- area.margin + check.filled2 is useful to make sure nodes weren't placed too far
|
|
||||||
-- place_pattern + check.pattern is useful to test ops that operate on existing data
|
|
||||||
|
|
||||||
|
|
||||||
register_test("Internal self-test")
|
|
||||||
register_test("is area loaded?", function()
|
|
||||||
local pos1, _ = area.get(1)
|
|
||||||
assert(get_node(pos1).name == "air")
|
|
||||||
end, {dry=true})
|
|
||||||
|
|
||||||
register_test("area.split", function()
|
|
||||||
for i = 2, 6 do
|
|
||||||
local pos1, pos2 = area.get(1, 1, i)
|
|
||||||
local half1, half2 = area.split(pos1, pos2)
|
|
||||||
assert(pos1.x == half1.x and pos1.y == half1.y)
|
|
||||||
assert(half1.x == half2.x and half1.y == half2.y)
|
|
||||||
assert(half1.z + 1 == half2.z)
|
|
||||||
if i % 2 == 0 then
|
|
||||||
assert((half1.z - pos1.z) == (pos2.z - half2.z)) -- divided equally
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end, {dry=true})
|
|
||||||
|
|
||||||
register_test("check.filled", function()
|
|
||||||
local pos1, pos2 = area.get(1, 2, 1)
|
|
||||||
set_node(pos1, {name=testnode1})
|
|
||||||
set_node(pos2, {name=testnode2})
|
|
||||||
check.filled(pos1, pos1, testnode1)
|
|
||||||
check.filled(pos1, pos2, {testnode1, testnode2})
|
|
||||||
check.not_filled(pos1, pos1, air)
|
|
||||||
check.not_filled(pos1, pos2, {air, testnode3})
|
|
||||||
end)
|
|
||||||
|
|
||||||
register_test("pattern", function()
|
|
||||||
local pos1, pos2 = area.get(3, 2, 1)
|
|
||||||
local pattern = {testnode1, testnode3}
|
|
||||||
place_pattern(pos1, pos2, pattern)
|
|
||||||
assert(get_node(pos1).name == testnode1)
|
|
||||||
check.pattern(pos1, pos2, pattern)
|
|
||||||
end)
|
|
||||||
|
|
||||||
|
|
||||||
register_test("Generic node manipulations")
|
|
||||||
register_test("worldedit.set", function()
|
|
||||||
local pos1, pos2 = area.get(10)
|
|
||||||
local m = area.margin(1)
|
|
||||||
|
|
||||||
worldedit.set(pos1, pos2, testnode1)
|
|
||||||
|
|
||||||
check.filled(pos1, pos2, testnode1)
|
|
||||||
check.filled2(m, air)
|
|
||||||
end)
|
|
||||||
|
|
||||||
register_test("worldedit.set mix", function()
|
|
||||||
local pos1, pos2 = area.get(10)
|
|
||||||
local m = area.margin(1)
|
|
||||||
|
|
||||||
worldedit.set(pos1, pos2, {testnode1, testnode2})
|
|
||||||
|
|
||||||
check.filled(pos1, pos2, {testnode1, testnode2})
|
|
||||||
check.filled2(m, air)
|
|
||||||
end)
|
|
||||||
|
|
||||||
register_test("worldedit.replace", function()
|
|
||||||
local pos1, pos2 = area.get(10)
|
|
||||||
local half1, half2 = area.split(pos1, pos2)
|
|
||||||
|
|
||||||
worldedit.set(pos1, half1, testnode1)
|
|
||||||
worldedit.set(half2, pos2, testnode2)
|
|
||||||
worldedit.replace(pos1, pos2, testnode1, testnode3)
|
|
||||||
|
|
||||||
check.not_filled(pos1, pos2, testnode1)
|
|
||||||
check.filled(pos1, half1, testnode3)
|
|
||||||
check.filled(half2, pos2, testnode2)
|
|
||||||
end)
|
|
||||||
|
|
||||||
register_test("worldedit.replace inverse", function()
|
|
||||||
local pos1, pos2 = area.get(10)
|
|
||||||
local half1, half2 = area.split(pos1, pos2)
|
|
||||||
|
|
||||||
worldedit.set(pos1, half1, testnode1)
|
|
||||||
worldedit.set(half2, pos2, testnode2)
|
|
||||||
worldedit.replace(pos1, pos2, testnode1, testnode3, true)
|
|
||||||
|
|
||||||
check.filled(pos1, half1, testnode1)
|
|
||||||
check.filled(half2, pos2, testnode3)
|
|
||||||
end)
|
|
||||||
|
|
||||||
-- FIXME?: this one looks overcomplicated
|
|
||||||
register_test("worldedit.copy", function()
|
|
||||||
local pos1, pos2 = area.get(4)
|
|
||||||
local axis, n = area.dir(2)
|
|
||||||
local m = area.margin(1)
|
|
||||||
local b = pos1[axis]
|
|
||||||
|
|
||||||
-- create one slice with testnode1, one with testnode2
|
|
||||||
worldedit.set(pos1, vecw(axis, b + 1, pos2), testnode1)
|
|
||||||
worldedit.set(vecw(axis, b + 2, pos1), pos2, testnode2)
|
|
||||||
worldedit.copy(pos1, pos2, axis, n)
|
|
||||||
|
|
||||||
-- should have three slices now
|
|
||||||
check.filled(pos1, vecw(axis, b + 1, pos2), testnode1)
|
|
||||||
check.filled(vecw(axis, b + 2, pos1), pos2, testnode1)
|
|
||||||
check.filled(vecw(axis, b + 4, pos1), vector.add(pos2, vecw(axis, n)), testnode2)
|
|
||||||
check.filled2(m, "air")
|
|
||||||
end)
|
|
||||||
|
|
||||||
register_test("worldedit.copy2", function()
|
|
||||||
local pos1, pos2 = area.get(6)
|
|
||||||
local m1 = area.margin(1)
|
|
||||||
local pos1_, pos2_ = area.get(6)
|
|
||||||
local m2 = area.margin(1)
|
|
||||||
|
|
||||||
local pattern = {testnode1, testnode2, testnode3, testnode1, testnode2}
|
|
||||||
place_pattern(pos1, pos2, pattern)
|
|
||||||
worldedit.copy2(pos1, pos2, vector.subtract(pos1_, pos1))
|
|
||||||
|
|
||||||
check.pattern(pos1, pos2, pattern)
|
|
||||||
check.pattern(pos1_, pos2_, pattern)
|
|
||||||
check.filled2(m1, "air")
|
|
||||||
check.filled2(m2, "air")
|
|
||||||
end)
|
|
||||||
|
|
||||||
register_test("worldedit.move (overlap)", function()
|
|
||||||
local pos1, pos2 = area.get(7)
|
|
||||||
local axis, n = area.dir(2)
|
|
||||||
local m = area.margin(1)
|
|
||||||
|
|
||||||
local pattern = {testnode2, testnode1, testnode2, testnode3, testnode3}
|
|
||||||
place_pattern(pos1, pos2, pattern)
|
|
||||||
worldedit.move(pos1, pos2, axis, n)
|
|
||||||
|
|
||||||
check.filled(pos1, vecw(axis, pos1[axis] + n - 1, pos2), "air")
|
|
||||||
check.pattern(vecw(axis, pos1[axis] + n, pos1), vecw(axis, pos2[axis] + n, pos2), pattern)
|
|
||||||
check.filled2(m, "air")
|
|
||||||
end)
|
|
||||||
|
|
||||||
register_test("worldedit.move", function()
|
|
||||||
local pos1, pos2 = area.get(10)
|
|
||||||
local axis, n = area.dir(10)
|
|
||||||
local m = area.margin(1)
|
|
||||||
|
|
||||||
local pattern = {testnode1, testnode3, testnode3, testnode2}
|
|
||||||
place_pattern(pos1, pos2, pattern)
|
|
||||||
worldedit.move(pos1, pos2, axis, n)
|
|
||||||
|
|
||||||
check.filled(pos1, pos2, "air")
|
|
||||||
check.pattern(vecw(axis, pos1[axis] + n, pos1), vecw(axis, pos2[axis] + n, pos2), pattern)
|
|
||||||
check.filled2(m, "air")
|
|
||||||
end)
|
|
||||||
|
|
||||||
-- TODO: the rest (also testing param2 + metadata)
|
|
||||||
|
|
||||||
register_test("Schematics")
|
|
||||||
register_test("worldedit.read_header", function()
|
|
||||||
local value = '5,foo,BAR,-1,234:the content'
|
|
||||||
local version, header, content = worldedit.read_header(value)
|
|
||||||
assert(version == 5)
|
|
||||||
assert(#header == 4)
|
|
||||||
assert(header[1] == "foo" and header[2] == "BAR")
|
|
||||||
assert(header[3] == "-1" and header[4] == "234")
|
|
||||||
assert(content == "the content")
|
|
||||||
end)
|
|
||||||
|
|
||||||
register_test("worldedit.allocate", function()
|
|
||||||
local value = '3:-1 0 0 dummy 0 0\n0 0 4 dummy 0 0\n0 1 0 dummy 0 0'
|
|
||||||
local pos1, pos2, count = worldedit.allocate(vec(1, 1, 1), value)
|
|
||||||
assert(vector.equals(pos1, vec(0, 1, 1)))
|
|
||||||
assert(vector.equals(pos2, vec(1, 2, 5)))
|
|
||||||
assert(count == 3)
|
|
||||||
end)
|
|
||||||
|
|
||||||
do
|
|
||||||
local function output_weird(numbers, body)
|
|
||||||
local s = {"return {"}
|
|
||||||
for _, parts in ipairs(numbers) do
|
|
||||||
s[#s+1] = "{"
|
|
||||||
for _, n in ipairs(parts) do
|
|
||||||
s[#s+1] = string.format(" {%d},", n)
|
|
||||||
end
|
|
||||||
s[#s+1] = "},"
|
|
||||||
end
|
|
||||||
return table.concat(s, "\n") .. table.concat(body, "\n") .. "}"
|
|
||||||
end
|
|
||||||
local fmt1p = '{\n ["x"]=%d,\n ["y"]=%d,\n ["z"]=%d,\n},'
|
|
||||||
local fmt1n = '{\n ["name"]="%s",\n},'
|
|
||||||
local fmt4 = '{ ["x"] = %d, ["y"] = %d, ["z"] = %d, ["meta"] = { ["fields"] = { }, ["inventory"] = { } }, ["param2"] = 0, ["param1"] = 0, ["name"] = "%s" }'
|
|
||||||
local fmt5 = '{ ["x"] = %d, ["y"] = %d, ["z"] = %d, ["name"] = "%s" }'
|
|
||||||
local fmt51 = '{[r2]=0,x=%d,y=%d,z=%d,name=r%d}'
|
|
||||||
local fmt52 = '{x=%d,y=%d,z=%d,name=_[%d]}'
|
|
||||||
local test_data = {
|
|
||||||
-- used by WorldEdit 0.2 (first public release)
|
|
||||||
{
|
|
||||||
name = "v1", ver = 1,
|
|
||||||
gen = function(pat)
|
|
||||||
local numbers = {
|
|
||||||
{2, 3, 4, 5, 6},
|
|
||||||
{7, 8}, {9, 10}, {11, 12},
|
|
||||||
{13, 14}, {15, 16}
|
|
||||||
}
|
|
||||||
return output_weird(numbers, {
|
|
||||||
fmt1p:format(0, 0, 0),
|
|
||||||
fmt1n:format(pat[1]),
|
|
||||||
fmt1p:format(0, 1, 0),
|
|
||||||
fmt1n:format(pat[3]),
|
|
||||||
fmt1p:format(1, 1, 0),
|
|
||||||
fmt1n:format(pat[1]),
|
|
||||||
fmt1p:format(1, 0, 1),
|
|
||||||
fmt1n:format(pat[3]),
|
|
||||||
fmt1p:format(0, 1, 1),
|
|
||||||
fmt1n:format(pat[1]),
|
|
||||||
})
|
|
||||||
end
|
|
||||||
},
|
|
||||||
|
|
||||||
-- v2: missing because I couldn't find any code in my archives that actually wrote this format
|
|
||||||
|
|
||||||
{
|
|
||||||
name = "v3", ver = 3,
|
|
||||||
gen = function(pat)
|
|
||||||
assert(pat[2] == "air")
|
|
||||||
return table.concat({
|
|
||||||
"0 0 0 " .. pat[1] .. " 0 0",
|
|
||||||
"0 1 0 " .. pat[3] .. " 0 0",
|
|
||||||
"1 1 0 " .. pat[1] .. " 0 0",
|
|
||||||
"1 0 1 " .. pat[3] .. " 0 0",
|
|
||||||
"0 1 1 " .. pat[1] .. " 0 0",
|
|
||||||
}, "\n")
|
|
||||||
end
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
name = "v4", ver = 4,
|
|
||||||
gen = function(pat)
|
|
||||||
return table.concat({
|
|
||||||
"return { " .. fmt4:format(0, 0, 0, pat[1]),
|
|
||||||
fmt4:format(0, 1, 0, pat[3]),
|
|
||||||
fmt4:format(1, 1, 0, pat[1]),
|
|
||||||
fmt4:format(1, 0, 1, pat[3]),
|
|
||||||
fmt4:format(0, 1, 1, pat[1]) .. " }",
|
|
||||||
}, ", ")
|
|
||||||
end
|
|
||||||
},
|
|
||||||
|
|
||||||
-- like v4 but no meta and param (if empty)
|
|
||||||
{
|
|
||||||
name = "v5 (pre-5.6)", ver = 5,
|
|
||||||
gen = function(pat)
|
|
||||||
return table.concat({
|
|
||||||
"5:return { " .. fmt5:format(0, 0, 0, pat[1]),
|
|
||||||
fmt5:format(0, 1, 0, pat[3]),
|
|
||||||
fmt5:format(1, 1, 0, pat[1]),
|
|
||||||
fmt5:format(1, 0, 1, pat[3]),
|
|
||||||
fmt5:format(0, 1, 1, pat[1]) .. " }",
|
|
||||||
}, ", ")
|
|
||||||
end
|
|
||||||
},
|
|
||||||
|
|
||||||
-- reworked engine serialization in 5.6
|
|
||||||
{
|
|
||||||
name = "v5 (5.6)", ver = 5,
|
|
||||||
gen = function(pat)
|
|
||||||
return table.concat({
|
|
||||||
'5:r1="' .. pat[1] .. '";r2="param1";r3="' .. pat[3] .. '";return {'
|
|
||||||
.. fmt51:format(0, 0, 0, 1),
|
|
||||||
fmt51:format(0, 1, 0, 3),
|
|
||||||
fmt51:format(1, 1, 0, 1),
|
|
||||||
fmt51:format(1, 0, 1, 3),
|
|
||||||
fmt51:format(0, 1, 1, 1) .. "}",
|
|
||||||
}, ",")
|
|
||||||
end
|
|
||||||
},
|
|
||||||
|
|
||||||
-- small changes on engine side again
|
|
||||||
{
|
|
||||||
name = "v5 (post-5.7)", ver = 5,
|
|
||||||
gen = function(pat)
|
|
||||||
return table.concat({
|
|
||||||
'5:local _={};_[1]="' .. pat[1] .. '";_[3]="' .. pat[3] .. '";return {'
|
|
||||||
.. fmt52:format(0, 0, 0, 1),
|
|
||||||
fmt52:format(0, 1, 0, 3),
|
|
||||||
fmt52:format(1, 1, 0, 1),
|
|
||||||
fmt52:format(1, 0, 1, 3),
|
|
||||||
fmt52:format(0, 1, 1, 1) .. "}",
|
|
||||||
}, ",")
|
|
||||||
end
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, e in ipairs(test_data) do
|
|
||||||
register_test("worldedit.deserialize " .. e.name, function()
|
|
||||||
local pos1, pos2 = area.get(2)
|
|
||||||
local m = area.margin(1)
|
|
||||||
|
|
||||||
local pat = {testnode3, "air", testnode2}
|
|
||||||
local value = e.gen(pat)
|
|
||||||
assert(type(value) == "string")
|
|
||||||
|
|
||||||
local version = worldedit.read_header(value)
|
|
||||||
assert(version == e.ver, "version: got " .. tostring(version) .. " expected " .. e.ver)
|
|
||||||
local count = worldedit.deserialize(pos1, value)
|
|
||||||
assert(count ~= nil and count > 0)
|
|
||||||
|
|
||||||
check.pattern(pos1, pos2, pat)
|
|
||||||
check.filled2(m, "air")
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
---------------------
|
|
||||||
-- Main function
|
|
||||||
---------------------
|
|
||||||
worldedit.run_tests = function()
|
|
||||||
do
|
|
||||||
local v = minetest.get_version()
|
|
||||||
print("Running " .. #tests .. " tests for WorldEdit " ..
|
|
||||||
worldedit.version_string .. " on " .. v.project .. " " .. (v.hash or v.string))
|
|
||||||
end
|
|
||||||
|
|
||||||
init_nodes()
|
|
||||||
|
|
||||||
-- emerge area from (0,0,0) ~ (56,56,56) and keep it loaded
|
|
||||||
-- Note: making this area smaller speeds up tests
|
|
||||||
local wanted = vec(56, 56, 56)
|
|
||||||
for x = 0, math.floor(wanted.x/16) do
|
|
||||||
for y = 0, math.floor(wanted.y/16) do
|
|
||||||
for z = 0, math.floor(wanted.z/16) do
|
|
||||||
assert(minetest.forceload_block(vector.new(x*16, y*16, z*16), true))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
area.assign(vec(0, 0, 0), wanted, function()
|
|
||||||
|
|
||||||
local failed = 0
|
|
||||||
for _, test in ipairs(tests) do
|
|
||||||
if not test.func then
|
|
||||||
local s = "---- " .. test.name .. " "
|
|
||||||
print(s .. string.rep("-", 60 - #s))
|
|
||||||
else
|
|
||||||
if not test.dry then
|
|
||||||
area.clear()
|
|
||||||
end
|
|
||||||
local ok, err = pcall(test.func)
|
|
||||||
print(string.format("%-60s %s", test.name, ok and "pass" or "FAIL"))
|
|
||||||
if not ok then
|
|
||||||
print(" " .. err)
|
|
||||||
failed = failed + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
print("Done, " .. failed .. " tests failed.")
|
|
||||||
if failed == 0 then
|
|
||||||
io.close(io.open(minetest.get_worldpath() .. "/tests_ok", "w"))
|
|
||||||
end
|
|
||||||
minetest.request_shutdown()
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- for debug purposes
|
|
||||||
minetest.register_on_joinplayer(function(player)
|
|
||||||
minetest.set_player_privs(player:get_player_name(),
|
|
||||||
minetest.string_to_privs("fly,fast,noclip,basic_debug,debug,interact"))
|
|
||||||
end)
|
|
||||||
minetest.register_on_punchnode(function(pos, node, puncher)
|
|
||||||
minetest.chat_send_player(puncher:get_player_name(), pos2str(pos))
|
|
||||||
end)
|
|
BIN
worldedit/textures/worldedit_wand.png
Normal file
After Width: | Height: | Size: 442 B |
@ -19,7 +19,7 @@ function worldedit.hide(pos1, pos2)
|
|||||||
|
|
||||||
worldedit.keep_loaded(pos1, pos2)
|
worldedit.keep_loaded(pos1, pos2)
|
||||||
|
|
||||||
local pos = vector.new(pos1.x, 0, 0)
|
local pos = {x=pos1.x, y=0, z=0}
|
||||||
local get_node, get_meta, swap_node = minetest.get_node,
|
local get_node, get_meta, swap_node = minetest.get_node,
|
||||||
minetest.get_meta, minetest.swap_node
|
minetest.get_meta, minetest.swap_node
|
||||||
while pos.x <= pos2.x do
|
while pos.x <= pos2.x do
|
||||||
@ -79,7 +79,7 @@ function worldedit.highlight(pos1, pos2, node_name)
|
|||||||
|
|
||||||
worldedit.keep_loaded(pos1, pos2)
|
worldedit.keep_loaded(pos1, pos2)
|
||||||
|
|
||||||
local pos = vector.new(pos1.x, 0, 0)
|
local pos = {x=pos1.x, y=0, z=0}
|
||||||
local get_node, get_meta, swap_node = minetest.get_node,
|
local get_node, get_meta, swap_node = minetest.get_node,
|
||||||
minetest.get_meta, minetest.swap_node
|
minetest.get_meta, minetest.swap_node
|
||||||
local count = 0
|
local count = 0
|
||||||
|
@ -27,7 +27,7 @@ local brush_on_use = function(itemstack, placer)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local raybegin = vector.add(placer:get_pos(),
|
local raybegin = vector.add(placer:get_pos(),
|
||||||
vector.new(0, placer:get_properties().eye_height, 0))
|
{x=0, y=placer:get_properties().eye_height, z=0})
|
||||||
local rayend = vector.add(raybegin, vector.multiply(placer:get_look_dir(), BRUSH_MAX_DIST))
|
local rayend = vector.add(raybegin, vector.multiply(placer:get_look_dir(), BRUSH_MAX_DIST))
|
||||||
local ray = minetest.raycast(raybegin, rayend, false, true)
|
local ray = minetest.raycast(raybegin, rayend, false, true)
|
||||||
local pointed_thing = ray:next()
|
local pointed_thing = ray:next()
|
||||||
|
Before Width: | Height: | Size: 301 B After Width: | Height: | Size: 337 B |
@ -1,8 +1,6 @@
|
|||||||
local S = minetest.get_translator("worldedit_commands")
|
|
||||||
|
|
||||||
worldedit.register_command("outset", {
|
worldedit.register_command("outset", {
|
||||||
params = "[h/v] <amount>",
|
params = "[h/v] <amount>",
|
||||||
description = S("Outset the selected region."),
|
description = "Outset the selected region.",
|
||||||
privs = {worldedit=true},
|
privs = {worldedit=true},
|
||||||
require_pos = 2,
|
require_pos = 2,
|
||||||
parse = function(param)
|
parse = function(param)
|
||||||
@ -13,7 +11,7 @@ worldedit.register_command("outset", {
|
|||||||
|
|
||||||
local hv_test = dir:find("[^hv]+")
|
local hv_test = dir:find("[^hv]+")
|
||||||
if hv_test ~= nil then
|
if hv_test ~= nil then
|
||||||
return false, S("Invalid direction: @1", dir)
|
return false, "Invalid direction."
|
||||||
end
|
end
|
||||||
|
|
||||||
return true, dir, tonumber(amount)
|
return true, dir, tonumber(amount)
|
||||||
@ -30,18 +28,18 @@ worldedit.register_command("outset", {
|
|||||||
assert(worldedit.cuboid_linear_expand(name, 'y', 1, amount))
|
assert(worldedit.cuboid_linear_expand(name, 'y', 1, amount))
|
||||||
assert(worldedit.cuboid_linear_expand(name, 'y', -1, amount))
|
assert(worldedit.cuboid_linear_expand(name, 'y', -1, amount))
|
||||||
else
|
else
|
||||||
return false, S("Invalid number of arguments")
|
return false, "Invalid number of arguments"
|
||||||
end
|
end
|
||||||
|
|
||||||
worldedit.marker_update(name)
|
worldedit.marker_update(name)
|
||||||
return true, S("Region outset by @1 nodes", amount)
|
return true, "Region outset by " .. amount .. " blocks"
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
worldedit.register_command("inset", {
|
worldedit.register_command("inset", {
|
||||||
params = "[h/v] <amount>",
|
params = "[h/v] <amount>",
|
||||||
description = S("Inset the selected region."),
|
description = "Inset the selected region.",
|
||||||
privs = {worldedit=true},
|
privs = {worldedit=true},
|
||||||
require_pos = 2,
|
require_pos = 2,
|
||||||
parse = function(param)
|
parse = function(param)
|
||||||
@ -50,7 +48,7 @@ worldedit.register_command("inset", {
|
|||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
if dir:find("[^hv]") ~= nil then
|
if dir:find("[^hv]") ~= nil then
|
||||||
return false, S("Invalid direction: @1", dir)
|
return false, "Invalid direction."
|
||||||
end
|
end
|
||||||
|
|
||||||
return true, dir, tonumber(amount)
|
return true, dir, tonumber(amount)
|
||||||
@ -67,18 +65,18 @@ worldedit.register_command("inset", {
|
|||||||
assert(worldedit.cuboid_linear_expand(name, 'y', 1, -amount))
|
assert(worldedit.cuboid_linear_expand(name, 'y', 1, -amount))
|
||||||
assert(worldedit.cuboid_linear_expand(name, 'y', -1, -amount))
|
assert(worldedit.cuboid_linear_expand(name, 'y', -1, -amount))
|
||||||
else
|
else
|
||||||
return false, S("Invalid number of arguments")
|
return false, "Invalid number of arguments"
|
||||||
end
|
end
|
||||||
|
|
||||||
worldedit.marker_update(name)
|
worldedit.marker_update(name)
|
||||||
return true, S("Region inset by @1 nodes", amount)
|
return true, "Region inset by " .. amount .. " blocks"
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
worldedit.register_command("shift", {
|
worldedit.register_command("shift", {
|
||||||
params = "x/y/z/?/up/down/left/right/front/back [+/-]<amount>",
|
params = "x/y/z/?/up/down/left/right/front/back [+/-]<amount>",
|
||||||
description = S("Shifts the selection area without moving its contents"),
|
description = "Shifts the selection area without moving its contents",
|
||||||
privs = {worldedit=true},
|
privs = {worldedit=true},
|
||||||
require_pos = 2,
|
require_pos = 2,
|
||||||
parse = function(param)
|
parse = function(param)
|
||||||
@ -100,20 +98,20 @@ worldedit.register_command("shift", {
|
|||||||
end
|
end
|
||||||
|
|
||||||
if axis == nil or dir == nil then
|
if axis == nil or dir == nil then
|
||||||
return false, S("Invalid if looking straight up or down")
|
return false, "Invalid if looking straight up or down"
|
||||||
end
|
end
|
||||||
|
|
||||||
assert(worldedit.cuboid_shift(name, axis, amount * dir))
|
assert(worldedit.cuboid_shift(name, axis, amount * dir))
|
||||||
worldedit.marker_update(name)
|
worldedit.marker_update(name)
|
||||||
|
|
||||||
return true, S("Region shifted by @1 nodes", amount)
|
return true, "Region shifted by " .. amount .. " nodes"
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
worldedit.register_command("expand", {
|
worldedit.register_command("expand", {
|
||||||
params = "[+/-]x/y/z/?/up/down/left/right/front/back <amount> [reverse amount]",
|
params = "[+/-]x/y/z/?/up/down/left/right/front/back <amount> [reverse amount]",
|
||||||
description = S("Expands the selection in the selected absolute or relative axis"),
|
description = "Expands the selection in the selected absolute or relative axis",
|
||||||
privs = {worldedit=true},
|
privs = {worldedit=true},
|
||||||
require_pos = 2,
|
require_pos = 2,
|
||||||
parse = function(param)
|
parse = function(param)
|
||||||
@ -137,7 +135,7 @@ worldedit.register_command("expand", {
|
|||||||
axis, dir = worldedit.translate_direction(name, direction)
|
axis, dir = worldedit.translate_direction(name, direction)
|
||||||
|
|
||||||
if axis == nil or dir == nil then
|
if axis == nil or dir == nil then
|
||||||
return false, S("Invalid if looking straight up or down")
|
return false, "Invalid if looking straight up or down"
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
if direction == "?" then
|
if direction == "?" then
|
||||||
@ -155,14 +153,14 @@ worldedit.register_command("expand", {
|
|||||||
worldedit.cuboid_linear_expand(name, axis, dir, amount)
|
worldedit.cuboid_linear_expand(name, axis, dir, amount)
|
||||||
worldedit.cuboid_linear_expand(name, axis, -dir, rev_amount)
|
worldedit.cuboid_linear_expand(name, axis, -dir, rev_amount)
|
||||||
worldedit.marker_update(name)
|
worldedit.marker_update(name)
|
||||||
return true, S("Region expanded by @1 nodes", amount + rev_amount)
|
return true, "Region expanded by " .. (amount + rev_amount) .. " nodes"
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
worldedit.register_command("contract", {
|
worldedit.register_command("contract", {
|
||||||
params = "[+/-]x/y/z/?/up/down/left/right/front/back <amount> [reverse amount]",
|
params = "[+/-]x/y/z/?/up/down/left/right/front/back <amount> [reverse amount]",
|
||||||
description = S("Contracts the selection in the selected absolute or relative axis"),
|
description = "Contracts the selection in the selected absolute or relative axis",
|
||||||
privs = {worldedit=true},
|
privs = {worldedit=true},
|
||||||
require_pos = 2,
|
require_pos = 2,
|
||||||
parse = function(param)
|
parse = function(param)
|
||||||
@ -186,7 +184,7 @@ worldedit.register_command("contract", {
|
|||||||
axis, dir = worldedit.translate_direction(name, direction)
|
axis, dir = worldedit.translate_direction(name, direction)
|
||||||
|
|
||||||
if axis == nil or dir == nil then
|
if axis == nil or dir == nil then
|
||||||
return false, S("Invalid if looking straight up or down")
|
return false, "Invalid if looking straight up or down"
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
if direction == "?" then
|
if direction == "?" then
|
||||||
@ -204,13 +202,13 @@ worldedit.register_command("contract", {
|
|||||||
worldedit.cuboid_linear_expand(name, axis, dir, -amount)
|
worldedit.cuboid_linear_expand(name, axis, dir, -amount)
|
||||||
worldedit.cuboid_linear_expand(name, axis, -dir, -rev_amount)
|
worldedit.cuboid_linear_expand(name, axis, -dir, -rev_amount)
|
||||||
worldedit.marker_update(name)
|
worldedit.marker_update(name)
|
||||||
return true, S("Region contracted by @1 nodes", amount + rev_amount)
|
return true, "Region contracted by " .. (amount + rev_amount) .. " nodes"
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
worldedit.register_command("cubeapply", {
|
worldedit.register_command("cubeapply", {
|
||||||
params = "<size>/(<sizex> <sizey> <sizez>) <command> [parameters]",
|
params = "<size>/(<sizex> <sizey> <sizez>) <command> [parameters]",
|
||||||
description = S("Select a cube with side length <size> around position 1 and run <command> on region"),
|
description = "Select a cube with side length <size> around position 1 and run <command> on region",
|
||||||
privs = {worldedit=true},
|
privs = {worldedit=true},
|
||||||
require_pos = 1,
|
require_pos = 1,
|
||||||
parse = function(param)
|
parse = function(param)
|
||||||
@ -232,7 +230,7 @@ worldedit.register_command("cubeapply", {
|
|||||||
end
|
end
|
||||||
local cmddef = worldedit.registered_commands[cmd]
|
local cmddef = worldedit.registered_commands[cmd]
|
||||||
if cmddef == nil or cmddef.require_pos ~= 2 then
|
if cmddef == nil or cmddef.require_pos ~= 2 then
|
||||||
return false, S("invalid usage: //@1 cannot be used with cubeapply", cmd)
|
return false, "invalid usage: //" .. cmd .. " cannot be used with cubeapply"
|
||||||
end
|
end
|
||||||
-- run parsing of target command
|
-- run parsing of target command
|
||||||
local parsed = {cmddef.parse(args)}
|
local parsed = {cmddef.parse(args)}
|
||||||
@ -249,7 +247,8 @@ worldedit.register_command("cubeapply", {
|
|||||||
local cmddef = assert(worldedit.registered_commands[cmd])
|
local cmddef = assert(worldedit.registered_commands[cmd])
|
||||||
local success, missing_privs = minetest.check_player_privs(name, cmddef.privs)
|
local success, missing_privs = minetest.check_player_privs(name, cmddef.privs)
|
||||||
if not success then
|
if not success then
|
||||||
worldedit.player_notify(name, S("Missing privileges: @1", table.concat(missing_privs, ", ")))
|
worldedit.player_notify(name, "Missing privileges: " ..
|
||||||
|
table.concat(missing_privs, ", "))
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1,145 +0,0 @@
|
|||||||
# textdomain: worldedit_commands
|
|
||||||
Outset the selected region.=
|
|
||||||
Invalid direction: @1=
|
|
||||||
Invalid number of arguments=
|
|
||||||
Region outset by @1 nodes=
|
|
||||||
Inset the selected region.=
|
|
||||||
Region inset by @1 nodes=
|
|
||||||
Shifts the selection area without moving its contents=
|
|
||||||
Invalid if looking straight up or down=
|
|
||||||
Region shifted by @1 nodes=
|
|
||||||
Expands the selection in the selected absolute or relative axis=
|
|
||||||
Region expanded by @1 nodes=
|
|
||||||
Contracts the selection in the selected absolute or relative axis=
|
|
||||||
Region contracted by @1 nodes=
|
|
||||||
Select a cube with side length <size> around position 1 and run <command> on region=
|
|
||||||
invalid usage: //@1 cannot be used with cubeapply=
|
|
||||||
Missing privileges: @1=
|
|
||||||
Can use WorldEdit commands=
|
|
||||||
no region selected=
|
|
||||||
no position 1 selected=
|
|
||||||
invalid usage=
|
|
||||||
Could not open file "@1"=
|
|
||||||
Invalid file format!=
|
|
||||||
Schematic was created with a newer version of WorldEdit.=
|
|
||||||
Get information about the WorldEdit mod=
|
|
||||||
WorldEdit @1 is available on this server. Type //help to get a list of commands, or get more information at @2=
|
|
||||||
Get help for WorldEdit commands=
|
|
||||||
You are not allowed to use any WorldEdit commands.=
|
|
||||||
Available commands: @1@nUse '//help <cmd>' to get more information, or '//help all' to list everything.=
|
|
||||||
Available commands:@n=
|
|
||||||
Command not available: =
|
|
||||||
Enable or disable node inspection=
|
|
||||||
inspector: inspection enabled for @1, currently facing the @2 axis=
|
|
||||||
inspector: inspection disabled=
|
|
||||||
inspector: @1 at @2 (param1@=@3, param2@=@4, received light@=@5) punched facing the @6 axis=
|
|
||||||
Reset the region so that it is empty=
|
|
||||||
region reset=
|
|
||||||
Show markers at the region positions=
|
|
||||||
region marked=
|
|
||||||
Hide markers if currently shown=
|
|
||||||
region unmarked=
|
|
||||||
Set WorldEdit region position @1 to the player's location=
|
|
||||||
position @1 set to @2=
|
|
||||||
Set WorldEdit region, WorldEdit position 1, or WorldEdit position 2 by punching nodes, or display the current WorldEdit region=
|
|
||||||
unknown subcommand: @1=
|
|
||||||
select positions by punching two nodes=
|
|
||||||
select position @1 by punching a node=
|
|
||||||
position @1: @2=
|
|
||||||
position @1 not set=
|
|
||||||
Set a WorldEdit region position to the position at (<x>, <y>, <z>)=
|
|
||||||
Display the volume of the current WorldEdit region=
|
|
||||||
current region has a volume of @1 nodes (@2*@3*@4)=
|
|
||||||
Remove all MapBlocks (16x16x16) containing the selected area from the map=
|
|
||||||
Area deleted.=
|
|
||||||
There was an error during deletion of the area.=
|
|
||||||
Set the current WorldEdit region to <node>=
|
|
||||||
invalid node name: @1=
|
|
||||||
@1 nodes set=
|
|
||||||
Set param2 of all nodes in the current WorldEdit region to <param2>=
|
|
||||||
Param2 is out of range (must be between 0 and 255 inclusive!)=
|
|
||||||
@1 nodes altered=
|
|
||||||
Fill the current WorldEdit region with a random mix of <node1>, ...=
|
|
||||||
invalid search node name: @1=
|
|
||||||
invalid replace node name: @1=
|
|
||||||
Replace all instances of <search node> with <replace node> in the current WorldEdit region=
|
|
||||||
@1 nodes replaced=
|
|
||||||
Replace all nodes other than <search node> with <replace node> in the current WorldEdit region=
|
|
||||||
Add a hollow cube with its ground level centered at WorldEdit position 1 with dimensions <width> x <height> x <length>, composed of <node>.=
|
|
||||||
@1 nodes added=
|
|
||||||
Add a cube with its ground level centered at WorldEdit position 1 with dimensions <width> x <height> x <length>, composed of <node>.=
|
|
||||||
Add hollow sphere centered at WorldEdit position 1 with radius <radius>, composed of <node>=
|
|
||||||
Add sphere centered at WorldEdit position 1 with radius <radius>, composed of <node>=
|
|
||||||
Add hollow dome centered at WorldEdit position 1 with radius <radius>, composed of <node>=
|
|
||||||
Add dome centered at WorldEdit position 1 with radius <radius>, composed of <node>=
|
|
||||||
Add hollow cylinder at WorldEdit position 1 along the given axis with length <length>, base radius <radius1> (and top radius [radius2]), composed of <node>=
|
|
||||||
Add cylinder at WorldEdit position 1 along the given axis with length <length>, base radius <radius1> (and top radius [radius2]), composed of <node>=
|
|
||||||
Add hollow pyramid centered at WorldEdit position 1 along the given axis with height <height>, composed of <node>=
|
|
||||||
Add pyramid centered at WorldEdit position 1 along the given axis with height <height>, composed of <node>=
|
|
||||||
Add spiral centered at WorldEdit position 1 with side length <length>, height <height>, space between walls <space>, composed of <node>=
|
|
||||||
Copy the current WorldEdit region along the given axis by <amount> nodes=
|
|
||||||
@1 nodes copied=
|
|
||||||
Move the current WorldEdit region along the given axis by <amount> nodes=
|
|
||||||
@1 nodes moved=
|
|
||||||
Stack the current WorldEdit region along the given axis <count> times=
|
|
||||||
@1 nodes stacked=
|
|
||||||
Stack the current WorldEdit region <count> times by offset <x>, <y>, <z>=
|
|
||||||
invalid count: @1=
|
|
||||||
invalid increments: @1=
|
|
||||||
Scale the current WorldEdit positions and region by a factor of <stretchx>, <stretchy>, <stretchz> along the X, Y, and Z axes, repectively, with position 1 as the origin=
|
|
||||||
invalid scaling factors: @1=
|
|
||||||
@1 nodes stretched=
|
|
||||||
Transpose the current WorldEdit region along the given axes=
|
|
||||||
invalid usage: axes must be different=
|
|
||||||
@1 nodes transposed=
|
|
||||||
Flip the current WorldEdit region along the given axis=
|
|
||||||
@1 nodes flipped=
|
|
||||||
Rotate the current WorldEdit region around the given axis by angle <angle> (90 degree increment)=
|
|
||||||
invalid usage: angle must be multiple of 90=
|
|
||||||
@1 nodes rotated=
|
|
||||||
Rotate oriented nodes in the current WorldEdit region around the Y axis by angle <angle> (90 degree increment)=
|
|
||||||
@1 nodes oriented=
|
|
||||||
Fix the lighting in the current WorldEdit region=
|
|
||||||
@1 nodes updated=
|
|
||||||
Remove any fluid node within the current WorldEdit region=
|
|
||||||
Remove any plant, tree or foliage-like nodes in the selected region=
|
|
||||||
@1 nodes removed=
|
|
||||||
Hide all nodes in the current WorldEdit region non-destructively=
|
|
||||||
@1 nodes hidden=
|
|
||||||
Suppress all <node> in the current WorldEdit region non-destructively=
|
|
||||||
@1 nodes suppressed=
|
|
||||||
Highlight <node> in the current WorldEdit region by hiding everything else non-destructively=
|
|
||||||
@1 nodes highlighted=
|
|
||||||
Restores nodes hidden with WorldEdit in the current WorldEdit region=
|
|
||||||
@1 nodes restored=
|
|
||||||
Warning: The schematic contains excessive free space and WILL be misaligned when allocated or loaded. To avoid this, shrink your area to cover exactly the nodes to be saved.=
|
|
||||||
Save the current WorldEdit region to "(world folder)/schems/<file>.we"=
|
|
||||||
Disallowed file name: @1=
|
|
||||||
Could not save file to "@1"=
|
|
||||||
@1 nodes saved=
|
|
||||||
Set the region defined by nodes from "(world folder)/schems/<file>.we" as the current WorldEdit region=
|
|
||||||
Schematic empty, nothing allocated=
|
|
||||||
@1 nodes allocated=
|
|
||||||
Load nodes from "(world folder)/schems/<file>[.we[m]]" with position 1 of the current WorldEdit region as the origin=
|
|
||||||
Loading failed!=
|
|
||||||
@1 nodes loaded=
|
|
||||||
Executes <code> as a Lua chunk in the global namespace=
|
|
||||||
Executes <code> as a Lua chunk in the global namespace with the variable pos available, for each node in the current WorldEdit region=
|
|
||||||
Save the current WorldEdit region using the Minetest Schematic format to "(world folder)/schems/<filename>.mts"=
|
|
||||||
Failed to create Minetest schematic=
|
|
||||||
Saved Minetest schematic to @1=
|
|
||||||
Load nodes from "(world folder)/schems/<file>.mts" with position 1 of the current WorldEdit region as the origin=
|
|
||||||
failed to place Minetest schematic=
|
|
||||||
placed Minetest schematic @1 at @2=
|
|
||||||
Begins node probability entry for Minetest schematics, gets the nodes that have probabilities set, or ends node probability entry=
|
|
||||||
select Minetest schematic probability values by punching nodes=
|
|
||||||
finished Minetest schematic probability selection=
|
|
||||||
currently set node probabilities:=
|
|
||||||
invalid node probability given, not saved=
|
|
||||||
Clears all objects within the WorldEdit region=
|
|
||||||
@1 objects cleared=
|
|
||||||
WARNING: this operation could affect up to @1 nodes; type //y to continue or //n to cancel=
|
|
||||||
Confirm a pending operation=
|
|
||||||
no operation pending=
|
|
||||||
Abort a pending operation=
|
|
||||||
WorldEdit Wand tool@nLeft-click to set 1st position, right-click to set 2nd=
|
|
@ -1,156 +0,0 @@
|
|||||||
# textdomain: worldedit_commands
|
|
||||||
##
|
|
||||||
# Übersetzungshinweise:
|
|
||||||
# node = Block
|
|
||||||
# command = Befehl
|
|
||||||
# region = Gebiet
|
|
||||||
# position 1/2 = Position 1/2
|
|
||||||
# schematic = Schematic
|
|
||||||
# Der Anwender wird gesiezt.
|
|
||||||
# Diese Datei auf Rechtschreibfehler prüfen (unter Linux):
|
|
||||||
# sed -rne 's|^.*[^@]=(.*)$|\1|gp' worldedit_commands/locale/worldedit_commands.de.tr | sed -re 's/\b(WorldEdit|Schematic|Minetest)\b/Beispiel/g' | LANG=de_DE.UTF-8 hunspell -L
|
|
||||||
##
|
|
||||||
Outset the selected region.=Ausgewähltes Gebiet vergrößern.
|
|
||||||
Invalid direction: @1=Ungültige Richtung: @1
|
|
||||||
Invalid number of arguments=Ungültige Anzahl der Argumente
|
|
||||||
Region outset by @1 nodes=Gebiet um @1 Blöcke vergrößert
|
|
||||||
Inset the selected region.=Ausgewähltes Gebiet verkleinern.
|
|
||||||
Region inset by @1 nodes=Gebiet um @1 Blöcke verkleinert
|
|
||||||
Shifts the selection area without moving its contents=Verschiebt das ausgewählte Gebiet ohne dessen Inhalt
|
|
||||||
Invalid if looking straight up or down=Nicht zulässig bei gerade Blickrichtung nach unten oder oben
|
|
||||||
Region shifted by @1 nodes=Gebiet um @1 Blöcke verschoben
|
|
||||||
Expands the selection in the selected absolute or relative axis=Erweitert das Gebiet in Richtung einer absoluten oder relativen Achse
|
|
||||||
Region expanded by @1 nodes=Gebiet um @1 Blöcke erweitert
|
|
||||||
Contracts the selection in the selected absolute or relative axis=Schrumpft das Gebiet in Richtung einer absoluten oder relativen Achse
|
|
||||||
Region contracted by @1 nodes=Gebiet um @1 Blöcke geschrumpft
|
|
||||||
Select a cube with side length <size> around position 1 and run <command> on region=Wähle einen Würfel mit Seitenlänge <size> um Position 1 und führe <command> auf diesem Gebiet aus
|
|
||||||
invalid usage: //@1 cannot be used with cubeapply=Ungültige Verwendung: //@1 kann nicht mit cubeapply verwendet werden
|
|
||||||
Missing privileges: @1=Fehlende Privilegien: @1
|
|
||||||
Can use WorldEdit commands=Kann WorldEdit-Befehle benutzen
|
|
||||||
no region selected=Kein Gebiet ausgewählt
|
|
||||||
no position 1 selected=Keine Position 1 ausgewählt
|
|
||||||
invalid usage=Ungültige Verwendung
|
|
||||||
Could not open file "@1"=Konnte die Datei „@1“ nicht öffnen
|
|
||||||
Invalid file format!=Ungültiges Dateiformat!
|
|
||||||
Schematic was created with a newer version of WorldEdit.=Schematic wurde mit einer neueren Version von WorldEdit erstellt.
|
|
||||||
Get information about the WorldEdit mod=Informationen über den WorldEdit-Mod erhalten.
|
|
||||||
WorldEdit @1 is available on this server. Type //help to get a list of commands, or get more information at @2=WorldEdit @1 ist auf diesem Server verfügbar. Nutzen Sie //help, um eine Liste der Befehle zu erhalten, oder finden Sie weitere Informationen unter @2
|
|
||||||
Get help for WorldEdit commands=Hilfe für WorldEdit-Befehle erhalten
|
|
||||||
You are not allowed to use any WorldEdit commands.=Ihnen ist nicht erlaubt WorldEdit-Befehle zu nutzen.
|
|
||||||
Available commands: @1@nUse '//help <cmd>' to get more information, or '//help all' to list everything.=Verfügbare Befehle: @1@n„//help <Befehl>“ benutzen, um mehr Informationen zu erhalten, oder „//help all“, um alles aufzulisten.
|
|
||||||
Available commands:@n=Verfügbare Befehle:@n
|
|
||||||
Command not available: =Befehl nicht verfügbar:
|
|
||||||
Enable or disable node inspection=Inspizieren von Blöcken ein- oder ausschalten
|
|
||||||
inspector: inspection enabled for @1, currently facing the @2 axis=Inspektur: für @1 aktiviert, aktuell der @2-Achse zugewandt
|
|
||||||
inspector: inspection disabled=Inspektur: deaktiviert
|
|
||||||
inspector: @1 at @2 (param1@=@3, param2@=@4, received light@=@5) punched facing the @6 axis=Inspektur: @1 bei @2 (param1@=@3, param2@=@4, einfallendes Licht@=@5), der @6-Achse zugewandt, gehauen
|
|
||||||
Reset the region so that it is empty=Gebiet zurücksetzen, sodass es leer ist
|
|
||||||
region reset=Gebiet zurückgesetzt
|
|
||||||
Show markers at the region positions=Markierungen bei den Gebietsposition anzeigen
|
|
||||||
region marked=Gebiet markiert
|
|
||||||
Hide markers if currently shown=Markierungen verstecken falls derzeit sichtbar
|
|
||||||
region unmarked=Gebiet nicht mehr markiert
|
|
||||||
Set WorldEdit region position @1 to the player's location=Position @1 des WorldEdit-Gebiets auf die Position des Spieler setzen
|
|
||||||
position @1 set to @2=Position @1 auf @2 gesetzt
|
|
||||||
Set WorldEdit region, WorldEdit position 1, or WorldEdit position 2 by punching nodes, or display the current WorldEdit region=
|
|
||||||
unknown subcommand: @1=Unbekannter Unterbefehl: @1
|
|
||||||
select positions by punching two nodes=Wählen Sie die Position durch Hauen zweier Blöcke
|
|
||||||
select position @1 by punching a node=Wählen Sie Position @1 durch Hauen eines Blocks
|
|
||||||
position @1: @2=Position @1: @2
|
|
||||||
position @1 not set=Position @1 ist nicht gesetzt
|
|
||||||
Set a WorldEdit region position to the position at (<x>, <y>, <z>)=Position des WorldEdit-Gebiets auf (<x>, <y>, <z>) setzen
|
|
||||||
Display the volume of the current WorldEdit region=Volumen des aktuellen WorldEdit-Gebiets anzeigen
|
|
||||||
current region has a volume of @1 nodes (@2*@3*@4)=Das aktuelle Gebiet hat ein Volumen von @1 Blöcken (@2*@3*@4)
|
|
||||||
Remove all MapBlocks (16x16x16) containing the selected area from the map=Alle Kartenblöcke (16x16x16) entfernen, die das Gebiet enthalten.
|
|
||||||
Area deleted.=Gebiet gelöscht.
|
|
||||||
There was an error during deletion of the area.=Während des Löschens des Gebiets trat ein Fehler aus.
|
|
||||||
Set the current WorldEdit region to <node>=Das aktuelle WorldEdit-Gebiet mit <node> füllen
|
|
||||||
invalid node name: @1=Ungültiger Blockname: @1
|
|
||||||
@1 nodes set=@1 Blöcke gesetzt
|
|
||||||
Set param2 of all nodes in the current WorldEdit region to <param2>=Den param2 aller Blocke im aktuellen WorldEdit-Gebiet auf <param2> setzen
|
|
||||||
Param2 is out of range (must be between 0 and 255 inclusive!)=Param2 muss zwischen 0 und 255 (inklusiv) sein
|
|
||||||
@1 nodes altered=@1 Blöcke verändert
|
|
||||||
Fill the current WorldEdit region with a random mix of <node1>, ...=Das aktuelle WorldEdit-Gebiet mit einer zufälligen Mischung aus <node1>, ... füllen
|
|
||||||
invalid search node name: @1=Ungültiger Blockname für die Suche: @1
|
|
||||||
invalid replace node name: @1=Ungültiger Blockname für das Ersetzen: @1
|
|
||||||
Replace all instances of <search node> with <replace node> in the current WorldEdit region=Alle Vorkommen von <search node> im aktuellen WorldEdit-Gebiet mit <replace node> ersetzen
|
|
||||||
@1 nodes replaced=@1 Blöcke ersetzt
|
|
||||||
Replace all nodes other than <search node> with <replace node> in the current WorldEdit region=Alle Blöcke außer <search node> im aktuellen WorldEdit-Gebiet mit <replace node> ersetzen.
|
|
||||||
Add a hollow cube with its ground level centered at WorldEdit position 1 with dimensions <width> x <height> x <length>, composed of <node>.=
|
|
||||||
@1 nodes added=@1 Blöcke hinzugefügt
|
|
||||||
Add a cube with its ground level centered at WorldEdit position 1 with dimensions <width> x <height> x <length>, composed of <node>.=
|
|
||||||
Add hollow sphere centered at WorldEdit position 1 with radius <radius>, composed of <node>=
|
|
||||||
Add sphere centered at WorldEdit position 1 with radius <radius>, composed of <node>=
|
|
||||||
Add hollow dome centered at WorldEdit position 1 with radius <radius>, composed of <node>=
|
|
||||||
Add dome centered at WorldEdit position 1 with radius <radius>, composed of <node>=
|
|
||||||
Add hollow cylinder at WorldEdit position 1 along the given axis with length <length>, base radius <radius1> (and top radius [radius2]), composed of <node>=
|
|
||||||
Add cylinder at WorldEdit position 1 along the given axis with length <length>, base radius <radius1> (and top radius [radius2]), composed of <node>=
|
|
||||||
Add hollow pyramid centered at WorldEdit position 1 along the given axis with height <height>, composed of <node>=
|
|
||||||
Add pyramid centered at WorldEdit position 1 along the given axis with height <height>, composed of <node>=
|
|
||||||
Add spiral centered at WorldEdit position 1 with side length <length>, height <height>, space between walls <space>, composed of <node>=
|
|
||||||
Copy the current WorldEdit region along the given axis by <amount> nodes=Das aktuelle WorldEdit-Gebiet entlang der gegebenen Achse um <amount> Blöcke kopieren
|
|
||||||
@1 nodes copied=@1 Blöcke kopiert
|
|
||||||
Move the current WorldEdit region along the given axis by <amount> nodes=Das aktuelle WorldEdit-Gebiet entlang der gegebenen Achse um <amount> Blöcke verschieben
|
|
||||||
@1 nodes moved=@1 Blöcke verschoben
|
|
||||||
Stack the current WorldEdit region along the given axis <count> times=Das aktuelle WorldEdit-Gebiet entlang der gegebenen Achse <count>-mal stapeln
|
|
||||||
@1 nodes stacked=@1 Blöcke gestapelt
|
|
||||||
Stack the current WorldEdit region <count> times by offset <x>, <y>, <z>=Das aktuelle WorldEdit-Gebiet <count>-mal um <x>, <y>, <z> versetzt stapeln
|
|
||||||
invalid count: @1=Ungültige Anzahl: @1
|
|
||||||
invalid increments: @1=Ungültige Schrittweite: @1
|
|
||||||
Scale the current WorldEdit positions and region by a factor of <stretchx>, <stretchy>, <stretchz> along the X, Y, and Z axes, repectively, with position 1 as the origin=
|
|
||||||
invalid scaling factors: @1=Ungültige Skalierungsfaktoren: @1
|
|
||||||
@1 nodes stretched=@1 Blöcke gestreckt
|
|
||||||
Transpose the current WorldEdit region along the given axes=
|
|
||||||
invalid usage: axes must be different=Ungültige Verwendung: Achsen müssen verschieden sein
|
|
||||||
@1 nodes transposed=
|
|
||||||
Flip the current WorldEdit region along the given axis=
|
|
||||||
@1 nodes flipped=
|
|
||||||
Rotate the current WorldEdit region around the given axis by angle <angle> (90 degree increment)=
|
|
||||||
invalid usage: angle must be multiple of 90=Ungültige Verwendung: Winkel muss ein Vielfaches von 90 sein
|
|
||||||
@1 nodes rotated=@1 Blöcke gedreht
|
|
||||||
Rotate oriented nodes in the current WorldEdit region around the Y axis by angle <angle> (90 degree increment)=
|
|
||||||
@1 nodes oriented=
|
|
||||||
Fix the lighting in the current WorldEdit region=Belichtung im aktuellen WorldEdit-Gebiet korrigieren
|
|
||||||
@1 nodes updated=@1 Blöcke verändert
|
|
||||||
Remove any fluid node within the current WorldEdit region=Alle flüssigen Blöcke im WorldEdit-Gebiet entfernen
|
|
||||||
Remove any plant, tree or foliage-like nodes in the selected region=Alle Pflanzen, Baum oder Laub-ähnliche Blöcke im WorldEdit-Gebiet entfernen
|
|
||||||
@1 nodes removed=@1 Blöcke entfernt
|
|
||||||
Hide all nodes in the current WorldEdit region non-destructively=Alle Blöcke im WorldEdit-Gebiet zerstörungsfrei verstecken
|
|
||||||
@1 nodes hidden=@1 Blöcke versteckt
|
|
||||||
Suppress all <node> in the current WorldEdit region non-destructively=
|
|
||||||
@1 nodes suppressed=
|
|
||||||
Highlight <node> in the current WorldEdit region by hiding everything else non-destructively=Alle <node> Blöcke im WorldEdit-Gebiet hervorheben, indem alle anderen zerstörungsfrei versteckt werden
|
|
||||||
@1 nodes highlighted=@1 Blöcke hervorgehoben
|
|
||||||
Restores nodes hidden with WorldEdit in the current WorldEdit region=Versteckte Blöcke im WorldEdit-Gebiet wiederherstellen.
|
|
||||||
@1 nodes restored=@1 Blöcke wiederhergestellt
|
|
||||||
Warning: The schematic contains excessive free space and WILL be misaligned when allocated or loaded. To avoid this, shrink your area to cover exactly the nodes to be saved.=Warnung: Das Schematic hat überschüssigen freien Platz und WIRD nach dem Laden falsch ausgerichtet sein. Um dies zu vermeiden, verkleinern Sie das Gebiet sodass es die zu speichernden Blöcke exakt umfasst.
|
|
||||||
Save the current WorldEdit region to "(world folder)/schems/<file>.we"=Das aktuelle WorldEdit-Gebiet in "(Weltordner)/schems/<file>.we" speichern
|
|
||||||
Disallowed file name: @1=Nicht erlaubter Dateiname: @1
|
|
||||||
Could not save file to "@1"=Konnte die Datei nicht unter "@1" speichern
|
|
||||||
@1 nodes saved=@1 Blöcke gespeichert
|
|
||||||
Set the region defined by nodes from "(world folder)/schems/<file>.we" as the current WorldEdit region=Das aktuelle WorldEdit-Gebiet anhand der Blöcke in "(Weltordner)/schems/<file>.we" setzen
|
|
||||||
Schematic empty, nothing allocated=Schematic leer, nichts reserviert
|
|
||||||
@1 nodes allocated=@1 Blöcke reserviert
|
|
||||||
Load nodes from "(world folder)/schems/<file>[.we[m]]" with position 1 of the current WorldEdit region as the origin=Blöcke aus "(Weltordner)/schems/<file>[.we[m]]" mit Position 1 als Ausgangspunkt laden
|
|
||||||
Loading failed!=Laden fehlgeschlagen!
|
|
||||||
@1 nodes loaded=@1 Blöcke geladen
|
|
||||||
Executes <code> as a Lua chunk in the global namespace=
|
|
||||||
Executes <code> as a Lua chunk in the global namespace with the variable pos available, for each node in the current WorldEdit region=
|
|
||||||
Save the current WorldEdit region using the Minetest Schematic format to "(world folder)/schems/<filename>.mts"=Das aktuelle WorldEdit-Gebiet als Minetest-Schematic in "(Weltordner)/schems/<filename>.mts" speichern
|
|
||||||
Failed to create Minetest schematic=Konnte Minetest-Schematic nicht erstellen
|
|
||||||
Saved Minetest schematic to @1=Minetest-Schematic in @1 gespeichert
|
|
||||||
Load nodes from "(world folder)/schems/<file>.mts" with position 1 of the current WorldEdit region as the origin=Blöcke aus "(Weltordner)/schems/<file>.mts" mit Position 1 als Ausgangspunkt laden
|
|
||||||
failed to place Minetest schematic=Konnte Minetest-Schematic nicht platzieren
|
|
||||||
placed Minetest schematic @1 at @2=Minetest-Schematic @1 bei @2 platziert
|
|
||||||
Begins node probability entry for Minetest schematics, gets the nodes that have probabilities set, or ends node probability entry=
|
|
||||||
select Minetest schematic probability values by punching nodes=
|
|
||||||
finished Minetest schematic probability selection=
|
|
||||||
currently set node probabilities:=
|
|
||||||
invalid node probability given, not saved=
|
|
||||||
Clears all objects within the WorldEdit region=Löscht alle Objekte innerhalb des WorldEdit-Gebiets
|
|
||||||
@1 objects cleared=@1 Objekte gelöscht
|
|
||||||
WARNING: this operation could affect up to @1 nodes; type //y to continue or //n to cancel=WARNUNG: Dieser Vorgang könnte bis zu @1 Blöcke betreffen; //y zum Fortfahren oder //n zum Abbrechen
|
|
||||||
Confirm a pending operation=Einen ausstehenden Vorgang bestätigen
|
|
||||||
no operation pending=Kein Vorgang ausstehend
|
|
||||||
Abort a pending operation=Einen ausstehenden Vorgang abbrechen
|
|
||||||
WorldEdit Wand tool@nLeft-click to set 1st position, right-click to set 2nd=WorldEdit Zauberstab@nSetzen der 1. Position mit Linksklick, der 2. mit Rechtsklick
|
|
@ -1,155 +0,0 @@
|
|||||||
# textdomain: worldedit_commands
|
|
||||||
|
|
||||||
### init.lua ###
|
|
||||||
Can use WorldEdit commands=Возможность редактировать мир с помощью команд WorldEdit
|
|
||||||
|
|
||||||
no region selected=не выделен регион
|
|
||||||
no position 1 selected=не установлена позиция региона 1
|
|
||||||
invalid usage=не верное использование команды
|
|
||||||
Could not open file "@1"=Не удаётся открыть файл "@1"
|
|
||||||
Invalid file format!=Не верный формат файла!
|
|
||||||
Schematic was created with a newer version of WorldEdit.=Схема была создана с использованием более новой версии WorldEdit.
|
|
||||||
|
|
||||||
Get information about the WorldEdit mod=Вывести информацию о WorldEdit
|
|
||||||
WorldEdit @1 is available on this server. Type //help to get a list of commands, or get more information at @2=WorldEdit @1 доступен на этом сервере. Наберите команду //help чтобы увидеть список команд, больше информации по ссылке @2
|
|
||||||
Get help for WorldEdit commands=Вывести информацию об использовании команд WorldEdit
|
|
||||||
You are not allowed to use any WorldEdit commands.=У вас нет привилегий, чтобы использовать команды WorldEdit.
|
|
||||||
Available commands: @1@nUse '//help <cmd>' to get more information, or '//help all' to list everything.=Доступные команды: @1@nИспользуйте '//help <cmd>' для получения информации по команде или '//help all' для вывода подсказок по всем командам.
|
|
||||||
Available commands:@n=Доступные команды:@n
|
|
||||||
Command not available: =Команда не найдена:
|
|
||||||
Enable or disable node inspection=Включить/отключить инспекцию блоков
|
|
||||||
inspector: inspection enabled for @1, currently facing the @2 axis=inspector: инспекция включена для @1, текущий взор в направлении оси @2
|
|
||||||
inspector: inspection disabled=inspector: инспекция отключена
|
|
||||||
inspector: @1 at @2 (param1@=@3, param2@=@4, received light@=@5) punched facing the @6 axis=inspector: @1 в @2 (param1@=@3, param2@=@4, received light@=@5) ударен по поверхности @6
|
|
||||||
Reset the region so that it is empty=Сбросить выделение области
|
|
||||||
region reset=регион сброшен
|
|
||||||
Show markers at the region positions=Отобразить маркеры выделенной области
|
|
||||||
region marked=маркеры отображены
|
|
||||||
Hide markers if currently shown=Скрыть маркеры выделенной области
|
|
||||||
region unmarked=маркеры скрыты
|
|
||||||
Set WorldEdit region position @1 to the player's location=Установить маркер @1 для WorldEdit-региона в месте нахождения игрока
|
|
||||||
Set WorldEdit region, WorldEdit position 1, or WorldEdit position 2 by punching nodes, or display the current WorldEdit region=Выделить WorldEdit-регион или установить маркеры для WorldEdit-региона, либо отобразить уже выбранную область
|
|
||||||
unknown subcommand: @1=неизвестная подкоманда: @1
|
|
||||||
select positions by punching two nodes=выберите позиции, ударив по блокам
|
|
||||||
select position @1 by punching a node=выберите позицию @1, ударив по блоку
|
|
||||||
position @1: @2=позиция @1: @2
|
|
||||||
position @1 not set=позиция @1 не установлена
|
|
||||||
Set a WorldEdit region position to the position at (<x>, <y>, <z>)=Установить маркер для WorldEdit в позиции (<x>, <y>, <z>)
|
|
||||||
position @1 set to @2=позиция @1 установлена в @2
|
|
||||||
Display the volume of the current WorldEdit region=Вывести информацию об объёме текущей выделенной области WorldEdit (кол-во нод, размеры)
|
|
||||||
current region has a volume of @1 nodes (@2*@3*@4)=текущий регион имеет объем @1 нод (@2*@3*@4)
|
|
||||||
Remove all MapBlocks (16x16x16) containing the selected area from the map=Удалить MapBlocks (16x16x16), содержащие выбранную область
|
|
||||||
Area deleted.=Область удалена.
|
|
||||||
There was an error during deletion of the area.=Что-то пошло не так при удалении области.
|
|
||||||
Set the current WorldEdit region to <node>=Заполнить выбранный WorldEdit-регион указанным типом блоков
|
|
||||||
invalid node name: @1=неверное название блока: @1
|
|
||||||
@1 nodes set=@1 блок(а/ов) установленно
|
|
||||||
Set param2 of all nodes in the current WorldEdit region to <param2>=Проставить param2 для всех блоков в текущем WorldEdit-регионе
|
|
||||||
Param2 is out of range (must be between 0 and 255 inclusive!)=Значение param2 должно быть от 0 до 255 (включительно!)
|
|
||||||
@1 nodes altered=изменено @1 блок(а/ов)
|
|
||||||
Fill the current WorldEdit region with a random mix of <node1>, ...=Заполнить выбранный WorldEdit-регион смесью указанных типов блоков
|
|
||||||
invalid search node name: @1=неверное название блока-поиска: @1
|
|
||||||
invalid replace node name: @1=неверное название блока-замены: @1
|
|
||||||
Replace all instances of <search node> with <replace node> in the current WorldEdit region=Заменить все блоки <search node> на <replace node> в выбранной WorldEdit-области
|
|
||||||
@1 nodes replaced=заменено @1 нод(а/ы)
|
|
||||||
Replace all nodes other than <search node> with <replace node> in the current WorldEdit region=Заменить все блоки, кроме <search node>, на <replace node> в выбранной WorldEdit-области
|
|
||||||
Add a hollow cube with its ground level centered at WorldEdit position 1 with dimensions <width> x <height> x <length>, composed of <node>.=Установить полый куб с центром нижней грани в позиции 1 и указанными размерами, состоящий из блоков <node>.
|
|
||||||
@1 nodes added=добавлен(о) @1 блок(а/ов)
|
|
||||||
Add a cube with its ground level centered at WorldEdit position 1 with dimensions <width> x <height> x <length>, composed of <node>.=Установить куб с центром нижней грани в позиции 1 и указанными размерами, состоящий из блоков <node>.
|
|
||||||
Add hollow sphere centered at WorldEdit position 1 with radius <radius>, composed of <node>=Установить полую сферу с центром в WorldEdit-позиции 1 радиусом <radius>, состоящую из блоков <node>
|
|
||||||
Add sphere centered at WorldEdit position 1 with radius <radius>, composed of <node>=Установить сферу с центром в WorldEdit-позиции 1 радиусом <radius>, состоящую из блоков <node>
|
|
||||||
Add hollow dome centered at WorldEdit position 1 with radius <radius>, composed of <node>=Установить полый купол с центром в WorldEdit-позиции 1 радиусом <radius>, состоящий из блоков <node>
|
|
||||||
Add dome centered at WorldEdit position 1 with radius <radius>, composed of <node>=Установить купол с центром в WorldEdit-позиции 1 радиусом <radius>, состоящий из блоков <node>
|
|
||||||
Add hollow cylinder at WorldEdit position 1 along the given axis with length <length>, base radius <radius1> (and top radius [radius2]), composed of <node>=Установить полый цилиндр вдоль указанной оси, с центром в позиции 1, высотой/длинной <length>, с радиусом основания <radius> (и радиусом вершины [radius 2]), состоящий из блоков <node>
|
|
||||||
Add cylinder at WorldEdit position 1 along the given axis with length <length>, base radius <radius1> (and top radius [radius2]), composed of <node>=Установить цилиндр вдоль указанной оси, с центром в позиции 1, высотой/длинной <length>, с радиусом основания <radius> (и радиусом вершины [radius 2]), состоящий из блоков <node>
|
|
||||||
Add hollow pyramid centered at WorldEdit position 1 along the given axis with height <height>, composed of <node>=Установить полую пирамиду вдоль указанной оси, с центром в WorldEdit-позиции 1 высотой <height>, состоящую из блоков <node>
|
|
||||||
Add pyramid centered at WorldEdit position 1 along the given axis with height <height>, composed of <node>=Установить пирамиду вдоль указанной оси, с центром в WorldEdit-позиции 1 высотой <height>, состоящую из блоков <node>
|
|
||||||
Add spiral centered at WorldEdit position 1 with side length <length>, height <height>, space between walls <space>, composed of <node>=Установить спираль с центром в WorldEdit-позиции 1 шириной <length>, высотой <height> и с расстоянием между витками <space>, состоящую из блоков <node>
|
|
||||||
Copy the current WorldEdit region along the given axis by <amount> nodes=Копировать текущий WorldEdit-регион со смещением вдоль указанной оси (x/y/z) на <amount> блоков
|
|
||||||
@1 nodes copied=скопировано @1 нод(а/ы)
|
|
||||||
Move the current WorldEdit region along the given axis by <amount> nodes=Переместить текущий WorldEdit-регион вдоль указанной оси (x/y/z) на <amount> блоков
|
|
||||||
@1 nodes moved=перемещено @1 нод(а/ы)
|
|
||||||
Stack the current WorldEdit region along the given axis <count> times=Размножить текущий WorldEdit-регион вдоль указанной оси <count> раз
|
|
||||||
@1 nodes stacked=размножено @1 нод(а/ы)
|
|
||||||
Stack the current WorldEdit region <count> times by offset <x>, <y>, <z>=Размножить текущий WorldEdit-регион <count> раз с шагом <x>, <y>, <z> по соответствующим осям
|
|
||||||
invalid count: @1=неверное количество: @1
|
|
||||||
invalid increments: @1=неверные приращения(шаг)
|
|
||||||
Scale the current WorldEdit positions and region by a factor of <stretchx>, <stretchy>, <stretchz> along the X, Y, and Z axes, repectively, with position 1 as the origin=Масштабировать текущий WorldEdit-регион с коэффициентами <stretchx>, <stretchy>, <stretchz> вдоль осей X, Y и Z, используя WorldEdit-позицию 1 в качестве точки отсчёта
|
|
||||||
invalid scaling factors: @1=неверные коэффициенты масштабирования: @1
|
|
||||||
@1 nodes stretched=масштабировано @1 нод(а/ы)
|
|
||||||
Transpose the current WorldEdit region along the given axes=Транспонировать текущий WorldEdit-регион по заданным осям.
|
|
||||||
invalid usage: axes must be different=недопустимое использование: оси должны быть разными
|
|
||||||
@1 nodes transposed=транспонировано @1 нод(а/ы)
|
|
||||||
Flip the current WorldEdit region along the given axis=Перевернуть/Отразить текущий WorldEdit-регион вдоль указанной оси
|
|
||||||
@1 nodes flipped=отражено @1 нод(а/ы)
|
|
||||||
Rotate the current WorldEdit region around the given axis by angle <angle> (90 degree increment)=Повернуть текущий WorldEdit-регион вокруг оси <axis> на угол <angle> (шаг - 90 градусов)
|
|
||||||
invalid usage: angle must be multiple of 90=недопустимое использование: угол должен быть кратен 90
|
|
||||||
@1 nodes rotated=повёрнуто @1 нод(а/ы)
|
|
||||||
Rotate oriented nodes in the current WorldEdit region around the Y axis by angle <angle> (90 degree increment)=Повернуть блоки в текущем WorldEdit-регионе вокруг оси Y на угол <angle> (шаг - 90 градусов)
|
|
||||||
@1 nodes oriented=повёрнуто @1 нод(а/ы)
|
|
||||||
Fix the lighting in the current WorldEdit region=Исправить освещение в текущем WorldEdit-регионе
|
|
||||||
@1 nodes updated=обновлено @1 нод(а/ы)
|
|
||||||
Remove any fluid node within the current WorldEdit region=Удалить любые жидкости в текущем WorldEdit-регионе
|
|
||||||
Remove any plant, tree or foliage-like nodes in the selected region=Удалить любые растения, деревья или листье-подобные ноды в текущем WorldEdit-регионе
|
|
||||||
@1 nodes removed=удалено @1 нод(а/ы)
|
|
||||||
Hide all nodes in the current WorldEdit region non-destructively=Скрыть узлы текущего WorldEdit-региона, не удаляя их
|
|
||||||
@1 nodes hidden=скрыто @1 нод(а/ы)
|
|
||||||
Suppress all <node> in the current WorldEdit region non-destructively=Скрыть все блоки <node> в текущем WorldEdit-регионе, не удаляя их
|
|
||||||
@1 nodes suppressed=скрыто @1 нод(а/ы)
|
|
||||||
Highlight <node> in the current WorldEdit region by hiding everything else non-destructively=Скрыть все блоки, кроме <node>, в текущем WorldEdit-регионе, не удаляя их
|
|
||||||
@1 nodes highlighted="подсвечено" @1 нод(а/ы)
|
|
||||||
Restores nodes hidden with WorldEdit in the current WorldEdit region=Восстановить скрытые WorldEdit'ом узлы в текущем WorldEdit-регионе
|
|
||||||
@1 nodes restored=восстановлено @1 нод(а/ы)
|
|
||||||
Warning: The schematic contains excessive free space and WILL be misaligned when allocated or loaded. To avoid this, shrink your area to cover exactly the nodes to be saved.=Предупреждение: Схема содержит слишком много свободного места и будет смещена при размещении или загрузке. Чтобы избежать этого, уменьшите область так, чтобы она охватывала именно те узлы, которые необходимо сохранить.
|
|
||||||
Save the current WorldEdit region to "(world folder)/schems/<file>.we"=Сохранить текущий WorldEdit-регион в файл "(world folder)/schems/<file>.we"
|
|
||||||
Disallowed file name: @1=Недопустимое имя файла: @1
|
|
||||||
Could not save file to "@1"=Не удалось сохранить файл в "@1"
|
|
||||||
@1 nodes saved=сохранено @1 нод(а/ы)
|
|
||||||
Set the region defined by nodes from "(world folder)/schems/<file>.we" as the current WorldEdit region=Выделить область, определённую узлами из "(world folder)/schems/<file>.we", как текущий WorldEdit-регион
|
|
||||||
Schematic empty, nothing allocated=Схема пуста, ничего не выделено
|
|
||||||
@1 nodes allocated=выделено @1 нод(а/ы)
|
|
||||||
Load nodes from "(world folder)/schems/<file>[.we[m]]" with position 1 of the current WorldEdit region as the origin=Загрузить регион из "(world folder)/schems/<file>[.we[m]]" с WorldEdit-позицией 1 в качестве точки отсчёта
|
|
||||||
Loading failed!=Не удалось загрузить!
|
|
||||||
@1 nodes loaded=загружено @1 нод(а/ы)
|
|
||||||
Executes <code> as a Lua chunk in the global namespace=Выполнить <code> как Lua-код в глобальном пространстве имён
|
|
||||||
Executes <code> as a Lua chunk in the global namespace with the variable pos available, for each node in the current WorldEdit region=Выполнить <code> как Lua-код в глобальном пространстве имён, с доступом к переменным позиций для каждого блока в текущем WordEdit-регионе
|
|
||||||
Save the current WorldEdit region using the Minetest Schematic format to "(world folder)/schems/<filename>.mts"=Сохранить текущий WorldEdit-регион с использованием сжатия в формат Minetest Schematic в файл "(world folder)/schems/<filename>.mts"
|
|
||||||
Failed to create Minetest schematic=Не удалось создать Minetest-схему
|
|
||||||
Saved Minetest schematic to @1=Minetest-схема сохранена в @1
|
|
||||||
Load nodes from "(world folder)/schems/<file>.mts" with position 1 of the current WorldEdit region as the origin=Загрузить блоки из "(world folder)/schems/<file>.mts" с WorldEdit-позицией 1 в качестве точки отсчёта
|
|
||||||
failed to place Minetest schematic=не удалось загрузить Minetest-схему
|
|
||||||
placed Minetest schematic @1 at @2=Minetest-схема @1 загружена в @2
|
|
||||||
Begins node probability entry for Minetest schematics, gets the nodes that have probabilities set, or ends node probability entry=Начать запись вероятностей для Minetest Schematic, ударяя по блокам, закончить запись вероятностей или вывести уже записанные вероятности
|
|
||||||
select Minetest schematic probability values by punching nodes=выберите значения вероятностей для Minetest-схемы, ударя по нодам
|
|
||||||
finished Minetest schematic probability selection=выбор вероятностей для Minetest-схемы завершен
|
|
||||||
currently set node probabilities:=заданные вероятности нод на данный момент:
|
|
||||||
invalid node probability given, not saved=недопустимая вероятность ноды, не сохранена
|
|
||||||
Clears all objects within the WorldEdit region=Очистить все объекты в текущем WorldEdit-регионе
|
|
||||||
@1 objects cleared=очищено @1 объектов
|
|
||||||
|
|
||||||
### safe.lua ###
|
|
||||||
WARNING: this operation could affect up to @1 nodes; type //y to continue or //n to cancel=ПРЕДУПРЕЖДЕНИЕ: эта операция может затронуть до @1 нод; введите //y для продолжения или //n для отмены
|
|
||||||
Confirm a pending operation=Подтвердить отложенную операцию
|
|
||||||
no operation pending=нет ожидающей операции
|
|
||||||
Abort a pending operation=Отклонить отложенную операцию
|
|
||||||
|
|
||||||
### cuboid.lua ###
|
|
||||||
Outset the selected region.=Расширить выделение региона.
|
|
||||||
Invalid direction: @1=Недопустимое направление: @1
|
|
||||||
Invalid number of arguments=Недопустимое количество аргументов
|
|
||||||
Region outset by @1 nodes=Регион расширен на @1 нод(у/ы)
|
|
||||||
Inset the selected region.=Сузить выделение региона.
|
|
||||||
Region inset by @1 nodes=Регион сужен на @1 нод(у/ы)
|
|
||||||
Shifts the selection area without moving its contents=Сдвинуть выделение региона без перемещения его содержимого
|
|
||||||
Invalid if looking straight up or down=Недопустимо, если смотреть прямо вверх или вниз
|
|
||||||
Region shifted by @1 nodes=Регион сдвинут на @1 нод(у/ы)
|
|
||||||
Expands the selection in the selected absolute or relative axis=Увеличить выделение региона по выбранной абсолютной или относительной оси
|
|
||||||
Region expanded by @1 nodes=Регион увеличен на @1 нод(у/ы)
|
|
||||||
Contracts the selection in the selected absolute or relative axis=Уменьшить выделение региона по выбранной абсолютной или относительной оси
|
|
||||||
Region contracted by @1 nodes=Регион уменьшен на @1 нод(у/ы)
|
|
||||||
Select a cube with side length <size> around position 1 and run <command> on region=Выделить куб с длиной стороны <size> вокруг позиции 1 и запустите <команду> в области
|
|
||||||
invalid usage: //@1 cannot be used with cubeapply=недопустимое использование: //@1 не может быть применено в cubeapply
|
|
||||||
Missing privileges: @1=Отсутствуют привилегии: @1
|
|
||||||
|
|
||||||
### wand.lua ###
|
|
||||||
WorldEdit Wand tool@nLeft-click to set 1st position, right-click to set 2nd=Инструмент WorldEdit Wand@nЛевая кнопка мыши, чтобы установить 1-ю позицию, правая кнопка мыши, чтобы установить 2-ю
|
|
@ -6,7 +6,7 @@ local init_sentinel = "new" .. tostring(math.random(99999))
|
|||||||
|
|
||||||
--marks worldedit region position 1
|
--marks worldedit region position 1
|
||||||
worldedit.mark_pos1 = function(name, region_too)
|
worldedit.mark_pos1 = function(name, region_too)
|
||||||
local pos1 = worldedit.pos1[name]
|
local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]
|
||||||
|
|
||||||
if worldedit.marker1[name] ~= nil then --marker already exists
|
if worldedit.marker1[name] ~= nil then --marker already exists
|
||||||
worldedit.marker1[name]:remove() --remove marker
|
worldedit.marker1[name]:remove() --remove marker
|
||||||
@ -30,7 +30,7 @@ end
|
|||||||
|
|
||||||
--marks worldedit region position 2
|
--marks worldedit region position 2
|
||||||
worldedit.mark_pos2 = function(name, region_too)
|
worldedit.mark_pos2 = function(name, region_too)
|
||||||
local pos2 = worldedit.pos2[name]
|
local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]
|
||||||
|
|
||||||
if worldedit.marker2[name] ~= nil then --marker already exists
|
if worldedit.marker2[name] ~= nil then --marker already exists
|
||||||
worldedit.marker2[name]:remove() --remove marker
|
worldedit.marker2[name]:remove() --remove marker
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
local S = minetest.get_translator("worldedit_commands")
|
|
||||||
|
|
||||||
local safe_region_callback = {}
|
local safe_region_callback = {}
|
||||||
|
|
||||||
--`count` is the number of nodes that would possibly be modified
|
--`count` is the number of nodes that would possibly be modified
|
||||||
@ -11,7 +9,7 @@ local function safe_region(name, count, callback)
|
|||||||
|
|
||||||
--save callback to call later
|
--save callback to call later
|
||||||
safe_region_callback[name] = callback
|
safe_region_callback[name] = callback
|
||||||
worldedit.player_notify(name, S("WARNING: this operation could affect up to @1 nodes; type //y to continue or //n to cancel", count))
|
worldedit.player_notify(name, "WARNING: this operation could affect up to " .. count .. " nodes; type //y to continue or //n to cancel")
|
||||||
end
|
end
|
||||||
|
|
||||||
local function reset_pending(name)
|
local function reset_pending(name)
|
||||||
@ -20,11 +18,11 @@ end
|
|||||||
|
|
||||||
minetest.register_chatcommand("/y", {
|
minetest.register_chatcommand("/y", {
|
||||||
params = "",
|
params = "",
|
||||||
description = S("Confirm a pending operation"),
|
description = "Confirm a pending operation",
|
||||||
func = function(name)
|
func = function(name)
|
||||||
local callback = safe_region_callback[name]
|
local callback = safe_region_callback[name]
|
||||||
if not callback then
|
if not callback then
|
||||||
worldedit.player_notify(name, S("no operation pending"))
|
worldedit.player_notify(name, "no operation pending")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -35,10 +33,10 @@ minetest.register_chatcommand("/y", {
|
|||||||
|
|
||||||
minetest.register_chatcommand("/n", {
|
minetest.register_chatcommand("/n", {
|
||||||
params = "",
|
params = "",
|
||||||
description = S("Abort a pending operation"),
|
description = "Abort a pending operation",
|
||||||
func = function(name)
|
func = function(name)
|
||||||
if not safe_region_callback[name] then
|
if not safe_region_callback[name] then
|
||||||
worldedit.player_notify(name, S("no operation pending"))
|
worldedit.player_notify(name, "no operation pending")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Before Width: | Height: | Size: 79 B After Width: | Height: | Size: 147 B |
Before Width: | Height: | Size: 100 B After Width: | Height: | Size: 142 B |
Before Width: | Height: | Size: 112 B After Width: | Height: | Size: 157 B |
Before Width: | Height: | Size: 303 B |
@ -1,5 +1,3 @@
|
|||||||
local S = minetest.get_translator("worldedit_commands")
|
|
||||||
|
|
||||||
local function above_or_under(placer, pointed_thing)
|
local function above_or_under(placer, pointed_thing)
|
||||||
if placer:get_player_control().sneak then
|
if placer:get_player_control().sneak then
|
||||||
return pointed_thing.above
|
return pointed_thing.above
|
||||||
@ -11,7 +9,7 @@ end
|
|||||||
local punched_air_time = {}
|
local punched_air_time = {}
|
||||||
|
|
||||||
minetest.register_tool(":worldedit:wand", {
|
minetest.register_tool(":worldedit:wand", {
|
||||||
description = S("WorldEdit Wand tool\nLeft-click to set 1st position, right-click to set 2nd"),
|
description = "WorldEdit Wand tool\nLeft-click to set 1st position, right-click to set 2nd",
|
||||||
inventory_image = "worldedit_wand.png",
|
inventory_image = "worldedit_wand.png",
|
||||||
stack_max = 1, -- there is no need to have more than one
|
stack_max = 1, -- there is no need to have more than one
|
||||||
liquids_pointable = true, -- ground with only water on can be selected as well
|
liquids_pointable = true, -- ground with only water on can be selected as well
|
||||||
|
@ -140,7 +140,7 @@ local function execute_worldedit_command(command_name, player_name, params)
|
|||||||
assert(chatcmd, "unknown command: " .. command_name)
|
assert(chatcmd, "unknown command: " .. command_name)
|
||||||
local _, msg = chatcmd.func(player_name, params)
|
local _, msg = chatcmd.func(player_name, params)
|
||||||
if msg then
|
if msg then
|
||||||
worldedit.player_notify(player_name, msg)
|
worldedit.player_notify(player_name, msg)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -4,10 +4,10 @@ worldedit = worldedit or {}
|
|||||||
Example:
|
Example:
|
||||||
|
|
||||||
worldedit.register_gui_function("worldedit_gui_hollow_cylinder", {
|
worldedit.register_gui_function("worldedit_gui_hollow_cylinder", {
|
||||||
name = "Make Hollow Cylinder",
|
name = "Make Hollow Cylinder",
|
||||||
privs = {worldedit=true},
|
privs = {worldedit=true},
|
||||||
get_formspec = function(name) return "some formspec here" end,
|
get_formspec = function(name) return "some formspec here" end,
|
||||||
on_select = function(name) print(name .. " clicked the button!") end,
|
on_select = function(name) print(name .. " clicked the button!") end,
|
||||||
})
|
})
|
||||||
|
|
||||||
Use `nil` for the `options` parameter to unregister the function associated with the given identifier.
|
Use `nil` for the `options` parameter to unregister the function associated with the given identifier.
|
||||||
@ -35,14 +35,14 @@ end
|
|||||||
Example:
|
Example:
|
||||||
|
|
||||||
worldedit.register_gui_handler("worldedit_gui_hollow_cylinder", function(name, fields)
|
worldedit.register_gui_handler("worldedit_gui_hollow_cylinder", function(name, fields)
|
||||||
print(minetest.serialize(fields))
|
print(minetest.serialize(fields))
|
||||||
end)
|
end)
|
||||||
]]
|
]]
|
||||||
|
|
||||||
worldedit.register_gui_handler = function(identifier, handler)
|
worldedit.register_gui_handler = function(identifier, handler)
|
||||||
local enabled = true
|
local enabled = true
|
||||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||||
if not enabled or formname ~= "" or fields.worldedit_gui then return false end
|
if not enabled then return false end
|
||||||
enabled = false
|
enabled = false
|
||||||
minetest.after(0.2, function() enabled = true end)
|
minetest.after(0.2, function() enabled = true end)
|
||||||
local name = player:get_player_name()
|
local name = player:get_player_name()
|
||||||
@ -216,7 +216,7 @@ elseif minetest.global_exists("sfinv") then -- sfinv installed
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
return minetest.log("error",
|
error(
|
||||||
"worldedit_gui requires a supported gui management mod to be installed.\n"..
|
"worldedit_gui requires a supported gui management mod to be installed.\n"..
|
||||||
"To use the it you need to either:\n"..
|
"To use the it you need to either:\n"..
|
||||||
"* use minetest_game or another sfinv-compatible subgame\n"..
|
"* use minetest_game or another sfinv-compatible subgame\n"..
|
||||||
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 382 B After Width: | Height: | Size: 597 B |