mirror of
https://github.com/sbrl/Minetest-WorldEditAdditions.git
synced 2024-11-22 23:42:59 +00:00
Implement //Smake (#61)
This commit is contained in:
commit
9ad3fd97d9
14 changed files with 305 additions and 33 deletions
|
@ -7,13 +7,14 @@ Note to self: See the bottom of this file for the release template text.
|
||||||
- Add `//spush`, `//spop`, and `//sstack`
|
- Add `//spush`, `//spop`, and `//sstack`
|
||||||
- Add `//srect` (_select rectangle_), `//scol` (_select column_), `//scube` (_select cube_) - thanks, @VorTechnix!
|
- 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!
|
- 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)
|
- Significantly refactored backend utility functions (more to come in future updates)
|
||||||
- `//bonemeal`: Try bonemealing everything that isn't an air block (#49)
|
- `//bonemeal`: Try bonemealing everything that isn't an air block (#49)
|
||||||
- Add new universal chance parsing
|
- Add new universal chance parsing
|
||||||
- Any `<chance>` can now either be a 1-in-N number (e.g. `4`, `10`), or a percentage chance (e.g. `50%`, `10%`).
|
- Any `<chance>` 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
|
- Caveat: Percentages are converted to a 1-in-N chance, but additionally that number is rounded down in some places
|
||||||
- `//torus`, `//hollowtorus`: Add optional new axes
|
- `//torus`, `//hollowtorus`: Add optional new axes
|
||||||
- `//torus`: Add optional hollow keyword - @VorTechnix
|
- `//torus`, `//ellipsoid`: Add optional hollow keyword - @VorTechnix
|
||||||
- `//multi`: Add curly brace syntax for nesting command calls ([more information](https://github.com/sbrl/Minetest-WorldEditAdditions/blob/main/Chat-Command-Reference.md#multi-command_a-command_b-command_c-))
|
- `//multi`: Add curly brace syntax for nesting command calls ([more information](https://github.com/sbrl/Minetest-WorldEditAdditions/blob/main/Chat-Command-Reference.md#multi-command_a-command_b-command_c-))
|
||||||
- `//erode`: Add new `river` erosion algorithm for filling in potholes and removing pillars
|
- `//erode`: Add new `river` erosion algorithm for filling in potholes and removing pillars
|
||||||
|
|
||||||
|
|
|
@ -109,13 +109,15 @@ Note that the *entire* cave you want filling must be selected, as `//fillcaves`
|
||||||
//fillcaves brick
|
//fillcaves brick
|
||||||
```
|
```
|
||||||
|
|
||||||
## `//ellipsoid <rx> <ry> <rz> <node_name>`
|
## `//ellipsoid <rx> <ry> <rz> <node_name> [h[ollow]]`
|
||||||
Creates a solid ellipsoid at position 1 with the radius `(rx, ry, rz)`.
|
Creates a solid ellipsoid at position 1 with the radius `(rx, ry, rz)`.
|
||||||
|
|
||||||
```
|
```
|
||||||
//ellipsoid 10 5 15 ice
|
//ellipsoid 10 5 15 ice
|
||||||
//ellipsoid 3 5 10 dirt
|
//ellipsoid 3 5 10 dirt
|
||||||
//ellipsoid 20 10 40 air
|
//ellipsoid 20 10 40 air
|
||||||
|
//ellipsoid 14 5 8 steelblock h
|
||||||
|
//ellipsoid 7 4 7 papyrus hollow
|
||||||
```
|
```
|
||||||
|
|
||||||
## `//hollowellipsoid <rx> <ry> <rz> <node_name>`
|
## `//hollowellipsoid <rx> <ry> <rz> <node_name>`
|
||||||
|
@ -447,7 +449,7 @@ maxdiff | `float` | 0.4 | The maximum difference in height (between 0 and
|
||||||
count | `float` | 25000 | The number of snowballs to simulate.
|
count | `float` | 25000 | The number of snowballs to simulate.
|
||||||
noconv | any | n/a | When set to any value, disables to automatic 3x3 gaussian convolution.
|
noconv | any | n/a | When set to any value, disables to automatic 3x3 gaussian convolution.
|
||||||
|
|
||||||
Example invocations:
|
Usage examples:
|
||||||
|
|
||||||
```
|
```
|
||||||
//erode
|
//erode
|
||||||
|
@ -468,7 +470,7 @@ raise_sides | `string` | 4,3 | Comma separated list of numbers. Columns wit
|
||||||
doraise | `boolean` | true | Whether to raise columns in height. If false, then no columns will be raised in height even if they are eligible to be so according to `raise_sides`.
|
doraise | `boolean` | true | Whether to raise columns in height. If false, then no columns will be raised in height even if they are eligible to be so according to `raise_sides`.
|
||||||
dolower | `boolean` | true | Whether to lower columns in height. If false, then no columns will be lowered in height even if they are eligible to be so according to `lower_sides`.
|
dolower | `boolean` | true | Whether to lower columns in height. If false, then no columns will be lowered in height even if they are eligible to be so according to `lower_sides`.
|
||||||
|
|
||||||
Example invocations:
|
Usage examples:
|
||||||
|
|
||||||
```
|
```
|
||||||
//erode river
|
//erode river
|
||||||
|
@ -584,14 +586,14 @@ Short for _select point cloud_. Sets pos1 and pos2 to include the nodes you punc
|
||||||
```
|
```
|
||||||
|
|
||||||
## `//scentre`
|
## `//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 by @VorTechnix.
|
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.
|
||||||
|
|
||||||
```
|
```
|
||||||
//scentre
|
//scentre
|
||||||
```
|
```
|
||||||
|
|
||||||
## `//srel <axis1> <length1> [<axis2> <length2> [<axis3> <length3>]]`
|
## `//srel <axis1> <length1> [<axis2> <length2> [<axis3> <length3>]]`
|
||||||
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 by @VorTechnix.
|
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.
|
||||||
|
|
||||||
```
|
```
|
||||||
//srel front 5
|
//srel front 5
|
||||||
|
@ -600,6 +602,55 @@ Short for _select relative_. Sets the pos2 at set distances along 3 axes relativ
|
||||||
//scube -z 12 -y -2 x -2
|
//scube -z 12 -y -2 x -2
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## `//smake <operation> <mode> [<target=xz> [<base>]]`
|
||||||
|
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:
|
||||||
|
|
||||||
|
```
|
||||||
|
//smake odd shrink
|
||||||
|
//smake even avg xz
|
||||||
|
//smake equal grow xy
|
||||||
|
//smake equal average
|
||||||
|
//smake equal zy x
|
||||||
|
```
|
||||||
|
|
||||||
|
### `<operation>`: odd/even/equal/factor
|
||||||
|
|
||||||
|
|Value | Description |
|
||||||
|
| --- | --- |
|
||||||
|
odd: | round up or down, based on mode, all axes specified in `<target>` to the nearest odd length relative to pos1
|
||||||
|
even: | round up or down, based on mode, all axes specified in `<target>` to the nearest even length relative to pos1
|
||||||
|
equal: | set `<target>` axes length equal to the length of `<base>` axis if specified or to the length of the largest, smallest or average of the `<target>` axes based on mode.
|
||||||
|
|
||||||
|
### `<mode>:` grow/shrink/average
|
||||||
|
|
||||||
|
#### *If `<operation>` == odd or even:*
|
||||||
|
|
||||||
|
|Value | Description |
|
||||||
|
| --- | --- |
|
||||||
|
grow: | grow each axis specified in `<target>` to the nearest odd/even number to itself
|
||||||
|
shrink: | shrink each axis specified in `<target>` to the nearest odd/even number to itself
|
||||||
|
average/avg: | take the average of all axes specified in `<target>` 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 `<operation>` == equal:* ^[1]
|
||||||
|
|
||||||
|
|Value | Description |
|
||||||
|
| --- | --- |
|
||||||
|
grow: | grow each axis specified in `<target>` to the length of the longest specified axis
|
||||||
|
shrink: | shrink each axis specified in `<target>` to the length of the shortest specified axis
|
||||||
|
average/avg: | set each axis specified in `<target>` to the average length of all the specified axes
|
||||||
|
|
||||||
|
### Additional arguments:
|
||||||
|
|
||||||
|
|Name | Description |
|
||||||
|
| --- | --- |
|
||||||
|
`<target>`: | Specify axes to perform operation on (default= xz)|
|
||||||
|
`<base>`: If `<operation>` == odd or even: | Does nothing
|
||||||
|
`<base>`: If `<operation>` == equal: | Overrides `<mode>`^[1] and sets all `<target>` axes equal to itself
|
||||||
|
|
||||||
|
^[1]: `<mode>` argument can be omitted and will not be parsed if present if `<base>` is specified
|
||||||
|
|
||||||
## `//sstack`
|
## `//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).
|
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).
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ See also:
|
||||||
|
|
||||||
|
|
||||||
## Fix lighting
|
## Fix lighting
|
||||||
|
|
||||||
```
|
```
|
||||||
//multi //1 //2 //outset 50 //fixlight //y
|
//multi //1 //2 //outset 50 //fixlight //y
|
||||||
```
|
```
|
||||||
|
|
|
@ -28,7 +28,7 @@ _(Do you have a cool build that you used WorldEditAdditions to build? [Get in to
|
||||||
The detailed explanations have moved! Check them out [here](https://github.com/sbrl/Minetest-WorldEditAdditions/blob/main/Chat-Command-Reference.md), or click the links below.
|
The detailed explanations have moved! Check them out [here](https://github.com/sbrl/Minetest-WorldEditAdditions/blob/main/Chat-Command-Reference.md), or click the links below.
|
||||||
|
|
||||||
### Geometry
|
### Geometry
|
||||||
- [`//ellipsoid <rx> <ry> <rz> <node_name>`](https://github.com/sbrl/Minetest-WorldEditAdditions/blob/main/Chat-Command-Reference.md#ellipsoid-rx-ry-rz-node_name)
|
- [`//ellipsoid <rx> <ry> <rz> <node_name> [h[ollow]]`](https://github.com/sbrl/Minetest-WorldEditAdditions/blob/main/Chat-Command-Reference.md#ellipsoid-rx-ry-rz-node_name-hollow)
|
||||||
- [`//hollowellipsoid <rx> <ry> <rz> <node_name>`](https://github.com/sbrl/Minetest-WorldEditAdditions/blob/main/Chat-Command-Reference.md#hollowellipsoid-rx-ry-rz-node_name)
|
- [`//hollowellipsoid <rx> <ry> <rz> <node_name>`](https://github.com/sbrl/Minetest-WorldEditAdditions/blob/main/Chat-Command-Reference.md#hollowellipsoid-rx-ry-rz-node_name)
|
||||||
- [`//torus <major_radius> <minor_radius> <node_name> [<axes=xy> [h[ollow]]]`](https://github.com/sbrl/Minetest-WorldEditAdditions/blob/main/Chat-Command-Reference.md#torus-major_radius-minor_radius-node_name-axesxy-hollow)
|
- [`//torus <major_radius> <minor_radius> <node_name> [<axes=xy> [h[ollow]]]`](https://github.com/sbrl/Minetest-WorldEditAdditions/blob/main/Chat-Command-Reference.md#torus-major_radius-minor_radius-node_name-axesxy-hollow)
|
||||||
- [`//hollowtorus <major_radius> <minor_radius> <node_name> [<axes=xy>]`](https://github.com/sbrl/Minetest-WorldEditAdditions/blob/main/Chat-Command-Reference.md#hollowtorus-major_radius-minor_radius-node_name-axesxy)
|
- [`//hollowtorus <major_radius> <minor_radius> <node_name> [<axes=xy>]`](https://github.com/sbrl/Minetest-WorldEditAdditions/blob/main/Chat-Command-Reference.md#hollowtorus-major_radius-minor_radius-node_name-axesxy)
|
||||||
|
|
|
@ -1,3 +1,9 @@
|
||||||
|
-- ██████ █████ ██████ ███████ ███████
|
||||||
|
-- ██ ██ ██ ██ ██ ██ ██ ██
|
||||||
|
-- ██████ ███████ ██████ ███████ █████
|
||||||
|
-- ██ ██ ██ ██ ██ ██ ██
|
||||||
|
-- ██ ██ ██ ██ ██ ███████ ███████
|
||||||
|
|
||||||
worldeditadditions.parse = {}
|
worldeditadditions.parse = {}
|
||||||
|
|
||||||
dofile(worldeditadditions.modpath.."/utils/parse/chance.lua")
|
dofile(worldeditadditions.modpath.."/utils/parse/chance.lua")
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
dofile(worldeditadditions.modpath.."/utils/strings/split.lua")
|
dofile(worldeditadditions.modpath.."/utils/strings/split.lua")
|
||||||
dofile(worldeditadditions.modpath.."/utils/strings/polyfill.lua")
|
dofile(worldeditadditions.modpath.."/utils/strings/polyfill.lua")
|
||||||
|
dofile(worldeditadditions.modpath.."/utils/strings/tochars.lua")
|
||||||
|
|
27
worldeditadditions/utils/strings/tochars.lua
Normal file
27
worldeditadditions/utils/strings/tochars.lua
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
--- Split into table of characters.
|
||||||
|
-- @param text string The string to iterate over
|
||||||
|
-- @param sort bool Sort characters
|
||||||
|
-- @param rem_dups bool Remove duplicate characters
|
||||||
|
-- @returns table A sequence table containing the substrings
|
||||||
|
function worldeditadditions.tochars(text,sort,rem_dups)
|
||||||
|
local t, set = {}, {}
|
||||||
|
if rem_dups then
|
||||||
|
text:gsub(".",function(c) set[c] = true end)
|
||||||
|
for k,v in pairs(set) do table.insert(t,k) end
|
||||||
|
else
|
||||||
|
text:gsub(".",function(c) table.insert(t,c) end)
|
||||||
|
end
|
||||||
|
|
||||||
|
if sort then table.sort(t) end
|
||||||
|
|
||||||
|
return t
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Split into a set of characters.
|
||||||
|
-- @param text string The string to iterate over
|
||||||
|
-- @returns table A sequence set table containing the substrings
|
||||||
|
function worldeditadditions.tocharset(text)
|
||||||
|
local t = {}
|
||||||
|
text:gsub(".",function(c) t[c] = true end)
|
||||||
|
return t
|
||||||
|
end
|
|
@ -9,12 +9,14 @@
|
||||||
-- extensive collection of functions :P
|
-- extensive collection of functions :P
|
||||||
|
|
||||||
-- TODO: Refactor into its own worldeditadditions.tables namespace.
|
-- TODO: Refactor into its own worldeditadditions.tables namespace.
|
||||||
|
worldeditadditions.tables = {}
|
||||||
|
|
||||||
|
dofile(worldeditadditions.modpath.."/utils/tables/sets.lua")
|
||||||
dofile(worldeditadditions.modpath.."/utils/tables/shallowcopy.lua")
|
dofile(worldeditadditions.modpath.."/utils/tables/shallowcopy.lua")
|
||||||
dofile(worldeditadditions.modpath.."/utils/tables/table_apply.lua")
|
dofile(worldeditadditions.modpath.."/utils/tables/table_apply.lua")
|
||||||
dofile(worldeditadditions.modpath.."/utils/tables/table_unpack.lua")
|
|
||||||
dofile(worldeditadditions.modpath.."/utils/tables/table_get_last.lua")
|
|
||||||
dofile(worldeditadditions.modpath.."/utils/tables/table_tostring.lua")
|
|
||||||
dofile(worldeditadditions.modpath.."/utils/tables/table_map.lua")
|
|
||||||
dofile(worldeditadditions.modpath.."/utils/tables/table_filter.lua")
|
dofile(worldeditadditions.modpath.."/utils/tables/table_filter.lua")
|
||||||
|
dofile(worldeditadditions.modpath.."/utils/tables/table_get_last.lua")
|
||||||
|
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_unique.lua")
|
||||||
|
dofile(worldeditadditions.modpath.."/utils/tables/table_unpack.lua")
|
||||||
|
|
9
worldeditadditions/utils/tables/sets.lua
Normal file
9
worldeditadditions/utils/tables/sets.lua
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
--- Creates a table that stores data in keys.
|
||||||
|
-- @source https://riptutorial.com/lua/example/13407/search-for-an-item-in-a-list
|
||||||
|
-- @param list table The table of values to convert to keys.
|
||||||
|
-- @return table The table of (key,true) pairs.
|
||||||
|
function worldeditadditions.makeset (list)
|
||||||
|
local set = {}
|
||||||
|
for _, l in ipairs(list) do set[l] = true end
|
||||||
|
return set
|
||||||
|
end
|
|
@ -5,7 +5,7 @@ function worldeditadditions.vector.tostring(v)
|
||||||
return "(" .. v.x ..", " .. v.y ..", " .. v.z ..")"
|
return "(" .. v.x ..", " .. v.y ..", " .. v.z ..")"
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Calculates the length squared of the given vector.
|
--- Calculates the length squared of the given vector.
|
||||||
-- @param v Vector The vector to operate on
|
-- @param v Vector The vector to operate on
|
||||||
-- @return number The length of the given vector squared
|
-- @return number The length of the given vector squared
|
||||||
function worldeditadditions.vector.lengthsquared(v)
|
function worldeditadditions.vector.lengthsquared(v)
|
||||||
|
@ -53,6 +53,17 @@ function worldeditadditions.vector.ceil(v)
|
||||||
if v.z then v.z = math.ceil(v.z) end
|
if v.z then v.z = math.ceil(v.z) end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Sets the values in a vector to their absolute values.
|
||||||
|
-- Warning: This MUTATES the given vector!
|
||||||
|
-- @param v Vector The vector to operate on
|
||||||
|
function worldeditadditions.vector.abs(v)
|
||||||
|
if v.x then v.x = math.abs(v.x) end
|
||||||
|
-- Some vectors are 2d, but on the x / z axes
|
||||||
|
if v.y then v.y = math.abs(v.y) end
|
||||||
|
-- Some vectors are 2d
|
||||||
|
if v.z then v.z = math.abs(v.z) end
|
||||||
|
end
|
||||||
|
|
||||||
--- Determines if the target point is contained within the defined worldedit region.
|
--- Determines if the target point is contained within the defined worldedit region.
|
||||||
-- @param pos1 Vector pos1 of the defined region.
|
-- @param pos1 Vector pos1 of the defined region.
|
||||||
-- @param pos2 Vector pos2 of the defined region.
|
-- @param pos2 Vector pos2 of the defined region.
|
||||||
|
@ -93,3 +104,19 @@ end
|
||||||
function worldeditadditions.vector.mean(pos1, pos2)
|
function worldeditadditions.vector.mean(pos1, pos2)
|
||||||
return vector.new((pos1.x + pos2.x)/2, (pos1.y + pos2.y)/2, (pos1.z + pos2.z)/2)
|
return vector.new((pos1.x + pos2.x)/2, (pos1.y + pos2.y)/2, (pos1.z + pos2.z)/2)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Returns a vector of the min values of 2 positions.
|
||||||
|
-- @param pos1 Vector pos1 of the defined region.
|
||||||
|
-- @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))
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Returns a vector of the max values of 2 positions.
|
||||||
|
-- @param pos1 Vector pos1 of the defined region.
|
||||||
|
-- @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))
|
||||||
|
end
|
||||||
|
|
|
@ -3,35 +3,35 @@
|
||||||
-- █████ ██ ██ ██ ██████ ███████ ██ ██ ██ ██ ██
|
-- █████ ██ ██ ██ ██████ ███████ ██ ██ ██ ██ ██
|
||||||
-- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
|
-- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
|
||||||
-- ███████ ███████ ███████ ██ ██ ███████ ██████ ██ ██████
|
-- ███████ ███████ ███████ ██ ██ ███████ ██████ ██ ██████
|
||||||
|
local wea = worldeditadditions
|
||||||
local function parse_params_ellipsoid(params_text)
|
local function parse_params_ellipsoid(params_text)
|
||||||
local found, _, radius_x, radius_y, radius_z, replace_node = params_text:find("([0-9]+)%s+([0-9]+)%s+([0-9]+)%s+([a-z:_\\-]+)")
|
local parts = wea.split(params_text, "%s+", false)
|
||||||
|
|
||||||
if found == nil then
|
if #parts < 4 then
|
||||||
return false, "Invalid syntax"
|
return false, "Error: Not enough arguments. Expected \"<rx> <ry> <rz> <replace_node> [h[ollow]]\"."
|
||||||
end
|
end
|
||||||
|
|
||||||
local radius = {
|
local radius = minetest.string_to_pos(parts[1].." "..parts[2].." "..parts[3])
|
||||||
x = tonumber(radius_x),
|
if not radius then
|
||||||
y = tonumber(radius_y),
|
return false, "Error: 3 radii must be specified."
|
||||||
z = tonumber(radius_z)
|
end
|
||||||
}
|
wea.vector.abs(radius)
|
||||||
|
|
||||||
replace_node = worldedit.normalize_nodename(replace_node)
|
local replace_node = worldedit.normalize_nodename(parts[4])
|
||||||
if not replace_node then
|
if not replace_node then
|
||||||
worldedit.player_notify(name, "Error: Invalid node name.")
|
return false, "Error: Invalid replace_node specified."
|
||||||
return false
|
|
||||||
end
|
|
||||||
if not radius.x or not radius.y or not radius.z then
|
|
||||||
worldedit.player_notify(name, "Error: Invalid radius(es).")
|
|
||||||
return false
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return true, replace_node, radius
|
local hollow = false
|
||||||
|
if parts[5] == "hollow" or parts[5] == "h" then
|
||||||
|
hollow = true
|
||||||
|
end
|
||||||
|
|
||||||
|
return true, replace_node, radius, hollow
|
||||||
end
|
end
|
||||||
|
|
||||||
worldedit.register_command("ellipsoid", {
|
worldedit.register_command("ellipsoid", {
|
||||||
params = "<rx> <ry> <rz> <replace_node>",
|
params = "<rx> <ry> <rz> <replace_node> [h[ollow]]",
|
||||||
description = "Creates a 3D ellipsoid with a radius of (rx, ry, rz) at pos1, filled with <replace_node>.",
|
description = "Creates a 3D ellipsoid with a radius of (rx, ry, rz) at pos1, filled with <replace_node>.",
|
||||||
privs = { worldedit = true },
|
privs = { worldedit = true },
|
||||||
require_pos = 1,
|
require_pos = 1,
|
||||||
|
@ -42,9 +42,9 @@ worldedit.register_command("ellipsoid", {
|
||||||
nodes_needed = function(name, target_node, radius)
|
nodes_needed = function(name, target_node, radius)
|
||||||
return math.ceil(4/3 * math.pi * radius.x * radius.y * radius.z)
|
return math.ceil(4/3 * math.pi * radius.x * radius.y * radius.z)
|
||||||
end,
|
end,
|
||||||
func = function(name, target_node, radius)
|
func = function(name, target_node, radius, hollow)
|
||||||
local start_time = worldeditadditions.get_ms_time()
|
local start_time = worldeditadditions.get_ms_time()
|
||||||
local replaced = worldeditadditions.ellipsoid(worldedit.pos1[name], radius, target_node, false)
|
local replaced = worldeditadditions.ellipsoid(worldedit.pos1[name], radius, target_node, hollow)
|
||||||
local time_taken = worldeditadditions.get_ms_time() - start_time
|
local time_taken = worldeditadditions.get_ms_time() - start_time
|
||||||
|
|
||||||
minetest.log("action", name .. " used //ellipsoid at " .. worldeditadditions.vector.tostring(worldedit.pos1[name]) .. ", replacing " .. replaced .. " nodes in " .. time_taken .. "s")
|
minetest.log("action", name .. " used //ellipsoid at " .. worldeditadditions.vector.tostring(worldedit.pos1[name]) .. ", replacing " .. replaced .. " nodes in " .. time_taken .. "s")
|
||||||
|
|
146
worldeditadditions_commands/commands/selectors/smake.lua
Normal file
146
worldeditadditions_commands/commands/selectors/smake.lua
Normal file
|
@ -0,0 +1,146 @@
|
||||||
|
-- ███████ ███ ███ █████ ██ ██ ███████
|
||||||
|
-- ██ ████ ████ ██ ██ ██ ██ ██
|
||||||
|
-- ███████ ██ ████ ██ ███████ █████ █████
|
||||||
|
-- ██ ██ ██ ██ ██ ██ ██ ██ ██
|
||||||
|
-- ███████ ██ ██ ██ ██ ██ ██ ███████
|
||||||
|
local wea = worldeditadditions
|
||||||
|
worldedit.register_command("smake", {
|
||||||
|
params = "<operation> <mode> [<target=xyz> [<base>]]",
|
||||||
|
description = "Make one or more axes of the current selection odd, even, or equal to another.",
|
||||||
|
privs = { worldedit = true },
|
||||||
|
require_pos = 2,
|
||||||
|
parse = function(params_text)
|
||||||
|
-- Split params_text, check for missing arguments and fill in empty spots
|
||||||
|
local parts = wea.split(params_text, "%s+", false)
|
||||||
|
if #parts < 2 then
|
||||||
|
return false, "Error: Not enough arguments. Expected \"<operation> <mode> [<target=xyz> [<base>]]\"."
|
||||||
|
else
|
||||||
|
for i=3,4 do if not parts[i] then parts[i] = false end end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Initialze local variables and sets
|
||||||
|
local oper, mode, targ, base = unpack(parts)
|
||||||
|
local operSet, modeSet = wea.makeset {"equal", "odd", "even"}, wea.makeset {"grow", "shrink", "avg"}
|
||||||
|
|
||||||
|
-- Main Logic
|
||||||
|
-- Check base if base is present and if so valid.
|
||||||
|
if base then
|
||||||
|
if base:match("[xyz]") then -- ensure correct base syntax
|
||||||
|
base = base:match("[xyz]")
|
||||||
|
else
|
||||||
|
return false, "Error: Invalid base \""..base.."\". Expected \"x\", \"y\" or \"z\"."
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Resolve target then mode (in that order incase mode is target).
|
||||||
|
if not targ then -- If no target set to default (xz)
|
||||||
|
targ = "xz"
|
||||||
|
elseif targ:match("[xyz]+") then -- ensure correct target syntax
|
||||||
|
targ = table.concat(wea.tochars(targ:match("[xyz]+"),true,true))
|
||||||
|
else
|
||||||
|
return false, "Error: Invalid <target> \""..targ.."\". Expected \"x\" and or \"y\" and or \"z\"."
|
||||||
|
end
|
||||||
|
|
||||||
|
if mode == "average" then -- If mode is average set to avg
|
||||||
|
mode = "avg"
|
||||||
|
elseif mode:match("[xyz]+") then -- If target is actually base set vars to correct values.
|
||||||
|
base, targ, mode = targ:sub(1,1), table.concat(wea.tochars(mode:match("[xyz]+"),true,true)), false
|
||||||
|
elseif not modeSet[mode] and not base then -- If mode is invalid and base isn't present throw error
|
||||||
|
return false, "Error: Invalid <mode> \""..mode.."\". Expected \"grow\", \"shrink\", or \"average\"/\"avg\"."
|
||||||
|
end
|
||||||
|
|
||||||
|
if base then
|
||||||
|
if oper ~= "equal" then base = false -- If operation isn't equalize we don't need <base>
|
||||||
|
elseif targ:match(base) then -- Else check that base is not in target and return error if it is
|
||||||
|
return false, "Error: <base> ("..base..") cannot be included in <target> ("..targ..")."
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check if operator is valid
|
||||||
|
if not operSet[oper] then
|
||||||
|
return false, "Error: Invalid operator \""..oper.."\". Expected \"odd\", \"even\" or \"equal\"."
|
||||||
|
end
|
||||||
|
|
||||||
|
if false then -- Argument test
|
||||||
|
return false, "<operator>: " .. oper .. ", <mode>: " .. tostring(mode) .. ", <target>: " .. tostring(targ) .. ", <base>: " .. tostring(base)
|
||||||
|
end
|
||||||
|
return true, oper, mode, targ, base
|
||||||
|
end,
|
||||||
|
func = function(name, oper, mode, targ, base)
|
||||||
|
local p1, p2 = vector.new(worldedit.pos1[name]), vector.new(worldedit.pos2[name])
|
||||||
|
local eval = function() end -- Declare eval placeholder function to edit later
|
||||||
|
|
||||||
|
local delta = vector.subtract(p2,p1) -- local delta equation: Vd(a) = V2(a) - V1(a)
|
||||||
|
local _tl = #targ -- Get targ length as a variable incase mode is "average"/"avg"
|
||||||
|
local targ = wea.tocharset(targ) -- Break up targ string into set table
|
||||||
|
local _m = 0 -- _m is the container to hold the max, min or average (depending on the mode) of the axes in targ targ
|
||||||
|
|
||||||
|
-- set _m to the max, min or mean of the target axes depending on mode or base if it exists
|
||||||
|
if base then _m = delta[base]
|
||||||
|
elseif mode == "avg" then
|
||||||
|
for k,v in pairs(targ) do _m = _m + math.abs(delta[k]) end
|
||||||
|
_m = _m / _tl
|
||||||
|
elseif mode == "grow" then
|
||||||
|
for k,v in pairs(targ) do if math.abs(delta[k]) > _m then _m = math.abs(delta[k]) end end
|
||||||
|
else
|
||||||
|
-- Take output of next(targ), put it in a table, wrap the table in brackets to force evlauation so that
|
||||||
|
-- we can call the first element of that table to serve as the key for a call to delta.
|
||||||
|
_m = delta[({next(targ)})[1]]
|
||||||
|
for k,v in pairs(targ) do if math.abs(delta[k]) < _m then _m = math.abs(delta[k]) end end
|
||||||
|
end
|
||||||
|
|
||||||
|
if oper == "even" then
|
||||||
|
eval = function(int)
|
||||||
|
local tmp, abs, neg = int / 2, math.abs(int), int < 0
|
||||||
|
if math.floor(tmp) ~= tmp then
|
||||||
|
if mode == "avg" then
|
||||||
|
if int > _m then int = abs - 1
|
||||||
|
else int = abs + 1 end
|
||||||
|
elseif mode == "shrink" and abs > 0 then int = abs - 1
|
||||||
|
else int = abs + 1 end
|
||||||
|
end
|
||||||
|
if neg then int = int * -1 end
|
||||||
|
return int
|
||||||
|
end
|
||||||
|
elseif oper == "odd" then
|
||||||
|
eval = function(int)
|
||||||
|
local tmp, abs, neg = int / 2, math.abs(int), int < 0
|
||||||
|
if math.floor(tmp) == tmp then
|
||||||
|
if mode == "avg" then
|
||||||
|
if int > _m then int = abs - 1
|
||||||
|
else int = abs + 1 end
|
||||||
|
elseif mode == "shrink" and abs > 0 then int = abs - 1
|
||||||
|
else int = abs + 1 end
|
||||||
|
end
|
||||||
|
if neg then int = int * -1 end
|
||||||
|
return int
|
||||||
|
end
|
||||||
|
else -- Case: oper == "equal"
|
||||||
|
eval = function(int)
|
||||||
|
-- Bug: shrink sets pos2 to pos1
|
||||||
|
if int < 0 then return _m * -1
|
||||||
|
else return _m end
|
||||||
|
end
|
||||||
|
-- return false, "Case \"equal\" not handled."
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Test:
|
||||||
|
if false then
|
||||||
|
local brk = ""
|
||||||
|
for k,v in pairs(targ) do
|
||||||
|
brk = brk..k..": "..delta[k]..", "
|
||||||
|
delta[k] = eval(delta[k])
|
||||||
|
brk = brk..k..": "..delta[k]..", "
|
||||||
|
end
|
||||||
|
return false, brk
|
||||||
|
end
|
||||||
|
-- //multi //fp set1 589 2 -82 //fp set2 615 2 -53
|
||||||
|
-- //smake even shrink
|
||||||
|
|
||||||
|
for k,v in pairs(targ) do delta[k] = eval(delta[k]) end
|
||||||
|
|
||||||
|
worldedit.pos2[name] = vector.add(p1,delta)
|
||||||
|
worldedit.mark_pos2(name)
|
||||||
|
return true, "position 2 set to " .. minetest.pos_to_string(p2)
|
||||||
|
end
|
||||||
|
})
|
|
@ -90,7 +90,7 @@ worldedit.register_command("hollowtorus", {
|
||||||
local values = {parse_params_torus(params_text)}
|
local values = {parse_params_torus(params_text)}
|
||||||
return unpack(values)
|
return unpack(values)
|
||||||
end,
|
end,
|
||||||
nodes_needed = function(name, target_node, major_radius, minor_radius, axes)
|
nodes_needed = function(name, target_node, major_radius, minor_radius)
|
||||||
return math.ceil(2 * math.pi*math.pi * major_radius * minor_radius*minor_radius)
|
return math.ceil(2 * math.pi*math.pi * major_radius * minor_radius*minor_radius)
|
||||||
end,
|
end,
|
||||||
func = function(name, target_node, major_radius, minor_radius, axes)
|
func = function(name, target_node, major_radius, minor_radius, axes)
|
||||||
|
|
|
@ -46,6 +46,7 @@ dofile(we_c.modpath.."/commands/selectors/scentre.lua")
|
||||||
dofile(we_c.modpath.."/commands/selectors/scloud.lua")
|
dofile(we_c.modpath.."/commands/selectors/scloud.lua")
|
||||||
dofile(we_c.modpath.."/commands/selectors/scol.lua")
|
dofile(we_c.modpath.."/commands/selectors/scol.lua")
|
||||||
dofile(we_c.modpath.."/commands/selectors/scube.lua")
|
dofile(we_c.modpath.."/commands/selectors/scube.lua")
|
||||||
|
dofile(we_c.modpath.."/commands/selectors/smake.lua")
|
||||||
dofile(we_c.modpath.."/commands/selectors/spop.lua")
|
dofile(we_c.modpath.."/commands/selectors/spop.lua")
|
||||||
dofile(we_c.modpath.."/commands/selectors/spush.lua")
|
dofile(we_c.modpath.."/commands/selectors/spush.lua")
|
||||||
dofile(we_c.modpath.."/commands/selectors/srect.lua")
|
dofile(we_c.modpath.."/commands/selectors/srect.lua")
|
||||||
|
|
Loading…
Reference in a new issue