From 25e6ff467ce866b6931d2065142861a3f2bc1ee8 Mon Sep 17 00:00:00 2001 From: Starbeamrainbowlabs Date: Sat, 26 Jun 2021 02:26:06 +0100 Subject: [PATCH 01/32] //smake: describe operation & mode a bit better --- Chat-Command-Reference.md | 2 +- worldeditadditions_commands/commands/selectors/smake.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Chat-Command-Reference.md b/Chat-Command-Reference.md index 3629ed5..ca3f633 100644 --- a/Chat-Command-Reference.md +++ b/Chat-Command-Reference.md @@ -602,7 +602,7 @@ Short for _select relative_. Sets the pos2 at set distances along 3 axes relativ //scube -z 12 -y -2 x -2 ``` -## `//smake [ []]` +## `//smake [ []]` Short for _selection make_. Modifies existing selection by moving pos2. Allows you to make the selection an odd or even length on one or more axes or set two or more axes equal to each other or the longest, shortest or average of them. Implementation thanks to @VorTechnix. Usage examples: diff --git a/worldeditadditions_commands/commands/selectors/smake.lua b/worldeditadditions_commands/commands/selectors/smake.lua index 6dcab3f..5c05f2e 100644 --- a/worldeditadditions_commands/commands/selectors/smake.lua +++ b/worldeditadditions_commands/commands/selectors/smake.lua @@ -5,7 +5,7 @@ -- ███████ ██ ██ ██ ██ ██ ██ ███████ local wea = worldeditadditions worldedit.register_command("smake", { - params = " [ []]", + params = " [ []]", description = "Make one or more axes of the current selection odd, even, or equal to another.", privs = { worldedit = true }, require_pos = 2, From 0aff7aa4760ae0ece3a0862e7b7e7494e9bdd5df Mon Sep 17 00:00:00 2001 From: Starbeamrainbowlabs Date: Sat, 26 Jun 2021 02:35:11 +0100 Subject: [PATCH 02/32] Reference: tidy up markdown etc --- Chat-Command-Reference.md | 61 +++++++++++++++++++++++---------------- 1 file changed, 36 insertions(+), 25 deletions(-) diff --git a/Chat-Command-Reference.md b/Chat-Command-Reference.md index ca3f633..1285866 100644 --- a/Chat-Command-Reference.md +++ b/Chat-Command-Reference.md @@ -505,6 +505,7 @@ While other server commands can be executed while a `//subdivide` is running, `/ //subdivice 25 25 25 fixlight ``` + ## `//multi .....` Executes multi chat commands in sequence. Intended for _WorldEdit_ commands, but does work with others too. Don't forget a space between commands! @@ -528,6 +529,7 @@ In addition, this also allows for including a double forward slash in the argume //multi /time 7:00 //1 //outset h 20 //outset v 5 //overlay dirt_with_grass //1 //2 //sphere 8 air //shift down 1 //floodfill //reset ``` + ## `//many ` Executes a single chat command many times in a row. Uses `minetest.after()` to yield to the main server thread to allow other things to happen at the same time, so technically you could have multiple `//many` calls going at once (but multithreading support is out of reach, so only a single one will be executing at the same time). @@ -538,6 +540,7 @@ Note that this isn't necessarily limited to executing WorldEdit / WorldEditAddit //many 100 //multi //1 //2 //outset 20 //set dirt ``` + ## `//ellipsoidapply ` Executes the given command, and then clips the result to the largest ellipsoid that will fit inside the defined region. The specified command must obviously take 2 positions - so for example `//set`, `//replacemix`, and `//maze3d` will work, but `//sphere`, `//torus`, and `//floodfill` won't. @@ -549,6 +552,7 @@ Executes the given command, and then clips the result to the largest ellipsoid t //ellipsoidapply layers desert_sand sand 2 desert_sandstone 4 sandstone 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. @@ -557,6 +561,7 @@ Short for _select column_. Sets the pos2 at a set distance along 1 axis from pos //scol x 3 ``` + ## `//srect [ []] ` Short for _select rectangle_. Sets the pos2 at a set distance along 2 axes from pos1. If the axes aren't specified, defaults to positive y and the direction you are facing. Implementation thanks to @VorTechnix. @@ -566,6 +571,7 @@ Short for _select rectangle_. Sets the pos2 at a set distance along 2 axes from //srect -z y 25 ``` + ## `//scube [ [ []]] ` Short for _select cube_. Sets the pos2 at a set distance along 3 axes from pos1. If the axes aren't specified, defaults to positive y, the direction you are facing and the axis to the left of facing. Implementation thanks to @VorTechnix. @@ -576,6 +582,7 @@ Short for _select cube_. Sets the pos2 at a set distance along 3 axes from pos1. //scube -z 12 ``` + ## `//scloud <0-6|stop|reset>` Short for _select point cloud_. Sets pos1 and pos2 to include the nodes you punch. Numbers 1-6 designate how many nodes you want to punch before the operation ends. 0 or stop terminate the operation so that any further nodes you punch won't be added to selection. Reset terminates operation if one is running and resets the selection area. @@ -585,6 +592,7 @@ Short for _select point cloud_. Sets pos1 and pos2 to include the nodes you punc //scloud stop ``` + ## `//scentre` Short for _select center_. Sets pos1 and pos2 to the centre point(s) of the current selection area. 1, 2, 4 or 8 nodes may be selected depending on what parts of the original selection are even in distance. Implementation thanks to @VorTechnix. @@ -592,6 +600,7 @@ Short for _select center_. Sets pos1 and pos2 to the centre point(s) of the curr //scentre ``` + ## `//srel [ [ ]]` Short for _select relative_. Sets the pos2 at set distances along 3 axes relative to pos1. If pos1 is not set it will default to the node directly under the player. The axis arguments accept `x, y, z` as well as `up, down, left, right, front, back`. Left, right, front and back are relative to player facing direction. Negative (`-`) can be applied to the axis, the length or both. Implementation thanks to @VorTechnix. @@ -602,6 +611,7 @@ Short for _select relative_. Sets the pos2 at set distances along 3 axes relativ //scube -z 12 -y -2 x -2 ``` + ## `//smake [ []]` Short for _selection make_. Modifies existing selection by moving pos2. Allows you to make the selection an odd or even length on one or more axes or set two or more axes equal to each other or the longest, shortest or average of them. Implementation thanks to @VorTechnix. @@ -615,41 +625,41 @@ Usage examples: //smake equal zy x ``` -### ``: odd/even/equal/factor +### ``: odd|even|equal|factor -|Value | Description | -| --- | --- | -odd: | round up or down, based on mode, all axes specified in `` to the nearest odd length relative to pos1 -even: | round up or down, based on mode, all axes specified in `` to the nearest even length relative to pos1 -equal: | set `` axes length equal to the length of `` axis if specified or to the length of the largest, smallest or average of the `` axes based on mode. +Value | Description +--------|--------------- +odd | Round up or down, based on mode, all axes specified in `` to the nearest odd length relative to pos1 +even | Round up or down, based on mode, all axes specified in `` to the nearest even length relative to pos1 +equal | Set `` axes length equal to the length of `` axis if specified or to the length of the largest, smallest or average of the `` axes based on mode. -### `:` grow/shrink/average +### ``: grow|shrink|average #### *If `` == odd or even:* -|Value | Description | -| --- | --- | -grow: | grow each axis specified in `` to the nearest odd/even number to itself -shrink: | shrink each axis specified in `` to the nearest odd/even number to itself -average/avg: | take the average of all axes specified in `` and then for each specified axis grow or shrink it, depending on weather it is less than or greater than the average, to the nearest odd/even number to itself +Value | Description +------------|-------------- +grow | Grow each axis specified in `` to the nearest odd/even number to itself +shrink | Shrink each axis specified in `` to the nearest odd/even number to itself +average/avg | Take the average of all axes specified in `` and then for each specified axis grow or shrink it, depending on weather it is less than or greater than the average, to the nearest odd/even number to itself -#### *If `` == equal:* ^[1] +#### *If `` == equal:* +The `` argument can be omitted and will not be parsed if present if `` is specified -|Value | Description | -| --- | --- | -grow: | grow each axis specified in `` to the length of the longest specified axis -shrink: | shrink each axis specified in `` to the length of the shortest specified axis -average/avg: | set each axis specified in `` to the average length of all the specified axes +Value | Description +------------|--------------- +grow | Grow each axis specified in `` to the length of the longest specified axis +shrink | Shrink each axis specified in `` to the length of the shortest specified axis +average/avg | Set each axis specified in `` to the average length of all the specified axes ### Additional arguments: -|Name | Description | -| --- | --- | -``: | Specify axes to perform operation on (default= xz)| -``: If `` == odd or even: | Does nothing -``: If `` == equal: | Overrides ``^[1] and sets all `` axes equal to itself - -^[1]: `` argument can be omitted and will not be parsed if present if `` is specified +Name | Description +------------|------------------ +`` | Specify axes to perform operation on (default= xz)| +``: If `` == odd or even | Does nothing +``: If `` == equal | Overrides ``^[1] and sets all `` axes equal to itself + ## `//sstack` Displays the contents of your per-user selection stack. This stack can be pushed to and popped from rather like a stack of plates. See also `//spush` (for pushing to the selection stack) and `//spop` (for popping from the selection stack). @@ -658,6 +668,7 @@ Displays the contents of your per-user selection stack. This stack can be pushed //sstack ``` + ## `//spush` Pushes the currently defined region onto your per-user selection stack. Does not otherwise alter the defined region. From 401af8cc3554f3fbcf4481f9da848b14681e37b8 Mon Sep 17 00:00:00 2001 From: Starbeamrainbowlabs Date: Sat, 26 Jun 2021 11:51:37 +0100 Subject: [PATCH 03/32] Reference: tweak //smake some more --- Chat-Command-Reference.md | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/Chat-Command-Reference.md b/Chat-Command-Reference.md index 1285866..09e16b0 100644 --- a/Chat-Command-Reference.md +++ b/Chat-Command-Reference.md @@ -629,28 +629,28 @@ Usage examples: Value | Description --------|--------------- -odd | Round up or down, based on mode, all axes specified in `` to the nearest odd length relative to pos1 -even | Round up or down, based on mode, all axes specified in `` to the nearest even length relative to pos1 -equal | Set `` axes length equal to the length of `` axis if specified or to the length of the largest, smallest or average of the `` axes based on mode. +`odd` | Round up or down, based on mode, all axes specified in `` to the nearest odd length relative to pos1 +`even` | Round up or down, based on mode, all axes specified in `` to the nearest even length relative to pos1 +`equal` | Set `` axes length equal to the length of `` axis if specified or to the length of the largest, smallest or average of the `` axes based on mode. ### ``: grow|shrink|average #### *If `` == odd or even:* -Value | Description -------------|-------------- -grow | Grow each axis specified in `` to the nearest odd/even number to itself -shrink | Shrink each axis specified in `` to the nearest odd/even number to itself -average/avg | Take the average of all axes specified in `` and then for each specified axis grow or shrink it, depending on weather it is less than or greater than the average, to the nearest odd/even number to itself +Value | Description +----------------|-------------- +`grow` | Grow each axis specified in `` to the nearest odd/even number to itself +`shrink` | Shrink each axis specified in `` to the nearest odd/even number to itself +`average`|`avg` | Take the average of all axes specified in `` and then for each specified axis grow or shrink it, depending on weather it is less than or greater than the average, to the nearest odd/even number to itself #### *If `` == equal:* The `` argument can be omitted and will not be parsed if present if `` is specified -Value | Description -------------|--------------- -grow | Grow each axis specified in `` to the length of the longest specified axis -shrink | Shrink each axis specified in `` to the length of the shortest specified axis -average/avg | Set each axis specified in `` to the average length of all the specified axes +Value | Description +----------------|--------------- +`grow` | Grow each axis specified in `` to the length of the longest specified axis +`shrink` | Shrink each axis specified in `` to the length of the shortest specified axis +`average`|`avg` | Set each axis specified in `` to the average length of all the specified axes ### Additional arguments: From 07579a2e757088251aedde5ba9cd410763cdb02b Mon Sep 17 00:00:00 2001 From: Starbeamrainbowlabs Date: Sat, 26 Jun 2021 11:56:49 +0100 Subject: [PATCH 04/32] =?UTF-8?q?Reference=20=E2=86=92=20//smake:=20Remove?= =?UTF-8?q?=20factor=20from=20operation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Chat-Command-Reference.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Chat-Command-Reference.md b/Chat-Command-Reference.md index 09e16b0..9200ec0 100644 --- a/Chat-Command-Reference.md +++ b/Chat-Command-Reference.md @@ -625,7 +625,7 @@ Usage examples: //smake equal zy x ``` -### ``: odd|even|equal|factor +### ``: odd|even|equal Value | Description --------|--------------- From bcc3f8e285413bb5e1c806fc367d5867a3f1bcf8 Mon Sep 17 00:00:00 2001 From: Starbeamrainbowlabs Date: Sat, 26 Jun 2021 12:06:01 +0100 Subject: [PATCH 05/32] README: Update quick reference with //smake --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index f55fb03..bfed01f 100644 --- a/README.md +++ b/README.md @@ -65,6 +65,7 @@ The detailed explanations have moved! Check them out [here](https://github.com/s - [`//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) From 1d096f7e8cdf78af4450b83dbfda635702ea853d Mon Sep 17 00:00:00 2001 From: Starbeamrainbowlabs Date: Sat, 26 Jun 2021 12:06:15 +0100 Subject: [PATCH 06/32] Prepare v1.12 release --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b1813d..b9b28d1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ It's about time I started a changelog! This will serve from now on as the main c Note to self: See the bottom of this file for the release template text. -## v1.12: The selection tools update (unreleased) +## v1.12: The selection tools update - Add `//spush`, `//spop`, and `//sstack` - Add `//srect` (_select rectangle_), `//scol` (_select column_), `//scube` (_select cube_) - thanks, @VorTechnix! - Add `//scloud` (_select point cloud_), `//scentre` (_select centre node(s)_), `//srel` (_select relative_) - thanks, @VorTechnix! From a403a55ac74b31c6cf9433aa474b4d052c361d83 Mon Sep 17 00:00:00 2001 From: Starbeamrainbowlabs Date: Sat, 26 Jun 2021 12:13:33 +0100 Subject: [PATCH 07/32] Changelog: tweak ordering --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b9b28d1..d885754 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,6 @@ Note to self: See the bottom of this file for the release template text. - Add `//scloud` (_select point cloud_), `//scentre` (_select centre node(s)_), `//srel` (_select relative_) - thanks, @VorTechnix! - Add `//smake` (_selection make_) - thanks, @VorTechnix! - Significantly refactored backend utility functions (more to come in future updates) - - `//bonemeal`: Try bonemealing everything that isn't an air block (#49) - Add new universal chance parsing - Any `` can now either be a 1-in-N number (e.g. `4`, `10`), or a percentage chance (e.g. `50%`, `10%`). - Caveat: Percentages are converted to a 1-in-N chance, but additionally that number is rounded down in some places @@ -19,6 +18,7 @@ Note to self: See the bottom of this file for the release template text. - `//erode`: Add new `river` erosion algorithm for filling in potholes and removing pillars ### Bugfixes + - `//bonemeal`: Try bonemealing everything that isn't an air block (#49) - `//overlay`: Don't place nodes above water - `//multi`: Improve resilience by handling some edge cases - `//layers`: Fix crash due to outdated debug code From b5c45533b7885fa86633561569ee09a9607d3090 Mon Sep 17 00:00:00 2001 From: Starbeamrainbowlabs Date: Sat, 26 Jun 2021 12:20:31 +0100 Subject: [PATCH 08/32] README: Add cloud wand to quick reference --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index bfed01f..0db3fd5 100644 --- a/README.md +++ b/README.md @@ -82,6 +82,7 @@ The detailed explanations have moved! Check them out [here](https://github.com/s ### Tools - [WorldEditAdditions Far Wand](https://github.com/sbrl/Minetest-WorldEditAdditions/blob/main/Chat-Command-Reference.md#far-wand) + - [WorldEditAdditions Cloud Wand](https://github.com/sbrl/Minetest-WorldEditAdditions/blob/main/Chat-Command-Reference.md#cloud-wand) - [`//farwand skip_liquid (true|false) | maxdist `](https://github.com/sbrl/Minetest-WorldEditAdditions/blob/main/Chat-Command-Reference.md#farwand-skip_liquid-truefalse--maxdist-number) From 5b26bbc0b8bf4eeda188ac601b4dcdb564d85a53 Mon Sep 17 00:00:00 2001 From: Starbeamrainbowlabs Date: Sat, 26 Jun 2021 12:26:15 +0100 Subject: [PATCH 09/32] Add release date for 1.12 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d885754..d4fe01c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ It's about time I started a changelog! This will serve from now on as the main c Note to self: See the bottom of this file for the release template text. -## v1.12: The selection tools update +## v1.12: The selection tools update (26th June 2021) - Add `//spush`, `//spop`, and `//sstack` - Add `//srect` (_select rectangle_), `//scol` (_select column_), `//scube` (_select cube_) - thanks, @VorTechnix! - Add `//scloud` (_select point cloud_), `//scentre` (_select centre node(s)_), `//srel` (_select relative_) - thanks, @VorTechnix! From bf71aae1d3b0232505646030c0a7d8d71f5604b1 Mon Sep 17 00:00:00 2001 From: Starbeamrainbowlabs Date: Sat, 26 Jun 2021 13:03:42 +0100 Subject: [PATCH 10/32] Docs/Reference: Remove arguments from command slugs --- .docs/lib/parse_sections.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.docs/lib/parse_sections.js b/.docs/lib/parse_sections.js index d9e4678..eaf807c 100644 --- a/.docs/lib/parse_sections.js +++ b/.docs/lib/parse_sections.js @@ -15,7 +15,8 @@ module.exports = function parse_sections(source) { result.push({ title: htmlentities.encode(title), slug: title.toLowerCase().replace(/[^a-z0-9-_\s]+/gi, "") - .replace(/\s+/g, "-"), + .replace(/\s+/g, "-") + .replace(/-.*$/, ""), content: markdown.render(acc.slice(1).join("\n")) }); } From 597f6d778fb16c7b797f31754d3f56d5d98d41f0 Mon Sep 17 00:00:00 2001 From: Starbeamrainbowlabs Date: Sat, 26 Jun 2021 13:06:35 +0100 Subject: [PATCH 11/32] docs/tutorial: Update links --- .docs/Tutorial.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.docs/Tutorial.md b/.docs/Tutorial.md index 4982348..e8c6d41 100644 --- a/.docs/Tutorial.md +++ b/.docs/Tutorial.md @@ -27,10 +27,10 @@ Explaining core WorldEdit commands is out of scope of this tutorial, but you can The purpose of _WorldEditAdditions_ is to extend _WorldEdit_ by adding additional commands. Example commands that have been implemented that are not present in core _WorldEdit_ include (but certainly aren't limited to): - - [`//maze`](/Reference/#maze-replace_node-path_length-path_width-seed): Create instant mazes - - [`//forest`](/Reference/#forest-density-sapling_a-chance_a-sapling_b-chance_b-sapling_n-chance_n-): Plant forests - - [`//torus`](http://localhost:8080/Reference/#torus-major_radius-minor_radius-node_name-axesxy-hollow): Generate [torus](https://en.wikipedia.org/wiki/Torus) shapes - - [`//scale`](/Reference/#scale-axis-scale_factor-factor_x-factor_y-factor_z-anchor_x-anchor_y-anchor_z): Scale things up and down - even both at the same time! + - [`//maze`](/Reference/#maze): Create instant mazes + - [`//forest`](/Reference/#forest): Plant forests + - [`//torus`](http://localhost:8080/Reference/#torus): Generate [torus](https://en.wikipedia.org/wiki/Torus) shapes + - [`//scale`](/Reference/#scale): Scale things up and down - even both at the same time! See a full list with complete explanations in the [chat command reference](/Reference). @@ -98,9 +98,9 @@ A number of additional concepts that are not required to use WorldEditAdditions ### Meta commands WorldEditAdditions provides a number of *meta commands*. Such commands don't do anything on their own, but call other commands in various different ways. Examples of meta commands include: - - [`//subdivide`](/Reference#subdivide-size_x-size_y-size_z-cmd_name-args): split a region into chunks, and execute the command once for each chunk - - [`//many`](/Reference#many-times-command): Execute a command multiple times - - [`//multi`](/Reference#multi-command_a-command_b-command_c-): Execute multiple commands in sequence + - [`//subdivide`](/Reference#subdivide): split a region into chunks, and execute the command once for each chunk + - [`//many`](/Reference#many): Execute a command multiple times + - [`//multi`](/!node_modules, !_sitemulti): Execute multiple commands in sequence Of course, this isn't an exhaustive list - check the [reference](/Reference) for a full list. @@ -109,7 +109,7 @@ Memory (or RAM - Random Access Memory) is used by all the processes running on a Depending on your system, Minetest and your system can slow to a crawl or even crash if you execute a command on a region that's too big. -To work around this, the [`//subdivide`](/Reference#subdivide-size_x-size_y-size_z-cmd_name-args) command was implemented. It splits the defined region into chunks, and calls the specified command over and over again for each chunk. +To work around this, the [`//subdivide`](/Reference#subdivide) command was implemented. It splits the defined region into chunks, and calls the specified command over and over again for each chunk. It's not suitable for all commands (since it requires that said command takes 2 points) though, but because it splits the defined region into multiple chunks, it can be executed on *enormous* regions that can't fit into memory all at the same time. From 9d197aefd210b18d09d009110149008cad763963 Mon Sep 17 00:00:00 2001 From: Starbeamrainbowlabs Date: Sat, 26 Jun 2021 14:10:28 +0100 Subject: [PATCH 12/32] Start implementing vector3. Currently we have the 4 basic operations down, plus tostring. --- .tests/Vector3/add.test.lua | 104 ++++++++++++++++++++ .tests/Vector3/divide.test.lua | 80 +++++++++++++++ .tests/Vector3/multiply.test.lua | 80 +++++++++++++++ .tests/Vector3/new.test.lua | 25 +++++ .tests/Vector3/subtract.test.lua | 80 +++++++++++++++ .tests/Vector3/tostring.test.lua | 48 +++++++++ tests.sh | 2 +- worldeditadditions/utils/vector3.lua | 141 +++++++++++++++++++++++++++ 8 files changed, 559 insertions(+), 1 deletion(-) create mode 100644 .tests/Vector3/add.test.lua create mode 100644 .tests/Vector3/divide.test.lua create mode 100644 .tests/Vector3/multiply.test.lua create mode 100644 .tests/Vector3/new.test.lua create mode 100644 .tests/Vector3/subtract.test.lua create mode 100644 .tests/Vector3/tostring.test.lua create mode 100644 worldeditadditions/utils/vector3.lua diff --git a/.tests/Vector3/add.test.lua b/.tests/Vector3/add.test.lua new file mode 100644 index 0000000..9eb1c6b --- /dev/null +++ b/.tests/Vector3/add.test.lua @@ -0,0 +1,104 @@ +local Vector3 = require("worldeditadditions.utils.vector3") + +local function format_map(map) + local result = {} + for key, value in pairs(map) do + table.insert(result, key.."\t"..tostring(value)) + end + return table.concat(result, "\n") +end + + +describe("Vector3.add", function() + it("should add 2 positive vectors", function() + local a = Vector3.new(3, 4, 5) + local b = Vector3.new(1, 1, 1) + assert.are.same( + a:add(b), + Vector3.new(4, 5, 6) + ) + end) + it("should support the add operator", function() + local a = Vector3.new(3, 4, 5) + local b = Vector3.new(1, 1, 1) + assert.are.same( + a + b, + Vector3.new(4, 5, 6) + ) + end) + it("should work with floats", function() + local a = Vector3.new(3.5, 4.5, 5.5) + local b = Vector3.new(1.1, 1.1, 1.1) + assert.are.same( + a + b, + Vector3.new(4.6, 5.6, 6.6) + ) + end) + it("should work with scalar a", function() + local a = 2 + local b = Vector3.new(6, 7, 8) + assert.are.same( + a + b, + Vector3.new(8, 9, 10) + ) + end) + it("should work with scalar b", function() + local a = Vector3.new(6, 7, 8) + local b = 2 + assert.are.same( + a + b, + Vector3.new(8, 9, 10) + ) + end) + it("should handle negative b", function() + local a = Vector3.new(3, 4, 5) + local b = Vector3.new(-1, -1, -1) + assert.are.same( + a + b, + Vector3.new(2, 3, 4) + ) + end) + it("should handle negative a", function() + local a = Vector3.new(-3, -4, -5) + local b = Vector3.new(1, 1, 1) + assert.are.same( + a + b, + Vector3.new(-2, -3, -4) + ) + end) + it("should handle negative a and b", function() + local a = Vector3.new(-3, -4, -5) + local b = Vector3.new(-1, -1, -1) + assert.are.same( + a + b, + Vector3.new(-4, -5, -6) + ) + end) + it("should throw an error on invalid x", function() + assert.has.errors(function() + Vector3.new("cheese", 4, 5) + end) + end) + it("should throw an error on invalid y", function() + assert.has.errors(function() + Vector3.new(4, "cheese", 5) + end) + end) + it("should throw an error on invalid z", function() + assert.has.errors(function() + Vector3.new(66, 2, "cheese") + end) + end) + it("should return a new Vector3 instance", function() + local a = Vector3.new(3, 4, 5) + local b = Vector3.new(1, 1, 1) + + local result = a + b + assert.are.same( + result, + Vector3.new(4, 5, 6) + ) + assert.are_not.equal(result, a) + assert.are_not.equal(result, b) + end) +end) diff --git a/.tests/Vector3/divide.test.lua b/.tests/Vector3/divide.test.lua new file mode 100644 index 0000000..6095e69 --- /dev/null +++ b/.tests/Vector3/divide.test.lua @@ -0,0 +1,80 @@ +local Vector3 = require("worldeditadditions.utils.vector3") + +describe("Vector3.divide", function() + it("should divide 2 positive vectors", function() + local a = Vector3.new(30, 40, 50) + local b = Vector3.new(2, 2, 2) + assert.are.same( + a:divide(b), + Vector3.new(15, 20, 25) + ) + end) + it("should work with the div alias", function() + local a = Vector3.new(30, 40, 50) + local b = Vector3.new(2, 2, 2) + assert.are.same( + a:div(b), + Vector3.new(15, 20, 25) + ) + end) + it("should work with scalar a", function() + local a = 2 + local b = Vector3.new(12, 14, 16) + assert.are.same( + a / b, + Vector3.new(6, 7, 8) + ) + end) + it("should work with scalar b", function() + local a = Vector3.new(6, 8, 10) + local b = 2 + assert.are.same( + a / b, + Vector3.new(3, 4, 5) + ) + end) + it("should support the divide operator", function() + local a = Vector3.new(10, 12, 14) + local b = Vector3.new(2, 3, 2) + assert.are.same( + a / b, + Vector3.new(5, 4, 7) + ) + end) + it("should handle negative b", function() + local a = Vector3.new(30, 40, 50) + local b = Vector3.new(-2, -2, -2) + assert.are.same( + a / b, + Vector3.new(-15, -20, -25) + ) + end) + it("should handle negative a", function() + local a = Vector3.new(-30, -40, -50) + local b = Vector3.new(2, 4, 2) + assert.are.same( + a / b, + Vector3.new(-15, -10, -25) + ) + end) + it("should handle negative a and b", function() + local a = Vector3.new(-30, -40, -50) + local b = Vector3.new(-2, -2, -2) + assert.are.same( + a / b, + Vector3.new(15, 20, 25) + ) + end) + it("should return a new Vector3 instance", function() + local a = Vector3.new(9, 12, 15) + local b = Vector3.new(3, 3, 3) + + local result = a / b + assert.are.same( + result, + Vector3.new(3, 4, 5) + ) + assert.are_not.equal(result, a) + assert.are_not.equal(result, b) + end) +end) diff --git a/.tests/Vector3/multiply.test.lua b/.tests/Vector3/multiply.test.lua new file mode 100644 index 0000000..d1a39d3 --- /dev/null +++ b/.tests/Vector3/multiply.test.lua @@ -0,0 +1,80 @@ +local Vector3 = require("worldeditadditions.utils.vector3") + +describe("Vector3.multiply", function() + it("should multiply 2 positive vectors", function() + local a = Vector3.new(3, 4, 5) + local b = Vector3.new(2, 2, 2) + assert.are.same( + a:multiply(b), + Vector3.new(6, 8, 10) + ) + end) + it("should work with the mul alias", function() + local a = Vector3.new(3, 4, 5) + local b = Vector3.new(2, 2, 2) + assert.are.same( + a:mul(b), + Vector3.new(6, 8, 10) + ) + end) + it("should work with scalar a", function() + local a = 2 + local b = Vector3.new(6, 7, 8) + assert.are.same( + a * b, + Vector3.new(12, 14, 16) + ) + end) + it("should work with scalar b", function() + local a = Vector3.new(6, 7, 8) + local b = 2 + assert.are.same( + a * b, + Vector3.new(12, 14, 16) + ) + end) + it("should support the multiply operator", function() + local a = Vector3.new(3, 4, 5) + local b = Vector3.new(2, 2, 2) + assert.are.same( + a * b, + Vector3.new(6, 8, 10) + ) + end) + it("should handle negative b", function() + local a = Vector3.new(3, 4, 5) + local b = Vector3.new(-1, -1, -1) + assert.are.same( + a * b, + Vector3.new(-3, -4, -5) + ) + end) + it("should handle negative a", function() + local a = Vector3.new(-3, -4, -5) + local b = Vector3.new(2, 2, 2) + assert.are.same( + a * b, + Vector3.new(-6, -8, -10) + ) + end) + it("should handle negative a and b", function() + local a = Vector3.new(-3, -4, -5) + local b = Vector3.new(-2, -2, -2) + assert.are.same( + a * b, + Vector3.new(6, 8, 10) + ) + end) + it("should return a new Vector3 instance", function() + local a = Vector3.new(3, 4, 5) + local b = Vector3.new(3, 3, 3) + + local result = a * b + assert.are.same( + result, + Vector3.new(9, 12, 15) + ) + assert.are_not.equal(result, a) + assert.are_not.equal(result, b) + end) +end) diff --git a/.tests/Vector3/new.test.lua b/.tests/Vector3/new.test.lua new file mode 100644 index 0000000..91c044f --- /dev/null +++ b/.tests/Vector3/new.test.lua @@ -0,0 +1,25 @@ +local Vector3 = require("worldeditadditions.utils.vector3") + +describe("Vector3.add", function() + it("should create a new Vector3", function() + assert.are.same( + Vector3.new(3, 4, 5), + { x = 3, y = 4, z = 5 } + ) + end) + it("should throw an error on invalid x", function() + assert.has.errors(function() + Vector3.new("cheese", 4, 5) + end) + end) + it("should throw an error on invalid y", function() + assert.has.errors(function() + Vector3.new(4, "cheese", 5) + end) + end) + it("should throw an error on invalid z", function() + assert.has.errors(function() + Vector3.new(66, 2, "cheese") + end) + end) +end) diff --git a/.tests/Vector3/subtract.test.lua b/.tests/Vector3/subtract.test.lua new file mode 100644 index 0000000..58de460 --- /dev/null +++ b/.tests/Vector3/subtract.test.lua @@ -0,0 +1,80 @@ +local Vector3 = require("worldeditadditions.utils.vector3") + +describe("Vector3.subtract", function() + it("should subtract 2 positive vectors", function() + local a = Vector3.new(3, 4, 5) + local b = Vector3.new(1, 1, 1) + assert.are.same( + a:subtract(b), + Vector3.new(2, 3, 4) + ) + end) + it("should work with the sub alias", function() + local a = Vector3.new(3, 4, 5) + local b = Vector3.new(1, 1, 1) + assert.are.same( + a:sub(b), + Vector3.new(2, 3, 4) + ) + end) + it("should work with scalar a", function() + local a = 2 + local b = Vector3.new(6, 7, 8) + assert.are.same( + a - b, + Vector3.new(4, 5, 6) + ) + end) + it("should work with scalar b", function() + local a = Vector3.new(6, 7, 8) + local b = 2 + assert.are.same( + a - b, + Vector3.new(4, 5, 6) + ) + end) + it("should support the subtract operator", function() + local a = Vector3.new(3, 4, 5) + local b = Vector3.new(1, 1, 1) + assert.are.same( + a - b, + Vector3.new(2, 3, 4) + ) + end) + it("should handle negative b", function() + local a = Vector3.new(3, 4, 5) + local b = Vector3.new(-1, -1, -1) + assert.are.same( + a - b, + Vector3.new(4, 5, 6) + ) + end) + it("should handle negative a", function() + local a = Vector3.new(-3, -4, -5) + local b = Vector3.new(1, 1, 1) + assert.are.same( + a - b, + Vector3.new(-4, -5, -6) + ) + end) + it("should handle negative a and b", function() + local a = Vector3.new(-3, -4, -5) + local b = Vector3.new(-1, -1, -1) + assert.are.same( + a - b, + Vector3.new(-2, -3, -4) + ) + end) + it("should return a new Vector3 instance", function() + local a = Vector3.new(3, 4, 5) + local b = Vector3.new(1, 1, 1) + + local result = a - b + assert.are.same( + result, + Vector3.new(2, 3, 4) + ) + assert.are_not.equal(result, a) + assert.are_not.equal(result, b) + end) +end) diff --git a/.tests/Vector3/tostring.test.lua b/.tests/Vector3/tostring.test.lua new file mode 100644 index 0000000..d8d3b0c --- /dev/null +++ b/.tests/Vector3/tostring.test.lua @@ -0,0 +1,48 @@ +local Vector3 = require("worldeditadditions.utils.vector3") + +local function format_map(map) + local result = {} + for key, value in pairs(map) do + table.insert(result, key.."\t"..tostring(value)) + end + return table.concat(result, "\n") +end + + +describe("Vector3.__tostring", function() + it("should stringify a Vector3", function() + local a = Vector3.new(3, 4, 5) + assert.are.same( + a:__tostring(), + "(3, 4, 5)" + ) + end) + it("should implicitly stringify a Vector3", function() + local a = Vector3.new(3, 4, 5) + assert.are.same( + tostring(a), + "(3, 4, 5)" + ) + end) + it("should implicitly stringify another Vector3", function() + local a = Vector3.new(55, 77, 22) + assert.are.same( + tostring(a), + "(55, 77, 22)" + ) + end) + it("should handle negative numbers", function() + local a = Vector3.new(-1, -2, -3) + assert.are.same( + tostring(a), + "(-1, -2, -3)" + ) + end) + it("should handle a mix of positive and negative numbers", function() + local a = Vector3.new(-7, 2, -99) + assert.are.same( + tostring(a), + "(-7, 2, -99)" + ) + end) +end) diff --git a/tests.sh b/tests.sh index 35bac85..d355f72 100755 --- a/tests.sh +++ b/tests.sh @@ -27,7 +27,7 @@ luarocks_root="${PWD}/.luarocks"; # Setup the lua module path eval "$(luarocks --tree "${luarocks_root}" path)"; -mode="${1}"; shift; +mode="${1}"; if [[ "$#" -gt 0 ]]; then shift; fi run_setup() { log_msg "Installing busted"; diff --git a/worldeditadditions/utils/vector3.lua b/worldeditadditions/utils/vector3.lua new file mode 100644 index 0000000..7e59715 --- /dev/null +++ b/worldeditadditions/utils/vector3.lua @@ -0,0 +1,141 @@ +local Vector3 = {} +Vector3.__index = Vector3 + +function Vector3.new(x, y, z) + if type(x) ~= "number" then + error("Error: Expected number for the value of x, but received argument of type "..type(x)..".") + end + if type(y) ~= "number" then + error("Error: Expected number for the value of y, but received argument of type "..type(y)..".") + end + if type(z) ~= "number" then + error("Error: Expected number for the value of z, but received argument of type "..type(z)..".") + end + + local result = { + x = x, + y = y, + z = z + } + setmetatable(result, Vector3) + return result +end + +--- Adds the specified vectors or numbers together. +-- Returns the result as a new vector. +-- If 1 of the inputs is a number and the other a vector, then the number will +-- be added to each of the components of the vector. +-- @param a Vector3|number The first item to add. +-- @param a Vector3|number The second item to add. +-- @returns Vector3 The result as a new Vector3 object. +function Vector3.add(a, b) + if type(a) == "number" then + return Vector3.new(b.x + a, b.y + a, b.z + a) + elseif type(b) == "number" then + return Vector3.new(a.x + b, a.y + b, a.z + b) + end + return Vector3.new(a.x + b.x, a.y + b.y, a.z + b.z) +end + +--- Subtracts the specified vectors or numbers together. +-- Returns the result as a new vector. +-- If 1 of the inputs is a number and the other a vector, then the number will +-- be subtracted to each of the components of the vector. +-- @param a Vector3|number The first item to subtract. +-- @param a Vector3|number The second item to subtract. +-- @returns Vector3 The result as a new Vector3 object. +function Vector3.subtract(a, b) + if type(a) == "number" then + return Vector3.new(b.x - a, b.y - a, b.z - a) + elseif type(b) == "number" then + return Vector3.new(a.x - b, a.y - b, a.z - b) + end + return Vector3.new(a.x - b.x, a.y - b.y, a.z - b.z) +end +--- Alias for Vector3.subtract. +function Vector3.sub(a, b) return Vector3.subtract(a, b) end + +--- Multiplies the specified vectors or numbers together. +-- Returns the result as a new vector. +-- If 1 of the inputs is a number and the other a vector, then the number will +-- be multiplied to each of the components of the vector. +-- +-- If both of the inputs are vectors, then the components are multiplied +-- by each other (NOT the cross product). In other words: +-- a.x * b.x, a.y * b.y, a.z * b.z +-- +-- @param a Vector3|number The first item to multiply. +-- @param a Vector3|number The second item to multiply. +-- @returns Vector3 The result as a new Vector3 object. +function Vector3.multiply(a, b) + if type(a) == "number" then + return Vector3.new(b.x * a, b.y * a, b.z * a) + elseif type(b) == "number" then + return Vector3.new(a.x * b, a.y * b, a.z * b) + end + return Vector3.new(a.x * b.x, a.y * b.y, a.z * b.z) +end +--- Alias for Vector3.multiply. +function Vector3.mul(a, b) return Vector3.multiply(a, b) end + +--- Divides the specified vectors or numbers together. +-- Returns the result as a new vector. +-- If 1 of the inputs is a number and the other a vector, then the number will +-- be divided to each of the components of the vector. +-- @param a Vector3|number The first item to divide. +-- @param a Vector3|number The second item to divide. +-- @returns Vector3 The result as a new Vector3 object. +function Vector3.divide(a, b) + if type(a) == "number" then + return Vector3.new(b.x / a, b.y / a, b.z / a) + elseif type(b) == "number" then + return Vector3.new(a.x / b, a.y / b, a.z / b) + end + return Vector3.new(a.x / b.x, a.y / b.y, a.z / b.z) +end +--- Alias for Vector3.divide. +function Vector3.div(a, b) return Vector3.divide(a, b) end + +-- ██████ ██████ ███████ ██████ █████ ████████ ██████ ██████ +-- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ +-- ██ ██ ██████ █████ ██████ ███████ ██ ██ ██ ██████ +-- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ +-- ██████ ██ ███████ ██ ██ ██ ██ ██ ██████ ██ ██ +-- +-- ██████ ██ ██ ███████ ██████ ██████ ██ ██████ ███████ ███████ +-- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ +-- ██ ██ ██ ██ █████ ██████ ██████ ██ ██ ██ █████ ███████ +-- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ +-- ██████ ████ ███████ ██ ██ ██ ██ ██ ██████ ███████ ███████ + +function Vector3.__call(x, y, z) + return Vector3.new(x, y, z) +end +function Vector3.__add(a, b) + return Vector3.add(a, b) +end + +function Vector3.__sub(a, b) + return Vector3.sub(a, b) +end + +function Vector3.__mul(a, b) + return Vector3.mul(a, b) +end + +function Vector3.__div(a, b) + return Vector3.divide(a, b) +end + +--- Returns the current Vector3 as a string. +function Vector3.__tostring(a) + return "("..a.x..", "..a.y..", "..a.z..")" +end + + + +if worldeditadditions then + worldeditadditions.Vector3 = Vector3 +else + return Vector3 +end From 06e19248c701ba60aa250679d62ce441886a2bda Mon Sep 17 00:00:00 2001 From: Starbeamrainbowlabs Date: Sat, 26 Jun 2021 14:19:18 +0100 Subject: [PATCH 13/32] Vector3: add floor/ceil --- .tests/Vector3/ceil.test.lua | 44 ++++++++++++++++++++++++++++ .tests/Vector3/floor.test.lua | 44 ++++++++++++++++++++++++++++ worldeditadditions/utils/vector3.lua | 14 +++++++++ 3 files changed, 102 insertions(+) create mode 100644 .tests/Vector3/ceil.test.lua create mode 100644 .tests/Vector3/floor.test.lua diff --git a/.tests/Vector3/ceil.test.lua b/.tests/Vector3/ceil.test.lua new file mode 100644 index 0000000..9c2ce99 --- /dev/null +++ b/.tests/Vector3/ceil.test.lua @@ -0,0 +1,44 @@ +local Vector3 = require("worldeditadditions.utils.vector3") + +local function format_map(map) + local result = {} + for key, value in pairs(map) do + table.insert(result, key.."\t"..tostring(value)) + end + return table.concat(result, "\n") +end + + +describe("Vector3.ceil", function() + it("should ceil a positive vector", function() + local a = Vector3.new(3.1, 4.2, 5.8) + assert.are.same( + a:ceil(), + Vector3.new(4, 5, 6) + ) + end) + it("should ceil a negative vector", function() + local a = Vector3.new(-3.1, -4.2, -5.3) + assert.are.same( + a:ceil(), + Vector3.new(-3, -4, -5) + ) + end) + it("should work with integers", function() + local a = Vector3.new(3, 4, 5) + assert.are.same( + a:ceil(), + Vector3.new(3, 4, 5) + ) + end) + it("should return a new Vector3 instance", function() + local a = Vector3.new(3.1, 4.7, 5.99999) + + local result = a:ceil() + assert.are.same( + result, + Vector3.new(4, 5, 6) + ) + assert.are_not.equal(result, a) + end) +end) diff --git a/.tests/Vector3/floor.test.lua b/.tests/Vector3/floor.test.lua new file mode 100644 index 0000000..61f4c7c --- /dev/null +++ b/.tests/Vector3/floor.test.lua @@ -0,0 +1,44 @@ +local Vector3 = require("worldeditadditions.utils.vector3") + +local function format_map(map) + local result = {} + for key, value in pairs(map) do + table.insert(result, key.."\t"..tostring(value)) + end + return table.concat(result, "\n") +end + + +describe("Vector3.floor", function() + it("should floor a positive vector", function() + local a = Vector3.new(3.1, 4.75, 5.9) + assert.are.same( + a:floor(), + Vector3.new(3, 4, 5) + ) + end) + it("should floor a negative vector", function() + local a = Vector3.new(-3.1, -4.2, -5.3) + assert.are.same( + a:floor(), + Vector3.new(-4, -5, -6) + ) + end) + it("should work with integers", function() + local a = Vector3.new(3, 4, 5) + assert.are.same( + a:floor(), + Vector3.new(3, 4, 5) + ) + end) + it("should return a new Vector3 instance", function() + local a = Vector3.new(3.1, 4.7, 5.99999) + + local result = a:floor() + assert.are.same( + result, + Vector3.new(3, 4, 5) + ) + assert.are_not.equal(result, a) + end) +end) diff --git a/worldeditadditions/utils/vector3.lua b/worldeditadditions/utils/vector3.lua index 7e59715..8db4260 100644 --- a/worldeditadditions/utils/vector3.lua +++ b/worldeditadditions/utils/vector3.lua @@ -96,6 +96,20 @@ end --- Alias for Vector3.divide. function Vector3.div(a, b) return Vector3.divide(a, b) end + +--- Rounds the components of this vector down. +-- @param a Vector3 The vector to operate on. +-- @returns Vector3 A new instance with the x/y/z components rounded down. +function Vector3.floor(a) + return Vector3.new(math.floor(a.x), math.floor(a.y), math.floor(a.z)) +end +--- Rounds the components of this vector up. +-- @param a Vector3 The vector to operate on. +-- @returns Vector3 A new instance with the x/y/z components rounded up. +function Vector3.ceil(a) + return Vector3.new(math.ceil(a.x), math.ceil(a.y), math.ceil(a.z)) +end + -- ██████ ██████ ███████ ██████ █████ ████████ ██████ ██████ -- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ -- ██ ██ ██████ █████ ██████ ███████ ██ ██ ██ ██████ From 1e1112c34a744fc4f12f97f9ee9f981df32a5ed1 Mon Sep 17 00:00:00 2001 From: Starbeamrainbowlabs Date: Sat, 26 Jun 2021 14:22:26 +0100 Subject: [PATCH 14/32] Vector3: Add round --- .tests/Vector3/round.test.lua | 44 ++++++++++++++++++++++++++++ worldeditadditions/utils/vector3.lua | 6 ++++ 2 files changed, 50 insertions(+) create mode 100644 .tests/Vector3/round.test.lua diff --git a/.tests/Vector3/round.test.lua b/.tests/Vector3/round.test.lua new file mode 100644 index 0000000..e997dae --- /dev/null +++ b/.tests/Vector3/round.test.lua @@ -0,0 +1,44 @@ +local Vector3 = require("worldeditadditions.utils.vector3") + +local function format_map(map) + local result = {} + for key, value in pairs(map) do + table.insert(result, key.."\t"..tostring(value)) + end + return table.concat(result, "\n") +end + + +describe("Vector3.round", function() + it("should round a positive vector", function() + local a = Vector3.new(3.1, 4.75, 5.9) + assert.are.same( + a:round(), + Vector3.new(3, 5, 6) + ) + end) + it("should round a negative vector", function() + local a = Vector3.new(-3.1, -4.2, -5.3) + assert.are.same( + a:round(), + Vector3.new(-3, -4, -5) + ) + end) + it("should work with integers", function() + local a = Vector3.new(3, 4, 5) + assert.are.same( + a:round(), + Vector3.new(3, 4, 5) + ) + end) + it("should return a new Vector3 instance", function() + local a = Vector3.new(3.1, 4.7, 5.99999) + + local result = a:round() + assert.are.same( + result, + Vector3.new(3, 5, 6) + ) + assert.are_not.equal(result, a) + end) +end) diff --git a/worldeditadditions/utils/vector3.lua b/worldeditadditions/utils/vector3.lua index 8db4260..8f81006 100644 --- a/worldeditadditions/utils/vector3.lua +++ b/worldeditadditions/utils/vector3.lua @@ -109,6 +109,12 @@ end function Vector3.ceil(a) return Vector3.new(math.ceil(a.x), math.ceil(a.y), math.ceil(a.z)) end +--- Rounds the components of this vector. +-- @param a Vector3 The vector to operate on. +-- @returns Vector3 A new instance with the x/y/z components rounded. +function Vector3.round(a) + return Vector3.new(math.floor(a.x+0.5), math.floor(a.y+0.5), math.floor(a.z+0.5)) +end -- ██████ ██████ ███████ ██████ █████ ████████ ██████ ██████ -- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ From 57df2d045f052becb7bc13b9cc45451a56e80356 Mon Sep 17 00:00:00 2001 From: Starbeamrainbowlabs Date: Sat, 26 Jun 2021 14:26:40 +0100 Subject: [PATCH 15/32] Vector3: add area --- .tests/Vector3/area.test.lua | 34 ++++++++++++++++++++++++++++ worldeditadditions/utils/vector3.lua | 8 +++++++ 2 files changed, 42 insertions(+) create mode 100644 .tests/Vector3/area.test.lua diff --git a/.tests/Vector3/area.test.lua b/.tests/Vector3/area.test.lua new file mode 100644 index 0000000..076c180 --- /dev/null +++ b/.tests/Vector3/area.test.lua @@ -0,0 +1,34 @@ +local Vector3 = require("worldeditadditions.utils.vector3") + +local function format_map(map) + local result = {} + for key, value in pairs(map) do + table.insert(result, key.."\t"..tostring(value)) + end + return table.concat(result, "\n") +end + + +describe("Vector3.area", function() + it("should work with a positive vector", function() + local a = Vector3.new(3, 3, 3) + assert.are.equal( + a:area(), + 27 + ) + end) + it("should work with a negative vector", function() + local a = Vector3.new(-4, -4, -4) + assert.are.equal( + a:area(), + -64 + ) + end) + it("should work with a mixed vector", function() + local a = Vector3.new(-3, 3, -3) + assert.are.equal( + a:area(), + 27 + ) + end) +end) diff --git a/worldeditadditions/utils/vector3.lua b/worldeditadditions/utils/vector3.lua index 8f81006..e57defa 100644 --- a/worldeditadditions/utils/vector3.lua +++ b/worldeditadditions/utils/vector3.lua @@ -116,6 +116,14 @@ function Vector3.round(a) return Vector3.new(math.floor(a.x+0.5), math.floor(a.y+0.5), math.floor(a.z+0.5)) end +--- Returns the area of this vector. +-- In other words, multiplies all the components together and returns a scalar value. +-- @param a Vector3 The vector to return the area of. +-- @returns number The area of this vector. +function Vector3.area(a) + return a.x * a.y * a.z +end + -- ██████ ██████ ███████ ██████ █████ ████████ ██████ ██████ -- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ -- ██ ██ ██████ █████ ██████ ███████ ██ ██ ██ ██████ From 8ae0d92e3d0092479aa2f94c2b720c4184686a8d Mon Sep 17 00:00:00 2001 From: Starbeamrainbowlabs Date: Sat, 26 Jun 2021 14:40:14 +0100 Subject: [PATCH 16/32] Vector3/tests: flip assert orderings --- .tests/Vector3/add.test.lua | 51 ++++++++++------------------ .tests/Vector3/area.test.lua | 12 +++---- .tests/Vector3/ceil.test.lua | 12 +++---- .tests/Vector3/divide.test.lua | 36 ++++++++++---------- .tests/Vector3/floor.test.lua | 16 ++++----- .tests/Vector3/multiply.test.lua | 36 ++++++++++---------- .tests/Vector3/new.test.lua | 4 +-- .tests/Vector3/round.test.lua | 16 ++++----- .tests/Vector3/snap_to.test.lua | 45 ++++++++++++++++++++++++ .tests/Vector3/subtract.test.lua | 36 ++++++++++---------- .tests/Vector3/tostring.test.lua | 20 +++++------ worldeditadditions/utils/vector3.lua | 10 ++++++ 12 files changed, 167 insertions(+), 127 deletions(-) create mode 100644 .tests/Vector3/snap_to.test.lua diff --git a/.tests/Vector3/add.test.lua b/.tests/Vector3/add.test.lua index 9eb1c6b..de2bae4 100644 --- a/.tests/Vector3/add.test.lua +++ b/.tests/Vector3/add.test.lua @@ -14,89 +14,74 @@ describe("Vector3.add", function() local a = Vector3.new(3, 4, 5) local b = Vector3.new(1, 1, 1) assert.are.same( - a:add(b), - Vector3.new(4, 5, 6) + Vector3.new(4, 5, 6), + a:add(b) ) end) it("should support the add operator", function() local a = Vector3.new(3, 4, 5) local b = Vector3.new(1, 1, 1) assert.are.same( - a + b, - Vector3.new(4, 5, 6) + Vector3.new(4, 5, 6), + a + b ) end) it("should work with floats", function() local a = Vector3.new(3.5, 4.5, 5.5) local b = Vector3.new(1.1, 1.1, 1.1) assert.are.same( - a + b, - Vector3.new(4.6, 5.6, 6.6) + Vector3.new(4.6, 5.6, 6.6), + a + b ) end) it("should work with scalar a", function() local a = 2 local b = Vector3.new(6, 7, 8) assert.are.same( - a + b, - Vector3.new(8, 9, 10) + Vector3.new(8, 9, 10), + a + b ) end) it("should work with scalar b", function() local a = Vector3.new(6, 7, 8) local b = 2 assert.are.same( - a + b, - Vector3.new(8, 9, 10) + Vector3.new(8, 9, 10), + a + b ) end) it("should handle negative b", function() local a = Vector3.new(3, 4, 5) local b = Vector3.new(-1, -1, -1) assert.are.same( - a + b, - Vector3.new(2, 3, 4) + Vector3.new(2, 3, 4), + a + b ) end) it("should handle negative a", function() local a = Vector3.new(-3, -4, -5) local b = Vector3.new(1, 1, 1) assert.are.same( - a + b, - Vector3.new(-2, -3, -4) + Vector3.new(-2, -3, -4), + a + b ) end) it("should handle negative a and b", function() local a = Vector3.new(-3, -4, -5) local b = Vector3.new(-1, -1, -1) assert.are.same( - a + b, - Vector3.new(-4, -5, -6) + Vector3.new(-4, -5, -6), + a + b ) end) - it("should throw an error on invalid x", function() - assert.has.errors(function() - Vector3.new("cheese", 4, 5) - end) - end) - it("should throw an error on invalid y", function() - assert.has.errors(function() - Vector3.new(4, "cheese", 5) - end) - end) - it("should throw an error on invalid z", function() - assert.has.errors(function() - Vector3.new(66, 2, "cheese") - end) - end) it("should return a new Vector3 instance", function() local a = Vector3.new(3, 4, 5) local b = Vector3.new(1, 1, 1) local result = a + b assert.are.same( - result, - Vector3.new(4, 5, 6) + Vector3.new(4, 5, 6), + result ) assert.are_not.equal(result, a) assert.are_not.equal(result, b) diff --git a/.tests/Vector3/area.test.lua b/.tests/Vector3/area.test.lua index 076c180..d593fd4 100644 --- a/.tests/Vector3/area.test.lua +++ b/.tests/Vector3/area.test.lua @@ -13,22 +13,22 @@ describe("Vector3.area", function() it("should work with a positive vector", function() local a = Vector3.new(3, 3, 3) assert.are.equal( - a:area(), - 27 + 27, + a:area() ) end) it("should work with a negative vector", function() local a = Vector3.new(-4, -4, -4) assert.are.equal( - a:area(), - -64 + -64, + a:area() ) end) it("should work with a mixed vector", function() local a = Vector3.new(-3, 3, -3) assert.are.equal( - a:area(), - 27 + 27, + a:area() ) end) end) diff --git a/.tests/Vector3/ceil.test.lua b/.tests/Vector3/ceil.test.lua index 9c2ce99..16ddd7e 100644 --- a/.tests/Vector3/ceil.test.lua +++ b/.tests/Vector3/ceil.test.lua @@ -13,15 +13,15 @@ describe("Vector3.ceil", function() it("should ceil a positive vector", function() local a = Vector3.new(3.1, 4.2, 5.8) assert.are.same( - a:ceil(), - Vector3.new(4, 5, 6) + Vector3.new(4, 5, 6), + a:ceil() ) end) it("should ceil a negative vector", function() local a = Vector3.new(-3.1, -4.2, -5.3) assert.are.same( - a:ceil(), - Vector3.new(-3, -4, -5) + Vector3.new(-3, -4, -5), + a:ceil() ) end) it("should work with integers", function() @@ -36,8 +36,8 @@ describe("Vector3.ceil", function() local result = a:ceil() assert.are.same( - result, - Vector3.new(4, 5, 6) + Vector3.new(4, 5, 6), + result ) assert.are_not.equal(result, a) end) diff --git a/.tests/Vector3/divide.test.lua b/.tests/Vector3/divide.test.lua index 6095e69..18c728f 100644 --- a/.tests/Vector3/divide.test.lua +++ b/.tests/Vector3/divide.test.lua @@ -5,64 +5,64 @@ describe("Vector3.divide", function() local a = Vector3.new(30, 40, 50) local b = Vector3.new(2, 2, 2) assert.are.same( - a:divide(b), - Vector3.new(15, 20, 25) + Vector3.new(15, 20, 25), + a:divide(b) ) end) it("should work with the div alias", function() local a = Vector3.new(30, 40, 50) local b = Vector3.new(2, 2, 2) assert.are.same( - a:div(b), - Vector3.new(15, 20, 25) + Vector3.new(15, 20, 25), + a:div(b) ) end) it("should work with scalar a", function() local a = 2 local b = Vector3.new(12, 14, 16) assert.are.same( - a / b, - Vector3.new(6, 7, 8) + Vector3.new(6, 7, 8), + a / b ) end) it("should work with scalar b", function() local a = Vector3.new(6, 8, 10) local b = 2 assert.are.same( - a / b, - Vector3.new(3, 4, 5) + Vector3.new(3, 4, 5), + a / b ) end) it("should support the divide operator", function() local a = Vector3.new(10, 12, 14) local b = Vector3.new(2, 3, 2) assert.are.same( - a / b, - Vector3.new(5, 4, 7) + Vector3.new(5, 4, 7), + a / b ) end) it("should handle negative b", function() local a = Vector3.new(30, 40, 50) local b = Vector3.new(-2, -2, -2) assert.are.same( - a / b, - Vector3.new(-15, -20, -25) + Vector3.new(-15, -20, -25), + a / b ) end) it("should handle negative a", function() local a = Vector3.new(-30, -40, -50) local b = Vector3.new(2, 4, 2) assert.are.same( - a / b, - Vector3.new(-15, -10, -25) + Vector3.new(-15, -10, -25), + a / b ) end) it("should handle negative a and b", function() local a = Vector3.new(-30, -40, -50) local b = Vector3.new(-2, -2, -2) assert.are.same( - a / b, - Vector3.new(15, 20, 25) + Vector3.new(15, 20, 25), + a / b ) end) it("should return a new Vector3 instance", function() @@ -71,8 +71,8 @@ describe("Vector3.divide", function() local result = a / b assert.are.same( - result, - Vector3.new(3, 4, 5) + Vector3.new(3, 4, 5), + result ) assert.are_not.equal(result, a) assert.are_not.equal(result, b) diff --git a/.tests/Vector3/floor.test.lua b/.tests/Vector3/floor.test.lua index 61f4c7c..4226475 100644 --- a/.tests/Vector3/floor.test.lua +++ b/.tests/Vector3/floor.test.lua @@ -13,22 +13,22 @@ describe("Vector3.floor", function() it("should floor a positive vector", function() local a = Vector3.new(3.1, 4.75, 5.9) assert.are.same( - a:floor(), - Vector3.new(3, 4, 5) + Vector3.new(3, 4, 5), + a:floor() ) end) it("should floor a negative vector", function() local a = Vector3.new(-3.1, -4.2, -5.3) assert.are.same( - a:floor(), - Vector3.new(-4, -5, -6) + Vector3.new(-4, -5, -6), + a:floor() ) end) it("should work with integers", function() local a = Vector3.new(3, 4, 5) assert.are.same( - a:floor(), - Vector3.new(3, 4, 5) + Vector3.new(3, 4, 5), + a:floor() ) end) it("should return a new Vector3 instance", function() @@ -36,8 +36,8 @@ describe("Vector3.floor", function() local result = a:floor() assert.are.same( - result, - Vector3.new(3, 4, 5) + Vector3.new(3, 4, 5), + result ) assert.are_not.equal(result, a) end) diff --git a/.tests/Vector3/multiply.test.lua b/.tests/Vector3/multiply.test.lua index d1a39d3..f133135 100644 --- a/.tests/Vector3/multiply.test.lua +++ b/.tests/Vector3/multiply.test.lua @@ -5,64 +5,64 @@ describe("Vector3.multiply", function() local a = Vector3.new(3, 4, 5) local b = Vector3.new(2, 2, 2) assert.are.same( - a:multiply(b), - Vector3.new(6, 8, 10) + Vector3.new(6, 8, 10), + a:multiply(b) ) end) it("should work with the mul alias", function() local a = Vector3.new(3, 4, 5) local b = Vector3.new(2, 2, 2) assert.are.same( - a:mul(b), - Vector3.new(6, 8, 10) + Vector3.new(6, 8, 10), + a:mul(b) ) end) it("should work with scalar a", function() local a = 2 local b = Vector3.new(6, 7, 8) assert.are.same( - a * b, - Vector3.new(12, 14, 16) + Vector3.new(12, 14, 16), + a * b ) end) it("should work with scalar b", function() local a = Vector3.new(6, 7, 8) local b = 2 assert.are.same( - a * b, - Vector3.new(12, 14, 16) + Vector3.new(12, 14, 16), + a * b ) end) it("should support the multiply operator", function() local a = Vector3.new(3, 4, 5) local b = Vector3.new(2, 2, 2) assert.are.same( - a * b, - Vector3.new(6, 8, 10) + Vector3.new(6, 8, 10), + a * b ) end) it("should handle negative b", function() local a = Vector3.new(3, 4, 5) local b = Vector3.new(-1, -1, -1) assert.are.same( - a * b, - Vector3.new(-3, -4, -5) + Vector3.new(-3, -4, -5), + a * b ) end) it("should handle negative a", function() local a = Vector3.new(-3, -4, -5) local b = Vector3.new(2, 2, 2) assert.are.same( - a * b, - Vector3.new(-6, -8, -10) + Vector3.new(-6, -8, -10), + a * b ) end) it("should handle negative a and b", function() local a = Vector3.new(-3, -4, -5) local b = Vector3.new(-2, -2, -2) assert.are.same( - a * b, - Vector3.new(6, 8, 10) + Vector3.new(6, 8, 10), + a * b ) end) it("should return a new Vector3 instance", function() @@ -71,8 +71,8 @@ describe("Vector3.multiply", function() local result = a * b assert.are.same( - result, - Vector3.new(9, 12, 15) + Vector3.new(9, 12, 15), + result ) assert.are_not.equal(result, a) assert.are_not.equal(result, b) diff --git a/.tests/Vector3/new.test.lua b/.tests/Vector3/new.test.lua index 91c044f..b74e5b1 100644 --- a/.tests/Vector3/new.test.lua +++ b/.tests/Vector3/new.test.lua @@ -3,8 +3,8 @@ local Vector3 = require("worldeditadditions.utils.vector3") describe("Vector3.add", function() it("should create a new Vector3", function() assert.are.same( - Vector3.new(3, 4, 5), - { x = 3, y = 4, z = 5 } + { x = 3, y = 4, z = 5 }, + Vector3.new(3, 4, 5) ) end) it("should throw an error on invalid x", function() diff --git a/.tests/Vector3/round.test.lua b/.tests/Vector3/round.test.lua index e997dae..9b673af 100644 --- a/.tests/Vector3/round.test.lua +++ b/.tests/Vector3/round.test.lua @@ -13,22 +13,22 @@ describe("Vector3.round", function() it("should round a positive vector", function() local a = Vector3.new(3.1, 4.75, 5.9) assert.are.same( - a:round(), - Vector3.new(3, 5, 6) + Vector3.new(3, 5, 6), + a:round() ) end) it("should round a negative vector", function() local a = Vector3.new(-3.1, -4.2, -5.3) assert.are.same( - a:round(), - Vector3.new(-3, -4, -5) + Vector3.new(-3, -4, -5), + a:round() ) end) it("should work with integers", function() local a = Vector3.new(3, 4, 5) assert.are.same( - a:round(), - Vector3.new(3, 4, 5) + Vector3.new(3, 4, 5), + a:round() ) end) it("should return a new Vector3 instance", function() @@ -36,8 +36,8 @@ describe("Vector3.round", function() local result = a:round() assert.are.same( - result, - Vector3.new(3, 5, 6) + Vector3.new(3, 5, 6), + result ) assert.are_not.equal(result, a) end) diff --git a/.tests/Vector3/snap_to.test.lua b/.tests/Vector3/snap_to.test.lua new file mode 100644 index 0000000..27028c4 --- /dev/null +++ b/.tests/Vector3/snap_to.test.lua @@ -0,0 +1,45 @@ +local Vector3 = require("worldeditadditions.utils.vector3") + +local function format_map(map) + local result = {} + for key, value in pairs(map) do + table.insert(result, key.."\t"..tostring(value)) + end + return table.concat(result, "\n") +end + + +describe("Vector3.snap_to", function() + it("should snap_to a positive vector", function() + local a = Vector3.new(3.1, 4.75, 5.9) + print("DEBUG "..tostring(a:snap_to(10))) + assert.are.same( + a:snap_to(10), + Vector3.new(0, 0, 10) + ) + end) + it("should snap_to a negative vector", function() + local a = Vector3.new(-2.5, -4.2, -5.3) + assert.are.same( + a:snap_to(6), + Vector3.new(0, -6, -6) + ) + end) + it("should work with integers", function() + local a = Vector3.new(3, 4, 5) + assert.are.same( + a:snap_to(3), + Vector3.new(3, 3, 6) + ) + end) + it("should return a new Vector3 instance", function() + local a = Vector3.new(3.1, 4.7, 5.99999) + + local result = a:snap_to(3) + assert.are.same( + result, + Vector3.new(3, 6, 6) + ) + assert.are_not.equal(result, a) + end) +end) diff --git a/.tests/Vector3/subtract.test.lua b/.tests/Vector3/subtract.test.lua index 58de460..c447c71 100644 --- a/.tests/Vector3/subtract.test.lua +++ b/.tests/Vector3/subtract.test.lua @@ -5,64 +5,64 @@ describe("Vector3.subtract", function() local a = Vector3.new(3, 4, 5) local b = Vector3.new(1, 1, 1) assert.are.same( - a:subtract(b), - Vector3.new(2, 3, 4) + Vector3.new(2, 3, 4), + a:subtract(b) ) end) it("should work with the sub alias", function() local a = Vector3.new(3, 4, 5) local b = Vector3.new(1, 1, 1) assert.are.same( - a:sub(b), - Vector3.new(2, 3, 4) + Vector3.new(2, 3, 4), + a:sub(b) ) end) it("should work with scalar a", function() local a = 2 local b = Vector3.new(6, 7, 8) assert.are.same( - a - b, - Vector3.new(4, 5, 6) + Vector3.new(4, 5, 6), + a - b ) end) it("should work with scalar b", function() local a = Vector3.new(6, 7, 8) local b = 2 assert.are.same( - a - b, - Vector3.new(4, 5, 6) + Vector3.new(4, 5, 6), + a - b ) end) it("should support the subtract operator", function() local a = Vector3.new(3, 4, 5) local b = Vector3.new(1, 1, 1) assert.are.same( - a - b, - Vector3.new(2, 3, 4) + Vector3.new(2, 3, 4), + a - b ) end) it("should handle negative b", function() local a = Vector3.new(3, 4, 5) local b = Vector3.new(-1, -1, -1) assert.are.same( - a - b, - Vector3.new(4, 5, 6) + Vector3.new(4, 5, 6), + a - b ) end) it("should handle negative a", function() local a = Vector3.new(-3, -4, -5) local b = Vector3.new(1, 1, 1) assert.are.same( - a - b, - Vector3.new(-4, -5, -6) + Vector3.new(-4, -5, -6), + a - b ) end) it("should handle negative a and b", function() local a = Vector3.new(-3, -4, -5) local b = Vector3.new(-1, -1, -1) assert.are.same( - a - b, - Vector3.new(-2, -3, -4) + Vector3.new(-2, -3, -4), + a - b ) end) it("should return a new Vector3 instance", function() @@ -71,8 +71,8 @@ describe("Vector3.subtract", function() local result = a - b assert.are.same( - result, - Vector3.new(2, 3, 4) + Vector3.new(2, 3, 4), + result ) assert.are_not.equal(result, a) assert.are_not.equal(result, b) diff --git a/.tests/Vector3/tostring.test.lua b/.tests/Vector3/tostring.test.lua index d8d3b0c..e46884a 100644 --- a/.tests/Vector3/tostring.test.lua +++ b/.tests/Vector3/tostring.test.lua @@ -13,36 +13,36 @@ describe("Vector3.__tostring", function() it("should stringify a Vector3", function() local a = Vector3.new(3, 4, 5) assert.are.same( - a:__tostring(), - "(3, 4, 5)" + "(3, 4, 5)", + a:__tostring() ) end) it("should implicitly stringify a Vector3", function() local a = Vector3.new(3, 4, 5) assert.are.same( - tostring(a), - "(3, 4, 5)" + "(3, 4, 5)", + tostring(a) ) end) it("should implicitly stringify another Vector3", function() local a = Vector3.new(55, 77, 22) assert.are.same( - tostring(a), - "(55, 77, 22)" + "(55, 77, 22)", + tostring(a) ) end) it("should handle negative numbers", function() local a = Vector3.new(-1, -2, -3) assert.are.same( - tostring(a), - "(-1, -2, -3)" + "(-1, -2, -3)", + tostring(a) ) end) it("should handle a mix of positive and negative numbers", function() local a = Vector3.new(-7, 2, -99) assert.are.same( - tostring(a), - "(-7, 2, -99)" + "(-7, 2, -99)", + tostring(a) ) end) end) diff --git a/worldeditadditions/utils/vector3.lua b/worldeditadditions/utils/vector3.lua index e57defa..239e59b 100644 --- a/worldeditadditions/utils/vector3.lua +++ b/worldeditadditions/utils/vector3.lua @@ -116,6 +116,16 @@ function Vector3.round(a) return Vector3.new(math.floor(a.x+0.5), math.floor(a.y+0.5), math.floor(a.z+0.5)) end + +--- Snaps this Vector3 to an imaginary square grid with the specified sized +-- squares. +-- @param a Vector3 The vector to operate on. +-- @param number grid_size The size of the squares on the imaginary grid to which to snap. +-- @returns Vector3 A new Vector3 instance snapped to an imaginary grid of the specified size. +function Vector3.snap_to(a, grid_size) + return a:round(a / grid_size) * grid_size +end + --- Returns the area of this vector. -- In other words, multiplies all the components together and returns a scalar value. -- @param a Vector3 The vector to return the area of. From cde3c3360cc50abb7a8e820793b1b2775fc2358d Mon Sep 17 00:00:00 2001 From: Starbeamrainbowlabs Date: Sat, 26 Jun 2021 14:44:40 +0100 Subject: [PATCH 17/32] Vector3: add snap_to --- .tests/Vector3/add.test.lua | 9 --------- .tests/Vector3/snap_to.test.lua | 26 ++++++++------------------ worldeditadditions/utils/vector3.lua | 2 +- 3 files changed, 9 insertions(+), 28 deletions(-) diff --git a/.tests/Vector3/add.test.lua b/.tests/Vector3/add.test.lua index de2bae4..cba5a2a 100644 --- a/.tests/Vector3/add.test.lua +++ b/.tests/Vector3/add.test.lua @@ -1,14 +1,5 @@ local Vector3 = require("worldeditadditions.utils.vector3") -local function format_map(map) - local result = {} - for key, value in pairs(map) do - table.insert(result, key.."\t"..tostring(value)) - end - return table.concat(result, "\n") -end - - describe("Vector3.add", function() it("should add 2 positive vectors", function() local a = Vector3.new(3, 4, 5) diff --git a/.tests/Vector3/snap_to.test.lua b/.tests/Vector3/snap_to.test.lua index 27028c4..389de35 100644 --- a/.tests/Vector3/snap_to.test.lua +++ b/.tests/Vector3/snap_to.test.lua @@ -1,35 +1,25 @@ local Vector3 = require("worldeditadditions.utils.vector3") -local function format_map(map) - local result = {} - for key, value in pairs(map) do - table.insert(result, key.."\t"..tostring(value)) - end - return table.concat(result, "\n") -end - - describe("Vector3.snap_to", function() it("should snap_to a positive vector", function() local a = Vector3.new(3.1, 4.75, 5.9) - print("DEBUG "..tostring(a:snap_to(10))) assert.are.same( - a:snap_to(10), - Vector3.new(0, 0, 10) + Vector3.new(0, 0, 10), + a:snap_to(10) ) end) it("should snap_to a negative vector", function() local a = Vector3.new(-2.5, -4.2, -5.3) assert.are.same( - a:snap_to(6), - Vector3.new(0, -6, -6) + Vector3.new(0, -6, -6), + a:snap_to(6) ) end) it("should work with integers", function() local a = Vector3.new(3, 4, 5) assert.are.same( - a:snap_to(3), - Vector3.new(3, 3, 6) + Vector3.new(3, 3, 6), + a:snap_to(3) ) end) it("should return a new Vector3 instance", function() @@ -37,8 +27,8 @@ describe("Vector3.snap_to", function() local result = a:snap_to(3) assert.are.same( - result, - Vector3.new(3, 6, 6) + Vector3.new(3, 6, 6), + result ) assert.are_not.equal(result, a) end) diff --git a/worldeditadditions/utils/vector3.lua b/worldeditadditions/utils/vector3.lua index 239e59b..8d08af2 100644 --- a/worldeditadditions/utils/vector3.lua +++ b/worldeditadditions/utils/vector3.lua @@ -123,7 +123,7 @@ end -- @param number grid_size The size of the squares on the imaginary grid to which to snap. -- @returns Vector3 A new Vector3 instance snapped to an imaginary grid of the specified size. function Vector3.snap_to(a, grid_size) - return a:round(a / grid_size) * grid_size + return (a / grid_size):round() * grid_size end --- Returns the area of this vector. From 7549b0eaea7ec01b3e1c9985db8fda9ace1d9743 Mon Sep 17 00:00:00 2001 From: Starbeamrainbowlabs Date: Sat, 26 Jun 2021 15:15:32 +0100 Subject: [PATCH 18/32] Vector3: add length, length_squared, sqrt --- .tests/Vector3/length.test.lua | 38 ++++++++++++++++++++++++++ .tests/Vector3/length_squared.test.lua | 34 +++++++++++++++++++++++ .tests/Vector3/sqrt.test.lua | 37 +++++++++++++++++++++++++ worldeditadditions/utils/vector3.lua | 21 ++++++++++++++ 4 files changed, 130 insertions(+) create mode 100644 .tests/Vector3/length.test.lua create mode 100644 .tests/Vector3/length_squared.test.lua create mode 100644 .tests/Vector3/sqrt.test.lua diff --git a/.tests/Vector3/length.test.lua b/.tests/Vector3/length.test.lua new file mode 100644 index 0000000..3d225b9 --- /dev/null +++ b/.tests/Vector3/length.test.lua @@ -0,0 +1,38 @@ +local Vector3 = require("worldeditadditions.utils.vector3") + +local function format_map(map) + local result = {} + for key, value in pairs(map) do + table.insert(result, key.."\t"..tostring(value)) + end + return table.concat(result, "\n") +end + +-- To find these numbers, in Javascript: +-- function t(x) { return Math.sqrt((x*x)*3); } +-- for(let i = 0; i < 1000000000; i++) { let r = t(i); if(Math.floor(r) === r) console.log(`i ${i}, r ${r}`); } + + +describe("Vector3.length", function() + it("should work with a positive vector", function() + local a = Vector3.new(80198051, 80198051, 80198051) + assert.are.equal( + 138907099, + a:length() + ) + end) + it("should work with a negative vector", function() + local a = Vector3.new(-189750626, -189750626, -189750626) + assert.are.equal( + 328657725, + a:length() + ) + end) + it("should work with a mixed vector", function() + local a = Vector3.new(-371635731, 371635731, -371635731) + assert.are.equal( + 643691968, + a:length() + ) + end) +end) diff --git a/.tests/Vector3/length_squared.test.lua b/.tests/Vector3/length_squared.test.lua new file mode 100644 index 0000000..d3bb2a4 --- /dev/null +++ b/.tests/Vector3/length_squared.test.lua @@ -0,0 +1,34 @@ +local Vector3 = require("worldeditadditions.utils.vector3") + +local function format_map(map) + local result = {} + for key, value in pairs(map) do + table.insert(result, key.."\t"..tostring(value)) + end + return table.concat(result, "\n") +end + + +describe("Vector3.length_squared", function() + it("should work with a positive vector", function() + local a = Vector3.new(3, 3, 3) + assert.are.equal( + 27, + a:length_squared() + ) + end) + it("should work with a negative vector", function() + local a = Vector3.new(-4, -4, -4) + assert.are.equal( + 48, + a:length_squared() + ) + end) + it("should work with a mixed vector", function() + local a = Vector3.new(-3, 3, -3) + assert.are.equal( + 27, + a:length_squared() + ) + end) +end) diff --git a/.tests/Vector3/sqrt.test.lua b/.tests/Vector3/sqrt.test.lua new file mode 100644 index 0000000..6726a64 --- /dev/null +++ b/.tests/Vector3/sqrt.test.lua @@ -0,0 +1,37 @@ +local Vector3 = require("worldeditadditions.utils.vector3") + +local function format_map(map) + local result = {} + for key, value in pairs(map) do + table.insert(result, key.."\t"..tostring(value)) + end + return table.concat(result, "\n") +end + + +describe("Vector3.sqrt", function() + it("should sqrt a positive vector", function() + local a = Vector3.new(16, 64, 16) + assert.are.same( + Vector3.new(4, 8, 4), + a:sqrt() + ) + end) + it("should sqrt another positive vector", function() + local a = Vector3.new(9, 16, 25) + assert.are.same( + Vector3.new(3, 4, 5), + a:sqrt() + ) + end) + it("should return a new Vector3 instance", function() + local a = Vector3.new(9, 16, 25) + + local result = a:sqrt() + assert.are.same( + Vector3.new(3, 4, 5), + result + ) + assert.are_not.equal(result, a) + end) +end) diff --git a/worldeditadditions/utils/vector3.lua b/worldeditadditions/utils/vector3.lua index 8d08af2..85a9019 100644 --- a/worldeditadditions/utils/vector3.lua +++ b/worldeditadditions/utils/vector3.lua @@ -134,6 +134,27 @@ function Vector3.area(a) return a.x * a.y * a.z end +--- Returns the scalar length of this vector squared. +-- @param a Vector3 The vector to operate on. +-- @returns number The length squared of this vector as a scalar value. +function Vector3.length_squared(a) + return a.x * a.x + a.y * a.y + a.z * a.z +end + +--- Square roots each component of this vector. +-- @param a Vector3 The vector to operate on. +-- @returns number A new vector with each component square rooted. +function Vector3.sqrt(a) + return Vector3.new(math.sqrt(a.x), math.sqrt(a.y), math.sqrt(a.z)) +end + +--- Calculates the scalar length of this vector. +-- @param a Vector3 The vector to operate on. +-- @returns number The length of this vector as a scalar value. +function Vector3.length(a) + return math.sqrt(a:length_squared()) +end + -- ██████ ██████ ███████ ██████ █████ ████████ ██████ ██████ -- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ -- ██ ██ ██████ █████ ██████ ███████ ██ ██ ██ ██████ From 6d0447a02fe2aa1c6a926bf5e4f6423045095a11 Mon Sep 17 00:00:00 2001 From: Starbeamrainbowlabs Date: Sat, 26 Jun 2021 15:23:16 +0100 Subject: [PATCH 19/32] Vector3: add clone --- .tests/Vector3/area.test.lua | 9 --------- .tests/Vector3/ceil.test.lua | 9 --------- .tests/Vector3/clone.test.lua | 24 ++++++++++++++++++++++++ .tests/Vector3/floor.test.lua | 9 --------- .tests/Vector3/length.test.lua | 8 -------- .tests/Vector3/length_squared.test.lua | 9 --------- .tests/Vector3/round.test.lua | 9 --------- .tests/Vector3/sqrt.test.lua | 9 --------- .tests/Vector3/tostring.test.lua | 9 --------- worldeditadditions/utils/vector3.lua | 7 +++++++ 10 files changed, 31 insertions(+), 71 deletions(-) create mode 100644 .tests/Vector3/clone.test.lua diff --git a/.tests/Vector3/area.test.lua b/.tests/Vector3/area.test.lua index d593fd4..d7fc97f 100644 --- a/.tests/Vector3/area.test.lua +++ b/.tests/Vector3/area.test.lua @@ -1,14 +1,5 @@ local Vector3 = require("worldeditadditions.utils.vector3") -local function format_map(map) - local result = {} - for key, value in pairs(map) do - table.insert(result, key.."\t"..tostring(value)) - end - return table.concat(result, "\n") -end - - describe("Vector3.area", function() it("should work with a positive vector", function() local a = Vector3.new(3, 3, 3) diff --git a/.tests/Vector3/ceil.test.lua b/.tests/Vector3/ceil.test.lua index 16ddd7e..449d89d 100644 --- a/.tests/Vector3/ceil.test.lua +++ b/.tests/Vector3/ceil.test.lua @@ -1,14 +1,5 @@ local Vector3 = require("worldeditadditions.utils.vector3") -local function format_map(map) - local result = {} - for key, value in pairs(map) do - table.insert(result, key.."\t"..tostring(value)) - end - return table.concat(result, "\n") -end - - describe("Vector3.ceil", function() it("should ceil a positive vector", function() local a = Vector3.new(3.1, 4.2, 5.8) diff --git a/.tests/Vector3/clone.test.lua b/.tests/Vector3/clone.test.lua new file mode 100644 index 0000000..361f9a2 --- /dev/null +++ b/.tests/Vector3/clone.test.lua @@ -0,0 +1,24 @@ +local Vector3 = require("worldeditadditions.utils.vector3") + +describe("Vector3.clone", function() + it("should return a new Vector3 instance", function() + local a = Vector3.new(3, 4, 5) + + local result = a:clone() + assert.are.same( + Vector3.new(3, 4, 5), + result + ) + assert.are_not.equal(result, a) + end) + it("should return a new Vector3 instance for a different vector", function() + local a = Vector3.new(-99, 66, 88) + + local result = a:clone() + assert.are.same( + Vector3.new(-99, 66, 88), + result + ) + assert.are_not.equal(result, a) + end) +end) diff --git a/.tests/Vector3/floor.test.lua b/.tests/Vector3/floor.test.lua index 4226475..c29b56d 100644 --- a/.tests/Vector3/floor.test.lua +++ b/.tests/Vector3/floor.test.lua @@ -1,14 +1,5 @@ local Vector3 = require("worldeditadditions.utils.vector3") -local function format_map(map) - local result = {} - for key, value in pairs(map) do - table.insert(result, key.."\t"..tostring(value)) - end - return table.concat(result, "\n") -end - - describe("Vector3.floor", function() it("should floor a positive vector", function() local a = Vector3.new(3.1, 4.75, 5.9) diff --git a/.tests/Vector3/length.test.lua b/.tests/Vector3/length.test.lua index 3d225b9..3c8924b 100644 --- a/.tests/Vector3/length.test.lua +++ b/.tests/Vector3/length.test.lua @@ -1,13 +1,5 @@ local Vector3 = require("worldeditadditions.utils.vector3") -local function format_map(map) - local result = {} - for key, value in pairs(map) do - table.insert(result, key.."\t"..tostring(value)) - end - return table.concat(result, "\n") -end - -- To find these numbers, in Javascript: -- function t(x) { return Math.sqrt((x*x)*3); } -- for(let i = 0; i < 1000000000; i++) { let r = t(i); if(Math.floor(r) === r) console.log(`i ${i}, r ${r}`); } diff --git a/.tests/Vector3/length_squared.test.lua b/.tests/Vector3/length_squared.test.lua index d3bb2a4..3e049c9 100644 --- a/.tests/Vector3/length_squared.test.lua +++ b/.tests/Vector3/length_squared.test.lua @@ -1,14 +1,5 @@ local Vector3 = require("worldeditadditions.utils.vector3") -local function format_map(map) - local result = {} - for key, value in pairs(map) do - table.insert(result, key.."\t"..tostring(value)) - end - return table.concat(result, "\n") -end - - describe("Vector3.length_squared", function() it("should work with a positive vector", function() local a = Vector3.new(3, 3, 3) diff --git a/.tests/Vector3/round.test.lua b/.tests/Vector3/round.test.lua index 9b673af..6107381 100644 --- a/.tests/Vector3/round.test.lua +++ b/.tests/Vector3/round.test.lua @@ -1,14 +1,5 @@ local Vector3 = require("worldeditadditions.utils.vector3") -local function format_map(map) - local result = {} - for key, value in pairs(map) do - table.insert(result, key.."\t"..tostring(value)) - end - return table.concat(result, "\n") -end - - describe("Vector3.round", function() it("should round a positive vector", function() local a = Vector3.new(3.1, 4.75, 5.9) diff --git a/.tests/Vector3/sqrt.test.lua b/.tests/Vector3/sqrt.test.lua index 6726a64..dbd84ca 100644 --- a/.tests/Vector3/sqrt.test.lua +++ b/.tests/Vector3/sqrt.test.lua @@ -1,14 +1,5 @@ local Vector3 = require("worldeditadditions.utils.vector3") -local function format_map(map) - local result = {} - for key, value in pairs(map) do - table.insert(result, key.."\t"..tostring(value)) - end - return table.concat(result, "\n") -end - - describe("Vector3.sqrt", function() it("should sqrt a positive vector", function() local a = Vector3.new(16, 64, 16) diff --git a/.tests/Vector3/tostring.test.lua b/.tests/Vector3/tostring.test.lua index e46884a..56f3dac 100644 --- a/.tests/Vector3/tostring.test.lua +++ b/.tests/Vector3/tostring.test.lua @@ -1,14 +1,5 @@ local Vector3 = require("worldeditadditions.utils.vector3") -local function format_map(map) - local result = {} - for key, value in pairs(map) do - table.insert(result, key.."\t"..tostring(value)) - end - return table.concat(result, "\n") -end - - describe("Vector3.__tostring", function() it("should stringify a Vector3", function() local a = Vector3.new(3, 4, 5) diff --git a/worldeditadditions/utils/vector3.lua b/worldeditadditions/utils/vector3.lua index 85a9019..e91aca1 100644 --- a/worldeditadditions/utils/vector3.lua +++ b/worldeditadditions/utils/vector3.lua @@ -21,6 +21,13 @@ function Vector3.new(x, y, z) return result end +--- Returns a new instance of this vector. +-- @param a Vector3 The vector to clone. +-- @returns Vector3 A new vector whose values are identical to those of the original vector. +function Vector3.clone(a) + return Vector3.new(a.x, a.y, a.z) +end + --- Adds the specified vectors or numbers together. -- Returns the result as a new vector. -- If 1 of the inputs is a number and the other a vector, then the number will From 773e6354ada083b81249bfb2ebacb66ba73881d7 Mon Sep 17 00:00:00 2001 From: Starbeamrainbowlabs Date: Sat, 26 Jun 2021 15:32:47 +0100 Subject: [PATCH 20/32] Vector3: add limit_to --- .tests/Vector3/limit_to.test.lua | 52 ++++++++++++++++++++++++++++ worldeditadditions/utils/vector3.lua | 14 ++++++++ 2 files changed, 66 insertions(+) create mode 100644 .tests/Vector3/limit_to.test.lua diff --git a/.tests/Vector3/limit_to.test.lua b/.tests/Vector3/limit_to.test.lua new file mode 100644 index 0000000..3519d96 --- /dev/null +++ b/.tests/Vector3/limit_to.test.lua @@ -0,0 +1,52 @@ +local Vector3 = require("worldeditadditions.utils.vector3") + +describe("Vector3.limit_to", function() + it("should limit_to a positive vector", function() + local a = Vector3.new(801980510, 801980510, 801980510) + assert.are.same( + Vector3.new(80198051, 80198051, 80198051), + a:limit_to(138907099) + ) + end) + it("should limit_to a negative vector", function() + local a = Vector3.new(-1897506260, -1897506260, -1897506260) + assert.are.same( + Vector3.new(-189750626, -189750626, -189750626), + a:limit_to(328657725) + ) + end) + it("should work if the length is borderline", function() + local a = Vector3.new(80198051, 80198051, 80198051) + assert.are.same( + Vector3.new(80198051, 80198051, 80198051), + a:limit_to(138907099) + ) + end) + it("should not change anything if the length is smaller", function() + local a = Vector3.new(3, 4, 5) + assert.are.same( + Vector3.new(3, 4, 5), + a:limit_to(100) + ) + end) + it("should return a new Vector3 instance", function() + local a = Vector3.new(801980510, 801980510, 801980510) + + local result = a:limit_to(138907099) + assert.are.same( + Vector3.new(80198051, 80198051, 80198051), + result + ) + assert.are_not.equal(result, a) + end) + it("should return a new Vector3 instance if the length is smaller", function() + local a = Vector3.new(3, 4, 5) + + local result = a:limit_to(101) + assert.are.same( + Vector3.new(3, 4, 5), + result + ) + assert.are_not.equal(result, a) + end) +end) diff --git a/worldeditadditions/utils/vector3.lua b/worldeditadditions/utils/vector3.lua index e91aca1..4526322 100644 --- a/worldeditadditions/utils/vector3.lua +++ b/worldeditadditions/utils/vector3.lua @@ -162,6 +162,20 @@ function Vector3.length(a) return math.sqrt(a:length_squared()) end +--- Returns a new vector whose length clamped to the given length. +-- The direction in which the vector is pointing is not changed. +-- @param a Vector3 The vector to operate on. +-- @returns Vector3 A new Vector3 instance limited to the specified length. +function Vector3.limit_to(a, length) + if type(length) ~= "number" then error("Error: Expected number, but found "..type(length)..".") end + + if a:length() > length then + return (a / a:length()) * length + end + return a:clone() +end + + -- ██████ ██████ ███████ ██████ █████ ████████ ██████ ██████ -- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ -- ██ ██ ██████ █████ ██████ ███████ ██ ██ ██ ██████ From 133cae587c4385ffbb0eb7f795b77a392677469c Mon Sep 17 00:00:00 2001 From: Starbeamrainbowlabs Date: Sat, 26 Jun 2021 15:39:47 +0100 Subject: [PATCH 21/32] Vector3: add move_towards --- .tests/Vector3/move_towards.test.lua | 17 +++++++++++++++++ worldeditadditions/utils/vector3.lua | 8 ++++++++ 2 files changed, 25 insertions(+) create mode 100644 .tests/Vector3/move_towards.test.lua diff --git a/.tests/Vector3/move_towards.test.lua b/.tests/Vector3/move_towards.test.lua new file mode 100644 index 0000000..c48ba82 --- /dev/null +++ b/.tests/Vector3/move_towards.test.lua @@ -0,0 +1,17 @@ +local Vector3 = require("worldeditadditions.utils.vector3") + +-- To find these numbers, in Javascript: +-- function t(x) { return Math.sqrt((x*x)*3); } +-- for(let i = 0; i < 1000000000; i++) { let r = t(i); if(Math.floor(r) === r) console.log(`i ${i}, r ${r}`); } + + +describe("Vector3.move_towards", function() + it("should work with a positive vector", function() + local a = Vector3.new(3, 4, 5) + local b = Vector3.new(10, 10, 10) + assert.are.same( + Vector3.new(5.0022714374157439821, 5.7162326606420661435, 6.4301938838683883048), + a:move_towards(b, 3) + ) + end) +end) diff --git a/worldeditadditions/utils/vector3.lua b/worldeditadditions/utils/vector3.lua index 4526322..17d3152 100644 --- a/worldeditadditions/utils/vector3.lua +++ b/worldeditadditions/utils/vector3.lua @@ -175,6 +175,14 @@ function Vector3.limit_to(a, length) return a:clone() end +--- Return a vector that is amount distance towards b from a. +-- @param a Vector3 The vector to move from. +-- @param b Vector3 The vector to move towards. +-- @param amount number The amount to move. +function Vector3.move_towards(a, b, amount) + return a + (b - a):limit_to(amount) +end + -- ██████ ██████ ███████ ██████ █████ ████████ ██████ ██████ -- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ From dc5645cfeb89e602daf18d1001d4c6d2f1688fa8 Mon Sep 17 00:00:00 2001 From: Starbeamrainbowlabs Date: Sat, 26 Jun 2021 15:43:42 +0100 Subject: [PATCH 22/32] Vector3: add set_to --- .tests/Vector3/set_to.test.lua | 52 ++++++++++++++++++++++++++++ worldeditadditions/utils/vector3.lua | 11 ++++++ 2 files changed, 63 insertions(+) create mode 100644 .tests/Vector3/set_to.test.lua diff --git a/.tests/Vector3/set_to.test.lua b/.tests/Vector3/set_to.test.lua new file mode 100644 index 0000000..99eedab --- /dev/null +++ b/.tests/Vector3/set_to.test.lua @@ -0,0 +1,52 @@ +local Vector3 = require("worldeditadditions.utils.vector3") + +describe("Vector3.set_to", function() + it("should set_to a positive vector", function() + local a = Vector3.new(801980510, 801980510, 801980510) + assert.are.same( + Vector3.new(80198051, 80198051, 80198051), + a:set_to(138907099) + ) + end) + it("should set_to a negative vector", function() + local a = Vector3.new(-1897506260, -1897506260, -1897506260) + assert.are.same( + Vector3.new(-189750626, -189750626, -189750626), + a:set_to(328657725) + ) + end) + it("should work if the length is borderline", function() + local a = Vector3.new(80198051, 80198051, 80198051) + assert.are.same( + Vector3.new(80198051, 80198051, 80198051), + a:set_to(138907099) + ) + end) + it("should work if the length is smaller", function() + local a = Vector3.new(80198051, 80198051, 80198051) + assert.are.same( + Vector3.new(109552575, 109552575, 109552575), + a:set_to(189750626):floor() -- Hack to ignore flating-point errors. In theory we should really use epsilon here instead + ) + end) + it("should return a new Vector3 instance", function() + local a = Vector3.new(801980510, 801980510, 801980510) + + local result = a:set_to(138907099) + assert.are.same( + Vector3.new(80198051, 80198051, 80198051), + result + ) + assert.are_not.equal(result, a) + end) + it("should return a new Vector3 instance if the length is smaller", function() + local a = Vector3.new(80198051, 80198051, 80198051) + + local result = a:set_to(189750626):floor() + assert.are.same( + Vector3.new(109552575, 109552575, 109552575), + result + ) + assert.are_not.equal(result, a) + end) +end) diff --git a/worldeditadditions/utils/vector3.lua b/worldeditadditions/utils/vector3.lua index 17d3152..7fa33df 100644 --- a/worldeditadditions/utils/vector3.lua +++ b/worldeditadditions/utils/vector3.lua @@ -175,6 +175,17 @@ function Vector3.limit_to(a, length) return a:clone() end +--- Returns a new vector whose length clamped to the given length. +-- The direction in which the vector is pointing is not changed. +-- @param a Vector3 The vector to operate on. +-- @returns Vector3 A new Vector3 instance limited to the specified length. +function Vector3.set_to(a, length) + if type(length) ~= "number" then error("Error: Expected number, but found "..type(length)..".") end + + return (a / a:length()) * length +end + + --- Return a vector that is amount distance towards b from a. -- @param a Vector3 The vector to move from. -- @param b Vector3 The vector to move towards. From cfa086ce467f02489a0243209fae3b3eed6f1020 Mon Sep 17 00:00:00 2001 From: Starbeamrainbowlabs Date: Sat, 26 Jun 2021 15:47:53 +0100 Subject: [PATCH 23/32] Vector3: add dot product --- .tests/Vector3/dot.test.lua | 36 ++++++++++++++++++++++++++++ worldeditadditions/utils/vector3.lua | 12 ++++++++++ 2 files changed, 48 insertions(+) create mode 100644 .tests/Vector3/dot.test.lua diff --git a/.tests/Vector3/dot.test.lua b/.tests/Vector3/dot.test.lua new file mode 100644 index 0000000..3f6f6b3 --- /dev/null +++ b/.tests/Vector3/dot.test.lua @@ -0,0 +1,36 @@ +local Vector3 = require("worldeditadditions.utils.vector3") + +describe("Vector3.dot", function() + it("should work with a positive vector", function() + local a = Vector3.new(3, 3, 3) + local b = Vector3.new(4, 5, 6) + assert.are.equal( + 45, + a:dot(b) + ) + end) + it("should work with a negative vector", function() + local a = Vector3.new(-4, -4, -4) + local b = Vector3.new(4, 5, 6) + assert.are.equal( + -60, + a:dot(b) + ) + end) + it("should work with a mixed vector", function() + local a = Vector3.new(-3, 3, -3) + local b = Vector3.new(7, 8, 9) + assert.are.equal( + -24, + a:dot(b) + ) + end) + it("should work with the dot_product alias", function() + local a = Vector3.new(-3, 3, -3) + local b = Vector3.new(7, 8, 9) + assert.are.equal( + -24, + a:dot_product(b) + ) + end) +end) diff --git a/worldeditadditions/utils/vector3.lua b/worldeditadditions/utils/vector3.lua index 7fa33df..a81464c 100644 --- a/worldeditadditions/utils/vector3.lua +++ b/worldeditadditions/utils/vector3.lua @@ -162,6 +162,18 @@ function Vector3.length(a) return math.sqrt(a:length_squared()) end +--- Calculates the dot product of this vector and another vector. +-- @param a Vector3 The first vector to operate on. +-- @param a Vector3 The second vector to operate on. +-- @returns number The dot product of this vector as a scalar value. +function Vector3.dot(a, b) + return a.x * b.x + a.y * b.y + a.z * b.z; +end +--- Alias of Vector3.dot. +function Vector3.dot_product(a, b) + return Vector3.dot(a, b) +end + --- Returns a new vector whose length clamped to the given length. -- The direction in which the vector is pointing is not changed. -- @param a Vector3 The vector to operate on. From 112bb96e99028d92f5deaa08f9177db3bafb832f Mon Sep 17 00:00:00 2001 From: Starbeamrainbowlabs Date: Sat, 26 Jun 2021 16:28:39 +0100 Subject: [PATCH 24/32] Vector3: add equals, equality operator --- .tests/Vector3/clone.test.lua | 16 +++++------ .tests/Vector3/equal.test.lua | 40 ++++++++++++++++++++++++++++ .tests/Vector3/limit_to.test.lua | 8 ++++-- worldeditadditions/utils/vector3.lua | 15 +++++++++++ 4 files changed, 67 insertions(+), 12 deletions(-) create mode 100644 .tests/Vector3/equal.test.lua diff --git a/.tests/Vector3/clone.test.lua b/.tests/Vector3/clone.test.lua index 361f9a2..a6b4804 100644 --- a/.tests/Vector3/clone.test.lua +++ b/.tests/Vector3/clone.test.lua @@ -5,20 +5,16 @@ describe("Vector3.clone", function() local a = Vector3.new(3, 4, 5) local result = a:clone() - assert.are.same( - Vector3.new(3, 4, 5), - result - ) - assert.are_not.equal(result, a) + result.x = 4 + assert.are.same(Vector3.new(3, 4, 5), a) + assert.are.same(Vector3.new(4, 4, 5), result) end) it("should return a new Vector3 instance for a different vector", function() local a = Vector3.new(-99, 66, 88) local result = a:clone() - assert.are.same( - Vector3.new(-99, 66, 88), - result - ) - assert.are_not.equal(result, a) + result.y = -44 + assert.are.same(Vector3.new(-99, 66, 88), a) + assert.are.same(Vector3.new(-99, -44, 88), result) end) end) diff --git a/.tests/Vector3/equal.test.lua b/.tests/Vector3/equal.test.lua new file mode 100644 index 0000000..25ee004 --- /dev/null +++ b/.tests/Vector3/equal.test.lua @@ -0,0 +1,40 @@ +local Vector3 = require("worldeditadditions.utils.vector3") + +describe("Vector3.equals", function() + it("should return true when identical", function() + local a = Vector3.new(3, 4, 5) + local b = Vector3.new(3, 4, 5) + + assert.are.same( + true, + a:equals(b) + ) + end) + it("should return false when not identical", function() + local a = Vector3.new(3, 4, 5) + local b = Vector3.new(6, 7, 8) + + assert.are.same( + false, + a:equals(b) + ) + end) + it("should return false when not identical x", function() + local a = Vector3.new(3, 4, 5) + local b = Vector3.new(4, 4, 5) + + assert.are.same( + false, + a:equals(b) + ) + end) + it("should return false when not identical y", function() + local a = Vector3.new(3, 4, 5) + local b = Vector3.new(3, 5, 5) + + assert.are.same( + false, + a:equals(b) + ) + end) +end) diff --git a/.tests/Vector3/limit_to.test.lua b/.tests/Vector3/limit_to.test.lua index 3519d96..0847fc9 100644 --- a/.tests/Vector3/limit_to.test.lua +++ b/.tests/Vector3/limit_to.test.lua @@ -37,7 +37,9 @@ describe("Vector3.limit_to", function() Vector3.new(80198051, 80198051, 80198051), result ) - assert.are_not.equal(result, a) + a.x = 4 + assert.are.same(Vector3.new(4, 801980510, 801980510), a) + assert.are.same(Vector3.new(80198051, 80198051, 80198051), result) end) it("should return a new Vector3 instance if the length is smaller", function() local a = Vector3.new(3, 4, 5) @@ -47,6 +49,8 @@ describe("Vector3.limit_to", function() Vector3.new(3, 4, 5), result ) - assert.are_not.equal(result, a) + a.x = 40 + assert.are.same(Vector3.new(40, 4, 5), a) + assert.are.same(Vector3.new(3, 4, 5), result) end) end) diff --git a/worldeditadditions/utils/vector3.lua b/worldeditadditions/utils/vector3.lua index a81464c..161e273 100644 --- a/worldeditadditions/utils/vector3.lua +++ b/worldeditadditions/utils/vector3.lua @@ -174,6 +174,17 @@ function Vector3.dot_product(a, b) return Vector3.dot(a, b) end +--- Determines if 2 vectors are equal to each other. +-- 2 vectors are equal if their values are identical. +-- @param a Vector3 The first vector to test. +-- @param a Vector3 The second vector to test. +-- @returns bool Whether the 2 vectors are equal or not. +function Vector3.equals(a, b) + return a.x == b.x + and a.y == b.y + and a.z == b.z +end + --- Returns a new vector whose length clamped to the given length. -- The direction in which the vector is pointing is not changed. -- @param a Vector3 The vector to operate on. @@ -238,6 +249,10 @@ function Vector3.__div(a, b) return Vector3.divide(a, b) end +function Vector3.__eq(a, b) + return Vector3.equals(a, b) +end + --- Returns the current Vector3 as a string. function Vector3.__tostring(a) return "("..a.x..", "..a.y..", "..a.z..")" From c76a049286426467677e4918f3298c9a6b441cc1 Mon Sep 17 00:00:00 2001 From: Starbeamrainbowlabs Date: Sat, 26 Jun 2021 16:47:22 +0100 Subject: [PATCH 25/32] Vector3: tweak --- worldeditadditions/utils/vector3.lua | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/worldeditadditions/utils/vector3.lua b/worldeditadditions/utils/vector3.lua index 161e273..30771ff 100644 --- a/worldeditadditions/utils/vector3.lua +++ b/worldeditadditions/utils/vector3.lua @@ -230,9 +230,8 @@ end -- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ -- ██████ ████ ███████ ██ ██ ██ ██ ██ ██████ ███████ ███████ -function Vector3.__call(x, y, z) - return Vector3.new(x, y, z) -end +function Vector3.__call(x, y, z) return Vector3.new(x, y, z) end + function Vector3.__add(a, b) return Vector3.add(a, b) end From 0a3680aa7d1e64a2fc0aff4f5b61673ad7c7486b Mon Sep 17 00:00:00 2001 From: Starbeamrainbowlabs Date: Sat, 26 Jun 2021 16:56:26 +0100 Subject: [PATCH 26/32] Vector3: add unit / normalise --- .tests/Vector3/unit.test.lua | 37 ++++++++++++++++++++++++++++ worldeditadditions/utils/vector3.lua | 12 +++++++++ 2 files changed, 49 insertions(+) create mode 100644 .tests/Vector3/unit.test.lua diff --git a/.tests/Vector3/unit.test.lua b/.tests/Vector3/unit.test.lua new file mode 100644 index 0000000..3d3b01d --- /dev/null +++ b/.tests/Vector3/unit.test.lua @@ -0,0 +1,37 @@ +local Vector3 = require("worldeditadditions.utils.vector3") + +-- To find these numbers, in Javascript: +-- function t(x) { return Math.sqrt((x*x)*3); } +-- for(let i = 0; i < 1000000000; i++) { let r = t(i); if(Math.floor(r) === r) console.log(`i ${i}, r ${r}`); } + + +describe("Vector3.unit", function() + it("should work with a positive vector", function() + local a = Vector3.new(10, 10, 10) + assert.are.same( + Vector3.new(57735, 57735, 57735), + a:unit():multiply(100000):floor() + ) + end) + it("should work with a the normalise alias", function() + local a = Vector3.new(10, 10, 10) + assert.are.same( + Vector3.new(57735, 57735, 57735), + a:normalise():multiply(100000):floor() + ) + end) + it("should work with a negative vector", function() + local a = Vector3.new(10, 10, 10) + assert.are.same( + Vector3.new(57735, 57735, 57735), + a:unit():multiply(100000):floor() + ) + end) + it("should work with a mixed vector", function() + local a = Vector3.new(-371635731, 371635731, -371635731) + assert.are.same( + Vector3.new(-57736, 57735, -57736), + a:unit():multiply(100000):floor() + ) + end) +end) diff --git a/worldeditadditions/utils/vector3.lua b/worldeditadditions/utils/vector3.lua index 30771ff..3d4bcc5 100644 --- a/worldeditadditions/utils/vector3.lua +++ b/worldeditadditions/utils/vector3.lua @@ -208,6 +208,18 @@ function Vector3.set_to(a, length) return (a / a:length()) * length end +--- Returns the unit vector of this vector. +-- The unit vector is a vector with a length of 1. +-- Returns a new vector. +-- Does not change the direction of the vector. +-- @param a Vector3 The vector to operate on. +-- @returns Vector3 The unit vector of this vector. +function Vector3.unit(a) + return a / a:length() +end +--- Alias of Vector3.unit. +function Vector3.normalise(a) return a:unit() end + --- Return a vector that is amount distance towards b from a. -- @param a Vector3 The vector to move from. From 88214aef57cc27493beb8a3c14e64dc1309cd0ad Mon Sep 17 00:00:00 2001 From: Starbeamrainbowlabs Date: Sat, 26 Jun 2021 17:02:35 +0100 Subject: [PATCH 27/32] Vector3: add min_component, max_component --- .tests/Vector3/max_component.test.lua | 39 +++++++++++++++++++++++++++ .tests/Vector3/min_component.test.lua | 39 +++++++++++++++++++++++++++ worldeditadditions/utils/vector3.lua | 16 +++++++++++ 3 files changed, 94 insertions(+) create mode 100644 .tests/Vector3/max_component.test.lua create mode 100644 .tests/Vector3/min_component.test.lua diff --git a/.tests/Vector3/max_component.test.lua b/.tests/Vector3/max_component.test.lua new file mode 100644 index 0000000..3c74bab --- /dev/null +++ b/.tests/Vector3/max_component.test.lua @@ -0,0 +1,39 @@ +local Vector3 = require("worldeditadditions.utils.vector3") + +describe("Vector3.max_component", function() + it("should work with a positive vector x", function() + local a = Vector3.new(30, 4, 5) + assert.are.equal( + 30, + a:max_component() + ) + end) + it("should work with a positive vector y", function() + local a = Vector3.new(3, 10, 5) + assert.are.equal( + 10, + a:max_component() + ) + end) + it("should work with a positive vector z", function() + local a = Vector3.new(3, 1, 50.5) + assert.are.equal( + 50.5, + a:max_component() + ) + end) + it("should work with a negative vector", function() + local a = Vector3.new(-4, -5, -1) + assert.are.equal( + -1, + a:max_component() + ) + end) + it("should work with a mixed vector", function() + local a = Vector3.new(-30, 3, -3) + assert.are.equal( + 3, + a:max_component() + ) + end) +end) diff --git a/.tests/Vector3/min_component.test.lua b/.tests/Vector3/min_component.test.lua new file mode 100644 index 0000000..d1e8fc4 --- /dev/null +++ b/.tests/Vector3/min_component.test.lua @@ -0,0 +1,39 @@ +local Vector3 = require("worldeditadditions.utils.vector3") + +describe("Vector3.min_component", function() + it("should work with a positive vector x", function() + local a = Vector3.new(3, 4, 5) + assert.are.equal( + 3, + a:min_component() + ) + end) + it("should work with a positive vector y", function() + local a = Vector3.new(3, 1, 5) + assert.are.equal( + 1, + a:min_component() + ) + end) + it("should work with a positive vector z", function() + local a = Vector3.new(3, 1, 0.5) + assert.are.equal( + 0.5, + a:min_component() + ) + end) + it("should work with a negative vector", function() + local a = Vector3.new(-4, -5, -46) + assert.are.equal( + -46, + a:min_component() + ) + end) + it("should work with a mixed vector", function() + local a = Vector3.new(-30, 3, -3) + assert.are.equal( + -30, + a:min_component() + ) + end) +end) diff --git a/worldeditadditions/utils/vector3.lua b/worldeditadditions/utils/vector3.lua index 3d4bcc5..fa6115e 100644 --- a/worldeditadditions/utils/vector3.lua +++ b/worldeditadditions/utils/vector3.lua @@ -229,6 +229,22 @@ function Vector3.move_towards(a, b, amount) return a + (b - a):limit_to(amount) end +--- Returns the value of the minimum component of the vector. +-- Returns a scalar value. +-- @param a Vector3 The vector to operate on. +-- @returns number The value of the minimum component of the vector. +function Vector3.min_component(a) + return math.min(a.x, a.y, a.z) +end + +--- Returns the value of the maximum component of the vector. +-- Returns a scalar value. +-- @param a Vector3 The vector to operate on. +-- @returns number The value of the maximum component of the vector. +function Vector3.max_component(a) + return math.max(a.x, a.y, a.z) +end + -- ██████ ██████ ███████ ██████ █████ ████████ ██████ ██████ -- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ From 91b77c981b06f9183b03a8cfcb7b79171c420b98 Mon Sep 17 00:00:00 2001 From: Starbeamrainbowlabs Date: Sat, 26 Jun 2021 17:06:53 +0100 Subject: [PATCH 28/32] Vector3: add abs --- .tests/Vector3/abs.test.lua | 35 ++++++++++++++++++++++++++++ worldeditadditions/utils/vector3.lua | 8 +++++++ 2 files changed, 43 insertions(+) create mode 100644 .tests/Vector3/abs.test.lua diff --git a/.tests/Vector3/abs.test.lua b/.tests/Vector3/abs.test.lua new file mode 100644 index 0000000..9803c57 --- /dev/null +++ b/.tests/Vector3/abs.test.lua @@ -0,0 +1,35 @@ +local Vector3 = require("worldeditadditions.utils.vector3") + +describe("Vector3.abs", function() + it("should work with a positive vector", function() + local a = Vector3.new(16, 64, 16) + assert.are.same( + Vector3.new(16, 64, 16), + a:abs() + ) + end) + it("should abs another positive vector", function() + local a = Vector3.new(9, 16, 25) + assert.are.same( + Vector3.new(9, 16, 25), + a:abs() + ) + end) + it("should abs a negative vector", function() + local a = Vector3.new(-9, -16, -25) + assert.are.same( + Vector3.new(9, 16, 25), + a:abs() + ) + end) + it("should return a new Vector3 instance", function() + local a = Vector3.new(9, -16, 25) + + local result = a:abs() + assert.are.same( + Vector3.new(9, 16, 25), + result + ) + assert.are_not.equal(result, a) + end) +end) diff --git a/worldeditadditions/utils/vector3.lua b/worldeditadditions/utils/vector3.lua index fa6115e..2598c07 100644 --- a/worldeditadditions/utils/vector3.lua +++ b/worldeditadditions/utils/vector3.lua @@ -245,6 +245,14 @@ function Vector3.max_component(a) return math.max(a.x, a.y, a.z) end +--- Returns the absolute form of this vector. +-- In other words, it removes the minus sign from all components of the vector. +-- @param a Vector3 The vector to operate on. +-- @returns Vector3 The absolute form of the given vector. +function Vector3.abs(a) + return Vector3.new(math.abs(a.x), math.abs(a.y), math.abs(a.z)) +end + -- ██████ ██████ ███████ ██████ █████ ████████ ██████ ██████ -- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ From 65c07d59eabfd4297376c5abea615a8f85f4ff07 Mon Sep 17 00:00:00 2001 From: Starbeamrainbowlabs Date: Sat, 26 Jun 2021 17:48:39 +0100 Subject: [PATCH 29/32] Vector3: add sort, is_contained, expand_region, mean, min, and max --- .tests/Vector3/expand_region.test.lua | 48 ++++++++++++++ .tests/Vector3/is_contained.test.lua | 44 ++++++++++++ .tests/Vector3/max.test.lua | 44 ++++++++++++ .tests/Vector3/mean.test.lua | 47 +++++++++++++ .tests/Vector3/min.test.lua | 44 ++++++++++++ .tests/Vector3/sort_pos.test.lua | 44 ++++++++++++ worldeditadditions/utils/vector3.lua | 96 +++++++++++++++++++++++++++ 7 files changed, 367 insertions(+) create mode 100644 .tests/Vector3/expand_region.test.lua create mode 100644 .tests/Vector3/is_contained.test.lua create mode 100644 .tests/Vector3/max.test.lua create mode 100644 .tests/Vector3/mean.test.lua create mode 100644 .tests/Vector3/min.test.lua create mode 100644 .tests/Vector3/sort_pos.test.lua diff --git a/.tests/Vector3/expand_region.test.lua b/.tests/Vector3/expand_region.test.lua new file mode 100644 index 0000000..2847464 --- /dev/null +++ b/.tests/Vector3/expand_region.test.lua @@ -0,0 +1,48 @@ +local Vector3 = require("worldeditadditions.utils.vector3") + +describe("Vector3.expand_region", function() + it("should work with positive vectors", function() + local a = Vector3.new(16, 64, 16) + local b = Vector3.new(1, 4, 6) + local target = Vector3.new(99, 99, 99) + + local result_a, result_b = target:expand_region(a, b) + assert.are.same(Vector3.new(1, 4, 6), result_a) + assert.are.same(Vector3.new(99, 99, 99), result_b) + end) + it("should work with mixed components", function() + local a = Vector3.new(16, 1, 16) + local b = Vector3.new(1, 4, 60) + local target = Vector3.new(-99, -99, -99) + + local result_a, result_b = target:expand_region(a, b) + assert.are.same(Vector3.new(-99, -99, -99), result_a) + assert.are.same(Vector3.new(16, 4, 60), result_b) + end) + it("should work with negative vectors", function() + local a = Vector3.new(-9, -16, -25) + local b = Vector3.new(-3, -6, -2) + local target = Vector3.new(-99, -99, -99) + + local result_a, result_b = target:expand_region(a, b) + assert.are.same(Vector3.new(-99, -99, -99), result_a) + assert.are.same(Vector3.new(-3, -6, -2), result_b) + end) + it("should return new Vector3 instances", function() + local a = Vector3.new(16, 1, 16) + local b = Vector3.new(1, 4, 60) + local target = Vector3.new(99, 99, 99) + + local result_a, result_b = target:expand_region(a, b) + assert.are.same(Vector3.new(1, 1, 16), result_a) + assert.are.same(Vector3.new(99, 99, 99), result_b) + + result_a.y = 999 + result_b.y = 999 + + assert.are.same(Vector3.new(16, 1, 16), a) + assert.are.same(Vector3.new(1, 4, 60), b) + assert.are.same(Vector3.new(1, 999, 16), result_a) + assert.are.same(Vector3.new(99, 999, 99), result_b) + end) +end) diff --git a/.tests/Vector3/is_contained.test.lua b/.tests/Vector3/is_contained.test.lua new file mode 100644 index 0000000..9c245ee --- /dev/null +++ b/.tests/Vector3/is_contained.test.lua @@ -0,0 +1,44 @@ +local Vector3 = require("worldeditadditions.utils.vector3") + +describe("Vector3.is_contained", function() + it("should return true when inside", function() + local a = Vector3.new(3, 4, 5) + local b = Vector3.new(30, 40, 50) + local target = Vector3.new(6, 6, 6) + + assert.are.same( + true, + target:is_contained(a, b) + ) + end) + it("should return false when outside x", function() + local a = Vector3.new(3, 4, 5) + local b = Vector3.new(30, 40, 50) + local target = Vector3.new(60, 6, 6) + + assert.are.same( + false, + target:is_contained(a, b) + ) + end) + it("should return false when outside y", function() + local a = Vector3.new(3, 4, 5) + local b = Vector3.new(30, 40, 50) + local target = Vector3.new(6, 60, 6) + + assert.are.same( + false, + target:is_contained(a, b) + ) + end) + it("should return false when outside z", function() + local a = Vector3.new(3, 4, 5) + local b = Vector3.new(30, 40, 50) + local target = Vector3.new(6, 6, 60) + + assert.are.same( + false, + target:is_contained(a, b) + ) + end) +end) diff --git a/.tests/Vector3/max.test.lua b/.tests/Vector3/max.test.lua new file mode 100644 index 0000000..f8d3d2a --- /dev/null +++ b/.tests/Vector3/max.test.lua @@ -0,0 +1,44 @@ +local Vector3 = require("worldeditadditions.utils.vector3") + +describe("Vector3.max", function() + it("should work with positive vectors", function() + local a = Vector3.new(16, 64, 16) + local b = Vector3.new(1, 4, 6) + + assert.are.same( + Vector3.new(16, 64, 16), + Vector3.max(a, b) + ) + end) + it("should work with mixed components", function() + local a = Vector3.new(16, 1, 16) + local b = Vector3.new(1, 4, 60) + + assert.are.same( + Vector3.new(16, 4, 60), + Vector3.max(a, b) + ) + end) + it("should work with negative vectors", function() + local a = Vector3.new(-9, -16, -25) + local b = Vector3.new(-3, -6, -2) + + assert.are.same( + Vector3.new(-3, -6, -2), + Vector3.max(a, b) + ) + end) + it("should return new Vector3 instances", function() + local a = Vector3.new(16, 1, 16) + local b = Vector3.new(1, 4, 60) + + local result = Vector3.max(a, b) + assert.are.same(Vector3.new(16, 4, 60), result) + + result.y = 999 + + assert.are.same(Vector3.new(16, 1, 16), a) + assert.are.same(Vector3.new(1, 4, 60), b) + assert.are.same(Vector3.new(16, 999, 60), result) + end) +end) diff --git a/.tests/Vector3/mean.test.lua b/.tests/Vector3/mean.test.lua new file mode 100644 index 0000000..0604d68 --- /dev/null +++ b/.tests/Vector3/mean.test.lua @@ -0,0 +1,47 @@ +local Vector3 = require("worldeditadditions.utils.vector3") + +describe("Vector3.mean", function() + it("should work with a positive vector", function() + local a = Vector3.new(2, 2, 2) + local b = Vector3.new(4, 4, 4) + assert.are.same( + Vector3.new(3, 3, 3), + a:mean(b) + ) + end) + it("should work with a positive vector the other way around", function() + local a = Vector3.new(2, 2, 2) + local b = Vector3.new(4, 4, 4) + assert.are.same( + Vector3.new(3, 3, 3), + b:mean(a) + ) + end) + it("should mean another positive vector", function() + local a = Vector3.new(6, 6, 6) + local b = Vector3.new(10, 10, 10) + assert.are.same( + Vector3.new(8, 8, 8), + a:mean(b) + ) + end) + it("should mean a negative vector", function() + local a = Vector3.new(-2, -2, -2) + local b = Vector3.new(0, 0, 0) + assert.are.same( + Vector3.new(-1, -1, -1), + a:mean(b) + ) + end) + it("should return a new Vector3 instance", function() + local a = Vector3.new(6, 6, 6) + local b = Vector3.new(10, 10, 10) + assert.are.same( + Vector3.new(8, 8, 8), + a:mean(b) + ) + + assert.are.same(Vector3.new(6, 6, 6), a) + assert.are.same(Vector3.new(10, 10, 10), b) + end) +end) diff --git a/.tests/Vector3/min.test.lua b/.tests/Vector3/min.test.lua new file mode 100644 index 0000000..332d74d --- /dev/null +++ b/.tests/Vector3/min.test.lua @@ -0,0 +1,44 @@ +local Vector3 = require("worldeditadditions.utils.vector3") + +describe("Vector3.min", function() + it("should work with positive vectors", function() + local a = Vector3.new(16, 64, 16) + local b = Vector3.new(1, 4, 6) + + assert.are.same( + Vector3.new(1, 4, 6), + Vector3.min(a, b) + ) + end) + it("should work with mixed components", function() + local a = Vector3.new(16, 1, 16) + local b = Vector3.new(1, 4, 60) + + assert.are.same( + Vector3.new(1, 1, 16), + Vector3.min(a, b) + ) + end) + it("should work with negative vectors", function() + local a = Vector3.new(-9, -16, -25) + local b = Vector3.new(-3, -6, -2) + + assert.are.same( + Vector3.new(-9, -16, -25), + Vector3.min(a, b) + ) + end) + it("should return new Vector3 instances", function() + local a = Vector3.new(16, 1, 16) + local b = Vector3.new(1, 4, 60) + + local result = Vector3.min(a, b) + assert.are.same(Vector3.new(1, 1, 16), result) + + result.y = 999 + + assert.are.same(Vector3.new(16, 1, 16), a) + assert.are.same(Vector3.new(1, 4, 60), b) + assert.are.same(Vector3.new(1, 999, 16), result) + end) +end) diff --git a/.tests/Vector3/sort_pos.test.lua b/.tests/Vector3/sort_pos.test.lua new file mode 100644 index 0000000..df8a89f --- /dev/null +++ b/.tests/Vector3/sort_pos.test.lua @@ -0,0 +1,44 @@ +local Vector3 = require("worldeditadditions.utils.vector3") + +describe("Vector3.sort", function() + it("should work with positive vectors", function() + local a = Vector3.new(16, 64, 16) + local b = Vector3.new(1, 4, 6) + + local result_a, result_b = Vector3.sort(a, b) + assert.are.same(Vector3.new(1, 4, 6), result_a) + assert.are.same(Vector3.new(16, 64, 16), result_b) + end) + it("should work with mixed components", function() + local a = Vector3.new(16, 1, 16) + local b = Vector3.new(1, 4, 60) + + local result_a, result_b = Vector3.sort(a, b) + assert.are.same(Vector3.new(1, 1, 16), result_a) + assert.are.same(Vector3.new(16, 4, 60), result_b) + end) + it("should work with negative vectors", function() + local a = Vector3.new(-9, -16, -25) + local b = Vector3.new(-3, -6, -2) + + local result_a, result_b = Vector3.sort(a, b) + assert.are.same(Vector3.new(-9, -16, -25), result_a) + assert.are.same(Vector3.new(-3, -6, -2), result_b) + end) + it("should return new Vector3 instances", function() + local a = Vector3.new(16, 1, 16) + local b = Vector3.new(1, 4, 60) + + local result_a, result_b = Vector3.sort(a, b) + assert.are.same(Vector3.new(1, 1, 16), result_a) + assert.are.same(Vector3.new(16, 4, 60), result_b) + + result_a.y = 999 + result_b.y = 999 + + assert.are.same(Vector3.new(16, 1, 16), a) + assert.are.same(Vector3.new(1, 4, 60), b) + assert.are.same(Vector3.new(1, 999, 16), result_a) + assert.are.same(Vector3.new(16, 999, 60), result_b) + end) +end) diff --git a/worldeditadditions/utils/vector3.lua b/worldeditadditions/utils/vector3.lua index 2598c07..cfa2440 100644 --- a/worldeditadditions/utils/vector3.lua +++ b/worldeditadditions/utils/vector3.lua @@ -253,6 +253,102 @@ function Vector3.abs(a) return Vector3.new(math.abs(a.x), math.abs(a.y), math.abs(a.z)) end +--- Sorts the components of the given vectors. +-- pos1 will contain the minimum values, and pos2 the maximum values. +-- Returns 2 new vectors. +-- Note that the vectors provided do not *have* to be instances of Vector3. +-- It is only required that they have the keys x, y, and z. +-- Vector3 instances are always returned. +-- This enables convenient ingesting of positions from outside. +-- @param pos1 Vector3 The first vector to operate on. +-- @param pos2 Vector3 The second vector to operate on. +-- @returns Vector3,Vector3 The 2 sorted vectors. +function Vector3.sort(pos1, pos2) + local pos1_new = Vector3.clone(pos1) -- This way we can accept non-Vector3 instances + local pos2_new = Vector3.clone(pos2) -- This way we can accept non-Vector3 instances + if pos1_new.x > pos2_new.x then + pos1_new.x, pos2_new.x = pos2_new.x, pos1_new.x + end + if pos1_new.y > pos2_new.y then + pos1_new.y, pos2_new.y = pos2_new.y, pos1_new.y + end + if pos1_new.z > pos2_new.z then + pos1_new.z, pos2_new.z = pos2_new.z, pos1_new.z + end + return pos1_new, pos2_new +end + +--- Determines if this vector is contained within the region defined by the given vectors. +-- @param a Vector3 The target vector to check. +-- @param pos1 Vector3 pos1 of the defined region. +-- @param pos2 Vector3 pos2 of the defined region. +-- @return boolean Whether the given target is contained within the defined worldedit region. +function Vector3.is_contained(target, pos1, pos2) + local pos1, pos2 = Vector3.sort(pos1, pos2) + + return pos1.x <= target.x + and pos1.y <= target.y + and pos1.z <= target.z + and pos2.x >= target.x + and pos2.y >= target.y + and pos2.z >= target.z +end + + +--- Expands the defined region to include the given point. +-- @param target Vector3 The target vector to include. +-- @param pos1 Vector3 pos1 of the defined region. +-- @param pos2 Vector3 pos2 of the defined region. +-- @returns Vector3,Vector3 2 vectors that represent the expand_region. +function Vector3.expand_region(target, pos1, pos2) + local pos1, pos2 = Vector3.sort(pos1, pos2) + + if target.x < pos1.x then pos1.x = target.x end + if target.y < pos1.y then pos1.y = target.y end + if target.z < pos1.z then pos1.z = target.z end + + if target.x > pos2.x then pos2.x = target.x end + if target.y > pos2.y then pos2.y = target.y end + if target.z > pos2.z then pos2.z = target.z end + + return pos1, pos2 +end + +--- Returns the mean (average) of 2 positions. +-- In other words, returns the centre of 2 points. +-- @param pos1 Vector3 pos1 of the defined region. +-- @param pos2 Vector3 pos2 of the defined region. +-- @param target Vector3 Centre coordinates. +function Vector3.mean(pos1, pos2) + return (pos1 + pos2) / 2 +end + + +--- Returns a vector of the min components of 2 vectors. +-- @param pos1 Vector3 The first vector to operate on. +-- @param pos2 Vector3 The second vector to operate on. +-- @return Vector3 The minimum values from the input vectors +function Vector3.min(pos1, pos2) + return Vector3.new( + math.min(pos1.x, pos2.x), + math.min(pos1.y, pos2.y), + math.min(pos1.z, pos2.z) + ) +end + +--- Returns a vector of the max values of 2 vectors. +-- @param pos1 Vector3 The first vector to operate on. +-- @param pos2 Vector3 The second vector to operate on. +-- @return Vector3 The maximum values from the input vectors. +function Vector3.max(pos1, pos2) + return Vector3.new( + math.max(pos1.x, pos2.x), + math.max(pos1.y, pos2.y), + math.max(pos1.z, pos2.z) + ) +end + + -- ██████ ██████ ███████ ██████ █████ ████████ ██████ ██████ -- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ From dbdf509d79c397d215f0f03a788ace4661a5b0a3 Mon Sep 17 00:00:00 2001 From: Starbeamrainbowlabs Date: Sat, 26 Jun 2021 19:48:32 +0100 Subject: [PATCH 30/32] Add dofile for vector3 --- worldeditadditions/init.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/worldeditadditions/init.lua b/worldeditadditions/init.lua index 08c03e0..85df12c 100644 --- a/worldeditadditions/init.lua +++ b/worldeditadditions/init.lua @@ -8,6 +8,7 @@ worldeditadditions = {} worldeditadditions.modpath = minetest.get_modpath("worldeditadditions") dofile(worldeditadditions.modpath.."/utils/vector.lua") +dofile(worldeditadditions.modpath.."/utils/vector3.lua") dofile(worldeditadditions.modpath.."/utils/strings/init.lua") dofile(worldeditadditions.modpath.."/utils/format/init.lua") From f32d8588e07b2e605a4fddd558d5ee0293854227 Mon Sep 17 00:00:00 2001 From: Starbeamrainbowlabs Date: Sat, 26 Jun 2021 22:03:55 +0100 Subject: [PATCH 31/32] Add Mesh & Face classes for #59 Together, these classes provide a way to represent a mesh of faces generated from the Minetest world. This way, the generation of a mesh can be abstracted away from any potential output file writers, thereby allowing for multiple different output file formats to be supported. --- worldeditadditions/init.lua | 1 + worldeditadditions/utils/mesh.lua | 99 +++++++++++++++++++ worldeditadditions/utils/tables/init.lua | 1 + .../utils/tables/table_contains.lua | 18 ++++ worldeditadditions/utils/vector3.lua | 1 + 5 files changed, 120 insertions(+) create mode 100644 worldeditadditions/utils/mesh.lua create mode 100644 worldeditadditions/utils/tables/table_contains.lua diff --git a/worldeditadditions/init.lua b/worldeditadditions/init.lua index 85df12c..4a1e1cb 100644 --- a/worldeditadditions/init.lua +++ b/worldeditadditions/init.lua @@ -9,6 +9,7 @@ worldeditadditions = {} worldeditadditions.modpath = minetest.get_modpath("worldeditadditions") dofile(worldeditadditions.modpath.."/utils/vector.lua") dofile(worldeditadditions.modpath.."/utils/vector3.lua") +dofile(worldeditadditions.modpath.."/utils/mesh.lua") dofile(worldeditadditions.modpath.."/utils/strings/init.lua") dofile(worldeditadditions.modpath.."/utils/format/init.lua") diff --git a/worldeditadditions/utils/mesh.lua b/worldeditadditions/utils/mesh.lua new file mode 100644 index 0000000..e496f8f --- /dev/null +++ b/worldeditadditions/utils/mesh.lua @@ -0,0 +1,99 @@ +local wea = worldeditadditions + + +-- ███████ █████ ██████ ███████ +-- ██ ██ ██ ██ ██ +-- █████ ███████ ██ █████ +-- ██ ██ ██ ██ ██ +-- ██ ██ ██ ██████ ███████ + +--- A single face of a Mesh. +local Face = {} +Face.__index = Face + +--- Creates a new face from a list of vertices. +-- The list of vertices should be anti-clockwise. +-- @param vertices Vector3[] A list of Vector3 vertices that define the face. +function Face.new(vertices) + local result = { vertices = vertices } + setmetatable(result, Face) + return result +end + +--- Determines whether this face is equal to another face or not. +-- @param a Face The first face to compare. +-- @param b Face The second face to compare. +-- @returns bool Whether the 2 faces are equal or not. +function Face.equal(a, b) + if #a.vertices ~= #b.vertices then return false end + for i,vertex in ipairs(a) do + if vertex ~= b.vertices[i] then return false end + end + return true +end +function Face.__eq(a, b) return Face.equal(a, b) end + + +-- ███ ███ ███████ ███████ ██ ██ +-- ████ ████ ██ ██ ██ ██ +-- ██ ████ ██ █████ ███████ ███████ +-- ██ ██ ██ ██ ██ ██ ██ +-- ██ ██ ███████ ███████ ██ ██ + +--- A mesh of faces. +local Mesh = {} +Mesh.__index = Mesh + +--- Creates a new empty mesh object container. +-- @returns Mesh +function Mesh.new() + local result = { faces = {} } + setmetatable(result, Mesh) +end + +--- Adds a face to this mesh. +-- @param self Mesh The mesh instance to operate on. +-- @param face Face The face to add. +-- @returns void +function Mesh.add_face(self, face) + table.insert(self.faces, face) +end + +--- Deduplicate the list of faces in this Mesh. +-- Removes all faces that are exactly equal to one another. This reduces the +-- filesize. +-- @returns number The number of faces removed. +function Mesh.dedupe(self) + -- Find the faces to remove + local toremove = {} + for i,face_check in ipairs(self.faces) do + for j,face_next in ipairs(self.faces) do + if i ~= j -- If we're not comparing a face to itself... + and face_check == face_next -- ....and the 2 faces are equal.... + and not wea.table_contains(toremove, j) then -- ...and we haven't already marked it for removal... + -- Mark it for removal + table.insert(toremove, j) + end + end + end + -- Sort the list of indexes marked for removal from largest to smallest + -- This way, removing smaller items doesn't alter the index of larger ones + table.sort(toremove, function(a, b) return a > b end) + + -- Remove the faces marked for removal + for i, remove_index in ipairs(toremove) do + table.remove(self.faces, remove_index) + end + return #toremove +end + + +if worldeditadditions then + worldeditadditions.Face = Face + worldeditadditions.Mesh = Mesh +else + return { + Face = Face, + Mesh = Mesh + } +end diff --git a/worldeditadditions/utils/tables/init.lua b/worldeditadditions/utils/tables/init.lua index 2536672..2ccf93b 100644 --- a/worldeditadditions/utils/tables/init.lua +++ b/worldeditadditions/utils/tables/init.lua @@ -20,3 +20,4 @@ dofile(worldeditadditions.modpath.."/utils/tables/table_map.lua") dofile(worldeditadditions.modpath.."/utils/tables/table_tostring.lua") dofile(worldeditadditions.modpath.."/utils/tables/table_unique.lua") dofile(worldeditadditions.modpath.."/utils/tables/table_unpack.lua") +dofile(worldeditadditions.modpath.."/utils/tables/table_contains.lua") diff --git a/worldeditadditions/utils/tables/table_contains.lua b/worldeditadditions/utils/tables/table_contains.lua new file mode 100644 index 0000000..c65fdfe --- /dev/null +++ b/worldeditadditions/utils/tables/table_contains.lua @@ -0,0 +1,18 @@ + +--- Looks to see whether a given table contains a given value. +-- @param tbl table The table to look in. +-- @param target any The target to look for. +-- @returns bool Whether the table contains the given target or not. +local function table_contains(tbl, target) + for key, value in ipairs(tbl) do + if value == target then return true end + end + return false +end + + +if worldeditadditions then + worldeditadditions.table_contains = table_contains +else + return table_contains +end diff --git a/worldeditadditions/utils/vector3.lua b/worldeditadditions/utils/vector3.lua index cfa2440..095c3d8 100644 --- a/worldeditadditions/utils/vector3.lua +++ b/worldeditadditions/utils/vector3.lua @@ -1,3 +1,4 @@ +--- A 3-dimensional vector. local Vector3 = {} Vector3.__index = Vector3 From 3467f9c5b60e45230d1d6dcf0b37b0cd62d43ba3 Mon Sep 17 00:00:00 2001 From: VorTechnix <45538536+VorTechnix@users.noreply.github.com> Date: Sat, 26 Jun 2021 21:39:16 -0700 Subject: [PATCH 32/32] fixed min and max --- worldeditadditions/utils/vector.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/worldeditadditions/utils/vector.lua b/worldeditadditions/utils/vector.lua index 4c767b4..7f330da 100644 --- a/worldeditadditions/utils/vector.lua +++ b/worldeditadditions/utils/vector.lua @@ -110,7 +110,7 @@ end -- @param pos2 Vector pos2 of the defined region. -- @return Vector Min values from input vectors. function worldeditadditions.vector.min(pos1, pos2) - return vector.new(math.min(pos1.x + pos2.x), math.min(pos1.y + pos2.y), math.min(pos1.z + pos2.z)) + return vector.new(math.min(pos1.x, pos2.x), math.min(pos1.y, pos2.y), math.min(pos1.z, pos2.z)) end --- Returns a vector of the max values of 2 positions. @@ -118,5 +118,5 @@ end -- @param pos2 Vector pos2 of the defined region. -- @return Vector Max values from input vectors. function worldeditadditions.vector.max(pos1, pos2) - return vector.new(math.max(pos1.x + pos2.x), math.max(pos1.y + pos2.y), math.max(pos1.z + pos2.z)) + return vector.new(math.max(pos1.x, pos2.x), math.max(pos1.y, pos2.y), math.max(pos1.z, pos2.z)) end