mirror of
https://github.com/Uberi/Minetest-WorldEdit.git
synced 2025-06-29 22:50:46 +02:00
Compare commits
37 Commits
Author | SHA1 | Date | |
---|---|---|---|
03327a767d | |||
8bd5db51b2 | |||
416ffb3709 | |||
040282bbe6 | |||
b0bf52e9b6 | |||
3c51ec8c4a | |||
49b683f27f | |||
c1f3cfc1e4 | |||
b252df2166 | |||
7e1be63344 | |||
faa4a7b065 | |||
8b9054a1cc | |||
dfcf02bbc2 | |||
0fddd17f23 | |||
e550604747 | |||
8ebf9d3c2a | |||
ac5e801834 | |||
b6bc841c39 | |||
48009b6c62 | |||
9db6192eba | |||
1e5f623cbb | |||
58970e7fab | |||
7070f81c59 | |||
a192d51a58 | |||
d4187866db | |||
74018dab99 | |||
f1cfc47189 | |||
0664cde287 | |||
f952ee4740 | |||
a1dcc43210 | |||
d7ae19b7b8 | |||
52c1379bce | |||
d52f3d649e | |||
cedecac3f8 | |||
18bc4e6815 | |||
9e1c2614d3 | |||
98c5bc5c5f |
172
Chat Commands.md
172
Chat Commands.md
@ -2,6 +2,21 @@ Chat Commands
|
||||
-------------
|
||||
For more information, see the [README](README.md).
|
||||
|
||||
### //inspect
|
||||
|
||||
Enable or disable node inspection.
|
||||
|
||||
//inspect on
|
||||
//inspect off
|
||||
//inspect 1
|
||||
//inspect 0
|
||||
//inspect true
|
||||
//inspect false
|
||||
//inspect yes
|
||||
//inspect no
|
||||
//inspect enable
|
||||
//inspect disable
|
||||
|
||||
### //reset
|
||||
|
||||
Reset the region so that it is empty.
|
||||
@ -14,6 +29,12 @@ Show markers at the region positions.
|
||||
|
||||
//mark
|
||||
|
||||
### //unmark
|
||||
|
||||
Hide markers if currently shown.
|
||||
|
||||
//unmark
|
||||
|
||||
### //pos1
|
||||
|
||||
Set WorldEdit region position 1 to the player's location.
|
||||
@ -35,6 +56,14 @@ Set WorldEdit region, WorldEdit position 1, or WorldEdit position 2 by punching
|
||||
//p set2
|
||||
//p get
|
||||
|
||||
### //fixedpos set1 x y z
|
||||
|
||||
Set a WorldEdit region position to the position at (<x>, <y>, <z>).
|
||||
|
||||
//fixedpos set1 0, 0, 0
|
||||
//fixedpos set1 -30, 5, 28
|
||||
//fixedpos set2 1004, -200, 432
|
||||
|
||||
### //volume
|
||||
|
||||
Display the volume of the current WorldEdit region.
|
||||
@ -45,93 +74,95 @@ Display the volume of the current WorldEdit region.
|
||||
|
||||
Set the current WorldEdit region to <node>.
|
||||
|
||||
//set dirt
|
||||
//set default:glass
|
||||
//set mesecons:mesecon
|
||||
//set air
|
||||
//set cactus
|
||||
//set Bronze Block
|
||||
//set mesecons:wire_00000000_off
|
||||
|
||||
### //replace <search node> <replace node>
|
||||
|
||||
Replace all instances of <search node> with <replace node> in the current WorldEdit region.
|
||||
|
||||
//replace cobble stone
|
||||
//replace default:steelblock glass
|
||||
//replace dirt flowers:flower_waterlily
|
||||
//replace flowers:flower_rose flowers:flower_tulip
|
||||
//replace Cobblestone air
|
||||
//replace lightstone_blue glass
|
||||
//replace dirt Bronze Block
|
||||
//replace mesecons:wire_00000000_off flowers:flower_tulip
|
||||
|
||||
### //replaceinverse <search node> <replace node>
|
||||
|
||||
Replace all nodes other than <search node> with <replace node> in the current WorldEdit region.
|
||||
|
||||
//replaceinverse air stone
|
||||
//replaceinverse water_source default:dirt
|
||||
//replaceinverse mesecons:mesecon air
|
||||
//replaceinverse default:steelblock default:glass
|
||||
//replaceinverse Cobblestone air
|
||||
//replaceinverse flowers:flower_waterlily glass
|
||||
//replaceinverse dirt Bronze Block
|
||||
//replaceinverse mesecons:wire_00000000_off flowers:flower_tulip
|
||||
|
||||
### //hollowsphere <radius> <node>
|
||||
|
||||
Add hollow sphere at WorldEdit position 1 with radius <radius>, composed of <node>.
|
||||
Add hollow sphere centered at WorldEdit position 1 with radius <radius>, composed of <node>.
|
||||
|
||||
//hollowsphere 5 dirt
|
||||
//hollowsphere 12 default:glass
|
||||
//hollowsphere 17 mesecons:mesecon
|
||||
//hollowsphere 5 Diamond Block
|
||||
//hollowsphere 12 glass
|
||||
//hollowsphere 17 mesecons:wire_00000000_off
|
||||
|
||||
### //sphere <radius> <node>
|
||||
|
||||
Add sphere at WorldEdit position 1 with radius <radius>, composed of <node>.
|
||||
Add sphere centered at WorldEdit position 1 with radius <radius>, composed of <node>.
|
||||
|
||||
//sphere 5 dirt
|
||||
//sphere 12 default:glass
|
||||
//sphere 17 mesecons:mesecon
|
||||
//sphere 5 Diamond Block
|
||||
//sphere 12 glass
|
||||
//sphere 17 mesecons:wire_00000000_off
|
||||
|
||||
### //hollowdome <radius> <node>
|
||||
|
||||
Add hollow dome at WorldEdit position 1 with radius <radius>, composed of <node>.
|
||||
Add hollow dome centered at WorldEdit position 1 with radius <radius>, composed of <node>.
|
||||
|
||||
//hollowdome 5 dirt
|
||||
//hollowdome 12 default:glass
|
||||
//hollowdome 17 mesecons:mesecon
|
||||
//hollowdome 5 Diamond Block
|
||||
//hollowdome -12 glass
|
||||
//hollowdome 17 mesecons:wire_00000000_off
|
||||
|
||||
### //dome <radius> <node>
|
||||
|
||||
Add dome at WorldEdit position 1 with radius <radius>, composed of <node>.
|
||||
Add dome centered at WorldEdit position 1 with radius <radius>, composed of <node>.
|
||||
|
||||
//dome 5 dirt
|
||||
//dome 12 default:glass
|
||||
//dome 17 mesecons:mesecon
|
||||
//dome 5 Diamond Block
|
||||
//dome -12 glass
|
||||
//dome 17 mesecons:wire_00000000_off
|
||||
|
||||
### //hollowcylinder x/y/z/? <length> <radius> <node>
|
||||
|
||||
Add hollow cylinder at WorldEdit position 1 along the x/y/z/? axis with length <length> and radius <radius>, composed of <node>.
|
||||
|
||||
//hollowcylinder x +5 8 dirt
|
||||
//hollowcylinder y 28 10 default:glass
|
||||
//hollowcylinder z -12 3 mesecons:mesecon
|
||||
//hollowcylinder ? 2 4 stone
|
||||
//hollowcylinder x +5 8 Bronze Block
|
||||
//hollowcylinder y 28 10 glass
|
||||
//hollowcylinder z -12 3 mesecons:wire_00000000_off
|
||||
//hollowcylinder ? 2 4 default:stone
|
||||
|
||||
### //cylinder x/y/z/? <length> <radius> <node>
|
||||
|
||||
Add cylinder at WorldEdit position 1 along the x/y/z/? axis with length <length> and radius <radius>, composed of <node>.
|
||||
|
||||
//cylinder x +5 8 dirt
|
||||
//cylinder y 28 10 default:glass
|
||||
//cylinder z -12 3 mesecons:mesecon
|
||||
//cylinder ? 2 4 stone
|
||||
//cylinder x +5 8 Bronze Block
|
||||
//cylinder y 28 10 glass
|
||||
//cylinder z -12 3 mesecons:wire_00000000_off
|
||||
//cylinder ? 2 4 default:stone
|
||||
|
||||
### //pyramid <height> <node>
|
||||
### //pyramid x/y/z? <height> <node>
|
||||
|
||||
Add pyramid at WorldEdit position 1 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>.
|
||||
|
||||
//pyramid 8 dirt
|
||||
//pyramid 5 default:glass
|
||||
//pyramid 2 stone
|
||||
//pyramid x 8 Diamond Block
|
||||
//pyramid y -5 glass
|
||||
//pyramid z 2 mesecons:wire_00000000_off
|
||||
//pyramid ? 12 mesecons:wire_00000000_off
|
||||
|
||||
### //spiral <width> <height> <spacer> <node>
|
||||
### //spiral <length> <height> <spacer> <node>
|
||||
|
||||
Add spiral at WorldEdit position 1 with width <width>, height <height>, space between walls <spacer>, composed of <node>.
|
||||
Add spiral centered at WorldEdit position 1 with side length <length>, height <height>, space between walls <spacer>, composed of <node>.
|
||||
|
||||
//spiral 20 5 3 dirt
|
||||
//spiral 5 2 1 default:glass
|
||||
//spiral 7 1 5 stone
|
||||
//spiral 20 5 3 Diamond Block
|
||||
//spiral 5 2 1 glass
|
||||
//spiral 7 1 5 mesecons:wire_00000000_off
|
||||
|
||||
### //copy x/y/z/? <amount>
|
||||
|
||||
@ -160,6 +191,14 @@ Stack the current WorldEdit region along the x/y/z/? axis <count> times.
|
||||
//stack z +5
|
||||
//stack ? 12
|
||||
|
||||
### //scale <factor>
|
||||
|
||||
Scale the current WorldEdit positions and region by a factor of positive integer <factor> with position 1 as the origin.
|
||||
|
||||
//scale 2
|
||||
//scale 1
|
||||
//scale 10
|
||||
|
||||
### //transpose x/y/z/? x/y/z/?
|
||||
|
||||
Transpose the current WorldEdit positions and region along the x/y/z/? and x/y/z/? axes.
|
||||
@ -212,17 +251,17 @@ Hide all nodes in the current WorldEdit region non-destructively.
|
||||
|
||||
Suppress all <node> in the current WorldEdit region non-destructively.
|
||||
|
||||
//suppress dirt
|
||||
//suppress default:glass
|
||||
//suppress mesecons:mesecon
|
||||
//suppress Diamond Block
|
||||
//suppress glass
|
||||
//suppress mesecons:wire_00000000_off
|
||||
|
||||
### //highlight <node>
|
||||
|
||||
Highlight <node> in the current WorldEdit region by hiding everything else non-destructively.
|
||||
|
||||
//highlight dirt
|
||||
//highlight default:glass
|
||||
//highlight mesecons:mesecon
|
||||
//highlight Diamond Block
|
||||
//highlight glass
|
||||
//highlight mesecons:wire_00000000_off
|
||||
|
||||
### //restore
|
||||
|
||||
@ -262,5 +301,32 @@ Executes <code> as a Lua chunk in the global namespace.
|
||||
|
||||
Executes <code> as a Lua chunk in the global namespace with the variable pos available, for each node in the current WorldEdit region.
|
||||
|
||||
//luatransform minetest.env:add_node(pos, {name="default:stone"})
|
||||
//luatransform if minetest.env:get_node(pos).name == "air" then minetest.env:add_node(pos, {name="default:water_source"})
|
||||
//luatransform minetest.add_node(pos, {name="default:stone"})
|
||||
//luatransform if minetest.get_node(pos).name == "air" then minetest.add_node(pos, {name="default:water_source"})
|
||||
|
||||
### //mtschemcreate <file>
|
||||
|
||||
Save the current WorldEdit region using the Minetest Schematic format to "(world folder)/schems/<file>.mts".
|
||||
|
||||
//mtschemcreate some random filename
|
||||
//mtschemcreate huge_base
|
||||
|
||||
### //mtschemplace <file>
|
||||
|
||||
Load nodes from "(world folder)/schems/<file>.mts" with position 1 of the current WorldEdit region as the origin.
|
||||
|
||||
//mtschemplace some random filename
|
||||
//mtschemplace huge_base
|
||||
|
||||
### //mtschemprob start/finish/get
|
||||
|
||||
After using //mtschemprob start all nodes punched will bring up a text field where a probablity can be entered.
|
||||
This mode can be left with //mtschemprob finish. //mtschemprob get will display the probabilities saved for the nodes.
|
||||
|
||||
//mtschemprob get
|
||||
|
||||
### //clearobjects
|
||||
|
||||
Clears all objects within the WorldEdit region.
|
||||
|
||||
//clearobjects
|
||||
|
81
README.md
81
README.md
@ -1,8 +1,10 @@
|
||||
WorldEdit v0.6 for MineTest 0.4
|
||||
===============================
|
||||
In-game world editing for [MineTest](http://minetest.net/)! Tons of chat commands to help with building, fixing, and more.
|
||||
WorldEdit v1.0 for MineTest 0.4.8+
|
||||
==================================
|
||||
The ultimate in-game world editing tool for [Minetest](http://minetest.net/)! Tons of functionality to help with building, fixing, and more.
|
||||
|
||||
For more information, see the [forum topic](http://minetest.net/forum/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.
|
||||
|
||||
# New users should see the [tutorial](Tutorial.md).
|
||||
|
||||
Usage
|
||||
-----
|
||||
@ -12,6 +14,30 @@ WorldEdit has a huge potential for abuse by untrusted players. Therefore, users
|
||||
|
||||
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.
|
||||
|
||||
Chat Commands
|
||||
-------------
|
||||
WorldEdit is accessed in-game through an interface. By default, the mod distribution includes a chat interface for this purpose. It is documented in the [Chat Commands Reference](Chat Commands.md).
|
||||
|
||||
If visual manipulation of nodes is desired, the [WorldEdit GUI](https://forum.minetest.net/viewtopic.php?id=3112) mod provides a simple interface with buttons and text entry fields for this purpose.
|
||||
|
||||
Compatibility
|
||||
-------------
|
||||
This mod supports Minetest versions 0.4.8 and newer. Older versions of WorldEdit may work with older versions of Minetest, but are not recommended.
|
||||
|
||||
WorldEdit works quite well with other mods, and does not have any known mod conflicts.
|
||||
|
||||
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.
|
||||
|
||||
If you don't add WorldEdit to your "depends.txt" file, each file in the WorldEdit mod is also independent. For example, one may import the WorldEdit primitives API using the following code:
|
||||
|
||||
dofile(minetest.get_modpath("worldedit").."/primitives.lua")
|
||||
|
||||
AGPLv3 compatible mods may further include WorldEdit files in their own mods. This may be useful if a modder wishes to completely avoid any dependencies on WorldEdit. Note that it is required to give credit to the authors.
|
||||
|
||||
This API is documented in the [WorldEdit API Reference](WorldEdit API.md).
|
||||
|
||||
Axes
|
||||
----
|
||||
The coordinate system is the same as that used by MineTest; Y is upwards, X is perpendicular, and Z is parallel.
|
||||
@ -20,9 +46,21 @@ When an axis is specified in a WorldEdit command, it is specified as one of the
|
||||
|
||||
The value ? represents the axis the player is currently facing. If the player is facing more than one axis, the axis the player face direction is closest to will be used.
|
||||
|
||||
Nodes
|
||||
-----
|
||||
Node names are required for many types of commands that identify or modify specific types of nodes. They can be specified in a number of ways.
|
||||
|
||||
First, by description - the tooltip that appears when hovering over the item in an inventory. This is case insensitive and includes values such as "Cobblestone" and "bronze block". Note that certain commands (namely, `//replace` and `//replaceinverse`) do not support descriptions that contain spaces in the `<searchnode>` field.
|
||||
|
||||
Second, by name - the node name that is defined by code, but without the mod name prefix. This is case sensitive and includes values such as "piston_normal_off" and "cactus". Nodes defined in the `default` mod always take precedence over other nodes when searching for the correct one, and if there are multiple possible nodes (such as "a:celery" and "b:celery"), one is chosen in no particular order.
|
||||
|
||||
Finally, by full name - the unambiguous identifier of the node, prefixes and all. This is case sensitive and includes values such as "default:stone" and "mesecons:wire_00000000_off".
|
||||
|
||||
The node name "air" can be used anywhere a normal node name can, and acts as a blank node. This is useful for clearing or removing nodes. For example, `//set air` would remove all the nodes in the current WorldEdit region. Similarly, `//sphere 10 air`, when WorldEdit position 1 underground, would dig a large sphere out of the ground.
|
||||
|
||||
Regions
|
||||
-------
|
||||
Most WorldEdit commands operate on regions. Regions are a set of two positions that define a 3D cube. They are local to each player and chat commands affect only the region for the player giving the commands.
|
||||
Most WorldEdit commands operate on regions. Regions are a set of two positions that define a 3D cuboid. They are local to each player and chat commands affect only the region for the player giving the commands.
|
||||
|
||||
Each positions together define two opposing corners of the cube. With two opposing corners it is possible to determine both the location and dimensions of the region.
|
||||
|
||||
@ -34,21 +72,36 @@ Entities are used to mark the location of the WorldEdit regions. They appear as
|
||||
|
||||
To remove the entities, simply punch them. This does not reset the positions themselves.
|
||||
|
||||
Chat Commands
|
||||
-------------
|
||||
WorldEdit is accessed in-game through an interface. By default, the mod distribution includes a chat interface for this purpose. It is documented in the [Chat Commands Reference](Chat Commands.md).
|
||||
Schematics
|
||||
----------
|
||||
WorldEdit supports two different types of schematics.
|
||||
|
||||
If visual manipulation of nodes is desired, the [WorldEdit GUI](http://minetest.net/forum/viewtopic.php?id=3112) mod provides a simple interface with buttons and text entry fields for this purpose.
|
||||
The first is the WorldEdit Schematic format, with the file extension ".we", and in some older versions, ".wem". There have been several previous versions of the WorldEdit Schematic format, but WorldEdit is capable of loading any past versions, and will always support them - there is no need to worry about schematics becoming obselete.
|
||||
|
||||
WorldEdit API
|
||||
-------------
|
||||
WorldEdit exposes all significant functionality in a simple 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.
|
||||
The current version of the WorldEdit Schematic format, internally known as version 4, is essentially an array of node data tables in Lua 5.2 table syntax. Specifically:
|
||||
|
||||
This API is documented in the [WorldEdit API Reference](WorldEdit API.md).
|
||||
return {
|
||||
{
|
||||
["y"] = <y-axis coordinate>,
|
||||
["x"] = <x-axis coordinate>,
|
||||
["name"] = <node name>,
|
||||
["z"] = <z-axis coordinate>,
|
||||
["meta"] = <metadata table>,
|
||||
["param2"] = <param2 value>,
|
||||
["param1"] = <y-axis coordinate>,
|
||||
},
|
||||
<...>
|
||||
}
|
||||
|
||||
Value ordering and minor aspects of the syntax, such as trailing commas or newlines, are not guaranteed.
|
||||
|
||||
The WorldEdit Schematic format is accessed via the WorldEdit API, or WorldEdit serialization chat commands such as `//serialize` and `//deserialize`.
|
||||
|
||||
The second is the Minetest Schematic format (MTS). The details of this format may be found in the Minetest documentation and are out of the scope of this document. Access to this format is done via specialized MTS commands such as `//mtschemcreate` and `//mtschemplace`.
|
||||
|
||||
License
|
||||
-------
|
||||
Copyright 2012 sfan5, Anthony Zhang (Temperest), and Brett O'Donnell (cornernote).
|
||||
Copyright 2013 sfan5, Anthony Zhang (Uberi/Temperest), and Brett O'Donnell (cornernote).
|
||||
|
||||
This mod is licensed under the [GNU Affero General Public License](http://www.gnu.org/licenses/agpl-3.0.html).
|
||||
|
||||
|
55
Tutorial.md
Normal file
55
Tutorial.md
Normal file
@ -0,0 +1,55 @@
|
||||
WorldEdit Tutorial
|
||||
==================
|
||||
This is a step-by-step tutorial outlining the basic usage of WorldEdit. For more information, see the [README](README.md).
|
||||
|
||||
Let's start with a few assumptions:
|
||||
|
||||
* You have a compatible version of Minetest working.
|
||||
* See the [README](README.md) for compatibility information.
|
||||
* You have WorldEdit installed as a mod.
|
||||
* If using Windows, [MODSTER](https://forum.minetest.net/viewtopic.php?pid=101463) makes installing mods totally painless.
|
||||
* Simply download the file, extract the archive, and move it to the correct mod folder for Minetest.
|
||||
* You are familiar with the basics of the game.
|
||||
* How to walk, jump, and climb.
|
||||
* How to dig, place, and punch blocks.
|
||||
* How to type into the chat and read text from it.
|
||||
|
||||
Overview
|
||||
--------
|
||||
WorldEdit has a "region", which is simply a cuboid area defined by two markers, both of which the player can move around. Every player can have their own region with their own two markers.
|
||||
|
||||
WorldEdit chat commands can work inside the region selected, or around the first marker.
|
||||
|
||||
Step 1: Selecting a region
|
||||
--------------------------
|
||||
In the chat prompt, enter `//p set`. In the chat, you are prompted to punch two nodes to set the positions of the two markers.
|
||||
|
||||
Punch a nearby node. Be careful of breakable ones such as torches. A black cube reading "1" will appear around the node. This is the marker for WorldEdit position 1.
|
||||
|
||||
Walk away from the node you just punched. Now, punch another node. A black cube reading "2" will appear around the node. This is the marker for WorldEdit position 2.
|
||||
|
||||
Step 2: Region commands
|
||||
-----------------------
|
||||
In the chat prompt, enter `//set mese`. In the chat, you will see a message showing the number of nodes set after a small delay.
|
||||
|
||||
Look at the place between the two markers: it is now filled with MESE blocks!
|
||||
|
||||
The `//set <node>` command fills the region with whatever node you want. It is a region-oriented command, which means it works inside the WorldEdit region only.
|
||||
|
||||
Now, try a few different variations, such as `//set torch`, `//set cobble`, and `//set water`.
|
||||
|
||||
Step 3: Position commands
|
||||
-------------------------
|
||||
In the chat prompt, enter `//hollowdome 30 glass`. In the chat, you will see a message showing the number of nodes set after a small delay.
|
||||
|
||||
Look around marker 1: it is now surrounded by a hollow glass dome!
|
||||
|
||||
The `//hollowdome <radius> <node>` command creates a hollow dome centered around marker 1, made of any node you want. It is a position-oriented command, which means it works around marker 1 and can go outside the WorldEdit region.
|
||||
|
||||
Step 4: Other commands
|
||||
----------------------
|
||||
There are many more commands than what is shown here. See the [Chat Commands Reference](Chat Commands.md) for a detailed list of them, along with descriptions and examples for every single one.
|
||||
|
||||
If you're in-game and forgot how a command works, just use the `/help <command name>` command, without the first forward slash. For example, to see some information about the `//set <node>` command mentioned earlier, simply use `/help /set`.
|
||||
|
||||
A very useful command to check out is the `//save <schematic>` command, which can save everything inside the WorldEdit region to a file, stored on the computer hosting the server (the player's computer, in single player mode). You can then later use `//load <schematic>` to load the data in a file into a world, even another world on another computer.
|
@ -46,11 +46,17 @@ Duplicates the region defined by positions `pos1` and `pos2` along the `axis` ax
|
||||
|
||||
Returns the number of nodes stacked.
|
||||
|
||||
### count, newpos1, newpos2 = worldedit.scale(pos1, pos2, factor)
|
||||
|
||||
Scales the region defined by positions `pos1` and `pos2` by an factor of positive integer `factor` with `pos1` as the origin.
|
||||
|
||||
Returns the number of nodes scaled, the new scaled position 1, and the new scaled position 2.
|
||||
|
||||
### count, newpos1, newpos2 = worldedit.transpose(pos1, pos2, axis1, axis2)
|
||||
|
||||
Transposes a region defined by the positions `pos1` and `pos2` between the `axis1` and `axis2` axes ("x" or "y" or "z").
|
||||
|
||||
Returns the number of nodes transposed, the new position 1, and the new position 2.
|
||||
Returns the number of nodes transposed, the new transposed position 1, and the new transposed position 2.
|
||||
|
||||
### count = worldedit.flip(pos1, pos2, axis)
|
||||
|
||||
@ -76,31 +82,37 @@ Fixes the lighting in a region defined by positions `pos1` and `pos2`.
|
||||
|
||||
Returns the number of nodes updated.
|
||||
|
||||
### count = worldedit.clearobjects(pos1, pos2)
|
||||
|
||||
Clears all objects in a region defined by the positions `pos1` and `pos2`.
|
||||
|
||||
Returns the number of objects cleared.
|
||||
|
||||
Primitives
|
||||
----------
|
||||
Contained in primitives.lua, this module allows the creation of several geometric primitives.
|
||||
|
||||
### count = worldedit.hollow_sphere(pos, radius, nodename)
|
||||
|
||||
Adds a hollow sphere at `pos` with radius `radius`, composed of `nodename`.
|
||||
Adds a hollow sphere centered at `pos` with radius `radius`, composed of `nodename`.
|
||||
|
||||
Returns the number of nodes added.
|
||||
|
||||
### count = worldedit.sphere(pos, radius, nodename)
|
||||
|
||||
Adds a sphere at `pos` with radius `radius`, composed of `nodename`.
|
||||
Adds a sphere centered at `pos` with radius `radius`, composed of `nodename`.
|
||||
|
||||
Returns the number of nodes added.
|
||||
|
||||
### count = worldedit.hollow_dome(pos, radius, nodename)
|
||||
|
||||
Adds a hollow dome at `pos` with radius `radius`, composed of `nodename`.
|
||||
Adds a hollow dome centered at `pos` with radius `radius`, composed of `nodename`.
|
||||
|
||||
Returns the number of nodes added.
|
||||
|
||||
### count = worldedit.dome(pos, radius, nodename)
|
||||
|
||||
Adds a dome at `pos` with radius `radius`, composed of `nodename`.
|
||||
Adds a dome centered at `pos` with radius `radius`, composed of `nodename`.
|
||||
|
||||
Returns the number of nodes added.
|
||||
|
||||
@ -116,15 +128,15 @@ Adds a cylinder at `pos` along the `axis` axis ("x" or "y" or "z") with length `
|
||||
|
||||
Returns the number of nodes added.
|
||||
|
||||
### count = worldedit.pyramid(pos, height, nodename)
|
||||
### count = worldedit.pyramid(pos, axis, height, nodename)
|
||||
|
||||
Adds a pyramid at `pos` with height `height`.
|
||||
Adds a pyramid centered at `pos` along the `axis` axis ("x" or "y" or "z") with height `height`.
|
||||
|
||||
Returns the number of nodes added.
|
||||
|
||||
### count = worldedit.spiral(pos, width, height, spacer, nodename)
|
||||
### count = worldedit.spiral(pos, length, height, spacer, nodename)
|
||||
|
||||
Adds a spiral at `pos` with width `width`, height `height`, space between walls `spacer`, composed of `nodename`.
|
||||
Adds a spiral centered at `pos` with side length `length`, height `height`, space between walls `spacer`, composed of `nodename`.
|
||||
|
||||
Returns the number of nodes added.
|
||||
|
||||
@ -202,6 +214,6 @@ Returns an error if the code fails or nil otherwise.
|
||||
|
||||
### error = worldedit.luatransform(pos1, pos2, code)
|
||||
|
||||
Executes `code` as a Lua chunk in the global namespace with the variable pos available, for each node in a region defined by positions `pos1` and `pos2`.
|
||||
Executes `code` as a Lua chunk in the global namespace with the variable `pos` available, for each node in a region defined by positions `pos1` and `pos2`.
|
||||
|
||||
Returns an error if the code fails or nil otherwise.
|
@ -1,4 +1,5 @@
|
||||
worldedit = worldedit or {}
|
||||
local minetest = minetest --local copy of global
|
||||
|
||||
--executes `code` as a Lua chunk in the global namespace, returning an error if the code fails or nil otherwise
|
||||
worldedit.lua = function(code)
|
||||
@ -23,6 +24,10 @@ worldedit.luatransform = function(pos1, pos2, code)
|
||||
end
|
||||
local operation = factory()
|
||||
|
||||
--make area stay loaded
|
||||
local manip = minetest.get_voxel_manip()
|
||||
manip:read_from_map(pos1, pos2)
|
||||
|
||||
local pos = {x=pos1.x, y=0, z=0}
|
||||
while pos.x <= pos2.x do
|
||||
pos.y = pos1.y
|
||||
|
@ -1,4 +1,5 @@
|
||||
worldedit = worldedit or {}
|
||||
local minetest = minetest --local copy of global
|
||||
|
||||
worldedit.allocate_old = worldedit.allocate
|
||||
worldedit.deserialize_old = worldedit.deserialize
|
||||
|
@ -1,9 +1,14 @@
|
||||
local path = minetest.get_modpath("worldedit")
|
||||
assert(minetest.get_voxel_manip, string.rep(">", 300) .. "HEY YOU! YES, YOU OVER THERE. THIS VERSION OF WORLDEDIT REQUIRES MINETEST 0.4.8 OR LATER! YOU HAVE AN OLD VERSION." .. string.rep("<", 300))
|
||||
|
||||
local path = minetest.get_modpath(minetest.get_current_modname())
|
||||
|
||||
local loadmodule = function(path)
|
||||
return pcall(function()
|
||||
dofile(path)
|
||||
end)
|
||||
local file = io.open(path)
|
||||
if not file then
|
||||
return
|
||||
end
|
||||
file:close()
|
||||
return dofile(path)
|
||||
end
|
||||
|
||||
loadmodule(path .. "/manipulations.lua")
|
||||
@ -12,4 +17,3 @@ loadmodule(path .. "/visualization.lua")
|
||||
loadmodule(path .. "/serialization.lua")
|
||||
loadmodule(path .. "/code.lua")
|
||||
loadmodule(path .. "/compatibility.lua")
|
||||
loadmodule(path .. "/queue.lua")
|
||||
|
@ -1,4 +1,5 @@
|
||||
worldedit = worldedit or {}
|
||||
local minetest = minetest --local copy of global
|
||||
|
||||
--modifies positions `pos1` and `pos2` so that each component of `pos1` is less than or equal to its corresponding conent of `pos2`, returning two new positions
|
||||
worldedit.sort_pos = function(pos1, pos2)
|
||||
@ -23,93 +24,154 @@ worldedit.volume = function(pos1, pos2)
|
||||
end
|
||||
|
||||
--sets a region defined by positions `pos1` and `pos2` to `nodename`, returning the number of nodes filled
|
||||
worldedit.set = function(pos1, pos2, nodename, env)
|
||||
worldedit.set = function(pos1, pos2, nodename)
|
||||
local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
|
||||
if env == nil then env = minetest.env end
|
||||
|
||||
local node = {name=nodename}
|
||||
local pos = {x=pos1.x, y=0, z=0}
|
||||
while pos.x <= pos2.x do
|
||||
pos.y = pos1.y
|
||||
while pos.y <= pos2.y do
|
||||
pos.z = pos1.z
|
||||
while pos.z <= pos2.z do
|
||||
env:add_node(pos, node)
|
||||
pos.z = pos.z + 1
|
||||
end
|
||||
pos.y = pos.y + 1
|
||||
end
|
||||
pos.x = pos.x + 1
|
||||
--set up voxel manipulator
|
||||
local manip = minetest.get_voxel_manip()
|
||||
local emerged_pos1, emerged_pos2 = manip:read_from_map(pos1, pos2)
|
||||
local area = VoxelArea:new({MinEdge=emerged_pos1, MaxEdge=emerged_pos2})
|
||||
|
||||
--fill emerged area with ignore
|
||||
local nodes = {}
|
||||
local ignore = minetest.get_content_id("ignore")
|
||||
for i = 1, worldedit.volume(emerged_pos1, emerged_pos2) do
|
||||
nodes[i] = ignore
|
||||
end
|
||||
|
||||
--fill selected area with node
|
||||
local node_id = minetest.get_content_id(nodename)
|
||||
for i in area:iterp(pos1, pos2) do
|
||||
nodes[i] = node_id
|
||||
end
|
||||
|
||||
--update map nodes
|
||||
manip:set_data(nodes)
|
||||
manip:write_to_map()
|
||||
manip:update_map()
|
||||
|
||||
return worldedit.volume(pos1, pos2)
|
||||
end
|
||||
|
||||
--replaces all instances of `searchnode` with `replacenode` in a region defined by positions `pos1` and `pos2`, returning the number of nodes replaced
|
||||
worldedit.replace = function(pos1, pos2, searchnode, replacenode, env)
|
||||
worldedit.replace = function(pos1, pos2, searchnode, replacenode)
|
||||
local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
|
||||
if env == nil then env = minetest.env end
|
||||
|
||||
if minetest.registered_nodes[searchnode] == nil then
|
||||
searchnode = "default:" .. searchnode
|
||||
end
|
||||
--set up voxel manipulator
|
||||
local manip = minetest.get_voxel_manip()
|
||||
local emerged_pos1, emerged_pos2 = manip:read_from_map(pos1, pos2)
|
||||
local area = VoxelArea:new({MinEdge=emerged_pos1, MaxEdge=emerged_pos2})
|
||||
|
||||
local pos = {x=pos1.x, y=0, z=0}
|
||||
local node = {name=replacenode}
|
||||
local nodes = manip:get_data()
|
||||
local searchnode_id = minetest.get_content_id(searchnode)
|
||||
local replacenode_id = minetest.get_content_id(replacenode)
|
||||
local count = 0
|
||||
while pos.x <= pos2.x do
|
||||
pos.y = pos1.y
|
||||
while pos.y <= pos2.y do
|
||||
pos.z = pos1.z
|
||||
while pos.z <= pos2.z do
|
||||
if env:get_node(pos).name == searchnode then
|
||||
env:add_node(pos, node)
|
||||
count = count + 1
|
||||
end
|
||||
pos.z = pos.z + 1
|
||||
end
|
||||
pos.y = pos.y + 1
|
||||
for i in area:iterp(pos1, pos2) do --replace searchnode with replacenode
|
||||
if nodes[i] == searchnode_id then
|
||||
nodes[i] = replacenode_id
|
||||
count = count + 1
|
||||
end
|
||||
pos.x = pos.x + 1
|
||||
end
|
||||
|
||||
--update map nodes
|
||||
manip:set_data(nodes)
|
||||
manip:write_to_map()
|
||||
manip:update_map()
|
||||
|
||||
return count
|
||||
end
|
||||
|
||||
--replaces all nodes other than `searchnode` with `replacenode` in a region defined by positions `pos1` and `pos2`, returning the number of nodes replaced
|
||||
worldedit.replaceinverse = function(pos1, pos2, searchnode, replacenode, env)
|
||||
worldedit.replaceinverse = function(pos1, pos2, searchnode, replacenode)
|
||||
local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
|
||||
if env == nil then env = minetest.env end
|
||||
|
||||
if minetest.registered_nodes[searchnode] == nil then
|
||||
searchnode = "default:" .. searchnode
|
||||
end
|
||||
--set up voxel manipulator
|
||||
local manip = minetest.get_voxel_manip()
|
||||
local emerged_pos1, emerged_pos2 = manip:read_from_map(pos1, pos2)
|
||||
local area = VoxelArea:new({MinEdge=emerged_pos1, MaxEdge=emerged_pos2})
|
||||
|
||||
local pos = {x=pos1.x, y=0, z=0}
|
||||
local node = {name=replacenode}
|
||||
local nodes = manip:get_data()
|
||||
local searchnode_id = minetest.get_content_id(searchnode)
|
||||
local replacenode_id = minetest.get_content_id(replacenode)
|
||||
local count = 0
|
||||
while pos.x <= pos2.x do
|
||||
pos.y = pos1.y
|
||||
while pos.y <= pos2.y do
|
||||
pos.z = pos1.z
|
||||
while pos.z <= pos2.z do
|
||||
local name = env:get_node(pos).name
|
||||
if name ~= "ignore" and name ~= searchnode then
|
||||
env:add_node(pos, node)
|
||||
count = count + 1
|
||||
end
|
||||
pos.z = pos.z + 1
|
||||
end
|
||||
pos.y = pos.y + 1
|
||||
for i in area:iterp(pos1, pos2) do --replace anything that is not searchnode with replacenode
|
||||
if nodes[i] ~= searchnode_id then
|
||||
nodes[i] = replacenode_id
|
||||
count = count + 1
|
||||
end
|
||||
pos.x = pos.x + 1
|
||||
end
|
||||
|
||||
--update map nodes
|
||||
manip:set_data(nodes)
|
||||
manip:write_to_map()
|
||||
manip:update_map()
|
||||
|
||||
return count
|
||||
end
|
||||
|
||||
--copies the region defined by positions `pos1` and `pos2` along the `axis` axis ("x" or "y" or "z") by `amount` nodes, returning the number of nodes copied
|
||||
worldedit.copy = function(pos1, pos2, axis, amount, env)
|
||||
worldedit.copy = function(pos1, pos2, axis, amount)
|
||||
local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
|
||||
if env == nil then env = minetest.env end
|
||||
|
||||
if amount == 0 then
|
||||
return
|
||||
end
|
||||
|
||||
local other1, other2
|
||||
if axis == "x" then
|
||||
other1, other2 = "y", "z"
|
||||
elseif axis == "y" then
|
||||
other1, other2 = "x", "z"
|
||||
else --axis == "z"
|
||||
other1, other2 = "x", "y"
|
||||
end
|
||||
|
||||
--make area stay loaded
|
||||
local manip = minetest.get_voxel_manip()
|
||||
manip:read_from_map(pos1, pos2)
|
||||
|
||||
--prepare slice along axis
|
||||
local extent = {
|
||||
[axis] = 1,
|
||||
[other1]=pos2[other1] - pos1[other1] + 1,
|
||||
[other2]=pos2[other2] - pos1[other2] + 1,
|
||||
}
|
||||
local nodes = {}
|
||||
local schematic = {size=extent, data=nodes}
|
||||
|
||||
local currentpos = {x=pos1.x, y=pos1.y, z=pos1.z}
|
||||
local stride = {x=1, y=extent.x, z=extent.x * extent.y}
|
||||
local get_node = minetest.get_node
|
||||
for index1 = 1, extent[axis] do --go through each slice
|
||||
--copy slice into schematic
|
||||
local newindex1 = (index1 + offset[axis]) * stride[axis] + 1 --offset contributed by axis plus 1 to make it 1-indexed
|
||||
for index2 = 1, extent[other1] do
|
||||
local newindex2 = newindex1 + (index2 + offset[other1]) * stride[other1]
|
||||
for index3 = 1, extent[other2] do
|
||||
local i = newindex2 + (index3 + offset[other2]) * stride[other2]
|
||||
nodes[i] = get_node(pos)
|
||||
end
|
||||
end
|
||||
|
||||
--copy schematic to target
|
||||
currentpos[axis] = currentpos[axis] + amount
|
||||
place_schematic(currentpos, schematic)
|
||||
|
||||
--wip: copy meta
|
||||
|
||||
currentpos[axis] = currentpos[axis] + 1
|
||||
end
|
||||
return worldedit.volume(pos1, pos2)
|
||||
end
|
||||
|
||||
--copies the region defined by positions `pos1` and `pos2` along the `axis` axis ("x" or "y" or "z") by `amount` nodes, returning the number of nodes copied
|
||||
worldedit.copy = function(pos1, pos2, axis, amount)
|
||||
local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
|
||||
|
||||
--make area stay loaded
|
||||
local manip = minetest.get_voxel_manip()
|
||||
manip:read_from_map(pos1, pos2)
|
||||
|
||||
local get_node, get_meta, add_node = minetest.get_node, minetest.get_meta, minetest.add_node
|
||||
if amount < 0 then
|
||||
local pos = {x=pos1.x, y=0, z=0}
|
||||
while pos.x <= pos2.x do
|
||||
@ -117,12 +179,12 @@ worldedit.copy = function(pos1, pos2, axis, amount, env)
|
||||
while pos.y <= pos2.y do
|
||||
pos.z = pos1.z
|
||||
while pos.z <= pos2.z do
|
||||
local node = env:get_node(pos) --obtain current node
|
||||
local meta = env:get_meta(pos):to_table() --get meta of current node
|
||||
local node = get_node(pos) --obtain current node
|
||||
local meta = get_meta(pos):to_table() --get meta of current node
|
||||
local value = pos[axis] --store current position
|
||||
pos[axis] = value + amount --move along axis
|
||||
env:add_node(pos, node) --copy node to new position
|
||||
env:get_meta(pos):from_table(meta) --set metadata of new node
|
||||
add_node(pos, node) --copy node to new position
|
||||
get_meta(pos):from_table(meta) --set metadata of new node
|
||||
pos[axis] = value --restore old position
|
||||
pos.z = pos.z + 1
|
||||
end
|
||||
@ -137,12 +199,12 @@ worldedit.copy = function(pos1, pos2, axis, amount, env)
|
||||
while pos.y >= pos1.y do
|
||||
pos.z = pos2.z
|
||||
while pos.z >= pos1.z do
|
||||
local node = minetest.env:get_node(pos) --obtain current node
|
||||
local meta = env:get_meta(pos):to_table() --get meta of current node
|
||||
local node = get_node(pos) --obtain current node
|
||||
local meta = get_meta(pos):to_table() --get meta of current node
|
||||
local value = pos[axis] --store current position
|
||||
pos[axis] = value + amount --move along axis
|
||||
minetest.env:add_node(pos, node) --copy node to new position
|
||||
env:get_meta(pos):from_table(meta) --set metadata of new node
|
||||
add_node(pos, node) --copy node to new position
|
||||
get_meta(pos):from_table(meta) --set metadata of new node
|
||||
pos[axis] = value --restore old position
|
||||
pos.z = pos.z - 1
|
||||
end
|
||||
@ -155,10 +217,15 @@ worldedit.copy = function(pos1, pos2, axis, amount, env)
|
||||
end
|
||||
|
||||
--moves the region defined by positions `pos1` and `pos2` along the `axis` axis ("x" or "y" or "z") by `amount` nodes, returning the number of nodes moved
|
||||
worldedit.move = function(pos1, pos2, axis, amount, env)
|
||||
worldedit.move = function(pos1, pos2, axis, amount)
|
||||
local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
|
||||
if env == nil then env = minetest.env end
|
||||
|
||||
--make area stay loaded
|
||||
local manip = minetest.get_voxel_manip()
|
||||
manip:read_from_map(pos1, pos2)
|
||||
|
||||
--wip: move slice by slice using schematic method in the move axis and transfer metadata in separate loop (and if the amount is greater than the length in the axis, copy whole thing at a time and erase original after, using schematic method)
|
||||
local get_node, get_meta, add_node, remove_node = minetest.get_node, minetest.get_meta, minetest.add_node, minetest.remove_node
|
||||
if amount < 0 then
|
||||
local pos = {x=pos1.x, y=0, z=0}
|
||||
while pos.x <= pos2.x do
|
||||
@ -166,13 +233,13 @@ worldedit.move = function(pos1, pos2, axis, amount, env)
|
||||
while pos.y <= pos2.y do
|
||||
pos.z = pos1.z
|
||||
while pos.z <= pos2.z do
|
||||
local node = env:get_node(pos) --obtain current node
|
||||
local meta = env:get_meta(pos):to_table() --get metadata of current node
|
||||
env:remove_node(pos)
|
||||
local node = get_node(pos) --obtain current node
|
||||
local meta = get_meta(pos):to_table() --get metadata of current node
|
||||
remove_node(pos)
|
||||
local value = pos[axis] --store current position
|
||||
pos[axis] = value + amount --move along axis
|
||||
env:add_node(pos, node) --move node to new position
|
||||
env:get_meta(pos):from_table(meta) --set metadata of new node
|
||||
add_node(pos, node) --move node to new position
|
||||
get_meta(pos):from_table(meta) --set metadata of new node
|
||||
pos[axis] = value --restore old position
|
||||
pos.z = pos.z + 1
|
||||
end
|
||||
@ -187,13 +254,13 @@ worldedit.move = function(pos1, pos2, axis, amount, env)
|
||||
while pos.y >= pos1.y do
|
||||
pos.z = pos2.z
|
||||
while pos.z >= pos1.z do
|
||||
local node = env:get_node(pos) --obtain current node
|
||||
local meta = env:get_meta(pos):to_table() --get metadata of current node
|
||||
env:remove_node(pos)
|
||||
local node = get_node(pos) --obtain current node
|
||||
local meta = get_meta(pos):to_table() --get metadata of current node
|
||||
remove_node(pos)
|
||||
local value = pos[axis] --store current position
|
||||
pos[axis] = value + amount --move along axis
|
||||
env:add_node(pos, node) --move node to new position
|
||||
env:get_meta(pos):from_table(meta) --set metadata of new node
|
||||
add_node(pos, node) --move node to new position
|
||||
get_meta(pos):from_table(meta) --set metadata of new node
|
||||
pos[axis] = value --restore old position
|
||||
pos.z = pos.z - 1
|
||||
end
|
||||
@ -206,7 +273,7 @@ worldedit.move = function(pos1, pos2, axis, amount, env)
|
||||
end
|
||||
|
||||
--duplicates the region defined by positions `pos1` and `pos2` along the `axis` axis ("x" or "y" or "z") `count` times, returning the number of nodes stacked
|
||||
worldedit.stack = function(pos1, pos2, axis, count, env)
|
||||
worldedit.stack = function(pos1, pos2, axis, count)
|
||||
local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
|
||||
local length = pos2[axis] - pos1[axis] + 1
|
||||
if count < 0 then
|
||||
@ -217,13 +284,72 @@ worldedit.stack = function(pos1, pos2, axis, count, env)
|
||||
local copy = worldedit.copy
|
||||
for i = 1, count do
|
||||
amount = amount + length
|
||||
copy(pos1, pos2, axis, amount, env)
|
||||
copy(pos1, pos2, axis, amount)
|
||||
end
|
||||
return worldedit.volume(pos1, pos2)
|
||||
return worldedit.volume(pos1, pos2) * count
|
||||
end
|
||||
|
||||
--transposes a region defined by the positions `pos1` and `pos2` between the `axis1` and `axis2` axes, returning the number of nodes transposed, the new position 1, and the new position 2
|
||||
worldedit.transpose = function(pos1, pos2, axis1, axis2, env)
|
||||
--scales the region defined by positions `pos1` and `pos2` by an factor of positive integer `factor` with `pos1` as the origin, returning the number of nodes scaled, the new scaled position 1, and the new scaled position 2
|
||||
worldedit.scale = function(pos1, pos2, factor)
|
||||
local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
|
||||
|
||||
--prepare schematic of large node
|
||||
local get_node, get_meta, place_schematic = minetest.get_node, minetest.get_meta, minetest.place_schematic
|
||||
local placeholder_node = {name="", param1=0, param2=0}
|
||||
local nodes = {}
|
||||
for i = 1, factor ^ 3 do
|
||||
nodes[i] = placeholder_node
|
||||
end
|
||||
local schematic = {size={x=factor, y=factor, z=factor}, data=nodes}
|
||||
|
||||
local size = factor - 1
|
||||
|
||||
--make area stay loaded
|
||||
local manip = minetest.get_voxel_manip()
|
||||
local new_pos2 = {x=pos1.x + (pos2.x - pos1.x) * factor + size, y=pos1.y + (pos2.y - pos1.y) * factor + size, z=pos1.z + (pos2.z - pos1.z) * factor + size}
|
||||
manip:read_from_map(pos1, new_pos2)
|
||||
|
||||
local pos = {x=pos2.x, y=0, z=0}
|
||||
local bigpos = {x=0, y=0, z=0}
|
||||
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 value = pos[axis] --store current position
|
||||
local posx, posy, posz = pos1.x + (pos.x - pos1.x) * factor, pos1.y + (pos.y - pos1.y) * factor, pos1.z + (pos.z - pos1.z) * factor
|
||||
|
||||
--create large node
|
||||
placeholder_node.name = node.name
|
||||
placeholder_node.param1, placeholder_node.param2 = node.param1, node.param2
|
||||
bigpos.x, bigpos.y, bigpos.z = posx, posy, posz
|
||||
place_schematic(bigpos, schematic)
|
||||
|
||||
--fill in large node meta
|
||||
if next(meta.fields) ~= nil and next(meta.inventory) ~= nil then --node has meta fields
|
||||
for x = 0, size do
|
||||
for y = 0, size do
|
||||
for z = 0, size do
|
||||
bigpos.x, bigpos.y, bigpos.z = posx + x, posy + y, posz + z
|
||||
get_meta(bigpos):from_table(meta) --set metadata of new node
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
pos.z = pos.z - 1
|
||||
end
|
||||
pos.y = pos.y - 1
|
||||
end
|
||||
pos.x = pos.x - 1
|
||||
end
|
||||
return worldedit.volume(pos1, pos2) * (factor ^ 3), pos1, new_pos2
|
||||
end
|
||||
|
||||
--transposes a region defined by the positions `pos1` and `pos2` between the `axis1` and `axis2` axes, returning the number of nodes transposed, the new transposed position 1, and the new transposed position 2
|
||||
worldedit.transpose = function(pos1, pos2, axis1, axis2)
|
||||
local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
|
||||
|
||||
local compare
|
||||
@ -240,12 +366,19 @@ worldedit.transpose = function(pos1, pos2, axis1, axis2, env)
|
||||
end
|
||||
|
||||
--calculate the new position 2 after transposition
|
||||
local newpos2 = {x=pos2.x, y=pos2.y, z=pos2.z}
|
||||
newpos2[axis1] = pos1[axis1] + extent2
|
||||
newpos2[axis2] = pos1[axis2] + extent1
|
||||
local new_pos2 = {x=pos2.x, y=pos2.y, z=pos2.z}
|
||||
new_pos2[axis1] = pos1[axis1] + extent2
|
||||
new_pos2[axis2] = pos1[axis2] + extent1
|
||||
|
||||
--make area stay loaded
|
||||
local manip = minetest.get_voxel_manip()
|
||||
local upperbound = {x=pos2.x, y=pos2.y, z=pos2.z}
|
||||
if upperbound[axis1] < new_pos2[axis1] then upperbound[axis1] = new_pos2[axis1] end
|
||||
if upperbound[axis2] < new_pos2[axis2] then upperbound[axis2] = new_pos2[axis2] end
|
||||
manip:read_from_map(pos1, upperbound)
|
||||
|
||||
local pos = {x=pos1.x, y=0, z=0}
|
||||
if env == nil then env = minetest.env end
|
||||
local get_node, get_meta, add_node = minetest.get_node, minetest.get_meta, minetest.add_node
|
||||
while pos.x <= pos2.x do
|
||||
pos.y = pos1.y
|
||||
while pos.y <= pos2.y do
|
||||
@ -253,17 +386,17 @@ worldedit.transpose = function(pos1, pos2, axis1, axis2, env)
|
||||
while pos.z <= pos2.z do
|
||||
local extent1, extent2 = pos[axis1] - pos1[axis1], pos[axis2] - pos1[axis2]
|
||||
if compare(extent1, extent2) then --transpose only if below the diagonal
|
||||
local node1 = env:get_node(pos)
|
||||
local meta1 = env:get_meta(pos):to_table()
|
||||
local node1 = get_node(pos)
|
||||
local meta1 = get_meta(pos):to_table()
|
||||
local value1, value2 = pos[axis1], pos[axis2] --save position values
|
||||
pos[axis1], pos[axis2] = pos1[axis1] + extent2, pos1[axis2] + extent1 --swap axis extents
|
||||
local node2 = env:get_node(pos)
|
||||
local meta2 = env:get_meta(pos):to_table()
|
||||
env:add_node(pos, node1)
|
||||
env:get_meta(pos):from_table(meta1)
|
||||
local node2 = get_node(pos)
|
||||
local meta2 = get_meta(pos):to_table()
|
||||
add_node(pos, node1)
|
||||
get_meta(pos):from_table(meta1)
|
||||
pos[axis1], pos[axis2] = value1, value2 --restore position values
|
||||
env:add_node(pos, node2)
|
||||
env:get_meta(pos):from_table(meta2)
|
||||
add_node(pos, node2)
|
||||
get_meta(pos):from_table(meta2)
|
||||
end
|
||||
pos.z = pos.z + 1
|
||||
end
|
||||
@ -271,33 +404,38 @@ worldedit.transpose = function(pos1, pos2, axis1, axis2, env)
|
||||
end
|
||||
pos.x = pos.x + 1
|
||||
end
|
||||
return worldedit.volume(pos1, pos2), pos1, newpos2
|
||||
return worldedit.volume(pos1, pos2), pos1, new_pos2
|
||||
end
|
||||
|
||||
--flips a region defined by the positions `pos1` and `pos2` along the `axis` axis ("x" or "y" or "z"), returning the number of nodes flipped
|
||||
worldedit.flip = function(pos1, pos2, axis, env)
|
||||
worldedit.flip = function(pos1, pos2, axis)
|
||||
local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
|
||||
|
||||
--make area stay loaded
|
||||
local manip = minetest.get_voxel_manip()
|
||||
manip:read_from_map(pos1, pos2)
|
||||
|
||||
--wip: flip the region slice by slice along the flip axis using schematic method
|
||||
local pos = {x=pos1.x, y=0, z=0}
|
||||
local start = pos1[axis] + pos2[axis]
|
||||
pos2[axis] = pos1[axis] + math.floor((pos2[axis] - pos1[axis]) / 2)
|
||||
if env == nil then env = minetest.env end
|
||||
local get_node, get_meta, add_node = minetest.get_node, minetest.get_meta, minetest.add_node
|
||||
while pos.x <= pos2.x do
|
||||
pos.y = pos1.y
|
||||
while pos.y <= pos2.y do
|
||||
pos.z = pos1.z
|
||||
while pos.z <= pos2.z do
|
||||
local node1 = env:get_node(pos)
|
||||
local meta1 = env:get_meta(pos):to_table()
|
||||
local node1 = get_node(pos)
|
||||
local meta1 = get_meta(pos):to_table()
|
||||
local value = pos[axis]
|
||||
pos[axis] = start - value
|
||||
local node2 = env:get_node(pos)
|
||||
local meta2 = env:get_meta(pos):to_table()
|
||||
env:add_node(pos, node1)
|
||||
env:get_meta(pos):from_table(meta1)
|
||||
local node2 = get_node(pos)
|
||||
local meta2 = get_meta(pos):to_table()
|
||||
add_node(pos, node1)
|
||||
get_meta(pos):from_table(meta1)
|
||||
pos[axis] = value
|
||||
env:add_node(pos, node2)
|
||||
env:get_meta(pos):from_table(meta2)
|
||||
add_node(pos, node2)
|
||||
get_meta(pos):from_table(meta2)
|
||||
pos.z = pos.z + 1
|
||||
end
|
||||
pos.y = pos.y + 1
|
||||
@ -308,7 +446,7 @@ worldedit.flip = function(pos1, pos2, axis, env)
|
||||
end
|
||||
|
||||
--rotates a region defined by the positions `pos1` and `pos2` by `angle` degrees clockwise around axis `axis` (90 degree increment), returning the number of nodes rotated
|
||||
worldedit.rotate = function(pos1, pos2, axis, angle, env)
|
||||
worldedit.rotate = function(pos1, pos2, axis, angle)
|
||||
local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
|
||||
|
||||
local axis1, axis2
|
||||
@ -323,23 +461,23 @@ worldedit.rotate = function(pos1, pos2, axis, angle, env)
|
||||
|
||||
local count
|
||||
if angle == 90 then
|
||||
worldedit.flip(pos1, pos2, axis1, env)
|
||||
count, pos1, pos2 = worldedit.transpose(pos1, pos2, axis1, axis2, env)
|
||||
worldedit.flip(pos1, pos2, axis1)
|
||||
count, pos1, pos2 = worldedit.transpose(pos1, pos2, axis1, axis2)
|
||||
elseif angle == 180 then
|
||||
worldedit.flip(pos1, pos2, axis1, env)
|
||||
count = worldedit.flip(pos1, pos2, axis2, env)
|
||||
worldedit.flip(pos1, pos2, axis1)
|
||||
count = worldedit.flip(pos1, pos2, axis2)
|
||||
elseif angle == 270 then
|
||||
worldedit.flip(pos1, pos2, axis2, env)
|
||||
count, pos1, pos2 = worldedit.transpose(pos1, pos2, axis1, axis2, env)
|
||||
worldedit.flip(pos1, pos2, axis2)
|
||||
count, pos1, pos2 = worldedit.transpose(pos1, pos2, axis1, axis2)
|
||||
end
|
||||
return count, pos1, pos2
|
||||
end
|
||||
|
||||
--rotates all oriented nodes in a region defined by the positions `pos1` and `pos2` by `angle` degrees clockwise (90 degree increment) around the Y axis, returning the number of nodes oriented
|
||||
worldedit.orient = function(pos1, pos2, angle, env)
|
||||
worldedit.orient = function(pos1, pos2, angle) --wip: support 6D facedir rotation along arbitrary axis
|
||||
local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
|
||||
local nodes = minetest.registered_nodes
|
||||
if env == nil then env = minetest.env end
|
||||
local registered_nodes = minetest.registered_nodes
|
||||
|
||||
local wallmounted = {
|
||||
[90]={[0]=0, [1]=1, [2]=5, [3]=4, [4]=2, [5]=3},
|
||||
[180]={[0]=0, [1]=1, [2]=3, [3]=2, [4]=5, [5]=4},
|
||||
@ -358,27 +496,32 @@ worldedit.orient = function(pos1, pos2, angle, env)
|
||||
local wallmounted_substitution = wallmounted[angle]
|
||||
local facedir_substitution = facedir[angle]
|
||||
|
||||
--make area stay loaded
|
||||
local manip = minetest.get_voxel_manip()
|
||||
manip:read_from_map(pos1, pos2)
|
||||
|
||||
local count = 0
|
||||
local get_node, get_meta, add_node = minetest.get_node, minetest.get_meta, minetest.add_node
|
||||
local pos = {x=pos1.x, y=0, z=0}
|
||||
while pos.x <= pos2.x do
|
||||
pos.y = pos1.y
|
||||
while pos.y <= pos2.y do
|
||||
pos.z = pos1.z
|
||||
while pos.z <= pos2.z do
|
||||
local node = env:get_node(pos)
|
||||
local def = nodes[node.name]
|
||||
local node = get_node(pos)
|
||||
local def = registered_nodes[node.name]
|
||||
if def then
|
||||
if def.paramtype2 == "wallmounted" then
|
||||
node.param2 = wallmounted_substitution[node.param2]
|
||||
local meta = env:get_meta(pos):to_table()
|
||||
env:add_node(pos, node)
|
||||
env:get_meta(pos):from_table(meta)
|
||||
local meta = get_meta(pos):to_table()
|
||||
add_node(pos, node)
|
||||
get_meta(pos):from_table(meta)
|
||||
count = count + 1
|
||||
elseif def.paramtype2 == "facedir" then
|
||||
node.param2 = facedir_substitution[node.param2]
|
||||
local meta = env:get_meta(pos):to_table()
|
||||
env:add_node(pos, node)
|
||||
env:get_meta(pos):from_table(meta)
|
||||
local meta = get_meta(pos):to_table()
|
||||
add_node(pos, node)
|
||||
get_meta(pos):from_table(meta)
|
||||
count = count + 1
|
||||
end
|
||||
end
|
||||
@ -392,26 +535,45 @@ worldedit.orient = function(pos1, pos2, angle, env)
|
||||
end
|
||||
|
||||
--fixes the lighting in a region defined by positions `pos1` and `pos2`, returning the number of nodes updated
|
||||
worldedit.fixlight = function(pos1, pos2, env)
|
||||
worldedit.fixlight = function(pos1, pos2)
|
||||
local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
|
||||
if env == nil then env = minetest.env end
|
||||
local count = 0
|
||||
|
||||
local pos = {x=pos1.x, y=0, z=0}
|
||||
while pos.x <= pos2.x do
|
||||
pos.y = pos1.y
|
||||
while pos.y <= pos2.y do
|
||||
pos.z = pos1.z
|
||||
while pos.z <= pos2.z do
|
||||
if env:get_node(pos).name == "air" then
|
||||
env:dig_node(pos)
|
||||
count = count + 1
|
||||
end
|
||||
pos.z = pos.z + 1
|
||||
--make area stay loaded
|
||||
local manip = minetest.get_voxel_manip()
|
||||
manip:read_from_map(pos1, pos2)
|
||||
|
||||
local nodes = minetest.find_nodes_in_area(pos1, pos2, "air")
|
||||
local dig_node = minetest.dig_node
|
||||
for _, pos in ipairs(nodes) do
|
||||
dig_node(pos)
|
||||
end
|
||||
return #nodes
|
||||
end
|
||||
|
||||
--clears all objects in a region defined by the positions `pos1` and `pos2`, returning the number of objects cleared
|
||||
worldedit.clearobjects = function(pos1, pos2)
|
||||
local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
|
||||
|
||||
--make area stay loaded
|
||||
local manip = minetest.get_voxel_manip()
|
||||
manip:read_from_map(pos1, pos2)
|
||||
|
||||
local pos1x, pos1y, pos1z = pos1.x, pos1.y, pos1.z
|
||||
local pos2x, pos2y, pos2z = pos2.x + 1, pos2.y + 1, pos2.z + 1
|
||||
local center = {x=(pos1x + pos2x) / 2, y=(pos1y + pos2y) / 2, z=(pos1z + pos2z) / 2} --center of region
|
||||
local radius = ((center.x - pos1x + 0.5) + (center.y - pos1y + 0.5) + (center.z - pos1z + 0.5)) ^ 0.5 --bounding sphere radius
|
||||
local count = 0
|
||||
for _, obj in pairs(minetest.get_objects_inside_radius(center, radius)) do --all objects in bounding sphere
|
||||
local entity = obj:get_luaentity()
|
||||
if not (entity and entity.name:find("^worldedit:")) then --avoid WorldEdit entities
|
||||
local pos = obj:getpos()
|
||||
if pos.x >= pos1x and pos.x <= pos2x
|
||||
and pos.y >= pos1y and pos.y <= pos2y
|
||||
and pos.z >= pos1z and pos.z <= pos2z then --inside region
|
||||
obj:remove()
|
||||
count = count + 1
|
||||
end
|
||||
pos.y = pos.y + 1
|
||||
end
|
||||
pos.x = pos.x + 1
|
||||
end
|
||||
return count
|
||||
end
|
||||
|
@ -1,101 +1,198 @@
|
||||
worldedit = worldedit or {}
|
||||
local minetest = minetest --local copy of global
|
||||
|
||||
--adds a hollow sphere at `pos` with radius `radius`, composed of `nodename`, returning the number of nodes added
|
||||
worldedit.hollow_sphere = function(pos, radius, nodename, env)
|
||||
local node = {name=nodename}
|
||||
local pos1 = {x=0, y=0, z=0}
|
||||
local min_radius = radius * (radius - 1)
|
||||
local max_radius = radius * (radius + 1)
|
||||
--adds a hollow sphere centered at `pos` with radius `radius`, composed of `nodename`, returning the number of nodes added
|
||||
worldedit.hollow_sphere = function(pos, radius, nodename)
|
||||
--set up voxel manipulator
|
||||
local manip = minetest.get_voxel_manip()
|
||||
local pos1 = {x=pos.x - radius, y=pos.y - radius, z=pos.z - radius}
|
||||
local pos2 = {x=pos.x + radius, y=pos.y + radius, z=pos.z + radius}
|
||||
local emerged_pos1, emerged_pos2 = manip:read_from_map(pos1, pos2)
|
||||
local area = VoxelArea:new({MinEdge=emerged_pos1, MaxEdge=emerged_pos2})
|
||||
|
||||
--fill emerged area with ignore
|
||||
local nodes = {}
|
||||
local ignore = minetest.get_content_id("ignore")
|
||||
for i = 1, worldedit.volume(emerged_pos1, emerged_pos2) do
|
||||
nodes[i] = ignore
|
||||
end
|
||||
|
||||
--fill selected area with node
|
||||
local node_id = minetest.get_content_id(nodename)
|
||||
local min_radius, max_radius = radius * (radius - 1), radius * (radius + 1)
|
||||
local offsetx, offsety, offsetz = pos.x - emerged_pos1.x, pos.y - emerged_pos1.y, pos.z - emerged_pos1.z
|
||||
local zstride, ystride = area.zstride, area.ystride
|
||||
local count = 0
|
||||
if env == nil then env = minetest.env end
|
||||
for x = -radius, radius do
|
||||
pos1.x = pos.x + x
|
||||
for z = -radius, radius do
|
||||
local newz = (z + offsetz) * zstride + 1 --offset contributed by z plus 1 to make it 1-indexed
|
||||
for y = -radius, radius do
|
||||
pos1.y = pos.y + y
|
||||
for z = -radius, radius do
|
||||
if x*x+y*y+z*z >= min_radius and x*x+y*y+z*z <= max_radius then
|
||||
pos1.z = pos.z + z
|
||||
env:add_node(pos1, node)
|
||||
local newy = newz + (y + offsety) * ystride
|
||||
for x = -radius, radius do
|
||||
local squared = x * x + y * y + z * z
|
||||
if squared >= min_radius and squared <= max_radius then --position is on surface of sphere
|
||||
local i = newy + (x + offsetx)
|
||||
nodes[i] = node_id
|
||||
count = count + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--update map nodes
|
||||
manip:set_data(nodes)
|
||||
manip:write_to_map()
|
||||
manip:update_map()
|
||||
|
||||
return count
|
||||
end
|
||||
|
||||
--adds a sphere at `pos` with radius `radius`, composed of `nodename`, returning the number of nodes added
|
||||
worldedit.sphere = function(pos, radius, nodename, env)
|
||||
local node = {name=nodename}
|
||||
local pos1 = {x=0, y=0, z=0}
|
||||
--adds a sphere centered at `pos` with radius `radius`, composed of `nodename`, returning the number of nodes added
|
||||
worldedit.sphere = function(pos, radius, nodename)
|
||||
--set up voxel manipulator
|
||||
local manip = minetest.get_voxel_manip()
|
||||
local pos1 = {x=pos.x - radius, y=pos.y - radius, z=pos.z - radius}
|
||||
local pos2 = {x=pos.x + radius, y=pos.y + radius, z=pos.z + radius}
|
||||
local emerged_pos1, emerged_pos2 = manip:read_from_map(pos1, pos2)
|
||||
local area = VoxelArea:new({MinEdge=emerged_pos1, MaxEdge=emerged_pos2})
|
||||
|
||||
--fill emerged area with ignore
|
||||
local nodes = {}
|
||||
local ignore = minetest.get_content_id("ignore")
|
||||
for i = 1, worldedit.volume(emerged_pos1, emerged_pos2) do
|
||||
nodes[i] = ignore
|
||||
end
|
||||
|
||||
--fill selected area with node
|
||||
local node_id = minetest.get_content_id(nodename)
|
||||
local max_radius = radius * (radius + 1)
|
||||
local offsetx, offsety, offsetz = pos.x - emerged_pos1.x, pos.y - emerged_pos1.y, pos.z - emerged_pos1.z
|
||||
local zstride, ystride = area.zstride, area.ystride
|
||||
local count = 0
|
||||
if env == nil then env = minetest.env end
|
||||
for x = -radius, radius do
|
||||
pos1.x = pos.x + x
|
||||
for z = -radius, radius do
|
||||
local newz = (z + offsetz) * zstride + 1 --offset contributed by z plus 1 to make it 1-indexed
|
||||
for y = -radius, radius do
|
||||
pos1.y = pos.y + y
|
||||
for z = -radius, radius do
|
||||
if x*x+y*y+z*z <= max_radius then
|
||||
pos1.z = pos.z + z
|
||||
env:add_node(pos1, node)
|
||||
local newy = newz + (y + offsety) * ystride
|
||||
for x = -radius, radius do
|
||||
if x * x + y * y + z * z <= max_radius then --position is inside sphere
|
||||
local i = newy + (x + offsetx)
|
||||
nodes[i] = node_id
|
||||
count = count + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--update map nodes
|
||||
manip:set_data(nodes)
|
||||
manip:write_to_map()
|
||||
manip:update_map()
|
||||
|
||||
return count
|
||||
end
|
||||
|
||||
--adds a hollow dome at `pos` with radius `radius`, composed of `nodename`, returning the number of nodes added
|
||||
worldedit.hollow_dome = function(pos, radius, nodename, env) --wip: use bresenham sphere for maximum speed
|
||||
local node = {name=nodename}
|
||||
local pos1 = {x=0, y=0, z=0}
|
||||
local min_radius = radius * (radius - 1)
|
||||
local max_radius = radius * (radius + 1)
|
||||
--adds a hollow dome centered at `pos` with radius `radius`, composed of `nodename`, returning the number of nodes added
|
||||
worldedit.hollow_dome = function(pos, radius, nodename)
|
||||
--set up voxel manipulator
|
||||
local manip = minetest.get_voxel_manip()
|
||||
local pos1 = {x=pos.x - radius, y=pos.y, z=pos.z - radius}
|
||||
local pos2 = {x=pos.x + radius, y=pos.y + radius, z=pos.z + radius}
|
||||
local emerged_pos1, emerged_pos2 = manip:read_from_map(pos1, pos2)
|
||||
local area = VoxelArea:new({MinEdge=emerged_pos1, MaxEdge=emerged_pos2})
|
||||
|
||||
--fill emerged area with ignore
|
||||
local nodes = {}
|
||||
local ignore = minetest.get_content_id("ignore")
|
||||
for i = 1, worldedit.volume(emerged_pos1, emerged_pos2) do
|
||||
nodes[i] = ignore
|
||||
end
|
||||
|
||||
local miny, maxy = 0, radius
|
||||
if radius < 0 then
|
||||
radius = -radius
|
||||
miny, maxy = -radius, 0
|
||||
end
|
||||
|
||||
--fill selected area with node
|
||||
local node_id = minetest.get_content_id(nodename)
|
||||
local min_radius, max_radius = radius * (radius - 1), radius * (radius + 1)
|
||||
local offsetx, offsety, offsetz = pos.x - emerged_pos1.x, pos.y - emerged_pos1.y, pos.z - emerged_pos1.z
|
||||
local zstride, ystride = area.zstride, area.ystride
|
||||
local count = 0
|
||||
if env == nil then env = minetest.env end
|
||||
for x = -radius, radius do
|
||||
pos1.x = pos.x + x
|
||||
for y = 0, radius do
|
||||
pos1.y = pos.y + y
|
||||
for z = -radius, radius do
|
||||
if x*x+y*y+z*z >= min_radius and x*x+y*y+z*z <= max_radius then
|
||||
pos1.z = pos.z + z
|
||||
env:add_node(pos1, node)
|
||||
for z = -radius, radius do
|
||||
local newz = (z + offsetz) * zstride + 1 --offset contributed by z plus 1 to make it 1-indexed
|
||||
for y = miny, maxy do
|
||||
local newy = newz + (y + offsety) * ystride
|
||||
for x = -radius, radius do
|
||||
local squared = x * x + y * y + z * z
|
||||
if squared >= min_radius and squared <= max_radius then --position is on surface of sphere
|
||||
local i = newy + (x + offsetx)
|
||||
nodes[i] = node_id
|
||||
count = count + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--update map nodes
|
||||
manip:set_data(nodes)
|
||||
manip:write_to_map()
|
||||
manip:update_map()
|
||||
|
||||
return count
|
||||
end
|
||||
|
||||
--adds a dome at `pos` with radius `radius`, composed of `nodename`, returning the number of nodes added
|
||||
worldedit.dome = function(pos, radius, nodename, env) --wip: use bresenham sphere for maximum speed
|
||||
local node = {name=nodename}
|
||||
local pos1 = {x=0, y=0, z=0}
|
||||
--adds a dome centered at `pos` with radius `radius`, composed of `nodename`, returning the number of nodes added
|
||||
worldedit.dome = function(pos, radius, nodename)
|
||||
--set up voxel manipulator
|
||||
local manip = minetest.get_voxel_manip()
|
||||
local pos1 = {x=pos.x - radius, y=pos.y, z=pos.z - radius}
|
||||
local pos2 = {x=pos.x + radius, y=pos.y + radius, z=pos.z + radius}
|
||||
local emerged_pos1, emerged_pos2 = manip:read_from_map(pos1, pos2)
|
||||
local area = VoxelArea:new({MinEdge=emerged_pos1, MaxEdge=emerged_pos2})
|
||||
|
||||
--fill emerged area with ignore
|
||||
local nodes = {}
|
||||
local ignore = minetest.get_content_id("ignore")
|
||||
for i = 1, worldedit.volume(emerged_pos1, emerged_pos2) do
|
||||
nodes[i] = ignore
|
||||
end
|
||||
|
||||
local miny, maxy = 0, radius
|
||||
if radius < 0 then
|
||||
radius = -radius
|
||||
miny, maxy = -radius, 0
|
||||
end
|
||||
|
||||
--fill selected area with node
|
||||
local node_id = minetest.get_content_id(nodename)
|
||||
local max_radius = radius * (radius + 1)
|
||||
local offsetx, offsety, offsetz = pos.x - emerged_pos1.x, pos.y - emerged_pos1.y, pos.z - emerged_pos1.z
|
||||
local zstride, ystride = area.zstride, area.ystride
|
||||
local count = 0
|
||||
if env == nil then env = minetest.env end
|
||||
for x = -radius, radius do
|
||||
pos1.x = pos.x + x
|
||||
for y = 0, radius do
|
||||
pos1.y = pos.y + y
|
||||
for z = -radius, radius do
|
||||
if x*x+y*y+z*z <= max_radius then
|
||||
pos1.z = pos.z + z
|
||||
env:add_node(pos1, node)
|
||||
for z = -radius, radius do
|
||||
local newz = (z + offsetz) * zstride + 1 --offset contributed by z plus 1 to make it 1-indexed
|
||||
for y = miny, maxy do
|
||||
local newy = newz + (y + offsety) * ystride
|
||||
for x = -radius, radius do
|
||||
if x * x + y * y + z * z <= max_radius then --position is inside sphere
|
||||
local i = newy + (x + offsetx)
|
||||
nodes[i] = node_id
|
||||
count = count + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--update map nodes
|
||||
manip:set_data(nodes)
|
||||
manip:write_to_map()
|
||||
manip:update_map()
|
||||
|
||||
return count
|
||||
end
|
||||
|
||||
--adds a hollow cylinder at `pos` along the `axis` axis ("x" or "y" or "z") with length `length` and radius `radius`, composed of `nodename`, returning the number of nodes added
|
||||
worldedit.hollow_cylinder = function(pos, axis, length, radius, nodename, env)
|
||||
worldedit.hollow_cylinder = function(pos, axis, length, radius, nodename) --wip: rewrite this using voxelmanip
|
||||
local other1, other2
|
||||
if axis == "x" then
|
||||
other1, other2 = "y", "z"
|
||||
@ -105,58 +202,79 @@ worldedit.hollow_cylinder = function(pos, axis, length, radius, nodename, env)
|
||||
other1, other2 = "x", "y"
|
||||
end
|
||||
|
||||
if env == nil then env = minetest.env end
|
||||
--handle negative lengths
|
||||
local currentpos = {x=pos.x, y=pos.y, z=pos.z}
|
||||
local node = {name=nodename}
|
||||
local count = 0
|
||||
local step = 1
|
||||
if length < 0 then
|
||||
length = -length
|
||||
step = -1
|
||||
currentpos[axis] = currentpos[axis] - length
|
||||
end
|
||||
|
||||
--make area stay loaded
|
||||
local manip = minetest.get_voxel_manip()
|
||||
local pos1 = {
|
||||
[axis]=currentpos[axis],
|
||||
[other1]=currentpos[other1] - radius,
|
||||
[other2]=currentpos[other2] - radius
|
||||
}
|
||||
local pos2 = {
|
||||
[axis]=currentpos[axis] + length - 1,
|
||||
[other1]=currentpos[other1] + radius,
|
||||
[other2]=currentpos[other2] + radius
|
||||
}
|
||||
manip:read_from_map(pos1, pos2)
|
||||
|
||||
--create schematic for single node column along the axis
|
||||
local node = {name=nodename, param1=0, param2=0}
|
||||
local nodes = {}
|
||||
for i = 1, length do
|
||||
local offset1, offset2 = 0, radius
|
||||
local delta = -radius
|
||||
while offset1 <= offset2 do
|
||||
--add node at each octant
|
||||
local first1, first2 = pos[other1] + offset1, pos[other1] - offset1
|
||||
local second1, second2 = pos[other2] + offset2, pos[other2] - offset2
|
||||
currentpos[other1], currentpos[other2] = first1, second1
|
||||
env:add_node(currentpos, node) --octant 1
|
||||
currentpos[other1] = first2
|
||||
env:add_node(currentpos, node) --octant 4
|
||||
currentpos[other2] = second2
|
||||
env:add_node(currentpos, node) --octant 5
|
||||
currentpos[other1] = first1
|
||||
env:add_node(currentpos, node) --octant 8
|
||||
local first1, first2 = pos[other1] + offset2, pos[other1] - offset2
|
||||
local second1, second2 = pos[other2] + offset1, pos[other2] - offset1
|
||||
currentpos[other1], currentpos[other2] = first1, second1
|
||||
env:add_node(currentpos, node) --octant 2
|
||||
currentpos[other1] = first2
|
||||
env:add_node(currentpos, node) --octant 3
|
||||
currentpos[other2] = second2
|
||||
env:add_node(currentpos, node) --octant 6
|
||||
currentpos[other1] = first1
|
||||
env:add_node(currentpos, node) --octant 7
|
||||
|
||||
count = count + 8 --wip: broken
|
||||
|
||||
--move to next location
|
||||
delta = delta + (offset1 * 2) + 1
|
||||
if delta >= 0 then
|
||||
offset2 = offset2 - 1
|
||||
delta = delta - (offset2 * 2)
|
||||
end
|
||||
offset1 = offset1 + 1
|
||||
end
|
||||
currentpos[axis] = currentpos[axis] + step
|
||||
nodes[i] = node
|
||||
end
|
||||
local schematic = {size={[axis]=length, [other1]=1, [other2]=1}, data=nodes}
|
||||
|
||||
--add columns in a circle around axis to form cylinder
|
||||
local place_schematic = minetest.place_schematic
|
||||
local count = 0
|
||||
local offset1, offset2 = 0, radius
|
||||
local delta = -radius
|
||||
while offset1 <= offset2 do
|
||||
--add node at each octant
|
||||
local first1, first2 = pos[other1] + offset1, pos[other1] - offset1
|
||||
local second1, second2 = pos[other2] + offset2, pos[other2] - offset2
|
||||
currentpos[other1], currentpos[other2] = first1, second1
|
||||
place_schematic(currentpos, schematic) --octant 1
|
||||
currentpos[other1] = first2
|
||||
place_schematic(currentpos, schematic) --octant 4
|
||||
currentpos[other2] = second2
|
||||
place_schematic(currentpos, schematic) --octant 5
|
||||
currentpos[other1] = first1
|
||||
place_schematic(currentpos, schematic) --octant 8
|
||||
local first1, first2 = pos[other1] + offset2, pos[other1] - offset2
|
||||
local second1, second2 = pos[other2] + offset1, pos[other2] - offset1
|
||||
currentpos[other1], currentpos[other2] = first1, second1
|
||||
place_schematic(currentpos, schematic) --octant 2
|
||||
currentpos[other1] = first2
|
||||
place_schematic(currentpos, schematic) --octant 3
|
||||
currentpos[other2] = second2
|
||||
place_schematic(currentpos, schematic) --octant 6
|
||||
currentpos[other1] = first1
|
||||
place_schematic(currentpos, schematic) --octant 7
|
||||
|
||||
count = count + 8 --wip: broken because sometimes currentpos is repeated
|
||||
|
||||
--move to next location
|
||||
delta = delta + (offset1 * 2) + 1
|
||||
if delta >= 0 then
|
||||
offset2 = offset2 - 1
|
||||
delta = delta - (offset2 * 2)
|
||||
end
|
||||
offset1 = offset1 + 1
|
||||
end
|
||||
count = count * length --apply the length to the number of nodes
|
||||
return count
|
||||
end
|
||||
|
||||
--adds a cylinder at `pos` along the `axis` axis ("x" or "y" or "z") with length `length` and radius `radius`, composed of `nodename`, returning the number of nodes added
|
||||
worldedit.cylinder = function(pos, axis, length, radius, nodename, env)
|
||||
worldedit.cylinder = function(pos, axis, length, radius, nodename)
|
||||
local other1, other2
|
||||
if axis == "x" then
|
||||
other1, other2 = "y", "z"
|
||||
@ -166,146 +284,195 @@ worldedit.cylinder = function(pos, axis, length, radius, nodename, env)
|
||||
other1, other2 = "x", "y"
|
||||
end
|
||||
|
||||
if env == nil then env = minetest.env end
|
||||
--handle negative lengths
|
||||
local currentpos = {x=pos.x, y=pos.y, z=pos.z}
|
||||
local node = {name=nodename}
|
||||
local count = 0
|
||||
local step = 1
|
||||
if length < 0 then
|
||||
length = -length
|
||||
currentpos[axis] = currentpos[axis] - length
|
||||
end
|
||||
|
||||
--set up voxel manipulator
|
||||
local manip = minetest.get_voxel_manip()
|
||||
local pos1 = {
|
||||
[axis]=currentpos[axis],
|
||||
[other1]=currentpos[other1] - radius,
|
||||
[other2]=currentpos[other2] - radius
|
||||
}
|
||||
local pos2 = {
|
||||
[axis]=currentpos[axis] + length - 1,
|
||||
[other1]=currentpos[other1] + radius,
|
||||
[other2]=currentpos[other2] + radius
|
||||
}
|
||||
local emerged_pos1, emerged_pos2 = manip:read_from_map(pos1, pos2)
|
||||
local area = VoxelArea:new({MinEdge=emerged_pos1, MaxEdge=emerged_pos2})
|
||||
|
||||
--fill emerged area with ignore
|
||||
local nodes = {}
|
||||
local ignore = minetest.get_content_id("ignore")
|
||||
for i = 1, worldedit.volume(emerged_pos1, emerged_pos2) do
|
||||
nodes[i] = ignore
|
||||
end
|
||||
|
||||
--fill selected area with node
|
||||
local node_id = minetest.get_content_id(nodename)
|
||||
local max_radius = radius * (radius + 1)
|
||||
local stride = {x=1, y=area.ystride, z=area.zstride}
|
||||
local offset = {x=currentpos.x - emerged_pos1.x, y=currentpos.y - emerged_pos1.y, z=currentpos.z - emerged_pos1.z}
|
||||
local min_slice, max_slice = offset[axis], offset[axis] + length - 1
|
||||
local count = 0
|
||||
for index2 = -radius, radius do
|
||||
local newindex2 = (index2 + offset[other1]) * stride[other1] + 1 --offset contributed by other axis 1 plus 1 to make it 1-indexed
|
||||
for index3 = -radius, radius do
|
||||
local newindex3 = newindex2 + (index3 + offset[other2]) * stride[other2]
|
||||
if index2 * index2 + index3 * index3 <= max_radius then
|
||||
for index1 = min_slice, max_slice do --add column along axis
|
||||
local i = newindex3 + index1 * stride[axis]
|
||||
nodes[i] = node_id
|
||||
end
|
||||
count = count + length
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--update map nodes
|
||||
manip:set_data(nodes)
|
||||
manip:write_to_map()
|
||||
manip:update_map()
|
||||
|
||||
return count
|
||||
end
|
||||
|
||||
--adds a pyramid centered at `pos` with height `height`, composed of `nodename`, returning the number of nodes added
|
||||
worldedit.pyramid = function(pos, axis, height, nodename)
|
||||
local other1, other2
|
||||
if axis == "x" then
|
||||
other1, other2 = "y", "z"
|
||||
elseif axis == "y" then
|
||||
other1, other2 = "x", "z"
|
||||
else --axis == "z"
|
||||
other1, other2 = "x", "y"
|
||||
end
|
||||
|
||||
local pos1 = {x=pos.x - height, y=pos.y - height, z=pos.z - height}
|
||||
local pos2 = {x=pos.x + height, y=pos.y + height, z=pos.z + height}
|
||||
|
||||
--handle inverted pyramids
|
||||
local startaxis, endaxis, step
|
||||
if height > 0 then
|
||||
height = height - 1
|
||||
step = 1
|
||||
pos1[axis] = pos[axis] --upper half of box
|
||||
else
|
||||
height = height + 1
|
||||
step = -1
|
||||
pos2[axis] = pos[axis] --lower half of box
|
||||
end
|
||||
for i = 1, length do
|
||||
local offset1, offset2 = 0, radius
|
||||
local delta = -radius
|
||||
while offset1 <= offset2 do
|
||||
--connect each pair of octants
|
||||
currentpos[other1] = pos[other1] - offset1
|
||||
local second1, second2 = pos[other2] + offset2, pos[other2] - offset2
|
||||
for i = 0, offset1 * 2 do
|
||||
currentpos[other2] = second1
|
||||
env:add_node(currentpos, node) --octant 1 to 4
|
||||
currentpos[other2] = second2
|
||||
env:add_node(currentpos, node) --octant 5 to 8
|
||||
currentpos[other1] = currentpos[other1] + 1
|
||||
end
|
||||
currentpos[other1] = pos[other1] - offset2
|
||||
local second1, second2 = pos[other2] + offset1, pos[other2] - offset1
|
||||
for i = 0, offset2 * 2 do
|
||||
currentpos[other2] = second1
|
||||
env:add_node(currentpos, node) --octant 2 to 3
|
||||
currentpos[other2] = second2
|
||||
env:add_node(currentpos, node) --octant 6 to 7
|
||||
currentpos[other1] = currentpos[other1] + 1
|
||||
end
|
||||
|
||||
count = count + (offset1 * 4) + (offset2 * 4) + 4 --wip: broken
|
||||
--set up voxel manipulator
|
||||
local manip = minetest.get_voxel_manip()
|
||||
local emerged_pos1, emerged_pos2 = manip:read_from_map(pos1, pos2)
|
||||
local area = VoxelArea:new({MinEdge=emerged_pos1, MaxEdge=emerged_pos2})
|
||||
|
||||
--move to next location
|
||||
delta = delta + (offset1 * 2) + 1
|
||||
offset1 = offset1 + 1
|
||||
if delta >= 0 then
|
||||
offset2 = offset2 - 1
|
||||
delta = delta - (offset2 * 2)
|
||||
end
|
||||
end
|
||||
currentpos[axis] = currentpos[axis] + step
|
||||
--fill emerged area with ignore
|
||||
local nodes = {}
|
||||
local ignore = minetest.get_content_id("ignore")
|
||||
for i = 1, worldedit.volume(emerged_pos1, emerged_pos2) do
|
||||
nodes[i] = ignore
|
||||
end
|
||||
return count
|
||||
end
|
||||
|
||||
--adds a pyramid at `pos` with height `height`, composed of `nodename`, returning the number of nodes added
|
||||
worldedit.pyramid = function(pos, height, nodename, env)
|
||||
local pos1x, pos1y, pos1z = pos.x - height, pos.y, pos.z - height
|
||||
local pos2x, pos2y, pos2z = pos.x + height, pos.y + height, pos.z + height
|
||||
local pos = {x=0, y=pos1y, z=0}
|
||||
|
||||
--fill selected area with node
|
||||
local node_id = minetest.get_content_id(nodename)
|
||||
local stride = {x=1, y=area.ystride, z=area.zstride}
|
||||
local offset = {x=pos.x - emerged_pos1.x, y=pos.y - emerged_pos1.y, z=pos.z - emerged_pos1.z}
|
||||
local size = height * step
|
||||
local count = 0
|
||||
local node = {name=nodename}
|
||||
if env == nil then env = minetest.env end
|
||||
while pos.y <= pos2y do --each vertical level of the pyramid
|
||||
pos.x = pos1x
|
||||
while pos.x <= pos2x do
|
||||
pos.z = pos1z
|
||||
while pos.z <= pos2z do
|
||||
env:add_node(pos, node)
|
||||
pos.z = pos.z + 1
|
||||
for index1 = 0, height, step do --go through each level of the pyramid
|
||||
local newindex1 = (index1 + offset[axis]) * stride[axis] + 1 --offset contributed by axis plus 1 to make it 1-indexed
|
||||
for index2 = -size, size do
|
||||
local newindex2 = newindex1 + (index2 + offset[other1]) * stride[other1]
|
||||
for index3 = -size, size do
|
||||
local i = newindex2 + (index3 + offset[other2]) * stride[other2]
|
||||
nodes[i] = node_id
|
||||
end
|
||||
pos.x = pos.x + 1
|
||||
end
|
||||
count = count + ((pos2y - pos.y) * 2 + 1) ^ 2
|
||||
pos.y = pos.y + 1
|
||||
|
||||
pos1x, pos2x = pos1x + 1, pos2x - 1
|
||||
pos1z, pos2z = pos1z + 1, pos2z - 1
|
||||
|
||||
count = count + (size * 2 + 1) ^ 2
|
||||
size = size - 1
|
||||
end
|
||||
|
||||
--update map nodes
|
||||
manip:set_data(nodes)
|
||||
manip:write_to_map()
|
||||
manip:update_map()
|
||||
|
||||
return count
|
||||
end
|
||||
|
||||
--adds a spiral at `pos` with width `width`, height `height`, space between walls `spacer`, composed of `nodename`, returning the number of nodes added
|
||||
worldedit.spiral = function(pos, width, height, spacer, nodename, env) --wip: clean this up
|
||||
-- spiral matrix - http://rosettacode.org/wiki/Spiral_matrix#Lua
|
||||
av, sn = math.abs, function(s) return s~=0 and s/av(s) or 0 end
|
||||
local function sindex(z, x) -- returns the value at (x, z) in a spiral that starts at 1 and goes outwards
|
||||
if z == -x and z >= x then return (2*z+1)^2 end
|
||||
local l = math.max(av(z), av(x))
|
||||
return (2*l-1)^2+4*l+2*l*sn(x+z)+sn(z^2-x^2)*(l-(av(z)==l and sn(z)*x or sn(x)*z)) -- OH GOD WHAT
|
||||
--adds a spiral centered at `pos` with side length `length`, height `height`, space between walls `spacer`, composed of `nodename`, returning the number of nodes added
|
||||
worldedit.spiral = function(pos, length, height, spacer, nodename)
|
||||
local extent = math.ceil(length / 2)
|
||||
local pos1 = {x=pos.x - extent, y=pos.y, z=pos.z - extent}
|
||||
local pos2 = {x=pos.x + extent, y=pos.y + height, z=pos.z + extent}
|
||||
|
||||
--set up voxel manipulator
|
||||
local manip = minetest.get_voxel_manip()
|
||||
local emerged_pos1, emerged_pos2 = manip:read_from_map(pos1, pos2)
|
||||
local area = VoxelArea:new({MinEdge=emerged_pos1, MaxEdge=emerged_pos2})
|
||||
|
||||
--fill emerged area with ignore
|
||||
local nodes = {}
|
||||
local ignore = minetest.get_content_id("ignore")
|
||||
for i = 1, worldedit.volume(emerged_pos1, emerged_pos2) do
|
||||
nodes[i] = ignore
|
||||
end
|
||||
local function spiralt(side)
|
||||
local ret, id, start, stop = {}, 0, math.floor((-side+1)/2), math.floor((side-1)/2)
|
||||
for i = 1, side do
|
||||
for j = 1, side do
|
||||
local id = side^2 - sindex(stop - i + 1,start + j - 1)
|
||||
ret[id] = {x=i,z=j}
|
||||
|
||||
--
|
||||
local node_id = minetest.get_content_id(nodename)
|
||||
local stride = {x=1, y=area.ystride, z=area.zstride}
|
||||
local offsetx, offsety, offsetz = pos.x - emerged_pos1.x, pos.y - emerged_pos1.y, pos.z - emerged_pos1.z
|
||||
local i = offsetz * stride.z + offsety * stride.y + offsetx + 1
|
||||
|
||||
--add first column
|
||||
local column = i
|
||||
for y = 1, height do
|
||||
nodes[column] = node_id
|
||||
column = column + stride.y
|
||||
end
|
||||
|
||||
--add spiral segments
|
||||
local axis, other = "x", "z"
|
||||
local sign = 1
|
||||
local count = height
|
||||
for segment = 1, length / spacer - 1 do --go through each segment except the last
|
||||
for index = 1, segment * spacer do --fill segment
|
||||
i = i + stride[axis] * sign
|
||||
local column = i
|
||||
for y = 1, height do --add column
|
||||
nodes[column] = node_id
|
||||
column = column + stride.y
|
||||
end
|
||||
count = count + height
|
||||
end
|
||||
return ret
|
||||
end
|
||||
if env == nil then env = minetest.env end
|
||||
-- connect the joined parts
|
||||
local spiral = spiralt(width)
|
||||
height = tonumber(height)
|
||||
if height < 1 then height = 1 end
|
||||
spacer = tonumber(spacer)-1
|
||||
if spacer < 1 then spacer = 1 end
|
||||
local count = 0
|
||||
local node = {name=nodename}
|
||||
local np,lp
|
||||
for y=0,height do
|
||||
lp = nil
|
||||
for _,v in ipairs(spiral) do
|
||||
np = {x=pos.x+v.x*spacer, y=pos.y+y, z=pos.z+v.z*spacer}
|
||||
if lp~=nil then
|
||||
if lp.x~=np.x then
|
||||
if lp.x<np.x then
|
||||
for i=lp.x+1,np.x do
|
||||
env:add_node({x=i, y=np.y, z=np.z}, node)
|
||||
count = count + 1
|
||||
end
|
||||
else
|
||||
for i=np.x,lp.x-1 do
|
||||
env:add_node({x=i, y=np.y, z=np.z}, node)
|
||||
count = count + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
if lp.z~=np.z then
|
||||
if lp.z<np.z then
|
||||
for i=lp.z+1,np.z do
|
||||
env:add_node({x=np.x, y=np.y, z=i}, node)
|
||||
count = count + 1
|
||||
end
|
||||
else
|
||||
for i=np.z,lp.z-1 do
|
||||
env:add_node({x=np.x, y=np.y, z=i}, node)
|
||||
count = count + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
lp = np
|
||||
axis, other = other, axis --swap axes
|
||||
if segment % 2 == 1 then --change sign every other turn
|
||||
sign = -sign
|
||||
end
|
||||
end
|
||||
|
||||
--add shorter final segment
|
||||
for index = 1, (math.floor(length / spacer) - 2) * spacer do
|
||||
i = i + stride[axis] * sign
|
||||
local column = i
|
||||
for y = 1, height do --add column
|
||||
nodes[column] = node_id
|
||||
column = column + stride.y
|
||||
end
|
||||
count = count + height
|
||||
end
|
||||
print(minetest.serialize(nodes))
|
||||
--update map nodes
|
||||
manip:set_data(nodes)
|
||||
manip:write_to_map()
|
||||
manip:update_map()
|
||||
|
||||
return count
|
||||
end
|
@ -1,108 +0,0 @@
|
||||
worldedit = worldedit or {}
|
||||
|
||||
worldedit.queue = {}
|
||||
|
||||
worldedit.ENABLE_QUEUE = true
|
||||
worldedit.BLOCKS_PER_GLOBALSTEP = 512
|
||||
|
||||
minetest.register_globalstep(function(dtime)
|
||||
i = 1
|
||||
while i <= #worldedit.queue and i <= worldedit.BLOCKS_PER_GLOBALSTEP do
|
||||
idx = (#worldedit.queue + 1) - i -- we use the last entry, so we don't spend days moving stuff in the table because we removed the first entry
|
||||
if worldedit.queue[idx].t == "set_node" then
|
||||
minetest.env:set_node(worldedit.queue[idx].pos, worldedit.queue[idx].node)
|
||||
elseif worldedit.queue[idx].t == "remove_node" then
|
||||
minetest.env:remove_node(worldedit.queue[idx].pos)
|
||||
elseif worldedit.queue[idx].t == "place_node" then
|
||||
minetest.env:place_node(worldedit.queue[idx].pos, worldedit.queue[idx].node)
|
||||
elseif worldedit.queue[idx].t == "dig_node" then
|
||||
minetest.env:dig_node(worldedit.queue[idx].pos)
|
||||
elseif worldedit.queue[idx].t == "add_entity" then
|
||||
minetest.env:add_entity(worldedit.queue[idx].pos, worldedit.queue[idx].name)
|
||||
elseif worldedit.queue[idx].t == "add_item" then
|
||||
minetest.env:add_item(worldedit.queue[idx].pos, worldedit.queue[idx].item)
|
||||
elseif worldedit.queue[idx].t == "meta_from_table" then
|
||||
minetest.env:get_meta(worldedit.queue[idx].pos):from_table(worldedit.queue[idx].table)
|
||||
else
|
||||
print("Unknown queue event type: " .. worldedit.queue[idx].t)
|
||||
end
|
||||
table.remove(worldedit.queue, idx)
|
||||
i = i + 1
|
||||
end
|
||||
end)
|
||||
|
||||
function table.copy(t, seen)
|
||||
seen = seen or {}
|
||||
if t == nil then return nil end
|
||||
if seen[t] then return seen[t] end
|
||||
|
||||
local nt = {}
|
||||
for k, v in pairs(t) do
|
||||
if type(v) == 'table' then
|
||||
nt[k] = table.copy(v, seen)
|
||||
else
|
||||
nt[k] = v
|
||||
end
|
||||
end
|
||||
seen[t] = nt
|
||||
return nt
|
||||
end
|
||||
|
||||
local quene_setnode = function(self, pos_, node_)
|
||||
table.insert(worldedit.queue, {pos=table.copy(pos_), node=table.copy(node_), t="set_node"})
|
||||
end
|
||||
|
||||
local quene_removenode = function(self, pos_)
|
||||
table.insert(worldedit.queue, {pos=table.copy(pos_), t="remove_node"})
|
||||
end
|
||||
|
||||
local quene_placenode = function(self, pos_, node_)
|
||||
table.insert(worldedit.queue, {pos=table.copy(pos_), node=table.copy(node_), t="place_node"})
|
||||
end
|
||||
|
||||
local quene_dignode = function(self, pos_)
|
||||
table.insert(worldedit.queue, {pos=table.copy(pos_), t="dig_node"})
|
||||
end
|
||||
|
||||
local quene_addentity = function(self, pos_, name_)
|
||||
table.insert(worldedit.queue, {pos=table.copy(pos_), name=name_.."", t="add_entity"})
|
||||
end
|
||||
|
||||
local quene_additem = function(self, pos_, item_)
|
||||
table.insert(worldedit.queue, {pos=table.copy(pos_), item=item_.."", t="add_item"})
|
||||
end
|
||||
|
||||
local quene_setmeta = function(self, pos_, table_)
|
||||
table.insert(worldedit.queue, {pos=table.copy(pos_), table=table.copy(table_), t="meta_from_table"})
|
||||
end
|
||||
|
||||
local aliasmeta = {
|
||||
-- the other functions are left out because they are not used in worldedit
|
||||
to_table = function(self) return minetest.env:get_meta(self._pos):to_table() end,
|
||||
set_string = function(self, name_, value_) minetest.env:get_meta(self._pos):set_string(name_, value_) end,
|
||||
from_table = function(self, tbl) quene_setmeta(nil, self._pos, tbl) end,
|
||||
}
|
||||
|
||||
local get_meta_alias = function(self, pos)
|
||||
local am = table.copy(aliasmeta)
|
||||
am._pos = pos
|
||||
return am
|
||||
end
|
||||
|
||||
worldedit.quene_aliasenv = {
|
||||
-- ALL functions that are not just piped to the real minetest.env function must copy the arguments, not just reference them
|
||||
set_node = quene_setnode,
|
||||
add_node = quene_setnode,
|
||||
remove_node = quene_removenode,
|
||||
get_node = function(self, pos) return minetest.env:get_node(pos) end,
|
||||
get_node_or_nil = function(self, pos) return minetest.env:get_node_or_nil(pos) end,
|
||||
get_node_light = function(self, pos, timeofday) return minetest.env:get_node_light(pos, timeofday) end,
|
||||
place_node = quene_placenode,
|
||||
dig_node = quene_dignode,
|
||||
punch_node = function(self, pos) return minetest.env:punch_node(pos) end,
|
||||
get_meta = get_meta_alias,
|
||||
get_node_timer = function(self, pos) return minetest.env:get_node_timer(pos) end,
|
||||
add_entity = quene_addentity,
|
||||
add_item = quene_additem,
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
worldedit = worldedit or {}
|
||||
local minetest = minetest --local copy of global
|
||||
|
||||
--modifies positions `pos1` and `pos2` so that each component of `pos1` is less than or equal to its corresponding conent of `pos2`, returning two new positions
|
||||
worldedit.sort_pos = function(pos1, pos2)
|
||||
@ -32,26 +33,30 @@ worldedit.valueversion = function(value)
|
||||
end
|
||||
|
||||
--converts the region defined by positions `pos1` and `pos2` into a single string, returning the serialized data and the number of nodes serialized
|
||||
worldedit.serialize = function(pos1, pos2) --wip: check for ItemStacks and whether they can be serialized
|
||||
worldedit.serialize = function(pos1, pos2)
|
||||
--make area stay loaded
|
||||
local manip = minetest.get_voxel_manip()
|
||||
manip:read_from_map(pos1, pos2)
|
||||
|
||||
local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
|
||||
local pos = {x=pos1.x, y=0, z=0}
|
||||
local count = 0
|
||||
local result = {}
|
||||
local env = minetest.env
|
||||
local get_node, get_meta = minetest.get_node, minetest.get_meta
|
||||
while pos.x <= pos2.x do
|
||||
pos.y = pos1.y
|
||||
while pos.y <= pos2.y do
|
||||
pos.z = pos1.z
|
||||
while pos.z <= pos2.z do
|
||||
local node = env:get_node(pos)
|
||||
local node = get_node(pos)
|
||||
if node.name ~= "air" and node.name ~= "ignore" then
|
||||
count = count + 1
|
||||
local meta = env:get_meta(pos):to_table()
|
||||
local meta = get_meta(pos):to_table()
|
||||
|
||||
--convert metadata itemstacks to itemstrings
|
||||
for name, inventory in pairs(meta.inventory) do
|
||||
for index, stack in ipairs(inventory) do
|
||||
inventory[index] = stack:to_string()
|
||||
inventory[index] = stack.to_string and stack:to_string() or stack
|
||||
end
|
||||
end
|
||||
|
||||
@ -140,7 +145,24 @@ worldedit.allocate = function(originpos, value)
|
||||
count = count + 1
|
||||
end
|
||||
elseif version == 4 then --current nested table format
|
||||
local nodes = minetest.deserialize(value)
|
||||
--wip: this is a filthy hack that works surprisingly well
|
||||
value = value:gsub("return%s*{", "", 1):gsub("}%s*$", "", 1)
|
||||
local escaped = value:gsub("\\\\", "@@"):gsub("\\\"", "@@"):gsub("(\"[^\"]*\")", function(s) return string.rep("@", #s) end)
|
||||
local startpos, startpos1, endpos = 1, 1
|
||||
local nodes = {}
|
||||
while true do
|
||||
startpos, endpos = escaped:find("},%s*{", startpos)
|
||||
if not startpos then
|
||||
break
|
||||
end
|
||||
local current = value:sub(startpos1, startpos)
|
||||
table.insert(nodes, minetest.deserialize("return " .. current))
|
||||
startpos, startpos1 = endpos, endpos
|
||||
end
|
||||
table.insert(nodes, minetest.deserialize("return " .. value:sub(startpos1)))
|
||||
|
||||
--local nodes = minetest.deserialize(value) --wip: this is broken for larger tables in the current version of LuaJIT
|
||||
|
||||
count = #nodes
|
||||
for index = 1, count do
|
||||
local entry = nodes[index]
|
||||
@ -160,10 +182,15 @@ end
|
||||
|
||||
--loads the nodes represented by string `value` at position `originpos`, returning the number of nodes deserialized
|
||||
--contains code based on [table.save/table.load](http://lua-users.org/wiki/SaveTableToFile) by ChillCode, available under the MIT license (GPL compatible)
|
||||
worldedit.deserialize = function(originpos, value, env)
|
||||
worldedit.deserialize = function(originpos, value)
|
||||
--make area stay loaded --wip: not very performant
|
||||
local pos1, pos2 = worldedit.allocate(originpos, value)
|
||||
local manip = minetest.get_voxel_manip()
|
||||
manip:read_from_map(pos1, pos2)
|
||||
|
||||
local originx, originy, originz = originpos.x, originpos.y, originpos.z
|
||||
local count = 0
|
||||
if env == nil then env = minetest.env end
|
||||
local add_node, get_meta = minetest.add_node, minetest.get_meta
|
||||
local version = worldedit.valueversion(value)
|
||||
if version == 1 or version == 2 then --original flat table format
|
||||
--obtain the node table
|
||||
@ -190,33 +217,29 @@ worldedit.deserialize = function(originpos, value, env)
|
||||
local entry = nodes[index]
|
||||
local pos = entry[1]
|
||||
pos.x, pos.y, pos.z = originx - pos.x, originy - pos.y, originz - pos.z
|
||||
env:add_node(pos, entry[2])
|
||||
add_node(pos, entry[2])
|
||||
end
|
||||
else --previous meta flat table format
|
||||
for index = 1, #nodes do
|
||||
local entry = nodes[index]
|
||||
entry.x, entry.y, entry.z = originx + entry.x, originy + entry.y, originz + entry.z
|
||||
env:add_node(entry, entry) --entry acts both as position and as node
|
||||
env:get_meta(entry):from_table(entry.meta)
|
||||
add_node(entry, entry) --entry acts both as position and as node
|
||||
get_meta(entry):from_table(entry.meta)
|
||||
end
|
||||
end
|
||||
elseif version == 3 then --previous list format
|
||||
local pos = {x=0, y=0, z=0}
|
||||
local node = {name="", param1=0, param2=0}
|
||||
for x, y, z, name, param1, param2 in value:gmatch("([+-]?%d+)%s+([+-]?%d+)%s+([+-]?%d+)%s+([^%s]+)%s+(%d+)%s+(%d+)[^\r\n]*[\r\n]*") do --match node entries
|
||||
pos.x = originx + tonumber(x)
|
||||
pos.y = originy + tonumber(y)
|
||||
pos.z = originz + tonumber(z)
|
||||
node.name = name
|
||||
node.param1 = param1
|
||||
node.param2 = param2
|
||||
env:add_node(pos, node)
|
||||
pos.x, pos.y, pos.z = originx + tonumber(x), originy + tonumber(y), originz + tonumber(z)
|
||||
node.name, node.param1, node.param2 = name, param1, param2
|
||||
add_node(pos, node)
|
||||
count = count + 1
|
||||
end
|
||||
elseif version == 4 then --current nested table format
|
||||
--wip: this is a filthy hack that works surprisingly well
|
||||
value = value:gsub("return%s*{", "", 1):gsub("}%s*$", "", 1)
|
||||
local escaped = value:gsub("\\\\", "@@"):gsub("\\\"", "@@"):gsub("(\"[^\"]+\")", function(s) return string.rep("@", #s) end)
|
||||
local escaped = value:gsub("\\\\", "@@"):gsub("\\\"", "@@"):gsub("(\"[^\"]*\")", function(s) return string.rep("@", #s) end)
|
||||
local startpos, startpos1, endpos = 1, 1
|
||||
local nodes = {}
|
||||
while true do
|
||||
@ -228,14 +251,22 @@ worldedit.deserialize = function(originpos, value, env)
|
||||
table.insert(nodes, minetest.deserialize("return " .. current))
|
||||
startpos, startpos1 = endpos, endpos
|
||||
end
|
||||
table.insert(nodes, minetest.deserialize("return " .. value:sub(startpos1)))
|
||||
|
||||
--local nodes = minetest.deserialize(value) --wip: this is broken for larger tables in the current version of LuaJIT
|
||||
|
||||
--load the nodes
|
||||
count = #nodes
|
||||
for index = 1, count do
|
||||
local entry = nodes[index]
|
||||
entry.x, entry.y, entry.z = originx + entry.x, originy + entry.y, originz + entry.z
|
||||
env:add_node(entry, entry) --entry acts both as position and as node
|
||||
env:get_meta(entry):from_table(entry.meta)
|
||||
add_node(entry, entry) --entry acts both as position and as node
|
||||
end
|
||||
|
||||
--load the metadata
|
||||
for index = 1, count do
|
||||
local entry = nodes[index]
|
||||
get_meta(entry):from_table(entry.meta)
|
||||
end
|
||||
end
|
||||
return count
|
||||
|
@ -1,4 +1,5 @@
|
||||
worldedit = worldedit or {}
|
||||
local minetest = minetest --local copy of global
|
||||
|
||||
--modifies positions `pos1` and `pos2` so that each component of `pos1` is less than or equal to its corresponding conent of `pos2`, returning two new positions
|
||||
worldedit.sort_pos = function(pos1, pos2)
|
||||
@ -31,24 +32,27 @@ minetest.register_node("worldedit:placeholder", {
|
||||
})
|
||||
|
||||
--hides all nodes in a region defined by positions `pos1` and `pos2` by non-destructively replacing them with invisible nodes, returning the number of nodes hidden
|
||||
worldedit.hide = function(pos1, pos2, tenv)
|
||||
local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
|
||||
if env == nil then env = minetest.env end
|
||||
worldedit.hide = function(pos1, pos2)
|
||||
--make area stay loaded
|
||||
local manip = minetest.get_voxel_manip()
|
||||
manip:read_from_map(pos1, pos2)
|
||||
|
||||
local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
|
||||
local pos = {x=pos1.x, y=0, z=0}
|
||||
local placeholder = {name="worldedit:placeholder", param1=0, param2=0}
|
||||
local get_node, get_meta, add_node = minetest.get_node, minetest.get_meta, minetest.add_node
|
||||
while pos.x <= pos2.x do
|
||||
pos.y = pos1.y
|
||||
while pos.y <= pos2.y do
|
||||
pos.z = pos1.z
|
||||
while pos.z <= pos2.z do
|
||||
local node = env:get_node(pos)
|
||||
placeholder.param1, placeholder.param2 = node.param1, node.param2 --copy node's param1 and param2
|
||||
local data = env:get_meta(pos):to_table() --obtain metadata of original node
|
||||
env:add_node(pos, placeholder) --add placeholder node
|
||||
local meta = env:get_meta(pos) --obtain placeholder meta
|
||||
meta:from_table(data) --set placeholder metadata to the original node's metadata
|
||||
meta:set_string("worldedit_placeholder", node.name) --add the node's name
|
||||
local node = get_node(pos)
|
||||
if node.name ~= "worldedit:placeholder" then
|
||||
local data = get_meta(pos):to_table() --obtain metadata of original node
|
||||
data.fields.worldedit_placeholder = node.name --add the node's name
|
||||
node.name = "worldedit:placeholder" --set node name
|
||||
add_node(pos, node) --add placeholder node
|
||||
get_meta(pos):from_table(data) --set placeholder metadata to the original node's metadata
|
||||
end
|
||||
pos.z = pos.z + 1
|
||||
end
|
||||
pos.y = pos.y + 1
|
||||
@ -59,68 +63,54 @@ worldedit.hide = function(pos1, pos2, tenv)
|
||||
end
|
||||
|
||||
--suppresses all instances of `nodename` in a region defined by positions `pos1` and `pos2` by non-destructively replacing them with invisible nodes, returning the number of nodes suppressed
|
||||
worldedit.suppress = function(pos1, pos2, nodename, tenv)
|
||||
worldedit.suppress = function(pos1, pos2, nodename)
|
||||
--ignore placeholder supression
|
||||
if nodename == "worldedit:placeholder" then
|
||||
return 0
|
||||
end
|
||||
|
||||
--make area stay loaded
|
||||
local manip = minetest.get_voxel_manip()
|
||||
manip:read_from_map(pos1, pos2)
|
||||
|
||||
local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
|
||||
if env == nil then env = minetest.env end
|
||||
|
||||
if minetest.registered_nodes[nodename] == nil then
|
||||
nodename = "default:" .. nodename
|
||||
local nodes = minetest.find_nodes_in_area(pos1, pos2, nodename)
|
||||
local get_node, get_meta, add_node = minetest.get_node, minetest.get_meta, minetest.add_node
|
||||
for _, pos in ipairs(nodes) do
|
||||
local node = get_node(pos)
|
||||
local data = get_meta(pos):to_table() --obtain metadata of original node
|
||||
data.fields.worldedit_placeholder = node.name --add the node's name
|
||||
node.name = "worldedit:placeholder" --set node name
|
||||
add_node(pos, node) --add placeholder node
|
||||
get_meta(pos):from_table(data) --set placeholder metadata to the original node's metadata
|
||||
end
|
||||
|
||||
local pos = {x=pos1.x, y=0, z=0}
|
||||
local placeholder = {name="worldedit:placeholder", param1=0, param2=0}
|
||||
local count = 0
|
||||
while pos.x <= pos2.x do
|
||||
pos.y = pos1.y
|
||||
while pos.y <= pos2.y do
|
||||
pos.z = pos1.z
|
||||
while pos.z <= pos2.z do
|
||||
local node = env:get_node(pos)
|
||||
if node.name == nodename then
|
||||
placeholder.param1, placeholder.param2 = node.param1, node.param2 --copy node's param1 and param2
|
||||
local data = env:get_meta(pos):to_table() --obtain metadata of original node
|
||||
env:add_node(pos, placeholder) --add placeholder node
|
||||
local meta = env:get_meta(pos) --obtain placeholder meta
|
||||
meta:from_table(data) --set placeholder metadata to the original node's metadata
|
||||
meta:set_string("worldedit_placeholder", nodename) --add the node's name
|
||||
count = count + 1
|
||||
end
|
||||
pos.z = pos.z + 1
|
||||
end
|
||||
pos.y = pos.y + 1
|
||||
end
|
||||
pos.x = pos.x + 1
|
||||
end
|
||||
return count
|
||||
return #nodes
|
||||
end
|
||||
|
||||
--highlights all instances of `nodename` in a region defined by positions `pos1` and `pos2` by non-destructively hiding all other nodes, returning the number of nodes found
|
||||
worldedit.highlight = function(pos1, pos2, nodename, tenv)
|
||||
worldedit.highlight = function(pos1, pos2, nodename)
|
||||
--make area stay loaded
|
||||
local manip = minetest.get_voxel_manip()
|
||||
manip:read_from_map(pos1, pos2)
|
||||
|
||||
local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
|
||||
if env == nil then env = minetest.env end
|
||||
|
||||
if minetest.registered_nodes[nodename] == nil then
|
||||
nodename = "default:" .. nodename
|
||||
end
|
||||
|
||||
local pos = {x=pos1.x, y=0, z=0}
|
||||
local placeholder = {name="worldedit:placeholder", param1=0, param2=0}
|
||||
local get_node, get_meta, add_node = minetest.get_node, minetest.get_meta, minetest.add_node
|
||||
local count = 0
|
||||
while pos.x <= pos2.x do
|
||||
pos.y = pos1.y
|
||||
while pos.y <= pos2.y do
|
||||
pos.z = pos1.z
|
||||
while pos.z <= pos2.z do
|
||||
local node = env:get_node(pos)
|
||||
local node = get_node(pos)
|
||||
if node.name == nodename then --node found
|
||||
count = count + 1
|
||||
else --hide other nodes
|
||||
placeholder.param1, placeholder.param2 = node.param1, node.param2 --copy node's param1 and param2
|
||||
local data = env:get_meta(pos):to_table() --obtain metadata of original node
|
||||
env:add_node(pos, placeholder) --add placeholder node
|
||||
local meta = env:get_meta(pos) --obtain placeholder meta
|
||||
meta:from_table(data) --set placeholder metadata to the original node's metadata
|
||||
meta:set_string("worldedit_placeholder", node.name) --add the node's name
|
||||
elseif node.name ~= "worldedit:placeholder" then --hide other nodes
|
||||
local data = get_meta(pos):to_table() --obtain metadata of original node
|
||||
data.fields.worldedit_placeholder = node.name --add the node's name
|
||||
node.name = "worldedit:placeholder" --set node name
|
||||
add_node(pos, node) --add placeholder node
|
||||
get_meta(pos):from_table(data) --set placeholder metadata to the original node's metadata
|
||||
end
|
||||
pos.z = pos.z + 1
|
||||
end
|
||||
@ -132,33 +122,21 @@ worldedit.highlight = function(pos1, pos2, nodename, tenv)
|
||||
end
|
||||
|
||||
--restores all nodes hidden with WorldEdit functions in a region defined by positions `pos1` and `pos2`, returning the number of nodes restored
|
||||
worldedit.restore = function(pos1, pos2, tenv)
|
||||
local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
|
||||
if env == nil then env = minetest.env end
|
||||
worldedit.restore = function(pos1, pos2)
|
||||
--make area stay loaded
|
||||
local manip = minetest.get_voxel_manip()
|
||||
manip:read_from_map(pos1, pos2)
|
||||
|
||||
local pos = {x=pos1.x, y=0, z=0}
|
||||
local node = {name="", param1=0, param2=0}
|
||||
local count = 0
|
||||
while pos.x <= pos2.x do
|
||||
pos.y = pos1.y
|
||||
while pos.y <= pos2.y do
|
||||
pos.z = pos1.z
|
||||
while pos.z <= pos2.z do
|
||||
local currentnode = env:get_node(pos)
|
||||
if currentnode.name == "worldedit:placeholder" then
|
||||
node.param1, node.param2 = currentnode.param1, currentnode.param2 --copy node's param1 and param2
|
||||
local data = env:get_meta(pos):to_table() --obtain node metadata
|
||||
node.name = data.fields.worldedit_placeholder --set node name
|
||||
data.fields.worldedit_placeholder = nil --delete old nodename
|
||||
env:add_node(pos, node) --add original node
|
||||
env:get_meta(pos):from_table(data) --set original node metadata
|
||||
count = count + 1
|
||||
end
|
||||
pos.z = pos.z + 1
|
||||
end
|
||||
pos.y = pos.y + 1
|
||||
end
|
||||
pos.x = pos.x + 1
|
||||
local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
|
||||
local nodes = minetest.find_nodes_in_area(pos1, pos2, "worldedit:placeholder")
|
||||
local get_node, get_meta, add_node = minetest.get_node, minetest.get_meta, minetest.add_node
|
||||
for _, pos in ipairs(nodes) do
|
||||
local node = get_node(pos)
|
||||
local data = get_meta(pos):to_table() --obtain node metadata
|
||||
node.name = data.fields.worldedit_placeholder --set node name
|
||||
data.fields.worldedit_placeholder = nil --delete old nodename
|
||||
add_node(pos, node) --add original node
|
||||
get_meta(pos):from_table(data) --set original node metadata
|
||||
end
|
||||
return count
|
||||
return #nodes
|
||||
end
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,29 +1,82 @@
|
||||
worldedit.marker1 = {}
|
||||
worldedit.marker2 = {}
|
||||
worldedit.marker = {}
|
||||
|
||||
--wip: use this as a huge entity to make a full worldedit region box
|
||||
minetest.register_entity(":worldedit:region_cube", {
|
||||
initial_properties = {
|
||||
visual = "upright_sprite",
|
||||
visual_size = {x=1.1, y=1.1},
|
||||
textures = {"worldedit_pos1.png"},
|
||||
visual_size = {x=10, y=10},
|
||||
physical = false,
|
||||
},
|
||||
on_step = function(self, dtime)
|
||||
if self.active == nil then
|
||||
self.object:remove()
|
||||
end
|
||||
end,
|
||||
on_punch = function(self, hitter)
|
||||
--wip: remove the entire region marker
|
||||
end,
|
||||
})
|
||||
|
||||
--marks worldedit region position 1
|
||||
worldedit.mark_pos1 = function(name)
|
||||
local pos = worldedit.pos1[name]
|
||||
local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]
|
||||
|
||||
if pos1 ~= nil then
|
||||
--make area stay loaded
|
||||
local manip = minetest.get_voxel_manip()
|
||||
manip:read_from_map(pos1, pos1)
|
||||
end
|
||||
if worldedit.marker1[name] ~= nil then --marker already exists
|
||||
worldedit.marker1[name]:remove() --remove marker
|
||||
worldedit.marker1[name] = nil
|
||||
end
|
||||
if pos ~= nil then --add marker
|
||||
worldedit.marker1[name] = minetest.env:add_entity(pos, "worldedit:pos1")
|
||||
if pos1 ~= nil then
|
||||
--add marker
|
||||
worldedit.marker1[name] = minetest.add_entity(pos1, "worldedit:pos1")
|
||||
worldedit.marker1[name]:get_luaentity().active = true
|
||||
if pos2 ~= nil then --region defined
|
||||
worldedit.mark_region(pos1, pos2)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--marks worldedit region position 2
|
||||
worldedit.mark_pos2 = function(name)
|
||||
local pos = worldedit.pos2[name]
|
||||
local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]
|
||||
|
||||
if pos2 ~= nil then
|
||||
--make area stay loaded
|
||||
local manip = minetest.get_voxel_manip()
|
||||
manip:read_from_map(pos2, pos2)
|
||||
end
|
||||
if worldedit.marker2[name] ~= nil then --marker already exists
|
||||
worldedit.marker2[name]:remove() --remove marker
|
||||
worldedit.marker2[name] = nil
|
||||
end
|
||||
if pos ~= nil then --add marker
|
||||
worldedit.marker2[name] = minetest.env:add_entity(pos, "worldedit:pos2")
|
||||
if pos2 ~= nil then
|
||||
--add marker
|
||||
worldedit.marker2[name] = minetest.add_entity(pos2, "worldedit:pos2")
|
||||
worldedit.marker2[name]:get_luaentity().active = true
|
||||
if pos1 ~= nil then --region defined
|
||||
worldedit.mark_region(pos1, pos2)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
worldedit.mark_region = function(pos1, pos2)
|
||||
--make area stay loaded
|
||||
local manip = minetest.get_voxel_manip()
|
||||
manip:read_from_map(pos1, pos2)
|
||||
|
||||
if worldedit.marker[name] ~= nil then --marker already exists
|
||||
--wip: remove markers
|
||||
end
|
||||
if pos1 ~= nil and pos2 ~= nil then
|
||||
--wip: place markers
|
||||
end
|
||||
end
|
||||
|
||||
@ -35,6 +88,7 @@ minetest.register_entity(":worldedit:pos1", {
|
||||
"worldedit_pos1.png", "worldedit_pos1.png",
|
||||
"worldedit_pos1.png", "worldedit_pos1.png"},
|
||||
collisionbox = {-0.55, -0.55, -0.55, 0.55, 0.55, 0.55},
|
||||
physical = false,
|
||||
},
|
||||
on_step = function(self, dtime)
|
||||
if self.active == nil then
|
||||
@ -56,6 +110,7 @@ minetest.register_entity(":worldedit:pos2", {
|
||||
"worldedit_pos2.png", "worldedit_pos2.png",
|
||||
"worldedit_pos2.png", "worldedit_pos2.png"},
|
||||
collisionbox = {-0.55, -0.55, -0.55, 0.55, 0.55, 0.55},
|
||||
physical = false,
|
||||
},
|
||||
on_step = function(self, dtime)
|
||||
if self.active == nil then
|
||||
|
Reference in New Issue
Block a user