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]))