forked from mtcontrib/Minetest-WorldEdit
Compare commits
99 Commits
Author | SHA1 | Date | |
---|---|---|---|
59dc2d34d9 | |||
283f47f10d | |||
35ad2f031d | |||
d572d769ce | |||
5bbb6b3909 | |||
d6a9b517b5 | |||
3c61759bae | |||
2f4eb19a3a | |||
2cb3fcde66 | |||
e680d8087e | |||
870873ad15 | |||
e356f4521c | |||
bf8e2a8233 | |||
6ceb56c3dc | |||
1fabe60d77 | |||
acc9188828 | |||
3240167b13 | |||
66b1fa032d | |||
a31f955fb1 | |||
38e9b42caf | |||
ea465f8fe4 | |||
0ce45a5900 | |||
56f77a2f27 | |||
610cd9981d | |||
c0f3bb6958 | |||
e49f717000 | |||
6e7b9a60be | |||
bcac45a476 | |||
426f3b949f | |||
78e4ba828e | |||
92fe95fab7 | |||
3a7fb5bf1e | |||
aa0e46d4e2 | |||
83288c969e | |||
f9311b2b15 | |||
15f0cea72e | |||
6e2e2385e9 | |||
152707a322 | |||
d040d324e8 | |||
df6b54d2f5 | |||
5abe1cee3d | |||
5afea424ba | |||
2aed498849 | |||
0b68b2aec6 | |||
f72abdb766 | |||
e18525d8c9 | |||
78890dde07 | |||
b922097e7a | |||
48f3f59fc3 | |||
f8f1f3b9cc | |||
d5e004be67 | |||
fad021d0ba | |||
f1fe0c6bba | |||
40cee99700 | |||
04d20de4cd | |||
859c6bd12a | |||
240380ff16 | |||
8d213d32a0 | |||
ae29a9f064 | |||
6cf8b92434 | |||
0b97a7c740 | |||
900b2f25aa | |||
f49663902c | |||
d475682d8f | |||
9e087ff995 | |||
b23e92921c | |||
61ab240cea | |||
b06e004d80 | |||
6dddc93ed7 | |||
b99a51f468 | |||
91c5053e67 | |||
f2f714c19e | |||
47712844a3 | |||
2bd4d6fa8f | |||
e9e8de385c | |||
2e2fcfdfa2 | |||
e0a2661700 | |||
7a19c5303b | |||
35b68c481b | |||
51158eca9f | |||
3aa315f134 | |||
3d30588a68 | |||
48f9c6c23f | |||
5f9efb1205 | |||
fc037e9c82 | |||
90d6b3d237 | |||
4bd5d56909 | |||
163dffccb3 | |||
6b2fe397e6 | |||
5c115e282c | |||
ab47385f7b | |||
78915d4a54 | |||
09de34aabf | |||
c1bd4986b0 | |||
bea38a116a | |||
4336e7ca14 | |||
eca54f0851 | |||
b0fbcf197f | |||
b468e24a20 |
@ -17,11 +17,15 @@ Many commands also have shorter names that can be typed faster. For example, if
|
|||||||
| `//s` | `//set` |
|
| `//s` | `//set` |
|
||||||
| `//r` | `//replace` |
|
| `//r` | `//replace` |
|
||||||
| `//ri` | `//replaceinverse` |
|
| `//ri` | `//replaceinverse` |
|
||||||
|
| `//hcube` | `//hollowcube` |
|
||||||
| `//hspr` | `//hollowsphere` |
|
| `//hspr` | `//hollowsphere` |
|
||||||
| `//spr` | `//sphere` |
|
| `//spr` | `//sphere` |
|
||||||
| `//hdo` | `//hollowdome` |
|
| `//hdo` | `//hollowdome` |
|
||||||
| `//do` | `//dome` |
|
| `//do` | `//dome` |
|
||||||
| `//hcyl` | `//hollowcylinder` |
|
| `//hcyl` | `//hollowcylinder` |
|
||||||
|
| `//cyl` | `//cylinder` |
|
||||||
|
| `//hpyr` | `//hollowpyramid` |
|
||||||
|
| `//pyr` | `//pyramid` |
|
||||||
|
|
||||||
### `//about`
|
### `//about`
|
||||||
|
|
||||||
@ -98,6 +102,12 @@ Display the volume of the current WorldEdit region.
|
|||||||
|
|
||||||
//volume
|
//volume
|
||||||
|
|
||||||
|
### `//deleteblocks`
|
||||||
|
|
||||||
|
Delete the MapBlocks (16x16x16 units) that contain the selected region. This means that mapgen will be invoked for that area. As only whole MapBlocks get removed, the deleted area is usually larger than the selected one. Also, mapgen can trigger mechanisms like mud reflow or cavegen, which affects nodes (up to 112 nodes away) outside the MapBlock, so dont use this near buildings. Note that active entities are not part of a MapBlock and do not get deleted.
|
||||||
|
|
||||||
|
//deleteblocks
|
||||||
|
|
||||||
### `//set <node>`
|
### `//set <node>`
|
||||||
|
|
||||||
Set the current WorldEdit region to `<node>`.
|
Set the current WorldEdit region to `<node>`.
|
||||||
@ -107,6 +117,10 @@ Set the current WorldEdit region to `<node>`.
|
|||||||
//set Blue Lightstone
|
//set Blue Lightstone
|
||||||
//set dirt with grass
|
//set dirt with grass
|
||||||
|
|
||||||
|
### `//param2 <param2>`
|
||||||
|
|
||||||
|
Set the param2 value of all nodes in the current WorldEdit region to `<param2>`.
|
||||||
|
|
||||||
### `//mix <node1> ...`
|
### `//mix <node1> ...`
|
||||||
|
|
||||||
Fill the current WorldEdit region with a random mix of `<node1>`, `...`.
|
Fill the current WorldEdit region with a random mix of `<node1>`, `...`.
|
||||||
@ -134,6 +148,19 @@ Replace all nodes other than `<search node>` with `<replace node>` in the curren
|
|||||||
//replaceinverse dirt Bronze Block
|
//replaceinverse dirt Bronze Block
|
||||||
//replaceinverse mesecons:wire_00000000_off flowers:flower_tulip
|
//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>`
|
### `//hollowsphere <radius> <node>`
|
||||||
|
|
||||||
Add hollow sphere centered at WorldEdit position 1 with radius `<radius>`, composed of `<node>`.
|
Add hollow sphere centered at WorldEdit position 1 with radius `<radius>`, composed of `<node>`.
|
||||||
@ -166,24 +193,45 @@ Add dome centered at WorldEdit position 1 with radius `<radius>`, composed of `<
|
|||||||
//dome -12 glass
|
//dome -12 glass
|
||||||
//dome 17 mesecons:wire_00000000_off
|
//dome 17 mesecons:wire_00000000_off
|
||||||
|
|
||||||
### `//hollowcylinder x/y/z/? <length> <radius> <node>`
|
### `//hollowcylinder x/y/z/? <length> <radius1> [radius2] <node>`
|
||||||
|
|
||||||
Add hollow cylinder at WorldEdit position 1 along the x/y/z/? axis with length `<length>` and radius `<radius>`, composed of `<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.
|
||||||
|
|
||||||
//hollowcylinder x +5 8 Bronze Block
|
//hollowcylinder x +5 8 Bronze Block
|
||||||
//hollowcylinder y 28 10 glass
|
//hollowcylinder y 28 10 glass
|
||||||
//hollowcylinder z -12 3 mesecons:wire_00000000_off
|
//hollowcylinder z -12 3 mesecons:wire_00000000_off
|
||||||
//hollowcylinder ? 2 4 default:stone
|
//hollowcylinder ? 2 4 default:stone
|
||||||
|
|
||||||
### `//cylinder x/y/z/? <length> <radius> <node>`
|
//hollowcylinder y 10 10 0 walls:cobble
|
||||||
|
//hollowcylinder x 6 0 5 Dirt
|
||||||
|
//hollowcylinder z 20 10 20 default:desert_stone
|
||||||
|
|
||||||
Add cylinder at WorldEdit position 1 along the x/y/z/? axis with length `<length>` and radius `<radius>`, composed of `<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).
|
||||||
|
|
||||||
//cylinder x +5 8 Bronze Block
|
//cylinder x +5 8 Bronze Block
|
||||||
//cylinder y 28 10 glass
|
//cylinder y 28 10 glass
|
||||||
//cylinder z -12 3 mesecons:wire_00000000_off
|
//cylinder z -12 3 mesecons:wire_00000000_off
|
||||||
//cylinder ? 2 4 default:stone
|
//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>`
|
||||||
|
|
||||||
|
Add hollow pyramid centered at WorldEdit position 1 along the x/y/z/? axis with height `<height>`, composed of `<node>`.
|
||||||
|
|
||||||
|
//hollowpyramid x 8 Diamond Block
|
||||||
|
//hollowpyramid y -5 glass
|
||||||
|
//hollowpyramid z 2 mesecons:wire_00000000_off
|
||||||
|
//hollowpyramid ? 12 mesecons:wire_00000000_off
|
||||||
|
|
||||||
### `//pyramid x/y/z? <height> <node>`
|
### `//pyramid x/y/z? <height> <node>`
|
||||||
|
|
||||||
Add pyramid centered at WorldEdit position 1 along the x/y/z/? axis with height `<height>`, composed of `<node>`.
|
Add pyramid centered at WorldEdit position 1 along the x/y/z/? axis with height `<height>`, composed of `<node>`.
|
||||||
@ -285,6 +333,12 @@ Fixes the lighting in the current WorldEdit region.
|
|||||||
|
|
||||||
//fixlight
|
//fixlight
|
||||||
|
|
||||||
|
### `//drain`
|
||||||
|
|
||||||
|
Removes any fluid node within the current WorldEdit region.
|
||||||
|
|
||||||
|
//drain
|
||||||
|
|
||||||
### `//hide`
|
### `//hide`
|
||||||
|
|
||||||
Hide all nodes in the current WorldEdit region non-destructively.
|
Hide all nodes in the current WorldEdit region non-destructively.
|
||||||
@ -374,3 +428,38 @@ This mode can be left with `//mtschemprob finish`. `//mtschemprob get` will disp
|
|||||||
Clears all objects within the WorldEdit region.
|
Clears all objects within the WorldEdit region.
|
||||||
|
|
||||||
//clearobjects
|
//clearobjects
|
||||||
|
|
||||||
|
### `//shift x/y/z/?/up/down/left/right/front/back [+|-]<amount>`
|
||||||
|
|
||||||
|
Shifts the selection area by `[+|-]<amount>` without touching its contents. The shifting axis can be absolute (`x/y/z`) or
|
||||||
|
relative (`up/down/left/right/front/back`).
|
||||||
|
|
||||||
|
//shift left 5
|
||||||
|
|
||||||
|
### `//expand [+|-]x/y/z/?/up/down/left/right/front/back <amount> [reverse-amount]`
|
||||||
|
|
||||||
|
Expands the selection by `<amount>` in the selected absolute or relative axis. If specified, the selection can be expanded in the
|
||||||
|
opposite direction over the same axis by `[reverse-amount]`.
|
||||||
|
|
||||||
|
//expand right 7 5
|
||||||
|
|
||||||
|
### `//contract [+|-]x/y/z/?/up/down/left/right/front/back <amount> [reverse-amount]`
|
||||||
|
|
||||||
|
Contracts the selection by `<amount>` in the selected absolute or relative axis. If specified, the selection can be contracted in the
|
||||||
|
opposite direction over the same axis by `[reverse-amount]`.
|
||||||
|
|
||||||
|
//expand right 7 5
|
||||||
|
|
||||||
|
### `//outset [hv] <amount>`
|
||||||
|
|
||||||
|
Expands the selection in all directions by `<amount>`. If specified, the selection can be expanded horizontally in the x and z axes `[h]`
|
||||||
|
or vertically in the y axis `[v]`.
|
||||||
|
|
||||||
|
//outset v 5
|
||||||
|
|
||||||
|
### `//inset [hv] <amount>`
|
||||||
|
|
||||||
|
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
|
||||||
|
21
README.md
21
README.md
@ -1,5 +1,5 @@
|
|||||||
WorldEdit v1.1 for Minetest 0.4.8+
|
WorldEdit v1.2
|
||||||
==================================
|
==============
|
||||||
The ultimate in-game world editing tool for [Minetest](http://minetest.net/)! Tons of functionality to help with building, fixing, and more.
|
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.
|
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`.
|
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 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.
|
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.
|
||||||
|
|
||||||
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.
|
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,21 +51,19 @@ 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 works quite well with other mods, and does not have any known mod conflicts.
|
||||||
|
|
||||||
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.
|
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).
|
||||||
|
|
||||||
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.
|
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 API
|
||||||
-------------
|
-------------
|
||||||
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.
|
WorldEdit exposes all significant functionality in a simple Lua interface.
|
||||||
|
|
||||||
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:
|
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.
|
||||||
|
|
||||||
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.
|
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 API.md).
|
This API is documented in the [WorldEdit API Reference](WorldEdit%20API.md).
|
||||||
|
|
||||||
Axes
|
Axes
|
||||||
----
|
----
|
||||||
@ -141,9 +139,13 @@ WorldEdit would not be possible without the contributions of many developers and
|
|||||||
cheapie
|
cheapie
|
||||||
cornernote
|
cornernote
|
||||||
cyisfor
|
cyisfor
|
||||||
|
danierukun
|
||||||
electricface
|
electricface
|
||||||
|
est31
|
||||||
kaeza
|
kaeza
|
||||||
khonkhortisan
|
khonkhortisan
|
||||||
|
pickardjoe
|
||||||
|
Sebastien Ponce
|
||||||
sfan5
|
sfan5
|
||||||
ShadowNinja
|
ShadowNinja
|
||||||
spillz
|
spillz
|
||||||
@ -156,5 +158,4 @@ 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).
|
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.
|
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.
|
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.
|
||||||
|
@ -27,6 +27,12 @@ Sets a region defined by positions `pos1` and `pos2` to `node_name`. To clear a
|
|||||||
|
|
||||||
Returns the number of nodes set.
|
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)
|
### count = worldedit.replace(pos1, pos2, searchnode, replacenode)
|
||||||
|
|
||||||
Replaces all instances of `searchnode` with `replacenode` in a region defined by positions `pos1` and `pos2`.
|
Replaces all instances of `searchnode` with `replacenode` in a region defined by positions `pos1` and `pos2`.
|
||||||
@ -45,6 +51,12 @@ Copies the region defined by positions `pos1` and `pos2` along the `axis` axis (
|
|||||||
|
|
||||||
Returns the number of nodes copied.
|
Returns the number of nodes copied.
|
||||||
|
|
||||||
|
### count = worldedit.copy2(pos1, pos2, off)
|
||||||
|
|
||||||
|
Copies the region defined by positions `pos1` and `pos2` by the offset vector `off`.
|
||||||
|
|
||||||
|
Returns the number of nodes copied.
|
||||||
|
|
||||||
### count = worldedit.move(pos1, pos2, axis, amount)
|
### count = worldedit.move(pos1, pos2, axis, amount)
|
||||||
|
|
||||||
Moves the region defined by positions `pos1` and `pos2` along the `axis` axis ("x" or "y" or "z") by `amount` nodes.
|
Moves the region defined by positions `pos1` and `pos2` along the `axis` axis ("x" or "y" or "z") by `amount` nodes.
|
||||||
@ -109,6 +121,12 @@ Primitives
|
|||||||
----------
|
----------
|
||||||
Contained in primitives.lua, this module allows the creation of several geometric 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)
|
### count = worldedit.sphere(pos, radius, node_name, hollow)
|
||||||
|
|
||||||
Adds a sphere centered at `pos` with radius `radius`, composed of `node_name`.
|
Adds a sphere centered at `pos` with radius `radius`, composed of `node_name`.
|
||||||
@ -121,15 +139,15 @@ Adds a dome centered at `pos` with radius `radius`, composed of `node_name`.
|
|||||||
|
|
||||||
Returns the number of nodes added.
|
Returns the number of nodes added.
|
||||||
|
|
||||||
### count = worldedit.cylinder(pos, axis, length, radius, node_name, hollow)
|
### count = worldedit.cylinder(pos, axis, length, radius1, radius2, node_name, hollow)
|
||||||
|
|
||||||
Adds a cylinder at `pos` along the `axis` axis ("x" or "y" or "z") with length `length` and radius `radius`, composed of `node_name`.
|
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`.
|
||||||
|
|
||||||
Returns the number of nodes added.
|
Returns the number of nodes added.
|
||||||
|
|
||||||
### count = worldedit.pyramid(pos, axis, height, node_name)
|
### count = worldedit.pyramid(pos, axis, height, node_name, hollow)
|
||||||
|
|
||||||
Adds a pyramid centered at `pos` along the `axis` axis ("x" or "y" or "z") with height `height`.
|
Adds a pyramid centered at `pos` along the `axis` axis ("x" or "y" or "z") with height `height`, composed of `node_name`.
|
||||||
|
|
||||||
Returns the number of nodes added.
|
Returns the number of nodes added.
|
||||||
|
|
||||||
|
258
worldedit/cuboid.lua
Normal file
258
worldedit/cuboid.lua
Normal file
@ -0,0 +1,258 @@
|
|||||||
|
-- Expands or contracts the cuboid in all axes by amount (positive or negative)
|
||||||
|
worldedit.cuboid_volumetric_expand = function(name, amount)
|
||||||
|
local pos1 = worldedit.pos1[name]
|
||||||
|
local pos2 = worldedit.pos2[name]
|
||||||
|
|
||||||
|
if pos1 == nil or pos2 == nil then
|
||||||
|
return false, "Undefined cuboid"
|
||||||
|
end
|
||||||
|
|
||||||
|
local delta1 = vector.new()
|
||||||
|
local delta2 = vector.new()
|
||||||
|
local delta_dir1
|
||||||
|
local delta_dir2
|
||||||
|
|
||||||
|
delta1 = vector.add(delta1, amount)
|
||||||
|
delta2 = vector.add(delta2, amount)
|
||||||
|
delta_dir1, delta_dir2 = worldedit.get_expansion_directions(pos1, pos2)
|
||||||
|
delta1 = vector.multiply(delta1, delta_dir1)
|
||||||
|
delta2 = vector.multiply(delta2, delta_dir2)
|
||||||
|
worldedit.pos1[name] = vector.add(pos1, delta1)
|
||||||
|
worldedit.pos2[name] = vector.add(pos2, delta2)
|
||||||
|
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- Expands or contracts the cuboid in a single axis by amount (positive or negative)
|
||||||
|
worldedit.cuboid_linear_expand = function(name, axis, direction, amount)
|
||||||
|
local pos1 = worldedit.pos1[name]
|
||||||
|
local pos2 = worldedit.pos2[name]
|
||||||
|
|
||||||
|
if pos1 == nil or pos2 == nil then
|
||||||
|
return false, "undefined cuboid"
|
||||||
|
end
|
||||||
|
|
||||||
|
if direction ~= 1 and direction ~= -1 then
|
||||||
|
return false, "invalid marker"
|
||||||
|
end
|
||||||
|
|
||||||
|
local marker = worldedit.marker_get_closest_to_axis(name, axis, direction)
|
||||||
|
local deltavect = vector.new()
|
||||||
|
|
||||||
|
if axis == 'x' then
|
||||||
|
deltavect.x = amount * direction
|
||||||
|
elseif axis == 'y' then
|
||||||
|
deltavect.y = amount * direction
|
||||||
|
elseif axis == 'z' then
|
||||||
|
deltavect.z = amount * direction
|
||||||
|
else
|
||||||
|
return false, "invalid axis"
|
||||||
|
end
|
||||||
|
|
||||||
|
worldedit.marker_move(name, marker, deltavect)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- Shifts the cuboid by '+-amount' in axis 'axis'
|
||||||
|
worldedit.cuboid_shift = function(name, axis, amount)
|
||||||
|
local pos1 = worldedit.pos1[name]
|
||||||
|
local pos2 = worldedit.pos2[name]
|
||||||
|
|
||||||
|
if pos1 == nil or pos2 == nil then
|
||||||
|
return false, "undefined cuboid"
|
||||||
|
end
|
||||||
|
|
||||||
|
if axis == 'x' then
|
||||||
|
worldedit.pos1[name].x = pos1.x + amount
|
||||||
|
worldedit.pos2[name].x = pos2.x + amount
|
||||||
|
elseif axis == 'y' then
|
||||||
|
worldedit.pos1[name].y = pos1.y + amount
|
||||||
|
worldedit.pos2[name].y = pos2.y + amount
|
||||||
|
elseif axis == 'z' then
|
||||||
|
worldedit.pos1[name].z = pos1.z + amount
|
||||||
|
worldedit.pos2[name].z = pos2.z + amount
|
||||||
|
else
|
||||||
|
return false, "invalid axis"
|
||||||
|
end
|
||||||
|
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- Moves the location of a single marker by adding deltavector
|
||||||
|
worldedit.marker_move = function(name, marker, deltavector)
|
||||||
|
if marker ~= 1 and marker ~= 2 then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
if marker == 1 then
|
||||||
|
local pos = worldedit.pos1[name]
|
||||||
|
worldedit.pos1[name] = vector.add(deltavector, pos)
|
||||||
|
else
|
||||||
|
local pos = worldedit.pos2[name]
|
||||||
|
worldedit.pos2[name] = vector.add(deltavector, pos)
|
||||||
|
end
|
||||||
|
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Updates the location ingame of the markers
|
||||||
|
worldedit.marker_update = function(name, marker)
|
||||||
|
if marker == nil then
|
||||||
|
worldedit.mark_pos1(name)
|
||||||
|
worldedit.mark_pos2(name)
|
||||||
|
elseif marker == 1 then
|
||||||
|
worldedit.mark_pos1(name)
|
||||||
|
elseif marker == 2 then
|
||||||
|
worldedit.mark_pos2(name)
|
||||||
|
else
|
||||||
|
minetest.debug(
|
||||||
|
"worldedit: Invalid execution of function update_markers")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- Returns two vectors with the directions for volumetric expansion
|
||||||
|
worldedit.get_expansion_directions = function(mark1, mark2)
|
||||||
|
if mark1 == nil or mark2 == nil then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local dir1 = vector.new()
|
||||||
|
local dir2 = vector.new()
|
||||||
|
|
||||||
|
if mark1.x < mark2.x then
|
||||||
|
dir1.x = -1
|
||||||
|
dir2.x = 1
|
||||||
|
else
|
||||||
|
dir1.x = 1
|
||||||
|
dir2.x = -1
|
||||||
|
end
|
||||||
|
if mark1.y < mark2.y then
|
||||||
|
dir1.y = -1
|
||||||
|
dir2.y = 1
|
||||||
|
else
|
||||||
|
dir1.y = 1
|
||||||
|
dir2.y = -1
|
||||||
|
end
|
||||||
|
if mark1.z < mark2.z then
|
||||||
|
dir1.z = -1
|
||||||
|
dir2.z = 1
|
||||||
|
else
|
||||||
|
dir1.z = 1
|
||||||
|
dir2.z = -1
|
||||||
|
end
|
||||||
|
return dir1, dir2
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- Return the marker that is closest to the player
|
||||||
|
worldedit.marker_get_closest_to_player = function(name)
|
||||||
|
local playerpos = minetest.get_player_by_name(name):getpos()
|
||||||
|
local dist1 = vector.distance(playerpos, worldedit.pos1[name])
|
||||||
|
local dist2 = vector.distance(playerpos, worldedit.pos2[name])
|
||||||
|
|
||||||
|
if dist1 < dist2 then
|
||||||
|
return 1
|
||||||
|
else
|
||||||
|
return 2
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- Returns the closest marker to the specified axis and direction
|
||||||
|
worldedit.marker_get_closest_to_axis = function(name, axis, direction)
|
||||||
|
local pos1 = vector.new()
|
||||||
|
local pos2 = vector.new()
|
||||||
|
|
||||||
|
if direction ~= 1 and direction ~= -1 then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
if axis == 'x' then
|
||||||
|
pos1.x = worldedit.pos1[name].x * direction
|
||||||
|
pos2.x = worldedit.pos2[name].x * direction
|
||||||
|
if pos1.x > pos2.x then
|
||||||
|
return 1
|
||||||
|
else
|
||||||
|
return 2
|
||||||
|
end
|
||||||
|
elseif axis == 'y' then
|
||||||
|
pos1.y = worldedit.pos1[name].y * direction
|
||||||
|
pos2.y = worldedit.pos2[name].y * direction
|
||||||
|
if pos1.y > pos2.y then
|
||||||
|
return 1
|
||||||
|
else
|
||||||
|
return 2
|
||||||
|
end
|
||||||
|
elseif axis == 'z' then
|
||||||
|
pos1.z = worldedit.pos1[name].z * direction
|
||||||
|
pos2.z = worldedit.pos2[name].z * direction
|
||||||
|
if pos1.z > pos2.z then
|
||||||
|
return 1
|
||||||
|
else
|
||||||
|
return 2
|
||||||
|
end
|
||||||
|
else
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- Translates up, down, left, right, front, back to their corresponding axes and
|
||||||
|
-- directions according to faced direction
|
||||||
|
worldedit.translate_direction = function(name, direction)
|
||||||
|
local axis, dir = worldedit.player_axis(name)
|
||||||
|
local resaxis, resdir
|
||||||
|
|
||||||
|
if direction == "up" then
|
||||||
|
return 'y', 1
|
||||||
|
end
|
||||||
|
|
||||||
|
if direction == "down" then
|
||||||
|
return 'y', -1
|
||||||
|
end
|
||||||
|
|
||||||
|
if direction == "front" then
|
||||||
|
if axis == "y" then
|
||||||
|
resaxis = nil
|
||||||
|
resdir = nil
|
||||||
|
else
|
||||||
|
resaxis = axis
|
||||||
|
resdir = dir
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if direction == "back" then
|
||||||
|
if axis == "y" then
|
||||||
|
resaxis = nil
|
||||||
|
resdir = nil
|
||||||
|
else
|
||||||
|
resaxis = axis
|
||||||
|
resdir = -dir
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if direction == "left" then
|
||||||
|
if axis == 'x' then
|
||||||
|
resaxis = 'z'
|
||||||
|
resdir = dir
|
||||||
|
elseif axis == 'z' then
|
||||||
|
resaxis = 'x'
|
||||||
|
resdir = -dir
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if direction == "right" then
|
||||||
|
if axis == 'x' then
|
||||||
|
resaxis = 'z'
|
||||||
|
resdir = -dir
|
||||||
|
elseif axis == 'z' then
|
||||||
|
resaxis = 'x'
|
||||||
|
resdir = dir
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return resaxis, resdir
|
||||||
|
end
|
@ -1,6 +1,6 @@
|
|||||||
--- Worldedit.
|
--- Worldedit.
|
||||||
-- @module worldedit
|
-- @module worldedit
|
||||||
-- @release 1.1
|
-- @release 1.2
|
||||||
-- @copyright 2013 sfan5, Anthony Zhang (Uberi/Temperest), and Brett O'Donnell (cornernote).
|
-- @copyright 2013 sfan5, Anthony Zhang (Uberi/Temperest), and Brett O'Donnell (cornernote).
|
||||||
-- @license GNU Affero General Public License version 3 (AGPLv3)
|
-- @license GNU Affero General Public License version 3 (AGPLv3)
|
||||||
-- @author sfan5
|
-- @author sfan5
|
||||||
@ -8,9 +8,12 @@
|
|||||||
-- @author Bret O'Donnel (cornernote)
|
-- @author Bret O'Donnel (cornernote)
|
||||||
-- @author ShadowNinja
|
-- @author ShadowNinja
|
||||||
|
|
||||||
|
|
||||||
worldedit = {}
|
worldedit = {}
|
||||||
worldedit.version = {1, 1, major=1, minor=1}
|
|
||||||
worldedit.version_string = table.concat(worldedit.version, ".")
|
local ver = {major=1, minor=2}
|
||||||
|
worldedit.version = ver
|
||||||
|
worldedit.version_string = string.format("%d.%d", ver.major, ver.minor)
|
||||||
|
|
||||||
if not minetest.get_voxel_manip then
|
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."
|
local err_msg = "This version of WorldEdit requires Minetest 0.4.8 or later! You have an old version."
|
||||||
@ -23,7 +26,7 @@ end
|
|||||||
local path = minetest.get_modpath(minetest.get_current_modname())
|
local path = minetest.get_modpath(minetest.get_current_modname())
|
||||||
|
|
||||||
local function load_module(path)
|
local function load_module(path)
|
||||||
local file = io.open(path)
|
local file = io.open(path, "r")
|
||||||
if not file then return end
|
if not file then return end
|
||||||
file:close()
|
file:close()
|
||||||
return dofile(path)
|
return dofile(path)
|
||||||
@ -36,6 +39,7 @@ load_module(path .. "/visualization.lua")
|
|||||||
load_module(path .. "/serialization.lua")
|
load_module(path .. "/serialization.lua")
|
||||||
load_module(path .. "/code.lua")
|
load_module(path .. "/code.lua")
|
||||||
load_module(path .. "/compatibility.lua")
|
load_module(path .. "/compatibility.lua")
|
||||||
|
load_module(path .. "/cuboid.lua")
|
||||||
|
|
||||||
|
|
||||||
if minetest.setting_getbool("log_mods") then
|
if minetest.setting_getbool("log_mods") then
|
||||||
|
@ -38,6 +38,29 @@ function worldedit.set(pos1, pos2, node_names)
|
|||||||
return worldedit.volume(pos1, pos2)
|
return worldedit.volume(pos1, pos2)
|
||||||
end
|
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.
|
--- Replaces all instances of `search_node` with `replace_node` in a region.
|
||||||
-- When `inverse` is `true`, replaces all instances that are NOT `search_node`.
|
-- When `inverse` is `true`, replaces all instances that are NOT `search_node`.
|
||||||
@ -90,7 +113,7 @@ function worldedit.stack2(pos1, pos2, direction, amount, finished)
|
|||||||
translated.x = translated.x + direction.x
|
translated.x = translated.x + direction.x
|
||||||
translated.y = translated.y + direction.y
|
translated.y = translated.y + direction.y
|
||||||
translated.z = translated.z + direction.z
|
translated.z = translated.z + direction.z
|
||||||
worldedit.copy2(pos1, pos2, translated, volume)
|
worldedit.copy2(pos1, pos2, translated)
|
||||||
minetest.after(0, next_one)
|
minetest.after(0, next_one)
|
||||||
else
|
else
|
||||||
if finished then
|
if finished then
|
||||||
@ -164,6 +187,38 @@ function worldedit.copy(pos1, pos2, axis, amount)
|
|||||||
return worldedit.volume(pos1, pos2)
|
return worldedit.volume(pos1, pos2)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Copies a region by offset vector `off`.
|
||||||
|
-- @param pos1
|
||||||
|
-- @param pos2
|
||||||
|
-- @param off
|
||||||
|
-- @return The number of nodes copied.
|
||||||
|
function worldedit.copy2(pos1, pos2, off)
|
||||||
|
local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
|
||||||
|
|
||||||
|
worldedit.keep_loaded(pos1, pos2)
|
||||||
|
|
||||||
|
local get_node, get_meta, set_node = minetest.get_node,
|
||||||
|
minetest.get_meta, minetest.set_node
|
||||||
|
local pos = {}
|
||||||
|
pos.x = pos2.x
|
||||||
|
while pos.x >= pos1.x do
|
||||||
|
pos.y = pos2.y
|
||||||
|
while pos.y >= pos1.y do
|
||||||
|
pos.z = pos2.z
|
||||||
|
while pos.z >= pos1.z do
|
||||||
|
local node = get_node(pos) -- Obtain current node
|
||||||
|
local meta = get_meta(pos):to_table() -- Get meta of current node
|
||||||
|
local newpos = vector.add(pos, off) -- Calculate new position
|
||||||
|
set_node(newpos, node) -- Copy node to new position
|
||||||
|
get_meta(newpos):from_table(meta) -- Set metadata of new node
|
||||||
|
pos.z = pos.z - 1
|
||||||
|
end
|
||||||
|
pos.y = pos.y - 1
|
||||||
|
end
|
||||||
|
pos.x = pos.x - 1
|
||||||
|
end
|
||||||
|
return worldedit.volume(pos1, pos2)
|
||||||
|
end
|
||||||
|
|
||||||
--- Moves a region along `axis` by `amount` nodes.
|
--- Moves a region along `axis` by `amount` nodes.
|
||||||
-- @return The number of nodes moved.
|
-- @return The number of nodes moved.
|
||||||
@ -503,8 +558,8 @@ function worldedit.orient(pos1, pos2, angle)
|
|||||||
worldedit.keep_loaded(pos1, pos2)
|
worldedit.keep_loaded(pos1, pos2)
|
||||||
|
|
||||||
local count = 0
|
local count = 0
|
||||||
local get_node, get_meta, swap_node = minetest.get_node,
|
local set_node, get_node, get_meta, swap_node = minetest.set_node,
|
||||||
minetest.get_meta, minetest.swap_node
|
minetest.get_node, minetest.get_meta, minetest.swap_node
|
||||||
local pos = {x=pos1.x, y=0, z=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
|
||||||
@ -543,14 +598,11 @@ end
|
|||||||
function worldedit.fixlight(pos1, pos2)
|
function worldedit.fixlight(pos1, pos2)
|
||||||
local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
|
local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
|
||||||
|
|
||||||
worldedit.keep_loaded(pos1, pos2)
|
local vmanip = minetest.get_voxel_manip(pos1, pos2)
|
||||||
|
vmanip:write_to_map()
|
||||||
|
vmanip:update_map() -- this updates the lighting
|
||||||
|
|
||||||
local nodes = minetest.find_nodes_in_area(pos1, pos2, "air")
|
return worldedit.volume(pos1, pos2)
|
||||||
local dig_node = minetest.dig_node
|
|
||||||
for _, pos in ipairs(nodes) do
|
|
||||||
dig_node(pos)
|
|
||||||
end
|
|
||||||
return #nodes
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@ -4,6 +4,47 @@
|
|||||||
local mh = worldedit.manip_helpers
|
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`.
|
--- Adds a sphere of `node_name` centered at `pos`.
|
||||||
-- @param pos Position to center sphere at.
|
-- @param pos Position to center sphere at.
|
||||||
-- @param radius Sphere radius.
|
-- @param radius Sphere radius.
|
||||||
@ -92,35 +133,48 @@ end
|
|||||||
-- @param pos Position to center base of cylinder at.
|
-- @param pos Position to center base of cylinder at.
|
||||||
-- @param axis Axis ("x", "y", or "z")
|
-- @param axis Axis ("x", "y", or "z")
|
||||||
-- @param length Cylinder length.
|
-- @param length Cylinder length.
|
||||||
-- @param radius Cylinder radius.
|
-- @param radius1 Cylinder base radius.
|
||||||
|
-- @param radius2 Cylinder top radius.
|
||||||
-- @param node_name Name of node to make cylinder of.
|
-- @param node_name Name of node to make cylinder of.
|
||||||
-- @param hollow Whether the cylinder should be hollow.
|
-- @param hollow Whether the cylinder should be hollow.
|
||||||
-- @return The number of nodes added.
|
-- @return The number of nodes added.
|
||||||
function worldedit.cylinder(pos, axis, length, radius, node_name, hollow)
|
function worldedit.cylinder(pos, axis, length, radius1, radius2, node_name, hollow)
|
||||||
local other1, other2 = worldedit.get_axis_others(axis)
|
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
|
-- Handle negative lengths
|
||||||
local current_pos = {x=pos.x, y=pos.y, z=pos.z}
|
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
|
||||||
|
radius1, radius2 = radius2, radius1
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Set up voxel manipulator
|
-- Set up voxel manipulator
|
||||||
local manip, area = mh.init_axis_radius_length(current_pos, axis, radius, length)
|
local manip, area = mh.init_axis_radius_length(current_pos, axis, math.max(radius1, radius2), length)
|
||||||
local data = mh.get_empty_data(area)
|
local data = mh.get_empty_data(area)
|
||||||
|
|
||||||
-- Add cylinder
|
-- 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 min_radius, max_radius = radius * (radius - 1), radius * (radius + 1)
|
|
||||||
local stride = {x=1, y=area.ystride, z=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,
|
||||||
z = current_pos.z - area.MinEdge.z,
|
z = current_pos.z - area.MinEdge.z,
|
||||||
}
|
}
|
||||||
local min_slice, max_slice = offset[axis], offset[axis] + length - 1
|
|
||||||
local count = 0
|
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
|
for index2 = -radius, radius do
|
||||||
-- Offset contributed by other axis 1 plus 1 to make it 1-indexed
|
-- Offset contributed by other axis 1 plus 1 to make it 1-indexed
|
||||||
local new_index2 = (index2 + offset[other1]) * stride[other1] + 1
|
local new_index2 = (index2 + offset[other1]) * stride[other1] + 1
|
||||||
@ -128,13 +182,11 @@ function worldedit.cylinder(pos, axis, length, radius, node_name, hollow)
|
|||||||
local new_index3 = new_index2 + (index3 + offset[other2]) * stride[other2]
|
local new_index3 = new_index2 + (index3 + offset[other2]) * stride[other2]
|
||||||
local squared = index2 * index2 + index3 * index3
|
local squared = index2 * index2 + index3 * index3
|
||||||
if squared <= max_radius and (not hollow or squared >= min_radius) then
|
if squared <= max_radius and (not hollow or squared >= min_radius) then
|
||||||
-- Position is in cylinder
|
-- Position is in cylinder, add node here
|
||||||
-- Add column along axis
|
local vi = new_index3 + (offset[axis] + i) * stride[axis]
|
||||||
for index1 = min_slice, max_slice do
|
|
||||||
local vi = new_index3 + index1 * stride[axis]
|
|
||||||
data[vi] = node_id
|
data[vi] = node_id
|
||||||
|
count = count + 1
|
||||||
end
|
end
|
||||||
count = count + length
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -150,14 +202,15 @@ end
|
|||||||
-- @param axis Axis ("x", "y", or "z")
|
-- @param axis Axis ("x", "y", or "z")
|
||||||
-- @param height Pyramid height.
|
-- @param height Pyramid height.
|
||||||
-- @param node_name Name of node to make pyramid of.
|
-- @param node_name Name of node to make pyramid of.
|
||||||
|
-- @param hollow Whether the pyramid should be hollow.
|
||||||
-- @return The number of nodes added.
|
-- @return The number of nodes added.
|
||||||
function worldedit.pyramid(pos, axis, height, node_name)
|
function worldedit.pyramid(pos, axis, height, node_name, hollow)
|
||||||
local other1, other2 = worldedit.get_axis_others(axis)
|
local other1, other2 = worldedit.get_axis_others(axis)
|
||||||
|
|
||||||
-- Set up voxel manipulator
|
-- Set up voxel manipulator
|
||||||
local manip, area = mh.init_axis_radius(pos, axis,
|
local manip, area = mh.init_axis_radius(pos, axis,
|
||||||
height >= 0 and height or -height)
|
height >= 0 and height or -height)
|
||||||
local data = mh.get_empty_data()
|
local data = mh.get_empty_data(area)
|
||||||
|
|
||||||
-- Handle inverted pyramids
|
-- Handle inverted pyramids
|
||||||
local start_axis, end_axis, step
|
local start_axis, end_axis, step
|
||||||
@ -177,7 +230,7 @@ function worldedit.pyramid(pos, axis, height, node_name)
|
|||||||
y = pos.y - area.MinEdge.y,
|
y = pos.y - area.MinEdge.y,
|
||||||
z = pos.z - area.MinEdge.z,
|
z = pos.z - area.MinEdge.z,
|
||||||
}
|
}
|
||||||
local size = height * step
|
local size = math.abs(height * step)
|
||||||
local count = 0
|
local count = 0
|
||||||
-- For each level of the pyramid
|
-- For each level of the pyramid
|
||||||
for index1 = 0, height, step do
|
for index1 = 0, height, step do
|
||||||
@ -187,10 +240,12 @@ function worldedit.pyramid(pos, axis, height, node_name)
|
|||||||
local new_index2 = new_index1 + (index2 + offset[other1]) * stride[other1]
|
local new_index2 = new_index1 + (index2 + offset[other1]) * stride[other1]
|
||||||
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
|
||||||
data[i] = node_id
|
data[i] = node_id
|
||||||
|
count = count + 1
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
count = count + (size * 2 + 1) ^ 2
|
|
||||||
size = size - 1
|
size = size - 1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -144,9 +144,9 @@ local function load_schematic(value)
|
|||||||
"([^%s]+)%s+(%d+)%s+(%d+)[^\r\n]*[\r\n]*") do
|
"([^%s]+)%s+(%d+)%s+(%d+)[^\r\n]*[\r\n]*") do
|
||||||
param1, param2 = tonumber(param1), tonumber(param2)
|
param1, param2 = tonumber(param1), tonumber(param2)
|
||||||
table.insert(nodes, {
|
table.insert(nodes, {
|
||||||
x = originx + tonumber(x),
|
x = tonumber(x),
|
||||||
y = originy + tonumber(y),
|
y = tonumber(y),
|
||||||
z = originz + tonumber(z),
|
z = tonumber(z),
|
||||||
name = name,
|
name = name,
|
||||||
param1 = param1 ~= 0 and param1 or nil,
|
param1 = param1 ~= 0 and param1 or nil,
|
||||||
param2 = param2 ~= 0 and param2 or nil,
|
param2 = param2 ~= 0 and param2 or nil,
|
||||||
@ -159,20 +159,20 @@ local function load_schematic(value)
|
|||||||
else
|
else
|
||||||
-- XXX: This is a filthy hack that works surprisingly well - in LuaJIT, `minetest.deserialize` will fail due to the register limit
|
-- XXX: This is a filthy hack that works surprisingly well - in LuaJIT, `minetest.deserialize` will fail due to the register limit
|
||||||
nodes = {}
|
nodes = {}
|
||||||
value = value:gsub("return%s*{", "", 1):gsub("}%s*$", "", 1) -- remove the starting and ending values to leave only the node data
|
content = content:gsub("return%s*{", "", 1):gsub("}%s*$", "", 1) -- remove the starting and ending values to leave only the node data
|
||||||
local escaped = value: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, endpos = 1, 1
|
local startpos, startpos1, endpos = 1, 1
|
||||||
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*{", startpos)
|
startpos, endpos = escaped:find("},%s*{", startpos)
|
||||||
if not startpos then
|
if not startpos then
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
local current = value:sub(startpos1, startpos)
|
local current = content:sub(startpos1, startpos)
|
||||||
local entry = minetest.deserialize("return " .. current)
|
local entry = minetest.deserialize("return " .. current)
|
||||||
table.insert(nodes, entry)
|
table.insert(nodes, entry)
|
||||||
startpos, startpos1 = endpos, endpos
|
startpos, startpos1 = endpos, endpos
|
||||||
end
|
end
|
||||||
local entry = minetest.deserialize("return " .. value:sub(startpos1)) -- process the last entry
|
local entry = minetest.deserialize("return " .. content:sub(startpos1)) -- process the last entry
|
||||||
table.insert(nodes, entry)
|
table.insert(nodes, entry)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
|
BIN
worldedit/textures/worldedit_wand.png
Normal file
BIN
worldedit/textures/worldedit_wand.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 442 B |
1
worldedit_commands/.gitignore
vendored
Normal file
1
worldedit_commands/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
*~
|
240
worldedit_commands/cuboid.lua
Normal file
240
worldedit_commands/cuboid.lua
Normal file
@ -0,0 +1,240 @@
|
|||||||
|
minetest.register_chatcommand("/outset", {
|
||||||
|
params = "[h|v] <amount>",
|
||||||
|
description = "outset the selection",
|
||||||
|
privs = {worldedit=true},
|
||||||
|
func = function(name, param)
|
||||||
|
local find, _, dir, amount = param:find("(%a*)%s*([+-]?%d+)")
|
||||||
|
|
||||||
|
if find == nil then
|
||||||
|
return false, "invalid usage: " .. param
|
||||||
|
end
|
||||||
|
|
||||||
|
local pos1 = worldedit.pos1[name]
|
||||||
|
local pos2 = worldedit.pos2[name]
|
||||||
|
|
||||||
|
if pos1 == nil or pos2 == nil then
|
||||||
|
return false,
|
||||||
|
"Undefined region. Region must be defined beforehand."
|
||||||
|
end
|
||||||
|
|
||||||
|
local hv_test = dir:find("[^hv]+")
|
||||||
|
|
||||||
|
if hv_test ~= nil then
|
||||||
|
return false, "Invalid direction."
|
||||||
|
end
|
||||||
|
|
||||||
|
if dir == "" or dir == "hv" or dir == "vh" then
|
||||||
|
assert(worldedit.cuboid_volumetric_expand(name, amount))
|
||||||
|
elseif dir == "h" then
|
||||||
|
assert(worldedit.cuboid_linear_expand(name, 'x', 1, amount))
|
||||||
|
assert(worldedit.cuboid_linear_expand(name, 'x', -1, amount))
|
||||||
|
assert(worldedit.cuboid_linear_expand(name, 'z', 1, amount))
|
||||||
|
assert(worldedit.cuboid_linear_expand(name, 'z', -1, amount))
|
||||||
|
elseif dir == "v" then
|
||||||
|
assert(worldedit.cuboid_linear_expand(name, 'y', 1, amount))
|
||||||
|
assert(worldedit.cuboid_linear_expand(name, 'y', -1, amount))
|
||||||
|
else
|
||||||
|
return false, "Invalid number of arguments"
|
||||||
|
end
|
||||||
|
|
||||||
|
worldedit.marker_update(name)
|
||||||
|
return true, "Region outset by " .. amount .. " blocks"
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
minetest.register_chatcommand("/inset", {
|
||||||
|
params = "[h|v] <amount>",
|
||||||
|
description = "inset the selection",
|
||||||
|
privs = {worldedit=true},
|
||||||
|
func = function(name, param)
|
||||||
|
local find, _, dir, amount = param:find("(%a*)%s*([+-]?%d+)")
|
||||||
|
|
||||||
|
if find == nil then
|
||||||
|
return false, "invalid usage: " .. param
|
||||||
|
end
|
||||||
|
|
||||||
|
local pos1 = worldedit.pos1[name]
|
||||||
|
local pos2 = worldedit.pos2[name]
|
||||||
|
|
||||||
|
if pos1 == nil or pos2 == nil then
|
||||||
|
return false,
|
||||||
|
"Undefined region. Region must be defined beforehand."
|
||||||
|
end
|
||||||
|
|
||||||
|
local hv_test = dir:find("[^hv]+")
|
||||||
|
|
||||||
|
if hv_test ~= nil then
|
||||||
|
return false, "Invalid direction."
|
||||||
|
end
|
||||||
|
|
||||||
|
if dir == "" or dir == "vh" or dir == "hv" then
|
||||||
|
assert(worldedit.cuboid_volumetric_expand(name, -amount))
|
||||||
|
elseif dir == "h" then
|
||||||
|
assert(worldedit.cuboid_linear_expand(name, 'x', 1, -amount))
|
||||||
|
assert(worldedit.cuboid_linear_expand(name, 'x', -1, -amount))
|
||||||
|
assert(worldedit.cuboid_linear_expand(name, 'z', 1, -amount))
|
||||||
|
assert(worldedit.cuboid_linear_expand(name, 'z', -1, -amount))
|
||||||
|
elseif dir == "v" then
|
||||||
|
assert(worldedit.cuboid_linear_expand(name, 'y', 1, -amount))
|
||||||
|
assert(worldedit.cuboid_linear_expand(name, 'y', -1, -amount))
|
||||||
|
else
|
||||||
|
return false, "Invalid number of arguments"
|
||||||
|
end
|
||||||
|
|
||||||
|
worldedit.marker_update(name)
|
||||||
|
return true, "Region inset by " .. amount .. " blocks"
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
minetest.register_chatcommand("/shift", {
|
||||||
|
params = "[x|y|z|?|up|down|left|right|front|back] [+|-]<amount>",
|
||||||
|
description = "Moves the selection region. Does not move contents.",
|
||||||
|
privs = {worldedit=true},
|
||||||
|
func = function(name, param)
|
||||||
|
local pos1 = worldedit.pos1[name]
|
||||||
|
local pos2 = worldedit.pos2[name]
|
||||||
|
local find, _, direction, amount = param:find("([%?%l]+)%s*([+-]?%d+)")
|
||||||
|
|
||||||
|
if find == nil then
|
||||||
|
worldedit.player_notify(name, "invalid usage: " .. param)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if pos1 == nil or pos2 == nil then
|
||||||
|
worldedit.player_notify(name,
|
||||||
|
"Undefined region. Region must be defined beforehand.")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local axis, dir
|
||||||
|
if direction == "x" or direction == "y" or direction == "z" then
|
||||||
|
axis, dir = direction, 1
|
||||||
|
elseif direction == "?" then
|
||||||
|
axis, dir = worldedit.player_axis(name)
|
||||||
|
else
|
||||||
|
axis, dir = worldedit.translate_direction(name, direction)
|
||||||
|
end
|
||||||
|
|
||||||
|
if axis == nil or dir == nil then
|
||||||
|
return false, "Invalid if looking straight up or down"
|
||||||
|
end
|
||||||
|
|
||||||
|
assert(worldedit.cuboid_shift(name, axis, amount * dir))
|
||||||
|
worldedit.marker_update(name)
|
||||||
|
|
||||||
|
return true, "Region shifted by " .. amount .. " nodes"
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
minetest.register_chatcommand("/expand", {
|
||||||
|
params = "[+|-]<x|y|z|?|up|down|left|right|front|back> <amount> [reverse-amount]",
|
||||||
|
description = "expand the selection in one or two directions at once",
|
||||||
|
privs = {worldedit=true},
|
||||||
|
func = function(name, param)
|
||||||
|
local find, _, sign, direction, amount,
|
||||||
|
rev_amount = param:find("([+-]?)([%?%l]+)%s*(%d+)%s*(%d*)")
|
||||||
|
|
||||||
|
if find == nil then
|
||||||
|
worldedit.player_notify(name, "invalid use: " .. param)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if worldedit.pos1[name] == nil or worldedit.pos2[name] == nil then
|
||||||
|
worldedit.player_notify(name,
|
||||||
|
"Undefined region. Region must be defined beforehand.")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local absolute = direction:find("[xyz?]")
|
||||||
|
local dir, axis
|
||||||
|
|
||||||
|
if rev_amount == "" then
|
||||||
|
rev_amount = 0
|
||||||
|
end
|
||||||
|
|
||||||
|
if absolute == nil then
|
||||||
|
axis, dir = worldedit.translate_direction(name, direction)
|
||||||
|
|
||||||
|
if axis == nil or dir == nil then
|
||||||
|
return false, "Invalid if looking straight up or down"
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if direction == "?" then
|
||||||
|
axis, dir = worldedit.player_axis(name)
|
||||||
|
else
|
||||||
|
axis = direction
|
||||||
|
dir = 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if sign == "-" then
|
||||||
|
dir = -dir
|
||||||
|
end
|
||||||
|
|
||||||
|
worldedit.cuboid_linear_expand(name, axis, dir, amount)
|
||||||
|
worldedit.cuboid_linear_expand(name, axis, -dir, rev_amount)
|
||||||
|
worldedit.marker_update(name)
|
||||||
|
return true, "Region expanded by " .. (amount + rev_amount) .. " nodes"
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
minetest.register_chatcommand("/contract", {
|
||||||
|
params = "[+|-]<x|y|z|?|up|down|left|right|front|back> <amount> [reverse-amount]",
|
||||||
|
description = "contract the selection in one or two directions at once",
|
||||||
|
privs = {worldedit=true},
|
||||||
|
func = function(name, param)
|
||||||
|
local find, _, sign, direction, amount,
|
||||||
|
rev_amount = param:find("([+-]?)([%?%l]+)%s*(%d+)%s*(%d*)")
|
||||||
|
|
||||||
|
if find == nil then
|
||||||
|
worldedit.player_notify(name, "invalid use: " .. param)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if worldedit.pos1[name] == nil or worldedit.pos2[name] == nil then
|
||||||
|
worldedit.player_notify(name,
|
||||||
|
"Undefined region. Region must be defined beforehand.")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local absolute = direction:find("[xyz?]")
|
||||||
|
local dir, axis
|
||||||
|
|
||||||
|
if rev_amount == "" then
|
||||||
|
rev_amount = 0
|
||||||
|
end
|
||||||
|
|
||||||
|
if absolute == nil then
|
||||||
|
axis, dir = worldedit.translate_direction(name, direction)
|
||||||
|
|
||||||
|
if axis == nil or dir == nil then
|
||||||
|
return false, "Invalid if looking straight up or down"
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if direction == "?" then
|
||||||
|
axis, dir = worldedit.player_axis(name)
|
||||||
|
else
|
||||||
|
axis = direction
|
||||||
|
dir = 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if sign == "-" then
|
||||||
|
dir = -dir
|
||||||
|
end
|
||||||
|
|
||||||
|
worldedit.cuboid_linear_expand(name, axis, dir, -amount)
|
||||||
|
worldedit.cuboid_linear_expand(name, axis, -dir, -rev_amount)
|
||||||
|
worldedit.marker_update(name)
|
||||||
|
return true, "Region contracted by " .. (amount + rev_amount) .. " nodes"
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
)
|
@ -10,10 +10,12 @@ if minetest.place_schematic then
|
|||||||
worldedit.prob_list = {}
|
worldedit.prob_list = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
dofile(minetest.get_modpath("worldedit_commands") .. "/cuboid.lua")
|
||||||
dofile(minetest.get_modpath("worldedit_commands") .. "/mark.lua")
|
dofile(minetest.get_modpath("worldedit_commands") .. "/mark.lua")
|
||||||
dofile(minetest.get_modpath("worldedit_commands") .. "/safe.lua"); safe_region = safe_region or function(callback) return callback end
|
dofile(minetest.get_modpath("worldedit_commands") .. "/wand.lua")
|
||||||
|
local safe_region, check_region, reset_pending = dofile(minetest.get_modpath("worldedit_commands") .. "/safe.lua")
|
||||||
|
|
||||||
local get_position = function(name) --position 1 retrieval function for when not using `safe_region`
|
local function get_position(name) --position 1 retrieval function for when not using `safe_region`
|
||||||
local pos1 = worldedit.pos1[name]
|
local pos1 = worldedit.pos1[name]
|
||||||
if pos1 == nil then
|
if pos1 == nil then
|
||||||
worldedit.player_notify(name, "no position 1 selected")
|
worldedit.player_notify(name, "no position 1 selected")
|
||||||
@ -21,7 +23,8 @@ local get_position = function(name) --position 1 retrieval function for when not
|
|||||||
return pos1
|
return pos1
|
||||||
end
|
end
|
||||||
|
|
||||||
local get_node = function(name, nodename)
|
-- normalize_nodename wrapper for convenience purposes
|
||||||
|
local function get_node(name, nodename)
|
||||||
local node = worldedit.normalize_nodename(nodename)
|
local node = worldedit.normalize_nodename(nodename)
|
||||||
if not node then
|
if not node then
|
||||||
worldedit.player_notify(name, "invalid node name: " .. nodename)
|
worldedit.player_notify(name, "invalid node name: " .. nodename)
|
||||||
@ -30,34 +33,54 @@ local get_node = function(name, nodename)
|
|||||||
return node
|
return node
|
||||||
end
|
end
|
||||||
|
|
||||||
worldedit.player_notify = function(name, message)
|
function worldedit.player_notify(name, message)
|
||||||
minetest.chat_send_player(name, "WorldEdit -!- " .. message, false)
|
minetest.chat_send_player(name, "WorldEdit -!- " .. message, false)
|
||||||
end
|
end
|
||||||
|
|
||||||
--determines whether `nodename` is a valid node name, returning a boolean
|
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)
|
||||||
worldedit.normalize_nodename = function(nodename)
|
worldedit.normalize_nodename = function(nodename)
|
||||||
nodename = nodename:gsub("^%s*(.-)%s*$", "%1")
|
nodename = nodename:gsub("^%s*(.-)%s*$", "%1") -- strip spaces
|
||||||
if nodename == "" then return nil end
|
if nodename == "" then return nil end
|
||||||
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
|
local fullname = ItemStack({name=nodename}):get_name() -- resolve aliases
|
||||||
|
if minetest.registered_nodes[fullname] or fullname == "air" then -- full name
|
||||||
return fullname
|
return fullname
|
||||||
end
|
end
|
||||||
for key, value in pairs(minetest.registered_nodes) do
|
for key, value in pairs(minetest.registered_nodes) do
|
||||||
if key:find(":" .. nodename, 1, true) then --found in mod
|
if string_endswith(key, ":" .. nodename) then -- matches name (w/o mod part)
|
||||||
return key
|
return key
|
||||||
end
|
end
|
||||||
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
|
for key, value in pairs(minetest.registered_nodes) do
|
||||||
if value.description:lower() == nodename then --found in description
|
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")
|
||||||
return key
|
return key
|
||||||
end
|
end
|
||||||
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
|
return nil
|
||||||
end
|
end
|
||||||
|
match = key -- substring description match (only if no ambiguities)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return match
|
||||||
|
end
|
||||||
|
|
||||||
--determines the axis in which a player is facing, returning an axis ("x", "y", or "z") and the sign (1 or -1)
|
-- Determines the axis in which a player is facing, returning an axis ("x", "y", or "z") and the sign (1 or -1)
|
||||||
worldedit.player_axis = function(name)
|
function worldedit.player_axis(name)
|
||||||
local dir = minetest.get_player_by_name(name):get_look_dir()
|
local dir = minetest.get_player_by_name(name):get_look_dir()
|
||||||
local x, y, z = math.abs(dir.x), math.abs(dir.y), math.abs(dir.z)
|
local x, y, z = math.abs(dir.x), math.abs(dir.y), math.abs(dir.z)
|
||||||
if x > y then
|
if x > y then
|
||||||
@ -70,6 +93,19 @@ worldedit.player_axis = function(name)
|
|||||||
return "z", dir.z > 0 and 1 or -1
|
return "z", dir.z > 0 and 1 or -1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function mkdir(path)
|
||||||
|
if minetest.mkdir then
|
||||||
|
minetest.mkdir(path)
|
||||||
|
else
|
||||||
|
os.execute('mkdir "' .. path .. '"')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function check_filename(name)
|
||||||
|
return name:find("^[%w%s%^&'@{}%[%],%$=!%-#%(%)%%%.%+~_]+$") ~= nil
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
minetest.register_chatcommand("/about", {
|
minetest.register_chatcommand("/about", {
|
||||||
params = "",
|
params = "",
|
||||||
description = "Get information about the mod",
|
description = "Get information about the mod",
|
||||||
@ -78,6 +114,56 @@ minetest.register_chatcommand("/about", {
|
|||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
-- mostly copied from builtin/chatcommands.lua with minor modifications
|
||||||
|
minetest.register_chatcommand("/help", {
|
||||||
|
privs = {},
|
||||||
|
params = "[all/<cmd>]",
|
||||||
|
description = "Get help for WorldEdit commands",
|
||||||
|
func = function(name, param)
|
||||||
|
local function is_we_command(cmd)
|
||||||
|
return cmd:sub(0, 1) == "/"
|
||||||
|
end
|
||||||
|
local function format_help_line(cmd, def)
|
||||||
|
local msg = minetest.colorize("#00ffff", "/"..cmd)
|
||||||
|
if def.params and def.params ~= "" then
|
||||||
|
msg = msg .. " " .. def.params
|
||||||
|
end
|
||||||
|
if def.description and def.description ~= "" then
|
||||||
|
msg = msg .. ": " .. def.description
|
||||||
|
end
|
||||||
|
return msg
|
||||||
|
end
|
||||||
|
|
||||||
|
if not minetest.check_player_privs(name, "worldedit") then
|
||||||
|
return false, "You are not allowed to use any WorldEdit commands."
|
||||||
|
end
|
||||||
|
if param == "" then
|
||||||
|
local msg = ""
|
||||||
|
local cmds = {}
|
||||||
|
for cmd, def in pairs(minetest.chatcommands) do
|
||||||
|
if is_we_command(cmd) and minetest.check_player_privs(name, def.privs) then
|
||||||
|
cmds[#cmds + 1] = cmd:sub(2) -- strip the /
|
||||||
|
end
|
||||||
|
end
|
||||||
|
table.sort(cmds)
|
||||||
|
return true, "Available commands: " .. table.concat(cmds, " ") .. "\n"
|
||||||
|
.. "Use '//help <cmd>' to get more information,"
|
||||||
|
.. " or '//help all' to list everything."
|
||||||
|
elseif param == "all" then
|
||||||
|
local cmds = {}
|
||||||
|
for cmd, def in pairs(minetest.chatcommands) do
|
||||||
|
if is_we_command(cmd) and minetest.check_player_privs(name, def.privs) then
|
||||||
|
cmds[#cmds + 1] = format_help_line(cmd, def)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
table.sort(cmds)
|
||||||
|
return true, "Available commands:\n"..table.concat(cmds, "\n")
|
||||||
|
else
|
||||||
|
return minetest.chatcommands["help"].func(name, "/" .. param)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
minetest.register_chatcommand("/inspect", {
|
minetest.register_chatcommand("/inspect", {
|
||||||
params = "on/off/1/0/true/false/yes/no/enable/disable/<blank>",
|
params = "on/off/1/0/true/false/yes/no/enable/disable/<blank>",
|
||||||
description = "Enable or disable node inspection",
|
description = "Enable or disable node inspection",
|
||||||
@ -97,16 +183,28 @@ minetest.register_chatcommand("/inspect", {
|
|||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
local function get_node_rlight(pos)
|
||||||
|
local vecs = { -- neighboring nodes
|
||||||
|
{x= 1, y= 0, z= 0},
|
||||||
|
{x=-1, y= 0, z= 0},
|
||||||
|
{x= 0, y= 1, z= 0},
|
||||||
|
{x= 0, y=-1, z= 0},
|
||||||
|
{x= 0, y= 0, z= 1},
|
||||||
|
{x= 0, y= 0, z=-1},
|
||||||
|
}
|
||||||
|
local ret = 0
|
||||||
|
for _, v in ipairs(vecs) do
|
||||||
|
ret = math.max(ret, minetest.get_node_light(vector.add(pos, v)))
|
||||||
|
end
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
|
||||||
minetest.register_on_punchnode(function(pos, node, puncher)
|
minetest.register_on_punchnode(function(pos, node, puncher)
|
||||||
local name = puncher:get_player_name()
|
local name = puncher:get_player_name()
|
||||||
if worldedit.inspect[name] then
|
if worldedit.inspect[name] then
|
||||||
if minetest.check_player_privs(name, {worldedit=true}) then
|
|
||||||
local axis, sign = worldedit.player_axis(name)
|
local axis, sign = worldedit.player_axis(name)
|
||||||
message = string.format("inspector: %s at %s (param1=%d, param2=%d) punched by %s 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, name, axis .. (sign > 0 and "+" or "-"))
|
node.name, minetest.pos_to_string(pos), node.param1, node.param2, get_node_rlight(pos), axis .. (sign > 0 and "+" or "-"))
|
||||||
else
|
|
||||||
message = "inspector: worldedit privileges required"
|
|
||||||
end
|
|
||||||
worldedit.player_notify(name, message)
|
worldedit.player_notify(name, message)
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
@ -121,6 +219,8 @@ minetest.register_chatcommand("/reset", {
|
|||||||
worldedit.mark_pos1(name)
|
worldedit.mark_pos1(name)
|
||||||
worldedit.mark_pos2(name)
|
worldedit.mark_pos2(name)
|
||||||
worldedit.set_pos[name] = nil
|
worldedit.set_pos[name] = nil
|
||||||
|
--make sure the user does not try to confirm an operation after resetting pos:
|
||||||
|
reset_pending(name)
|
||||||
worldedit.player_notify(name, "region reset")
|
worldedit.player_notify(name, "region reset")
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
@ -277,22 +377,53 @@ minetest.register_chatcommand("/volume", {
|
|||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
minetest.register_chatcommand("/deleteblocks", {
|
||||||
|
params = "",
|
||||||
|
description = "remove all MapBlocks (16x16x16) containing the selected area from the map",
|
||||||
|
privs = {worldedit=true},
|
||||||
|
func = safe_region(function(name, param)
|
||||||
|
local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]
|
||||||
|
local success = minetest.delete_area(pos1, pos2)
|
||||||
|
if success then
|
||||||
|
worldedit.player_notify(name, "Area deleted.")
|
||||||
|
else
|
||||||
|
worldedit.player_notify(name, "There was an error during deletion of the area.")
|
||||||
|
end
|
||||||
|
end),
|
||||||
|
})
|
||||||
|
|
||||||
minetest.register_chatcommand("/set", {
|
minetest.register_chatcommand("/set", {
|
||||||
params = "<node>",
|
params = "<node>",
|
||||||
description = "Set the current WorldEdit region to <node>",
|
description = "Set the current WorldEdit region to <node>",
|
||||||
privs = {worldedit=true},
|
privs = {worldedit=true},
|
||||||
func = safe_region(function(name, param)
|
func = safe_region(function(name, param)
|
||||||
local node = get_node(name, param)
|
local node = get_node(name, param)
|
||||||
if not node then
|
if not node then return end
|
||||||
worldedit.player_notify(name, "Could not identify node \"" .. param .. "\"")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local count = worldedit.set(worldedit.pos1[name], worldedit.pos2[name], node)
|
local count = worldedit.set(worldedit.pos1[name], worldedit.pos2[name], node)
|
||||||
worldedit.player_notify(name, count .. " nodes set")
|
worldedit.player_notify(name, count .. " nodes set")
|
||||||
end, check_region),
|
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", {
|
minetest.register_chatcommand("/mix", {
|
||||||
params = "<node1> ...",
|
params = "<node1> ...",
|
||||||
description = "Fill the current WorldEdit region with a random mix of <node1>, ...",
|
description = "Fill the current WorldEdit region with a random mix of <node1>, ...",
|
||||||
@ -301,10 +432,7 @@ minetest.register_chatcommand("/mix", {
|
|||||||
local nodes = {}
|
local nodes = {}
|
||||||
for nodename in param:gmatch("[^%s]+") do
|
for nodename in param:gmatch("[^%s]+") do
|
||||||
local node = get_node(name, nodename)
|
local node = get_node(name, nodename)
|
||||||
if not node then
|
if not node then return end
|
||||||
worldedit.player_notify(name, "Could not identify node \"" .. name .. "\"")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
nodes[#nodes + 1] = node
|
nodes[#nodes + 1] = node
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -361,6 +489,45 @@ minetest.register_chatcommand("/replaceinverse", {
|
|||||||
end, check_replace),
|
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)
|
local check_sphere = function(name, param)
|
||||||
if worldedit.pos1[name] == nil then
|
if worldedit.pos1[name] == nil then
|
||||||
worldedit.player_notify(name, "no position 1 selected")
|
worldedit.player_notify(name, "no position 1 selected")
|
||||||
@ -444,50 +611,102 @@ local check_cylinder = function(name, param)
|
|||||||
worldedit.player_notify(name, "no position 1 selected")
|
worldedit.player_notify(name, "no position 1 selected")
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
local found, _, axis, length, radius, nodename = param:find("^([xyz%?])%s+([+-]?%d+)%s+(%d+)%s+(.+)$")
|
-- 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
|
||||||
if found == nil then
|
if found == nil then
|
||||||
worldedit.player_notify(name, "invalid usage: " .. param)
|
worldedit.player_notify(name, "invalid usage: " .. param)
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
local node = get_node(name, nodename)
|
local node = get_node(name, nodename)
|
||||||
if not node then return nil end
|
if not node then return nil end
|
||||||
return math.ceil(math.pi * (tonumber(radius) ^ 2) * tonumber(length))
|
local radius = math.max(tonumber(radius1), tonumber(radius2))
|
||||||
|
return math.ceil(math.pi * (radius ^ 2) * tonumber(length))
|
||||||
end
|
end
|
||||||
|
|
||||||
minetest.register_chatcommand("/hollowcylinder", {
|
minetest.register_chatcommand("/hollowcylinder", {
|
||||||
params = "x/y/z/? <length> <radius> <node>",
|
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> and radius <radius>, composed of <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>",
|
||||||
privs = {worldedit=true},
|
privs = {worldedit=true},
|
||||||
func = safe_region(function(name, param)
|
func = safe_region(function(name, param)
|
||||||
local found, _, axis, length, radius, nodename = param:find("^([xyz%?])%s+([+-]?%d+)%s+(%d+)%s+(.+)$")
|
-- 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
|
||||||
length = tonumber(length)
|
length = tonumber(length)
|
||||||
if axis == "?" then
|
if axis == "?" then
|
||||||
axis, sign = worldedit.player_axis(name)
|
axis, sign = worldedit.player_axis(name)
|
||||||
length = length * sign
|
length = length * sign
|
||||||
end
|
end
|
||||||
local node = get_node(name, nodename)
|
local node = get_node(name, nodename)
|
||||||
local count = worldedit.cylinder(worldedit.pos1[name], axis, length, tonumber(radius), node, true)
|
local count = worldedit.cylinder(worldedit.pos1[name], axis, length, tonumber(radius1), tonumber(radius2), node, true)
|
||||||
worldedit.player_notify(name, count .. " nodes added")
|
worldedit.player_notify(name, count .. " nodes added")
|
||||||
end, check_cylinder),
|
end, check_cylinder),
|
||||||
})
|
})
|
||||||
|
|
||||||
minetest.register_chatcommand("/cylinder", {
|
minetest.register_chatcommand("/cylinder", {
|
||||||
params = "x/y/z/? <length> <radius> <node>",
|
params = "x/y/z/? <length> <radius1> [radius2] <node>",
|
||||||
description = "Add cylinder at WorldEdit position 1 along the x/y/z/? axis with length <length> and radius <radius>, composed of <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>",
|
||||||
privs = {worldedit=true},
|
privs = {worldedit=true},
|
||||||
func = safe_region(function(name, param)
|
func = safe_region(function(name, param)
|
||||||
local found, _, axis, length, radius, nodename = param:find("^([xyz%?])%s+([+-]?%d+)%s+(%d+)%s+(.+)$")
|
-- 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
|
||||||
length = tonumber(length)
|
length = tonumber(length)
|
||||||
if axis == "?" then
|
if axis == "?" then
|
||||||
axis, sign = worldedit.player_axis(name)
|
axis, sign = worldedit.player_axis(name)
|
||||||
length = length * sign
|
length = length * sign
|
||||||
end
|
end
|
||||||
local node = get_node(name, nodename)
|
local node = get_node(name, nodename)
|
||||||
local count = worldedit.cylinder(worldedit.pos1[name], axis, length, tonumber(radius), node)
|
local count = worldedit.cylinder(worldedit.pos1[name], axis, length, tonumber(radius1), tonumber(radius2), node)
|
||||||
worldedit.player_notify(name, count .. " nodes added")
|
worldedit.player_notify(name, count .. " nodes added")
|
||||||
end, check_cylinder),
|
end, check_cylinder),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
local check_pyramid = function(name, param)
|
||||||
|
if worldedit.pos1[name] == nil then
|
||||||
|
worldedit.player_notify(name, "no position 1 selected")
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
local found, _, axis, height, nodename = param:find("^([xyz%?])%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
|
||||||
|
height = tonumber(height)
|
||||||
|
return math.ceil(((height * 2 + 1) ^ 2) * height / 3)
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.register_chatcommand("/hollowpyramid", {
|
||||||
|
params = "x/y/z/? <height> <node>",
|
||||||
|
description = "Add hollow pyramid centered at WorldEdit position 1 along the x/y/z/? axis with height <height>, composed of <node>",
|
||||||
|
privs = {worldedit=true},
|
||||||
|
func = safe_region(function(name, param)
|
||||||
|
local found, _, axis, height, nodename = param:find("^([xyz%?])%s+([+-]?%d+)%s+(.+)$")
|
||||||
|
height = tonumber(height)
|
||||||
|
if axis == "?" then
|
||||||
|
axis, sign = worldedit.player_axis(name)
|
||||||
|
height = height * sign
|
||||||
|
end
|
||||||
|
local node = get_node(name, nodename)
|
||||||
|
local count = worldedit.pyramid(worldedit.pos1[name], axis, height, node, true)
|
||||||
|
worldedit.player_notify(name, count .. " nodes added")
|
||||||
|
end, check_pyramid),
|
||||||
|
})
|
||||||
|
|
||||||
minetest.register_chatcommand("/pyramid", {
|
minetest.register_chatcommand("/pyramid", {
|
||||||
params = "x/y/z/? <height> <node>",
|
params = "x/y/z/? <height> <node>",
|
||||||
description = "Add pyramid centered at WorldEdit position 1 along the x/y/z/? axis with height <height>, composed of <node>",
|
description = "Add pyramid centered at WorldEdit position 1 along the x/y/z/? axis with height <height>, composed of <node>",
|
||||||
@ -502,22 +721,7 @@ minetest.register_chatcommand("/pyramid", {
|
|||||||
local node = get_node(name, nodename)
|
local node = get_node(name, nodename)
|
||||||
local count = worldedit.pyramid(worldedit.pos1[name], axis, height, node)
|
local count = worldedit.pyramid(worldedit.pos1[name], axis, height, node)
|
||||||
worldedit.player_notify(name, count .. " nodes added")
|
worldedit.player_notify(name, count .. " nodes added")
|
||||||
end,
|
end, check_pyramid),
|
||||||
function(name, param)
|
|
||||||
if worldedit.pos1[name] == nil then
|
|
||||||
worldedit.player_notify(name, "no position 1 selected")
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
local found, _, axis, height, nodename = param:find("^([xyz%?])%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
|
|
||||||
height = tonumber(height)
|
|
||||||
return math.ceil(((height * 2 + 1) ^ 2) * height / 3)
|
|
||||||
end),
|
|
||||||
})
|
})
|
||||||
|
|
||||||
minetest.register_chatcommand("/spiral", {
|
minetest.register_chatcommand("/spiral", {
|
||||||
@ -542,7 +746,7 @@ minetest.register_chatcommand("/spiral", {
|
|||||||
end
|
end
|
||||||
local node = get_node(name, nodename)
|
local node = get_node(name, nodename)
|
||||||
if not node then return nil end
|
if not node then return nil end
|
||||||
return check_region(name, param)
|
return 1 -- TODO: return an useful value
|
||||||
end),
|
end),
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -810,6 +1014,30 @@ minetest.register_chatcommand("/fixlight", {
|
|||||||
end),
|
end),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
minetest.register_chatcommand("/drain", {
|
||||||
|
params = "",
|
||||||
|
description = "Remove any fluid node within the current WorldEdit region",
|
||||||
|
privs = {worldedit=true},
|
||||||
|
func = safe_region(function(name, param)
|
||||||
|
-- TODO: make an API function for this
|
||||||
|
local count = 0
|
||||||
|
local pos1, pos2 = worldedit.sort_pos(worldedit.pos1[name], worldedit.pos2[name])
|
||||||
|
for x = pos1.x, pos2.x do
|
||||||
|
for y = pos1.y, pos2.y do
|
||||||
|
for z = pos1.z, pos2.z do
|
||||||
|
local n = minetest.get_node({x=x, y=y, z=z}).name
|
||||||
|
local d = minetest.registered_nodes[n]
|
||||||
|
if d ~= nil and (d["drawtype"] == "liquid" or d["drawtype"] == "flowingliquid") then
|
||||||
|
minetest.remove_node({x=x, y=y, z=z})
|
||||||
|
count = count + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
worldedit.player_notify(name, count .. " nodes updated")
|
||||||
|
end),
|
||||||
|
})
|
||||||
|
|
||||||
minetest.register_chatcommand("/hide", {
|
minetest.register_chatcommand("/hide", {
|
||||||
params = "",
|
params = "",
|
||||||
description = "Hide all nodes in the current WorldEdit region non-destructively",
|
description = "Hide all nodes in the current WorldEdit region non-destructively",
|
||||||
@ -861,20 +1089,21 @@ minetest.register_chatcommand("/save", {
|
|||||||
worldedit.player_notify(name, "invalid usage: " .. param)
|
worldedit.player_notify(name, "invalid usage: " .. param)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
if not string.find(param, "^[%w \t.,+-_=!@#$%%^&*()%[%]{};'\"]+$") then
|
if not check_filename(param) then
|
||||||
worldedit.player_notify(name, "invalid file name: " .. param)
|
worldedit.player_notify(name, "Disallowed file name: " .. param)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
local result, count = worldedit.serialize(worldedit.pos1[name],
|
||||||
local result, count = worldedit.serialize(worldedit.pos1[name], worldedit.pos2[name])
|
worldedit.pos2[name])
|
||||||
|
|
||||||
local path = minetest.get_worldpath() .. "/schems"
|
local path = minetest.get_worldpath() .. "/schems"
|
||||||
|
-- Create directory if it does not already exist
|
||||||
|
mkdir(path)
|
||||||
|
|
||||||
local filename = path .. "/" .. param .. ".we"
|
local filename = path .. "/" .. param .. ".we"
|
||||||
filename = filename:gsub("\"", "\\\""):gsub("\\", "\\\\") --escape any nasty characters
|
|
||||||
os.execute("mkdir \"" .. path .. "\"") --create directory if it does not already exist
|
|
||||||
local file, err = io.open(filename, "wb")
|
local file, err = io.open(filename, "wb")
|
||||||
if err ~= nil then
|
if err ~= nil then
|
||||||
worldedit.player_notify(name, "could not save file to \"" .. filename .. "\"")
|
worldedit.player_notify(name, "Could not save file to \"" .. filename .. "\"")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
file:write(result)
|
file:write(result)
|
||||||
@ -897,8 +1126,8 @@ minetest.register_chatcommand("/allocate", {
|
|||||||
worldedit.player_notify(name, "invalid usage: " .. param)
|
worldedit.player_notify(name, "invalid usage: " .. param)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
if not string.find(param, "^[%w \t.,+-_=!@#$%%^&*()%[%]{};'\"]+$") then
|
if not check_filename(param) then
|
||||||
worldedit.player_notify(name, "invalid file name: " .. param)
|
worldedit.player_notify(name, "Disallowed file name: " .. param)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -986,16 +1215,13 @@ minetest.register_chatcommand("/lua", {
|
|||||||
description = "Executes <code> as a Lua chunk in the global namespace",
|
description = "Executes <code> as a Lua chunk in the global namespace",
|
||||||
privs = {worldedit=true, server=true},
|
privs = {worldedit=true, server=true},
|
||||||
func = function(name, param)
|
func = function(name, param)
|
||||||
local admin = minetest.setting_get("name")
|
|
||||||
if not admin or not name == admin then
|
|
||||||
worldedit.player_notify(name, "this command can only be run by the server administrator")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
local err = worldedit.lua(param)
|
local err = worldedit.lua(param)
|
||||||
if err then
|
if err then
|
||||||
worldedit.player_notify(name, "code error: " .. err)
|
worldedit.player_notify(name, "code error: " .. err)
|
||||||
|
minetest.log("action", name.." tried to execute "..param)
|
||||||
else
|
else
|
||||||
worldedit.player_notify(name, "code successfully executed", false)
|
worldedit.player_notify(name, "code successfully executed", false)
|
||||||
|
minetest.log("action", name.." executed "..param)
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
@ -1005,41 +1231,44 @@ minetest.register_chatcommand("/luatransform", {
|
|||||||
description = "Executes <code> as a Lua chunk in the global namespace with the variable pos available, for each node in the current WorldEdit region",
|
description = "Executes <code> as a Lua chunk in the global namespace with the variable pos available, for each node in the current WorldEdit region",
|
||||||
privs = {worldedit=true, server=true},
|
privs = {worldedit=true, server=true},
|
||||||
func = safe_region(function(name, param)
|
func = safe_region(function(name, param)
|
||||||
local admin = minetest.setting_get("name")
|
|
||||||
if not admin or not name == admin then
|
|
||||||
worldedit.player_notify(name, "this command can only be run by the server administrator")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local err = worldedit.luatransform(worldedit.pos1[name], worldedit.pos2[name], param)
|
local err = worldedit.luatransform(worldedit.pos1[name], worldedit.pos2[name], param)
|
||||||
if err then
|
if err then
|
||||||
worldedit.player_notify(name, "code error: " .. err, false)
|
worldedit.player_notify(name, "code error: " .. err, false)
|
||||||
|
minetest.log("action", name.." tried to execute luatransform "..param)
|
||||||
else
|
else
|
||||||
worldedit.player_notify(name, "code successfully executed", false)
|
worldedit.player_notify(name, "code successfully executed", false)
|
||||||
|
minetest.log("action", name.." executed luatransform "..param)
|
||||||
end
|
end
|
||||||
end),
|
end),
|
||||||
})
|
})
|
||||||
|
|
||||||
minetest.register_chatcommand("/mtschemcreate", {
|
minetest.register_chatcommand("/mtschemcreate", {
|
||||||
params = "<file>",
|
params = "<file>",
|
||||||
description = "Save the current WorldEdit region using the Minetest Schematic format to \"(world folder)/schems/<filename>.mts\"",
|
description = "Save the current WorldEdit region using the Minetest "..
|
||||||
|
"Schematic format to \"(world folder)/schems/<filename>.mts\"",
|
||||||
privs = {worldedit=true},
|
privs = {worldedit=true},
|
||||||
func = safe_region(function(name, param)
|
func = safe_region(function(name, param)
|
||||||
if param == nil then
|
if param == nil then
|
||||||
worldedit.player_notify(name, "No filename specified")
|
worldedit.player_notify(name, "No filename specified")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
if not check_filename(param) then
|
||||||
|
worldedit.player_notify(name, "Disallowed file name: " .. param)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
local path = minetest.get_worldpath() .. "/schems"
|
local path = minetest.get_worldpath() .. "/schems"
|
||||||
local filename = path .. "/" .. param .. ".mts"
|
-- Create directory if it does not already exist
|
||||||
filename = filename:gsub("\"", "\\\""):gsub("\\", "\\\\") --escape any nasty characters
|
mkdir(path)
|
||||||
os.execute("mkdir \"" .. path .. "\"") --create directory if it does not already exist
|
|
||||||
|
|
||||||
local ret = minetest.create_schematic(worldedit.pos1[name], worldedit.pos2[name], worldedit.prob_list[name], filename)
|
local filename = path .. "/" .. param .. ".mts"
|
||||||
|
local ret = minetest.create_schematic(worldedit.pos1[name],
|
||||||
|
worldedit.pos2[name], worldedit.prob_list[name],
|
||||||
|
filename)
|
||||||
if ret == nil then
|
if ret == nil then
|
||||||
worldedit.player_notify(name, "failed to create Minetest schematic", false)
|
worldedit.player_notify(name, "Failed to create Minetest schematic", false)
|
||||||
else
|
else
|
||||||
worldedit.player_notify(name, "saved Minetest schematic to " .. param, false)
|
worldedit.player_notify(name, "Saved Minetest schematic to " .. param, false)
|
||||||
end
|
end
|
||||||
worldedit.prob_list[name] = {}
|
worldedit.prob_list[name] = {}
|
||||||
end),
|
end),
|
||||||
@ -1050,10 +1279,14 @@ minetest.register_chatcommand("/mtschemplace", {
|
|||||||
description = "Load nodes from \"(world folder)/schems/<file>.mts\" with position 1 of the current WorldEdit region as the origin",
|
description = "Load nodes from \"(world folder)/schems/<file>.mts\" with position 1 of the current WorldEdit region as the origin",
|
||||||
privs = {worldedit=true},
|
privs = {worldedit=true},
|
||||||
func = function(name, param)
|
func = function(name, param)
|
||||||
if param == nil then
|
if param == "" then
|
||||||
worldedit.player_notify(name, "no filename specified")
|
worldedit.player_notify(name, "no filename specified")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
if not check_filename(param) then
|
||||||
|
worldedit.player_notify(name, "Disallowed file name: " .. param)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
local pos = get_position(name)
|
local pos = get_position(name)
|
||||||
if pos == nil then return end
|
if pos == nil then return end
|
||||||
@ -1087,8 +1320,8 @@ minetest.register_chatcommand("/mtschemprob", {
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
for k,v in pairs(problist) do
|
for k,v in pairs(problist) do
|
||||||
local prob = math.floor(((v["prob"] / 256) * 100) * 100 + 0.5) / 100
|
local prob = math.floor(((v.prob / 256) * 100) * 100 + 0.5) / 100
|
||||||
text = text .. minetest.pos_to_string(v["pos"]) .. ": " .. prob .. "% | "
|
text = text .. minetest.pos_to_string(v.pos) .. ": " .. prob .. "% | "
|
||||||
end
|
end
|
||||||
worldedit.player_notify(name, "currently set node probabilities:")
|
worldedit.player_notify(name, "currently set node probabilities:")
|
||||||
worldedit.player_notify(name, text)
|
worldedit.player_notify(name, text)
|
||||||
@ -1098,16 +1331,14 @@ minetest.register_chatcommand("/mtschemprob", {
|
|||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
minetest.register_on_player_receive_fields(
|
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||||
function(player, formname, fields)
|
if formname == "prob_val_enter" and not (fields.text == "" or fields.text == nil) then
|
||||||
if (formname == "prob_val_enter") and (fields.text ~= "") then
|
|
||||||
local name = player:get_player_name()
|
local name = player:get_player_name()
|
||||||
local prob_entry = {pos=worldedit.prob_pos[name], prob=tonumber(fields.text)}
|
local prob_entry = {pos=worldedit.prob_pos[name], prob=tonumber(fields.text)}
|
||||||
local index = table.getn(worldedit.prob_list[name]) + 1
|
local index = table.getn(worldedit.prob_list[name]) + 1
|
||||||
worldedit.prob_list[name][index] = prob_entry
|
worldedit.prob_list[name][index] = prob_entry
|
||||||
end
|
end
|
||||||
end
|
end)
|
||||||
)
|
|
||||||
|
|
||||||
minetest.register_chatcommand("/clearobjects", {
|
minetest.register_chatcommand("/clearobjects", {
|
||||||
params = "",
|
params = "",
|
||||||
|
@ -58,8 +58,19 @@ worldedit.mark_region = function(name)
|
|||||||
end
|
end
|
||||||
worldedit.marker_region[name] = nil
|
worldedit.marker_region[name] = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
if pos1 ~= nil and pos2 ~= nil then
|
if pos1 ~= nil and pos2 ~= nil then
|
||||||
local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
|
local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
|
||||||
|
|
||||||
|
local vec = vector.subtract(pos2, pos1)
|
||||||
|
local maxside = math.max(vec.x, math.max(vec.y, vec.z))
|
||||||
|
local limit = tonumber(minetest.setting_get("active_object_send_range_blocks")) * 16
|
||||||
|
if maxside > limit * 1.5 then
|
||||||
|
-- The client likely won't be able to see the plane markers as intended anyway,
|
||||||
|
-- thus don't place them and also don't load the area into memory
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
local thickness = 0.2
|
local thickness = 0.2
|
||||||
local sizex, sizey, sizez = (1 + pos2.x - pos1.x) / 2, (1 + pos2.y - pos1.y) / 2, (1 + pos2.z - pos1.z) / 2
|
local sizex, sizey, sizez = (1 + pos2.x - pos1.x) / 2, (1 + pos2.y - pos1.y) / 2, (1 + pos2.z - pos1.z) / 2
|
||||||
|
|
||||||
@ -72,6 +83,7 @@ worldedit.mark_region = function(name)
|
|||||||
--XY plane markers
|
--XY plane markers
|
||||||
for _, z in ipairs({pos1.z - 0.5, pos2.z + 0.5}) do
|
for _, z in ipairs({pos1.z - 0.5, pos2.z + 0.5}) do
|
||||||
local marker = minetest.add_entity({x=pos1.x + sizex - 0.5, y=pos1.y + sizey - 0.5, z=z}, "worldedit:region_cube")
|
local marker = minetest.add_entity({x=pos1.x + sizex - 0.5, y=pos1.y + sizey - 0.5, z=z}, "worldedit:region_cube")
|
||||||
|
if marker ~= nil then
|
||||||
marker:set_properties({
|
marker:set_properties({
|
||||||
visual_size={x=sizex * 2, y=sizey * 2},
|
visual_size={x=sizex * 2, y=sizey * 2},
|
||||||
collisionbox = {-sizex, -sizey, -thickness, sizex, sizey, thickness},
|
collisionbox = {-sizex, -sizey, -thickness, sizex, sizey, thickness},
|
||||||
@ -79,10 +91,12 @@ worldedit.mark_region = function(name)
|
|||||||
marker:get_luaentity().player_name = name
|
marker:get_luaentity().player_name = name
|
||||||
table.insert(markers, marker)
|
table.insert(markers, marker)
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
--YZ plane markers
|
--YZ plane markers
|
||||||
for _, x in ipairs({pos1.x - 0.5, pos2.x + 0.5}) do
|
for _, x in ipairs({pos1.x - 0.5, pos2.x + 0.5}) do
|
||||||
local marker = minetest.add_entity({x=x, y=pos1.y + sizey - 0.5, z=pos1.z + sizez - 0.5}, "worldedit:region_cube")
|
local marker = minetest.add_entity({x=x, y=pos1.y + sizey - 0.5, z=pos1.z + sizez - 0.5}, "worldedit:region_cube")
|
||||||
|
if marker ~= nil then
|
||||||
marker:set_properties({
|
marker:set_properties({
|
||||||
visual_size={x=sizez * 2, y=sizey * 2},
|
visual_size={x=sizez * 2, y=sizey * 2},
|
||||||
collisionbox = {-thickness, -sizey, -sizez, thickness, sizey, sizez},
|
collisionbox = {-thickness, -sizey, -sizez, thickness, sizey, sizez},
|
||||||
@ -91,6 +105,7 @@ worldedit.mark_region = function(name)
|
|||||||
marker:get_luaentity().player_name = name
|
marker:get_luaentity().player_name = name
|
||||||
table.insert(markers, marker)
|
table.insert(markers, marker)
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
worldedit.marker_region[name] = markers
|
worldedit.marker_region[name] = markers
|
||||||
end
|
end
|
||||||
@ -153,7 +168,11 @@ minetest.register_entity(":worldedit:region_cube", {
|
|||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
on_punch = function(self, hitter)
|
on_punch = function(self, hitter)
|
||||||
for _, entity in ipairs(worldedit.marker_region[self.player_name]) do
|
local markers = worldedit.marker_region[self.player_name]
|
||||||
|
if not markers then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
for _, entity in ipairs(markers) do
|
||||||
entity:remove()
|
entity:remove()
|
||||||
end
|
end
|
||||||
worldedit.marker_region[self.player_name] = nil
|
worldedit.marker_region[self.player_name] = nil
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
local safe_region_callback = {}
|
local safe_region_callback = {}
|
||||||
local safe_region_param = {}
|
local safe_region_param = {}
|
||||||
|
|
||||||
check_region = function(name, param)
|
local function check_region(name, param)
|
||||||
local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] --obtain positions
|
local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] --obtain positions
|
||||||
if pos1 == nil or pos2 == nil then
|
if pos1 == nil or pos2 == nil then
|
||||||
worldedit.player_notify(name, "no region selected")
|
worldedit.player_notify(name, "no region selected")
|
||||||
@ -12,7 +12,7 @@ end
|
|||||||
|
|
||||||
--`callback` is a callback to run when the user confirms
|
--`callback` is a callback to run when the user confirms
|
||||||
--`nodes_needed` is a function accepting `param`, `pos1`, and `pos2` to calculate the number of nodes needed
|
--`nodes_needed` is a function accepting `param`, `pos1`, and `pos2` to calculate the number of nodes needed
|
||||||
safe_region = function(callback, nodes_needed)
|
local function safe_region(callback, nodes_needed)
|
||||||
--default node volume calculation
|
--default node volume calculation
|
||||||
nodes_needed = nodes_needed or check_region
|
nodes_needed = nodes_needed or check_region
|
||||||
|
|
||||||
@ -30,6 +30,10 @@ safe_region = function(callback, nodes_needed)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function reset_pending(name)
|
||||||
|
safe_region_callback[name], safe_region_param[name] = nil, nil
|
||||||
|
end
|
||||||
|
|
||||||
minetest.register_chatcommand("/y", {
|
minetest.register_chatcommand("/y", {
|
||||||
params = "",
|
params = "",
|
||||||
description = "Confirm a pending operation",
|
description = "Confirm a pending operation",
|
||||||
@ -40,15 +44,8 @@ minetest.register_chatcommand("/y", {
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
--obtain positions
|
|
||||||
local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]
|
|
||||||
if pos1 == nil or pos2 == nil then
|
|
||||||
worldedit.player_notify(name, "no region selected")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
safe_region_callback[name], safe_region_param[name] = nil, nil --reset pending operation
|
safe_region_callback[name], safe_region_param[name] = nil, nil --reset pending operation
|
||||||
callback(name, param, pos1, pos2)
|
callback(name, param)
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -63,3 +60,6 @@ minetest.register_chatcommand("/n", {
|
|||||||
safe_region_callback[name], safe_region_param[name] = nil, nil
|
safe_region_callback[name], safe_region_param[name] = nil, nil
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
return safe_region, check_region, reset_pending
|
||||||
|
24
worldedit_commands/wand.lua
Normal file
24
worldedit_commands/wand.lua
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
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",
|
||||||
|
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
|
||||||
|
|
||||||
|
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] = pointed_thing.under
|
||||||
|
worldedit.mark_pos1(name)
|
||||||
|
end
|
||||||
|
return itemstack -- nothing consumed, nothing changed
|
||||||
|
end,
|
||||||
|
|
||||||
|
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] = pointed_thing.under
|
||||||
|
worldedit.mark_pos2(name)
|
||||||
|
end
|
||||||
|
return itemstack -- nothing consumed, nothing changed
|
||||||
|
end,
|
||||||
|
})
|
@ -2,4 +2,5 @@ worldedit
|
|||||||
worldedit_commands
|
worldedit_commands
|
||||||
unified_inventory?
|
unified_inventory?
|
||||||
inventory_plus?
|
inventory_plus?
|
||||||
|
sfinv?
|
||||||
creative?
|
creative?
|
@ -1,6 +1,6 @@
|
|||||||
--saved state for each player
|
--saved state for each player
|
||||||
local gui_nodename1 = {} --mapping of player names to node names (arbitrary strings may also appear as values)
|
local gui_nodename1 = {} --mapping of player names to node names
|
||||||
local gui_nodename2 = {} --mapping of player names to node names (arbitrary strings may also appear as values)
|
local gui_nodename2 = {} --mapping of player names to node names
|
||||||
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_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_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)
|
local gui_distance1 = {} --mapping of player names to a distance (arbitrary strings may also appear as values)
|
||||||
@ -10,9 +10,7 @@ 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_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_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_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 (arbitrary strings may also appear as values)
|
local gui_filename = {} --mapping of player names to file names
|
||||||
local gui_formspec = {} --mapping of player names to formspecs
|
|
||||||
local gui_code = {} --mapping of player names to formspecs
|
|
||||||
|
|
||||||
--set default values
|
--set default values
|
||||||
setmetatable(gui_nodename1, {__index = function() return "Cobblestone" end})
|
setmetatable(gui_nodename1, {__index = function() return "Cobblestone" end})
|
||||||
@ -27,8 +25,6 @@ setmetatable(gui_count2, {__index = function() return "6" end})
|
|||||||
setmetatable(gui_count3, {__index = function() return "4" end})
|
setmetatable(gui_count3, {__index = function() return "4" end})
|
||||||
setmetatable(gui_angle, {__index = function() return 90 end})
|
setmetatable(gui_angle, {__index = function() return 90 end})
|
||||||
setmetatable(gui_filename, {__index = function() return "building" 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_indices = {["X axis"]=1, ["Y axis"]=2, ["Z axis"]=3, ["Look direction"]=4}
|
||||||
local axis_values = {"x", "y", "z", "?"}
|
local axis_values = {"x", "y", "z", "?"}
|
||||||
@ -46,7 +42,7 @@ local combine_privs = function(...)
|
|||||||
for i, privs in ipairs({...}) do
|
for i, privs in ipairs({...}) do
|
||||||
for name, value in pairs(privs) do
|
for name, value in pairs(privs) do
|
||||||
if result[name] ~= nil and result[name] ~= value then --the priv must be both true and false, which can never happen
|
if result[name] ~= nil and result[name] ~= value then --the priv must be both true and false, which can never happen
|
||||||
return {__fake_priv_that_nobody_has__=true} --priviledge table that can never be satisfied
|
return {__fake_priv_that_nobody_has__=true} --privilege table that can never be satisfied
|
||||||
end
|
end
|
||||||
result[name] = value
|
result[name] = value
|
||||||
end
|
end
|
||||||
@ -54,22 +50,44 @@ local combine_privs = function(...)
|
|||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- display node (or unknown_node image otherwise) at specified pos in formspec
|
||||||
|
local formspec_node = function(pos, nodename)
|
||||||
|
return nodename and string.format("item_image[%s;1,1;%s]", pos, nodename)
|
||||||
|
or string.format("image[%s;1,1;worldedit_gui_unknown.png]", pos)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- two further priv helpers
|
||||||
|
local function we_privs(command)
|
||||||
|
return minetest.chatcommands["/" .. command].privs
|
||||||
|
end
|
||||||
|
|
||||||
|
local function combine_we_privs(list)
|
||||||
|
local args = {}
|
||||||
|
for _, t in ipairs(list) do
|
||||||
|
table.insert(args, we_privs(t))
|
||||||
|
end
|
||||||
|
return combine_privs(unpack(args))
|
||||||
|
end
|
||||||
|
|
||||||
worldedit.register_gui_function("worldedit_gui_about", {
|
worldedit.register_gui_function("worldedit_gui_about", {
|
||||||
name = "About", privs = minetest.chatcommands["/about"].privs,
|
name = "About",
|
||||||
|
privs = {interact=true},
|
||||||
on_select = function(name)
|
on_select = function(name)
|
||||||
minetest.chatcommands["/about"].func(name, "")
|
minetest.chatcommands["/about"].func(name, "")
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
worldedit.register_gui_function("worldedit_gui_inspect", {
|
worldedit.register_gui_function("worldedit_gui_inspect", {
|
||||||
name = "Toggle Inspect", privs = minetest.chatcommands["/inspect"].privs,
|
name = "Toggle Inspect",
|
||||||
|
privs = we_privs("inspect"),
|
||||||
on_select = function(name)
|
on_select = function(name)
|
||||||
minetest.chatcommands["/inspect"].func(name, worldedit.inspect[name] and "disable" or "enable")
|
minetest.chatcommands["/inspect"].func(name, worldedit.inspect[name] and "disable" or "enable")
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
worldedit.register_gui_function("worldedit_gui_region", {
|
worldedit.register_gui_function("worldedit_gui_region", {
|
||||||
name = "Get/Set Region", privs = combine_privs(minetest.chatcommands["/p"].privs, minetest.chatcommands["/pos1"].privs, minetest.chatcommands["/pos2"].privs, minetest.chatcommands["/reset"].privs, minetest.chatcommands["/mark"].privs, minetest.chatcommands["/unmark"].privs, minetest.chatcommands["/volume"].privs, minetest.chatcommands["/fixedpos"].privs),
|
name = "Get/Set Region",
|
||||||
|
privs = combine_we_privs({"p", "pos1", "pos2", "reset", "mark", "unmark", "volume", "fixedpos"}),
|
||||||
get_formspec = function(name)
|
get_formspec = function(name)
|
||||||
local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]
|
local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]
|
||||||
return "size[9,7]" .. worldedit.get_formspec_header("worldedit_gui_region") ..
|
return "size[9,7]" .. worldedit.get_formspec_header("worldedit_gui_region") ..
|
||||||
@ -148,15 +166,15 @@ worldedit.register_gui_handler("worldedit_gui_region", function(name, fields)
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
worldedit.register_gui_function("worldedit_gui_set", {
|
worldedit.register_gui_function("worldedit_gui_set", {
|
||||||
name = "Set Nodes", privs = minetest.chatcommands["/set"].privs,
|
name = "Set Nodes",
|
||||||
|
privs = we_privs("set"),
|
||||||
get_formspec = function(name)
|
get_formspec = function(name)
|
||||||
local node = gui_nodename1[name]
|
local node = gui_nodename1[name]
|
||||||
local nodename = worldedit.normalize_nodename(node)
|
local nodename = worldedit.normalize_nodename(node)
|
||||||
return "size[6.5,3]" .. worldedit.get_formspec_header("worldedit_gui_set") ..
|
return "size[6.5,3]" .. worldedit.get_formspec_header("worldedit_gui_set") ..
|
||||||
string.format("field[0.5,1.5;4,0.8;worldedit_gui_set_node;Name;%s]", minetest.formspec_escape(node)) ..
|
string.format("field[0.5,1.5;4,0.8;worldedit_gui_set_node;Name;%s]", minetest.formspec_escape(node)) ..
|
||||||
"button[4,1.18;1.5,0.8;worldedit_gui_set_search;Search]" ..
|
"button[4,1.18;1.5,0.8;worldedit_gui_set_search;Search]" ..
|
||||||
(nodename and string.format("item_image[5.5,1.1;1,1;%s]", nodename)
|
formspec_node("5.5,1.1", nodename) ..
|
||||||
or "image[5.5,1.1;1,1;unknown_node.png]") ..
|
|
||||||
"button_exit[0,2.5;3,0.8;worldedit_gui_set_submit;Set Nodes]"
|
"button_exit[0,2.5;3,0.8;worldedit_gui_set_submit;Set Nodes]"
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
@ -166,7 +184,10 @@ worldedit.register_gui_handler("worldedit_gui_set", function(name, fields)
|
|||||||
gui_nodename1[name] = tostring(fields.worldedit_gui_set_node)
|
gui_nodename1[name] = tostring(fields.worldedit_gui_set_node)
|
||||||
worldedit.show_page(name, "worldedit_gui_set")
|
worldedit.show_page(name, "worldedit_gui_set")
|
||||||
if fields.worldedit_gui_set_submit then
|
if fields.worldedit_gui_set_submit then
|
||||||
minetest.chatcommands["/set"].func(name, gui_nodename1[name])
|
local n = worldedit.normalize_nodename(gui_nodename1[name])
|
||||||
|
if n then
|
||||||
|
minetest.chatcommands["/set"].func(name, n)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
@ -174,19 +195,18 @@ worldedit.register_gui_handler("worldedit_gui_set", function(name, fields)
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
worldedit.register_gui_function("worldedit_gui_replace", {
|
worldedit.register_gui_function("worldedit_gui_replace", {
|
||||||
name = "Replace Nodes", privs = combine_privs(minetest.chatcommands["/replace"].privs, minetest.chatcommands["/replaceinverse"].privs),
|
name = "Replace Nodes",
|
||||||
|
privs = combine_we_privs({"replace", "replaceinverse"}),
|
||||||
get_formspec = function(name)
|
get_formspec = function(name)
|
||||||
local search, replace = gui_nodename1[name], gui_nodename2[name]
|
local search, replace = gui_nodename1[name], gui_nodename2[name]
|
||||||
local search_nodename, replace_nodename = worldedit.normalize_nodename(search), worldedit.normalize_nodename(replace)
|
local search_nodename, replace_nodename = worldedit.normalize_nodename(search), worldedit.normalize_nodename(replace)
|
||||||
return "size[6.5,4]" .. worldedit.get_formspec_header("worldedit_gui_replace") ..
|
return "size[6.5,4]" .. worldedit.get_formspec_header("worldedit_gui_replace") ..
|
||||||
string.format("field[0.5,1.5;4,0.8;worldedit_gui_replace_search;Name;%s]", minetest.formspec_escape(search)) ..
|
string.format("field[0.5,1.5;4,0.8;worldedit_gui_replace_search;Name;%s]", minetest.formspec_escape(search)) ..
|
||||||
"button[4,1.18;1.5,0.8;worldedit_gui_replace_search_search;Search]" ..
|
"button[4,1.18;1.5,0.8;worldedit_gui_replace_search_search;Search]" ..
|
||||||
(search_nodename and string.format("item_image[5.5,1.1;1,1;%s]", search_nodename)
|
formspec_node("5.5,1.1", search_nodename) ..
|
||||||
or "image[5.5,1.1;1,1;unknown_node.png]") ..
|
|
||||||
string.format("field[0.5,2.5;4,0.8;worldedit_gui_replace_replace;Name;%s]", minetest.formspec_escape(replace)) ..
|
string.format("field[0.5,2.5;4,0.8;worldedit_gui_replace_replace;Name;%s]", minetest.formspec_escape(replace)) ..
|
||||||
"button[4,2.18;1.5,0.8;worldedit_gui_replace_replace_search;Search]" ..
|
"button[4,2.18;1.5,0.8;worldedit_gui_replace_replace_search;Search]" ..
|
||||||
(replace_nodename and string.format("item_image[5.5,2.1;1,1;%s]", replace_nodename)
|
formspec_node("5.5,2.1", replace_nodename) ..
|
||||||
or "image[5.5,2.1;1,1;unknown_node.png]") ..
|
|
||||||
"button_exit[0,3.5;3,0.8;worldedit_gui_replace_submit;Replace Nodes]" ..
|
"button_exit[0,3.5;3,0.8;worldedit_gui_replace_submit;Replace Nodes]" ..
|
||||||
"button_exit[3.5,3.5;3,0.8;worldedit_gui_replace_submit_inverse;Replace Inverse]"
|
"button_exit[3.5,3.5;3,0.8;worldedit_gui_replace_submit_inverse;Replace Inverse]"
|
||||||
end,
|
end,
|
||||||
@ -198,10 +218,19 @@ worldedit.register_gui_handler("worldedit_gui_replace", function(name, fields)
|
|||||||
gui_nodename1[name] = tostring(fields.worldedit_gui_replace_search)
|
gui_nodename1[name] = tostring(fields.worldedit_gui_replace_search)
|
||||||
gui_nodename2[name] = tostring(fields.worldedit_gui_replace_replace)
|
gui_nodename2[name] = tostring(fields.worldedit_gui_replace_replace)
|
||||||
worldedit.show_page(name, "worldedit_gui_replace")
|
worldedit.show_page(name, "worldedit_gui_replace")
|
||||||
|
|
||||||
|
local submit = nil
|
||||||
if fields.worldedit_gui_replace_submit then
|
if fields.worldedit_gui_replace_submit then
|
||||||
minetest.chatcommands["/replace"].func(name, string.format("%s %s", gui_nodename1[name], gui_nodename2[name]))
|
submit = "replace"
|
||||||
elseif fields.worldedit_gui_replace_submit_inverse then
|
elseif fields.worldedit_gui_replace_submit_inverse then
|
||||||
minetest.chatcommands["/replaceinverse"].func(name, string.format("%s %s", gui_nodename1[name], gui_nodename2[name]))
|
submit = "replaceinverse"
|
||||||
|
end
|
||||||
|
if submit then
|
||||||
|
local n1 = worldedit.normalize_nodename(gui_nodename1[name])
|
||||||
|
local n2 = worldedit.normalize_nodename(gui_nodename2[name])
|
||||||
|
if n1 and n2 then
|
||||||
|
minetest.chatcommands["/"..submit].func(name, string.format("%s %s", n1, n2))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
@ -209,15 +238,15 @@ worldedit.register_gui_handler("worldedit_gui_replace", function(name, fields)
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
worldedit.register_gui_function("worldedit_gui_sphere_dome", {
|
worldedit.register_gui_function("worldedit_gui_sphere_dome", {
|
||||||
name = "Sphere/Dome", privs = combine_privs(minetest.chatcommands["/hollowsphere"].privs, minetest.chatcommands["/sphere"].privs, minetest.chatcommands["/hollowdome"].privs, minetest.chatcommands["/dome"].privs),
|
name = "Sphere/Dome",
|
||||||
|
privs = combine_we_privs({"hollowsphere", "sphere", "hollowdome", "dome"}),
|
||||||
get_formspec = function(name)
|
get_formspec = function(name)
|
||||||
local node, radius = gui_nodename1[name], gui_distance2[name]
|
local node, radius = gui_nodename1[name], gui_distance2[name]
|
||||||
local nodename = worldedit.normalize_nodename(node)
|
local nodename = worldedit.normalize_nodename(node)
|
||||||
return "size[6.5,5]" .. worldedit.get_formspec_header("worldedit_gui_sphere_dome") ..
|
return "size[6.5,5]" .. worldedit.get_formspec_header("worldedit_gui_sphere_dome") ..
|
||||||
string.format("field[0.5,1.5;4,0.8;worldedit_gui_sphere_dome_node;Name;%s]", minetest.formspec_escape(node)) ..
|
string.format("field[0.5,1.5;4,0.8;worldedit_gui_sphere_dome_node;Name;%s]", minetest.formspec_escape(node)) ..
|
||||||
"button[4,1.18;1.5,0.8;worldedit_gui_sphere_dome_search;Search]" ..
|
"button[4,1.18;1.5,0.8;worldedit_gui_sphere_dome_search;Search]" ..
|
||||||
(nodename and string.format("item_image[5.5,1.1;1,1;%s]", nodename)
|
formspec_node("5.5,1.1", nodename) ..
|
||||||
or "image[5.5,1.1;1,1;unknown_node.png]") ..
|
|
||||||
string.format("field[0.5,2.5;4,0.8;worldedit_gui_sphere_dome_radius;Radius;%s]", minetest.formspec_escape(radius)) ..
|
string.format("field[0.5,2.5;4,0.8;worldedit_gui_sphere_dome_radius;Radius;%s]", minetest.formspec_escape(radius)) ..
|
||||||
"button_exit[0,3.5;3,0.8;worldedit_gui_sphere_dome_submit_hollow;Hollow Sphere]" ..
|
"button_exit[0,3.5;3,0.8;worldedit_gui_sphere_dome_submit_hollow;Hollow Sphere]" ..
|
||||||
"button_exit[3.5,3.5;3,0.8;worldedit_gui_sphere_dome_submit_solid;Solid Sphere]" ..
|
"button_exit[3.5,3.5;3,0.8;worldedit_gui_sphere_dome_submit_solid;Solid Sphere]" ..
|
||||||
@ -233,14 +262,22 @@ worldedit.register_gui_handler("worldedit_gui_sphere_dome", function(name, field
|
|||||||
gui_nodename1[name] = tostring(fields.worldedit_gui_sphere_dome_node)
|
gui_nodename1[name] = tostring(fields.worldedit_gui_sphere_dome_node)
|
||||||
gui_distance2[name] = tostring(fields.worldedit_gui_sphere_dome_radius)
|
gui_distance2[name] = tostring(fields.worldedit_gui_sphere_dome_radius)
|
||||||
worldedit.show_page(name, "worldedit_gui_sphere_dome")
|
worldedit.show_page(name, "worldedit_gui_sphere_dome")
|
||||||
|
|
||||||
|
local submit = nil
|
||||||
if fields.worldedit_gui_sphere_dome_submit_hollow then
|
if fields.worldedit_gui_sphere_dome_submit_hollow then
|
||||||
minetest.chatcommands["/hollowsphere"].func(name, string.format("%s %s", gui_distance2[name], gui_nodename1[name]))
|
submit = "hollowsphere"
|
||||||
elseif fields.worldedit_gui_sphere_dome_submit_solid then
|
elseif fields.worldedit_gui_sphere_dome_submit_solid then
|
||||||
minetest.chatcommands["/sphere"].func(name, string.format("%s %s", gui_distance2[name], gui_nodename1[name]))
|
submit = "sphere"
|
||||||
elseif fields.worldedit_gui_sphere_dome_submit_hollow_dome then
|
elseif fields.worldedit_gui_sphere_dome_submit_hollow_dome then
|
||||||
minetest.chatcommands["/hollowdome"].func(name, string.format("%s %s", gui_distance2[name], gui_nodename1[name]))
|
submit = "hollowdome"
|
||||||
elseif fields.worldedit_gui_sphere_dome_submit_solid_dome then
|
elseif fields.worldedit_gui_sphere_dome_submit_solid_dome then
|
||||||
minetest.chatcommands["/dome"].func(name, string.format("%s %s", gui_distance2[name], gui_nodename1[name]))
|
submit = "dome"
|
||||||
|
end
|
||||||
|
if submit then
|
||||||
|
local n = worldedit.normalize_nodename(gui_nodename1[name])
|
||||||
|
if n then
|
||||||
|
minetest.chatcommands["/"..submit].func(name, string.format("%s %s", gui_distance2[name], n))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
@ -248,20 +285,24 @@ worldedit.register_gui_handler("worldedit_gui_sphere_dome", function(name, field
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
worldedit.register_gui_function("worldedit_gui_cylinder", {
|
worldedit.register_gui_function("worldedit_gui_cylinder", {
|
||||||
name = "Cylinder", privs = combine_privs(minetest.chatcommands["/hollowcylinder"].privs, minetest.chatcommands["/cylinder"].privs),
|
name = "Cylinder",
|
||||||
|
privs = combine_we_privs({"hollowcylinder", "cylinder"}),
|
||||||
get_formspec = function(name)
|
get_formspec = function(name)
|
||||||
local node, axis, length, radius = gui_nodename1[name], gui_axis1[name], gui_distance1[name], gui_distance2[name]
|
local node, axis, length = gui_nodename1[name], gui_axis1[name], gui_distance1[name]
|
||||||
|
local radius1, radius2 = gui_distance2[name], gui_distance3[name]
|
||||||
local nodename = worldedit.normalize_nodename(node)
|
local nodename = worldedit.normalize_nodename(node)
|
||||||
return "size[6.5,5]" .. worldedit.get_formspec_header("worldedit_gui_cylinder") ..
|
return "size[6.5,6]" .. 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)) ..
|
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]" ..
|
"button[4,1.18;1.5,0.8;worldedit_gui_cylinder_search;Search]" ..
|
||||||
(nodename and string.format("item_image[5.5,1.1;1,1;%s]", nodename)
|
formspec_node("5.5,1.1", nodename) ..
|
||||||
or "image[5.5,1.1;1,1;unknown_node.png]") ..
|
|
||||||
string.format("field[0.5,2.5;4,0.8;worldedit_gui_cylinder_length;Length;%s]", minetest.formspec_escape(length)) ..
|
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("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;4,0.8;worldedit_gui_cylinder_radius;Radius;%s]", minetest.formspec_escape(radius)) ..
|
string.format("field[0.5,3.5;2,0.8;worldedit_gui_cylinder_radius1;Base Radius;%s]", minetest.formspec_escape(radius1)) ..
|
||||||
"button_exit[0,4.5;3,0.8;worldedit_gui_cylinder_submit_hollow;Hollow Cylinder]" ..
|
string.format("field[2.5,3.5;2,0.8;worldedit_gui_cylinder_radius2;Top Radius;%s]", minetest.formspec_escape(radius2)) ..
|
||||||
"button_exit[3.5,4.5;3,0.8;worldedit_gui_cylinder_submit_solid;Solid Cylinder]"
|
"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]"
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -271,58 +312,89 @@ worldedit.register_gui_handler("worldedit_gui_cylinder", function(name, fields)
|
|||||||
gui_nodename1[name] = tostring(fields.worldedit_gui_cylinder_node)
|
gui_nodename1[name] = tostring(fields.worldedit_gui_cylinder_node)
|
||||||
gui_axis1[name] = axis_indices[fields.worldedit_gui_cylinder_axis]
|
gui_axis1[name] = axis_indices[fields.worldedit_gui_cylinder_axis]
|
||||||
gui_distance1[name] = tostring(fields.worldedit_gui_cylinder_length)
|
gui_distance1[name] = tostring(fields.worldedit_gui_cylinder_length)
|
||||||
gui_distance2[name] = tostring(fields.worldedit_gui_cylinder_radius)
|
gui_distance2[name] = tostring(fields.worldedit_gui_cylinder_radius1)
|
||||||
|
gui_distance3[name] = tostring(fields.worldedit_gui_cylinder_radius2)
|
||||||
worldedit.show_page(name, "worldedit_gui_cylinder")
|
worldedit.show_page(name, "worldedit_gui_cylinder")
|
||||||
|
|
||||||
|
local submit = nil
|
||||||
if fields.worldedit_gui_cylinder_submit_hollow then
|
if fields.worldedit_gui_cylinder_submit_hollow then
|
||||||
minetest.chatcommands["/hollowcylinder"].func(name, string.format("%s %s %s %s", axis_values[gui_axis1[name]], gui_distance1[name], gui_distance2[name], gui_nodename1[name]))
|
submit = "hollowcylinder"
|
||||||
elseif fields.worldedit_gui_cylinder_submit_solid then
|
elseif fields.worldedit_gui_cylinder_submit_solid then
|
||||||
minetest.chatcommands["/cylinder"].func(name, string.format("%s %s %s %s", axis_values[gui_axis1[name]], gui_distance1[name], gui_distance2[name], gui_nodename1[name]))
|
submit = "cylinder"
|
||||||
end
|
end
|
||||||
|
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)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
if fields.worldedit_gui_cylinder_axis then
|
||||||
|
gui_axis1[name] = axis_indices[fields.worldedit_gui_cylinder_axis]
|
||||||
|
worldedit.show_page(name, "worldedit_gui_cylinder")
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
return false
|
return false
|
||||||
end)
|
end)
|
||||||
|
|
||||||
worldedit.register_gui_function("worldedit_gui_pyramid", {
|
worldedit.register_gui_function("worldedit_gui_pyramid", {
|
||||||
name = "Pyramid", privs = minetest.chatcommands["/pyramid"].privs,
|
name = "Pyramid",
|
||||||
|
privs = we_privs("pyramid"),
|
||||||
get_formspec = function(name)
|
get_formspec = function(name)
|
||||||
local node, axis, length = gui_nodename1[name], gui_axis1[name], gui_distance1[name]
|
local node, axis, length = gui_nodename1[name], gui_axis1[name], gui_distance1[name]
|
||||||
local nodename = worldedit.normalize_nodename(node)
|
local nodename = worldedit.normalize_nodename(node)
|
||||||
return "size[6.5,4]" .. worldedit.get_formspec_header("worldedit_gui_pyramid") ..
|
return "size[6.5,4]" .. worldedit.get_formspec_header("worldedit_gui_pyramid") ..
|
||||||
string.format("field[0.5,1.5;4,0.8;worldedit_gui_pyramid_node;Name;%s]", minetest.formspec_escape(node)) ..
|
string.format("field[0.5,1.5;4,0.8;worldedit_gui_pyramid_node;Name;%s]", minetest.formspec_escape(node)) ..
|
||||||
"button[4,1.18;1.5,0.8;worldedit_gui_pyramid_search;Search]" ..
|
"button[4,1.18;1.5,0.8;worldedit_gui_pyramid_search;Search]" ..
|
||||||
(nodename and string.format("item_image[5.5,1.1;1,1;%s]", nodename)
|
formspec_node("5.5,1.1", nodename) ..
|
||||||
or "image[5.5,1.1;1,1;unknown_node.png]") ..
|
|
||||||
string.format("field[0.5,2.5;4,0.8;worldedit_gui_pyramid_length;Length;%s]", minetest.formspec_escape(length)) ..
|
string.format("field[0.5,2.5;4,0.8;worldedit_gui_pyramid_length;Length;%s]", minetest.formspec_escape(length)) ..
|
||||||
string.format("dropdown[4,2.18;2.5;worldedit_gui_pyramid_axis;X axis,Y axis,Z axis,Look direction;%d]", axis) ..
|
string.format("dropdown[4,2.18;2.5;worldedit_gui_pyramid_axis;X axis,Y axis,Z axis,Look direction;%d]", axis) ..
|
||||||
"button_exit[0,3.5;3,0.8;worldedit_gui_pyramid_submit;Pyramid]"
|
"button_exit[0,3.5;3,0.8;worldedit_gui_pyramid_submit_hollow;Hollow Pyramid]" ..
|
||||||
|
"button_exit[3.5,3.5;3,0.8;worldedit_gui_pyramid_submit_solid;Solid Pyramid]"
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
worldedit.register_gui_handler("worldedit_gui_pyramid", function(name, fields)
|
worldedit.register_gui_handler("worldedit_gui_pyramid", function(name, fields)
|
||||||
if fields.worldedit_gui_pyramid_search or fields.worldedit_gui_pyramid_submit then
|
if fields.worldedit_gui_pyramid_search or fields.worldedit_gui_pyramid_submit_solid or fields.worldedit_gui_pyramid_submit_hollow or fields.worldedit_gui_pyramid_axis then
|
||||||
gui_nodename1[name] = tostring(fields.worldedit_gui_pyramid_node)
|
gui_nodename1[name] = tostring(fields.worldedit_gui_pyramid_node)
|
||||||
gui_axis1[name] = axis_indices[fields.worldedit_gui_pyramid_axis]
|
gui_axis1[name] = axis_indices[fields.worldedit_gui_pyramid_axis]
|
||||||
gui_distance1[name] = tostring(fields.worldedit_gui_pyramid_length)
|
gui_distance1[name] = tostring(fields.worldedit_gui_pyramid_length)
|
||||||
worldedit.show_page(name, "worldedit_gui_pyramid")
|
worldedit.show_page(name, "worldedit_gui_pyramid")
|
||||||
if fields.worldedit_gui_pyramid_submit then
|
|
||||||
minetest.chatcommands["/pyramid"].func(name, string.format("%s %s %s", axis_values[gui_axis1[name]], gui_distance1[name], gui_nodename1[name]))
|
local submit = nil
|
||||||
|
if fields.worldedit_gui_pyramid_submit_solid then
|
||||||
|
submit = "pyramid"
|
||||||
|
elseif fields.worldedit_gui_pyramid_submit_hollow then
|
||||||
|
submit = "hollowpyramid"
|
||||||
end
|
end
|
||||||
|
if submit then
|
||||||
|
local n = worldedit.normalize_nodename(gui_nodename1[name])
|
||||||
|
if n then
|
||||||
|
minetest.chatcommands["/"..submit].func(name, string.format("%s %s %s", axis_values[gui_axis1[name]], gui_distance1[name], n))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
if fields.worldedit_gui_pyramid_axis then
|
||||||
|
gui_axis1[name] = axis_indices[fields.worldedit_gui_pyramid_axis]
|
||||||
|
worldedit.show_page(name, "worldedit_gui_pyramid")
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
return false
|
return false
|
||||||
end)
|
end)
|
||||||
|
|
||||||
worldedit.register_gui_function("worldedit_gui_spiral", {
|
worldedit.register_gui_function("worldedit_gui_spiral", {
|
||||||
name = "Spiral", privs = minetest.chatcommands["/spiral"].privs,
|
name = "Spiral",
|
||||||
|
privs = we_privs("spiral"),
|
||||||
get_formspec = function(name)
|
get_formspec = function(name)
|
||||||
local node, length, height, space = gui_nodename1[name], gui_distance1[name], gui_distance2[name], gui_distance3[name]
|
local node, length, height, space = gui_nodename1[name], gui_distance1[name], gui_distance2[name], gui_distance3[name]
|
||||||
local nodename = worldedit.normalize_nodename(node)
|
local nodename = worldedit.normalize_nodename(node)
|
||||||
return "size[6.5,6]" .. worldedit.get_formspec_header("worldedit_gui_spiral") ..
|
return "size[6.5,6]" .. worldedit.get_formspec_header("worldedit_gui_spiral") ..
|
||||||
string.format("field[0.5,1.5;4,0.8;worldedit_gui_spiral_node;Name;%s]", minetest.formspec_escape(node)) ..
|
string.format("field[0.5,1.5;4,0.8;worldedit_gui_spiral_node;Name;%s]", minetest.formspec_escape(node)) ..
|
||||||
"button[4,1.18;1.5,0.8;worldedit_gui_spiral_search;Search]" ..
|
"button[4,1.18;1.5,0.8;worldedit_gui_spiral_search;Search]" ..
|
||||||
(nodename and string.format("item_image[5.5,1.1;1,1;%s]", nodename)
|
formspec_node("5.5,1.1", nodename) ..
|
||||||
or "image[5.5,1.1;1,1;unknown_node.png]") ..
|
|
||||||
string.format("field[0.5,2.5;4,0.8;worldedit_gui_spiral_length;Side Length;%s]", minetest.formspec_escape(length)) ..
|
string.format("field[0.5,2.5;4,0.8;worldedit_gui_spiral_length;Side Length;%s]", minetest.formspec_escape(length)) ..
|
||||||
string.format("field[0.5,3.5;4,0.8;worldedit_gui_spiral_height;Height;%s]", minetest.formspec_escape(height)) ..
|
string.format("field[0.5,3.5;4,0.8;worldedit_gui_spiral_height;Height;%s]", minetest.formspec_escape(height)) ..
|
||||||
string.format("field[0.5,4.5;4,0.8;worldedit_gui_spiral_space;Wall Spacing;%s]", minetest.formspec_escape(space)) ..
|
string.format("field[0.5,4.5;4,0.8;worldedit_gui_spiral_space;Wall Spacing;%s]", minetest.formspec_escape(space)) ..
|
||||||
@ -338,7 +410,10 @@ worldedit.register_gui_handler("worldedit_gui_spiral", function(name, fields)
|
|||||||
gui_distance3[name] = tostring(fields.worldedit_gui_spiral_space)
|
gui_distance3[name] = tostring(fields.worldedit_gui_spiral_space)
|
||||||
worldedit.show_page(name, "worldedit_gui_spiral")
|
worldedit.show_page(name, "worldedit_gui_spiral")
|
||||||
if fields.worldedit_gui_spiral_submit then
|
if fields.worldedit_gui_spiral_submit then
|
||||||
minetest.chatcommands["/spiral"].func(name, string.format("%s %s %s %s", gui_distance1[name], gui_distance2[name], gui_distance3[name], gui_nodename1[name]))
|
local n = worldedit.normalize_nodename(gui_nodename1[name])
|
||||||
|
if n then
|
||||||
|
minetest.chatcommands["/spiral"].func(name, string.format("%s %s %s %s", gui_distance1[name], gui_distance2[name], gui_distance3[name], n))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
@ -346,7 +421,8 @@ worldedit.register_gui_handler("worldedit_gui_spiral", function(name, fields)
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
worldedit.register_gui_function("worldedit_gui_copy_move", {
|
worldedit.register_gui_function("worldedit_gui_copy_move", {
|
||||||
name = "Copy/Move", privs = combine_privs(minetest.chatcommands["/copy"].privs, minetest.chatcommands["/move"].privs),
|
name = "Copy/Move",
|
||||||
|
privs = combine_we_privs({"copy", "move"}),
|
||||||
get_formspec = function(name)
|
get_formspec = function(name)
|
||||||
local axis = gui_axis1[name] or 4
|
local axis = gui_axis1[name] or 4
|
||||||
local amount = gui_distance1[name] or "10"
|
local amount = gui_distance1[name] or "10"
|
||||||
@ -370,11 +446,17 @@ worldedit.register_gui_handler("worldedit_gui_copy_move", function(name, fields)
|
|||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
if fields.worldedit_gui_copy_move_axis then
|
||||||
|
gui_axis1[name] = axis_indices[fields.worldedit_gui_copy_move_axis] or 4
|
||||||
|
worldedit.show_page(name, "worldedit_gui_copy_move")
|
||||||
|
return true
|
||||||
|
end
|
||||||
return false
|
return false
|
||||||
end)
|
end)
|
||||||
|
|
||||||
worldedit.register_gui_function("worldedit_gui_stack", {
|
worldedit.register_gui_function("worldedit_gui_stack", {
|
||||||
name = "Stack", privs = minetest.chatcommands["/stack"].privs,
|
name = "Stack",
|
||||||
|
privs = we_privs("stack"),
|
||||||
get_formspec = function(name)
|
get_formspec = function(name)
|
||||||
local axis, count = gui_axis1[name], gui_count1[name]
|
local axis, count = gui_axis1[name], gui_count1[name]
|
||||||
return "size[6.5,3]" .. worldedit.get_formspec_header("worldedit_gui_stack") ..
|
return "size[6.5,3]" .. worldedit.get_formspec_header("worldedit_gui_stack") ..
|
||||||
@ -392,11 +474,17 @@ worldedit.register_gui_handler("worldedit_gui_stack", function(name, fields)
|
|||||||
minetest.chatcommands["/stack"].func(name, string.format("%s %s", axis_values[gui_axis1[name]], gui_count1[name]))
|
minetest.chatcommands["/stack"].func(name, string.format("%s %s", axis_values[gui_axis1[name]], gui_count1[name]))
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
if fields.worldedit_gui_stack_axis then
|
||||||
|
gui_axis1[name] = axis_indices[fields.worldedit_gui_stack_axis]
|
||||||
|
worldedit.show_page(name, "worldedit_gui_stack")
|
||||||
|
return true
|
||||||
|
end
|
||||||
return false
|
return false
|
||||||
end)
|
end)
|
||||||
|
|
||||||
worldedit.register_gui_function("worldedit_gui_stretch", {
|
worldedit.register_gui_function("worldedit_gui_stretch", {
|
||||||
name = "Stretch", privs = minetest.chatcommands["/stretch"].privs,
|
name = "Stretch",
|
||||||
|
privs = we_privs("stretch"),
|
||||||
get_formspec = function(name)
|
get_formspec = function(name)
|
||||||
local stretchx, stretchy, stretchz = gui_count1[name], gui_count2[name], gui_count3[name]
|
local stretchx, stretchy, stretchz = gui_count1[name], gui_count2[name], gui_count3[name]
|
||||||
return "size[5,5]" .. worldedit.get_formspec_header("worldedit_gui_stretch") ..
|
return "size[5,5]" .. worldedit.get_formspec_header("worldedit_gui_stretch") ..
|
||||||
@ -420,7 +508,8 @@ worldedit.register_gui_handler("worldedit_gui_stretch", function(name, fields)
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
worldedit.register_gui_function("worldedit_gui_transpose", {
|
worldedit.register_gui_function("worldedit_gui_transpose", {
|
||||||
name = "Transpose", privs = minetest.chatcommands["/transpose"].privs,
|
name = "Transpose",
|
||||||
|
privs = we_privs("transpose"),
|
||||||
get_formspec = function(name)
|
get_formspec = function(name)
|
||||||
local axis1, axis2 = gui_axis1[name], gui_axis2[name]
|
local axis1, axis2 = gui_axis1[name], gui_axis2[name]
|
||||||
return "size[5.5,3]" .. worldedit.get_formspec_header("worldedit_gui_transpose") ..
|
return "size[5.5,3]" .. worldedit.get_formspec_header("worldedit_gui_transpose") ..
|
||||||
@ -433,18 +522,28 @@ worldedit.register_gui_function("worldedit_gui_transpose", {
|
|||||||
worldedit.register_gui_handler("worldedit_gui_transpose", function(name, fields)
|
worldedit.register_gui_handler("worldedit_gui_transpose", function(name, fields)
|
||||||
if fields.worldedit_gui_transpose_submit then
|
if fields.worldedit_gui_transpose_submit then
|
||||||
gui_axis1[name] = axis_indices[fields.worldedit_gui_transpose_axis1]
|
gui_axis1[name] = axis_indices[fields.worldedit_gui_transpose_axis1]
|
||||||
gui_axis2[name] = axis_indices[fields.worldedit_gui_transpose_axis2]
|
|
||||||
worldedit.show_page(name, "worldedit_gui_transpose")
|
worldedit.show_page(name, "worldedit_gui_transpose")
|
||||||
minetest.chatcommands["/transpose"].func(name, string.format("%s %s", axis_values[gui_axis1[name]], axis_values[gui_axis2[name]]))
|
minetest.chatcommands["/transpose"].func(name, string.format("%s %s", axis_values[gui_axis1[name]], axis_values[gui_axis2[name]]))
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
if fields.worldedit_gui_transpose_axis1 then
|
||||||
|
gui_axis1[name] = axis_indices[fields.worldedit_gui_transpose_axis1]
|
||||||
|
worldedit.show_page(name, "worldedit_gui_transpose")
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
if fields.worldedit_gui_transpose_axis2 then
|
||||||
|
gui_axis2[name] = axis_indices[fields.worldedit_gui_transpose_axis2]
|
||||||
|
worldedit.show_page(name, "worldedit_gui_transpose")
|
||||||
|
return true
|
||||||
|
end
|
||||||
return false
|
return false
|
||||||
end)
|
end)
|
||||||
|
|
||||||
worldedit.register_gui_function("worldedit_gui_flip", {
|
worldedit.register_gui_function("worldedit_gui_flip", {
|
||||||
name = "Flip", privs = minetest.chatcommands["/flip"].privs,
|
name = "Flip",
|
||||||
|
privs = we_privs("flip"),
|
||||||
get_formspec = function(name)
|
get_formspec = function(name)
|
||||||
local axis = gui_axis2[name]
|
local axis = gui_axis1[name]
|
||||||
return "size[5,3]" .. worldedit.get_formspec_header("worldedit_gui_flip") ..
|
return "size[5,3]" .. worldedit.get_formspec_header("worldedit_gui_flip") ..
|
||||||
string.format("dropdown[0,1;2.5;worldedit_gui_flip_axis;X axis,Y axis,Z axis,Look direction;%d]", axis) ..
|
string.format("dropdown[0,1;2.5;worldedit_gui_flip_axis;X axis,Y axis,Z axis,Look direction;%d]", axis) ..
|
||||||
"button_exit[0,2.5;3,0.8;worldedit_gui_flip_submit;Flip]"
|
"button_exit[0,2.5;3,0.8;worldedit_gui_flip_submit;Flip]"
|
||||||
@ -453,16 +552,22 @@ worldedit.register_gui_function("worldedit_gui_flip", {
|
|||||||
|
|
||||||
worldedit.register_gui_handler("worldedit_gui_flip", function(name, fields)
|
worldedit.register_gui_handler("worldedit_gui_flip", function(name, fields)
|
||||||
if fields.worldedit_gui_flip_submit then
|
if fields.worldedit_gui_flip_submit then
|
||||||
gui_axis2[name] = axis_indices[fields.worldedit_gui_flip_axis]
|
gui_axis1[name] = axis_indices[fields.worldedit_gui_flip_axis]
|
||||||
|
worldedit.show_page(name, "worldedit_gui_flip")
|
||||||
|
minetest.chatcommands["/flip"].func(name, axis_values[gui_axis1[name]])
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
if fields.worldedit_gui_flip_axis then
|
||||||
|
gui_axis1[name] = axis_indices[fields.worldedit_gui_flip_axis]
|
||||||
worldedit.show_page(name, "worldedit_gui_flip")
|
worldedit.show_page(name, "worldedit_gui_flip")
|
||||||
minetest.chatcommands["/flip"].func(name, axis_values[gui_axis2[name]])
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
return false
|
return false
|
||||||
end)
|
end)
|
||||||
|
|
||||||
worldedit.register_gui_function("worldedit_gui_rotate", {
|
worldedit.register_gui_function("worldedit_gui_rotate", {
|
||||||
name = "Rotate", privs = minetest.chatcommands["/rotate"].privs,
|
name = "Rotate",
|
||||||
|
privs = we_privs("rotate"),
|
||||||
get_formspec = function(name)
|
get_formspec = function(name)
|
||||||
local axis, angle = gui_axis1[name], gui_angle[name]
|
local axis, angle = gui_axis1[name], gui_angle[name]
|
||||||
return "size[5.5,3]" .. worldedit.get_formspec_header("worldedit_gui_rotate") ..
|
return "size[5.5,3]" .. worldedit.get_formspec_header("worldedit_gui_rotate") ..
|
||||||
@ -480,15 +585,26 @@ worldedit.register_gui_handler("worldedit_gui_rotate", function(name, fields)
|
|||||||
minetest.chatcommands["/rotate"].func(name, string.format("%s %s", axis_values[gui_axis1[name]], angle_values[gui_angle[name]]))
|
minetest.chatcommands["/rotate"].func(name, string.format("%s %s", axis_values[gui_axis1[name]], angle_values[gui_angle[name]]))
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
if fields.worldedit_gui_rotate_axis then
|
||||||
|
gui_axis1[name] = axis_indices[fields.worldedit_gui_rotate_axis]
|
||||||
|
worldedit.show_page(name, "worldedit_gui_rotate")
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
if fields.worldedit_gui_rotate_angle then
|
||||||
|
gui_angle[name] = angle_indices[fields.worldedit_gui_rotate_angle]
|
||||||
|
worldedit.show_page(name, "worldedit_gui_rotate")
|
||||||
|
return true
|
||||||
|
end
|
||||||
return false
|
return false
|
||||||
end)
|
end)
|
||||||
|
|
||||||
worldedit.register_gui_function("worldedit_gui_orient", {
|
worldedit.register_gui_function("worldedit_gui_orient", {
|
||||||
name = "Orient", privs = minetest.chatcommands["/orient"].privs,
|
name = "Orient",
|
||||||
|
privs = we_privs("orient"),
|
||||||
get_formspec = function(name)
|
get_formspec = function(name)
|
||||||
local angle = gui_angle[name]
|
local angle = gui_angle[name]
|
||||||
return "size[5,3]" .. worldedit.get_formspec_header("worldedit_gui_orient") ..
|
return "size[5,3]" .. worldedit.get_formspec_header("worldedit_gui_orient") ..
|
||||||
string.format("dropdown[0,1;2.5;worldedit_gui_rotate_angle;90 degrees,180 degrees,270 degrees;%s]", angle) ..
|
string.format("dropdown[0,1;2.5;worldedit_gui_orient_angle;90 degrees,180 degrees,270 degrees;%s]", angle) ..
|
||||||
"button_exit[0,2.5;3,0.8;worldedit_gui_orient_submit;Orient]"
|
"button_exit[0,2.5;3,0.8;worldedit_gui_orient_submit;Orient]"
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
@ -497,36 +613,43 @@ worldedit.register_gui_handler("worldedit_gui_orient", function(name, fields)
|
|||||||
if fields.worldedit_gui_orient_submit then
|
if fields.worldedit_gui_orient_submit then
|
||||||
gui_angle[name] = angle_indices[fields.worldedit_gui_orient_angle]
|
gui_angle[name] = angle_indices[fields.worldedit_gui_orient_angle]
|
||||||
worldedit.show_page(name, "worldedit_gui_orient")
|
worldedit.show_page(name, "worldedit_gui_orient")
|
||||||
minetest.chatcommands["/orient"].func(name, angle_values[gui_angle[name]])
|
minetest.chatcommands["/orient"].func(name, tostring(angle_values[gui_angle[name]]))
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
if fields.worldedit_gui_orient_angle then
|
||||||
|
gui_angle[name] = angle_indices[fields.worldedit_gui_orient_angle]
|
||||||
|
worldedit.show_page(name, "worldedit_gui_orient")
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
return false
|
return false
|
||||||
end)
|
end)
|
||||||
|
|
||||||
worldedit.register_gui_function("worldedit_gui_fixlight", {
|
worldedit.register_gui_function("worldedit_gui_fixlight", {
|
||||||
name = "Fix Lighting", privs = minetest.chatcommands["/fixlight"].privs,
|
name = "Fix Lighting",
|
||||||
|
privs = we_privs("fixlight"),
|
||||||
on_select = function(name)
|
on_select = function(name)
|
||||||
minetest.chatcommands["/fixlight"].func(name, "")
|
minetest.chatcommands["/fixlight"].func(name, "")
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
worldedit.register_gui_function("worldedit_gui_hide", {
|
worldedit.register_gui_function("worldedit_gui_hide", {
|
||||||
name = "Hide Region", privs = minetest.chatcommands["/hide"].privs,
|
name = "Hide Region",
|
||||||
|
privs = we_privs("hide"),
|
||||||
on_select = function(name)
|
on_select = function(name)
|
||||||
minetest.chatcommands["/hide"].func(name, "")
|
minetest.chatcommands["/hide"].func(name, "")
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
worldedit.register_gui_function("worldedit_gui_suppress", {
|
worldedit.register_gui_function("worldedit_gui_suppress", {
|
||||||
name = "Suppress Nodes", privs = minetest.chatcommands["/suppress"].privs,
|
name = "Suppress Nodes",
|
||||||
|
privs = we_privs("suppress"),
|
||||||
get_formspec = function(name)
|
get_formspec = function(name)
|
||||||
local node = gui_nodename1[name]
|
local node = gui_nodename1[name]
|
||||||
local nodename = worldedit.normalize_nodename(node)
|
local nodename = worldedit.normalize_nodename(node)
|
||||||
return "size[6.5,3]" .. worldedit.get_formspec_header("worldedit_gui_suppress") ..
|
return "size[6.5,3]" .. worldedit.get_formspec_header("worldedit_gui_suppress") ..
|
||||||
string.format("field[0.5,1.5;4,0.8;worldedit_gui_suppress_node;Name;%s]", minetest.formspec_escape(node)) ..
|
string.format("field[0.5,1.5;4,0.8;worldedit_gui_suppress_node;Name;%s]", minetest.formspec_escape(node)) ..
|
||||||
"button[4,1.18;1.5,0.8;worldedit_gui_suppress_search;Search]" ..
|
"button[4,1.18;1.5,0.8;worldedit_gui_suppress_search;Search]" ..
|
||||||
(nodename and string.format("item_image[5.5,1.1;1,1;%s]", nodename)
|
formspec_node("5.5,1.1", nodename) ..
|
||||||
or "image[5.5,1.1;1,1;unknown_node.png]") ..
|
|
||||||
"button_exit[0,2.5;3,0.8;worldedit_gui_suppress_submit;Suppress Nodes]"
|
"button_exit[0,2.5;3,0.8;worldedit_gui_suppress_submit;Suppress Nodes]"
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
@ -536,7 +659,10 @@ worldedit.register_gui_handler("worldedit_gui_suppress", function(name, fields)
|
|||||||
gui_nodename1[name] = tostring(fields.worldedit_gui_suppress_node)
|
gui_nodename1[name] = tostring(fields.worldedit_gui_suppress_node)
|
||||||
worldedit.show_page(name, "worldedit_gui_suppress")
|
worldedit.show_page(name, "worldedit_gui_suppress")
|
||||||
if fields.worldedit_gui_suppress_submit then
|
if fields.worldedit_gui_suppress_submit then
|
||||||
minetest.chatcommands["/suppress"].func(name, gui_nodename1[name])
|
local n = worldedit.normalize_nodename(gui_nodename1[name])
|
||||||
|
if n then
|
||||||
|
minetest.chatcommands["/suppress"].func(name, n)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
@ -544,15 +670,15 @@ worldedit.register_gui_handler("worldedit_gui_suppress", function(name, fields)
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
worldedit.register_gui_function("worldedit_gui_highlight", {
|
worldedit.register_gui_function("worldedit_gui_highlight", {
|
||||||
name = "Highlight Nodes", privs = minetest.chatcommands["/highlight"].privs,
|
name = "Highlight Nodes",
|
||||||
|
privs = we_privs("highlight"),
|
||||||
get_formspec = function(name)
|
get_formspec = function(name)
|
||||||
local node = gui_nodename1[name]
|
local node = gui_nodename1[name]
|
||||||
local nodename = worldedit.normalize_nodename(node)
|
local nodename = worldedit.normalize_nodename(node)
|
||||||
return "size[6.5,3]" .. worldedit.get_formspec_header("worldedit_gui_highlight") ..
|
return "size[6.5,3]" .. worldedit.get_formspec_header("worldedit_gui_highlight") ..
|
||||||
string.format("field[0.5,1.5;4,0.8;worldedit_gui_highlight_node;Name;%s]", minetest.formspec_escape(node)) ..
|
string.format("field[0.5,1.5;4,0.8;worldedit_gui_highlight_node;Name;%s]", minetest.formspec_escape(node)) ..
|
||||||
"button[4,1.18;1.5,0.8;worldedit_gui_highlight_search;Search]" ..
|
"button[4,1.18;1.5,0.8;worldedit_gui_highlight_search;Search]" ..
|
||||||
(nodename and string.format("item_image[5.5,1.1;1,1;%s]", nodename)
|
formspec_node("5.5,1.1", nodename) ..
|
||||||
or "image[5.5,1.1;1,1;unknown_node.png]") ..
|
|
||||||
"button_exit[0,2.5;3,0.8;worldedit_gui_highlight_submit;Highlight Nodes]"
|
"button_exit[0,2.5;3,0.8;worldedit_gui_highlight_submit;Highlight Nodes]"
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
@ -562,7 +688,10 @@ worldedit.register_gui_handler("worldedit_gui_highlight", function(name, fields)
|
|||||||
gui_nodename1[name] = tostring(fields.worldedit_gui_highlight_node)
|
gui_nodename1[name] = tostring(fields.worldedit_gui_highlight_node)
|
||||||
worldedit.show_page(name, "worldedit_gui_highlight")
|
worldedit.show_page(name, "worldedit_gui_highlight")
|
||||||
if fields.worldedit_gui_highlight_submit then
|
if fields.worldedit_gui_highlight_submit then
|
||||||
minetest.chatcommands["/highlight"].func(name, gui_nodename1[name])
|
local n = worldedit.normalize_nodename(gui_nodename1[name])
|
||||||
|
if n then
|
||||||
|
minetest.chatcommands["/highlight"].func(name, n)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
@ -570,14 +699,16 @@ worldedit.register_gui_handler("worldedit_gui_highlight", function(name, fields)
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
worldedit.register_gui_function("worldedit_gui_restore", {
|
worldedit.register_gui_function("worldedit_gui_restore", {
|
||||||
name = "Restore Region", privs = minetest.chatcommands["/restore"].privs,
|
name = "Restore Region",
|
||||||
|
privs = we_privs("restore"),
|
||||||
on_select = function(name)
|
on_select = function(name)
|
||||||
minetest.chatcommands["/restore"].func(name, "")
|
minetest.chatcommands["/restore"].func(name, "")
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
worldedit.register_gui_function("worldedit_gui_save_load", {
|
worldedit.register_gui_function("worldedit_gui_save_load", {
|
||||||
name = "Save/Load", privs = combine_privs(minetest.chatcommands["/save"].privs, minetest.chatcommands["/allocate"].privs, minetest.chatcommands["/load"].privs),
|
name = "Save/Load",
|
||||||
|
privs = combine_we_privs({"save", "allocate", "load"}),
|
||||||
get_formspec = function(name)
|
get_formspec = function(name)
|
||||||
local filename = gui_filename[name]
|
local filename = gui_filename[name]
|
||||||
return "size[6,4]" .. worldedit.get_formspec_header("worldedit_gui_save_load") ..
|
return "size[6,4]" .. worldedit.get_formspec_header("worldedit_gui_save_load") ..
|
||||||
@ -588,9 +719,9 @@ worldedit.register_gui_function("worldedit_gui_save_load", {
|
|||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
worldedit.register_gui_handler("worldedit_gui_save", function(name, fields)
|
worldedit.register_gui_handler("worldedit_gui_save_load", function(name, fields)
|
||||||
if fields.worldedit_gui_save_load_submit_save or worldedit_gui_save_load_submit_allocate or worldedit_gui_save_load_submit_load then
|
if fields.worldedit_gui_save_load_submit_save or fields.worldedit_gui_save_load_submit_allocate or fields.worldedit_gui_save_load_submit_load then
|
||||||
gui_filename[name] = tostring(fields.worldedit_gui_save_axis)
|
gui_filename[name] = tostring(fields.worldedit_gui_save_filename)
|
||||||
worldedit.show_page(name, "worldedit_gui_save_load")
|
worldedit.show_page(name, "worldedit_gui_save_load")
|
||||||
if fields.worldedit_gui_save_load_submit_save then
|
if fields.worldedit_gui_save_load_submit_save then
|
||||||
minetest.chatcommands["/save"].func(name, gui_filename[name])
|
minetest.chatcommands["/save"].func(name, gui_filename[name])
|
||||||
@ -604,25 +735,46 @@ worldedit.register_gui_handler("worldedit_gui_save", function(name, fields)
|
|||||||
return false
|
return false
|
||||||
end)
|
end)
|
||||||
|
|
||||||
worldedit.register_gui_function("worldedit_gui_lua", {
|
worldedit.register_gui_function("worldedit_gui_cube", {
|
||||||
name = "Run Lua",
|
name = "Cuboid", -- technically the command is misnamed, I know...
|
||||||
|
privs = combine_we_privs({"hollowcube", "cube"}),
|
||||||
get_formspec = function(name)
|
get_formspec = function(name)
|
||||||
local code = gui_code[name]
|
local width, height, length = gui_distance1[name], gui_distance2[name], gui_distance3[name]
|
||||||
return "size[8,6.5]" .. worldedit.get_formspec_header("worldedit_gui_lua") ..
|
local node = gui_nodename1[name]
|
||||||
string.format("textarea[0.5,1;7.5,5.5;worldedit_gui_lua_code;Lua Code;%s]", minetest.formspec_escape(code)) ..
|
local nodename = worldedit.normalize_nodename(node)
|
||||||
"button_exit[0,6;3,0.8;worldedit_gui_lua_run;Run Lua]" ..
|
return "size[6.5,4]" .. worldedit.get_formspec_header("worldedit_gui_cube") ..
|
||||||
"button_exit[5,6;3,0.8;worldedit_gui_lua_transform;Lua Transform]"
|
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]"
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
worldedit.register_gui_handler("worldedit_gui_lua", function(name, fields)
|
worldedit.register_gui_handler("worldedit_gui_cube", function(name, fields)
|
||||||
if fields.worldedit_gui_lua_run or fields.worldedit_gui_lua_transform then
|
if fields.worldedit_gui_cube_search
|
||||||
gui_code[name] = fields.worldedit_gui_lua_value
|
or fields.worldedit_gui_cube_submit_hollow or fields.worldedit_gui_cube_submit_solid then
|
||||||
worldedit.show_page(name, "worldedit_gui_lua")
|
gui_nodename1[name] = tostring(fields.worldedit_gui_cube_node)
|
||||||
if fields.worldedit_gui_lua_run then
|
gui_distance1[name] = tostring(fields.worldedit_gui_cube_width)
|
||||||
minetest.chatcommands["/lua"].func(name, gui_code[name])
|
gui_distance2[name] = tostring(fields.worldedit_gui_cube_height)
|
||||||
else --fields.worldedit_gui_lua_transform
|
gui_distance3[name] = tostring(fields.worldedit_gui_cube_length)
|
||||||
minetest.chatcommands["/luatransform"].func(name, gui_code[name])
|
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
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
@ -630,28 +782,9 @@ worldedit.register_gui_handler("worldedit_gui_lua", function(name, fields)
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
worldedit.register_gui_function("worldedit_gui_clearobjects", {
|
worldedit.register_gui_function("worldedit_gui_clearobjects", {
|
||||||
name = "Clear Objects", privs = minetest.chatcommands["/clearobjects"].privs,
|
name = "Clear Objects",
|
||||||
|
privs = we_privs("clearobjects"),
|
||||||
on_select = function(name)
|
on_select = function(name)
|
||||||
minetest.chatcommands["/clearobjects"].func(name, "")
|
minetest.chatcommands["/clearobjects"].func(name, "")
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
worldedit.register_gui_function("worldedit_gui_formspec_tester", {
|
|
||||||
name = "Formspec Tester",
|
|
||||||
get_formspec = function(name)
|
|
||||||
local value = gui_formspec[name]
|
|
||||||
return "size[8,6.5]" .. worldedit.get_formspec_header("worldedit_gui_formspec_tester") ..
|
|
||||||
string.format("textarea[0.5,1;7.5,5.5;worldedit_gui_formspec_tester_value;Formspec Code;%s]", minetest.formspec_escape(value)) ..
|
|
||||||
"button_exit[0,6;3,0.8;worldedit_gui_formspec_tester_show;Show Formspec]"
|
|
||||||
end,
|
|
||||||
})
|
|
||||||
|
|
||||||
worldedit.register_gui_handler("worldedit_gui_formspec_tester", function(name, fields)
|
|
||||||
if fields.worldedit_gui_formspec_tester_show then
|
|
||||||
gui_formspec[name] = fields.worldedit_gui_formspec_tester_value or ""
|
|
||||||
worldedit.show_page(name, "worldedit_gui_formspec_tester")
|
|
||||||
minetest.show_formspec(name, "worldedit:formspec_tester", gui_formspec[name])
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end)
|
|
||||||
|
@ -14,7 +14,7 @@ Use `nil` for the `options` parameter to unregister the function associated with
|
|||||||
|
|
||||||
Use `nil` for the `get_formspec` field to denote that the function does not have its own screen.
|
Use `nil` for the `get_formspec` field to denote that the function does not have its own screen.
|
||||||
|
|
||||||
Use `nil` for the `privs` field to denote that no special privileges are required to use the function.
|
The `privs` field may not be `nil`.
|
||||||
|
|
||||||
If the identifier is already registered to another function, it will be replaced by the new one.
|
If the identifier is already registered to another function, it will be replaced by the new one.
|
||||||
|
|
||||||
@ -24,6 +24,9 @@ The `on_select` function must not call `worldedit.show_page`
|
|||||||
worldedit.pages = {} --mapping of identifiers to options
|
worldedit.pages = {} --mapping of identifiers to options
|
||||||
local identifiers = {} --ordered list of identifiers
|
local identifiers = {} --ordered list of identifiers
|
||||||
worldedit.register_gui_function = function(identifier, options)
|
worldedit.register_gui_function = function(identifier, options)
|
||||||
|
if options.privs == nil or next(options.privs) == nil then
|
||||||
|
error("privs unset")
|
||||||
|
end
|
||||||
worldedit.pages[identifier] = options
|
worldedit.pages[identifier] = options
|
||||||
table.insert(identifiers, identifier)
|
table.insert(identifiers, identifier)
|
||||||
end
|
end
|
||||||
@ -46,7 +49,7 @@ worldedit.register_gui_handler = function(identifier, handler)
|
|||||||
|
|
||||||
--ensure the player has permission to perform the action
|
--ensure the player has permission to perform the action
|
||||||
local entry = worldedit.pages[identifier]
|
local entry = worldedit.pages[identifier]
|
||||||
if entry and minetest.check_player_privs(name, entry.privs or {}) then
|
if entry and minetest.check_player_privs(name, entry.privs) then
|
||||||
return handler(name, fields)
|
return handler(name, fields)
|
||||||
end
|
end
|
||||||
return false
|
return false
|
||||||
@ -67,7 +70,7 @@ local get_formspec = function(name, identifier)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--implement worldedit.show_page(name, page) in different ways depending on the available APIs
|
--implement worldedit.show_page(name, page) in different ways depending on the available APIs
|
||||||
if unified_inventory then --unified inventory installed
|
if rawget(_G, "unified_inventory") then --unified inventory installed
|
||||||
local old_func = worldedit.register_gui_function
|
local old_func = worldedit.register_gui_function
|
||||||
worldedit.register_gui_function = function(identifier, options)
|
worldedit.register_gui_function = function(identifier, options)
|
||||||
old_func(identifier, options)
|
old_func(identifier, options)
|
||||||
@ -100,9 +103,12 @@ if unified_inventory then --unified inventory installed
|
|||||||
player:set_inventory_formspec(get_formspec(name, page))
|
player:set_inventory_formspec(get_formspec(name, page))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
elseif inventory_plus then --inventory++ installed
|
elseif rawget(_G, "inventory_plus") then --inventory++ installed
|
||||||
minetest.register_on_joinplayer(function(player)
|
minetest.register_on_joinplayer(function(player)
|
||||||
|
local can_worldedit = minetest.check_player_privs(player:get_player_name(), {worldedit=true})
|
||||||
|
if can_worldedit then
|
||||||
inventory_plus.register_button(player, "worldedit_gui", "WorldEdit")
|
inventory_plus.register_button(player, "worldedit_gui", "WorldEdit")
|
||||||
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
--show the form when the button is pressed and hide it when done
|
--show the form when the button is pressed and hide it when done
|
||||||
@ -115,7 +121,7 @@ elseif inventory_plus then --inventory++ installed
|
|||||||
return true
|
return true
|
||||||
elseif fields.worldedit_gui_exit then --return to original page
|
elseif fields.worldedit_gui_exit then --return to original page
|
||||||
if gui_player_formspecs[name] then
|
if gui_player_formspecs[name] then
|
||||||
inventory_plus.set_inventory_formspec(player, gui_player_formspecs[name])
|
inventory_plus.set_inventory_formspec(player, inventory_plus.get_formspec(player, "main"))
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
@ -128,60 +134,35 @@ elseif inventory_plus then --inventory++ installed
|
|||||||
inventory_plus.set_inventory_formspec(player, get_formspec(name, page))
|
inventory_plus.set_inventory_formspec(player, get_formspec(name, page))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
else --fallback button
|
elseif rawget(_G, "sfinv") then --sfinv installed (part of minetest_game since 0.4.15)
|
||||||
local player_formspecs = {}
|
assert(sfinv.enabled)
|
||||||
|
local orig_get = sfinv.pages["sfinv:crafting"].get
|
||||||
|
sfinv.override_page("sfinv:crafting", {
|
||||||
|
get = function(self, player, context)
|
||||||
|
local can_worldedit = minetest.check_player_privs(player, {worldedit=true})
|
||||||
|
local fs = orig_get(self, player, context)
|
||||||
|
return fs .. (can_worldedit and "image_button[0,0;1,1;inventory_plus_worldedit_gui.png;worldedit_gui;]" or "")
|
||||||
|
end
|
||||||
|
})
|
||||||
|
|
||||||
local update_main_formspec = function(name)
|
--compatibility with pre-0.4.16 sfinv
|
||||||
local formspec = player_formspecs[name]
|
local set_page = sfinv.set_page or function(player, name)
|
||||||
if not formspec then
|
--assumptions: src pg has no leave callback, dst pg has no enter callback
|
||||||
return
|
local ctx = {page=name}
|
||||||
end
|
sfinv.contexts[player:get_player_name()] = ctx
|
||||||
local player = minetest.get_player_by_name(name)
|
sfinv.set_player_inventory_formspec(player, ctx)
|
||||||
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_inventory then --creative_inventory is active, add button to modified formspec
|
|
||||||
formspec = player:get_inventory_formspec() .. "image_button[6,0;1,1;inventory_plus_worldedit_gui.png;worldedit_gui;]"
|
|
||||||
else
|
|
||||||
formspec = formspec .. "image_button[0,0;1,1;inventory_plus_worldedit_gui.png;worldedit_gui;]"
|
|
||||||
end
|
|
||||||
player:set_inventory_formspec(formspec)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
minetest.register_on_joinplayer(function(player)
|
--show the form when the button is pressed and hide it when done
|
||||||
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)
|
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||||
local name = player:get_player_name()
|
|
||||||
if fields.worldedit_gui then --main page
|
if fields.worldedit_gui then --main page
|
||||||
gui_player_formspecs[name] = player:get_inventory_formspec()
|
worldedit.show_page(player:get_player_name(), "worldedit_gui")
|
||||||
worldedit.show_page(name, "worldedit_gui")
|
|
||||||
return true
|
return true
|
||||||
elseif fields.worldedit_gui_exit then --return to original page
|
elseif fields.worldedit_gui_exit then --return to original page
|
||||||
if gui_player_formspecs[name] then
|
set_page(player, "sfinv:crafting")
|
||||||
player:set_inventory_formspec(gui_player_formspecs[name])
|
|
||||||
end
|
|
||||||
return true
|
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
|
||||||
|
return false
|
||||||
end)
|
end)
|
||||||
|
|
||||||
worldedit.show_page = function(name, page)
|
worldedit.show_page = function(name, page)
|
||||||
@ -190,10 +171,19 @@ else --fallback button
|
|||||||
player:set_inventory_formspec(get_formspec(name, page))
|
player:set_inventory_formspec(get_formspec(name, page))
|
||||||
end
|
end
|
||||||
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"
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
worldedit.register_gui_function("worldedit_gui", {
|
worldedit.register_gui_function("worldedit_gui", {
|
||||||
name = "WorldEdit GUI",
|
name = "WorldEdit GUI",
|
||||||
|
privs = {interact=true},
|
||||||
get_formspec = function(name)
|
get_formspec = function(name)
|
||||||
--create a form with all the buttons arranged in a grid
|
--create a form with all the buttons arranged in a grid
|
||||||
local buttons, x, y, index = {}, 0, 1, 0
|
local buttons, x, y, index = {}, 0, 1, 0
|
||||||
@ -226,7 +216,7 @@ worldedit.register_gui_handler("worldedit_gui", function(name, fields)
|
|||||||
for identifier, entry in pairs(worldedit.pages) do --check for WorldEdit GUI main formspec button selection
|
for identifier, entry in pairs(worldedit.pages) do --check for WorldEdit GUI main formspec button selection
|
||||||
if fields[identifier] and identifier ~= "worldedit_gui" then
|
if fields[identifier] and identifier ~= "worldedit_gui" then
|
||||||
--ensure player has permission to perform action
|
--ensure player has permission to perform action
|
||||||
local has_privs, missing_privs = minetest.check_player_privs(name, entry.privs or {})
|
local has_privs, missing_privs = minetest.check_player_privs(name, entry.privs)
|
||||||
if not has_privs then
|
if not has_privs then
|
||||||
worldedit.player_notify(name, "you are not allowed to use this function (missing privileges: " .. table.concat(missing_privs, ", ") .. ")")
|
worldedit.player_notify(name, "you are not allowed to use this function (missing privileges: " .. table.concat(missing_privs, ", ") .. ")")
|
||||||
return false
|
return false
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 21 KiB |
BIN
worldedit_gui/textures/worldedit_gui_unknown.png
Normal file
BIN
worldedit_gui/textures/worldedit_gui_unknown.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 597 B |
@ -1,103 +0,0 @@
|
|||||||
worldedit = 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 +0,0 @@
|
|||||||
worldedit
|
|
@ -1,120 +0,0 @@
|
|||||||
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
|
|
@ -25,12 +25,14 @@ worldedit.alias_chatcommand("/v", "/volume")
|
|||||||
worldedit.alias_chatcommand("/s", "/set")
|
worldedit.alias_chatcommand("/s", "/set")
|
||||||
worldedit.alias_chatcommand("/r", "/replace")
|
worldedit.alias_chatcommand("/r", "/replace")
|
||||||
worldedit.alias_chatcommand("/ri", "/replaceinverse")
|
worldedit.alias_chatcommand("/ri", "/replaceinverse")
|
||||||
|
worldedit.alias_chatcommand("/hcube", "/hollowcube")
|
||||||
worldedit.alias_chatcommand("/hspr", "/hollowsphere")
|
worldedit.alias_chatcommand("/hspr", "/hollowsphere")
|
||||||
worldedit.alias_chatcommand("/spr", "/sphere")
|
worldedit.alias_chatcommand("/spr", "/sphere")
|
||||||
worldedit.alias_chatcommand("/hdo", "/hollowdome")
|
worldedit.alias_chatcommand("/hdo", "/hollowdome")
|
||||||
worldedit.alias_chatcommand("/do", "/dome")
|
worldedit.alias_chatcommand("/do", "/dome")
|
||||||
worldedit.alias_chatcommand("/hcyl", "/hollowcylinder")
|
worldedit.alias_chatcommand("/hcyl", "/hollowcylinder")
|
||||||
worldedit.alias_chatcommand("/cyl", "/cylinder")
|
worldedit.alias_chatcommand("/cyl", "/cylinder")
|
||||||
|
worldedit.alias_chatcommand("/hpyr", "/hollowpyramid")
|
||||||
worldedit.alias_chatcommand("/pyr", "/pyramid")
|
worldedit.alias_chatcommand("/pyr", "/pyramid")
|
||||||
worldedit.alias_chatcommand("/spl", "/spiral")
|
worldedit.alias_chatcommand("/spl", "/spiral")
|
||||||
worldedit.alias_chatcommand("/m", "/move")
|
worldedit.alias_chatcommand("/m", "/move")
|
||||||
|
Reference in New Issue
Block a user