mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2026-02-16 18:40:46 +00:00
Compare commits
573 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ba4a50e234 | ||
|
|
9a97f1178d | ||
|
|
e6a551d84d | ||
|
|
92921430d8 | ||
|
|
20c905aae4 | ||
|
|
ec0730ef73 | ||
|
|
e4576b3405 | ||
|
|
c5800970a8 | ||
|
|
8f88b1c156 | ||
|
|
1360994a67 | ||
|
|
e00b28d27e | ||
|
|
c5ff5c101d | ||
|
|
b1a1001c49 | ||
|
|
77d5162e73 | ||
|
|
2e8cd54ac2 | ||
|
|
28222c074e | ||
|
|
1b70766a17 | ||
|
|
cda2d4688c | ||
|
|
5028582198 | ||
|
|
5458564cfa | ||
|
|
7f11373f75 | ||
|
|
f9ca8d139b | ||
|
|
6f287a1894 | ||
|
|
6f4251796e | ||
|
|
5ad349e350 | ||
|
|
ec4e0694a4 | ||
|
|
6ab8cd5b5b | ||
|
|
b3868bd750 | ||
|
|
ff8181bbfa | ||
|
|
074ad44bca | ||
|
|
9a6c34a2d5 | ||
|
|
ce3c0f105e | ||
|
|
58162027a9 | ||
|
|
39400cce0a | ||
|
|
819d795c23 | ||
|
|
d6b5f60b18 | ||
|
|
1f16a82a8d | ||
|
|
51fa58b481 | ||
|
|
bed8c561a4 | ||
|
|
fdb2441b1a | ||
|
|
bf5be91868 | ||
|
|
06956a7a2d | ||
|
|
a584ac2401 | ||
|
|
513c6a647f | ||
|
|
5a85aced45 | ||
|
|
41933b84a0 | ||
|
|
67aae87754 | ||
|
|
13346daa6a | ||
|
|
5e9b841cac | ||
|
|
5820fe1db3 | ||
|
|
f5c0174473 | ||
|
|
31b583910e | ||
|
|
fac4cb43a8 | ||
|
|
0f39d64d72 | ||
|
|
5fc012f7ba | ||
|
|
f773ca2322 | ||
|
|
52c56af02c | ||
|
|
22d6fdf293 | ||
|
|
b1256427a2 | ||
|
|
026a6066d3 | ||
|
|
0cd5898107 | ||
|
|
a5d101ff61 | ||
|
|
c1b04d1772 | ||
|
|
0d58201e3f | ||
|
|
939121dea6 | ||
|
|
c44d26cc18 | ||
|
|
c047209b86 | ||
|
|
f989e4dc89 | ||
|
|
c8c3ab312b | ||
|
|
dc52dd635b | ||
|
|
4e97ba6da9 | ||
|
|
c0d26256af | ||
|
|
7828de74aa | ||
|
|
01396e739c | ||
|
|
e4c1a056ae | ||
|
|
613e9c0c54 | ||
|
|
c5a174ba7a | ||
|
|
72296cf960 | ||
|
|
265449c5a7 | ||
|
|
1125b498ec | ||
|
|
a28f3fa660 | ||
|
|
5a6b7ac4c1 | ||
|
|
7f988dcf26 | ||
|
|
7c177d568b | ||
|
|
12af19edba | ||
|
|
924bc6e469 | ||
|
|
4569a9ed13 | ||
|
|
4ca2f0c08d | ||
|
|
4a47815be7 | ||
|
|
dd446b3034 | ||
|
|
0fcc0f798c | ||
|
|
1637644bdd | ||
|
|
2b114f225e | ||
|
|
32746e8dd9 | ||
|
|
d29c1e572e | ||
|
|
bb6dcb3880 | ||
|
|
3c56813d6b | ||
|
|
5c0482e972 | ||
|
|
83f981111a | ||
|
|
4171768cc9 | ||
|
|
df2acfaa40 | ||
|
|
533380107b | ||
|
|
9c2b844290 | ||
|
|
98c1fea7fd | ||
|
|
415df211ed | ||
|
|
ac09e059fc | ||
|
|
268cc7c48b | ||
|
|
358bd350b5 | ||
|
|
a328ff2f2a | ||
|
|
46a08e49f5 | ||
|
|
05cd0b625c | ||
|
|
5e940187d9 | ||
|
|
8b196716a4 | ||
|
|
6025e0f557 | ||
|
|
e00209c99c | ||
|
|
03e9f6b882 | ||
|
|
fab8c90e92 | ||
|
|
3b719d0880 | ||
|
|
45dbe45fb4 | ||
|
|
76f2a3fbc4 | ||
|
|
5e761c3e29 | ||
|
|
6d51da3118 | ||
|
|
839f429806 | ||
|
|
e533180dab | ||
|
|
40b9c6c08c | ||
|
|
c8c9247dfe | ||
|
|
7f8749239f | ||
|
|
2b84967e05 | ||
|
|
6446f9b4a7 | ||
|
|
5933f97f93 | ||
|
|
d670fc904f | ||
|
|
33371675e1 | ||
|
|
bd91506069 | ||
|
|
393a92730f | ||
|
|
5ff016ea1f | ||
|
|
84b8df6d96 | ||
|
|
353999aa45 | ||
|
|
4a4e7e42cc | ||
|
|
06cd1dc562 | ||
|
|
48296fb14a | ||
|
|
b3a4c3af19 | ||
|
|
c0773be780 | ||
|
|
79df7eed21 | ||
|
|
14ce12f08e | ||
|
|
7cfa96f925 | ||
|
|
4131b45c6f | ||
|
|
4bf31d863e | ||
|
|
92db30e181 | ||
|
|
0f152f9281 | ||
|
|
7ca779f845 | ||
|
|
76a2d08906 | ||
|
|
161b047c39 | ||
|
|
8309ad665e | ||
|
|
b6e414f944 | ||
|
|
36db83b253 | ||
|
|
c4e641069d | ||
|
|
5e40fbbf07 | ||
|
|
8a47a01dd8 | ||
|
|
e41587dbd9 | ||
|
|
d5de91a864 | ||
|
|
f8cf61e281 | ||
|
|
7323b051db | ||
|
|
72f86e68e8 | ||
|
|
5f9b21ea09 | ||
|
|
dd44839bd3 | ||
|
|
b8cec40317 | ||
|
|
19f781af31 | ||
|
|
af825761c7 | ||
|
|
490fed8c2c | ||
|
|
85efa44673 | ||
|
|
985443e228 | ||
|
|
213182e2ab | ||
|
|
76eb0f3fe0 | ||
|
|
a2f3752c31 | ||
|
|
4aebb83b0c | ||
|
|
7418d67b09 | ||
|
|
565266992f | ||
|
|
1863ba29fc | ||
|
|
e600b50a11 | ||
|
|
762c3064d9 | ||
|
|
b99fabcf1d | ||
|
|
af248ee14a | ||
|
|
c834d80206 | ||
|
|
66fb481ac2 | ||
|
|
7858cc34c2 | ||
|
|
e306a0fd09 | ||
|
|
02d61d0764 | ||
|
|
dddf644c34 | ||
|
|
a8266f99b1 | ||
|
|
2fb30322ff | ||
|
|
d05fdeb94c | ||
|
|
dfec463765 | ||
|
|
f6967be95f | ||
|
|
82fa9abe15 | ||
|
|
1d6cdf9eaa | ||
|
|
89f52a22c8 | ||
|
|
dca0891e00 | ||
|
|
bd4812ef2b | ||
|
|
ce62f1d7ac | ||
|
|
da5d3fe0ce | ||
|
|
3318161c44 | ||
|
|
25acda4410 | ||
|
|
115bb414c0 | ||
|
|
708ef16a1c | ||
|
|
8b501ddcde | ||
|
|
5b8beebaa3 | ||
|
|
7b6d195615 | ||
|
|
9e830abb90 | ||
|
|
01d0d4c00a | ||
|
|
4b21fcd80a | ||
|
|
af5b316326 | ||
|
|
beb18c6e2c | ||
|
|
09c1957ab6 | ||
|
|
b2c3498a32 | ||
|
|
20de531c8f | ||
|
|
6d1dd3acbf | ||
|
|
346a8826aa | ||
|
|
25f6f3dbe1 | ||
|
|
87f7af1e1b | ||
|
|
764344b4ef | ||
|
|
d327909389 | ||
|
|
c1fdfa94f1 | ||
|
|
d65c700bb9 | ||
|
|
cbc2885c16 | ||
|
|
8fd3530653 | ||
|
|
244f0fba11 | ||
|
|
56a0d5d15b | ||
|
|
ca8cc8bc66 | ||
|
|
627f1b75d6 | ||
|
|
18731a5aa0 | ||
|
|
4bd943ae7b | ||
|
|
e04d363123 | ||
|
|
d1c018690d | ||
|
|
54f732176d | ||
|
|
fb32531584 | ||
|
|
5c9a9c7dfa | ||
|
|
fc46c8bd4d | ||
|
|
f28759d07a | ||
|
|
93c33ca455 | ||
|
|
9c50dc2ef9 | ||
|
|
883124d8ab | ||
|
|
1ee2b180d4 | ||
|
|
e6e2c62474 | ||
|
|
5df511a940 | ||
|
|
462b0af225 | ||
|
|
5c469ed378 | ||
|
|
c59ab5d917 | ||
|
|
8a10a9807d | ||
|
|
623a4dea4f | ||
|
|
18d7408f53 | ||
|
|
462b6f4198 | ||
|
|
1049bb901d | ||
|
|
999c9b565d | ||
|
|
27aeb73157 | ||
|
|
12ff9cc146 | ||
|
|
f114baebd6 | ||
|
|
11a6546064 | ||
|
|
771e42d1a8 | ||
|
|
5e3c12298b | ||
|
|
a5dd4a63d1 | ||
|
|
9fbe117f78 | ||
|
|
3429165aca | ||
|
|
9310114c0e | ||
|
|
141b4f86ae | ||
|
|
67ffd91641 | ||
|
|
9a94485c91 | ||
|
|
28b6fe49bb | ||
|
|
308ba887a3 | ||
|
|
d2a1901f44 | ||
|
|
64391f3abc | ||
|
|
e47b3f0397 | ||
|
|
c6ff808cce | ||
|
|
e9d0c14eee | ||
|
|
23d8a0aeeb | ||
|
|
512edae9c6 | ||
|
|
25ae2b3c9b | ||
|
|
44176f7ee6 | ||
|
|
47cad8a30b | ||
|
|
4ad2db3ca8 | ||
|
|
24a5a9425e | ||
|
|
1cdf4478b8 | ||
|
|
b67814d68a | ||
|
|
5a64424b16 | ||
|
|
32b3b4cd3f | ||
|
|
d0a24f7041 | ||
|
|
aa406d9b8b | ||
|
|
a38eba2916 | ||
|
|
aec1d671fa | ||
|
|
26504d6d83 | ||
|
|
87a1b0bf5a | ||
|
|
bd0726db37 | ||
|
|
75fbda5a9f | ||
|
|
ee093397d3 | ||
|
|
3c12a98ef3 | ||
|
|
fff918e0ee | ||
|
|
1536a13d3c | ||
|
|
b26847f250 | ||
|
|
c7d3e5294a | ||
|
|
86d42a03a0 | ||
|
|
bf4a831781 | ||
|
|
90cc88f05f | ||
|
|
315230af27 | ||
|
|
fed24920f8 | ||
|
|
a785d7b892 | ||
|
|
de9eb26ebc | ||
|
|
a5105f9f9d | ||
|
|
0fef1619d2 | ||
|
|
b209c49877 | ||
|
|
ddc218c4d4 | ||
|
|
77f348912f | ||
|
|
6bac82da25 | ||
|
|
a51727b636 | ||
|
|
ec722014e6 | ||
|
|
256761eb5b | ||
|
|
07731c06c0 | ||
|
|
556584f9f5 | ||
|
|
61c93b47ca | ||
|
|
044aa738a3 | ||
|
|
8da2b63f31 | ||
|
|
ce033b0956 | ||
|
|
a9df684b80 | ||
|
|
356771bcea | ||
|
|
166c0f7dfb | ||
|
|
aa41cc4d3d | ||
|
|
0c3e3f2bc6 | ||
|
|
792b6efd12 | ||
|
|
122fbd841c | ||
|
|
ad5823055d | ||
|
|
92afe1c9ab | ||
|
|
1826adf1c2 | ||
|
|
97f6cda4ad | ||
|
|
bccfcdf9a1 | ||
|
|
8049824170 | ||
|
|
99acadaf59 | ||
|
|
2be4b36d1a | ||
|
|
c283f37390 | ||
|
|
d21d448947 | ||
|
|
d16c28aebd | ||
|
|
ce45bacc6f | ||
|
|
a68b85c522 | ||
|
|
7d0149b59d | ||
|
|
447c82f74a | ||
|
|
8db263e19b | ||
|
|
7cf34dbd8a | ||
|
|
283495832f | ||
|
|
f6312a01d7 | ||
|
|
c7d43142f2 | ||
|
|
c4da858095 | ||
|
|
5ff47bad18 | ||
|
|
18819ae53d | ||
|
|
ddc2cea427 | ||
|
|
bc17597923 | ||
|
|
49f3c16a38 | ||
|
|
5db1494341 | ||
|
|
cccb706ad5 | ||
|
|
c6d7d1a947 | ||
|
|
9685dbbb9d | ||
|
|
a18d459343 | ||
|
|
4b5013231c | ||
|
|
a04bcf5b23 | ||
|
|
1c579e8e5b | ||
|
|
bbab6e39ff | ||
|
|
2e68a0db5d | ||
|
|
abc59901c1 | ||
|
|
aaa0c99524 | ||
|
|
0780539326 | ||
|
|
c8434e73ef | ||
|
|
058ec9f24d | ||
|
|
7127943298 | ||
|
|
9adc03d56b | ||
|
|
5d6b060dee | ||
|
|
fc82eff93b | ||
|
|
1c316e52a9 | ||
|
|
76afd54d3c | ||
|
|
7fe7dac57a | ||
|
|
63e59692e2 | ||
|
|
405a96034c | ||
|
|
e9dc7428b8 | ||
|
|
b4342a36aa | ||
|
|
1158ae958a | ||
|
|
062c9b5efb | ||
|
|
66e8647517 | ||
|
|
f47b975fe7 | ||
|
|
e5d9ae62fa | ||
|
|
9c1eab04b9 | ||
|
|
72d4370878 | ||
|
|
88da796923 | ||
|
|
2ab4ed871c | ||
|
|
0ecd275c56 | ||
|
|
4f40bcbe5e | ||
|
|
cb7b3de48c | ||
|
|
13fbb9bf54 | ||
|
|
be8ed913e5 | ||
|
|
fe17683d27 | ||
|
|
7d72a91bb7 | ||
|
|
7a75f20a2c | ||
|
|
8a7499d874 | ||
|
|
adc5f0becc | ||
|
|
6d710ca442 | ||
|
|
7cbf8dffbe | ||
|
|
e1cb46c8fd | ||
|
|
8b97d74e0a | ||
|
|
c4f927e72c | ||
|
|
2880c29f8c | ||
|
|
474962db39 | ||
|
|
f970838ecf | ||
|
|
29e2746e72 | ||
|
|
1ce884d1c7 | ||
|
|
24697ae60f | ||
|
|
53c554f25c | ||
|
|
d1af8c1224 | ||
|
|
9ac098f1ca | ||
|
|
300fe10da5 | ||
|
|
b33c8d6b77 | ||
|
|
b06a755154 | ||
|
|
817b962c4a | ||
|
|
56c52e860d | ||
|
|
fd89c1128a | ||
|
|
beec1a97d4 | ||
|
|
b955e3d9b9 | ||
|
|
b12079694c | ||
|
|
7a83584317 | ||
|
|
1c4cc090af | ||
|
|
a614d7dddd | ||
|
|
ae21b8305a | ||
|
|
6f6767ab86 | ||
|
|
ee35c371ec | ||
|
|
4d59c27a13 | ||
|
|
0dc0742e81 | ||
|
|
3b0abb7a20 | ||
|
|
42231cf319 | ||
|
|
11c8025ef4 | ||
|
|
eda976bb5d | ||
|
|
49c445d0f7 | ||
|
|
875e1feafe | ||
|
|
5f5504100b | ||
|
|
2215c8a98c | ||
|
|
ebe887def0 | ||
|
|
1dded41311 | ||
|
|
6db4755109 | ||
|
|
a01dee9a27 | ||
|
|
582bde8d0e | ||
|
|
f609727afb | ||
|
|
a058f1c58b | ||
|
|
70abf69dc7 | ||
|
|
269ec257b5 | ||
|
|
2c15a9fc0c | ||
|
|
0826246cbe | ||
|
|
a3add9b20f | ||
|
|
6c20b5911f | ||
|
|
d779b3ea27 | ||
|
|
618e7ed12e | ||
|
|
d84dd3a526 | ||
|
|
27dbd494bd | ||
|
|
15100caf32 | ||
|
|
4e9c7e0b91 | ||
|
|
0261ecdcbb | ||
|
|
5bf699cba9 | ||
|
|
7ee1d2c391 | ||
|
|
5c9c47d078 | ||
|
|
af5309ff21 | ||
|
|
c7539dc5dd | ||
|
|
4b2c2d8ba2 | ||
|
|
ee529a5973 | ||
|
|
3e04dc6b46 | ||
|
|
dbf4b4dd3b | ||
|
|
560fdf17fa | ||
|
|
7a61a2548b | ||
|
|
31361286b5 | ||
|
|
abd29c1cb4 | ||
|
|
9f4e120283 | ||
|
|
d9f585e4b2 | ||
|
|
f4456f46a7 | ||
|
|
3dc27f2b0a | ||
|
|
95e39324c7 | ||
|
|
392ba59741 | ||
|
|
26228d2c71 | ||
|
|
8f58ba17a8 | ||
|
|
75f39640b0 | ||
|
|
42dcc159e9 | ||
|
|
791faa6dfd | ||
|
|
aea2b23fc3 | ||
|
|
47438b7db9 | ||
|
|
df3d3c6398 | ||
|
|
1457a10b0b | ||
|
|
2b6e8eb67c | ||
|
|
11cb11bc2b | ||
|
|
bb5552c8bc | ||
|
|
8f5a9b7b8e | ||
|
|
7e365c351d | ||
|
|
a0f0206ed8 | ||
|
|
554628c486 | ||
|
|
37c2d945ec | ||
|
|
59a24ef37f | ||
|
|
ad58a1efeb | ||
|
|
682b155deb | ||
|
|
0e0d84fea7 | ||
|
|
4ceb4e22d4 | ||
|
|
2ae2801058 | ||
|
|
5189aa5003 | ||
|
|
87cc2d01cb | ||
|
|
f86fe4db32 | ||
|
|
1940309954 | ||
|
|
d946ea9b15 | ||
|
|
0f8ce8966a | ||
|
|
c9b2c83dc4 | ||
|
|
2d24a7bf00 | ||
|
|
4c80a71bca | ||
|
|
264f1df172 | ||
|
|
5b17d87a97 | ||
|
|
0e4df43ddb | ||
|
|
3d7796d8c3 | ||
|
|
4e647620f0 | ||
|
|
a38fcef6f1 | ||
|
|
b5fdeef535 | ||
|
|
5d3ae11374 | ||
|
|
7db75ab21b | ||
|
|
3d12af6b21 | ||
|
|
601eb3e7ff | ||
|
|
5754a95f48 | ||
|
|
b3e76f6485 | ||
|
|
47b3278f96 | ||
|
|
27e31fef9f | ||
|
|
3807b8c277 | ||
|
|
7db83c1dee | ||
|
|
496cd486b1 | ||
|
|
034f1072bf | ||
|
|
b5c99c87e1 | ||
|
|
c5fe86272e | ||
|
|
15840302e0 | ||
|
|
0f526ca616 | ||
|
|
bc3d694f7f | ||
|
|
7f880c23b8 | ||
|
|
7c6aa3a425 | ||
|
|
9636c808fe | ||
|
|
f49ba88cb4 | ||
|
|
0cbc225408 | ||
|
|
f85d047ee6 | ||
|
|
f033b8219c | ||
|
|
1357e7f84e | ||
|
|
3eaab219f1 | ||
|
|
ce97732da7 | ||
|
|
7fe2fa493e | ||
|
|
78acf59f98 | ||
|
|
1c0954d0cf | ||
|
|
fe6ea9511b | ||
|
|
1c9c183d66 | ||
|
|
67ff426894 | ||
|
|
6eb5c0e0ec | ||
|
|
4e11d5c1cf | ||
|
|
155b293b61 | ||
|
|
282bfe9c5d | ||
|
|
4ddace2a92 | ||
|
|
4b7b0ee7e9 | ||
|
|
af6ba33921 | ||
|
|
622e65e7a5 | ||
|
|
2f9f89042c | ||
|
|
538000ed32 | ||
|
|
fe676db0ce | ||
|
|
30e89a0b69 | ||
|
|
8e49f7ec26 | ||
|
|
86088d1dcd | ||
|
|
5c6ea59d30 | ||
|
|
f364420007 | ||
|
|
96ff875d2b | ||
|
|
717ece9d1f | ||
|
|
013216ad8c | ||
|
|
16d8d56832 | ||
|
|
06d9fa1d98 | ||
|
|
59141f99bd | ||
|
|
dbbe7dbd0d | ||
|
|
c46161fc87 | ||
|
|
70ec483581 |
@@ -6,7 +6,7 @@ end_of_line = lf
|
||||
indent_size = 4
|
||||
indent_style = space
|
||||
insert_final_newline = false
|
||||
max_line_length = 120
|
||||
max_line_length = 140
|
||||
tab_width = 4
|
||||
ij_continuation_indent_size = 8
|
||||
ij_formatter_off_tag = @formatter:off
|
||||
|
||||
40
.github/workflows/build.yml
vendored
Normal file
40
.github/workflows/build.yml
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
# This workflow will build a Java project with Gradle
|
||||
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle
|
||||
|
||||
name: Java CI with Gradle
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "v*" # Push events to matching v*, i.e. v1.0, v20.15.10
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Set up JDK 1.8
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 1.8
|
||||
|
||||
- name: Build Terra
|
||||
run: gradle shadowJar
|
||||
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Package
|
||||
path: build/libs
|
||||
|
||||
- name: Publish release
|
||||
uses: marvinpinto/action-automatic-releases@latest
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
prerelease: false
|
||||
files: |
|
||||
build/libs/Terra-*.jar
|
||||
LICENSE
|
||||
|
||||
7
.gitignore
vendored
7
.gitignore
vendored
@@ -52,6 +52,7 @@ gradle-app.setting
|
||||
|
||||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||
hs_err_pid*
|
||||
*.hprof
|
||||
|
||||
### JetBrains template
|
||||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
||||
@@ -137,3 +138,9 @@ build
|
||||
|
||||
!lib/*.jar
|
||||
.idea/Terra.iml
|
||||
/run/
|
||||
.idea/**.iml
|
||||
/lang/
|
||||
/packs/
|
||||
/config.yml
|
||||
/region/
|
||||
|
||||
8
.idea/.gitignore
generated
vendored
8
.idea/.gitignore
generated
vendored
@@ -1,8 +0,0 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
6
.idea/compiler.xml
generated
6
.idea/compiler.xml
generated
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<bytecodeTargetLevel target="1.8" />
|
||||
</component>
|
||||
</project>
|
||||
6
.idea/discord.xml
generated
6
.idea/discord.xml
generated
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DiscordProjectSettings">
|
||||
<option name="show" value="PROJECT_FILES" />
|
||||
</component>
|
||||
</project>
|
||||
18
.idea/gradle.xml
generated
18
.idea/gradle.xml
generated
@@ -1,18 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="GradleMigrationSettings" migrationVersion="1" />
|
||||
<component name="GradleSettings">
|
||||
<option name="linkedExternalProjectsSettings">
|
||||
<GradleProjectSettings>
|
||||
<option name="distributionType" value="DEFAULT_WRAPPED" />
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="gradleHome" value="/usr/share/java/gradle" />
|
||||
<option name="modules">
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
</set>
|
||||
</option>
|
||||
</GradleProjectSettings>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
23
.idea/inspectionProfiles/Project_Default.xml
generated
23
.idea/inspectionProfiles/Project_Default.xml
generated
@@ -1,23 +0,0 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<profile version="1.0">
|
||||
<option name="myName" value="Project Default" />
|
||||
<inspection_tool class="DuplicatedCode" enabled="true" level="WEAK WARNING" enabled_by_default="true">
|
||||
<Languages>
|
||||
<language minSize="54" name="Java" />
|
||||
</Languages>
|
||||
</inspection_tool>
|
||||
<inspection_tool class="NonSerializableObjectPassedToObjectStream" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="SerialVersionUIDNotStaticFinal" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="SerializableHasSerialVersionUIDField" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<option name="ignoreAnonymousInnerClasses" value="false" />
|
||||
<option name="superClassString" value="java.awt.Component" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="SerializableInnerClassHasSerialVersionUIDField" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<option name="ignoreAnonymousInnerClasses" value="false" />
|
||||
<option name="superClassString" value="java.awt.Component" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="SerializableStoresNonSerializable" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="TransientFieldInNonSerializableClass" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="TransientFieldNotInitialized" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
</profile>
|
||||
</component>
|
||||
85
.idea/jarRepositories.xml
generated
85
.idea/jarRepositories.xml
generated
@@ -1,85 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RemoteRepositoriesConfiguration">
|
||||
<remote-repository>
|
||||
<option name="id" value="BintrayJCenter" />
|
||||
<option name="name" value="BintrayJCenter" />
|
||||
<option name="url" value="https://jcenter.bintray.com/" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="central" />
|
||||
<option name="name" value="Central Repository" />
|
||||
<option name="url" value="https://repo.maven.apache.org/maven2" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="papermc" />
|
||||
<option name="name" value="papermc" />
|
||||
<option name="url" value="https://papermc.io/repo/repository/maven-public/" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="central" />
|
||||
<option name="name" value="Maven Central repository" />
|
||||
<option name="url" value="https://repo1.maven.org/maven2" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="parsii.local" />
|
||||
<option name="name" value="parsii" />
|
||||
<option name="url" value="file:$PROJECT_DIR$/../parsii/repo" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="local" />
|
||||
<option name="name" value="local" />
|
||||
<option name="url" value="file:lib" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="aikar" />
|
||||
<option name="name" value="aikar" />
|
||||
<option name="url" value="https://repo.aikar.co/content/groups/aikar/" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="enginehub-maven" />
|
||||
<option name="name" value="enginehub-maven" />
|
||||
<option name="url" value="http://maven.enginehub.org/repo/" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="spigotmc-repo" />
|
||||
<option name="name" value="spigotmc-repo" />
|
||||
<option name="url" value="https://hub.spigotmc.org/nexus/content/repositories/snapshots/" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="jboss.community" />
|
||||
<option name="name" value="JBoss Community repository" />
|
||||
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="enginehub" />
|
||||
<option name="name" value="enginehub" />
|
||||
<option name="url" value="https://maven.enginehub.org/repo/" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="minecraft-repo" />
|
||||
<option name="name" value="minecraft-repo" />
|
||||
<option name="url" value="https://libraries.minecraft.net/" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="gaea.local" />
|
||||
<option name="name" value="gaea" />
|
||||
<option name="url" value="file:$PROJECT_DIR$/../Gaea/repo" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="gaea.local" />
|
||||
<option name="name" value="gaea-local" />
|
||||
<option name="url" value="file:$PROJECT_DIR$/../Gaea/repo" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="CodeMC" />
|
||||
<option name="name" value="CodeMC" />
|
||||
<option name="url" value="https://repo.codemc.org/repository/maven-public" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="MavenLocal" />
|
||||
<option name="name" value="MavenLocal" />
|
||||
<option name="url" value="file:$MAVEN_REPOSITORY$/" />
|
||||
</remote-repository>
|
||||
</component>
|
||||
</project>
|
||||
25
.idea/misc.xml
generated
25
.idea/misc.xml
generated
@@ -1,25 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="EntryPointsManager">
|
||||
<entry_points version="2.0">
|
||||
<entry_point TYPE="field" FQNAME="com.dfsek.terra.util.StructureTypeEnum NETHER_FORTRESS" />
|
||||
</entry_points>
|
||||
<list size="1">
|
||||
<item index="0" class="java.lang.String" itemvalue="org.bukkit.event.EventHandler" />
|
||||
</list>
|
||||
</component>
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="FrameworkDetectionExcludesConfiguration">
|
||||
<file type="web" url="file://$PROJECT_DIR$" />
|
||||
</component>
|
||||
<component name="MavenProjectsManager">
|
||||
<option name="originalFiles">
|
||||
<list>
|
||||
<option value="$PROJECT_DIR$/pom.xml" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="8" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
124
.idea/uiDesigner.xml
generated
124
.idea/uiDesigner.xml
generated
@@ -1,124 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Palette2">
|
||||
<group name="Swing">
|
||||
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
|
||||
</item>
|
||||
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true">
|
||||
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
|
||||
<initial-values>
|
||||
<property name="text" value="Button" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="RadioButton" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="CheckBox" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="Label" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||
<preferred-size width="200" height="200" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||
<preferred-size width="200" height="200" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
|
||||
<preferred-size width="-1" height="20" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
|
||||
</item>
|
||||
</group>
|
||||
</component>
|
||||
</project>
|
||||
6
.idea/vcs.xml
generated
6
.idea/vcs.xml
generated
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
27
README.md
27
README.md
@@ -1,20 +1,25 @@
|
||||
# Terra
|
||||
Terra is a data-driven world generator based on [Gaea](https://github.com/PolyhedralDev/Gaea). Find out more on our
|
||||
[Spigot page](https://www.spigotmc.org/resources/85151/)!
|
||||
|
||||
Terra is an incredibly powerful free & open-source data-driven, platform-agnostic world generator. It allows you to create a world exactly
|
||||
to your specifications, with no knowledge of Java required.
|
||||
|
||||
## Downloads:
|
||||
|
||||
* Paper+ servers (Paper, Tuinity, Purpur, etc): [SpigotMC](https://www.spigotmc.org/resources/85151/)
|
||||
* Fabric: [Modrinth](https://modrinth.com/mod/terra) / [CurseForge](https://www.curseforge.com/minecraft/mc-mods/terra-world-generator)
|
||||
|
||||
## Building and running Terra
|
||||
To build, simply run `./gradlew build` on Linux/MacOS, or `gradlew.bat build` on Windows.
|
||||
This will produce a jar in `build/libs` called `Terra-[CURRENT VERSION].jar`.
|
||||
You can put this right into your plugins dir, along with the correct Gaea version.
|
||||
|
||||
To build, simply run `./gradlew build` (`gradlew.bat build` on Windows). This will produce a jar in `build/libs`
|
||||
called `Terra-[CURRENT VERSION].jar`. You can put this right into your plugins dir, along with the correct Gaea version.
|
||||
|
||||
If you would like to test it with a default server config, just run `./gradlew setupServer` or
|
||||
`./gradlew.bat setupServer` to set up the server, then `./gradlew testWithPaper` or `gradlew.bat testWithPaper` to run
|
||||
the server. If you want a clean installation of the server, re-run the `setupServer` task.
|
||||
This will download a default server config from [here](https://github.com/PolyhedralDev/WorldGenTestServer)
|
||||
`./gradlew.bat setupServer` to set up the server, then `./gradlew testWithPaper` or `gradlew.bat testWithPaper` to run the server. If you
|
||||
want a clean installation of the server, re-run the `setupServer` task. This will download a default server config
|
||||
from [here](https://github.com/PolyhedralDev/WorldGenTestServer)
|
||||
and install the server in the `target/server` directory, along with all the needed plugins.
|
||||
|
||||
**Note: You will need to adjust the `NAME` variable `bukkit.yml` of the test server if you are not using the default
|
||||
Terra config.**
|
||||
|
||||
**Note: You will need to adjust the `NAME` variable `bukkit.yml` of the test server if you are not using the default Terra config.**
|
||||
|
||||
## Contributing
|
||||
Contributions are welcome! If you want to see a feature in Terra, please, open an issue, or implement it yourself and
|
||||
|
||||
17
Terra.iml
17
Terra.iml
@@ -1,17 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module version="4">
|
||||
<component name="CheckStyle-IDEA-Module">
|
||||
<option name="configuration">
|
||||
<map />
|
||||
</option>
|
||||
</component>
|
||||
<component name="FacetManager">
|
||||
<facet type="minecraft" name="Minecraft">
|
||||
<configuration>
|
||||
<autoDetectTypes>
|
||||
<platformType>SPIGOT</platformType>
|
||||
</autoDetectTypes>
|
||||
</configuration>
|
||||
</facet>
|
||||
</component>
|
||||
</module>
|
||||
232
build.gradle.kts
232
build.gradle.kts
@@ -1,200 +1,11 @@
|
||||
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.net.URL
|
||||
import java.nio.channels.Channels
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Paths
|
||||
import java.nio.file.StandardCopyOption
|
||||
//import java.util.zip.ZipFile
|
||||
import java.util.zip.ZipInputStream
|
||||
import com.dfsek.terra.getGitHash
|
||||
|
||||
plugins {
|
||||
java
|
||||
maven
|
||||
id("com.github.johnrengelman.shadow").version("6.1.0")
|
||||
val versionObj = Version("5", "1", "1", true)
|
||||
|
||||
allprojects {
|
||||
version = versionObj
|
||||
group = "com.dfsek.terra"
|
||||
}
|
||||
|
||||
repositories {
|
||||
flatDir {
|
||||
dirs("lib")
|
||||
}
|
||||
maven { url = uri("https://hub.spigotmc.org/nexus/content/repositories/snapshots/") }
|
||||
maven { url = uri("http://maven.enginehub.org/repo/") }
|
||||
maven { url = uri("https://repo.codemc.org/repository/maven-public") }
|
||||
maven { url = uri("https://papermc.io/repo/repository/maven-public/") }
|
||||
// maven { url = uri("https://maven.pkg.github.com/solonovamax/Gaea") }
|
||||
}
|
||||
|
||||
java {
|
||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||
targetCompatibility = JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
val versionObj = Version("1", "5", "0", true)
|
||||
|
||||
version = versionObj
|
||||
|
||||
dependencies {
|
||||
val gaeaVersion = "1.14.3"
|
||||
compileOnly(name = "Gaea-${gaeaVersion}", group = "")
|
||||
testImplementation(name = "Gaea-${gaeaVersion}", group = "")
|
||||
|
||||
compileOnly("org.jetbrains:annotations:20.1.0")
|
||||
|
||||
implementation("commons-io:commons-io:2.4")
|
||||
implementation("org.apache.commons:commons-imaging:1.0-alpha2")
|
||||
|
||||
compileOnly("com.sk89q.worldedit:worldedit-bukkit:7.2.0-SNAPSHOT")
|
||||
implementation("org.bstats:bstats-bukkit:1.7")
|
||||
|
||||
compileOnly("com.googlecode.json-simple:json-simple:1.1")
|
||||
|
||||
implementation(name = "parsii-1.2.1", group = "")
|
||||
|
||||
compileOnly("org.spigotmc:spigot-api:1.16.2-R0.1-SNAPSHOT")
|
||||
implementation("io.papermc:paperlib:1.0.5")
|
||||
|
||||
implementation("net.jafama:jafama:2.3.2")
|
||||
|
||||
|
||||
// JUnit.
|
||||
testImplementation("org.junit.jupiter:junit-jupiter-api:5.7.0")
|
||||
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.7.0")
|
||||
}
|
||||
|
||||
val compileJava: JavaCompile by tasks
|
||||
val mainSourceSet: SourceSet = sourceSets["main"]
|
||||
|
||||
val tokenizeJavaSources = task<Copy>(name = "tokenizeJavaSources") {
|
||||
from(mainSourceSet.allSource) {
|
||||
include("**/plugin.yml")
|
||||
println("version: $versionObj")
|
||||
val tokens = mapOf("VERSION" to versionObj.toString())
|
||||
|
||||
filter(org.apache.tools.ant.filters.ReplaceTokens::class, "tokens" to tokens)
|
||||
}
|
||||
into("build/tokenizedSources")
|
||||
includeEmptyDirs = false
|
||||
}
|
||||
|
||||
|
||||
compileJava.apply {
|
||||
dependsOn(tokenizeJavaSources)
|
||||
|
||||
options.encoding = "UTF-8"
|
||||
doFirst {
|
||||
options.compilerArgs = mutableListOf("-Xlint:all")
|
||||
}
|
||||
}
|
||||
|
||||
tasks.test {
|
||||
useJUnitPlatform()
|
||||
|
||||
maxHeapSize = "4G"
|
||||
ignoreFailures = false
|
||||
failFast = true
|
||||
maxParallelForks = 12
|
||||
}
|
||||
|
||||
tasks.named<ShadowJar>("shadowJar") {
|
||||
from(tokenizeJavaSources.destinationDir)
|
||||
|
||||
archiveClassifier.set("")
|
||||
archiveBaseName.set("Terra")
|
||||
setVersion(project.version)
|
||||
relocate("org.apache.commons", "com.dfsek.terra.lib.commons")
|
||||
relocate("org.bstats.bukkit", "com.dfsek.terra.lib.bstats")
|
||||
relocate("parsii", "com.dfsek.terra.lib.parsii")
|
||||
relocate("io.papermc.lib", "com.dfsek.terra.lib.paperlib")
|
||||
relocate("net.jafama", "com.dfsek.terra.lib.jafama")
|
||||
minimize()
|
||||
}
|
||||
|
||||
tasks.build {
|
||||
dependsOn(tasks.shadowJar)
|
||||
// dependsOn(testWithPaper)
|
||||
// testWithPaper.mustRunAfter(tasks.shadowJar)
|
||||
}
|
||||
|
||||
val testDir = "target/server/"
|
||||
|
||||
val setupServer = tasks.create("setupServer") {
|
||||
dependsOn(tasks.shadowJar)
|
||||
doFirst {
|
||||
// clean
|
||||
file("${testDir}/").deleteRecursively()
|
||||
file("${testDir}/plugins").mkdirs()
|
||||
|
||||
// Downloading latest paper jar.
|
||||
val paperUrl = URL("https://papermc.io/api/v1/paper/1.16.4/latest/download")
|
||||
val paperReadableByteChannel = Channels.newChannel(paperUrl.openStream())
|
||||
val paperFile = file("${testDir}/paper.jar")
|
||||
val paperFileOutputStream = paperFile.outputStream()
|
||||
val paperFileChannel = paperFileOutputStream.channel
|
||||
paperFileChannel.transferFrom(paperReadableByteChannel, 0, Long.MAX_VALUE)
|
||||
|
||||
// Cloning test setup.
|
||||
gitClone("https://github.com/PolyhedralDev/WorldGenTestServer")
|
||||
// Copying plugins
|
||||
Files.move(Paths.get("WorldGenTestServer/plugins"),
|
||||
Paths.get("$testDir/plugins"),
|
||||
StandardCopyOption.REPLACE_EXISTING)
|
||||
// Copying config
|
||||
val serverText = URL("https://raw.githubusercontent.com/PolyhedralDev/WorldGenTestServer/master/server.properties").readText()
|
||||
file("${testDir}/server.properties").writeText(serverText)
|
||||
val bukkitText = URL("https://raw.githubusercontent.com/PolyhedralDev/WorldGenTestServer/master/bukkit.yml").readText()
|
||||
file("${testDir}/bukkit.yml").writeText(bukkitText.replace("\${world}", "world").replace("\${gen}", "Terra:DEFAULT"))
|
||||
|
||||
File("${testDir}/eula.txt").writeText("eula=true")
|
||||
|
||||
// clean up
|
||||
file("WorldGenTestServer").deleteRecursively()
|
||||
}
|
||||
}
|
||||
|
||||
val downloadDefaultPacks = tasks.create("downloadDefaultPacks") {
|
||||
doFirst {
|
||||
// Downloading latest paper jar.
|
||||
// if (file("${buildDir}/resources/main/packs/default").exists() && file("${buildDir}/resources/main/packs/nether").exists())
|
||||
// return@doFirst
|
||||
// else
|
||||
file("${buildDir}/resources/main/packs/").deleteRecursively()
|
||||
|
||||
val defaultPackUrl = URL("https://github.com/PolyhedralDev/TerraDefaultConfig/releases/download/latest/default.zip")
|
||||
downloadAndUnzipPack(defaultPackUrl)
|
||||
val netherPackUrl = URL("https://github.com/PolyhedralDev/TerraDefaultConfig/releases/download/latest/nether.zip")
|
||||
downloadAndUnzipPack(netherPackUrl)
|
||||
}
|
||||
}
|
||||
tasks.processResources.get().dependsOn(downloadDefaultPacks)
|
||||
|
||||
val testWithPaper = task<JavaExec>(name = "testWithPaper") {
|
||||
standardInput = System.`in`
|
||||
dependsOn(tasks.shadowJar)
|
||||
// Copy Terra into dir
|
||||
doFirst {
|
||||
copy {
|
||||
from("${buildDir}/libs/Terra-${versionObj}.jar")
|
||||
into("${testDir}/plugins/")
|
||||
}
|
||||
}
|
||||
|
||||
main = "io.papermc.paperclip.Paperclip"
|
||||
jvmArgs = listOf("-XX:+UseG1GC", "-XX:+ParallelRefProcEnabled", "-XX:MaxGCPauseMillis=200",
|
||||
"-XX:+UnlockExperimentalVMOptions", "-XX:+DisableExplicitGC", "-XX:+AlwaysPreTouch",
|
||||
"-XX:G1NewSizePercent=30", "-XX:G1MaxNewSizePercent=40", "-XX:G1HeapRegionSize=8M",
|
||||
"-XX:G1ReservePercent=20", "-XX:G1HeapWastePercent=5", "-XX:G1MixedGCCountTarget=4",
|
||||
"-XX:InitiatingHeapOccupancyPercent=15", "-XX:G1MixedGCLiveThresholdPercent=90",
|
||||
"-XX:G1RSetUpdatingPauseTimePercent=5", "-XX:SurvivorRatio=32", "-XX:+PerfDisableSharedMem",
|
||||
"-XX:MaxTenuringThreshold=1", "-Dusing.aikars.flags=https://mcflags.emc.gs",
|
||||
"-Daikars.new.flags=true", "-DIReallyKnowWhatIAmDoingISwear")
|
||||
maxHeapSize = "2G"
|
||||
args = listOf("nogui")
|
||||
workingDir = file("${testDir}/")
|
||||
classpath = files("${testDir}/paper.jar")
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Version class that does version stuff.
|
||||
*/
|
||||
@@ -207,35 +18,4 @@ class Version(val major: String, val minor: String, val revision: String, val pr
|
||||
else //Only use git hash if it's a prerelease.
|
||||
"$major.$minor.$revision-BETA+${getGitHash()}"
|
||||
}
|
||||
}
|
||||
|
||||
fun getGitHash(): String {
|
||||
val stdout = ByteArrayOutputStream()
|
||||
exec {
|
||||
commandLine = mutableListOf("git", "rev-parse", "--short", "HEAD")
|
||||
standardOutput = stdout
|
||||
}
|
||||
return stdout.toString().trim()
|
||||
}
|
||||
|
||||
fun gitClone(name: String) {
|
||||
val stdout = ByteArrayOutputStream()
|
||||
exec {
|
||||
commandLine = mutableListOf("git", "clone", name)
|
||||
standardOutput = stdout
|
||||
}
|
||||
}
|
||||
|
||||
fun downloadAndUnzipPack(packUrl: URL) {
|
||||
ZipInputStream(packUrl.openStream()).use { zip ->
|
||||
while (true) {
|
||||
val entry = zip.nextEntry ?: break
|
||||
if (entry.isDirectory)
|
||||
file("${buildDir}/resources/main/packs/${entry.name}").mkdirs()
|
||||
else
|
||||
file("${buildDir}/resources/main/packs/${entry.name}").outputStream().use { output ->
|
||||
output.write(zip.readBytes())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
13
buildSrc/build.gradle.kts
Normal file
13
buildSrc/build.gradle.kts
Normal file
@@ -0,0 +1,13 @@
|
||||
plugins {
|
||||
`kotlin-dsl`
|
||||
kotlin("jvm") version embeddedKotlinVersion
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
gradlePluginPortal()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
"implementation"("com.github.jengelman.gradle.plugins:shadow:+")
|
||||
}
|
||||
47
buildSrc/src/main/kotlin/com/dfsek/terra/CommonConfig.kt
Normal file
47
buildSrc/src/main/kotlin/com/dfsek/terra/CommonConfig.kt
Normal file
@@ -0,0 +1,47 @@
|
||||
package com.dfsek.terra
|
||||
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.tasks.testing.Test
|
||||
import org.gradle.kotlin.dsl.apply
|
||||
import org.gradle.kotlin.dsl.withType
|
||||
import java.io.ByteArrayOutputStream
|
||||
|
||||
fun Project.configureCommon() {
|
||||
apply(plugin = "java-library")
|
||||
apply(plugin = "maven-publish")
|
||||
apply(plugin = "idea")
|
||||
|
||||
configureDependencies()
|
||||
configureCompilation()
|
||||
configureDistribution()
|
||||
|
||||
version = rootProject.version
|
||||
|
||||
|
||||
|
||||
tasks.withType<Test>().configureEach {
|
||||
useJUnitPlatform()
|
||||
|
||||
maxHeapSize = "2G"
|
||||
ignoreFailures = false
|
||||
failFast = true
|
||||
maxParallelForks = 12
|
||||
}
|
||||
}
|
||||
|
||||
fun Project.getGitHash(): String {
|
||||
val stdout = ByteArrayOutputStream()
|
||||
exec {
|
||||
commandLine = mutableListOf("git", "rev-parse", "--short", "HEAD")
|
||||
standardOutput = stdout
|
||||
}
|
||||
return stdout.toString().trim()
|
||||
}
|
||||
|
||||
fun Project.gitClone(name: String) {
|
||||
val stdout = ByteArrayOutputStream()
|
||||
exec {
|
||||
commandLine = mutableListOf("git", "clone", name)
|
||||
standardOutput = stdout
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.dfsek.terra
|
||||
|
||||
import org.gradle.api.JavaVersion
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.plugins.JavaPluginConvention
|
||||
import org.gradle.api.tasks.compile.JavaCompile
|
||||
import org.gradle.api.tasks.javadoc.Javadoc
|
||||
import org.gradle.kotlin.dsl.configure
|
||||
import org.gradle.kotlin.dsl.filter
|
||||
import org.gradle.kotlin.dsl.withType
|
||||
import org.gradle.language.jvm.tasks.ProcessResources
|
||||
|
||||
fun Project.configureCompilation() {
|
||||
configure<JavaPluginConvention> {
|
||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||
targetCompatibility = JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
tasks.withType<JavaCompile> {
|
||||
options.encoding = "UTF-8"
|
||||
doFirst {
|
||||
options.compilerArgs = mutableListOf("-Xlint:all")
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType<ProcessResources> {
|
||||
include("**/*.*")
|
||||
filter<org.apache.tools.ant.filters.ReplaceTokens>(
|
||||
"tokens" to mapOf(
|
||||
"VERSION" to project.version.toString()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
tasks.withType<Javadoc> {
|
||||
options.encoding = "UTF-8"
|
||||
}
|
||||
}
|
||||
26
buildSrc/src/main/kotlin/com/dfsek/terra/DependencyConfig.kt
Normal file
26
buildSrc/src/main/kotlin/com/dfsek/terra/DependencyConfig.kt
Normal file
@@ -0,0 +1,26 @@
|
||||
package com.dfsek.terra
|
||||
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.kotlin.dsl.dependencies
|
||||
import org.gradle.kotlin.dsl.repositories
|
||||
|
||||
fun Project.configureDependencies() {
|
||||
|
||||
repositories {
|
||||
maven { url = uri("http://maven.enginehub.org/repo/") }
|
||||
maven { url = uri("https://repo.codemc.org/repository/maven-public") }
|
||||
maven { url = uri("https://papermc.io/repo/repository/maven-public/") }
|
||||
maven { url = uri("https://maven.fabricmc.net/") }
|
||||
gradlePluginPortal()
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
"testImplementation"("org.junit.jupiter:junit-jupiter-api:5.7.0")
|
||||
"testImplementation"("org.yaml:snakeyaml:1.27")
|
||||
"testImplementation"("com.googlecode.json-simple:json-simple:1.1.1")
|
||||
"testRuntimeOnly"("org.junit.jupiter:junit-jupiter-engine:5.7.0")
|
||||
"compileOnly"("org.jetbrains:annotations:20.1.0")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package com.dfsek.terra
|
||||
|
||||
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.plugins.BasePluginConvention
|
||||
import org.gradle.api.tasks.bundling.Jar
|
||||
import org.gradle.api.tasks.javadoc.Javadoc
|
||||
import org.gradle.kotlin.dsl.*
|
||||
import java.io.File
|
||||
import java.net.URL
|
||||
|
||||
fun Project.configureDistribution() {
|
||||
apply(plugin = "java-library")
|
||||
apply(plugin = "com.github.johnrengelman.shadow")
|
||||
|
||||
configurations {
|
||||
val shaded = create("shaded")
|
||||
getByName("compile").extendsFrom(shaded)
|
||||
val shadedApi = create("shadedApi")
|
||||
shaded.extendsFrom(shadedApi)
|
||||
getByName("api").extendsFrom(shadedApi)
|
||||
val shadedImplementation = create("shadedImplementation")
|
||||
shaded.extendsFrom(shadedImplementation)
|
||||
getByName("implementation").extendsFrom(shadedImplementation)
|
||||
}
|
||||
|
||||
val downloadDefaultPacks = tasks.create("downloadDefaultPacks") {
|
||||
group = "terra"
|
||||
doFirst {
|
||||
file("${buildDir}/resources/main/packs/").deleteRecursively()
|
||||
|
||||
val defaultPackUrl = URL("https://github.com/PolyhedralDev/TerraDefaultConfig/releases/download/latest/default.zip")
|
||||
downloadPack(defaultPackUrl, project)
|
||||
val netherPackUrl = URL("https://github.com/PolyhedralDev/TerraDefaultConfig/releases/download/latest/nether.zip")
|
||||
downloadPack(netherPackUrl, project)
|
||||
}
|
||||
}
|
||||
tasks["processResources"].dependsOn(downloadDefaultPacks)
|
||||
|
||||
tasks.withType<Jar> {
|
||||
archiveBaseName.set("Terra-${archiveBaseName.get()}")
|
||||
from("../LICENSE", "../../LICENSE")
|
||||
}
|
||||
|
||||
tasks.register<Jar>("sourcesJar") {
|
||||
archiveClassifier.set("sources")
|
||||
}
|
||||
|
||||
tasks.register<Jar>("javadocJar") {
|
||||
dependsOn("javadoc")
|
||||
archiveClassifier.set("javadoc")
|
||||
from(tasks.getByName<Javadoc>("javadoc").destinationDir)
|
||||
}
|
||||
|
||||
tasks.named<ShadowJar>("shadowJar") {
|
||||
// Tell shadow to download the packs
|
||||
dependsOn(downloadDefaultPacks)
|
||||
|
||||
configurations = listOf(project.configurations["shaded"])
|
||||
|
||||
archiveClassifier.set("shaded")
|
||||
setVersion(project.version)
|
||||
relocate("org.apache.commons", "com.dfsek.terra.lib.commons")
|
||||
relocate("parsii", "com.dfsek.terra.lib.parsii")
|
||||
relocate("net.jafama", "com.dfsek.terra.lib.jafama")
|
||||
minimize()
|
||||
}
|
||||
convention.getPlugin<BasePluginConvention>().archivesBaseName = project.name
|
||||
|
||||
tasks.named<DefaultTask>("build") {
|
||||
dependsOn(tasks["shadowJar"])
|
||||
}
|
||||
}
|
||||
|
||||
fun downloadPack(packUrl: URL, project: Project) {
|
||||
val fileName = packUrl.file.substring(packUrl.file.lastIndexOf("/"))
|
||||
val file = File("${project.buildDir}/resources/main/packs/${fileName}")
|
||||
file.parentFile.mkdirs()
|
||||
file.outputStream().write(packUrl.readBytes())
|
||||
}
|
||||
53
common/build.gradle.kts
Normal file
53
common/build.gradle.kts
Normal file
@@ -0,0 +1,53 @@
|
||||
import com.dfsek.terra.configureCommon
|
||||
|
||||
plugins {
|
||||
`java-library`
|
||||
`maven-publish`
|
||||
}
|
||||
|
||||
configureCommon()
|
||||
|
||||
group = "com.dfsek.terra.common"
|
||||
|
||||
dependencies {
|
||||
"shadedApi"("org.apache.commons:commons-rng-core:1.3")
|
||||
"shadedApi"("commons-io:commons-io:2.4")
|
||||
|
||||
"shadedApi"("com.dfsek:Paralithic:0.3.2")
|
||||
"shadedApi"("com.dfsek:Tectonic:1.2.3")
|
||||
"shadedApi"("net.jafama:jafama:2.3.2")
|
||||
"shadedApi"("org.yaml:snakeyaml:1.27")
|
||||
"shadedApi"("org.ow2.asm:asm:9.0")
|
||||
"shadedApi"("commons-io:commons-io:2.6")
|
||||
|
||||
"compileOnly"("com.googlecode.json-simple:json-simple:1.1")
|
||||
|
||||
"compileOnly"("com.google.guava:guava:30.0-jre")
|
||||
|
||||
"testImplementation"("com.google.guava:guava:30.0-jre")
|
||||
}
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
create<MavenPublication>("mavenJava") {
|
||||
artifact(tasks["sourcesJar"])
|
||||
artifact(tasks["jar"])
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
val mavenUrl = "https://repo.codemc.io/repository/maven-releases/"
|
||||
val mavenSnapshotUrl = "https://repo.codemc.io/repository/maven-snapshots/"
|
||||
|
||||
maven(mavenUrl) {
|
||||
val mavenUsername: String? by project
|
||||
val mavenPassword: String? by project
|
||||
if (mavenUsername != null && mavenPassword != null) {
|
||||
credentials {
|
||||
username = mavenUsername
|
||||
password = mavenPassword
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.dfsek.terra.addon;
|
||||
|
||||
import com.dfsek.terra.api.addons.TerraAddon;
|
||||
import com.dfsek.terra.api.addons.annotations.Addon;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
public class AddonClassLoader extends URLClassLoader {
|
||||
static {
|
||||
ClassLoader.registerAsParallelCapable();
|
||||
}
|
||||
|
||||
public AddonClassLoader(URL[] urls, ClassLoader parent) {
|
||||
super(urls, parent);
|
||||
}
|
||||
|
||||
public AddonClassLoader(URL[] urls) {
|
||||
super(urls);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Set<Class<? extends TerraAddon>> fetchAddonClasses(File file) throws IOException {
|
||||
JarFile jarFile = new JarFile(file);
|
||||
Enumeration<JarEntry> entries = jarFile.entries();
|
||||
|
||||
AddonClassLoader loader = new AddonClassLoader(new URL[] {file.toURI().toURL()}, AddonClassLoader.class.getClassLoader());
|
||||
|
||||
Set<Class<? extends TerraAddon>> set = new HashSet<>();
|
||||
while(entries.hasMoreElements()) {
|
||||
JarEntry entry = entries.nextElement();
|
||||
|
||||
if(entry.isDirectory() || !entry.getName().endsWith(".class")) continue;
|
||||
String className = entry.getName().substring(0, entry.getName().length() - 6).replace('/', '.');
|
||||
|
||||
try {
|
||||
Class<?> clazz = loader.loadClass(className);
|
||||
|
||||
Addon addon = clazz.getAnnotation(Addon.class);
|
||||
|
||||
if(addon == null) continue;
|
||||
|
||||
if(!TerraAddon.class.isAssignableFrom(clazz))
|
||||
throw new IllegalArgumentException("Addon class \"" + clazz + "\" must extend TerraAddon.");
|
||||
|
||||
set.add((Class<? extends TerraAddon>) clazz);
|
||||
} catch(ClassNotFoundException e) {
|
||||
throw new IllegalStateException(e); // this should literally never happen, if it does something is very wrong
|
||||
}
|
||||
}
|
||||
|
||||
return set;
|
||||
}
|
||||
}
|
||||
42
common/src/main/java/com/dfsek/terra/addon/AddonPool.java
Normal file
42
common/src/main/java/com/dfsek/terra/addon/AddonPool.java
Normal file
@@ -0,0 +1,42 @@
|
||||
package com.dfsek.terra.addon;
|
||||
|
||||
import com.dfsek.terra.addon.exception.AddonLoadException;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class AddonPool {
|
||||
private final Map<String, PreLoadAddon> pool = new HashMap<>();
|
||||
|
||||
public void add(PreLoadAddon addon) throws AddonLoadException {
|
||||
if(pool.containsKey(addon.getId())) {
|
||||
String message = "Duplicate addon ID: " +
|
||||
addon.getId() + "; original ID from file: " +
|
||||
pool.get(addon.getId()).getFile().getAbsolutePath() +
|
||||
", class: " +
|
||||
pool.get(addon.getId()).getAddonClass().getCanonicalName() +
|
||||
"Duplicate ID from file: " +
|
||||
addon.getFile().getAbsolutePath() +
|
||||
", class: " +
|
||||
addon.getAddonClass().getCanonicalName();
|
||||
throw new AddonLoadException(message);
|
||||
}
|
||||
pool.put(addon.getId(), addon);
|
||||
}
|
||||
|
||||
public PreLoadAddon get(String id) {
|
||||
return pool.get(id);
|
||||
}
|
||||
|
||||
public void buildAll() throws AddonLoadException {
|
||||
for(PreLoadAddon value : pool.values()) {
|
||||
value.rebuildDependencies(this, value, true);
|
||||
}
|
||||
}
|
||||
|
||||
public Set<PreLoadAddon> getAddons() {
|
||||
return new HashSet<>(pool.values());
|
||||
}
|
||||
}
|
||||
58
common/src/main/java/com/dfsek/terra/addon/PreLoadAddon.java
Normal file
58
common/src/main/java/com/dfsek/terra/addon/PreLoadAddon.java
Normal file
@@ -0,0 +1,58 @@
|
||||
package com.dfsek.terra.addon;
|
||||
|
||||
import com.dfsek.terra.addon.exception.AddonLoadException;
|
||||
import com.dfsek.terra.addon.exception.CircularDependencyException;
|
||||
import com.dfsek.terra.addon.exception.DependencyMissingException;
|
||||
import com.dfsek.terra.api.addons.TerraAddon;
|
||||
import com.dfsek.terra.api.addons.annotations.Addon;
|
||||
import com.dfsek.terra.api.addons.annotations.Depends;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class PreLoadAddon {
|
||||
private final List<PreLoadAddon> depends = new ArrayList<>();
|
||||
private final Class<? extends TerraAddon> addonClass;
|
||||
private final String id;
|
||||
private final String[] dependencies;
|
||||
private final File file;
|
||||
|
||||
public PreLoadAddon(Class<? extends TerraAddon> addonClass, File file) {
|
||||
this.addonClass = addonClass;
|
||||
this.id = addonClass.getAnnotation(Addon.class).value();
|
||||
this.file = file;
|
||||
Depends depends = addonClass.getAnnotation(Depends.class);
|
||||
this.dependencies = depends == null ? new String[] {} : depends.value();
|
||||
}
|
||||
|
||||
public List<PreLoadAddon> getDepends() {
|
||||
return depends;
|
||||
}
|
||||
|
||||
public void rebuildDependencies(AddonPool pool, PreLoadAddon origin, boolean levelG1) throws AddonLoadException {
|
||||
if(this.equals(origin) && !levelG1)
|
||||
throw new CircularDependencyException("Detected circular dependency in addon \"" + id + "\", dependencies: " + Arrays.toString(dependencies));
|
||||
|
||||
for(String dependency : dependencies) {
|
||||
PreLoadAddon preLoadAddon = pool.get(dependency);
|
||||
if(preLoadAddon == null)
|
||||
throw new DependencyMissingException("Dependency " + dependency + " was not found. Please install " + dependency + " to use " + id + ".");
|
||||
depends.add(preLoadAddon);
|
||||
preLoadAddon.rebuildDependencies(pool, origin, false);
|
||||
}
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public Class<? extends TerraAddon> getAddonClass() {
|
||||
return addonClass;
|
||||
}
|
||||
|
||||
public File getFile() {
|
||||
return file;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.dfsek.terra.addon.exception;
|
||||
|
||||
public class AddonLoadException extends Exception {
|
||||
private static final long serialVersionUID = -4949084729296580176L;
|
||||
|
||||
public AddonLoadException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public AddonLoadException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.dfsek.terra.addon.exception;
|
||||
|
||||
public class CircularDependencyException extends AddonLoadException {
|
||||
private static final long serialVersionUID = 7398510879124125121L;
|
||||
|
||||
public CircularDependencyException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public CircularDependencyException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.dfsek.terra.addon.exception;
|
||||
|
||||
public class DependencyMissingException extends AddonLoadException {
|
||||
private static final long serialVersionUID = -8419489102208521583L;
|
||||
|
||||
public DependencyMissingException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public DependencyMissingException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.dfsek.terra.api;
|
||||
|
||||
import com.dfsek.tectonic.loading.TypeRegistry;
|
||||
|
||||
public interface LoaderRegistrar {
|
||||
void register(TypeRegistry registry);
|
||||
}
|
||||
67
common/src/main/java/com/dfsek/terra/api/TerraPlugin.java
Normal file
67
common/src/main/java/com/dfsek/terra/api/TerraPlugin.java
Normal file
@@ -0,0 +1,67 @@
|
||||
package com.dfsek.terra.api;
|
||||
|
||||
import com.dfsek.terra.api.addons.TerraAddon;
|
||||
import com.dfsek.terra.api.event.EventManager;
|
||||
import com.dfsek.terra.api.platform.handle.ItemHandle;
|
||||
import com.dfsek.terra.api.platform.handle.WorldHandle;
|
||||
import com.dfsek.terra.api.platform.world.World;
|
||||
import com.dfsek.terra.api.registry.CheckedRegistry;
|
||||
import com.dfsek.terra.api.registry.LockedRegistry;
|
||||
import com.dfsek.terra.api.util.logging.DebugLogger;
|
||||
import com.dfsek.terra.api.util.logging.Logger;
|
||||
import com.dfsek.terra.config.PluginConfig;
|
||||
import com.dfsek.terra.config.lang.Language;
|
||||
import com.dfsek.terra.config.pack.ConfigPack;
|
||||
import com.dfsek.terra.world.TerraWorld;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* Represents a Terra mod/plugin instance.
|
||||
*/
|
||||
public interface TerraPlugin extends LoaderRegistrar {
|
||||
WorldHandle getWorldHandle();
|
||||
|
||||
TerraWorld getWorld(World world);
|
||||
|
||||
Logger logger();
|
||||
|
||||
PluginConfig getTerraConfig();
|
||||
|
||||
File getDataFolder();
|
||||
|
||||
boolean isDebug();
|
||||
|
||||
Language getLanguage();
|
||||
|
||||
CheckedRegistry<ConfigPack> getConfigRegistry();
|
||||
|
||||
LockedRegistry<TerraAddon> getAddons();
|
||||
|
||||
boolean reload();
|
||||
|
||||
ItemHandle getItemHandle();
|
||||
|
||||
void saveDefaultConfig();
|
||||
|
||||
String platformName();
|
||||
|
||||
DebugLogger getDebugLogger();
|
||||
|
||||
EventManager getEventManager();
|
||||
|
||||
default String getVersion() {
|
||||
return "@VERSION@";
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs a task that may or may not be thread safe, depending on platform.
|
||||
* <p>
|
||||
* Allows platforms to define what code is safe to be run asynchronously.
|
||||
*
|
||||
* @param task Task to be run.
|
||||
*/
|
||||
default void runPossiblyUnsafeTask(Runnable task) {
|
||||
task.run();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.dfsek.terra.api.addons;
|
||||
|
||||
|
||||
import com.dfsek.terra.api.addons.annotations.Addon;
|
||||
import com.dfsek.terra.api.addons.annotations.Author;
|
||||
import com.dfsek.terra.api.addons.annotations.Version;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Represents an entry point for an addon. Implementations must be annotated with {@link Addon}.
|
||||
*/
|
||||
public abstract class TerraAddon {
|
||||
/**
|
||||
* Gets the version of this addon.
|
||||
*
|
||||
* @return Addon version.
|
||||
*/
|
||||
public final @NotNull String getVersion() {
|
||||
Version version = getClass().getAnnotation(Version.class);
|
||||
return version == null ? "0.1.0" : version.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the author of this addon.
|
||||
*
|
||||
* @return Addon author.
|
||||
*/
|
||||
public final @NotNull String getAuthor() {
|
||||
Author author = getClass().getAnnotation(Author.class);
|
||||
return author == null ? "Anon Y. Mous" : author.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name (ID) of this addon.
|
||||
*
|
||||
* @return Addon ID.
|
||||
*/
|
||||
public final @NotNull String getName() {
|
||||
Addon addon = getClass().getAnnotation(Addon.class);
|
||||
if(addon == null)
|
||||
throw new IllegalStateException("Addon annotation not present"); // This should never happen; the presence of this annotation is checked by the addon loader.
|
||||
return addon.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked immediately after an addon is loaded.
|
||||
*/
|
||||
public abstract void initialize();
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.dfsek.terra.api.addons.annotations;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Specifies that the annotated class is an entry point for a Terra addon.
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Addon {
|
||||
/**
|
||||
* @return The ID of the addon.
|
||||
*/
|
||||
@NotNull String value();
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.dfsek.terra.api.addons.annotations;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Optional annotation that specifies the author of an addon.
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface Author {
|
||||
/**
|
||||
* @return Name of the addon author.
|
||||
*/
|
||||
@NotNull String value();
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.dfsek.terra.api.addons.annotations;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Optional annotation that specifies dependencies of an addon.
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Depends {
|
||||
/**
|
||||
* @return All addons this addon is dependent upon.
|
||||
*/
|
||||
@NotNull String[] value();
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.dfsek.terra.api.addons.annotations;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Optional annotation that specifies the version of an addon.
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Version {
|
||||
/**
|
||||
* @return Version of the addon.
|
||||
*/
|
||||
@NotNull String value();
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.dfsek.terra.api.command;
|
||||
|
||||
import com.dfsek.terra.api.command.exception.CommandException;
|
||||
import com.dfsek.terra.api.command.exception.MalformedCommandException;
|
||||
import com.dfsek.terra.api.platform.CommandSender;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface CommandManager {
|
||||
void execute(String command, CommandSender sender, List<String> args) throws CommandException;
|
||||
|
||||
void register(String name, Class<? extends CommandTemplate> clazz) throws MalformedCommandException;
|
||||
|
||||
List<String> tabComplete(String command, CommandSender sender, List<String> args) throws CommandException;
|
||||
|
||||
int getMaxArgumentDepth();
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.dfsek.terra.api.command;
|
||||
|
||||
import com.dfsek.terra.api.platform.CommandSender;
|
||||
|
||||
public interface CommandTemplate {
|
||||
void execute(CommandSender sender);
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.dfsek.terra.api.command;
|
||||
|
||||
import com.dfsek.terra.api.platform.CommandSender;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public final class ExecutionState {
|
||||
private final Set<String> switches = new HashSet<>();
|
||||
private final Map<String, String> args = new HashMap<>();
|
||||
private final CommandSender sender;
|
||||
|
||||
protected ExecutionState(CommandSender sender) {
|
||||
this.sender = sender;
|
||||
}
|
||||
|
||||
protected void addSwitch(String flag) {
|
||||
switches.add(flag);
|
||||
}
|
||||
|
||||
protected void addArgument(String arg, String value) {
|
||||
args.put(arg, value);
|
||||
}
|
||||
|
||||
public String getArgument(String argument) {
|
||||
return args.get(argument);
|
||||
}
|
||||
|
||||
public boolean hasSwitch(String flag) {
|
||||
return switches.contains(flag);
|
||||
}
|
||||
|
||||
public CommandSender getSender() {
|
||||
return sender;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,283 @@
|
||||
package com.dfsek.terra.api.command;
|
||||
|
||||
import com.dfsek.terra.api.TerraPlugin;
|
||||
import com.dfsek.terra.api.command.annotation.Argument;
|
||||
import com.dfsek.terra.api.command.annotation.Command;
|
||||
import com.dfsek.terra.api.command.annotation.Subcommand;
|
||||
import com.dfsek.terra.api.command.annotation.Switch;
|
||||
import com.dfsek.terra.api.command.annotation.inject.ArgumentTarget;
|
||||
import com.dfsek.terra.api.command.annotation.inject.SwitchTarget;
|
||||
import com.dfsek.terra.api.command.annotation.type.DebugCommand;
|
||||
import com.dfsek.terra.api.command.annotation.type.PlayerCommand;
|
||||
import com.dfsek.terra.api.command.annotation.type.WorldCommand;
|
||||
import com.dfsek.terra.api.command.arg.ArgumentParser;
|
||||
import com.dfsek.terra.api.command.exception.CommandException;
|
||||
import com.dfsek.terra.api.command.exception.ExecutionException;
|
||||
import com.dfsek.terra.api.command.exception.InvalidArgumentsException;
|
||||
import com.dfsek.terra.api.command.exception.MalformedCommandException;
|
||||
import com.dfsek.terra.api.command.exception.SwitchFormatException;
|
||||
import com.dfsek.terra.api.command.tab.TabCompleter;
|
||||
import com.dfsek.terra.api.injection.Injector;
|
||||
import com.dfsek.terra.api.injection.exception.InjectionException;
|
||||
import com.dfsek.terra.api.platform.CommandSender;
|
||||
import com.dfsek.terra.api.platform.entity.Player;
|
||||
import com.dfsek.terra.api.util.ReflectionUtil;
|
||||
import com.dfsek.terra.world.TerraWorld;
|
||||
import net.jafama.FastMath;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class TerraCommandManager implements CommandManager {
|
||||
private final Map<String, CommandHolder> commands = new HashMap<>();
|
||||
private final Injector<TerraPlugin> pluginInjector;
|
||||
private final TerraPlugin main;
|
||||
|
||||
public TerraCommandManager(TerraPlugin main) {
|
||||
this.main = main;
|
||||
this.pluginInjector = new Injector<>(main);
|
||||
pluginInjector.addExplicitTarget(TerraPlugin.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(String commandName, CommandSender sender, List<String> argsIn) throws CommandException {
|
||||
if(!commands.containsKey(commandName)) throw new InvalidArgumentsException("No such command \"" + commandName + "\"");
|
||||
execute(commands.get(commandName), sender, new ArrayList<>(argsIn));
|
||||
}
|
||||
|
||||
private void execute(CommandHolder commandHolder, CommandSender sender, List<String> args) throws CommandException {
|
||||
Class<? extends CommandTemplate> commandClass = commandHolder.clazz;
|
||||
|
||||
if(commandClass.isAnnotationPresent(DebugCommand.class) && !main.isDebug()) {
|
||||
sender.sendMessage("Command must be executed with debug mode enabled.");
|
||||
return;
|
||||
}
|
||||
|
||||
if(commandClass.isAnnotationPresent(PlayerCommand.class) && !(sender instanceof Player)) {
|
||||
sender.sendMessage("Command must be executed by player.");
|
||||
return;
|
||||
}
|
||||
|
||||
if(commandClass.isAnnotationPresent(WorldCommand.class) && (!(sender instanceof Player) || !TerraWorld.isTerraWorld(((Player) sender).getWorld()))) {
|
||||
sender.sendMessage("Command must be executed in a Terra world.");
|
||||
return;
|
||||
}
|
||||
|
||||
List<String> ogArgs = new ArrayList<>(args);
|
||||
|
||||
ExecutionState state = new ExecutionState(sender);
|
||||
|
||||
if(!commandClass.isAnnotationPresent(Command.class)) {
|
||||
invoke(commandClass, state, commandHolder);
|
||||
return;
|
||||
}
|
||||
|
||||
Command command = commandClass.getAnnotation(Command.class);
|
||||
|
||||
if(command.arguments().length == 0 && command.subcommands().length == 0) {
|
||||
if(args.isEmpty()) {
|
||||
invoke(commandClass, state, commandHolder);
|
||||
return;
|
||||
} else throw new InvalidArgumentsException("Expected 0 arguments, found " + args.size());
|
||||
}
|
||||
|
||||
if(!args.isEmpty() && commandHolder.subcommands.containsKey(args.get(0))) {
|
||||
String c = args.get(0);
|
||||
args.remove(0);
|
||||
execute(commandHolder.subcommands.get(c), sender, args);
|
||||
return;
|
||||
}
|
||||
|
||||
boolean req = true;
|
||||
for(Argument argument : command.arguments()) {
|
||||
if(!req && argument.required()) {
|
||||
throw new MalformedCommandException("Required arguments must come first! Arguments: " + Arrays.toString(command.arguments()));
|
||||
}
|
||||
req = argument.required();
|
||||
|
||||
if(args.isEmpty()) {
|
||||
if(req) throw new InvalidArgumentsException("Invalid arguments: " + ogArgs + ", usage: " + command.usage());
|
||||
break;
|
||||
}
|
||||
|
||||
String arg = args.get(0);
|
||||
|
||||
if(arg.startsWith("-")) { // switches have started.
|
||||
if(req) throw new InvalidArgumentsException("Switches must come after arguments.");
|
||||
break;
|
||||
}
|
||||
|
||||
state.addArgument(argument.value(), args.remove(0));
|
||||
}
|
||||
|
||||
while(!args.isEmpty()) {
|
||||
String aSwitch = args.remove(0);
|
||||
if(!aSwitch.startsWith("-")) throw new SwitchFormatException("Invalid switch \"" + aSwitch + "\"");
|
||||
|
||||
String val = aSwitch.substring(1); // remove dash
|
||||
|
||||
if(!commandHolder.switches.containsKey(val)) throw new SwitchFormatException("No such switch \"" + aSwitch + "\"");
|
||||
|
||||
state.addSwitch(commandHolder.switches.get(val));
|
||||
}
|
||||
|
||||
invoke(commandClass, state, commandHolder);
|
||||
}
|
||||
|
||||
private void invoke(Class<? extends CommandTemplate> clazz, ExecutionState state, CommandHolder holder) throws CommandException {
|
||||
try {
|
||||
CommandTemplate template = clazz.getConstructor().newInstance();
|
||||
|
||||
pluginInjector.inject(template);
|
||||
|
||||
for(Field field : ReflectionUtil.getFields(clazz)) {
|
||||
if(field.isAnnotationPresent(ArgumentTarget.class)) {
|
||||
ArgumentTarget argumentTarget = field.getAnnotation(ArgumentTarget.class);
|
||||
if(!holder.argumentMap.containsKey(argumentTarget.value())) {
|
||||
throw new MalformedCommandException("Argument Target specifies nonexistent argument \"" + argumentTarget.value() + "\"");
|
||||
}
|
||||
|
||||
String argument = argumentTarget.value();
|
||||
|
||||
ArgumentParser<?> argumentParser = holder.argumentMap.get(argumentTarget.value()).argumentParser().getConstructor().newInstance();
|
||||
|
||||
pluginInjector.inject(argumentParser);
|
||||
|
||||
field.setAccessible(true);
|
||||
String value = state.getArgument(argument);
|
||||
|
||||
if(value == null) value = holder.argumentMap.get(argumentTarget.value()).defaultValue();
|
||||
|
||||
field.set(template, argumentParser.parse(state.getSender(), value));
|
||||
}
|
||||
if(field.isAnnotationPresent(SwitchTarget.class)) {
|
||||
SwitchTarget switchTarget = field.getAnnotation(SwitchTarget.class);
|
||||
if(!holder.switches.containsValue(switchTarget.value())) {
|
||||
throw new MalformedCommandException("Switch Target specifies nonexistent switch \"" + switchTarget.value() + "\"");
|
||||
}
|
||||
|
||||
if(!(field.getType() == boolean.class)) {
|
||||
throw new MalformedCommandException("Switch Target must be of type boolean.");
|
||||
}
|
||||
|
||||
field.setAccessible(true);
|
||||
field.setBoolean(template, state.hasSwitch(switchTarget.value()));
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
template.execute(state.getSender());
|
||||
} catch(Throwable e) {
|
||||
throw new ExecutionException("Failed to execute command: " + e.getMessage(), e);
|
||||
}
|
||||
} catch(InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException | InjectionException e) {
|
||||
throw new MalformedCommandException("Unable to reflectively instantiate command: ", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(String name, Class<? extends CommandTemplate> clazz) throws MalformedCommandException {
|
||||
commands.put(name, new CommandHolder(clazz));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> tabComplete(String command, CommandSender sender, List<String> args) throws CommandException {
|
||||
if(args.isEmpty()) return new ArrayList<>(commands.keySet()).stream().sorted(String::compareTo).collect(Collectors.toList());
|
||||
if(!commands.containsKey(command)) return Collections.emptyList();
|
||||
return tabComplete(commands.get(command), sender, new ArrayList<>(args)).stream().filter(s -> s.toLowerCase().startsWith(args.get(args.size() - 1).toLowerCase())).sorted(String::compareTo).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxArgumentDepth() {
|
||||
int max = 0;
|
||||
for(CommandHolder value : commands.values()) {
|
||||
max = FastMath.max(getMaxArgumentDepth(value), max);
|
||||
}
|
||||
return max;
|
||||
}
|
||||
|
||||
private int getMaxArgumentDepth(CommandHolder holder) {
|
||||
int max = 0;
|
||||
max = FastMath.max(holder.arguments.size() + holder.switchList.size(), max);
|
||||
for(CommandHolder value : holder.subcommands.values()) {
|
||||
max = FastMath.max(max, getMaxArgumentDepth(value) + 1);
|
||||
}
|
||||
return max;
|
||||
}
|
||||
|
||||
private List<String> tabComplete(CommandHolder holder, CommandSender sender, List<String> args) throws CommandException {
|
||||
if(args.isEmpty()) return Collections.emptyList();
|
||||
List<String> completions = new ArrayList<>();
|
||||
|
||||
if(args.size() == 1) {
|
||||
completions.addAll(holder.subcommands.keySet());
|
||||
}
|
||||
|
||||
if(holder.subcommands.containsKey(args.get(0))) {
|
||||
List<String> newArgs = new ArrayList<>(args);
|
||||
newArgs.remove(0);
|
||||
completions.addAll(tabComplete(holder.subcommands.get(args.get(0)), sender, newArgs));
|
||||
}
|
||||
try {
|
||||
if(args.size() <= holder.arguments.size()) {
|
||||
TabCompleter completer = holder.arguments.get(args.size() - 1).tabCompleter().getConstructor().newInstance();
|
||||
pluginInjector.inject(completer);
|
||||
completions.addAll(completer.complete(sender));
|
||||
}
|
||||
} catch(InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException | InjectionException e) {
|
||||
throw new MalformedCommandException("Unable to reflectively instantiate tab-completer: ", e);
|
||||
}
|
||||
return completions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pre-processes command metadata.
|
||||
*/
|
||||
private static final class CommandHolder {
|
||||
private final Class<? extends CommandTemplate> clazz;
|
||||
private final Map<String, CommandHolder> subcommands = new HashMap<>();
|
||||
private final Map<String, String> switches = new HashMap<>();
|
||||
private final List<Argument> arguments;
|
||||
private final List<Switch> switchList;
|
||||
private final Map<String, Argument> argumentMap = new HashMap<>();
|
||||
|
||||
private CommandHolder(Class<? extends CommandTemplate> clazz) throws MalformedCommandException {
|
||||
this.clazz = clazz;
|
||||
if(clazz.isAnnotationPresent(Command.class)) {
|
||||
Command command = clazz.getAnnotation(Command.class);
|
||||
for(Subcommand subcommand : command.subcommands()) {
|
||||
if(subcommands.containsKey(subcommand.value()))
|
||||
throw new MalformedCommandException("Duplicate subcommand: " + subcommand);
|
||||
CommandHolder holder = new CommandHolder(subcommand.clazz());
|
||||
subcommands.put(subcommand.value(), holder);
|
||||
for(String alias : subcommand.aliases()) {
|
||||
subcommands.put(alias, holder);
|
||||
}
|
||||
}
|
||||
for(Switch aSwitch : command.switches()) {
|
||||
if(switches.containsKey(aSwitch.value())) throw new MalformedCommandException("Duplicate switch: " + aSwitch);
|
||||
switches.put(aSwitch.value(), aSwitch.value());
|
||||
for(String alias : aSwitch.aliases()) {
|
||||
switches.put(alias, aSwitch.value());
|
||||
}
|
||||
}
|
||||
for(Argument argument : command.arguments()) {
|
||||
if(argumentMap.containsKey(argument.value())) throw new MalformedCommandException("Duplicate argument: " + argument);
|
||||
argumentMap.put(argument.value(), argument);
|
||||
}
|
||||
arguments = Arrays.asList(command.arguments());
|
||||
switchList = Arrays.asList(command.switches());
|
||||
} else {
|
||||
arguments = Collections.emptyList();
|
||||
switchList = Collections.emptyList();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.dfsek.terra.api.command.annotation;
|
||||
|
||||
import com.dfsek.terra.api.command.arg.ArgumentParser;
|
||||
import com.dfsek.terra.api.command.arg.StringArgumentParser;
|
||||
import com.dfsek.terra.api.command.tab.NothingCompleter;
|
||||
import com.dfsek.terra.api.command.tab.TabCompleter;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(ElementType.ANNOTATION_TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Argument {
|
||||
String value();
|
||||
|
||||
boolean required() default true;
|
||||
|
||||
Class<? extends TabCompleter> tabCompleter() default NothingCompleter.class;
|
||||
|
||||
Class<? extends ArgumentParser<?>> argumentParser() default StringArgumentParser.class;
|
||||
|
||||
String defaultValue() default "";
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.dfsek.terra.api.command.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Command {
|
||||
Argument[] arguments() default {};
|
||||
|
||||
Switch[] switches() default {};
|
||||
|
||||
Subcommand[] subcommands() default {};
|
||||
|
||||
String usage() default "";
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.dfsek.terra.api.command.annotation;
|
||||
|
||||
import com.dfsek.terra.api.command.CommandTemplate;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.ANNOTATION_TYPE)
|
||||
public @interface Subcommand {
|
||||
String value();
|
||||
|
||||
String[] aliases() default {};
|
||||
|
||||
Class<? extends CommandTemplate> clazz();
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.dfsek.terra.api.command.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.ANNOTATION_TYPE)
|
||||
public @interface Switch {
|
||||
String value();
|
||||
|
||||
String[] aliases() default {};
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.dfsek.terra.api.command.annotation.inject;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
public @interface ArgumentTarget {
|
||||
String value();
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.dfsek.terra.api.command.annotation.inject;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
public @interface SwitchTarget {
|
||||
String value();
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.dfsek.terra.api.command.annotation.type;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Command may only be executed with debug mode enabled.
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface DebugCommand {
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.dfsek.terra.api.command.annotation.type;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Marks command as player-only
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface PlayerCommand {
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.dfsek.terra.api.command.annotation.type;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Command may only be executed in a Terra world.
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface WorldCommand {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.dfsek.terra.api.command.arg;
|
||||
|
||||
import com.dfsek.terra.api.platform.CommandSender;
|
||||
|
||||
public interface ArgumentParser<T> {
|
||||
T parse(CommandSender sender, String arg);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.dfsek.terra.api.command.arg;
|
||||
|
||||
import com.dfsek.terra.api.platform.CommandSender;
|
||||
|
||||
public class DoubleArgumentParser implements ArgumentParser<Double> {
|
||||
@Override
|
||||
public Double parse(CommandSender sender, String arg) {
|
||||
return arg == null ? null : Double.parseDouble(arg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.dfsek.terra.api.command.arg;
|
||||
|
||||
import com.dfsek.terra.api.platform.CommandSender;
|
||||
|
||||
public class IntegerArgumentParser implements ArgumentParser<Integer> {
|
||||
@Override
|
||||
public Integer parse(CommandSender sender, String arg) {
|
||||
return arg == null ? null : Integer.parseInt(arg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.dfsek.terra.api.command.arg;
|
||||
|
||||
import com.dfsek.terra.api.platform.CommandSender;
|
||||
|
||||
public class StringArgumentParser implements ArgumentParser<String> {
|
||||
@Override
|
||||
public String parse(CommandSender sender, String arg) {
|
||||
return arg;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.dfsek.terra.api.command.exception;
|
||||
|
||||
public abstract class CommandException extends Exception {
|
||||
private static final long serialVersionUID = -2955328495045879822L;
|
||||
|
||||
public CommandException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public CommandException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.dfsek.terra.api.command.exception;
|
||||
|
||||
public class ExecutionException extends CommandException {
|
||||
private static final long serialVersionUID = -6345523475880607959L;
|
||||
|
||||
public ExecutionException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public ExecutionException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.dfsek.terra.api.command.exception;
|
||||
|
||||
public class InvalidArgumentsException extends CommandException {
|
||||
private static final long serialVersionUID = 7563619667472569824L;
|
||||
|
||||
public InvalidArgumentsException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public InvalidArgumentsException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.dfsek.terra.api.command.exception;
|
||||
|
||||
/**
|
||||
* Thrown when command is incorrectly defined.
|
||||
*/
|
||||
public class MalformedCommandException extends CommandException {
|
||||
private static final long serialVersionUID = -5417760860407895496L;
|
||||
|
||||
public MalformedCommandException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public MalformedCommandException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.dfsek.terra.api.command.exception;
|
||||
|
||||
public class SwitchFormatException extends CommandException {
|
||||
private static final long serialVersionUID = -965858989317844628L;
|
||||
|
||||
public SwitchFormatException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public SwitchFormatException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.dfsek.terra.api.command.tab;
|
||||
|
||||
import com.dfsek.terra.api.platform.CommandSender;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class NothingCompleter implements TabCompleter {
|
||||
@Override
|
||||
public List<String> complete(CommandSender sender) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.dfsek.terra.api.command.tab;
|
||||
|
||||
import com.dfsek.terra.api.platform.CommandSender;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface TabCompleter {
|
||||
List<String> complete(CommandSender sender);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.dfsek.terra.api.event;
|
||||
|
||||
import com.dfsek.terra.api.event.events.Event;
|
||||
|
||||
/**
|
||||
* Marker interface for a class that contains event listener methods.
|
||||
*
|
||||
* @see Event
|
||||
* @see EventManager
|
||||
*/
|
||||
public interface EventListener {
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.dfsek.terra.api.event;
|
||||
|
||||
import com.dfsek.terra.api.addons.TerraAddon;
|
||||
import com.dfsek.terra.api.event.events.Event;
|
||||
|
||||
/**
|
||||
* Manages event registration and triggering.
|
||||
*/
|
||||
public interface EventManager {
|
||||
/**
|
||||
* Call an event, and return the execution status.
|
||||
*
|
||||
* @param event Event to pass to all registered EventListeners.
|
||||
* @return False if the event is cancellable and has been cancelled, otherwise true.
|
||||
*/
|
||||
boolean callEvent(Event event);
|
||||
|
||||
/**
|
||||
* Register an {@link EventListener} under an {@link TerraAddon}.
|
||||
*
|
||||
* @param addon Addon to register listener for.
|
||||
* @param listener Listener to register.
|
||||
*/
|
||||
void registerListener(TerraAddon addon, EventListener listener);
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
package com.dfsek.terra.api.event;
|
||||
|
||||
import com.dfsek.terra.api.TerraPlugin;
|
||||
import com.dfsek.terra.api.addons.TerraAddon;
|
||||
import com.dfsek.terra.api.event.annotations.Global;
|
||||
import com.dfsek.terra.api.event.annotations.Priority;
|
||||
import com.dfsek.terra.api.event.events.Cancellable;
|
||||
import com.dfsek.terra.api.event.events.Event;
|
||||
import com.dfsek.terra.api.event.events.PackEvent;
|
||||
import com.dfsek.terra.api.util.ReflectionUtil;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class TerraEventManager implements EventManager {
|
||||
private final Map<Class<? extends Event>, List<ListenerHolder>> listeners = new HashMap<>();
|
||||
private final TerraPlugin main;
|
||||
|
||||
public TerraEventManager(TerraPlugin main) {
|
||||
this.main = main;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean callEvent(Event event) {
|
||||
listeners.getOrDefault(event.getClass(), Collections.emptyList()).forEach(listenerHolder -> {
|
||||
try {
|
||||
if(event instanceof PackEvent && !listenerHolder.global) {
|
||||
PackEvent packEvent = (PackEvent) event;
|
||||
if(packEvent
|
||||
.getPack()
|
||||
.getTemplate()
|
||||
.getAddons()
|
||||
.contains(listenerHolder.addon)) {
|
||||
listenerHolder.method.invoke(listenerHolder.listener, event);
|
||||
}
|
||||
} else {
|
||||
listenerHolder.method.invoke(listenerHolder.listener, event);
|
||||
}
|
||||
} catch(InvocationTargetException e) {
|
||||
StringWriter writer = new StringWriter();
|
||||
e.getTargetException().printStackTrace(new PrintWriter(writer));
|
||||
main.logger().warning("Exception occurred during event handling:");
|
||||
main.logger().warning(writer.toString());
|
||||
main.logger().warning("Report this to the maintainers of " + listenerHolder.method.getName());
|
||||
} catch(Exception e) {
|
||||
StringWriter writer = new StringWriter();
|
||||
e.printStackTrace(new PrintWriter(writer));
|
||||
main.logger().warning("Exception occurred during event handling:");
|
||||
main.logger().warning(writer.toString());
|
||||
main.logger().warning("Report this to the maintainers of " + listenerHolder.method.getName());
|
||||
}
|
||||
}
|
||||
);
|
||||
if(event instanceof Cancellable) return !((Cancellable) event).isCancelled();
|
||||
return true;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void registerListener(TerraAddon addon, EventListener listener) {
|
||||
Class<? extends EventListener> listenerClass = listener.getClass();
|
||||
Method[] methods = ReflectionUtil.getMethods(listenerClass);
|
||||
|
||||
for(Method method : methods) {
|
||||
if(method.getParameterCount() != 1) continue; // Check that parameter count is only 1.
|
||||
Class<?> eventParam = method.getParameterTypes()[0];
|
||||
if(!Event.class.isAssignableFrom(eventParam)) continue; // Check that parameter is an Event.
|
||||
|
||||
Priority p = method.getAnnotation(Priority.class);
|
||||
|
||||
int priority = p == null ? 0 : p.value();
|
||||
|
||||
method.setAccessible(true);
|
||||
|
||||
List<ListenerHolder> holders = listeners.computeIfAbsent((Class<? extends Event>) eventParam, e -> new ArrayList<>());
|
||||
|
||||
holders.add(new ListenerHolder(method, listener, priority, addon, method.getAnnotation(Global.class) != null));
|
||||
|
||||
holders.sort(Comparator.comparingInt(ListenerHolder::getPriority)); // Sort priorities.
|
||||
}
|
||||
}
|
||||
|
||||
private static final class ListenerHolder {
|
||||
private final Method method;
|
||||
private final EventListener listener;
|
||||
private final int priority;
|
||||
private final TerraAddon addon;
|
||||
private final boolean global;
|
||||
|
||||
private ListenerHolder(Method method, EventListener listener, int priority, TerraAddon addon, boolean global) {
|
||||
this.method = method;
|
||||
this.listener = listener;
|
||||
this.priority = priority;
|
||||
this.addon = addon;
|
||||
this.global = global;
|
||||
}
|
||||
|
||||
public int getPriority() {
|
||||
return priority;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.dfsek.terra.api.event.annotations;
|
||||
|
||||
import com.dfsek.terra.api.event.events.PackEvent;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Specifies that an event handler is to handle all {@link PackEvent}s, regardless of whether the pack
|
||||
* depends on the addon's listener.
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
public @interface Global {
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.dfsek.terra.api.event.annotations;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Annotated listener methods will have a specific priority set.
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
public @interface Priority {
|
||||
/**
|
||||
* Highest possible priority. Listeners with this priority will always be invoked last.
|
||||
*/
|
||||
int HIGHEST = Integer.MAX_VALUE;
|
||||
/**
|
||||
* Lowest possible priority. Listeners with this priority will always be invoked first.
|
||||
*/
|
||||
int LOWEST = Integer.MIN_VALUE;
|
||||
/**
|
||||
* Default priority.
|
||||
*/
|
||||
int NORMAL = 0;
|
||||
/**
|
||||
* High priority.
|
||||
*/
|
||||
int HIGH = 1;
|
||||
/**
|
||||
* Low Priority.
|
||||
*/
|
||||
int LOW = -1;
|
||||
/**
|
||||
* @return Priority of this event. Events are executed from lowest to highest priorities.
|
||||
*/
|
||||
int value();
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.dfsek.terra.api.event.events;
|
||||
|
||||
import com.dfsek.terra.api.util.mutable.MutableBoolean;
|
||||
|
||||
/**
|
||||
* Abstract class containing basic {@link Cancellable} implementation.
|
||||
*/
|
||||
public abstract class AbstractCancellable implements Cancellable {
|
||||
private final MutableBoolean cancelled = new MutableBoolean(false);
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return cancelled.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCancelled(boolean cancelled) {
|
||||
this.cancelled.set(cancelled);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.dfsek.terra.api.event.events;
|
||||
|
||||
/**
|
||||
* Events that implement this interface may be cancelled.
|
||||
* <p>
|
||||
* Cancelling an event is assumed to stop the execution of whatever action triggered the event.
|
||||
*/
|
||||
public interface Cancellable extends Event {
|
||||
/**
|
||||
* Get the cancellation status of the event.
|
||||
*
|
||||
* @return Whether event is cancelled.
|
||||
*/
|
||||
boolean isCancelled();
|
||||
|
||||
/**
|
||||
* Set the cancellation status of the event.
|
||||
*
|
||||
* @param cancelled Whether event is cancelled.
|
||||
*/
|
||||
void setCancelled(boolean cancelled);
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.dfsek.terra.api.event.events;
|
||||
|
||||
/**
|
||||
* An event that addons may listen to.
|
||||
*/
|
||||
public interface Event {
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.dfsek.terra.api.event.events;
|
||||
|
||||
import com.dfsek.terra.api.event.annotations.Global;
|
||||
import com.dfsek.terra.config.pack.ConfigPack;
|
||||
|
||||
/**
|
||||
* An event with functionality directly linked to a {@link ConfigPack}.
|
||||
* <p>
|
||||
* PackEvents are only invoked when the pack specifies the addon in its
|
||||
* {@code addon} key (or when the listener is annotated {@link Global}).
|
||||
*/
|
||||
@SuppressWarnings("InterfaceMayBeAnnotatedFunctional")
|
||||
public interface PackEvent extends Event {
|
||||
/**
|
||||
* Get the {@link ConfigPack} associated with this event.
|
||||
*
|
||||
* @return ConfigPack associated with the event.
|
||||
*/
|
||||
ConfigPack getPack();
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.dfsek.terra.api.event.events.config;
|
||||
|
||||
import com.dfsek.terra.api.event.events.PackEvent;
|
||||
import com.dfsek.terra.config.pack.ConfigPack;
|
||||
|
||||
/**
|
||||
* An event related to the loading process of config packs.
|
||||
*/
|
||||
public abstract class ConfigPackLoadEvent implements PackEvent {
|
||||
private final ConfigPack pack;
|
||||
|
||||
public ConfigPackLoadEvent(ConfigPack pack) {
|
||||
this.pack = pack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigPack getPack() {
|
||||
return pack;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.dfsek.terra.api.event.events.config;
|
||||
|
||||
import com.dfsek.terra.config.pack.ConfigPack;
|
||||
|
||||
/**
|
||||
* Called when a config pack has finished loading.
|
||||
*/
|
||||
public class ConfigPackPostLoadEvent extends ConfigPackLoadEvent {
|
||||
public ConfigPackPostLoadEvent(ConfigPack pack) {
|
||||
super(pack);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.dfsek.terra.api.event.events.config;
|
||||
|
||||
import com.dfsek.terra.config.pack.ConfigPack;
|
||||
|
||||
/**
|
||||
* Called before a config pack's registries are filled. At this point, the pack manifest has been loaded, and all registries are empty.
|
||||
*/
|
||||
public class ConfigPackPreLoadEvent extends ConfigPackLoadEvent {
|
||||
public ConfigPackPreLoadEvent(ConfigPack pack) {
|
||||
super(pack);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.dfsek.terra.api.event.events.world;
|
||||
|
||||
import com.dfsek.terra.api.event.events.PackEvent;
|
||||
import com.dfsek.terra.config.pack.ConfigPack;
|
||||
import com.dfsek.terra.config.pack.WorldConfig;
|
||||
import com.dfsek.terra.world.TerraWorld;
|
||||
|
||||
/**
|
||||
* Called upon initialization of a TerraWorld.
|
||||
*/
|
||||
public class TerraWorldLoadEvent implements PackEvent {
|
||||
private final TerraWorld world;
|
||||
private final ConfigPack pack;
|
||||
|
||||
public TerraWorldLoadEvent(TerraWorld world, ConfigPack pack) {
|
||||
this.world = world;
|
||||
this.pack = pack;
|
||||
}
|
||||
|
||||
public TerraWorld getWorld() {
|
||||
return world;
|
||||
}
|
||||
|
||||
public ConfigPack getPack() {
|
||||
return pack;
|
||||
}
|
||||
|
||||
public WorldConfig getWorldConfig() {
|
||||
return world.getConfig();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.dfsek.terra.api.event.events.world.generation;
|
||||
|
||||
import com.dfsek.terra.api.event.events.PackEvent;
|
||||
import com.dfsek.terra.api.math.vector.Location;
|
||||
import com.dfsek.terra.api.platform.entity.Entity;
|
||||
import com.dfsek.terra.api.structures.structure.buffer.items.BufferedEntity;
|
||||
import com.dfsek.terra.config.pack.ConfigPack;
|
||||
|
||||
/**
|
||||
* Called when an entity is spawned via {@link BufferedEntity}.
|
||||
*/
|
||||
public class EntitySpawnEvent implements PackEvent {
|
||||
private final ConfigPack pack;
|
||||
private final Entity entity;
|
||||
private final Location location;
|
||||
|
||||
public EntitySpawnEvent(ConfigPack pack, Entity entity, Location location) {
|
||||
this.pack = pack;
|
||||
this.entity = entity;
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigPack getPack() {
|
||||
return pack;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the entity that triggered the event.
|
||||
*
|
||||
* @return The entity.
|
||||
*/
|
||||
public Entity getEntity() {
|
||||
return entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the location of the entity.
|
||||
*
|
||||
* @return Location of the entity.
|
||||
*/
|
||||
public Location getLocation() {
|
||||
return location;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package com.dfsek.terra.api.event.events.world.generation;
|
||||
|
||||
import com.dfsek.terra.api.event.events.AbstractCancellable;
|
||||
import com.dfsek.terra.api.event.events.Cancellable;
|
||||
import com.dfsek.terra.api.event.events.PackEvent;
|
||||
import com.dfsek.terra.api.platform.block.Block;
|
||||
import com.dfsek.terra.api.platform.block.state.Container;
|
||||
import com.dfsek.terra.api.structures.loot.LootTable;
|
||||
import com.dfsek.terra.api.structures.script.StructureScript;
|
||||
import com.dfsek.terra.api.structures.structure.buffer.items.BufferedLootApplication;
|
||||
import com.dfsek.terra.config.pack.ConfigPack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Called when loot is populated via {@link BufferedLootApplication}.
|
||||
*/
|
||||
public class LootPopulateEvent extends AbstractCancellable implements PackEvent, Cancellable {
|
||||
private final Block block;
|
||||
private final Container container;
|
||||
private LootTable table;
|
||||
private final ConfigPack pack;
|
||||
private final StructureScript script;
|
||||
|
||||
public LootPopulateEvent(Block block, Container container, LootTable table, ConfigPack pack, StructureScript script) {
|
||||
this.block = block;
|
||||
this.container = container;
|
||||
this.table = table;
|
||||
this.pack = pack;
|
||||
this.script = script;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigPack getPack() {
|
||||
return pack;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the block containing the tile entity loot is applied to.
|
||||
*
|
||||
* @return Block at which loot is applied.
|
||||
*/
|
||||
public Block getBlock() {
|
||||
return block;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link Container} representing the inventory.
|
||||
*
|
||||
* @return Inventory recieving loot.
|
||||
*/
|
||||
public Container getContainer() {
|
||||
return container;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the loot table to be populated.
|
||||
* @return Loot table.
|
||||
*/
|
||||
public LootTable getTable() {
|
||||
return table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the loot table to be populated.
|
||||
*
|
||||
* @param table New loot table.
|
||||
*/
|
||||
public void setTable(@NotNull LootTable table) {
|
||||
this.table = table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the script used to generate the structure.
|
||||
*
|
||||
* @return Structure script.
|
||||
*/
|
||||
public StructureScript getStructureScript() {
|
||||
return script;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package com.dfsek.terra.api.injection;
|
||||
|
||||
import com.dfsek.terra.api.injection.annotations.Inject;
|
||||
import com.dfsek.terra.api.injection.exception.InjectionException;
|
||||
import com.dfsek.terra.api.util.ReflectionUtil;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Dynamic dependency injector.
|
||||
* <p>
|
||||
* Stores an object to inject, and injects it into objects passed to {@link #inject(Object)}.
|
||||
*
|
||||
* @param <T> Type of object to inject.
|
||||
*/
|
||||
public class Injector<T> {
|
||||
private final T value;
|
||||
private final Set<Class<? extends T>> targets = new HashSet<>();
|
||||
|
||||
/**
|
||||
* Instantiate an Injector with a value to inject
|
||||
*
|
||||
* @param value Value to inject
|
||||
*/
|
||||
public Injector(T value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an explicit class as a target. Useful for applications where subclasses may cause issues with DI.
|
||||
*
|
||||
* @param target Target class type.
|
||||
*/
|
||||
public void addExplicitTarget(Class<? extends T> target) {
|
||||
targets.add(target);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inject the stored object into an object.
|
||||
* <p>
|
||||
* Injects the stored object into any non-static, non-final fields
|
||||
* annotated with {@link Inject},
|
||||
* with type matching the stored object or any explicit targets
|
||||
* ({@link #addExplicitTarget(Class)}.
|
||||
*
|
||||
* @param object Object to inject into
|
||||
* @throws InjectionException If:
|
||||
* <ul>
|
||||
* <li>Matching field annotated with {@link Inject} is final</li>
|
||||
* <li>Matching field annotated with {@link Inject} is static</li>
|
||||
* <li>A reflective access exception occurs</li>
|
||||
* </ul>
|
||||
*/
|
||||
public void inject(Object object) throws InjectionException {
|
||||
for(Field field : ReflectionUtil.getFields(object.getClass())) {
|
||||
Inject inject = field.getAnnotation(Inject.class);
|
||||
if(inject == null) continue;
|
||||
if(value.getClass().equals(field.getType()) || targets.contains(field.getType())) {
|
||||
int mod = field.getModifiers();
|
||||
if(Modifier.isFinal(mod)) {
|
||||
throw new InjectionException("Attempted to inject final field: " + field);
|
||||
}
|
||||
if(Modifier.isStatic(mod)) {
|
||||
throw new InjectionException("Attempted to inject static field: " + field);
|
||||
}
|
||||
field.setAccessible(true);
|
||||
try {
|
||||
field.set(object, value);
|
||||
} catch(IllegalAccessException e) {
|
||||
throw new InjectionException("Failed to inject field: " + field, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.dfsek.terra.api.injection.annotations;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Specifies that a field is a target for dependency injection.
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
public @interface Inject {
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.dfsek.terra.api.injection.exception;
|
||||
|
||||
import com.dfsek.terra.api.injection.Injector;
|
||||
|
||||
/**
|
||||
* Thrown when dynamic dependency injection cannot be completed by an {@link Injector}.
|
||||
*/
|
||||
public class InjectionException extends Exception {
|
||||
private static final long serialVersionUID = -6929631447064215387L;
|
||||
|
||||
public InjectionException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public InjectionException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,8 @@
|
||||
package com.dfsek.terra.procgen;
|
||||
package com.dfsek.terra.api.math;
|
||||
|
||||
import org.bukkit.util.Vector;
|
||||
import org.polydev.gaea.math.MathUtil;
|
||||
import org.polydev.gaea.util.FastRandom;
|
||||
import org.polydev.gaea.util.GlueList;
|
||||
import com.dfsek.terra.api.math.vector.Vector3;
|
||||
import com.dfsek.terra.api.util.FastRandom;
|
||||
import com.dfsek.terra.api.util.GlueList;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
@@ -14,10 +13,12 @@ import java.util.Random;
|
||||
public class GridSpawn {
|
||||
private final int separation;
|
||||
private final int width;
|
||||
private final int salt;
|
||||
|
||||
public GridSpawn(int width, int separation) {
|
||||
public GridSpawn(int width, int separation, int salt) {
|
||||
this.separation = separation;
|
||||
this.width = width;
|
||||
this.salt = salt;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -28,18 +29,18 @@ public class GridSpawn {
|
||||
* @param seed Seed for RNG
|
||||
* @return Vector representing nearest spawnpoint
|
||||
*/
|
||||
public Vector getNearestSpawn(int x, int z, long seed) {
|
||||
public Vector3 getNearestSpawn(int x, int z, long seed) {
|
||||
int structureChunkX = x / (width + 2 * separation);
|
||||
int structureChunkZ = z / (width + 2 * separation);
|
||||
List<Vector> zones = new GlueList<>();
|
||||
List<Vector3> zones = new GlueList<>();
|
||||
for(int xi = structureChunkX - 1; xi <= structureChunkX + 1; xi++) {
|
||||
for(int zi = structureChunkZ - 1; zi <= structureChunkZ + 1; zi++) {
|
||||
zones.add(getChunkSpawn(xi, zi, seed));
|
||||
}
|
||||
}
|
||||
Vector shortest = zones.get(0);
|
||||
Vector compare = new Vector(x, 0, z);
|
||||
for(Vector v : zones) {
|
||||
Vector3 shortest = zones.get(0);
|
||||
Vector3 compare = new Vector3(x, 0, z);
|
||||
for(Vector3 v : zones) {
|
||||
if(compare.distanceSquared(shortest) > compare.distanceSquared(v)) shortest = v.clone();
|
||||
}
|
||||
return shortest;
|
||||
@@ -53,13 +54,13 @@ public class GridSpawn {
|
||||
* @param seed Seed for RNG
|
||||
* @return Vector representing spawnpoint
|
||||
*/
|
||||
public Vector getChunkSpawn(int structureChunkX, int structureChunkZ, long seed) {
|
||||
Random r = new FastRandom(MathUtil.getCarverChunkSeed(structureChunkX, structureChunkZ, seed));
|
||||
public Vector3 getChunkSpawn(int structureChunkX, int structureChunkZ, long seed) {
|
||||
Random r = new FastRandom(MathUtil.getCarverChunkSeed(structureChunkX, structureChunkZ, seed + salt));
|
||||
int offsetX = r.nextInt(width);
|
||||
int offsetZ = r.nextInt(width);
|
||||
int sx = structureChunkX * (width + 2 * separation) + offsetX;
|
||||
int sz = structureChunkZ * (width + 2 * separation) + offsetZ;
|
||||
return new Vector(sx, 0, sz);
|
||||
return new Vector3(sx, 0, sz);
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
193
common/src/main/java/com/dfsek/terra/api/math/MathUtil.java
Normal file
193
common/src/main/java/com/dfsek/terra/api/math/MathUtil.java
Normal file
@@ -0,0 +1,193 @@
|
||||
package com.dfsek.terra.api.math;
|
||||
|
||||
import com.dfsek.terra.api.util.FastRandom;
|
||||
import com.dfsek.terra.world.generation.math.samplers.Sampler;
|
||||
import net.jafama.FastMath;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Utility class for mathematical functions.
|
||||
*/
|
||||
public final class MathUtil {
|
||||
/**
|
||||
* Epsilon for fuzzy floating point comparisons.
|
||||
*/
|
||||
public static final double EPSILON = 1.0E-5;
|
||||
/**
|
||||
* Derivative constant.
|
||||
*/
|
||||
private static final double DERIVATIVE_DIST = 0.55;
|
||||
|
||||
/**
|
||||
* Gets the standard deviation of an array of doubles.
|
||||
*
|
||||
* @param numArray The array of numbers to calculate the standard deviation of.
|
||||
* @return double - The standard deviation.
|
||||
*/
|
||||
public static double standardDeviation(List<Number> numArray) {
|
||||
double sum = 0.0, standardDeviation = 0.0;
|
||||
int length = numArray.size();
|
||||
|
||||
for(Number num : numArray) {
|
||||
sum += num.doubleValue();
|
||||
}
|
||||
|
||||
double mean = sum / length;
|
||||
|
||||
for(Number num : numArray) {
|
||||
standardDeviation += FastMath.pow2(num.doubleValue() - mean);
|
||||
}
|
||||
|
||||
return FastMath.sqrt(standardDeviation / length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the carver seed for a chunk.
|
||||
*
|
||||
* @param chunkX Chunk's X coordinate
|
||||
* @param chunkZ Chunk's Z coordinate
|
||||
* @param seed World seed
|
||||
* @return long - The carver seed.
|
||||
*/
|
||||
public static long getCarverChunkSeed(int chunkX, int chunkZ, long seed) {
|
||||
Random r = new FastRandom(seed);
|
||||
return chunkX * r.nextLong() ^ chunkZ * r.nextLong() ^ seed;
|
||||
}
|
||||
|
||||
public static long hashToLong(String s) {
|
||||
if(s == null) {
|
||||
return 0;
|
||||
}
|
||||
long hash = 0;
|
||||
for(char c : s.toCharArray()) {
|
||||
hash = 31L * hash + c;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare 2 floating-point values with epsilon to account for rounding errors
|
||||
*
|
||||
* @param a Value 1
|
||||
* @param b Value 2
|
||||
* @return Whether these values are equal
|
||||
*/
|
||||
public static boolean equals(double a, double b) {
|
||||
return a == b || FastMath.abs(a - b) < EPSILON;
|
||||
}
|
||||
|
||||
public static double derivative(Sampler sampler, double x, double y, double z) {
|
||||
double baseSample = sampler.sample(x, y, z);
|
||||
|
||||
double xVal1 = (sampler.sample(x + DERIVATIVE_DIST, y, z) - baseSample) / DERIVATIVE_DIST;
|
||||
double xVal2 = (sampler.sample(x - DERIVATIVE_DIST, y, z) - baseSample) / DERIVATIVE_DIST;
|
||||
double zVal1 = (sampler.sample(x, y, z + DERIVATIVE_DIST) - baseSample) / DERIVATIVE_DIST;
|
||||
double zVal2 = (sampler.sample(x, y, z - DERIVATIVE_DIST) - baseSample) / DERIVATIVE_DIST;
|
||||
double yVal1 = (sampler.sample(x, y + DERIVATIVE_DIST, z) - baseSample) / DERIVATIVE_DIST;
|
||||
double yVal2 = (sampler.sample(x, y - DERIVATIVE_DIST, z) - baseSample) / DERIVATIVE_DIST;
|
||||
|
||||
return Math.sqrt(((xVal2 - xVal1) * (xVal2 - xVal1)) + ((zVal2 - zVal1) * (zVal2 - zVal1)) + ((yVal2 - yVal1) * (yVal2 - yVal1)));
|
||||
}
|
||||
|
||||
public static int normalizeIndex(double val, int size) {
|
||||
return FastMath.max(FastMath.min(FastMath.floorToInt(((val + 1D) / 2D) * size), size - 1), 0);
|
||||
}
|
||||
|
||||
public static long squash(int first, int last) {
|
||||
return (((long) first) << 32) | (last & 0xffffffffL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clamp value to range of [-1, 1]
|
||||
*
|
||||
* @param in Value to clamp
|
||||
* @return Clamped value
|
||||
*/
|
||||
public static double clamp(double in) {
|
||||
return FastMath.min(FastMath.max(in, -1), 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the value in a normally distributed data set that has probability p.
|
||||
*
|
||||
* @param p Probability of value
|
||||
* @param mu Mean of data
|
||||
* @param sigma Standard deviation of data
|
||||
* @return Value corresponding to input probability
|
||||
*/
|
||||
public static double normalInverse(double p, double mu, double sigma) {
|
||||
if(p < 0 || p > 1)
|
||||
throw new IllegalArgumentException("Probability must be in range [0, 1]");
|
||||
if(sigma < 0)
|
||||
throw new IllegalArgumentException("Standard deviation must be positive.");
|
||||
if(p == 0)
|
||||
return Double.NEGATIVE_INFINITY;
|
||||
if(p == 1)
|
||||
return Double.POSITIVE_INFINITY;
|
||||
if(sigma == 0)
|
||||
return mu;
|
||||
double q, r, val;
|
||||
|
||||
q = p - 0.5;
|
||||
|
||||
if(FastMath.abs(q) <= .425) {
|
||||
r = .180625 - q * q;
|
||||
val =
|
||||
q * (((((((r * 2509.0809287301226727 +
|
||||
33430.575583588128105) * r + 67265.770927008700853) * r +
|
||||
45921.953931549871457) * r + 13731.693765509461125) * r +
|
||||
1971.5909503065514427) * r + 133.14166789178437745) * r +
|
||||
3.387132872796366608)
|
||||
/ (((((((r * 5226.495278852854561 +
|
||||
28729.085735721942674) * r + 39307.89580009271061) * r +
|
||||
21213.794301586595867) * r + 5394.1960214247511077) * r +
|
||||
687.1870074920579083) * r + 42.313330701600911252) * r + 1);
|
||||
} else {
|
||||
if(q > 0) {
|
||||
r = 1 - p;
|
||||
} else {
|
||||
r = p;
|
||||
}
|
||||
|
||||
r = FastMath.sqrt(-FastMath.log(r));
|
||||
|
||||
if(r <= 5) {
|
||||
r += -1.6;
|
||||
val = (((((((r * 7.7454501427834140764e-4 +
|
||||
.0227238449892691845833) * r + .24178072517745061177) *
|
||||
r + 1.27045825245236838258) * r +
|
||||
3.64784832476320460504) * r + 5.7694972214606914055) *
|
||||
r + 4.6303378461565452959) * r +
|
||||
1.42343711074968357734)
|
||||
/ (((((((r *
|
||||
1.05075007164441684324e-9 + 5.475938084995344946e-4) *
|
||||
r + .0151986665636164571966) * r +
|
||||
.14810397642748007459) * r + .68976733498510000455) *
|
||||
r + 1.6763848301838038494) * r +
|
||||
2.05319162663775882187) * r + 1);
|
||||
} else {
|
||||
r += -5;
|
||||
val = (((((((r * 2.01033439929228813265e-7 +
|
||||
2.71155556874348757815e-5) * r +
|
||||
.0012426609473880784386) * r + .026532189526576123093) *
|
||||
r + .29656057182850489123) * r +
|
||||
1.7848265399172913358) * r + 5.4637849111641143699) *
|
||||
r + 6.6579046435011037772)
|
||||
/ (((((((r *
|
||||
2.04426310338993978564e-15 + 1.4215117583164458887e-7) *
|
||||
r + 1.8463183175100546818e-5) * r +
|
||||
7.868691311456132591e-4) * r + .0148753612908506148525)
|
||||
* r + .13692988092273580531) * r +
|
||||
.59983220655588793769) * r + 1);
|
||||
}
|
||||
|
||||
if(q < 0.0) {
|
||||
val = -val;
|
||||
}
|
||||
}
|
||||
|
||||
return mu + sigma * val;
|
||||
}
|
||||
}
|
||||
123
common/src/main/java/com/dfsek/terra/api/math/Range.java
Normal file
123
common/src/main/java/com/dfsek/terra/api/math/Range.java
Normal file
@@ -0,0 +1,123 @@
|
||||
package com.dfsek.terra.api.math;
|
||||
|
||||
import net.jafama.FastMath;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Random;
|
||||
|
||||
public class Range implements Iterable<Integer> {
|
||||
private int min;
|
||||
private int max;
|
||||
|
||||
public Range(int min, int max) {
|
||||
if(min > max) throw new IllegalArgumentException("Minimum must not be grater than maximum!");
|
||||
this.max = max;
|
||||
this.min = min;
|
||||
}
|
||||
|
||||
public boolean isInRange(int test) {
|
||||
return test >= min && test < max;
|
||||
}
|
||||
|
||||
public int getMax() {
|
||||
return max;
|
||||
}
|
||||
|
||||
public Range setMax(int max) {
|
||||
this.max = max;
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getMin() {
|
||||
return min;
|
||||
}
|
||||
|
||||
public Range setMin(int min) {
|
||||
this.min = min;
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getRange() {
|
||||
return max - min;
|
||||
}
|
||||
|
||||
public Range multiply(int mult) {
|
||||
min *= mult;
|
||||
max *= mult;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Range reflect(int pt) {
|
||||
return new Range(2 * pt - this.getMax(), 2 * pt - this.getMin());
|
||||
}
|
||||
|
||||
public int get(Random r) {
|
||||
return r.nextInt((max - min) + 1) + min;
|
||||
}
|
||||
|
||||
public Range intersects(com.dfsek.terra.api.math.Range other) {
|
||||
try {
|
||||
return new Range(FastMath.max(this.getMin(), other.getMin()), FastMath.min(this.getMax(), other.getMax()));
|
||||
} catch(IllegalArgumentException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public Range add(int add) {
|
||||
this.min += add;
|
||||
this.max += add;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Range sub(int sub) {
|
||||
this.min -= sub;
|
||||
this.max -= sub;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Min: " + getMin() + ", Max:" + getMax();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return min * 31 + max;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if(!(obj instanceof com.dfsek.terra.api.math.Range)) return false;
|
||||
Range other = (com.dfsek.terra.api.math.Range) obj;
|
||||
return other.getMin() == this.getMin() && other.getMax() == this.getMax();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Iterator<Integer> iterator() {
|
||||
return new RangeIterator(this);
|
||||
}
|
||||
|
||||
private static class RangeIterator implements Iterator<Integer> {
|
||||
private final Range m;
|
||||
private Integer current;
|
||||
|
||||
public RangeIterator(Range m) {
|
||||
this.m = m;
|
||||
current = m.getMin();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return current < m.getMax();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer next() {
|
||||
current++;
|
||||
return current - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.dfsek.terra.api.math.noise;
|
||||
|
||||
import com.dfsek.terra.api.math.vector.Vector2;
|
||||
import com.dfsek.terra.api.math.vector.Vector3;
|
||||
|
||||
public interface NoiseSampler {
|
||||
/**
|
||||
* 2D noise at given position using current settings
|
||||
* <p>
|
||||
* Noise output bounded between -1...1
|
||||
*/
|
||||
double getNoise(double x, double y);
|
||||
|
||||
/**
|
||||
* 3D noise at given position using current settings
|
||||
* <p>
|
||||
* Noise output bounded between -1...1
|
||||
*/
|
||||
double getNoise(double x, double y, double z);
|
||||
|
||||
default double getNoise(Vector3 vector3) {
|
||||
return getNoise(vector3.getX(), vector3.getY(), vector3.getZ());
|
||||
}
|
||||
|
||||
default double getNoise(Vector2 vector2) {
|
||||
return getNoise(vector2.getX(), vector2.getZ());
|
||||
}
|
||||
|
||||
double getNoiseSeeded(int seed, double x, double y);
|
||||
|
||||
double getNoiseSeeded(int seed, double x, double y, double z);
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.dfsek.terra.api.math.noise.normalizer;
|
||||
|
||||
import com.dfsek.terra.api.math.noise.NoiseSampler;
|
||||
import net.jafama.FastMath;
|
||||
|
||||
public class ClampNormalizer extends Normalizer {
|
||||
private final double min;
|
||||
private final double max;
|
||||
|
||||
public ClampNormalizer(NoiseSampler sampler, double min, double max) {
|
||||
super(sampler);
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double normalize(double in) {
|
||||
return FastMath.max(FastMath.min(in, max), min);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.dfsek.terra.api.math.noise.normalizer;
|
||||
|
||||
import com.dfsek.terra.api.math.noise.NoiseSampler;
|
||||
|
||||
/**
|
||||
* Normalizer to linearly scale data's range.
|
||||
*/
|
||||
public class LinearNormalizer extends Normalizer {
|
||||
private final double min;
|
||||
private final double max;
|
||||
|
||||
public LinearNormalizer(NoiseSampler sampler, double min, double max) {
|
||||
super(sampler);
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double normalize(double in) {
|
||||
return (in - min) * (2 / (max - min)) - 1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.dfsek.terra.api.math.noise.normalizer;
|
||||
|
||||
import com.dfsek.terra.api.math.MathUtil;
|
||||
import com.dfsek.terra.api.math.noise.NoiseSampler;
|
||||
import net.jafama.FastMath;
|
||||
|
||||
/**
|
||||
* Normalizer to redistribute normally distributed data to a continuous distribution via an automatically generated lookup table.
|
||||
*/
|
||||
public class NormalNormalizer extends Normalizer {
|
||||
|
||||
private final double[] lookup;
|
||||
|
||||
public NormalNormalizer(NoiseSampler sampler, int buckets, double mean, double standardDeviation) {
|
||||
super(sampler);
|
||||
this.lookup = new double[buckets];
|
||||
|
||||
for(int i = 0; i < buckets; i++) {
|
||||
lookup[i] = MathUtil.normalInverse((double) i / buckets, mean, standardDeviation);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public double normalize(double in) {
|
||||
int start = 0;
|
||||
int end = lookup.length - 1;
|
||||
while(start + 1 < end) {
|
||||
int mid = start + (end - start) / 2;
|
||||
if(lookup[mid] <= in) {
|
||||
start = mid;
|
||||
} else {
|
||||
end = mid;
|
||||
}
|
||||
}
|
||||
double left = FastMath.abs(lookup[start] - in);
|
||||
double right = FastMath.abs(lookup[end] - in);
|
||||
|
||||
double fin;
|
||||
if(left <= right) {
|
||||
fin = (double) start / (lookup.length);
|
||||
} else fin = (double) end / (lookup.length);
|
||||
|
||||
return (fin - 0.5) * 2;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.dfsek.terra.api.math.noise.normalizer;
|
||||
|
||||
import com.dfsek.terra.api.math.noise.NoiseSampler;
|
||||
|
||||
public abstract class Normalizer implements NoiseSampler {
|
||||
private final NoiseSampler sampler;
|
||||
|
||||
public Normalizer(NoiseSampler sampler) {
|
||||
this.sampler = sampler;
|
||||
}
|
||||
|
||||
public abstract double normalize(double in);
|
||||
|
||||
@Override
|
||||
public double getNoise(double x, double y) {
|
||||
return normalize(sampler.getNoise(x, y));
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getNoise(double x, double y, double z) {
|
||||
return normalize(sampler.getNoise(x, y, z));
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getNoiseSeeded(int seed, double x, double y) {
|
||||
return normalize(sampler.getNoiseSeeded(seed, x, y));
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getNoiseSeeded(int seed, double x, double y, double z) {
|
||||
return normalize(sampler.getNoiseSeeded(seed, x, y, z));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.dfsek.terra.api.math.noise.samplers;
|
||||
|
||||
import com.dfsek.terra.api.math.noise.NoiseSampler;
|
||||
|
||||
public class DomainWarpedSampler implements NoiseSampler {
|
||||
private final NoiseSampler function;
|
||||
private final NoiseSampler warp;
|
||||
private final int seed;
|
||||
private final double amplitude;
|
||||
|
||||
public DomainWarpedSampler(NoiseSampler function, NoiseSampler warp, int seed, double amplitude) {
|
||||
this.function = function;
|
||||
this.warp = warp;
|
||||
this.seed = seed;
|
||||
this.amplitude = amplitude;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getNoise(double x, double y) {
|
||||
return getNoiseSeeded(seed, x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getNoise(double x, double y, double z) {
|
||||
return getNoiseSeeded(seed, x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getNoiseSeeded(int seed, double x, double y) {
|
||||
return function.getNoise(
|
||||
x + warp.getNoiseSeeded(seed, x, y) * amplitude,
|
||||
y + warp.getNoiseSeeded(seed + 1, x, y) * amplitude
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getNoiseSeeded(int seed, double x, double y, double z) {
|
||||
return function.getNoise(
|
||||
x + warp.getNoiseSeeded(seed, x, y, z) * amplitude,
|
||||
y + warp.getNoiseSeeded(seed + 1, x, y, z) * amplitude,
|
||||
z + warp.getNoiseSeeded(seed + 2, x, y, z) * amplitude
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package com.dfsek.terra.api.math.noise.samplers;
|
||||
|
||||
import com.dfsek.paralithic.Expression;
|
||||
import com.dfsek.paralithic.eval.parser.Parser;
|
||||
import com.dfsek.paralithic.eval.parser.Scope;
|
||||
import com.dfsek.paralithic.eval.tokenizer.ParseException;
|
||||
import com.dfsek.terra.api.math.noise.NoiseSampler;
|
||||
import com.dfsek.terra.api.math.paralithic.defined.UserDefinedFunction;
|
||||
import com.dfsek.terra.api.math.paralithic.noise.NoiseFunction2;
|
||||
import com.dfsek.terra.api.math.paralithic.noise.NoiseFunction3;
|
||||
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
|
||||
import com.dfsek.terra.config.loaders.config.function.FunctionTemplate;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Sampler3D implementation using Paralithic expression
|
||||
*/
|
||||
public class ExpressionSampler implements NoiseSampler {
|
||||
private final Expression expression;
|
||||
|
||||
public ExpressionSampler(String equation, Scope parent, long seed, Map<String, NoiseSeeded> functions, Map<String, FunctionTemplate> definedFunctions) throws ParseException {
|
||||
Parser parser = new Parser();
|
||||
Scope scope = new Scope().withParent(parent);
|
||||
|
||||
scope.addInvocationVariable("x");
|
||||
scope.addInvocationVariable("y");
|
||||
scope.addInvocationVariable("z");
|
||||
|
||||
functions.forEach((id, noise) -> {
|
||||
switch(noise.getDimensions()) {
|
||||
case 2:
|
||||
parser.registerFunction(id, new NoiseFunction2(noise.apply(seed)));
|
||||
break;
|
||||
case 3:
|
||||
parser.registerFunction(id, new NoiseFunction3(noise.apply(seed)));
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
for(Map.Entry<String, FunctionTemplate> entry : definedFunctions.entrySet()) {
|
||||
parser.registerFunction(entry.getKey(), UserDefinedFunction.newInstance(entry.getValue(), parser, parent));
|
||||
}
|
||||
|
||||
this.expression = parser.parse(equation, scope);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getNoise(double x, double y) {
|
||||
return getNoise(x, 0, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getNoise(double x, double y, double z) {
|
||||
return expression.evaluate(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getNoiseSeeded(int seed, double x, double y) {
|
||||
return getNoise(x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getNoiseSeeded(int seed, double x, double y, double z) {
|
||||
return getNoise(x, y, z);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package com.dfsek.terra.api.math.noise.samplers;
|
||||
|
||||
import com.dfsek.terra.api.math.noise.NoiseSampler;
|
||||
import net.jafama.FastMath;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
public class ImageSampler implements NoiseSampler {
|
||||
private final BufferedImage image;
|
||||
private final Channel channel;
|
||||
|
||||
private final double frequency;
|
||||
|
||||
public ImageSampler(BufferedImage image, Channel channel, double frequency) {
|
||||
this.image = image;
|
||||
this.channel = channel;
|
||||
this.frequency = frequency;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getNoise(double x, double y) {
|
||||
return ((channel.getChannel(image.getRGB(FastMath.floorMod(FastMath.floorToInt(x * frequency), image.getWidth()), FastMath.floorMod(FastMath.floorToInt(y * frequency), image.getHeight()))) / 255D) - 0.5) * 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getNoise(double x, double y, double z) {
|
||||
return getNoise(x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getNoiseSeeded(int seed, double x, double y) {
|
||||
return getNoise(x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getNoiseSeeded(int seed, double x, double y, double z) {
|
||||
return getNoise(x, y, z);
|
||||
}
|
||||
|
||||
public enum Channel {
|
||||
RED {
|
||||
@Override
|
||||
public int getChannel(int mashed) {
|
||||
return (mashed >> 16) & 0xff;
|
||||
}
|
||||
}, GREEN {
|
||||
@Override
|
||||
public int getChannel(int mashed) {
|
||||
return (mashed >> 8) & 0xff;
|
||||
}
|
||||
}, BLUE {
|
||||
@Override
|
||||
public int getChannel(int mashed) {
|
||||
return mashed & 0xff;
|
||||
}
|
||||
}, GRAYSCALE {
|
||||
@Override
|
||||
public int getChannel(int mashed) {
|
||||
return (RED.getChannel(mashed) + GREEN.getChannel(mashed) + BLUE.getChannel(mashed)) / 3;
|
||||
}
|
||||
}, ALPHA {
|
||||
@Override
|
||||
public int getChannel(int mashed) {
|
||||
return (mashed >> 24) & 0xff;
|
||||
}
|
||||
};
|
||||
|
||||
public abstract int getChannel(int mashed);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package com.dfsek.terra.api.math.noise.samplers;
|
||||
|
||||
import com.dfsek.terra.api.math.noise.NoiseSampler;
|
||||
|
||||
public class KernelSampler implements NoiseSampler {
|
||||
private final double[][] kernel;
|
||||
private final NoiseSampler in;
|
||||
private double frequency = 1;
|
||||
|
||||
public KernelSampler(double[][] kernel, NoiseSampler in) {
|
||||
this.kernel = kernel;
|
||||
this.in = in;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getNoise(double x, double y) {
|
||||
return getNoiseSeeded(0, x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getNoise(double x, double y, double z) {
|
||||
return getNoiseSeeded(0, x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getNoiseSeeded(int seed, double x, double y) {
|
||||
x *= frequency;
|
||||
y *= frequency;
|
||||
double accumulator = 0;
|
||||
|
||||
for(int kx = 0; kx < kernel.length; kx++) {
|
||||
for(int ky = 0; ky < kernel[kx].length; ky++) {
|
||||
accumulator += in.getNoise(x + kx, y + ky) * kernel[kx][ky];
|
||||
}
|
||||
}
|
||||
|
||||
return accumulator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getNoiseSeeded(int seed, double x, double y, double z) {
|
||||
x *= frequency;
|
||||
y *= frequency;
|
||||
z *= frequency;
|
||||
double accumulator = 0;
|
||||
|
||||
for(int kx = 0; kx < kernel.length; kx++) {
|
||||
for(int ky = 0; ky < kernel[kx].length; ky++) {
|
||||
accumulator += in.getNoise(x + kx, y, z + ky) * kernel[kx][ky];
|
||||
}
|
||||
}
|
||||
|
||||
return accumulator;
|
||||
}
|
||||
|
||||
public void setFrequency(double frequency) {
|
||||
this.frequency = frequency;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,565 @@
|
||||
package com.dfsek.terra.api.math.noise.samplers.noise;
|
||||
|
||||
import com.dfsek.terra.api.math.noise.NoiseSampler;
|
||||
import com.dfsek.terra.api.math.noise.samplers.noise.simplex.OpenSimplex2Sampler;
|
||||
import com.dfsek.terra.api.math.vector.Vector2;
|
||||
import com.dfsek.terra.api.math.vector.Vector3;
|
||||
|
||||
/**
|
||||
* NoiseSampler implementation for Cellular (Voronoi/Worley) Noise.
|
||||
*/
|
||||
public class CellularSampler extends NoiseFunction {
|
||||
private static final double[] RAND_VECS_3D = {
|
||||
-0.7292736885d, -0.6618439697d, 0.1735581948d, 0, 0.790292081d, -0.5480887466d, -0.2739291014d, 0, 0.7217578935d, 0.6226212466d,
|
||||
-0.3023380997d, 0, 0.565683137d, -0.8208298145d, -0.0790000257d, 0, 0.760049034d, -0.5555979497d, -0.3370999617d, 0,
|
||||
0.3713945616d, 0.5011264475d, 0.7816254623d, 0, -0.1277062463d, -0.4254438999d, -0.8959289049d, 0, -0.2881560924d,
|
||||
-0.5815838982d, 0.7607405838d, 0, 0.5849561111d, -0.662820239d, -0.4674352136d, 0, 0.3307171178d, 0.0391653737d, 0.94291689d, 0,
|
||||
0.8712121778d, -0.4113374369d, -0.2679381538d, 0, 0.580981015d, 0.7021915846d, 0.4115677815d, 0, 0.503756873d, 0.6330056931d,
|
||||
-0.5878203852d, 0, 0.4493712205d, 0.601390195d, 0.6606022552d, 0, -0.6878403724d, 0.09018890807d, -0.7202371714d, 0,
|
||||
-0.5958956522d, -0.6469350577d, 0.475797649d, 0, -0.5127052122d, 0.1946921978d, -0.8361987284d, 0, -0.9911507142d,
|
||||
-0.05410276466d, -0.1212153153d, 0, -0.2149721042d, 0.9720882117d, -0.09397607749d, 0, -0.7518650936d, -0.5428057603d,
|
||||
0.3742469607d, 0, 0.5237068895d, 0.8516377189d, -0.02107817834d, 0, 0.6333504779d, 0.1926167129d, -0.7495104896d, 0,
|
||||
-0.06788241606d, 0.3998305789d, 0.9140719259d, 0, -0.5538628599d, -0.4729896695d, -0.6852128902d, 0, -0.7261455366d,
|
||||
-0.5911990757d, 0.3509933228d, 0, -0.9229274737d, -0.1782808786d, 0.3412049336d, 0, -0.6968815002d, 0.6511274338d,
|
||||
0.3006480328d, 0, 0.9608044783d, -0.2098363234d, -0.1811724921d, 0, 0.06817146062d, -0.9743405129d, 0.2145069156d, 0,
|
||||
-0.3577285196d, -0.6697087264d, -0.6507845481d, 0, -0.1868621131d, 0.7648617052d, -0.6164974636d, 0, -0.6541697588d,
|
||||
0.3967914832d, 0.6439087246d, 0, 0.6993340405d, -0.6164538506d, 0.3618239211d, 0, -0.1546665739d, 0.6291283928d, 0.7617583057d,
|
||||
0, -0.6841612949d, -0.2580482182d, -0.6821542638d, 0, 0.5383980957d, 0.4258654885d, 0.7271630328d, 0, -0.5026987823d,
|
||||
-0.7939832935d, -0.3418836993d, 0, 0.3202971715d, 0.2834415347d, 0.9039195862d, 0, 0.8683227101d, -0.0003762656404d,
|
||||
-0.4959995258d, 0, 0.791120031d, -0.08511045745d, 0.6057105799d, 0, -0.04011016052d, -0.4397248749d, 0.8972364289d, 0,
|
||||
0.9145119872d, 0.3579346169d, -0.1885487608d, 0, -0.9612039066d, -0.2756484276d, 0.01024666929d, 0, 0.6510361721d,
|
||||
-0.2877799159d, -0.7023778346d, 0, -0.2041786351d, 0.7365237271d, 0.644859585d, 0, -0.7718263711d, 0.3790626912d, 0.5104855816d,
|
||||
0, -0.3060082741d, -0.7692987727d, 0.5608371729d, 0, 0.454007341d, -0.5024843065d, 0.7357899537d, 0, 0.4816795475d,
|
||||
0.6021208291d, -0.6367380315d, 0, 0.6961980369d, -0.3222197429d, 0.641469197d, 0, -0.6532160499d, -0.6781148932d, 0.3368515753d,
|
||||
0, 0.5089301236d, -0.6154662304d, -0.6018234363d, 0, -0.1635919754d, -0.9133604627d, -0.372840892d, 0, 0.52408019d,
|
||||
-0.8437664109d, 0.1157505864d, 0, 0.5902587356d, 0.4983817807d, -0.6349883666d, 0, 0.5863227872d, 0.494764745d, 0.6414307729d,
|
||||
0, 0.6779335087d, 0.2341345225d, 0.6968408593d, 0, 0.7177054546d, -0.6858979348d, 0.120178631d, 0, -0.5328819713d,
|
||||
-0.5205125012d, 0.6671608058d, 0, -0.8654874251d, -0.0700727088d, -0.4960053754d, 0, -0.2861810166d, 0.7952089234d,
|
||||
0.5345495242d, 0, -0.04849529634d, 0.9810836427d, -0.1874115585d, 0, -0.6358521667d, 0.6058348682d, 0.4781800233d, 0,
|
||||
0.6254794696d, -0.2861619734d, 0.7258696564d, 0, -0.2585259868d, 0.5061949264d, -0.8227581726d, 0, 0.02136306781d,
|
||||
0.5064016808d, -0.8620330371d, 0, 0.200111773d, 0.8599263484d, 0.4695550591d, 0, 0.4743561372d, 0.6014985084d, -0.6427953014d,
|
||||
0, 0.6622993731d, -0.5202474575d, -0.5391679918d, 0, 0.08084972818d, -0.6532720452d, 0.7527940996d, 0, -0.6893687501d,
|
||||
0.0592860349d, 0.7219805347d, 0, -0.1121887082d, -0.9673185067d, 0.2273952515d, 0, 0.7344116094d, 0.5979668656d, -0.3210532909d,
|
||||
0, 0.5789393465d, -0.2488849713d, 0.7764570201d, 0, 0.6988182827d, 0.3557169806d, -0.6205791146d, 0, -0.8636845529d,
|
||||
-0.2748771249d, -0.4224826141d, 0, -0.4247027957d, -0.4640880967d, 0.777335046d, 0, 0.5257722489d, -0.8427017621d,
|
||||
0.1158329937d, 0, 0.9343830603d, 0.316302472d, -0.1639543925d, 0, -0.1016836419d, -0.8057303073d, -0.5834887393d, 0,
|
||||
-0.6529238969d, 0.50602126d, -0.5635892736d, 0, -0.2465286165d, -0.9668205684d, -0.06694497494d, 0, -0.9776897119d,
|
||||
-0.2099250524d, -0.007368825344d, 0, 0.7736893337d, 0.5734244712d, 0.2694238123d, 0, -0.6095087895d, 0.4995678998d,
|
||||
0.6155736747d, 0, 0.5794535482d, 0.7434546771d, 0.3339292269d, 0, -0.8226211154d, 0.08142581855d, 0.5627293636d, 0,
|
||||
-0.510385483d, 0.4703667658d, 0.7199039967d, 0, -0.5764971849d, -0.07231656274d, -0.8138926898d, 0, 0.7250628871d,
|
||||
0.3949971505d, -0.5641463116d, 0, -0.1525424005d, 0.4860840828d, -0.8604958341d, 0, -0.5550976208d, -0.4957820792d,
|
||||
0.667882296d, 0, -0.1883614327d, 0.9145869398d, 0.357841725d, 0, 0.7625556724d, -0.5414408243d, -0.3540489801d, 0,
|
||||
-0.5870231946d, -0.3226498013d, -0.7424963803d, 0, 0.3051124198d, 0.2262544068d, -0.9250488391d, 0, 0.6379576059d, 0.577242424d,
|
||||
-0.5097070502d, 0, -0.5966775796d, 0.1454852398d, -0.7891830656d, 0, -0.658330573d, 0.6555487542d, -0.3699414651d, 0,
|
||||
0.7434892426d, 0.2351084581d, 0.6260573129d, 0, 0.5562114096d, 0.8264360377d, -0.0873632843d, 0, -0.3028940016d, -0.8251527185d,
|
||||
0.4768419182d, 0, 0.1129343818d, -0.985888439d, -0.1235710781d, 0, 0.5937652891d, -0.5896813806d, 0.5474656618d, 0,
|
||||
0.6757964092d, -0.5835758614d, -0.4502648413d, 0, 0.7242302609d, -0.1152719764d, 0.6798550586d, 0, -0.9511914166d,
|
||||
0.0753623979d, -0.2992580792d, 0, 0.2539470961d, -0.1886339355d, 0.9486454084d, 0, 0.571433621d, -0.1679450851d, -0.8032795685d,
|
||||
0, -0.06778234979d, 0.3978269256d, 0.9149531629d, 0, 0.6074972649d, 0.733060024d, -0.3058922593d, 0, -0.5435478392d,
|
||||
0.1675822484d, 0.8224791405d, 0, -0.5876678086d, -0.3380045064d, -0.7351186982d, 0, -0.7967562402d, 0.04097822706d,
|
||||
-0.6029098428d, 0, -0.1996350917d, 0.8706294745d, 0.4496111079d, 0, -0.02787660336d, -0.9106232682d, -0.4122962022d, 0,
|
||||
-0.7797625996d, -0.6257634692d, 0.01975775581d, 0, -0.5211232846d, 0.7401644346d, -0.4249554471d, 0, 0.8575424857d,
|
||||
0.4053272873d, -0.3167501783d, 0, 0.1045223322d, 0.8390195772d, -0.5339674439d, 0, 0.3501822831d, 0.9242524096d, -0.1520850155d,
|
||||
0, 0.1987849858d, 0.07647613266d, 0.9770547224d, 0, 0.7845996363d, 0.6066256811d, -0.1280964233d, 0, 0.09006737436d,
|
||||
-0.9750989929d, -0.2026569073d, 0, -0.8274343547d, -0.542299559d, 0.1458203587d, 0, -0.3485797732d, -0.415802277d, 0.840000362d,
|
||||
0, -0.2471778936d, -0.7304819962d, -0.6366310879d, 0, -0.3700154943d, 0.8577948156d, 0.3567584454d, 0, 0.5913394901d,
|
||||
-0.548311967d, -0.5913303597d, 0, 0.1204873514d, -0.7626472379d, -0.6354935001d, 0, 0.616959265d, 0.03079647928d, 0.7863922953d,
|
||||
0, 0.1258156836d, -0.6640829889d, -0.7369967419d, 0, -0.6477565124d, -0.1740147258d, -0.7417077429d, 0, 0.6217889313d,
|
||||
-0.7804430448d, -0.06547655076d, 0, 0.6589943422d, -0.6096987708d, 0.4404473475d, 0, -0.2689837504d, -0.6732403169d,
|
||||
-0.6887635427d, 0, -0.3849775103d, 0.5676542638d, 0.7277093879d, 0, 0.5754444408d, 0.8110471154d, -0.1051963504d, 0,
|
||||
0.9141593684d, 0.3832947817d, 0.131900567d, 0, -0.107925319d, 0.9245493968d, 0.3654593525d, 0, 0.377977089d, 0.3043148782d,
|
||||
0.8743716458d, 0, -0.2142885215d, -0.8259286236d, 0.5214617324d, 0, 0.5802544474d, 0.4148098596d, -0.7008834116d, 0,
|
||||
-0.1982660881d, 0.8567161266d, -0.4761596756d, 0, -0.03381553704d, 0.3773180787d, -0.9254661404d, 0, -0.6867922841d,
|
||||
-0.6656597827d, 0.2919133642d, 0, 0.7731742607d, -0.2875793547d, -0.5652430251d, 0, -0.09655941928d, 0.9193708367d,
|
||||
-0.3813575004d, 0, 0.2715702457d, -0.9577909544d, -0.09426605581d, 0, 0.2451015704d, -0.6917998565d, -0.6792188003d, 0,
|
||||
0.977700782d, -0.1753855374d, 0.1155036542d, 0, -0.5224739938d, 0.8521606816d, 0.02903615945d, 0, -0.7734880599d,
|
||||
-0.5261292347d, 0.3534179531d, 0, -0.7134492443d, -0.269547243d, 0.6467878011d, 0, 0.1644037271d, 0.5105846203d, -0.8439637196d,
|
||||
0, 0.6494635788d, 0.05585611296d, 0.7583384168d, 0, -0.4711970882d, 0.5017280509d, -0.7254255765d, 0, -0.6335764307d,
|
||||
-0.2381686273d, -0.7361091029d, 0, -0.9021533097d, -0.270947803d, -0.3357181763d, 0, -0.3793711033d, 0.872258117d,
|
||||
0.3086152025d, 0, -0.6855598966d, -0.3250143309d, 0.6514394162d, 0, 0.2900942212d, -0.7799057743d, -0.5546100667d, 0,
|
||||
-0.2098319339d, 0.85037073d, 0.4825351604d, 0, -0.4592603758d, 0.6598504336d, -0.5947077538d, 0, 0.8715945488d, 0.09616365406d,
|
||||
-0.4807031248d, 0, -0.6776666319d, 0.7118504878d, -0.1844907016d, 0, 0.7044377633d, 0.312427597d, 0.637304036d, 0,
|
||||
-0.7052318886d, -0.2401093292d, -0.6670798253d, 0, 0.081921007d, -0.7207336136d, -0.6883545647d, 0, -0.6993680906d,
|
||||
-0.5875763221d, -0.4069869034d, 0, -0.1281454481d, 0.6419895885d, 0.7559286424d, 0, -0.6337388239d, -0.6785471501d,
|
||||
-0.3714146849d, 0, 0.5565051903d, -0.2168887573d, -0.8020356851d, 0, -0.5791554484d, 0.7244372011d, -0.3738578718d, 0,
|
||||
0.1175779076d, -0.7096451073d, 0.6946792478d, 0, -0.6134619607d, 0.1323631078d, 0.7785527795d, 0, 0.6984635305d,
|
||||
-0.02980516237d, -0.715024719d, 0, 0.8318082963d, -0.3930171956d, 0.3919597455d, 0, 0.1469576422d, 0.05541651717d,
|
||||
-0.9875892167d, 0, 0.708868575d, -0.2690503865d, 0.6520101478d, 0, 0.2726053183d, 0.67369766d, -0.68688995d, 0, -0.6591295371d,
|
||||
0.3035458599d, -0.6880466294d, 0, 0.4815131379d, -0.7528270071d, 0.4487723203d, 0, 0.9430009463d, 0.1675647412d, -0.2875261255d,
|
||||
0, 0.434802957d, 0.7695304522d, -0.4677277752d, 0, 0.3931996188d, 0.594473625d, 0.7014236729d, 0, 0.7254336655d, -0.603925654d,
|
||||
0.3301814672d, 0, 0.7590235227d, -0.6506083235d, 0.02433313207d, 0, -0.8552768592d, -0.3430042733d, 0.3883935666d, 0,
|
||||
-0.6139746835d, 0.6981725247d, 0.3682257648d, 0, -0.7465905486d, -0.5752009504d, 0.3342849376d, 0, 0.5730065677d, 0.810555537d,
|
||||
-0.1210916791d, 0, -0.9225877367d, -0.3475211012d, -0.167514036d, 0, -0.7105816789d, -0.4719692027d, -0.5218416899d, 0,
|
||||
-0.08564609717d, 0.3583001386d, 0.929669703d, 0, -0.8279697606d, -0.2043157126d, 0.5222271202d, 0, 0.427944023d, 0.278165994d,
|
||||
0.8599346446d, 0, 0.5399079671d, -0.7857120652d, -0.3019204161d, 0, 0.5678404253d, -0.5495413974d, -0.6128307303d, 0,
|
||||
-0.9896071041d, 0.1365639107d, -0.04503418428d, 0, -0.6154342638d, -0.6440875597d, 0.4543037336d, 0, 0.1074204368d,
|
||||
-0.7946340692d, 0.5975094525d, 0, -0.3595449969d, -0.8885529948d, 0.28495784d, 0, -0.2180405296d, 0.1529888965d, 0.9638738118d,
|
||||
0, -0.7277432317d, -0.6164050508d, -0.3007234646d, 0, 0.7249729114d, -0.00669719484d, 0.6887448187d, 0, -0.5553659455d,
|
||||
-0.5336586252d, 0.6377908264d, 0, 0.5137558015d, 0.7976208196d, -0.3160000073d, 0, -0.3794024848d, 0.9245608561d,
|
||||
-0.03522751494d, 0, 0.8229248658d, 0.2745365933d, -0.4974176556d, 0, -0.5404114394d, 0.6091141441d, 0.5804613989d, 0,
|
||||
0.8036581901d, -0.2703029469d, 0.5301601931d, 0, 0.6044318879d, 0.6832968393d, 0.4095943388d, 0, 0.06389988817d, 0.9658208605d,
|
||||
-0.2512108074d, 0, 0.1087113286d, 0.7402471173d, -0.6634877936d, 0, -0.713427712d, -0.6926784018d, 0.1059128479d, 0,
|
||||
0.6458897819d, -0.5724548511d, -0.5050958653d, 0, -0.6553931414d, 0.7381471625d, 0.159995615d, 0, 0.3910961323d, 0.9188871375d,
|
||||
-0.05186755998d, 0, -0.4879022471d, -0.5904376907d, 0.6429111375d, 0, 0.6014790094d, 0.7707441366d, -0.2101820095d, 0,
|
||||
-0.5677173047d, 0.7511360995d, 0.3368851762d, 0, 0.7858573506d, 0.226674665d, 0.5753666838d, 0, -0.4520345543d, -0.604222686d,
|
||||
-0.6561857263d, 0, 0.002272116345d, 0.4132844051d, -0.9105991643d, 0, -0.5815751419d, -0.5162925989d, 0.6286591339d, 0,
|
||||
-0.03703704785d, 0.8273785755d, 0.5604221175d, 0, -0.5119692504d, 0.7953543429d, -0.3244980058d, 0, -0.2682417366d,
|
||||
-0.9572290247d, -0.1084387619d, 0, -0.2322482736d, -0.9679131102d, -0.09594243324d, 0, 0.3554328906d, -0.8881505545d,
|
||||
0.2913006227d, 0, 0.7346520519d, -0.4371373164d, 0.5188422971d, 0, 0.9985120116d, 0.04659011161d, -0.02833944577d, 0,
|
||||
-0.3727687496d, -0.9082481361d, 0.1900757285d, 0, 0.91737377d, -0.3483642108d, 0.1925298489d, 0, 0.2714911074d, 0.4147529736d,
|
||||
-0.8684886582d, 0, 0.5131763485d, -0.7116334161d, 0.4798207128d, 0, -0.8737353606d, 0.18886992d, -0.4482350644d, 0,
|
||||
0.8460043821d, -0.3725217914d, 0.3814499973d, 0, 0.8978727456d, -0.1780209141d, -0.4026575304d, 0, 0.2178065647d,
|
||||
-0.9698322841d, -0.1094789531d, 0, -0.1518031304d, -0.7788918132d, -0.6085091231d, 0, -0.2600384876d, -0.4755398075d,
|
||||
-0.8403819825d, 0, 0.572313509d, -0.7474340931d, -0.3373418503d, 0, -0.7174141009d, 0.1699017182d, -0.6756111411d, 0,
|
||||
-0.684180784d, 0.02145707593d, -0.7289967412d, 0, -0.2007447902d, 0.06555605789d, -0.9774476623d, 0, -0.1148803697d,
|
||||
-0.8044887315d, 0.5827524187d, 0, -0.7870349638d, 0.03447489231d, 0.6159443543d, 0, -0.2015596421d, 0.6859872284d,
|
||||
0.6991389226d, 0, -0.08581082512d, -0.10920836d, -0.9903080513d, 0, 0.5532693395d, 0.7325250401d, -0.396610771d, 0,
|
||||
-0.1842489331d, -0.9777375055d, -0.1004076743d, 0, 0.0775473789d, -0.9111505856d, 0.4047110257d, 0, 0.1399838409d,
|
||||
0.7601631212d, -0.6344734459d, 0, 0.4484419361d, -0.845289248d, 0.2904925424d, 0
|
||||
};
|
||||
|
||||
private static final double[] RAND_VECS_2D = {
|
||||
-0.2700222198d, -0.9628540911d, 0.3863092627d, -0.9223693152d, 0.04444859006d, -0.999011673d, -0.5992523158d, -0.8005602176d,
|
||||
-0.7819280288d, 0.6233687174d, 0.9464672271d, 0.3227999196d, -0.6514146797d, -0.7587218957d, 0.9378472289d, 0.347048376d,
|
||||
-0.8497875957d, -0.5271252623d, -0.879042592d, 0.4767432447d, -0.892300288d, -0.4514423508d, -0.379844434d, -0.9250503802d,
|
||||
-0.9951650832d, 0.0982163789d, 0.7724397808d, -0.6350880136d, 0.7573283322d, -0.6530343002d, -0.9928004525d, -0.119780055d,
|
||||
-0.0532665713d, 0.9985803285d, 0.9754253726d, -0.2203300762d, -0.7665018163d, 0.6422421394d, 0.991636706d, 0.1290606184d,
|
||||
-0.994696838d, 0.1028503788d, -0.5379205513d, -0.84299554d, 0.5022815471d, -0.8647041387d, 0.4559821461d, -0.8899889226d,
|
||||
-0.8659131224d, -0.5001944266d, 0.0879458407d, -0.9961252577d, -0.5051684983d, 0.8630207346d, 0.7753185226d, -0.6315704146d,
|
||||
-0.6921944612d, 0.7217110418d, -0.5191659449d, -0.8546734591d, 0.8978622882d, -0.4402764035d, -0.1706774107d, 0.9853269617d,
|
||||
-0.9353430106d, -0.3537420705d, -0.9992404798d, 0.03896746794d, -0.2882064021d, -0.9575683108d, -0.9663811329d, 0.2571137995d,
|
||||
-0.8759714238d, -0.4823630009d, -0.8303123018d, -0.5572983775d, 0.05110133755d, -0.9986934731d, -0.8558373281d, -0.5172450752d,
|
||||
0.09887025282d, 0.9951003332d, 0.9189016087d, 0.3944867976d, -0.2439375892d, -0.9697909324d, -0.8121409387d, -0.5834613061d,
|
||||
-0.9910431363d, 0.1335421355d, 0.8492423985d, -0.5280031709d, -0.9717838994d, -0.2358729591d, 0.9949457207d, 0.1004142068d,
|
||||
0.6241065508d, -0.7813392434d, 0.662910307d, 0.7486988212d, -0.7197418176d, 0.6942418282d, -0.8143370775d, -0.5803922158d,
|
||||
0.104521054d, -0.9945226741d, -0.1065926113d, -0.9943027784d, 0.445799684d, -0.8951327509d, 0.105547406d, 0.9944142724d,
|
||||
-0.992790267d, 0.1198644477d, -0.8334366408d, 0.552615025d, 0.9115561563d, -0.4111755999d, 0.8285544909d, -0.5599084351d,
|
||||
0.7217097654d, -0.6921957921d, 0.4940492677d, -0.8694339084d, -0.3652321272d, -0.9309164803d, -0.9696606758d, 0.2444548501d,
|
||||
0.08925509731d, -0.996008799d, 0.5354071276d, -0.8445941083d, -0.1053576186d, 0.9944343981d, -0.9890284586d, 0.1477251101d,
|
||||
0.004856104961d, 0.9999882091d, 0.9885598478d, 0.1508291331d, 0.9286129562d, -0.3710498316d, -0.5832393863d, -0.8123003252d,
|
||||
0.3015207509d, 0.9534596146d, -0.9575110528d, 0.2883965738d, 0.9715802154d, -0.2367105511d, 0.229981792d, 0.9731949318d,
|
||||
0.955763816d, -0.2941352207d, 0.740956116d, 0.6715534485d, -0.9971513787d, -0.07542630764d, 0.6905710663d, -0.7232645452d,
|
||||
-0.290713703d, -0.9568100872d, 0.5912777791d, -0.8064679708d, -0.9454592212d, -0.325740481d, 0.6664455681d, 0.74555369d,
|
||||
0.6236134912d, 0.7817328275d, 0.9126993851d, -0.4086316587d, -0.8191762011d, 0.5735419353d, -0.8812745759d, -0.4726046147d,
|
||||
0.9953313627d, 0.09651672651d, 0.9855650846d, -0.1692969699d, -0.8495980887d, 0.5274306472d, 0.6174853946d, -0.7865823463d,
|
||||
0.8508156371d, 0.52546432d, 0.9985032451d, -0.05469249926d, 0.1971371563d, -0.9803759185d, 0.6607855748d, -0.7505747292d,
|
||||
-0.03097494063d, 0.9995201614d, -0.6731660801d, 0.739491331d, -0.7195018362d, -0.6944905383d, 0.9727511689d, 0.2318515979d,
|
||||
0.9997059088d, -0.0242506907d, 0.4421787429d, -0.8969269532d, 0.9981350961d, -0.061043673d, -0.9173660799d, -0.3980445648d,
|
||||
-0.8150056635d, -0.5794529907d, -0.8789331304d, 0.4769450202d, 0.0158605829d, 0.999874213d, -0.8095464474d, 0.5870558317d,
|
||||
-0.9165898907d, -0.3998286786d, -0.8023542565d, 0.5968480938d, -0.5176737917d, 0.8555780767d, -0.8154407307d, -0.5788405779d,
|
||||
0.4022010347d, -0.9155513791d, -0.9052556868d, -0.4248672045d, 0.7317445619d, 0.6815789728d, -0.5647632201d, -0.8252529947d,
|
||||
-0.8403276335d, -0.5420788397d, -0.9314281527d, 0.363925262d, 0.5238198472d, 0.8518290719d, 0.7432803869d, -0.6689800195d,
|
||||
-0.985371561d, -0.1704197369d, 0.4601468731d, 0.88784281d, 0.825855404d, 0.5638819483d, 0.6182366099d, 0.7859920446d,
|
||||
0.8331502863d, -0.553046653d, 0.1500307506d, 0.9886813308d, -0.662330369d, -0.7492119075d, -0.668598664d, 0.743623444d,
|
||||
0.7025606278d, 0.7116238924d, -0.5419389763d, -0.8404178401d, -0.3388616456d, 0.9408362159d, 0.8331530315d, 0.5530425174d,
|
||||
-0.2989720662d, -0.9542618632d, 0.2638522993d, 0.9645630949d, 0.124108739d, -0.9922686234d, -0.7282649308d, -0.6852956957d,
|
||||
0.6962500149d, 0.7177993569d, -0.9183535368d, 0.3957610156d, -0.6326102274d, -0.7744703352d, -0.9331891859d, -0.359385508d,
|
||||
-0.1153779357d, -0.9933216659d, 0.9514974788d, -0.3076565421d, -0.08987977445d, -0.9959526224d, 0.6678496916d, 0.7442961705d,
|
||||
0.7952400393d, -0.6062947138d, -0.6462007402d, -0.7631674805d, -0.2733598753d, 0.9619118351d, 0.9669590226d, -0.254931851d,
|
||||
-0.9792894595d, 0.2024651934d, -0.5369502995d, -0.8436138784d, -0.270036471d, -0.9628500944d, -0.6400277131d, 0.7683518247d,
|
||||
-0.7854537493d, -0.6189203566d, 0.06005905383d, -0.9981948257d, -0.02455770378d, 0.9996984141d, -0.65983623d, 0.751409442d,
|
||||
-0.6253894466d, -0.7803127835d, -0.6210408851d, -0.7837781695d, 0.8348888491d, 0.5504185768d, -0.1592275245d, 0.9872419133d,
|
||||
0.8367622488d, 0.5475663786d, -0.8675753916d, -0.4973056806d, -0.2022662628d, -0.9793305667d, 0.9399189937d, 0.3413975472d,
|
||||
0.9877404807d, -0.1561049093d, -0.9034455656d, 0.4287028224d, 0.1269804218d, -0.9919052235d, -0.3819600854d, 0.924178821d,
|
||||
0.9754625894d, 0.2201652486d, -0.3204015856d, -0.9472818081d, -0.9874760884d, 0.1577687387d, 0.02535348474d, -0.9996785487d,
|
||||
0.4835130794d, -0.8753371362d, -0.2850799925d, -0.9585037287d, -0.06805516006d, -0.99768156d, -0.7885244045d, -0.6150034663d,
|
||||
0.3185392127d, -0.9479096845d, 0.8880043089d, 0.4598351306d, 0.6476921488d, -0.7619021462d, 0.9820241299d, 0.1887554194d,
|
||||
0.9357275128d, -0.3527237187d, -0.8894895414d, 0.4569555293d, 0.7922791302d, 0.6101588153d, 0.7483818261d, 0.6632681526d,
|
||||
-0.7288929755d, -0.6846276581d, 0.8729032783d, -0.4878932944d, 0.8288345784d, 0.5594937369d, 0.08074567077d, 0.9967347374d,
|
||||
0.9799148216d, -0.1994165048d, -0.580730673d, -0.8140957471d, -0.4700049791d, -0.8826637636d, 0.2409492979d, 0.9705377045d,
|
||||
0.9437816757d, -0.3305694308d, -0.8927998638d, -0.4504535528d, -0.8069622304d, 0.5906030467d, 0.06258973166d, 0.9980393407d,
|
||||
-0.9312597469d, 0.3643559849d, 0.5777449785d, 0.8162173362d, -0.3360095855d, -0.941858566d, 0.697932075d, -0.7161639607d,
|
||||
-0.002008157227d, -0.9999979837d, -0.1827294312d, -0.9831632392d, -0.6523911722d, 0.7578824173d, -0.4302626911d, -0.9027037258d,
|
||||
-0.9985126289d, -0.05452091251d, -0.01028102172d, -0.9999471489d, -0.4946071129d, 0.8691166802d, -0.2999350194d, 0.9539596344d,
|
||||
0.8165471961d, 0.5772786819d, 0.2697460475d, 0.962931498d, -0.7306287391d, -0.6827749597d, -0.7590952064d, -0.6509796216d,
|
||||
-0.907053853d, 0.4210146171d, -0.5104861064d, -0.8598860013d, 0.8613350597d, 0.5080373165d, 0.5007881595d, -0.8655698812d,
|
||||
-0.654158152d, 0.7563577938d, -0.8382755311d, -0.545246856d, 0.6940070834d, 0.7199681717d, 0.06950936031d, 0.9975812994d,
|
||||
0.1702942185d, -0.9853932612d, 0.2695973274d, 0.9629731466d, 0.5519612192d, -0.8338697815d, 0.225657487d, -0.9742067022d,
|
||||
0.4215262855d, -0.9068161835d, 0.4881873305d, -0.8727388672d, -0.3683854996d, -0.9296731273d, -0.9825390578d, 0.1860564427d,
|
||||
0.81256471d, 0.5828709909d, 0.3196460933d, -0.9475370046d, 0.9570913859d, 0.2897862643d, -0.6876655497d, -0.7260276109d,
|
||||
-0.9988770922d, -0.047376731d, -0.1250179027d, 0.992154486d, -0.8280133617d, 0.560708367d, 0.9324863769d, -0.3612051451d,
|
||||
0.6394653183d, 0.7688199442d, -0.01623847064d, -0.9998681473d, -0.9955014666d, -0.09474613458d, -0.81453315d, 0.580117012d,
|
||||
0.4037327978d, -0.9148769469d, 0.9944263371d, 0.1054336766d, -0.1624711654d, 0.9867132919d, -0.9949487814d, -0.100383875d,
|
||||
-0.6995302564d, 0.7146029809d, 0.5263414922d, -0.85027327d, -0.5395221479d, 0.841971408d, 0.6579370318d, 0.7530729462d,
|
||||
0.01426758847d, -0.9998982128d, -0.6734383991d, 0.7392433447d, 0.639412098d, -0.7688642071d, 0.9211571421d, 0.3891908523d,
|
||||
-0.146637214d, -0.9891903394d, -0.782318098d, 0.6228791163d, -0.5039610839d, -0.8637263605d, -0.7743120191d, -0.6328039957d,
|
||||
};
|
||||
|
||||
|
||||
private DistanceFunction distanceFunction = DistanceFunction.EuclideanSq;
|
||||
private ReturnType returnType = ReturnType.Distance;
|
||||
private double jitterModifier = 1.0;
|
||||
|
||||
private NoiseSampler noiseLookup;
|
||||
|
||||
public CellularSampler(int seed) {
|
||||
super(seed);
|
||||
noiseLookup = new OpenSimplex2Sampler(seed);
|
||||
}
|
||||
|
||||
public void setDistanceFunction(DistanceFunction distanceFunction) {
|
||||
this.distanceFunction = distanceFunction;
|
||||
}
|
||||
|
||||
public void setJitterModifier(double jitterModifier) {
|
||||
this.jitterModifier = jitterModifier;
|
||||
}
|
||||
|
||||
public void setNoiseLookup(NoiseSampler noiseLookup) {
|
||||
this.noiseLookup = noiseLookup;
|
||||
}
|
||||
|
||||
public void setReturnType(ReturnType returnType) {
|
||||
this.returnType = returnType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getNoiseRaw(int seed, double x, double y) {
|
||||
int xr = fastRound(x);
|
||||
int yr = fastRound(y);
|
||||
|
||||
double distance0 = Double.MAX_VALUE;
|
||||
double distance1 = Double.MAX_VALUE;
|
||||
double distance2 = Double.MAX_VALUE;
|
||||
|
||||
int closestHash = 0;
|
||||
|
||||
double cellularJitter = 0.43701595 * jitterModifier;
|
||||
|
||||
int xPrimed = (xr - 1) * PRIME_X;
|
||||
int yPrimedBase = (yr - 1) * PRIME_Y;
|
||||
|
||||
Vector2 center = new Vector2(x, y);
|
||||
|
||||
switch(distanceFunction) {
|
||||
default:
|
||||
case Euclidean:
|
||||
case EuclideanSq:
|
||||
for(int xi = xr - 1; xi <= xr + 1; xi++) {
|
||||
int yPrimed = yPrimedBase;
|
||||
|
||||
for(int yi = yr - 1; yi <= yr + 1; yi++) {
|
||||
int hash = hash(seed, xPrimed, yPrimed);
|
||||
int idx = hash & (255 << 1);
|
||||
|
||||
double vecX = (xi - x) + RAND_VECS_2D[idx] * cellularJitter;
|
||||
double vecY = (yi - y) + RAND_VECS_2D[idx | 1] * cellularJitter;
|
||||
|
||||
double newDistance = vecX * vecX + vecY * vecY;
|
||||
|
||||
distance1 = fastMax(fastMin(distance1, newDistance), distance0);
|
||||
if(newDistance < distance0) {
|
||||
distance0 = newDistance;
|
||||
closestHash = hash;
|
||||
center.setX((xi + RAND_VECS_2D[idx] * cellularJitter) / frequency);
|
||||
center.setZ((yi + RAND_VECS_2D[idx | 1] * cellularJitter) / frequency);
|
||||
} else if(newDistance < distance1) {
|
||||
distance2 = distance1;
|
||||
distance1 = newDistance;
|
||||
} else if(newDistance < distance2) {
|
||||
distance2 = newDistance;
|
||||
}
|
||||
yPrimed += PRIME_Y;
|
||||
}
|
||||
xPrimed += PRIME_X;
|
||||
}
|
||||
break;
|
||||
case Manhattan:
|
||||
for(int xi = xr - 1; xi <= xr + 1; xi++) {
|
||||
int yPrimed = yPrimedBase;
|
||||
|
||||
for(int yi = yr - 1; yi <= yr + 1; yi++) {
|
||||
int hash = hash(seed, xPrimed, yPrimed);
|
||||
int idx = hash & (255 << 1);
|
||||
|
||||
double vecX = (xi - x) + RAND_VECS_2D[idx] * cellularJitter;
|
||||
double vecY = (yi - y) + RAND_VECS_2D[idx | 1] * cellularJitter;
|
||||
|
||||
double newDistance = fastAbs(vecX) + fastAbs(vecY);
|
||||
|
||||
distance1 = fastMax(fastMin(distance1, newDistance), distance0);
|
||||
if(newDistance < distance0) {
|
||||
distance0 = newDistance;
|
||||
closestHash = hash;
|
||||
center.setX((xi + RAND_VECS_2D[idx] * cellularJitter) / frequency);
|
||||
center.setZ((yi + RAND_VECS_2D[idx | 1] * cellularJitter) / frequency);
|
||||
} else if(newDistance < distance1) {
|
||||
distance2 = distance1;
|
||||
distance1 = newDistance;
|
||||
} else if(newDistance < distance2) {
|
||||
distance2 = newDistance;
|
||||
}
|
||||
yPrimed += PRIME_Y;
|
||||
}
|
||||
xPrimed += PRIME_X;
|
||||
}
|
||||
break;
|
||||
case Hybrid:
|
||||
for(int xi = xr - 1; xi <= xr + 1; xi++) {
|
||||
int yPrimed = yPrimedBase;
|
||||
|
||||
for(int yi = yr - 1; yi <= yr + 1; yi++) {
|
||||
int hash = hash(seed, xPrimed, yPrimed);
|
||||
int idx = hash & (255 << 1);
|
||||
|
||||
double vecX = (xi - x) + RAND_VECS_2D[idx] * cellularJitter;
|
||||
double vecY = (yi - y) + RAND_VECS_2D[idx | 1] * cellularJitter;
|
||||
|
||||
double newDistance = (fastAbs(vecX) + fastAbs(vecY)) + (vecX * vecX + vecY * vecY);
|
||||
|
||||
distance1 = fastMax(fastMin(distance1, newDistance), distance0);
|
||||
if(newDistance < distance0) {
|
||||
distance0 = newDistance;
|
||||
closestHash = hash;
|
||||
center.setX((xi + RAND_VECS_2D[idx] * cellularJitter) / frequency);
|
||||
center.setZ((yi + RAND_VECS_2D[idx | 1] * cellularJitter) / frequency);
|
||||
} else if(newDistance < distance1) {
|
||||
distance2 = distance1;
|
||||
distance1 = newDistance;
|
||||
} else if(newDistance < distance2) {
|
||||
distance2 = newDistance;
|
||||
}
|
||||
yPrimed += PRIME_Y;
|
||||
}
|
||||
xPrimed += PRIME_X;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(distanceFunction == DistanceFunction.Euclidean && returnType != ReturnType.CellValue) {
|
||||
distance0 = fastSqrt(distance0);
|
||||
if(returnType != ReturnType.CellValue) {
|
||||
distance1 = fastSqrt(distance1);
|
||||
}
|
||||
}
|
||||
|
||||
switch(returnType) {
|
||||
case CellValue:
|
||||
return closestHash * (1 / 2147483648.0);
|
||||
case Distance:
|
||||
return distance0 - 1;
|
||||
case Distance2:
|
||||
return distance1 - 1;
|
||||
case Distance2Add:
|
||||
return (distance1 + distance0) * 0.5 - 1;
|
||||
case Distance2Sub:
|
||||
return distance1 - distance0 - 1;
|
||||
case Distance2Mul:
|
||||
return distance1 * distance0 * 0.5 - 1;
|
||||
case Distance2Div:
|
||||
return distance0 / distance1 - 1;
|
||||
case NoiseLookup:
|
||||
return noiseLookup.getNoise(center.getX(), center.getZ());
|
||||
case Distance3:
|
||||
return distance2 - 1;
|
||||
case Distance3Add:
|
||||
return (distance2 + distance0) * 0.5 - 1;
|
||||
case Distance3Sub:
|
||||
return distance2 - distance0 - 1;
|
||||
case Distance3Mul:
|
||||
return distance2 * distance0 - 1;
|
||||
case Distance3Div:
|
||||
return distance0 / distance2 - 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getNoiseRaw(int seed, double x, double y, double z) {
|
||||
int xr = fastRound(x);
|
||||
int yr = fastRound(y);
|
||||
int zr = fastRound(z);
|
||||
|
||||
double distance0 = Double.MAX_VALUE;
|
||||
double distance1 = Double.MAX_VALUE;
|
||||
double distance2 = Double.MAX_VALUE;
|
||||
int closestHash = 0;
|
||||
|
||||
double cellularJitter = 0.39614353 * jitterModifier;
|
||||
|
||||
int xPrimed = (xr - 1) * PRIME_X;
|
||||
int yPrimedBase = (yr - 1) * PRIME_Y;
|
||||
int zPrimedBase = (zr - 1) * PRIME_Z;
|
||||
|
||||
Vector3 center = new Vector3(x, y, z);
|
||||
|
||||
switch(distanceFunction) {
|
||||
case Euclidean:
|
||||
case EuclideanSq:
|
||||
for(int xi = xr - 1; xi <= xr + 1; xi++) {
|
||||
int yPrimed = yPrimedBase;
|
||||
|
||||
for(int yi = yr - 1; yi <= yr + 1; yi++) {
|
||||
int zPrimed = zPrimedBase;
|
||||
|
||||
for(int zi = zr - 1; zi <= zr + 1; zi++) {
|
||||
int hash = hash(seed, xPrimed, yPrimed, zPrimed);
|
||||
int idx = hash & (255 << 2);
|
||||
|
||||
double vecX = (xi - x) + RAND_VECS_3D[idx] * cellularJitter;
|
||||
double vecY = (yi - y) + RAND_VECS_3D[idx | 1] * cellularJitter;
|
||||
double vecZ = (zi - z) + RAND_VECS_3D[idx | 2] * cellularJitter;
|
||||
|
||||
double newDistance = vecX * vecX + vecY * vecY + vecZ * vecZ;
|
||||
|
||||
if(newDistance < distance0) {
|
||||
distance0 = newDistance;
|
||||
closestHash = hash;
|
||||
center.setX((xi + RAND_VECS_3D[idx] * cellularJitter) / frequency);
|
||||
center.setY((yi + RAND_VECS_3D[idx | 1] * cellularJitter) / frequency);
|
||||
center.setZ((zi + RAND_VECS_3D[idx | 2] * cellularJitter) / frequency);
|
||||
} else if(newDistance < distance1) {
|
||||
distance2 = distance1;
|
||||
distance1 = newDistance;
|
||||
} else if(newDistance < distance2) {
|
||||
distance2 = newDistance;
|
||||
}
|
||||
zPrimed += PRIME_Z;
|
||||
}
|
||||
yPrimed += PRIME_Y;
|
||||
}
|
||||
xPrimed += PRIME_X;
|
||||
}
|
||||
break;
|
||||
case Manhattan:
|
||||
for(int xi = xr - 1; xi <= xr + 1; xi++) {
|
||||
int yPrimed = yPrimedBase;
|
||||
|
||||
for(int yi = yr - 1; yi <= yr + 1; yi++) {
|
||||
int zPrimed = zPrimedBase;
|
||||
|
||||
for(int zi = zr - 1; zi <= zr + 1; zi++) {
|
||||
int hash = hash(seed, xPrimed, yPrimed, zPrimed);
|
||||
int idx = hash & (255 << 2);
|
||||
|
||||
double vecX = (xi - x) + RAND_VECS_3D[idx] * cellularJitter;
|
||||
double vecY = (yi - y) + RAND_VECS_3D[idx | 1] * cellularJitter;
|
||||
double vecZ = (zi - z) + RAND_VECS_3D[idx | 2] * cellularJitter;
|
||||
|
||||
double newDistance = fastAbs(vecX) + fastAbs(vecY) + fastAbs(vecZ);
|
||||
|
||||
if(newDistance < distance0) {
|
||||
distance0 = newDistance;
|
||||
closestHash = hash;
|
||||
center.setX((xi + RAND_VECS_3D[idx] * cellularJitter) / frequency);
|
||||
center.setY((yi + RAND_VECS_3D[idx | 1] * cellularJitter) / frequency);
|
||||
center.setZ((zi + RAND_VECS_3D[idx | 2] * cellularJitter) / frequency);
|
||||
} else if(newDistance < distance1) {
|
||||
distance2 = distance1;
|
||||
distance1 = newDistance;
|
||||
} else if(newDistance < distance2) {
|
||||
distance2 = newDistance;
|
||||
}
|
||||
zPrimed += PRIME_Z;
|
||||
}
|
||||
yPrimed += PRIME_Y;
|
||||
}
|
||||
xPrimed += PRIME_X;
|
||||
}
|
||||
break;
|
||||
case Hybrid:
|
||||
for(int xi = xr - 1; xi <= xr + 1; xi++) {
|
||||
int yPrimed = yPrimedBase;
|
||||
|
||||
for(int yi = yr - 1; yi <= yr + 1; yi++) {
|
||||
int zPrimed = zPrimedBase;
|
||||
|
||||
for(int zi = zr - 1; zi <= zr + 1; zi++) {
|
||||
int hash = hash(seed, xPrimed, yPrimed, zPrimed);
|
||||
int idx = hash & (255 << 2);
|
||||
|
||||
double vecX = (xi - x) + RAND_VECS_3D[idx] * cellularJitter;
|
||||
double vecY = (yi - y) + RAND_VECS_3D[idx | 1] * cellularJitter;
|
||||
double vecZ = (zi - z) + RAND_VECS_3D[idx | 2] * cellularJitter;
|
||||
|
||||
double newDistance = (fastAbs(vecX) + fastAbs(vecY) + fastAbs(vecZ)) +
|
||||
(vecX * vecX + vecY * vecY + vecZ * vecZ);
|
||||
|
||||
distance1 = fastMax(fastMin(distance1, newDistance), distance0);
|
||||
if(newDistance < distance0) {
|
||||
distance0 = newDistance;
|
||||
closestHash = hash;
|
||||
center.setX((xi + RAND_VECS_3D[idx] * cellularJitter) / frequency);
|
||||
center.setY((yi + RAND_VECS_3D[idx | 1] * cellularJitter) / frequency);
|
||||
center.setZ((zi + RAND_VECS_3D[idx | 2] * cellularJitter) / frequency);
|
||||
} else if(newDistance < distance1) {
|
||||
distance2 = distance1;
|
||||
distance1 = newDistance;
|
||||
} else if(newDistance < distance2) {
|
||||
distance2 = newDistance;
|
||||
}
|
||||
zPrimed += PRIME_Z;
|
||||
}
|
||||
yPrimed += PRIME_Y;
|
||||
}
|
||||
xPrimed += PRIME_X;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if(distanceFunction == DistanceFunction.Euclidean && returnType != ReturnType.CellValue) {
|
||||
distance0 = fastSqrt(distance0);
|
||||
if(returnType != ReturnType.CellValue) {
|
||||
distance1 = fastSqrt(distance1);
|
||||
}
|
||||
}
|
||||
|
||||
switch(returnType) {
|
||||
case CellValue:
|
||||
return closestHash * (1 / 2147483648.0);
|
||||
case Distance:
|
||||
return distance0 - 1;
|
||||
case Distance2:
|
||||
return distance1 - 1;
|
||||
case Distance2Add:
|
||||
return (distance1 + distance0) * 0.5 - 1;
|
||||
case Distance2Sub:
|
||||
return distance1 - distance0 - 1;
|
||||
case Distance2Mul:
|
||||
return distance1 * distance0 * 0.5 - 1;
|
||||
case Distance2Div:
|
||||
return distance0 / distance1 - 1;
|
||||
case NoiseLookup:
|
||||
return noiseLookup.getNoise(center.getX(), center.getY(), center.getZ());
|
||||
case Distance3:
|
||||
return distance2 - 1;
|
||||
case Distance3Add:
|
||||
return (distance2 + distance0) * 0.5 - 1;
|
||||
case Distance3Sub:
|
||||
return distance2 - distance0 - 1;
|
||||
case Distance3Mul:
|
||||
return distance2 * distance0 - 1;
|
||||
case Distance3Div:
|
||||
return distance0 / distance2 - 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public enum DistanceFunction {
|
||||
Euclidean,
|
||||
EuclideanSq,
|
||||
Manhattan,
|
||||
Hybrid
|
||||
}
|
||||
|
||||
|
||||
public enum ReturnType {
|
||||
CellValue,
|
||||
Distance,
|
||||
Distance2,
|
||||
Distance2Add,
|
||||
Distance2Sub,
|
||||
Distance2Mul,
|
||||
Distance2Div,
|
||||
NoiseLookup,
|
||||
Distance3,
|
||||
Distance3Add,
|
||||
Distance3Sub,
|
||||
Distance3Mul,
|
||||
Distance3Div
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.dfsek.terra.api.math.noise.samplers.noise;
|
||||
|
||||
/**
|
||||
* Sampler3D implementation that returns a constant.
|
||||
*/
|
||||
public class ConstantSampler extends NoiseFunction {
|
||||
private final double constant;
|
||||
|
||||
public ConstantSampler(double constant) {
|
||||
super(0);
|
||||
this.constant = constant;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getNoiseRaw(int seed, double x, double y) {
|
||||
return constant;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getNoiseRaw(int seed, double x, double y, double z) {
|
||||
return constant;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.dfsek.terra.api.math.noise.samplers.noise;
|
||||
|
||||
import com.dfsek.paralithic.Expression;
|
||||
import com.dfsek.paralithic.eval.parser.Parser;
|
||||
import com.dfsek.paralithic.eval.parser.Scope;
|
||||
import com.dfsek.paralithic.eval.tokenizer.ParseException;
|
||||
import com.dfsek.paralithic.functions.Function;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* NoiseSampler implementation using a Paralithic expression.
|
||||
*/
|
||||
public class ExpressionFunction extends NoiseFunction {
|
||||
private final Expression expression;
|
||||
|
||||
public ExpressionFunction(Map<String, Function> functions, String eq, Map<String, Double> vars) throws ParseException {
|
||||
super(0);
|
||||
Parser p = new Parser();
|
||||
Scope scope = new Scope();
|
||||
|
||||
scope.addInvocationVariable("x");
|
||||
scope.addInvocationVariable("y");
|
||||
scope.addInvocationVariable("z");
|
||||
|
||||
vars.forEach(scope::create);
|
||||
|
||||
functions.forEach(p::registerFunction);
|
||||
|
||||
expression = p.parse(eq, scope);
|
||||
frequency = 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getNoiseRaw(int seed, double x, double y) {
|
||||
return expression.evaluate(x, 0, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getNoiseRaw(int seed, double x, double y, double z) {
|
||||
return expression.evaluate(x, y, z);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
package com.dfsek.terra.api.math.noise.samplers.noise;
|
||||
|
||||
import com.dfsek.terra.api.math.noise.samplers.noise.random.WhiteNoiseSampler;
|
||||
import net.jafama.FastMath;
|
||||
|
||||
public class GaborNoiseSampler extends NoiseFunction {
|
||||
private final WhiteNoiseSampler rand;
|
||||
private double k = 1.0;
|
||||
private double a = 0.1;
|
||||
private double f0 = 0.625;
|
||||
private double kernelRadius = (FastMath.sqrt(-FastMath.log(0.05) / Math.PI) / a);
|
||||
private double omega0 = Math.PI * 0.25;
|
||||
private boolean isotropic = true;
|
||||
private double impulsesPerKernel = 64d;
|
||||
private double impulseDensity = (impulsesPerKernel / (Math.PI * kernelRadius * kernelRadius));
|
||||
|
||||
private double impulsesPerCell = impulseDensity * kernelRadius * kernelRadius;
|
||||
private double g = FastMath.exp(-impulsesPerCell);
|
||||
|
||||
|
||||
public GaborNoiseSampler(int seed) {
|
||||
super(seed);
|
||||
rand = new WhiteNoiseSampler(seed);
|
||||
}
|
||||
|
||||
public void setIsotropic(boolean isotropic) {
|
||||
this.isotropic = isotropic;
|
||||
}
|
||||
|
||||
public void setImpulsesPerKernel(double impulsesPerKernel) {
|
||||
this.impulsesPerKernel = impulsesPerKernel;
|
||||
recalculateRadiusAndDensity();
|
||||
}
|
||||
|
||||
public void setA(double a) {
|
||||
this.a = a;
|
||||
recalculateRadiusAndDensity();
|
||||
}
|
||||
|
||||
public void setFrequency0(double f0) {
|
||||
this.f0 = f0;
|
||||
}
|
||||
|
||||
public void setRotation(double omega0) {
|
||||
this.omega0 = Math.PI * omega0;
|
||||
}
|
||||
|
||||
public void setDeviation(double k) {
|
||||
this.k = k;
|
||||
}
|
||||
|
||||
private void recalculateRadiusAndDensity() {
|
||||
kernelRadius = (FastMath.sqrt(-FastMath.log(0.05) / Math.PI) / this.a);
|
||||
impulseDensity = (impulsesPerKernel / (Math.PI * kernelRadius * kernelRadius));
|
||||
impulsesPerCell = impulseDensity * kernelRadius * kernelRadius;
|
||||
g = FastMath.exp(-impulsesPerCell);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getNoiseRaw(int seed, double x, double z) {
|
||||
return gaborNoise(seed, x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getNoiseRaw(int seed, double x, double y, double z) {
|
||||
return gaborNoise(seed, x, z);
|
||||
}
|
||||
|
||||
private double gaborNoise(int seed, double x, double y) {
|
||||
x /= kernelRadius;
|
||||
y /= kernelRadius;
|
||||
int xi = fastFloor(x);
|
||||
int yi = fastFloor(y);
|
||||
double xf = x - xi;
|
||||
double yf = y - yi;
|
||||
double noise = 0;
|
||||
for(int dx = -1; dx <= 1; dx++) {
|
||||
for(int dz = -1; dz <= 1; dz++) {
|
||||
noise += calculateCell(seed, xi + dx, yi + dz, xf - dx, yf - dz);
|
||||
}
|
||||
}
|
||||
return noise;
|
||||
}
|
||||
|
||||
private double calculateCell(int seed, int xi, int yi, double x, double y) {
|
||||
long mashedSeed = murmur64(31L * xi + yi) + seed;
|
||||
|
||||
double gaussianSource = (rand.getNoiseRaw(mashedSeed++) + 1) / 2;
|
||||
int impulses = 0;
|
||||
while(gaussianSource > g) {
|
||||
impulses++;
|
||||
gaussianSource *= (rand.getNoiseRaw(mashedSeed++) + 1) / 2;
|
||||
}
|
||||
|
||||
double noise = 0;
|
||||
for(int i = 0; i < impulses; i++) {
|
||||
noise += rand.getNoiseRaw(mashedSeed++) * gabor(isotropic ? (rand.getNoiseRaw(mashedSeed++) + 1) * Math.PI : omega0, x * kernelRadius, y * kernelRadius);
|
||||
}
|
||||
return noise;
|
||||
}
|
||||
|
||||
private double gabor(double omega_0, double x, double y) {
|
||||
return k * (FastMath.exp(-Math.PI * (a * a) * (x * x + y * y)) * fastCos(2 * Math.PI * f0 * (x * fastCos(omega_0) + y * fastSin(omega_0))));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
package com.dfsek.terra.api.math.noise.samplers.noise;
|
||||
|
||||
import com.dfsek.terra.api.math.noise.NoiseSampler;
|
||||
import net.jafama.FastMath;
|
||||
|
||||
@SuppressWarnings("ManualMinMaxCalculation")
|
||||
public abstract class NoiseFunction implements NoiseSampler {
|
||||
// Hashing
|
||||
protected static final int PRIME_X = 501125321;
|
||||
protected static final int PRIME_Y = 1136930381;
|
||||
protected static final int PRIME_Z = 1720413743;
|
||||
|
||||
|
||||
protected double frequency = 0.02d;
|
||||
protected int seed;
|
||||
|
||||
public NoiseFunction(int seed) {
|
||||
this.seed = seed;
|
||||
}
|
||||
|
||||
protected static int fastFloor(double f) {
|
||||
return f >= 0 ? (int) f : (int) f - 1;
|
||||
}
|
||||
|
||||
static final int precision = 100;
|
||||
|
||||
protected static int hash(int seed, int xPrimed, int yPrimed, int zPrimed) {
|
||||
int hash = seed ^ xPrimed ^ yPrimed ^ zPrimed;
|
||||
|
||||
hash *= 0x27d4eb2d;
|
||||
return hash;
|
||||
}
|
||||
|
||||
protected static int hash(int seed, int xPrimed, int yPrimed) {
|
||||
int hash = seed ^ xPrimed ^ yPrimed;
|
||||
|
||||
hash *= 0x27d4eb2d;
|
||||
return hash;
|
||||
}
|
||||
|
||||
static final int modulus = 360 * precision;
|
||||
|
||||
protected static int fastRound(double f) {
|
||||
return f >= 0 ? (int) (f + 0.5f) : (int) (f - 0.5);
|
||||
}
|
||||
|
||||
protected static double lerp(double a, double b, double t) {
|
||||
return a + t * (b - a);
|
||||
}
|
||||
|
||||
protected static double interpHermite(double t) {
|
||||
return t * t * (3 - 2 * t);
|
||||
}
|
||||
|
||||
protected static double interpQuintic(double t) {
|
||||
return t * t * t * (t * (t * 6 - 15) + 10);
|
||||
}
|
||||
|
||||
protected static double cubicLerp(double a, double b, double c, double d, double t) {
|
||||
double p = (d - c) - (a - b);
|
||||
return t * t * t * p + t * t * ((a - b) - p) + t * (c - a) + b;
|
||||
}
|
||||
|
||||
protected static double fastMin(double a, double b) {
|
||||
return a < b ? a : b;
|
||||
}
|
||||
|
||||
protected static double fastMax(double a, double b) {
|
||||
return a > b ? a : b;
|
||||
}
|
||||
|
||||
protected static double fastAbs(double f) {
|
||||
return f < 0 ? -f : f;
|
||||
}
|
||||
|
||||
protected static double fastSqrt(double f) {
|
||||
return FastMath.sqrt(f);
|
||||
}
|
||||
|
||||
static final double[] sin = new double[360 * 100]; // lookup table
|
||||
|
||||
static {
|
||||
for(int i = 0; i < sin.length; i++) {
|
||||
sin[i] = (float) Math.sin((double) (i) / (precision));
|
||||
}
|
||||
}
|
||||
|
||||
protected static int fastCeil(double f) {
|
||||
int i = (int) f;
|
||||
if(i < f) i++;
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Murmur64 hashing function
|
||||
*
|
||||
* @param h Input value
|
||||
* @return Hashed value
|
||||
*/
|
||||
protected static long murmur64(long h) {
|
||||
h ^= h >>> 33;
|
||||
h *= 0xff51afd7ed558ccdL;
|
||||
h ^= h >>> 33;
|
||||
h *= 0xc4ceb9fe1a85ec53L;
|
||||
h ^= h >>> 33;
|
||||
return h;
|
||||
}
|
||||
|
||||
private static double sinLookup(int a) {
|
||||
return a >= 0 ? sin[a % (modulus)] : -sin[-a % (modulus)];
|
||||
}
|
||||
|
||||
protected static double fastSin(double a) {
|
||||
return sinLookup((int) (a * precision + 0.5f));
|
||||
}
|
||||
|
||||
protected static double fastCos(double a) {
|
||||
return sinLookup((int) ((a + Math.PI / 2) * precision + 0.5f));
|
||||
}
|
||||
|
||||
|
||||
public void setSeed(int seed) {
|
||||
this.seed = seed;
|
||||
}
|
||||
|
||||
public double getFrequency() {
|
||||
return frequency;
|
||||
}
|
||||
|
||||
public void setFrequency(double frequency) {
|
||||
this.frequency = frequency;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getNoise(double x, double y) {
|
||||
return getNoiseSeeded(seed, x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getNoise(double x, double y, double z) {
|
||||
return getNoiseSeeded(seed, x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getNoiseSeeded(int seed, double x, double y) {
|
||||
return getNoiseRaw(seed, x * frequency, y * frequency);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getNoiseSeeded(int seed, double x, double y, double z) {
|
||||
return getNoiseRaw(seed, x * frequency, y * frequency, z * frequency);
|
||||
}
|
||||
|
||||
public abstract double getNoiseRaw(int seed, double x, double y);
|
||||
|
||||
public abstract double getNoiseRaw(int seed, double x, double y, double z);
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.dfsek.terra.api.math.noise.samplers.noise.fractal;
|
||||
|
||||
import com.dfsek.terra.api.math.noise.NoiseSampler;
|
||||
|
||||
public class BrownianMotionSampler extends FractalNoiseFunction {
|
||||
public BrownianMotionSampler(int seed, NoiseSampler input) {
|
||||
super(seed, input);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getNoiseRaw(int seed, double x, double y) {
|
||||
double sum = 0;
|
||||
double amp = fractalBounding;
|
||||
|
||||
for(int i = 0; i < octaves; i++) {
|
||||
double noise = input.getNoiseSeeded(seed++, x, y);
|
||||
sum += noise * amp;
|
||||
amp *= lerp(1.0, fastMin(noise + 1, 2) * 0.5, weightedStrength);
|
||||
|
||||
x *= lacunarity;
|
||||
y *= lacunarity;
|
||||
amp *= gain;
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getNoiseRaw(int seed, double x, double y, double z) {
|
||||
double sum = 0;
|
||||
double amp = fractalBounding;
|
||||
|
||||
for(int i = 0; i < octaves; i++) {
|
||||
double noise = input.getNoiseSeeded(seed++, x, y, z);
|
||||
sum += noise * amp;
|
||||
amp *= lerp(1.0, (noise + 1) * 0.5, weightedStrength);
|
||||
|
||||
x *= lacunarity;
|
||||
y *= lacunarity;
|
||||
z *= lacunarity;
|
||||
amp *= gain;
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.dfsek.terra.api.math.noise.samplers.noise.fractal;
|
||||
|
||||
import com.dfsek.terra.api.math.noise.NoiseSampler;
|
||||
import com.dfsek.terra.api.math.noise.samplers.noise.NoiseFunction;
|
||||
|
||||
public abstract class FractalNoiseFunction extends NoiseFunction {
|
||||
protected final NoiseSampler input;
|
||||
protected double fractalBounding = 1 / 1.75;
|
||||
protected int octaves = 3;
|
||||
protected double gain = 0.5;
|
||||
protected double lacunarity = 2.0d;
|
||||
protected double weightedStrength = 0.0d;
|
||||
|
||||
public FractalNoiseFunction(int seed, NoiseSampler input) {
|
||||
super(seed);
|
||||
this.input = input;
|
||||
frequency = 1;
|
||||
}
|
||||
|
||||
public void setWeightedStrength(double weightedStrength) {
|
||||
this.weightedStrength = weightedStrength;
|
||||
}
|
||||
|
||||
protected void calculateFractalBounding() {
|
||||
double gain = fastAbs(this.gain);
|
||||
double amp = gain;
|
||||
double ampFractal = 1.0;
|
||||
for(int i = 1; i < octaves; i++) {
|
||||
ampFractal += amp;
|
||||
amp *= gain;
|
||||
}
|
||||
fractalBounding = 1 / ampFractal;
|
||||
}
|
||||
|
||||
public void setOctaves(int octaves) {
|
||||
this.octaves = octaves;
|
||||
calculateFractalBounding();
|
||||
}
|
||||
|
||||
public void setGain(double gain) {
|
||||
this.gain = gain;
|
||||
calculateFractalBounding();
|
||||
}
|
||||
|
||||
public void setLacunarity(double lacunarity) {
|
||||
this.lacunarity = lacunarity;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.dfsek.terra.api.math.noise.samplers.noise.fractal;
|
||||
|
||||
import com.dfsek.terra.api.math.noise.NoiseSampler;
|
||||
|
||||
public class PingPongSampler extends FractalNoiseFunction {
|
||||
private double pingPongStrength = 2.0;
|
||||
|
||||
public PingPongSampler(int seed, NoiseSampler input) {
|
||||
super(seed, input);
|
||||
}
|
||||
|
||||
|
||||
private static double pingPong(double t) {
|
||||
t -= (int) (t * 0.5f) << 1;
|
||||
return t < 1 ? t : 2 - t;
|
||||
}
|
||||
|
||||
public void setPingPongStrength(double strength) {
|
||||
this.pingPongStrength = strength;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getNoiseRaw(int seed, double x, double y) {
|
||||
double sum = 0;
|
||||
double amp = fractalBounding;
|
||||
|
||||
for(int i = 0; i < octaves; i++) {
|
||||
double noise = pingPong((input.getNoiseSeeded(seed++, x, y) + 1) * pingPongStrength);
|
||||
sum += (noise - 0.5) * 2 * amp;
|
||||
amp *= lerp(1.0, noise, weightedStrength);
|
||||
|
||||
x *= lacunarity;
|
||||
y *= lacunarity;
|
||||
amp *= gain;
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getNoiseRaw(int seed, double x, double y, double z) {
|
||||
double sum = 0;
|
||||
double amp = fractalBounding;
|
||||
|
||||
for(int i = 0; i < octaves; i++) {
|
||||
double noise = pingPong((input.getNoiseSeeded(seed++, x, y, z) + 1) * pingPongStrength);
|
||||
sum += (noise - 0.5) * 2 * amp;
|
||||
amp *= lerp(1.0, noise, weightedStrength);
|
||||
|
||||
x *= lacunarity;
|
||||
y *= lacunarity;
|
||||
z *= lacunarity;
|
||||
amp *= gain;
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.dfsek.terra.api.math.noise.samplers.noise.fractal;
|
||||
|
||||
import com.dfsek.terra.api.math.noise.NoiseSampler;
|
||||
|
||||
public class RidgedFractalSampler extends FractalNoiseFunction {
|
||||
|
||||
public RidgedFractalSampler(int seed, NoiseSampler input) {
|
||||
super(seed, input);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getNoiseRaw(int seed, double x, double y) {
|
||||
double sum = 0;
|
||||
double amp = fractalBounding;
|
||||
|
||||
for(int i = 0; i < octaves; i++) {
|
||||
double noise = fastAbs(input.getNoiseSeeded(seed++, x, y));
|
||||
sum += (noise * -2 + 1) * amp;
|
||||
amp *= lerp(1.0, 1 - noise, weightedStrength);
|
||||
|
||||
x *= lacunarity;
|
||||
y *= lacunarity;
|
||||
amp *= gain;
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getNoiseRaw(int seed, double x, double y, double z) {
|
||||
double sum = 0;
|
||||
double amp = fractalBounding;
|
||||
|
||||
for(int i = 0; i < octaves; i++) {
|
||||
double noise = fastAbs(input.getNoiseSeeded(seed++, x, y, z));
|
||||
sum += (noise * -2 + 1) * amp;
|
||||
amp *= lerp(1.0, 1 - noise, weightedStrength);
|
||||
|
||||
x *= lacunarity;
|
||||
y *= lacunarity;
|
||||
z *= lacunarity;
|
||||
amp *= gain;
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.dfsek.terra.api.math.noise.samplers.noise.random;
|
||||
|
||||
import com.dfsek.terra.api.math.noise.samplers.noise.NoiseFunction;
|
||||
|
||||
/**
|
||||
* NoiseSampler implementation to provide random, normally distributed (Gaussian) noise.
|
||||
*/
|
||||
public class GaussianNoiseSampler extends NoiseFunction {
|
||||
private final WhiteNoiseSampler whiteNoiseSampler; // Back with a white noise sampler.
|
||||
|
||||
public GaussianNoiseSampler(int seed) {
|
||||
super(seed);
|
||||
whiteNoiseSampler = new WhiteNoiseSampler(seed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getNoiseRaw(int seed, double x, double y) {
|
||||
double v1, v2, s;
|
||||
do {
|
||||
v1 = whiteNoiseSampler.getNoiseSeeded(seed++, x, y);
|
||||
v2 = whiteNoiseSampler.getNoiseSeeded(seed++, x, y);
|
||||
s = v1 * v1 + v2 * v2;
|
||||
} while(s >= 1 || s == 0);
|
||||
double multiplier = StrictMath.sqrt(-2 * StrictMath.log(s) / s);
|
||||
return v1 * multiplier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getNoiseRaw(int seed, double x, double y, double z) {
|
||||
double v1, v2, s;
|
||||
do {
|
||||
v1 = whiteNoiseSampler.getNoiseSeeded(seed++, x, y, z);
|
||||
v2 = whiteNoiseSampler.getNoiseSeeded(seed++, x, y, z);
|
||||
s = v1 * v1 + v2 * v2;
|
||||
} while(s >= 1 || s == 0);
|
||||
double multiplier = StrictMath.sqrt(-2 * StrictMath.log(s) / s);
|
||||
return v1 * multiplier;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.dfsek.terra.api.math.noise.samplers.noise.random;
|
||||
|
||||
import com.dfsek.terra.api.math.noise.samplers.noise.NoiseFunction;
|
||||
|
||||
/**
|
||||
* NoiseSampler implementation to produce random, uniformly distributed (white) noise.
|
||||
*/
|
||||
public class WhiteNoiseSampler extends NoiseFunction {
|
||||
private static final long POSITIVE_POW1 = 0b01111111111L << 52; // Bits that when applied to the exponent/sign section of a double, produce a positive number with a power of 1.
|
||||
|
||||
public WhiteNoiseSampler(int seed) {
|
||||
super(seed);
|
||||
}
|
||||
|
||||
public double getNoiseRaw(long seed) {
|
||||
return (Double.longBitsToDouble((murmur64(seed) & 0x000fffffffffffffL) | POSITIVE_POW1) - 1.5) * 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getNoiseRaw(int seed, double x, double y) {
|
||||
return (getNoiseUnmapped(seed, x, y) - 1.5) * 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getNoiseRaw(int seed, double x, double y, double z) {
|
||||
return (getNoiseUnmapped(seed, x, y, z) - 1.5) * 2;
|
||||
}
|
||||
|
||||
public double getNoiseUnmapped(int seed, double x, double y, double z) {
|
||||
long base = ((randomBits(seed, x, y, z)) & 0x000fffffffffffffL) | POSITIVE_POW1; // Sign and exponent
|
||||
return Double.longBitsToDouble(base);
|
||||
}
|
||||
|
||||
public double getNoiseUnmapped(int seed, double x, double y) {
|
||||
long base = (randomBits(seed, x, y) & 0x000fffffffffffffL) | POSITIVE_POW1; // Sign and exponent
|
||||
return Double.longBitsToDouble(base);
|
||||
}
|
||||
|
||||
public long randomBits(int seed, double x, double y, double z) {
|
||||
long hashX = Double.doubleToRawLongBits(x) ^ seed;
|
||||
long hashZ = Double.doubleToRawLongBits(y) ^ seed;
|
||||
long hash = (((hashX ^ (hashX >>> 32)) + ((hashZ ^ (hashZ >>> 32)) << 32)) ^ seed) + Double.doubleToRawLongBits(z);
|
||||
return murmur64(hash);
|
||||
}
|
||||
|
||||
public long randomBits(int seed, double x, double y) {
|
||||
long hashX = Double.doubleToRawLongBits(x) ^ seed;
|
||||
long hashZ = Double.doubleToRawLongBits(y) ^ seed;
|
||||
long hash = ((hashX ^ (hashX >>> 32)) + ((hashZ ^ (hashZ >>> 32)) << 32)) ^ seed;
|
||||
return murmur64(hash);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,266 @@
|
||||
package com.dfsek.terra.api.math.noise.samplers.noise.simplex;
|
||||
|
||||
/**
|
||||
* NoiseSampler implementation to provide OpenSimplex2 (Smooth Variant) noise.
|
||||
*/
|
||||
public class OpenSimplex2SSampler extends SimplexStyleSampler {
|
||||
public OpenSimplex2SSampler(int seed) {
|
||||
super(seed);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("NumericOverflow")
|
||||
public double getNoiseRaw(int seed, double x, double y) {
|
||||
// 2D OpenSimplex2S case is a modified 2D simplex noise.
|
||||
|
||||
final double SQRT3 = 1.7320508075688772935274463415059;
|
||||
final double G2 = (3 - SQRT3) / 6;
|
||||
|
||||
final double F2 = 0.5f * (SQRT3 - 1);
|
||||
double s = (x + y) * F2;
|
||||
x += s;
|
||||
y += s;
|
||||
|
||||
|
||||
int i = fastFloor(x);
|
||||
int j = fastFloor(y);
|
||||
double xi = x - i;
|
||||
double yi = y - j;
|
||||
|
||||
i *= PRIME_X;
|
||||
j *= PRIME_Y;
|
||||
int i1 = i + PRIME_X;
|
||||
int j1 = j + PRIME_Y;
|
||||
|
||||
double t = (xi + yi) * G2;
|
||||
double x0 = xi - t;
|
||||
double y0 = yi - t;
|
||||
|
||||
double a0 = (2.0 / 3.0) - x0 * x0 - y0 * y0;
|
||||
double value = (a0 * a0) * (a0 * a0) * gradCoord(seed, i, j, x0, y0);
|
||||
|
||||
double a1 = 2 * (1 - 2 * G2) * (1 / G2 - 2) * t + ((-2 * (1 - 2 * G2) * (1 - 2 * G2)) + a0);
|
||||
double x1 = x0 - (1 - 2 * G2);
|
||||
double y1 = y0 - (1 - 2 * G2);
|
||||
value += (a1 * a1) * (a1 * a1) * gradCoord(seed, i1, j1, x1, y1);
|
||||
|
||||
// Nested conditionals were faster than compact bit logic/arithmetic.
|
||||
double xmyi = xi - yi;
|
||||
if(t > G2) {
|
||||
if(xi + xmyi > 1) {
|
||||
double x2 = x0 + (3 * G2 - 2);
|
||||
double y2 = y0 + (3 * G2 - 1);
|
||||
double a2 = (2.0 / 3.0) - x2 * x2 - y2 * y2;
|
||||
if(a2 > 0) {
|
||||
value += (a2 * a2) * (a2 * a2) * gradCoord(seed, i + (PRIME_X << 1), j + PRIME_Y, x2, y2);
|
||||
}
|
||||
} else {
|
||||
double x2 = x0 + G2;
|
||||
double y2 = y0 + (G2 - 1);
|
||||
double a2 = (2.0 / 3.0) - x2 * x2 - y2 * y2;
|
||||
if(a2 > 0) {
|
||||
value += (a2 * a2) * (a2 * a2) * gradCoord(seed, i, j + PRIME_Y, x2, y2);
|
||||
}
|
||||
}
|
||||
|
||||
if(yi - xmyi > 1) {
|
||||
double x3 = x0 + (3 * G2 - 1);
|
||||
double y3 = y0 + (3 * G2 - 2);
|
||||
double a3 = (2.0 / 3.0) - x3 * x3 - y3 * y3;
|
||||
if(a3 > 0) {
|
||||
value += (a3 * a3) * (a3 * a3) * gradCoord(seed, i + PRIME_X, j + (PRIME_Y << 1), x3, y3);
|
||||
}
|
||||
} else {
|
||||
double x3 = x0 + (G2 - 1);
|
||||
double y3 = y0 + G2;
|
||||
double a3 = (2.0 / 3.0) - x3 * x3 - y3 * y3;
|
||||
if(a3 > 0) {
|
||||
value += (a3 * a3) * (a3 * a3) * gradCoord(seed, i + PRIME_X, j, x3, y3);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(xi + xmyi < 0) {
|
||||
double x2 = x0 + (1 - G2);
|
||||
double y2 = y0 - G2;
|
||||
double a2 = (2.0 / 3.0) - x2 * x2 - y2 * y2;
|
||||
if(a2 > 0) {
|
||||
value += (a2 * a2) * (a2 * a2) * gradCoord(seed, i - PRIME_X, j, x2, y2);
|
||||
}
|
||||
} else {
|
||||
double x2 = x0 + (G2 - 1);
|
||||
double y2 = y0 + G2;
|
||||
double a2 = (2.0 / 3.0) - x2 * x2 - y2 * y2;
|
||||
if(a2 > 0) {
|
||||
value += (a2 * a2) * (a2 * a2) * gradCoord(seed, i + PRIME_X, j, x2, y2);
|
||||
}
|
||||
}
|
||||
|
||||
if(yi < xmyi) {
|
||||
double x2 = x0 - G2;
|
||||
double y2 = y0 - (G2 - 1);
|
||||
double a2 = (2.0 / 3.0) - x2 * x2 - y2 * y2;
|
||||
if(a2 > 0) {
|
||||
value += (a2 * a2) * (a2 * a2) * gradCoord(seed, i, j - PRIME_Y, x2, y2);
|
||||
}
|
||||
} else {
|
||||
double x2 = x0 + G2;
|
||||
double y2 = y0 + (G2 - 1);
|
||||
double a2 = (2.0 / 3.0) - x2 * x2 - y2 * y2;
|
||||
if(a2 > 0) {
|
||||
value += (a2 * a2) * (a2 * a2) * gradCoord(seed, i, j + PRIME_Y, x2, y2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return value * 18.24196194486065;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("NumericOverflow")
|
||||
public double getNoiseRaw(int seed, double x, double y, double z) {
|
||||
// 3D OpenSimplex2S case uses two offset rotated cube grids.
|
||||
final double R3 = (2.0 / 3.0);
|
||||
double r = (x + y + z) * R3; // Rotation, not skew
|
||||
x = r - x;
|
||||
y = r - y;
|
||||
z = r - z;
|
||||
|
||||
|
||||
int i = fastFloor(x);
|
||||
int j = fastFloor(y);
|
||||
int k = fastFloor(z);
|
||||
double xi = x - i;
|
||||
double yi = y - j;
|
||||
double zi = z - k;
|
||||
|
||||
i *= PRIME_X;
|
||||
j *= PRIME_Y;
|
||||
k *= PRIME_Z;
|
||||
int seed2 = seed + 1293373;
|
||||
|
||||
int xNMask = (int) (-0.5 - xi);
|
||||
int yNMask = (int) (-0.5 - yi);
|
||||
int zNMask = (int) (-0.5 - zi);
|
||||
|
||||
double x0 = xi + xNMask;
|
||||
double y0 = yi + yNMask;
|
||||
double z0 = zi + zNMask;
|
||||
double a0 = 0.75 - x0 * x0 - y0 * y0 - z0 * z0;
|
||||
double value = (a0 * a0) * (a0 * a0) * gradCoord(seed, i + (xNMask & PRIME_X), j + (yNMask & PRIME_Y), k + (zNMask & PRIME_Z), x0, y0,
|
||||
z0);
|
||||
|
||||
double x1 = xi - 0.5;
|
||||
double y1 = yi - 0.5;
|
||||
double z1 = zi - 0.5;
|
||||
double a1 = 0.75 - x1 * x1 - y1 * y1 - z1 * z1;
|
||||
value += (a1 * a1) * (a1 * a1) * gradCoord(seed2, i + PRIME_X, j + PRIME_Y, k + PRIME_Z, x1, y1, z1);
|
||||
|
||||
double xAFlipMask0 = ((xNMask | 1) << 1) * x1;
|
||||
double yAFlipMask0 = ((yNMask | 1) << 1) * y1;
|
||||
double zAFlipMask0 = ((zNMask | 1) << 1) * z1;
|
||||
double xAFlipMask1 = (-2 - (xNMask << 2)) * x1 - 1.0;
|
||||
double yAFlipMask1 = (-2 - (yNMask << 2)) * y1 - 1.0;
|
||||
double zAFlipMask1 = (-2 - (zNMask << 2)) * z1 - 1.0;
|
||||
|
||||
boolean skip5 = false;
|
||||
double a2 = xAFlipMask0 + a0;
|
||||
if(a2 > 0) {
|
||||
double x2 = x0 - (xNMask | 1);
|
||||
value += (a2 * a2) * (a2 * a2) * gradCoord(seed, i + (~xNMask & PRIME_X), j + (yNMask & PRIME_Y), k + (zNMask & PRIME_Z), x2, y0,
|
||||
z0);
|
||||
} else {
|
||||
double a3 = yAFlipMask0 + zAFlipMask0 + a0;
|
||||
if(a3 > 0) {
|
||||
double y3 = y0 - (yNMask | 1);
|
||||
double z3 = z0 - (zNMask | 1);
|
||||
value += (a3 * a3) * (a3 * a3) * gradCoord(seed, i + (xNMask & PRIME_X), j + (~yNMask & PRIME_Y), k + (~zNMask & PRIME_Z), x0,
|
||||
y3, z3);
|
||||
}
|
||||
|
||||
double a4 = xAFlipMask1 + a1;
|
||||
if(a4 > 0) {
|
||||
double x4 = (xNMask | 1) + x1;
|
||||
value += (a4 * a4) * (a4 * a4) * gradCoord(seed2, i + (xNMask & (PRIME_X << 1)), j + PRIME_Y, k + PRIME_Z, x4, y1, z1);
|
||||
skip5 = true;
|
||||
}
|
||||
}
|
||||
|
||||
boolean skip9 = false;
|
||||
double a6 = yAFlipMask0 + a0;
|
||||
if(a6 > 0) {
|
||||
double y6 = y0 - (yNMask | 1);
|
||||
value += (a6 * a6) * (a6 * a6) * gradCoord(seed, i + (xNMask & PRIME_X), j + (~yNMask & PRIME_Y), k + (zNMask & PRIME_Z), x0, y6,
|
||||
z0);
|
||||
} else {
|
||||
double a7 = xAFlipMask0 + zAFlipMask0 + a0;
|
||||
if(a7 > 0) {
|
||||
double x7 = x0 - (xNMask | 1);
|
||||
double z7 = z0 - (zNMask | 1);
|
||||
value += (a7 * a7) * (a7 * a7) * gradCoord(seed, i + (~xNMask & PRIME_X), j + (yNMask & PRIME_Y), k + (~zNMask & PRIME_Z), x7,
|
||||
y0, z7);
|
||||
}
|
||||
|
||||
double a8 = yAFlipMask1 + a1;
|
||||
if(a8 > 0) {
|
||||
double y8 = (yNMask | 1) + y1;
|
||||
value += (a8 * a8) * (a8 * a8) * gradCoord(seed2, i + PRIME_X, j + (yNMask & (PRIME_Y << 1)), k + PRIME_Z, x1, y8, z1);
|
||||
skip9 = true;
|
||||
}
|
||||
}
|
||||
|
||||
boolean skipD = false;
|
||||
double aA = zAFlipMask0 + a0;
|
||||
if(aA > 0) {
|
||||
double zA = z0 - (zNMask | 1);
|
||||
value += (aA * aA) * (aA * aA) * gradCoord(seed, i + (xNMask & PRIME_X), j + (yNMask & PRIME_Y), k + (~zNMask & PRIME_Z), x0, y0,
|
||||
zA);
|
||||
} else {
|
||||
double aB = xAFlipMask0 + yAFlipMask0 + a0;
|
||||
if(aB > 0) {
|
||||
double xB = x0 - (xNMask | 1);
|
||||
double yB = y0 - (yNMask | 1);
|
||||
value += (aB * aB) * (aB * aB) * gradCoord(seed, i + (~xNMask & PRIME_X), j + (~yNMask & PRIME_Y), k + (zNMask & PRIME_Z), xB,
|
||||
yB, z0);
|
||||
}
|
||||
|
||||
double aC = zAFlipMask1 + a1;
|
||||
if(aC > 0) {
|
||||
double zC = (zNMask | 1) + z1;
|
||||
value += (aC * aC) * (aC * aC) * gradCoord(seed2, i + PRIME_X, j + PRIME_Y, k + (zNMask & (PRIME_Z << 1)), x1, y1, zC);
|
||||
skipD = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(!skip5) {
|
||||
double a5 = yAFlipMask1 + zAFlipMask1 + a1;
|
||||
if(a5 > 0) {
|
||||
double y5 = (yNMask | 1) + y1;
|
||||
double z5 = (zNMask | 1) + z1;
|
||||
value += (a5 * a5) * (a5 * a5) * gradCoord(seed2, i + PRIME_X, j + (yNMask & (PRIME_Y << 1)), k + (zNMask & (PRIME_Z << 1)),
|
||||
x1, y5, z5);
|
||||
}
|
||||
}
|
||||
|
||||
if(!skip9) {
|
||||
double a9 = xAFlipMask1 + zAFlipMask1 + a1;
|
||||
if(a9 > 0) {
|
||||
double x9 = (xNMask | 1) + x1;
|
||||
double z9 = (zNMask | 1) + z1;
|
||||
value += (a9 * a9) * (a9 * a9) * gradCoord(seed2, i + (xNMask & (PRIME_X << 1)), j + PRIME_Y, k + (zNMask & (PRIME_Z << 1)), x9,
|
||||
y1, z9);
|
||||
}
|
||||
}
|
||||
|
||||
if(!skipD) {
|
||||
double aD = xAFlipMask1 + yAFlipMask1 + a1;
|
||||
if(aD > 0) {
|
||||
double xD = (xNMask | 1) + x1;
|
||||
double yD = (yNMask | 1) + y1;
|
||||
value += (aD * aD) * (aD * aD) * gradCoord(seed2, i + (xNMask & (PRIME_X << 1)), j + (yNMask & (PRIME_Y << 1)), k + PRIME_Z,
|
||||
xD, yD, z1);
|
||||
}
|
||||
}
|
||||
|
||||
return value * 9.046026385208288;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user