diff --git a/.docs/_data/contributors.js b/.docs/_data/contributors.js
index b03dacc..d9f8e6d 100644
--- a/.docs/_data/contributors.js
+++ b/.docs/_data/contributors.js
@@ -1,6 +1,6 @@
const fs = require("fs");
const path = require("path");
-const htmlentities = require("htmlentities");
+const htmlentities = require("html-entities");
function read_contributors() {
return fs.readFileSync(path.resolve(__dirname, "../../CONTRIBUTORS.tsv"), "utf-8")
diff --git a/.docs/images/gallery-d.jpeg b/.docs/images/gallery-d.jpeg
new file mode 100644
index 0000000..9bb51ad
Binary files /dev/null and b/.docs/images/gallery-d.jpeg differ
diff --git a/.docs/images/gallery-e.jpeg b/.docs/images/gallery-e.jpeg
new file mode 100644
index 0000000..e0d23eb
Binary files /dev/null and b/.docs/images/gallery-e.jpeg differ
diff --git a/.docs/index.html b/.docs/index.html
index 4c5d3e4..99eb7f2 100644
--- a/.docs/index.html
+++ b/.docs/index.html
@@ -16,7 +16,9 @@ date: 2000-01-01
Extra tools and commands to extend WorldEdit for Minetest
If you can dream of it, it probably belongs here!
- Get Started
+
+ Get Started
+
@@ -62,12 +64,18 @@ date: 2000-01-01
{% gallerybox "images/gallery-a.jpeg" "image-first" "image-last" "image-b" %}
A scene demonstrating //replacemix
, //ellipsoid
, //layers
, smoothadv
(aka convolve
and conv
), and //floodfill
- all of which are provided by WorldEditAdditions.
{% endgallerybox %}
- {% gallerybox "images/gallery-b.jpeg" "image-b" "image-first" "image-last" %}
+ {% gallerybox "images/gallery-b.jpeg" "image-b" "image-first" "image-c" %}
The inside of a 3d maze made with //maze3d
. Lighting was placed manually to improve screenshot quality.
{% endgallerybox %}
- {% gallerybox "images/gallery-c.jpeg" "image-last" "image-b" "image-first" %}
+ {% gallerybox "images/gallery-c.jpeg" "image-c" "image-b" "image-d" %}
A cliff made with //layers
and //erode
. A //forest
has been applied on top with multiple sapling / tree types.
{% endgallerybox %}
+ {% gallerybox "images/gallery-d.jpeg" "image-d" "image-c" "image-e" %}
+ A small mountain made with //layers
and //erode
, using the new optional //layers
slope constraints in WorldEditAdditions v1.13.
+ {% endgallerybox %}
+ {% gallerybox "images/gallery-e.jpeg" "image-e" "image-d" "image-first" %}
+ A small mesa canyons terrain scene made with //erode
, the new optional //layers
slope contraints, and //noiseapply2d
- the latter 2 of which are new in WorldEditAdditions v1.13. Minimal manual tuning was required.
+ {% endgallerybox %}
@@ -105,7 +113,7 @@ git clone https://github.com/sbrl/Minetest-WorldEditAdditions.git worldeditaddit
diff --git a/.docs/lib/parse_sections.js b/.docs/lib/parse_sections.js
index 4e5789d..5cdecf6 100644
--- a/.docs/lib/parse_sections.js
+++ b/.docs/lib/parse_sections.js
@@ -1,4 +1,4 @@
-const htmlentities = require("htmlentities");
+const htmlentities = require("html-entities");
const markdown = require("markdown-it")({
xhtmlOut: true
});
diff --git a/.docs/package-lock.json b/.docs/package-lock.json
index 3bc23b6..6f48460 100644
--- a/.docs/package-lock.json
+++ b/.docs/package-lock.json
@@ -8,11 +8,12 @@
"name": "worldeditadditions",
"version": "1.0.0",
"license": "MPL-2.0",
+ "dependencies": {
+ "html-entities": "^2.3.2"
+ },
"devDependencies": {
"@11ty/eleventy": "^0.12.1",
"@11ty/eleventy-img": "^0.9.0",
- "html-entities": "^2.3.2",
- "htmlentities": "^1.0.0",
"markdown-it-prism": "^2.1.8",
"phin": "^3.6.0"
}
@@ -1870,14 +1871,7 @@
"node_modules/html-entities": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.2.tgz",
- "integrity": "sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ==",
- "dev": true
- },
- "node_modules/htmlentities": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/htmlentities/-/htmlentities-1.0.0.tgz",
- "integrity": "sha1-CTqMH7Cd/l4Wn8M9CVdIJdYeQKQ=",
- "dev": true
+ "integrity": "sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ=="
},
"node_modules/http-errors": {
"version": "1.7.3",
@@ -6169,14 +6163,7 @@
"html-entities": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.2.tgz",
- "integrity": "sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ==",
- "dev": true
- },
- "htmlentities": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/htmlentities/-/htmlentities-1.0.0.tgz",
- "integrity": "sha1-CTqMH7Cd/l4Wn8M9CVdIJdYeQKQ=",
- "dev": true
+ "integrity": "sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ=="
},
"http-errors": {
"version": "1.7.3",
diff --git a/.docs/package.json b/.docs/package.json
index 27ec9cc..538f0ed 100644
--- a/.docs/package.json
+++ b/.docs/package.json
@@ -22,9 +22,10 @@
"devDependencies": {
"@11ty/eleventy": "^0.12.1",
"@11ty/eleventy-img": "^0.9.0",
- "html-entities": "^2.3.2",
- "htmlentities": "^1.0.0",
"markdown-it-prism": "^2.1.8",
"phin": "^3.6.0"
+ },
+ "dependencies": {
+ "html-entities": "^2.3.2"
}
}
diff --git a/.luacheckrc b/.luacheckrc
index c3a1473..b4d086c 100644
--- a/.luacheckrc
+++ b/.luacheckrc
@@ -31,6 +31,7 @@ read_globals = {
"it",
"describe",
"bonemeal",
- "dofile"
+ "dofile",
+ "PerlinNoise"
}
std = "max"
diff --git a/CHANGELOG.md b/CHANGELOG.md
index c6cc91f..cf327de 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,11 +10,25 @@ Note to self: See the bottom of this file for the release template text.
- Add `//wcorner` (_wireframe corners_), `//wbox` (_wireframe box_), `//compass` (_wireframe compass_) - Wireframes implemented by @VorTechnix.
- Add `//for` for executing commands while changing their arguments - Implemented by @VorTechnix.
- Add `//sshift` (_selection shift_) - WorldEdit cuboid manipulator replacements implemented by @VorTechnix.
+ - Add `//noise2d` for perturbing terrain with multiple different noise functions
+ - Add `//noiseapply2d` for running commands on columns where a noise value is over a threshold
- Use [luacheck](https://github.com/mpeterv/luacheck) to find and fix a large number of bugs and other issues
- Multiple commands: Allow using quotes (`"thing"`, `'thing'`) to quote values when splitting
- `//layers`: Add optional slope constraint (inspired by [WorldPainter](https://worldpainter.net/))
- `//bonemeal`: Add optional node list constraint
- `//walls`: Add optional thickness argument
+ - `//sstack`: Add human-readable approx volumes of regions in the selection stack
+
+
+### Bugfixes
+ - `//airapply`: Improve error handling, fix safe_region node counter
+ - `//floodfill`: Fix crash caused by internal refactoring of the `Queue` data structure
+ - `//spop`: Fix wording in displayed message
+ - Sapling alias compatibility:
+ - Correct alias of `default:sapling` from `oak` to `apple` (since it produces apples)
+ - `moretrees:apple_tree_sapling_ongen` from `apple` to `apple_moretrees`
+ - Add `plum` → `plumtree:sapling`
+ - Add `holly` ⇒ `hollytree:sapling`
## v1.12: The selection tools update (26th June 2021)
diff --git a/Chat-Command-Reference.md b/Chat-Command-Reference.md
index 1efcebc..0ab854f 100644
--- a/Chat-Command-Reference.md
+++ b/Chat-Command-Reference.md
@@ -532,7 +532,7 @@ Applies 2D noise to the terrain in the defined region. Like `//erode`, this comm
Parameter | Type | Default Value | Description
------------|-----------|---------------|-----------------------
-algorithm | `string` | perlin | The 2D noise algorithm to apply - see below.
+algorithm | `string` | perlinmt | The 2D noise algorithm to apply - see below.
apply | `string|integer` | 5 | How to apply the noise to the terrain - see below.
scalex | `float` | 1 | The scale of the noise on the x axis.
scaley | `float` | 1 | The scale of the noise on the y axis.
@@ -555,7 +555,8 @@ The following algorithms are currently available:
Algorithm | Description
------------|--------------------------
-`perlin` | Perlin noise. Functional, but currently contains artefacts I'm having difficulty tracking down.
+`perlinmt` | **Default**.Perlin noise, backed by Minetest's inbuilt `PerlinNoise` class.
+`perlin` | Perlin noise, backed by a pure Lua perlin noise implementation. Functional, but currently contains artefacts I'm having difficulty tracking down.
`sin` | A sine wave created with `math.sin()`.
`white` | Random white noise.
`red` | Red noise - has a lower frequency than white noise. Ref [Noise Functions and Map Generation by Red Blob Games](https://www.redblobgames.com/articles/noise/introduction.html).
@@ -681,6 +682,21 @@ As with `//ellipsoidapply` for advanced users `//multi` is also supported - but
```
+## `//noiseapply2d `
+Like [`//ellipsoidapply`](#ellipsoidapply), but instead only keeps changes where a noise function (defaults to `perlinmt`, see [`//noise2d`](#noise2d)) returns a value greater than a given threshold value.
+
+Also takes a scale value that controls the scale of the noise - -higher values result in smaller "blobs". If you're operating on small areas, then a value of at least 10 is advised as "blobs" are by default on the scale of ~50 nodes.
+
+As with `//ellipsoidapply` for advanced users `//multi` is also supported - but make sure your modifications stay within the defined region - otherwise they be kept regardless, as `//noiseapply2d` only applies the masking to the nodes in the defined region.
+
+Any suggestions on how to provide more customisability without making this command more difficult to use or significantly more inconsistent with other `//*apply` functions are welcome - please [open an issue](https://github.com/sbrl/Minetest-WorldEditAdditions/issues/new).
+
+```weacmd
+//noiseapply2d 0.5 10 set dirt
+//noiseapply2d 0.4 3 layers dirt_with_snow dirt 3 stone 10
+```
+
+
## `//scol [ ] `
Short for _select column_. Sets the pos2 at a set distance along 1 axis from pos1. If the axis isn't specified, defaults the direction you are facing. Implementation thanks to @VorTechnix.
diff --git a/Cookbook.md b/Cookbook.md
index 824e7c9..146fecd 100644
--- a/Cookbook.md
+++ b/Cookbook.md
@@ -43,7 +43,13 @@ The following brushes together can make large-scale terrain sculpting easy:
```
## En-mass Foliage clearing
-Clearing large amounts of foliage is easy!
+Clearing large amounts of foliage is easy with the new `//subdivide` function!
+
+```
+//subdivide 20 20 20 //clearcut
+```
+
+Another good way to clear large chunk of land is with `//many`:
```
//many 25 //multi //clearcut //y //shift x 10
diff --git a/README.md b/README.md
index 9bc9379..e49deca 100644
--- a/README.md
+++ b/README.md
@@ -28,59 +28,62 @@ _(Do you have a cool build that you used WorldEditAdditions to build? [Get in to
The detailed explanations have moved! Check them out [here](https://github.com/sbrl/Minetest-WorldEditAdditions/blob/main/Chat-Command-Reference.md), or click the links below.
### Geometry
- - [`//ellipsoid [h[ollow]]`](https://github.com/sbrl/Minetest-WorldEditAdditions/blob/main/Chat-Command-Reference.md#ellipsoid-rx-ry-rz-node_name-hollow)
- - [`//hollowellipsoid `](https://github.com/sbrl/Minetest-WorldEditAdditions/blob/main/Chat-Command-Reference.md#hollowellipsoid-rx-ry-rz-node_name)
- - [`//torus [ [h[ollow]]]`](https://github.com/sbrl/Minetest-WorldEditAdditions/blob/main/Chat-Command-Reference.md#torus-major_radius-minor_radius-node_name-axesxy-hollow)
- - [`//hollowtorus []`](https://github.com/sbrl/Minetest-WorldEditAdditions/blob/main/Chat-Command-Reference.md#hollowtorus-major_radius-minor_radius-node_name-axesxy)
- - [`//walls `](https://github.com/sbrl/Minetest-WorldEditAdditions/blob/main/Chat-Command-Reference.md#walls-replace_node)
- - [`//line [ []]`](https://github.com/sbrl/Minetest-WorldEditAdditions/blob/main/Chat-Command-Reference.md#line-replace_node-radius)
- - [`//hollow []`](https://github.com/sbrl/Minetest-WorldEditAdditions/blob/main/Chat-Command-Reference.md#hollow-wall_thickness)
- - [`//maze [ [ []]]`](https://github.com/sbrl/Minetest-WorldEditAdditions/blob/main/Chat-Command-Reference.md#maze-replace_node-path_length-path_width-seed)
- - [`//maze3d [ [ [ []]]]`](https://github.com/sbrl/Minetest-WorldEditAdditions/blob/main/Chat-Command-Reference.md#maze3d-replace_node-path_length-path_width-path_depth-seed)
+ - [`//ellipsoid [h[ollow]]`](https://worldeditadditions.mooncarrot.space/Reference/#ellipsoid)
+ - [`//hollowellipsoid `](https://worldeditadditions.mooncarrot.space/Reference/#hollowellipsoid)
+ - [`//torus [ [h[ollow]]]`](https://worldeditadditions.mooncarrot.space/Reference/#torus)
+ - [`//hollowtorus []`](https://worldeditadditions.mooncarrot.space/Reference/#hollowtorus)
+ - [`//walls `](https://worldeditadditions.mooncarrot.space/Reference/#walls)
+ - [`//line [ []]`](https://worldeditadditions.mooncarrot.space/Reference/#line)
+ - [`//hollow []`](https://worldeditadditions.mooncarrot.space/Reference/#hollow)
+ - [`//maze [ [ []]]`](https://worldeditadditions.mooncarrot.space/Reference/#maze)
+ - [`//maze3d [ [ [ []]]]`](https://worldeditadditions.mooncarrot.space/Reference/#maze3d)
### Misc
- - [`//replacemix [] [] [ []] [ []] ....`](https://github.com/sbrl/Minetest-WorldEditAdditions/blob/main/Chat-Command-Reference.md#replacemix-target_node-chance-replace_node_a-chance_a-replace_node_b-chance_b-replace_node_n-chance_n-)
- - [`//floodfill [ []]`](https://github.com/sbrl/Minetest-WorldEditAdditions/blob/main/Chat-Command-Reference.md#floodfill-replace_node-radius-floodfill)
- - [`//scale | [ [ ]]`](https://github.com/sbrl/Minetest-WorldEditAdditions/blob/main/Chat-Command-Reference.md#scale-axis-scale_factor--factor_x-factor_y-factor_z-anchor_x-anchor_y-anchor_z) **experimental**
+ - [`//replacemix [] [] [ []] [ []] ....`](https://worldeditadditions.mooncarrot.space/Reference/#replacemix)
+ - [`//floodfill [ []]`](https://worldeditadditions.mooncarrot.space/Reference/#floodfill)
+ - [`//scale | [ [ ]]`](https://worldeditadditions.mooncarrot.space/Reference/#scale) **experimental**
### Terrain
- - [`//overlay [] [] [ []] ...`](https://github.com/sbrl/Minetest-WorldEditAdditions/blob/main/Chat-Command-Reference.md#overlay-node_name_a-chance_a-node_name_b-chance_b-node_name_n-chance_n-)
- - [`//layers [ []] [ []] ...`](https://github.com/sbrl/Minetest-WorldEditAdditions/blob/main/Chat-Command-Reference.md#layers-node_name_1-layer_count_1-node_name_2-layer_count_2-)
- - [`//fillcaves []`](https://github.com/sbrl/Minetest-WorldEditAdditions/blob/main/Chat-Command-Reference.md#fillcaves-node_name)
- - [`//convolve [[,]] []`](https://github.com/sbrl/Minetest-WorldEditAdditions/blob/main/Chat-Command-Reference.md#convolve-kernel-widthheight-sigma)
- - [`//erode [ [ []] [ []] ...]`](https://github.com/sbrl/Minetest-WorldEditAdditions/blob/main/Chat-Command-Reference.md#erode-snowballsriver-key_1-value_1-key_2-value_2-) **experimental**
+ - [`//overlay [] [] [ []] ...`](https://worldeditadditions.mooncarrot.space/Reference/#overlay)
+ - [`//layers [ []] [ []] ...`](https://worldeditadditions.mooncarrot.space/Reference/#layers)
+ - [`//fillcaves []`](https://worldeditadditions.mooncarrot.space/Reference/#fillcaves)
+ - [`//convolve [[,]] []`](https://worldeditadditions.mooncarrot.space/Reference/#convolve)
+ - [`//erode [ [ []] [ []] ...]`](https://worldeditadditions.mooncarrot.space/Reference/#erode) **experimental**
+ - [`//noise2d [ []] [ []] ...]`](https://worldeditadditions.mooncarrot.space/Reference/#noise2d)
### Flora
- [`//bonemeal [ []]`](https://github.com/sbrl/Minetest-WorldEditAdditions/blob/main/Chat-Command-Reference.md#bonemeal-strength-chance)
- - [`//forest [] [] [] [ []] ...`](https://github.com/sbrl/Minetest-WorldEditAdditions/blob/main/Chat-Command-Reference.md#forest-density-sapling_a-chance_a-sapling_b-chance_b-sapling_N-chance_N-) _(new in v1.9)_
- - [`//saplingaliases [aliases|all_saplings]`](https://github.com/sbrl/Minetest-WorldEditAdditions/blob/main/Chat-Command-Reference.md#saplingaliases-aliasesall_saplings) _(new in v1.9)_
+ - [`//forest [] [] [] [ []] ...`](https://worldeditadditions.mooncarrot.space/Reference/#forest) _(new in v1.9)_
+ - [`//saplingaliases [aliases|all_saplings]`](https://worldeditadditions.mooncarrot.space/Reference/#saplingaliases) _(new in v1.9)_
### Statistics
- - [`//count`](https://github.com/sbrl/Minetest-WorldEditAdditions/blob/main/Chat-Command-Reference.md#count)
+ - [`//count`](https://worldeditadditions.mooncarrot.space/Reference/#count)
### Selection
- - [`//scol [ ] `](https://github.com/sbrl/Minetest-WorldEditAdditions/blob/main/Chat-Command-Reference.md#scol-axis1--length)
- - [`//srect [ []] `](https://github.com/sbrl/Minetest-WorldEditAdditions/blob/main/Chat-Command-Reference.md#srect-axis1-axis2-length)
- - [`//scube [ [ []]] `](https://github.com/sbrl/Minetest-WorldEditAdditions/blob/main/Chat-Command-Reference.md#scube-axis1-axis2-axis3-length)
- - [`//scloud <0-6|stop|reset>`](https://github.com/sbrl/Minetest-WorldEditAdditions/blob/main/Chat-Command-Reference.md#scloud-0-6stopreset)
- - [`//scentre`](https://github.com/sbrl/Minetest-WorldEditAdditions/blob/main/Chat-Command-Reference.md#scentre)
- - [`//srel [ [ ]]`](https://github.com/sbrl/Minetest-WorldEditAdditions/blob/main/Chat-Command-Reference.md#srel-axis1-length1-axis2-length2-axis3-length3)
- - [`//smake [ []]`](https://github.com/sbrl/Minetest-WorldEditAdditions/blob/main/Chat-Command-Reference.md#smake-operationoddevenequal-modegrowshrinkaverage-targetxz-base)
- - [`//sstack`](https://github.com/sbrl/Minetest-WorldEditAdditions/blob/main/Chat-Command-Reference.md#sstack)
- - [`//spush`](https://github.com/sbrl/Minetest-WorldEditAdditions/blob/main/Chat-Command-Reference.md#spush)
- - [`//spop`](https://github.com/sbrl/Minetest-WorldEditAdditions/blob/main/Chat-Command-Reference.md#spop)
+ - [`//scol [ ] `](https://worldeditadditions.mooncarrot.space/Reference/#scol)
+ - [`//srect [ []] `](https://worldeditadditions.mooncarrot.space/Reference/#srect)
+ - [`//scube [ [ []]] `](https://worldeditadditions.mooncarrot.space/Reference/#scube)
+ - [`//scloud <0-6|stop|reset>`](https://worldeditadditions.mooncarrot.space/Reference/#scloud)
+ - [`//scentre`](https://worldeditadditions.mooncarrot.space/Reference/#scentre)
+ - [`//srel [ [ ]]`](https://worldeditadditions.mooncarrot.space/Reference/#srel)
+ - [`//smake [ []]`](https://worldeditadditions.mooncarrot.space/Reference/#smake)
+ - [`//sstack`](https://worldeditadditions.mooncarrot.space/Reference/#sstack)
+ - [`//spush`](https://worldeditadditions.mooncarrot.space/Reference/#spush)
+ - [`//spop`](https://worldeditadditions.mooncarrot.space/Reference/#spop)
### Measure
- - [`//mface`](Chat-Command-Reference.md#mface)
- - [`//midpos`](Chat-Command-Reference.md#midpos)
- - [`//msize`](Chat-Command-Reference.md#msize)
- - [`//mtrig`](Chat-Command-Reference.md#mtrig)
+ - [`//mface`](https://worldeditadditions.mooncarrot.space/Reference/#mface) _(new in v1.13)_
+ - [`//midpos`](https://worldeditadditions.mooncarrot.space/Reference/#midpos) _(new in v1.13)_
+ - [`//msize`](https://worldeditadditions.mooncarrot.space/Reference/#msize) _(new in v1.13)_
+ - [`//mtrig`](https://worldeditadditions.mooncarrot.space/Reference/#mtrig) _(new in v1.13)_
### Meta
- - [`//multi ....`](https://github.com/sbrl/Minetest-WorldEditAdditions/blob/main/Chat-Command-Reference.md#multi-command_a-command_b-command_c-)
- - [`//many `](https://github.com/sbrl/Minetest-WorldEditAdditions/blob/main/Chat-Command-Reference.md#many-times-command) _(new in v1.9)_
- - [`//subdivide `](https://github.com/sbrl/Minetest-WorldEditAdditions/blob/main/Chat-Command-Reference.md#subdivide-size_x-size_y-size_z-cmd_name-args) **experimental**
- - [`//ellipsoidapply `](https://github.com/sbrl/Minetest-WorldEditAdditions/blob/main/Chat-Command-Reference.md#ellipsoidapply-command_name-args) _(new in v1.9)_
+ - [`//multi ....`](https://worldeditadditions.mooncarrot.space/Reference/#multi)
+ - [`//many `](https://worldeditadditions.mooncarrot.space/Reference/#many) _(new in v1.9)_
+ - [`//subdivide `](https://worldeditadditions.mooncarrot.space/Reference/#subdivide)
+ - [`//ellipsoidapply `](https://worldeditadditions.mooncarrot.space/Reference/#ellipsoidapply) _(new in v1.9)_
+ - [`//airapply `](https://worldeditadditions.mooncarrot.space/Reference/#airapply) _(new in v1.9)_
+ - [`//noiseapply2d `](https://worldeditadditions.mooncarrot.space/Reference/#noiseapply2d) _(new in v1.13)_
### Extras
- [`//y`](https://github.com/sbrl/Minetest-WorldEditAdditions/blob/main/Chat-Command-Reference.md#y)
diff --git a/worldeditadditions/init.lua b/worldeditadditions/init.lua
index 1360a81..81cb234 100644
--- a/worldeditadditions/init.lua
+++ b/worldeditadditions/init.lua
@@ -62,6 +62,7 @@ dofile(wea.modpath.."/lib/forest.lua")
dofile(wea.modpath.."/lib/ellipsoidapply.lua")
dofile(wea.modpath.."/lib/airapply.lua")
+dofile(wea.modpath.."/lib/noiseapply2d.lua")
dofile(wea.modpath.."/lib/subdivide.lua")
diff --git a/worldeditadditions/lib/compat/saplingnames.lua b/worldeditadditions/lib/compat/saplingnames.lua
index 15e9ea2..2938597 100644
--- a/worldeditadditions/lib/compat/saplingnames.lua
+++ b/worldeditadditions/lib/compat/saplingnames.lua
@@ -16,7 +16,7 @@ Alternatively, you can register support in your mod directly. Do that by adding
if minetest.get_modpath("default") then
worldeditadditions.register_sapling_alias_many({
- { "default:sapling", "oak" },
+ { "default:sapling", "apple" },
{ "default:bush_sapling", "bush" },
{ "default:pine_sapling", "pine" },
{ "default:pine_bush_sapling", "pine_bush" },
@@ -40,7 +40,7 @@ if minetest.get_modpath("moretrees") then
{ "moretrees:willow_sapling_ongen", "willow_moretrees" },
{ "moretrees:poplar_sapling_ongen", "poplar" },
{ "moretrees:poplar_small_sapling_ongen", "poplar_small" },
- { "moretrees:apple_tree_sapling_ongen", "apple" },
+ { "moretrees:apple_tree_sapling_ongen", "apple_moretrees" },
{ "moretrees:birch_sapling_ongen", "birch_moretrees" },
{ "moretrees:palm_sapling_ongen", "palm_moretrees" },
{ "moretrees:date_palm_sapling_ongen", "palm_date" },
@@ -110,6 +110,12 @@ end
if minetest.get_modpath("palm") then
worldeditadditions.register_sapling_alias("palm:sapling", "palm")
end
+if minetest.get_modpath("plumtree") then
+ worldeditadditions.register_sapling_alias("plumtree:sapling", "plum")
+end
+if minetest.get_modpath("hollytree") then
+ worldeditadditions.register_sapling_alias("hollytree:sapling", "holly")
+end
if minetest.get_modpath("pomegranate") then
worldeditadditions.register_sapling_alias("pomegranate:sapling", "pomegranate")
end
diff --git a/worldeditadditions/lib/floodfill.lua b/worldeditadditions/lib/floodfill.lua
index bfefe28..e1b5691 100644
--- a/worldeditadditions/lib/floodfill.lua
+++ b/worldeditadditions/lib/floodfill.lua
@@ -27,8 +27,7 @@ function worldeditadditions.floodfill(start_pos, radius, replace_node)
end
local count = 0
- local remaining_nodes = wea.Queue.new()
- remaining_nodes:enqueue(start_pos_index)
+ local remaining_nodes = wea.Queue.new() remaining_nodes:enqueue(start_pos_index)
-- Do the floodfill
while remaining_nodes:is_empty() == false do
diff --git a/worldeditadditions/lib/noise/engines/init.lua b/worldeditadditions/lib/noise/engines/init.lua
index 38cd625..2266d70 100644
--- a/worldeditadditions/lib/noise/engines/init.lua
+++ b/worldeditadditions/lib/noise/engines/init.lua
@@ -2,8 +2,9 @@ local wea = worldeditadditions
return {
- available = { "perlin", "sin", "white", "red", "infrared" },
+ available = { "perlin", "perlinmt", "sin", "white", "red", "infrared" },
Perlin = dofile(wea.modpath.."/lib/noise/engines/perlin.lua"),
+ PerlinMT = dofile(wea.modpath.."/lib/noise/engines/perlinmt.lua"),
Sin = dofile(wea.modpath.."/lib/noise/engines/sin.lua"),
White = dofile(wea.modpath.."/lib/noise/engines/white.lua"),
Red = dofile(wea.modpath.."/lib/noise/engines/red.lua"),
diff --git a/worldeditadditions/lib/noise/engines/perlinmt.lua b/worldeditadditions/lib/noise/engines/perlinmt.lua
new file mode 100644
index 0000000..711f429
--- /dev/null
+++ b/worldeditadditions/lib/noise/engines/perlinmt.lua
@@ -0,0 +1,32 @@
+local wea = worldeditadditions
+
+
+local PerlinMT = {}
+PerlinMT.__index = PerlinMT
+
+
+function PerlinMT.new(seed, params)
+ if not seed then seed = 0 end
+ local result = {
+ -- Provided by Minetest
+ engine = PerlinNoise({
+ offset = 0,
+ scale = 1,
+ spread = {x = 50, y = 50, z = 50},
+ seed = seed,
+ octaves = 1,
+ persistence = 0.63,
+ lacunarity = 2.0,
+ flags = "defaults,absvalue",
+ })
+ }
+ setmetatable(result, PerlinMT)
+ return result
+end
+
+function PerlinMT:noise( x, y, z )
+ local value = self.engine:get_3d(wea.Vector3.new(x, y, z))
+ return value
+end
+
+return PerlinMT
diff --git a/worldeditadditions/lib/noise/make_2d.lua b/worldeditadditions/lib/noise/make_2d.lua
index 92e4972..2c69949 100644
--- a/worldeditadditions/lib/noise/make_2d.lua
+++ b/worldeditadditions/lib/noise/make_2d.lua
@@ -11,12 +11,16 @@ local wea = worldeditadditions
-- @param size Vector An x/y vector representing the size of the noise area to generate.
-- @param params table|table A table of noise params to use to generate the noise. Values that aren't specified are filled in automatically. If a table of tables is specified, it is interpreted as multiple octaves of noise to apply in sequence.
function worldeditadditions.noise.make_2d(size, start_pos, params)
+ params = worldeditadditions.noise.params_apply_default(params)
+
local result = {}
for layer_i, layer in ipairs(params) do
local generator
if layer.algorithm == "perlin" then
generator = wea.noise.engines.Perlin.new()
+ elseif layer.algorithm == "perlinmt" then
+ generator = wea.noise.engines.PerlinMT.new()
elseif layer.algorithm == "sin" then
generator = wea.noise.engines.Sin.new()
elseif layer.algorithm == "white" then
diff --git a/worldeditadditions/lib/noise/params_apply_default.lua b/worldeditadditions/lib/noise/params_apply_default.lua
index e1121ad..a2bf2fd 100644
--- a/worldeditadditions/lib/noise/params_apply_default.lua
+++ b/worldeditadditions/lib/noise/params_apply_default.lua
@@ -13,7 +13,7 @@ function worldeditadditions.noise.params_apply_default(params)
-- - A string in the form of digits followed, then the noise will is remapped from the range 0 - 1 to the range -1 - +1 and multiplied by this number / 2, and then for each pixel in the heightmap the corresponding noise value will be added to it.
apply = 5,
-- The backend noise algorithm to use
- algorithm = "perlin",
+ algorithm = "perlinmt",
-- Zooms in and out
scale = wea.Vector3.new(1, 1, 1),
-- Offset the generated noise by this vector.
diff --git a/worldeditadditions/lib/noiseapply2d.lua b/worldeditadditions/lib/noiseapply2d.lua
new file mode 100644
index 0000000..844ba99
--- /dev/null
+++ b/worldeditadditions/lib/noiseapply2d.lua
@@ -0,0 +1,60 @@
+-- ███ ██ ██████ ██ ███████ ███████ █████ ██████ ██████ ██ ██ ██ ██████ ██████
+-- ████ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
+-- ██ ██ ██ ██ ██ ██ ███████ █████ ███████ ██████ ██████ ██ ████ █████ ██ ██
+-- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
+-- ██ ████ ██████ ██ ███████ ███████ ██ ██ ██ ██ ███████ ██ ███████ ██████
+
+--- Similar to cubeapply, except that it takes 2 positions and randomly keeps changes based on a noise pattern.
+-- Takes a backup copy of the defined region, runs the given function, and then
+-- restores the bits that aren't above the nosie threshold.
+-- @param {Position} pos1 The 1st position defining the region boundary
+-- @param {Position} pos2 The 2nd positioon defining the region boundary
+-- @param {Function} func The function to call that performs the action in question. It is expected that the given function will accept no arguments.
+function worldeditadditions.noiseapply2d(pos1, pos2, threshold, scale, func)
+ local time_taken_all = worldeditadditions.get_ms_time()
+ pos1, pos2 = worldeditadditions.Vector3.sort(pos1, pos2)
+ if not threshold then threshold = 0.5 end
+ -- pos2 will always have the highest co-ordinates now
+
+ -- Fetch the nodes in the specified area
+ local manip_before, area_before = worldedit.manip_helpers.init(pos1, pos2)
+ local data_before = manip_before:get_data()
+
+ local time_taken_fn = worldeditadditions.get_ms_time()
+ func()
+ time_taken_fn = worldeditadditions.get_ms_time() - time_taken_fn
+
+ local manip_after, area_after = worldedit.manip_helpers.init(pos1, pos2)
+ local data_after = manip_after:get_data()
+
+ local size2d = pos2 - pos1 + worldeditadditions.Vector3.new(1, 1, 1)
+ print("DEBUG pos1", pos1, "pos2", pos2, "size2d", size2d)
+ local success, noise = worldeditadditions.noise.make_2d(size2d, pos1, {
+ algorithm = "perlinmt",
+ scale = scale
+ })
+ if not success then return success, noise end
+
+ for z = pos2.z, pos1.z, -1 do
+ for y = pos2.y, pos1.y, -1 do
+ for x = pos2.x, pos1.x, -1 do
+ local i_before = area_before:index(x, y, z)
+ local i_after = area_after:index(x, y, z)
+
+ local i_noise = (z-pos1.z)*size2d.x + (x-pos1.x)
+
+ -- Roll everything where the noise function returns less than 0.5
+ if noise[i_noise] < threshold then
+ data_after[i_after] = data_before[i_before]
+ end
+ end
+ end
+ end
+
+ -- Save the modified nodes back to disk & return
+ -- No need to save - this function doesn't actually change anything
+ worldedit.manip_helpers.finish(manip_after, data_after)
+
+ time_taken_all = worldeditadditions.get_ms_time() - time_taken_all
+ return true, { all = time_taken_all, fn = time_taken_fn }
+end
diff --git a/worldeditadditions/utils/queue.lua b/worldeditadditions/utils/queue.lua
index a00f1e5..197ff2e 100644
--- a/worldeditadditions/utils/queue.lua
+++ b/worldeditadditions/utils/queue.lua
@@ -61,7 +61,7 @@ function Queue:dequeue()
-- Find the next non-nil item
local value
while value == nil do
- if first >= self.last then return nil end
+ if first > self.last then return nil end
value = self.items[first]
self.items[first] = nil -- Help the garbage collector out
first = first + 1
diff --git a/worldeditadditions_commands/commands/meta/airapply.lua b/worldeditadditions_commands/commands/meta/airapply.lua
index 5cd3331..bd0f548 100644
--- a/worldeditadditions_commands/commands/meta/airapply.lua
+++ b/worldeditadditions_commands/commands/meta/airapply.lua
@@ -38,8 +38,10 @@ worldedit.register_command("airapply", {
return true, cmd_we, args_parsed
end,
nodes_needed = function(name)
- local pos1, pos2 = worldedit.sort_pos(worldedit.pos1[name], worldedit.pos2[name])
- return math.ceil(4/3 * math.pi * (pos2.x - pos1.x)/2 * (pos2.y - pos1.y)/2 * (pos2.z - pos1.z)/2)
+ return worldedit.volume(
+ worldedit.pos1[name],
+ worldedit.pos2[name]
+ )
end,
func = function(name, cmd, args_parsed)
if not minetest.check_player_privs(name, cmd.privs) then
@@ -56,8 +58,9 @@ worldedit.register_command("airapply", {
pos1, pos2,
function()
cmd.func(name, worldeditadditions.table.unpack(args_parsed))
- end, args_parsed
+ end
)
+ if not success then return success, stats_time end
local time_overhead = 100 - worldeditadditions.round((stats_time.fn / stats_time.all) * 100, 3)
diff --git a/worldeditadditions_commands/commands/meta/noiseapply2d.lua b/worldeditadditions_commands/commands/meta/noiseapply2d.lua
new file mode 100644
index 0000000..14d127c
--- /dev/null
+++ b/worldeditadditions_commands/commands/meta/noiseapply2d.lua
@@ -0,0 +1,87 @@
+-- ███ ██ ██████ ██ ███████ ███████ █████ ██████ ██████ ██ ██ ██ ██████ ██████
+-- ████ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
+-- ██ ██ ██ ██ ██ ██ ███████ █████ ███████ ██████ ██████ ██ ████ █████ ██ ██
+-- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
+-- ██ ████ ██████ ██ ███████ ███████ ██ ██ ██ ██ ███████ ██ ███████ ██████
+
+
+worldedit.register_command("noiseapply2d", {
+ params = " ",
+ description = "Executes the given command (automatically prepending '//'), but uses a 2d noise function with both a threshold value (a number between 0 and 1) and a scale value (number, 1 = normal scale, for small areas 10+ is recommended) to filter where in the defined region it's applied.",
+ privs = { worldedit = true },
+ require_pos = 2,
+ parse = function(params_text)
+ if params_text == "" then return false, "Error: No command specified." end
+
+ local threshold_text, scale_text, cmd_name, args_text = params_text:match("([^%s]+)%s+([^%s]+)%s+([^%s]+)%s*(.*)")
+ if not args_text then
+ args_text = ""
+ end
+
+ -- Note that we search the worldedit commands here, not the minetest ones
+ local cmd_we = worldedit.registered_commands[cmd_name]
+ if cmd_we == nil then
+ return false, "Error: "..cmd_name.." isn't a valid command."
+ end
+ if cmd_we.require_pos ~= 2 and cmd_name ~= "multi" then
+ return false, "Error: The command "..cmd_name.." exists, but doesn't take 2 positions and so can't be used with //noiseapply2d."
+ end
+
+ -- Run parsing of target command
+ -- Lifted from cubeapply in WorldEdit
+ local args_parsed = {cmd_we.parse(args_text)}
+ if not table.remove(args_parsed, 1) then
+ return false, args_parsed[1]
+ end
+
+ local threshold = tonumber(threshold_text)
+ if not threshold then
+ return false, "Error: Invalid threshold value '"..threshold_text.."'. Threshold values should be a floating-point number between 0 and 1."
+ end
+ if threshold < 0 or threshold > 1 then
+ return false, "Error: The threshold value '"..threshold.."' is out of bounds. Threshold values should be floating-point numbers between 0 and 1."
+ end
+ local scale = tonumber(scale_text)
+ if not scale then
+ return false, "Error: Invalid scale value '"..threshold_text.."'. Threshold values should be a floating-point number between 0 and 1."
+ end
+
+ return true, 1 - threshold, scale, cmd_we, args_parsed
+ end,
+ nodes_needed = function(name)
+ return worldedit.volume(
+ worldedit.pos1[name],
+ worldedit.pos2[name]
+ )
+ end,
+ func = function(name, threshold, scale, cmd, args_parsed)
+ if not minetest.check_player_privs(name, cmd.privs) then
+ return false, "Your privileges are insufficient to execute the command '"..cmd.."'."
+ end
+
+ local pos1, pos2 = worldeditadditions.Vector3.sort(
+ worldedit.pos1[name],
+ worldedit.pos2[name]
+ )
+
+
+ local success, stats_time = worldeditadditions.noiseapply2d(
+ pos1, pos2,
+ threshold,
+ worldeditadditions.Vector3.new(
+ scale, scale, scale
+ ),
+ function()
+ cmd.func(name, worldeditadditions.table.unpack(args_parsed))
+ end
+ )
+ if not success then return success, stats_time end
+
+ local time_overhead = 100 - worldeditadditions.round((stats_time.fn / stats_time.all) * 100, 3)
+ local text_time_all = worldeditadditions.format.human_time(stats_time.all)
+ local text_time_fn = worldeditadditions.format.human_time(stats_time.fn)
+
+ minetest.log("action", name.." used //noiseapply2d at "..pos1.." - "..pos2.." in "..text_time_all)
+ return true, "Complete in "..text_time_all.." ("..text_time_fn.." fn, "..time_overhead.."% noiseapply2d overhead)"
+ end
+})
diff --git a/worldeditadditions_commands/commands/selectors/spop.lua b/worldeditadditions_commands/commands/selectors/spop.lua
index 0e3ea9c..a7f1ba8 100644
--- a/worldeditadditions_commands/commands/selectors/spop.lua
+++ b/worldeditadditions_commands/commands/selectors/spop.lua
@@ -27,7 +27,7 @@ worldedit.register_command("spop", {
local region_text = worldeditadditions.vector.tostring(worldedit.pos1[name]).." - "..worldeditadditions.vector.tostring(worldedit.pos2[name])
- minetest.log("action", name .. " used //spush at "..region_text..". Stack height is now " .. new_count.." regions")
- return true, "Region "..region_text.." pushed onto selection stack; "..new_count.." region"..plural.." now in the stack"
+ minetest.log("action", name .. " used //spopped at "..region_text..". Stack height is now " .. new_count.." regions")
+ return true, "Region "..region_text.." popped from selection stack; "..new_count.." region"..plural.." now in the stack"
end
})
diff --git a/worldeditadditions_commands/commands/selectors/sstack.lua b/worldeditadditions_commands/commands/selectors/sstack.lua
index 6ff4cac..e748d2d 100644
--- a/worldeditadditions_commands/commands/selectors/sstack.lua
+++ b/worldeditadditions_commands/commands/selectors/sstack.lua
@@ -20,8 +20,15 @@ worldedit.register_command("sstack", {
table.insert(result, "(empty)")
else
for i,item in ipairs(worldeditadditions.sstack[name]) do
+ local volume = worldedit.volume(item[1], item[2])
+ local volume_text = worldeditadditions.format.human_size(volume, 2)
+ if volume > 1000 then volume_text = "~"..volume_text end
+
table.insert(result, i)
table.insert(result, ": ")
+
+ table.insert(result, volume_text)
+ table.insert(result, " nodes - ")
table.insert(result, worldeditadditions.vector.tostring(item[1]))
table.insert(result, " - ")
table.insert(result, worldeditadditions.vector.tostring(item[2]))