Compare commits
1173 commits
Author | SHA1 | Date | |
---|---|---|---|
Starbeamrainbowlabs | e89d61034f | ||
Starbeamrainbowlabs | 8efceeaa4c | ||
Starbeamrainbowlabs | 5ca5d1f1de | ||
Starbeamrainbowlabs | 2a9dca6926 | ||
Starbeamrainbowlabs | dd6e34bde1 | ||
Starbeamrainbowlabs | 125638a079 | ||
Starbeamrainbowlabs | 7be2fb125e | ||
Starbeamrainbowlabs | 6231132055 | ||
Starbeamrainbowlabs | abfd76930a | ||
Starbeamrainbowlabs | aec204de8e | ||
Starbeamrainbowlabs | daae15eb57 | ||
Starbeamrainbowlabs | 200e588c59 | ||
Starbeamrainbowlabs | 2840ba4dea | ||
Starbeamrainbowlabs | 564785ddf6 | ||
Starbeamrainbowlabs | a465a50244 | ||
Starbeamrainbowlabs | 5505575cf9 | ||
Starbeamrainbowlabs | fd3ee43728 | ||
Starbeamrainbowlabs | ee4b3e09bb | ||
Starbeamrainbowlabs | 0645bc7b8e | ||
7766af8a8a | |||
d2fb6db3d0 | |||
Starbeamrainbowlabs | a6e8753e64 | ||
Starbeamrainbowlabs | 1a227e3bd8 | ||
Starbeamrainbowlabs | ffc90ed179 | ||
Starbeamrainbowlabs | ab3120fe79 | ||
Starbeamrainbowlabs | 87a80d2faf | ||
Starbeamrainbowlabs | 83b4b02b40 | ||
Starbeamrainbowlabs | 95a82add86 | ||
Starbeamrainbowlabs | 5baa72cf6f | ||
Starbeamrainbowlabs | 177aea02a8 | ||
Starbeamrainbowlabs | 7f4798432e | ||
Starbeamrainbowlabs | 7236232dc0 | ||
Starbeamrainbowlabs | c8e717a6d6 | ||
Starbeamrainbowlabs | 4745009632 | ||
Starbeamrainbowlabs | f7429fa40e | ||
Starbeamrainbowlabs | 277f3a8155 | ||
Starbeamrainbowlabs | d63400e697 | ||
Starbeamrainbowlabs | 5c632df658 | ||
Starbeamrainbowlabs | 693fc145d5 | ||
Starbeamrainbowlabs | 2c30ed8634 | ||
Starbeamrainbowlabs | bf365d2d11 | ||
Starbeamrainbowlabs | f2214150f2 | ||
Starbeamrainbowlabs | 3bfc62be24 | ||
Starbeamrainbowlabs | e916057133 | ||
Starbeamrainbowlabs | 3194a2c53e | ||
Starbeamrainbowlabs | 20935d8379 | ||
Starbeamrainbowlabs | 74cc6669c0 | ||
Starbeamrainbowlabs | 2edc9f6f6c | ||
Starbeamrainbowlabs | a78d385666 | ||
Starbeamrainbowlabs | fd9d76353d | ||
5cf155772d | |||
55ddc16b2e | |||
Starbeamrainbowlabs | 6bc1987916 | ||
Starbeamrainbowlabs | 365b491aa1 | ||
Starbeamrainbowlabs | 5d18f6d0db | ||
Starbeamrainbowlabs | 66c257c146 | ||
Starbeamrainbowlabs | 7bdefc8d42 | ||
Starbeamrainbowlabs | 78c4a67c7b | ||
Starbeamrainbowlabs | 02ad40eaae | ||
Starbeamrainbowlabs | c988daeda6 | ||
Starbeamrainbowlabs | 047033a6ef | ||
Starbeamrainbowlabs | c6bc6e26e7 | ||
Starbeamrainbowlabs | 8981bc4baa | ||
Starbeamrainbowlabs | 464ea53465 | ||
Starbeamrainbowlabs | e9c3d51863 | ||
Starbeamrainbowlabs | 5a76b3eaa9 | ||
Starbeamrainbowlabs | 2e8642b4d7 | ||
Starbeamrainbowlabs | 9b4a777a67 | ||
Starbeamrainbowlabs | 9be7854297 | ||
Starbeamrainbowlabs | 09ee1ae3fa | ||
Starbeamrainbowlabs | f970a8d6bb | ||
Starbeamrainbowlabs | 61403108d6 | ||
Starbeamrainbowlabs | f5e2ada5bd | ||
Starbeamrainbowlabs | 2756eb0eb5 | ||
Starbeamrainbowlabs | 92fd201b42 | ||
Starbeamrainbowlabs | f800d7e3d7 | ||
Starbeamrainbowlabs | b3f7ae9d7c | ||
Starbeamrainbowlabs | 46587164bd | ||
Starbeamrainbowlabs | e3dac29a80 | ||
Starbeamrainbowlabs | 109c69502a | ||
Starbeamrainbowlabs | 277da67dda | ||
Starbeamrainbowlabs | a173edfbc4 | ||
Starbeamrainbowlabs | c622fb554f | ||
Starbeamrainbowlabs | 1b0001d88e | ||
Starbeamrainbowlabs | 5fe84ada79 | ||
Starbeamrainbowlabs | f7530da608 | ||
Starbeamrainbowlabs | 8cc2c735b1 | ||
Starbeamrainbowlabs | 61e04952e0 | ||
Starbeamrainbowlabs | 141ea2f0a7 | ||
Starbeamrainbowlabs | bfecc2da80 | ||
Starbeamrainbowlabs | 53bbe14c63 | ||
8d9f51de35 | |||
67baee7465 | |||
8de2892907 | |||
16afb9eddc | |||
Starbeamrainbowlabs | 1c163186b6 | ||
Starbeamrainbowlabs | daad494c7e | ||
Starbeamrainbowlabs | b2556934b1 | ||
Starbeamrainbowlabs | 7cb1160e65 | ||
b88cec64d4 | |||
Starbeamrainbowlabs | 8652ad6335 | ||
Starbeamrainbowlabs | ebbaed88d8 | ||
Starbeamrainbowlabs | 558fc1c04b | ||
Starbeamrainbowlabs | 1d53233621 | ||
Starbeamrainbowlabs | 66aab7ba64 | ||
Starbeamrainbowlabs | fcde8e581c | ||
Starbeamrainbowlabs | cfef411bbd | ||
Starbeamrainbowlabs | cf8406b80f | ||
Starbeamrainbowlabs | e942e4fb2f | ||
Starbeamrainbowlabs | d1b9d1c1c1 | ||
Starbeamrainbowlabs | 392708b190 | ||
Starbeamrainbowlabs | 87812679d9 | ||
Starbeamrainbowlabs | 2ecc8cb2d7 | ||
Starbeamrainbowlabs | 66227153d0 | ||
Starbeamrainbowlabs | 42fb6571da | ||
Starbeamrainbowlabs | 9c66288827 | ||
Starbeamrainbowlabs | cbd2ae7df8 | ||
Starbeamrainbowlabs | 3e123ddc56 | ||
Starbeamrainbowlabs | 8372a12f48 | ||
Starbeamrainbowlabs | 53609ac83e | ||
Starbeamrainbowlabs | 2e275e3993 | ||
Starbeamrainbowlabs | cfc1fe3639 | ||
Starbeamrainbowlabs | 97bb896829 | ||
Starbeamrainbowlabs | 58dd3ea875 | ||
Starbeamrainbowlabs | 554bc86b3d | ||
Starbeamrainbowlabs | 902d03ca0b | ||
Starbeamrainbowlabs | 410841562a | ||
Starbeamrainbowlabs | dea51cb9a3 | ||
Starbeamrainbowlabs | 9f2bfb33c7 | ||
Starbeamrainbowlabs | b493c0073a | ||
Starbeamrainbowlabs | bc0276875d | ||
Starbeamrainbowlabs | c319be5840 | ||
Starbeamrainbowlabs | fe30fd5c51 | ||
Starbeamrainbowlabs | 2748f4cdfa | ||
Starbeamrainbowlabs | 9a4b4beb76 | ||
Starbeamrainbowlabs | 9806828760 | ||
Starbeamrainbowlabs | 888e4b0f78 | ||
Starbeamrainbowlabs | 5d9dee9523 | ||
Starbeamrainbowlabs | 268e123221 | ||
Starbeamrainbowlabs | 363acde496 | ||
Starbeamrainbowlabs | 7a14e8a590 | ||
Starbeamrainbowlabs | f998110303 | ||
Starbeamrainbowlabs | 285572e16b | ||
Starbeamrainbowlabs | 258a9c1cde | ||
Starbeamrainbowlabs | a768378dfd | ||
Starbeamrainbowlabs | c2d19105ed | ||
Starbeamrainbowlabs | 3583de4731 | ||
Starbeamrainbowlabs | dfb24e679b | ||
Starbeamrainbowlabs | da9f578e86 | ||
Starbeamrainbowlabs | 8f03c6473b | ||
Starbeamrainbowlabs | bdaedf0e7a | ||
Starbeamrainbowlabs | 38a72468d9 | ||
Starbeamrainbowlabs | bc5dc6b2b4 | ||
Starbeamrainbowlabs | c9fd68fac3 | ||
Starbeamrainbowlabs | 84226a9909 | ||
Starbeamrainbowlabs | 2473c1ce41 | ||
Starbeamrainbowlabs | 6357d590d9 | ||
Starbeamrainbowlabs | 440cdcc504 | ||
98a74c63dc | |||
Starbeamrainbowlabs | 7f2be74580 | ||
Starbeamrainbowlabs | 3fa6dbefcf | ||
Starbeamrainbowlabs | 1473074d4a | ||
Starbeamrainbowlabs | fd1e3fb20f | ||
Starbeamrainbowlabs | f7bd17131a | ||
Starbeamrainbowlabs | ea6a7ced2b | ||
Starbeamrainbowlabs | 7423bee714 | ||
Starbeamrainbowlabs | e2e235ce6d | ||
Starbeamrainbowlabs | 9910bfad44 | ||
Starbeamrainbowlabs | 47b1c44b38 | ||
Starbeamrainbowlabs | d9877b8c6c | ||
Starbeamrainbowlabs | 6c8ce90593 | ||
Starbeamrainbowlabs | 44e6ba8e3c | ||
Starbeamrainbowlabs | c3ae96548e | ||
Starbeamrainbowlabs | d03e333e35 | ||
Starbeamrainbowlabs | c82c83d008 | ||
Starbeamrainbowlabs | 073d621629 | ||
Starbeamrainbowlabs | 4be7bf33d0 | ||
Starbeamrainbowlabs | 9dc8165464 | ||
Starbeamrainbowlabs | 5ec877f2b7 | ||
Starbeamrainbowlabs | 8ec118eed7 | ||
Starbeamrainbowlabs | 1024b19629 | ||
Starbeamrainbowlabs | 7a688969b2 | ||
Starbeamrainbowlabs | 1ae36d3898 | ||
Starbeamrainbowlabs | 2af1226b49 | ||
Starbeamrainbowlabs | 41e3ebc7dd | ||
Starbeamrainbowlabs | a3acf3b16e | ||
Starbeamrainbowlabs | 21c5b9d483 | ||
Starbeamrainbowlabs | 6102a1adf5 | ||
Starbeamrainbowlabs | 4a56d45c4b | ||
Starbeamrainbowlabs | c3e8df3a9e | ||
Starbeamrainbowlabs | 459e15b5c2 | ||
Starbeamrainbowlabs | 128dc8f103 | ||
Starbeamrainbowlabs | 0641a9f55c | ||
Starbeamrainbowlabs | 927f2f90f8 | ||
Starbeamrainbowlabs | 2f4c333ca0 | ||
e2947c4ae2 | |||
Starbeamrainbowlabs | 8d6db6d3f5 | ||
Starbeamrainbowlabs | adfc6d6499 | ||
Starbeamrainbowlabs | e167fb1536 | ||
Starbeamrainbowlabs | 6f3118036d | ||
Starbeamrainbowlabs | 2625ed1a53 | ||
Starbeamrainbowlabs | 58a7629ea1 | ||
Starbeamrainbowlabs | 2b88fa867e | ||
Starbeamrainbowlabs | 4a6cb2551c | ||
Starbeamrainbowlabs | 52d24a63f3 | ||
Starbeamrainbowlabs | 0983e09f50 | ||
Starbeamrainbowlabs | cf0be6c1fb | ||
Starbeamrainbowlabs | 17d92870b3 | ||
Starbeamrainbowlabs | 817387d7f2 | ||
Starbeamrainbowlabs | fa62864e16 | ||
Starbeamrainbowlabs | 9932852053 | ||
Starbeamrainbowlabs | fd42d96702 | ||
Starbeamrainbowlabs | 08d40c8780 | ||
Starbeamrainbowlabs | 763ae3db8d | ||
Starbeamrainbowlabs | 382194321b | ||
Starbeamrainbowlabs | e6a48c8799 | ||
Starbeamrainbowlabs | d3900e2ad9 | ||
Starbeamrainbowlabs | 63abd1f539 | ||
Starbeamrainbowlabs | 0e7b292bb1 | ||
Starbeamrainbowlabs | 8eec6a32f7 | ||
Starbeamrainbowlabs | bd88f93296 | ||
Starbeamrainbowlabs | c465d6efb0 | ||
Starbeamrainbowlabs | 2d989acee5 | ||
Starbeamrainbowlabs | 6e0779a4e5 | ||
Starbeamrainbowlabs | 77c634dd7d | ||
Starbeamrainbowlabs | fc4f64d25a | ||
Starbeamrainbowlabs | e294d96efe | ||
dc73e0e1e9 | |||
Starbeamrainbowlabs | be0612e6be | ||
74ca84fcee | |||
53600789d8 | |||
6e3252b471 | |||
Starbeamrainbowlabs | 5ac98cfa22 | ||
Starbeamrainbowlabs | b94c38bb99 | ||
98e9888897 | |||
Starbeamrainbowlabs | 50b1df57c4 | ||
d79c187a9d | |||
Starbeamrainbowlabs | cb75776164 | ||
021fdac284 | |||
Starbeamrainbowlabs | 64ff61a4d2 | ||
6ed65074b8 | |||
a8655373a2 | |||
3196a590f5 | |||
1cef968731 | |||
Starbeamrainbowlabs | af7d39110b | ||
Starbeamrainbowlabs | 9bfb428c3f | ||
e17b2cce4e | |||
23140467d2 | |||
2cddccdca4 | |||
8789b39d1d | |||
a0982c70f0 | |||
a6b4d047b8 | |||
Starbeamrainbowlabs | 1750d62d3c | ||
Starbeamrainbowlabs | c2c0fa5d8d | ||
Starbeamrainbowlabs | 8de49ac0af | ||
Starbeamrainbowlabs | 3bcca82b43 | ||
Starbeamrainbowlabs | c53fb32d2b | ||
Starbeamrainbowlabs | 95c0e96da9 | ||
Starbeamrainbowlabs | b816133716 | ||
Starbeamrainbowlabs | c60b5c5bad | ||
Starbeamrainbowlabs | 4306035ef2 | ||
Starbeamrainbowlabs | 8f6c3e020f | ||
Starbeamrainbowlabs | d21f7ca5fb | ||
Starbeamrainbowlabs | 1fda9725c7 | ||
Starbeamrainbowlabs | 4ab386788d | ||
Starbeamrainbowlabs | 9bdd7d2a25 | ||
Starbeamrainbowlabs | fa9b511e33 | ||
Starbeamrainbowlabs | 19c8d0e7b9 | ||
Starbeamrainbowlabs | f984f5d7b7 | ||
Starbeamrainbowlabs | d3119ee54a | ||
Starbeamrainbowlabs | 10f350c967 | ||
Starbeamrainbowlabs | 9d3a4ce263 | ||
Starbeamrainbowlabs | 60c8f30109 | ||
Starbeamrainbowlabs | 98909f0fae | ||
Starbeamrainbowlabs | 722e62bae0 | ||
Starbeamrainbowlabs | 3311d80a2a | ||
Starbeamrainbowlabs | 0d7922d747 | ||
bcfe39cd21 | |||
Starbeamrainbowlabs | f34617a3d3 | ||
Starbeamrainbowlabs | 03fb033b70 | ||
Starbeamrainbowlabs | 04e971e12d | ||
Starbeamrainbowlabs | a99cef7bf9 | ||
Starbeamrainbowlabs | 6d075be525 | ||
Starbeamrainbowlabs | dbc056139a | ||
Starbeamrainbowlabs | 8eb1faf1b9 | ||
Starbeamrainbowlabs | 8b385690c0 | ||
Starbeamrainbowlabs | a4237dcca5 | ||
Starbeamrainbowlabs | 7622d85efa | ||
1c80bbc031 | |||
Starbeamrainbowlabs | d77799a871 | ||
2ed3042bc8 | |||
9995ea2fb9 | |||
Starbeamrainbowlabs | c443459282 | ||
Starbeamrainbowlabs | 3d12345972 | ||
Starbeamrainbowlabs | 4c7bb6a980 | ||
Starbeamrainbowlabs | 67b4495aad | ||
Starbeamrainbowlabs | ee465070c9 | ||
Starbeamrainbowlabs | 58933c6435 | ||
Starbeamrainbowlabs | 6c49b9d598 | ||
Starbeamrainbowlabs | 364de73fd0 | ||
Starbeamrainbowlabs | 5bc8687ff1 | ||
Starbeamrainbowlabs | bc1ded787c | ||
Starbeamrainbowlabs | 3db39a3789 | ||
Starbeamrainbowlabs | 81773c8556 | ||
Starbeamrainbowlabs | 80e230a9d7 | ||
Starbeamrainbowlabs | 6a1fd707d4 | ||
Starbeamrainbowlabs | d9204e95b5 | ||
Starbeamrainbowlabs | dc5f8f0753 | ||
Starbeamrainbowlabs | 1da5599e80 | ||
Starbeamrainbowlabs | d45e4e893a | ||
Starbeamrainbowlabs | 98bf0ef386 | ||
Starbeamrainbowlabs | cce27525cc | ||
Starbeamrainbowlabs | 2d53869f11 | ||
Starbeamrainbowlabs | 8170ecb1f1 | ||
Starbeamrainbowlabs | d6cd0cdb59 | ||
Starbeamrainbowlabs | c93f692f9d | ||
Starbeamrainbowlabs | b87c846e67 | ||
Starbeamrainbowlabs | b0019b87e1 | ||
Starbeamrainbowlabs | 9d0ca493b8 | ||
Starbeamrainbowlabs | c5276ae47e | ||
Starbeamrainbowlabs | db7602a8b3 | ||
Starbeamrainbowlabs | d252ec4675 | ||
Starbeamrainbowlabs | 934007c07b | ||
Starbeamrainbowlabs | 56a83572e7 | ||
Starbeamrainbowlabs | 1310dae884 | ||
Starbeamrainbowlabs | 9df5ba6fe5 | ||
Starbeamrainbowlabs | 227265db72 | ||
Starbeamrainbowlabs | dd8cd78d6b | ||
Starbeamrainbowlabs | 70d6f36444 | ||
Starbeamrainbowlabs | 4597edcf1e | ||
Starbeamrainbowlabs | 08cff1c967 | ||
Starbeamrainbowlabs | f19b22e906 | ||
Starbeamrainbowlabs | ec04cc58be | ||
Starbeamrainbowlabs | 3f1e01a282 | ||
Starbeamrainbowlabs | f259f85771 | ||
Starbeamrainbowlabs | 1e9a651537 | ||
Starbeamrainbowlabs | d60d3073bd | ||
Starbeamrainbowlabs | 3c279559f5 | ||
Starbeamrainbowlabs | 691b71adfe | ||
Starbeamrainbowlabs | ef2dbc1806 | ||
Starbeamrainbowlabs | b0e0b83c0d | ||
Starbeamrainbowlabs | be7d46740a | ||
Starbeamrainbowlabs | ca6f1e7cea | ||
Starbeamrainbowlabs | 732010a8ee | ||
Starbeamrainbowlabs | 1de037c341 | ||
Starbeamrainbowlabs | 3e2687f82d | ||
Starbeamrainbowlabs | 1cad9f4064 | ||
Starbeamrainbowlabs | db5d25d1de | ||
Starbeamrainbowlabs | 17cc91ba1c | ||
Starbeamrainbowlabs | 2da0f2dcc2 | ||
Starbeamrainbowlabs | a2a9108d36 | ||
Starbeamrainbowlabs | bbafca2020 | ||
Starbeamrainbowlabs | b0c3d34dd0 | ||
Starbeamrainbowlabs | 75ffa81b7e | ||
Starbeamrainbowlabs | f1a433b5e3 | ||
Starbeamrainbowlabs | 462570f2eb | ||
Starbeamrainbowlabs | 58d3c1e43b | ||
Starbeamrainbowlabs | d657ce1abe | ||
Starbeamrainbowlabs | 10c9d6f886 | ||
Starbeamrainbowlabs | c030acfd7e | ||
Starbeamrainbowlabs | eab498aac2 | ||
Starbeamrainbowlabs | 6e89fc868f | ||
Starbeamrainbowlabs | af0e54cfdf | ||
Starbeamrainbowlabs | b962ace8a8 | ||
Starbeamrainbowlabs | f7a5e223d4 | ||
Starbeamrainbowlabs | 502595579e | ||
Starbeamrainbowlabs | 01d6132055 | ||
Starbeamrainbowlabs | caa06a5c4c | ||
Starbeamrainbowlabs | a7412a2c2f | ||
Starbeamrainbowlabs | 2d8dcc7ebc | ||
Starbeamrainbowlabs | 50840ad5b9 | ||
104fe97be3 | |||
Starbeamrainbowlabs | 14ba42fa4a | ||
Starbeamrainbowlabs | a321c7d2ab | ||
Starbeamrainbowlabs | e773edb58c | ||
Starbeamrainbowlabs | 607f2bfdea | ||
Starbeamrainbowlabs | 8ec89c3e67 | ||
Starbeamrainbowlabs | eaabf40301 | ||
Starbeamrainbowlabs | acb1ef1a0a | ||
Starbeamrainbowlabs | d560583121 | ||
Starbeamrainbowlabs | 9729e82e35 | ||
Starbeamrainbowlabs | 94f675ddce | ||
Starbeamrainbowlabs | 41604d19ac | ||
Starbeamrainbowlabs | 43ea6e34c1 | ||
Starbeamrainbowlabs | e82440a096 | ||
Starbeamrainbowlabs | 35970b31b3 | ||
Starbeamrainbowlabs | 4fb59a160f | ||
Starbeamrainbowlabs | be81e6dfaa | ||
Starbeamrainbowlabs | 96c3ede365 | ||
Starbeamrainbowlabs | 3f5fc45e1a | ||
Starbeamrainbowlabs | 2babba9c55 | ||
Starbeamrainbowlabs | f569358229 | ||
46bd5d4fce | |||
54268431b5 | |||
f7d4c5c6ac | |||
Starbeamrainbowlabs | 43a720bec4 | ||
Starbeamrainbowlabs | 579e040bb1 | ||
Starbeamrainbowlabs | 3f48832fff | ||
Starbeamrainbowlabs | 12371a472d | ||
Starbeamrainbowlabs | 3f1f3b5628 | ||
Starbeamrainbowlabs | a5b32bc2d9 | ||
Starbeamrainbowlabs | 3eb59633b7 | ||
Starbeamrainbowlabs | ea8a91568e | ||
Starbeamrainbowlabs | 33a2ff1ed4 | ||
Starbeamrainbowlabs | f5133d287b | ||
Starbeamrainbowlabs | 21902b8512 | ||
Starbeamrainbowlabs | 9d7000baed | ||
Starbeamrainbowlabs | e610eb7a92 | ||
Starbeamrainbowlabs | dae59b63db | ||
Starbeamrainbowlabs | d3a8efb9b8 | ||
Starbeamrainbowlabs | a3f26200a0 | ||
Starbeamrainbowlabs | 0bcd82a11c | ||
Starbeamrainbowlabs | ad789d500a | ||
Starbeamrainbowlabs | 5fca3e4322 | ||
Starbeamrainbowlabs | 84741f5cb9 | ||
Starbeamrainbowlabs | 2aa15116e2 | ||
Starbeamrainbowlabs | 6eaa3799d3 | ||
Starbeamrainbowlabs | 2ae241aee5 | ||
Starbeamrainbowlabs | 91d5b9abc2 | ||
Starbeamrainbowlabs | 5bdd8ddb5e | ||
Starbeamrainbowlabs | 32fb8be8fe | ||
Starbeamrainbowlabs | 4955aa7579 | ||
Starbeamrainbowlabs | 653864be99 | ||
0352595e41 | |||
191e99f0b5 | |||
b72d36816e | |||
Starbeamrainbowlabs | 8044a9059c | ||
Starbeamrainbowlabs | de60c94c40 | ||
Starbeamrainbowlabs | c8773efe22 | ||
Starbeamrainbowlabs | 5f2d5216af | ||
Starbeamrainbowlabs | d642d44e4c | ||
Starbeamrainbowlabs | da15c577a6 | ||
Starbeamrainbowlabs | 66a3244203 | ||
Starbeamrainbowlabs | 55982b2eab | ||
Starbeamrainbowlabs | be3166624a | ||
Starbeamrainbowlabs | 75d40d7a6c | ||
Starbeamrainbowlabs | 889ccf3acc | ||
Starbeamrainbowlabs | 4a40e78dd7 | ||
Starbeamrainbowlabs | d6b5a4c01e | ||
bc0658b545 | |||
a5960983e7 | |||
Starbeamrainbowlabs | 9d00eb26cf | ||
Starbeamrainbowlabs | 62582b6abb | ||
Starbeamrainbowlabs | eb9236a153 | ||
Starbeamrainbowlabs | f1aa481d99 | ||
Starbeamrainbowlabs | 115855fc99 | ||
Starbeamrainbowlabs | 5228aef56c | ||
Starbeamrainbowlabs | 2920f7081d | ||
Starbeamrainbowlabs | 6cd367915d | ||
Starbeamrainbowlabs | fcd4de3429 | ||
Starbeamrainbowlabs | b131970f16 | ||
Starbeamrainbowlabs | 6f00394d3d | ||
Starbeamrainbowlabs | 7de09e92b3 | ||
Starbeamrainbowlabs | 10a649e597 | ||
Starbeamrainbowlabs | e1b1efb7ed | ||
Starbeamrainbowlabs | 516611db63 | ||
Starbeamrainbowlabs | 16f500b465 | ||
Starbeamrainbowlabs | 82c1ebd42c | ||
Starbeamrainbowlabs | fc2444c5cd | ||
Starbeamrainbowlabs | d1b0866af2 | ||
551f0c7e16 | |||
cff58792bf | |||
4cf30a0e74 | |||
533519d318 | |||
Starbeamrainbowlabs | e9398862b9 | ||
Starbeamrainbowlabs | 9bcf242443 | ||
Starbeamrainbowlabs | 35777b7ae5 | ||
Starbeamrainbowlabs | f5f486f303 | ||
Starbeamrainbowlabs | f30ddbae3b | ||
Starbeamrainbowlabs | c2702a8fde | ||
Starbeamrainbowlabs | 7e008df540 | ||
Starbeamrainbowlabs | 87f84e2482 | ||
Starbeamrainbowlabs | 3338a3fddf | ||
Starbeamrainbowlabs | 5d27ba9ccb | ||
Starbeamrainbowlabs | c48e9f2ab8 | ||
Starbeamrainbowlabs | 7c7abf4509 | ||
Starbeamrainbowlabs | b7c3f21135 | ||
Starbeamrainbowlabs | ef678e6a05 | ||
Starbeamrainbowlabs | db830c6633 | ||
Starbeamrainbowlabs | 902d5ddc8b | ||
Starbeamrainbowlabs | 1833e68ec5 | ||
e5443bc3ce | |||
f9ac0e65ec | |||
77ffda46f7 | |||
74ba9cc36f | |||
325f1cc11e | |||
af1640c4da | |||
9669e46ff8 | |||
b20c8f9af1 | |||
Starbeamrainbowlabs | a9b746986a | ||
Starbeamrainbowlabs | 07c55dc740 | ||
Starbeamrainbowlabs | 38b095d33e | ||
Starbeamrainbowlabs | 45def53294 | ||
f0cd689049 | |||
bd84979393 | |||
Starbeamrainbowlabs | e16fa0f5c8 | ||
Starbeamrainbowlabs | 655d9ebac9 | ||
Starbeamrainbowlabs | c14bb40f7e | ||
Starbeamrainbowlabs | 23e08c5693 | ||
Starbeamrainbowlabs | 1c8d572bb8 | ||
Starbeamrainbowlabs | 47303acac1 | ||
Starbeamrainbowlabs | 9ccd62845f | ||
Starbeamrainbowlabs | ee561cd6e4 | ||
Starbeamrainbowlabs | 8c76b3b760 | ||
Starbeamrainbowlabs | f0e1111b7c | ||
Starbeamrainbowlabs | 0164a9b9eb | ||
Starbeamrainbowlabs | 05eaf01912 | ||
Starbeamrainbowlabs | 3ac0fa14f9 | ||
Starbeamrainbowlabs | a8e0a3088b | ||
Starbeamrainbowlabs | 3c414f2dbd | ||
Starbeamrainbowlabs | 64ed01132e | ||
Starbeamrainbowlabs | 54d0f5a3a3 | ||
Starbeamrainbowlabs | 51e1e7dcbd | ||
Starbeamrainbowlabs | 1f4a115063 | ||
Starbeamrainbowlabs | f37a2aabcf | ||
Starbeamrainbowlabs | c6bae3b7e0 | ||
Starbeamrainbowlabs | fd2ae78625 | ||
Starbeamrainbowlabs | 082f491fa6 | ||
Starbeamrainbowlabs | 910d4b036f | ||
Starbeamrainbowlabs | e10dd1ff2e | ||
Starbeamrainbowlabs | 73a9ff3d60 | ||
Starbeamrainbowlabs | 6f8c4d0c7c | ||
Starbeamrainbowlabs | 37f25d40a1 | ||
Starbeamrainbowlabs | 04b5723db2 | ||
Starbeamrainbowlabs | 624b9539a7 | ||
Starbeamrainbowlabs | 26617d71a7 | ||
Starbeamrainbowlabs | 591ffb977e | ||
Starbeamrainbowlabs | 1c4310b6dd | ||
Starbeamrainbowlabs | caee6a8443 | ||
Starbeamrainbowlabs | c86cff6de6 | ||
Starbeamrainbowlabs | 5a211279e2 | ||
Starbeamrainbowlabs | ce923353f2 | ||
Starbeamrainbowlabs | 7a77fffbca | ||
Starbeamrainbowlabs | 971deaa63b | ||
Starbeamrainbowlabs | baf8a5e02d | ||
Starbeamrainbowlabs | 21043f7c9d | ||
Starbeamrainbowlabs | b2fcc4d72f | ||
Starbeamrainbowlabs | 7ef3d694a7 | ||
Starbeamrainbowlabs | f7cda8c817 | ||
Starbeamrainbowlabs | 92451cf125 | ||
Starbeamrainbowlabs | ecb846fcfe | ||
b795f3b169 | |||
5757ef892d | |||
ebae1cd844 | |||
0ecd6233ad | |||
8225199520 | |||
43a59b68ff | |||
Starbeamrainbowlabs | bd1da727a4 | ||
57369099a7 | |||
Starbeamrainbowlabs | b708fec2db | ||
Starbeamrainbowlabs | 6a77b3cd21 | ||
Starbeamrainbowlabs | c282e286bb | ||
Starbeamrainbowlabs | 31a4d89a49 | ||
1436974e9b | |||
415f36013f | |||
9ee24cf32f | |||
9b585f2906 | |||
Starbeamrainbowlabs | a3bba21266 | ||
9f3bb3a3bb | |||
db8aef5f7c | |||
77fef22d29 | |||
b4d07e9d75 | |||
Starbeamrainbowlabs | 2687c4a5f6 | ||
Starbeamrainbowlabs | d00b5a6213 | ||
af07a158a8 | |||
6e3b9d99e9 | |||
f6ed5241b4 | |||
24569c37d3 | |||
8718e59206 | |||
72513b350a | |||
ce1ba27728 | |||
4b35142044 | |||
40f0e437fb | |||
19404484a0 | |||
Starbeamrainbowlabs | 22c404b320 | ||
d7d96ae263 | |||
7b17c3675a | |||
0c9987c745 | |||
1a78e61c31 | |||
1e7ab670f7 | |||
2c42e0495c | |||
dbab2e4a0d | |||
9420be3896 | |||
f7323afe10 | |||
7f9c8796d0 | |||
Starbeamrainbowlabs | 73e07eb013 | ||
Starbeamrainbowlabs | 9020948dc5 | ||
d94ebd7e54 | |||
5ea6ac18d2 | |||
0b01520118 | |||
Starbeamrainbowlabs | fa2c0642c1 | ||
Starbeamrainbowlabs | 53f387344a | ||
Starbeamrainbowlabs | 496d41731a | ||
Starbeamrainbowlabs | e4d3f26692 | ||
Starbeamrainbowlabs | 5c7b5432d9 | ||
Starbeamrainbowlabs | a80ab3b657 | ||
Starbeamrainbowlabs | 8b4ba8ccc1 | ||
Starbeamrainbowlabs | eed691f6e0 | ||
Starbeamrainbowlabs | 271032a6d7 | ||
c1bfb496b5 | |||
caed5e7195 | |||
49617b7f47 | |||
7b651d7abe | |||
0ad0c63def | |||
Starbeamrainbowlabs | 57caddece7 | ||
a06413977e | |||
c57e8e6558 | |||
e3dd7ae428 | |||
a6d5ead042 | |||
b605ab5a5c | |||
Starbeamrainbowlabs | 1930b8c64d | ||
Starbeamrainbowlabs | 0fef39d707 | ||
Starbeamrainbowlabs | 0b379c48cb | ||
0d7043b537 | |||
5ac0b8a04c | |||
Starbeamrainbowlabs | 0d1900d37c | ||
Starbeamrainbowlabs | aeea17524d | ||
Starbeamrainbowlabs | 81957070f9 | ||
Starbeamrainbowlabs | e799a2ea61 | ||
428ec12918 | |||
9d2a0ca23c | |||
3f6b8f4d21 | |||
f94906c854 | |||
Starbeamrainbowlabs | e85b91d074 | ||
Starbeamrainbowlabs | 643e1a2dce | ||
Starbeamrainbowlabs | 03038689e2 | ||
Starbeamrainbowlabs | 8891c47e98 | ||
Starbeamrainbowlabs | 0dee65ca1d | ||
Starbeamrainbowlabs | 7db2207aea | ||
Starbeamrainbowlabs | 46c2a02ade | ||
d69dae5087 | |||
71460cb316 | |||
Starbeamrainbowlabs | b55f7018f9 | ||
Starbeamrainbowlabs | a42e296f4e | ||
Starbeamrainbowlabs | 40173b2647 | ||
Starbeamrainbowlabs | 8a14d35c04 | ||
Starbeamrainbowlabs | 30f7927af4 | ||
Starbeamrainbowlabs | 457f436a09 | ||
Starbeamrainbowlabs | 0b0595a1d3 | ||
Starbeamrainbowlabs | 0212950d87 | ||
Starbeamrainbowlabs | 1d82013d86 | ||
Starbeamrainbowlabs | 49bf0f19bc | ||
Starbeamrainbowlabs | b2eb76d280 | ||
Starbeamrainbowlabs | ad8d8eab6b | ||
Starbeamrainbowlabs | 239113d415 | ||
Starbeamrainbowlabs | 33e839db29 | ||
Starbeamrainbowlabs | fafe2c22de | ||
Starbeamrainbowlabs | b6bee59097 | ||
e047372c22 | |||
Starbeamrainbowlabs | ee2e5716eb | ||
Starbeamrainbowlabs | cae75ec5a2 | ||
f709d12b75 | |||
484b7532eb | |||
d479e167b9 | |||
11bf486bf2 | |||
9ad27404b0 | |||
ba93cb7bea | |||
d65fe98de6 | |||
71fb8da089 | |||
Starbeamrainbowlabs | 442cb8a8d8 | ||
8a57590179 | |||
Starbeamrainbowlabs | 643790dc07 | ||
Starbeamrainbowlabs | 1984c67295 | ||
Starbeamrainbowlabs | db7b20d485 | ||
4f895f2da5 | |||
Starbeamrainbowlabs | 624abc899b | ||
Starbeamrainbowlabs | 810d3049ee | ||
590a6f3c3a | |||
29bb6a0063 | |||
5d28179bab | |||
79211cf8cb | |||
df209a9f61 | |||
03093112bb | |||
d176cb5419 | |||
0b23f0174b | |||
e5044368b3 | |||
3467f9c5b6 | |||
Starbeamrainbowlabs | f32d8588e0 | ||
Starbeamrainbowlabs | dbdf509d79 | ||
Starbeamrainbowlabs | 65c07d59ea | ||
Starbeamrainbowlabs | 91b77c981b | ||
Starbeamrainbowlabs | 88214aef57 | ||
Starbeamrainbowlabs | 0a3680aa7d | ||
Starbeamrainbowlabs | c76a049286 | ||
Starbeamrainbowlabs | 112bb96e99 | ||
Starbeamrainbowlabs | cfa086ce46 | ||
Starbeamrainbowlabs | dc5645cfeb | ||
Starbeamrainbowlabs | 133cae587c | ||
Starbeamrainbowlabs | 773e6354ad | ||
Starbeamrainbowlabs | 6d0447a02f | ||
Starbeamrainbowlabs | 7549b0eaea | ||
Starbeamrainbowlabs | cde3c3360c | ||
Starbeamrainbowlabs | 8ae0d92e3d | ||
Starbeamrainbowlabs | 57df2d045f | ||
Starbeamrainbowlabs | 1e1112c34a | ||
Starbeamrainbowlabs | 06e19248c7 | ||
Starbeamrainbowlabs | 9d197aefd2 | ||
Starbeamrainbowlabs | 597f6d778f | ||
Starbeamrainbowlabs | bf71aae1d3 | ||
Starbeamrainbowlabs | 5b26bbc0b8 | ||
Starbeamrainbowlabs | b5c45533b7 | ||
Starbeamrainbowlabs | a403a55ac7 | ||
Starbeamrainbowlabs | 1d096f7e8c | ||
Starbeamrainbowlabs | bcc3f8e285 | ||
Starbeamrainbowlabs | 07579a2e75 | ||
Starbeamrainbowlabs | 401af8cc35 | ||
Starbeamrainbowlabs | 0aff7aa476 | ||
Starbeamrainbowlabs | 25e6ff467c | ||
Starbeamrainbowlabs | 9ad3fd97d9 | ||
Starbeamrainbowlabs | 90b456a687 | ||
Starbeamrainbowlabs | afce954306 | ||
3f96fa708f | |||
851dde84f8 | |||
16b7748ac6 | |||
Starbeamrainbowlabs | 6a42aa6838 | ||
2d6bd676d6 | |||
a6a858046f | |||
a40b65af3e | |||
e592e6746f | |||
8be867b2eb | |||
88c70ee233 | |||
92c7d0447a | |||
fc8f76b9dc | |||
70972f4084 | |||
7c92c811e5 | |||
99c0b26086 | |||
efef201fde | |||
5b6062017a | |||
Starbeamrainbowlabs | e12114ffcd | ||
Starbeamrainbowlabs | e5fe220698 | ||
Starbeamrainbowlabs | 3ec4f6b2c7 | ||
Starbeamrainbowlabs | f0bafdcb64 | ||
Starbeamrainbowlabs | 96a645c546 | ||
Starbeamrainbowlabs | 10677e279e | ||
4f1c5c95da | |||
Starbeamrainbowlabs | b72ba10ea3 | ||
Starbeamrainbowlabs | e805f66681 | ||
Starbeamrainbowlabs | 33e90ba6d7 | ||
Starbeamrainbowlabs | 4a36ef7e17 | ||
Starbeamrainbowlabs | cd0bea7219 | ||
Starbeamrainbowlabs | 142adc5beb | ||
Starbeamrainbowlabs | a7abeadb9d | ||
Starbeamrainbowlabs | 816eb6671a | ||
Starbeamrainbowlabs | f009cce911 | ||
Starbeamrainbowlabs | f04deaad15 | ||
Starbeamrainbowlabs | 4d24e4e884 | ||
Starbeamrainbowlabs | 37195edb66 | ||
Starbeamrainbowlabs | 9232b79925 | ||
Starbeamrainbowlabs | cc20fb499d | ||
Starbeamrainbowlabs | ed5f583e04 | ||
Starbeamrainbowlabs | 5362c8956e | ||
Starbeamrainbowlabs | 1dcfc22f7a | ||
Starbeamrainbowlabs | ce41e8bc55 | ||
Starbeamrainbowlabs | 70b6adaa0d | ||
Starbeamrainbowlabs | 4fff388656 | ||
Starbeamrainbowlabs | dcc66f2bd0 | ||
Starbeamrainbowlabs | 79d7712740 | ||
Starbeamrainbowlabs | f01fee3699 | ||
Starbeamrainbowlabs | 8a500735c0 | ||
Starbeamrainbowlabs | b88080a698 | ||
Starbeamrainbowlabs | 85e5eb3971 | ||
Starbeamrainbowlabs | 66234cdeae | ||
7553163e11 | |||
622ea7a683 | |||
3c7cd38459 | |||
3dff6fe66c | |||
0026bcdab7 | |||
38335e291f | |||
8bffeda5b5 | |||
Starbeamrainbowlabs | 1f44e240fb | ||
Starbeamrainbowlabs | 78e6ebe4ae | ||
Starbeamrainbowlabs | 722912a0c2 | ||
21217f20df | |||
75c998f369 | |||
830e5f0d53 | |||
Starbeamrainbowlabs | 117002f9e9 | ||
Starbeamrainbowlabs | 9cb746e86a | ||
Starbeamrainbowlabs | 9c4e23daa8 | ||
5a1fecedd4 | |||
956fc5370a | |||
6e04b11e18 | |||
Starbeamrainbowlabs | de8b35dfee | ||
Starbeamrainbowlabs | 9325f19de2 | ||
8884c938e0 | |||
Starbeamrainbowlabs | 5083ea05ca | ||
Starbeamrainbowlabs | 0474f5a0ee | ||
Starbeamrainbowlabs | 8bc2e543da | ||
Starbeamrainbowlabs | 2f18e9d4ab | ||
Starbeamrainbowlabs | 7ca3f26208 | ||
Starbeamrainbowlabs | 9b53b73bc9 | ||
Starbeamrainbowlabs | af1c1decb0 | ||
Starbeamrainbowlabs | 74bde4e60c | ||
Starbeamrainbowlabs | ccf27c8629 | ||
Starbeamrainbowlabs | dc7ccf49f3 | ||
Starbeamrainbowlabs | 0498125ca7 | ||
Starbeamrainbowlabs | a5c6e82ef3 | ||
Starbeamrainbowlabs | 00a60eba17 | ||
Starbeamrainbowlabs | 9ecdd01914 | ||
Starbeamrainbowlabs | 17b8f8a555 | ||
Starbeamrainbowlabs | a8ddc7831a | ||
Starbeamrainbowlabs | b23f353b19 | ||
Starbeamrainbowlabs | c7c6a848dc | ||
Starbeamrainbowlabs | 8eb9a8ed0f | ||
Starbeamrainbowlabs | 1e677c1f3f | ||
Starbeamrainbowlabs | f7ecb84da4 | ||
Starbeamrainbowlabs | 82f273e19e | ||
Starbeamrainbowlabs | 0b02ce90af | ||
96b408f575 | |||
4d1295ddcd | |||
d7ee9545b9 | |||
Starbeamrainbowlabs | dcc8b2d6f4 | ||
Starbeamrainbowlabs | ffdef17761 | ||
Starbeamrainbowlabs | 98a04b12db | ||
Starbeamrainbowlabs | 46eaf10884 | ||
Starbeamrainbowlabs | 50da328c67 | ||
Starbeamrainbowlabs | a937740275 | ||
Starbeamrainbowlabs | e111decd3a | ||
Starbeamrainbowlabs | 87b7254350 | ||
Starbeamrainbowlabs | 75a5f14f01 | ||
93f9a655cd | |||
9776fc8539 | |||
912371f5b6 | |||
912ecf09c2 | |||
Starbeamrainbowlabs | ff29f9b168 | ||
Starbeamrainbowlabs | 4382e0edeb | ||
Starbeamrainbowlabs | e3e5710217 | ||
Starbeamrainbowlabs | 97aa24bcd3 | ||
Starbeamrainbowlabs | 6d6252b2c3 | ||
Starbeamrainbowlabs | 5d2df22c0a | ||
639c2061ef | |||
45d5f74d0a | |||
d0fdc62d3d | |||
313ab6e62a | |||
0a44992676 | |||
2b02f9ff2e | |||
184ca1a328 | |||
d4b457f85d | |||
0ca9ed30bc | |||
cb841bfb80 | |||
7defe829c3 | |||
d7f328c65b | |||
ec1623b230 | |||
3988e947df | |||
79253b2ce5 | |||
1fda285e39 | |||
5b893901dc | |||
9bb9aeda5c | |||
63d284b35b | |||
d9069b3cfa | |||
35eeb918d0 | |||
Starbeamrainbowlabs | 57ff577694 | ||
Starbeamrainbowlabs | bf8c847dc1 | ||
Starbeamrainbowlabs | 0100725a7b | ||
Starbeamrainbowlabs | 3fbfc1fb15 | ||
Starbeamrainbowlabs | 4d080853d4 | ||
Starbeamrainbowlabs | 8eaa76c752 | ||
Starbeamrainbowlabs | 4e544c555c | ||
Starbeamrainbowlabs | ea05d5f559 | ||
Starbeamrainbowlabs | f9eb67b4cc | ||
Starbeamrainbowlabs | 81f3a87180 | ||
Starbeamrainbowlabs | 040d7fbfde | ||
Starbeamrainbowlabs | 4ec04c03b3 | ||
Starbeamrainbowlabs | efd8a8682e | ||
Starbeamrainbowlabs | 8d7d54c8ff | ||
Starbeamrainbowlabs | 11fbe5e153 | ||
3c3ea2dcce | |||
Starbeamrainbowlabs | 74190e2031 | ||
Starbeamrainbowlabs | d6d11c6b1a | ||
Starbeamrainbowlabs | aa3f89c097 | ||
Starbeamrainbowlabs | 8ba3babf92 | ||
Starbeamrainbowlabs | 7639bd2c2b | ||
Starbeamrainbowlabs | 1f273e4b13 | ||
Starbeamrainbowlabs | 6af8bba987 | ||
Starbeamrainbowlabs | 8877e356f0 | ||
Starbeamrainbowlabs | c6ed5278cc | ||
866748a5c3 | |||
134d2b0999 | |||
a027130917 | |||
d4edeaeff7 | |||
60fb4f1b57 | |||
4c4c7809b0 | |||
ad05b2ac4d | |||
Starbeamrainbowlabs | 9bda3bf05a | ||
Starbeamrainbowlabs | c10880f9ff | ||
00b9a1f517 | |||
Starbeamrainbowlabs | a1911037d2 | ||
20a879a7af | |||
Starbeamrainbowlabs | 237c4839c8 | ||
Starbeamrainbowlabs | 3c4f8e463b | ||
Starbeamrainbowlabs | 683a742fe2 | ||
0b55863d55 | |||
18347f93bf | |||
c39fc1c9e8 | |||
5ffa67b7ac | |||
f79871e5d1 | |||
39f82c99ca | |||
f95d7622c7 | |||
4777b93f60 | |||
cc20297b88 | |||
Starbeamrainbowlabs | d20764cffd | ||
3df23e8086 | |||
Starbeamrainbowlabs | 9c02ffbd04 | ||
Starbeamrainbowlabs | 008a559854 | ||
97f8d551cd | |||
53d899b3fe | |||
f0f6fe3765 | |||
ff9abded2e | |||
bdb51ff944 | |||
Starbeamrainbowlabs | 7774f8538c | ||
Starbeamrainbowlabs | 48619163d5 | ||
cbd07aee4f | |||
234e0a1325 | |||
a671f742e9 | |||
786a9454ff | |||
Starbeamrainbowlabs | 587d430e48 | ||
7f6c8e146e | |||
Starbeamrainbowlabs | 3cc1e120aa | ||
Starbeamrainbowlabs | feb4d6a4bf | ||
Starbeamrainbowlabs | 093a4823bb | ||
Starbeamrainbowlabs | e8d97959b2 | ||
7f4ebb8b8d | |||
Starbeamrainbowlabs | 108c280843 | ||
Starbeamrainbowlabs | e9e7df73b2 | ||
Starbeamrainbowlabs | 7633923911 | ||
Starbeamrainbowlabs | 8cce699313 | ||
Starbeamrainbowlabs | 9f01703744 | ||
Starbeamrainbowlabs | e1755ce8e1 | ||
Starbeamrainbowlabs | 2acc6b3470 | ||
12e5be8da6 | |||
727ee41e72 | |||
0c4736fbc2 | |||
e82c8b1e81 | |||
b31b005bdd | |||
cb1d54c665 | |||
Starbeamrainbowlabs | a9603e29ec | ||
Starbeamrainbowlabs | 1034e592bd | ||
Starbeamrainbowlabs | eae005dc36 | ||
Starbeamrainbowlabs | 56380f149b | ||
Starbeamrainbowlabs | 756bd49470 | ||
b62e4f706d | |||
f6ed297270 | |||
1d93122801 | |||
191f1385b1 | |||
489d856176 | |||
Starbeamrainbowlabs | a0c20a1503 | ||
Starbeamrainbowlabs | 478d1269a1 | ||
Starbeamrainbowlabs | 566b370960 | ||
Starbeamrainbowlabs | a6b34f9311 | ||
Starbeamrainbowlabs | 78572e453e | ||
Starbeamrainbowlabs | f2aa87b396 | ||
Starbeamrainbowlabs | 4ba59a6ec3 | ||
Starbeamrainbowlabs | aef4fe4380 | ||
Starbeamrainbowlabs | ee3effd458 | ||
Starbeamrainbowlabs | d2a1913e90 | ||
Starbeamrainbowlabs | 553dfdd658 | ||
Starbeamrainbowlabs | 5808afe035 | ||
Starbeamrainbowlabs | 523fa856e0 | ||
Starbeamrainbowlabs | 4368f74e30 | ||
Starbeamrainbowlabs | b2b3f5bec5 | ||
Starbeamrainbowlabs | 3f871e01f5 | ||
Starbeamrainbowlabs | a63923fec9 | ||
Starbeamrainbowlabs | ed3adde56a | ||
Starbeamrainbowlabs | 17a67fc5f9 | ||
Starbeamrainbowlabs | 2a268d9ff8 | ||
Starbeamrainbowlabs | 756c1c12f2 | ||
Starbeamrainbowlabs | e19df51916 | ||
1d3c2a0416 | |||
Starbeamrainbowlabs | 0d5e71eb4f | ||
Starbeamrainbowlabs | 4ea69f910a | ||
679de9d591 | |||
Starbeamrainbowlabs | ad9e5a26b1 | ||
Starbeamrainbowlabs | 03afd7e75c | ||
Starbeamrainbowlabs | 555058b4ac | ||
Starbeamrainbowlabs | 1179ecb19a | ||
Starbeamrainbowlabs | 151afadf6c | ||
Starbeamrainbowlabs | a360f06138 | ||
Starbeamrainbowlabs | 2b29334d82 | ||
Starbeamrainbowlabs | 9d76c5d98a | ||
Starbeamrainbowlabs | 2f5c1b759d | ||
Starbeamrainbowlabs | 888ee04f9d | ||
Starbeamrainbowlabs | edb80d7478 | ||
Starbeamrainbowlabs | 122ff381f1 | ||
Starbeamrainbowlabs | 15417354c6 | ||
Starbeamrainbowlabs | ac954abaea | ||
Starbeamrainbowlabs | 9dffb17f3d | ||
Starbeamrainbowlabs | ebed73fc49 | ||
Starbeamrainbowlabs | 38e5c81d33 | ||
Starbeamrainbowlabs | 25e659321a | ||
Starbeamrainbowlabs | 85a715a0ea | ||
Starbeamrainbowlabs | a511d85e29 | ||
Starbeamrainbowlabs | 39a7168ac8 | ||
Starbeamrainbowlabs | e8584c4ec6 | ||
Starbeamrainbowlabs | 6896a9bdd4 | ||
Starbeamrainbowlabs | 8c47e05e52 | ||
Starbeamrainbowlabs | 9bd909b25e | ||
Starbeamrainbowlabs | 263bb4fa8b | ||
Starbeamrainbowlabs | c627ea224c | ||
Starbeamrainbowlabs | 0f4d95fc01 | ||
Starbeamrainbowlabs | 0be205dae7 | ||
Starbeamrainbowlabs | f19a897a9e | ||
Starbeamrainbowlabs | 4b1cf074d5 | ||
Starbeamrainbowlabs | 8b32353f74 | ||
Starbeamrainbowlabs | 0bd909cc31 | ||
Starbeamrainbowlabs | 4b2f2b0001 | ||
Starbeamrainbowlabs | 0cfd651510 | ||
Starbeamrainbowlabs | 830ab77cd1 | ||
Starbeamrainbowlabs | b965f12ca4 | ||
Starbeamrainbowlabs | d2f101e9dd | ||
Starbeamrainbowlabs | 008519177c | ||
Starbeamrainbowlabs | 2ac6ea03a7 | ||
Starbeamrainbowlabs | aa234595a8 | ||
Starbeamrainbowlabs | 1ac64a9ebc | ||
Starbeamrainbowlabs | 3cadf6c83f | ||
Starbeamrainbowlabs | 986558d8cb | ||
Starbeamrainbowlabs | 7e02714c86 | ||
Starbeamrainbowlabs | ef165b9c58 | ||
Starbeamrainbowlabs | 4367b4bc70 | ||
Starbeamrainbowlabs | f0e7246f97 | ||
Starbeamrainbowlabs | fea89f2e3c | ||
Starbeamrainbowlabs | 39103a046f | ||
Starbeamrainbowlabs | cf2d3f408c | ||
Starbeamrainbowlabs | fedef59560 | ||
Starbeamrainbowlabs | ecda678c38 | ||
Starbeamrainbowlabs | 0f2eeec604 | ||
Starbeamrainbowlabs | e3d5479e0c | ||
Starbeamrainbowlabs | 54e4c04464 | ||
Starbeamrainbowlabs | 3ce3c2501a | ||
Starbeamrainbowlabs | 130524a7d0 | ||
Starbeamrainbowlabs | d943d7ac78 | ||
Starbeamrainbowlabs | a6f5fe5123 | ||
Starbeamrainbowlabs | e0e64dc6b9 | ||
Starbeamrainbowlabs | 13278570cb | ||
Starbeamrainbowlabs | 358fac7c7c | ||
Starbeamrainbowlabs | d2b38d0ea1 | ||
Starbeamrainbowlabs | 5967db2496 | ||
Starbeamrainbowlabs | c6a1571e1f | ||
Starbeamrainbowlabs | ebe17efec6 | ||
Starbeamrainbowlabs | 0ddf160e84 | ||
Starbeamrainbowlabs | 5ad44e7c31 | ||
Starbeamrainbowlabs | 36a982b314 | ||
Starbeamrainbowlabs | d556a4e710 | ||
Starbeamrainbowlabs | ad4f4e9dd0 | ||
Starbeamrainbowlabs | 9bd3875d98 | ||
Starbeamrainbowlabs | 66a265bbce | ||
Starbeamrainbowlabs | 2a592a808c | ||
Starbeamrainbowlabs | a6fc9712b4 | ||
Starbeamrainbowlabs | 0b285fa681 | ||
Starbeamrainbowlabs | 0abf9d095b | ||
Starbeamrainbowlabs | 44efb9bb38 | ||
Starbeamrainbowlabs | 4c0c6c1b00 | ||
Starbeamrainbowlabs | b8ce7393bc | ||
Starbeamrainbowlabs | 27f2e1b68a | ||
Starbeamrainbowlabs | b2bf11b369 | ||
Starbeamrainbowlabs | 85e4ecc2c9 | ||
Starbeamrainbowlabs | 2384279884 | ||
Starbeamrainbowlabs | 25f369c582 | ||
Starbeamrainbowlabs | 9c9db3f253 | ||
Starbeamrainbowlabs | 5ac7dc8706 | ||
Starbeamrainbowlabs | b303f8758a | ||
Starbeamrainbowlabs | 71b7de4e10 | ||
Starbeamrainbowlabs | 305ecb0a88 | ||
Starbeamrainbowlabs | 6846369cf9 | ||
Starbeamrainbowlabs | e8a9ba8800 | ||
Starbeamrainbowlabs | 07588e0940 | ||
Starbeamrainbowlabs | fd5804dd9c | ||
Starbeamrainbowlabs | 997eb4d101 | ||
Starbeamrainbowlabs | acb288b984 | ||
Starbeamrainbowlabs | cdba38d37d | ||
Starbeamrainbowlabs | 20ccf321ce | ||
Starbeamrainbowlabs | de6ea49d6f | ||
Starbeamrainbowlabs | a1cd76d515 | ||
Starbeamrainbowlabs | 3c6ca58bfa | ||
Starbeamrainbowlabs | 90ea388003 | ||
Starbeamrainbowlabs | 91f11a2b0d | ||
Starbeamrainbowlabs | 5009ca7782 | ||
Starbeamrainbowlabs | b7eab3a6e5 | ||
Starbeamrainbowlabs | 967d2d0f54 | ||
Starbeamrainbowlabs | 029008c0e6 | ||
Starbeamrainbowlabs | 97efa8e54c | ||
Starbeamrainbowlabs | 9404d2411a | ||
Starbeamrainbowlabs | 813c3084a9 | ||
Starbeamrainbowlabs | f3c6329526 | ||
Starbeamrainbowlabs | 32b4a84a4a | ||
Starbeamrainbowlabs | ce6ed01b36 | ||
Starbeamrainbowlabs | 0e74d22971 | ||
Starbeamrainbowlabs | 4e39ea6e71 | ||
Starbeamrainbowlabs | a03b5ae834 | ||
Starbeamrainbowlabs | 9b913bdfb1 | ||
Starbeamrainbowlabs | 3487e5c32b | ||
Starbeamrainbowlabs | 0afbba4deb | ||
Starbeamrainbowlabs | 5aec4d756c | ||
Starbeamrainbowlabs | be38facaab | ||
Starbeamrainbowlabs | ce999dd537 | ||
Starbeamrainbowlabs | 20a026724f | ||
Starbeamrainbowlabs | c05b1b2f67 | ||
Starbeamrainbowlabs | 257d8dd15d | ||
Starbeamrainbowlabs | c0624f5a94 | ||
Starbeamrainbowlabs | 00177637b5 | ||
Starbeamrainbowlabs | adca852f56 | ||
Starbeamrainbowlabs | 4976b1956c | ||
Starbeamrainbowlabs | 4e889145d1 | ||
Starbeamrainbowlabs | 2f17b4a794 | ||
Starbeamrainbowlabs | f8a6a204f8 | ||
Starbeamrainbowlabs | db21baa539 | ||
Starbeamrainbowlabs | fbf2b894e5 | ||
Starbeamrainbowlabs | 6f20b31763 | ||
Starbeamrainbowlabs | b8a5bec987 | ||
Starbeamrainbowlabs | caf56313cd | ||
Starbeamrainbowlabs | 5232406dbb | ||
Starbeamrainbowlabs | 75a17ed64f | ||
Starbeamrainbowlabs | 905ccc2d50 | ||
Starbeamrainbowlabs | 6b3cb02004 | ||
Starbeamrainbowlabs | 682aba5aa2 | ||
Starbeamrainbowlabs | 55da495db2 | ||
Starbeamrainbowlabs | da1c56cc23 | ||
Starbeamrainbowlabs | 2b32385fdf | ||
Starbeamrainbowlabs | d96f169950 | ||
Starbeamrainbowlabs | 32e786401a | ||
Starbeamrainbowlabs | 2dbbeef9c9 | ||
Starbeamrainbowlabs | 868052f945 | ||
Starbeamrainbowlabs | e5d847f7e6 | ||
Starbeamrainbowlabs | 6dac57c53e | ||
Starbeamrainbowlabs | 9b9a471aa8 | ||
Starbeamrainbowlabs | 35001f05f8 | ||
Starbeamrainbowlabs | e26d5b1580 | ||
Starbeamrainbowlabs | 435964daec | ||
Starbeamrainbowlabs | 650ad47753 | ||
Starbeamrainbowlabs | 985fb8db9f | ||
Starbeamrainbowlabs | c0b40266c8 | ||
Starbeamrainbowlabs | 47514a5748 | ||
Starbeamrainbowlabs | f3a8c1dd64 | ||
Starbeamrainbowlabs | f0dc2f5a3c | ||
Starbeamrainbowlabs | 952d7a96f8 | ||
Starbeamrainbowlabs | 32eb0ffc79 | ||
Starbeamrainbowlabs | db2c867086 | ||
Starbeamrainbowlabs | 5f7a64702a | ||
Starbeamrainbowlabs | 238ef7c810 | ||
Starbeamrainbowlabs | df629157b2 | ||
Starbeamrainbowlabs | fb228bb37b | ||
Starbeamrainbowlabs | 70f7e64371 | ||
Starbeamrainbowlabs | e4df5af008 | ||
Starbeamrainbowlabs | 6418104f5c | ||
Starbeamrainbowlabs | 576351225a | ||
Starbeamrainbowlabs | 6be534d4b7 | ||
Starbeamrainbowlabs | b7888a2b3f | ||
Starbeamrainbowlabs | bdf0bdea93 | ||
Starbeamrainbowlabs | ae068989e2 | ||
Starbeamrainbowlabs | afce170d4c | ||
Starbeamrainbowlabs | bdfd74346e | ||
Starbeamrainbowlabs | 58faa8349e | ||
Starbeamrainbowlabs | 8e515c3778 | ||
Starbeamrainbowlabs | 94760f5d9b | ||
Starbeamrainbowlabs | 121b06eb9a | ||
Starbeamrainbowlabs | 076297553b | ||
Starbeamrainbowlabs | 35bd8f19b2 | ||
Starbeamrainbowlabs | 29223a3455 | ||
Starbeamrainbowlabs | 2720f62d09 | ||
Starbeamrainbowlabs | d35a55ea9e | ||
Starbeamrainbowlabs | 30859d313a | ||
Starbeamrainbowlabs | a3a193cd68 | ||
Starbeamrainbowlabs | 394f3ec4ef | ||
Starbeamrainbowlabs | dc65c721bd | ||
Starbeamrainbowlabs | a2d078e156 | ||
Starbeamrainbowlabs | 340191b2cf | ||
Starbeamrainbowlabs | c83cc9bf39 | ||
Starbeamrainbowlabs | b235562ab5 | ||
Starbeamrainbowlabs | 71021cd379 | ||
Starbeamrainbowlabs | 9bfb2c86f8 | ||
Starbeamrainbowlabs | cf4f602f38 | ||
Starbeamrainbowlabs | c4d6e6e716 | ||
Starbeamrainbowlabs | 4824f28a95 | ||
Starbeamrainbowlabs | cdf246bff8 | ||
Starbeamrainbowlabs | c12683ca73 |
140
.docs/.eleventy.js
Normal file
|
@ -0,0 +1,140 @@
|
|||
"use strict";
|
||||
|
||||
const os = require("os");
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
const debug = require("debug");
|
||||
const htmlentities = require("html-entities");
|
||||
const phin = require("phin");
|
||||
const CleanCSS = require("clean-css");
|
||||
const { minify: minify_html } = require("html-minifier-terser");
|
||||
|
||||
const HTMLPicture = require("./lib/HTMLPicture.js");
|
||||
const FileFetcher = require("./lib/FileFetcher.js");
|
||||
|
||||
const file_fetcher = new FileFetcher();
|
||||
|
||||
const is_production = typeof process.env.NODE_ENV === "string" && process.env.NODE_ENV === "production";
|
||||
|
||||
var nextid = 0;
|
||||
|
||||
const image_filename_format = (_id, src, width, format, _options) => {
|
||||
const extension = path.extname(src);
|
||||
const name = path.basename(src, extension);
|
||||
return `${name}-${width}w.${format}`;
|
||||
};
|
||||
|
||||
async function shortcode_image(src, alt) {
|
||||
|
||||
return HTMLPicture(
|
||||
src, alt,
|
||||
`./_site/img`, `/img`
|
||||
);
|
||||
}
|
||||
|
||||
async function shortcode_image_url(src) {
|
||||
const src_parsed = path.parse(src);
|
||||
const target = path.join(`./_site/img`, src_parsed.base);
|
||||
if(!fs.existsSync(path.dirname(target)))
|
||||
await fs.promises.mkdir(target_dir, { recursive: true });
|
||||
await fs.promises.copyFile(src, target);
|
||||
|
||||
return path.join(`/img`, src_parsed.base);
|
||||
}
|
||||
|
||||
async function shortcode_image_urlpass(src) {
|
||||
let target_dir = `./_site/img`;
|
||||
if(!fs.existsSync(target_dir))
|
||||
await fs.promises.mkdir(target_dir, { recursive: true });
|
||||
let filename = path.basename(src);
|
||||
// Generally speaking we optimise PNGs *very* well with oxipng/Zopfli,
|
||||
// and the Image plugin doesn't respect this
|
||||
await fs.promises.copyFile(src, path.join(target_dir, filename));
|
||||
return `/img/${filename}`;
|
||||
}
|
||||
|
||||
async function shortcode_gallerybox(content, src, id_this, id_prev, id_next) {
|
||||
return `<figure class="gallerybox-item" id="${id_this}">
|
||||
<!-- ${await shortcode_image(src, "", "gallerybox-thumb", "300w")} -->
|
||||
${await shortcode_image(src, "", "", "1920w")}
|
||||
|
||||
<figcaption>${content}</figcaption>
|
||||
|
||||
<a class="gallerybox-prev" href="#${id_prev}">❰</a>
|
||||
<a class="gallerybox-next" href="#${id_next}">❱</a>
|
||||
</figure>`;
|
||||
}
|
||||
|
||||
async function fetch(url) {
|
||||
return (await phin({
|
||||
url,
|
||||
headers: {
|
||||
"user-agent": `WorldEditAdditionsStaticBuilder/${pkg_obj.version} (Node.js/${process.version}; ${os.platform()} ${os.arch()}) eleventy/${pkg_obj.devDependencies["@11ty/eleventy"].replace(/\^/, "")}`
|
||||
},
|
||||
followRedirects: true,
|
||||
parse: "string"
|
||||
})).body;
|
||||
}
|
||||
|
||||
function fetch_file(url) {
|
||||
return file_fetcher.fetch_file(url);
|
||||
}
|
||||
|
||||
function do_minify_css(source, output_path) {
|
||||
if(!output_path.endsWith(".css") || !is_production) return source;
|
||||
|
||||
const result = new CleanCSS({
|
||||
level: 2
|
||||
}).minify(source).styles.trim();
|
||||
console.log(`MINIFY ${output_path}`, source.length, `→`, result.length, `(${((1 - (result.length / source.length)) * 100).toFixed(2)}% reduction)`);
|
||||
return result;
|
||||
}
|
||||
|
||||
async function do_minify_html(source, output_path) {
|
||||
if(!output_path.endsWith(".html") || !is_production) return source;
|
||||
|
||||
const result = await minify_html(source, {
|
||||
collapseBooleanAttributes: true,
|
||||
collapseWhitespace: true,
|
||||
collapseInlineTagWhitespace: true,
|
||||
continueOnParseError: true,
|
||||
decodeEntities: true,
|
||||
keepClosingSlash: true,
|
||||
minifyCSS: true,
|
||||
quoteCharacter: `"`,
|
||||
removeComments: true,
|
||||
removeAttributeQuotes: true,
|
||||
removeRedundantAttributes: true,
|
||||
removeScriptTypeAttributes: true,
|
||||
removeStyleLinkTypeAttributes: true,
|
||||
sortAttributes: true,
|
||||
sortClassName: true,
|
||||
useShortDoctype: true
|
||||
});
|
||||
|
||||
console.log(`MINIFY ${output_path}`, source.length, `→`, result.length, `(${((1 - (result.length / source.length)) * 100).toFixed(2)}% reduction)`);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
if(is_production) console.log("Production environment detected, minifying content");
|
||||
|
||||
module.exports = function(eleventyConfig) {
|
||||
eleventyConfig.addTransform("cssmin", do_minify_css);
|
||||
eleventyConfig.addTransform("htmlmin", do_minify_html);
|
||||
|
||||
eleventyConfig.addPassthroughCopy("img2brush/img2brush.js");
|
||||
eleventyConfig.addAsyncShortcode("fetch", fetch);
|
||||
eleventyConfig.addFilter("fetch_file", fetch_file);
|
||||
|
||||
// eleventyConfig.addPassthroughCopy("images");
|
||||
// eleventyConfig.addPassthroughCopy("css");
|
||||
eleventyConfig.addShortcode("image", shortcode_image);
|
||||
eleventyConfig.addJavaScriptFunction("image", shortcode_image);
|
||||
// eleventyConfig.addNunjucksAsyncShortcode("image_url", shortcode_image_url);
|
||||
eleventyConfig.addAsyncShortcode("image_url", shortcode_image_url);
|
||||
eleventyConfig.addAsyncShortcode("image_urlpass", shortcode_image_urlpass);
|
||||
eleventyConfig.addNunjucksAsyncShortcode("image_urlpass", shortcode_image_urlpass);
|
||||
eleventyConfig.addPairedShortcode("gallerybox", shortcode_gallerybox);
|
||||
}
|
1
.docs/.eleventyignore
Normal file
|
@ -0,0 +1 @@
|
|||
css/
|
6
.docs/Changelog.11tydata.json
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"layout": "content-generic.njk",
|
||||
"title": "Changelog",
|
||||
"tags": "navigable",
|
||||
"date": "2002-01-01"
|
||||
}
|
1
.docs/Changelog.md
Symbolic link
|
@ -0,0 +1 @@
|
|||
../CHANGELOG.md
|
6
.docs/Cookbook.11tydata.json
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"layout": "content-generic.njk",
|
||||
"title": "Cookbook",
|
||||
"tags": "navigable",
|
||||
"date": "2006-01-01"
|
||||
}
|
1
.docs/Cookbook.md
Symbolic link
|
@ -0,0 +1 @@
|
|||
../Cookbook.md
|
47
.docs/Reference.11tydata.js
Normal file
|
@ -0,0 +1,47 @@
|
|||
"use strict";
|
||||
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
const columnify = require("columnify");
|
||||
const htmlentities = require("html-entities");
|
||||
|
||||
const a = require("./lib/Ansi.js");
|
||||
const parse_sections = require("./lib/parse_sections.js");
|
||||
|
||||
let { sections, categories } = parse_sections(fs.readFileSync(
|
||||
path.resolve(
|
||||
__dirname,
|
||||
`../Chat-Command-Reference.md`
|
||||
),
|
||||
"utf-8"
|
||||
))
|
||||
|
||||
sections = sections.sort((a, b) => a.title.replace(/^\/+/g, "").localeCompare(
|
||||
b.title.replace(/^\/+/g, "")));
|
||||
|
||||
|
||||
console.log(`REFERENCE SECTION TITLES`)
|
||||
console.log(columnify(sections.map(s => { return {
|
||||
category: `${a.hicol}${a.fyellow}${s.category}${a.reset}`,
|
||||
command: `${a.hicol}${a.fmagenta}${htmlentities.decode(s.title)}${a.reset}`
|
||||
} })));
|
||||
// console.log(sections
|
||||
// .map(s => `${a.fyellow}${a.hicol}${s.category}${a.reset}\t${a.fmagenta}${a.hicol}${s.title}${a.reset}`).join(`\n`));
|
||||
console.log(`************************`);
|
||||
|
||||
console.log(`REFERENCE SECTION COLOURS`);
|
||||
console.log(columnify(Array.from(categories).map(el => { return {
|
||||
category: el[0],
|
||||
colour: el[1]
|
||||
} })));
|
||||
|
||||
module.exports = {
|
||||
layout: "theme.njk",
|
||||
title: "Reference",
|
||||
tags: "navigable",
|
||||
date: "2001-01-01",
|
||||
section_intro: sections[0],
|
||||
sections_help: sections, // Remove the very beginning bit
|
||||
categories: [...categories.keys()].join("|")
|
||||
}
|
220
.docs/Reference.html
Normal file
|
@ -0,0 +1,220 @@
|
|||
<main>
|
||||
<section class="panel-generic">
|
||||
<h1 id="#reference">Reference</h1>
|
||||
<p>This is the full chat command reference for WorldEditAdditions. It has 2 parts:</p>
|
||||
|
||||
<ol>
|
||||
<li>A contents list of commands and their syntax</li>
|
||||
<li>A full reference, with detailed explanations for each command</li>
|
||||
</ol>
|
||||
|
||||
<p>There is also a <a href="#filter">filter box</a> for filtering everything to quickly find the one you're after.</p>
|
||||
|
||||
</section>
|
||||
|
||||
<section id="filter" class="panel-generic">
|
||||
<div class="form-item bigsearch">
|
||||
<label for="input-filter">Filter:</label>
|
||||
<input type="search" id="input-filter" placeholder="Start typing to filter." autofocus />
|
||||
</div>
|
||||
<div class="form-item centre checkbox">
|
||||
<input type="checkbox" id="input-searchall" />
|
||||
<label for="input-searchall" title="If unchecked, only the title will be searched.">Search content</label>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="panel-generic">
|
||||
<h2 id="contents" class="linked-section-heading">
|
||||
<a class="section-link" href="#{{ section.slug }}">🔗 <!-- Link Symbol --></a>
|
||||
<span class="title">Contents</span>
|
||||
</h2>
|
||||
<div class="command-ordering-tabs">
|
||||
<button class="active" data-mode="alphabetical">Alphabetical</button>
|
||||
<button data-mode="categorical">Categorical</button>
|
||||
</div>
|
||||
<input type="hidden" id="category-names" value="{{ categories }}" />
|
||||
<div class="command-container">
|
||||
<h3>Alphabetical</h3>
|
||||
<ul class="command-list">
|
||||
{% for section in sections_help %}
|
||||
<li data-filtermode-force="all" data-category="{{ section.category }}" style="--cat-colour: {{ section.category_colour }};"><a href="#{{ section.slug }}">
|
||||
<code>{{ section.title }}</code>
|
||||
</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<script>
|
||||
function search_text(query, text) {
|
||||
return text.toLocaleLowerCase().includes(query);
|
||||
}
|
||||
|
||||
function handle_display_mode(event) {
|
||||
set_display_mode(event.target.dataset.mode);
|
||||
|
||||
localStorage.setItem("commandlist-displaymode", event.target.dataset.mode);
|
||||
}
|
||||
|
||||
function sort_command_list(list) {
|
||||
list.sort((a, b) =>
|
||||
a.querySelector("a").href.localeCompare(b.querySelector("a").href))
|
||||
}
|
||||
function nodelist2array(list) {
|
||||
const result = [];
|
||||
for(let i = 0; i < list.length; i++) result.push(list[i]);
|
||||
return result;
|
||||
}
|
||||
|
||||
function set_display_mode(mode) {
|
||||
console.info(`SET DISPLAYMODE ${mode}`)
|
||||
|
||||
const commands = nodelist2array(document.querySelectorAll(`.command-list li`));
|
||||
const container = document.querySelector(`.command-container`);
|
||||
|
||||
switch(mode) {
|
||||
case "categorical":
|
||||
const sections = Object.create(null);
|
||||
for(const command of [...commands]) {
|
||||
const cat = command.dataset.category;
|
||||
if(!(sections[cat] instanceof Array))
|
||||
sections[cat] = [];
|
||||
sections[cat].push(command);
|
||||
}
|
||||
|
||||
const section_names = document.querySelector("#category-names").value
|
||||
.split("|");
|
||||
|
||||
const fragment = new DocumentFragment();
|
||||
|
||||
for(const section_name of section_names) {
|
||||
sort_command_list(sections[section_name]);
|
||||
|
||||
const header = document.createElement("h3");
|
||||
header.appendChild(document.createTextNode(section_name));
|
||||
fragment.appendChild(header);
|
||||
const list = document.createElement("ul");
|
||||
list.classList.add("command-list", "coloured");
|
||||
for(const item of sections[section_name])
|
||||
list.appendChild(item);
|
||||
fragment.appendChild(list);
|
||||
}
|
||||
container.replaceChildren(fragment);
|
||||
break;
|
||||
|
||||
case "alphabetical":
|
||||
const alpha_fragment = new DocumentFragment();
|
||||
const alpha_header = document.createElement("h3");
|
||||
alpha_header.appendChild(document.createTextNode("Alphabetical"));
|
||||
alpha_fragment.appendChild(alpha_header);
|
||||
const alpha_list = document.createElement("ul");
|
||||
alpha_list.classList.add("command-list");
|
||||
alpha_list.classList.add("command-alpha_list");
|
||||
sort_command_list(commands);
|
||||
for(let i = 0; i < commands.length; i++)
|
||||
alpha_list.appendChild(commands[i]);
|
||||
alpha_fragment.appendChild(alpha_list);
|
||||
container.replaceChildren(alpha_fragment);
|
||||
break;
|
||||
}
|
||||
|
||||
const el_alpha = document.querySelector(".command-ordering-tabs [data-mode=alphabetical]");
|
||||
const el_cats = document.querySelector(".command-ordering-tabs [data-mode=categorical]");
|
||||
|
||||
el_alpha.classList.toggle("active");
|
||||
el_cats.classList.toggle("active");
|
||||
}
|
||||
|
||||
function do_filter() {
|
||||
let el_search = document.querySelector("#input-filter");
|
||||
let el_searchall = document.querySelector("#input-searchall");
|
||||
localStorage.setItem("commandlist-searchall", el_searchall.checked);
|
||||
/* Filterable items
|
||||
- Sections
|
||||
- Commands in the command list
|
||||
*/
|
||||
let els_filterable = document.querySelectorAll("section.filterable, .command-list > li");
|
||||
|
||||
let query = el_search.value.toLocaleLowerCase();
|
||||
|
||||
let mode = el_searchall.checked ? "all" : "header";
|
||||
console.log(`SEARCH | mode`, mode, `query`, query);
|
||||
|
||||
for(let i = 0; i < els_filterable.length; i++) {
|
||||
let el_next = els_filterable[i];
|
||||
|
||||
let mode_this = mode;
|
||||
if(typeof el_next.dataset.filtermodeForce == "string")
|
||||
mode_this = el_next.dataset.filtermodeForce;
|
||||
|
||||
let show = true;
|
||||
if(query.length > 0) {
|
||||
switch(mode_this) {
|
||||
case "all":
|
||||
show = search_text(query,
|
||||
el_next.textContent + ` ` + el_next.dataset.category
|
||||
);
|
||||
break;
|
||||
case "header":
|
||||
show = search_text(query,
|
||||
el_next.querySelector(".linked-section-heading").textContent
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
el_next.classList.remove("visible", "hidden");
|
||||
el_next.classList.add(show ? "visible" : "hidden");
|
||||
}
|
||||
|
||||
let commandlist_is_categorical = document.querySelector("button.active[data-mode=categorical]") !== null;
|
||||
if(commandlist_is_categorical) {
|
||||
let container = document.querySelector(".command-container");
|
||||
for(let i = 0; i < container.children.length; i++) {
|
||||
if(container.children[i].nodeName.toLowerCase() === "ul") {
|
||||
let class_name = "visible";
|
||||
if(container.children[i].querySelector("li.visible") === null)
|
||||
class_name = "hidden";
|
||||
if(i > 0) {
|
||||
container.children[i-1].classList.remove("visible", "hidden");
|
||||
container.children[i-1].classList.add(class_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener("load", (_event) => {
|
||||
let el_search = document.querySelector("#input-filter");
|
||||
let el_searchall = document.querySelector("#input-searchall");
|
||||
let els_cats = document.querySelectorAll(".command-ordering-tabs button");
|
||||
|
||||
el_search.addEventListener("input", do_filter);
|
||||
el_search.addEventListener("search", do_filter);
|
||||
el_searchall.addEventListener("change", do_filter);
|
||||
|
||||
for(let i = 0; i < els_cats.length; i++) {
|
||||
els_cats[i].addEventListener("click", handle_display_mode);
|
||||
els_cats[i].addEventListener("touchend", handle_display_mode);
|
||||
}
|
||||
|
||||
if(localStorage.getItem("commandlist-searchall") !== null)
|
||||
el_searchall.checked = localStorage.getItem("commandlist-searchall") === "true";
|
||||
|
||||
if(localStorage.getItem("commandlist-displaymode") !== null)
|
||||
set_display_mode(localStorage.getItem("commandlist-displaymode"))
|
||||
});
|
||||
</script>
|
||||
|
||||
{% for section in sections_help %}
|
||||
<section class="panel-generic filterable" style="--cat-colour: {{ section.category_colour_dark }};">
|
||||
<h2 id="{{ section.slug }}" class="linked-section-heading">
|
||||
<a class="section-link" href="#{{ section.slug }}">🔗 <!-- Link Symbol --></a>
|
||||
<span class="title">{{ section.title }}</span>
|
||||
<span class="category">{{ section.category }}</span>
|
||||
</h2>
|
||||
|
||||
{{ section.content }}
|
||||
</section>
|
||||
{% endfor %}
|
||||
</main>
|
120
.docs/Tutorial.md
Normal file
|
@ -0,0 +1,120 @@
|
|||
---
|
||||
layout: content-generic.njk
|
||||
title: Tutorial
|
||||
tags: navigable
|
||||
date: 2004-01-01
|
||||
---
|
||||
|
||||
# WorldEditAdditions Beginner's Tutorial
|
||||
Welcome to the WorldEditAdditions beginners tutorial! There are a number of conventions used in the [chat command reference](/Reference) that may not be immediately obvious - this guide serves to explain in detail.
|
||||
|
||||
It is assumed that:
|
||||
|
||||
- You are already familiar the basics of [Minetest](https://www.minetest.net/) (try the [tutorial game](https://content.minetest.net/packages/Wuzzy/tutorial/) if you're unsure)
|
||||
- You have both WorldEdit and WorldEditAdditions installed (see the [Download](/#download) section)
|
||||
|
||||
Minetest supports the execution of _Chat Commands_ to manipulate the Minetest world. While in a Minetest world, simply type `/help` (the first forward slash `/` will automatically cause the chat window to appear) and hit <kbd>enter</kbd> to display a list of chat commands that are currently registered grouped by mod for example.
|
||||
|
||||
WorldEdit commands are, by convention, prefixed with an additional forward slash `/`. Here are some examples of WorldEdit chat commands:
|
||||
|
||||
```
|
||||
//1
|
||||
//2
|
||||
//set dirt
|
||||
```
|
||||
|
||||
Explaining core WorldEdit commands is out of scope of this tutorial, but you can find a complete list of them here: <https://github.com/Uberi/Minetest-WorldEdit/blob/master/ChatCommands.md>.
|
||||
|
||||
The purpose of _WorldEditAdditions_ is to extend _WorldEdit_ by adding additional commands. Example commands that have been implemented that are not present in core _WorldEdit_ include (but certainly aren't limited to):
|
||||
|
||||
- [`//maze`](/Reference/#maze): Create instant mazes
|
||||
- [`//forest`](/Reference/#forest): Plant forests
|
||||
- [`//torus`](http://localhost:8080/Reference/#torus): Generate [torus](https://en.wikipedia.org/wiki/Torus) shapes
|
||||
- [`//scale`](/Reference/#scale): Scale things up and down - even both at the same time!
|
||||
|
||||
See a full list with complete explanations in the [chat command reference](/Reference).
|
||||
|
||||
|
||||
## Regions
|
||||
WorldEdit allows you to define a _region_ by specifying 2 points in the world - we number these points 1 and 2. By using the WorldEdit wand (or WorldEditAdditions Far Wand), one can left click to set the position of point 1, and right click to set point 2:
|
||||
|
||||
{% image "images/tutorial_pos1_2.jpeg" "A screenshot showing WorldEdit points 1 and 2 in a desert with a cactus" %}
|
||||
|
||||
Point 1 is on the cactus, and point 2 is on the ground in the bottom left.
|
||||
|
||||
Most WorldEdit and WorldEditAdditions commands require either 1 or 2 points to be set in order to work.
|
||||
|
||||
- If 1 point is required, it's the origin point used by the command
|
||||
- If 2 points are required, the defined region specifies the area in which the command is operate
|
||||
|
||||
|
||||
## Command syntax
|
||||
When explaining the syntax (ref [a](https://en.wikipedia.org/wiki/Syntax_(programming_languages)), [b](https://www.bbc.co.uk/bitesize/guides/z22wwmn/revision/6)) of a command, a number of different conventions are used to concisely explain said syntax. Understanding enables you to quickly understand the output of `/help /maze` for example, or the list of commands in the [reference](/Reference).
|
||||
|
||||
- `<thing>`: A placeholder for a value that you can change. Do *not* include the `<` angle brackets `>` when replacing it with your actual value.
|
||||
- `a | b`: 1 thing or another, but not both.
|
||||
- `[optional_thing]`: Something that's optional. Specifying it enables greater control over the behaviour of the command, but it can be left out for convenience.
|
||||
- `<thing|other_thing>`: Pick 1 item from the list and replace the entire group, removing the `<` angle brackets `>` as with `<thing>`. For example `<snowballs|river>` could become either `snowballs` or `river`, but not both at the same time.
|
||||
- `<thing=default_value>`: Most commonly seen in `[` square brackets `]` indicating an optional thing. Indicates the default value of something that you can replace (or omit).
|
||||
- `...`: Indicates that the previous items can be repeated.
|
||||
|
||||
Let's illustrate this with a practical example. Consider the following:
|
||||
|
||||
```
|
||||
//example <height> <apple|orange> | <height> <width> <pear|maple> [<extra_value>]
|
||||
```
|
||||
|
||||
The following different invocations of the above would be valid:
|
||||
|
||||
```
|
||||
//example 10 apple
|
||||
//example 45 30 maple
|
||||
//example 30 12 pear something_else
|
||||
```
|
||||
|
||||
Now let's apply this to a more practical example:
|
||||
|
||||
```
|
||||
//erode [<snowballs|river> [<key_1> [<value_1>]] [<key_2> [<value_2>]] ...]
|
||||
```
|
||||
|
||||
The `<snowballs|river>` explains that either a value of `snowballs` or `river` is acceptable. Then, a key - value list of options can be specified - allowing an arbitrary number of options.
|
||||
|
||||
From this, we can infer the following usage:
|
||||
|
||||
```
|
||||
//erode snowballs speed 1 count 50000
|
||||
```
|
||||
|
||||
|
||||
## Anything else?
|
||||
|
||||
- Make sure we have covered everything
|
||||
|
||||
|
||||
## Advanced Concepts
|
||||
A number of additional concepts that are not required to use WorldEditAdditions are explained here, as they can be helpful for understanding some of the more advanced concepts and commands provided by WorldEditAdditions.
|
||||
|
||||
### Meta commands
|
||||
WorldEditAdditions provides a number of *meta commands*. Such commands don't do anything on their own, but call other commands in various different ways. Examples of meta commands include:
|
||||
|
||||
- [`//subdivide`](/Reference#subdivide): split a region into chunks, and execute the command once for each chunk
|
||||
- [`//many`](/Reference#many): Execute a command multiple times
|
||||
- [`//multi`](/Reference#multi): Execute multiple commands in sequence
|
||||
|
||||
Of course, this isn't an exhaustive list - check the [reference](/Reference) for a full list.
|
||||
|
||||
### Memory usage
|
||||
Memory (or RAM - Random Access Memory) is used by all the processes running on a system to hold data that they are currently working with. This is especially important for WorldEdit and WorldEditAdditions, since the larger the region you define the more memory that will be required to run commands on it.
|
||||
|
||||
Depending on your system, Minetest and your system can slow to a crawl or even crash if you execute a command on a region that's too big.
|
||||
|
||||
To work around this, the [`//subdivide`](/Reference#subdivide) command was implemented. It splits the defined region into chunks, and calls the specified command over and over again for each chunk.
|
||||
|
||||
It's not suitable for all commands (since it requires that said command takes 2 points) though, but because it splits the defined region into multiple chunks, it can be executed on *enormous* regions that can't fit into memory all at the same time.
|
||||
|
||||
|
||||
## Conclusion
|
||||
This short tutorial has explained a few key concepts that are useful for understanding WorldEditAdditions, from executing chat commands to the syntax used in the [reference](/Reference) to concisely describe commands.
|
||||
|
||||
If there's a concept that you don't understand after reading this and the [reference](/Reference), please [open an issue](https://github.com/sbrl/Minetest-WorldEditAdditions/issues/new) with a detailed explanation of what it is that you're finding difficult to understand.
|
23
.docs/_data/contributors.js
Normal file
|
@ -0,0 +1,23 @@
|
|||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const htmlentities = require("html-entities");
|
||||
|
||||
function read_contributors() {
|
||||
return fs.readFileSync(path.resolve(__dirname, "../../CONTRIBUTORS.tsv"), "utf-8")
|
||||
.split("\n")
|
||||
.slice(1)
|
||||
.filter(line => line.length > 0)
|
||||
.map(line => line.split(/\s+/))
|
||||
.map(items => { return {
|
||||
handle: htmlentities.encode(items[0]),
|
||||
name: htmlentities.encode(items[1]),
|
||||
profile_url: `https://github.com/${encodeURIComponent(items[0])}`,
|
||||
avatar_url: `https://avatars.githubusercontent.com/${encodeURIComponent(items[0])}`
|
||||
} });
|
||||
}
|
||||
|
||||
const contributors = read_contributors();
|
||||
|
||||
console.log(`CONTRIBUTORS`, contributors);
|
||||
|
||||
module.exports = contributors;
|
7
.docs/_includes/content-generic.njk
Normal file
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
layout: theme.njk
|
||||
---
|
||||
|
||||
<main class="panel-generic">
|
||||
{{ content | safe }}
|
||||
</main>
|
63
.docs/_includes/theme.njk
Normal file
|
@ -0,0 +1,63 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset='utf-8' />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>{{ title }} • WorldEditAdditions</title>
|
||||
|
||||
<link rel="stylesheet" href="/theme.css" />
|
||||
|
||||
<link rel="icon" href="{% image_urlpass '../worldeditadditions-64.png' %}" type="image/png" sizes="64x64" />
|
||||
<link rel="icon" href="{% image_urlpass '../worldeditadditions.png' %}" type="image/png" sizes="540x540" />
|
||||
|
||||
<meta name="theme-color" content="#61b4f4" />
|
||||
|
||||
<!-- OpenGraph -->
|
||||
<meta property="og:title" content="WorldEditAdditions" />
|
||||
<meta property="og:type" content="website" />
|
||||
<!-- We wanted pepperminty.wiki, but it's too expensive :-( -->
|
||||
<meta property="og:url" content="https://worldeditadditions.mooncarrot.space/" />
|
||||
<meta property="og:image" content="https://worldeditadditions.mooncarrot.space{% image_url 'images/banner-main.jpeg' %}" />
|
||||
<meta property="og:description" content="Extra tools and commands to extend WorldEdit for Minetest. If you can dream of it, it probably belongs here!" />
|
||||
|
||||
<!-- Twitter Cards -->
|
||||
<meta property="twitter:card" content="summary" />
|
||||
<meta property="twitter:site" content="@SBRLabs" />
|
||||
<meta property="twitter:title" content="WorldEditAdditions" />
|
||||
<meta property="twitter:description" content="Extra tools and commands to extend WorldEdit for Minetest. If you can dream of it, it probably belongs here!" />
|
||||
<meta property="twitter:image" content="https://worldeditadditions.mooncarrot.space{% image_urlpass '../worldeditadditions.png' %}" />
|
||||
</head>
|
||||
<body>
|
||||
<nav class="shadow-bottom">
|
||||
<h1><a href="/" class="invisilink">
|
||||
<img src="{% image_urlpass '../worldeditadditions.png' %}" alt="" class="icon logo" />
|
||||
WorldEditAdditions
|
||||
</a></h1>
|
||||
<ul>
|
||||
{% for navitem in collections.navigable %}
|
||||
<li {% if page.url == navitem.url %}aria-current="page"{% endif %}>
|
||||
<a href="{{ navitem.url }}" class="nav">{{ navitem.data.title }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
<li><a href="https://github.com/sbrl/Minetest-WorldEditAdditions/" class="nav image"><img src="{% image_urlpass 'images/github.svg' %}" alt="GitHub" title="GitHub" /></a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
{{ content | safe }}
|
||||
|
||||
<footer class="shadow-top">
|
||||
<p>WorldEditAdditions is built with ❤️ by these awesome people:</p>
|
||||
<ul class="contributor-list">
|
||||
{% for contributor in contributors %}
|
||||
<li><a href="{{ contributor.profile_url }}">
|
||||
<img class="icon large" src="{{ contributor.avatar_url | fetch_file }}" alt="{{ contributor.name }}" />
|
||||
<span>{{ contributor.name }}</span>
|
||||
</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
<p>Tech: <a href="https://www.11ty.dev/">Eleventy</a> (this website), <a href="https://www.heropatterns.com/">Hero Patterns</a> (background patterns), <a href="https://github.com/shssoichiro/oxipng">Oxipng</a> (PNG image compression), <a href="https://www.minetest.net/">Minetest</a> (of course)</p>
|
||||
<p>Licensed under the <a href="https://www.mozilla.org/en-US/MPL/2.0/">Mozilla Public Licence 2.0</a> (<a href="https://tldrlegal.com/license/mozilla-public-license-2.0-(mpl-2)">tldr</a>)</p>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
13
.docs/css.njk
Normal file
|
@ -0,0 +1,13 @@
|
|||
---
|
||||
permalink: theme.css
|
||||
---
|
||||
|
||||
{% include "css/patterns.css" %}
|
||||
{% include "css/theme.css" %}
|
||||
{% include "css/gallerybox.css" %}
|
||||
{% include "css/smallscreens.css" %}
|
||||
{% include "css/prism-custom.css" %}
|
||||
|
||||
{# {% fetch "https://unpkg.com/prismjs/themes/prism-okaidia.css" %} #}
|
||||
{# {% fetch "https://raw.githubusercontent.com/PrismJS/prism-themes/master/themes/prism-shades-of-purple.css" %} #}
|
||||
{# {% fetch "https://raw.githubusercontent.com/PrismJS/prism-themes/master/themes/prism-material-light.css" %} #}
|
139
.docs/css/gallerybox.css
Normal file
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
██████ █████ ██ ██ ███████ ██████ ██ ██ ██████ ██████ ██ ██
|
||||
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
|
||||
██ ███ ███████ ██ ██ █████ ██████ ████ ██████ ██ ██ ███
|
||||
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
|
||||
██████ ██ ██ ███████ ███████ ███████ ██ ██ ██ ██████ ██████ ██ ██
|
||||
|
||||
A pure css gallery, made with a bunch of wonderful hacks! Will be upgraded to
|
||||
be (slightly) less hacky once :target-within lands in browsers.
|
||||
|
||||
Exported to codepen: https://codepen.io/sbrl/details/YzZJYxg
|
||||
*/
|
||||
|
||||
:root {
|
||||
--gallerybox-bg: hsla(0, 0%, 95%, 0.75);
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--gallerybox-bg: hsla(0, 0%, 30%, 0.75);
|
||||
}
|
||||
}
|
||||
|
||||
@media (orientation: landscape) {
|
||||
.gallerybox-gallery {
|
||||
max-width: 95vw;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.gallerybox {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
/*
|
||||
The <picture /> element causes a small amount of extra padding at the
|
||||
bottom of the element, so we use this to balance out the look at the top
|
||||
ideally we'd shift the <picture> out of the way, but we can't without also
|
||||
shifting the <img /> inside
|
||||
*/
|
||||
padding-top: 0.2em;
|
||||
}
|
||||
|
||||
.gallerybox-gallery {
|
||||
--gallerybox-nextprev-padding: 5vw;
|
||||
--gallerybox-nextprev-move: 0.2em;
|
||||
--gallerybox-nextprev-hover: 0.1em;
|
||||
|
||||
max-width: 80vmax;
|
||||
|
||||
display: grid;
|
||||
grid-template-columns: auto;
|
||||
grid-template-rows: auto;
|
||||
grid-template-areas: "main";
|
||||
}
|
||||
|
||||
/* .gallerybox picture {
|
||||
position: relative;
|
||||
top: -1em;
|
||||
}
|
||||
.gallerybox picture > img {
|
||||
position: relative;
|
||||
top: 1em;
|
||||
} */
|
||||
|
||||
.gallerybox-item {
|
||||
grid-area: main;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.gallerybox-item > figcaption {
|
||||
background: var(--gallerybox-bg);
|
||||
position: absolute;
|
||||
bottom: 0.25em; left: 0; right: 0;
|
||||
padding: 0.75em 1em;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.gallerybox-gallery > .gallerybox-item:target {
|
||||
display: block;
|
||||
z-index: 100;
|
||||
}
|
||||
/* .gallerybox-gallery > .gallerybox-item:not(:target) {
|
||||
display: none;
|
||||
z-index: 2;
|
||||
}
|
||||
.gallerybox-item:not(:target) ~ .gallerybox-item:last-child {
|
||||
display: block;
|
||||
z-index: 2;
|
||||
} */
|
||||
|
||||
/*
|
||||
.gallerybox-gallery:target-within > .gallerybox-item:target {
|
||||
display: block;
|
||||
}
|
||||
.gallerybox-gallery:target-within > .gallerybox-item:not(:target) {
|
||||
display: none;
|
||||
} */
|
||||
|
||||
|
||||
.gallerybox-item {
|
||||
position: relative;
|
||||
}
|
||||
.gallerybox-item img {
|
||||
max-width: 100%;
|
||||
}
|
||||
:where(.gallerybox-prev, .gallerybox-next) {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
position: absolute; top: 0;
|
||||
vertical-align: middle;
|
||||
font-weight: bold;
|
||||
font-size: 4em;
|
||||
color: hsla(0, 0%, 100%, 0.8) !important;
|
||||
text-decoration: none;
|
||||
transform: none;
|
||||
transition: transform 0.25s;
|
||||
}
|
||||
.gallerybox-item > .gallerybox-prev {
|
||||
padding-left: var(--gallerybox-nextprev-padding);
|
||||
left: 0;
|
||||
}
|
||||
.gallerybox-item > .gallerybox-next {
|
||||
padding-right: var(--gallerybox-nextprev-padding);
|
||||
right: 0;
|
||||
}
|
||||
|
||||
|
||||
:where(.gallerybox-prev, .gallerybox-next):hover {
|
||||
color: hsla(0, 0%, 100%, 1) !important;
|
||||
}
|
||||
:is(.gallerybox-prev, .gallerybox-next):active {
|
||||
color: hsla(0, 0%, 100%, 1) !important;
|
||||
}
|
||||
.gallerybox-next:hover { transform: translateX(calc(var(--gallerybox-nextprev-hover) * -1)); }
|
||||
.gallerybox-prev:hover { transform: translateX(var(--gallerybox-nextprev-hover)); }
|
||||
|
||||
.gallerybox-prev:active { transform: translateX(calc(var(--gallerybox-nextprev-move) * -1)); }
|
||||
.gallerybox-next:active { transform: translateX(var(--gallerybox-nextprev-move)); }
|
6
.docs/css/patterns.css
Normal file
|
@ -0,0 +1,6 @@
|
|||
:root {
|
||||
/* Ref https://www.heropatterns.com/ */
|
||||
--pattern-bricks: url("data:image/svg+xml,%3Csvg width='42' height='44' viewBox='0 0 42 44' xmlns='http://www.w3.org/2000/svg'%3E%3Cg id='Page-1' fill='none' fill-rule='evenodd'%3E%3Cg id='brick-wall' fill='%236ca8c7' fill-opacity='0.14'%3E%3Cpath d='M0 0h42v44H0V0zm1 1h40v20H1V1zM0 23h20v20H0V23zm22 0h20v20H22V23z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
|
||||
--pattern-hex: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='28' height='49' viewBox='0 0 28 49'%3E%3Cg fill-rule='evenodd'%3E%3Cg id='hexagons' fill='%236ca8c7' fill-opacity='0.1' fill-rule='nonzero'%3E%3Cpath d='M13.99 9.25l13 7.5v15l-13 7.5L1 31.75v-15l12.99-7.5zM3 17.9v12.7l10.99 6.34 11-6.35V17.9l-11-6.34L3 17.9zM0 15l12.98-7.5V0h-2v6.35L0 12.69v2.3zm0 18.5L12.98 41v8h-2v-6.85L0 35.81v-2.3zM15 0v7.5L27.99 15H28v-2.31h-.01L17 6.35V0h-2zm0 49v-8l12.99-7.5H28v2.31h-.01L17 42.15V49h-2z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
|
||||
--pattern-jigsaw-green: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='192' height='192' viewBox='0 0 192 192'%3E%3Cpath fill='%23b7e3ad' fill-opacity='0.4' d='M192 15v2a11 11 0 0 0-11 11c0 1.94 1.16 4.75 2.53 6.11l2.36 2.36a6.93 6.93 0 0 1 1.22 7.56l-.43.84a8.08 8.08 0 0 1-6.66 4.13H145v35.02a6.1 6.1 0 0 0 3.03 4.87l.84.43c1.58.79 4 .4 5.24-.85l2.36-2.36a12.04 12.04 0 0 1 7.51-3.11 13 13 0 1 1 .02 26 12 12 0 0 1-7.53-3.11l-2.36-2.36a4.93 4.93 0 0 0-5.24-.85l-.84.43a6.1 6.1 0 0 0-3.03 4.87V143h35.02a8.08 8.08 0 0 1 6.66 4.13l.43.84a6.91 6.91 0 0 1-1.22 7.56l-2.36 2.36A10.06 10.06 0 0 0 181 164a11 11 0 0 0 11 11v2a13 13 0 0 1-13-13 12 12 0 0 1 3.11-7.53l2.36-2.36a4.93 4.93 0 0 0 .85-5.24l-.43-.84a6.1 6.1 0 0 0-4.87-3.03H145v35.02a8.08 8.08 0 0 1-4.13 6.66l-.84.43a6.91 6.91 0 0 1-7.56-1.22l-2.36-2.36A10.06 10.06 0 0 0 124 181a11 11 0 0 0-11 11h-2a13 13 0 0 1 13-13c2.47 0 5.79 1.37 7.53 3.11l2.36 2.36a4.94 4.94 0 0 0 5.24.85l.84-.43a6.1 6.1 0 0 0 3.03-4.87V145h-35.02a8.08 8.08 0 0 1-6.66-4.13l-.43-.84a6.91 6.91 0 0 1 1.22-7.56l2.36-2.36A10.06 10.06 0 0 0 107 124a11 11 0 0 0-22 0c0 1.94 1.16 4.75 2.53 6.11l2.36 2.36a6.93 6.93 0 0 1 1.22 7.56l-.43.84a8.08 8.08 0 0 1-6.66 4.13H49v35.02a6.1 6.1 0 0 0 3.03 4.87l.84.43c1.58.79 4 .4 5.24-.85l2.36-2.36a12.04 12.04 0 0 1 7.51-3.11A13 13 0 0 1 81 192h-2a11 11 0 0 0-11-11c-1.94 0-4.75 1.16-6.11 2.53l-2.36 2.36a6.93 6.93 0 0 1-7.56 1.22l-.84-.43a8.08 8.08 0 0 1-4.13-6.66V145H11.98a6.1 6.1 0 0 0-4.87 3.03l-.43.84c-.79 1.58-.4 4 .85 5.24l2.36 2.36a12.04 12.04 0 0 1 3.11 7.51A13 13 0 0 1 0 177v-2a11 11 0 0 0 11-11c0-1.94-1.16-4.75-2.53-6.11l-2.36-2.36a6.93 6.93 0 0 1-1.22-7.56l.43-.84a8.08 8.08 0 0 1 6.66-4.13H47v-35.02a6.1 6.1 0 0 0-3.03-4.87l-.84-.43c-1.59-.8-4-.4-5.24.85l-2.36 2.36A12 12 0 0 1 28 109a13 13 0 1 1 0-26c2.47 0 5.79 1.37 7.53 3.11l2.36 2.36a4.94 4.94 0 0 0 5.24.85l.84-.43A6.1 6.1 0 0 0 47 84.02V49H11.98a8.08 8.08 0 0 1-6.66-4.13l-.43-.84a6.91 6.91 0 0 1 1.22-7.56l2.36-2.36A10.06 10.06 0 0 0 11 28 11 11 0 0 0 0 17v-2a13 13 0 0 1 13 13c0 2.47-1.37 5.79-3.11 7.53l-2.36 2.36a4.94 4.94 0 0 0-.85 5.24l.43.84A6.1 6.1 0 0 0 11.98 47H47V11.98a8.08 8.08 0 0 1 4.13-6.66l.84-.43a6.91 6.91 0 0 1 7.56 1.22l2.36 2.36A10.06 10.06 0 0 0 68 11 11 11 0 0 0 79 0h2a13 13 0 0 1-13 13 12 12 0 0 1-7.53-3.11l-2.36-2.36a4.93 4.93 0 0 0-5.24-.85l-.84.43A6.1 6.1 0 0 0 49 11.98V47h35.02a8.08 8.08 0 0 1 6.66 4.13l.43.84a6.91 6.91 0 0 1-1.22 7.56l-2.36 2.36A10.06 10.06 0 0 0 85 68a11 11 0 0 0 22 0c0-1.94-1.16-4.75-2.53-6.11l-2.36-2.36a6.93 6.93 0 0 1-1.22-7.56l.43-.84a8.08 8.08 0 0 1 6.66-4.13H143V11.98a6.1 6.1 0 0 0-3.03-4.87l-.84-.43c-1.59-.8-4-.4-5.24.85l-2.36 2.36A12 12 0 0 1 124 13a13 13 0 0 1-13-13h2a11 11 0 0 0 11 11c1.94 0 4.75-1.16 6.11-2.53l2.36-2.36a6.93 6.93 0 0 1 7.56-1.22l.84.43a8.08 8.08 0 0 1 4.13 6.66V47h35.02a6.1 6.1 0 0 0 4.87-3.03l.43-.84c.8-1.59.4-4-.85-5.24l-2.36-2.36A12 12 0 0 1 179 28a13 13 0 0 1 13-13zM84.02 143a6.1 6.1 0 0 0 4.87-3.03l.43-.84c.8-1.59.4-4-.85-5.24l-2.36-2.36A12 12 0 0 1 83 124a13 13 0 1 1 26 0c0 2.47-1.37 5.79-3.11 7.53l-2.36 2.36a4.94 4.94 0 0 0-.85 5.24l.43.84a6.1 6.1 0 0 0 4.87 3.03H143v-35.02a8.08 8.08 0 0 1 4.13-6.66l.84-.43a6.91 6.91 0 0 1 7.56 1.22l2.36 2.36A10.06 10.06 0 0 0 164 107a11 11 0 0 0 0-22c-1.94 0-4.75 1.16-6.11 2.53l-2.36 2.36a6.93 6.93 0 0 1-7.56 1.22l-.84-.43a8.08 8.08 0 0 1-4.13-6.66V49h-35.02a6.1 6.1 0 0 0-4.87 3.03l-.43.84c-.79 1.58-.4 4 .85 5.24l2.36 2.36a12.04 12.04 0 0 1 3.11 7.51A13 13 0 1 1 83 68a12 12 0 0 1 3.11-7.53l2.36-2.36a4.93 4.93 0 0 0 .85-5.24l-.43-.84A6.1 6.1 0 0 0 84.02 49H49v35.02a8.08 8.08 0 0 1-4.13 6.66l-.84.43a6.91 6.91 0 0 1-7.56-1.22l-2.36-2.36A10.06 10.06 0 0 0 28 85a11 11 0 0 0 0 22c1.94 0 4.75-1.16 6.11-2.53l2.36-2.36a6.93 6.93 0 0 1 7.56-1.22l.84.43a8.08 8.08 0 0 1 4.13 6.66V143h35.02z'%3E%3C/path%3E%3C/svg%3E");
|
||||
}
|
159
.docs/css/prism-custom.css
Normal file
|
@ -0,0 +1,159 @@
|
|||
/* Ref https://github.com/jGleitz/markdown-it-prism/issues/1; we don't get have
|
||||
line numbers because we don't have 1 span per line :-/*/
|
||||
|
||||
pre[class*='language-'] {
|
||||
counter-reset: line-numbers;
|
||||
border: 0;
|
||||
}
|
||||
span[class*='language-'] {
|
||||
counter-increment: line-numbers;
|
||||
}
|
||||
span[class*='language-']::before {
|
||||
content: counter(line-numbers);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* PrismJS 1.16.0
|
||||
https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript&plugins=line-highlight+line-numbers+autolinker+data-uri-highlight+toolbar+previewers+autoloader+command-line+normalize-whitespace+show-language */
|
||||
/**
|
||||
* prism.js default theme for JavaScript, CSS and HTML
|
||||
* Based on dabblet (http://dabblet.com)
|
||||
* @author Lea Verou
|
||||
*/
|
||||
|
||||
code[class*="language-"],
|
||||
pre[class*="language-"] {
|
||||
color: black;
|
||||
background: none;
|
||||
text-shadow: 0 1px white;
|
||||
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
|
||||
font-size: 1em;
|
||||
text-align: left;
|
||||
white-space: pre;
|
||||
word-spacing: normal;
|
||||
word-break: normal;
|
||||
word-wrap: normal;
|
||||
line-height: 1.5;
|
||||
|
||||
-moz-tab-size: 4;
|
||||
-o-tab-size: 4;
|
||||
tab-size: 4;
|
||||
|
||||
-webkit-hyphens: none;
|
||||
-moz-hyphens: none;
|
||||
-ms-hyphens: none;
|
||||
hyphens: none;
|
||||
}
|
||||
|
||||
pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection,
|
||||
code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection {
|
||||
text-shadow: none;
|
||||
background: #b3d4fc;
|
||||
}
|
||||
|
||||
pre[class*="language-"]::selection, pre[class*="language-"] ::selection,
|
||||
code[class*="language-"]::selection, code[class*="language-"] ::selection {
|
||||
text-shadow: none;
|
||||
background: #b3d4fc;
|
||||
}
|
||||
|
||||
@media print {
|
||||
code[class*="language-"],
|
||||
pre[class*="language-"] {
|
||||
text-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Code blocks */
|
||||
pre[class*="language-"] {
|
||||
padding: 1em;
|
||||
margin: .5em 0;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
:not(pre) > code[class*="language-"],
|
||||
pre[class*="language-"] {
|
||||
background: #f5f2f0;
|
||||
}
|
||||
|
||||
/* Inline code */
|
||||
:not(pre) > code[class*="language-"] {
|
||||
padding: .1em;
|
||||
border-radius: .3em;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.token.comment,
|
||||
.token.prolog,
|
||||
.token.doctype,
|
||||
.token.cdata {
|
||||
color: slategray;
|
||||
}
|
||||
|
||||
.token.punctuation {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.namespace {
|
||||
opacity: .7;
|
||||
}
|
||||
|
||||
.token.property,
|
||||
.token.tag,
|
||||
.token.boolean,
|
||||
.token.number,
|
||||
.token.constant,
|
||||
.token.symbol,
|
||||
.token.deleted {
|
||||
color: #905;
|
||||
}
|
||||
|
||||
.token.selector,
|
||||
.token.attr-name,
|
||||
.token.string,
|
||||
.token.char,
|
||||
.token.builtin,
|
||||
.token.inserted {
|
||||
color: #690;
|
||||
}
|
||||
|
||||
.token.operator,
|
||||
.token.entity,
|
||||
.token.url,
|
||||
.language-css .token.string,
|
||||
.style .token.string {
|
||||
color: #9a6e3a;
|
||||
background: hsla(0, 0%, 100%, .5);
|
||||
}
|
||||
|
||||
.token.atrule,
|
||||
.token.attr-value,
|
||||
.token.keyword {
|
||||
color: #07a;
|
||||
}
|
||||
|
||||
.token.function,
|
||||
.token.class-name {
|
||||
/* color: #DD4A68; */
|
||||
color: hsl(347, 87%, 44%);
|
||||
}
|
||||
|
||||
.token.regex,
|
||||
.token.important,
|
||||
.token.variable {
|
||||
color: #e90;
|
||||
}
|
||||
|
||||
.token.important,
|
||||
.token.bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
.token.italic {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.token.entity {
|
||||
cursor: help;
|
||||
}
|
34
.docs/css/smallscreens.css
Normal file
|
@ -0,0 +1,34 @@
|
|||
@media (max-width: 1200px) {
|
||||
nav > ul a {
|
||||
padding: 1.45em 0.5em;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@media (max-width: 930px) {
|
||||
nav {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
nav > h1 {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.bigbox {
|
||||
padding: 0 5vmin;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
nav > ul {
|
||||
padding-top: 0.5em;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.bigbox h1 {
|
||||
font-size: 1.5em;
|
||||
}
|
||||
}
|
473
.docs/css/theme.css
Normal file
|
@ -0,0 +1,473 @@
|
|||
/* Base CSS */
|
||||
|
||||
/*
|
||||
* This CSS file contains (for me) logical style defaults that are easy to read.
|
||||
*
|
||||
* This file is quite often used as a starting point for other projects.
|
||||
*
|
||||
* Todo:
|
||||
* <button>
|
||||
* <inputs>
|
||||
* <progress>
|
||||
* <meter>
|
||||
*/
|
||||
|
||||
:root {
|
||||
--bg-main: hsl(206, 87%, 67%);
|
||||
/* --bg-bright: #57b43f; */
|
||||
--bg-bright: #7ac767;
|
||||
--bg-alt: #3F57B4;
|
||||
--bg-transcluscent-slight: rgba(255, 255, 255, 0.1);
|
||||
--bg-transcluscent: rgba(255, 255, 255, 0.85);
|
||||
--bg-transcluscent-alt: hsla(226, 59%, 38%, 0.8);
|
||||
--bg-transcluscent-alt-vdark: hsla(226, 59%, 8%, 0.8);
|
||||
--bg-transcluscent-alt-slight: hsla(196, 91%, 62%, 0.23);
|
||||
|
||||
/* --text-main: #3F57B4; */
|
||||
--text-main: hsl(227, 70%, 35%);
|
||||
--text-bright: #efefef;
|
||||
--text-alt: #38871e;
|
||||
|
||||
--shadow: hsla(0, 0%, 25%, 0.25);
|
||||
--shadow-dark: hsla(0, 0%, 25%, 0.5);
|
||||
|
||||
--highlight: hsl(353, 100%, 36%);
|
||||
|
||||
--bg-image: url('{% image_urlpass "images/clouds.png" %}');
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--bg-main: #020B18;
|
||||
--bg-bright: hsl(108, 46%, 34%);
|
||||
--bg-alt: hsl(228, 68%, 68%);
|
||||
|
||||
--bg-transcluscent: hsla(224, 20%, 16%, 0.85);
|
||||
--bg-transcluscent-alt: hsla(226, 79%, 70%, 0.8);
|
||||
|
||||
--text-main: hsl(227, 80%, 95%);
|
||||
|
||||
--bg-image: url('{% image_urlpass "images/clouds-night.png" %}');
|
||||
}
|
||||
|
||||
a { color: #7c7cff; }
|
||||
a:active { color: #ee0000; }
|
||||
a:not(.nav):not(.bigbutton):visited { color: hsl(296, 84%, 75%); }
|
||||
}
|
||||
|
||||
/* rem is relative to the html element, and em is relative to the current element. */
|
||||
html { font-size: 100%; scroll-behavior: smooth; }
|
||||
|
||||
body
|
||||
{
|
||||
margin: 0;
|
||||
font-family: sans-serif; /* Serif is awful :( */
|
||||
|
||||
background: var(--bg-image) center / cover fixed,
|
||||
var(--bg-main); /* Don't forget to update the @page one too for paged media */
|
||||
color: var(--text-main);
|
||||
}
|
||||
|
||||
title { string-set: page-title content(text); }
|
||||
|
||||
/* Special tweaks for paged media (e.g. PDFs) */
|
||||
@page {
|
||||
font-family: sans-serif;
|
||||
background: var(--bg-main); /* Set the background colour to cover the whole page */
|
||||
|
||||
@top-right {
|
||||
content: "By Starbeamrainbowlabs";
|
||||
opacity: 0.6;
|
||||
}
|
||||
@bottom-right {
|
||||
content: "Page " counter(page) " of " counter(pages);
|
||||
opacity: 0.6;
|
||||
}
|
||||
}
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
text-align: center;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.linked-section-heading {
|
||||
display: flex;
|
||||
}
|
||||
.linked-section-heading > a.section-link {
|
||||
opacity: 0.75;
|
||||
text-decoration: none;
|
||||
transition: 0.25s opacity;
|
||||
}
|
||||
.linked-section-heading > a.section-link:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
.linked-section-heading > span.title {
|
||||
flex: 1;
|
||||
word-wrap: anywhere;
|
||||
}
|
||||
.linked-section-heading > span.category {
|
||||
font-size: 0.75em;
|
||||
border-radius: 1em;
|
||||
background: var(--cat-colour);
|
||||
padding: 0 0.5em;
|
||||
line-height: 1.5;
|
||||
align-self: flex-start;
|
||||
}
|
||||
h3 {
|
||||
margin-top: 2em;
|
||||
padding-bottom: 0.2em;
|
||||
border-bottom: 0.1em solid var(--cat-colour);
|
||||
}
|
||||
h3, h3 > code {
|
||||
font-size: 1.1em;
|
||||
text-align: left;
|
||||
}
|
||||
h3 > code {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
nav {
|
||||
background: var(--bg-bright);
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
font-size: 1.1em;
|
||||
margin: 0;
|
||||
}
|
||||
nav h1 {
|
||||
background: var(--text-bright);
|
||||
margin: 0;
|
||||
padding: 0.2em 0.5em 0.2em 0.2em;
|
||||
font-size: 1.2em;
|
||||
color: var(--bg-alt);
|
||||
}
|
||||
nav ul {
|
||||
flex: 1;
|
||||
list-style-type: none;
|
||||
margin: 0; padding: 0;
|
||||
display: flex;
|
||||
justify-content: space-evenly;
|
||||
align-items: center;
|
||||
}
|
||||
nav > ul a {
|
||||
background: var(--bg-transcluscent-slight);
|
||||
display: inline-block;
|
||||
padding: 1.45em 2em;
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
color: var(--text-main);
|
||||
}
|
||||
nav li[aria-current=page] a {
|
||||
color: var(--bg-bright);
|
||||
background: var(--text-main);
|
||||
}
|
||||
|
||||
nav a.image {
|
||||
padding: 0.75em 1em 0.5em 1em;
|
||||
}
|
||||
nav img { max-height: 2em; }
|
||||
|
||||
|
||||
/* A small tweak to things more responsive */
|
||||
iframe, object, embed, img, table
|
||||
{
|
||||
max-width: 100%;
|
||||
}
|
||||
picture img { height: initial; }
|
||||
|
||||
/* Turn the user's cursor into a hand when over things they can click */
|
||||
button, summary
|
||||
{
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
th, td
|
||||
{
|
||||
margin: 4px 6px;
|
||||
padding: 4px 6px;
|
||||
}
|
||||
|
||||
a { font-weight: bold; }
|
||||
/* a:not(.nav) { color: hsl(208, 67%, 40%); }
|
||||
a:not(.nav):hover { color: hsl(214, 67%, 50%); }
|
||||
a:not(.nav):active, a:focus { color: hsl(214, 87%, 60%); } */
|
||||
a:not(.nav):not(.bigbutton):visited { color: hsl(240, 77%, 60%); }
|
||||
pre {
|
||||
page-break-inside: avoid;
|
||||
break-inside: avoid;
|
||||
padding: 0.6em;
|
||||
border: 0.2em solid var(--bg-transcluscent-alt);
|
||||
border-radius: 0.25em;
|
||||
background: var(--bg-transcluscent-alt);
|
||||
box-shadow: inset 0 0 0.5em 0.1em var(--shadow-dark);
|
||||
line-height: 1.75em;
|
||||
color: var(--text-bright);
|
||||
}
|
||||
pre, code {
|
||||
text-align: left;
|
||||
font-size: 1rem;
|
||||
font-family: "Source Code Pro", "Ubuntu Mono", monospace;
|
||||
white-space: pre-wrap;
|
||||
-moz-tab-size: 4;
|
||||
tab-size: 4;
|
||||
}
|
||||
pre > code { background: transparent; padding: 0; }
|
||||
code {
|
||||
background: var(--bg-transcluscent-alt-slight);
|
||||
border-radius: 0.25em;
|
||||
padding: 0.15em;
|
||||
}
|
||||
/* pre.language-weacmd {
|
||||
background: var(--bg-transcluscent-alt-vdark);
|
||||
} */
|
||||
|
||||
label {
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
padding: 0.25em 0.45em;
|
||||
}
|
||||
|
||||
|
||||
/* todo add the rest of the textbox like inputs here */
|
||||
input[type=text], input[type=number], textarea
|
||||
{
|
||||
margin: 3px 5px;
|
||||
padding: 5px 8px;
|
||||
|
||||
background: var(--bg-bright);
|
||||
border: 0;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.form-item {
|
||||
display: flex;
|
||||
margin: 0.5em 0;
|
||||
}
|
||||
.form-item.checkbox:not(.centre) > label { flex: 1; }
|
||||
.form-item:not(.checkbox):not(.centre) > input { flex: 1; }
|
||||
.form-item.centre { justify-content: center; }
|
||||
.bigsearch {
|
||||
flex-direction: row;
|
||||
}
|
||||
.bigsearch > input[type=search] {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
footer {
|
||||
margin: 3em 0 0 0;
|
||||
padding: 1em;
|
||||
text-align: center;
|
||||
background: var(--pattern-jigsaw-green),
|
||||
var(--bg-bright);
|
||||
/* color: var(--text-bright); */
|
||||
}
|
||||
|
||||
.text-left { text-align: left; }
|
||||
.text-centre { text-align: center; }
|
||||
.text-right { text-align: right; }
|
||||
|
||||
.invisilink { text-decoration: none; color: inherit; }
|
||||
.invisilist { list-style-type: none; margin: 5px; padding: 5px; }
|
||||
|
||||
.icon { vertical-align: middle; }
|
||||
.icon.tiny { max-width: 1em; max-height: 1em; }
|
||||
.icon.small { max-width: 1.25em; max-height: 1.25em; }
|
||||
.icon.medium { max-width: 2em; max-height: 2em; }
|
||||
.icon.large { max-width: 5em; max-height: 5em; }
|
||||
.icon.logo {
|
||||
max-width: 3em;
|
||||
max-height: 3em;
|
||||
}
|
||||
.icon.logo-large {
|
||||
max-width: 8em;
|
||||
max-height: 8em;
|
||||
}
|
||||
|
||||
.shadow-top { box-shadow: 0 -0.25em 0.5em var(--shadow); }
|
||||
.shadow-bottom { box-shadow: 0 0.25em 0.5em var(--shadow); }
|
||||
.shadow-vertical{ box-shadow: 0 0 0.5em 0.25em var(--shadow); }
|
||||
.shadow-text { text-shadow: 0.15em 0.15em 0.15em var(--shadow); }
|
||||
|
||||
.hidden { display: none; }
|
||||
|
||||
.bigbox {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center; justify-content: center;
|
||||
text-align: center; /* If any text wraps in a <p>, then this makes sure it's still centred */
|
||||
background: content-box linear-gradient(var(--bg-transcluscent), var(--bg-transcluscent)),
|
||||
var(--bg) center / cover;
|
||||
|
||||
height: max(30em, 80vh);
|
||||
padding: 0 5em 0 5em;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.bigbox h1 {
|
||||
margin: 0;
|
||||
font-size: 3em;
|
||||
/* color: var(--text-alt); */
|
||||
color: var(--bg-alt);
|
||||
}
|
||||
|
||||
.features-large {
|
||||
margin: 3em 0;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
.features-large > :where(figure, .features-item) {
|
||||
background: var(--bg-transcluscent);
|
||||
background-image: var(--pattern-bricks);
|
||||
margin: 1em 0.1em;
|
||||
padding: 1em;
|
||||
max-width: 15em;
|
||||
box-shadow: 0.25em 0.25em 0.5em var(--shadow);
|
||||
}
|
||||
.features-item.wide {
|
||||
flex: 1;
|
||||
max-width: initial;
|
||||
margin: 0.5em 2em;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
/* .features-item.wide > :last-child {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
} */
|
||||
|
||||
.panel-generic {
|
||||
background: var(--bg-transcluscent);
|
||||
background-image: var(--pattern-bricks);
|
||||
margin: 2em;
|
||||
padding: 1em;
|
||||
box-shadow: 0.25em 0.25em 0.5em var(--shadow);
|
||||
}
|
||||
|
||||
.bigbutton-list {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 1em 0;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.bigbutton {
|
||||
display: inline-block;
|
||||
|
||||
margin: 0.25em 0;
|
||||
padding: 0.35em 0.45em;
|
||||
border: 0;
|
||||
border-radius: 0.25em;
|
||||
|
||||
background: var(--bg-alt);
|
||||
|
||||
color: var(--text-bright);
|
||||
font-size: 1.25em;
|
||||
text-decoration: none;
|
||||
text-align: center;
|
||||
|
||||
box-shadow: 0 0 0.5em var(--shadow);
|
||||
|
||||
cursor: pointer;
|
||||
transition: box-shadow 0.25s, transform 0.25s;
|
||||
}
|
||||
.bigbutton:hover {
|
||||
box-shadow: 0 0.25em 0.65em var(--shadow);
|
||||
transform: translateY(-0.25em);
|
||||
}
|
||||
.bigbutton:active {
|
||||
box-shadow: 0 0 0.25em var(--shadow);
|
||||
transform: translateY(0.1em);
|
||||
}
|
||||
.bigbutton.disabled {
|
||||
filter: saturate(25%);
|
||||
opacity: 0.75;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.gallerybox {
|
||||
background: var(--pattern-hex), var(--bg-transcluscent);
|
||||
}
|
||||
|
||||
.command-ordering-tabs {
|
||||
display: flex;
|
||||
gap: 1em;
|
||||
margin-bottom: 2em;
|
||||
}
|
||||
.command-ordering-tabs button {
|
||||
flex: 1;
|
||||
font-size: 1.1em;
|
||||
padding: 0.5em;
|
||||
}
|
||||
.command-ordering-tabs button.active { font-weight: bold; }
|
||||
|
||||
.command-list {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style-type: none;
|
||||
word-wrap: anywhere;
|
||||
}
|
||||
.command-list > li > a {
|
||||
text-decoration: none;
|
||||
}
|
||||
.command-list.coloured code { background: var(--cat-colour); }
|
||||
.command-list code {
|
||||
display: block;
|
||||
padding: 0.5em;
|
||||
box-sizing: border-box;
|
||||
margin: 0.5em 0;
|
||||
}
|
||||
|
||||
.filterable {
|
||||
border: 0.2em solid var(--cat-colour);
|
||||
}
|
||||
|
||||
|
||||
.contributor-list {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.contributor-list li {
|
||||
padding: 0.5em;
|
||||
}
|
||||
.contributor-list a {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
@keyframes move-diagonal {
|
||||
from {
|
||||
background-position: -2px -2px, -2px -2px, -1px -1px, -1px -1px;
|
||||
}
|
||||
to {
|
||||
background-position: -52px -52px, -52px -52px, -51px -51px, -51px -51px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#dropzone {
|
||||
border: 0.3em dashed #aaaaaa;
|
||||
transition: border 0.2s;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
#dropzone.dropzone-active {
|
||||
border: 0.3em dashed hsl(203, 79%, 55%);
|
||||
|
||||
/* Ref https://www.magicpattern.design/tools/css-backgrounds */
|
||||
background-image: linear-gradient(var(--bg-bright) 2px, transparent 2px), linear-gradient(90deg, var(--bg-bright) 2px, transparent 2px), linear-gradient(var(--bg-bright) 1px, transparent 1px), linear-gradient(90deg, var(--bg-bright) 1px, var(--bg-transcluscent) 1px);
|
||||
background-size: 50px 50px, 50px 50px, 10px 10px, 10px 10px;
|
||||
background-position: -2px -2px, -2px -2px, -1px -1px, -1px -1px;
|
||||
|
||||
animation: move-diagonal 5s linear infinite;
|
||||
}
|
||||
#brushimg-preview { flex: 1; }
|
40
.docs/grammars/axes.bnf
Normal file
|
@ -0,0 +1,40 @@
|
|||
{%
|
||||
# Lists of axes
|
||||
|
||||
In various commands such as `//copy+`, `//move+`, and others lists of axes are used. These are all underpinned by a single grammar and a single parser (located in `worldeditadditions/utils/parse/axes.lua`). While the parser itself requires pre-split tokens (see `split_shell` for that), the grammar which it parses is documented here.
|
||||
|
||||
Examples:
|
||||
|
||||
```
|
||||
front 3 left 10 y 77 x 30 back 99
|
||||
```
|
||||
|
||||
%}
|
||||
|
||||
<axes> ::= <axis_part> *
|
||||
|
||||
<axes_part> ::= <axis_name> <number>
|
||||
| <axis_name> <number> <reverse>
|
||||
|
||||
<reverse> ::= <number>
|
||||
| <reverse_name>
|
||||
|
||||
<reverse_name> ::= sym | symmetrical | mirror | mir | rev | reverse | true
|
||||
|
||||
|
||||
|
||||
<axis_name> ::= <axis_name_absolute>
|
||||
| <axis_name_relative>
|
||||
|
||||
<axis_name_absolute> ::= <axis_letters_absolute>
|
||||
| "-" <axis_letters_absolute>
|
||||
|
||||
<axis_name_relative> ::= front | back | left | right | up | down | "?"
|
||||
|
||||
<axis_letters_absolute> ::= x | y | z | h | v
|
||||
|
||||
|
||||
|
||||
<number> ::= <digit> *
|
||||
|
||||
<digit> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 0
|
BIN
.docs/images/banner-main.jpeg
Normal file
After Width: | Height: | Size: 887 KiB |
BIN
.docs/images/clouds-night.png
Normal file
After Width: | Height: | Size: 34 KiB |
BIN
.docs/images/clouds.png
Normal file
After Width: | Height: | Size: 25 KiB |
BIN
.docs/images/contentdb.png
Normal file
After Width: | Height: | Size: 6.3 KiB |
BIN
.docs/images/conv-layers.png
Normal file
After Width: | Height: | Size: 317 KiB |
BIN
.docs/images/forest.png
Normal file
After Width: | Height: | Size: 474 KiB |
BIN
.docs/images/gallery-a.jpeg
Normal file
After Width: | Height: | Size: 725 KiB |
BIN
.docs/images/gallery-b.jpeg
Normal file
After Width: | Height: | Size: 1.7 MiB |
BIN
.docs/images/gallery-c.jpeg
Normal file
After Width: | Height: | Size: 827 KiB |
BIN
.docs/images/gallery-d.jpeg
Normal file
After Width: | Height: | Size: 708 KiB |
BIN
.docs/images/gallery-e.jpeg
Normal file
After Width: | Height: | Size: 615 KiB |
BIN
.docs/images/gallery-f.jpeg
Normal file
After Width: | Height: | Size: 393 KiB |
6
.docs/images/github.svg
Normal file
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg width="256px" height="250px" viewBox="0 0 256 250" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid">
|
||||
<g>
|
||||
<path d="M128.00106,0 C57.3172926,0 0,57.3066942 0,128.00106 C0,184.555281 36.6761997,232.535542 87.534937,249.460899 C93.9320223,250.645779 96.280588,246.684165 96.280588,243.303333 C96.280588,240.251045 96.1618878,230.167899 96.106777,219.472176 C60.4967585,227.215235 52.9826207,204.369712 52.9826207,204.369712 C47.1599584,189.574598 38.770408,185.640538 38.770408,185.640538 C27.1568785,177.696113 39.6458206,177.859325 39.6458206,177.859325 C52.4993419,178.762293 59.267365,191.04987 59.267365,191.04987 C70.6837675,210.618423 89.2115753,204.961093 96.5158685,201.690482 C97.6647155,193.417512 100.981959,187.77078 104.642583,184.574357 C76.211799,181.33766 46.324819,170.362144 46.324819,121.315702 C46.324819,107.340889 51.3250588,95.9223682 59.5132437,86.9583937 C58.1842268,83.7344152 53.8029229,70.715562 60.7532354,53.0843636 C60.7532354,53.0843636 71.5019501,49.6441813 95.9626412,66.2049595 C106.172967,63.368876 117.123047,61.9465949 128.00106,61.8978432 C138.879073,61.9465949 149.837632,63.368876 160.067033,66.2049595 C184.49805,49.6441813 195.231926,53.0843636 195.231926,53.0843636 C202.199197,70.715562 197.815773,83.7344152 196.486756,86.9583937 C204.694018,95.9223682 209.660343,107.340889 209.660343,121.315702 C209.660343,170.478725 179.716133,181.303747 151.213281,184.472614 C155.80443,188.444828 159.895342,196.234518 159.895342,208.176593 C159.895342,225.303317 159.746968,239.087361 159.746968,243.303333 C159.746968,246.709601 162.05102,250.70089 168.53925,249.443941 C219.370432,232.499507 256,184.536204 256,128.00106 C256,57.3066942 198.691187,0 128.00106,0 Z M47.9405593,182.340212 C47.6586465,182.976105 46.6581745,183.166873 45.7467277,182.730227 C44.8183235,182.312656 44.2968914,181.445722 44.5978808,180.80771 C44.8734344,180.152739 45.876026,179.97045 46.8023103,180.409216 C47.7328342,180.826786 48.2627451,181.702199 47.9405593,182.340212 Z M54.2367892,187.958254 C53.6263318,188.524199 52.4329723,188.261363 51.6232682,187.366874 C50.7860088,186.474504 50.6291553,185.281144 51.2480912,184.70672 C51.8776254,184.140775 53.0349512,184.405731 53.8743302,185.298101 C54.7115892,186.201069 54.8748019,187.38595 54.2367892,187.958254 Z M58.5562413,195.146347 C57.7719732,195.691096 56.4895886,195.180261 55.6968417,194.042013 C54.9125733,192.903764 54.9125733,191.538713 55.713799,190.991845 C56.5086651,190.444977 57.7719732,190.936735 58.5753181,192.066505 C59.3574669,193.22383 59.3574669,194.58888 58.5562413,195.146347 Z M65.8613592,203.471174 C65.1597571,204.244846 63.6654083,204.03712 62.5716717,202.981538 C61.4524999,201.94927 61.1409122,200.484596 61.8446341,199.710926 C62.5547146,198.935137 64.0575422,199.15346 65.1597571,200.200564 C66.2704506,201.230712 66.6095936,202.705984 65.8613592,203.471174 Z M75.3025151,206.281542 C74.9930474,207.284134 73.553809,207.739857 72.1039724,207.313809 C70.6562556,206.875043 69.7087748,205.700761 70.0012857,204.687571 C70.302275,203.678621 71.7478721,203.20382 73.2083069,203.659543 C74.6539041,204.09619 75.6035048,205.261994 75.3025151,206.281542 Z M86.046947,207.473627 C86.0829806,208.529209 84.8535871,209.404622 83.3316829,209.4237 C81.8013,209.457614 80.563428,208.603398 80.5464708,207.564772 C80.5464708,206.498591 81.7483088,205.631657 83.2786917,205.606221 C84.8005962,205.576546 86.046947,206.424403 86.046947,207.473627 Z M96.6021471,207.069023 C96.7844366,208.099171 95.7267341,209.156872 94.215428,209.438785 C92.7295577,209.710099 91.3539086,209.074206 91.1652603,208.052538 C90.9808515,206.996955 92.0576306,205.939253 93.5413813,205.66582 C95.054807,205.402984 96.4092596,206.021919 96.6021471,207.069023 Z" fill="#161614"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.8 KiB |
BIN
.docs/images/maze2d-alt.png
Normal file
After Width: | Height: | Size: 341 KiB |
BIN
.docs/images/maze2d.png
Normal file
After Width: | Height: | Size: 434 KiB |
BIN
.docs/images/reference/spline.jpeg
Normal file
After Width: | Height: | Size: 181 KiB |
BIN
.docs/images/torus-bonemeal.png
Normal file
After Width: | Height: | Size: 354 KiB |
BIN
.docs/images/tutorial_pos1_2.jpeg
Normal file
After Width: | Height: | Size: 685 KiB |
112
.docs/img2brush/img2brush.js
Normal file
|
@ -0,0 +1,112 @@
|
|||
window.addEventListener("load", () => {
|
||||
let dropzone = document.querySelector("#dropzone");
|
||||
dropzone.addEventListener("dragenter", handle_drag_enter);
|
||||
dropzone.addEventListener("dragleave", handle_drag_leave);
|
||||
dropzone.addEventListener("dragover", handle_drag_over);
|
||||
dropzone.addEventListener("drop", handle_drop);
|
||||
|
||||
document.querySelector("#brushimg-tsv").addEventListener("click", select_output);
|
||||
let button_copy = document.querySelector("#brushimg-copy")
|
||||
button_copy.addEventListener("click", () => {
|
||||
select_output();
|
||||
button_copy.innerHTML = document.execCommand("copy") ? "Copied!" : "Failed to copy :-(";
|
||||
})
|
||||
});
|
||||
|
||||
function get_source_channel_offset() {
|
||||
const select = document.querySelector("#img2brush-channel");
|
||||
console.info(`get_source_channel_offset: channel is ${select.value}`)
|
||||
switch(select.value) {
|
||||
case "alpha":
|
||||
return 3;
|
||||
case "red":
|
||||
return 0;
|
||||
case "green":
|
||||
return 1;
|
||||
case "blue":
|
||||
return 2;
|
||||
default:
|
||||
throw new Error(`Error : Unknown channel name ${select.value}.`);
|
||||
}
|
||||
}
|
||||
|
||||
function select_output() {
|
||||
let output = document.querySelector("#brushimg-tsv");
|
||||
|
||||
let selection = window.getSelection();
|
||||
|
||||
if (selection.rangeCount > 0)
|
||||
selection.removeAllRanges();
|
||||
|
||||
let range = document.createRange();
|
||||
range.selectNode(output);
|
||||
selection.addRange(range);
|
||||
}
|
||||
|
||||
function handle_drag_enter(event) {
|
||||
event.target.classList.add("dropzone-active");
|
||||
}
|
||||
function handle_drag_leave(event) {
|
||||
event.target.classList.remove("dropzone-active");
|
||||
}
|
||||
|
||||
function handle_drag_over(event) {
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
function handle_drop(event) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
event.target.classList.remove("dropzone-active");
|
||||
|
||||
let image_file = null;
|
||||
|
||||
image_file = event.dataTransfer.files[0];
|
||||
|
||||
let reader = new FileReader();
|
||||
reader.addEventListener("load", function(_event) {
|
||||
let image = new Image();
|
||||
image.src = reader.result;
|
||||
image.addEventListener("load", () => handle_new_image(image));
|
||||
|
||||
|
||||
document.querySelector("#brushimg-preview").src = image.src;
|
||||
});
|
||||
reader.readAsDataURL(image_file);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function image2pixels(image) {
|
||||
let canvas = document.createElement("canvas"),
|
||||
ctx = canvas.getContext("2d");
|
||||
|
||||
canvas.width = image.width;
|
||||
canvas.height = image.height;
|
||||
|
||||
ctx.drawImage(image, 0, 0);
|
||||
|
||||
return ctx.getImageData(0, 0, image.width, image.height);
|
||||
}
|
||||
|
||||
function handle_new_image(image) {
|
||||
let tsv = pixels2tsv(image2pixels(image));
|
||||
document.querySelector("#brushimg-stats").value = `${image.width} x ${image.height} | ${image.width * image.height} pixels`;
|
||||
document.querySelector("#brushimg-tsv").value = tsv;
|
||||
}
|
||||
|
||||
function pixels2tsv(pixels) {
|
||||
const offset = get_source_channel_offset();
|
||||
console.info(`pixels2tsv: offset is ${offset}`);
|
||||
let result = "";
|
||||
for(let y = 0; y < pixels.height; y++) {
|
||||
let row = [];
|
||||
for(let x = 0; x < pixels.width; x++) {
|
||||
// No need to rescale here - this is done automagically by WorldEditAdditions.
|
||||
// r/b/g/alpha
|
||||
row.push(pixels.data[((y*pixels.width + x) * 4) + offset] / 255);
|
||||
}
|
||||
result += row.join(`\t`) + `\n`;
|
||||
}
|
||||
return result;
|
||||
}
|
44
.docs/img2brush/index.html
Normal file
|
@ -0,0 +1,44 @@
|
|||
---
|
||||
layout: theme.njk
|
||||
title: Image to brush converter
|
||||
---
|
||||
|
||||
<section class="panel-generic">
|
||||
<h1>Image to sculpting brush converter</h1>
|
||||
|
||||
<p>Convert any image to a sculpting brush here!</p>
|
||||
<p>
|
||||
<strong>Use this channel to convert:</strong>
|
||||
<select name="img2brush-channel" id="img2brush-channel">
|
||||
<option value="alpha" selected>Alpha (opacity)</option>
|
||||
<option value="red">Red</option>
|
||||
<option value="green">Green</option>
|
||||
<option value="blue">Blue</option>
|
||||
</select>
|
||||
</p>
|
||||
<p>Only the selected channel is used to determine the weight of the brush - <strong>all other channels are ignored</strong>! Change the channel option <strong>before</strong> you drag + drop the image onto this page.</p>
|
||||
</section>
|
||||
|
||||
<section id="dropzone" class="bigbox panel-generic">
|
||||
<h2>Input</h2>
|
||||
<p>Drop your image here.</p>
|
||||
|
||||
<img id="brushimg-preview" alt="" />
|
||||
|
||||
<output id="brushimg-stats"></output>
|
||||
</section>
|
||||
|
||||
|
||||
<section class="panel-generic">
|
||||
<h2>Output</h2>
|
||||
|
||||
<p>Paste the output below into a text file in <code>worldeditadditions/lib/sculpt/brushes</code> with the file extension <code>.brush.tsv</code> and restart your Minetest server for the brush to be recognised.</p>
|
||||
|
||||
<p class="text-centre">
|
||||
<button id="brushimg-copy" class="bigbutton">Copy</button>
|
||||
</p>
|
||||
|
||||
<pre><output id="brushimg-tsv"><em>(your output will appear here as soon as you drop an image above)</em></output></pre>
|
||||
</section>
|
||||
|
||||
<script src="./img2brush.js"></script>
|
125
.docs/index.html
Normal file
|
@ -0,0 +1,125 @@
|
|||
---
|
||||
layout: theme.njk
|
||||
title: Welcome
|
||||
tags: navigable
|
||||
date: 2000-01-01
|
||||
---
|
||||
|
||||
<section class="bigbox shadow-bottom" style="--bg: url({% image_url "images/banner-main.jpeg" %})">
|
||||
<img src="{% image_urlpass '../worldeditadditions.png' %}" alt="" class="icon logo-large" />
|
||||
<h1>WorldEditAdditions</h1>
|
||||
<p>
|
||||
<a href="https://content.minetest.net/packages/Starbeamrainbowlabs/worldeditadditions/"><img src="https://img.shields.io/badge/dynamic/json?color=%23375a7f&label=ContentDB&query=downloads&suffix=+downloads&url=https%3A//content.minetest.net/api/packages/Starbeamrainbowlabs/worldeditadditions/" alt="WorldEditAdditions on ContentDB" /></a>
|
||||
<a href="https://forum.minetest.net/viewtopic.php?f=11&t=24635"><img src="https://img.shields.io/badge/%F0%9F%92%AC-Forums-%2366D034" alt="WorldEditAdditions on the Minetest Forums" /></a>
|
||||
<a href="https://github.com/sbrl/Minetest-WorldEditAdditions/releases/latest"><img src="https://img.shields.io/github/v/release/sbrl/Minetest-WorldEditAdditions?color=green&label=latest%20release" alt="Latest release on GitHub" /></a>
|
||||
<a href="/Changelog"><img src="https://img.shields.io/badge/%F0%9F%93%B0-Changelog-informational" alt="View the changelog" /></a>
|
||||
</p>
|
||||
<p><em>Extra tools and commands to extend <a href="https://github.com/Uberi/Minetest-WorldEdit">WorldEdit</a> for <a href="https://www.minetest.net/">Minetest</a></em></p>
|
||||
<p>If you can dream of it, it probably belongs here!</p>
|
||||
<p>
|
||||
<a href="#download" class="bigbutton">Get Started</a>
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section class="features-large">
|
||||
<figure>
|
||||
{% image "images/maze2d-alt.png", "A green 2D hedge maze, made with the //maze command" %}
|
||||
<!-- <img src="/images/maze2d-alt.png" alt="A green 2D hedge maze, made with the //maze command" /> -->
|
||||
<figcaption>
|
||||
<p>Use <code>//maze</code> and <code>//maze3d</code> to generate customisable mazes in 2 or 3 dimensions.</p>
|
||||
<p>Customise the path sizing for additional artistic control.</p>
|
||||
</figcaption>
|
||||
</figure>
|
||||
|
||||
<figure>
|
||||
{% image "images/forest.png", "A forest of orange and lemon trees from the cooltrees mod, along with some bushes from Minetest Game." %}
|
||||
<!-- <img src="/images/forest.png" alt="A forest of orange and lemon trees from the cooltrees mod, along with some bushes from Minetest Game." /> -->
|
||||
<figcaption>
|
||||
<p>Save time by creating instant forests with <code>//forest</code>.</p>
|
||||
<p>Artibrary mixes of saplings are supported too as a weighted list.</p>
|
||||
</figcaption>
|
||||
</figure>
|
||||
|
||||
<figure>
|
||||
{% image "images/conv-layers.png", "A small mountain smoothed with //smoothadv and topped with snow with //overlay" %}
|
||||
<!-- <img src="/images/conv-layers.png" alt="A small mountain smoothed with //smoothadv and topped with snow with //overlay" /> -->
|
||||
<figcaption>
|
||||
<p>Unlock a continuously growing library of commands, such as <code>//smoothadv</code> for easy terrain smoothing, and <code>//overlay</code> for overlaying a node on top of terrain.</p>
|
||||
<p>Many more commands are waiting to be discovered, including <code>//torus</code>, <code>//bonemeal</code>, and <code>//scale</code>.</p>
|
||||
</figcaption>
|
||||
</figure>
|
||||
|
||||
<figure>
|
||||
{% image "images/torus-bonemeal.png", "A dirt torus with a grassy top, and a meadow of grass/flowers. Demonstrates //layers and //bonemeal. Doesn't have much to do with the sentences below - I just thought it looked nice as meta commands are difficult to find a good picture for." %}
|
||||
<!-- <img src="/images/torus-bonemeal.png" alt="A dirt torus with a grassy top, and a meadow of grass/flowers. Demonstrates //layers and //bonemeal. Doesn't have much to do with the sentences below - I just thought it looked nice as meta commands are difficult to find a good picture for." /> -->
|
||||
<figcaption>
|
||||
<p>Powerful meta commands such as <code>//multi</code> for executing multiple commands at once and <code>//subdivide</code> for running commands on areas of virtually unlimited size enable convenience and enhance flexibility.</p>
|
||||
</figcaption>
|
||||
</figure>
|
||||
</section>
|
||||
|
||||
<!-- Potentially we might want some inspiration from https://codepen.io/emared/pen/gWGBLR here -->
|
||||
<section class="gallerybox shadow-vertical">
|
||||
<section class="gallerybox-gallery">
|
||||
{% gallerybox "images/gallery-a.jpeg" "image-first" "image-last" "image-b" %}
|
||||
A scene demonstrating <code>//replacemix</code>, <code>//ellipsoid</code>, <code>//layers</code>, <code>smoothadv</code> (aka <code>convolve</code> and <code>conv</code>), and <code>//floodfill</code> - all of which are provided by WorldEditAdditions.
|
||||
{% endgallerybox %}
|
||||
{% gallerybox "images/gallery-b.jpeg" "image-b" "image-first" "image-c" %}
|
||||
The inside of a 3d maze made with <code>//maze3d</code>. Lighting was placed manually to improve screenshot quality.
|
||||
{% endgallerybox %}
|
||||
{% gallerybox "images/gallery-c.jpeg" "image-c" "image-b" "image-d" %}
|
||||
A cliff made with <code>//layers</code> and <code>//erode</code>. A <code>//forest</code> has been applied on top with multiple sapling / tree types.
|
||||
{% endgallerybox %}
|
||||
{% gallerybox "images/gallery-d.jpeg" "image-d" "image-c" "image-e" %}
|
||||
A small mountain made with <code>//layers</code> and <code>//erode</code>, using the new optional <code>//layers</code> slope constraints in WorldEditAdditions v1.13.
|
||||
{% endgallerybox %}
|
||||
{% gallerybox "images/gallery-e.jpeg" "image-e" "image-d" "image-f" %}
|
||||
A small mesa canyons terrain scene made with <code>//erode</code>, the new optional <code>//layers</code> slope contraints, and <code>//noiseapply2d</code> - the latter 2 of which are new in WorldEditAdditions v1.13. Minimal manual tuning was required.
|
||||
{% endgallerybox %}
|
||||
{% gallerybox "images/gallery-f.jpeg" "image-last" "image-e" "image-first" %}
|
||||
A stack of slices of the terrain, made with <code>//many</code> (WorldEditAdditions v1.9+) and <code>//multi</code>. By <a href="https://github.com/VorTechnix">@VorTechnix</a>.
|
||||
{% endgallerybox %}
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 id="download" class="shadow-text">Download</h2>
|
||||
<div class="features-large">
|
||||
<div class="features-item wide text-centre">
|
||||
<h3>ContentDB</h3>
|
||||
|
||||
<p><a href="https://content.minetest.net/packages/Starbeamrainbowlabs/worldeditadditions/"><img class="icon-medium" src="{% image_urlpass 'images/contentdb.png' %}" alt="WorldEditAdditions on ContentDB" /></a></p>
|
||||
|
||||
<p>Download from ContentDB, or from the <em>Content</em> tab in Minetest.</p>
|
||||
|
||||
<p><a class="bigbutton" href="https://content.minetest.net/packages/Starbeamrainbowlabs/worldeditadditions/">WorldEditAdditions on ContentDB</a></p>
|
||||
</div>
|
||||
<div class="features-item wide text-centre">
|
||||
<h3>Git</h3>
|
||||
<p>WorldEditAdditions is dependent on <a href="https://content.minetest.net/packages/sfan5/worldedit/">WorldEdit</a>. Clone using Git:</p>
|
||||
|
||||
<pre><code>cd path/to/worldmods;
|
||||
git clone https://github.com/Uberi/Minetest-WorldEdit.git worldedit;
|
||||
git clone https://github.com/sbrl/Minetest-WorldEditAdditions.git worldeditadditions;
|
||||
cd worldeditadditions;
|
||||
git checkout "$(git describe --tags --abbrev=0)";</code></pre>
|
||||
|
||||
|
||||
<p><a class="bigbutton" href="https://github.com/sbrl/Minetest-WorldEditAdditions">Source code on GitHub</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 class="shadow-text">Getting Started</h2>
|
||||
|
||||
<div class="panel-generic">
|
||||
<p>If you're familiar with WorldEdit already, then WorldEditAdditions will follow the existing expectations you're used to. For players new to WorldEdit / WorldEditAdditions, we have a tutorial that will get you up to speed in no time!</p>
|
||||
|
||||
<ul class="bigbutton-list">
|
||||
<li><a class="bigbutton" href="/Reference">Reference</a></li>
|
||||
<li><a class="bigbutton" href="/Cookbook">Cookbook</a></li>
|
||||
<li><a class="bigbutton" href="/Tutorial">Tutorial</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
88
.docs/lib/Ansi.js
Normal file
|
@ -0,0 +1,88 @@
|
|||
"use strict";
|
||||
|
||||
/**
|
||||
* Generates various VT100 ANSI escape sequences.
|
||||
* Ported from C#.
|
||||
* @licence MPL-2.0 <https://www.mozilla.org/en-US/MPL/2.0/>
|
||||
* @source https://gist.github.com/a4edd3204a03f4eedb79785751efb0f3#file-ansi-cs
|
||||
* @author Starbeamrainbowlabs
|
||||
* GitHub: @sbrl | Twitter: @SBRLabs | Reddit: u/Starbeamrainbowlabs
|
||||
***** Changelog *****
|
||||
* 27th March 2019:
|
||||
* - Initial public release
|
||||
* 9th March 2020:
|
||||
* - Add Italics (\u001b[3m])
|
||||
* - Export a new instance of it by default (makes it so that there's 1 global instance)
|
||||
* 5th September 2020:
|
||||
* - Add support for NO_COLOR environment variable <https://no-color.org/>
|
||||
*/
|
||||
class Ansi {
|
||||
constructor() {
|
||||
/**
|
||||
* Whether we should *actually* emit ANSI escape codes or not.
|
||||
* Useful when we want to output to a log file, for example
|
||||
* @type {Boolean}
|
||||
*/
|
||||
this.enabled = true;
|
||||
|
||||
this.escape_codes();
|
||||
}
|
||||
|
||||
escape_codes() {
|
||||
if(typeof process !== "undefined" && typeof process.env.NO_COLOR == "string") {
|
||||
this.enabled = false;
|
||||
return;
|
||||
}
|
||||
// Solution on how to output ANSI escape codes in C# from here:
|
||||
// https://www.jerriepelser.com/blog/using-ansi-color-codes-in-net-console-apps
|
||||
this.reset = this.enabled ? "\u001b[0m" : "";
|
||||
this.hicol = this.enabled ? "\u001b[1m" : "";
|
||||
this.locol = this.enabled ? "\u001b[2m" : "";
|
||||
this.italics = this.enabled ? "\u001b[3m" : "";
|
||||
this.underline = this.enabled ? "\u001b[4m" : "";
|
||||
this.inverse = this.enabled ? "\u001b[7m" : "";
|
||||
this.fblack = this.enabled ? "\u001b[30m" : "";
|
||||
this.fred = this.enabled ? "\u001b[31m" : "";
|
||||
this.fgreen = this.enabled ? "\u001b[32m" : "";
|
||||
this.fyellow = this.enabled ? "\u001b[33m" : "";
|
||||
this.fblue = this.enabled ? "\u001b[34m" : "";
|
||||
this.fmagenta = this.enabled ? "\u001b[35m" : "";
|
||||
this.fcyan = this.enabled ? "\u001b[36m" : "";
|
||||
this.fwhite = this.enabled ? "\u001b[37m" : "";
|
||||
this.bblack = this.enabled ? "\u001b[40m" : "";
|
||||
this.bred = this.enabled ? "\u001b[41m" : "";
|
||||
this.bgreen = this.enabled ? "\u001b[42m" : "";
|
||||
this.byellow = this.enabled ? "\u001b[43m" : "";
|
||||
this.bblue = this.enabled ? "\u001b[44m" : "";
|
||||
this.bmagenta = this.enabled ? "\u001b[45m" : "";
|
||||
this.bcyan = this.enabled ? "\u001b[46m" : "";
|
||||
this.bwhite = this.enabled ? "\u001b[47m" : "";
|
||||
}
|
||||
|
||||
// Thanks to http://ascii-table.com/ansi-escape-sequences.php for the following ANSI escape sequences
|
||||
up(lines = 1) {
|
||||
return this.enabled ? `\u001b[${lines}A` : "";
|
||||
}
|
||||
down(lines = 1) {
|
||||
return this.enabled ? `\u001b[${lines}B` : "";
|
||||
}
|
||||
right(lines = 1) {
|
||||
return this.enabled ? `\u001b[${lines}C` : "";
|
||||
}
|
||||
left(lines = 1) {
|
||||
return this.enabled ? `\u001b[${lines}D` : "";
|
||||
}
|
||||
|
||||
jump_to(x, y) {
|
||||
return this.enabled ? `\u001b[${y};${x}H` : "";
|
||||
}
|
||||
|
||||
cursor_pos_save() {
|
||||
return this.enabled ? `\u001b[s` : "";
|
||||
}
|
||||
cursor_pos_restore() {
|
||||
return this.enabled ? `\u001b[u` : "";
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new Ansi();
|
65
.docs/lib/FileFetcher.js
Normal file
|
@ -0,0 +1,65 @@
|
|||
"use strict";
|
||||
|
||||
const path = require("path");
|
||||
const fs = require("fs");
|
||||
const os = require("os");
|
||||
|
||||
const phin = require("phin");
|
||||
|
||||
const a = require("./Ansi.js");
|
||||
const pretty_ms = require("pretty-ms");
|
||||
|
||||
class FileFetcher {
|
||||
#cache = [];
|
||||
|
||||
#pkg_obj = null;
|
||||
|
||||
constructor() {
|
||||
|
||||
}
|
||||
|
||||
fetch_file(url) {
|
||||
let target_client = path.join(`/img`, path.basename(url));
|
||||
|
||||
if(this.#cache.includes(url)) return target_client;
|
||||
|
||||
this.#cache.push(url);
|
||||
|
||||
this.download_file(url); // Returns a promise! We fire-and-forget it though 'cause this function *must* be synchronous :-/
|
||||
|
||||
return target_client;
|
||||
}
|
||||
|
||||
async download_file(url) {
|
||||
const time_start = new Date();
|
||||
|
||||
if(this.#pkg_obj === null) {
|
||||
this.#pkg_obj = JSON.parse(await fs.promises.readFile(
|
||||
path.join(path.dirname(__dirname), "package.json"), "utf8"
|
||||
));
|
||||
}
|
||||
|
||||
let target_download = path.join(`_site/img`, path.basename(url));
|
||||
|
||||
const response = await phin({
|
||||
url,
|
||||
headers: {
|
||||
"user-agent": `WorldEditAdditionsStaticBuilder/${this.#pkg_obj.version} (Node.js/${process.version}; ${os.platform()} ${os.arch()}) eleventy/${this.#pkg_obj.dependencies["@11ty/eleventy"].replace(/\^/, "")}`
|
||||
},
|
||||
followRedirects: true,
|
||||
parse: 'none' // Returns a Buffer
|
||||
// If we stream and pipe to a file, the build never ends :-/
|
||||
});
|
||||
|
||||
await fs.promises.writeFile(target_download, response.body);
|
||||
|
||||
console.log([
|
||||
`${a.fred}${a.hicol}FETCH_FILE${a.reset}`,
|
||||
`${a.fyellow}${pretty_ms(new Date() - time_start)}${a.reset}`,
|
||||
`${a.fgreen}${url}${a.reset}`
|
||||
].join("\t"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports = FileFetcher;
|
154
.docs/lib/HTMLPicture.js
Normal file
|
@ -0,0 +1,154 @@
|
|||
"use strict";
|
||||
|
||||
const os = require(`os`);
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
const pretty_ms = require("pretty-ms");
|
||||
const debug = require("debug")("image");
|
||||
const imagickal = require("imagickal");
|
||||
const htmlentities = require("html-entities");
|
||||
|
||||
const a = require("./Ansi.js");
|
||||
|
||||
function calculate_size(width, height, size_spec) {
|
||||
if(size_spec.indexOf("%") > -1) {
|
||||
// It's a percentage
|
||||
const multiplier = parseInt(size_spec.replace(/%/, ""), 10) / 100;
|
||||
return {
|
||||
width: Math.ceil(width * multiplier),
|
||||
height: Math.ceil(height * multiplier)
|
||||
};
|
||||
}
|
||||
else {
|
||||
// It's an absolute image width
|
||||
const new_width = parseInt(size_spec, 10);
|
||||
return {
|
||||
width: new_width,
|
||||
height: Math.ceil(new_width/width * height)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Main task list - we make sure it completes before exiting.
|
||||
var queue = null;
|
||||
|
||||
async function make_queue() {
|
||||
// 1: Setup task queue
|
||||
const PQueue = (await import("p-queue")).default;
|
||||
let concurrency = os.cpus().length;
|
||||
if(process.env["MAX_CONCURRENT"])
|
||||
concurrency = parseInt(process.env["MAX_CONCURRENT"], 10);
|
||||
debug(`Image conversion queue concurrency: `, concurrency);
|
||||
queue = new PQueue({ concurrency });
|
||||
queue.on("idle", () => console.log(`IMAGE ${a.fcyan}all conversions complete${a.reset}`));
|
||||
process.on("exit", async () => {
|
||||
debug(`Waiting for image conversions to finish...`);
|
||||
await queue.onEmpty();
|
||||
debug(`All image conversions complete.`);
|
||||
});
|
||||
}
|
||||
|
||||
async function srcset(source_image, target_dir, urlpath, format = "__AUTO__", sizes = [ "25%", "50%", "100%" ], quality = 95, strip = true) {
|
||||
if(queue === null) await make_queue();
|
||||
|
||||
const source_parsed = path.parse(source_image);
|
||||
// ext contains the dot . already
|
||||
const target_format = format == "__AUTO__" ? source_parsed.ext.replace(/\./g, "") : format;
|
||||
|
||||
const source_size = await imagickal.dimensions(source_image);
|
||||
|
||||
debug(`SOURCE_SIZE`, source_size, `TARGET_FORMAT`, target_format);
|
||||
|
||||
let setitems = await Promise.all(sizes.map(async (size) => {
|
||||
let target_filename = `${source_parsed.name}_${size}.${target_format}`
|
||||
.replace(/%/, "pcent");
|
||||
let target_current = path.join(
|
||||
target_dir,
|
||||
target_filename
|
||||
);
|
||||
queue.add(async () => {
|
||||
const start = new Date();
|
||||
await imagickal.transform(source_image, target_current, {
|
||||
resize: { width: size },
|
||||
quality,
|
||||
strip
|
||||
});
|
||||
console.log(`${a.fmagenta}${a.hicol}IMAGE${a.reset}\t${a.fcyan}${queue.size}/${queue.pending} tasks${a.reset}\t${a.fyellow}${pretty_ms(new Date() - start)}${a.reset}\t${a.fgreen}${target_current}${a.reset}`);
|
||||
});
|
||||
// const size_target = await imagickal.dimensions(target_current);
|
||||
|
||||
const predict = calculate_size(source_size.width, source_size.height, size);
|
||||
// debug(`size spec:`, size, `size predicted: ${predict.width}x${predict.height} actual: ${size_target.width}x${size_target.height}`);
|
||||
return `${path.resolve(urlpath, target_filename)} ${predict.width}w`;
|
||||
}));
|
||||
|
||||
return setitems.join(", ");
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a string of HTML for a <picture> element, converting images to the specified formats in the process.
|
||||
* @param {string} source_image The filepath to the source image.
|
||||
* @param {string} alt The alt (alternative) text. Automatically run though htmlentities.
|
||||
* @param {string} target_dir The target directory to save converted images to.
|
||||
* @param {string} urlpath The path to the aforementionoed target directory as a URL. Image paths in the HTML will be prefixed with this value.
|
||||
* @param {string} [formats="__AUTO__"] A list of formats to convert the source image to. Defaults to automatically determining the most optimal formats based on the input format. [must be lowercase]
|
||||
* @param {Array} [sizes=["25%","50%", "100%" ]] The sizes, as imagemagick size specs, to convert the source image to.
|
||||
* @param {Number} [quality=95] The quality value to use when converting images.
|
||||
* @param {Boolean} [strip=true] Whether to strip all metadata from images when converting them [saves some space]
|
||||
* @return {Promise<string>} A Promise that returns a generated string of HTML.
|
||||
*/
|
||||
async function picture(source_image, alt, target_dir, urlpath, formats = "__AUTO__", sizes = [ "25%", "50%", "100%" ], quality = 95, strip = true) {
|
||||
const source_parsed = path.parse(source_image);
|
||||
const source_format = source_parsed.ext.toLowerCase().replace(".", "");
|
||||
|
||||
if(formats == "__AUTO__") {
|
||||
switch(source_format) {
|
||||
case "png":
|
||||
case "gif": // * shudder *
|
||||
case "bmp":
|
||||
formats = [ "png" ];
|
||||
break;
|
||||
default:
|
||||
// jxl = JPEG XL <https://jpegxl.info/> - not currently supported by the old version of imagemagick shipped via apt :-/
|
||||
// Imagemagick v7+ does support it, but isn't shipped yet :-(
|
||||
formats = [ "jpeg", "webp", "avif", /*"jxl"*/ ];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const target_original = path.join(target_dir, source_parsed.base);
|
||||
await fs.promises.copyFile(source_image, target_original);
|
||||
|
||||
const sources = await Promise.all(formats.map(async (format) => {
|
||||
debug(`${format} ${source_image}`);
|
||||
|
||||
return {
|
||||
mime: `image/${format}`,
|
||||
srcset: await srcset(
|
||||
source_image,
|
||||
target_dir, urlpath,
|
||||
format, sizes,
|
||||
quality, strip
|
||||
)
|
||||
};
|
||||
}));
|
||||
|
||||
let result = `<picture>\n\t`;
|
||||
result += sources.map(source => `<source srcset="${source.srcset}" type="${source.mime}" />`).join(`\n\t`);
|
||||
result += `\n\t<img loading="lazy" decoding="async" src="${urlpath}/${source_parsed.base}" alt="${htmlentities.encode(alt)}" />\n`;
|
||||
result += `</picture>\n`
|
||||
return result;
|
||||
}
|
||||
|
||||
var picture_memoize = null;
|
||||
|
||||
async function setup_memoize() {
|
||||
const pMemoize = (await import("p-memoize")).default;
|
||||
picture_memoize = pMemoize(picture);
|
||||
}
|
||||
|
||||
module.exports = async function(...args) {
|
||||
if(picture_memoize === null) await setup_memoize();
|
||||
return await picture_memoize(...args);
|
||||
};
|
91
.docs/lib/parse_sections.js
Normal file
|
@ -0,0 +1,91 @@
|
|||
"use strict";
|
||||
|
||||
const crypto = require("crypto");
|
||||
|
||||
const htmlentities = require("html-entities");
|
||||
const markdown = require("markdown-it")({
|
||||
xhtmlOut: true
|
||||
});
|
||||
const chroma = require("chroma-js");
|
||||
|
||||
const markdown_prism = require("markdown-it-prism");
|
||||
markdown.use(markdown_prism, {
|
||||
init: (Prism) => {
|
||||
Prism.languages.weacmd = {
|
||||
"string": /\<[^>]+?\>/,
|
||||
"function": /^(?:\/\/\S+)\b/m,
|
||||
"number": /\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?%?/i,
|
||||
"operator": /[<>:=\[\]|{}]/,
|
||||
"keyword": /\b(?:[-+]?[zyx])\b/
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function extract_title(line) {
|
||||
return line.match(/#+\s+(.+)\s*/)[1].replace(/^`*|`*$/g, "")
|
||||
}
|
||||
|
||||
function make_section(acc, cat_current, cats) {
|
||||
let title = extract_title(acc[0]);
|
||||
return {
|
||||
category: cat_current,
|
||||
category_colour: cats.get(cat_current),
|
||||
category_colour_dark: chroma(cats.get(cat_current))
|
||||
.set("hsl.s", 0.8)
|
||||
.set("hsl.l", "*0.6")
|
||||
.css("hsl"),
|
||||
title: htmlentities.encode(title),
|
||||
slug: title.toLowerCase().replace(/[^a-z0-9-_\s]+/gi, "")
|
||||
.replace(/\s+/g, "-")
|
||||
.replace(/-.*$/, ""),
|
||||
content: markdown.render(acc.slice(1).join("\n"))
|
||||
.replace(/<h4(\/?)>/g, "<h3$1>")
|
||||
.replace(/<h5(\/?)>/g, "<h4$1>")
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = function parse_sections(source) {
|
||||
const cats = new Map();
|
||||
source.match(/^##\s+.*$/gm)
|
||||
.map(extract_title)
|
||||
.map((item, i, all) => cats.set(
|
||||
item,
|
||||
chroma(`hsl(${i/all.length*(360-360/all.length)}, 60%, 90%)`).css("hsl")
|
||||
));
|
||||
const lines = source.split(/\r?\n/gi);
|
||||
const result = [];
|
||||
let acc = [];
|
||||
let cat_current = null;
|
||||
for(let line of lines) {
|
||||
|
||||
if(line.startsWith(`#`)) {
|
||||
let heading_level = line.match(/^#+/)[0].length;
|
||||
|
||||
// 1: Deal with the previous section
|
||||
if(acc.length > 0) {
|
||||
let heading_level_prev = acc[0].match(/^#+/)[0].length;
|
||||
if(heading_level_prev === 3 && acc.length > 0 && heading_level <= 3) {
|
||||
result.push(make_section(acc, cat_current, cats));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 2: Deal with the new line
|
||||
|
||||
if(heading_level === 2)
|
||||
cat_current = extract_title(line);
|
||||
|
||||
if(heading_level > 3)
|
||||
acc.push(line)
|
||||
else
|
||||
acc = [ line ];
|
||||
}
|
||||
else
|
||||
acc.push(line);
|
||||
}
|
||||
|
||||
if(acc.length > 0)
|
||||
result.push(make_section(acc, cat_current, cats));
|
||||
|
||||
return { sections: result, categories: cats };
|
||||
}
|
4396
.docs/package-lock.json
generated
Normal file
37
.docs/package.json
Normal file
|
@ -0,0 +1,37 @@
|
|||
{
|
||||
"name": "worldeditadditions",
|
||||
"version": "1.14.5",
|
||||
"description": "Documentation website for WorldEditAdditions",
|
||||
"main": "index.js",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"test": "echo \"No tests have been implemented yet\"",
|
||||
"start": "npx @11ty/eleventy --serve",
|
||||
"build": "npx @11ty/eleventy"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/sbrl/Minetest-WorldEditAdditions.git"
|
||||
},
|
||||
"author": "Starbeamrainbowlabs",
|
||||
"license": "MPL-2.0",
|
||||
"bugs": {
|
||||
"url": "https://github.com/sbrl/Minetest-WorldEditAdditions/issues"
|
||||
},
|
||||
"homepage": "https://github.com/sbrl/Minetest-WorldEditAdditions#readme",
|
||||
"dependencies": {
|
||||
"@11ty/eleventy": "^2.0.1",
|
||||
"chroma-js": "^2.4.2",
|
||||
"clean-css": "^5.3.2",
|
||||
"columnify": "^1.6.0",
|
||||
"debug": "^4.3.4",
|
||||
"html-entities": "^2.4.0",
|
||||
"html-minifier-terser": "^7.0.0-beta.0",
|
||||
"imagickal": "^5.0.1",
|
||||
"markdown-it-prism": "^2.3.0",
|
||||
"p-memoize": "^7.1.1",
|
||||
"p-queue": "^7.3.4",
|
||||
"phin": "^3.7.0",
|
||||
"pretty-ms": "^7.0.1"
|
||||
}
|
||||
}
|
26
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
|
@ -0,0 +1,26 @@
|
|||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: bug
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
What's the bug? Be clear and concise in our explanation. Don't forget to include any context, error messages, logs, and screenshots required to understand the issue if applicable.
|
||||
|
||||
**Reproduction steps:**
|
||||
Steps to reproduce the behaviour:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Enter this command to '....'
|
||||
4. See error
|
||||
|
||||
**System information (please complete the following information):**
|
||||
- **Operating system and version:** [e.g. iOS]
|
||||
- **Minetest version:** [e.g. 5.8.0]
|
||||
- **WorldEdit version:**
|
||||
- **WorldEditAdditions version:**
|
||||
|
||||
Please add any other additional specific system information here too if you think it would help.
|
22
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: enhancement
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
## Problem
|
||||
A clear and concise description of what the problem you want to solve is. e.g. I'm always frustrated when [...]
|
||||
|
||||
## Solution
|
||||
Describe clearly the solution you'd like.
|
||||
|
||||
## Alternatives
|
||||
A clear and concise description of any alternative solutions or features you've considered, and how they relate to your proposed feature.
|
||||
|
||||
## Additional context
|
||||
Add any other context or screenshots about the feature request here.
|
||||
|
||||
Don't forget to remove replace descriptions, but keep the headers.
|
52
.github/workflows/test.yml
vendored
Normal file
|
@ -0,0 +1,52 @@
|
|||
name: "CI Tests"
|
||||
on: [push]
|
||||
jobs:
|
||||
Syntax-Check:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
# Checkout the git repo
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Install apt dependencies
|
||||
run: sudo apt-get --quiet install lua5.1
|
||||
|
||||
- name: Environment info
|
||||
run: uname -a; lua -v
|
||||
|
||||
- name: Perform Check
|
||||
run: find . -type f -name '*.lua' -not -path '*luarocks*' -not -path '*.git/*' -print0 | xargs -0 -n1 -P "$(nproc)" luac -p;
|
||||
Busted:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
# Checkout the git repo
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Install apt dependencies
|
||||
run: sudo apt-get --quiet install lua5.1 luarocks
|
||||
|
||||
- name: Environment info
|
||||
run: uname -a; lua -v
|
||||
|
||||
- name: Set up tests
|
||||
run: ./tests.sh run
|
||||
|
||||
- name: Run Tests
|
||||
run: ./tests.sh run
|
||||
LuaCheck:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
# Checkout the git repo
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Install apt dependencies
|
||||
run: sudo apt-get --quiet install lua5.1 lua-check
|
||||
|
||||
- name: Environment info
|
||||
run: uname -a; lua -v
|
||||
|
||||
- name: Run luacheck
|
||||
run: luacheck .
|
||||
|
199
.gitignore
vendored
|
@ -1,3 +1,26 @@
|
|||
_site/
|
||||
.luarocks/
|
||||
|
||||
# Created by https://www.toptal.com/developers/gitignore/api/git
|
||||
# Edit at https://www.toptal.com/developers/gitignore?templates=git
|
||||
|
||||
### Git ###
|
||||
# Created by git for backups. To disable backups in Git:
|
||||
# $ git config --global mergetool.keepBackup false
|
||||
*.orig
|
||||
|
||||
# Created by git when using merge tools for conflicts
|
||||
*.BACKUP.*
|
||||
*.BASE.*
|
||||
*.LOCAL.*
|
||||
*.REMOTE.*
|
||||
*_BACKUP_*.txt
|
||||
*_BASE_*.txt
|
||||
*_LOCAL_*.txt
|
||||
*_REMOTE_*.txt
|
||||
|
||||
# End of https://www.toptal.com/developers/gitignore/api/git
|
||||
|
||||
# Compiled Lua sources
|
||||
luac.out
|
||||
|
||||
|
@ -39,3 +62,179 @@ luac.out
|
|||
*.x86_64
|
||||
*.hex
|
||||
|
||||
# Created by https://www.toptal.com/developers/gitignore/api/lua,node
|
||||
# Edit at https://www.toptal.com/developers/gitignore?templates=lua,node
|
||||
|
||||
### Lua ###
|
||||
# Compiled Lua sources
|
||||
luac.out
|
||||
|
||||
# luarocks build files
|
||||
*.src.rock
|
||||
*.zip
|
||||
*.tar.gz
|
||||
|
||||
# Object files
|
||||
*.o
|
||||
*.os
|
||||
*.ko
|
||||
*.obj
|
||||
*.elf
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
||||
# Libraries
|
||||
*.lib
|
||||
*.a
|
||||
*.la
|
||||
*.lo
|
||||
*.def
|
||||
*.exp
|
||||
|
||||
# Shared objects (inc. Windows DLLs)
|
||||
*.dll
|
||||
*.so
|
||||
*.so.*
|
||||
*.dylib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
*.i*86
|
||||
*.x86_64
|
||||
*.hex
|
||||
|
||||
|
||||
### Node ###
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# TypeScript v1 declaration files
|
||||
typings/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional stylelint cache
|
||||
.stylelintcache
|
||||
|
||||
# Microbundle cache
|
||||
.rpt2_cache/
|
||||
.rts2_cache_cjs/
|
||||
.rts2_cache_es/
|
||||
.rts2_cache_umd/
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
.env.test
|
||||
.env*.local
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
.parcel-cache
|
||||
|
||||
# Next.js build output
|
||||
.next
|
||||
|
||||
# Nuxt.js build / generate output
|
||||
.nuxt
|
||||
dist
|
||||
|
||||
# Storybook build outputs
|
||||
.out
|
||||
.storybook-out
|
||||
storybook-static
|
||||
|
||||
# rollup.js default build output
|
||||
dist/
|
||||
|
||||
# Gatsby files
|
||||
.cache/
|
||||
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||
# public
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
||||
# TernJS port file
|
||||
.tern-port
|
||||
|
||||
# Stores VSCode versions used for testing VSCode extensions
|
||||
.vscode-test
|
||||
|
||||
# Temporary folders
|
||||
tmp/
|
||||
temp/
|
||||
|
||||
# End of https://www.toptal.com/developers/gitignore/api/lua,node
|
||||
|
||||
# VorTechnix stuff
|
||||
.vdev/
|
||||
|
|
39
.luacheckrc
Normal file
|
@ -0,0 +1,39 @@
|
|||
quiet = 1
|
||||
codes = true
|
||||
|
||||
exclude_files = {
|
||||
".luarocks/*",
|
||||
"worldeditadditions_core/utils/bit.lua"
|
||||
}
|
||||
|
||||
files["worldeditadditions_core/register/check.lua"] = { read_globals = { "table" } }
|
||||
|
||||
ignore = {
|
||||
"631", "61[124]",
|
||||
"542",
|
||||
"412",
|
||||
"321/bit",
|
||||
"21[123]"
|
||||
}
|
||||
|
||||
-- Read-write globals (i.e. they can be defined)
|
||||
globals = {
|
||||
"worldedit",
|
||||
"worldeditadditions",
|
||||
"worldeditadditions_commands",
|
||||
"worldeditadditions_core"
|
||||
}
|
||||
-- Read-only globals
|
||||
read_globals = {
|
||||
"minetest",
|
||||
"vector",
|
||||
"assert",
|
||||
"bit",
|
||||
"it",
|
||||
"describe",
|
||||
"bonemeal",
|
||||
"dofile",
|
||||
"PerlinNoise",
|
||||
"Settings"
|
||||
}
|
||||
std = "max"
|
35
.tests/Vector3/abs.test.lua
Normal file
|
@ -0,0 +1,35 @@
|
|||
local Vector3 = require("worldeditadditions_core.utils.vector3")
|
||||
|
||||
describe("Vector3.abs", function()
|
||||
it("should work with a positive vector", function()
|
||||
local a = Vector3.new(16, 64, 16)
|
||||
assert.are.same(
|
||||
Vector3.new(16, 64, 16),
|
||||
a:abs()
|
||||
)
|
||||
end)
|
||||
it("should abs another positive vector", function()
|
||||
local a = Vector3.new(9, 16, 25)
|
||||
assert.are.same(
|
||||
Vector3.new(9, 16, 25),
|
||||
a:abs()
|
||||
)
|
||||
end)
|
||||
it("should abs a negative vector", function()
|
||||
local a = Vector3.new(-9, -16, -25)
|
||||
assert.are.same(
|
||||
Vector3.new(9, 16, 25),
|
||||
a:abs()
|
||||
)
|
||||
end)
|
||||
it("should return a new Vector3 instance", function()
|
||||
local a = Vector3.new(9, -16, 25)
|
||||
|
||||
local result = a:abs()
|
||||
assert.are.same(
|
||||
Vector3.new(9, 16, 25),
|
||||
result
|
||||
)
|
||||
assert.are_not.equal(result, a)
|
||||
end)
|
||||
end)
|
80
.tests/Vector3/add.test.lua
Normal file
|
@ -0,0 +1,80 @@
|
|||
local Vector3 = require("worldeditadditions_core.utils.vector3")
|
||||
|
||||
describe("Vector3.add", function()
|
||||
it("should add 2 positive vectors", function()
|
||||
local a = Vector3.new(3, 4, 5)
|
||||
local b = Vector3.new(1, 1, 1)
|
||||
assert.are.same(
|
||||
Vector3.new(4, 5, 6),
|
||||
a:add(b)
|
||||
)
|
||||
end)
|
||||
it("should support the add operator", function()
|
||||
local a = Vector3.new(3, 4, 5)
|
||||
local b = Vector3.new(1, 1, 1)
|
||||
assert.are.same(
|
||||
Vector3.new(4, 5, 6),
|
||||
a + b
|
||||
)
|
||||
end)
|
||||
it("should work with floats", function()
|
||||
local a = Vector3.new(3.5, 4.5, 5.5)
|
||||
local b = Vector3.new(1.1, 1.1, 1.1)
|
||||
assert.are.same(
|
||||
Vector3.new(4.6, 5.6, 6.6),
|
||||
a + b
|
||||
)
|
||||
end)
|
||||
it("should work with scalar a", function()
|
||||
local a = 2
|
||||
local b = Vector3.new(6, 7, 8)
|
||||
assert.are.same(
|
||||
Vector3.new(8, 9, 10),
|
||||
a + b
|
||||
)
|
||||
end)
|
||||
it("should work with scalar b", function()
|
||||
local a = Vector3.new(6, 7, 8)
|
||||
local b = 2
|
||||
assert.are.same(
|
||||
Vector3.new(8, 9, 10),
|
||||
a + b
|
||||
)
|
||||
end)
|
||||
it("should handle negative b", function()
|
||||
local a = Vector3.new(3, 4, 5)
|
||||
local b = Vector3.new(-1, -1, -1)
|
||||
assert.are.same(
|
||||
Vector3.new(2, 3, 4),
|
||||
a + b
|
||||
)
|
||||
end)
|
||||
it("should handle negative a", function()
|
||||
local a = Vector3.new(-3, -4, -5)
|
||||
local b = Vector3.new(1, 1, 1)
|
||||
assert.are.same(
|
||||
Vector3.new(-2, -3, -4),
|
||||
a + b
|
||||
)
|
||||
end)
|
||||
it("should handle negative a and b", function()
|
||||
local a = Vector3.new(-3, -4, -5)
|
||||
local b = Vector3.new(-1, -1, -1)
|
||||
assert.are.same(
|
||||
Vector3.new(-4, -5, -6),
|
||||
a + b
|
||||
)
|
||||
end)
|
||||
it("should return a new Vector3 instance", function()
|
||||
local a = Vector3.new(3, 4, 5)
|
||||
local b = Vector3.new(1, 1, 1)
|
||||
|
||||
local result = a + b
|
||||
assert.are.same(
|
||||
Vector3.new(4, 5, 6),
|
||||
result
|
||||
)
|
||||
assert.are_not.equal(result, a)
|
||||
assert.are_not.equal(result, b)
|
||||
end)
|
||||
end)
|
25
.tests/Vector3/area.test.lua
Normal file
|
@ -0,0 +1,25 @@
|
|||
local Vector3 = require("worldeditadditions_core.utils.vector3")
|
||||
|
||||
describe("Vector3.area", function()
|
||||
it("should work with a positive vector", function()
|
||||
local a = Vector3.new(3, 3, 3)
|
||||
assert.are.equal(
|
||||
27,
|
||||
a:area()
|
||||
)
|
||||
end)
|
||||
it("should work with a negative vector", function()
|
||||
local a = Vector3.new(-4, -4, -4)
|
||||
assert.are.equal(
|
||||
-64,
|
||||
a:area()
|
||||
)
|
||||
end)
|
||||
it("should work with a mixed vector", function()
|
||||
local a = Vector3.new(-3, 3, -3)
|
||||
assert.are.equal(
|
||||
27,
|
||||
a:area()
|
||||
)
|
||||
end)
|
||||
end)
|
35
.tests/Vector3/ceil.test.lua
Normal file
|
@ -0,0 +1,35 @@
|
|||
local Vector3 = require("worldeditadditions_core.utils.vector3")
|
||||
|
||||
describe("Vector3.ceil", function()
|
||||
it("should ceil a positive vector", function()
|
||||
local a = Vector3.new(3.1, 4.2, 5.8)
|
||||
assert.are.same(
|
||||
Vector3.new(4, 5, 6),
|
||||
a:ceil()
|
||||
)
|
||||
end)
|
||||
it("should ceil a negative vector", function()
|
||||
local a = Vector3.new(-3.1, -4.2, -5.3)
|
||||
assert.are.same(
|
||||
Vector3.new(-3, -4, -5),
|
||||
a:ceil()
|
||||
)
|
||||
end)
|
||||
it("should work with integers", function()
|
||||
local a = Vector3.new(3, 4, 5)
|
||||
assert.are.same(
|
||||
a:ceil(),
|
||||
Vector3.new(3, 4, 5)
|
||||
)
|
||||
end)
|
||||
it("should return a new Vector3 instance", function()
|
||||
local a = Vector3.new(3.1, 4.7, 5.99999)
|
||||
|
||||
local result = a:ceil()
|
||||
assert.are.same(
|
||||
Vector3.new(4, 5, 6),
|
||||
result
|
||||
)
|
||||
assert.are_not.equal(result, a)
|
||||
end)
|
||||
end)
|
100
.tests/Vector3/clamp.test.lua
Normal file
|
@ -0,0 +1,100 @@
|
|||
local Vector3 = require("worldeditadditions_core.utils.vector3")
|
||||
|
||||
describe("Vector3.clamp", function()
|
||||
it("should work by not changing values if it's already clamped", function()
|
||||
local a = Vector3.new(5, 6, 7)
|
||||
local pos1 = Vector3.new(0, 0, 0)
|
||||
local pos2 = Vector3.new(10, 10, 10)
|
||||
|
||||
local result = Vector3.clamp(a, pos1, pos2)
|
||||
|
||||
assert.are.same(
|
||||
Vector3.new(5, 6, 7),
|
||||
result
|
||||
)
|
||||
|
||||
result.z = 999
|
||||
|
||||
assert.are.same(Vector3.new(5, 6, 7), a)
|
||||
assert.are.same(Vector3.new(0, 0, 0), pos1)
|
||||
assert.are.same(Vector3.new(10, 10, 10), pos2)
|
||||
end)
|
||||
it("should work with positive vectors", function()
|
||||
local a = Vector3.new(30, 3, 3)
|
||||
local pos1 = Vector3.new(0, 0, 0)
|
||||
local pos2 = Vector3.new(10, 10, 10)
|
||||
|
||||
assert.are.same(
|
||||
Vector3.new(10, 3, 3),
|
||||
Vector3.clamp(a, pos1, pos2)
|
||||
)
|
||||
end)
|
||||
it("should work with multiple positive vectors", function()
|
||||
local a = Vector3.new(30, 99, 88)
|
||||
local pos1 = Vector3.new(4, 4, 4)
|
||||
local pos2 = Vector3.new(13, 13, 13)
|
||||
|
||||
assert.are.same(
|
||||
Vector3.new(13, 13, 13),
|
||||
Vector3.clamp(a, pos1, pos2)
|
||||
)
|
||||
end)
|
||||
it("should work with multiple positive vectors with an irregular defined region", function()
|
||||
local a = Vector3.new(30, 99, 88)
|
||||
local pos1 = Vector3.new(1, 5, 3)
|
||||
local pos2 = Vector3.new(10, 15, 8)
|
||||
|
||||
assert.are.same(
|
||||
Vector3.new(10, 15, 8),
|
||||
Vector3.clamp(a, pos1, pos2)
|
||||
)
|
||||
end)
|
||||
it("should work with multiple negative vectors", function()
|
||||
local a = Vector3.new(-30, -99, -88)
|
||||
local pos1 = Vector3.new(4, 4, 4)
|
||||
local pos2 = Vector3.new(13, 13, 13)
|
||||
|
||||
assert.are.same(
|
||||
Vector3.new(4, 4, 4),
|
||||
Vector3.clamp(a, pos1, pos2)
|
||||
)
|
||||
end)
|
||||
it("should work with multiple negative vectors with an irregular defined region", function()
|
||||
local a = Vector3.new(-30, -99, -88)
|
||||
local pos1 = Vector3.new(1, 5, 3)
|
||||
local pos2 = Vector3.new(10, 15, 8)
|
||||
|
||||
assert.are.same(
|
||||
Vector3.new(1, 5, 3),
|
||||
Vector3.clamp(a, pos1, pos2)
|
||||
)
|
||||
end)
|
||||
it("should work with multiple negative vectors with an irregular defined region with mixed signs", function()
|
||||
local a = Vector3.new(-30, -99, -88)
|
||||
local pos1 = Vector3.new(-1, 5, 3)
|
||||
local pos2 = Vector3.new(10, 15, 8)
|
||||
|
||||
assert.are.same(
|
||||
Vector3.new(-1, 5, 3),
|
||||
Vector3.clamp(a, pos1, pos2)
|
||||
)
|
||||
end)
|
||||
|
||||
|
||||
|
||||
|
||||
it("should return new Vector3 instances", function()
|
||||
local a = Vector3.new(30, 3, 3)
|
||||
local pos1 = Vector3.new(0, 0, 0)
|
||||
local pos2 = Vector3.new(10, 10, 10)
|
||||
|
||||
local result = Vector3.clamp(a, pos1, pos2)
|
||||
assert.are.same(Vector3.new(10, 3, 3), result)
|
||||
|
||||
result.y = 999
|
||||
|
||||
assert.are.same(Vector3.new(30, 3, 3), a)
|
||||
assert.are.same(Vector3.new(0, 0, 0), pos1)
|
||||
assert.are.same(Vector3.new(10, 10, 10), pos2)
|
||||
end)
|
||||
end)
|
20
.tests/Vector3/clone.test.lua
Normal file
|
@ -0,0 +1,20 @@
|
|||
local Vector3 = require("worldeditadditions_core.utils.vector3")
|
||||
|
||||
describe("Vector3.clone", function()
|
||||
it("should return a new Vector3 instance", function()
|
||||
local a = Vector3.new(3, 4, 5)
|
||||
|
||||
local result = a:clone()
|
||||
result.x = 4
|
||||
assert.are.same(Vector3.new(3, 4, 5), a)
|
||||
assert.are.same(Vector3.new(4, 4, 5), result)
|
||||
end)
|
||||
it("should return a new Vector3 instance for a different vector", function()
|
||||
local a = Vector3.new(-99, 66, 88)
|
||||
|
||||
local result = a:clone()
|
||||
result.y = -44
|
||||
assert.are.same(Vector3.new(-99, 66, 88), a)
|
||||
assert.are.same(Vector3.new(-99, -44, 88), result)
|
||||
end)
|
||||
end)
|
28
.tests/Vector3/concat.test.lua
Normal file
|
@ -0,0 +1,28 @@
|
|||
local Vector3 = require("worldeditadditions_core.utils.vector3")
|
||||
|
||||
describe("Vector3.__concat", function()
|
||||
it("should work when concatenating a Vector3 + Vector3", function()
|
||||
local a = Vector3.new(3, 4, 5)
|
||||
local b = Vector3.new(6, 7, 8)
|
||||
|
||||
assert.are.is_true(
|
||||
type(tostring(a .. b)) == "string"
|
||||
)
|
||||
end)
|
||||
it("should work when concatenating a string + Vector3", function()
|
||||
local a = "yay"
|
||||
local b = Vector3.new(6, 7, 8)
|
||||
|
||||
assert.are.is_true(
|
||||
type(tostring(a .. b)) == "string"
|
||||
)
|
||||
end)
|
||||
it("should work when concatenating a Vector3 + string", function()
|
||||
local a = Vector3.new(3, 4, 5)
|
||||
local b = "yay"
|
||||
|
||||
assert.are.is_true(
|
||||
type(tostring(a .. b)) == "string"
|
||||
)
|
||||
end)
|
||||
end)
|
80
.tests/Vector3/divide.test.lua
Normal file
|
@ -0,0 +1,80 @@
|
|||
local Vector3 = require("worldeditadditions_core.utils.vector3")
|
||||
|
||||
describe("Vector3.divide", function()
|
||||
it("should divide 2 positive vectors", function()
|
||||
local a = Vector3.new(30, 40, 50)
|
||||
local b = Vector3.new(2, 2, 2)
|
||||
assert.are.same(
|
||||
Vector3.new(15, 20, 25),
|
||||
a:divide(b)
|
||||
)
|
||||
end)
|
||||
it("should work with the div alias", function()
|
||||
local a = Vector3.new(30, 40, 50)
|
||||
local b = Vector3.new(2, 2, 2)
|
||||
assert.are.same(
|
||||
Vector3.new(15, 20, 25),
|
||||
a:div(b)
|
||||
)
|
||||
end)
|
||||
it("should work with scalar a", function()
|
||||
local a = 100
|
||||
local b = Vector3.new(4, 5, 2)
|
||||
assert.are.same(
|
||||
Vector3.new(25, 20, 50),
|
||||
a / b
|
||||
)
|
||||
end)
|
||||
it("should work with scalar b", function()
|
||||
local a = Vector3.new(6, 8, 10)
|
||||
local b = 2
|
||||
assert.are.same(
|
||||
Vector3.new(3, 4, 5),
|
||||
a / b
|
||||
)
|
||||
end)
|
||||
it("should support the divide operator", function()
|
||||
local a = Vector3.new(10, 12, 14)
|
||||
local b = Vector3.new(2, 3, 2)
|
||||
assert.are.same(
|
||||
Vector3.new(5, 4, 7),
|
||||
a / b
|
||||
)
|
||||
end)
|
||||
it("should handle negative b", function()
|
||||
local a = Vector3.new(30, 40, 50)
|
||||
local b = Vector3.new(-2, -2, -2)
|
||||
assert.are.same(
|
||||
Vector3.new(-15, -20, -25),
|
||||
a / b
|
||||
)
|
||||
end)
|
||||
it("should handle negative a", function()
|
||||
local a = Vector3.new(-30, -40, -50)
|
||||
local b = Vector3.new(2, 4, 2)
|
||||
assert.are.same(
|
||||
Vector3.new(-15, -10, -25),
|
||||
a / b
|
||||
)
|
||||
end)
|
||||
it("should handle negative a and b", function()
|
||||
local a = Vector3.new(-30, -40, -50)
|
||||
local b = Vector3.new(-2, -2, -2)
|
||||
assert.are.same(
|
||||
Vector3.new(15, 20, 25),
|
||||
a / b
|
||||
)
|
||||
end)
|
||||
it("should return a new Vector3 instance", function()
|
||||
local a = Vector3.new(9, 12, 15)
|
||||
local b = Vector3.new(3, 3, 3)
|
||||
|
||||
local result = a / b
|
||||
assert.are.same(
|
||||
Vector3.new(3, 4, 5),
|
||||
result
|
||||
)
|
||||
assert.are_not.equal(result, a)
|
||||
assert.are_not.equal(result, b)
|
||||
end)
|
||||
end)
|
36
.tests/Vector3/dot.test.lua
Normal file
|
@ -0,0 +1,36 @@
|
|||
local Vector3 = require("worldeditadditions_core.utils.vector3")
|
||||
|
||||
describe("Vector3.dot", function()
|
||||
it("should work with a positive vector", function()
|
||||
local a = Vector3.new(3, 3, 3)
|
||||
local b = Vector3.new(4, 5, 6)
|
||||
assert.are.equal(
|
||||
45,
|
||||
a:dot(b)
|
||||
)
|
||||
end)
|
||||
it("should work with a negative vector", function()
|
||||
local a = Vector3.new(-4, -4, -4)
|
||||
local b = Vector3.new(4, 5, 6)
|
||||
assert.are.equal(
|
||||
-60,
|
||||
a:dot(b)
|
||||
)
|
||||
end)
|
||||
it("should work with a mixed vector", function()
|
||||
local a = Vector3.new(-3, 3, -3)
|
||||
local b = Vector3.new(7, 8, 9)
|
||||
assert.are.equal(
|
||||
-24,
|
||||
a:dot(b)
|
||||
)
|
||||
end)
|
||||
it("should work with the dot_product alias", function()
|
||||
local a = Vector3.new(-3, 3, -3)
|
||||
local b = Vector3.new(7, 8, 9)
|
||||
assert.are.equal(
|
||||
-24,
|
||||
a:dot_product(b)
|
||||
)
|
||||
end)
|
||||
end)
|
40
.tests/Vector3/equal.test.lua
Normal file
|
@ -0,0 +1,40 @@
|
|||
local Vector3 = require("worldeditadditions_core.utils.vector3")
|
||||
|
||||
describe("Vector3.equals", function()
|
||||
it("should return true when identical", function()
|
||||
local a = Vector3.new(3, 4, 5)
|
||||
local b = Vector3.new(3, 4, 5)
|
||||
|
||||
assert.are.same(
|
||||
true,
|
||||
a:equals(b)
|
||||
)
|
||||
end)
|
||||
it("should return false when not identical", function()
|
||||
local a = Vector3.new(3, 4, 5)
|
||||
local b = Vector3.new(6, 7, 8)
|
||||
|
||||
assert.are.same(
|
||||
false,
|
||||
a:equals(b)
|
||||
)
|
||||
end)
|
||||
it("should return false when not identical x", function()
|
||||
local a = Vector3.new(3, 4, 5)
|
||||
local b = Vector3.new(4, 4, 5)
|
||||
|
||||
assert.are.same(
|
||||
false,
|
||||
a:equals(b)
|
||||
)
|
||||
end)
|
||||
it("should return false when not identical y", function()
|
||||
local a = Vector3.new(3, 4, 5)
|
||||
local b = Vector3.new(3, 5, 5)
|
||||
|
||||
assert.are.same(
|
||||
false,
|
||||
a:equals(b)
|
||||
)
|
||||
end)
|
||||
end)
|
48
.tests/Vector3/expand_region.test.lua
Normal file
|
@ -0,0 +1,48 @@
|
|||
local Vector3 = require("worldeditadditions_core.utils.vector3")
|
||||
|
||||
describe("Vector3.expand_region", function()
|
||||
it("should work with positive vectors", function()
|
||||
local a = Vector3.new(16, 64, 16)
|
||||
local b = Vector3.new(1, 4, 6)
|
||||
local target = Vector3.new(99, 99, 99)
|
||||
|
||||
local result_a, result_b = target:expand_region(a, b)
|
||||
assert.are.same(Vector3.new(1, 4, 6), result_a)
|
||||
assert.are.same(Vector3.new(99, 99, 99), result_b)
|
||||
end)
|
||||
it("should work with mixed components", function()
|
||||
local a = Vector3.new(16, 1, 16)
|
||||
local b = Vector3.new(1, 4, 60)
|
||||
local target = Vector3.new(-99, -99, -99)
|
||||
|
||||
local result_a, result_b = target:expand_region(a, b)
|
||||
assert.are.same(Vector3.new(-99, -99, -99), result_a)
|
||||
assert.are.same(Vector3.new(16, 4, 60), result_b)
|
||||
end)
|
||||
it("should work with negative vectors", function()
|
||||
local a = Vector3.new(-9, -16, -25)
|
||||
local b = Vector3.new(-3, -6, -2)
|
||||
local target = Vector3.new(-99, -99, -99)
|
||||
|
||||
local result_a, result_b = target:expand_region(a, b)
|
||||
assert.are.same(Vector3.new(-99, -99, -99), result_a)
|
||||
assert.are.same(Vector3.new(-3, -6, -2), result_b)
|
||||
end)
|
||||
it("should return new Vector3 instances", function()
|
||||
local a = Vector3.new(16, 1, 16)
|
||||
local b = Vector3.new(1, 4, 60)
|
||||
local target = Vector3.new(99, 99, 99)
|
||||
|
||||
local result_a, result_b = target:expand_region(a, b)
|
||||
assert.are.same(Vector3.new(1, 1, 16), result_a)
|
||||
assert.are.same(Vector3.new(99, 99, 99), result_b)
|
||||
|
||||
result_a.y = 999
|
||||
result_b.y = 999
|
||||
|
||||
assert.are.same(Vector3.new(16, 1, 16), a)
|
||||
assert.are.same(Vector3.new(1, 4, 60), b)
|
||||
assert.are.same(Vector3.new(1, 999, 16), result_a)
|
||||
assert.are.same(Vector3.new(99, 999, 99), result_b)
|
||||
end)
|
||||
end)
|
35
.tests/Vector3/floor.test.lua
Normal file
|
@ -0,0 +1,35 @@
|
|||
local Vector3 = require("worldeditadditions_core.utils.vector3")
|
||||
|
||||
describe("Vector3.floor", function()
|
||||
it("should floor a positive vector", function()
|
||||
local a = Vector3.new(3.1, 4.75, 5.9)
|
||||
assert.are.same(
|
||||
Vector3.new(3, 4, 5),
|
||||
a:floor()
|
||||
)
|
||||
end)
|
||||
it("should floor a negative vector", function()
|
||||
local a = Vector3.new(-3.1, -4.2, -5.3)
|
||||
assert.are.same(
|
||||
Vector3.new(-4, -5, -6),
|
||||
a:floor()
|
||||
)
|
||||
end)
|
||||
it("should work with integers", function()
|
||||
local a = Vector3.new(3, 4, 5)
|
||||
assert.are.same(
|
||||
Vector3.new(3, 4, 5),
|
||||
a:floor()
|
||||
)
|
||||
end)
|
||||
it("should return a new Vector3 instance", function()
|
||||
local a = Vector3.new(3.1, 4.7, 5.99999)
|
||||
|
||||
local result = a:floor()
|
||||
assert.are.same(
|
||||
Vector3.new(3, 4, 5),
|
||||
result
|
||||
)
|
||||
assert.are_not.equal(result, a)
|
||||
end)
|
||||
end)
|
44
.tests/Vector3/is_contained.test.lua
Normal file
|
@ -0,0 +1,44 @@
|
|||
local Vector3 = require("worldeditadditions_core.utils.vector3")
|
||||
|
||||
describe("Vector3.is_contained", function()
|
||||
it("should return true when inside", function()
|
||||
local a = Vector3.new(3, 4, 5)
|
||||
local b = Vector3.new(30, 40, 50)
|
||||
local target = Vector3.new(6, 6, 6)
|
||||
|
||||
assert.are.same(
|
||||
true,
|
||||
target:is_contained(a, b)
|
||||
)
|
||||
end)
|
||||
it("should return false when outside x", function()
|
||||
local a = Vector3.new(3, 4, 5)
|
||||
local b = Vector3.new(30, 40, 50)
|
||||
local target = Vector3.new(60, 6, 6)
|
||||
|
||||
assert.are.same(
|
||||
false,
|
||||
target:is_contained(a, b)
|
||||
)
|
||||
end)
|
||||
it("should return false when outside y", function()
|
||||
local a = Vector3.new(3, 4, 5)
|
||||
local b = Vector3.new(30, 40, 50)
|
||||
local target = Vector3.new(6, 60, 6)
|
||||
|
||||
assert.are.same(
|
||||
false,
|
||||
target:is_contained(a, b)
|
||||
)
|
||||
end)
|
||||
it("should return false when outside z", function()
|
||||
local a = Vector3.new(3, 4, 5)
|
||||
local b = Vector3.new(30, 40, 50)
|
||||
local target = Vector3.new(6, 6, 60)
|
||||
|
||||
assert.are.same(
|
||||
false,
|
||||
target:is_contained(a, b)
|
||||
)
|
||||
end)
|
||||
end)
|
30
.tests/Vector3/length.test.lua
Normal file
|
@ -0,0 +1,30 @@
|
|||
local Vector3 = require("worldeditadditions_core.utils.vector3")
|
||||
|
||||
-- To find these numbers, in Javascript:
|
||||
-- function t(x) { return Math.sqrt((x*x)*3); }
|
||||
-- for(let i = 0; i < 1000000000; i++) { let r = t(i); if(Math.floor(r) === r) console.log(`i ${i}, r ${r}`); }
|
||||
|
||||
|
||||
describe("Vector3.length", function()
|
||||
it("should work with a positive vector", function()
|
||||
local a = Vector3.new(80198051, 80198051, 80198051)
|
||||
assert.are.equal(
|
||||
138907099,
|
||||
a:length()
|
||||
)
|
||||
end)
|
||||
it("should work with a negative vector", function()
|
||||
local a = Vector3.new(-189750626, -189750626, -189750626)
|
||||
assert.are.equal(
|
||||
328657725,
|
||||
a:length()
|
||||
)
|
||||
end)
|
||||
it("should work with a mixed vector", function()
|
||||
local a = Vector3.new(-371635731, 371635731, -371635731)
|
||||
assert.are.equal(
|
||||
643691968,
|
||||
a:length()
|
||||
)
|
||||
end)
|
||||
end)
|
25
.tests/Vector3/length_squared.test.lua
Normal file
|
@ -0,0 +1,25 @@
|
|||
local Vector3 = require("worldeditadditions_core.utils.vector3")
|
||||
|
||||
describe("Vector3.length_squared", function()
|
||||
it("should work with a positive vector", function()
|
||||
local a = Vector3.new(3, 3, 3)
|
||||
assert.are.equal(
|
||||
27,
|
||||
a:length_squared()
|
||||
)
|
||||
end)
|
||||
it("should work with a negative vector", function()
|
||||
local a = Vector3.new(-4, -4, -4)
|
||||
assert.are.equal(
|
||||
48,
|
||||
a:length_squared()
|
||||
)
|
||||
end)
|
||||
it("should work with a mixed vector", function()
|
||||
local a = Vector3.new(-3, 3, -3)
|
||||
assert.are.equal(
|
||||
27,
|
||||
a:length_squared()
|
||||
)
|
||||
end)
|
||||
end)
|
56
.tests/Vector3/limit_to.test.lua
Normal file
|
@ -0,0 +1,56 @@
|
|||
local Vector3 = require("worldeditadditions_core.utils.vector3")
|
||||
|
||||
describe("Vector3.limit_to", function()
|
||||
it("should limit_to a positive vector", function()
|
||||
local a = Vector3.new(801980510, 801980510, 801980510)
|
||||
assert.are.same(
|
||||
Vector3.new(80198051, 80198051, 80198051),
|
||||
a:limit_to(138907099)
|
||||
)
|
||||
end)
|
||||
it("should limit_to a negative vector", function()
|
||||
local a = Vector3.new(-1897506260, -1897506260, -1897506260)
|
||||
assert.are.same(
|
||||
Vector3.new(-189750626, -189750626, -189750626),
|
||||
a:limit_to(328657725)
|
||||
)
|
||||
end)
|
||||
it("should work if the length is borderline", function()
|
||||
local a = Vector3.new(80198051, 80198051, 80198051)
|
||||
assert.are.same(
|
||||
Vector3.new(80198051, 80198051, 80198051),
|
||||
a:limit_to(138907099)
|
||||
)
|
||||
end)
|
||||
it("should not change anything if the length is smaller", function()
|
||||
local a = Vector3.new(3, 4, 5)
|
||||
assert.are.same(
|
||||
Vector3.new(3, 4, 5),
|
||||
a:limit_to(100)
|
||||
)
|
||||
end)
|
||||
it("should return a new Vector3 instance", function()
|
||||
local a = Vector3.new(801980510, 801980510, 801980510)
|
||||
|
||||
local result = a:limit_to(138907099)
|
||||
assert.are.same(
|
||||
Vector3.new(80198051, 80198051, 80198051),
|
||||
result
|
||||
)
|
||||
a.x = 4
|
||||
assert.are.same(Vector3.new(4, 801980510, 801980510), a)
|
||||
assert.are.same(Vector3.new(80198051, 80198051, 80198051), result)
|
||||
end)
|
||||
it("should return a new Vector3 instance if the length is smaller", function()
|
||||
local a = Vector3.new(3, 4, 5)
|
||||
|
||||
local result = a:limit_to(101)
|
||||
assert.are.same(
|
||||
Vector3.new(3, 4, 5),
|
||||
result
|
||||
)
|
||||
a.x = 40
|
||||
assert.are.same(Vector3.new(40, 4, 5), a)
|
||||
assert.are.same(Vector3.new(3, 4, 5), result)
|
||||
end)
|
||||
end)
|
62
.tests/Vector3/max.test.lua
Normal file
|
@ -0,0 +1,62 @@
|
|||
local Vector3 = require("worldeditadditions_core.utils.vector3")
|
||||
|
||||
describe("Vector3.max", function()
|
||||
it("should work with positive vectors", function()
|
||||
local a = Vector3.new(16, 64, 16)
|
||||
local b = Vector3.new(1, 4, 6)
|
||||
|
||||
assert.are.same(
|
||||
Vector3.new(16, 64, 16),
|
||||
Vector3.max(a, b)
|
||||
)
|
||||
end)
|
||||
it("should work with mixed components", function()
|
||||
local a = Vector3.new(16, 1, 16)
|
||||
local b = Vector3.new(1, 4, 60)
|
||||
|
||||
assert.are.same(
|
||||
Vector3.new(16, 4, 60),
|
||||
Vector3.max(a, b)
|
||||
)
|
||||
end)
|
||||
it("should work with scalar numbers", function()
|
||||
local a = Vector3.new(16, 1, 16)
|
||||
local b = 2
|
||||
|
||||
assert.are.same(
|
||||
Vector3.new(16, 2, 16),
|
||||
Vector3.max(a, b)
|
||||
)
|
||||
end)
|
||||
it("should work with scalar numbers both ways around", function()
|
||||
local a = Vector3.new(16, 1, 16)
|
||||
local b = 2
|
||||
|
||||
assert.are.same(
|
||||
Vector3.new(16, 2, 16),
|
||||
Vector3.max(b, a)
|
||||
)
|
||||
end)
|
||||
it("should work with negative vectors", function()
|
||||
local a = Vector3.new(-9, -16, -25)
|
||||
local b = Vector3.new(-3, -6, -2)
|
||||
|
||||
assert.are.same(
|
||||
Vector3.new(-3, -6, -2),
|
||||
Vector3.max(a, b)
|
||||
)
|
||||
end)
|
||||
it("should return new Vector3 instances", function()
|
||||
local a = Vector3.new(16, 1, 16)
|
||||
local b = Vector3.new(1, 4, 60)
|
||||
|
||||
local result = Vector3.max(a, b)
|
||||
assert.are.same(Vector3.new(16, 4, 60), result)
|
||||
|
||||
result.y = 999
|
||||
|
||||
assert.are.same(Vector3.new(16, 1, 16), a)
|
||||
assert.are.same(Vector3.new(1, 4, 60), b)
|
||||
assert.are.same(Vector3.new(16, 999, 60), result)
|
||||
end)
|
||||
end)
|
39
.tests/Vector3/max_component.test.lua
Normal file
|
@ -0,0 +1,39 @@
|
|||
local Vector3 = require("worldeditadditions_core.utils.vector3")
|
||||
|
||||
describe("Vector3.max_component", function()
|
||||
it("should work with a positive vector x", function()
|
||||
local a = Vector3.new(30, 4, 5)
|
||||
assert.are.equal(
|
||||
30,
|
||||
a:max_component()
|
||||
)
|
||||
end)
|
||||
it("should work with a positive vector y", function()
|
||||
local a = Vector3.new(3, 10, 5)
|
||||
assert.are.equal(
|
||||
10,
|
||||
a:max_component()
|
||||
)
|
||||
end)
|
||||
it("should work with a positive vector z", function()
|
||||
local a = Vector3.new(3, 1, 50.5)
|
||||
assert.are.equal(
|
||||
50.5,
|
||||
a:max_component()
|
||||
)
|
||||
end)
|
||||
it("should work with a negative vector", function()
|
||||
local a = Vector3.new(-4, -5, -1)
|
||||
assert.are.equal(
|
||||
-1,
|
||||
a:max_component()
|
||||
)
|
||||
end)
|
||||
it("should work with a mixed vector", function()
|
||||
local a = Vector3.new(-30, 3, -3)
|
||||
assert.are.equal(
|
||||
3,
|
||||
a:max_component()
|
||||
)
|
||||
end)
|
||||
end)
|
47
.tests/Vector3/mean.test.lua
Normal file
|
@ -0,0 +1,47 @@
|
|||
local Vector3 = require("worldeditadditions_core.utils.vector3")
|
||||
|
||||
describe("Vector3.mean", function()
|
||||
it("should work with a positive vector", function()
|
||||
local a = Vector3.new(2, 2, 2)
|
||||
local b = Vector3.new(4, 4, 4)
|
||||
assert.are.same(
|
||||
Vector3.new(3, 3, 3),
|
||||
a:mean(b)
|
||||
)
|
||||
end)
|
||||
it("should work with a positive vector the other way around", function()
|
||||
local a = Vector3.new(2, 2, 2)
|
||||
local b = Vector3.new(4, 4, 4)
|
||||
assert.are.same(
|
||||
Vector3.new(3, 3, 3),
|
||||
b:mean(a)
|
||||
)
|
||||
end)
|
||||
it("should mean another positive vector", function()
|
||||
local a = Vector3.new(6, 6, 6)
|
||||
local b = Vector3.new(10, 10, 10)
|
||||
assert.are.same(
|
||||
Vector3.new(8, 8, 8),
|
||||
a:mean(b)
|
||||
)
|
||||
end)
|
||||
it("should mean a negative vector", function()
|
||||
local a = Vector3.new(-2, -2, -2)
|
||||
local b = Vector3.new(0, 0, 0)
|
||||
assert.are.same(
|
||||
Vector3.new(-1, -1, -1),
|
||||
a:mean(b)
|
||||
)
|
||||
end)
|
||||
it("should return a new Vector3 instance", function()
|
||||
local a = Vector3.new(6, 6, 6)
|
||||
local b = Vector3.new(10, 10, 10)
|
||||
assert.are.same(
|
||||
Vector3.new(8, 8, 8),
|
||||
a:mean(b)
|
||||
)
|
||||
|
||||
assert.are.same(Vector3.new(6, 6, 6), a)
|
||||
assert.are.same(Vector3.new(10, 10, 10), b)
|
||||
end)
|
||||
end)
|
62
.tests/Vector3/min.test.lua
Normal file
|
@ -0,0 +1,62 @@
|
|||
local Vector3 = require("worldeditadditions_core.utils.vector3")
|
||||
|
||||
describe("Vector3.min", function()
|
||||
it("should work with positive vectors", function()
|
||||
local a = Vector3.new(16, 64, 16)
|
||||
local b = Vector3.new(1, 4, 6)
|
||||
|
||||
assert.are.same(
|
||||
Vector3.new(1, 4, 6),
|
||||
Vector3.min(a, b)
|
||||
)
|
||||
end)
|
||||
it("should work with mixed components", function()
|
||||
local a = Vector3.new(16, 1, 16)
|
||||
local b = Vector3.new(1, 4, 60)
|
||||
|
||||
assert.are.same(
|
||||
Vector3.new(1, 1, 16),
|
||||
Vector3.min(a, b)
|
||||
)
|
||||
end)
|
||||
it("should work with scalar numbers", function()
|
||||
local a = Vector3.new(16, 1, 16)
|
||||
local b = 2
|
||||
|
||||
assert.are.same(
|
||||
Vector3.new(2, 1, 2),
|
||||
Vector3.min(a, b)
|
||||
)
|
||||
end)
|
||||
it("should work with scalar numbers both ways around", function()
|
||||
local a = Vector3.new(16, 1, 16)
|
||||
local b = 2
|
||||
|
||||
assert.are.same(
|
||||
Vector3.new(2, 1, 2),
|
||||
Vector3.min(b, a)
|
||||
)
|
||||
end)
|
||||
it("should work with negative vectors", function()
|
||||
local a = Vector3.new(-9, -16, -25)
|
||||
local b = Vector3.new(-3, -6, -2)
|
||||
|
||||
assert.are.same(
|
||||
Vector3.new(-9, -16, -25),
|
||||
Vector3.min(a, b)
|
||||
)
|
||||
end)
|
||||
it("should return new Vector3 instances", function()
|
||||
local a = Vector3.new(16, 1, 16)
|
||||
local b = Vector3.new(1, 4, 60)
|
||||
|
||||
local result = Vector3.min(a, b)
|
||||
assert.are.same(Vector3.new(1, 1, 16), result)
|
||||
|
||||
result.y = 999
|
||||
|
||||
assert.are.same(Vector3.new(16, 1, 16), a)
|
||||
assert.are.same(Vector3.new(1, 4, 60), b)
|
||||
assert.are.same(Vector3.new(1, 999, 16), result)
|
||||
end)
|
||||
end)
|
39
.tests/Vector3/min_component.test.lua
Normal file
|
@ -0,0 +1,39 @@
|
|||
local Vector3 = require("worldeditadditions_core.utils.vector3")
|
||||
|
||||
describe("Vector3.min_component", function()
|
||||
it("should work with a positive vector x", function()
|
||||
local a = Vector3.new(3, 4, 5)
|
||||
assert.are.equal(
|
||||
3,
|
||||
a:min_component()
|
||||
)
|
||||
end)
|
||||
it("should work with a positive vector y", function()
|
||||
local a = Vector3.new(3, 1, 5)
|
||||
assert.are.equal(
|
||||
1,
|
||||
a:min_component()
|
||||
)
|
||||
end)
|
||||
it("should work with a positive vector z", function()
|
||||
local a = Vector3.new(3, 1, 0.5)
|
||||
assert.are.equal(
|
||||
0.5,
|
||||
a:min_component()
|
||||
)
|
||||
end)
|
||||
it("should work with a negative vector", function()
|
||||
local a = Vector3.new(-4, -5, -46)
|
||||
assert.are.equal(
|
||||
-46,
|
||||
a:min_component()
|
||||
)
|
||||
end)
|
||||
it("should work with a mixed vector", function()
|
||||
local a = Vector3.new(-30, 3, -3)
|
||||
assert.are.equal(
|
||||
-30,
|
||||
a:min_component()
|
||||
)
|
||||
end)
|
||||
end)
|
17
.tests/Vector3/move_towards.test.lua
Normal file
|
@ -0,0 +1,17 @@
|
|||
local Vector3 = require("worldeditadditions_core.utils.vector3")
|
||||
|
||||
-- To find these numbers, in Javascript:
|
||||
-- function t(x) { return Math.sqrt((x*x)*3); }
|
||||
-- for(let i = 0; i < 1000000000; i++) { let r = t(i); if(Math.floor(r) === r) console.log(`i ${i}, r ${r}`); }
|
||||
|
||||
|
||||
describe("Vector3.move_towards", function()
|
||||
it("should work with a positive vector", function()
|
||||
local a = Vector3.new(3, 4, 5)
|
||||
local b = Vector3.new(10, 10, 10)
|
||||
assert.are.same(
|
||||
Vector3.new(5.0022714374157439821, 5.7162326606420661435, 6.4301938838683883048),
|
||||
a:move_towards(b, 3)
|
||||
)
|
||||
end)
|
||||
end)
|
80
.tests/Vector3/multiply.test.lua
Normal file
|
@ -0,0 +1,80 @@
|
|||
local Vector3 = require("worldeditadditions_core.utils.vector3")
|
||||
|
||||
describe("Vector3.multiply", function()
|
||||
it("should multiply 2 positive vectors", function()
|
||||
local a = Vector3.new(3, 4, 5)
|
||||
local b = Vector3.new(2, 2, 2)
|
||||
assert.are.same(
|
||||
Vector3.new(6, 8, 10),
|
||||
a:multiply(b)
|
||||
)
|
||||
end)
|
||||
it("should work with the mul alias", function()
|
||||
local a = Vector3.new(3, 4, 5)
|
||||
local b = Vector3.new(2, 2, 2)
|
||||
assert.are.same(
|
||||
Vector3.new(6, 8, 10),
|
||||
a:mul(b)
|
||||
)
|
||||
end)
|
||||
it("should work with scalar a", function()
|
||||
local a = 2
|
||||
local b = Vector3.new(6, 7, 8)
|
||||
assert.are.same(
|
||||
Vector3.new(12, 14, 16),
|
||||
a * b
|
||||
)
|
||||
end)
|
||||
it("should work with scalar b", function()
|
||||
local a = Vector3.new(6, 7, 8)
|
||||
local b = 2
|
||||
assert.are.same(
|
||||
Vector3.new(12, 14, 16),
|
||||
a * b
|
||||
)
|
||||
end)
|
||||
it("should support the multiply operator", function()
|
||||
local a = Vector3.new(3, 4, 5)
|
||||
local b = Vector3.new(2, 2, 2)
|
||||
assert.are.same(
|
||||
Vector3.new(6, 8, 10),
|
||||
a * b
|
||||
)
|
||||
end)
|
||||
it("should handle negative b", function()
|
||||
local a = Vector3.new(3, 4, 5)
|
||||
local b = Vector3.new(-1, -1, -1)
|
||||
assert.are.same(
|
||||
Vector3.new(-3, -4, -5),
|
||||
a * b
|
||||
)
|
||||
end)
|
||||
it("should handle negative a", function()
|
||||
local a = Vector3.new(-3, -4, -5)
|
||||
local b = Vector3.new(2, 2, 2)
|
||||
assert.are.same(
|
||||
Vector3.new(-6, -8, -10),
|
||||
a * b
|
||||
)
|
||||
end)
|
||||
it("should handle negative a and b", function()
|
||||
local a = Vector3.new(-3, -4, -5)
|
||||
local b = Vector3.new(-2, -2, -2)
|
||||
assert.are.same(
|
||||
Vector3.new(6, 8, 10),
|
||||
a * b
|
||||
)
|
||||
end)
|
||||
it("should return a new Vector3 instance", function()
|
||||
local a = Vector3.new(3, 4, 5)
|
||||
local b = Vector3.new(3, 3, 3)
|
||||
|
||||
local result = a * b
|
||||
assert.are.same(
|
||||
Vector3.new(9, 12, 15),
|
||||
result
|
||||
)
|
||||
assert.are_not.equal(result, a)
|
||||
assert.are_not.equal(result, b)
|
||||
end)
|
||||
end)
|
31
.tests/Vector3/new.test.lua
Normal file
|
@ -0,0 +1,31 @@
|
|||
local Vector3 = require("worldeditadditions_core.utils.vector3")
|
||||
|
||||
describe("Vector3.add", function()
|
||||
it("should create a new Vector3", function()
|
||||
assert.are.same(
|
||||
{ x = 3, y = 4, z = 5 },
|
||||
Vector3.new(3, 4, 5)
|
||||
)
|
||||
end)
|
||||
it("should default to (0, 0, 0)", function()
|
||||
assert.are.same(
|
||||
{ x = 0, y = 0, z = 0 },
|
||||
Vector3.new()
|
||||
)
|
||||
end)
|
||||
it("should not throw an error on invalid x", function()
|
||||
assert.has_no.errors(function()
|
||||
Vector3.new("cheese", 4, 5)
|
||||
end)
|
||||
end)
|
||||
it("should not throw an error on invalid y", function()
|
||||
assert.has_no.errors(function()
|
||||
Vector3.new(4, "cheese", 5)
|
||||
end)
|
||||
end)
|
||||
it("should not throw an error on invalid z", function()
|
||||
assert.has_no.errors(function()
|
||||
Vector3.new(66, 2, "cheese")
|
||||
end)
|
||||
end)
|
||||
end)
|
132
.tests/Vector3/rotate3d.test.lua
Normal file
|
@ -0,0 +1,132 @@
|
|||
local Vector3 = require("worldeditadditions_core.utils.vector3")
|
||||
|
||||
describe("Vector3.rotate3d", function()
|
||||
it("should work with an origin of (0,0,0) X axis", function()
|
||||
local origin = Vector3.new(0, 0, 0)
|
||||
local point = Vector3.new(0, 1, 0)
|
||||
local rotate = Vector3.new(
|
||||
math.rad(180), -- x axis = yz plane
|
||||
math.rad(0), -- y axis = xz plane
|
||||
math.rad(0)-- z axis = xy plane
|
||||
)
|
||||
assert.are.same(
|
||||
Vector3.new(0, -1, 0),
|
||||
Vector3.rotate3d(origin, point, rotate):round_dp(4)
|
||||
)
|
||||
end)
|
||||
it("should work with an origin of (0,0,0) Y axis", function()
|
||||
local origin = Vector3.new(0, 0, 0)
|
||||
local point = Vector3.new(1, 0, 0)
|
||||
local rotate = Vector3.new(
|
||||
math.rad(0), -- x axis = yz plane
|
||||
math.rad(180), -- y axis = xz plane
|
||||
math.rad(0)-- z axis = xy plane
|
||||
)
|
||||
assert.are.same(
|
||||
Vector3.new(-1, 0, 0),
|
||||
Vector3.rotate3d(origin, point, rotate):round_dp(4)
|
||||
)
|
||||
end)
|
||||
it("should work with an origin of (0,0,0) Z axis", function()
|
||||
local origin = Vector3.new(0, 0, 0)
|
||||
local point = Vector3.new(1, 0, 0)
|
||||
local rotate = Vector3.new(
|
||||
math.rad(0), -- x axis = yz plane
|
||||
math.rad(0), -- y axis = xz plane
|
||||
math.rad(180)-- z axis = xy plane
|
||||
)
|
||||
assert.are.same(
|
||||
Vector3.new(-1, 0, 0),
|
||||
Vector3.rotate3d(origin, point, rotate):round_dp(4)
|
||||
)
|
||||
end)
|
||||
|
||||
|
||||
|
||||
it("should work with a non-zero origin X axis", function()
|
||||
local origin = Vector3.new(1, 1, 1)
|
||||
local point = Vector3.new(0, 2, 0)
|
||||
local rotate = Vector3.new(
|
||||
math.rad(180), -- x axis = yz plane
|
||||
math.rad(0), -- y axis = xz plane
|
||||
math.rad(0)-- z axis = xy plane
|
||||
)
|
||||
assert.are.same(
|
||||
Vector3.new(0, 0, 2),
|
||||
Vector3.rotate3d(origin, point, rotate):round_dp(4)
|
||||
)
|
||||
end)
|
||||
it("should work with a non-zero origin Y axis", function()
|
||||
local origin = Vector3.new(1, 1, 1)
|
||||
local point = Vector3.new(0, 2, 0)
|
||||
local rotate = Vector3.new(
|
||||
math.rad(0), -- x axis = yz plane
|
||||
math.rad(180), -- y axis = xz plane
|
||||
math.rad(0)-- z axis = xy plane
|
||||
)
|
||||
assert.are.same(
|
||||
Vector3.new(2, 2, 2),
|
||||
Vector3.rotate3d(origin, point, rotate):round_dp(4)
|
||||
)
|
||||
end)
|
||||
it("should work with a non-zero origin Z axis", function()
|
||||
local origin = Vector3.new(1, 1, 1)
|
||||
local point = Vector3.new(0, 2, 0)
|
||||
local rotate = Vector3.new(
|
||||
math.rad(0), -- x axis = yz plane
|
||||
math.rad(0), -- y axis = xz plane
|
||||
math.rad(180)-- z axis = xy plane
|
||||
)
|
||||
assert.are.same(
|
||||
Vector3.new(2, 0, 0),
|
||||
Vector3.rotate3d(origin, point, rotate):round_dp(4)
|
||||
)
|
||||
end)
|
||||
it("should work with a non-zero origin Z axis -90 degrees", function()
|
||||
local origin = Vector3.new(1, 1, 1)
|
||||
local point = Vector3.new(0, 2, 0)
|
||||
local rotate = Vector3.new(
|
||||
math.rad(0), -- x axis = yz plane
|
||||
math.rad(0), -- y axis = xz plane
|
||||
math.rad(-90)-- z axis = xy plane
|
||||
)
|
||||
assert.are.same(
|
||||
Vector3.new(2, 2, 0),
|
||||
Vector3.rotate3d(origin, point, rotate):round_dp(4)
|
||||
)
|
||||
end)
|
||||
it("should work with multiple axes X Y", function()
|
||||
local origin = Vector3.new(0, 0, 0)
|
||||
local point = Vector3.new(0, 2, 0)
|
||||
local rotate = Vector3.new(
|
||||
math.rad(90), -- x axis = yz plane
|
||||
math.rad(90), -- y axis = xz plane
|
||||
math.rad(0)-- z axis = xy plane
|
||||
)
|
||||
assert.are.same(
|
||||
Vector3.new(2, 0, 0),
|
||||
Vector3.rotate3d(origin, point, rotate):round_dp(4)
|
||||
)
|
||||
end)
|
||||
|
||||
|
||||
|
||||
it("should return new Vector3 instances", function()
|
||||
local origin = Vector3.new(0, 0, 0)
|
||||
local point = Vector3.new(1, 0, 0)
|
||||
local rotate = Vector3.new(
|
||||
math.rad(0), -- x axis = yz plane
|
||||
math.rad(180), -- y axis = xz plane
|
||||
math.rad(0)-- z axis = xy plane
|
||||
)
|
||||
|
||||
local result = Vector3.rotate3d(origin, point, rotate):round(4)
|
||||
assert.are.same(Vector3.new(-1, 0, 0), result)
|
||||
|
||||
result.y = 999
|
||||
|
||||
assert.are.same(Vector3.new(0, 0, 0), origin)
|
||||
assert.are.same(Vector3.new(1, 0, 0), point)
|
||||
assert.are.same(Vector3.new(-1, 999, 0), result)
|
||||
end)
|
||||
end)
|
35
.tests/Vector3/round.test.lua
Normal file
|
@ -0,0 +1,35 @@
|
|||
local Vector3 = require("worldeditadditions_core.utils.vector3")
|
||||
|
||||
describe("Vector3.round", function()
|
||||
it("should round a positive vector", function()
|
||||
local a = Vector3.new(3.1, 4.75, 5.9)
|
||||
assert.are.same(
|
||||
Vector3.new(3, 5, 6),
|
||||
a:round()
|
||||
)
|
||||
end)
|
||||
it("should round a negative vector", function()
|
||||
local a = Vector3.new(-3.1, -4.2, -5.3)
|
||||
assert.are.same(
|
||||
Vector3.new(-3, -4, -5),
|
||||
a:round()
|
||||
)
|
||||
end)
|
||||
it("should work with integers", function()
|
||||
local a = Vector3.new(3, 4, 5)
|
||||
assert.are.same(
|
||||
Vector3.new(3, 4, 5),
|
||||
a:round()
|
||||
)
|
||||
end)
|
||||
it("should return a new Vector3 instance", function()
|
||||
local a = Vector3.new(3.1, 4.7, 5.99999)
|
||||
|
||||
local result = a:round()
|
||||
assert.are.same(
|
||||
Vector3.new(3, 5, 6),
|
||||
result
|
||||
)
|
||||
assert.are_not.equal(result, a)
|
||||
end)
|
||||
end)
|
52
.tests/Vector3/set_to.test.lua
Normal file
|
@ -0,0 +1,52 @@
|
|||
local Vector3 = require("worldeditadditions_core.utils.vector3")
|
||||
|
||||
describe("Vector3.set_to", function()
|
||||
it("should set_to a positive vector", function()
|
||||
local a = Vector3.new(801980510, 801980510, 801980510)
|
||||
assert.are.same(
|
||||
Vector3.new(80198051, 80198051, 80198051),
|
||||
a:set_to(138907099)
|
||||
)
|
||||
end)
|
||||
it("should set_to a negative vector", function()
|
||||
local a = Vector3.new(-1897506260, -1897506260, -1897506260)
|
||||
assert.are.same(
|
||||
Vector3.new(-189750626, -189750626, -189750626),
|
||||
a:set_to(328657725)
|
||||
)
|
||||
end)
|
||||
it("should work if the length is borderline", function()
|
||||
local a = Vector3.new(80198051, 80198051, 80198051)
|
||||
assert.are.same(
|
||||
Vector3.new(80198051, 80198051, 80198051),
|
||||
a:set_to(138907099)
|
||||
)
|
||||
end)
|
||||
it("should work if the length is smaller", function()
|
||||
local a = Vector3.new(80198051, 80198051, 80198051)
|
||||
assert.are.same(
|
||||
Vector3.new(109552575, 109552575, 109552575),
|
||||
a:set_to(189750626):floor() -- Hack to ignore flating-point errors. In theory we should really use epsilon here instead
|
||||
)
|
||||
end)
|
||||
it("should return a new Vector3 instance", function()
|
||||
local a = Vector3.new(801980510, 801980510, 801980510)
|
||||
|
||||
local result = a:set_to(138907099)
|
||||
assert.are.same(
|
||||
Vector3.new(80198051, 80198051, 80198051),
|
||||
result
|
||||
)
|
||||
assert.are_not.equal(result, a)
|
||||
end)
|
||||
it("should return a new Vector3 instance if the length is smaller", function()
|
||||
local a = Vector3.new(80198051, 80198051, 80198051)
|
||||
|
||||
local result = a:set_to(189750626):floor()
|
||||
assert.are.same(
|
||||
Vector3.new(109552575, 109552575, 109552575),
|
||||
result
|
||||
)
|
||||
assert.are_not.equal(result, a)
|
||||
end)
|
||||
end)
|
35
.tests/Vector3/snap_to.test.lua
Normal file
|
@ -0,0 +1,35 @@
|
|||
local Vector3 = require("worldeditadditions_core.utils.vector3")
|
||||
|
||||
describe("Vector3.snap_to", function()
|
||||
it("should snap_to a positive vector", function()
|
||||
local a = Vector3.new(3.1, 4.75, 5.9)
|
||||
assert.are.same(
|
||||
Vector3.new(0, 0, 10),
|
||||
a:snap_to(10)
|
||||
)
|
||||
end)
|
||||
it("should snap_to a negative vector", function()
|
||||
local a = Vector3.new(-2.5, -4.2, -5.3)
|
||||
assert.are.same(
|
||||
Vector3.new(0, -6, -6),
|
||||
a:snap_to(6)
|
||||
)
|
||||
end)
|
||||
it("should work with integers", function()
|
||||
local a = Vector3.new(3, 4, 5)
|
||||
assert.are.same(
|
||||
Vector3.new(3, 3, 6),
|
||||
a:snap_to(3)
|
||||
)
|
||||
end)
|
||||
it("should return a new Vector3 instance", function()
|
||||
local a = Vector3.new(3.1, 4.7, 5.99999)
|
||||
|
||||
local result = a:snap_to(3)
|
||||
assert.are.same(
|
||||
Vector3.new(3, 6, 6),
|
||||
result
|
||||
)
|
||||
assert.are_not.equal(result, a)
|
||||
end)
|
||||
end)
|
44
.tests/Vector3/sort_pos.test.lua
Normal file
|
@ -0,0 +1,44 @@
|
|||
local Vector3 = require("worldeditadditions_core.utils.vector3")
|
||||
|
||||
describe("Vector3.sort", function()
|
||||
it("should work with positive vectors", function()
|
||||
local a = Vector3.new(16, 64, 16)
|
||||
local b = Vector3.new(1, 4, 6)
|
||||
|
||||
local result_a, result_b = Vector3.sort(a, b)
|
||||
assert.are.same(Vector3.new(1, 4, 6), result_a)
|
||||
assert.are.same(Vector3.new(16, 64, 16), result_b)
|
||||
end)
|
||||
it("should work with mixed components", function()
|
||||
local a = Vector3.new(16, 1, 16)
|
||||
local b = Vector3.new(1, 4, 60)
|
||||
|
||||
local result_a, result_b = Vector3.sort(a, b)
|
||||
assert.are.same(Vector3.new(1, 1, 16), result_a)
|
||||
assert.are.same(Vector3.new(16, 4, 60), result_b)
|
||||
end)
|
||||
it("should work with negative vectors", function()
|
||||
local a = Vector3.new(-9, -16, -25)
|
||||
local b = Vector3.new(-3, -6, -2)
|
||||
|
||||
local result_a, result_b = Vector3.sort(a, b)
|
||||
assert.are.same(Vector3.new(-9, -16, -25), result_a)
|
||||
assert.are.same(Vector3.new(-3, -6, -2), result_b)
|
||||
end)
|
||||
it("should return new Vector3 instances", function()
|
||||
local a = Vector3.new(16, 1, 16)
|
||||
local b = Vector3.new(1, 4, 60)
|
||||
|
||||
local result_a, result_b = Vector3.sort(a, b)
|
||||
assert.are.same(Vector3.new(1, 1, 16), result_a)
|
||||
assert.are.same(Vector3.new(16, 4, 60), result_b)
|
||||
|
||||
result_a.y = 999
|
||||
result_b.y = 999
|
||||
|
||||
assert.are.same(Vector3.new(16, 1, 16), a)
|
||||
assert.are.same(Vector3.new(1, 4, 60), b)
|
||||
assert.are.same(Vector3.new(1, 999, 16), result_a)
|
||||
assert.are.same(Vector3.new(16, 999, 60), result_b)
|
||||
end)
|
||||
end)
|
28
.tests/Vector3/sqrt.test.lua
Normal file
|
@ -0,0 +1,28 @@
|
|||
local Vector3 = require("worldeditadditions_core.utils.vector3")
|
||||
|
||||
describe("Vector3.sqrt", function()
|
||||
it("should sqrt a positive vector", function()
|
||||
local a = Vector3.new(16, 64, 16)
|
||||
assert.are.same(
|
||||
Vector3.new(4, 8, 4),
|
||||
a:sqrt()
|
||||
)
|
||||
end)
|
||||
it("should sqrt another positive vector", function()
|
||||
local a = Vector3.new(9, 16, 25)
|
||||
assert.are.same(
|
||||
Vector3.new(3, 4, 5),
|
||||
a:sqrt()
|
||||
)
|
||||
end)
|
||||
it("should return a new Vector3 instance", function()
|
||||
local a = Vector3.new(9, 16, 25)
|
||||
|
||||
local result = a:sqrt()
|
||||
assert.are.same(
|
||||
Vector3.new(3, 4, 5),
|
||||
result
|
||||
)
|
||||
assert.are_not.equal(result, a)
|
||||
end)
|
||||
end)
|
80
.tests/Vector3/subtract.test.lua
Normal file
|
@ -0,0 +1,80 @@
|
|||
local Vector3 = require("worldeditadditions_core.utils.vector3")
|
||||
|
||||
describe("Vector3.subtract", function()
|
||||
it("should subtract 2 positive vectors", function()
|
||||
local a = Vector3.new(3, 4, 5)
|
||||
local b = Vector3.new(1, 1, 1)
|
||||
assert.are.same(
|
||||
Vector3.new(2, 3, 4),
|
||||
a:subtract(b)
|
||||
)
|
||||
end)
|
||||
it("should work with the sub alias", function()
|
||||
local a = Vector3.new(3, 4, 5)
|
||||
local b = Vector3.new(1, 1, 1)
|
||||
assert.are.same(
|
||||
Vector3.new(2, 3, 4),
|
||||
a:sub(b)
|
||||
)
|
||||
end)
|
||||
it("should work with scalar a", function()
|
||||
local a = 2
|
||||
local b = Vector3.new(6, 7, 8)
|
||||
assert.are.same(
|
||||
Vector3.new(4, 5, 6),
|
||||
a - b
|
||||
)
|
||||
end)
|
||||
it("should work with scalar b", function()
|
||||
local a = Vector3.new(6, 7, 8)
|
||||
local b = 2
|
||||
assert.are.same(
|
||||
Vector3.new(4, 5, 6),
|
||||
a - b
|
||||
)
|
||||
end)
|
||||
it("should support the subtract operator", function()
|
||||
local a = Vector3.new(3, 4, 5)
|
||||
local b = Vector3.new(1, 1, 1)
|
||||
assert.are.same(
|
||||
Vector3.new(2, 3, 4),
|
||||
a - b
|
||||
)
|
||||
end)
|
||||
it("should handle negative b", function()
|
||||
local a = Vector3.new(3, 4, 5)
|
||||
local b = Vector3.new(-1, -1, -1)
|
||||
assert.are.same(
|
||||
Vector3.new(4, 5, 6),
|
||||
a - b
|
||||
)
|
||||
end)
|
||||
it("should handle negative a", function()
|
||||
local a = Vector3.new(-3, -4, -5)
|
||||
local b = Vector3.new(1, 1, 1)
|
||||
assert.are.same(
|
||||
Vector3.new(-4, -5, -6),
|
||||
a - b
|
||||
)
|
||||
end)
|
||||
it("should handle negative a and b", function()
|
||||
local a = Vector3.new(-3, -4, -5)
|
||||
local b = Vector3.new(-1, -1, -1)
|
||||
assert.are.same(
|
||||
Vector3.new(-2, -3, -4),
|
||||
a - b
|
||||
)
|
||||
end)
|
||||
it("should return a new Vector3 instance", function()
|
||||
local a = Vector3.new(3, 4, 5)
|
||||
local b = Vector3.new(1, 1, 1)
|
||||
|
||||
local result = a - b
|
||||
assert.are.same(
|
||||
Vector3.new(2, 3, 4),
|
||||
result
|
||||
)
|
||||
assert.are_not.equal(result, a)
|
||||
assert.are_not.equal(result, b)
|
||||
end)
|
||||
end)
|
39
.tests/Vector3/tostring.test.lua
Normal file
|
@ -0,0 +1,39 @@
|
|||
local Vector3 = require("worldeditadditions_core.utils.vector3")
|
||||
|
||||
describe("Vector3.__tostring", function()
|
||||
it("should stringify a Vector3", function()
|
||||
local a = Vector3.new(3, 4, 5)
|
||||
assert.are.same(
|
||||
"(3, 4, 5)",
|
||||
a:__tostring()
|
||||
)
|
||||
end)
|
||||
it("should implicitly stringify a Vector3", function()
|
||||
local a = Vector3.new(3, 4, 5)
|
||||
assert.are.same(
|
||||
"(3, 4, 5)",
|
||||
tostring(a)
|
||||
)
|
||||
end)
|
||||
it("should implicitly stringify another Vector3", function()
|
||||
local a = Vector3.new(55, 77, 22)
|
||||
assert.are.same(
|
||||
"(55, 77, 22)",
|
||||
tostring(a)
|
||||
)
|
||||
end)
|
||||
it("should handle negative numbers", function()
|
||||
local a = Vector3.new(-1, -2, -3)
|
||||
assert.are.same(
|
||||
"(-1, -2, -3)",
|
||||
tostring(a)
|
||||
)
|
||||
end)
|
||||
it("should handle a mix of positive and negative numbers", function()
|
||||
local a = Vector3.new(-7, 2, -99)
|
||||
assert.are.same(
|
||||
"(-7, 2, -99)",
|
||||
tostring(a)
|
||||
)
|
||||
end)
|
||||
end)
|
37
.tests/Vector3/unit.test.lua
Normal file
|
@ -0,0 +1,37 @@
|
|||
local Vector3 = require("worldeditadditions_core.utils.vector3")
|
||||
|
||||
-- To find these numbers, in Javascript:
|
||||
-- function t(x) { return Math.sqrt((x*x)*3); }
|
||||
-- for(let i = 0; i < 1000000000; i++) { let r = t(i); if(Math.floor(r) === r) console.log(`i ${i}, r ${r}`); }
|
||||
|
||||
|
||||
describe("Vector3.unit", function()
|
||||
it("should work with a positive vector", function()
|
||||
local a = Vector3.new(10, 10, 10)
|
||||
assert.are.same(
|
||||
Vector3.new(57735, 57735, 57735),
|
||||
a:unit():multiply(100000):floor()
|
||||
)
|
||||
end)
|
||||
it("should work with a the normalise alias", function()
|
||||
local a = Vector3.new(10, 10, 10)
|
||||
assert.are.same(
|
||||
Vector3.new(57735, 57735, 57735),
|
||||
a:normalise():multiply(100000):floor()
|
||||
)
|
||||
end)
|
||||
it("should work with a negative vector", function()
|
||||
local a = Vector3.new(10, 10, 10)
|
||||
assert.are.same(
|
||||
Vector3.new(57735, 57735, 57735),
|
||||
a:unit():multiply(100000):floor()
|
||||
)
|
||||
end)
|
||||
it("should work with a mixed vector", function()
|
||||
local a = Vector3.new(-371635731, 371635731, -371635731)
|
||||
assert.are.same(
|
||||
Vector3.new(-57736, 57735, -57736),
|
||||
a:unit():multiply(100000):floor()
|
||||
)
|
||||
end)
|
||||
end)
|
44
.tests/Vector3/volume.test.lua
Normal file
|
@ -0,0 +1,44 @@
|
|||
local Vector3 = require("worldeditadditions_core.utils.vector3")
|
||||
|
||||
describe("Vector3.volume", function()
|
||||
it("should work", function()
|
||||
local a = Vector3.new(4, 4, 4)
|
||||
local b = Vector3.new(8, 8, 8)
|
||||
assert.are.equal(
|
||||
64,
|
||||
Vector3.volume(a, b)
|
||||
)
|
||||
end)
|
||||
it("should work the other way around", function()
|
||||
local a = Vector3.new(4, 4, 4)
|
||||
local b = Vector3.new(8, 8, 8)
|
||||
assert.are.equal(
|
||||
64,
|
||||
Vector3.volume(b, a)
|
||||
)
|
||||
end)
|
||||
it("should work with negative values", function()
|
||||
local a = Vector3.new(-4, -4, -4)
|
||||
local b = Vector3.new(-8, -8, -8)
|
||||
assert.are.equal(
|
||||
64,
|
||||
Vector3.volume(a, b)
|
||||
)
|
||||
end)
|
||||
it("should work with different values", function()
|
||||
local a = Vector3.new(5, 6, 7)
|
||||
local b = Vector3.new(10, 10, 10)
|
||||
assert.are.equal(
|
||||
60,
|
||||
Vector3.volume(a, b)
|
||||
)
|
||||
end)
|
||||
it("should work with mixed values", function()
|
||||
local a = Vector3.new(10, 5, 8)
|
||||
local b = Vector3.new(5, 10, 2)
|
||||
assert.are.equal(
|
||||
150,
|
||||
Vector3.volume(a, b)
|
||||
)
|
||||
end)
|
||||
end)
|
158
.tests/parse/axes/axes_parser.test.lua
Normal file
|
@ -0,0 +1,158 @@
|
|||
local Vector3 = require("worldeditadditions_core.utils.vector3")
|
||||
|
||||
local facing_dirs = dofile("./.tests/parse/axes/include_facing_dirs.lua")
|
||||
|
||||
local parse = require("worldeditadditions_core.utils.parse.axes_parser")
|
||||
local parse_axes = parse.keytable
|
||||
|
||||
|
||||
describe("parse_axes", function()
|
||||
|
||||
-- Basic tests
|
||||
it("should work on single horizontal axes", function()
|
||||
local minv, maxv = parse_axes({
|
||||
"x", "3",
|
||||
"-z", "10",
|
||||
}, facing_dirs.x_pos)
|
||||
assert.is.truthy(minv)
|
||||
assert.are.same(Vector3.new(0, 0, -10), minv)
|
||||
assert.are.same(Vector3.new(3, 0, 0), maxv)
|
||||
end)
|
||||
|
||||
it("should handle axis clumps and orphan (universal) values", function()
|
||||
local minv, maxv = parse_axes({
|
||||
"xz", "-3",
|
||||
"10",
|
||||
}, facing_dirs.x_pos)
|
||||
assert.is.truthy(minv)
|
||||
assert.are.same(Vector3.new(-3, 0, -3), minv)
|
||||
assert.are.same(Vector3.new(10, 10, 10), maxv)
|
||||
end)
|
||||
|
||||
it("should work on directions and their abriviations", function()
|
||||
local minv, maxv = parse_axes({
|
||||
"l", "3", -- +z
|
||||
"-r", "-3", -- +z
|
||||
"b", "-10", -- -x
|
||||
}, facing_dirs.x_pos)
|
||||
assert.is.truthy(minv)
|
||||
assert.are.same(Vector3.new(0, 0, -3), minv)
|
||||
assert.are.same(Vector3.new(10, 0, 3), maxv)
|
||||
end)
|
||||
|
||||
it("should work with compass directions and their abriviations", function()
|
||||
local minv, maxv = parse_axes({
|
||||
"n", "3", -- +z
|
||||
"south", "3", -- -z
|
||||
"-west", "10", -- +x
|
||||
}, facing_dirs.x_pos)
|
||||
assert.is.truthy(minv)
|
||||
assert.are.same(Vector3.new(0, 0, -3), minv)
|
||||
assert.are.same(Vector3.new(10, 0, 3), maxv)
|
||||
end)
|
||||
|
||||
it("should work with ?", function()
|
||||
local minv, maxv = parse_axes({
|
||||
"?", "3", -- -z
|
||||
}, facing_dirs.z_neg)
|
||||
assert.is.truthy(minv)
|
||||
assert.are.same(Vector3.new(0, 0, -3), minv)
|
||||
assert.are.same(Vector3.new(0, 0, 0), maxv)
|
||||
end)
|
||||
|
||||
it("should work with complex relative / absolute combinations", function()
|
||||
local minv, maxv = parse_axes({
|
||||
"f", "3", -- +x
|
||||
"left", "10", -- +z
|
||||
"y", "77",
|
||||
"x", "30",
|
||||
"back", "99",
|
||||
}, facing_dirs.x_pos)
|
||||
assert.is.truthy(minv)
|
||||
assert.are.same(Vector3.new(-99, 0, 0), minv)
|
||||
assert.are.same(Vector3.new(33, 77, 10), maxv)
|
||||
end)
|
||||
|
||||
it("should work with complex relative / absolute combinations with negative facing_dirs", function()
|
||||
local minv, maxv = parse_axes({
|
||||
"f", "3", -- -z
|
||||
"l", "10", -- +x
|
||||
"y", "77",
|
||||
"x", "30",
|
||||
"b", "99", -- +z
|
||||
}, facing_dirs.z_neg)
|
||||
assert.is.truthy(minv)
|
||||
assert.are.same(Vector3.new(0, 0, -3), minv)
|
||||
assert.are.same(Vector3.new(40, 77, 99), maxv)
|
||||
end)
|
||||
|
||||
it("should return 2 0,0,0 vectors if no input", function()
|
||||
local minv, maxv = parse_axes({
|
||||
-- No input
|
||||
}, facing_dirs.z_neg)
|
||||
assert.is.truthy(minv)
|
||||
assert.are.same(Vector3.new(0, 0, 0), minv)
|
||||
assert.are.same(Vector3.new(0, 0, 0), maxv)
|
||||
end)
|
||||
|
||||
-- Options tests
|
||||
it("should mirror the max values of the two vectors if mirroring keyword is present", function()
|
||||
local minv, maxv = parse_axes({
|
||||
"x", "3",
|
||||
"f", "-5", -- +x
|
||||
"z", "-10",
|
||||
"mir",
|
||||
}, facing_dirs.x_pos)
|
||||
assert.is.truthy(minv)
|
||||
assert.are.same(Vector3.new(-5, 0, -10), minv)
|
||||
assert.are.same(Vector3.new(5, 0, 10), maxv)
|
||||
end)
|
||||
|
||||
it("should return a single vector if 'sum' input is truthy", function()
|
||||
local minv, maxv = parse_axes({
|
||||
"x", "3",
|
||||
"z", "-10",
|
||||
}, facing_dirs.x_pos,"sum")
|
||||
assert.is.truthy(minv)
|
||||
assert.are.same(Vector3.new(3, 0, -10), minv)
|
||||
assert.are.same(nil, maxv)
|
||||
end)
|
||||
|
||||
it("should dissable mirroring if 'sum' input is truthy", function()
|
||||
local minv, maxv = parse_axes({
|
||||
"x", "3",
|
||||
"f", "-5", -- +x
|
||||
"z", "-10",
|
||||
"sym",
|
||||
}, facing_dirs.x_pos,"sum")
|
||||
assert.is.truthy(minv)
|
||||
assert.are.same(Vector3.new(-2, 0, -10), minv)
|
||||
assert.are.same(nil, maxv)
|
||||
end)
|
||||
|
||||
-- Error tests
|
||||
it("should return error if bad axis/dir", function()
|
||||
local minv, maxv = parse_axes({
|
||||
"f", "3", -- +x
|
||||
"lift", "10", -- Invalid axis
|
||||
"y", "77",
|
||||
"x", "30",
|
||||
"back", "99", -- -x
|
||||
}, facing_dirs.x_pos)
|
||||
assert.are.same(false, minv)
|
||||
assert.are.same("string", type(maxv))
|
||||
end)
|
||||
|
||||
it("should return error if bad value", function()
|
||||
local minv, maxv = parse_axes({
|
||||
"f", "3", -- +x
|
||||
"left", "10", -- +z
|
||||
"y", "!Q", -- Invalid value
|
||||
"x", "30",
|
||||
"back", "99",
|
||||
}, facing_dirs.x_pos)
|
||||
assert.are.same(false, minv)
|
||||
assert.are.same("string", type(maxv))
|
||||
end)
|
||||
|
||||
end)
|
142
.tests/parse/axes/include_facing_dirs.lua
Normal file
|
@ -0,0 +1,142 @@
|
|||
local z_pos = {
|
||||
right = {
|
||||
axis = "x",
|
||||
sign = 1
|
||||
},
|
||||
x = 0.30876246094704,
|
||||
y = -0.22614130377769,
|
||||
up = {
|
||||
axis = "y",
|
||||
sign = 1
|
||||
},
|
||||
left = {
|
||||
axis = "x",
|
||||
sign = -1
|
||||
},
|
||||
back = {
|
||||
axis = "z",
|
||||
sign = -1
|
||||
},
|
||||
front = {
|
||||
axis = "z",
|
||||
sign = 1
|
||||
},
|
||||
down = {
|
||||
axis = "y",
|
||||
sign = -1
|
||||
},
|
||||
z = 0.92386466264725,
|
||||
facing = {
|
||||
axis = "z",
|
||||
sign = 1
|
||||
}
|
||||
}
|
||||
|
||||
local x_pos = {
|
||||
right = {
|
||||
axis = "z",
|
||||
sign = -1
|
||||
},
|
||||
x = 0.9800808429718,
|
||||
y = -0.095324546098709,
|
||||
up = {
|
||||
axis = "y",
|
||||
sign = 1
|
||||
},
|
||||
left = {
|
||||
axis = "z",
|
||||
sign = 1
|
||||
},
|
||||
back = {
|
||||
axis = "x",
|
||||
sign = -1
|
||||
},
|
||||
front = {
|
||||
axis = "x",
|
||||
sign = 1
|
||||
},
|
||||
down = {
|
||||
axis = "y",
|
||||
sign = -1
|
||||
},
|
||||
z = -0.17422623932362,
|
||||
facing = {
|
||||
axis = "x",
|
||||
sign = 1
|
||||
}
|
||||
}
|
||||
|
||||
local z_neg = {
|
||||
right = {
|
||||
axis = "x",
|
||||
sign = -1
|
||||
},
|
||||
x = -0.29956161975861,
|
||||
y = -0.16453117132187,
|
||||
up = {
|
||||
axis = "y",
|
||||
sign = 1,
|
||||
},
|
||||
left = {
|
||||
axis = "x",
|
||||
sign = 1,
|
||||
},
|
||||
back = {
|
||||
axis = "z",
|
||||
sign = 1
|
||||
},
|
||||
front = {
|
||||
axis = "z",
|
||||
sign = -1
|
||||
},
|
||||
down = {
|
||||
axis = "y",
|
||||
sign = -1
|
||||
},
|
||||
z = -0.93978309631348,
|
||||
facing = {
|
||||
axis = "z",
|
||||
sign = -1
|
||||
}
|
||||
}
|
||||
|
||||
local x_neg = {
|
||||
right = {
|
||||
axis = "z",
|
||||
sign = 1
|
||||
},
|
||||
x = -0.96041119098663,
|
||||
y = -0.20227454602718,
|
||||
up = {
|
||||
axis = "y",
|
||||
sign = 1
|
||||
},
|
||||
left = {
|
||||
axis = "z",
|
||||
sign = -1
|
||||
},
|
||||
back = {
|
||||
axis = "x",
|
||||
sign = 1
|
||||
},
|
||||
front = {
|
||||
axis = "x",
|
||||
sign = -1
|
||||
},
|
||||
down = {
|
||||
axis = "y",
|
||||
sign = -1
|
||||
},
|
||||
z = 0.19156044721603,
|
||||
facing = {
|
||||
axis = "x",
|
||||
sign = -1
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
x_pos = x_pos,
|
||||
z_pos = z_pos,
|
||||
x_neg = x_neg,
|
||||
z_neg = z_neg
|
||||
}
|
104
.tests/parse/axes/parse_abs_axis_name.test.lua
Normal file
|
@ -0,0 +1,104 @@
|
|||
local Vector3 = require("worldeditadditions_core.utils.vector3")
|
||||
|
||||
local axes = require("worldeditadditions_core.utils.parse.axes")
|
||||
local parse_abs_axis_name = axes.parse_abs_axis_name
|
||||
|
||||
|
||||
describe("parse_abs_axis_name", function()
|
||||
it("should work with positive x", function()
|
||||
local success, result = parse_abs_axis_name("x")
|
||||
assert.is_true(success)
|
||||
assert.are.same(
|
||||
Vector3.new(1, 0, 0),
|
||||
result
|
||||
)
|
||||
end)
|
||||
it("should work with negative x", function()
|
||||
local success, result = parse_abs_axis_name("-x")
|
||||
assert.is_true(success)
|
||||
assert.are.same(
|
||||
Vector3.new(-1, 0, 0),
|
||||
result
|
||||
)
|
||||
end)
|
||||
it("should work with positive y", function()
|
||||
local success, result = parse_abs_axis_name("y")
|
||||
assert.is_true(success)
|
||||
assert.are.same(
|
||||
Vector3.new(0, 1, 0),
|
||||
result
|
||||
)
|
||||
end)
|
||||
it("should work with negative y", function()
|
||||
local success, result = parse_abs_axis_name("-y")
|
||||
assert.is_true(success)
|
||||
assert.are.same(
|
||||
Vector3.new(0, -1, 0),
|
||||
result
|
||||
)
|
||||
end)
|
||||
it("should work with positive z", function()
|
||||
local success, result = parse_abs_axis_name("z")
|
||||
assert.is_true(success)
|
||||
assert.are.same(
|
||||
Vector3.new(0, 0, 1),
|
||||
result
|
||||
)
|
||||
end)
|
||||
it("should work with negative z", function()
|
||||
local success, result = parse_abs_axis_name("-z")
|
||||
assert.is_true(success)
|
||||
assert.are.same(
|
||||
Vector3.new(0, 0, -1),
|
||||
result
|
||||
)
|
||||
end)
|
||||
it("should work with multiple axes -x y", function()
|
||||
local success, result = parse_abs_axis_name("-xy")
|
||||
assert.is_true(success)
|
||||
assert.are.same(
|
||||
Vector3.new(-1, 1, 0),
|
||||
result
|
||||
)
|
||||
end)
|
||||
it("should work with multiple axes z-y", function()
|
||||
local success, result = parse_abs_axis_name("z-y")
|
||||
assert.is_true(success)
|
||||
assert.are.same(
|
||||
Vector3.new(0, -1, 1),
|
||||
result
|
||||
)
|
||||
end)
|
||||
it("returns an error with invalid input", function()
|
||||
local success, result = parse_abs_axis_name("cheese")
|
||||
assert.is_false(success)
|
||||
assert.are.same(
|
||||
"string",
|
||||
type(result)
|
||||
)
|
||||
end)
|
||||
it("returns an error with no input", function()
|
||||
local success, result = parse_abs_axis_name()
|
||||
assert.is_false(success)
|
||||
assert.are.same(
|
||||
"string",
|
||||
type(result)
|
||||
)
|
||||
end)
|
||||
it("returns an error with input of the wrong type", function()
|
||||
local success, result = parse_abs_axis_name(5)
|
||||
assert.is_false(success)
|
||||
assert.are.same(
|
||||
"string",
|
||||
type(result)
|
||||
)
|
||||
end)
|
||||
it("returns an error with input of the wrong type again", function()
|
||||
local success, result = parse_abs_axis_name({ "yay", "tests are very useful" })
|
||||
assert.is_false(success)
|
||||
assert.are.same(
|
||||
"string",
|
||||
type(result)
|
||||
)
|
||||
end)
|
||||
end)
|
250
.tests/parse/axes/parse_axes.test.lua
Normal file
|
@ -0,0 +1,250 @@
|
|||
local Vector3 = require("worldeditadditions_core.utils.vector3")
|
||||
|
||||
local facing_dirs = dofile("./.tests/parse/axes/include_facing_dirs.lua")
|
||||
|
||||
local axes = require("worldeditadditions_core.utils.parse.axes")
|
||||
local parse_axes = axes.parse_axes
|
||||
|
||||
--[[ Original idea for how this function was supposed to work from @VorTechnix
|
||||
-- It's changed a bit to make it more testable
|
||||
parse_axes("6",name) == return Vector3.new(6,6,6), Vector3.new(-6,-6,-6)
|
||||
parse_axes("h 4",name) == return Vector3.new(4,0,4), Vector3.new(-4,0,-4)
|
||||
parse_axes("v 4",name) == return Vector3.new(0,4,0), Vector3.new(0,-4,0)
|
||||
parse_axes("-x 4 z 3 5",name) == return Vector3.new(0,0,3), Vector3.new(-4,0,-5)
|
||||
parse_axes("x -10 y 14 true",name) == return Vector3.new(0,14,0), Vector3.new(-10,-14,0)
|
||||
parse_axes("x -10 y 14 r",name) == return Vector3.new(0,14,0), Vector3.new(-10,-14,0)
|
||||
parse_axes("x -10 y 14 rev",name) == return Vector3.new(0,14,0), Vector3.new(-10,-14,0)
|
||||
|
||||
-- Assuming player is facing +Z (north)
|
||||
parse_axes("front 4 y 2 r",name) == return Vector3.new(0,2,4), Vector3.new(0,-2,0)
|
||||
parse_axes("right 4 y 2 r",name) == return Vector3.new(0,2,0), Vector3.new(-4,-2,0)
|
||||
]]--
|
||||
|
||||
|
||||
describe("parse_axes", function()
|
||||
it("should work with complex relative / absolute combinations", function()
|
||||
local success, pos1, pos2 = parse_axes({
|
||||
"front", "3", -- +x
|
||||
"left", "10", -- +z
|
||||
"y", "77",
|
||||
"x", "30",
|
||||
"back", "99"
|
||||
}, facing_dirs.x_pos)
|
||||
assert.is_true(success)
|
||||
assert.are.same(Vector3.new(-99, 0, 0), pos1)
|
||||
assert.are.same(Vector3.new(33, 77, 10), pos2)
|
||||
end)
|
||||
it("should work with complex relative / absolute combinations with other facing_dirs", function()
|
||||
local success, pos1, pos2 = parse_axes({
|
||||
"front", "3", -- +x
|
||||
"left", "10", -- +z
|
||||
"y", "77",
|
||||
"x", "30",
|
||||
"back", "99"
|
||||
}, facing_dirs.z_neg)
|
||||
assert.is_true(success)
|
||||
assert.are.same(Vector3.new(0, 0, -3), pos1)
|
||||
assert.are.same(Vector3.new(40, 77, 99), pos2)
|
||||
end)
|
||||
|
||||
it("should work with ?", function()
|
||||
local success, pos1, pos2 = parse_axes({
|
||||
"?", "3"
|
||||
}, facing_dirs.x_pos)
|
||||
assert.is_true(success)
|
||||
assert.are.same(Vector3.new(0, 0, 0), pos1)
|
||||
assert.are.same(Vector3.new(3, 0, 0), pos2)
|
||||
end)
|
||||
|
||||
|
||||
it("should work with positive y / positive value", function()
|
||||
local success, pos1, pos2 = parse_axes({ "y", "17" }, facing_dirs.x_pos)
|
||||
assert.is_true(success)
|
||||
assert.are.same(Vector3.new(0, 0, 0), pos1)
|
||||
assert.are.same(Vector3.new(0, 17, 0), pos2)
|
||||
end)
|
||||
it("should work with positive y / negative value", function()
|
||||
local success, pos1, pos2 = parse_axes({ "y", "-6" }, facing_dirs.x_pos)
|
||||
assert.is_true(success)
|
||||
assert.are.same(Vector3.new(0, -6, 0), pos1)
|
||||
assert.are.same(Vector3.new(0, 0, 0), pos2)
|
||||
end)
|
||||
it("should work with negative y / positive value", function()
|
||||
local success, pos1, pos2 = parse_axes({ "-y", "17" }, facing_dirs.x_pos)
|
||||
assert.is_true(success)
|
||||
assert.are.same(Vector3.new(0, -17, 0), pos1)
|
||||
assert.are.same(Vector3.new(0, 0, 0), pos2)
|
||||
end)
|
||||
it("should work with negative y / negative value", function()
|
||||
local success, pos1, pos2 = parse_axes({ "-y", "-6" }, facing_dirs.x_pos)
|
||||
assert.is_true(success)
|
||||
assert.are.same(Vector3.new(0, 0, 0), pos1)
|
||||
assert.are.same(Vector3.new(0, 6, 0), pos2)
|
||||
end)
|
||||
|
||||
|
||||
it("should work with positive x / positive value", function()
|
||||
local success, pos1, pos2 = parse_axes({ "x", "1" }, facing_dirs.x_pos)
|
||||
assert.is_true(success)
|
||||
assert.are.same(Vector3.new(0, 0, 0), pos1)
|
||||
assert.are.same(Vector3.new(1, 0, 0), pos2)
|
||||
end)
|
||||
it("should work with positive x / big positive value", function()
|
||||
local success, pos1, pos2 = parse_axes({ "x", "99" }, facing_dirs.x_pos)
|
||||
assert.is_true(success)
|
||||
assert.are.same(Vector3.new(0, 0, 0), pos1)
|
||||
assert.are.same(Vector3.new(99, 0, 0), pos2)
|
||||
end)
|
||||
it("should work with positive x / negative value", function()
|
||||
local success, pos1, pos2 = parse_axes({ "x", "-1" }, facing_dirs.x_pos)
|
||||
assert.is_true(success)
|
||||
assert.are.same(Vector3.new(-1, 0, 0), pos1)
|
||||
assert.are.same(Vector3.new(0, 0, 0), pos2)
|
||||
end)
|
||||
it("should work with positive z / positive value", function()
|
||||
local success, pos1, pos2 = parse_axes({ "z", "1" }, facing_dirs.x_pos)
|
||||
assert.is_true(success)
|
||||
assert.are.same(Vector3.new(0, 0, 0), pos1)
|
||||
assert.are.same(Vector3.new(0, 0, 1), pos2)
|
||||
end)
|
||||
it("should work with positive z / negative value", function()
|
||||
local success, pos1, pos2 = parse_axes({ "z", "-1" }, facing_dirs.x_pos)
|
||||
assert.is_true(success)
|
||||
assert.are.same(Vector3.new(0, 0, -1), pos1)
|
||||
assert.are.same(Vector3.new(0, 0, 0), pos2)
|
||||
end)
|
||||
it("should work with multiple positive axes / positive values", function()
|
||||
local success, pos1, pos2 = parse_axes({ "x", "14", "z", "3" }, facing_dirs.x_pos)
|
||||
assert.is_true(success)
|
||||
assert.are.same(Vector3.new(0, 0, 0), pos1)
|
||||
assert.are.same(Vector3.new(14, 0, 3), pos2)
|
||||
end)
|
||||
it("should work with multiple positive axes / negative values", function()
|
||||
local success, pos1, pos2 = parse_axes({ "x", "-16", "z", "-9" }, facing_dirs.x_pos)
|
||||
assert.is_true(success)
|
||||
assert.are.same(Vector3.new(-16, 0, -9), pos1)
|
||||
assert.are.same(Vector3.new(0, 0, 0), pos2)
|
||||
end)
|
||||
|
||||
it("should work with negative x / positive value", function()
|
||||
local success, pos1, pos2 = parse_axes({ "-x", "1" }, facing_dirs.x_pos)
|
||||
assert.is_true(success)
|
||||
assert.are.same(Vector3.new(-1, 0, 0), pos1)
|
||||
assert.are.same(Vector3.new(0, 0, 0), pos2)
|
||||
end)
|
||||
it("should work with negative x / big positive value", function()
|
||||
local success, pos1, pos2 = parse_axes({ "-x", "99" }, facing_dirs.x_pos)
|
||||
assert.is_true(success)
|
||||
assert.are.same(Vector3.new(-99, 0, 0), pos1)
|
||||
assert.are.same(Vector3.new(0, 0, 0), pos2)
|
||||
end)
|
||||
it("should work with negative x / negative value", function()
|
||||
local success, pos1, pos2 = parse_axes({ "-x", "-3" }, facing_dirs.x_pos)
|
||||
assert.is_true(success)
|
||||
assert.are.same(Vector3.new(0, 0, 0), pos1)
|
||||
assert.are.same(Vector3.new(3, 0, 0), pos2)
|
||||
end)
|
||||
it("should work with negative z / positive value", function()
|
||||
local success, pos1, pos2 = parse_axes({ "-z", "6" }, facing_dirs.x_pos)
|
||||
assert.is_true(success)
|
||||
assert.are.same(Vector3.new(0, 0, -6), pos1)
|
||||
assert.are.same(Vector3.new(0, 0, 0), pos2)
|
||||
end)
|
||||
it("should work with negative z / negative value", function()
|
||||
local success, pos1, pos2 = parse_axes({ "-z", "-4" }, facing_dirs.x_pos)
|
||||
assert.is_true(success)
|
||||
assert.are.same(Vector3.new(0, 0, 0), pos1)
|
||||
assert.are.same(Vector3.new(0, 0, 4), pos2)
|
||||
end)
|
||||
it("should work with multiple negative axes / positive values", function()
|
||||
local success, pos1, pos2 = parse_axes({ "-x", "14", "z", "-3" }, facing_dirs.x_pos)
|
||||
assert.is_true(success)
|
||||
assert.are.same(Vector3.new(-14, 0, -3), pos1)
|
||||
assert.are.same(Vector3.new(0, 0, 0), pos2)
|
||||
end)
|
||||
it("should work with multiple negative axes / negative values", function()
|
||||
local success, pos1, pos2 = parse_axes({ "-x", "-16", "-z", "-9" }, facing_dirs.x_pos)
|
||||
assert.is_true(success)
|
||||
assert.are.same(Vector3.new(0, 0, 0), pos1)
|
||||
assert.are.same(Vector3.new(16, 0, 9), pos2)
|
||||
end)
|
||||
|
||||
it("should work with complex multiple positive / negative combinations", function()
|
||||
local success, pos1, pos2 = parse_axes({ "x", "-16", "-x", "10", "-z", "-9", "y", "88" }, facing_dirs.x_pos)
|
||||
assert.is_true(success)
|
||||
assert.are.same(Vector3.new(-26, 0, 0), pos1)
|
||||
assert.are.same(Vector3.new(0, 88, 9), pos2)
|
||||
end)
|
||||
|
||||
it("should work with mirroring too", function()
|
||||
local success, pos1, pos2 = parse_axes({ "x", "6", "sym" }, facing_dirs.x_pos)
|
||||
assert.is_true(success)
|
||||
assert.are.same(Vector3.new(-6, 0, 0), pos1)
|
||||
assert.are.same(Vector3.new(6, 0, 0), pos2)
|
||||
end)
|
||||
|
||||
it("should work with relative mirroring", function()
|
||||
local success, pos1, pos2 = parse_axes({ "front", "2", "mirror" }, facing_dirs.x_pos)
|
||||
assert.is_true(success)
|
||||
assert.are.same(Vector3.new(-2, 0, 0), pos1)
|
||||
assert.are.same(Vector3.new(2, 0, 0), pos2)
|
||||
end)
|
||||
|
||||
it("should work with relative mirroring in a different direction", function()
|
||||
local success, pos1, pos2 = parse_axes({ "back", "7", "rev" }, facing_dirs.z_pos)
|
||||
assert.is_true(success)
|
||||
assert.are.same(Vector3.new(0, 0, -7), pos1)
|
||||
assert.are.same(Vector3.new(0, 0, 7), pos2)
|
||||
end)
|
||||
|
||||
|
||||
|
||||
it("returns an error with invalid token list", function()
|
||||
local success, result = parse_axes("cheese", facing_dirs.z_neg)
|
||||
assert.is_false(success)
|
||||
assert.are.same(
|
||||
"string",
|
||||
type(result)
|
||||
)
|
||||
end)
|
||||
it("returns an error with invalid facing_dir", function()
|
||||
local success, result = parse_axes({ "-x", "1" }, "rocket")
|
||||
assert.is_false(success)
|
||||
assert.are.same(
|
||||
"string",
|
||||
type(result)
|
||||
)
|
||||
end)
|
||||
it("returns an error with no input", function()
|
||||
local success, result = parse_axes()
|
||||
assert.is_false(success)
|
||||
assert.are.same(
|
||||
"string",
|
||||
type(result)
|
||||
)
|
||||
end)
|
||||
it("returns an error with token list of the wrong type", function()
|
||||
local success, result = parse_axes(5, facing_dirs.x_pos)
|
||||
assert.is_false(success)
|
||||
assert.are.same(
|
||||
"string",
|
||||
type(result)
|
||||
)
|
||||
end)
|
||||
it("returns an error with token list of the wrong type again", function()
|
||||
local success, result = parse_axes(false, facing_dirs.x_pos)
|
||||
assert.is_false(success)
|
||||
assert.are.same(
|
||||
"string",
|
||||
type(result)
|
||||
)
|
||||
end)
|
||||
it("returns an error with token of the wrong type in token list", function()
|
||||
local success, result = parse_axes({ "-x", "99", false }, facing_dirs.x_pos)
|
||||
assert.is_false(success)
|
||||
assert.are.same(
|
||||
"string",
|
||||
type(result)
|
||||
)
|
||||
end)
|
||||
end)
|
315
.tests/parse/axes/parse_relative_axis_name.test.lua
Normal file
|
@ -0,0 +1,315 @@
|
|||
local Vector3 = require("worldeditadditions_core.utils.vector3")
|
||||
|
||||
local facing_dirs = dofile("./.tests/parse/axes/include_facing_dirs.lua")
|
||||
|
||||
local axes = require("worldeditadditions_core.utils.parse.axes")
|
||||
local parse_relative_axis_name = axes.parse_relative_axis_name
|
||||
|
||||
|
||||
|
||||
describe("parse_relative_axis_name", function()
|
||||
it("should work with up", function()
|
||||
local success, result = parse_relative_axis_name(
|
||||
"up",
|
||||
facing_dirs.x_pos
|
||||
)
|
||||
assert.is_true(success)
|
||||
assert.are.same(
|
||||
Vector3.new(0, 1, 0),
|
||||
result
|
||||
)
|
||||
end)
|
||||
it("should work with down", function()
|
||||
local success, result = parse_relative_axis_name(
|
||||
"down",
|
||||
facing_dirs.x_pos
|
||||
)
|
||||
assert.is_true(success)
|
||||
assert.are.same(
|
||||
Vector3.new(0, -1, 0),
|
||||
result
|
||||
)
|
||||
end)
|
||||
|
||||
-- ██ ██ ██████ ██████ ███████
|
||||
-- ██ ██ ██ ██ ██ ██ ██
|
||||
-- ███ ██████ ██ ██ ███████
|
||||
-- ██ ██ ██ ██ ██ ██
|
||||
-- ██ ██ ███████ ██ ██████ ███████
|
||||
it("should work with positive x → front", function()
|
||||
local success, result = parse_relative_axis_name(
|
||||
"front",
|
||||
facing_dirs.x_pos
|
||||
)
|
||||
assert.is_true(success)
|
||||
assert.are.same(
|
||||
Vector3.new(1, 0, 0),
|
||||
result
|
||||
)
|
||||
end)
|
||||
it("should work with positive x → ?", function()
|
||||
local success, result = parse_relative_axis_name(
|
||||
"?",
|
||||
facing_dirs.x_pos
|
||||
)
|
||||
assert.is_true(success)
|
||||
assert.are.same(
|
||||
Vector3.new(1, 0, 0),
|
||||
result
|
||||
)
|
||||
end)
|
||||
it("should work with positive x → back", function()
|
||||
local success, result = parse_relative_axis_name(
|
||||
"back",
|
||||
facing_dirs.x_pos
|
||||
)
|
||||
assert.is_true(success)
|
||||
assert.are.same(
|
||||
Vector3.new(-1, 0, 0),
|
||||
result
|
||||
)
|
||||
end)
|
||||
it("should work with positive x → left", function()
|
||||
local success, result = parse_relative_axis_name(
|
||||
"left",
|
||||
facing_dirs.x_pos
|
||||
)
|
||||
assert.is_true(success)
|
||||
assert.are.same(
|
||||
Vector3.new(0, 0, 1),
|
||||
result
|
||||
)
|
||||
end)
|
||||
it("should work with positive x → right", function()
|
||||
local success, result = parse_relative_axis_name(
|
||||
"right",
|
||||
facing_dirs.x_pos
|
||||
)
|
||||
assert.is_true(success)
|
||||
assert.are.same(
|
||||
Vector3.new(0, 0, -1),
|
||||
result
|
||||
)
|
||||
end)
|
||||
|
||||
|
||||
-- ██ ██ ███ ██ ███████ ██████
|
||||
-- ██ ██ ████ ██ ██ ██
|
||||
-- ███ ██ ██ ██ █████ ██ ███
|
||||
-- ██ ██ ██ ██ ██ ██ ██ ██
|
||||
-- ██ ██ ███████ ██ ████ ███████ ██████
|
||||
it("should work with negative x → front", function()
|
||||
local success, result = parse_relative_axis_name(
|
||||
"front",
|
||||
facing_dirs.x_neg
|
||||
)
|
||||
assert.is_true(success)
|
||||
assert.are.same(
|
||||
Vector3.new(-1, 0, 0),
|
||||
result
|
||||
)
|
||||
end)
|
||||
it("should work with negative x → ?", function()
|
||||
local success, result = parse_relative_axis_name(
|
||||
"?",
|
||||
facing_dirs.x_neg
|
||||
)
|
||||
assert.is_true(success)
|
||||
assert.are.same(
|
||||
Vector3.new(-1, 0, 0),
|
||||
result
|
||||
)
|
||||
end)
|
||||
it("should work with negative x → back", function()
|
||||
local success, result = parse_relative_axis_name(
|
||||
"back",
|
||||
facing_dirs.x_neg
|
||||
)
|
||||
assert.is_true(success)
|
||||
assert.are.same(
|
||||
Vector3.new(1, 0, 0),
|
||||
result
|
||||
)
|
||||
end)
|
||||
it("should work with negative x → left", function()
|
||||
local success, result = parse_relative_axis_name(
|
||||
"left",
|
||||
facing_dirs.x_neg
|
||||
)
|
||||
assert.is_true(success)
|
||||
assert.are.same(
|
||||
Vector3.new(0, 0, -1),
|
||||
result
|
||||
)
|
||||
end)
|
||||
it("should work with negative x → right", function()
|
||||
local success, result = parse_relative_axis_name(
|
||||
"right",
|
||||
facing_dirs.x_neg
|
||||
)
|
||||
assert.is_true(success)
|
||||
assert.are.same(
|
||||
Vector3.new(0, 0, 1),
|
||||
result
|
||||
)
|
||||
end)
|
||||
|
||||
|
||||
-- ███████ ██████ ██████ ███████
|
||||
-- ███ ██ ██ ██ ██ ██
|
||||
-- ███ ██████ ██ ██ ███████
|
||||
-- ███ ██ ██ ██ ██
|
||||
-- ███████ ███████ ██ ██████ ███████
|
||||
it("should work with positive z → front", function()
|
||||
local success, result = parse_relative_axis_name(
|
||||
"front",
|
||||
facing_dirs.z_pos
|
||||
)
|
||||
assert.is_true(success)
|
||||
assert.are.same(
|
||||
Vector3.new(0, 0, 1),
|
||||
result
|
||||
)
|
||||
end)
|
||||
it("should work with positive z → ?", function()
|
||||
local success, result = parse_relative_axis_name(
|
||||
"?",
|
||||
facing_dirs.z_pos
|
||||
)
|
||||
assert.is_true(success)
|
||||
assert.are.same(
|
||||
Vector3.new(0, 0, 1),
|
||||
result
|
||||
)
|
||||
end)
|
||||
it("should work with positive z → back", function()
|
||||
local success, result = parse_relative_axis_name(
|
||||
"back",
|
||||
facing_dirs.z_pos
|
||||
)
|
||||
assert.is_true(success)
|
||||
assert.are.same(
|
||||
Vector3.new(0, 0, -1),
|
||||
result
|
||||
)
|
||||
end)
|
||||
it("should work with positive z → left", function()
|
||||
local success, result = parse_relative_axis_name(
|
||||
"left",
|
||||
facing_dirs.z_pos
|
||||
)
|
||||
assert.is_true(success)
|
||||
assert.are.same(
|
||||
Vector3.new(-1, 0, 0),
|
||||
result
|
||||
)
|
||||
end)
|
||||
it("should work with positive z → right", function()
|
||||
local success, result = parse_relative_axis_name(
|
||||
"right",
|
||||
facing_dirs.z_pos
|
||||
)
|
||||
assert.is_true(success)
|
||||
assert.are.same(
|
||||
Vector3.new(1, 0, 0),
|
||||
result
|
||||
)
|
||||
end)
|
||||
|
||||
|
||||
-- ███████ ███ ██ ███████ ██████
|
||||
-- ███ ████ ██ ██ ██
|
||||
-- ███ ██ ██ ██ █████ ██ ███
|
||||
-- ███ ██ ██ ██ ██ ██ ██
|
||||
-- ███████ ███████ ██ ████ ███████ ██████
|
||||
it("should work with negative z → front", function()
|
||||
local success, result = parse_relative_axis_name(
|
||||
"front",
|
||||
facing_dirs.z_neg
|
||||
)
|
||||
assert.is_true(success)
|
||||
assert.are.same(
|
||||
Vector3.new(0, 0, -1),
|
||||
result
|
||||
)
|
||||
end)
|
||||
it("should work with negative z → ?", function()
|
||||
local success, result = parse_relative_axis_name(
|
||||
"?",
|
||||
facing_dirs.z_neg
|
||||
)
|
||||
assert.is_true(success)
|
||||
assert.are.same(
|
||||
Vector3.new(0, 0, -1),
|
||||
result
|
||||
)
|
||||
end)
|
||||
it("should work with negative z → back", function()
|
||||
local success, result = parse_relative_axis_name(
|
||||
"back",
|
||||
facing_dirs.z_neg
|
||||
)
|
||||
assert.is_true(success)
|
||||
assert.are.same(
|
||||
Vector3.new(0, 0, 1),
|
||||
result
|
||||
)
|
||||
end)
|
||||
it("should work with negative z → left", function()
|
||||
local success, result = parse_relative_axis_name(
|
||||
"left",
|
||||
facing_dirs.z_neg
|
||||
)
|
||||
assert.is_true(success)
|
||||
assert.are.same(
|
||||
Vector3.new(1, 0, 0),
|
||||
result
|
||||
)
|
||||
end)
|
||||
it("should work with negative z → right", function()
|
||||
local success, result = parse_relative_axis_name(
|
||||
"right",
|
||||
facing_dirs.z_neg
|
||||
)
|
||||
assert.is_true(success)
|
||||
assert.are.same(
|
||||
Vector3.new(-1, 0, 0),
|
||||
result
|
||||
)
|
||||
end)
|
||||
|
||||
|
||||
|
||||
it("returns an error with invalid input", function()
|
||||
local success, result = parse_relative_axis_name("cheese")
|
||||
assert.is_false(success)
|
||||
assert.are.same(
|
||||
"string",
|
||||
type(result)
|
||||
)
|
||||
end)
|
||||
it("returns an error with no input", function()
|
||||
local success, result = parse_relative_axis_name()
|
||||
assert.is_false(success)
|
||||
assert.are.same(
|
||||
"string",
|
||||
type(result)
|
||||
)
|
||||
end)
|
||||
it("returns an error with input of the wrong type", function()
|
||||
local success, result = parse_relative_axis_name(5)
|
||||
assert.is_false(success)
|
||||
assert.are.same(
|
||||
"string",
|
||||
type(result)
|
||||
)
|
||||
end)
|
||||
it("returns an error with input of the wrong type again", function()
|
||||
local success, result = parse_relative_axis_name({ "yay", "tests are very useful" })
|
||||
assert.is_false(success)
|
||||
assert.are.same(
|
||||
"string",
|
||||
type(result)
|
||||
)
|
||||
end)
|
||||
end)
|
36
.tests/parse/chance.test.lua
Normal file
|
@ -0,0 +1,36 @@
|
|||
local parse_chance = require("worldeditadditions_core.utils.parse.chance")
|
||||
|
||||
describe("parse.chance", function()
|
||||
it("should work in 1-in-n mode by default", function()
|
||||
local source = "50%"
|
||||
|
||||
assert.are.equal(
|
||||
2,
|
||||
parse_chance(source)
|
||||
)
|
||||
end)
|
||||
it("should work with a different value in 1-in-n mode", function()
|
||||
local source = "25%"
|
||||
|
||||
assert.are.equal(
|
||||
4,
|
||||
parse_chance(source)
|
||||
)
|
||||
end)
|
||||
it("should work in weight mode", function()
|
||||
local source = "50%"
|
||||
|
||||
assert.are.equal(
|
||||
2,
|
||||
parse_chance(source, "weight")
|
||||
)
|
||||
end)
|
||||
it("should work in weight mode with different number", function()
|
||||
local source = "90%"
|
||||
|
||||
assert.are.equal(
|
||||
10,
|
||||
parse_chance(source, "weight")
|
||||
)
|
||||
end)
|
||||
end)
|
122
.tests/parse/map.test.lua
Normal file
|
@ -0,0 +1,122 @@
|
|||
_G.worldeditadditions_core = {
|
||||
split = require("worldeditadditions_core.utils.strings.split"),
|
||||
table = {
|
||||
contains = require("worldeditadditions_core.utils.table.table_contains")
|
||||
}
|
||||
}
|
||||
local parse_map = require("worldeditadditions_core.utils.parse.map")
|
||||
|
||||
describe("parse.map", function()
|
||||
it("should work with a single param", function()
|
||||
local success, result = parse_map("apples yay")
|
||||
assert.are.equal(true, success)
|
||||
assert.are.same(
|
||||
{ apples = "yay" },
|
||||
result
|
||||
)
|
||||
end)
|
||||
it("should work with 2 params", function()
|
||||
local success, result = parse_map("apples yay oranges yummy")
|
||||
assert.are.equal(true, success)
|
||||
assert.are.same(
|
||||
{ apples = "yay", oranges = "yummy" },
|
||||
result
|
||||
)
|
||||
end)
|
||||
it("should work with an int value", function()
|
||||
local success, result = parse_map("apples 2")
|
||||
assert.are.equal(true, success)
|
||||
assert.are.same(
|
||||
{ apples = 2 },
|
||||
result
|
||||
)
|
||||
end)
|
||||
it("should work with a float value", function()
|
||||
local success, result = parse_map("apples 2.71")
|
||||
assert.are.equal(true, success)
|
||||
assert.are.same(
|
||||
{ apples = 2.71 },
|
||||
result
|
||||
)
|
||||
end)
|
||||
it("should work with 2 int values", function()
|
||||
local success, result = parse_map("apples 2 banana 23")
|
||||
assert.are.equal(true, success)
|
||||
assert.are.same(
|
||||
{ apples = 2, banana = 23 },
|
||||
result
|
||||
)
|
||||
end)
|
||||
it("should work with mixed values", function()
|
||||
local success, result = parse_map("apples 2 banana yummy")
|
||||
assert.are.equal(true, success)
|
||||
assert.are.same(
|
||||
{ apples = 2, banana = "yummy" },
|
||||
result
|
||||
)
|
||||
end)
|
||||
it("should work with a value that starts as a number and ends as a string", function()
|
||||
local success, result = parse_map("apples 20t banana yummy")
|
||||
assert.are.equal(true, success)
|
||||
assert.are.same(
|
||||
{ apples = "20t", banana = "yummy" },
|
||||
result
|
||||
)
|
||||
end)
|
||||
it("should work with a value that starts as a string and ends as a number", function()
|
||||
local success, result = parse_map("apples t20 banana yummy")
|
||||
assert.are.equal(true, success)
|
||||
assert.are.same(
|
||||
{ apples = "t20", banana = "yummy" },
|
||||
result
|
||||
)
|
||||
end)
|
||||
it("should work with multiple spaces", function()
|
||||
local success, result = parse_map("apples 2 banana \t yummy")
|
||||
assert.are.equal(true, success)
|
||||
assert.are.same(
|
||||
{ apples = 2, banana = "yummy" },
|
||||
result
|
||||
)
|
||||
end)
|
||||
it("should ignore a hanging item at the end", function()
|
||||
local success, result = parse_map("apples 2 banana")
|
||||
assert.are.equal(true, success)
|
||||
assert.are.same(
|
||||
{ apples = 2 },
|
||||
result
|
||||
)
|
||||
end)
|
||||
it("should work with hanging items declared as keywords at the end", function()
|
||||
local success, result = parse_map("apples 2 banana", { "banana" })
|
||||
assert.are.equal(true, success)
|
||||
assert.are.same(
|
||||
{ apples = 2, banana = true },
|
||||
result
|
||||
)
|
||||
end)
|
||||
it("should work with hanging items declared as keywords in the middle", function()
|
||||
local success, result = parse_map("apples 2 banana pear paris", { "banana" })
|
||||
assert.are.equal(true, success)
|
||||
assert.are.same(
|
||||
{ apples = 2, banana = true, pear = "paris" },
|
||||
result
|
||||
)
|
||||
end)
|
||||
it("should work with some but not other hanging items declared as keywords", function()
|
||||
local success, result = parse_map("apples 2 banana pear paris arrange", { "banana" })
|
||||
assert.are.equal(true, success)
|
||||
assert.are.same(
|
||||
{ apples = 2, banana = true, pear = "paris" },
|
||||
result
|
||||
)
|
||||
end)
|
||||
it("should work with hanging items declared as keywords at the beginning", function()
|
||||
local success, result = parse_map("banana apples 2 pear paris", { "banana" })
|
||||
assert.are.equal(true, success)
|
||||
assert.are.same(
|
||||
{ apples = 2, banana = true, pear = "paris" },
|
||||
result
|
||||
)
|
||||
end)
|
||||
end)
|
24
.tests/parse/seed.test.lua
Normal file
|
@ -0,0 +1,24 @@
|
|||
local parse_seed = require("worldeditadditions_core.utils.parse.seed")
|
||||
|
||||
describe("parse.seed", function()
|
||||
it("should work", function()
|
||||
local source = "a test string"
|
||||
|
||||
local result = parse_seed(source)
|
||||
|
||||
assert.are.equal(
|
||||
"number",
|
||||
type(result)
|
||||
)
|
||||
end)
|
||||
it("should work with a long string", function()
|
||||
local source = "If it looks like a duck and quacks like a duck but it needs batteries, you probably have the wrong abstraction. If it looks like a duck and quacks like a duck but it needs batteries, you probably have the wrong abstraction. If it looks like a duck and quacks like a duck but it needs batteries, you probably have the wrong abstraction. If it looks like a duck and quacks like a duck but it needs batteries, you probably have the wrong abstraction. If it looks like a duck and quacks like a duck but it needs batteries, you probably have the wrong abstraction. If it looks like a duck and quacks like a duck but it needs batteries, you probably have the wrong abstraction. If it looks like a duck and quacks like a duck but it needs batteries, you probably have the wrong abstraction. If it looks like a duck and quacks like a duck but it needs batteries, you probably have the wrong abstraction. If it looks like a duck and quacks like a duck but it needs batteries, you probably have the wrong abstraction."
|
||||
|
||||
local result = parse_seed(source)
|
||||
|
||||
assert.are.equal(
|
||||
"number",
|
||||
type(result)
|
||||
)
|
||||
end)
|
||||
end)
|
32
.tests/parse/table/makeset.test.lua
Normal file
|
@ -0,0 +1,32 @@
|
|||
local makeset = require("worldeditadditions_core.utils.table.makeset")
|
||||
|
||||
describe("table.makeset", function()
|
||||
it("should work with a single item", function()
|
||||
local result = makeset({ "apples" })
|
||||
assert.are.same(
|
||||
{ apples = true },
|
||||
result
|
||||
)
|
||||
end)
|
||||
it("should work with 2 items", function()
|
||||
local result = makeset({ "apples", "orange" })
|
||||
assert.are.same(
|
||||
{ apples = true, orange = true },
|
||||
result
|
||||
)
|
||||
end)
|
||||
it("should work with duplicate items", function()
|
||||
local result = makeset({ "apples", "apples" })
|
||||
assert.are.same(
|
||||
{ apples = true },
|
||||
result
|
||||
)
|
||||
end)
|
||||
it("should work with duplicate items and non-duplicate items", function()
|
||||
local result = makeset({ "apples", "oranges", "apples" })
|
||||
assert.are.same(
|
||||
{ apples = true, oranges = true },
|
||||
result
|
||||
)
|
||||
end)
|
||||
end)
|
48
.tests/parse/table/table_apply.test.lua
Normal file
|
@ -0,0 +1,48 @@
|
|||
local apply = require("worldeditadditions_core.utils.table.table_apply")
|
||||
|
||||
describe("table.makeset", function()
|
||||
it("should work", function()
|
||||
local source = { apples = 4 }
|
||||
local target = { oranges = 3 }
|
||||
|
||||
apply(source, target)
|
||||
|
||||
assert.are.same(
|
||||
{ apples = 4, oranges = 3 },
|
||||
target
|
||||
)
|
||||
end)
|
||||
it("should overwrite values in target", function()
|
||||
local source = { apples = 4 }
|
||||
local target = { apples = 3 }
|
||||
|
||||
apply(source, target)
|
||||
|
||||
assert.are.same(
|
||||
{ apples = 4 },
|
||||
target
|
||||
)
|
||||
end)
|
||||
it("should work with strings", function()
|
||||
local source = { apples = "4" }
|
||||
local target = { oranges = "3" }
|
||||
|
||||
apply(source, target)
|
||||
|
||||
assert.are.same(
|
||||
{ apples = "4", oranges = "3" },
|
||||
target
|
||||
)
|
||||
end)
|
||||
it("should overwrite values in target with strings", function()
|
||||
local source = { apples = "4" }
|
||||
local target = { apples = "3" }
|
||||
|
||||
apply(source, target)
|
||||
|
||||
assert.are.same(
|
||||
{ apples = "4" },
|
||||
target
|
||||
)
|
||||
end)
|
||||
end)
|
40
.tests/parse/table/table_contains.test.lua
Normal file
|
@ -0,0 +1,40 @@
|
|||
local contains = require("worldeditadditions_core.utils.table.table_contains")
|
||||
|
||||
describe("table.makeset", function()
|
||||
it("should work with a string", function()
|
||||
assert.are.same(
|
||||
true,
|
||||
contains({ "apples" }, "apples")
|
||||
)
|
||||
end)
|
||||
it("should work with a number", function()
|
||||
assert.are.same(
|
||||
true,
|
||||
contains({ 4 }, 4)
|
||||
)
|
||||
end)
|
||||
it("should return false if a number doesn't exist", function()
|
||||
assert.are.same(
|
||||
false,
|
||||
contains({ 5 }, 4)
|
||||
)
|
||||
end)
|
||||
it("should work with a string and multiple items in the table", function()
|
||||
assert.are.same(
|
||||
true,
|
||||
contains({ "yay", "apples", "cat" }, "apples")
|
||||
)
|
||||
end)
|
||||
it("should return false if it doesn't exist", function()
|
||||
assert.are.same(
|
||||
false,
|
||||
contains({ "yay" }, "orange")
|
||||
)
|
||||
end)
|
||||
it("should return false if it doesn't exist wiith multiple items", function()
|
||||
assert.are.same(
|
||||
false,
|
||||
contains({ "yay", "apples", "cat" }, "orange")
|
||||
)
|
||||
end)
|
||||
end)
|
178
.tests/strings/split_shell.test.lua
Normal file
|
@ -0,0 +1,178 @@
|
|||
local split_shell = require("worldeditadditions_core.utils.strings.split_shell")
|
||||
|
||||
describe("split_shell", function()
|
||||
it("should handle a single case x3", function()
|
||||
assert.are.same(
|
||||
{ "yay", "yay", "yay" },
|
||||
split_shell("yay yay yay")
|
||||
)
|
||||
end)
|
||||
|
||||
it("should handle double quotes simple", function()
|
||||
assert.are.same(
|
||||
{ "dirt", "snow block" },
|
||||
split_shell("dirt \"snow block\"")
|
||||
)
|
||||
end)
|
||||
|
||||
it("should handle an escaped double quote inside double quotes", function()
|
||||
assert.are.same(
|
||||
{ "yay", "yay\" yay", "yay" },
|
||||
split_shell("yay \"yay\\\" yay\" yay")
|
||||
)
|
||||
end)
|
||||
|
||||
it("should handle single quotes", function()
|
||||
assert.are.same(
|
||||
{ "yay", "yay", "yay" },
|
||||
split_shell("yay 'yay' yay")
|
||||
)
|
||||
end)
|
||||
|
||||
it("should handle single quotes again", function()
|
||||
assert.are.same(
|
||||
{ "yay", "inside quotes", "another" },
|
||||
split_shell("yay 'inside quotes' another")
|
||||
)
|
||||
end)
|
||||
|
||||
it("should handle single quotes inside double quotes", function()
|
||||
assert.are.same(
|
||||
{ "yay", "yay 'inside quotes' yay", "yay" },
|
||||
split_shell("yay \"yay 'inside quotes' yay\" yay")
|
||||
)
|
||||
end)
|
||||
|
||||
it("should handle single quotes and an escaped double quote inside double quotes", function()
|
||||
assert.are.same(
|
||||
{ "yay", "yay 'inside quotes' yay\"", "yay" },
|
||||
split_shell("yay \"yay 'inside quotes' yay\\\"\" yay")
|
||||
)
|
||||
end)
|
||||
|
||||
it("should handle a complex case", function()
|
||||
assert.are.same(
|
||||
{ "y\"ay", "yay 'in\"side quotes' yay", "y\"ay" },
|
||||
split_shell("y\"ay \"yay 'in\\\"side quotes' yay\" y\\\"ay")
|
||||
)
|
||||
end)
|
||||
it("should handle a subtly different complex case", function()
|
||||
assert.are.same(
|
||||
{ "y\"ay", "yay", "in\"side quotes", "yay", "y\"ay" },
|
||||
split_shell("y\"ay yay 'in\\\"side quotes' yay y\\\"ay")
|
||||
)
|
||||
end)
|
||||
it("should handle redundant double quotes", function()
|
||||
assert.are.same(
|
||||
{ "cake" },
|
||||
split_shell("\"cake\"")
|
||||
)
|
||||
end)
|
||||
it("should handle redundant double quotes multi", function()
|
||||
assert.are.same(
|
||||
{ "cake", "cake", "cake" },
|
||||
split_shell("\"cake\" \"cake\" \"cake\"")
|
||||
)
|
||||
end)
|
||||
it("should handle redundant single quotes", function()
|
||||
assert.are.same(
|
||||
{ "cake" },
|
||||
split_shell("'cake'")
|
||||
)
|
||||
end)
|
||||
it("should handle redundant single quotes multi", function()
|
||||
assert.are.same(
|
||||
{ "cake", "cake", "cake" },
|
||||
split_shell("'cake' 'cake' 'cake'")
|
||||
)
|
||||
end)
|
||||
it("should handle redundant double and single quotes", function()
|
||||
assert.are.same(
|
||||
{ "cake", "cake", "cake" },
|
||||
split_shell("'cake' \"cake\" 'cake'")
|
||||
)
|
||||
end)
|
||||
|
||||
it("should handle redundant double and single quotes opposite", function()
|
||||
assert.are.same(
|
||||
{ "cake", "cake", "cake" },
|
||||
split_shell("\"cake\" 'cake' \"cake\"")
|
||||
)
|
||||
end)
|
||||
it("should handle a random backslash single quotes", function()
|
||||
assert.are.same(
|
||||
{ "cake", "ca\\ke" },
|
||||
split_shell("\"cake\" 'ca\\ke'")
|
||||
)
|
||||
end)
|
||||
it("should handle a random backslash double quotes", function()
|
||||
assert.are.same(
|
||||
{ "cake", "ca\\ke" },
|
||||
split_shell("\"cake\" \"ca\\ke\"")
|
||||
)
|
||||
end)
|
||||
it("should handle a backslash after double quotes", function()
|
||||
assert.are.same(
|
||||
{ "\\cake", "cake" },
|
||||
split_shell("\"\\cake\" \"cake\"")
|
||||
)
|
||||
end)
|
||||
it("should handle a double backslash before double quotes", function()
|
||||
assert.are.same(
|
||||
{ "\\\"cake\"", "cake" },
|
||||
split_shell("\\\\\"cake\" \"cake\"")
|
||||
)
|
||||
end)
|
||||
it("should handle a single backslash before double quotes", function()
|
||||
assert.are.same(
|
||||
{ "\"cake\"", "cake" },
|
||||
split_shell("\\\"cake\" \"cake\"")
|
||||
)
|
||||
end)
|
||||
it("should handle a double backslash before single quotes", function()
|
||||
assert.are.same(
|
||||
{ "\\'cake'", "cake" },
|
||||
split_shell("\\\\'cake' 'cake'")
|
||||
)
|
||||
end)
|
||||
it("should handle a single backslash before single quotes", function()
|
||||
assert.are.same(
|
||||
{ "\"cake\"", "cake" },
|
||||
split_shell("\\\"cake\" \"cake\"")
|
||||
)
|
||||
end)
|
||||
it("should handle redundant double and single quotes again", function()
|
||||
assert.are.same(
|
||||
{ "cake", "cake", "cake", "is", "a", "li\\e" },
|
||||
split_shell("\"cake\" 'cake' \"cake\" is a \"li\\e\"")
|
||||
)
|
||||
end)
|
||||
|
||||
-- Unclosed quotes are currently considered to last until the end of the string.
|
||||
|
||||
it("should handle an unclosed double quote", function()
|
||||
assert.are.same(
|
||||
{ "the", "cake is a lie" },
|
||||
split_shell("the \"cake is a lie")
|
||||
)
|
||||
end)
|
||||
it("should handle an unclosed single quote", function()
|
||||
assert.are.same(
|
||||
{ "the", "cake is a lie" },
|
||||
split_shell("the 'cake is a lie")
|
||||
)
|
||||
end)
|
||||
it("should handle an unclosed single quote at the end", function()
|
||||
assert.are.same(
|
||||
{ "the", "cake is a lie'" },
|
||||
split_shell("the \"cake is a lie'")
|
||||
)
|
||||
end)
|
||||
it("should handle an unclosed single and double quote", function()
|
||||
assert.are.same(
|
||||
{ "the", "cake is \"a lie" },
|
||||
split_shell("the 'cake is \"a lie")
|
||||
)
|
||||
end)
|
||||
|
||||
end)
|
40
.tests/strings/str_ends.test.lua
Normal file
|
@ -0,0 +1,40 @@
|
|||
local polyfill = require("worldeditadditions_core.utils.strings.polyfill")
|
||||
|
||||
describe("str_ends", function()
|
||||
it("should return true for a single character", function()
|
||||
assert.are.equal(
|
||||
true,
|
||||
polyfill.str_ends("test", "t")
|
||||
)
|
||||
end)
|
||||
it("should return true for a multiple characters", function()
|
||||
assert.are.equal(
|
||||
true,
|
||||
polyfill.str_ends("test", "st")
|
||||
)
|
||||
end)
|
||||
it("should return true for identical strings", function()
|
||||
assert.are.equal(
|
||||
true,
|
||||
polyfill.str_ends("test", "test")
|
||||
)
|
||||
end)
|
||||
it("should return false for a single character ", function()
|
||||
assert.are.equal(
|
||||
false,
|
||||
polyfill.str_ends("test", "y")
|
||||
)
|
||||
end)
|
||||
it("should return false for a character present elsewherer", function()
|
||||
assert.are.equal(
|
||||
false,
|
||||
polyfill.str_ends("test", "e")
|
||||
)
|
||||
end)
|
||||
it("should return false for another substring", function()
|
||||
assert.are.equal(
|
||||
false,
|
||||
polyfill.str_ends("test", "tes")
|
||||
)
|
||||
end)
|
||||
end)
|
40
.tests/strings/str_padend.test.lua
Normal file
|
@ -0,0 +1,40 @@
|
|||
local polyfill = require("worldeditadditions_core.utils.strings.polyfill")
|
||||
|
||||
describe("str_padend", function()
|
||||
it("should pad a string", function()
|
||||
assert.are.equal(
|
||||
polyfill.str_padend("test", 5, " "),
|
||||
"test "
|
||||
)
|
||||
end)
|
||||
it("should pad a different string", function()
|
||||
assert.are.equal(
|
||||
polyfill.str_padend("yay", 4, " "),
|
||||
"yay "
|
||||
)
|
||||
end)
|
||||
it("should pad a string with multiple characters", function()
|
||||
assert.are.equal(
|
||||
polyfill.str_padend("test", 10, " "),
|
||||
"test "
|
||||
)
|
||||
end)
|
||||
it("should not pad a long string", function()
|
||||
assert.are.equal(
|
||||
polyfill.str_padend("testtest", 5, " "),
|
||||
"testtest"
|
||||
)
|
||||
end)
|
||||
it("should pad with other characters", function()
|
||||
assert.are.equal(
|
||||
polyfill.str_padend("1", 2, "0"),
|
||||
"10"
|
||||
)
|
||||
end)
|
||||
it("should pad with multiple other characters", function()
|
||||
assert.are.equal(
|
||||
polyfill.str_padend("1", 5, "0"),
|
||||
"10000"
|
||||
)
|
||||
end)
|
||||
end)
|
40
.tests/strings/str_padstart.test.lua
Normal file
|
@ -0,0 +1,40 @@
|
|||
local polyfill = require("worldeditadditions_core.utils.strings.polyfill")
|
||||
|
||||
describe("str_padstart", function()
|
||||
it("should pad a string", function()
|
||||
assert.are.equal(
|
||||
polyfill.str_padstart("test", 5, " "),
|
||||
" test"
|
||||
)
|
||||
end)
|
||||
it("should pad a different string", function()
|
||||
assert.are.equal(
|
||||
polyfill.str_padstart("yay", 4, " "),
|
||||
" yay"
|
||||
)
|
||||
end)
|
||||
it("should pad a string with multiple characters", function()
|
||||
assert.are.equal(
|
||||
polyfill.str_padstart("test", 10, " "),
|
||||
" test"
|
||||
)
|
||||
end)
|
||||
it("should not pad a long string", function()
|
||||
assert.are.equal(
|
||||
polyfill.str_padstart("testtest", 5, " "),
|
||||
"testtest"
|
||||
)
|
||||
end)
|
||||
it("should pad with other characters", function()
|
||||
assert.are.equal(
|
||||
polyfill.str_padstart("1", 2, "0"),
|
||||
"01"
|
||||
)
|
||||
end)
|
||||
it("should pad with multiple other characters", function()
|
||||
assert.are.equal(
|
||||
polyfill.str_padstart("1", 5, "0"),
|
||||
"00001"
|
||||
)
|
||||
end)
|
||||
end)
|