mirror of
https://github.com/Uberi/Minetest-WorldEdit.git
synced 2025-06-29 22:50:46 +02:00
Compare commits
1 Commits
supports_m
...
master
Author | SHA1 | Date | |
---|---|---|---|
f10da8c9f6 |
@ -17,7 +17,6 @@ Many commands also have shorter names that can be typed faster. For example, if
|
||||
| `//s` | `//set` |
|
||||
| `//r` | `//replace` |
|
||||
| `//ri` | `//replaceinverse` |
|
||||
| `//hcube` | `//hollowcube` |
|
||||
| `//hspr` | `//hollowsphere` |
|
||||
| `//spr` | `//sphere` |
|
||||
| `//hdo` | `//hollowdome` |
|
||||
@ -117,20 +116,14 @@ Set the current WorldEdit region to `<node>`.
|
||||
//set Blue Lightstone
|
||||
//set dirt with grass
|
||||
|
||||
### `//param2 <param2>`
|
||||
### `//mix <node1> ...`
|
||||
|
||||
Set the param2 value of all nodes in the current WorldEdit region to `<param2>`.
|
||||
|
||||
### `//mix <node1> [<count1>] <node2> [<count2>]...`
|
||||
|
||||
Fill the current WorldEdit region with a random mix of `<node1>`, `<node2>`, `...`. Weightings can be optionally specified via a number after a node name.
|
||||
Fill the current WorldEdit region with a random mix of `<node1>`, `...`.
|
||||
|
||||
//mix air
|
||||
//mix cactus stone glass sandstone
|
||||
//mix Bronze
|
||||
//mix default:cobble air
|
||||
//mix stone 3 dirt 2
|
||||
//mix cobblestone 8 stoneblock 2 stonebrick
|
||||
|
||||
### `//replace <search node> <replace node>`
|
||||
|
||||
@ -150,19 +143,6 @@ Replace all nodes other than `<search node>` with `<replace node>` in the curren
|
||||
//replaceinverse dirt Bronze Block
|
||||
//replaceinverse mesecons:wire_00000000_off flowers:flower_tulip
|
||||
|
||||
### `//hollowcube <width> <height> <length> <node>`
|
||||
|
||||
Adds a hollow cube with its ground level centered at WorldEdit position 1 with dimensions `<width>` x `<height>` x `<length>`, composed of `<node>`.
|
||||
|
||||
//hollowcube 6 5 6 Diamond Block
|
||||
|
||||
### `//cube <width> <height> <length> <node>`
|
||||
|
||||
Adds a cube with its ground level centered at WorldEdit position 1 with dimensions `<width>` x `<height>` x `<length>`, composed of `<node>`.
|
||||
|
||||
//cube 6 5 6 Diamond Block
|
||||
//cube 7 2 1 default:cobble
|
||||
|
||||
### `//hollowsphere <radius> <node>`
|
||||
|
||||
Add hollow sphere centered at WorldEdit position 1 with radius `<radius>`, composed of `<node>`.
|
||||
@ -195,35 +175,23 @@ Add dome centered at WorldEdit position 1 with radius `<radius>`, composed of `<
|
||||
//dome -12 glass
|
||||
//dome 17 mesecons:wire_00000000_off
|
||||
|
||||
### `//hollowcylinder x/y/z/? <length> <radius1> [radius2] <node>`
|
||||
### `//hollowcylinder x/y/z/? <length> <radius> <node>`
|
||||
|
||||
Add hollow cylinder at WorldEdit position 1 along the x/y/z/? axis with length `<length>`, base radius `<radius1>` (and top radius `[radius2]`), composed of `<node>`.
|
||||
|
||||
Despite its name this command allows you to create cones (`radius2` = 0) as well as any shapes inbetween (0 < `radius2` < `radius1`).
|
||||
Swapping `radius1` and `radius2` will create the same object but upside-down.
|
||||
Add hollow cylinder at WorldEdit position 1 along the x/y/z/? axis with length `<length>` and radius `<radius>`, composed of `<node>`.
|
||||
|
||||
//hollowcylinder x +5 8 Bronze Block
|
||||
//hollowcylinder y 28 10 glass
|
||||
//hollowcylinder z -12 3 mesecons:wire_00000000_off
|
||||
//hollowcylinder ? 2 4 default:stone
|
||||
|
||||
//hollowcylinder y 10 10 0 walls:cobble
|
||||
//hollowcylinder x 6 0 5 Dirt
|
||||
//hollowcylinder z 20 10 20 default:desert_stone
|
||||
### `//cylinder x/y/z/? <length> <radius> <node>`
|
||||
|
||||
### `//cylinder x/y/z/? <length> <radius1> [radius2] <node>`
|
||||
|
||||
Add cylinder at WorldEdit position 1 along the x/y/z/? axis with length `<length>`, base radius `<radius1>` (and top radius `[radius2]`), composed of `<node>`.
|
||||
Can also create shapes other than cylinders, e.g. cones (see documentation above).
|
||||
Add cylinder at WorldEdit position 1 along the x/y/z/? axis with length `<length>` and radius `<radius>`, composed of `<node>`.
|
||||
|
||||
//cylinder x +5 8 Bronze Block
|
||||
//cylinder y 28 10 glass
|
||||
//cylinder z -12 3 mesecons:wire_00000000_off
|
||||
//cylinder ? 2 4 default:stone
|
||||
|
||||
//cylinder y 10 10 0 walls:cobble
|
||||
//cylinder x 6 0 5 Dirt
|
||||
//cylinder z 20 10 20 default:desert_stone
|
||||
|
||||
### `//hollowpyramid x/y/z? <height> <node>`
|
||||
|
||||
@ -285,13 +253,13 @@ Stack the current WorldEdit region `<count>` times by offset `<x>`, `<y>`, `<z>`
|
||||
//stack2 5 3 8 2
|
||||
//stack2 1 -1 -1 -1
|
||||
|
||||
### `//stretch <stretchx> <stretchy> <stretchz>`
|
||||
### `//scale <factor>`
|
||||
|
||||
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.
|
||||
Scale the current WorldEdit positions and region by a factor of positive integer `<factor>` with position 1 as the origin.
|
||||
|
||||
//stretch 2 2 2
|
||||
//stretch 1 2 1
|
||||
//stretch 10 20 1
|
||||
//scale 2
|
||||
//scale 1
|
||||
//scale 10
|
||||
|
||||
### `//transpose x/y/z/? x/y/z/?`
|
||||
|
||||
@ -464,15 +432,4 @@ or vertically in the y axis `[v]`.
|
||||
Contracts the selection in all directions by `<amount>`. If specified, the selection can be contracted horizontally in the x and z axes `[h]`
|
||||
or vertically in the y axis `[v]`.
|
||||
|
||||
//outset v 5
|
||||
|
||||
### `//brush none/<command> [parameters]`
|
||||
|
||||
Assigns the given `<command>` to the currently held brush item, it will be ran with the first pointed solid node (as determined via raycast) as
|
||||
WorldEdit position 1 when using that specific brush item.
|
||||
Passing `none` instead clears the command assigned to the currently held brush item.
|
||||
Note that this functionality requires the `worldedit_brush` mod enabled.
|
||||
|
||||
//brush cube 8 8 8 Cobblestone
|
||||
//brush spr 12 glass
|
||||
//brush none
|
||||
//outset v 5
|
0
LICENSE.txt
Normal file → Executable file
0
LICENSE.txt
Normal file → Executable file
21
README.md
Normal file → Executable file
21
README.md
Normal file → Executable file
@ -1,5 +1,5 @@
|
||||
WorldEdit v1.2
|
||||
==============
|
||||
WorldEdit v1.1 for Minetest 0.4.8+
|
||||
==================================
|
||||
The ultimate in-game world editing tool for [Minetest](http://minetest.net/)! Tons of functionality to help with building, fixing, and more.
|
||||
|
||||
For more information, see the [forum topic](https://forum.minetest.net/viewtopic.php?id=572) at the Minetest forums.
|
||||
@ -33,7 +33,7 @@ WorldEdit works primarily through the WorldEdit GUI and chat commands. Depending
|
||||
|
||||
WorldEdit has a huge potential for abuse by untrusted players. Therefore, users will not be able to use WorldEdit unless they have the `worldedit` privelege. This is available by default in single player, but in multiplayer the permission must be explicitly given by someone with the right credentials, using the follwoing chat command: `/grant <player name> worldedit`. This privelege can later be removed using the following chat command: `/revoke <player name> worldedit`.
|
||||
|
||||
Certain functions/commands such as WorldEdit `//lua` and `//luatransform` chat commands additionally require the `server` privilege. This is because it is extremely dangerous to give access to these commands to untrusted players, since they essentially are able to control the computer the server is running on. Give this privilege only to people you trust with your computer.
|
||||
Certain functions/commands such as WorldEdit GUI's "Run Lua" function (equivalent to the `//lua` and `//luatransform` chat command) additionally require the `server` privilege. This is because it is extremely dangerous to give access to these commands to untrusted players, since they essentially are able to control the computer the server is running on. Give this privilege only to people you trust with your computer.
|
||||
|
||||
For in-game information about these commands, type `/help <command name>` in the chat. For example, to learn more about the `//copy` command, simply type `/help /copy` to display information relevant to copying a region.
|
||||
|
||||
@ -51,19 +51,21 @@ This mod supports Minetest versions 0.4.8 and newer. Older versions of WorldEdit
|
||||
|
||||
WorldEdit works quite well with other mods, and does not have any known mod conflicts.
|
||||
|
||||
WorldEdit GUI requires one of [sfinv](https://github.com/minetest/minetest_game/tree/master/mods/sfinv) (included in minetest_game since 0.4.15), [Unified Inventory](https://forum.minetest.net/viewtopic.php?id=3933) or [Inventory++](https://forum.minetest.net/viewtopic.php?id=6204).
|
||||
WorldEdit GUI works with [Unified Inventory](https://forum.minetest.net/viewtopic.php?id=3933) and [Inventory++](https://forum.minetest.net/viewtopic.php?id=6204), but these are not required to use the mod.
|
||||
|
||||
If you use any other inventory manager mods, note that they may conflict with the WorldEdit GUI. If this is the case, it may be necessary to disable them.
|
||||
|
||||
WorldEdit API
|
||||
-------------
|
||||
WorldEdit exposes all significant functionality in a simple Lua interface.
|
||||
WorldEdit exposes all significant functionality in a simple Lua interface. Adding WorldEdit to the file "depends.txt" in your mod gives you access to all of the `worldedit` functions. The API is useful for tasks such as high-performance node manipulation, alternative interfaces, and map creation.
|
||||
|
||||
Adding WorldEdit to the file "depends.txt" in your mod gives you access to all of the `worldedit` functions. The API is useful for tasks such as high-performance node manipulation, alternative interfaces, and map creation.
|
||||
If you don't add WorldEdit to your "depends.txt" file, each file in the WorldEdit mod is also independent. For example, one may import the WorldEdit primitives API using the following code:
|
||||
|
||||
dofile(minetest.get_modpath("worldedit").."/primitives.lua")
|
||||
|
||||
AGPLv3 compatible mods may further include WorldEdit files in their own mods. This may be useful if a modder wishes to completely avoid any dependencies on WorldEdit. Note that it is required to give credit to the authors.
|
||||
|
||||
This API is documented in the [WorldEdit API Reference](WorldEdit%20API.md).
|
||||
This API is documented in the [WorldEdit API Reference](WorldEdit API.md).
|
||||
|
||||
Axes
|
||||
----
|
||||
@ -139,13 +141,9 @@ WorldEdit would not be possible without the contributions of many developers and
|
||||
cheapie
|
||||
cornernote
|
||||
cyisfor
|
||||
danierukun
|
||||
electricface
|
||||
est31
|
||||
kaeza
|
||||
khonkhortisan
|
||||
pickardjoe
|
||||
Sebastien Ponce
|
||||
sfan5
|
||||
ShadowNinja
|
||||
spillz
|
||||
@ -158,4 +156,5 @@ Copyright 2013 sfan5, Anthony Zhang (Uberi/Temperest), and Brett O'Donnell (corn
|
||||
This mod is licensed under the [GNU Affero General Public License](http://www.gnu.org/licenses/agpl-3.0.html).
|
||||
|
||||
Basically, this means everyone is free to use, modify, and distribute the files, as long as these modifications are also licensed the same way.
|
||||
|
||||
Most importantly, the Affero variant of the GPL requires you to publish your modifications in source form, even if the mod is run only on the server, and not distributed.
|
||||
|
0
Tutorial.md
Normal file → Executable file
0
Tutorial.md
Normal file → Executable file
@ -27,12 +27,6 @@ Sets a region defined by positions `pos1` and `pos2` to `node_name`. To clear a
|
||||
|
||||
Returns the number of nodes set.
|
||||
|
||||
### `count = worldedit.set_param2(pos1, pos2, param2)`
|
||||
|
||||
Sets the param2 values of all nodes in a region defined by positions `pos1` and `pos2` to `param2`.
|
||||
|
||||
Returns the number of nodes set.
|
||||
|
||||
### count = worldedit.replace(pos1, pos2, searchnode, replacenode)
|
||||
|
||||
Replaces all instances of `searchnode` with `replacenode` in a region defined by positions `pos1` and `pos2`.
|
||||
@ -121,12 +115,6 @@ Primitives
|
||||
----------
|
||||
Contained in primitives.lua, this module allows the creation of several geometric primitives.
|
||||
|
||||
### count = worldedit.cube(pos, width, height, length, node_name, hollow)
|
||||
|
||||
Adds a cube with its ground level centered at `pos`, the dimensions `width` x `height` x `length`, composed of `node_name`.
|
||||
|
||||
Returns the number of nodes added.
|
||||
|
||||
### count = worldedit.sphere(pos, radius, node_name, hollow)
|
||||
|
||||
Adds a sphere centered at `pos` with radius `radius`, composed of `node_name`.
|
||||
@ -139,9 +127,9 @@ Adds a dome centered at `pos` with radius `radius`, composed of `node_name`.
|
||||
|
||||
Returns the number of nodes added.
|
||||
|
||||
### count = worldedit.cylinder(pos, axis, length, radius1, radius2, node_name, hollow)
|
||||
### count = worldedit.cylinder(pos, axis, length, radius, node_name, hollow)
|
||||
|
||||
Adds a cylinder-like at `pos` along the `axis` axis ("x" or "y" or "z") with length `length`, base radius `radius1` and top radius `radius2`, composed of `node_name`.
|
||||
Adds a cylinder at `pos` along the `axis` axis ("x" or "y" or "z") with length `length` and radius `radius`, composed of `node_name`.
|
||||
|
||||
Returns the number of nodes added.
|
||||
|
||||
@ -193,7 +181,7 @@ Returns the number of nodes restored.
|
||||
|
||||
Serialization
|
||||
-------------
|
||||
Contained in serialization.lua, this module allows regions of nodes to be serialized and deserialized to formats suitable for use outside Minetest.
|
||||
Contained in serialization.lua, this module allows regions of nodes to be serialized and deserialized to formats suitable for use outside MineTest.
|
||||
|
||||
### version, extra_fields, content = worldedit.read_header(value)
|
||||
|
||||
|
0
modpack.txt
Normal file → Executable file
0
modpack.txt
Normal file → Executable file
0
worldedit/code.lua
Normal file → Executable file
0
worldedit/code.lua
Normal file → Executable file
0
worldedit/common.lua
Normal file → Executable file
0
worldedit/common.lua
Normal file → Executable file
0
worldedit/compatibility.lua
Normal file → Executable file
0
worldedit/compatibility.lua
Normal file → Executable file
11
worldedit/init.lua
Normal file → Executable file
11
worldedit/init.lua
Normal file → Executable file
@ -1,6 +1,6 @@
|
||||
--- Worldedit.
|
||||
-- @module worldedit
|
||||
-- @release 1.2
|
||||
-- @release 1.1
|
||||
-- @copyright 2013 sfan5, Anthony Zhang (Uberi/Temperest), and Brett O'Donnell (cornernote).
|
||||
-- @license GNU Affero General Public License version 3 (AGPLv3)
|
||||
-- @author sfan5
|
||||
@ -8,12 +8,9 @@
|
||||
-- @author Bret O'Donnel (cornernote)
|
||||
-- @author ShadowNinja
|
||||
|
||||
|
||||
worldedit = {}
|
||||
|
||||
local ver = {major=1, minor=2}
|
||||
worldedit.version = ver
|
||||
worldedit.version_string = string.format("%d.%d", ver.major, ver.minor)
|
||||
worldedit.version = {1, 1, major=1, minor=1}
|
||||
worldedit.version_string = table.concat(worldedit.version, ".")
|
||||
|
||||
if not minetest.get_voxel_manip then
|
||||
local err_msg = "This version of WorldEdit requires Minetest 0.4.8 or later! You have an old version."
|
||||
@ -42,7 +39,7 @@ load_module(path .. "/compatibility.lua")
|
||||
load_module(path .. "/cuboid.lua")
|
||||
|
||||
|
||||
if minetest.settings:get_bool("log_mods") then
|
||||
if minetest.setting_getbool("log_mods") then
|
||||
print("[WorldEdit] Loaded!")
|
||||
end
|
||||
|
||||
|
@ -38,29 +38,6 @@ function worldedit.set(pos1, pos2, node_names)
|
||||
return worldedit.volume(pos1, pos2)
|
||||
end
|
||||
|
||||
--- Sets param2 of a region.
|
||||
-- @param pos1
|
||||
-- @param pos2
|
||||
-- @param param2 Value of param2 to set
|
||||
-- @return The number of nodes set.
|
||||
function worldedit.set_param2(pos1, pos2, param2)
|
||||
pos1, pos2 = worldedit.sort_pos(pos1, pos2)
|
||||
|
||||
local manip, area = mh.init(pos1, pos2)
|
||||
local param2_data = manip:get_param2_data()
|
||||
|
||||
-- Set param2 for every node
|
||||
for i in area:iterp(pos1, pos2) do
|
||||
param2_data[i] = param2
|
||||
end
|
||||
|
||||
-- Update map
|
||||
manip:set_param2_data(param2_data)
|
||||
manip:write_to_map()
|
||||
manip:update_map()
|
||||
|
||||
return worldedit.volume(pos1, pos2)
|
||||
end
|
||||
|
||||
--- Replaces all instances of `search_node` with `replace_node` in a region.
|
||||
-- When `inverse` is `true`, replaces all instances that are NOT `search_node`.
|
||||
@ -301,7 +278,7 @@ function worldedit.stack(pos1, pos2, axis, count)
|
||||
local amount = 0
|
||||
local copy = worldedit.copy
|
||||
local i = 1
|
||||
local function next_one()
|
||||
function next_one()
|
||||
if i <= count then
|
||||
i = i + 1
|
||||
amount = amount + length
|
||||
@ -529,22 +506,20 @@ end
|
||||
-- @param pos2
|
||||
-- @param angle Angle in degrees (90 degree increments only).
|
||||
-- @return The number of nodes oriented.
|
||||
-- TODO: Support 6D facedir rotation along arbitrary axis.
|
||||
function worldedit.orient(pos1, pos2, angle)
|
||||
local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
|
||||
local registered_nodes = minetest.registered_nodes
|
||||
|
||||
local wallmounted = {
|
||||
[90] = {0, 1, 5, 4, 2, 3, 0, 0},
|
||||
[180] = {0, 1, 3, 2, 5, 4, 0, 0},
|
||||
[270] = {0, 1, 4, 5, 3, 2, 0, 0}
|
||||
[90] = {[0]=0, 1, 5, 4, 2, 3},
|
||||
[180] = {[0]=0, 1, 3, 2, 5, 4},
|
||||
[270] = {[0]=0, 1, 4, 5, 3, 2}
|
||||
}
|
||||
local facedir = {
|
||||
[90] = { 1, 2, 3, 0, 13, 14, 15, 12, 17, 18, 19, 16,
|
||||
9, 10, 11, 8, 5, 6, 7, 4, 23, 20, 21, 22},
|
||||
[180] = { 2, 3, 0, 1, 10, 11, 8, 9, 6, 7, 4, 5,
|
||||
18, 19, 16, 17, 14, 15, 12, 13, 22, 23, 20, 21},
|
||||
[270] = { 3, 0, 1, 2, 19, 16, 17, 18, 15, 12, 13, 14,
|
||||
7, 4, 5, 6, 11, 8, 9, 10, 21, 22, 23, 20}
|
||||
[90] = {[0]=1, 2, 3, 0},
|
||||
[180] = {[0]=2, 3, 0, 1},
|
||||
[270] = {[0]=3, 0, 1, 2}
|
||||
}
|
||||
|
||||
angle = angle % 360
|
||||
@ -560,7 +535,8 @@ function worldedit.orient(pos1, pos2, angle)
|
||||
worldedit.keep_loaded(pos1, pos2)
|
||||
|
||||
local count = 0
|
||||
local get_node, swap_node = minetest.get_node, minetest.swap_node
|
||||
local set_node, get_node, get_meta, swap_node = minetest.set_node,
|
||||
minetest.get_node, minetest.get_meta, minetest.swap_node
|
||||
local pos = {x=pos1.x, y=0, z=0}
|
||||
while pos.x <= pos2.x do
|
||||
pos.y = pos1.y
|
||||
@ -570,20 +546,17 @@ function worldedit.orient(pos1, pos2, angle)
|
||||
local node = get_node(pos)
|
||||
local def = registered_nodes[node.name]
|
||||
if def then
|
||||
local paramtype2 = def.paramtype2
|
||||
if paramtype2 == "wallmounted" or
|
||||
paramtype2 == "colorwallmounted" then
|
||||
local orient = node.param2 % 8
|
||||
node.param2 = node.param2 - orient +
|
||||
wallmounted_substitution[orient + 1]
|
||||
swap_node(pos, node)
|
||||
if def.paramtype2 == "wallmounted" then
|
||||
node.param2 = wallmounted_substitution[node.param2]
|
||||
local meta = get_meta(pos):to_table()
|
||||
set_node(pos, node)
|
||||
get_meta(pos):from_table(meta)
|
||||
count = count + 1
|
||||
elseif paramtype2 == "facedir" or
|
||||
paramtype2 == "colorfacedir" then
|
||||
local orient = node.param2 % 32
|
||||
node.param2 = node.param2 - orient +
|
||||
facedir_substitution[orient + 1]
|
||||
swap_node(pos, node)
|
||||
elseif def.paramtype2 == "facedir" then
|
||||
node.param2 = facedir_substitution[node.param2]
|
||||
local meta = get_meta(pos):to_table()
|
||||
set_node(pos, node)
|
||||
get_meta(pos):from_table(meta)
|
||||
count = count + 1
|
||||
end
|
||||
end
|
||||
|
@ -4,47 +4,6 @@
|
||||
local mh = worldedit.manip_helpers
|
||||
|
||||
|
||||
--- Adds a cube
|
||||
-- @param pos Position of ground level center of cube
|
||||
-- @param width Cube width. (x)
|
||||
-- @param height Cube height. (y)
|
||||
-- @param length Cube length. (z)
|
||||
-- @param node_name Name of node to make cube of.
|
||||
-- @param hollow Whether the cube should be hollow.
|
||||
-- @return The number of nodes added.
|
||||
function worldedit.cube(pos, width, height, length, node_name, hollow)
|
||||
-- Set up voxel manipulator
|
||||
local basepos = vector.subtract(pos, {x=math.floor(width/2), y=0, z=math.floor(length/2)})
|
||||
local manip, area = mh.init(basepos, vector.add(basepos, {x=width, y=height, z=length}))
|
||||
local data = mh.get_empty_data(area)
|
||||
|
||||
-- Add cube
|
||||
local node_id = minetest.get_content_id(node_name)
|
||||
local stride = {x=1, y=area.ystride, z=area.zstride}
|
||||
local offset = vector.subtract(basepos, area.MinEdge)
|
||||
local count = 0
|
||||
|
||||
for z = 0, length-1 do
|
||||
local index_z = (offset.z + z) * stride.z + 1 -- +1 for 1-based indexing
|
||||
for y = 0, height-1 do
|
||||
local index_y = index_z + (offset.y + y) * stride.y
|
||||
for x = 0, width-1 do
|
||||
local is_wall = z == 0 or z == length-1
|
||||
or y == 0 or y == height-1
|
||||
or x == 0 or x == width-1
|
||||
if not hollow or is_wall then
|
||||
local i = index_y + (offset.x + x)
|
||||
data[i] = node_id
|
||||
count = count + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
mh.finish(manip, data)
|
||||
return count
|
||||
end
|
||||
|
||||
--- Adds a sphere of `node_name` centered at `pos`.
|
||||
-- @param pos Position to center sphere at.
|
||||
-- @param radius Sphere radius.
|
||||
@ -133,60 +92,49 @@ end
|
||||
-- @param pos Position to center base of cylinder at.
|
||||
-- @param axis Axis ("x", "y", or "z")
|
||||
-- @param length Cylinder length.
|
||||
-- @param radius1 Cylinder base radius.
|
||||
-- @param radius2 Cylinder top radius.
|
||||
-- @param radius Cylinder radius.
|
||||
-- @param node_name Name of node to make cylinder of.
|
||||
-- @param hollow Whether the cylinder should be hollow.
|
||||
-- @return The number of nodes added.
|
||||
function worldedit.cylinder(pos, axis, length, radius1, radius2, node_name, hollow)
|
||||
function worldedit.cylinder(pos, axis, length, radius, node_name, hollow)
|
||||
local other1, other2 = worldedit.get_axis_others(axis)
|
||||
|
||||
-- Backwards compatibility
|
||||
if type(radius2) == "string" then
|
||||
hollow = node_name
|
||||
node_name = radius2
|
||||
radius2 = radius1 -- straight cylinder
|
||||
end
|
||||
|
||||
-- Handle negative lengths
|
||||
local current_pos = {x=pos.x, y=pos.y, z=pos.z}
|
||||
if length < 0 then
|
||||
length = -length
|
||||
current_pos[axis] = current_pos[axis] - length
|
||||
radius1, radius2 = radius2, radius1
|
||||
end
|
||||
|
||||
-- Set up voxel manipulator
|
||||
local manip, area = mh.init_axis_radius_length(current_pos, axis, math.max(radius1, radius2), length)
|
||||
local manip, area = mh.init_axis_radius_length(current_pos, axis, radius, length)
|
||||
local data = mh.get_empty_data(area)
|
||||
|
||||
-- Add desired shape (anything inbetween cylinder & cone)
|
||||
-- Add cylinder
|
||||
local node_id = minetest.get_content_id(node_name)
|
||||
local min_radius, max_radius = radius * (radius - 1), radius * (radius + 1)
|
||||
local stride = {x=1, y=area.ystride, z=area.zstride}
|
||||
local offset = {
|
||||
x = current_pos.x - area.MinEdge.x,
|
||||
y = current_pos.y - area.MinEdge.y,
|
||||
z = current_pos.z - area.MinEdge.z,
|
||||
}
|
||||
local min_slice, max_slice = offset[axis], offset[axis] + length - 1
|
||||
local count = 0
|
||||
for i = 0, length - 1 do
|
||||
-- Calulate radius for this "height" in the cylinder
|
||||
local radius = radius1 + (radius2 - radius1) * (i + 1) / length
|
||||
radius = math.floor(radius + 0.5) -- round
|
||||
local min_radius, max_radius = radius * (radius - 1), radius * (radius + 1)
|
||||
|
||||
for index2 = -radius, radius do
|
||||
-- Offset contributed by other axis 1 plus 1 to make it 1-indexed
|
||||
local new_index2 = (index2 + offset[other1]) * stride[other1] + 1
|
||||
for index3 = -radius, radius do
|
||||
local new_index3 = new_index2 + (index3 + offset[other2]) * stride[other2]
|
||||
local squared = index2 * index2 + index3 * index3
|
||||
if squared <= max_radius and (not hollow or squared >= min_radius) then
|
||||
-- Position is in cylinder, add node here
|
||||
local vi = new_index3 + (offset[axis] + i) * stride[axis]
|
||||
for index2 = -radius, radius do
|
||||
-- Offset contributed by other axis 1 plus 1 to make it 1-indexed
|
||||
local new_index2 = (index2 + offset[other1]) * stride[other1] + 1
|
||||
for index3 = -radius, radius do
|
||||
local new_index3 = new_index2 + (index3 + offset[other2]) * stride[other2]
|
||||
local squared = index2 * index2 + index3 * index3
|
||||
if squared <= max_radius and (not hollow or squared >= min_radius) then
|
||||
-- Position is in cylinder
|
||||
-- Add column along axis
|
||||
for index1 = min_slice, max_slice do
|
||||
local vi = new_index3 + index1 * stride[axis]
|
||||
data[vi] = node_id
|
||||
count = count + 1
|
||||
end
|
||||
count = count + length
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -208,13 +156,12 @@ function worldedit.pyramid(pos, axis, height, node_name, hollow)
|
||||
local other1, other2 = worldedit.get_axis_others(axis)
|
||||
|
||||
-- Set up voxel manipulator
|
||||
-- FIXME: passing negative <radius> causes mis-sorted pos to be passed
|
||||
-- into mh.init() which is technically not allowed but works
|
||||
local manip, area = mh.init_axis_radius(pos, axis, height)
|
||||
local manip, area = mh.init_axis_radius(pos, axis,
|
||||
height >= 0 and height or -height)
|
||||
local data = mh.get_empty_data(area)
|
||||
|
||||
-- Handle inverted pyramids
|
||||
local step
|
||||
local start_axis, end_axis, step
|
||||
if height > 0 then
|
||||
height = height - 1
|
||||
step = 1
|
||||
|
@ -56,19 +56,10 @@ function worldedit.serialize(pos1, pos2)
|
||||
|
||||
worldedit.keep_loaded(pos1, pos2)
|
||||
|
||||
local get_node, get_meta, hash_node_position =
|
||||
minetest.get_node, minetest.get_meta, minetest.hash_node_position
|
||||
|
||||
-- Find the positions which have metadata
|
||||
local has_meta = {}
|
||||
local meta_positions = minetest.find_nodes_with_meta(pos1, pos2)
|
||||
for i = 1, #meta_positions do
|
||||
has_meta[hash_node_position(meta_positions[i])] = true
|
||||
end
|
||||
|
||||
local pos = {x=pos1.x, y=0, z=0}
|
||||
local count = 0
|
||||
local result = {}
|
||||
local get_node, get_meta = minetest.get_node, minetest.get_meta
|
||||
while pos.x <= pos2.x do
|
||||
pos.y = pos1.y
|
||||
while pos.y <= pos2.y do
|
||||
@ -77,19 +68,20 @@ function worldedit.serialize(pos1, pos2)
|
||||
local node = get_node(pos)
|
||||
if node.name ~= "air" and node.name ~= "ignore" then
|
||||
count = count + 1
|
||||
local meta = get_meta(pos):to_table()
|
||||
|
||||
local meta
|
||||
if has_meta[hash_node_position(pos)] then
|
||||
meta = get_meta(pos):to_table()
|
||||
|
||||
-- Convert metadata item stacks to item strings
|
||||
for _, invlist in pairs(meta.inventory) do
|
||||
for index = 1, #invlist do
|
||||
local itemstack = invlist[index]
|
||||
if itemstack.to_string then
|
||||
invlist[index] = itemstack:to_string()
|
||||
end
|
||||
end
|
||||
local meta_empty = true
|
||||
-- Convert metadata item stacks to item strings
|
||||
for name, inventory in pairs(meta.inventory) do
|
||||
for index, stack in ipairs(inventory) do
|
||||
meta_empty = false
|
||||
inventory[index] = stack.to_string and stack:to_string() or stack
|
||||
end
|
||||
end
|
||||
for k in pairs(meta) do
|
||||
if k ~= "inventory" then
|
||||
meta_empty = false
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
@ -100,7 +92,7 @@ function worldedit.serialize(pos1, pos2)
|
||||
name = node.name,
|
||||
param1 = node.param1 ~= 0 and node.param1 or nil,
|
||||
param2 = node.param2 ~= 0 and node.param2 or nil,
|
||||
meta = meta,
|
||||
meta = not meta_empty and meta or nil,
|
||||
}
|
||||
end
|
||||
pos.z = pos.z + 1
|
||||
@ -196,7 +188,7 @@ end
|
||||
-- @return The number of nodes.
|
||||
function worldedit.allocate(origin_pos, value)
|
||||
local nodes = load_schematic(value)
|
||||
if not nodes or #nodes == 0 then return nil end
|
||||
if not nodes then return nil end
|
||||
return worldedit.allocate_with_nodes(origin_pos, nodes)
|
||||
end
|
||||
|
||||
@ -227,7 +219,6 @@ end
|
||||
function worldedit.deserialize(origin_pos, value)
|
||||
local nodes = load_schematic(value)
|
||||
if not nodes then return nil end
|
||||
if #nodes == 0 then return #nodes end
|
||||
|
||||
local pos1, pos2 = worldedit.allocate_with_nodes(origin_pos, nodes)
|
||||
worldedit.keep_loaded(pos1, pos2)
|
||||
|
1
worldedit/visualization.lua
Normal file → Executable file
1
worldedit/visualization.lua
Normal file → Executable file
@ -6,7 +6,6 @@ minetest.register_node("worldedit:placeholder", {
|
||||
paramtype = "light",
|
||||
sunlight_propagates = true,
|
||||
diggable = false,
|
||||
pointable = false,
|
||||
walkable = false,
|
||||
groups = {not_in_creative_inventory=1},
|
||||
})
|
||||
|
@ -1,2 +0,0 @@
|
||||
worldedit
|
||||
worldedit_commands
|
@ -1,161 +0,0 @@
|
||||
local modname = minetest.get_current_modname()
|
||||
|
||||
-- check compatibility
|
||||
if minetest.raycast == nil then
|
||||
function log_unavailable_error()
|
||||
minetest.log("error",
|
||||
"[MOD] " .. modname .. " is not compatible with current game version, " ..
|
||||
"you can disable it in the game settings!"
|
||||
)
|
||||
minetest.log("verbose",
|
||||
"[MOD] " .. modname .. " requires a suitable version of 0.4.16-dev or higher, " ..
|
||||
"that includes support for minetest.raycast() [since 7th July 2017]"
|
||||
)
|
||||
end
|
||||
|
||||
if minetest.is_singleplayer() then
|
||||
-- delay message until player is connected
|
||||
minetest.register_on_joinplayer(log_unavailable_error)
|
||||
else
|
||||
log_unavailable_error()
|
||||
end
|
||||
|
||||
-- exit here / do not load this mod
|
||||
return
|
||||
end
|
||||
|
||||
local BRUSH_MAX_DIST = 150
|
||||
local BRUSH_ALLOWED_COMMANDS = {
|
||||
-- basically everything that only needs pos1
|
||||
"cube",
|
||||
"cylinder",
|
||||
"dome",
|
||||
"hollowcube",
|
||||
"hollowcylinder",
|
||||
"hollowdome",
|
||||
"hollowpyramid",
|
||||
"hollowsphere",
|
||||
"load",
|
||||
"pyramid",
|
||||
"sphere",
|
||||
"spiral",
|
||||
|
||||
"cyl",
|
||||
"do",
|
||||
"hcube",
|
||||
"hcyl",
|
||||
"hdo",
|
||||
"hpyr",
|
||||
"hspr",
|
||||
"l",
|
||||
"pyr",
|
||||
"spr",
|
||||
"spl",
|
||||
}
|
||||
local brush_on_use = function(itemstack, placer)
|
||||
local meta = itemstack:get_meta()
|
||||
local name = placer:get_player_name()
|
||||
|
||||
local cmd = meta:get_string("command")
|
||||
if cmd == "" then
|
||||
worldedit.player_notify(name,
|
||||
"This brush is not bound, use //brush to bind a command to it.")
|
||||
return false
|
||||
end
|
||||
local cmddef = minetest.registered_chatcommands["/" .. cmd]
|
||||
if cmddef == nil then return false end -- shouldn't happen as //brush checks this
|
||||
local has_privs, missing_privs = minetest.check_player_privs(name, cmddef.privs)
|
||||
if not has_privs then
|
||||
worldedit.player_notify(name,
|
||||
"Missing privileges: " .. table.concat(missing_privs, ", "))
|
||||
return false
|
||||
end
|
||||
|
||||
local raybegin = vector.add(placer:get_pos(), {x=0, y=2, z=0}) -- player head
|
||||
local rayend = vector.add(raybegin, vector.multiply(placer:get_look_dir(), BRUSH_MAX_DIST))
|
||||
local ray = minetest.raycast(raybegin, rayend, false, true)
|
||||
local pointed_thing = ray:next()
|
||||
if pointed_thing == nil then
|
||||
worldedit.player_notify(name, "Too far away.")
|
||||
return false
|
||||
end
|
||||
|
||||
assert(pointed_thing.type == "node")
|
||||
worldedit.pos1[name] = pointed_thing.under
|
||||
worldedit.pos2[name] = nil
|
||||
worldedit.mark_region(name)
|
||||
-- is this a horrible hack? oh yes.
|
||||
worldedit._override_safe_regions = true
|
||||
local player_notify_old = worldedit.player_notify
|
||||
worldedit.player_notify = function(name, msg)
|
||||
if string.match(msg, "^%d") then return end -- discard "1234 nodes added."
|
||||
return player_notify_old(name, msg)
|
||||
end
|
||||
|
||||
minetest.log("action", string.format("%s uses WorldEdit brush (//%s) at %s",
|
||||
name, cmd, minetest.pos_to_string(pointed_thing.under)))
|
||||
cmddef.func(name, meta:get_string("params"))
|
||||
|
||||
worldedit._override_safe_regions = false
|
||||
worldedit.player_notify = player_notify_old
|
||||
return true
|
||||
end
|
||||
|
||||
minetest.register_tool(":worldedit:brush", {
|
||||
description = "WorldEdit Brush",
|
||||
inventory_image = "worldedit_brush.png",
|
||||
stack_max = 1, -- no need to stack these (metadata prevents this anyway)
|
||||
range = 0,
|
||||
on_use = function(itemstack, placer, pointed_thing)
|
||||
brush_on_use(itemstack, placer)
|
||||
return itemstack -- nothing consumed, nothing changed
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand("/brush", {
|
||||
privs = {worldedit=true},
|
||||
params = "none/<cmd> [parameters]",
|
||||
description = "Assign command to WorldEdit brush item",
|
||||
func = function(name, param)
|
||||
local found, _, cmd, params = param:find("^([^%s]+)%s+(.+)$")
|
||||
if not found then
|
||||
params = ""
|
||||
found, _, cmd = param:find("^(.+)$")
|
||||
end
|
||||
if not found then
|
||||
worldedit.player_notify(name, "Invalid usage.")
|
||||
return
|
||||
end
|
||||
|
||||
local itemstack = minetest.get_player_by_name(name):get_wielded_item()
|
||||
if itemstack == nil or itemstack:get_name() ~= "worldedit:brush" then
|
||||
worldedit.player_notify(name, "Not holding brush item.")
|
||||
return
|
||||
end
|
||||
|
||||
cmd = cmd:lower()
|
||||
local meta = itemstack:get_meta()
|
||||
if cmd == "none" then
|
||||
meta:from_table(nil)
|
||||
worldedit.player_notify(name, "Brush assignment cleared.")
|
||||
else
|
||||
local cmddef
|
||||
if table.indexof(BRUSH_ALLOWED_COMMANDS, cmd) ~= -1 then
|
||||
cmddef = minetest.registered_chatcommands["/" .. cmd]
|
||||
else
|
||||
cmddef = nil
|
||||
end
|
||||
if cmddef == nil then
|
||||
worldedit.player_notify(name, "Invalid command for brush use: //" .. cmd)
|
||||
return
|
||||
end
|
||||
meta:set_string("command", cmd)
|
||||
meta:set_string("params", params)
|
||||
local fullcmd = "//" .. cmd .. " " .. params
|
||||
meta:set_string("description",
|
||||
minetest.registered_tools["worldedit:brush"].description .. ": " .. fullcmd)
|
||||
worldedit.player_notify(name, "Brush assigned to command: " .. fullcmd)
|
||||
end
|
||||
minetest.get_player_by_name(name):set_wielded_item(itemstack)
|
||||
end,
|
||||
})
|
Binary file not shown.
Before Width: | Height: | Size: 337 B |
0
worldedit_commands/depends.txt
Normal file → Executable file
0
worldedit_commands/depends.txt
Normal file → Executable file
@ -23,7 +23,6 @@ local function get_position(name) --position 1 retrieval function for when not u
|
||||
return pos1
|
||||
end
|
||||
|
||||
-- normalize_nodename wrapper for convenience purposes
|
||||
local function get_node(name, nodename)
|
||||
local node = worldedit.normalize_nodename(nodename)
|
||||
if not node then
|
||||
@ -37,46 +36,26 @@ function worldedit.player_notify(name, message)
|
||||
minetest.chat_send_player(name, "WorldEdit -!- " .. message, false)
|
||||
end
|
||||
|
||||
local function string_endswith(full, part)
|
||||
return full:find(part, 1, true) == #full - #part + 1
|
||||
end
|
||||
|
||||
-- normalizes node "description" `nodename`, returning a string (or nil)
|
||||
--determines whether `nodename` is a valid node name, returning a boolean
|
||||
worldedit.normalize_nodename = function(nodename)
|
||||
nodename = nodename:gsub("^%s*(.-)%s*$", "%1") -- strip spaces
|
||||
nodename = nodename:gsub("^%s*(.-)%s*$", "%1")
|
||||
if nodename == "" then return nil end
|
||||
|
||||
local fullname = ItemStack({name=nodename}):get_name() -- resolve aliases
|
||||
if minetest.registered_nodes[fullname] or fullname == "air" then -- full name
|
||||
local fullname = ItemStack({name=nodename}):get_name() --resolve aliases of node names to full names
|
||||
if minetest.registered_nodes[fullname] or fullname == "air" then --directly found node name or alias of nodename
|
||||
return fullname
|
||||
end
|
||||
for key, value in pairs(minetest.registered_nodes) do
|
||||
if string_endswith(key, ":" .. nodename) then -- matches name (w/o mod part)
|
||||
if key:find(":" .. nodename, 1, true) then --found in mod
|
||||
return key
|
||||
end
|
||||
end
|
||||
nodename = nodename:lower() -- lowercase both for case insensitive comparison
|
||||
nodename = nodename:lower() --lowercase both for case insensitive comparison
|
||||
for key, value in pairs(minetest.registered_nodes) do
|
||||
local desc = value.description:lower()
|
||||
if desc == nodename then -- matches description
|
||||
return key
|
||||
end
|
||||
if string_endswith(desc, " block") and desc == nodename.." block" then
|
||||
-- fuzzy description match (e.g. "Steel" == "Steel Block")
|
||||
if value.description:lower() == nodename then --found in description
|
||||
return key
|
||||
end
|
||||
end
|
||||
|
||||
local match = nil
|
||||
for key, value in pairs(minetest.registered_nodes) do
|
||||
if value.description:lower():find(nodename, 1, true) ~= nil then
|
||||
if match ~= nil then
|
||||
return nil
|
||||
end
|
||||
match = key -- substring description match (only if no ambiguities)
|
||||
end
|
||||
end
|
||||
return match
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Determines the axis in which a player is facing, returning an axis ("x", "y", or "z") and the sign (1 or -1)
|
||||
@ -108,9 +87,9 @@ end
|
||||
|
||||
minetest.register_chatcommand("/about", {
|
||||
params = "",
|
||||
description = "Get information about the WorldEdit mod",
|
||||
description = "Get information about the mod",
|
||||
func = function(name, param)
|
||||
worldedit.player_notify(name, "WorldEdit " .. worldedit.version_string .. " is available on this server. Type /help to get a list of commands, or get more information at https://github.com/Uberi/Minetest-WorldEdit/")
|
||||
worldedit.player_notify(name, "WorldEdit " .. worldedit.version_string .. " is available on this server. Type /help to get a list of commands, or get more information at https://github.com/Uberi/MineTest-WorldEdit/")
|
||||
end,
|
||||
})
|
||||
|
||||
@ -203,7 +182,7 @@ minetest.register_on_punchnode(function(pos, node, puncher)
|
||||
local name = puncher:get_player_name()
|
||||
if worldedit.inspect[name] then
|
||||
local axis, sign = worldedit.player_axis(name)
|
||||
local message = string.format("inspector: %s at %s (param1=%d, param2=%d, received light=%d) punched facing the %s axis",
|
||||
message = string.format("inspector: %s at %s (param1=%d, param2=%d, received light=%d) punched facing the %s axis",
|
||||
node.name, minetest.pos_to_string(pos), node.param1, node.param2, get_node_rlight(pos), axis .. (sign > 0 and "+" or "-"))
|
||||
worldedit.player_notify(name, message)
|
||||
end
|
||||
@ -398,49 +377,29 @@ minetest.register_chatcommand("/set", {
|
||||
privs = {worldedit=true},
|
||||
func = safe_region(function(name, param)
|
||||
local node = get_node(name, param)
|
||||
if not node then return end
|
||||
if not node then
|
||||
worldedit.player_notify(name, "Could not identify node \"" .. param .. "\"")
|
||||
return
|
||||
end
|
||||
|
||||
local count = worldedit.set(worldedit.pos1[name], worldedit.pos2[name], node)
|
||||
worldedit.player_notify(name, count .. " nodes set")
|
||||
end, check_region),
|
||||
})
|
||||
|
||||
minetest.register_chatcommand("/param2", {
|
||||
params = "<param2>",
|
||||
description = "Set param2 of all nodes in the current WorldEdit region to <param2>",
|
||||
privs = {worldedit=true},
|
||||
func = safe_region(function(name, param)
|
||||
local param2 = tonumber(param)
|
||||
if not param2 then
|
||||
worldedit.player_notify(name, "Invalid or missing param2 argument")
|
||||
return
|
||||
elseif param2 < 0 or param2 > 255 then
|
||||
worldedit.player_notify(name, "Param2 is out of range (must be between 0 and 255 inclusive)!")
|
||||
return
|
||||
end
|
||||
|
||||
local count = worldedit.set_param2(worldedit.pos1[name], worldedit.pos2[name], param2)
|
||||
worldedit.player_notify(name, count .. " nodes altered")
|
||||
end, check_region),
|
||||
})
|
||||
|
||||
minetest.register_chatcommand("/mix", {
|
||||
params = "<node1> [<weighting1>] [<node2> [<weighting2>]] ...",
|
||||
params = "<node1> ...",
|
||||
description = "Fill the current WorldEdit region with a random mix of <node1>, ...",
|
||||
privs = {worldedit=true},
|
||||
func = safe_region(function(name, param)
|
||||
local nodes = {}
|
||||
for nodename in param:gmatch("[^%s]+") do
|
||||
if tonumber(nodename) ~= nil and #nodes > 0 then
|
||||
local last_node = nodes[#nodes]
|
||||
for i = 1, tonumber(nodename) do
|
||||
nodes[#nodes + 1] = last_node
|
||||
end
|
||||
else
|
||||
local node = get_node(name, nodename)
|
||||
if not node then return end
|
||||
nodes[#nodes + 1] = node
|
||||
local node = get_node(name, nodename)
|
||||
if not node then
|
||||
worldedit.player_notify(name, "Could not identify node \"" .. name .. "\"")
|
||||
return
|
||||
end
|
||||
nodes[#nodes + 1] = node
|
||||
end
|
||||
|
||||
local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]
|
||||
@ -496,45 +455,6 @@ minetest.register_chatcommand("/replaceinverse", {
|
||||
end, check_replace),
|
||||
})
|
||||
|
||||
local check_cube = function(name, param)
|
||||
if worldedit.pos1[name] == nil then
|
||||
worldedit.player_notify(name, "no position 1 selected")
|
||||
return nil
|
||||
end
|
||||
local found, _, w, h, l, nodename = param:find("^(%d+)%s+(%d+)%s+(%d+)%s+(.+)$")
|
||||
if found == nil then
|
||||
worldedit.player_notify(name, "invalid usage: " .. param)
|
||||
return nil
|
||||
end
|
||||
local node = get_node(name, nodename)
|
||||
if not node then return nil end
|
||||
return tonumber(w) * tonumber(h) * tonumber(l)
|
||||
end
|
||||
|
||||
minetest.register_chatcommand("/hollowcube", {
|
||||
params = "<width> <height> <length> <node>",
|
||||
description = "Add a hollow cube with its ground level centered at WorldEdit position 1 with dimensions <width> x <height> x <length>, composed of <node>.",
|
||||
privs = {worldedit=true},
|
||||
func = safe_region(function(name, param)
|
||||
local found, _, w, h, l, nodename = param:find("^(%d+)%s+(%d+)%s+(%d+)%s+(.+)$")
|
||||
local node = get_node(name, nodename)
|
||||
local count = worldedit.cube(worldedit.pos1[name], tonumber(w), tonumber(h), tonumber(l), node, true)
|
||||
worldedit.player_notify(name, count .. " nodes added")
|
||||
end, check_cube),
|
||||
})
|
||||
|
||||
minetest.register_chatcommand("/cube", {
|
||||
params = "<width> <height> <length> <node>",
|
||||
description = "Add a cube with its ground level centered at WorldEdit position 1 with dimensions <width> x <height> x <length>, composed of <node>.",
|
||||
privs = {worldedit=true},
|
||||
func = safe_region(function(name, param)
|
||||
local found, _, w, h, l, nodename = param:find("^(%d+)%s+(%d+)%s+(%d+)%s+(.+)$")
|
||||
local node = get_node(name, nodename)
|
||||
local count = worldedit.cube(worldedit.pos1[name], tonumber(w), tonumber(h), tonumber(l), node)
|
||||
worldedit.player_notify(name, count .. " nodes added")
|
||||
end, check_cube),
|
||||
})
|
||||
|
||||
local check_sphere = function(name, param)
|
||||
if worldedit.pos1[name] == nil then
|
||||
worldedit.player_notify(name, "no position 1 selected")
|
||||
@ -618,67 +538,46 @@ local check_cylinder = function(name, param)
|
||||
worldedit.player_notify(name, "no position 1 selected")
|
||||
return nil
|
||||
end
|
||||
-- two radii
|
||||
local found, _, axis, length, radius1, radius2, nodename = param:find("^([xyz%?])%s+([+-]?%d+)%s+(%d+)%s+(%d+)%s+(.+)$")
|
||||
if found == nil then
|
||||
-- single radius
|
||||
found, _, axis, length, radius1, nodename = param:find("^([xyz%?])%s+([+-]?%d+)%s+(%d+)%s+(.+)$")
|
||||
radius2 = radius1
|
||||
end
|
||||
local found, _, axis, length, radius, nodename = param:find("^([xyz%?])%s+([+-]?%d+)%s+(%d+)%s+(.+)$")
|
||||
if found == nil then
|
||||
worldedit.player_notify(name, "invalid usage: " .. param)
|
||||
return nil
|
||||
end
|
||||
local node = get_node(name, nodename)
|
||||
if not node then return nil end
|
||||
local radius = math.max(tonumber(radius1), tonumber(radius2))
|
||||
return math.ceil(math.pi * (radius ^ 2) * tonumber(length))
|
||||
return math.ceil(math.pi * (tonumber(radius) ^ 2) * tonumber(length))
|
||||
end
|
||||
|
||||
minetest.register_chatcommand("/hollowcylinder", {
|
||||
params = "x/y/z/? <length> <radius1> [radius2] <node>",
|
||||
description = "Add hollow cylinder at WorldEdit position 1 along the x/y/z/? axis with length <length>, base radius <radius1> (and top radius [radius2]), composed of <node>",
|
||||
params = "x/y/z/? <length> <radius> <node>",
|
||||
description = "Add hollow cylinder at WorldEdit position 1 along the x/y/z/? axis with length <length> and radius <radius>, composed of <node>",
|
||||
privs = {worldedit=true},
|
||||
func = safe_region(function(name, param)
|
||||
-- two radii
|
||||
local found, _, axis, length, radius1, radius2, nodename = param:find("^([xyz%?])%s+([+-]?%d+)%s+(%d+)%s+(%d+)%s+(.+)$")
|
||||
if found == nil then
|
||||
-- single radius
|
||||
found, _, axis, length, radius1, nodename = param:find("^([xyz%?])%s+([+-]?%d+)%s+(%d+)%s+(.+)$")
|
||||
radius2 = radius1
|
||||
end
|
||||
local found, _, axis, length, radius, nodename = param:find("^([xyz%?])%s+([+-]?%d+)%s+(%d+)%s+(.+)$")
|
||||
length = tonumber(length)
|
||||
if axis == "?" then
|
||||
local sign
|
||||
axis, sign = worldedit.player_axis(name)
|
||||
length = length * sign
|
||||
end
|
||||
local node = get_node(name, nodename)
|
||||
local count = worldedit.cylinder(worldedit.pos1[name], axis, length, tonumber(radius1), tonumber(radius2), node, true)
|
||||
local count = worldedit.cylinder(worldedit.pos1[name], axis, length, tonumber(radius), node, true)
|
||||
worldedit.player_notify(name, count .. " nodes added")
|
||||
end, check_cylinder),
|
||||
})
|
||||
|
||||
minetest.register_chatcommand("/cylinder", {
|
||||
params = "x/y/z/? <length> <radius1> [radius2] <node>",
|
||||
description = "Add cylinder at WorldEdit position 1 along the x/y/z/? axis with length <length>, base radius <radius1> (and top radius [radius2]), composed of <node>",
|
||||
params = "x/y/z/? <length> <radius> <node>",
|
||||
description = "Add cylinder at WorldEdit position 1 along the x/y/z/? axis with length <length> and radius <radius>, composed of <node>",
|
||||
privs = {worldedit=true},
|
||||
func = safe_region(function(name, param)
|
||||
-- two radii
|
||||
local found, _, axis, length, radius1, radius2, nodename = param:find("^([xyz%?])%s+([+-]?%d+)%s+(%d+)%s+(%d+)%s+(.+)$")
|
||||
if found == nil then
|
||||
-- single radius
|
||||
found, _, axis, length, radius1, nodename = param:find("^([xyz%?])%s+([+-]?%d+)%s+(%d+)%s+(.+)$")
|
||||
radius2 = radius1
|
||||
end
|
||||
local found, _, axis, length, radius, nodename = param:find("^([xyz%?])%s+([+-]?%d+)%s+(%d+)%s+(.+)$")
|
||||
length = tonumber(length)
|
||||
if axis == "?" then
|
||||
local sign
|
||||
axis, sign = worldedit.player_axis(name)
|
||||
length = length * sign
|
||||
end
|
||||
local node = get_node(name, nodename)
|
||||
local count = worldedit.cylinder(worldedit.pos1[name], axis, length, tonumber(radius1), tonumber(radius2), node)
|
||||
local count = worldedit.cylinder(worldedit.pos1[name], axis, length, tonumber(radius), node)
|
||||
worldedit.player_notify(name, count .. " nodes added")
|
||||
end, check_cylinder),
|
||||
})
|
||||
@ -707,7 +606,6 @@ minetest.register_chatcommand("/hollowpyramid", {
|
||||
local found, _, axis, height, nodename = param:find("^([xyz%?])%s+([+-]?%d+)%s+(.+)$")
|
||||
height = tonumber(height)
|
||||
if axis == "?" then
|
||||
local sign
|
||||
axis, sign = worldedit.player_axis(name)
|
||||
height = height * sign
|
||||
end
|
||||
@ -725,7 +623,6 @@ minetest.register_chatcommand("/pyramid", {
|
||||
local found, _, axis, height, nodename = param:find("^([xyz%?])%s+([+-]?%d+)%s+(.+)$")
|
||||
height = tonumber(height)
|
||||
if axis == "?" then
|
||||
local sign
|
||||
axis, sign = worldedit.player_axis(name)
|
||||
height = height * sign
|
||||
end
|
||||
@ -773,7 +670,6 @@ minetest.register_chatcommand("/copy", {
|
||||
end
|
||||
amount = tonumber(amount)
|
||||
if axis == "?" then
|
||||
local sign
|
||||
axis, sign = worldedit.player_axis(name)
|
||||
amount = amount * sign
|
||||
end
|
||||
@ -800,7 +696,6 @@ minetest.register_chatcommand("/move", {
|
||||
end
|
||||
amount = tonumber(amount)
|
||||
if axis == "?" then
|
||||
local sign
|
||||
axis, sign = worldedit.player_axis(name)
|
||||
amount = amount * sign
|
||||
end
|
||||
@ -823,7 +718,6 @@ minetest.register_chatcommand("/stack", {
|
||||
local found, _, axis, repetitions = param:find("^([xyz%?])%s+([+-]?%d+)$")
|
||||
repetitions = tonumber(repetitions)
|
||||
if axis == "?" then
|
||||
local sign
|
||||
axis, sign = worldedit.player_axis(name)
|
||||
repetitions = repetitions * sign
|
||||
end
|
||||
@ -905,12 +799,9 @@ minetest.register_chatcommand("/stretch", {
|
||||
stretchx, stretchy, stretchz = tonumber(stretchx), tonumber(stretchy), tonumber(stretchz)
|
||||
if stretchx == 0 or stretchy == 0 or stretchz == 0 then
|
||||
worldedit.player_notify(name, "invalid scaling factors: " .. param)
|
||||
return nil
|
||||
end
|
||||
local count = check_region(name, param)
|
||||
if count then
|
||||
return stretchx * stretchy * stretchz * count
|
||||
end
|
||||
if count then return tonumber(stretchx) * tonumber(stretchy) * tonumber(stretchz) * count end
|
||||
return nil
|
||||
end),
|
||||
})
|
||||
@ -1163,15 +1054,9 @@ minetest.register_chatcommand("/allocate", {
|
||||
return
|
||||
elseif version > worldedit.LATEST_SERIALIZATION_VERSION then
|
||||
worldedit.player_notify(name, "File was created with newer version of WorldEdit!")
|
||||
return
|
||||
end
|
||||
local nodepos1, nodepos2, count = worldedit.allocate(pos, value)
|
||||
|
||||
if not nodepos1 then
|
||||
worldedit.player_notify(name, "Schematic empty, nothing allocated")
|
||||
return
|
||||
end
|
||||
|
||||
worldedit.pos1[name] = nodepos1
|
||||
worldedit.mark_pos1(name)
|
||||
worldedit.pos2[name] = nodepos2
|
||||
@ -1241,10 +1126,8 @@ minetest.register_chatcommand("/lua", {
|
||||
local err = worldedit.lua(param)
|
||||
if err then
|
||||
worldedit.player_notify(name, "code error: " .. err)
|
||||
minetest.log("action", name.." tried to execute "..param)
|
||||
else
|
||||
worldedit.player_notify(name, "code successfully executed", false)
|
||||
minetest.log("action", name.." executed "..param)
|
||||
end
|
||||
end,
|
||||
})
|
||||
@ -1257,10 +1140,8 @@ minetest.register_chatcommand("/luatransform", {
|
||||
local err = worldedit.luatransform(worldedit.pos1[name], worldedit.pos2[name], param)
|
||||
if err then
|
||||
worldedit.player_notify(name, "code error: " .. err, false)
|
||||
minetest.log("action", name.." tried to execute luatransform "..param)
|
||||
else
|
||||
worldedit.player_notify(name, "code successfully executed", false)
|
||||
minetest.log("action", name.." executed luatransform "..param)
|
||||
end
|
||||
end),
|
||||
})
|
||||
|
@ -1,8 +1,6 @@
|
||||
local safe_region_callback = {}
|
||||
local safe_region_param = {}
|
||||
|
||||
worldedit._override_safe_regions = false -- internal use ONLY!
|
||||
|
||||
local function check_region(name, param)
|
||||
local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] --obtain positions
|
||||
if pos1 == nil or pos2 == nil then
|
||||
@ -22,7 +20,7 @@ local function safe_region(callback, nodes_needed)
|
||||
--check if the operation applies to a safe number of nodes
|
||||
local count = nodes_needed(name, param)
|
||||
if count == nil then return end --invalid command
|
||||
if worldedit._override_safe_regions or count < 10000 then
|
||||
if count < 10000 then
|
||||
return callback(name, param)
|
||||
end
|
||||
|
||||
@ -46,21 +44,20 @@ minetest.register_chatcommand("/y", {
|
||||
return
|
||||
end
|
||||
|
||||
reset_pending(name)
|
||||
safe_region_callback[name], safe_region_param[name] = nil, nil --reset pending operation
|
||||
callback(name, param)
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand("/n", {
|
||||
params = "",
|
||||
description = "Abort a pending operation",
|
||||
description = "Confirm a pending operation",
|
||||
func = function(name)
|
||||
if not safe_region_callback[name] then
|
||||
worldedit.player_notify(name, "no operation pending")
|
||||
return
|
||||
end
|
||||
|
||||
reset_pending(name)
|
||||
safe_region_callback[name], safe_region_param[name] = nil, nil
|
||||
end,
|
||||
})
|
||||
|
||||
|
@ -1,11 +1,3 @@
|
||||
local function above_or_under(placer, pointed_thing)
|
||||
if placer:get_player_control().sneak then
|
||||
return pointed_thing.above
|
||||
else
|
||||
return pointed_thing.under
|
||||
end
|
||||
end
|
||||
|
||||
minetest.register_tool(":worldedit:wand", {
|
||||
description = "WorldEdit Wand tool, Left-click to set 1st position, right-click to set 2nd",
|
||||
inventory_image = "worldedit_wand.png",
|
||||
@ -15,7 +7,7 @@ minetest.register_tool(":worldedit:wand", {
|
||||
on_use = function(itemstack, placer, pointed_thing)
|
||||
if placer ~= nil and pointed_thing ~= nil and pointed_thing.type == "node" then
|
||||
local name = placer:get_player_name()
|
||||
worldedit.pos1[name] = above_or_under(placer, pointed_thing)
|
||||
worldedit.pos1[name] = pointed_thing.under
|
||||
worldedit.mark_pos1(name)
|
||||
end
|
||||
return itemstack -- nothing consumed, nothing changed
|
||||
@ -24,7 +16,7 @@ minetest.register_tool(":worldedit:wand", {
|
||||
on_place = function(itemstack, placer, pointed_thing) -- Left Click
|
||||
if placer ~= nil and pointed_thing ~= nil and pointed_thing.type == "node" then
|
||||
local name = placer:get_player_name()
|
||||
worldedit.pos2[name] = above_or_under(placer, pointed_thing)
|
||||
worldedit.pos2[name] = pointed_thing.under
|
||||
worldedit.mark_pos2(name)
|
||||
end
|
||||
return itemstack -- nothing consumed, nothing changed
|
||||
|
@ -4,4 +4,3 @@ unified_inventory?
|
||||
inventory_plus?
|
||||
sfinv?
|
||||
creative?
|
||||
smart_inventory?
|
||||
|
82
worldedit_gui/functionality.lua
Normal file → Executable file
82
worldedit_gui/functionality.lua
Normal file → Executable file
@ -1,6 +1,6 @@
|
||||
--saved state for each player
|
||||
local gui_nodename1 = {} --mapping of player names to node names
|
||||
local gui_nodename2 = {} --mapping of player names to node names
|
||||
local gui_nodename1 = {} --mapping of player names to node names (arbitrary strings may also appear as values)
|
||||
local gui_nodename2 = {} --mapping of player names to node names (arbitrary strings may also appear as values)
|
||||
local gui_axis1 = {} --mapping of player names to axes (one of 1, 2, 3, or 4, representing the axes in the `axis_indices` table below)
|
||||
local gui_axis2 = {} --mapping of player names to axes (one of 1, 2, 3, or 4, representing the axes in the `axis_indices` table below)
|
||||
local gui_distance1 = {} --mapping of player names to a distance (arbitrary strings may also appear as values)
|
||||
@ -10,7 +10,9 @@ local gui_count1 = {} --mapping of player names to a quantity (arbitrary strings
|
||||
local gui_count2 = {} --mapping of player names to a quantity (arbitrary strings may also appear as values)
|
||||
local gui_count3 = {} --mapping of player names to a quantity (arbitrary strings may also appear as values)
|
||||
local gui_angle = {} --mapping of player names to an angle (one of 90, 180, 270, representing the angle in degrees clockwise)
|
||||
local gui_filename = {} --mapping of player names to file names
|
||||
local gui_filename = {} --mapping of player names to file names (arbitrary strings may also appear as values)
|
||||
local gui_formspec = {} --mapping of player names to formspecs
|
||||
local gui_code = {} --mapping of player names to formspecs
|
||||
|
||||
--set default values
|
||||
setmetatable(gui_nodename1, {__index = function() return "Cobblestone" end})
|
||||
@ -25,6 +27,8 @@ setmetatable(gui_count2, {__index = function() return "6" end})
|
||||
setmetatable(gui_count3, {__index = function() return "4" end})
|
||||
setmetatable(gui_angle, {__index = function() return 90 end})
|
||||
setmetatable(gui_filename, {__index = function() return "building" end})
|
||||
setmetatable(gui_formspec, {__index = function() return "size[5,5]\nlabel[0,0;Hello, world!]" end})
|
||||
setmetatable(gui_code, {__index = function() return "minetest.chat_send_player(\"singleplayer\", \"Hello, world!\")" end})
|
||||
|
||||
local axis_indices = {["X axis"]=1, ["Y axis"]=2, ["Z axis"]=3, ["Look direction"]=4}
|
||||
local axis_values = {"x", "y", "z", "?"}
|
||||
@ -288,21 +292,17 @@ worldedit.register_gui_function("worldedit_gui_cylinder", {
|
||||
name = "Cylinder",
|
||||
privs = combine_we_privs({"hollowcylinder", "cylinder"}),
|
||||
get_formspec = function(name)
|
||||
local node, axis, length = gui_nodename1[name], gui_axis1[name], gui_distance1[name]
|
||||
local radius1, radius2 = gui_distance2[name], gui_distance3[name]
|
||||
local node, axis, length, radius = gui_nodename1[name], gui_axis1[name], gui_distance1[name], gui_distance2[name]
|
||||
local nodename = worldedit.normalize_nodename(node)
|
||||
return "size[6.5,6]" .. worldedit.get_formspec_header("worldedit_gui_cylinder") ..
|
||||
return "size[6.5,5]" .. worldedit.get_formspec_header("worldedit_gui_cylinder") ..
|
||||
string.format("field[0.5,1.5;4,0.8;worldedit_gui_cylinder_node;Name;%s]", minetest.formspec_escape(node)) ..
|
||||
"button[4,1.18;1.5,0.8;worldedit_gui_cylinder_search;Search]" ..
|
||||
formspec_node("5.5,1.1", nodename) ..
|
||||
string.format("field[0.5,2.5;4,0.8;worldedit_gui_cylinder_length;Length;%s]", minetest.formspec_escape(length)) ..
|
||||
string.format("dropdown[4,2.18;2.5;worldedit_gui_cylinder_axis;X axis,Y axis,Z axis,Look direction;%d]", axis) ..
|
||||
string.format("field[0.5,3.5;2,0.8;worldedit_gui_cylinder_radius1;Base Radius;%s]", minetest.formspec_escape(radius1)) ..
|
||||
string.format("field[2.5,3.5;2,0.8;worldedit_gui_cylinder_radius2;Top Radius;%s]", minetest.formspec_escape(radius2)) ..
|
||||
"label[0.25,4;Equal base and top radius creates a cylinder,\n"..
|
||||
"zero top radius creates a cone.\nConsult documentation for more information.]"..
|
||||
"button_exit[0,5.5;3,0.8;worldedit_gui_cylinder_submit_hollow;Hollow Cylinder]" ..
|
||||
"button_exit[3.5,5.5;3,0.8;worldedit_gui_cylinder_submit_solid;Solid Cylinder]"
|
||||
string.format("field[0.5,3.5;4,0.8;worldedit_gui_cylinder_radius;Radius;%s]", minetest.formspec_escape(radius)) ..
|
||||
"button_exit[0,4.5;3,0.8;worldedit_gui_cylinder_submit_hollow;Hollow Cylinder]" ..
|
||||
"button_exit[3.5,4.5;3,0.8;worldedit_gui_cylinder_submit_solid;Solid Cylinder]"
|
||||
end,
|
||||
})
|
||||
|
||||
@ -312,8 +312,7 @@ worldedit.register_gui_handler("worldedit_gui_cylinder", function(name, fields)
|
||||
gui_nodename1[name] = tostring(fields.worldedit_gui_cylinder_node)
|
||||
gui_axis1[name] = axis_indices[fields.worldedit_gui_cylinder_axis]
|
||||
gui_distance1[name] = tostring(fields.worldedit_gui_cylinder_length)
|
||||
gui_distance2[name] = tostring(fields.worldedit_gui_cylinder_radius1)
|
||||
gui_distance3[name] = tostring(fields.worldedit_gui_cylinder_radius2)
|
||||
gui_distance2[name] = tostring(fields.worldedit_gui_cylinder_radius)
|
||||
worldedit.show_page(name, "worldedit_gui_cylinder")
|
||||
|
||||
local submit = nil
|
||||
@ -325,8 +324,7 @@ worldedit.register_gui_handler("worldedit_gui_cylinder", function(name, fields)
|
||||
if submit then
|
||||
local n = worldedit.normalize_nodename(gui_nodename1[name])
|
||||
if n then
|
||||
local args = string.format("%s %s %s %s %s", axis_values[gui_axis1[name]], gui_distance1[name], gui_distance2[name], gui_distance3[name], n)
|
||||
minetest.chatcommands["/"..submit].func(name, args)
|
||||
minetest.chatcommands["/"..submit].func(name, string.format("%s %s %s %s", axis_values[gui_axis1[name]], gui_distance1[name], gui_distance2[name], n))
|
||||
end
|
||||
end
|
||||
return true
|
||||
@ -735,46 +733,26 @@ worldedit.register_gui_handler("worldedit_gui_save_load", function(name, fields)
|
||||
return false
|
||||
end)
|
||||
|
||||
worldedit.register_gui_function("worldedit_gui_cube", {
|
||||
name = "Cuboid", -- technically the command is misnamed, I know...
|
||||
privs = combine_we_privs({"hollowcube", "cube"}),
|
||||
worldedit.register_gui_function("worldedit_gui_lua", {
|
||||
name = "Run Lua", privs = minetest.chatcommands["/clearobjects"].privs,
|
||||
privs = we_privs("lua"),
|
||||
get_formspec = function(name)
|
||||
local width, height, length = gui_distance1[name], gui_distance2[name], gui_distance3[name]
|
||||
local node = gui_nodename1[name]
|
||||
local nodename = worldedit.normalize_nodename(node)
|
||||
return "size[6.5,4]" .. worldedit.get_formspec_header("worldedit_gui_cube") ..
|
||||
string.format("field[0.5,1.5;4,0.8;worldedit_gui_cube_node;Name;%s]", minetest.formspec_escape(node)) ..
|
||||
"button[4,1.18;1.5,0.8;worldedit_gui_cube_search;Search]" ..
|
||||
formspec_node("5.5,1.1", nodename) ..
|
||||
string.format("field[0.5,2.5;1,0.8;worldedit_gui_cube_width;Width;%s]", minetest.formspec_escape(width)) ..
|
||||
string.format("field[1.5,2.5;1,0.8;worldedit_gui_cube_height;Height;%s]", minetest.formspec_escape(height)) ..
|
||||
string.format("field[2.5,2.5;1,0.8;worldedit_gui_cube_length;Length;%s]", minetest.formspec_escape(length)) ..
|
||||
"button_exit[0,3.5;3,0.8;worldedit_gui_cube_submit_hollow;Hollow Cuboid]" ..
|
||||
"button_exit[3.5,3.5;3,0.8;worldedit_gui_cube_submit_solid;Solid Cuboid]"
|
||||
local code = gui_code[name]
|
||||
return "size[8,6.5]" .. worldedit.get_formspec_header("worldedit_gui_lua") ..
|
||||
string.format("textarea[0.5,1;7.5,5.5;worldedit_gui_lua_code;Lua Code;%s]", minetest.formspec_escape(code)) ..
|
||||
"button_exit[0,6;3,0.8;worldedit_gui_lua_run;Run Lua]" ..
|
||||
"button_exit[5,6;3,0.8;worldedit_gui_lua_transform;Lua Transform]"
|
||||
end,
|
||||
})
|
||||
|
||||
worldedit.register_gui_handler("worldedit_gui_cube", function(name, fields)
|
||||
if fields.worldedit_gui_cube_search
|
||||
or fields.worldedit_gui_cube_submit_hollow or fields.worldedit_gui_cube_submit_solid then
|
||||
gui_nodename1[name] = tostring(fields.worldedit_gui_cube_node)
|
||||
gui_distance1[name] = tostring(fields.worldedit_gui_cube_width)
|
||||
gui_distance2[name] = tostring(fields.worldedit_gui_cube_height)
|
||||
gui_distance3[name] = tostring(fields.worldedit_gui_cube_length)
|
||||
worldedit.show_page(name, "worldedit_gui_cube")
|
||||
|
||||
local submit = nil
|
||||
if fields.worldedit_gui_cube_submit_hollow then
|
||||
submit = "hollowcube"
|
||||
elseif fields.worldedit_gui_cube_submit_solid then
|
||||
submit = "cube"
|
||||
end
|
||||
if submit then
|
||||
local n = worldedit.normalize_nodename(gui_nodename1[name])
|
||||
if n then
|
||||
local args = string.format("%s %s %s %s", gui_distance1[name], gui_distance2[name], gui_distance3[name], n)
|
||||
minetest.chatcommands["/"..submit].func(name, args)
|
||||
end
|
||||
worldedit.register_gui_handler("worldedit_gui_lua", function(name, fields)
|
||||
if fields.worldedit_gui_lua_run or fields.worldedit_gui_lua_transform then
|
||||
gui_code[name] = fields.worldedit_gui_lua_code
|
||||
worldedit.show_page(name, "worldedit_gui_lua")
|
||||
if fields.worldedit_gui_lua_run then
|
||||
minetest.chatcommands["/lua"].func(name, gui_code[name])
|
||||
else --fields.worldedit_gui_lua_transform
|
||||
minetest.chatcommands["/luatransform"].func(name, gui_code[name])
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
145
worldedit_gui/init.lua
Normal file → Executable file
145
worldedit_gui/init.lua
Normal file → Executable file
@ -80,6 +80,8 @@ if rawget(_G, "unified_inventory") then --unified inventory installed
|
||||
unified_inventory.register_button("worldedit_gui", {
|
||||
type = "image",
|
||||
image = "inventory_plus_worldedit_gui.png",
|
||||
tooltip = "Worldedit GUI",
|
||||
show_with = "worldedit", --Modiff MFF (Crabman 30/06/2015)
|
||||
})
|
||||
|
||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||
@ -134,55 +136,6 @@ elseif rawget(_G, "inventory_plus") then --inventory++ installed
|
||||
inventory_plus.set_inventory_formspec(player, get_formspec(name, page))
|
||||
end
|
||||
end
|
||||
elseif rawget(_G, "smart_inventory") then -- smart_inventory installed
|
||||
-- redefinition: Update the code element on inventory page to show the we-page
|
||||
function worldedit.show_page(name, page)
|
||||
local state = smart_inventory.get_page_state("worldedit_gui", name)
|
||||
if state then
|
||||
state:get("code"):set_we_formspec(page)
|
||||
state.location.rootState:show() -- update inventory page
|
||||
end
|
||||
end
|
||||
|
||||
-- smart_inventory page callback. Contains just a "custom code" element
|
||||
local function smart_worldedit_gui_callback(state)
|
||||
local codebox = state:element("code", { name = "code", code = "" })
|
||||
function codebox:set_we_formspec(we_page)
|
||||
local new_formspec = get_formspec(state.location.rootState.location.player, we_page)
|
||||
new_formspec = new_formspec:gsub('button_exit','button') --no inventory closing
|
||||
self.data.code = "container[1,1]".. new_formspec .. "container_end[]"
|
||||
end
|
||||
codebox:set_we_formspec("worldedit_gui")
|
||||
|
||||
-- process input (the back button)
|
||||
state:onInput(function(state, fields, player)
|
||||
if fields.worldedit_gui then --main page
|
||||
state:get("code"):set_we_formspec("worldedit_gui")
|
||||
elseif fields.worldedit_gui_exit then --return to original page
|
||||
state:get("code"):set_we_formspec("worldedit_gui")
|
||||
state.location.parentState:get("crafting_button"):submit() -- switch to the crafting tab
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
-- all handler should return false to force inventory UI update
|
||||
local orig_register_gui_handler = worldedit.register_gui_handler
|
||||
worldedit.register_gui_handler = function(identifier, handler)
|
||||
local wrapper = function(...)
|
||||
handler(...)
|
||||
return false
|
||||
end
|
||||
orig_register_gui_handler(identifier, wrapper)
|
||||
end
|
||||
|
||||
-- register the inventory button
|
||||
smart_inventory.register_page({
|
||||
name = "worldedit_gui",
|
||||
tooltip = "Edit your World!",
|
||||
icon = "inventory_plus_worldedit_gui.png",
|
||||
smartfs_callback = smart_worldedit_gui_callback,
|
||||
sequence = 99
|
||||
})
|
||||
elseif rawget(_G, "sfinv") then --sfinv installed (part of minetest_game since 0.4.15)
|
||||
assert(sfinv.enabled)
|
||||
local orig_get = sfinv.pages["sfinv:crafting"].get
|
||||
@ -194,21 +147,13 @@ elseif rawget(_G, "sfinv") then --sfinv installed (part of minetest_game since 0
|
||||
end
|
||||
})
|
||||
|
||||
--compatibility with pre-0.4.16 sfinv
|
||||
local set_page = sfinv.set_page or function(player, name)
|
||||
--assumptions: src pg has no leave callback, dst pg has no enter callback
|
||||
local ctx = {page=name}
|
||||
sfinv.contexts[player:get_player_name()] = ctx
|
||||
sfinv.set_player_inventory_formspec(player, ctx)
|
||||
end
|
||||
|
||||
--show the form when the button is pressed and hide it when done
|
||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||
if fields.worldedit_gui then --main page
|
||||
worldedit.show_page(player:get_player_name(), "worldedit_gui")
|
||||
return true
|
||||
elseif fields.worldedit_gui_exit then --return to original page
|
||||
set_page(player, "sfinv:crafting")
|
||||
sfinv.set_page(player, "sfinv:crafting")
|
||||
return true
|
||||
end
|
||||
return false
|
||||
@ -220,14 +165,82 @@ elseif rawget(_G, "sfinv") then --sfinv installed (part of minetest_game since 0
|
||||
player:set_inventory_formspec(get_formspec(name, page))
|
||||
end
|
||||
end
|
||||
else
|
||||
error(
|
||||
"worldedit_gui requires a supported \"gui management\" mod to be installed\n"..
|
||||
"To use the GUI you need to either\n"..
|
||||
"* Use minetest_game (at least 0.4.15) or a subgame with compatible sfinv\n"..
|
||||
"* Install Unified Inventory or Inventory++\n"..
|
||||
"If you do not want to use worldedit_gui, disable it by editing world.mt or from the Main Menu"
|
||||
)
|
||||
else --fallback button
|
||||
-- FIXME: this is a huge clusterfuck and the back button is broken
|
||||
local player_formspecs = {}
|
||||
|
||||
local update_main_formspec = function(name)
|
||||
local formspec = player_formspecs[name]
|
||||
if not formspec then
|
||||
return
|
||||
end
|
||||
local player = minetest.get_player_by_name(name)
|
||||
if not player then --this is in case the player signs off while the media is loading
|
||||
return
|
||||
end
|
||||
if (minetest.check_player_privs(name, {creative=true}) or
|
||||
minetest.setting_getbool("creative_mode")) and
|
||||
creative then --creative is active, add button to modified formspec
|
||||
local creative_formspec = player:get_inventory_formspec()
|
||||
local tab_id = tonumber(creative_formspec:match("tabheader%[.-;(%d+)%;"))
|
||||
|
||||
if tab_id == 1 then
|
||||
formspec = creative_formspec ..
|
||||
"image_button[0,1;1,1;inventory_plus_worldedit_gui.png;worldedit_gui;]"
|
||||
elseif not tab_id then
|
||||
formspec = creative_formspec ..
|
||||
"image_button[6,0;1,1;inventory_plus_worldedit_gui.png;worldedit_gui;]"
|
||||
else
|
||||
return
|
||||
end
|
||||
else
|
||||
formspec = formspec .. "image_button[0,0;1,1;inventory_plus_worldedit_gui.png;worldedit_gui;]"
|
||||
end
|
||||
player:set_inventory_formspec(formspec)
|
||||
end
|
||||
|
||||
minetest.register_on_joinplayer(function(player)
|
||||
local name = player:get_player_name()
|
||||
minetest.after(1, function()
|
||||
if minetest.get_player_by_name(name) then --ensure the player is still signed in
|
||||
player_formspecs[name] = player:get_inventory_formspec()
|
||||
minetest.after(0.01, function()
|
||||
update_main_formspec(name)
|
||||
end)
|
||||
end
|
||||
end)
|
||||
end)
|
||||
|
||||
minetest.register_on_leaveplayer(function(player)
|
||||
player_formspecs[player:get_player_name()] = nil
|
||||
end)
|
||||
|
||||
local gui_player_formspecs = {}
|
||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||
local name = player:get_player_name()
|
||||
if fields.worldedit_gui then --main page
|
||||
gui_player_formspecs[name] = player:get_inventory_formspec()
|
||||
worldedit.show_page(name, "worldedit_gui")
|
||||
return true
|
||||
elseif fields.worldedit_gui_exit then --return to original page
|
||||
if gui_player_formspecs[name] then
|
||||
player:set_inventory_formspec(gui_player_formspecs[name])
|
||||
end
|
||||
return true
|
||||
else --deal with creative_inventory setting the formspec on every single message
|
||||
minetest.after(0.01,function()
|
||||
update_main_formspec(name)
|
||||
end)
|
||||
return false --continue processing in creative inventory
|
||||
end
|
||||
end)
|
||||
|
||||
worldedit.show_page = function(name, page)
|
||||
local player = minetest.get_player_by_name(name)
|
||||
if player then
|
||||
player:set_inventory_formspec(get_formspec(name, page))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
worldedit.register_gui_function("worldedit_gui", {
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 25 KiB |
1
worldedit_infinity/depends.txt
Executable file
1
worldedit_infinity/depends.txt
Executable file
@ -0,0 +1 @@
|
||||
worldedit?
|
103
worldedit_infinity/init.lua
Executable file
103
worldedit_infinity/init.lua
Executable file
@ -0,0 +1,103 @@
|
||||
worldedit = rawget(_G, "worldedit") or {}
|
||||
local minetest = minetest --local copy of global
|
||||
|
||||
local get_pointed = function(pos, nearest, distance)
|
||||
if distance > 100 then
|
||||
return false
|
||||
end
|
||||
|
||||
--check for collision with node
|
||||
local nodename = minetest.get_node(pos).name
|
||||
if nodename ~= "air"
|
||||
and nodename ~= "default:water_source"
|
||||
and nodename ~= "default:water_flowing" then
|
||||
if nodename ~= "ignore" then
|
||||
return nearest
|
||||
end
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
local use = function(itemstack, user, pointed_thing)
|
||||
if pointed_thing.type == "nothing" then --pointing at nothing
|
||||
local placepos = worldedit.raytrace(user:getpos(), user:get_look_dir(), get_pointed)
|
||||
if placepos then --extended reach
|
||||
pointed_thing.type = "node"
|
||||
pointed_thing.under = nil --wip
|
||||
pointed_thing.above = nil --wip
|
||||
end
|
||||
end
|
||||
return minetest.item_place_node(itemstack, user, pointed_thing)
|
||||
end
|
||||
--
|
||||
|
||||
worldedit.raytrace = function(pos, dir, callback)
|
||||
local base = {x=math.floor(pos.x), y=math.floor(pos.y), z=math.floor(pos.z)}
|
||||
local stepx, stepy, stepz = 0, 0, 0
|
||||
local componentx, componenty, componentz = 0, 0, 0
|
||||
local intersectx, intersecty, intersectz = 0, 0, 0
|
||||
|
||||
if dir.x == 0 then
|
||||
intersectx = math.huge
|
||||
elseif dir.x > 0 then
|
||||
stepx = 1
|
||||
componentx = 1 / dir.x
|
||||
intersectx = ((base.x - pos.x) + 1) * componentx
|
||||
else
|
||||
stepx = -1
|
||||
componentx = 1 / -dir.x
|
||||
intersectx = (pos.x - base.x) * componentx
|
||||
end
|
||||
if dir.y == 0 then
|
||||
intersecty = math.huge
|
||||
elseif dir.y > 0 then
|
||||
stepy = 1
|
||||
componenty = 1 / dir.y
|
||||
intersecty = ((base.y - pos.y) + 1) * componenty
|
||||
else
|
||||
stepy = -1
|
||||
componenty = 1 / -dir.y
|
||||
intersecty = (pos.y - base.y) * componenty
|
||||
end
|
||||
if dir.z == 0 then
|
||||
intersectz = math.huge
|
||||
elseif dir.z > 0 then
|
||||
stepz = 1
|
||||
componentz = 1 / dir.z
|
||||
intersectz = ((base.z - pos.z) + 1) * componentz
|
||||
else
|
||||
stepz = -1
|
||||
componentz = 1 / -dir.z
|
||||
intersectz = (pos.z - base.z) * componentz
|
||||
end
|
||||
|
||||
local distance = 0
|
||||
local nearest = {x=base.x, y=base.y, z=base.z}
|
||||
while true do
|
||||
local values = {callback(base, nearest, distance)}
|
||||
if #values > 0 then
|
||||
return unpack(values)
|
||||
end
|
||||
|
||||
nearest.x, nearest.y, nearest.z = base.x, base.y, base.z
|
||||
if intersectx < intersecty then
|
||||
if intersectx < intersectz then
|
||||
base.x = base.x + stepx
|
||||
distance = intersectx
|
||||
intersectx = intersectx + componentx
|
||||
else
|
||||
base.z = base.z + stepz
|
||||
distance = intersectz
|
||||
intersectz = intersectz + componentz
|
||||
end
|
||||
elseif intersecty < intersectz then
|
||||
base.y = base.y + stepy
|
||||
distance = intersecty
|
||||
intersecty = intersecty + componenty
|
||||
else
|
||||
base.z = base.z + stepz
|
||||
distance = intersectz
|
||||
intersectz = intersectz + componentz
|
||||
end
|
||||
end
|
||||
end
|
1
worldedit_limited/depends.txt
Executable file
1
worldedit_limited/depends.txt
Executable file
@ -0,0 +1 @@
|
||||
worldedit
|
120
worldedit_limited/init.lua
Executable file
120
worldedit_limited/init.lua
Executable file
@ -0,0 +1,120 @@
|
||||
do return end
|
||||
do
|
||||
local MAX_VOLUME = 30 * 30 * 30
|
||||
|
||||
local we = worldedit
|
||||
local volume = we.volume
|
||||
local safewrap = function(func)
|
||||
return function(pos1, pos2, ...)
|
||||
if validbox(pos1, pos2) then
|
||||
return func(pos1, pos2, ...)
|
||||
end
|
||||
return 0, pos1, pos2
|
||||
end
|
||||
end
|
||||
|
||||
local validbox = function(pos1, pos2)
|
||||
tpos1, tpos2 = we.sort_pos(pos1, pos2)
|
||||
|
||||
if volume(tpos1, tpos2) > MAX_VOLUME then
|
||||
return false
|
||||
end
|
||||
|
||||
--check for ownership of area if ownership mod is installed
|
||||
if owner_defs then
|
||||
local inside = false
|
||||
for _, def in pairs(owner_defs) do
|
||||
--sort positions
|
||||
local tdef = {x1=def.x1, x2 = def.x2, y1=def.y1, y2=def.y2, z1=def.z1, z2=def.z2}
|
||||
if tdef.x1 > tdef.x2 then
|
||||
tdef.x1, tdef.x2 = tdef.x2, tdef.x1
|
||||
end
|
||||
if tdef.y1 > tdef.y2 then
|
||||
tdef.y1, tdef.y2 = tdef.y2, tdef.y1
|
||||
end
|
||||
if tdef.z1 > tdef.z2 then
|
||||
tdef.z1, tdef.z2 = tdef.z2, tdef.z1
|
||||
end
|
||||
|
||||
--check ownership
|
||||
if tpos1.x >= tdef.x1 and tpos1.x <= tdef.x2
|
||||
and tpos2.x >= tdef.x1 and tpos2.x <= tdef.x2
|
||||
and tpos1.y >= tdef.y1 and tpos1.y <= tdef.y2
|
||||
and tpos2.y >= tdef.y1 and tpos2.y <= tdef.y2
|
||||
and tpos1.z >= tdef.z1 and tpos1.z <= tdef.z2
|
||||
and tpos2.z >= tdef.z1 and tpos2.z <= tdef.z2
|
||||
and name == def.owner then --wip: name isn't available here
|
||||
inside = true
|
||||
break
|
||||
end
|
||||
end
|
||||
if not inside then
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
worldedit = {
|
||||
sort_pos = we.sort_pos,
|
||||
|
||||
set = safewrap(we.set),
|
||||
replace = safewrap(we.replace),
|
||||
replaceinverse = safewrap(we.replaceinverse),
|
||||
copy = function(pos1, pos2, axis, amount)
|
||||
tpos1, tpos2 = we.sort_pos(pos1, pos2)
|
||||
tpos1[axis] = tpos1[axis] + amount
|
||||
tpos2[axis] = tpos2[axis] + amount
|
||||
if validbox(pos1, pos2) and validbox(tpos1, tpos2) then
|
||||
we.copy(pos1, pos2, axis, amount)
|
||||
else
|
||||
return 0
|
||||
end
|
||||
end,
|
||||
move = function(pos1, pos2, axis, amount)
|
||||
tpos1, tpos2 = we.sort_pos(pos1, pos2)
|
||||
tpos1[axis] = tpos1[axis] + amount
|
||||
tpos2[axis] = tpos2[axis] + amount
|
||||
if validbox(pos1, pos2) and validbox(tpos1, tpos2) then
|
||||
we.move(pos1, pos2, axis, amount)
|
||||
else
|
||||
return 0
|
||||
end
|
||||
end,
|
||||
stack = function(pos1, pos2, axis, count)
|
||||
tpos1, tpos2 = we.sort_pos(pos1, pos2)
|
||||
local length = (tpos2[axis] - tpos1[axis] + 1) * count
|
||||
if count < 0 then
|
||||
tpos1[axis] = tpos1[axis] + length
|
||||
else
|
||||
tpos2[axis] = tpos2[axis] + length
|
||||
end
|
||||
if validbox(tpos1, tpos2) then
|
||||
we.stack(pos1, pos2, axis, amount)
|
||||
else
|
||||
return 0
|
||||
end
|
||||
end,
|
||||
--wip: add transpose, rotate safely
|
||||
flip = safewrap(we.flip),
|
||||
orient = safewrap(we.orient),
|
||||
fixlight = safewrap(we.fixlight),
|
||||
--wip: add primitives here
|
||||
volume = we.volume,
|
||||
hide = safewrap(we.hide),
|
||||
suppress = safewrap(we.suppress),
|
||||
highlight = safewrap(we.highlight),
|
||||
restore = safewrap(we.restore),
|
||||
serialize = safewrap(we.serialize),
|
||||
allocate = we.allocate,
|
||||
deserialize = function(originpos, value)
|
||||
local tpos1, tpos2 = we.allocate(originpos, value)
|
||||
if validbox(tpos1, tpos2) then
|
||||
we.deserialize(originpos, value)
|
||||
else
|
||||
return 0
|
||||
end
|
||||
end,
|
||||
}
|
||||
end
|
0
worldedit_shortcommands/depends.txt
Normal file → Executable file
0
worldedit_shortcommands/depends.txt
Normal file → Executable file
1
worldedit_shortcommands/init.lua
Normal file → Executable file
1
worldedit_shortcommands/init.lua
Normal file → Executable file
@ -25,7 +25,6 @@ worldedit.alias_chatcommand("/v", "/volume")
|
||||
worldedit.alias_chatcommand("/s", "/set")
|
||||
worldedit.alias_chatcommand("/r", "/replace")
|
||||
worldedit.alias_chatcommand("/ri", "/replaceinverse")
|
||||
worldedit.alias_chatcommand("/hcube", "/hollowcube")
|
||||
worldedit.alias_chatcommand("/hspr", "/hollowsphere")
|
||||
worldedit.alias_chatcommand("/spr", "/sphere")
|
||||
worldedit.alias_chatcommand("/hdo", "/hollowdome")
|
||||
|
Reference in New Issue
Block a user