mirror of
https://github.com/sbrl/Minetest-WorldEditAdditions.git
synced 2024-11-01 05:43:01 +00:00
Merge pull request #112 from sbrl/selection-tools-refactor
Selection tools refactor
This commit is contained in:
commit
f24ceffd2c
20 changed files with 660 additions and 618 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -242,6 +242,7 @@ temp/
|
||||||
|
|
||||||
# VorTechnix stuff
|
# VorTechnix stuff
|
||||||
.vdev/
|
.vdev/
|
||||||
|
*.old.lua
|
||||||
# Created by https://www.toptal.com/developers/gitignore/api/archives
|
# Created by https://www.toptal.com/developers/gitignore/api/archives
|
||||||
# Edit at https://www.toptal.com/developers/gitignore?templates=archives
|
# Edit at https://www.toptal.com/developers/gitignore?templates=archives
|
||||||
|
|
||||||
|
|
|
@ -96,6 +96,15 @@ describe("parse_axes", function()
|
||||||
assert.are.same(Vector3.new(40, 77, 99), maxv)
|
assert.are.same(Vector3.new(40, 77, 99), maxv)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it("should infer that directions before a value are connected to that value", function()
|
||||||
|
local minv, maxv = parse_axes({
|
||||||
|
"xy", "-x", "5"
|
||||||
|
}, facing_dirs.z_neg)
|
||||||
|
assert.is.truthy(minv)
|
||||||
|
assert.are.same(Vector3.new(-5, 0, 0), minv)
|
||||||
|
assert.are.same(Vector3.new(5, 5, 0), maxv)
|
||||||
|
end)
|
||||||
|
|
||||||
it("should return 2 0,0,0 vectors if no input", function()
|
it("should return 2 0,0,0 vectors if no input", function()
|
||||||
local minv, maxv = parse_axes({
|
local minv, maxv = parse_axes({
|
||||||
-- No input
|
-- No input
|
||||||
|
|
12
CHANGELOG.md
12
CHANGELOG.md
|
@ -4,7 +4,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.
|
Note to self: See the bottom of this file for the release template text.
|
||||||
|
|
||||||
|
|
||||||
## v1.15: The untitled update (unreleased)
|
## v1.15: The direction update (unreleased)
|
||||||
- Added the optional argument `all` to [`//unmark`](https://worldeditadditions.mooncarrot.space/Reference/#unmark)
|
- Added the optional argument `all` to [`//unmark`](https://worldeditadditions.mooncarrot.space/Reference/#unmark)
|
||||||
- Added a (rather nuclear) fix (attempt 4) at finally exterminating all zombie region marker walls forever
|
- Added a (rather nuclear) fix (attempt 4) at finally exterminating all zombie region marker walls forever
|
||||||
- This is not a hotfix to avoid endless small releases fixing the bug, as it's clear it's much more difficult to fix on all systems than initially expected
|
- This is not a hotfix to avoid endless small releases fixing the bug, as it's clear it's much more difficult to fix on all systems than initially expected
|
||||||
|
@ -16,11 +16,21 @@ Note to self: See the bottom of this file for the release template text.
|
||||||
- Added [`//set+`](https://worldeditadditions.mooncarrot.space/Reference/#set) for setting nodes and param2/light levels quickly.
|
- Added [`//set+`](https://worldeditadditions.mooncarrot.space/Reference/#set) for setting nodes and param2/light levels quickly.
|
||||||
- NOTE TO SELF: Setting light values doesn't appear to be working very well for some reason
|
- NOTE TO SELF: Setting light values doesn't appear to be working very well for some reason
|
||||||
- Added [`//ndef`](https://worldeditadditions.mooncarrot.space/Reference/#ndef) to print a given node's definition table. This is for debugging and development purposes.
|
- Added [`//ndef`](https://worldeditadditions.mooncarrot.space/Reference/#ndef) to print a given node's definition table. This is for debugging and development purposes.
|
||||||
|
- Added `//sgrow` and `//sshrink` commands to enlarge and shrink selection regions and aliased them over WorldEdit equivalents (`//expand`, `//outset` and `//contract`, `//inset` respectively).
|
||||||
|
- Added Unified Axis Syntax (UAS) parser. - Implementation by @VorTechnix
|
||||||
|
- See [UAS System reference] for details. (Note to self hook up hyperlink)
|
||||||
|
- Added `//uasparse` command to show the vectors produced by a given UAS expression. - Implementation by @VorTechnix
|
||||||
|
|
||||||
### Bugfixes and changes
|
### Bugfixes and changes
|
||||||
- Don't warn on failed registration of `//flora` → [`//bonemeal`](https://worldeditadditions.mooncarrot.space/Reference/#bonemeal) if the `bonemeal` mod isn't installed (e.g. in MineClone2) - thanks @VorTechnix in #106
|
- Don't warn on failed registration of `//flora` → [`//bonemeal`](https://worldeditadditions.mooncarrot.space/Reference/#bonemeal) if the `bonemeal` mod isn't installed (e.g. in MineClone2) - thanks @VorTechnix in #106
|
||||||
- Improve documentation of [`//noise2d`](https://worldeditadditions.mooncarrot.space/Reference/#noise2d). If it still doesn't make sense, please let me know. It's a complicated command that needs reworking a bit to be easier to use.
|
- Improve documentation of [`//noise2d`](https://worldeditadditions.mooncarrot.space/Reference/#noise2d). If it still doesn't make sense, please let me know. It's a complicated command that needs reworking a bit to be easier to use.
|
||||||
- Alias `//napply` to [`//nodeapply`](https://worldeditadditions.mooncarrot.space/Reference/#nodeapply)
|
- Alias `//napply` to [`//nodeapply`](https://worldeditadditions.mooncarrot.space/Reference/#nodeapply)
|
||||||
|
- Re-factored selection tools to all use WEA position system and UAS Parser if applicable. - Re-factor by @VorTechnix
|
||||||
|
- `//sshift` now overrides `//shift` from WorldEdit. - Re-factor by @VorTechnix
|
||||||
|
|
||||||
|
### Deprecations
|
||||||
|
- Deprecated `//scol`, `//srect` and `//scube`. Now that `//srel` is using UAS parser there is no need for them. - Deprecated by @VorTechnix
|
||||||
|
- Deprecated `//sfactor`. Now that `//sgrow` and `//sshrink` exist it is no longer needed. - Deprecated by @VorTechnix
|
||||||
|
|
||||||
|
|
||||||
### Lua API changes
|
### Lua API changes
|
||||||
|
|
|
@ -1201,6 +1201,16 @@ This command is intended for debugging and development purposes, but if you're i
|
||||||
//ndef glass
|
//ndef glass
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### `//uasparse <unified axis syntax>`
|
||||||
|
Short for *Unified Axis Syntax Parse*. Parses the given UAS expression and prints the resulting vectors to the chat window.
|
||||||
|
|
||||||
|
```weacmd
|
||||||
|
//uasparse front right 5
|
||||||
|
//uasparse y 12 h -2
|
||||||
|
//uasparse left 3 up 5 -front 7
|
||||||
|
//uasparse -z 12 -y -2 x -2
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Selection
|
## Selection
|
||||||
|
@ -1212,6 +1222,58 @@ This command is intended for debugging and development purposes, but if you're i
|
||||||
███████ ███████ ███████ ███████ ██████ ██ ██ ██████ ██ ████
|
███████ ███████ ███████ ███████ ██████ ██ ██ ██████ ██ ████
|
||||||
-->
|
-->
|
||||||
|
|
||||||
|
### Unified Axis Syntax (UAS)
|
||||||
|
The Unified Axis Syntax system allows users to input direction and distance information in three dimensions using "natural" measurement syntax. The key features include axis clumping, double negatives, relative directions, mirroring and compass directions (more information below).
|
||||||
|
|
||||||
|
*Note: negatives can be applied to axes, directions **AND** distances*
|
||||||
|
|
||||||
|
#### Relative Directions
|
||||||
|
|Key Words | Interpretation|
|
||||||
|
|----------|---------------|
|
||||||
|
|`f[ront]\|facing\|?` | The direction the player is facing most toward in the world
|
||||||
|
|`b[ack]\|behind\|rear` | The opposite of the direction the player is facing most toward in the world
|
||||||
|
|`l[eft]` | The direction to the left of the player
|
||||||
|
|`r[ight]` | The direction to the right of the player
|
||||||
|
|
||||||
|
```weacmd
|
||||||
|
back 1
|
||||||
|
f r 4
|
||||||
|
-facing 13
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Compass Directions
|
||||||
|
|Key Words | Interpretation|
|
||||||
|
|----------|---------------|
|
||||||
|
|`n[orth]` | z
|
||||||
|
|`s[outh]` | -z
|
||||||
|
|`e[ast]` | x
|
||||||
|
|`w[est]` | -x
|
||||||
|
|`u[p]` | y
|
||||||
|
|`d[own]` | -y
|
||||||
|
|
||||||
|
```weacmd
|
||||||
|
south 3
|
||||||
|
north west 5
|
||||||
|
e d -2
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Axis Clumping
|
||||||
|
Supported axes are `x`, `y`, `z`, `h`, `v`. All horizontal axes are covered by `h` and both vertical ones are covered by `v`.
|
||||||
|
|
||||||
|
- `h 5` == `xz -xz 5` == `x 5 z 5 x -5 z -5`
|
||||||
|
- `v 5` == `up down 5` == `y -y 5`
|
||||||
|
- `vxz 5` == `xyz -y 5` == `xyz 5 y -5`
|
||||||
|
|
||||||
|
#### Inference and Omnidirectionality
|
||||||
|
The UAS parser takes command input that is split by whitespace and interprets it as a series of numbers preceded by directional cues. If a number is preceded by another number or nothing it assumes that the number is to be applied on all axes in both positive and negative directions.
|
||||||
|
|
||||||
|
- `10` == `hv 10` == `xyz -xyz 10`
|
||||||
|
- `x 3 6` == `x 3 hv 6`
|
||||||
|
|
||||||
|
From the above examples you can also see the principle of inference. All direction modifiers before a value are interpreted as belonging to that value. So `x v 5` is equivalent to `x 5 v 5` and `xv 5`.
|
||||||
|
|
||||||
|
Because UAS parses "natural" measurement syntax, there are many ways to express the same direction and distance. This caters to users with different ways of thinking and different play styles which will hopefully make the tools easier to use.
|
||||||
|
|
||||||
### `//unmark`
|
### `//unmark`
|
||||||
> First overridden in v1.14
|
> First overridden in v1.14
|
||||||
|
|
||||||
|
@ -1310,7 +1372,6 @@ Short for _select column_. Sets the pos2 at a set distance along 1 axis from pos
|
||||||
//scol x 3
|
//scol x 3
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### `//srect [<axis1> [<axis2>]] <length>`
|
### `//srect [<axis1> [<axis2>]] <length>`
|
||||||
> Added in v1.12; deprecated in favour of [`//srel`](#srel) in v1.15
|
> Added in v1.12; deprecated in favour of [`//srel`](#srel) in v1.15
|
||||||
|
|
||||||
|
@ -1365,17 +1426,43 @@ Short for _select center_. Sets pos1 and pos2 to the centre point(s) of the curr
|
||||||
//scentre
|
//scentre
|
||||||
```
|
```
|
||||||
|
|
||||||
### `//srel <axis1> <length1> [<axis2> <length2> [<axis3> <length3>]]`
|
### `//srel <unified axis syntax>`
|
||||||
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.
|
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.
|
||||||
|
|
||||||
```weacmd
|
```weacmd
|
||||||
//srel front 5
|
//srel front 5
|
||||||
//srel y 12 right -2
|
//srel y 12 right -2
|
||||||
//srel left 3 up 5 -front 7
|
//srel left 3 up 5 -front 7
|
||||||
//srel -z 12 -y -2 x -2
|
//srel -z 12 -y -2 x -2
|
||||||
```
|
```
|
||||||
|
|
||||||
### `//sshift <axis1> <length1> [<axis2> <length2> [<axis3> <length3>]]`
|
### `//sgrow <unified axis syntax>`
|
||||||
|
> Added in v1.15
|
||||||
|
|
||||||
|
Short for _selection grow_. Grows the current selection along specified axes/directions.
|
||||||
|
Aliases: `//extend`, `//outset`.
|
||||||
|
|
||||||
|
```weacmd
|
||||||
|
//sgrow back 4
|
||||||
|
//sgrow left -2 v r 2
|
||||||
|
//sgrow h 4
|
||||||
|
//sgrow -zy -2 x -2
|
||||||
|
```
|
||||||
|
|
||||||
|
### `//sshrink <unified axis syntax>`
|
||||||
|
> Added in v1.15
|
||||||
|
|
||||||
|
Short for _selection shrink_. Shrinks the current selection along specified axes/directions.
|
||||||
|
Aliases: `//contract`, `//inset`.
|
||||||
|
|
||||||
|
```weacmd
|
||||||
|
//sshrink left 4
|
||||||
|
//sshrink right -2 up 2
|
||||||
|
//sshrink v 4
|
||||||
|
//sshrink -hy 2 x -3 true
|
||||||
|
```
|
||||||
|
|
||||||
|
### `//sshift <unified axis syntax>`
|
||||||
> Added in v1.13
|
> Added in v1.13
|
||||||
|
|
||||||
Short for _selection shift_. Shifts the WorldEdit region along 3 axes. 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.
|
Short for _selection shift_. Shifts the WorldEdit region along 3 axes. 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.
|
||||||
|
|
15
README.md
15
README.md
|
@ -80,20 +80,23 @@ The detailed explanations have moved! Check them out [here](https://worldeditadd
|
||||||
- [`//basename <name>`](https://worldeditadditions.mooncarrot.space/Reference/#basename)
|
- [`//basename <name>`](https://worldeditadditions.mooncarrot.space/Reference/#basename)
|
||||||
- [`//ngroups <node_name> [v[erbose]]`](https://worldeditadditions.mooncarrot.space/Reference/#ngroups) _(new in v1.15)_
|
- [`//ngroups <node_name> [v[erbose]]`](https://worldeditadditions.mooncarrot.space/Reference/#ngroups) _(new in v1.15)_
|
||||||
- [`//ndef <node_name>`](https://worldeditadditions.mooncarrot.space/Reference/#ndef) _(new in v1.15)_
|
- [`//ndef <node_name>`](https://worldeditadditions.mooncarrot.space/Reference/#ndef) _(new in v1.15)_
|
||||||
|
- [`//uasparse <unified axis syntax>`](https://worldeditadditions.mooncarrot.space/Reference/#uasparse) _(new in v1.15)_
|
||||||
|
|
||||||
### Selection
|
### Selection
|
||||||
- [`//scol [<axis1> ] <length>`](https://worldeditadditions.mooncarrot.space/Reference/#scol)
|
- [~~`//scol [<axis1> ] <length>`~~](https://worldeditadditions.mooncarrot.space/Reference/#scol) (REMOVED in v1.15)
|
||||||
- [`//srect [<axis1> [<axis2>]] <length>`](https://worldeditadditions.mooncarrot.space/Reference/#srect)
|
- [~~`//srect [<axis1> [<axis2>]] <length>`~~](https://worldeditadditions.mooncarrot.space/Reference/#srect) (REMOVED in v1.15)
|
||||||
- [`//scube [<axis1> [<axis2> [<axis3>]]] <length>`](https://worldeditadditions.mooncarrot.space/Reference/#scube)
|
- [~~`//scube [<axis1> [<axis2> [<axis3>]]] <length>`~~](https://worldeditadditions.mooncarrot.space/Reference/#scube) (REMOVED in v1.15)
|
||||||
- [`//scloud <0-6|stop|reset>`](https://worldeditadditions.mooncarrot.space/Reference/#scloud)
|
- [`//scloud <0-6|stop|reset>`](https://worldeditadditions.mooncarrot.space/Reference/#scloud)
|
||||||
- [`//scentre`](https://worldeditadditions.mooncarrot.space/Reference/#scentre)
|
- [`//scentre`](https://worldeditadditions.mooncarrot.space/Reference/#scentre)
|
||||||
- [`//srel <axis1> <length1> [<axis2> <length2> [<axis3> <length3>]]`](https://worldeditadditions.mooncarrot.space/Reference/#srel)
|
- [`//sgrow <unified axis syntax>`](https://worldeditadditions.mooncarrot.space/Reference/#sgrow) _(new in v1.15)_
|
||||||
|
- [`//srel <unified axis syntax>`](https://worldeditadditions.mooncarrot.space/Reference/#srel)
|
||||||
- [`//smake <operation:odd|even|equal> <mode:grow|shrink|average> [<target=xz> [<base>]]`](https://worldeditadditions.mooncarrot.space/Reference/#smake)
|
- [`//smake <operation:odd|even|equal> <mode:grow|shrink|average> [<target=xz> [<base>]]`](https://worldeditadditions.mooncarrot.space/Reference/#smake)
|
||||||
|
- [`//sshrink <unified axis syntax>`](https://worldeditadditions.mooncarrot.space/Reference/#sshrink) _(new in v1.15)_
|
||||||
- [`//sstack`](https://worldeditadditions.mooncarrot.space/Reference/#sstack)
|
- [`//sstack`](https://worldeditadditions.mooncarrot.space/Reference/#sstack)
|
||||||
- [`//spush`](https://worldeditadditions.mooncarrot.space/Reference/#spush)
|
- [`//spush`](https://worldeditadditions.mooncarrot.space/Reference/#spush)
|
||||||
- [`//spop`](https://worldeditadditions.mooncarrot.space/Reference/#spop)
|
- [`//spop`](https://worldeditadditions.mooncarrot.space/Reference/#spop)
|
||||||
- [`//sshift <axis1> <length1> [<axis2> <length2> [<axis3> <length3>]]`](https://worldeditadditions.mooncarrot.space/Reference/#sshift)
|
- [`//sshift <unified axis syntax>`](https://worldeditadditions.mooncarrot.space/Reference/#sshift)
|
||||||
- [`//sfactor <mode:grow|shrink|average> <factor> [<target=xz>]`](https://worldeditadditions.mooncarrot.space/Reference/#sfactor)
|
- [~~`//sfactor <mode:grow|shrink|average> <factor> [<target=xz>]`~~](https://worldeditadditions.mooncarrot.space/Reference/#sfactor) (REMOVED in v1.15)
|
||||||
- [`//pos <index>`](https://worldeditadditions.mooncarrot.space/Reference/#pos)
|
- [`//pos <index>`](https://worldeditadditions.mooncarrot.space/Reference/#pos)
|
||||||
- [`//pos1`](https://worldeditadditions.mooncarrot.space/Reference/#pos1)
|
- [`//pos1`](https://worldeditadditions.mooncarrot.space/Reference/#pos1)
|
||||||
- [`//pos2`](https://worldeditadditions.mooncarrot.space/Reference/#pos2)
|
- [`//pos2`](https://worldeditadditions.mooncarrot.space/Reference/#pos2)
|
||||||
|
|
|
@ -1,34 +1,46 @@
|
||||||
-- ███████ ███████ ██ ███████ ██████ ████████ ██████ ██████ ███████
|
-- ███████ ███████ ██ ███████ ██████ ████████ ██████ ██████ ███████
|
||||||
-- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
|
-- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
|
||||||
-- ███████ █████ ██ █████ ██ ██ ██ ██ ██████ ███████
|
-- ███████ █████ ██ █████ ██ ██ ██ ██ ██████ ███████
|
||||||
-- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
|
-- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
|
||||||
-- ███████ ███████ ███████ ███████ ██████ ██ ██████ ██ ██ ███████
|
-- ███████ ███████ ███████ ███████ ██████ ██ ██████ ██ ██ ███████
|
||||||
|
|
||||||
-- Chat commands that operate on selections.
|
-- Chat commands that operate on selections.
|
||||||
|
|
||||||
local wea_cmdpath = worldeditadditions_commands.modpath .. "/commands/selectors/"
|
local wea_cmdpath = worldeditadditions_commands.modpath .. "/commands/selectors/"
|
||||||
local weac = worldeditadditions_core
|
local weac = worldeditadditions_core
|
||||||
|
|
||||||
dofile(wea_cmdpath.."srel.lua")
|
dofile(wea_cmdpath.."scentre.lua")
|
||||||
dofile(wea_cmdpath.."scentre.lua")
|
dofile(wea_cmdpath.."scloud.lua")
|
||||||
dofile(wea_cmdpath.."scloud.lua")
|
dofile(wea_cmdpath.."sgrow.lua")
|
||||||
dofile(wea_cmdpath.."scol.lua")
|
dofile(wea_cmdpath.."smake.lua")
|
||||||
dofile(wea_cmdpath.."scube.lua")
|
dofile(wea_cmdpath.."spop.lua")
|
||||||
dofile(wea_cmdpath.."sfactor.lua")
|
dofile(wea_cmdpath.."spush.lua")
|
||||||
dofile(wea_cmdpath.."smake.lua")
|
dofile(wea_cmdpath.."srel.lua")
|
||||||
dofile(wea_cmdpath.."spop.lua")
|
dofile(wea_cmdpath.."sshift.lua")
|
||||||
dofile(wea_cmdpath.."spush.lua")
|
dofile(wea_cmdpath.."sshrink.lua")
|
||||||
dofile(wea_cmdpath.."srect.lua")
|
dofile(wea_cmdpath.."sstack.lua")
|
||||||
dofile(wea_cmdpath.."sshift.lua")
|
|
||||||
dofile(wea_cmdpath.."sstack.lua")
|
--- DEPRECATED ---
|
||||||
|
dofile(wea_cmdpath.."scol.lua")
|
||||||
dofile(wea_cmdpath.."unmark.lua")
|
dofile(wea_cmdpath.."scube.lua")
|
||||||
dofile(wea_cmdpath.."mark.lua")
|
dofile(wea_cmdpath.."srect.lua")
|
||||||
dofile(wea_cmdpath.."pos1-2.lua")
|
dofile(wea_cmdpath.."sfactor.lua")
|
||||||
dofile(wea_cmdpath.."reset.lua")
|
--- END DEPRECATED ---
|
||||||
|
|
||||||
-- Aliases
|
dofile(wea_cmdpath.."unmark.lua")
|
||||||
weac.register_alias("sfac", "sfactor")
|
dofile(wea_cmdpath.."mark.lua")
|
||||||
|
dofile(wea_cmdpath.."pos1-2.lua")
|
||||||
weac.register_alias("1", "pos1", true) -- true = override target
|
dofile(wea_cmdpath.."reset.lua")
|
||||||
weac.register_alias("2", "pos2", true) -- true = override target
|
|
||||||
|
-- Aliases
|
||||||
|
weac.register_alias("sfac", "sfactor")
|
||||||
|
|
||||||
|
weac.register_alias("sgrow", "expand", true) -- true = override target
|
||||||
|
weac.register_alias("sgrow", "outset", true) -- true = override target
|
||||||
|
weac.register_alias("sshrink", "contract", true) -- true = override target
|
||||||
|
weac.register_alias("sshrink", "inset", true) -- true = override target
|
||||||
|
|
||||||
|
weac.register_alias("sshift", "shift", true) -- true = override target
|
||||||
|
|
||||||
|
weac.register_alias("1", "pos1", true) -- true = override target
|
||||||
|
weac.register_alias("2", "pos2", true) -- true = override target
|
||||||
|
|
|
@ -1,35 +1,33 @@
|
||||||
local wea_c = worldeditadditions_core
|
local wea_c = worldeditadditions_core
|
||||||
local Vector3 = wea_c.Vector3
|
local Vector3 = wea_c.Vector3
|
||||||
|
|
||||||
-- ███████ ██████ ███████ ███ ██ ████████ ███████ ██████
|
-- ███████ ██████ ███████ ███ ██ ████████ ███████ ██████
|
||||||
-- ██ ██ ██ ████ ██ ██ ██ ██ ██
|
-- ██ ██ ██ ████ ██ ██ ██ ██ ██
|
||||||
-- ███████ ██ █████ ██ ██ ██ ██ █████ ██████
|
-- ███████ ██ █████ ██ ██ ██ ██ █████ ██████
|
||||||
-- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
|
-- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
|
||||||
-- ███████ ██████ ███████ ██ ████ ██ ███████ ██ ██
|
-- ███████ ██████ ███████ ██ ████ ██ ███████ ██ ██
|
||||||
worldeditadditions_core.register_command("scentre", {
|
worldeditadditions_core.register_command("scentre", {
|
||||||
params = "",
|
params = "",
|
||||||
description = "Set WorldEdit region positions 1 and 2 to the centre of the current selection.",
|
description = "Set WorldEdit region positions 1 and 2 to the centre of the current selection.",
|
||||||
privs = {worldedit=true},
|
privs = {worldedit=true},
|
||||||
require_pos = 2,
|
require_pos = 2,
|
||||||
parse = function(params_text)
|
parse = function(params_text)
|
||||||
return true
|
return true
|
||||||
end,
|
end,
|
||||||
func = function(name)
|
func = function(name)
|
||||||
local mean = Vector3.mean(
|
local mean = Vector3.mean(
|
||||||
Vector3.clone(worldedit.pos1[name]),
|
Vector3.clone(wea_c.pos.get(name, 1)),
|
||||||
Vector3.clone(worldedit.pos2[name])
|
Vector3.clone(wea_c.pos.get(name, 2))
|
||||||
)
|
)
|
||||||
local pos1, pos2 = Vector3.clone(mean), Vector3.clone(mean)
|
local pos1, pos2 = Vector3.clone(mean), Vector3.clone(mean)
|
||||||
|
|
||||||
pos1 = pos1:floor()
|
pos1 = pos1:floor()
|
||||||
pos2 = pos2:ceil()
|
pos2 = pos2:ceil()
|
||||||
|
|
||||||
worldedit.pos1[name], worldedit.pos2[name] = pos1, pos2
|
wea_c.pos.set_all(name, {pos1, pos2})
|
||||||
worldedit.mark_pos1(name)
|
|
||||||
worldedit.mark_pos2(name)
|
return true, "Position 1 to "..pos1..", Position 2 to "..pos2
|
||||||
|
end,
|
||||||
return true, "position 1 set to "..pos1..", position 2 set to "..pos2
|
})
|
||||||
end,
|
|
||||||
})
|
-- lua print(vecs.mean.x..", "..vecs.mean.y..", "..vecs.mean.z)
|
||||||
|
|
||||||
-- lua print(vecs.mean.x..", "..vecs.mean.y..", "..vecs.mean.z)
|
|
||||||
|
|
|
@ -7,37 +7,15 @@ local Vector3 = wea_c.Vector3
|
||||||
-- ██ ██ ██ ██ ██
|
-- ██ ██ ██ ██ ██
|
||||||
-- ███████ ██████ ██████ ███████
|
-- ███████ ██████ ██████ ███████
|
||||||
worldeditadditions_core.register_command("scol", {
|
worldeditadditions_core.register_command("scol", {
|
||||||
params = "[<axis1>] <length>",
|
params = "None",
|
||||||
description = "Set WorldEdit region position 2 at a set distance along 1 axis.",
|
description = "DEPRECATED: please use //srel instead.",
|
||||||
privs = {worldedit=true},
|
privs = { worldedit = true },
|
||||||
require_pos = 1,
|
require_pos = 1,
|
||||||
parse = function(params_text)
|
parse = function(params_text)
|
||||||
local vec, tmp = Vector3.new(0, 0, 0), {}
|
return params_text
|
||||||
local find = wea_c.split(params_text, "%s", false)
|
|
||||||
local ax1, sn1, len = (tostring(find[1]):match('[xyz]') or "g"):sub(1,1), wea_c.getsign(find[1]), find[table.maxn(find)]
|
|
||||||
|
|
||||||
tmp.len = tonumber(len)
|
|
||||||
-- If len == nil cancel the operation
|
|
||||||
if not tmp.len then return false, "No length specified." end
|
|
||||||
-- If ax1 is bad send "get" order
|
|
||||||
if ax1 == "g" then tmp.get = true
|
|
||||||
else vec[ax1] = sn1 * tmp.len end
|
|
||||||
|
|
||||||
return true, vec, tmp
|
|
||||||
-- tmp carries:
|
|
||||||
-- The length (len) arguement to the main function for use if "get" is invoked there
|
|
||||||
-- The bool value "get" to tell the main function if it needs to populate missing information in vec
|
|
||||||
end,
|
end,
|
||||||
func = function(name, vec, tmp)
|
func = function(name, paramtext)
|
||||||
if tmp.get then
|
return false, "DEPRECATED: please use //srel instead..."
|
||||||
local ax, dir = wea_c.player_axis2d(name)
|
|
||||||
vec[ax] = tmp.len * dir
|
|
||||||
end
|
|
||||||
|
|
||||||
local pos2 = vec + Vector3.clone(worldedit.pos1[name])
|
|
||||||
worldedit.pos2[name] = pos2
|
|
||||||
worldedit.mark_pos2(name)
|
|
||||||
return true, "position 2 set to "..pos2
|
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -7,48 +7,15 @@ local Vector3 = wea_c.Vector3
|
||||||
-- ██ ██ ██ ██ ██ ██ ██
|
-- ██ ██ ██ ██ ██ ██ ██
|
||||||
-- ███████ ██████ ██████ ██████ ███████
|
-- ███████ ██████ ██████ ██████ ███████
|
||||||
worldeditadditions_core.register_command("scube", {
|
worldeditadditions_core.register_command("scube", {
|
||||||
params = "[<axis1> [<axis2> [<axis3>]]] <length>",
|
params = "None",
|
||||||
description = "Set WorldEdit region position 2 at a set distance along 3 axes.",
|
description = "DEPRECATED: please use //srel instead.",
|
||||||
privs = { worldedit = true },
|
privs = { worldedit = true },
|
||||||
require_pos = 1,
|
require_pos = 1,
|
||||||
parse = function(params_text)
|
parse = function(params_text)
|
||||||
local vec, tmp = Vector3.new(0, 0, 0), {}
|
return params_text
|
||||||
local find = wea_c.split(params_text, "%s", false)
|
|
||||||
local ax1, ax2, ax3 = (tostring(find[1]):match('[xyz]') or "g"):sub(1,1), (tostring(find[2]):match('[xyz]') or "g"):sub(1,1),
|
|
||||||
(tostring(find[3]):match('[xyz]') or "g"):sub(1,1)
|
|
||||||
local sn1, sn2, sn3, len = wea_c.getsign(find[1]), wea_c.getsign(find[2]), wea_c.getsign(find[3]), find[table.maxn(find)]
|
|
||||||
|
|
||||||
tmp.len = tonumber(len)
|
|
||||||
-- If len is nill cancel the operation
|
|
||||||
if not tmp.len then return false, "No length specified." end
|
|
||||||
-- If axis is bad send "get" order
|
|
||||||
if ax1 == "g" then tmp.get = true
|
|
||||||
else vec[ax1] = sn1 * tmp.len end
|
|
||||||
if ax2 == "g" then tmp.get = true
|
|
||||||
else vec[ax2] = sn2 * tmp.len end
|
|
||||||
if ax3 == "g" then tmp.get = true
|
|
||||||
else vec[ax3] = sn3 * tmp.len end
|
|
||||||
|
|
||||||
tmp.axes = ax1..","..ax2..","..ax3
|
|
||||||
return true, vec, tmp
|
|
||||||
-- tmp carries:
|
|
||||||
-- The length (len) arguement to the main function for use if "get" is invoked there
|
|
||||||
-- The bool value "get" to tell the main function if it needs to populate missing information in vec
|
|
||||||
-- The string "axes" to tell the main function what axes are and/or need to be populated if "get" is invoked
|
|
||||||
end,
|
end,
|
||||||
func = function(name, vec, tmp)
|
func = function(name, paramtext)
|
||||||
if tmp.get then
|
return false, "DEPRECATED: please use //srel instead..."
|
||||||
local ax, dir = wea_c.player_axis2d(name)
|
|
||||||
local _, left, sn = wea_c.axis_left(ax,dir)
|
|
||||||
if not tmp.axes:find("x") then vec.x = tmp.len * (ax == "x" and dir or sn) end
|
|
||||||
if not tmp.axes:find("z") then vec.z = tmp.len * (ax == "z" and dir or sn) end
|
|
||||||
if not tmp.axes:find("y") then vec.y = tmp.len end
|
|
||||||
end
|
|
||||||
|
|
||||||
local pos2 = vec + Vector3.clone(worldedit.pos1[name])
|
|
||||||
worldedit.pos2[name] = pos2
|
|
||||||
worldedit.mark_pos2(name)
|
|
||||||
return true, "position 2 set to "..pos2
|
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -1,87 +1,22 @@
|
||||||
local wea = worldeditadditions
|
local wea = worldeditadditions
|
||||||
local wea_c = worldeditadditions_core
|
local wea_c = worldeditadditions_core
|
||||||
local Vector3 = wea_c.Vector3
|
local Vector3 = wea_c.Vector3
|
||||||
|
|
||||||
|
|
||||||
-- ███████ ███████ █████ ██████ ████████ ██████ ██████
|
-- ███████ ███████ █████ ██████ ████████ ██████ ██████
|
||||||
-- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
|
-- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
|
||||||
-- ███████ █████ ███████ ██ ██ ██ ██ ██████
|
-- ███████ █████ ███████ ██ ██ ██ ██ ██████
|
||||||
-- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
|
-- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
|
||||||
-- ███████ ██ ██ ██ ██████ ██ ██████ ██ ██
|
-- ███████ ██ ██ ██ ██████ ██ ██████ ██ ██
|
||||||
worldeditadditions_core.register_command("sfactor", {
|
worldeditadditions_core.register_command("sfactor", {
|
||||||
params = "<mode> <factor> [<target=xz>]",
|
params = "None",
|
||||||
description = "Make the length of one or more target axes of the current selection to be multiple(s) of <factor>.",
|
description = "DEPRECATED: please use //grow or //shrink instead.",
|
||||||
privs = { worldedit = true },
|
|
||||||
require_pos = 2,
|
privs = { worldedit = true },
|
||||||
parse = function(params_text)
|
parse = function(params_text)
|
||||||
local parts = wea_c.split(params_text, "%s+", false)
|
return params_text
|
||||||
|
end,
|
||||||
if #parts < 2 then
|
func = function(name, paramtext)
|
||||||
return false, "Error: Not enough arguments. Expected \"<mode> <factor> [<target>]\"."
|
return false, "DEPRECATED: please use //grow or //shrink instead..."
|
||||||
end
|
end
|
||||||
local mode, fac, targ = wea_c.table.unpack(parts)
|
})
|
||||||
local modeSet = wea_c.table.makeset {"grow", "shrink", "avg"}
|
|
||||||
|
|
||||||
-- Mode parsing
|
|
||||||
if mode == "average" then -- If mode is average set to avg
|
|
||||||
mode = "avg"
|
|
||||||
elseif not modeSet[mode] then -- If mode is invalid throw error
|
|
||||||
return false, "Error: Invalid <mode> \""..mode.."\". Expected \"grow\", \"shrink\", or \"average\"/\"avg\"."
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Factor parsing
|
|
||||||
local factest = tonumber(fac)
|
|
||||||
if not factest then
|
|
||||||
return false, "Error: Invalid <factor> \""..fac.."\". Expected a number."
|
|
||||||
elseif factest < 2 then
|
|
||||||
return false, "Error: <factor> is too low. Expected a number equal to or greater than 2."
|
|
||||||
else
|
|
||||||
fac = math.floor(factest+0.5)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Target parsing
|
|
||||||
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_c.tochars(targ:match("[xyz]+"),true,true))
|
|
||||||
else
|
|
||||||
return false, "Error: Invalid <target> \""..targ.."\". Expected \"x\" and or \"y\" and or \"z\"."
|
|
||||||
end
|
|
||||||
|
|
||||||
return true, mode, fac, targ
|
|
||||||
end,
|
|
||||||
func = function(name, mode, fac, targ)
|
|
||||||
local pos1, pos2 = Vector3.clone(worldedit.pos1[name]), Vector3.clone(worldedit.pos2[name])
|
|
||||||
local delta = pos2 - pos1 -- 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_c.tocharset(targ) -- Break up targ string into set table
|
|
||||||
local _m = 0 -- _m is the container to hold the average of the axes in targ
|
|
||||||
|
|
||||||
-- set _m to the max, min or mean of the target axes depending on mode (_tl is the length of targ) or base if it exists
|
|
||||||
if mode == "avg" then
|
|
||||||
for k,v in pairs(targ) do _m = _m + math.abs(delta[k]) end
|
|
||||||
_m = _m / _tl
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Equation: round(delta[<axis>] / factor) * factor
|
|
||||||
local eval = function(int,fac_inner)
|
|
||||||
local tmp, abs, neg = int / fac_inner, math.abs(int), int < 0
|
|
||||||
|
|
||||||
if mode == "avg" then
|
|
||||||
if int > _m then int = math.floor(abs / fac_inner) * fac_inner
|
|
||||||
else int = math.ceil(abs / fac_inner) * fac_inner end
|
|
||||||
elseif mode == "shrink" then int = math.floor(abs / fac_inner) * fac_inner
|
|
||||||
else int = math.ceil(abs / fac_inner) * fac_inner end
|
|
||||||
|
|
||||||
if int < fac_inner then int = fac_inner end -- Ensure selection doesn't collapse to 0
|
|
||||||
if neg then int = int * -1 end -- Ensure correct facing direction
|
|
||||||
return int
|
|
||||||
end
|
|
||||||
|
|
||||||
for k,v in pairs(targ) do delta[k] = eval(delta[k],fac) end
|
|
||||||
|
|
||||||
worldedit.pos2[name] = pos1 + delta
|
|
||||||
worldedit.mark_pos2(name)
|
|
||||||
return true, "position 2 set to "..pos2
|
|
||||||
end
|
|
||||||
})
|
|
||||||
|
|
42
worldeditadditions_commands/commands/selectors/sgrow.lua
Normal file
42
worldeditadditions_commands/commands/selectors/sgrow.lua
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
-- local wea = worldeditadditions
|
||||||
|
local wea_c = worldeditadditions_core
|
||||||
|
local Vector3 = wea_c.Vector3
|
||||||
|
|
||||||
|
|
||||||
|
-- ███████ ██████ ██████ ██████ ██ ██
|
||||||
|
-- ██ ██ ██ ██ ██ ██ ██ ██
|
||||||
|
-- ███████ ██ ███ ██████ ██ ██ ██ █ ██
|
||||||
|
-- ██ ██ ██ ██ ██ ██ ██ ██ ███ ██
|
||||||
|
-- ███████ ██████ ██ ██ ██████ ███ ███
|
||||||
|
|
||||||
|
|
||||||
|
worldeditadditions_core.register_command("sgrow", {
|
||||||
|
params = "<unified axis syntax>",
|
||||||
|
description = "Grow selection region",
|
||||||
|
privs = { worldedit = true },
|
||||||
|
require_pos = 0,
|
||||||
|
parse = function(params_text)
|
||||||
|
local ret = wea_c.split(params_text)
|
||||||
|
if #ret < 1 then return false, "SGROW: No params found!"
|
||||||
|
else return true, ret end
|
||||||
|
end,
|
||||||
|
func = function(name, params_text)
|
||||||
|
local facing = wea_c.player_dir(name)
|
||||||
|
local min, max = wea_c.parse.directions(params_text, facing)
|
||||||
|
if not min then return false, max end
|
||||||
|
|
||||||
|
local pos1 = wea_c.pos.get(name, 1)
|
||||||
|
local pos2 = wea_c.pos.get(name, 2)
|
||||||
|
|
||||||
|
if not pos2 then wea_c.pos.set(name, 2, pos1)
|
||||||
|
else pos1, pos2 = Vector3.sort(pos1, pos2) end
|
||||||
|
|
||||||
|
pos1, pos2 = pos1:add(min), pos2:add(max)
|
||||||
|
|
||||||
|
wea_c.pos.set_all(name, {pos1, pos2})
|
||||||
|
return true, "Position 1 to "..pos1..", Position 2 to "..pos2
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
-- Tests
|
||||||
|
-- //srel front 5 left 3 y 2
|
|
@ -1,133 +1,131 @@
|
||||||
local wea = worldeditadditions
|
local wea_c = worldeditadditions_core
|
||||||
local wea_c = worldeditadditions_core
|
local Vector3 = wea_c.Vector3
|
||||||
local Vector3 = wea_c.Vector3
|
|
||||||
|
|
||||||
|
-- ███████ ███ ███ █████ ██ ██ ███████
|
||||||
-- ███████ ███ ███ █████ ██ ██ ███████
|
-- ██ ████ ████ ██ ██ ██ ██ ██
|
||||||
-- ██ ████ ████ ██ ██ ██ ██ ██
|
-- ███████ ██ ████ ██ ███████ █████ █████
|
||||||
-- ███████ ██ ████ ██ ███████ █████ █████
|
-- ██ ██ ██ ██ ██ ██ ██ ██ ██
|
||||||
-- ██ ██ ██ ██ ██ ██ ██ ██ ██
|
-- ███████ ██ ██ ██ ██ ██ ██ ███████
|
||||||
-- ███████ ██ ██ ██ ██ ██ ██ ███████
|
worldeditadditions_core.register_command("smake", {
|
||||||
worldeditadditions_core.register_command("smake", {
|
params = "<operation:odd|even|equal> <mode:grow|shrink|average> [<target=xyz> [<base>]]",
|
||||||
params = "<operation:odd|even|equal> <mode:grow|shrink|average> [<target=xyz> [<base>]]",
|
description = "Make one or more axes of the current selection odd, even, or equal to another.",
|
||||||
description = "Make one or more axes of the current selection odd, even, or equal to another.",
|
privs = { worldedit = true },
|
||||||
privs = { worldedit = true },
|
require_pos = 2,
|
||||||
require_pos = 2,
|
parse = function(params_text)
|
||||||
parse = function(params_text)
|
-- Split params_text, check for missing arguments and fill in empty spots
|
||||||
-- Split params_text, check for missing arguments and fill in empty spots
|
local parts = wea_c.split(params_text, "%s+", false)
|
||||||
local parts = wea_c.split(params_text, "%s+", false)
|
if #parts < 2 then
|
||||||
if #parts < 2 then
|
return false, "Error: Not enough arguments. Expected \"<operation> <mode> [<target=xyz> [<base>]]\"."
|
||||||
return false, "Error: Not enough arguments. Expected \"<operation> <mode> [<target=xyz> [<base>]]\"."
|
else
|
||||||
else
|
for i=3,4 do if not parts[i] then parts[i] = false end end
|
||||||
for i=3,4 do if not parts[i] then parts[i] = false end end
|
end
|
||||||
end
|
|
||||||
|
-- Initialize local variables and sets
|
||||||
-- Initialize local variables and sets
|
local oper, mode, targ, base = wea_c.table.unpack(parts)
|
||||||
local oper, mode, targ, base = wea_c.table.unpack(parts)
|
local operSet, modeSet = wea_c.table.makeset {"equal", "odd", "even"}, wea_c.table.makeset {"grow", "shrink", "avg"}
|
||||||
local operSet, modeSet = wea_c.table.makeset {"equal", "odd", "even"}, wea_c.table.makeset {"grow", "shrink", "avg"}
|
|
||||||
|
-- Main Logic
|
||||||
-- Main Logic
|
-- Check base if base is present and if so valid.
|
||||||
-- Check base if base is present and if so valid.
|
if base then
|
||||||
if base then
|
if base:match("[xyz]") then -- ensure correct base syntax
|
||||||
if base:match("[xyz]") then -- ensure correct base syntax
|
base = base:match("[xyz]")
|
||||||
base = base:match("[xyz]")
|
else
|
||||||
else
|
return false, "Error: Invalid base \""..base.."\". Expected \"x\", \"y\" or \"z\"."
|
||||||
return false, "Error: Invalid base \""..base.."\". Expected \"x\", \"y\" or \"z\"."
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
-- Resolve target then mode (in that order incase mode is target).
|
||||||
-- Resolve target then mode (in that order incase mode is target).
|
if not targ then -- If no target set to default (xz)
|
||||||
if not targ then -- If no target set to default (xz)
|
targ = "xz"
|
||||||
targ = "xz"
|
elseif targ:match("[xyz]+") then -- ensure correct target syntax
|
||||||
elseif targ:match("[xyz]+") then -- ensure correct target syntax
|
targ = table.concat(wea_c.tochars(targ:match("[xyz]+"),true,true))
|
||||||
targ = table.concat(wea_c.tochars(targ:match("[xyz]+"),true,true))
|
else
|
||||||
else
|
return false, "Error: Invalid <target> \""..targ.."\". Expected \"x\" and or \"y\" and or \"z\"."
|
||||||
return false, "Error: Invalid <target> \""..targ.."\". Expected \"x\" and or \"y\" and or \"z\"."
|
end
|
||||||
end
|
|
||||||
|
if mode == "average" then -- If mode is average set to avg
|
||||||
if mode == "average" then -- If mode is average set to avg
|
mode = "avg"
|
||||||
mode = "avg"
|
elseif mode:match("[xyz]+") then -- If target is actually base set vars to correct values.
|
||||||
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_c.tochars(mode:match("[xyz]+"),true,true)), false
|
||||||
base, targ, mode = targ:sub(1,1), table.concat(wea_c.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
|
||||||
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\"."
|
||||||
return false, "Error: Invalid <mode> \""..mode.."\". Expected \"grow\", \"shrink\", or \"average\"/\"avg\"."
|
end
|
||||||
end
|
|
||||||
|
if base then
|
||||||
if base then
|
if oper ~= "equal" then base = false -- If operation isn't equalize we don't need <base>
|
||||||
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
|
||||||
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..")."
|
||||||
return false, "Error: <base> ("..base..") cannot be included in <target> ("..targ..")."
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
-- Check if operator is valid
|
||||||
-- Check if operator is valid
|
if not operSet[oper] then
|
||||||
if not operSet[oper] then
|
return false, "Error: Invalid operator \""..oper.."\". Expected \"odd\", \"even\" or \"equal\"."
|
||||||
return false, "Error: Invalid operator \""..oper.."\". Expected \"odd\", \"even\" or \"equal\"."
|
end
|
||||||
end
|
|
||||||
|
return true, oper, mode, targ, base
|
||||||
return true, oper, mode, targ, base
|
end,
|
||||||
end,
|
func = function(name, oper, mode, targ, base)
|
||||||
func = function(name, oper, mode, targ, base)
|
local pos1, pos2 = Vector3.clone(wea_c.pos.get(name, 1)), Vector3.clone(wea_c.pos.get(name, 2))
|
||||||
local pos1, pos2 = Vector3.clone(worldedit.pos1[name]), Vector3.clone(worldedit.pos2[name])
|
local eval -- Declare eval placeholder function to edit later
|
||||||
local eval -- Declare eval placeholder function to edit later
|
|
||||||
|
local delta = pos2 - pos1 -- local delta equation: Vd(a) = V2(a) - V1(a)
|
||||||
local delta = pos2 - pos1 -- local delta equation: Vd(a) = V2(a) - V1(a)
|
local _tl = #targ -- Get targ length as a variable incase mode is "average"/"avg"
|
||||||
local _tl = #targ -- Get targ length as a variable incase mode is "average"/"avg"
|
local targ = wea_c.tocharset(targ) -- Break up targ string into set table
|
||||||
local targ = wea_c.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
|
||||||
local _m = 0 -- _m is the container to hold the max, min or average (depending on the mode) of the axes in targ
|
|
||||||
|
-- set _m to the max, min or mean of the target axes depending on mode or base if it exists
|
||||||
-- 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]
|
||||||
if base then _m = delta[base]
|
elseif mode == "avg" then
|
||||||
elseif mode == "avg" then
|
for k,v in pairs(targ) do _m = _m + math.abs(delta[k]) end
|
||||||
for k,v in pairs(targ) do _m = _m + math.abs(delta[k]) end
|
_m = _m / _tl
|
||||||
_m = _m / _tl
|
elseif mode == "grow" then
|
||||||
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
|
||||||
for k,v in pairs(targ) do if math.abs(delta[k]) > _m then _m = math.abs(delta[k]) end end
|
else
|
||||||
else
|
-- Take output of next(targ), put it in a table, wrap the table in brackets to force evlauation so that
|
||||||
-- 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.
|
||||||
-- we can call the first element of that table to serve as the key for a call to delta.
|
_m = delta[({next(targ)})[1]]
|
||||||
_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
|
||||||
for k,v in pairs(targ) do if math.abs(delta[k]) < _m then _m = math.abs(delta[k]) end end
|
end
|
||||||
end
|
|
||||||
|
if oper == "even" then
|
||||||
if oper == "even" then
|
eval = function(int)
|
||||||
eval = function(int)
|
local tmp, abs, neg = int / 2, math.abs(int), int < 0
|
||||||
local tmp, abs, neg = int / 2, math.abs(int), int < 0
|
if math.floor(tmp) ~= tmp then
|
||||||
if math.floor(tmp) ~= tmp then
|
if mode == "avg" then
|
||||||
if mode == "avg" then
|
if int > _m then int = abs - 1
|
||||||
if int > _m then int = abs - 1
|
else int = abs + 1 end
|
||||||
else int = abs + 1 end
|
elseif mode == "shrink" and abs > 0 then int = abs - 1
|
||||||
elseif mode == "shrink" and abs > 0 then int = abs - 1
|
else int = abs + 1 end
|
||||||
else int = abs + 1 end
|
end
|
||||||
end
|
if neg then int = int * -1 end -- Ensure correct facing direction
|
||||||
if neg then int = int * -1 end -- Ensure correct facing direction
|
return int
|
||||||
return int
|
end
|
||||||
end
|
elseif oper == "odd" then
|
||||||
elseif oper == "odd" then
|
eval = function(int)
|
||||||
eval = function(int)
|
local tmp, abs, neg = int / 2, math.abs(int), int < 0
|
||||||
local tmp, abs, neg = int / 2, math.abs(int), int < 0
|
if math.floor(tmp) == tmp then
|
||||||
if math.floor(tmp) == tmp then
|
if mode == "avg" then
|
||||||
if mode == "avg" then
|
if int > _m then int = abs - 1
|
||||||
if int > _m then int = abs - 1
|
else int = abs + 1 end
|
||||||
else int = abs + 1 end
|
elseif mode == "shrink" and abs > 0 then int = abs - 1
|
||||||
elseif mode == "shrink" and abs > 0 then int = abs - 1
|
else int = abs + 1 end
|
||||||
else int = abs + 1 end
|
end
|
||||||
end
|
if neg then int = int * -1 end
|
||||||
if neg then int = int * -1 end
|
return int
|
||||||
return int
|
end
|
||||||
end
|
else -- Case: oper == "equal"
|
||||||
else -- Case: oper == "equal"
|
eval = function(int)
|
||||||
eval = function(int)
|
-- Bug: shrink sets pos2 to pos1
|
||||||
-- Bug: shrink sets pos2 to pos1
|
if int < 0 then return _m * -1
|
||||||
if int < 0 then return _m * -1
|
else return _m end
|
||||||
else return _m end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
for k,_ in pairs(targ) do delta[k] = eval(delta[k]) end
|
||||||
for k,v in pairs(targ) do delta[k] = eval(delta[k]) end
|
|
||||||
|
wea_c.pos.set(name, 2, pos1 + delta)
|
||||||
worldedit.pos2[name] = pos1 + delta
|
return true, "Position 2 to "..pos2
|
||||||
worldedit.mark_pos2(name)
|
end
|
||||||
return true, "position 2 set to "..pos2
|
})
|
||||||
end
|
|
||||||
})
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
local wea = worldeditadditions
|
|
||||||
local wea_c = worldeditadditions_core
|
local wea_c = worldeditadditions_core
|
||||||
local Vector3 = wea_c.Vector3
|
local Vector3 = wea_c.Vector3
|
||||||
|
|
||||||
|
@ -8,43 +7,15 @@ local Vector3 = wea_c.Vector3
|
||||||
-- ██ ██ ██ ██ ██ ██
|
-- ██ ██ ██ ██ ██ ██
|
||||||
-- ███████ ██ ██ ███████ ██████ ██
|
-- ███████ ██ ██ ███████ ██████ ██
|
||||||
worldeditadditions_core.register_command("srect", {
|
worldeditadditions_core.register_command("srect", {
|
||||||
params = "[<axis1> [<axis2>]] <length>",
|
params = "None",
|
||||||
description = "Set WorldEdit region position 2 at a set distance along 2 axes.",
|
description = "DEPRECATED: please use //srel instead.",
|
||||||
privs = { worldedit = true },
|
privs = { worldedit = true },
|
||||||
require_pos = 1,
|
require_pos = 1,
|
||||||
parse = function(params_text)
|
parse = function(params_text)
|
||||||
local vec, tmp = Vector3.new(0, 0, 0), {}
|
return params_text
|
||||||
local find = wea_c.split(params_text, "%s", false)
|
|
||||||
local ax1, ax2 = (tostring(find[1]):match('[xyz]') or "g"):sub(1,1), (tostring(find[2]):match('[xyz]') or "g"):sub(1,1)
|
|
||||||
local sn1, sn2, len = wea_c.getsign(find[1]), wea_c.getsign(find[2]), find[table.maxn(find)]
|
|
||||||
|
|
||||||
tmp.len = tonumber(len)
|
|
||||||
-- If len == nill cancel the operation
|
|
||||||
if not tmp.len then return false, "No length specified." end
|
|
||||||
-- If axis is bad send "get" order
|
|
||||||
if ax1 == "g" then tmp.get = true
|
|
||||||
else vec[ax1] = sn1 * tmp.len end
|
|
||||||
if ax2 == "g" then tmp.get = true
|
|
||||||
else vec[ax2] = sn2 * tmp.len end
|
|
||||||
|
|
||||||
tmp.axes = ax1..","..ax2
|
|
||||||
return true, vec, tmp
|
|
||||||
-- tmp carries:
|
|
||||||
-- The length (len) arguement to the main function for use if "get" is invoked there
|
|
||||||
-- The bool value "get" to tell the main function if it needs to populate missing information in vec
|
|
||||||
-- The string "axes" to tell the main function what axes are and/or need to be populated if "get" is invoked
|
|
||||||
end,
|
end,
|
||||||
func = function(name, vec, tmp)
|
func = function(name, paramtext)
|
||||||
if tmp.get then
|
return false, "DEPRECATED: please use //srel instead..."
|
||||||
local ax, dir = wea_c.player_axis2d(name)
|
|
||||||
if not tmp.axes:find("[xz]") then vec[ax] = tmp.len * dir end
|
|
||||||
if not tmp.axes:find("y") then vec.y = tmp.len end
|
|
||||||
end
|
|
||||||
|
|
||||||
local p2 = vec + Vector3.clone(worldedit.pos1[name])
|
|
||||||
worldedit.pos2[name] = p2
|
|
||||||
worldedit.mark_pos2(name)
|
|
||||||
return true, "position 2 set to "..p2
|
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -1,58 +1,37 @@
|
||||||
local wea = worldeditadditions
|
-- local wea = worldeditadditions
|
||||||
local wea_c = worldeditadditions_core
|
local wea_c = worldeditadditions_core
|
||||||
local Vector3 = wea_c.Vector3
|
local Vector3 = wea_c.Vector3
|
||||||
|
|
||||||
|
|
||||||
-- ███████ ██████ ███████ ██
|
-- ███████ ██████ ███████ ██
|
||||||
-- ██ ██ ██ ██ ██
|
-- ██ ██ ██ ██ ██
|
||||||
-- ███████ ██████ █████ ██
|
-- ███████ ██████ █████ ██
|
||||||
-- ██ ██ ██ ██ ██
|
-- ██ ██ ██ ██ ██
|
||||||
-- ███████ ██ ██ ███████ ███████
|
-- ███████ ██ ██ ███████ ███████
|
||||||
local function parse_with_name(name,args)
|
|
||||||
local vec, tmp = Vector3.new(0, 0, 0), {}
|
|
||||||
local find, _, i = {}, 0, 0
|
worldeditadditions_core.register_command("srel", {
|
||||||
repeat
|
params = "<unified axis syntax>",
|
||||||
_, i, tmp.proc = args:find("([%l%s+-]+%d+)%s*", i)
|
description = "Set WorldEdit region position 2 relative to position 1 and player facing.",
|
||||||
if tmp.proc:match("[xyz]") then
|
privs = { worldedit = true },
|
||||||
tmp.ax = tmp.proc:match("[xyz]")
|
require_pos = 0,
|
||||||
tmp.dir = tonumber(tmp.proc:match("[+-]?%d+")) * (tmp.proc:match("-%l+") and -1 or 1)
|
parse = function(params_text)
|
||||||
else
|
local ret = wea_c.split(params_text)
|
||||||
tmp.ax, _ = wea_c.dir_to_xyz(name, tmp.proc:match("%l+"))
|
if #ret < 1 then return false, "SREL: No params found!"
|
||||||
if not tmp.ax then return false, _ end
|
else return true, ret end
|
||||||
tmp.dir = tonumber(tmp.proc:match("[+-]?%d+")) * (tmp.proc:match("-%l+") and -1 or 1) * _
|
end,
|
||||||
end
|
func = function(name, params_text)
|
||||||
vec[tmp.ax] = tmp.dir
|
local facing = wea_c.player_dir(name)
|
||||||
until not args:find("([%l%s+-]+%d+)%s*", i)
|
local vec, err = wea_c.parse.directions(params_text, facing, true)
|
||||||
return true, vec
|
if not vec then return false, err end
|
||||||
end
|
|
||||||
worldeditadditions_core.register_command("srel", {
|
local pos1 = wea_c.pos.get(name, 1)
|
||||||
params = "<axis1> <length1> [<axis2> <length2> [<axis3> <length3>]]",
|
local pos2 = pos1:add(vec)
|
||||||
description = "Set WorldEdit region position 2 at set distances along 3 axes.",
|
|
||||||
privs = { worldedit = true },
|
wea_c.pos.set_all(name, {pos1, pos2})
|
||||||
require_pos = 0,
|
return true, "Position 1 to "..pos1..", Position 2 to "..pos2
|
||||||
parse = function(params_text)
|
end,
|
||||||
if params_text:match("([%l%s+-]+%d+)") then return true, params_text
|
})
|
||||||
else return false, "No acceptable params found" end
|
|
||||||
end,
|
-- Tests
|
||||||
func = function(name, params_text)
|
-- //srel front 5 left 3 y 2
|
||||||
local ret = ""
|
|
||||||
local _, vec = parse_with_name(name,params_text)
|
|
||||||
if not _ then return false, vec end
|
|
||||||
|
|
||||||
if not worldedit.pos1[name] then
|
|
||||||
local pos = wea_c.player_vector(name) + Vector3.new(0.5, -0.5, 0.5)
|
|
||||||
pos = pos:floor()
|
|
||||||
worldedit.pos1[name] = pos
|
|
||||||
worldedit.mark_pos1(name)
|
|
||||||
ret = "position 1 set to "..pos..", "
|
|
||||||
end
|
|
||||||
|
|
||||||
local p2 = vec + Vector3.clone(worldedit.pos1[name])
|
|
||||||
worldedit.pos2[name] = p2
|
|
||||||
worldedit.mark_pos2(name)
|
|
||||||
return true, ret.."position 2 set to "..p2
|
|
||||||
end,
|
|
||||||
})
|
|
||||||
|
|
||||||
-- Tests
|
|
||||||
-- //srel front 5 left 3 y 2
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
local wea = worldeditadditions
|
|
||||||
local wea_c = worldeditadditions_core
|
local wea_c = worldeditadditions_core
|
||||||
local Vector3 = worldeditadditions.Vector3
|
local Vector3 = worldeditadditions.Vector3
|
||||||
|
|
||||||
|
@ -8,46 +7,26 @@ local Vector3 = worldeditadditions.Vector3
|
||||||
-- ██ ██ ██ ██ ██ ██ ██
|
-- ██ ██ ██ ██ ██ ██ ██
|
||||||
-- ███████ ███████ ██ ██ ██ ██ ██
|
-- ███████ ███████ ██ ██ ██ ██ ██
|
||||||
|
|
||||||
local function parse_with_name(name,args)
|
|
||||||
local vec, tmp = Vector3.new(0, 0, 0), {}
|
|
||||||
local find, _, i = {}, 0, 0
|
|
||||||
repeat
|
|
||||||
_, i, tmp.proc = args:find("([%l%s+-]+%d+)%s*", i)
|
|
||||||
if tmp.proc:match("[xyz]") then
|
|
||||||
tmp.ax = tmp.proc:match("[xyz]")
|
|
||||||
tmp.dir = tonumber(tmp.proc:match("[+-]?%d+")) * (tmp.proc:match("-%l+") and -1 or 1)
|
|
||||||
else
|
|
||||||
tmp.ax, _ = wea_c.dir_to_xyz(name, tmp.proc:match("%l+"))
|
|
||||||
if not tmp.ax then return false, _ end
|
|
||||||
tmp.dir = tonumber(tmp.proc:match("[+-]?%d+")) * (tmp.proc:match("-%l+") and -1 or 1) * _
|
|
||||||
end
|
|
||||||
vec[tmp.ax] = tmp.dir
|
|
||||||
until not args:find("([%l%s+-]+%d+)%s*", i)
|
|
||||||
return true, vec
|
|
||||||
end
|
|
||||||
|
|
||||||
worldeditadditions_core.register_command("sshift", {
|
worldeditadditions_core.register_command("sshift", {
|
||||||
params = "<axis1> <distance1> [<axis2> <distance2> [<axis3> <distance3>]]",
|
params = "<unified axis syntax>",
|
||||||
description = "Shift the WorldEdit region in 3 dimensions.",
|
description = "Shift the WorldEdit region in 3 dimensions.",
|
||||||
privs = { worldedit = true },
|
privs = { worldedit = true },
|
||||||
require_pos = 2,
|
require_pos = 2,
|
||||||
parse = function(params_text)
|
parse = function(params_text)
|
||||||
if params_text:match("([%l%s+-]+%d+)") then return true, params_text
|
local ret = wea_c.split(params_text)
|
||||||
else return false, "No acceptable params found" end
|
if #ret < 1 then return false, "Error: No params found!"
|
||||||
|
else return true, ret end
|
||||||
end,
|
end,
|
||||||
func = function(name, params_text)
|
func = function(name, params_text)
|
||||||
local _, vec = parse_with_name(name,params_text)
|
local facing = wea_c.player_dir(name)
|
||||||
if not _ then return false, vec end
|
local vec, err = wea_c.parse.directions(params_text, facing, true)
|
||||||
|
if not vec then return false, err end
|
||||||
|
|
||||||
local pos1 = vec:add(worldedit.pos1[name])
|
local pos1 = vec:add(wea_c.pos.get(name, 1))
|
||||||
worldedit.pos1[name] = pos1
|
local pos2 = vec:add(wea_c.pos.get(name, 2))
|
||||||
worldedit.mark_pos1(name)
|
|
||||||
|
|
||||||
local pos2 = vec:add(worldedit.pos2[name])
|
wea_c.pos.set_all(name, {pos1, pos2})
|
||||||
worldedit.pos2[name] = pos2
|
return true, "Position 1 to "..pos1..", Position 2 to "..pos2
|
||||||
worldedit.mark_pos2(name)
|
|
||||||
|
|
||||||
return true, "Region shifted by " .. (vec.x + vec.y + vec.z) .. " nodes."
|
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
42
worldeditadditions_commands/commands/selectors/sshrink.lua
Normal file
42
worldeditadditions_commands/commands/selectors/sshrink.lua
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
-- local wea = worldeditadditions
|
||||||
|
local wea_c = worldeditadditions_core
|
||||||
|
local Vector3 = wea_c.Vector3
|
||||||
|
|
||||||
|
|
||||||
|
-- ███████ ███████ ██ ██ ██████ ██ ███ ██ ██ ██
|
||||||
|
-- ██ ██ ██ ██ ██ ██ ██ ████ ██ ██ ██
|
||||||
|
-- ███████ ███████ ███████ ██████ ██ ██ ██ ██ █████
|
||||||
|
-- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
|
||||||
|
-- ███████ ███████ ██ ██ ██ ██ ██ ██ ████ ██ ██
|
||||||
|
|
||||||
|
|
||||||
|
worldeditadditions_core.register_command("sshrink", {
|
||||||
|
params = "<unified axis syntax>",
|
||||||
|
description = "Shrink selection region",
|
||||||
|
privs = { worldedit = true },
|
||||||
|
require_pos = 0,
|
||||||
|
parse = function(params_text)
|
||||||
|
local ret = wea_c.split(params_text)
|
||||||
|
if #ret < 1 then return false, "Error: No params found!"
|
||||||
|
else return true, ret end
|
||||||
|
end,
|
||||||
|
func = function(name, params_text)
|
||||||
|
local facing = wea_c.player_dir(name)
|
||||||
|
local min, max = wea_c.parse.directions(params_text, facing)
|
||||||
|
if not min then return false, max end
|
||||||
|
|
||||||
|
local pos1 = wea_c.pos.get(name, 1)
|
||||||
|
local pos2 = wea_c.pos.get(name, 2)
|
||||||
|
|
||||||
|
if not pos2 then wea_c.pos.set(name, 2, pos1)
|
||||||
|
else pos1, pos2 = Vector3.sort(pos1, pos2) end
|
||||||
|
|
||||||
|
pos1, pos2 = pos1:add(max), pos2:add(min)
|
||||||
|
|
||||||
|
wea_c.pos.set_all(name, {pos1, pos2})
|
||||||
|
return true, "Position 1 to "..pos1..", Position 2 to "..pos2
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
-- Tests
|
||||||
|
-- //srel front 5 left 3 y 2
|
29
worldeditadditions_commands/commands/uasparse.lua
Normal file
29
worldeditadditions_commands/commands/uasparse.lua
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
local wea_c = worldeditadditions_core
|
||||||
|
-- local Vector3 = wea_c.Vector3
|
||||||
|
|
||||||
|
-- ██ ██ █████ ███████ ██████ █████ ██████ ███████ ███████
|
||||||
|
-- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
|
||||||
|
-- ██ ██ ███████ ███████ ██████ ███████ ██████ ███████ █████
|
||||||
|
-- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
|
||||||
|
-- ██████ ██ ██ ███████ ██ ██ ██ ██ ██ ███████ ███████
|
||||||
|
|
||||||
|
worldeditadditions_core.register_command("uasparse", {
|
||||||
|
params = "<unified axis syntax>",
|
||||||
|
description = "Debug command. Returns min and max vectors for given inputs",
|
||||||
|
privs = { worldedit = true },
|
||||||
|
-- require_pos = 2,
|
||||||
|
parse = function(params_text)
|
||||||
|
local ret = wea_c.split(params_text)
|
||||||
|
if #ret < 1 then return false, "Error: No params found!"
|
||||||
|
else return true, ret end
|
||||||
|
end,
|
||||||
|
func = function(name, params_text)
|
||||||
|
local facing = wea_c.player_dir(name)
|
||||||
|
local min, max = wea_c.parse.directions(params_text, facing)
|
||||||
|
if not min then
|
||||||
|
return false, max
|
||||||
|
else
|
||||||
|
return true, "Min: "..min.." Max: "..max
|
||||||
|
end
|
||||||
|
end
|
||||||
|
})
|
|
@ -41,6 +41,7 @@ dofile(wea_cmd.modpath.."/commands/revolve.lua")
|
||||||
dofile(wea_cmd.modpath.."/commands/rotate.lua")
|
dofile(wea_cmd.modpath.."/commands/rotate.lua")
|
||||||
dofile(wea_cmd.modpath.."/commands/orient.lua")
|
dofile(wea_cmd.modpath.."/commands/orient.lua")
|
||||||
dofile(wea_cmd.modpath.."/commands/set.lua")
|
dofile(wea_cmd.modpath.."/commands/set.lua")
|
||||||
|
dofile(wea_cmd.modpath.."/commands/uasparse.lua")
|
||||||
|
|
||||||
-- Meta Commands
|
-- Meta Commands
|
||||||
dofile(wea_cmd.modpath .. "/commands/meta/init.lua")
|
dofile(wea_cmd.modpath .. "/commands/meta/init.lua")
|
||||||
|
|
|
@ -23,7 +23,7 @@ else
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Unified Axis Keywords banks
|
--- Unified Axis Syntax banks
|
||||||
local keywords = {
|
local keywords = {
|
||||||
-- Compass keywords
|
-- Compass keywords
|
||||||
compass = {
|
compass = {
|
||||||
|
@ -36,7 +36,9 @@ local keywords = {
|
||||||
["w"] = "-x", ["west"] = "-x",
|
["w"] = "-x", ["west"] = "-x",
|
||||||
["-w"] = "x", ["-west"] = "x",
|
["-w"] = "x", ["-west"] = "x",
|
||||||
["u"] = "y", ["up"] = "y",
|
["u"] = "y", ["up"] = "y",
|
||||||
|
["-u"] = "-y", ["-up"] = "-y",
|
||||||
["d"] = "-y", ["down"] = "-y",
|
["d"] = "-y", ["down"] = "-y",
|
||||||
|
["-d"] = "y", ["-down"] = "y",
|
||||||
},
|
},
|
||||||
|
|
||||||
-- Direction keywords
|
-- Direction keywords
|
||||||
|
@ -90,9 +92,9 @@ function parse.num(str)
|
||||||
else return false end
|
else return false end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Checks if a string is a valid Unified Axis Keyword. (Supports axis clumping)
|
--- Checks if a string is a valid Unified Axis Syntax. (Supports axis clumping)
|
||||||
-- @param: str: String: Keyword instance to parse
|
-- @param: str: String: Keyword to parse
|
||||||
-- @returns: Key Instance: returns keyword type, processed keyword content and signed number (or nil)
|
-- @returns: keyword type, processed keyword content and signed number (or nil)
|
||||||
function parse.keyword(str)
|
function parse.keyword(str)
|
||||||
if type(str) ~= "string" then
|
if type(str) ~= "string" then
|
||||||
return "err", "Error: \""..tostring(str).."\" is not a string.", 404
|
return "err", "Error: \""..tostring(str).."\" is not a string.", 404
|
||||||
|
@ -135,68 +137,65 @@ end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--- Converts Unified Axis Keyword table into Vector3 instances.
|
--- Converts Unified Axis Syntax table into Vector3 instances.
|
||||||
-- @param: tbl: Table: Keyword table to parse
|
-- @param: tbl: Table: Keyword table to parse
|
||||||
-- @param: facing: Table: Output from worldeditadditions_core.player_dir(name)
|
-- @param: facing: Table: Output from worldeditadditions_core.player_dir(name)
|
||||||
-- @param: sum: Bool | String | nil: Return a single vector by summing the 2 output vectors together
|
-- @param: sum: Bool | String | nil: Return a single vector by summing the 2 output vectors together
|
||||||
-- @returns: Vector3, [Vector3]: returns min, max Vector3 or sum Vector3 (if @param: sum ~= nil)
|
-- @returns: Vector3, [Vector3]: returns min, max Vector3 or sum Vector3 (if @param: sum ~= nil)
|
||||||
-- if error: @returns: false, String: error message
|
-- if error: @returns: false, String: error message
|
||||||
function parse.keytable(tbl, facing, sum)
|
function parse.keytable(tbl, facing, sum)
|
||||||
local min, max = Vector3.new(), Vector3.new()
|
local min, max, mir= Vector3.new(), Vector3.new(), false
|
||||||
local expected = 1
|
local neg, pos, v0 = Vector3.new(), Vector3.new(), Vector3.new()
|
||||||
local tmp = {axes = {}, num = 0, sign = 1, mirror = false}
|
|
||||||
|
|
||||||
--- Processes a number and adds it to the min and max vectors.
|
local function update(num) -- Update "min" and "max"
|
||||||
-- @param num The number to process.
|
if num < 0 then
|
||||||
-- @param axes The axes to apply the number to.
|
min, max = min:add(pos:mul(num)), max:add(neg:mul(num))
|
||||||
-- @param sign The sign of the number.
|
|
||||||
local function parseNumber(num, axes, sign)
|
|
||||||
if axes.rev then parseNumber(num, axes.rev, -sign) end
|
|
||||||
if num * sign >= 0 then
|
|
||||||
max = max:add(parse.vectorize(axes, num, sign))
|
|
||||||
else
|
else
|
||||||
min = min:add(parse.vectorize(axes, num, sign))
|
min, max = min:add(neg:mul(num)), max:add(pos:mul(num))
|
||||||
|
end
|
||||||
|
neg, pos = v0:clone(), v0:clone()
|
||||||
|
end
|
||||||
|
|
||||||
|
local function udir(axes, sign) -- Update "neg" and "pos"
|
||||||
|
if axes.rev then udir(axes.rev, -sign) end
|
||||||
|
for _, v in ipairs(axes) do
|
||||||
|
if sign < 0 then neg[v] = -1
|
||||||
|
else pos[v] = 1 end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
for i, v in ipairs(tbl) do
|
for i,v in ipairs(tbl) do
|
||||||
if v:sub(1, 1) == "+" then
|
if v:sub(1, 1) == "+" then
|
||||||
v = v:sub(2)
|
v = v:sub(2)
|
||||||
end
|
end
|
||||||
|
|
||||||
tmp.num = parse.num(v)
|
local num = parse.num(v)
|
||||||
|
|
||||||
if expected == 1 then
|
-- If we have a dimension add it to output
|
||||||
if tmp.num then
|
-- Else gather direction statements
|
||||||
parseNumber(tmp.num, {"x", "y", "z", rev={"x", "y", "z"}}, tmp.sign)
|
if num then
|
||||||
else
|
-- Check for direction vectors
|
||||||
local key_type, key_entry, key_sign = parse.keyword(v)
|
if neg == v0 and pos == v0 then
|
||||||
|
neg, pos = v0:add(-1), v0:add(1)
|
||||||
|
end
|
||||||
|
update(num)
|
||||||
|
else
|
||||||
|
local key_type, key_entry, key_sign = parse.keyword(v)
|
||||||
|
|
||||||
if key_type == "axis" then
|
if key_type == "axis" then
|
||||||
tmp.axes = key_entry
|
udir(key_entry, key_sign)
|
||||||
tmp.sign = key_sign
|
|
||||||
elseif key_type == "dir" then
|
elseif key_type == "dir" then
|
||||||
tmp.axes = {facing[key_entry].axis}
|
udir({facing[key_entry].axis},
|
||||||
tmp.sign = facing[key_entry].sign * key_sign
|
facing[key_entry].sign * key_sign)
|
||||||
elseif key_type == "rev" then
|
elseif key_type == "rev" then
|
||||||
tmp.mirror = true
|
mir = true
|
||||||
else
|
else
|
||||||
return false, key_entry
|
return false, key_entry
|
||||||
end
|
end
|
||||||
|
|
||||||
expected = 2
|
|
||||||
end
|
|
||||||
else
|
|
||||||
if tmp.num then
|
|
||||||
parseNumber(tmp.num, tmp.axes, tmp.sign)
|
|
||||||
expected = 1
|
|
||||||
else
|
|
||||||
return false, "Error: Expected number after \""..tostring(tbl[i-1]).."\". Got \""..tostring(v).."\"."
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if tmp.mirror and not sum then
|
if mir and not sum then
|
||||||
max = max:max(min:abs())
|
max = max:max(min:abs())
|
||||||
min = max:multiply(-1)
|
min = max:multiply(-1)
|
||||||
end
|
end
|
||||||
|
@ -209,6 +208,7 @@ function parse.keytable(tbl, facing, sum)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
keyword = parse.keyword,
|
keyword = parse.keyword,
|
||||||
keytable = parse.keytable,
|
keytable = parse.keytable,
|
||||||
|
|
|
@ -1,89 +1,90 @@
|
||||||
-- Licence: GPLv2 (MPL-2.0 is compatible, so we can use this here)
|
-- Licence: GPLv2 (MPL-2.0 is compatible, so we can use this here)
|
||||||
-- Source: https://stackoverflow.com/a/43582076/1460422
|
-- Source: https://stackoverflow.com/a/43582076/1460422
|
||||||
|
|
||||||
-- gsplit: iterate over substrings in a string separated by a pattern
|
-- gsplit: iterate over substrings in a string separated by a pattern
|
||||||
--
|
--
|
||||||
-- Parameters:
|
-- Parameters:
|
||||||
-- text (string) - the string to iterate over
|
-- text (string) - the string to iterate over
|
||||||
-- pattern (string) - the separator pattern
|
-- pattern (string) - the separator pattern
|
||||||
-- plain (boolean) - if true (or truthy), pattern is interpreted as a plain
|
-- plain (boolean) - if true (or truthy), pattern is interpreted as a plain
|
||||||
-- string, not a Lua pattern
|
-- string, not a Lua pattern
|
||||||
--
|
--
|
||||||
-- Returns: iterator
|
-- Returns: iterator
|
||||||
--
|
--
|
||||||
-- Usage:
|
-- Usage:
|
||||||
-- for substr in gsplit(text, pattern, plain) do
|
-- for substr in gsplit(text, pattern, plain) do
|
||||||
-- doSomething(substr)
|
-- doSomething(substr)
|
||||||
-- end
|
-- end
|
||||||
local function gsplit(text, pattern, plain)
|
local function gsplit(text, pattern, plain)
|
||||||
local splitStart, length = 1, #text
|
local splitStart, length = 1, #text
|
||||||
return function ()
|
return function ()
|
||||||
if splitStart then
|
if splitStart then
|
||||||
local sepStart, sepEnd = string.find(text, pattern, splitStart, plain)
|
local sepStart, sepEnd = string.find(text, pattern, splitStart, plain)
|
||||||
local ret
|
local ret
|
||||||
if not sepStart then
|
if not sepStart then
|
||||||
ret = string.sub(text, splitStart)
|
ret = string.sub(text, splitStart)
|
||||||
splitStart = nil
|
splitStart = nil
|
||||||
elseif sepEnd < sepStart then
|
elseif sepEnd < sepStart then
|
||||||
-- Empty separator!
|
-- Empty separator!
|
||||||
ret = string.sub(text, splitStart, sepStart)
|
ret = string.sub(text, splitStart, sepStart)
|
||||||
if sepStart < length then
|
if sepStart < length then
|
||||||
splitStart = sepStart + 1
|
splitStart = sepStart + 1
|
||||||
else
|
else
|
||||||
splitStart = nil
|
splitStart = nil
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
ret = sepStart > splitStart and string.sub(text, splitStart, sepStart - 1) or ''
|
ret = sepStart > splitStart and string.sub(text, splitStart, sepStart - 1) or ''
|
||||||
splitStart = sepEnd + 1
|
splitStart = sepEnd + 1
|
||||||
end
|
end
|
||||||
return ret
|
return ret
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Split a string into substrings separated by a pattern. -- Deprecated
|
--- Split a string into substrings separated by a pattern. -- Deprecated
|
||||||
-- @param text string The string to iterate over
|
-- @param text string The string to iterate over
|
||||||
-- @param pattern string The separator pattern
|
-- @param pattern string The separator pattern
|
||||||
-- @param plain boolean If true (or truthy), pattern is interpreted as a
|
-- @param plain boolean If true (or truthy), pattern is interpreted as a
|
||||||
-- plain string, not a Lua pattern
|
-- plain string, not a Lua pattern
|
||||||
-- @returns table A sequence table containing the substrings
|
-- @returns table A sequence table containing the substrings
|
||||||
local function dsplit(text, pattern, plain)
|
local function dsplit(text, pattern, plain)
|
||||||
local ret = {}
|
local ret = {}
|
||||||
for match in gsplit(text, pattern, plain) do
|
for match in gsplit(text, pattern, plain) do
|
||||||
table.insert(ret, match)
|
table.insert(ret, match)
|
||||||
end
|
end
|
||||||
return ret
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Split a string into substrings separated by a pattern.
|
--- Split a string into substrings separated by a pattern.
|
||||||
-- @param str string The string to iterate over
|
-- @param str string The string to iterate over
|
||||||
-- @param dlm string The delimiter (separator) pattern
|
-- @param dlm="%s+" string The delimiter (separator) pattern. If a falsey value is passed, then the default value is used.
|
||||||
-- @param plain boolean If true (or truthy), pattern is interpreted as a
|
-- @param plain boolean If true (or truthy), pattern is interpreted as a
|
||||||
-- plain string, not a Lua pattern
|
-- plain string, not a Lua pattern
|
||||||
-- @returns table A sequence table containing the substrings
|
-- @returns table A sequence table containing the substrings
|
||||||
local function split(str,dlm,plain)
|
local function split(str,dlm,plain)
|
||||||
local pos, ret = 0, {}
|
if not dlm then dlm = "%s+" end
|
||||||
local ins, i = str:find(dlm,pos,plain)
|
local pos, ret = 0, {}
|
||||||
-- "if plain" shaves off some time in the while statement
|
local ins, i = str:find(dlm,pos,plain)
|
||||||
if plain then
|
-- "if plain" shaves off some time in the while statement
|
||||||
while ins do
|
if plain then
|
||||||
table.insert(ret,str:sub(pos,ins - 1))
|
while ins do
|
||||||
pos = ins + #dlm
|
table.insert(ret,str:sub(pos,ins - 1))
|
||||||
ins = str:find(dlm,pos,true)
|
pos = ins + #dlm
|
||||||
end
|
ins = str:find(dlm,pos,true)
|
||||||
else
|
end
|
||||||
while ins do
|
else
|
||||||
table.insert(ret,str:sub(pos,ins - 1))
|
while ins do
|
||||||
pos = i + 1
|
table.insert(ret,str:sub(pos,ins - 1))
|
||||||
ins, i = str:find(dlm,pos)
|
pos = i + 1
|
||||||
end
|
ins, i = str:find(dlm,pos)
|
||||||
end
|
end
|
||||||
-- print(pos..","..#str)
|
end
|
||||||
if str:sub(pos,#str) ~= "" then
|
-- print(pos..","..#str)
|
||||||
table.insert(ret,str:sub(pos,#str))
|
if str:sub(pos,#str) ~= "" then
|
||||||
end
|
table.insert(ret,str:sub(pos,#str))
|
||||||
return ret
|
end
|
||||||
end
|
return ret
|
||||||
|
end
|
||||||
|
|
||||||
return split
|
return split
|
Loading…
Reference in a new issue