mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2025-12-19 23:19:21 +00:00
Compare commits
987 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d9c7f35709 | ||
|
|
37893460f3 | ||
|
|
898f815878 | ||
|
|
49ee36b089 | ||
|
|
073be82dcc | ||
|
|
713c3a4762 | ||
|
|
b736377aec | ||
|
|
62fff7a56e | ||
|
|
5efb71eb3e | ||
|
|
d22f49492f | ||
|
|
b65b112220 | ||
|
|
c5456aa65c | ||
|
|
0a256eaa4c | ||
|
|
7d07ee4eb2 | ||
|
|
c98ed48ee2 | ||
|
|
9f392654d3 | ||
|
|
e21fdf46e0 | ||
|
|
a2ff5f58ed | ||
|
|
b0eedee519 | ||
|
|
e101155a4c | ||
|
|
3c9bcc9bb0 | ||
|
|
6763844030 | ||
|
|
08fa436885 | ||
|
|
df8fa79209 | ||
|
|
8041db4f40 | ||
|
|
18e57e4097 | ||
|
|
cc584ba377 | ||
|
|
0c92c20c65 | ||
|
|
613575c0c5 | ||
|
|
b414b01ac4 | ||
|
|
65dd039b07 | ||
|
|
747adb53d9 | ||
|
|
7125b38fd5 | ||
|
|
ec8af56f0d | ||
|
|
79341bf562 | ||
|
|
3f24d5c8e1 | ||
|
|
66a1739666 | ||
|
|
29007fdbfa | ||
|
|
be3e8ebd51 | ||
|
|
38ad345f85 | ||
|
|
82f71198e6 | ||
|
|
b1e87afc93 | ||
|
|
3bffe4cc7e | ||
|
|
08ab82216d | ||
|
|
c3ed7080dc | ||
|
|
ea8fb1bf86 | ||
|
|
4434cf6475 | ||
|
|
26aae2b730 | ||
|
|
e5c818cf7b | ||
|
|
6b4575e75d | ||
|
|
773be08b24 | ||
|
|
386131ddf0 | ||
|
|
3dfdb9654a | ||
|
|
805523d069 | ||
|
|
6cfa593eee | ||
|
|
414f46a08d | ||
|
|
00c2a5245a | ||
|
|
f6791b786e | ||
|
|
0fa9654824 | ||
|
|
2262e19cd1 | ||
|
|
055ddc7c9b | ||
|
|
817d7a602b | ||
|
|
3af4a8f621 | ||
|
|
7b80eb1c06 | ||
|
|
19c6f4f2ba | ||
|
|
8a753b42f8 | ||
|
|
9144606688 | ||
|
|
3f66634e5f | ||
|
|
c86815f47b | ||
|
|
f9d108dbb7 | ||
|
|
302e02ddac | ||
|
|
effb0f5b91 | ||
|
|
f32f8744b2 | ||
|
|
dd98f6f07e | ||
|
|
bb7bbb6379 | ||
|
|
bbf42d1af0 | ||
|
|
70aa607e5b | ||
|
|
09635e12a9 | ||
|
|
7b283a56ee | ||
|
|
888ba34eee | ||
|
|
dafca8e9db | ||
|
|
41b7aec084 | ||
|
|
dfe1cce6de | ||
|
|
62e98cc371 | ||
|
|
8fc70f42fc | ||
|
|
fc793592f7 | ||
|
|
13447b882c | ||
|
|
c3ac41f894 | ||
|
|
d0688782b1 | ||
|
|
25b41fe62c | ||
|
|
b468478fcb | ||
|
|
b6dc934198 | ||
|
|
344c50154a | ||
|
|
f58078e8a0 | ||
|
|
b6457e47e6 | ||
|
|
d275466e1e | ||
|
|
f9cb107728 | ||
|
|
ef93bee0b9 | ||
|
|
68ad206252 | ||
|
|
288bead792 | ||
|
|
de670ddfd5 | ||
|
|
9de0c5b96f | ||
|
|
a0a7b8cb3e | ||
|
|
ae2600227e | ||
|
|
ec1187923b | ||
|
|
ab04a686e9 | ||
|
|
efbfad437a | ||
|
|
9bcb1845b8 | ||
|
|
0f5364982d | ||
|
|
1b0411e23a | ||
|
|
29199dc2d2 | ||
|
|
3cb5f612c6 | ||
|
|
3b98b20f73 | ||
|
|
90bab2b292 | ||
|
|
8ad3cdf820 | ||
|
|
ca8933541a | ||
|
|
8572a444fa | ||
|
|
8dd14c80f0 | ||
|
|
61410aea97 | ||
|
|
79d6f34879 | ||
|
|
f892eb599c | ||
|
|
86f89bc718 | ||
|
|
ceb6c15c97 | ||
|
|
5be19c7c3c | ||
|
|
7cf43ad7ab | ||
|
|
9d8be5b382 | ||
|
|
ab30710e2a | ||
|
|
d2ecbc5727 | ||
|
|
22f9306fa3 | ||
|
|
ab3397a373 | ||
|
|
6b4a19a525 | ||
|
|
ad8ff2643b | ||
|
|
e6f829db31 | ||
|
|
8e9f78e982 | ||
|
|
b429448885 | ||
|
|
f00e037e26 | ||
|
|
bad3cd27e1 | ||
|
|
cad679a808 | ||
|
|
61bbfee640 | ||
|
|
488b76d1d2 | ||
|
|
1e22a65329 | ||
|
|
1477dc037c | ||
|
|
6174ec04ab | ||
|
|
1cac86252f | ||
|
|
773065eb56 | ||
|
|
a8524e43b9 | ||
|
|
cf4796bd12 | ||
|
|
bd89d8a308 | ||
|
|
df2186d70f | ||
|
|
0a62e222ee | ||
|
|
ec9a000bcf | ||
|
|
f9638e830f | ||
|
|
0445b6fe6e | ||
|
|
a0719117ad | ||
|
|
7ae846af6f | ||
|
|
fe5bb67973 | ||
|
|
482fa9b11e | ||
|
|
295fe16f8f | ||
|
|
c2ab688590 | ||
|
|
cd55a7fed4 | ||
|
|
fc890a5ba1 | ||
|
|
2ea54b7f2f | ||
|
|
e90e3901f5 | ||
|
|
36d58f29ab | ||
|
|
864c7ae27c | ||
|
|
6d104a2d1c | ||
|
|
89e754245d | ||
|
|
4c68d99c6f | ||
|
|
f8f0a65f0a | ||
|
|
6ff74639b5 | ||
|
|
13c61501e6 | ||
|
|
5ad848fc54 | ||
|
|
af80f882da | ||
|
|
84ce7372c3 | ||
|
|
e31d39c5f7 | ||
|
|
2296c1368b | ||
|
|
f6cf0682ed | ||
|
|
21d7d96dbc | ||
|
|
956e511fe0 | ||
|
|
e427887f8c | ||
|
|
88ea43fbbe | ||
|
|
29526a80a9 | ||
|
|
48f901fc8c | ||
|
|
6c3f3dc889 | ||
|
|
743410d3ee | ||
|
|
acccbb028f | ||
|
|
8b31fdc780 | ||
|
|
55017b9ac2 | ||
|
|
0288d35c85 | ||
|
|
8b3577dd0b | ||
|
|
ced77ec70d | ||
|
|
e1e90f5c8a | ||
|
|
3cb74ac922 | ||
|
|
dc3487583d | ||
|
|
e1d73ebcd5 | ||
|
|
dae3de8982 | ||
|
|
d7cf3b9500 | ||
|
|
8ce4e3c6b2 | ||
|
|
76f7d46b22 | ||
|
|
cfc52ed909 | ||
|
|
cee94d40e1 | ||
|
|
cad7166cbe | ||
|
|
c05fdbd0ec | ||
|
|
c9b26ebaff | ||
|
|
bee1973390 | ||
|
|
57efcab0b5 | ||
|
|
b1ab2b84f8 | ||
|
|
02601e5ee4 | ||
|
|
070479acf3 | ||
|
|
6b2ba74237 | ||
|
|
619de29710 | ||
|
|
12556fa98f | ||
|
|
bef4c0497f | ||
|
|
9193497d36 | ||
|
|
ca6affbde9 | ||
|
|
81c40ce228 | ||
|
|
6ba1d571f2 | ||
|
|
b0663f9b6c | ||
|
|
3ced6f3e9e | ||
|
|
3146d61efe | ||
|
|
a967b6af85 | ||
|
|
db3bc74364 | ||
|
|
eb19d9a846 | ||
|
|
96dd299de7 | ||
|
|
aee0806aa8 | ||
|
|
e39f13bbb4 | ||
|
|
52ec80d384 | ||
|
|
d9f8909bdc | ||
|
|
65aa9dc343 | ||
|
|
9bf7fdf174 | ||
|
|
dafb59e5a8 | ||
|
|
79f86ca87d | ||
|
|
1749fcf6b5 | ||
|
|
e1a0481cdf | ||
|
|
4576b95814 | ||
|
|
e113fa6a61 | ||
|
|
07228afbff | ||
|
|
afdffc2453 | ||
|
|
6348442962 | ||
|
|
fd10c005b0 | ||
|
|
44500d6af9 | ||
|
|
6ddb0b5304 | ||
|
|
8ce0976f88 | ||
|
|
8345a58f2b | ||
|
|
f92234297e | ||
|
|
6a5bcd5990 | ||
|
|
1fe6d9a636 | ||
|
|
97f6ab66c3 | ||
|
|
b78c182d94 | ||
|
|
09a0f83013 | ||
|
|
f68d7420e3 | ||
|
|
55c0fa5f32 | ||
|
|
8b5d1d0298 | ||
|
|
b70e94dc65 | ||
|
|
49a6552168 | ||
|
|
0dd6892b28 | ||
|
|
fec587edad | ||
|
|
712937d661 | ||
|
|
ace434e7b0 | ||
|
|
1e5aa6e8b0 | ||
|
|
441b27f8f4 | ||
|
|
3f3bf70212 | ||
|
|
a12eddbedf | ||
|
|
12abc1709e | ||
|
|
9e6035e7b4 | ||
|
|
20b41d65d3 | ||
|
|
1593bb2088 | ||
|
|
d4f9a20379 | ||
|
|
6e247597a4 | ||
|
|
8a8be4545c | ||
|
|
05f4955989 | ||
|
|
93469fb3b4 | ||
|
|
a70258d69f | ||
|
|
c653d852e4 | ||
|
|
40163d25b8 | ||
|
|
5b4265783e | ||
|
|
720417b6c8 | ||
|
|
bb78f412e0 | ||
|
|
a919b91efb | ||
|
|
a3dcf031c9 | ||
|
|
56eb4b6b84 | ||
|
|
393cb362db | ||
|
|
64e422036c | ||
|
|
468e7ef018 | ||
|
|
e3e4ecbc5c | ||
|
|
545ffc0e9d | ||
|
|
8125c8d5f4 | ||
|
|
304b01d0cf | ||
|
|
a5f687fd76 | ||
|
|
fc1761a55b | ||
|
|
e7c9cad7f6 | ||
|
|
979af82122 | ||
|
|
71a62b9c73 | ||
|
|
bb020cab25 | ||
|
|
1ad35c1310 | ||
|
|
6470b2f4a9 | ||
|
|
c1d5ba55cd | ||
|
|
100e450514 | ||
|
|
0f1d1d9860 | ||
|
|
178a462a4e | ||
|
|
8f4ae613f0 | ||
|
|
9e6963b6ce | ||
|
|
cb9a73c60e | ||
|
|
0e666a4c35 | ||
|
|
c80138a354 | ||
|
|
79a4ebcf65 | ||
|
|
a7118aa785 | ||
|
|
2555cd23a0 | ||
|
|
484fbeca7b | ||
|
|
9a45e0df10 | ||
|
|
9175296fc6 | ||
|
|
5a4a86aeba | ||
|
|
768fa7beb5 | ||
|
|
6645eb9806 | ||
|
|
d7a283c99f | ||
|
|
8f019cd794 | ||
|
|
c1d9cc62cb | ||
|
|
010a1e9e91 | ||
|
|
856c926cde | ||
|
|
72ed312654 | ||
|
|
c7fe4723f7 | ||
|
|
bfbea83a4a | ||
|
|
55c58fe896 | ||
|
|
72949e0950 | ||
|
|
61c0ddb15b | ||
|
|
9ac4024e4e | ||
|
|
7fb2a51a33 | ||
|
|
5b7c0b2bc3 | ||
|
|
fc15175ff9 | ||
|
|
1eec3a09c1 | ||
|
|
60d349dd8b | ||
|
|
0c8d144ffb | ||
|
|
b898f73a05 | ||
|
|
c2b9b0ba0e | ||
|
|
206a4e9057 | ||
|
|
83a0a7dd54 | ||
|
|
63b8a935ae | ||
|
|
16affd11cc | ||
|
|
33b0dec9da | ||
|
|
121a463788 | ||
|
|
3625e70948 | ||
|
|
3d90207172 | ||
|
|
ca7dc19c81 | ||
|
|
d0f16dbbc4 | ||
|
|
fd91c223b7 | ||
|
|
93690b766c | ||
|
|
cc4af9950b | ||
|
|
a6281483dd | ||
|
|
f587816b30 | ||
|
|
eea3c3ab0b | ||
|
|
ba68ab9e06 | ||
|
|
eb94d97ea4 | ||
|
|
04ad02719c | ||
|
|
f68f25b92f | ||
|
|
767cca36c8 | ||
|
|
b30172fe89 | ||
|
|
b2934b0cc2 | ||
|
|
50686795d0 | ||
|
|
5561a4dc2f | ||
|
|
15b8780e17 | ||
|
|
15c4d312cb | ||
|
|
ccbea89253 | ||
|
|
7b1e666b3b | ||
|
|
8af212fca8 | ||
|
|
352ee7a622 | ||
|
|
f26d0fac0b | ||
|
|
9612fef2a4 | ||
|
|
a691d49abc | ||
|
|
289eca35ec | ||
|
|
e9ca30257c | ||
|
|
6b21997baa | ||
|
|
6d3dbf84ef | ||
|
|
eb45339c81 | ||
|
|
65e3fdd26c | ||
|
|
34cad85942 | ||
|
|
e407679d2b | ||
|
|
8a08a3e148 | ||
|
|
a01d27d273 | ||
|
|
43f642ae8b | ||
|
|
93c1265de9 | ||
|
|
d08600fbaa | ||
|
|
fb9f8d28f4 | ||
|
|
cd3e9f772d | ||
|
|
7a95441799 | ||
|
|
9345828c97 | ||
|
|
58d88dd079 | ||
|
|
6cbc2374b3 | ||
|
|
12bd11386d | ||
|
|
0497045388 | ||
|
|
d3f1640855 | ||
|
|
960e2fcc61 | ||
|
|
6a012cf400 | ||
|
|
d658ec2099 | ||
|
|
c9a07bd9d7 | ||
|
|
c0136585e6 | ||
|
|
dc4cfc49ad | ||
|
|
9fc72868d7 | ||
|
|
7d4c9d6c1e | ||
|
|
e68b1a52ee | ||
|
|
955e8622b5 | ||
|
|
82640de06b | ||
|
|
c93cb19563 | ||
|
|
ccb7855d7d | ||
|
|
bad547356c | ||
|
|
1740bb0021 | ||
|
|
20f05bf317 | ||
|
|
669ede5482 | ||
|
|
ab658f58f9 | ||
|
|
1b3916749a | ||
|
|
e29ec657d3 | ||
|
|
04f3a226a1 | ||
|
|
099d1cc362 | ||
|
|
c11e9bf704 | ||
|
|
ffa0b984a0 | ||
|
|
f0f9261ed3 | ||
|
|
ba433bc244 | ||
|
|
27f8ad982a | ||
|
|
9b89ae7846 | ||
|
|
c11b5342e3 | ||
|
|
b9c88f5b12 | ||
|
|
02c7ab71d4 | ||
|
|
8ec1ac9875 | ||
|
|
e03027a386 | ||
|
|
387cf566c9 | ||
|
|
dff7665934 | ||
|
|
9421d788f3 | ||
|
|
d960574b24 | ||
|
|
e8671cbbf0 | ||
|
|
cbf8039eea | ||
|
|
d7415e3711 | ||
|
|
26e71ee6b5 | ||
|
|
f8c42b3e48 | ||
|
|
886bed9634 | ||
|
|
7b7023fc99 | ||
|
|
701bfe4a54 | ||
|
|
290d7a93ab | ||
|
|
729bcc7ba0 | ||
|
|
e46b68e2f3 | ||
|
|
cdf73c4629 | ||
|
|
2f0dd2d172 | ||
|
|
7e5704bf80 | ||
|
|
ef96fb9a0e | ||
|
|
f2370ad814 | ||
|
|
0783620104 | ||
|
|
2193b02c0a | ||
|
|
aef05bad20 | ||
|
|
e002ab6378 | ||
|
|
a2c2b4a2d4 | ||
|
|
3ae896457b | ||
|
|
683a90ed09 | ||
|
|
5685e25234 | ||
|
|
6edf083e7b | ||
|
|
995d1495eb | ||
|
|
d5f74631cd | ||
|
|
dd5b9b2e81 | ||
|
|
ca78200c1c | ||
|
|
d73c2a65ae | ||
|
|
0ee2cb8e3c | ||
|
|
5ba429ec73 | ||
|
|
709825d073 | ||
|
|
3fe73af5e8 | ||
|
|
ccc0b0dd7d | ||
|
|
1114ede267 | ||
|
|
5546f12499 | ||
|
|
4f38acb592 | ||
|
|
39f59e023c | ||
|
|
5ed5322fce | ||
|
|
33b926d547 | ||
|
|
af8778c6cd | ||
|
|
bb4ad08cc5 | ||
|
|
ee4eb7b3f0 | ||
|
|
5bc024a6ee | ||
|
|
0546caeb05 | ||
|
|
a75348d3ee | ||
|
|
3f3f947f43 | ||
|
|
5127b7c959 | ||
|
|
a28df78792 | ||
|
|
4f888f16bc | ||
|
|
55ed9d7132 | ||
|
|
779a56c3a1 | ||
|
|
f6440bde07 | ||
|
|
930dc2fd1c | ||
|
|
1e96fd529b | ||
|
|
167c865bb2 | ||
|
|
4e6b6c11a3 | ||
|
|
bfdb71ca91 | ||
|
|
f590f9824e | ||
|
|
b3a087702d | ||
|
|
1a786fb418 | ||
|
|
650d38e212 | ||
|
|
130cb7ad93 | ||
|
|
85e8ffeaa3 | ||
|
|
db40f608fa | ||
|
|
a7b471682a | ||
|
|
4595fea7d7 | ||
|
|
4580f8d9a4 | ||
|
|
37f76fa133 | ||
|
|
5507c35547 | ||
|
|
350328f99c | ||
|
|
91ec6b773d | ||
|
|
c0fdf23133 | ||
|
|
28523a9593 | ||
|
|
07e0b52ea3 | ||
|
|
008e758da8 | ||
|
|
7ce219a6a8 | ||
|
|
1809d4a53f | ||
|
|
54ae026c2b | ||
|
|
57c647fa0e | ||
|
|
9745f23fb2 | ||
|
|
7d2062f298 | ||
|
|
306a1948cf | ||
|
|
ac4c00d3f2 | ||
|
|
db43bc300e | ||
|
|
6494cded62 | ||
|
|
b5c1e7e2da | ||
|
|
83e311870f | ||
|
|
8fc6e3b335 | ||
|
|
18a69e97b3 | ||
|
|
80d8449f02 | ||
|
|
d830aa1d1a | ||
|
|
d473126d4c | ||
|
|
17f8fe69fb | ||
|
|
7263d102c7 | ||
|
|
815b2235a2 | ||
|
|
f61247f8bb | ||
|
|
205d9d528e | ||
|
|
1044f901bd | ||
|
|
de261a38fd | ||
|
|
81776e60fb | ||
|
|
0c179eae86 | ||
|
|
c30de98449 | ||
|
|
47990cde46 | ||
|
|
b098c210ce | ||
|
|
6edd8bf119 | ||
|
|
de0e124ebb | ||
|
|
5fc012a557 | ||
|
|
32afcc3478 | ||
|
|
a27f37945d | ||
|
|
0adfe6911f | ||
|
|
8bb1964b30 | ||
|
|
cc95e1ae63 | ||
|
|
9843f18c96 | ||
|
|
18ea61fcc0 | ||
|
|
5b3fdb6e62 | ||
|
|
c5220c8d06 | ||
|
|
74e87a7fae | ||
|
|
c809f50c3b | ||
|
|
e7e46f78c7 | ||
|
|
2b449a1f3d | ||
|
|
f257f2c551 | ||
|
|
7f91d73d27 | ||
|
|
15a90edb03 | ||
|
|
b2f1e16d9a | ||
|
|
f544455708 | ||
|
|
5118997188 | ||
|
|
b6ae649cd1 | ||
|
|
a6d0d85b84 | ||
|
|
c71c2494af | ||
|
|
4a3a7bc98d | ||
|
|
4e4f7f693d | ||
|
|
7a729c39a6 | ||
|
|
48b757f693 | ||
|
|
b449938730 | ||
|
|
ba55ff6a4b | ||
|
|
2b4bc621ac | ||
|
|
acac2d0fc5 | ||
|
|
6ff5975918 | ||
|
|
8912cfe37b | ||
|
|
9e02c318a1 | ||
|
|
f6b51c21d5 | ||
|
|
df3e4b055f | ||
|
|
ffcd2b4179 | ||
|
|
7afdbc2a53 | ||
|
|
5004481685 | ||
|
|
1905741a7c | ||
|
|
8bf7451107 | ||
|
|
fdfb708ce0 | ||
|
|
68a4eee8bb | ||
|
|
746ebfffbd | ||
|
|
213f8645bc | ||
|
|
1b2541bd84 | ||
|
|
522de89792 | ||
|
|
5feaa45edf | ||
|
|
9333775e0e | ||
|
|
afd15ad450 | ||
|
|
e7fc9e6fe5 | ||
|
|
021f9b1d0e | ||
|
|
dc21f05482 | ||
|
|
c22ccf71a7 | ||
|
|
d5b9a074e6 | ||
|
|
63e6104736 | ||
|
|
de475c9561 | ||
|
|
3f4fa0c67c | ||
|
|
ca3f228b89 | ||
|
|
2b159041ac | ||
|
|
5fa564969e | ||
|
|
8ba8627281 | ||
|
|
a12cb59a51 | ||
|
|
dd124fab33 | ||
|
|
9f8ef4c1f3 | ||
|
|
563c6d0403 | ||
|
|
1bad0fe048 | ||
|
|
b40dcd3164 | ||
|
|
8a0b443d28 | ||
|
|
5f38503ac5 | ||
|
|
231d1209c9 | ||
|
|
06bc180127 | ||
|
|
fb2221fa8d | ||
|
|
e1c7f38bb8 | ||
|
|
a82fa578eb | ||
|
|
0ecefdcc1c | ||
|
|
8bacc8128b | ||
|
|
3dff96152c | ||
|
|
79e198d441 | ||
|
|
e6cf33e262 | ||
|
|
f839ca674b | ||
|
|
f9427d1258 | ||
|
|
bd2cdc9bd0 | ||
|
|
67352311de | ||
|
|
555a7682e1 | ||
|
|
19d94489d7 | ||
|
|
0175cfa986 | ||
|
|
1b0ff36d51 | ||
|
|
f5c499ab60 | ||
|
|
81e3fd346a | ||
|
|
3bca1f5304 | ||
|
|
593e96a31a | ||
|
|
169b783e4f | ||
|
|
f129742a41 | ||
|
|
01016d1b14 | ||
|
|
a883e43acb | ||
|
|
e0d0657e7b | ||
|
|
e4c27bd49c | ||
|
|
7a31fd31eb | ||
|
|
4f0f2c3213 | ||
|
|
d9889b06ad | ||
|
|
9f5cff4ab8 | ||
|
|
958543a171 | ||
|
|
b8e03f5e13 | ||
|
|
e76218b39f | ||
|
|
7d1a375bda | ||
|
|
dfaa80f1e4 | ||
|
|
8939a903be | ||
|
|
d6f1ea78fa | ||
|
|
f25c4c74be | ||
|
|
1619df1ba3 | ||
|
|
566169cdbf | ||
|
|
ee3e631789 | ||
|
|
8202754988 | ||
|
|
447d7596dc | ||
|
|
7c4568066f | ||
|
|
46ee7a5983 | ||
|
|
5a8ef99afa | ||
|
|
571729cfe4 | ||
|
|
c1de316ed6 | ||
|
|
1e316acd64 | ||
|
|
f89460538d | ||
|
|
0bf0062c2c | ||
|
|
540d1b5801 | ||
|
|
8f0d1b7b7b | ||
|
|
5061791dcf | ||
|
|
ce98264552 | ||
|
|
15e6750e11 | ||
|
|
7a20421580 | ||
|
|
f42f06226c | ||
|
|
cce3d74c52 | ||
|
|
7b9fb880f4 | ||
|
|
2a9b0a54d9 | ||
|
|
373e9e9755 | ||
|
|
4115dd5797 | ||
|
|
57bfd251dc | ||
|
|
d324790f66 | ||
|
|
99d3dba440 | ||
|
|
5a44e79ad1 | ||
|
|
86808017db | ||
|
|
f735db9843 | ||
|
|
5a333c23ac | ||
|
|
4d2d51edfa | ||
|
|
dcfd5a0cd8 | ||
|
|
a821c0da50 | ||
|
|
804147e2c4 | ||
|
|
ed346291f9 | ||
|
|
2190f6eff8 | ||
|
|
ce30e24e42 | ||
|
|
d5e13541c8 | ||
|
|
2e707adaa0 | ||
|
|
4d8e36cb05 | ||
|
|
73b710cdde | ||
|
|
09182bf3f3 | ||
|
|
9a945837cd | ||
|
|
b64c821ef4 | ||
|
|
a9ab3bc519 | ||
|
|
94292cea6e | ||
|
|
b5fdeb2a02 | ||
|
|
fa3ac36e8c | ||
|
|
6632d1b65f | ||
|
|
8805693800 | ||
|
|
93db7ee0ee | ||
|
|
9ba4dd4099 | ||
|
|
36efacf43c | ||
|
|
d9bf91afa5 | ||
|
|
b0c96be841 | ||
|
|
673b08f174 | ||
|
|
989778af26 | ||
|
|
f5a3a7eb1a | ||
|
|
7a97928c21 | ||
|
|
12a6d022cf | ||
|
|
e3d2dfa99e | ||
|
|
35cc39e9e2 | ||
|
|
006b0b4a03 | ||
|
|
ec939b9f78 | ||
|
|
7a94f53735 | ||
|
|
a9efe146ba | ||
|
|
956e2f6b06 | ||
|
|
72623e0acf | ||
|
|
e0f673bc3c | ||
|
|
fe40f12d2e | ||
|
|
0fda7a8506 | ||
|
|
22887da769 | ||
|
|
a1e0a8ffc1 | ||
|
|
62010116d7 | ||
|
|
6ebcd02ae6 | ||
|
|
051015656a | ||
|
|
ee082762c6 | ||
|
|
e967b5e052 | ||
|
|
36505e2fa1 | ||
|
|
502aa054f6 | ||
|
|
cc5a880fd7 | ||
|
|
6f9ad8b0eb | ||
|
|
ac6ab74d48 | ||
|
|
807ed2b247 | ||
|
|
367de5a8fd | ||
|
|
5bf2da714a | ||
|
|
cc90f42deb | ||
|
|
20ceaead09 | ||
|
|
3ec2f8fb7b | ||
|
|
6c5fac154e | ||
|
|
540ab8f0d2 | ||
|
|
17d2ac8d70 | ||
|
|
a6ebdead19 | ||
|
|
aa7631ecd0 | ||
|
|
4e138cad9f | ||
|
|
7e55b5fcee | ||
|
|
e19e5278b4 | ||
|
|
dfcd2dc83e | ||
|
|
8775f842e6 | ||
|
|
7b07a4ba6c | ||
|
|
d78e5973e9 | ||
|
|
110d296184 | ||
|
|
23cd5c117b | ||
|
|
131c4692bc | ||
|
|
f6571367db | ||
|
|
f5c64c7480 | ||
|
|
085f63a915 | ||
|
|
3e022e1931 | ||
|
|
0dba3725ae | ||
|
|
8bb409df4e | ||
|
|
603168a147 | ||
|
|
2a95edd860 | ||
|
|
e94406fb45 | ||
|
|
e5a7b5d0c6 | ||
|
|
d6f816fe2f | ||
|
|
c15d4a349f | ||
|
|
3ce832583c | ||
|
|
5514fd2645 | ||
|
|
66d07dcaca | ||
|
|
c1cf8e88ee | ||
|
|
684bd739b9 | ||
|
|
d4c0e07b1d | ||
|
|
a6ea6fcfb2 | ||
|
|
c366ec0c40 | ||
|
|
8d715e2e4e | ||
|
|
dea3ec80ac | ||
|
|
4053f05ba9 | ||
|
|
ef07ec2c62 | ||
|
|
0ffc64231b | ||
|
|
fe112c3ba5 | ||
|
|
2fa03aac3b | ||
|
|
6ac5ad880d | ||
|
|
54f14392d9 | ||
|
|
c7ecdaf8a8 | ||
|
|
497c24a3b6 | ||
|
|
00aa26e602 | ||
|
|
3796381156 | ||
|
|
b0c5700cf5 | ||
|
|
78a4b1d2ce | ||
|
|
e5e6b9848f | ||
|
|
3e36f57f14 | ||
|
|
d794ede4d8 | ||
|
|
7a4d97d76a | ||
|
|
e76ab1d367 | ||
|
|
9731feff7f | ||
|
|
4ce790082d | ||
|
|
065b748036 | ||
|
|
76891d246f | ||
|
|
0832007991 | ||
|
|
87302a046c | ||
|
|
f0f7453b32 | ||
|
|
2991bea248 | ||
|
|
673b42c2f5 | ||
|
|
7d994e27e3 | ||
|
|
5f2b82aac7 | ||
|
|
af1a03cb67 | ||
|
|
85fbbeca9d | ||
|
|
a64272620f | ||
|
|
ef9966d02b | ||
|
|
a28e5bb38a | ||
|
|
34670759e9 | ||
|
|
7dd1d3881a | ||
|
|
7b93542014 | ||
|
|
ea1ac0a154 | ||
|
|
35c7068fa6 | ||
|
|
db4cbb2ea6 | ||
|
|
fa7c073999 | ||
|
|
72a077662d | ||
|
|
137abb04b2 | ||
|
|
211b15332d | ||
|
|
f6fbcade17 | ||
|
|
1ef115fee8 | ||
|
|
7973444fc5 | ||
|
|
2bdb0bfa69 | ||
|
|
bfb6f82ea3 | ||
|
|
7729ce3753 | ||
|
|
f6ea171669 | ||
|
|
ff081ebc11 | ||
|
|
0818f971fe | ||
|
|
27070f44c7 | ||
|
|
8331cbe375 | ||
|
|
f533ec34b0 | ||
|
|
23d4fcb827 | ||
|
|
a248962f1b | ||
|
|
afa8fad8e9 | ||
|
|
4c423bb493 | ||
|
|
e660fe9e1e | ||
|
|
23c1d12e73 | ||
|
|
9cf2785626 | ||
|
|
b8b65c7e3e | ||
|
|
dcb467280a | ||
|
|
6aa802b42d | ||
|
|
d78f6ca589 | ||
|
|
493f8e0cc0 | ||
|
|
119563c553 | ||
|
|
2d61e6af66 | ||
|
|
aa1be934a9 | ||
|
|
f9c98b0a60 | ||
|
|
bd66fa3bf5 | ||
|
|
380f191f6a | ||
|
|
7e217b5fba | ||
|
|
c4a516a858 | ||
|
|
bdf181e348 | ||
|
|
f4ea1343b4 | ||
|
|
a37ccddd38 | ||
|
|
243ef8c0be | ||
|
|
00d099383b | ||
|
|
dda3f0b8e9 | ||
|
|
00f4d8b1ee | ||
|
|
2f5198d533 | ||
|
|
148261f876 | ||
|
|
60843b3bb9 | ||
|
|
2ad9a525bd | ||
|
|
78e9f21439 | ||
|
|
a66d60eaea | ||
|
|
3aa3c13477 | ||
|
|
cc850522e6 | ||
|
|
6d28f57f88 | ||
|
|
563e0a7cd4 | ||
|
|
2f2f857e98 | ||
|
|
251c52a2ee | ||
|
|
7528bd343b | ||
|
|
06d9f279ac | ||
|
|
044403b829 | ||
|
|
5a24dd3b49 | ||
|
|
3189b3c7a5 | ||
|
|
3bf1c6a282 | ||
|
|
7c7309c3ab | ||
|
|
da777da476 | ||
|
|
3d0c0a11ed | ||
|
|
e545269b93 | ||
|
|
141ca76647 | ||
|
|
94557830f5 | ||
|
|
49acb7faba | ||
|
|
1904f67662 | ||
|
|
5b2bf38344 | ||
|
|
494c38a153 | ||
|
|
dd4b85cbfe | ||
|
|
8f7b54a5a4 | ||
|
|
cec502340e | ||
|
|
64e27c7fb0 | ||
|
|
b2bbd31548 | ||
|
|
17df92a07c | ||
|
|
2b749b5ab7 | ||
|
|
28e3402d88 | ||
|
|
d96bb061e0 | ||
|
|
e6def804f8 | ||
|
|
a5be48c07c | ||
|
|
fe3909f594 | ||
|
|
f37d91a530 | ||
|
|
614ef78771 | ||
|
|
fb294fc03c | ||
|
|
8c7e7c3d48 | ||
|
|
98b6280652 | ||
|
|
7c4c2d6382 | ||
|
|
1a29ea302e | ||
|
|
be39fce741 | ||
|
|
4fed2e6e5f | ||
|
|
14ae5809b0 | ||
|
|
0f66aa47c9 | ||
|
|
cf85d300f4 | ||
|
|
91d60e56df | ||
|
|
1d3681beb4 | ||
|
|
0b403cf329 | ||
|
|
8ba75899e3 | ||
|
|
4d4ed72159 | ||
|
|
b72bf072b3 | ||
|
|
4edcb54b31 | ||
|
|
eae7fc0e53 | ||
|
|
fddacd4410 | ||
|
|
de6c4b9a30 | ||
|
|
6990e34138 | ||
|
|
d9883697ef | ||
|
|
05a26ff8b2 | ||
|
|
84bb082d44 | ||
|
|
a0db94d84f | ||
|
|
0367b4ecd7 | ||
|
|
dbc425dce6 | ||
|
|
116c017c6d | ||
|
|
9c387475f0 | ||
|
|
0765c21cef | ||
|
|
2871038584 | ||
|
|
340885f939 | ||
|
|
1e32e47f54 | ||
|
|
3c759f3b01 | ||
|
|
6615f34d20 | ||
|
|
3a4aac1ee4 | ||
|
|
4d6c092615 | ||
|
|
93421a1dc9 | ||
|
|
209458a856 | ||
|
|
82bd94620e | ||
|
|
af9f017871 | ||
|
|
2f8922ea87 | ||
|
|
0ea936f3fe | ||
|
|
d1870ee0a8 | ||
|
|
d2151690ad | ||
|
|
dff373e7d5 | ||
|
|
0aec2a664f | ||
|
|
723b696393 | ||
|
|
f5f89eb4e4 | ||
|
|
df15332c7f | ||
|
|
61d9e5a869 | ||
|
|
9628b66a97 | ||
|
|
5e041366d4 | ||
|
|
3ecae8d72c | ||
|
|
5709ce9d82 | ||
|
|
ce3c334ac5 | ||
|
|
2ed5aa8730 | ||
|
|
8480a63dda | ||
|
|
132a1695f3 | ||
|
|
21775630c3 | ||
|
|
eac2ef7c6d | ||
|
|
386997f646 | ||
|
|
637b90ad62 | ||
|
|
95d755c2ec | ||
|
|
781aeebef6 | ||
|
|
5e133fd51a | ||
|
|
85f62a3b9d | ||
|
|
a32de58c8b | ||
|
|
1cb2ea6c17 | ||
|
|
6a37ab7af2 | ||
|
|
e0f0aaf767 | ||
|
|
3d7c5b050a | ||
|
|
6bc57c255f | ||
|
|
b82edfe688 | ||
|
|
6b32eb3441 | ||
|
|
23a07fa8a5 | ||
|
|
b019faedd2 | ||
|
|
4430433a10 | ||
|
|
f52cd29e7b | ||
|
|
6a44e593a6 | ||
|
|
f7065fe034 | ||
|
|
0a247956f7 | ||
|
|
03836acded | ||
|
|
b5fb277982 | ||
|
|
e523d3c166 | ||
|
|
41477e4aa6 | ||
|
|
fbaf42a8c4 | ||
|
|
1c3668047b | ||
|
|
7d78c69b6e |
4
.github/ISSUE_TEMPLATE/bug.yml
vendored
4
.github/ISSUE_TEMPLATE/bug.yml
vendored
@@ -39,6 +39,10 @@ body:
|
||||
- 1.17
|
||||
- 1.17.1
|
||||
- 1.18
|
||||
- 1.19
|
||||
- 1.20
|
||||
- 1.21
|
||||
- 1.22
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,5 +1,6 @@
|
||||
|
||||
build/
|
||||
libs/
|
||||
|
||||
.gradle/
|
||||
|
||||
@@ -9,4 +10,4 @@ build/
|
||||
|
||||
collection/
|
||||
|
||||
src/main/java/com/volmit/iris/util/uniques/
|
||||
/core/src/main/java/com/volmit/iris/util/uniques/
|
||||
|
||||
10
README.md
10
README.md
@@ -11,6 +11,8 @@ development.
|
||||
|
||||
Consider supporting our development by buying Iris on spigot! We work hard to make Iris the best it can be for everyone.
|
||||
|
||||
## Preface: if you need help compiling and you are a developer / intend to help out in the community or with development we would love to help you regardless in the discord! however do not come to the discord asking for free copies, or a tutorial on how to compile.
|
||||
|
||||
### Command Line Builds
|
||||
|
||||
1. Install [Java JDK 17](https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html)
|
||||
@@ -28,14 +30,11 @@ Consider supporting our development by buying Iris on spigot! We work hard to ma
|
||||
3. Add `export JAVA_HOME=$(/usr/libexec/java_home)` as a new line
|
||||
4. Use `CTRL + X`, then Press `Y`, Then `ENTER`
|
||||
5. Quit & Reopen Terminal and verify with `echo $JAVA_HOME`. It should print a directory
|
||||
3. If this is your first time building Iris for MC 1.18+ run `gradlew setup` inside the root Iris project folder.
|
||||
Otherwise, skip this step. Grab a coffee, this may take up to 5 minutes depending on your cpu & internet connection.
|
||||
4. Once the project has setup, run `gradlew iris`
|
||||
5. The Iris jar will be placed in `Iris/build/Iris-XXX-XXX.jar` Enjoy! Consider supporting us by buying it on spigot!
|
||||
3. Once the project has setup, run `gradlew iris`
|
||||
4. The Iris jar will be placed in `Iris/build/Iris-XXX-XXX.jar` Enjoy! Consider supporting us by buying it on spigot!
|
||||
|
||||
### IDE Builds (for development)
|
||||
|
||||
* Run `gradlew setup` any time you get dependency issues with craftbukkit
|
||||
* Configure ITJ Gradle to use JDK 17 (in settings, search for gradle)
|
||||
* Add a build line in the build.gradle for your own build task to directly compile Iris into your plugins folder if you
|
||||
prefer.
|
||||
@@ -67,7 +66,6 @@ IrisAccess access=IrisToolbelt.createWorld() // If you like builders...
|
||||
.name("myWorld") // The world name
|
||||
.dimension("terrifyinghands")
|
||||
.seed(69133742) // The world seed
|
||||
.headless(true) // Headless make gen go fast
|
||||
.pregen(PregenTask // Define a pregen job to run
|
||||
.builder()
|
||||
.center(new Position2(0,0)) // REGION coords (1 region = 32x32 chunks)
|
||||
|
||||
557
build.gradle
557
build.gradle
@@ -1,323 +1,234 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
plugins {
|
||||
id 'java'
|
||||
id 'java-library'
|
||||
id "io.freefair.lombok" version "6.3.0"
|
||||
id "com.github.johnrengelman.shadow" version "7.1.2"
|
||||
id "de.undercouch.download" version "5.0.1"
|
||||
}
|
||||
|
||||
version '2.2.1-1.19' // Needs to be version specific
|
||||
def nmsVersion = "1.19"
|
||||
def apiVersion = '1.19'
|
||||
def spigotJarVersion = '1.19-R0.1-SNAPSHOT'
|
||||
def name = getRootProject().getName() // Defined in settings.gradle
|
||||
def main = 'com.volmit.iris.Iris'
|
||||
|
||||
// ADD YOURSELF AS A NEW LINE IF YOU WANT YOUR OWN BUILD TASK GENERATED
|
||||
// ======================== WINDOWS =============================
|
||||
registerCustomOutputTask('Cyberpwn', 'C://Users/cyberpwn/Documents/development/server/plugins')
|
||||
registerCustomOutputTask('Psycho', 'D://Dan/MinecraftDevelopment/server/plugins')
|
||||
registerCustomOutputTask('ArcaneArts', 'C://Users/arcane/Documents/development/server/plugins')
|
||||
registerCustomOutputTask('Coco', 'D://Documents/MC/plugins')
|
||||
registerCustomOutputTask('Strange', 'D://Servers/1.17 Test Server/plugins')
|
||||
registerCustomOutputTask('Vatuu', 'D://Minecraft/Servers/1.19/plugins')
|
||||
// ========================== UNIX ==============================
|
||||
registerCustomOutputTaskUnix('CyberpwnLT', '/Users/danielmills/development/server/plugins')
|
||||
registerCustomOutputTaskUnix('PsychoLT', '/Users/brianfopiano/Desktop/REMOTES/RemoteMinecraft/plugins')
|
||||
// ==============================================================
|
||||
|
||||
/**
|
||||
* Gradle is weird sometimes, we need to delete the plugin yml from the build folder to actually filter properly.
|
||||
*/
|
||||
file(jar.archiveFile.get().getAsFile().getParentFile().getParentFile().getParentFile().getAbsolutePath() + '/build/resources/main/plugin.yml').delete()
|
||||
|
||||
/**
|
||||
* Expand properties into plugin yml
|
||||
*/
|
||||
processResources {
|
||||
filesMatching('**/plugin.yml') {
|
||||
expand(
|
||||
'name': name.toString(),
|
||||
'version': version.toString(),
|
||||
'main': main.toString(),
|
||||
'apiversion': apiVersion.toString()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unified repo
|
||||
*/
|
||||
repositories {
|
||||
mavenLocal {
|
||||
content {
|
||||
includeGroup("org.bukkit")
|
||||
includeGroup("org.spigotmc")
|
||||
}
|
||||
}
|
||||
maven { url "https://dl.cloudsmith.io/public/arcane/archive/maven/" }
|
||||
maven { url "https://maven.enginehub.org/repo/" }
|
||||
mavenCentral()
|
||||
mavenLocal()
|
||||
maven { url "https://jitpack.io"}
|
||||
}
|
||||
|
||||
/**
|
||||
* We need parameter meta for the decree command system
|
||||
*/
|
||||
compileJava {
|
||||
options.compilerArgs << '-parameters'
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure Iris for shading
|
||||
*/
|
||||
shadowJar {
|
||||
//minimize()
|
||||
append("plugin.yml")
|
||||
relocate 'com.dfsek.paralithic', 'com.volmit.iris.util.paralithic'
|
||||
relocate 'io.papermc.lib', 'com.volmit.iris.util.paper'
|
||||
relocate 'net.kyori', 'com.volmit.iris.util.kyori'
|
||||
dependencies {
|
||||
include(dependency('io.papermc:paperlib'))
|
||||
include(dependency('com.dfsek:Paralithic'))
|
||||
include(dependency('net.kyori:'))
|
||||
}
|
||||
}
|
||||
|
||||
configurations.all {
|
||||
resolutionStrategy.cacheChangingModulesFor 60, 'minutes'
|
||||
resolutionStrategy.cacheDynamicVersionsFor 60, 'minutes'
|
||||
}
|
||||
|
||||
/**
|
||||
* Dependencies.
|
||||
*
|
||||
* Provided or classpath dependencies are not shaded and are available on the runtime classpath
|
||||
*
|
||||
* Shaded dependencies are not available at runtime, nor are they available on mvn central so they
|
||||
* need to be shaded into the jar (increasing binary size)
|
||||
*
|
||||
* Dynamically loaded dependencies are defined in the plugin.yml (updating these must be updated in the
|
||||
* plugin.yml also, otherwise they wont be available). These do not increase binary size). Only declare
|
||||
* these dependencies if they are available on mvn central.
|
||||
*/
|
||||
dependencies {
|
||||
// Provided or Classpath
|
||||
compileOnly 'org.projectlombok:lombok:1.18.24'
|
||||
annotationProcessor 'org.projectlombok:lombok:1.18.24'
|
||||
implementation 'org.spigotmc:spigot-api:1.19-R0.1-SNAPSHOT'
|
||||
implementation 'me.clip:placeholderapi:2.11.1'
|
||||
implementation 'io.th0rgal:oraxen:1.94.0'
|
||||
implementation 'org.bukkit:craftbukkit:1.19-R0.1-SNAPSHOT:remapped-mojang'
|
||||
implementation 'com.github.LoneDev6:api-itemsadder:3.1.0b'
|
||||
|
||||
// Shaded
|
||||
implementation 'com.dfsek:Paralithic:0.4.0'
|
||||
implementation 'io.papermc:paperlib:1.0.5'
|
||||
implementation "net.kyori:adventure-text-minimessage:4.11.0"
|
||||
implementation 'net.kyori:adventure-platform-bukkit:4.1.0'
|
||||
implementation 'net.kyori:adventure-api:4.11.0'
|
||||
|
||||
// Dynamically Loaded
|
||||
implementation 'io.timeandspace:smoothie-map:2.0.2'
|
||||
implementation 'it.unimi.dsi:fastutil:8.5.8'
|
||||
implementation 'com.googlecode.concurrentlinkedhashmap:concurrentlinkedhashmap-lru:1.4.2'
|
||||
implementation 'org.zeroturnaround:zt-zip:1.14'
|
||||
implementation 'com.google.code.gson:gson:2.9.0'
|
||||
implementation 'org.ow2.asm:asm:9.2'
|
||||
implementation 'com.google.guava:guava:31.1-jre'
|
||||
implementation 'bsf:bsf:2.4.0'
|
||||
implementation 'rhino:js:1.7R2'
|
||||
implementation 'com.github.ben-manes.caffeine:caffeine:3.0.6'
|
||||
implementation 'org.apache.commons:commons-lang3:3.12.0'
|
||||
}
|
||||
|
||||
if (JavaVersion.current().toString() != "17") {
|
||||
System.err.println()
|
||||
System.err.println("=========================================================================================================")
|
||||
System.err.println("You must run gradle on Java 17. You are using " + JavaVersion.current())
|
||||
System.err.println()
|
||||
System.err.println("=== For IDEs ===")
|
||||
System.err.println("1. Configure the project for Java 17")
|
||||
System.err.println("2. Configure the bundled gradle to use Java 17 in settings")
|
||||
System.err.println()
|
||||
System.err.println("=== For Command Line (gradlew) ===")
|
||||
System.err.println("1. Install JDK 17 from https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html")
|
||||
System.err.println("2. Set JAVA_HOME environment variable to the new jdk installation folder such as C:\\Program Files\\Java\\jdk-17.0.1")
|
||||
System.err.println("3. Open a new command prompt window to get the new environment variables if need be.")
|
||||
System.err.println("=========================================================================================================")
|
||||
System.err.println()
|
||||
System.exit(69);
|
||||
}
|
||||
|
||||
def buildToolsJar = new File(buildDir, "buildtools/BuildTools.jar");
|
||||
def specialSourceJar = new File(buildDir, "specialsource/SpecialSource.jar");
|
||||
def buildToolsFolder = new File(buildDir, "buildtools");
|
||||
def specialSourceFolder = new File(buildDir, "specialsource");
|
||||
def buildToolsHint = new File(buildDir, "buildtools/craftbukkit-" + nmsVersion + ".jar");
|
||||
def outputShadeJar = new File(buildDir, "libs/Iris-" + version + "-all.jar");
|
||||
def ssiJar = new File(buildDir, "specialsource/Iris-" + version + "-all.jar");
|
||||
def ssobfJar = new File(buildDir, "specialsource/Iris-" + version + "-rmo.jar");
|
||||
def ssJar = new File(buildDir, "specialsource/Iris-" + version + "-rma.jar");
|
||||
def homePath = System.properties['user.home']
|
||||
def m2 = new File(homePath + "/.m2/repository")
|
||||
def m2s = m2.getAbsolutePath();
|
||||
|
||||
// ======================== Building Mapped Jars =============================
|
||||
task downloadBuildtools(type: Download) {
|
||||
group "remapping"
|
||||
src 'https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar'
|
||||
dest buildToolsJar
|
||||
onlyIf {
|
||||
!buildToolsJar.exists()
|
||||
}
|
||||
}
|
||||
|
||||
task downloadSpecialSource(type: Download) {
|
||||
group "remapping"
|
||||
src 'https://repo.maven.apache.org/maven2/net/md-5/SpecialSource/1.10.0/SpecialSource-1.10.0-shaded.jar'
|
||||
dest specialSourceJar
|
||||
onlyIf {
|
||||
!specialSourceJar.exists()
|
||||
}
|
||||
}
|
||||
|
||||
task executeBuildTools(dependsOn: downloadBuildtools, type: JavaExec)
|
||||
{
|
||||
group "remapping"
|
||||
classpath = files(buildToolsJar)
|
||||
workingDir = buildToolsFolder
|
||||
args = [
|
||||
"--rev",
|
||||
nmsVersion,
|
||||
"--compile",
|
||||
"craftbukkit",
|
||||
"--remap"
|
||||
]
|
||||
onlyIf {
|
||||
!buildToolsHint.exists()
|
||||
}
|
||||
}
|
||||
|
||||
task copyBuildToSpecialSource(type: Copy)
|
||||
{
|
||||
group "remapping"
|
||||
from outputShadeJar
|
||||
into specialSourceFolder
|
||||
dependsOn(downloadSpecialSource, shadowJar)
|
||||
}
|
||||
|
||||
task specialSourceRemapObfuscate(type: JavaExec)
|
||||
{
|
||||
group "remapping"
|
||||
dependsOn(copyBuildToSpecialSource, downloadSpecialSource, shadowJar)
|
||||
workingDir = specialSourceFolder
|
||||
classpath = files(specialSourceJar,
|
||||
new File(m2s + "/org/spigotmc/spigot/" + spigotJarVersion + "/spigot-" + spigotJarVersion + "-remapped-mojang.jar"))
|
||||
mainClass = "net.md_5.specialsource.SpecialSource"
|
||||
args = [
|
||||
"--live",
|
||||
"-i",
|
||||
ssiJar.getName(),
|
||||
"-o",
|
||||
ssobfJar.getName(),
|
||||
"-m",
|
||||
m2s + "/org/spigotmc/minecraft-server/" + spigotJarVersion + "/minecraft-server-" + spigotJarVersion + "-maps-mojang.txt",
|
||||
"--reverse",
|
||||
]
|
||||
}
|
||||
|
||||
task specialSourceRemap(type: JavaExec)
|
||||
{
|
||||
group "remapping"
|
||||
dependsOn(specialSourceRemapObfuscate)
|
||||
workingDir = specialSourceFolder
|
||||
classpath = files(specialSourceJar,
|
||||
new File(m2s + "/org/spigotmc/spigot/" + spigotJarVersion + "/spigot-" + spigotJarVersion + "-remapped-obf.jar"))
|
||||
mainClass = "net.md_5.specialsource.SpecialSource"
|
||||
args = [
|
||||
"--live",
|
||||
"-i",
|
||||
ssobfJar.getName(),
|
||||
"-o",
|
||||
ssJar.getName(),
|
||||
"-m",
|
||||
m2s + "/org/spigotmc/minecraft-server/" + spigotJarVersion + "/minecraft-server-" + spigotJarVersion + "-maps-spigot.csrg"
|
||||
]
|
||||
}
|
||||
|
||||
tasks.compileJava.dependsOn(executeBuildTools)
|
||||
|
||||
compileJava {
|
||||
options.encoding = "UTF-8"
|
||||
}
|
||||
|
||||
task setup()
|
||||
{
|
||||
group("iris")
|
||||
dependsOn(clean, executeBuildTools)
|
||||
}
|
||||
|
||||
task iris(type: Copy)
|
||||
{
|
||||
group "iris"
|
||||
from ssJar
|
||||
into buildDir
|
||||
rename { String fileName ->
|
||||
fileName.replace('Iris-' + version + '-rma.jar', "Iris-" + version + ".jar")
|
||||
}
|
||||
dependsOn(specialSourceRemap)
|
||||
}
|
||||
|
||||
def registerCustomOutputTask(name, path) {
|
||||
if (!System.properties['os.name'].toLowerCase().contains('windows')) {
|
||||
return;
|
||||
}
|
||||
|
||||
tasks.register('build' + name, Copy) {
|
||||
group('development')
|
||||
outputs.upToDateWhen { false }
|
||||
dependsOn(iris)
|
||||
from(new File(buildDir, "Iris-" + version + ".jar"))
|
||||
into(file(path))
|
||||
rename { String fileName ->
|
||||
fileName.replace("Iris-" + version + ".jar", "Iris.jar")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def registerCustomOutputTaskUnix(name, path) {
|
||||
if (System.properties['os.name'].toLowerCase().contains('windows')) {
|
||||
return;
|
||||
}
|
||||
|
||||
tasks.register('build' + name, Copy) {
|
||||
group('development')
|
||||
outputs.upToDateWhen { false }
|
||||
dependsOn(iris)
|
||||
from(new File(buildDir, "Iris-" + version + ".jar"))
|
||||
into(file(path))
|
||||
rename { String fileName ->
|
||||
fileName.replace("Iris-" + version + ".jar", "Iris.jar")
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
buildscript() {
|
||||
repositories {
|
||||
maven { url 'https://jitpack.io'}
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.github.VolmitSoftware:NMSTools:1.0.1'
|
||||
}
|
||||
}
|
||||
|
||||
plugins {
|
||||
id 'java'
|
||||
id 'java-library'
|
||||
id "io.github.goooler.shadow" version "8.1.7"
|
||||
id "de.undercouch.download" version "5.0.1"
|
||||
}
|
||||
|
||||
version '4.0-1.19.2-1.21.1'
|
||||
|
||||
// ADD YOURSELF AS A NEW LINE IF YOU WANT YOUR OWN BUILD TASK GENERATED
|
||||
// ======================== WINDOWS =============================
|
||||
registerCustomOutputTask('Cyberpwn', 'C://Users/cyberpwn/Documents/development/server/plugins')
|
||||
registerCustomOutputTask('Psycho', 'C://Dan/MinecraftDevelopment/Server/plugins')
|
||||
registerCustomOutputTask('ArcaneArts', 'C://Users/arcane/Documents/development/server/plugins')
|
||||
registerCustomOutputTask('Coco', 'D://mcsm/plugins')
|
||||
registerCustomOutputTask('Strange', 'D://Servers/1.17 Test Server/plugins')
|
||||
registerCustomOutputTask('Vatuu', 'D://Minecraft/Servers/1.19.4/plugins')
|
||||
registerCustomOutputTask('CrazyDev22', 'C://Users/Julian/Desktop/server/plugins')
|
||||
registerCustomOutputTask('Pixel', 'D://Iris Dimension Engine/1.20.4 - Development/plugins')
|
||||
// ========================== UNIX ==============================
|
||||
registerCustomOutputTaskUnix('CyberpwnLT', '/Users/danielmills/development/server/plugins')
|
||||
registerCustomOutputTaskUnix('PsychoLT', '/Users/brianfopiano/Developer/RemoteGit/Server/plugins')
|
||||
registerCustomOutputTaskUnix('PixelMac', '/Users/test/Desktop/mcserver/plugins')
|
||||
registerCustomOutputTaskUnix('CrazyDev22LT', '/home/julian/Desktop/server/plugins')
|
||||
// ==============================================================
|
||||
|
||||
def NMS_BINDINGS = Map.of(
|
||||
"v1_21_R1", "1.21-R0.1-SNAPSHOT",
|
||||
"v1_20_R4", "1.20.6-R0.1-SNAPSHOT",
|
||||
"v1_20_R3", "1.20.4-R0.1-SNAPSHOT",
|
||||
"v1_20_R2", "1.20.2-R0.1-SNAPSHOT",
|
||||
"v1_20_R1", "1.20.1-R0.1-SNAPSHOT",
|
||||
"v1_19_R3", "1.19.4-R0.1-SNAPSHOT",
|
||||
"v1_19_R2", "1.19.3-R0.1-SNAPSHOT",
|
||||
"v1_19_R1", "1.19.2-R0.1-SNAPSHOT"
|
||||
)
|
||||
def JVM_VERSION = Map.of(
|
||||
"v1_21_R1", 21,
|
||||
"v1_20_R4", 21,
|
||||
)
|
||||
def entryPoint = 'com.volmit.iris.server.EntryPoint'
|
||||
NMS_BINDINGS.each { nms ->
|
||||
project(":nms:${nms.key}") {
|
||||
apply plugin: 'java'
|
||||
apply plugin: 'com.volmit.nmstools'
|
||||
|
||||
nmsTools {
|
||||
it.jvm = JVM_VERSION.getOrDefault(nms.key, 17)
|
||||
it.version = nms.value
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation project(":core")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
NMS_BINDINGS.each {
|
||||
dependsOn(":nms:${it.key}:remap")
|
||||
from("${project(":nms:${it.key}").layout.buildDirectory.asFile.get()}/libs/${it.key}-mapped.jar")
|
||||
}
|
||||
//dependsOn(':com.volmit.gui:build')
|
||||
|
||||
//minimize()
|
||||
append("plugin.yml")
|
||||
relocate 'com.dfsek.paralithic', 'com.volmit.iris.util.paralithic'
|
||||
relocate 'io.papermc.lib', 'com.volmit.iris.util.paper'
|
||||
relocate 'net.kyori', 'com.volmit.iris.util.kyori'
|
||||
archiveFileName.set("Iris-${project.version}.jar")
|
||||
|
||||
manifest {
|
||||
attributes 'Main-Class': entryPoint
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation project(':core')
|
||||
}
|
||||
|
||||
configurations.configureEach {
|
||||
resolutionStrategy.cacheChangingModulesFor 60, 'minutes'
|
||||
resolutionStrategy.cacheDynamicVersionsFor 60, 'minutes'
|
||||
}
|
||||
|
||||
allprojects {
|
||||
apply plugin: 'java'
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven { url "https://repo.papermc.io/repository/maven-public/"}
|
||||
maven { url "https://repo.codemc.org/repository/maven-public" }
|
||||
maven { url "https://mvn.lumine.io/repository/maven-public/" }
|
||||
maven { url "https://jitpack.io"}
|
||||
|
||||
maven { url "https://s01.oss.sonatype.org/content/repositories/snapshots" }
|
||||
maven { url "https://mvn.lumine.io/repository/maven/" }
|
||||
maven { url "https://repo.triumphteam.dev/snapshots" }
|
||||
maven { url "https://repo.mineinabyss.com/releases" }
|
||||
maven { url 'https://hub.jeff-media.com/nexus/repository/jeff-media-public/' }
|
||||
maven { url "https://repo.oraxen.com/releases" }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// Provided or Classpath
|
||||
compileOnly 'org.projectlombok:lombok:1.18.34'
|
||||
annotationProcessor 'org.projectlombok:lombok:1.18.34'
|
||||
|
||||
// Shaded
|
||||
implementation 'com.dfsek:Paralithic:0.4.0'
|
||||
implementation 'io.papermc:paperlib:1.0.5'
|
||||
implementation "net.kyori:adventure-text-minimessage:4.17.0"
|
||||
implementation 'net.kyori:adventure-platform-bukkit:4.3.4'
|
||||
implementation 'net.kyori:adventure-api:4.17.0'
|
||||
//implementation 'org.bytedeco:javacpp:1.5.10'
|
||||
//implementation 'org.bytedeco:cuda-platform:12.3-8.9-1.5.10'
|
||||
//implementation "org.deeplearning4j:deeplearning4j-core:1.0.0-M2.1"
|
||||
compileOnly 'io.lumine:Mythic-Dist:5.2.1'
|
||||
|
||||
// Dynamically Loaded
|
||||
compileOnly 'io.timeandspace:smoothie-map:2.0.2'
|
||||
compileOnly 'it.unimi.dsi:fastutil:8.5.8'
|
||||
compileOnly 'com.googlecode.concurrentlinkedhashmap:concurrentlinkedhashmap-lru:1.4.2'
|
||||
compileOnly 'org.zeroturnaround:zt-zip:1.14'
|
||||
compileOnly 'com.google.code.gson:gson:2.10.1'
|
||||
compileOnly 'org.ow2.asm:asm:9.2'
|
||||
compileOnly 'com.google.guava:guava:33.0.0-jre'
|
||||
compileOnly 'bsf:bsf:2.4.0'
|
||||
compileOnly 'rhino:js:1.7R2'
|
||||
compileOnly 'com.github.ben-manes.caffeine:caffeine:3.0.6'
|
||||
compileOnly 'org.apache.commons:commons-lang3:3.12.0'
|
||||
compileOnly 'net.bytebuddy:byte-buddy:1.14.14'
|
||||
compileOnly 'net.bytebuddy:byte-buddy-agent:1.12.8'
|
||||
compileOnly 'org.bytedeco:javacpp:1.5.10'
|
||||
compileOnly 'org.bytedeco:cuda-platform:12.3-8.9-1.5.10'
|
||||
compileOnly 'io.netty:netty-all:4.1.112.Final'
|
||||
}
|
||||
|
||||
/**
|
||||
* We need parameter meta for the decree command system
|
||||
*/
|
||||
compileJava {
|
||||
options.compilerArgs << '-parameters'
|
||||
options.encoding = "UTF-8"
|
||||
}
|
||||
}
|
||||
|
||||
if (JavaVersion.current().toString() != "17") {
|
||||
System.err.println()
|
||||
System.err.println("=========================================================================================================")
|
||||
System.err.println("You must run gradle on Java 17. You are using " + JavaVersion.current())
|
||||
System.err.println()
|
||||
System.err.println("=== For IDEs ===")
|
||||
System.err.println("1. Configure the project for Java 17")
|
||||
System.err.println("2. Configure the bundled gradle to use Java 17 in settings")
|
||||
System.err.println()
|
||||
System.err.println("=== For Command Line (gradlew) ===")
|
||||
System.err.println("1. Install JDK 17 from https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html")
|
||||
System.err.println("2. Set JAVA_HOME environment variable to the new jdk installation folder such as C:/Program Files/Java/jdk-17.0.1")
|
||||
System.err.println("3. Open a new command prompt window to get the new environment variables if need be.")
|
||||
System.err.println("=========================================================================================================")
|
||||
System.err.println()
|
||||
System.exit(69);
|
||||
}
|
||||
|
||||
task iris(type: Copy) {
|
||||
group "iris"
|
||||
from new File(layout.buildDirectory.asFile.get(), "libs/Iris-${version}.jar")
|
||||
into layout.buildDirectory.asFile.get()
|
||||
dependsOn(build)
|
||||
}
|
||||
|
||||
def registerCustomOutputTask(name, path) {
|
||||
if (!System.properties['os.name'].toLowerCase().contains('windows')) {
|
||||
return;
|
||||
}
|
||||
|
||||
tasks.register('build' + name, Copy) {
|
||||
group('development')
|
||||
outputs.upToDateWhen { false }
|
||||
dependsOn(iris)
|
||||
from(new File(buildDir, "Iris-" + version + ".jar"))
|
||||
into(file(path))
|
||||
rename { String fileName ->
|
||||
fileName.replace("Iris-" + version + ".jar", "Iris.jar")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def registerCustomOutputTaskUnix(name, path) {
|
||||
if (System.properties['os.name'].toLowerCase().contains('windows')) {
|
||||
return;
|
||||
}
|
||||
|
||||
tasks.register('build' + name, Copy) {
|
||||
group('development')
|
||||
outputs.upToDateWhen { false }
|
||||
dependsOn(iris)
|
||||
from(new File(buildDir, "Iris-" + version + ".jar"))
|
||||
into(file(path))
|
||||
rename { String fileName ->
|
||||
fileName.replace("Iris-" + version + ".jar", "Iris.jar")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.build.dependsOn(shadowJar)
|
||||
|
||||
92
core/build.gradle
Normal file
92
core/build.gradle
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
plugins {
|
||||
id 'java'
|
||||
id 'java-library'
|
||||
id "io.freefair.lombok" version "8.6"
|
||||
}
|
||||
|
||||
def apiVersion = '1.19'
|
||||
def main = 'com.volmit.iris.Iris'
|
||||
|
||||
/**
|
||||
* We need parameter meta for the decree command system
|
||||
*/
|
||||
compileJava {
|
||||
options.compilerArgs << '-parameters'
|
||||
options.encoding = "UTF-8"
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven { url 'https://nexus.phoenixdevt.fr/repository/maven-public/' }
|
||||
maven { url 'https://repo.auxilor.io/repository/maven-public/' }
|
||||
}
|
||||
|
||||
/**
|
||||
* Dependencies.
|
||||
*
|
||||
* Provided or classpath dependencies are not shaded and are available on the runtime classpath
|
||||
*
|
||||
* Shaded dependencies are not available at runtime, nor are they available on mvn central so they
|
||||
* need to be shaded into the jar (increasing binary size)
|
||||
*
|
||||
* Dynamically loaded dependencies are defined in the plugin.yml (updating these must be updated in the
|
||||
* plugin.yml also, otherwise they wont be available). These do not increase binary size). Only declare
|
||||
* these dependencies if they are available on mvn central.
|
||||
*/
|
||||
dependencies {
|
||||
// Provided or Classpath
|
||||
compileOnly 'org.spigotmc:spigot-api:1.20.1-R0.1-SNAPSHOT'
|
||||
compileOnly 'org.apache.logging.log4j:log4j-api:2.19.0'
|
||||
compileOnly 'org.apache.logging.log4j:log4j-core:2.19.0'
|
||||
compileOnly 'commons-io:commons-io:2.13.0'
|
||||
compileOnly 'commons-lang:commons-lang:2.6'
|
||||
compileOnly 'com.github.oshi:oshi-core:5.8.5'
|
||||
compileOnly 'org.lz4:lz4-java:1.8.0'
|
||||
|
||||
// Third Party Integrations
|
||||
compileOnly 'com.ticxo.playeranimator:PlayerAnimator:R1.2.7'
|
||||
compileOnly 'io.th0rgal:oraxen:1.173.0'
|
||||
compileOnly 'com.github.LoneDev6:api-itemsadder:3.4.1-r4'
|
||||
compileOnly 'com.github.PlaceholderAPI:placeholderapi:2.11.3'
|
||||
compileOnly 'com.github.Ssomar-Developement:SCore:4.23.10.8'
|
||||
compileOnly 'net.Indyuce:MMOItems-API:6.9.5-SNAPSHOT'
|
||||
compileOnly 'com.willfp:EcoItems:5.44.0'
|
||||
//implementation files('libs/CustomItems.jar')
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gradle is weird sometimes, we need to delete the plugin yml from the build folder to actually filter properly.
|
||||
*/
|
||||
file(jar.archiveFile.get().getAsFile().getParentFile().getParentFile().getParentFile().getAbsolutePath() + '/build/resources/main/plugin.yml').delete()
|
||||
|
||||
/**
|
||||
* Expand properties into plugin yml
|
||||
*/
|
||||
processResources {
|
||||
filesMatching('**/plugin.yml') {
|
||||
expand(
|
||||
'name': rootProject.name.toString(),
|
||||
'version': rootProject.version.toString(),
|
||||
'main': main.toString(),
|
||||
'apiversion': apiVersion.toString()
|
||||
)
|
||||
}
|
||||
}
|
||||
985
core/src/main/java/com/volmit/iris/Iris.java
Normal file
985
core/src/main/java/com/volmit/iris/Iris.java
Normal file
@@ -0,0 +1,985 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.ServerConfigurator;
|
||||
import com.volmit.iris.core.link.IrisPapiExpansion;
|
||||
import com.volmit.iris.core.link.MultiverseCoreLink;
|
||||
import com.volmit.iris.core.link.MythicMobsLink;
|
||||
import com.volmit.iris.core.loader.IrisData;
|
||||
import com.volmit.iris.core.nms.INMS;
|
||||
import com.volmit.iris.core.nms.v1X.NMSBinding1X;
|
||||
import com.volmit.iris.core.pregenerator.LazyPregenerator;
|
||||
import com.volmit.iris.core.safeguard.IrisSafeguard;
|
||||
import com.volmit.iris.core.safeguard.UtilsSFG;
|
||||
import com.volmit.iris.core.service.StudioSVC;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.engine.EnginePanic;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.object.IrisCompat;
|
||||
import com.volmit.iris.engine.object.IrisDimension;
|
||||
import com.volmit.iris.engine.object.IrisWorld;
|
||||
import com.volmit.iris.engine.platform.BukkitChunkGenerator;
|
||||
import com.volmit.iris.engine.platform.DummyChunkGenerator;
|
||||
import com.volmit.iris.server.master.IrisMasterServer;
|
||||
import com.volmit.iris.server.node.IrisServer;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.exceptions.IrisException;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.function.NastyRunnable;
|
||||
import com.volmit.iris.util.io.FileWatcher;
|
||||
import com.volmit.iris.util.io.IO;
|
||||
import com.volmit.iris.util.io.InstanceState;
|
||||
import com.volmit.iris.util.io.JarScanner;
|
||||
import com.volmit.iris.util.math.M;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import com.volmit.iris.util.misc.getHardware;
|
||||
import com.volmit.iris.util.parallel.MultiBurst;
|
||||
import com.volmit.iris.util.plugin.IrisService;
|
||||
import com.volmit.iris.util.plugin.Metrics;
|
||||
import com.volmit.iris.util.plugin.VolmitPlugin;
|
||||
import com.volmit.iris.util.plugin.VolmitSender;
|
||||
import com.volmit.iris.util.reflect.ShadeFix;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import com.volmit.iris.util.scheduling.Queue;
|
||||
import com.volmit.iris.util.scheduling.ShurikenQueue;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import net.bytebuddy.agent.ByteBuddyAgent;
|
||||
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
|
||||
import net.kyori.adventure.text.serializer.ComponentSerializer;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.filefilter.IOFileFilter;
|
||||
import org.apache.commons.io.filefilter.TrueFileFilter;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.generator.BiomeProvider;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
import org.bukkit.plugin.IllegalPluginAccessException;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.*;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.net.URL;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static com.volmit.iris.core.safeguard.IrisSafeguard.InitializeSafeguard;
|
||||
|
||||
@SuppressWarnings("CanBeFinal")
|
||||
public class Iris extends VolmitPlugin implements Listener {
|
||||
public static final String OVERWORLD_TAG = "3800";
|
||||
|
||||
private static final Queue<Runnable> syncJobs = new ShurikenQueue<>();
|
||||
|
||||
public static Iris instance;
|
||||
public static BukkitAudiences audiences;
|
||||
public static MultiverseCoreLink linkMultiverseCore;
|
||||
public static MythicMobsLink linkMythicMobs;
|
||||
public static IrisCompat compat;
|
||||
public static FileWatcher configWatcher;
|
||||
private static IrisServer server;
|
||||
private static VolmitSender sender;
|
||||
|
||||
static {
|
||||
try {
|
||||
fixShading();
|
||||
InstanceState.updateInstanceId();
|
||||
} catch (Throwable ignored) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private final KList<Runnable> postShutdown = new KList<>();
|
||||
private KMap<Class<? extends IrisService>, IrisService> services;
|
||||
|
||||
public static VolmitSender getSender() {
|
||||
if (sender == null) {
|
||||
sender = new VolmitSender(Bukkit.getConsoleSender());
|
||||
sender.setTag(instance.getTag());
|
||||
}
|
||||
return sender;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T service(Class<T> c) {
|
||||
return (T) instance.services.get(c);
|
||||
}
|
||||
|
||||
public static void callEvent(Event e) {
|
||||
if (!e.isAsynchronous()) {
|
||||
J.s(() -> Bukkit.getPluginManager().callEvent(e));
|
||||
} else {
|
||||
Bukkit.getPluginManager().callEvent(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static KList<Object> initialize(String s, Class<? extends Annotation> slicedClass) {
|
||||
JarScanner js = new JarScanner(instance.getJarFile(), s);
|
||||
KList<Object> v = new KList<>();
|
||||
J.attempt(js::scan);
|
||||
for (Class<?> i : js.getClasses()) {
|
||||
if (slicedClass == null || i.isAnnotationPresent(slicedClass)) {
|
||||
try {
|
||||
v.add(i.getDeclaredConstructor().newInstance());
|
||||
} catch (Throwable ignored) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
public static KList<Class<?>> getClasses(String s, Class<? extends Annotation> slicedClass) {
|
||||
JarScanner js = new JarScanner(instance.getJarFile(), s);
|
||||
KList<Class<?>> v = new KList<>();
|
||||
J.attempt(js::scan);
|
||||
for (Class<?> i : js.getClasses()) {
|
||||
if (slicedClass == null || i.isAnnotationPresent(slicedClass)) {
|
||||
try {
|
||||
v.add(i);
|
||||
} catch (Throwable ignored) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
public static KList<Object> initialize(String s) {
|
||||
return initialize(s, null);
|
||||
}
|
||||
|
||||
public static void sq(Runnable r) {
|
||||
synchronized (syncJobs) {
|
||||
syncJobs.queue(r);
|
||||
}
|
||||
}
|
||||
|
||||
public static File getTemp() {
|
||||
return instance.getDataFolder("cache", "temp");
|
||||
}
|
||||
|
||||
public static void msg(String string) {
|
||||
try {
|
||||
getSender().sendMessage(string);
|
||||
} catch (Throwable e) {
|
||||
try {
|
||||
instance.getLogger().info(instance.getTag() + string.replaceAll("(<([^>]+)>)", ""));
|
||||
} catch (Throwable ignored1) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static File getCached(String name, String url) {
|
||||
String h = IO.hash(name + "@" + url);
|
||||
File f = Iris.instance.getDataFile("cache", h.substring(0, 2), h.substring(3, 5), h);
|
||||
|
||||
if (!f.exists()) {
|
||||
try (BufferedInputStream in = new BufferedInputStream(new URL(url).openStream()); FileOutputStream fileOutputStream = new FileOutputStream(f)) {
|
||||
byte[] dataBuffer = new byte[1024];
|
||||
int bytesRead;
|
||||
while ((bytesRead = in.read(dataBuffer, 0, 1024)) != -1) {
|
||||
fileOutputStream.write(dataBuffer, 0, bytesRead);
|
||||
Iris.verbose("Aquiring " + name);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Iris.reportError(e);
|
||||
}
|
||||
}
|
||||
|
||||
return f.exists() ? f : null;
|
||||
}
|
||||
|
||||
public static String getNonCached(String name, String url) {
|
||||
String h = IO.hash(name + "*" + url);
|
||||
File f = Iris.instance.getDataFile("cache", h.substring(0, 2), h.substring(3, 5), h);
|
||||
|
||||
try (BufferedInputStream in = new BufferedInputStream(new URL(url).openStream()); FileOutputStream fileOutputStream = new FileOutputStream(f)) {
|
||||
byte[] dataBuffer = new byte[1024];
|
||||
int bytesRead;
|
||||
while ((bytesRead = in.read(dataBuffer, 0, 1024)) != -1) {
|
||||
fileOutputStream.write(dataBuffer, 0, bytesRead);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Iris.reportError(e);
|
||||
}
|
||||
|
||||
try {
|
||||
return IO.readAll(f);
|
||||
} catch (IOException e) {
|
||||
Iris.reportError(e);
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
public static File getNonCachedFile(String name, String url) {
|
||||
String h = IO.hash(name + "*" + url);
|
||||
File f = Iris.instance.getDataFile("cache", h.substring(0, 2), h.substring(3, 5), h);
|
||||
Iris.verbose("Download " + name + " -> " + url);
|
||||
try (BufferedInputStream in = new BufferedInputStream(new URL(url).openStream()); FileOutputStream fileOutputStream = new FileOutputStream(f)) {
|
||||
byte[] dataBuffer = new byte[1024];
|
||||
int bytesRead;
|
||||
while ((bytesRead = in.read(dataBuffer, 0, 1024)) != -1) {
|
||||
fileOutputStream.write(dataBuffer, 0, bytesRead);
|
||||
}
|
||||
|
||||
fileOutputStream.flush();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
Iris.reportError(e);
|
||||
}
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
public static void warn(String format, Object... objs) {
|
||||
msg(C.YELLOW + String.format(format, objs));
|
||||
}
|
||||
|
||||
public static void error(String format, Object... objs) {
|
||||
msg(C.RED + String.format(format, objs));
|
||||
}
|
||||
|
||||
public static void debug(String string) {
|
||||
if (!IrisSettings.get().getGeneral().isDebug()) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
throw new RuntimeException();
|
||||
} catch (Throwable e) {
|
||||
try {
|
||||
String[] cc = e.getStackTrace()[1].getClassName().split("\\Q.\\E");
|
||||
|
||||
if (cc.length > 5) {
|
||||
debug(cc[3] + "/" + cc[4] + "/" + cc[cc.length - 1], e.getStackTrace()[1].getLineNumber(), string);
|
||||
} else {
|
||||
debug(cc[3] + "/" + cc[4], e.getStackTrace()[1].getLineNumber(), string);
|
||||
}
|
||||
} catch (Throwable ex) {
|
||||
debug("Origin", -1, string);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void debug(String category, int line, String string) {
|
||||
if (!IrisSettings.get().getGeneral().isDebug()) {
|
||||
return;
|
||||
}
|
||||
if (IrisSettings.get().getGeneral().isUseConsoleCustomColors()) {
|
||||
msg("<gradient:#095fe0:#a848db>" + category + " <#bf3b76>" + line + "<reset> " + C.LIGHT_PURPLE + string.replaceAll("\\Q<\\E", "[").replaceAll("\\Q>\\E", "]"));
|
||||
} else {
|
||||
msg(C.BLUE + category + ":" + C.AQUA + line + C.RESET + C.LIGHT_PURPLE + " " + string.replaceAll("\\Q<\\E", "[").replaceAll("\\Q>\\E", "]"));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static void verbose(String string) {
|
||||
debug(string);
|
||||
}
|
||||
|
||||
public static void success(String string) {
|
||||
msg(C.IRIS + string);
|
||||
}
|
||||
|
||||
public static void info(String format, Object... args) {
|
||||
msg(C.WHITE + String.format(format, args));
|
||||
}
|
||||
|
||||
public static void safeguard(String format, Object... args) {
|
||||
msg(C.RESET + String.format(format, args));
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public static void later(NastyRunnable object) {
|
||||
try {
|
||||
Bukkit.getScheduler().scheduleAsyncDelayedTask(instance, () ->
|
||||
{
|
||||
try {
|
||||
object.run();
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
Iris.reportError(e);
|
||||
}
|
||||
}, RNG.r.i(100, 1200));
|
||||
} catch (IllegalPluginAccessException ignored) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static int jobCount() {
|
||||
return syncJobs.size();
|
||||
}
|
||||
|
||||
public static void clearQueues() {
|
||||
synchronized (syncJobs) {
|
||||
syncJobs.clear();
|
||||
}
|
||||
}
|
||||
|
||||
public static int getJavaVersion() {
|
||||
String version = System.getProperty("java.version");
|
||||
if (version.startsWith("1.")) {
|
||||
version = version.substring(2, 3);
|
||||
} else {
|
||||
int dot = version.indexOf(".");
|
||||
if (dot != -1) {
|
||||
version = version.substring(0, dot);
|
||||
}
|
||||
}
|
||||
return Integer.parseInt(version);
|
||||
}
|
||||
|
||||
public static String getJava() {
|
||||
String javaRuntimeName = System.getProperty("java.vm.name");
|
||||
String javaRuntimeVendor = System.getProperty("java.vendor");
|
||||
String javaRuntimeVersion = System.getProperty("java.vm.version");
|
||||
return String.format("%s %s (build %s)", javaRuntimeName, javaRuntimeVendor, javaRuntimeVersion);
|
||||
}
|
||||
|
||||
public static void reportErrorChunk(int x, int z, Throwable e, String extra) {
|
||||
if (IrisSettings.get().getGeneral().isDebug()) {
|
||||
File f = instance.getDataFile("debug", "chunk-errors", "chunk." + x + "." + z + ".txt");
|
||||
|
||||
if (!f.exists()) {
|
||||
J.attempt(() -> {
|
||||
PrintWriter pw = new PrintWriter(f);
|
||||
pw.println("Thread: " + Thread.currentThread().getName());
|
||||
pw.println("First: " + new Date(M.ms()));
|
||||
e.printStackTrace(pw);
|
||||
pw.close();
|
||||
});
|
||||
}
|
||||
|
||||
Iris.debug("Chunk " + x + "," + z + " Exception Logged: " + e.getClass().getSimpleName() + ": " + C.RESET + "" + C.LIGHT_PURPLE + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public static void reportError(Throwable e) {
|
||||
String n = e.getClass().getCanonicalName() + "-" + e.getStackTrace()[0].getClassName() + "-" + e.getStackTrace()[0].getLineNumber();
|
||||
|
||||
if (e.getCause() != null) {
|
||||
n += "-" + e.getCause().getStackTrace()[0].getClassName() + "-" + e.getCause().getStackTrace()[0].getLineNumber();
|
||||
}
|
||||
|
||||
File f = instance.getDataFile("debug", "caught-exceptions", n + ".txt");
|
||||
|
||||
if (!f.exists()) {
|
||||
J.attempt(() -> {
|
||||
PrintWriter pw = new PrintWriter(f);
|
||||
pw.println("Thread: " + Thread.currentThread().getName());
|
||||
pw.println("First: " + new Date(M.ms()));
|
||||
e.printStackTrace(pw);
|
||||
pw.close();
|
||||
});
|
||||
}
|
||||
|
||||
Iris.debug("Exception Logged: " + e.getClass().getSimpleName() + ": " + C.RESET + "" + C.LIGHT_PURPLE + e.getMessage());
|
||||
}
|
||||
|
||||
public static void dump() {
|
||||
try {
|
||||
File fi = Iris.instance.getDataFile("dump", "td-" + new java.sql.Date(M.ms()) + ".txt");
|
||||
FileOutputStream fos = new FileOutputStream(fi);
|
||||
Map<Thread, StackTraceElement[]> f = Thread.getAllStackTraces();
|
||||
PrintWriter pw = new PrintWriter(fos);
|
||||
for (Thread i : f.keySet()) {
|
||||
pw.println("========================================");
|
||||
pw.println("Thread: '" + i.getName() + "' ID: " + i.getId() + " STATUS: " + i.getState().name());
|
||||
|
||||
for (StackTraceElement j : f.get(i)) {
|
||||
pw.println(" @ " + j.toString());
|
||||
}
|
||||
|
||||
pw.println("========================================");
|
||||
pw.println();
|
||||
pw.println();
|
||||
}
|
||||
|
||||
pw.close();
|
||||
Iris.info("DUMPED! See " + fi.getAbsolutePath());
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void panic() {
|
||||
EnginePanic.panic();
|
||||
}
|
||||
|
||||
public static void addPanic(String s, String v) {
|
||||
EnginePanic.add(s, v);
|
||||
}
|
||||
|
||||
private static void fixShading() {
|
||||
ShadeFix.fix(ComponentSerializer.class);
|
||||
}
|
||||
|
||||
private void enable() {
|
||||
instance = this;
|
||||
InitializeSafeguard();
|
||||
ByteBuddyAgent.install();
|
||||
services = new KMap<>();
|
||||
setupAudience();
|
||||
initialize("com.volmit.iris.core.service").forEach((i) -> services.put((Class<? extends IrisService>) i.getClass(), (IrisService) i));
|
||||
INMS.get();
|
||||
IO.delete(new File("iris"));
|
||||
IrisSafeguard.instance.IrisSafeguardSystem();
|
||||
getSender().setTag(getTag());
|
||||
INMS.get().injectBukkit();
|
||||
if (IrisSafeguard.instance.unstablemode && !IrisSafeguard.instance.acceptUnstable)
|
||||
IrisSafeguard.instance.earlySplash();
|
||||
compat = IrisCompat.configured(getDataFile("compat.json"));
|
||||
linkMultiverseCore = new MultiverseCoreLink();
|
||||
linkMythicMobs = new MythicMobsLink();
|
||||
configWatcher = new FileWatcher(getDataFile("settings.json"));
|
||||
services.values().forEach(IrisService::onEnable);
|
||||
services.values().forEach(this::registerListener);
|
||||
ServerConfigurator.setupDataPack();
|
||||
installMainDimension();
|
||||
try {
|
||||
info("Starting server...");
|
||||
try {
|
||||
int port = Integer.parseInt(System.getProperty("com.volmit.iris.server.port"));
|
||||
String[] remote = Optional.ofNullable(System.getProperty("com.volmit.iris.server.remote"))
|
||||
.map(String::trim)
|
||||
.map(s -> s.isBlank() ? null : s.split(","))
|
||||
.orElse(new String[0]);
|
||||
server = remote.length > 0 ? new IrisMasterServer(port, remote) : new IrisServer(port);
|
||||
} catch (NullPointerException | NumberFormatException ignored) {
|
||||
var serverSettings = IrisSettings.get().getServer();
|
||||
if (serverSettings.isActive()) {
|
||||
server = serverSettings.isRemote() ?
|
||||
new IrisMasterServer(serverSettings.getPort(), serverSettings.remote) :
|
||||
new IrisServer(serverSettings.getPort());
|
||||
}
|
||||
}
|
||||
} catch (InterruptedException ignored) {
|
||||
} catch (Throwable e) {
|
||||
error("Failed to start server: " + e.getClass().getSimpleName());
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
if (!IrisSafeguard.instance.acceptUnstable && IrisSafeguard.instance.unstablemode) {
|
||||
Iris.info(C.RED + "World loading has been disabled until the incompatibility is resolved.");
|
||||
Iris.info(C.DARK_RED + "Alternatively, go to plugins/iris/settings.json and set ignoreBootMode to true.");
|
||||
} else {
|
||||
J.s(() -> {
|
||||
J.a(() -> PaperLib.suggestPaper(this));
|
||||
J.a(() -> IO.delete(getTemp()));
|
||||
J.a(LazyPregenerator::loadLazyGenerators, 100);
|
||||
J.a(this::bstats);
|
||||
J.ar(this::checkConfigHotload, 60);
|
||||
J.sr(this::tickQueue, 0);
|
||||
J.s(this::setupPapi);
|
||||
J.a(ServerConfigurator::configure, 20);
|
||||
splash();
|
||||
UtilsSFG.splash();
|
||||
autoStartStudio();
|
||||
checkForBukkitWorlds();
|
||||
IrisToolbelt.retainMantleDataForSlice(String.class.getCanonicalName());
|
||||
IrisToolbelt.retainMantleDataForSlice(BlockData.class.getCanonicalName());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void checkForBukkitWorlds() {
|
||||
FileConfiguration fc = new YamlConfiguration();
|
||||
try {
|
||||
fc.load(new File("bukkit.yml"));
|
||||
ConfigurationSection section = fc.getConfigurationSection("worlds");
|
||||
if (section == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (String s : section.getKeys(false)) {
|
||||
try {
|
||||
|
||||
ConfigurationSection entry = section.getConfigurationSection(s);
|
||||
if (!entry.contains("backup-generator", true)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String generator = entry.getString("backup-generator");
|
||||
if (!generator.startsWith("Iris")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (new File(Bukkit.getWorldContainer().getPath() + "/" + s).exists()) {
|
||||
File world = new File(Bukkit.getWorldContainer().getPath() + "/" + s + "/iris/engine-data/");
|
||||
IOFileFilter jsonFilter = org.apache.commons.io.filefilter.FileFilterUtils.suffixFileFilter(".json");
|
||||
Collection<File> files = FileUtils.listFiles(world, jsonFilter, TrueFileFilter.INSTANCE);
|
||||
if (files.size() != 1) {
|
||||
Iris.info(C.DARK_GRAY + "------------------------------------------");
|
||||
Iris.info(C.RED + "Failed to load " + C.GRAY + s + C.RED + ". No valid engine-data file was found.");
|
||||
Iris.info(C.DARK_GRAY + "------------------------------------------");
|
||||
continue;
|
||||
}
|
||||
|
||||
for (File file : files) {
|
||||
int lastDotIndex = file.getName().lastIndexOf(".");
|
||||
generator = file.getName().substring(0, lastDotIndex);
|
||||
}
|
||||
} else {
|
||||
if (generator.startsWith("Iris:")) {
|
||||
generator = generator.split("\\Q:\\E")[1];
|
||||
} else if (generator.equalsIgnoreCase("Iris")) {
|
||||
generator = IrisSettings.get().getGenerator().getDefaultWorldType();
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
Iris.info("2 World: %s | Generator: %s", s, generator);
|
||||
|
||||
if (Bukkit.getWorlds().stream().anyMatch(w -> w.getName().equals(s))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Iris.info(C.LIGHT_PURPLE + "Preparing Spawn for " + s + "' using Iris:" + generator + "...");
|
||||
new WorldCreator(s)
|
||||
.generator(getDefaultWorldGenerator(s, generator))
|
||||
.environment(IrisData.loadAnyDimension(generator).getEnvironment())
|
||||
.createWorld();
|
||||
Iris.info(C.LIGHT_PURPLE + "Loaded " + s + "!");
|
||||
} catch (Exception e) {
|
||||
Iris.info(C.DARK_GRAY + "------------------------------------------");
|
||||
Iris.info(C.RED + "Failed to load " + C.GRAY + s);
|
||||
Iris.info(C.DARK_GRAY + "------------------------------------------");
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void autoStartStudio() {
|
||||
if (IrisSettings.get().getStudio().isAutoStartDefaultStudio()) {
|
||||
Iris.info("Starting up auto Studio!");
|
||||
try {
|
||||
Player r = new KList<>(getServer().getOnlinePlayers()).getRandom();
|
||||
Iris.service(StudioSVC.class).open(r != null ? new VolmitSender(r) : getSender(), 1337, IrisSettings.get().getGenerator().getDefaultWorldType(), (w) -> {
|
||||
J.s(() -> {
|
||||
for (Player i : getServer().getOnlinePlayers()) {
|
||||
i.setGameMode(GameMode.SPECTATOR);
|
||||
i.teleport(new Location(w, 0, 200, 0));
|
||||
}
|
||||
});
|
||||
});
|
||||
} catch (IrisException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setupAudience() {
|
||||
try {
|
||||
audiences = BukkitAudiences.create(this);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
IrisSettings.get().getGeneral().setUseConsoleCustomColors(false);
|
||||
IrisSettings.get().getGeneral().setUseCustomColorsIngame(false);
|
||||
Iris.error("Failed to setup Adventure API... No custom colors :(");
|
||||
}
|
||||
}
|
||||
|
||||
public void postShutdown(Runnable r) {
|
||||
postShutdown.add(r);
|
||||
}
|
||||
|
||||
public void onEnable() {
|
||||
enable();
|
||||
super.onEnable();
|
||||
Bukkit.getPluginManager().registerEvents(this, this);
|
||||
setupChecks();
|
||||
}
|
||||
|
||||
public void onDisable() {
|
||||
Bukkit.getWorlds().stream()
|
||||
.filter(IrisToolbelt::isIrisWorld)
|
||||
.forEach(w -> {
|
||||
Engine engine = IrisToolbelt.access(w).getEngine();
|
||||
engine.close();
|
||||
});
|
||||
services.values().forEach(IrisService::onDisable);
|
||||
Bukkit.getScheduler().cancelTasks(this);
|
||||
HandlerList.unregisterAll((Plugin) this);
|
||||
postShutdown.forEach(Runnable::run);
|
||||
services.clear();
|
||||
MultiBurst.burst.close();
|
||||
super.onDisable();
|
||||
}
|
||||
|
||||
private void setupPapi() {
|
||||
if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null) {
|
||||
new IrisPapiExpansion().register();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTag(String subTag) {
|
||||
if (IrisSafeguard.instance.unstablemode) {
|
||||
return C.BOLD + "" + C.DARK_GRAY + "[" + C.BOLD + "" + C.RED + "Iris" + C.BOLD + C.DARK_GRAY + "]" + C.RESET + "" + C.GRAY + ": ";
|
||||
}
|
||||
if (IrisSafeguard.instance.warningmode) {
|
||||
return C.BOLD + "" + C.DARK_GRAY + "[" + C.BOLD + "" + C.GOLD + "Iris" + C.BOLD + C.DARK_GRAY + "]" + C.RESET + "" + C.GRAY + ": ";
|
||||
}
|
||||
return C.BOLD + "" + C.DARK_GRAY + "[" + C.BOLD + "" + C.IRIS + "Iris" + C.BOLD + C.DARK_GRAY + "]" + C.RESET + "" + C.GRAY + ": ";
|
||||
|
||||
}
|
||||
|
||||
private boolean setupChecks() {
|
||||
boolean passed = true;
|
||||
Iris.info("Server type & version: " + instance.getServer().getVersion() + " | " + instance.getServer().getBukkitVersion());
|
||||
if (INMS.get() instanceof NMSBinding1X) {
|
||||
passed = false;
|
||||
Iris.warn("============================================");
|
||||
Iris.warn("=");
|
||||
Iris.warn("=");
|
||||
Iris.warn("=");
|
||||
Iris.warn("Iris is not compatible with this version of Minecraft.");
|
||||
Iris.warn("=");
|
||||
Iris.warn("=");
|
||||
Iris.warn("=");
|
||||
Iris.warn("============================================");
|
||||
}
|
||||
if (!instance.getServer().getVersion().contains("Purpur")) {
|
||||
passed = false;
|
||||
Iris.info("We recommend using Purpur for the best experience with Iris.");
|
||||
Iris.info("Purpur is a fork of Paper that is optimized for performance and stability.");
|
||||
Iris.info("Plugins that work on Spigot / Paper work on Purpur.");
|
||||
Iris.info("You can download it here: https://purpurmc.org");
|
||||
}
|
||||
return passed;
|
||||
}
|
||||
|
||||
private void checkConfigHotload() {
|
||||
if (configWatcher.checkModified()) {
|
||||
IrisSettings.invalidate();
|
||||
IrisSettings.get();
|
||||
configWatcher.checkModified();
|
||||
Iris.info("Hotloaded settings.json ");
|
||||
}
|
||||
}
|
||||
|
||||
private void tickQueue() {
|
||||
synchronized (Iris.syncJobs) {
|
||||
if (!Iris.syncJobs.hasNext()) {
|
||||
return;
|
||||
}
|
||||
|
||||
long ms = M.ms();
|
||||
|
||||
while (Iris.syncJobs.hasNext() && M.ms() - ms < 25) {
|
||||
try {
|
||||
Iris.syncJobs.next().run();
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
Iris.reportError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void bstats() {
|
||||
if (IrisSettings.get().getGeneral().isPluginMetrics()) {
|
||||
J.s(() -> new Metrics(Iris.instance, 8757));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
return super.onCommand(sender, command, label, args);
|
||||
}
|
||||
|
||||
public void imsg(CommandSender s, String msg) {
|
||||
s.sendMessage(C.IRIS + "[" + C.DARK_GRAY + "Iris" + C.IRIS + "]" + C.GRAY + ": " + msg);
|
||||
}
|
||||
|
||||
private void installMainDimension() {
|
||||
try {
|
||||
Properties props = new Properties();
|
||||
props.load(new FileInputStream("server.properties"));
|
||||
String world = props.getProperty("level-name");
|
||||
if (world == null) return;
|
||||
|
||||
FileConfiguration fc = new YamlConfiguration();
|
||||
fc.load(new File("bukkit.yml"));
|
||||
String id = fc.getString("worlds." + world + ".generator");
|
||||
if (id.startsWith("Iris:")) {
|
||||
id = id.split("\\Q:\\E")[1];
|
||||
} else if (id.equalsIgnoreCase("Iris")) {
|
||||
id = IrisSettings.get().getGenerator().getDefaultWorldType();
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
IrisDimension dim;
|
||||
if (id == null || id.isEmpty()) {
|
||||
dim = IrisData.loadAnyDimension(IrisSettings.get().getGenerator().getDefaultWorldType());
|
||||
} else {
|
||||
dim = IrisData.loadAnyDimension(id);
|
||||
}
|
||||
|
||||
File w = new File(Bukkit.getWorldContainer(), world);
|
||||
File packFolder = new File(w, "/iris/pack");
|
||||
if (!packFolder.exists() || packFolder.listFiles().length == 0) {
|
||||
packFolder.mkdirs();
|
||||
service(StudioSVC.class).installIntoWorld(getSender(), dim.getLoadKey(), w);
|
||||
}
|
||||
if (packFolder.exists()) {
|
||||
IrisDimension worldDim = IrisData.get(packFolder).getDimensionLoader().load(id);
|
||||
if (worldDim != null) dim = worldDim;
|
||||
}
|
||||
|
||||
INMS.get().registerDimension("overworld", dim);
|
||||
} catch (Throwable e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BiomeProvider getDefaultBiomeProvider(@NotNull String worldName, @Nullable String id) {
|
||||
Iris.debug("Biome Provider Called for " + worldName + " using ID: " + id);
|
||||
return super.getDefaultBiomeProvider(worldName, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChunkGenerator getDefaultWorldGenerator(String worldName, String id) {
|
||||
Iris.debug("Default World Generator Called for " + worldName + " using ID: " + id);
|
||||
if (worldName.equals("test")) {
|
||||
try {
|
||||
throw new RuntimeException();
|
||||
} catch (Throwable e) {
|
||||
Iris.info(e.getStackTrace()[1].getClassName());
|
||||
if (e.getStackTrace()[1].getClassName().contains("com.onarandombox.MultiverseCore")) {
|
||||
Iris.debug("MVC Test detected, Quick! Send them the dummy!");
|
||||
return new DummyChunkGenerator();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IrisDimension dim;
|
||||
if (id == null || id.isEmpty()) {
|
||||
dim = IrisData.loadAnyDimension(IrisSettings.get().getGenerator().getDefaultWorldType());
|
||||
} else {
|
||||
dim = IrisData.loadAnyDimension(id);
|
||||
}
|
||||
Iris.debug("Generator ID: " + id + " requested by bukkit/plugin");
|
||||
|
||||
if (dim == null) {
|
||||
Iris.warn("Unable to find dimension type " + id + " Looking for online packs...");
|
||||
|
||||
service(StudioSVC.class).downloadSearch(new VolmitSender(Bukkit.getConsoleSender()), id, true);
|
||||
dim = IrisData.loadAnyDimension(id);
|
||||
|
||||
if (dim == null) {
|
||||
throw new RuntimeException("Can't find dimension " + id + "!");
|
||||
} else {
|
||||
Iris.info("Resolved missing dimension, proceeding with generation.");
|
||||
}
|
||||
}
|
||||
File packFolder = new File(Bukkit.getWorldContainer(), worldName + "/iris/pack");
|
||||
if (packFolder.exists()) {
|
||||
IrisDimension worldDim = IrisData.get(packFolder).getDimensionLoader().load(id);
|
||||
if (worldDim != null) dim = worldDim;
|
||||
}
|
||||
|
||||
Iris.debug("Assuming IrisDimension: " + dim.getName());
|
||||
|
||||
IrisWorld w = IrisWorld.builder()
|
||||
.name(worldName)
|
||||
.seed(1337)
|
||||
.environment(dim.getEnvironment())
|
||||
.worldFolder(new File(Bukkit.getWorldContainer(), worldName))
|
||||
.minHeight(dim.getMinHeight())
|
||||
.maxHeight(dim.getMaxHeight())
|
||||
.build();
|
||||
|
||||
Iris.debug("Generator Config: " + w.toString());
|
||||
|
||||
File ff = new File(w.worldFolder(), "iris/pack");
|
||||
if (!ff.exists() || ff.listFiles().length == 0) {
|
||||
ff.mkdirs();
|
||||
service(StudioSVC.class).installIntoWorld(getSender(), dim.getLoadKey(), w.worldFolder());
|
||||
}
|
||||
if (!INMS.get().registerDimension(worldName, dim)) {
|
||||
throw new IllegalStateException("Unable to register dimension " + dim.getName());
|
||||
}
|
||||
INMS.get().reconnectAll();
|
||||
|
||||
return new BukkitChunkGenerator(w, false, ff, dim.getLoadKey());
|
||||
}
|
||||
|
||||
public void splash() {
|
||||
if (!IrisSettings.get().getGeneral().isSplashLogoStartup()) {
|
||||
return;
|
||||
}
|
||||
|
||||
String padd = Form.repeat(" ", 8);
|
||||
String padd2 = Form.repeat(" ", 4);
|
||||
|
||||
String colorIris, colorVolmit, colorVersion;
|
||||
if (IrisSafeguard.instance.unstablemode) {
|
||||
colorIris = String.valueOf(C.RED);
|
||||
colorVolmit = String.valueOf(C.DARK_RED);
|
||||
colorVersion = String.valueOf(C.RED);
|
||||
} else if (IrisSafeguard.instance.warningmode) {
|
||||
colorIris = String.valueOf(C.GOLD);
|
||||
colorVolmit = String.valueOf(C.GOLD);
|
||||
colorVersion = String.valueOf(C.GOLD);
|
||||
} else {
|
||||
colorIris = String.valueOf(C.IRIS);
|
||||
colorVolmit = "<rainbow>";
|
||||
colorVersion = String.valueOf(C.IRIS);
|
||||
}
|
||||
|
||||
String[] info = {
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
padd2 + colorIris + " Iris",
|
||||
padd2 + C.GRAY + " by " + colorVolmit + "Volmit Software",
|
||||
padd2 + C.GRAY + " v" + colorVersion + getDescription().getVersion()
|
||||
};
|
||||
|
||||
String[] splash = {
|
||||
padd + C.GRAY + " @@@@@@@@@@@@@@" + C.DARK_GRAY + "@@@",
|
||||
padd + C.GRAY + " @@&&&&&&&&&" + C.DARK_GRAY + "&&&&&&" + colorIris + " .(((()))). ",
|
||||
padd + C.GRAY + "@@@&&&&&&&&" + C.DARK_GRAY + "&&&&&" + colorIris + " .((((((())))))). ",
|
||||
padd + C.GRAY + "@@@&&&&&" + C.DARK_GRAY + "&&&&&&&" + colorIris + " ((((((((())))))))) " + C.GRAY + " @",
|
||||
padd + C.GRAY + "@@@&&&&" + C.DARK_GRAY + "@@@@@&" + colorIris + " ((((((((-))))))))) " + C.GRAY + " @@",
|
||||
padd + C.GRAY + "@@@&&" + colorIris + " ((((((({ })))))))) " + C.GRAY + " &&@@@",
|
||||
padd + C.GRAY + "@@" + colorIris + " ((((((((-))))))))) " + C.DARK_GRAY + "&@@@@@" + C.GRAY + "&&&&@@@",
|
||||
padd + C.GRAY + "@" + colorIris + " ((((((((())))))))) " + C.DARK_GRAY + "&&&&&" + C.GRAY + "&&&&&&&@@@",
|
||||
padd + C.GRAY + "" + colorIris + " '((((((()))))))' " + C.DARK_GRAY + "&&&&&" + C.GRAY + "&&&&&&&&@@@",
|
||||
padd + C.GRAY + "" + colorIris + " '(((())))' " + C.DARK_GRAY + "&&&&&&&&" + C.GRAY + "&&&&&&&@@",
|
||||
padd + C.GRAY + " " + C.DARK_GRAY + "@@@" + C.GRAY + "@@@@@@@@@@@@@@"
|
||||
};
|
||||
|
||||
setupChecks();
|
||||
Iris.info("Java: " + getJava());
|
||||
if (!instance.getServer().getVersion().contains("Purpur")) {
|
||||
if (instance.getServer().getVersion().contains("Spigot") && instance.getServer().getVersion().contains("Bukkit")) {
|
||||
Iris.info(C.RED + " Iris requires paper or above to function properly..");
|
||||
} else {
|
||||
Iris.info(C.YELLOW + "Purpur is recommended to use with iris.");
|
||||
}
|
||||
}
|
||||
if (getHardware.getProcessMemory() < 5999) {
|
||||
Iris.warn("6GB+ Ram is recommended");
|
||||
Iris.warn("Process Memory: " + getHardware.getProcessMemory() + " MB");
|
||||
}
|
||||
Iris.info("Bukkit distro: " + Bukkit.getName());
|
||||
Iris.info("Custom Biomes: " + INMS.get().countCustomBiomes());
|
||||
printPacks();
|
||||
|
||||
for (int i = 0; i < info.length; i++) {
|
||||
splash[i] += info[i];
|
||||
}
|
||||
|
||||
Iris.info("\n\n " + new KList<>(splash).toString("\n") + "\n");
|
||||
}
|
||||
|
||||
private void printPacks() {
|
||||
File packFolder = Iris.service(StudioSVC.class).getWorkspaceFolder();
|
||||
File[] packs = packFolder.listFiles(File::isDirectory);
|
||||
if (packs == null || packs.length == 0)
|
||||
return;
|
||||
Iris.info("Custom Dimensions: " + packs.length);
|
||||
for (File f : packs)
|
||||
printPack(f);
|
||||
}
|
||||
|
||||
private void printPack(File pack) {
|
||||
String dimName = pack.getName();
|
||||
String version = "???";
|
||||
try (FileReader r = new FileReader(new File(pack, "dimensions/" + dimName + ".json"))) {
|
||||
JsonObject json = JsonParser.parseReader(r).getAsJsonObject();
|
||||
if (json.has("version"))
|
||||
version = json.get("version").getAsString();
|
||||
} catch (IOException | JsonParseException ignored) {
|
||||
}
|
||||
Iris.info(" " + dimName + " v" + version);
|
||||
}
|
||||
|
||||
public int getIrisVersion() {
|
||||
String input = Iris.instance.getDescription().getVersion();
|
||||
int hyphenIndex = input.indexOf('-');
|
||||
if (hyphenIndex != -1) {
|
||||
String result = input.substring(0, hyphenIndex);
|
||||
result = result.replaceAll("\\.", "");
|
||||
return Integer.parseInt(result);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public int getMCVersion() {
|
||||
try {
|
||||
String version = Bukkit.getVersion();
|
||||
Matcher matcher = Pattern.compile("\\(MC: ([\\d.]+)\\)").matcher(version);
|
||||
if (matcher.find()) {
|
||||
version = matcher.group(1).replaceAll("\\.", "");
|
||||
long versionNumber = Long.parseLong(version);
|
||||
if (versionNumber > Integer.MAX_VALUE) {
|
||||
return -1;
|
||||
}
|
||||
return (int) versionNumber;
|
||||
}
|
||||
return -1;
|
||||
} catch (Exception e) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -33,6 +33,7 @@ import java.io.IOException;
|
||||
@Data
|
||||
public class IrisSettings {
|
||||
public static IrisSettings settings;
|
||||
private IrisSafeGuard safeguard = new IrisSafeGuard();
|
||||
private IrisSettingsGeneral general = new IrisSettingsGeneral();
|
||||
private IrisSettingsWorld world = new IrisSettingsWorld();
|
||||
private IrisSettingsGUI gui = new IrisSettingsGUI();
|
||||
@@ -41,15 +42,75 @@ public class IrisSettings {
|
||||
private IrisSettingsConcurrency concurrency = new IrisSettingsConcurrency();
|
||||
private IrisSettingsStudio studio = new IrisSettingsStudio();
|
||||
private IrisSettingsPerformance performance = new IrisSettingsPerformance();
|
||||
private IrisWorldDump worldDump = new IrisWorldDump();
|
||||
private IrisWorldSettings irisWorldSettings = new IrisWorldSettings();
|
||||
private IrisServerSettings server = new IrisServerSettings();
|
||||
|
||||
public static int getThreadCount(int c) {
|
||||
return switch(c) {
|
||||
return switch (c) {
|
||||
case -1, -2, -4 -> Runtime.getRuntime().availableProcessors() / -c;
|
||||
case 0, 1, 2 -> 1;
|
||||
default -> Math.max(c, 2);
|
||||
};
|
||||
}
|
||||
|
||||
public static IrisSettings get() {
|
||||
if (settings != null) {
|
||||
return settings;
|
||||
}
|
||||
|
||||
settings = new IrisSettings();
|
||||
|
||||
File s = Iris.instance.getDataFile("settings.json");
|
||||
|
||||
if (!s.exists()) {
|
||||
try {
|
||||
IO.writeAll(s, new JSONObject(new Gson().toJson(settings)).toString(4));
|
||||
} catch (JSONException | IOException e) {
|
||||
e.printStackTrace();
|
||||
Iris.reportError(e);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
String ss = IO.readAll(s);
|
||||
settings = new Gson().fromJson(ss, IrisSettings.class);
|
||||
try {
|
||||
IO.writeAll(s, new JSONObject(new Gson().toJson(settings)).toString(4));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} catch (Throwable ee) {
|
||||
// Iris.reportError(ee); causes a self-reference & stackoverflow
|
||||
Iris.error("Configuration Error in settings.json! " + ee.getClass().getSimpleName() + ": " + ee.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
return settings;
|
||||
}
|
||||
|
||||
public static void invalidate() {
|
||||
synchronized (settings) {
|
||||
settings = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void forceSave() {
|
||||
File s = Iris.instance.getDataFile("settings.json");
|
||||
|
||||
try {
|
||||
IO.writeAll(s, new JSONObject(new Gson().toJson(settings)).toString(4));
|
||||
} catch (JSONException | IOException e) {
|
||||
e.printStackTrace();
|
||||
Iris.reportError(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class IrisSafeGuard {
|
||||
public boolean ignoreBootMode = false;
|
||||
public boolean userUnstableWarning = true;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class IrisSettingsAutoconfiguration {
|
||||
public boolean configureSpigotTimeoutTime = true;
|
||||
@@ -86,6 +147,7 @@ public class IrisSettings {
|
||||
public static class IrisSettingsPerformance {
|
||||
public boolean trimMantleInStudio = false;
|
||||
public int mantleKeepAlive = 30;
|
||||
public int headlessKeepAlive = 10;
|
||||
public int cacheSize = 4_096;
|
||||
public int resourceLoaderCacheSize = 1_024;
|
||||
public int objectLoaderCacheSize = 4_096;
|
||||
@@ -105,6 +167,9 @@ public class IrisSettings {
|
||||
public int spinh = -20;
|
||||
public int spins = 7;
|
||||
public int spinb = 8;
|
||||
public String cartographerMessage = "Iris does not allow cartographers in its world due to crashes.";
|
||||
public String[] dataPackPaths = new String[0];
|
||||
|
||||
|
||||
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
|
||||
public boolean canUseCustomColors(VolmitSender volmitSender) {
|
||||
@@ -116,6 +181,7 @@ public class IrisSettings {
|
||||
public static class IrisSettingsGUI {
|
||||
public boolean useServerLaunchedGuis = true;
|
||||
public boolean maximumPregenGuiFPS = false;
|
||||
public boolean colorMode = true;
|
||||
}
|
||||
|
||||
@Data
|
||||
@@ -133,54 +199,27 @@ public class IrisSettings {
|
||||
public boolean autoStartDefaultStudio = false;
|
||||
}
|
||||
|
||||
public static IrisSettings get() {
|
||||
if(settings != null) {
|
||||
return settings;
|
||||
}
|
||||
|
||||
settings = new IrisSettings();
|
||||
|
||||
File s = Iris.instance.getDataFile("settings.json");
|
||||
|
||||
if(!s.exists()) {
|
||||
try {
|
||||
IO.writeAll(s, new JSONObject(new Gson().toJson(settings)).toString(4));
|
||||
} catch(JSONException | IOException e) {
|
||||
e.printStackTrace();
|
||||
Iris.reportError(e);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
String ss = IO.readAll(s);
|
||||
settings = new Gson().fromJson(ss, IrisSettings.class);
|
||||
try {
|
||||
IO.writeAll(s, new JSONObject(new Gson().toJson(settings)).toString(4));
|
||||
} catch(IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} catch(Throwable ee) {
|
||||
// Iris.reportError(ee); causes a self-reference & stackoverflow
|
||||
Iris.error("Configuration Error in settings.json! " + ee.getClass().getSimpleName() + ": " + ee.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
return settings;
|
||||
@Data
|
||||
public static class IrisWorldDump {
|
||||
public int mcaCacheSize = 3;
|
||||
}
|
||||
|
||||
public static void invalidate() {
|
||||
synchronized(settings) {
|
||||
settings = null;
|
||||
@Data
|
||||
public static class IrisServerSettings {
|
||||
public boolean active = false;
|
||||
public int port = 1337;
|
||||
public String[] remote = new String[0];
|
||||
|
||||
public boolean isRemote() {
|
||||
return remote.length != 0;
|
||||
}
|
||||
}
|
||||
|
||||
public void forceSave() {
|
||||
File s = Iris.instance.getDataFile("settings.json");
|
||||
// todo: Goal:Have these as the default world settings and when put in bukkit.yml it will again overwrite that world from these.
|
||||
@Data
|
||||
public static class IrisWorldSettings {
|
||||
public boolean dynamicEntityAdjustments;
|
||||
|
||||
|
||||
try {
|
||||
IO.writeAll(s, new JSONObject(new Gson().toJson(settings)).toString(4));
|
||||
} catch(JSONException | IOException e) {
|
||||
e.printStackTrace();
|
||||
Iris.reportError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
132
core/src/main/java/com/volmit/iris/core/ServerConfigurator.java
Normal file
132
core/src/main/java/com/volmit/iris/core/ServerConfigurator.java
Normal file
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.loader.IrisData;
|
||||
import com.volmit.iris.core.nms.INMS;
|
||||
import com.volmit.iris.engine.object.IrisBiome;
|
||||
import com.volmit.iris.engine.object.IrisDimension;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class ServerConfigurator {
|
||||
public static void configure() {
|
||||
IrisSettings.IrisSettingsAutoconfiguration s = IrisSettings.get().getAutoConfiguration();
|
||||
if (s.isConfigureSpigotTimeoutTime()) {
|
||||
J.attempt(ServerConfigurator::increaseKeepAliveSpigot);
|
||||
}
|
||||
|
||||
if (s.isConfigurePaperWatchdogDelay()) {
|
||||
J.attempt(ServerConfigurator::increasePaperWatchdog);
|
||||
}
|
||||
}
|
||||
|
||||
private static void increaseKeepAliveSpigot() throws IOException, InvalidConfigurationException {
|
||||
File spigotConfig = new File("spigot.yml");
|
||||
FileConfiguration f = new YamlConfiguration();
|
||||
f.load(spigotConfig);
|
||||
long tt = f.getLong("settings.timeout-time");
|
||||
|
||||
if (tt < TimeUnit.MINUTES.toSeconds(5)) {
|
||||
Iris.warn("Updating spigot.yml timeout-time: " + tt + " -> " + TimeUnit.MINUTES.toSeconds(20) + " (5 minutes)");
|
||||
Iris.warn("You can disable this change (autoconfigureServer) in Iris settings, then change back the value.");
|
||||
f.set("settings.timeout-time", TimeUnit.MINUTES.toSeconds(5));
|
||||
f.save(spigotConfig);
|
||||
}
|
||||
}
|
||||
|
||||
private static void increasePaperWatchdog() throws IOException, InvalidConfigurationException {
|
||||
File spigotConfig = new File("config/paper-global.yml");
|
||||
FileConfiguration f = new YamlConfiguration();
|
||||
f.load(spigotConfig);
|
||||
long tt = f.getLong("watchdog.early-warning-delay");
|
||||
|
||||
if (tt < TimeUnit.MINUTES.toMillis(3)) {
|
||||
Iris.warn("Updating paper.yml watchdog early-warning-delay: " + tt + " -> " + TimeUnit.MINUTES.toMillis(15) + " (3 minutes)");
|
||||
Iris.warn("You can disable this change (autoconfigureServer) in Iris settings, then change back the value.");
|
||||
f.set("watchdog.early-warning-delay", TimeUnit.MINUTES.toMillis(3));
|
||||
f.save(spigotConfig);
|
||||
}
|
||||
}
|
||||
|
||||
private static File[] getDataPacksFolder() {
|
||||
KList<File> files = new KList<>();
|
||||
files.add(new File("plugins/Iris/datapack"));
|
||||
Arrays.stream(IrisSettings.get().getGeneral().dataPackPaths)
|
||||
.map(File::new)
|
||||
.forEach(files::add);
|
||||
return files.toArray(File[]::new);
|
||||
}
|
||||
|
||||
public static void setupDataPack() {
|
||||
File packs = new File("plugins/Iris/packs");
|
||||
if (!packs.exists()) {
|
||||
disableDataPack();
|
||||
return;
|
||||
}
|
||||
for (File i : packs.listFiles()) {
|
||||
if (!i.isDirectory()) continue;
|
||||
|
||||
Iris.verbose("Checking Pack: " + i.getPath());
|
||||
IrisData data = IrisData.get(i);
|
||||
File dims = new File(i, "dimensions");
|
||||
|
||||
if (dims.exists()) {
|
||||
for (File j : dims.listFiles((f, s) -> s.endsWith(".json"))) {
|
||||
if (!j.isFile()) continue;
|
||||
IrisDimension dim = data.getDimensionLoader().load(j.getName().split("\\Q.\\E")[0]);
|
||||
if (dim == null) continue;
|
||||
|
||||
dim.getAllBiomes(() -> data)
|
||||
.stream()
|
||||
.map(IrisBiome::getCustomDerivitives)
|
||||
.filter(Objects::nonNull)
|
||||
.flatMap(KList::stream)
|
||||
.forEach(b -> INMS.get().registerBiome(dim.getLoadKey(), b, false));
|
||||
}
|
||||
}
|
||||
}
|
||||
dumpDataPack();
|
||||
}
|
||||
|
||||
public static void dumpDataPack() {
|
||||
if (!INMS.get().dumpRegistry(getDataPacksFolder())) {
|
||||
return;
|
||||
}
|
||||
disableDataPack();
|
||||
}
|
||||
|
||||
public static void disableDataPack() {
|
||||
var packs = INMS.get().getPackRepository();
|
||||
packs.reload();
|
||||
if (!packs.removePack("file/iris"))
|
||||
return;
|
||||
packs.reloadWorldData();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,313 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.commands;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.loader.IrisData;
|
||||
import com.volmit.iris.core.tools.IrisPackBenchmarking;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.core.tools.IrisWorldDump;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.framework.EnginePlayer;
|
||||
import com.volmit.iris.engine.object.IrisDimension;
|
||||
import com.volmit.iris.engine.service.EngineStatusSVC;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.decree.DecreeExecutor;
|
||||
import com.volmit.iris.util.decree.DecreeOrigin;
|
||||
import com.volmit.iris.util.decree.annotations.Decree;
|
||||
import com.volmit.iris.util.decree.annotations.Param;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.io.IO;
|
||||
import com.volmit.iris.util.mantle.TectonicPlate;
|
||||
import com.volmit.iris.util.parallel.MultiBurst;
|
||||
import com.volmit.iris.util.plugin.VolmitSender;
|
||||
import net.jpountz.lz4.LZ4BlockInputStream;
|
||||
import net.jpountz.lz4.LZ4BlockOutputStream;
|
||||
import net.jpountz.lz4.LZ4FrameInputStream;
|
||||
import net.jpountz.lz4.LZ4FrameOutputStream;
|
||||
import org.apache.commons.lang.RandomStringUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.World;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.InetAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
@Decree(name = "Developer", origin = DecreeOrigin.BOTH, description = "Iris World Manager", aliases = {"dev"})
|
||||
public class CommandDeveloper implements DecreeExecutor {
|
||||
private CommandTurboPregen turboPregen;
|
||||
private CommandUpdater updater;
|
||||
|
||||
@Decree(description = "Get Loaded TectonicPlates Count", origin = DecreeOrigin.BOTH, aliases = "status", sync = true)
|
||||
public void EngineStatus() {
|
||||
var status = EngineStatusSVC.getStatus();
|
||||
|
||||
sender().sendMessage("-------------------------");
|
||||
sender().sendMessage(C.DARK_PURPLE + "Engine Status");
|
||||
sender().sendMessage(C.DARK_PURPLE + "Total Engines: " + C.LIGHT_PURPLE + status.engineCount());
|
||||
sender().sendMessage(C.DARK_PURPLE + "Total Loaded Chunks: " + C.LIGHT_PURPLE + status.loadedChunks());
|
||||
sender().sendMessage(C.DARK_PURPLE + "Tectonic Limit: " + C.LIGHT_PURPLE + status.tectonicLimit());
|
||||
sender().sendMessage(C.DARK_PURPLE + "Tectonic Total Plates: " + C.LIGHT_PURPLE + status.tectonicPlates());
|
||||
sender().sendMessage(C.DARK_PURPLE + "Tectonic Active Plates: " + C.LIGHT_PURPLE + status.activeTectonicPlates());
|
||||
sender().sendMessage(C.DARK_PURPLE + "Tectonic ToUnload: " + C.LIGHT_PURPLE + status.queuedTectonicPlates());
|
||||
sender().sendMessage(C.DARK_PURPLE + "Lowest Tectonic Unload Duration: " + C.LIGHT_PURPLE + Form.duration(status.minTectonicUnloadDuration()));
|
||||
sender().sendMessage(C.DARK_PURPLE + "Highest Tectonic Unload Duration: " + C.LIGHT_PURPLE + Form.duration(status.maxTectonicUnloadDuration()));
|
||||
sender().sendMessage(C.DARK_PURPLE + "Cache Size: " + C.LIGHT_PURPLE + Form.f(IrisData.cacheSize()));
|
||||
sender().sendMessage("-------------------------");
|
||||
}
|
||||
|
||||
@Decree(description = "Test")
|
||||
public void benchmarkMantle(
|
||||
@Param(description = "The world to bench", aliases = {"world"})
|
||||
World world
|
||||
) throws IOException, ClassNotFoundException {
|
||||
Engine engine = IrisToolbelt.access(world).getEngine();
|
||||
int maxHeight = engine.getTarget().getHeight();
|
||||
File folder = new File(Bukkit.getWorldContainer(), world.getName());
|
||||
int c = 0;
|
||||
//MCAUtil.read()
|
||||
|
||||
File tectonicplates = new File(folder, "mantle");
|
||||
for (File i : Objects.requireNonNull(tectonicplates.listFiles())) {
|
||||
TectonicPlate.read(maxHeight, i);
|
||||
c++;
|
||||
sender().sendMessage("Loaded count: " + c);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Decree(description = "Test")
|
||||
public void packBenchmark(
|
||||
@Param(description = "The pack to bench", defaultValue = "overworld", aliases = {"pack"})
|
||||
IrisDimension dimension,
|
||||
@Param(description = "The address to use", defaultValue = "-")
|
||||
String address,
|
||||
@Param(description = "Headless", defaultValue = "true")
|
||||
boolean headless,
|
||||
@Param(description = "GUI", defaultValue = "false")
|
||||
boolean gui,
|
||||
@Param(description = "Diameter in regions", defaultValue = "5")
|
||||
int diameter
|
||||
) {
|
||||
int rb = diameter << 9;
|
||||
Iris.info("Benchmarking pack " + dimension.getName() + " with diameter: " + rb + "(" + diameter + ")");
|
||||
IrisPackBenchmarking benchmark = new IrisPackBenchmarking(dimension, address.replace("-", "").trim(), diameter, headless, gui);
|
||||
benchmark.runBenchmark();
|
||||
}
|
||||
|
||||
@Decree(description = "test")
|
||||
public void mca(
|
||||
@Param(description = "String") World world) {
|
||||
try {
|
||||
IrisWorldDump dump = new IrisWorldDump(world, sender());
|
||||
dump.start();
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Decree(description = "test")
|
||||
public void test() {
|
||||
try {
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Decree(description = "UnloadChunks for good reasons.")
|
||||
public void unloadchunks() {
|
||||
List<World> IrisWorlds = new ArrayList<>();
|
||||
int chunksUnloaded = 0;
|
||||
for (World world : Bukkit.getWorlds()) {
|
||||
try {
|
||||
if (IrisToolbelt.access(world).getEngine() != null) {
|
||||
IrisWorlds.add(world);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// no
|
||||
}
|
||||
}
|
||||
|
||||
for (World world : IrisWorlds) {
|
||||
for (Chunk chunk : world.getLoadedChunks()) {
|
||||
if (chunk.isLoaded()) {
|
||||
chunk.unload();
|
||||
chunksUnloaded++;
|
||||
}
|
||||
}
|
||||
}
|
||||
Iris.info(C.IRIS + "Chunks Unloaded: " + chunksUnloaded);
|
||||
|
||||
}
|
||||
|
||||
@Decree
|
||||
public void objects(@Param(defaultValue = "overworld") IrisDimension dimension) {
|
||||
var loader = dimension.getLoader().getObjectLoader();
|
||||
var sender = sender();
|
||||
var keys = loader.getPossibleKeys();
|
||||
var burst = MultiBurst.burst.burst(keys.length);
|
||||
AtomicInteger failed = new AtomicInteger();
|
||||
for (String key : keys) {
|
||||
burst.queue(() -> {
|
||||
if (loader.load(key) == null)
|
||||
failed.incrementAndGet();
|
||||
});
|
||||
}
|
||||
burst.complete();
|
||||
sender.sendMessage(C.RED + "Failed to load " + failed.get() + " of " + keys.length + " objects");
|
||||
}
|
||||
|
||||
@Decree(description = "Test", aliases = {"ip"})
|
||||
public void network() {
|
||||
try {
|
||||
Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
|
||||
for (NetworkInterface ni : Collections.list(networkInterfaces)) {
|
||||
Iris.info("Display Name: %s", ni.getDisplayName());
|
||||
Enumeration<InetAddress> inetAddresses = ni.getInetAddresses();
|
||||
for (InetAddress ia : Collections.list(inetAddresses)) {
|
||||
Iris.info("IP: %s", ia.getHostAddress());
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(description = "All players in iris worlds")
|
||||
public void getPlayers() {
|
||||
KList<World> IrisWorlds = new KList<>();
|
||||
for (World w : Bukkit.getServer().getWorlds()) {
|
||||
if(IrisToolbelt.isIrisWorld(w)) {
|
||||
IrisWorlds.add(w);
|
||||
}
|
||||
}
|
||||
|
||||
if (sender().isPlayer()) {
|
||||
sender().sendMessage(C.BLUE + "Iris Worlds: ");
|
||||
for (World IrisWorld : IrisWorlds.copy()) {
|
||||
sender().sendMessage(C.IRIS + "- " + IrisWorld.getName() + C.GRAY + ", " + IrisToolbelt.access(IrisWorld).getEngine().getEnginePlayers().stream().count() + " players");
|
||||
for (EnginePlayer player : IrisToolbelt.access(IrisWorld).getEngine().getEnginePlayers()) {
|
||||
sender().sendMessage(C.DARK_GRAY + "> " + player.getPlayer().getName());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Iris.info(C.BLUE + "Iris Worlds: ");
|
||||
for (World IrisWorld : IrisWorlds.copy()) {
|
||||
Iris.info(C.IRIS + "- " + IrisWorld.getName() + C.GRAY + ", " + IrisToolbelt.access(IrisWorld).getEngine().getEnginePlayers().stream().count() + " players");
|
||||
for (EnginePlayer player : IrisToolbelt.access(IrisWorld).getEngine().getEnginePlayers()) {
|
||||
Iris.info(C.DARK_GRAY + "> " + player.getPlayer().getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(description = "Test the compression algorithms")
|
||||
public void compression(
|
||||
@Param(description = "base IrisWorld") World world,
|
||||
@Param(description = "raw TectonicPlate File") String path,
|
||||
@Param(description = "Algorithm to Test") String algorithm,
|
||||
@Param(description = "Amount of Tests") int amount) {
|
||||
if (!IrisToolbelt.isIrisWorld(world)) {
|
||||
sender().sendMessage(C.RED + "This is not an Iris world. Iris worlds: " + String.join(", ", Bukkit.getServer().getWorlds().stream().filter(IrisToolbelt::isIrisWorld).map(World::getName).toList()));
|
||||
return;
|
||||
}
|
||||
|
||||
File file = new File(path);
|
||||
if (!file.exists()) return;
|
||||
|
||||
Engine engine = IrisToolbelt.access(world).getEngine();
|
||||
if (engine != null) {
|
||||
int height = engine.getTarget().getHeight();
|
||||
VolmitSender sender = sender();
|
||||
new Thread(() -> {
|
||||
try {
|
||||
DataInputStream raw = new DataInputStream(new FileInputStream(file));
|
||||
TectonicPlate plate = new TectonicPlate(height, raw);
|
||||
raw.close();
|
||||
|
||||
double d1 = 0;
|
||||
double d2 = 0;
|
||||
long size = 0;
|
||||
File folder = new File("tmp");
|
||||
folder.mkdirs();
|
||||
for (int i = 0; i < amount; i++) {
|
||||
File tmp = new File(folder, RandomStringUtils.randomAlphanumeric(10) + "." + algorithm + ".bin");
|
||||
DataOutputStream dos = createOutput(tmp, algorithm);
|
||||
long start = System.currentTimeMillis();
|
||||
plate.write(dos);
|
||||
dos.close();
|
||||
d1 += System.currentTimeMillis() - start;
|
||||
if (size == 0)
|
||||
size = tmp.length();
|
||||
start = System.currentTimeMillis();
|
||||
DataInputStream din = createInput(tmp, algorithm);
|
||||
new TectonicPlate(height, din);
|
||||
din.close();
|
||||
d2 += System.currentTimeMillis() - start;
|
||||
tmp.delete();
|
||||
}
|
||||
IO.delete(folder);
|
||||
sender.sendMessage(algorithm + " is " + Form.fileSize(size) + " big after compression");
|
||||
sender.sendMessage(algorithm + " Took " + d2 / amount + "ms to read");
|
||||
sender.sendMessage(algorithm + " Took " + d1 / amount + "ms to write");
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}, "Compression Test").start();
|
||||
} else {
|
||||
Iris.info(C.RED + "Engine is null!");
|
||||
}
|
||||
}
|
||||
|
||||
private DataInputStream createInput(File file, String algorithm) throws Throwable {
|
||||
FileInputStream in = new FileInputStream(file);
|
||||
|
||||
return new DataInputStream(switch (algorithm) {
|
||||
case "gzip" -> new GZIPInputStream(in);
|
||||
case "lz4f" -> new LZ4FrameInputStream(in);
|
||||
case "lz4b" -> new LZ4BlockInputStream(in);
|
||||
default -> throw new IllegalStateException("Unexpected value: " + algorithm);
|
||||
});
|
||||
}
|
||||
|
||||
private DataOutputStream createOutput(File file, String algorithm) throws Throwable {
|
||||
FileOutputStream out = new FileOutputStream(file);
|
||||
|
||||
return new DataOutputStream(switch (algorithm) {
|
||||
case "gzip" -> new GZIPOutputStream(out);
|
||||
case "lz4f" -> new LZ4FrameOutputStream(out);
|
||||
case "lz4b" -> new LZ4BlockOutputStream(out);
|
||||
default -> throw new IllegalStateException("Unexpected value: " + algorithm);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -19,36 +19,34 @@
|
||||
package com.volmit.iris.core.commands;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.nms.INMS;
|
||||
import com.volmit.iris.core.service.StudioSVC;
|
||||
import com.volmit.iris.engine.object.IrisBiome;
|
||||
import com.volmit.iris.engine.object.IrisCave;
|
||||
import com.volmit.iris.engine.object.IrisDimension;
|
||||
import com.volmit.iris.engine.object.IrisJigsawPiece;
|
||||
import com.volmit.iris.engine.object.IrisJigsawPool;
|
||||
import com.volmit.iris.engine.object.IrisJigsawStructure;
|
||||
import com.volmit.iris.engine.object.IrisRegion;
|
||||
import com.volmit.iris.engine.object.*;
|
||||
import com.volmit.iris.util.decree.DecreeExecutor;
|
||||
import com.volmit.iris.util.decree.DecreeOrigin;
|
||||
import com.volmit.iris.util.decree.annotations.Decree;
|
||||
import com.volmit.iris.util.decree.annotations.Param;
|
||||
import com.volmit.iris.util.decree.specialhandlers.NullableBiomeHandler;
|
||||
import com.volmit.iris.util.decree.specialhandlers.NullableRegionHandler;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import org.bukkit.block.Biome;
|
||||
|
||||
import java.awt.Desktop;
|
||||
import java.awt.*;
|
||||
|
||||
|
||||
@Decree(name = "edit", origin = DecreeOrigin.PLAYER, studio = true, description = "Edit something")
|
||||
public class CommandEdit implements DecreeExecutor {
|
||||
|
||||
private boolean noStudio() {
|
||||
if(!sender().isPlayer()) {
|
||||
if (!sender().isPlayer()) {
|
||||
sender().sendMessage(C.RED + "Players only!");
|
||||
return true;
|
||||
}
|
||||
if(!Iris.service(StudioSVC.class).isProjectOpen()) {
|
||||
if (!Iris.service(StudioSVC.class).isProjectOpen()) {
|
||||
sender().sendMessage(C.RED + "No studio world is open!");
|
||||
return true;
|
||||
}
|
||||
if(!engine().isStudio()) {
|
||||
if (!engine().isStudio()) {
|
||||
sender().sendMessage(C.RED + "You must be in a studio world!");
|
||||
return true;
|
||||
}
|
||||
@@ -57,36 +55,65 @@ public class CommandEdit implements DecreeExecutor {
|
||||
|
||||
|
||||
@Decree(description = "Edit the biome you specified", aliases = {"b"}, origin = DecreeOrigin.PLAYER)
|
||||
public void biome(@Param(contextual = false, description = "The biome to edit") IrisBiome biome) {
|
||||
if(noStudio()) {
|
||||
public void biome(@Param(contextual = false, description = "The biome to edit", defaultValue = "---", customHandler = NullableBiomeHandler.class) IrisBiome biome) {
|
||||
if (noStudio()) {
|
||||
return;
|
||||
}
|
||||
if (biome == null) {
|
||||
try {
|
||||
IrisBiome b = engine().getBiome(player().getLocation().getBlockX(), player().getLocation().getBlockY() - player().getWorld().getMinHeight(), player().getLocation().getBlockZ());
|
||||
Desktop.getDesktop().open(b.getLoadFile());
|
||||
sender().sendMessage(C.GREEN + "Opening " + b.getTypeName() + " " + b.getLoadFile().getName().split("\\Q.\\E")[0] + " in VSCode! ");
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
sender().sendMessage("Non-Iris Biome: " + player().getLocation().getBlock().getBiome().name());
|
||||
if (player().getLocation().getBlock().getBiome().equals(Biome.CUSTOM)) {
|
||||
try {
|
||||
sender().sendMessage("Data Pack Biome: " + INMS.get().getTrueBiomeBaseKey(player().getLocation()) + " (ID: " + INMS.get().getTrueBiomeBaseId(INMS.get().getTrueBiomeBase(player().getLocation())) + ")");
|
||||
} catch (Throwable ee) {
|
||||
Iris.reportError(ee);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if(biome == null || biome.getLoadFile() == null) {
|
||||
if (biome.getLoadFile() == null) {
|
||||
sender().sendMessage(C.GOLD + "Cannot find the file; Perhaps it was not loaded directly from a file?");
|
||||
return;
|
||||
}
|
||||
Desktop.getDesktop().open(biome.getLoadFile());
|
||||
sender().sendMessage(C.GREEN + "Opening " + biome.getTypeName() + " " + biome.getLoadFile().getName().split("\\Q.\\E")[0] + " in VSCode! ");
|
||||
} catch(Throwable e) {
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
sender().sendMessage(C.RED + "Cant find the file. Or registrant does not exist");
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(description = "Edit the region you specified", aliases = {"r"}, origin = DecreeOrigin.PLAYER)
|
||||
public void region(@Param(contextual = false, description = "The region to edit") IrisRegion region) {
|
||||
if(noStudio()) {
|
||||
public void region(@Param(contextual = false, description = "The region to edit", defaultValue = "---", customHandler = NullableRegionHandler.class) IrisRegion region) {
|
||||
if (noStudio()) {
|
||||
return;
|
||||
}
|
||||
if (region == null) {
|
||||
try {
|
||||
IrisRegion r = engine().getRegion(player().getLocation().getBlockX(), player().getLocation().getBlockZ());
|
||||
Desktop.getDesktop().open(r.getLoadFile());
|
||||
sender().sendMessage(C.GREEN + "Opening " + r.getTypeName() + " " + r.getLoadFile().getName().split("\\Q.\\E")[0] + " in VSCode! ");
|
||||
} catch (Throwable e) {
|
||||
sender().sendMessage(C.RED + "Failed to get region.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if(region == null || region.getLoadFile() == null) {
|
||||
if (region == null || region.getLoadFile() == null) {
|
||||
sender().sendMessage(C.GOLD + "Cannot find the file; Perhaps it was not loaded directly from a file?");
|
||||
return;
|
||||
}
|
||||
Desktop.getDesktop().open(region.getLoadFile());
|
||||
sender().sendMessage(C.GREEN + "Opening " + region.getTypeName() + " " + region.getLoadFile().getName().split("\\Q.\\E")[0] + " in VSCode! ");
|
||||
} catch(Throwable e) {
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
sender().sendMessage(C.RED + "Cant find the file. Or registrant does not exist");
|
||||
}
|
||||
@@ -94,17 +121,17 @@ public class CommandEdit implements DecreeExecutor {
|
||||
|
||||
@Decree(description = "Edit the dimension you specified", aliases = {"d"}, origin = DecreeOrigin.PLAYER)
|
||||
public void dimension(@Param(contextual = false, description = "The dimension to edit") IrisDimension dimension) {
|
||||
if(noStudio()) {
|
||||
if (noStudio()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if(dimension == null || dimension.getLoadFile() == null) {
|
||||
if (dimension == null || dimension.getLoadFile() == null) {
|
||||
sender().sendMessage(C.GOLD + "Cannot find the file; Perhaps it was not loaded directly from a file?");
|
||||
return;
|
||||
}
|
||||
Desktop.getDesktop().open(dimension.getLoadFile());
|
||||
sender().sendMessage(C.GREEN + "Opening " + dimension.getTypeName() + " " + dimension.getLoadFile().getName().split("\\Q.\\E")[0] + " in VSCode! ");
|
||||
} catch(Throwable e) {
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
sender().sendMessage(C.RED + "Cant find the file. Or registrant does not exist");
|
||||
}
|
||||
@@ -112,17 +139,17 @@ public class CommandEdit implements DecreeExecutor {
|
||||
|
||||
@Decree(description = "Edit the cave file you specified", aliases = {"c"}, origin = DecreeOrigin.PLAYER)
|
||||
public void cave(@Param(contextual = false, description = "The cave to edit") IrisCave cave) {
|
||||
if(noStudio()) {
|
||||
if (noStudio()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if(cave == null || cave.getLoadFile() == null) {
|
||||
if (cave == null || cave.getLoadFile() == null) {
|
||||
sender().sendMessage(C.GOLD + "Cannot find the file; Perhaps it was not loaded directly from a file?");
|
||||
return;
|
||||
}
|
||||
Desktop.getDesktop().open(cave.getLoadFile());
|
||||
sender().sendMessage(C.GREEN + "Opening " + cave.getTypeName() + " " + cave.getLoadFile().getName().split("\\Q.\\E")[0] + " in VSCode! ");
|
||||
} catch(Throwable e) {
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
sender().sendMessage(C.RED + "Cant find the file. Or registrant does not exist");
|
||||
}
|
||||
@@ -130,17 +157,17 @@ public class CommandEdit implements DecreeExecutor {
|
||||
|
||||
@Decree(description = "Edit the structure file you specified", aliases = {"jigsawstructure", "structure"}, origin = DecreeOrigin.PLAYER)
|
||||
public void jigsaw(@Param(contextual = false, description = "The jigsaw structure to edit") IrisJigsawStructure jigsaw) {
|
||||
if(noStudio()) {
|
||||
if (noStudio()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if(jigsaw == null || jigsaw.getLoadFile() == null) {
|
||||
if (jigsaw == null || jigsaw.getLoadFile() == null) {
|
||||
sender().sendMessage(C.GOLD + "Cannot find the file; Perhaps it was not loaded directly from a file?");
|
||||
return;
|
||||
}
|
||||
Desktop.getDesktop().open(jigsaw.getLoadFile());
|
||||
sender().sendMessage(C.GREEN + "Opening " + jigsaw.getTypeName() + " " + jigsaw.getLoadFile().getName().split("\\Q.\\E")[0] + " in VSCode! ");
|
||||
} catch(Throwable e) {
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
sender().sendMessage(C.RED + "Cant find the file. Or registrant does not exist");
|
||||
}
|
||||
@@ -148,17 +175,17 @@ public class CommandEdit implements DecreeExecutor {
|
||||
|
||||
@Decree(description = "Edit the pool file you specified", aliases = {"jigsawpool", "pool"}, origin = DecreeOrigin.PLAYER)
|
||||
public void jigsawPool(@Param(contextual = false, description = "The jigsaw pool to edit") IrisJigsawPool pool) {
|
||||
if(noStudio()) {
|
||||
if (noStudio()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if(pool == null || pool.getLoadFile() == null) {
|
||||
if (pool == null || pool.getLoadFile() == null) {
|
||||
sender().sendMessage(C.GOLD + "Cannot find the file; Perhaps it was not loaded directly from a file?");
|
||||
return;
|
||||
}
|
||||
Desktop.getDesktop().open(pool.getLoadFile());
|
||||
sender().sendMessage(C.GREEN + "Opening " + pool.getTypeName() + " " + pool.getLoadFile().getName().split("\\Q.\\E")[0] + " in VSCode! ");
|
||||
} catch(Throwable e) {
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
sender().sendMessage(C.RED + "Cant find the file. Or registrant does not exist");
|
||||
}
|
||||
@@ -166,17 +193,17 @@ public class CommandEdit implements DecreeExecutor {
|
||||
|
||||
@Decree(description = "Edit the jigsaw piece file you specified", aliases = {"jigsawpiece", "piece"}, origin = DecreeOrigin.PLAYER)
|
||||
public void jigsawPiece(@Param(contextual = false, description = "The jigsaw piece to edit") IrisJigsawPiece piece) {
|
||||
if(noStudio()) {
|
||||
if (noStudio()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if(piece == null || piece.getLoadFile() == null) {
|
||||
if (piece == null || piece.getLoadFile() == null) {
|
||||
sender().sendMessage(C.GOLD + "Cannot find the file; Perhaps it was not loaded directly from a file?");
|
||||
return;
|
||||
}
|
||||
Desktop.getDesktop().open(piece.getLoadFile());
|
||||
sender().sendMessage(C.GREEN + "Opening " + piece.getTypeName() + " " + piece.getLoadFile().getName().split("\\Q.\\E")[0] + " in VSCode! ");
|
||||
} catch(Throwable e) {
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
sender().sendMessage(C.RED + "Cant find the file. Or registrant does not exist");
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -33,61 +33,85 @@ import com.volmit.iris.util.format.C;
|
||||
public class CommandFind implements DecreeExecutor {
|
||||
@Decree(description = "Find a biome")
|
||||
public void biome(
|
||||
@Param(description = "The biome to look for")
|
||||
IrisBiome biome
|
||||
@Param(description = "The biome to look for")
|
||||
IrisBiome biome,
|
||||
@Param(description = "Should you be teleported", defaultValue = "true")
|
||||
boolean teleport
|
||||
) {
|
||||
Engine e = engine();
|
||||
|
||||
if(e == null) {
|
||||
if (e == null) {
|
||||
sender().sendMessage(C.GOLD + "Not in an Iris World!");
|
||||
return;
|
||||
}
|
||||
|
||||
e.gotoBiome(biome, player());
|
||||
e.gotoBiome(biome, player(), teleport);
|
||||
}
|
||||
|
||||
@Decree(description = "Find a region")
|
||||
public void region(
|
||||
@Param(description = "The region to look for")
|
||||
IrisRegion region
|
||||
@Param(description = "The region to look for")
|
||||
IrisRegion region,
|
||||
@Param(description = "Should you be teleported", defaultValue = "true")
|
||||
boolean teleport
|
||||
) {
|
||||
Engine e = engine();
|
||||
|
||||
if(e == null) {
|
||||
if (e == null) {
|
||||
sender().sendMessage(C.GOLD + "Not in an Iris World!");
|
||||
return;
|
||||
}
|
||||
|
||||
e.gotoRegion(region, player());
|
||||
e.gotoRegion(region, player(), teleport);
|
||||
}
|
||||
|
||||
@Decree(description = "Find a structure")
|
||||
public void structure(
|
||||
@Param(description = "The structure to look for")
|
||||
IrisJigsawStructure structure
|
||||
@Param(description = "The structure to look for")
|
||||
IrisJigsawStructure structure,
|
||||
@Param(description = "Should you be teleported", defaultValue = "true")
|
||||
boolean teleport
|
||||
) {
|
||||
Engine e = engine();
|
||||
|
||||
if(e == null) {
|
||||
if (e == null) {
|
||||
sender().sendMessage(C.GOLD + "Not in an Iris World!");
|
||||
return;
|
||||
}
|
||||
|
||||
e.gotoJigsaw(structure, player());
|
||||
e.gotoJigsaw(structure, player(), teleport);
|
||||
}
|
||||
|
||||
@Decree(description = "Find a point of interest.")
|
||||
public void poi(
|
||||
@Param(description = "The type of PoI to look for.")
|
||||
String type,
|
||||
@Param(description = "Should you be teleported", defaultValue = "true")
|
||||
boolean teleport
|
||||
) {
|
||||
Engine e = engine();
|
||||
if (e == null) {
|
||||
sender().sendMessage(C.GOLD + "Not in an Iris World!");
|
||||
return;
|
||||
}
|
||||
|
||||
e.gotoPOI(type, player(), teleport);
|
||||
}
|
||||
|
||||
@Decree(description = "Find an object")
|
||||
public void object(
|
||||
@Param(description = "The object to look for", customHandler = ObjectHandler.class)
|
||||
String object
|
||||
@Param(description = "The object to look for", customHandler = ObjectHandler.class)
|
||||
String object,
|
||||
@Param(description = "Should you be teleported", defaultValue = "true")
|
||||
boolean teleport
|
||||
) {
|
||||
Engine e = engine();
|
||||
|
||||
if(e == null) {
|
||||
if (e == null) {
|
||||
sender().sendMessage(C.GOLD + "Not in an Iris World!");
|
||||
return;
|
||||
}
|
||||
|
||||
e.gotoObject(object, player());
|
||||
e.gotoObject(object, player(), teleport);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,650 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.commands;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.loader.IrisData;
|
||||
import com.volmit.iris.core.pregenerator.ChunkUpdater;
|
||||
import com.volmit.iris.core.service.StudioSVC;
|
||||
import com.volmit.iris.core.tools.IrisBenchmarking;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.object.IrisDimension;
|
||||
import com.volmit.iris.engine.object.IrisWorld;
|
||||
import com.volmit.iris.engine.platform.BukkitChunkGenerator;
|
||||
import com.volmit.iris.engine.platform.DummyChunkGenerator;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.decree.DecreeExecutor;
|
||||
import com.volmit.iris.util.decree.DecreeOrigin;
|
||||
import com.volmit.iris.util.decree.annotations.Decree;
|
||||
import com.volmit.iris.util.decree.annotations.Param;
|
||||
import com.volmit.iris.util.decree.specialhandlers.NullablePlayerHandler;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.plugin.VolmitSender;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.filefilter.IOFileFilter;
|
||||
import org.apache.commons.io.filefilter.TrueFileFilter;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.WorldCreator;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static com.volmit.iris.Iris.service;
|
||||
import static com.volmit.iris.core.service.EditSVC.deletingWorld;
|
||||
import static com.volmit.iris.core.tools.IrisBenchmarking.inProgress;
|
||||
import static org.bukkit.Bukkit.getServer;
|
||||
|
||||
@Decree(name = "iris", aliases = {"ir", "irs"}, description = "Basic Command")
|
||||
public class CommandIris implements DecreeExecutor {
|
||||
public static boolean worldCreation = false;
|
||||
String WorldEngine;
|
||||
String worldNameToCheck = "YourWorldName";
|
||||
VolmitSender sender = Iris.getSender();
|
||||
private CommandStudio studio;
|
||||
private CommandPregen pregen;
|
||||
private CommandSettings settings;
|
||||
private CommandObject object;
|
||||
private CommandJigsaw jigsaw;
|
||||
private CommandWhat what;
|
||||
private CommandEdit edit;
|
||||
private CommandFind find;
|
||||
private CommandSupport support;
|
||||
private CommandDeveloper developer;
|
||||
|
||||
public static boolean deleteDirectory(File dir) {
|
||||
if (dir.isDirectory()) {
|
||||
File[] children = dir.listFiles();
|
||||
for (int i = 0; i < children.length; i++) {
|
||||
boolean success = deleteDirectory(children[i]);
|
||||
if (!success) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return dir.delete();
|
||||
}
|
||||
|
||||
@Decree(description = "Create a new world", aliases = {"+", "c"})
|
||||
public void create(
|
||||
@Param(aliases = "world-name", description = "The name of the world to create")
|
||||
String name,
|
||||
@Param(aliases = "dimension", description = "The dimension type to create the world with", defaultValue = "default")
|
||||
IrisDimension type,
|
||||
@Param(description = "The seed to generate the world with", defaultValue = "1337")
|
||||
long seed,
|
||||
@Param(description = "The radius of chunks to generate in headless mode (-1 to disable)", defaultValue = "10", aliases = "radius")
|
||||
int headlessRadius,
|
||||
@Param(description = "If it should convert the dimension to match the vanilla height system.", defaultValue = "false")
|
||||
boolean vanillaheight
|
||||
) {
|
||||
|
||||
if (name.equals("iris")) {
|
||||
sender().sendMessage(C.RED + "You cannot use the world name \"iris\" for creating worlds as Iris uses this directory for studio worlds.");
|
||||
sender().sendMessage(C.RED + "May we suggest the name \"IrisWorld\" instead?");
|
||||
return;
|
||||
}
|
||||
if (name.equals("Benchmark")) {
|
||||
sender().sendMessage(C.RED + "You cannot use the world name \"Benchmark\" for creating worlds as Iris uses this directory for Benchmarking Packs.");
|
||||
sender().sendMessage(C.RED + "May we suggest the name \"IrisWorld\" instead?");
|
||||
return;
|
||||
}
|
||||
|
||||
if (new File(Bukkit.getWorldContainer(), name).exists()) {
|
||||
sender().sendMessage(C.RED + "That folder already exists!");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
worldCreation = true;
|
||||
IrisToolbelt.createWorld()
|
||||
.dimension(type.getLoadKey())
|
||||
.name(name)
|
||||
.seed(seed)
|
||||
.sender(sender())
|
||||
.studio(false)
|
||||
.headlessRadius(headlessRadius)
|
||||
.create();
|
||||
} catch (Throwable e) {
|
||||
sender().sendMessage(C.RED + "Exception raised during creation. See the console for more details.");
|
||||
Iris.error("Exception raised during world creation: " + e.getMessage());
|
||||
Iris.reportError(e);
|
||||
worldCreation = false;
|
||||
return;
|
||||
}
|
||||
worldCreation = false;
|
||||
sender().sendMessage(C.GREEN + "Successfully created your world!");
|
||||
}
|
||||
|
||||
@Decree(description = "Teleport to another world", aliases = {"tp"}, sync = true)
|
||||
public void teleport(
|
||||
@Param(description = "World to teleport to")
|
||||
World world,
|
||||
@Param(description = "Player to teleport", defaultValue = "---", customHandler = NullablePlayerHandler.class)
|
||||
Player player
|
||||
) {
|
||||
if (player == null && sender().isPlayer())
|
||||
player = sender().player();
|
||||
|
||||
final Player target = player;
|
||||
if (target == null) {
|
||||
sender().sendMessage(C.RED + "The specified player does not exist.");
|
||||
return;
|
||||
}
|
||||
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
target.teleport(world.getSpawnLocation());
|
||||
new VolmitSender(target).sendMessage(C.GREEN + "You have been teleported to " + world.getName() + ".");
|
||||
}
|
||||
}.runTask(Iris.instance);
|
||||
}
|
||||
|
||||
@Decree(description = "Print version information")
|
||||
public void version() {
|
||||
sender().sendMessage(C.GREEN + "Iris v" + Iris.instance.getDescription().getVersion() + " by Volmit Software");
|
||||
}
|
||||
|
||||
/*
|
||||
/todo
|
||||
@Decree(description = "Benchmark a pack", origin = DecreeOrigin.CONSOLE)
|
||||
public void packbenchmark(
|
||||
@Param(description = "Dimension to benchmark")
|
||||
IrisDimension type
|
||||
) throws InterruptedException {
|
||||
|
||||
BenchDimension = type.getLoadKey();
|
||||
|
||||
IrisPackBenchmarking.runBenchmark();
|
||||
} */
|
||||
|
||||
//todo Move to React
|
||||
@Decree(description = "Benchmark your server", origin = DecreeOrigin.CONSOLE)
|
||||
public void serverbenchmark() throws InterruptedException {
|
||||
if (!inProgress) {
|
||||
IrisBenchmarking.runBenchmark();
|
||||
} else {
|
||||
Iris.info(C.RED + "Benchmark already is in progress.");
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(description = "Print world height information", origin = DecreeOrigin.PLAYER)
|
||||
public void height() {
|
||||
if (sender().isPlayer()) {
|
||||
sender().sendMessage(C.GREEN + "" + sender().player().getWorld().getMinHeight() + " to " + sender().player().getWorld().getMaxHeight());
|
||||
sender().sendMessage(C.GREEN + "Total Height: " + (sender().player().getWorld().getMaxHeight() - sender().player().getWorld().getMinHeight()));
|
||||
} else {
|
||||
World mainWorld = getServer().getWorlds().get(0);
|
||||
Iris.info(C.GREEN + "" + mainWorld.getMinHeight() + " to " + mainWorld.getMaxHeight());
|
||||
Iris.info(C.GREEN + "Total Height: " + (mainWorld.getMaxHeight() - mainWorld.getMinHeight()));
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(description = "QOL command to open a overworld studio world.", sync = true)
|
||||
public void so() {
|
||||
sender().sendMessage(C.GREEN + "Opening studio for the \"Overworld\" pack (seed: 1337)");
|
||||
Iris.service(StudioSVC.class).open(sender(), 1337, "overworld");
|
||||
}
|
||||
|
||||
@Decree(description = "Check access of all worlds.", aliases = {"accesslist"})
|
||||
public void worlds() {
|
||||
KList<World> IrisWorlds = new KList<>();
|
||||
KList<World> BukkitWorlds = new KList<>();
|
||||
|
||||
for (World w : Bukkit.getServer().getWorlds()) {
|
||||
try {
|
||||
Engine engine = IrisToolbelt.access(w).getEngine();
|
||||
if (engine != null) {
|
||||
IrisWorlds.add(w);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
BukkitWorlds.add(w);
|
||||
}
|
||||
}
|
||||
|
||||
if (sender().isPlayer()) {
|
||||
sender().sendMessage(C.BLUE + "Iris Worlds: ");
|
||||
for (World IrisWorld : IrisWorlds.copy()) {
|
||||
sender().sendMessage(C.IRIS + "- " + IrisWorld.getName());
|
||||
}
|
||||
sender().sendMessage(C.GOLD + "Bukkit Worlds: ");
|
||||
for (World BukkitWorld : BukkitWorlds.copy()) {
|
||||
sender().sendMessage(C.GRAY + "- " + BukkitWorld.getName());
|
||||
}
|
||||
} else {
|
||||
Iris.info(C.BLUE + "Iris Worlds: ");
|
||||
for (World IrisWorld : IrisWorlds.copy()) {
|
||||
Iris.info(C.IRIS + "- " + IrisWorld.getName());
|
||||
}
|
||||
Iris.info(C.GOLD + "Bukkit Worlds: ");
|
||||
for (World BukkitWorld : BukkitWorlds.copy()) {
|
||||
Iris.info(C.GRAY + "- " + BukkitWorld.getName());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(description = "Remove an Iris world", aliases = {"del", "rm", "delete"}, sync = true)
|
||||
public void remove(
|
||||
@Param(description = "The world to remove")
|
||||
World world,
|
||||
@Param(description = "Whether to also remove the folder (if set to false, just does not load the world)", defaultValue = "true")
|
||||
boolean delete
|
||||
) {
|
||||
if (!IrisToolbelt.isIrisWorld(world)) {
|
||||
sender().sendMessage(C.RED + "This is not an Iris world. Iris worlds: " + String.join(", ", getServer().getWorlds().stream().filter(IrisToolbelt::isIrisWorld).map(World::getName).toList()));
|
||||
return;
|
||||
}
|
||||
sender().sendMessage(C.GREEN + "Removing world: " + world.getName());
|
||||
try {
|
||||
if (IrisToolbelt.removeWorld(world)) {
|
||||
sender().sendMessage(C.GREEN + "Successfully removed " + world.getName() + " from bukkit.yml");
|
||||
} else {
|
||||
sender().sendMessage(C.YELLOW + "Looks like the world was already removed from bukkit.yml");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
sender().sendMessage(C.RED + "Failed to save bukkit.yml because of " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
IrisToolbelt.evacuate(world, "Deleting world");
|
||||
deletingWorld = true;
|
||||
Bukkit.unloadWorld(world, false);
|
||||
int retries = 12;
|
||||
if (delete) {
|
||||
if (deleteDirectory(world.getWorldFolder())) {
|
||||
sender().sendMessage(C.GREEN + "Successfully removed world folder");
|
||||
} else {
|
||||
while (true) {
|
||||
if (deleteDirectory(world.getWorldFolder())) {
|
||||
sender().sendMessage(C.GREEN + "Successfully removed world folder");
|
||||
break;
|
||||
}
|
||||
retries--;
|
||||
if (retries == 0) {
|
||||
sender().sendMessage(C.RED + "Failed to remove world folder");
|
||||
break;
|
||||
}
|
||||
J.sleep(3000);
|
||||
}
|
||||
}
|
||||
}
|
||||
deletingWorld = false;
|
||||
}
|
||||
|
||||
@Decree(description = "Updates all chunk in the specified world")
|
||||
public void updater(
|
||||
@Param(description = "World to update chunks at")
|
||||
World world
|
||||
) {
|
||||
if (!IrisToolbelt.isIrisWorld(world)) {
|
||||
sender().sendMessage(C.GOLD + "This is not an Iris world");
|
||||
return;
|
||||
}
|
||||
ChunkUpdater updater = new ChunkUpdater(world);
|
||||
if (sender().isPlayer()) {
|
||||
sender().sendMessage(C.GREEN + "Updating " + world.getName() + " Total chunks: " + Form.f(updater.getChunks()));
|
||||
} else {
|
||||
Iris.info(C.GREEN + "Updating " + world.getName() + " Total chunks: " + Form.f(updater.getChunks()));
|
||||
}
|
||||
updater.start();
|
||||
}
|
||||
|
||||
@Decree(description = "Set aura spins")
|
||||
public void aura(
|
||||
@Param(description = "The h color value", defaultValue = "-20")
|
||||
int h,
|
||||
@Param(description = "The s color value", defaultValue = "7")
|
||||
int s,
|
||||
@Param(description = "The b color value", defaultValue = "8")
|
||||
int b
|
||||
) {
|
||||
IrisSettings.get().getGeneral().setSpinh(h);
|
||||
IrisSettings.get().getGeneral().setSpins(s);
|
||||
IrisSettings.get().getGeneral().setSpinb(b);
|
||||
IrisSettings.get().forceSave();
|
||||
sender().sendMessage("<rainbow>Aura Spins updated to " + h + " " + s + " " + b);
|
||||
}
|
||||
|
||||
@Decree(description = "Bitwise calculations")
|
||||
public void bitwise(
|
||||
@Param(description = "The first value to run calculations on")
|
||||
int value1,
|
||||
@Param(description = "The operator: | & ^ ≺≺ ≻≻ %")
|
||||
String operator,
|
||||
@Param(description = "The second value to run calculations on")
|
||||
int value2
|
||||
) {
|
||||
Integer v = null;
|
||||
switch (operator) {
|
||||
case "|" -> v = value1 | value2;
|
||||
case "&" -> v = value1 & value2;
|
||||
case "^" -> v = value1 ^ value2;
|
||||
case "%" -> v = value1 % value2;
|
||||
case ">>" -> v = value1 >> value2;
|
||||
case "<<" -> v = value1 << value2;
|
||||
}
|
||||
if (v == null) {
|
||||
sender().sendMessage(C.RED + "The operator you entered: (" + operator + ") is invalid!");
|
||||
return;
|
||||
}
|
||||
sender().sendMessage(C.GREEN + "" + value1 + " " + C.GREEN + operator.replaceAll("<", "≺").replaceAll(">", "≻").replaceAll("%", "%") + " " + C.GREEN + value2 + C.GREEN + " returns " + C.GREEN + v);
|
||||
}
|
||||
|
||||
@Decree(description = "Toggle debug")
|
||||
public void debug(
|
||||
@Param(name = "on", description = "Whether or not debug should be on", defaultValue = "other")
|
||||
Boolean on
|
||||
) {
|
||||
boolean to = on == null ? !IrisSettings.get().getGeneral().isDebug() : on;
|
||||
IrisSettings.get().getGeneral().setDebug(to);
|
||||
IrisSettings.get().forceSave();
|
||||
sender().sendMessage(C.GREEN + "Set debug to: " + to);
|
||||
}
|
||||
|
||||
@Decree(description = "Download a project.", aliases = "dl")
|
||||
public void download(
|
||||
@Param(name = "pack", description = "The pack to download", defaultValue = "overworld", aliases = "project")
|
||||
String pack,
|
||||
@Param(name = "branch", description = "The branch to download from", defaultValue = "main")
|
||||
String branch,
|
||||
@Param(name = "trim", description = "Whether or not to download a trimmed version (do not enable when editing)", defaultValue = "false")
|
||||
boolean trim,
|
||||
@Param(name = "overwrite", description = "Whether or not to overwrite the pack with the downloaded one", aliases = "force", defaultValue = "false")
|
||||
boolean overwrite
|
||||
) {
|
||||
sender().sendMessage(C.GREEN + "Downloading pack: " + pack + "/" + branch + (trim ? " trimmed" : "") + (overwrite ? " overwriting" : ""));
|
||||
if (pack.equals("overworld")) {
|
||||
String url = "https://github.com/IrisDimensions/overworld/releases/download/" + Iris.OVERWORLD_TAG + "/overworld.zip";
|
||||
Iris.service(StudioSVC.class).downloadRelease(sender(), url, trim, overwrite);
|
||||
} else {
|
||||
Iris.service(StudioSVC.class).downloadSearch(sender(), "IrisDimensions/" + pack + "/" + branch, trim, overwrite);
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(description = "Get metrics for your world", aliases = "measure", origin = DecreeOrigin.PLAYER)
|
||||
public void metrics() {
|
||||
if (!IrisToolbelt.isIrisWorld(world())) {
|
||||
sender().sendMessage(C.RED + "You must be in an Iris world");
|
||||
return;
|
||||
}
|
||||
sender().sendMessage(C.GREEN + "Sending metrics...");
|
||||
engine().printMetrics(sender());
|
||||
}
|
||||
|
||||
@Decree(description = "Reload configuration file (this is also done automatically)")
|
||||
public void reload() {
|
||||
IrisSettings.invalidate();
|
||||
IrisSettings.get();
|
||||
sender().sendMessage(C.GREEN + "Hotloaded settings");
|
||||
}
|
||||
|
||||
@Decree(description = "Update the pack of a world (UNSAFE!)", name = "^world", aliases = "update-world")
|
||||
public void updateWorld(
|
||||
@Param(description = "The world to update", contextual = true)
|
||||
World world,
|
||||
@Param(description = "The pack to install into the world", contextual = true, aliases = "dimension")
|
||||
IrisDimension pack,
|
||||
@Param(description = "Make sure to make a backup & read the warnings first!", defaultValue = "false", aliases = "c")
|
||||
boolean confirm,
|
||||
@Param(description = "Should Iris download the pack again for you", defaultValue = "false", name = "fresh-download", aliases = {"fresh", "new"})
|
||||
boolean freshDownload
|
||||
) {
|
||||
if (!confirm) {
|
||||
sender().sendMessage(new String[]{
|
||||
C.RED + "You should always make a backup before using this",
|
||||
C.YELLOW + "Issues caused by this can be, but are not limited to:",
|
||||
C.YELLOW + " - Broken chunks (cut-offs) between old and new chunks (before & after the update)",
|
||||
C.YELLOW + " - Regenerated chunks that do not fit in with the old chunks",
|
||||
C.YELLOW + " - Structures not spawning again when regenerating",
|
||||
C.YELLOW + " - Caves not lining up",
|
||||
C.YELLOW + " - Terrain layers not lining up",
|
||||
C.RED + "Now that you are aware of the risks, and have made a back-up:",
|
||||
C.RED + "/iris ^world " + world.getName() + " " + pack.getLoadKey() + " confirm=true"
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
File folder = world.getWorldFolder();
|
||||
folder.mkdirs();
|
||||
|
||||
if (freshDownload) {
|
||||
Iris.service(StudioSVC.class).downloadSearch(sender(), pack.getLoadKey(), false, true);
|
||||
}
|
||||
|
||||
Iris.service(StudioSVC.class).installIntoWorld(sender(), pack.getLoadKey(), folder);
|
||||
}
|
||||
|
||||
@Decree(description = "Unload an Iris World", sync = true)
|
||||
public void unload(
|
||||
@Param(description = "The world to unload")
|
||||
World world
|
||||
) {
|
||||
if (!IrisToolbelt.isIrisWorld(world)) {
|
||||
sender().sendMessage(C.RED + "This is not an Iris world. Iris worlds: " + String.join(", ", getServer().getWorlds().stream().filter(IrisToolbelt::isIrisWorld).map(World::getName).toList()));
|
||||
return;
|
||||
}
|
||||
sender().sendMessage(C.GREEN + "Unloading world: " + world.getName());
|
||||
try {
|
||||
IrisToolbelt.evacuate(world);
|
||||
Bukkit.unloadWorld(world, false);
|
||||
sender().sendMessage(C.GREEN + "World unloaded successfully.");
|
||||
} catch (Exception e) {
|
||||
sender().sendMessage(C.RED + "Failed to unload the world: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(description = "Load an Iris World", origin = DecreeOrigin.PLAYER, sync = true, aliases = {"import"})
|
||||
public void load(
|
||||
@Param(description = "The name of the world to load")
|
||||
String world
|
||||
) {
|
||||
|
||||
FileConfiguration fc = new YamlConfiguration();
|
||||
try {
|
||||
fc.load(new File("bukkit.yml"));
|
||||
ConfigurationSection section = fc.getConfigurationSection("worlds");
|
||||
if (section == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (String s : section.getKeys(false)) {
|
||||
try {
|
||||
|
||||
ConfigurationSection entry = section.getConfigurationSection(s);
|
||||
if (!entry.contains("backup-generator", true)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String generator = entry.getString("backup-generator");
|
||||
if (!generator.startsWith("Iris")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!s.equalsIgnoreCase(world)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
File worldFolder = new File(Bukkit.getWorldContainer().getPath() + "/" + s + "/iris/engine-data/");
|
||||
IOFileFilter jsonFilter = org.apache.commons.io.filefilter.FileFilterUtils.suffixFileFilter(".json");
|
||||
Collection<File> files = FileUtils.listFiles(worldFolder, jsonFilter, TrueFileFilter.INSTANCE);
|
||||
if (files.size() != 1) {
|
||||
Iris.info(C.DARK_GRAY + "------------------------------------------");
|
||||
Iris.info(C.RED + "Failed to load " + C.GRAY + s + C.RED + ". No valid engine-data file was found.");
|
||||
Iris.info(C.DARK_GRAY + "------------------------------------------");
|
||||
continue;
|
||||
}
|
||||
|
||||
for (File file : files) {
|
||||
int lastDotIndex = file.getName().lastIndexOf(".");
|
||||
generator = file.getName().substring(0, lastDotIndex);
|
||||
}
|
||||
|
||||
Iris.info("2 World: %s | Generator: %s", s, generator);
|
||||
|
||||
if (Bukkit.getWorlds().stream().anyMatch(w -> w.getName().equals(s))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Iris.info(C.LIGHT_PURPLE + "Preparing Spawn for " + s + "' using Iris:" + generator + "...");
|
||||
new WorldCreator(s)
|
||||
.generator(getDefaultWorldGenerator(s, generator))
|
||||
.environment(IrisData.loadAnyDimension(generator).getEnvironment())
|
||||
.createWorld();
|
||||
Iris.info(C.LIGHT_PURPLE + "Loaded " + s + "!");
|
||||
break;
|
||||
} catch (Exception e) {
|
||||
Iris.info(C.DARK_GRAY + "------------------------------------------");
|
||||
Iris.info(C.RED + "Failed to load " + C.GRAY + s);
|
||||
Iris.info(C.DARK_GRAY + "------------------------------------------");
|
||||
}
|
||||
sender().sendMessage(C.GOLD + "Failed to find world: " + C.DARK_GRAY + world);
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(description = "Evacuate an iris world", origin = DecreeOrigin.PLAYER, sync = true)
|
||||
public void evacuate(
|
||||
@Param(description = "Evacuate the world")
|
||||
World world
|
||||
) {
|
||||
if (!IrisToolbelt.isIrisWorld(world)) {
|
||||
sender().sendMessage(C.RED + "This is not an Iris world. Iris worlds: " + String.join(", ", getServer().getWorlds().stream().filter(IrisToolbelt::isIrisWorld).map(World::getName).toList()));
|
||||
return;
|
||||
}
|
||||
sender().sendMessage(C.GREEN + "Evacuating world" + world.getName());
|
||||
IrisToolbelt.evacuate(world);
|
||||
}
|
||||
|
||||
boolean doesWorldExist(String worldName) {
|
||||
File worldContainer = Bukkit.getWorldContainer();
|
||||
File worldDirectory = new File(worldContainer, worldName);
|
||||
return worldDirectory.exists() && worldDirectory.isDirectory();
|
||||
}
|
||||
|
||||
private void checkForBukkitWorlds(String world) {
|
||||
FileConfiguration fc = new YamlConfiguration();
|
||||
try {
|
||||
fc.load(new File("bukkit.yml"));
|
||||
ConfigurationSection section = fc.getConfigurationSection("worlds");
|
||||
if (section == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<String> worldsToLoad = Collections.singletonList(world);
|
||||
|
||||
for (String s : section.getKeys(false)) {
|
||||
if (!worldsToLoad.contains(s)) {
|
||||
continue;
|
||||
}
|
||||
ConfigurationSection entry = section.getConfigurationSection(s);
|
||||
if (!entry.contains("generator", true)) {
|
||||
continue;
|
||||
}
|
||||
String generator = entry.getString("generator");
|
||||
if (generator.startsWith("Iris:")) {
|
||||
generator = generator.split("\\Q:\\E")[1];
|
||||
} else if (generator.equalsIgnoreCase("Iris")) {
|
||||
generator = IrisSettings.get().getGenerator().getDefaultWorldType();
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
Iris.info("2 World: %s | Generator: %s", s, generator);
|
||||
if (Bukkit.getWorlds().stream().anyMatch(w -> w.getName().equals(s))) {
|
||||
continue;
|
||||
}
|
||||
Iris.info(C.LIGHT_PURPLE + "Preparing Spawn for " + s + "' using Iris:" + generator + "...");
|
||||
new WorldCreator(s)
|
||||
.generator(getDefaultWorldGenerator(s, generator))
|
||||
.environment(IrisData.loadAnyDimension(generator).getEnvironment())
|
||||
.createWorld();
|
||||
Iris.info(C.LIGHT_PURPLE + "Loaded " + s + "!");
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public ChunkGenerator getDefaultWorldGenerator(String worldName, String id) {
|
||||
Iris.debug("Default World Generator Called for " + worldName + " using ID: " + id);
|
||||
if (worldName.equals("test")) {
|
||||
try {
|
||||
throw new RuntimeException();
|
||||
} catch (Throwable e) {
|
||||
Iris.info(e.getStackTrace()[1].getClassName());
|
||||
if (e.getStackTrace()[1].getClassName().contains("com.onarandombox.MultiverseCore")) {
|
||||
Iris.debug("MVC Test detected, Quick! Send them the dummy!");
|
||||
return new DummyChunkGenerator();
|
||||
}
|
||||
}
|
||||
}
|
||||
IrisDimension dim;
|
||||
if (id == null || id.isEmpty()) {
|
||||
dim = IrisData.loadAnyDimension(IrisSettings.get().getGenerator().getDefaultWorldType());
|
||||
} else {
|
||||
dim = IrisData.loadAnyDimension(id);
|
||||
}
|
||||
Iris.debug("Generator ID: " + id + " requested by bukkit/plugin");
|
||||
|
||||
if (dim == null) {
|
||||
Iris.warn("Unable to find dimension type " + id + " Looking for online packs...");
|
||||
|
||||
service(StudioSVC.class).downloadSearch(new VolmitSender(Bukkit.getConsoleSender()), id, true);
|
||||
dim = IrisData.loadAnyDimension(id);
|
||||
|
||||
if (dim == null) {
|
||||
throw new RuntimeException("Can't find dimension " + id + "!");
|
||||
} else {
|
||||
Iris.info("Resolved missing dimension, proceeding with generation.");
|
||||
}
|
||||
}
|
||||
Iris.debug("Assuming IrisDimension: " + dim.getName());
|
||||
IrisWorld w = IrisWorld.builder()
|
||||
.name(worldName)
|
||||
.seed(1337)
|
||||
.environment(dim.getEnvironment())
|
||||
.worldFolder(new File(Bukkit.getWorldContainer(), worldName))
|
||||
.minHeight(dim.getMinHeight())
|
||||
.maxHeight(dim.getMaxHeight())
|
||||
.build();
|
||||
Iris.debug("Generator Config: " + w.toString());
|
||||
File ff = new File(w.worldFolder(), "iris/pack");
|
||||
if (!ff.exists() || ff.listFiles().length == 0) {
|
||||
ff.mkdirs();
|
||||
service(StudioSVC.class).installIntoWorld(sender, dim.getLoadKey(), ff.getParentFile());
|
||||
}
|
||||
return new BukkitChunkGenerator(w, false, ff, dim.getLoadKey());
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -21,6 +21,7 @@ package com.volmit.iris.core.commands;
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.edit.JigsawEditor;
|
||||
import com.volmit.iris.core.loader.IrisData;
|
||||
import com.volmit.iris.engine.framework.placer.WorldObjectPlacer;
|
||||
import com.volmit.iris.engine.jigsaw.PlannedStructure;
|
||||
import com.volmit.iris.engine.object.IrisJigsawPiece;
|
||||
import com.volmit.iris.engine.object.IrisJigsawStructure;
|
||||
@@ -34,6 +35,7 @@ import com.volmit.iris.util.decree.specialhandlers.ObjectHandler;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import com.volmit.iris.util.plugin.VolmitSender;
|
||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||
|
||||
import java.io.File;
|
||||
@@ -42,7 +44,7 @@ import java.io.File;
|
||||
public class CommandJigsaw implements DecreeExecutor {
|
||||
@Decree(description = "Edit a jigsaw piece")
|
||||
public void edit(
|
||||
@Param(description = "The jigsaw piece to edit")
|
||||
@Param(description = "The jigsaw piece to edit")
|
||||
IrisJigsawPiece piece
|
||||
) {
|
||||
File dest = piece.getLoadFile();
|
||||
@@ -51,27 +53,34 @@ public class CommandJigsaw implements DecreeExecutor {
|
||||
|
||||
@Decree(description = "Place a jigsaw structure")
|
||||
public void place(
|
||||
@Param(description = "The jigsaw structure to place")
|
||||
@Param(description = "The jigsaw structure to place")
|
||||
IrisJigsawStructure structure
|
||||
) {
|
||||
PrecisionStopwatch p = PrecisionStopwatch.start();
|
||||
PlannedStructure ps = new PlannedStructure(structure, new IrisPosition(player().getLocation()), new RNG());
|
||||
sender().sendMessage(C.GREEN + "Generated " + ps.getPieces().size() + " pieces in " + Form.duration(p.getMilliseconds(), 2));
|
||||
ps.place(world());
|
||||
try {
|
||||
var world = world();
|
||||
WorldObjectPlacer placer = new WorldObjectPlacer(world);
|
||||
PlannedStructure ps = new PlannedStructure(structure, new IrisPosition(player().getLocation().add(0, world.getMinHeight(), 0)), new RNG());
|
||||
VolmitSender sender = sender();
|
||||
sender.sendMessage(C.GREEN + "Generated " + ps.getPieces().size() + " pieces in " + Form.duration(p.getMilliseconds(), 2));
|
||||
ps.place(placer, failed -> sender.sendMessage(failed ? C.GREEN + "Placed the structure!" : C.RED + "Failed to place the structure!"));
|
||||
} catch (IllegalArgumentException e) {
|
||||
sender().sendMessage(C.RED + "Failed to place the structure: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(description = "Create a jigsaw piece")
|
||||
public void create(
|
||||
@Param(description = "The name of the jigsaw piece")
|
||||
@Param(description = "The name of the jigsaw piece")
|
||||
String piece,
|
||||
@Param(description = "The project to add the jigsaw piece to")
|
||||
@Param(description = "The project to add the jigsaw piece to")
|
||||
String project,
|
||||
@Param(description = "The object to use for this piece", customHandler = ObjectHandler.class)
|
||||
@Param(description = "The object to use for this piece", customHandler = ObjectHandler.class)
|
||||
String object
|
||||
) {
|
||||
IrisObject o = IrisData.loadAnyObject(object);
|
||||
|
||||
if(object == null) {
|
||||
if (object == null) {
|
||||
sender().sendMessage(C.RED + "Failed to find existing object");
|
||||
return;
|
||||
}
|
||||
@@ -88,7 +97,7 @@ public class CommandJigsaw implements DecreeExecutor {
|
||||
public void exit() {
|
||||
JigsawEditor editor = JigsawEditor.editors.get(player());
|
||||
|
||||
if(editor == null) {
|
||||
if (editor == null) {
|
||||
sender().sendMessage(C.GOLD + "You don't have any pieces open to exit!");
|
||||
return;
|
||||
}
|
||||
@@ -101,7 +110,7 @@ public class CommandJigsaw implements DecreeExecutor {
|
||||
public void save() {
|
||||
JigsawEditor editor = JigsawEditor.editors.get(player());
|
||||
|
||||
if(editor == null) {
|
||||
if (editor == null) {
|
||||
sender().sendMessage(C.GOLD + "You don't have any pieces open to save!");
|
||||
return;
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.commands;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.pregenerator.LazyPregenerator;
|
||||
import com.volmit.iris.util.decree.DecreeExecutor;
|
||||
import com.volmit.iris.util.decree.annotations.Decree;
|
||||
import com.volmit.iris.util.decree.annotations.Param;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
@Decree(name = "lazypregen", aliases = "lazy", description = "Pregenerate your Iris worlds!")
|
||||
public class CommandLazyPregen implements DecreeExecutor {
|
||||
public String worldName;
|
||||
|
||||
@Decree(description = "Pregenerate a world")
|
||||
public void start(
|
||||
@Param(description = "The radius of the pregen in blocks", aliases = "size")
|
||||
int radius,
|
||||
@Param(description = "The world to pregen", contextual = true)
|
||||
World world,
|
||||
@Param(aliases = "middle", description = "The center location of the pregen. Use \"me\" for your current location", defaultValue = "0,0")
|
||||
Vector center,
|
||||
@Param(aliases = "maxcpm", description = "Limit the chunks per minute the pregen will generate", defaultValue = "999999999")
|
||||
int cpm,
|
||||
@Param(aliases = "silent", description = "Silent generation", defaultValue = "false")
|
||||
boolean silent
|
||||
) {
|
||||
|
||||
worldName = world.getName();
|
||||
File worldDirectory = new File(Bukkit.getWorldContainer(), world.getName());
|
||||
File lazyFile = new File(worldDirectory, "lazygen.json");
|
||||
if (lazyFile.exists()) {
|
||||
sender().sendMessage(C.BLUE + "Lazy pregen is already in progress");
|
||||
Iris.info(C.YELLOW + "Lazy pregen is already in progress");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (sender().isPlayer() && access() == null) {
|
||||
sender().sendMessage(C.RED + "The engine access for this world is null!");
|
||||
sender().sendMessage(C.RED + "Please make sure the world is loaded & the engine is initialized. Generate a new chunk, for example.");
|
||||
}
|
||||
|
||||
LazyPregenerator.LazyPregenJob pregenJob = LazyPregenerator.LazyPregenJob.builder()
|
||||
.world(worldName)
|
||||
.healingPosition(0)
|
||||
.healing(false)
|
||||
.chunksPerMinute(cpm)
|
||||
.radiusBlocks(radius)
|
||||
.position(0)
|
||||
.silent(silent)
|
||||
.build();
|
||||
|
||||
File lazyGenFile = new File(worldDirectory, "lazygen.json");
|
||||
LazyPregenerator pregenerator = new LazyPregenerator(pregenJob, lazyGenFile);
|
||||
pregenerator.start();
|
||||
|
||||
String msg = C.GREEN + "LazyPregen started in " + C.GOLD + worldName + C.GREEN + " of " + C.GOLD + (radius * 2) + C.GREEN + " by " + C.GOLD + (radius * 2) + C.GREEN + " blocks from " + C.GOLD + center.getX() + "," + center.getZ();
|
||||
sender().sendMessage(msg);
|
||||
Iris.info(msg);
|
||||
} catch (Throwable e) {
|
||||
sender().sendMessage(C.RED + "Epic fail. See console.");
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(description = "Stop the active pregeneration task", aliases = "x")
|
||||
public void stop(
|
||||
@Param(aliases = "world", description = "The world to pause")
|
||||
World world
|
||||
) throws IOException {
|
||||
if (LazyPregenerator.getInstance() != null) {
|
||||
LazyPregenerator.getInstance().shutdownInstance(world);
|
||||
sender().sendMessage(C.LIGHT_PURPLE + "Closed lazygen instance for " + world.getName());
|
||||
} else {
|
||||
sender().sendMessage(C.YELLOW + "No active pregeneration tasks to stop");
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(description = "Pause / continue the active pregeneration task", aliases = {"t", "resume", "unpause"})
|
||||
public void pause(
|
||||
@Param(aliases = "world", description = "The world to pause")
|
||||
World world
|
||||
) {
|
||||
if (LazyPregenerator.getInstance() != null) {
|
||||
LazyPregenerator.getInstance().setPausedLazy(world);
|
||||
sender().sendMessage(C.GREEN + "Paused/unpaused Lazy Pregen, now: " + (LazyPregenerator.getInstance().isPausedLazy(world) ? "Paused" : "Running") + ".");
|
||||
} else {
|
||||
sender().sendMessage(C.YELLOW + "No active Lazy Pregen tasks to pause/unpause.");
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -24,14 +24,9 @@ import com.volmit.iris.core.loader.IrisData;
|
||||
import com.volmit.iris.core.service.ObjectSVC;
|
||||
import com.volmit.iris.core.service.StudioSVC;
|
||||
import com.volmit.iris.core.service.WandSVC;
|
||||
import com.volmit.iris.core.tools.IrisConverter;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.object.IObjectPlacer;
|
||||
import com.volmit.iris.engine.object.IrisDimension;
|
||||
import com.volmit.iris.engine.object.IrisObject;
|
||||
import com.volmit.iris.engine.object.IrisObjectPlacement;
|
||||
import com.volmit.iris.engine.object.IrisObjectPlacementScaleInterpolator;
|
||||
import com.volmit.iris.engine.object.IrisObjectRotation;
|
||||
import com.volmit.iris.engine.object.TileData;
|
||||
import com.volmit.iris.engine.object.*;
|
||||
import com.volmit.iris.util.data.Cuboid;
|
||||
import com.volmit.iris.util.decree.DecreeExecutor;
|
||||
import com.volmit.iris.util.decree.DecreeOrigin;
|
||||
@@ -41,6 +36,7 @@ import com.volmit.iris.util.decree.specialhandlers.ObjectHandler;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.math.Direction;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import com.volmit.iris.util.misc.E;
|
||||
import com.volmit.iris.util.scheduling.Queue;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.block.Block;
|
||||
@@ -53,21 +49,13 @@ import org.bukkit.util.Vector;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.text.NumberFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.*;
|
||||
|
||||
@Decree(name = "object", aliases = "o", origin = DecreeOrigin.PLAYER, studio = true, description = "Iris object manipulation")
|
||||
public class CommandObject implements DecreeExecutor {
|
||||
|
||||
private static final Set<Material> skipBlocks = Set.of(Material.GRASS, Material.SNOW, Material.VINE, Material.TORCH, Material.DEAD_BUSH,
|
||||
Material.POPPY, Material.DANDELION);
|
||||
private static final Set<Material> skipBlocks = Set.of(E.getOrDefault(Material.class, "GRASS", "SHORT_GRASS"), Material.SNOW, Material.VINE, Material.TORCH, Material.DEAD_BUSH,
|
||||
Material.POPPY, Material.DANDELION);
|
||||
|
||||
public static IObjectPlacer createPlacer(World world, Map<Block, BlockData> futureBlockChanges) {
|
||||
|
||||
@@ -87,7 +75,8 @@ public class CommandObject implements DecreeExecutor {
|
||||
Block block = world.getBlockAt(x, y, z);
|
||||
|
||||
//Prevent blocks being set in or bellow bedrock
|
||||
if(y <= world.getMinHeight() || block.getType() == Material.BEDROCK) return;
|
||||
if (y <= world.getMinHeight() || block.getType() == Material.BEDROCK)
|
||||
return;
|
||||
|
||||
futureBlockChanges.put(block, block.getBlockData());
|
||||
|
||||
@@ -130,10 +119,8 @@ public class CommandObject implements DecreeExecutor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTile(int xx, int yy, int zz, TileData<? extends TileState> tile) {
|
||||
BlockState state = world.getBlockAt(xx, yy, zz).getState();
|
||||
tile.toBukkitTry(state);
|
||||
state.update();
|
||||
public void setTile(int xx, int yy, int zz, TileData tile) {
|
||||
tile.toBukkitTry(world.getBlockAt(xx, yy, zz));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -145,7 +132,7 @@ public class CommandObject implements DecreeExecutor {
|
||||
|
||||
@Decree(description = "Check the composition of an object")
|
||||
public void analyze(
|
||||
@Param(description = "The object to analyze", customHandler = ObjectHandler.class)
|
||||
@Param(description = "The object to analyze", customHandler = ObjectHandler.class)
|
||||
String object
|
||||
) {
|
||||
IrisObject o = IrisData.loadAnyObject(object);
|
||||
@@ -156,19 +143,19 @@ public class CommandObject implements DecreeExecutor {
|
||||
Map<Material, Set<BlockData>> unsorted = new HashMap<>();
|
||||
Map<BlockData, Integer> amounts = new HashMap<>();
|
||||
Map<Material, Integer> materials = new HashMap<>();
|
||||
while(queue.hasNext()) {
|
||||
while (queue.hasNext()) {
|
||||
BlockData block = queue.next();
|
||||
|
||||
//unsorted.put(block.getMaterial(), block);
|
||||
|
||||
if(!amounts.containsKey(block)) {
|
||||
if (!amounts.containsKey(block)) {
|
||||
amounts.put(block, 1);
|
||||
|
||||
|
||||
} else
|
||||
amounts.put(block, amounts.get(block) + 1);
|
||||
|
||||
if(!materials.containsKey(block.getMaterial())) {
|
||||
if (!materials.containsKey(block.getMaterial())) {
|
||||
materials.put(block.getMaterial(), 1);
|
||||
unsorted.put(block.getMaterial(), new HashSet<>());
|
||||
unsorted.get(block.getMaterial()).add(block);
|
||||
@@ -180,13 +167,13 @@ public class CommandObject implements DecreeExecutor {
|
||||
}
|
||||
|
||||
List<Material> sortedMatsList = amounts.keySet().stream().map(BlockData::getMaterial)
|
||||
.sorted().collect(Collectors.toList());
|
||||
.sorted().toList();
|
||||
Set<Material> sortedMats = new TreeSet<>(Comparator.comparingInt(materials::get).reversed());
|
||||
sortedMats.addAll(sortedMatsList);
|
||||
sender().sendMessage("== Blocks in object ==");
|
||||
|
||||
int n = 0;
|
||||
for(Material mat : sortedMats) {
|
||||
for (Material mat : sortedMats) {
|
||||
int amount = materials.get(mat);
|
||||
List<BlockData> set = new ArrayList<>(unsorted.get(mat));
|
||||
set.sort(Comparator.comparingInt(amounts::get).reversed());
|
||||
@@ -194,23 +181,47 @@ public class CommandObject implements DecreeExecutor {
|
||||
int dataAmount = amounts.get(data);
|
||||
|
||||
String string = " - " + mat.toString() + "*" + amount;
|
||||
if(data.getAsString(true).contains("[")) {
|
||||
if (data.getAsString(true).contains("[")) {
|
||||
string = string + " --> [" + data.getAsString(true).split("\\[")[1]
|
||||
.replaceAll("true", ChatColor.GREEN + "true" + ChatColor.GRAY)
|
||||
.replaceAll("false", ChatColor.RED + "false" + ChatColor.GRAY) + "*" + dataAmount;
|
||||
.replaceAll("true", ChatColor.GREEN + "true" + ChatColor.GRAY)
|
||||
.replaceAll("false", ChatColor.RED + "false" + ChatColor.GRAY) + "*" + dataAmount;
|
||||
}
|
||||
|
||||
sender().sendMessage(string);
|
||||
|
||||
n++;
|
||||
|
||||
if(n >= 10) {
|
||||
if (n >= 10) {
|
||||
sender().sendMessage(" + " + (sortedMats.size() - n) + " other block types");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(description = "Shrink an object to its minimum size")
|
||||
public void shrink(@Param(description = "The object to shrink", customHandler = ObjectHandler.class) String object) {
|
||||
IrisObject o = IrisData.loadAnyObject(object);
|
||||
sender().sendMessage("Current Object Size: " + o.getW() + " * " + o.getH() + " * " + o.getD());
|
||||
o.shrinkwrap();
|
||||
sender().sendMessage("New Object Size: " + o.getW() + " * " + o.getH() + " * " + o.getD());
|
||||
try {
|
||||
o.write(o.getLoadFile());
|
||||
} catch (IOException e) {
|
||||
sender().sendMessage("Failed to save object " + o.getLoadFile() + ": " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(description = "Convert .schem files in the 'convert' folder to .iob files.")
|
||||
public void convert () {
|
||||
try {
|
||||
IrisConverter.convertSchematics(sender());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Decree(description = "Get a powder that reveals objects", studio = true, aliases = "d")
|
||||
public void dust() {
|
||||
player().getInventory().addItem(WandSVC.createDust());
|
||||
@@ -219,16 +230,19 @@ public class CommandObject implements DecreeExecutor {
|
||||
|
||||
@Decree(description = "Contract a selection based on your looking direction", aliases = "-")
|
||||
public void contract(
|
||||
@Param(description = "The amount to inset by", defaultValue = "1")
|
||||
@Param(description = "The amount to inset by", defaultValue = "1")
|
||||
int amount
|
||||
) {
|
||||
if(!WandSVC.isHoldingWand(player())) {
|
||||
if (!WandSVC.isHoldingWand(player())) {
|
||||
sender().sendMessage("Hold your wand.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Location[] b = WandSVC.getCuboid(player());
|
||||
if (b == null) {
|
||||
return;
|
||||
}
|
||||
Location a1 = b[0].clone();
|
||||
Location a2 = b[1].clone();
|
||||
Cuboid cursor = new Cuboid(a1, a2);
|
||||
@@ -244,18 +258,21 @@ public class CommandObject implements DecreeExecutor {
|
||||
|
||||
@Decree(description = "Set point 1 to look", aliases = "p1")
|
||||
public void position1(
|
||||
@Param(description = "Whether to use your current position, or where you look", defaultValue = "true")
|
||||
@Param(description = "Whether to use your current position, or where you look", defaultValue = "true")
|
||||
boolean here
|
||||
) {
|
||||
if(!WandSVC.isHoldingWand(player())) {
|
||||
if (!WandSVC.isHoldingWand(player())) {
|
||||
sender().sendMessage("Ready your Wand.");
|
||||
return;
|
||||
}
|
||||
|
||||
if(WandSVC.isHoldingWand(player())) {
|
||||
if (WandSVC.isHoldingWand(player())) {
|
||||
Location[] g = WandSVC.getCuboid(player());
|
||||
|
||||
if(!here) {
|
||||
if (g == null) {
|
||||
return;
|
||||
}
|
||||
if (!here) {
|
||||
// TODO: WARNING HEIGHT
|
||||
g[1] = player().getTargetBlock(null, 256).getLocation().clone();
|
||||
} else {
|
||||
@@ -267,18 +284,22 @@ public class CommandObject implements DecreeExecutor {
|
||||
|
||||
@Decree(description = "Set point 2 to look", aliases = "p2")
|
||||
public void position2(
|
||||
@Param(description = "Whether to use your current position, or where you look", defaultValue = "true")
|
||||
@Param(description = "Whether to use your current position, or where you look", defaultValue = "true")
|
||||
boolean here
|
||||
) {
|
||||
if(!WandSVC.isHoldingWand(player())) {
|
||||
if (!WandSVC.isHoldingWand(player())) {
|
||||
sender().sendMessage("Ready your Wand.");
|
||||
return;
|
||||
}
|
||||
|
||||
if(WandSVC.isHoldingIrisWand(player())) {
|
||||
if (WandSVC.isHoldingIrisWand(player())) {
|
||||
Location[] g = WandSVC.getCuboid(player());
|
||||
|
||||
if(!here) {
|
||||
if (g == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!here) {
|
||||
// TODO: WARNING HEIGHT
|
||||
g[0] = player().getTargetBlock(null, 256).getLocation().clone();
|
||||
} else {
|
||||
@@ -290,13 +311,13 @@ public class CommandObject implements DecreeExecutor {
|
||||
|
||||
@Decree(description = "Paste an object", sync = true)
|
||||
public void paste(
|
||||
@Param(description = "The object to paste", customHandler = ObjectHandler.class)
|
||||
@Param(description = "The object to paste", customHandler = ObjectHandler.class)
|
||||
String object,
|
||||
@Param(description = "Whether or not to edit the object (need to hold wand)", defaultValue = "false")
|
||||
@Param(description = "Whether or not to edit the object (need to hold wand)", defaultValue = "false")
|
||||
boolean edit,
|
||||
@Param(description = "The amount of degrees to rotate by", defaultValue = "0")
|
||||
@Param(description = "The amount of degrees to rotate by", defaultValue = "0")
|
||||
int rotate,
|
||||
@Param(description = "The factor by which to scale the object placement", defaultValue = "1")
|
||||
@Param(description = "The factor by which to scale the object placement", defaultValue = "1")
|
||||
double scale
|
||||
// ,
|
||||
// @Param(description = "The scale interpolator to use", defaultValue = "none")
|
||||
@@ -304,7 +325,7 @@ public class CommandObject implements DecreeExecutor {
|
||||
) {
|
||||
IrisObject o = IrisData.loadAnyObject(object);
|
||||
double maxScale = Double.max(10 - o.getBlocks().size() / 10000d, 1);
|
||||
if(scale > maxScale) {
|
||||
if (scale > maxScale) {
|
||||
sender().sendMessage(C.YELLOW + "Indicated scale exceeds maximum. Downscaled to maximum: " + maxScale);
|
||||
scale = maxScale;
|
||||
}
|
||||
@@ -319,8 +340,7 @@ public class CommandObject implements DecreeExecutor {
|
||||
|
||||
Map<Block, BlockData> futureChanges = new HashMap<>();
|
||||
|
||||
if(scale != 1)
|
||||
{
|
||||
if (scale != 1) {
|
||||
o = o.scaled(scale, IrisObjectPlacementScaleInterpolator.TRICUBIC);
|
||||
}
|
||||
|
||||
@@ -328,16 +348,16 @@ public class CommandObject implements DecreeExecutor {
|
||||
|
||||
Iris.service(ObjectSVC.class).addChanges(futureChanges);
|
||||
|
||||
if(edit) {
|
||||
if (edit) {
|
||||
ItemStack newWand = WandSVC.createWand(block.clone().subtract(o.getCenter()).add(o.getW() - 1,
|
||||
o.getH() + o.getCenter().clone().getY() - 1, o.getD() - 1), block.clone().subtract(o.getCenter().clone().setY(0)));
|
||||
if(WandSVC.isWand(wand)) {
|
||||
o.getH() + o.getCenter().clone().getY() - 1, o.getD() - 1), block.clone().subtract(o.getCenter().clone().setY(0)));
|
||||
if (WandSVC.isWand(wand)) {
|
||||
wand = newWand;
|
||||
player().getInventory().setItemInMainHand(wand);
|
||||
sender().sendMessage("Updated wand for " + "objects/" + o.getLoadKey() + ".iob ");
|
||||
} else {
|
||||
int slot = WandSVC.findWand(player().getInventory());
|
||||
if(slot == -1) {
|
||||
if (slot == -1) {
|
||||
player().getInventory().addItem(newWand);
|
||||
sender().sendMessage("Given new wand for " + "objects/" + o.getLoadKey() + ".iob ");
|
||||
} else {
|
||||
@@ -346,35 +366,35 @@ public class CommandObject implements DecreeExecutor {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
sender().sendMessage("Placed " + object);
|
||||
sender().sendMessage(C.IRIS + "Placed " + object);
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(description = "Save an object")
|
||||
public void save(
|
||||
@Param(description = "The dimension to store the object in", contextual = true)
|
||||
@Param(description = "The dimension to store the object in", contextual = true)
|
||||
IrisDimension dimension,
|
||||
@Param(description = "The file to store it in, can use / for subfolders")
|
||||
@Param(description = "The file to store it in, can use / for subfolders")
|
||||
String name,
|
||||
@Param(description = "Overwrite existing object files", defaultValue = "false", aliases = "force")
|
||||
@Param(description = "Overwrite existing object files", defaultValue = "false", aliases = "force")
|
||||
boolean overwrite
|
||||
) {
|
||||
IrisObject o = WandSVC.createSchematic(player());
|
||||
|
||||
if(o == null) {
|
||||
if (o == null) {
|
||||
sender().sendMessage(C.YELLOW + "You need to hold your wand!");
|
||||
return;
|
||||
}
|
||||
|
||||
File file = Iris.service(StudioSVC.class).getWorkspaceFile(dimension.getLoadKey(), "objects", name + ".iob");
|
||||
|
||||
if(file.exists() && !overwrite) {
|
||||
if (file.exists() && !overwrite) {
|
||||
sender().sendMessage(C.RED + "File already exists. Set overwrite=true to overwrite it.");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
o.write(file);
|
||||
} catch(IOException e) {
|
||||
o.write(file, sender());
|
||||
} catch (IOException e) {
|
||||
sender().sendMessage(C.RED + "Failed to save object because of an IOException: " + e.getMessage());
|
||||
Iris.reportError(e);
|
||||
}
|
||||
@@ -385,10 +405,10 @@ public class CommandObject implements DecreeExecutor {
|
||||
|
||||
@Decree(description = "Shift a selection in your looking direction", aliases = "-")
|
||||
public void shift(
|
||||
@Param(description = "The amount to shift by", defaultValue = "1")
|
||||
@Param(description = "The amount to shift by", defaultValue = "1")
|
||||
int amount
|
||||
) {
|
||||
if(!WandSVC.isHoldingWand(player())) {
|
||||
if (!WandSVC.isHoldingWand(player())) {
|
||||
sender().sendMessage("Hold your wand.");
|
||||
return;
|
||||
}
|
||||
@@ -397,6 +417,9 @@ public class CommandObject implements DecreeExecutor {
|
||||
Location a1 = b[0].clone();
|
||||
Location a2 = b[1].clone();
|
||||
Direction d = Direction.closest(player().getLocation().getDirection()).reverse();
|
||||
if (d == null) {
|
||||
return; // HOW DID THIS HAPPEN
|
||||
}
|
||||
a1.add(d.toVector().multiply(amount));
|
||||
a2.add(d.toVector().multiply(amount));
|
||||
Cuboid cursor = new Cuboid(a1, a2);
|
||||
@@ -409,26 +432,25 @@ public class CommandObject implements DecreeExecutor {
|
||||
|
||||
@Decree(description = "Undo a number of pastes", aliases = "-")
|
||||
public void undo(
|
||||
@Param(description = "The amount of pastes to undo", defaultValue = "1")
|
||||
@Param(description = "The amount of pastes to undo", defaultValue = "1")
|
||||
int amount
|
||||
) {
|
||||
ObjectSVC service = Iris.service(ObjectSVC.class);
|
||||
int actualReverts = Math.min(service.getUndos().size(), amount);
|
||||
service.revertChanges(actualReverts);
|
||||
sender().sendMessage("Reverted " + actualReverts + " pastes!");
|
||||
sender().sendMessage(C.BLUE + "Reverted " + actualReverts + C.BLUE + " pastes!");
|
||||
}
|
||||
|
||||
@Decree(description = "Gets an object wand and grabs the current WorldEdit selection.", aliases = "we", origin = DecreeOrigin.PLAYER, studio = true)
|
||||
public void we() {
|
||||
if(!Bukkit.getPluginManager().isPluginEnabled("WorldEdit")) {
|
||||
if (!Bukkit.getPluginManager().isPluginEnabled("WorldEdit")) {
|
||||
sender().sendMessage(C.RED + "You can't get a WorldEdit selection without WorldEdit, you know.");
|
||||
return;
|
||||
}
|
||||
|
||||
Cuboid locs = WorldEditLink.getSelection(sender().player());
|
||||
|
||||
if(locs == null)
|
||||
{
|
||||
if (locs == null) {
|
||||
sender().sendMessage(C.RED + "You don't have a WorldEdit selection in this world.");
|
||||
return;
|
||||
}
|
||||
@@ -446,7 +468,7 @@ public class CommandObject implements DecreeExecutor {
|
||||
|
||||
@Decree(name = "x&y", description = "Autoselect up, down & out", sync = true)
|
||||
public void xay() {
|
||||
if(!WandSVC.isHoldingWand(player())) {
|
||||
if (!WandSVC.isHoldingWand(player())) {
|
||||
sender().sendMessage(C.YELLOW + "Hold your wand!");
|
||||
return;
|
||||
}
|
||||
@@ -459,7 +481,7 @@ public class CommandObject implements DecreeExecutor {
|
||||
Cuboid cursor = new Cuboid(a1, a2);
|
||||
Cuboid cursorx = new Cuboid(a1, a2);
|
||||
|
||||
while(!cursor.containsOnly(Material.AIR)) {
|
||||
while (!cursor.containsOnly(Material.AIR)) {
|
||||
a1.add(new org.bukkit.util.Vector(0, 1, 0));
|
||||
a2.add(new org.bukkit.util.Vector(0, 1, 0));
|
||||
cursor = new Cuboid(a1, a2);
|
||||
@@ -468,7 +490,7 @@ public class CommandObject implements DecreeExecutor {
|
||||
a1.add(new org.bukkit.util.Vector(0, -1, 0));
|
||||
a2.add(new org.bukkit.util.Vector(0, -1, 0));
|
||||
|
||||
while(!cursorx.containsOnly(Material.AIR)) {
|
||||
while (!cursorx.containsOnly(Material.AIR)) {
|
||||
a1x.add(new org.bukkit.util.Vector(0, -1, 0));
|
||||
a2x.add(new org.bukkit.util.Vector(0, -1, 0));
|
||||
cursorx = new Cuboid(a1x, a2x);
|
||||
@@ -493,7 +515,7 @@ public class CommandObject implements DecreeExecutor {
|
||||
|
||||
@Decree(name = "x+y", description = "Autoselect up & out", sync = true)
|
||||
public void xpy() {
|
||||
if(!WandSVC.isHoldingWand(player())) {
|
||||
if (!WandSVC.isHoldingWand(player())) {
|
||||
sender().sendMessage(C.YELLOW + "Hold your wand!");
|
||||
return;
|
||||
}
|
||||
@@ -505,7 +527,7 @@ public class CommandObject implements DecreeExecutor {
|
||||
Location a2 = b[1].clone();
|
||||
Cuboid cursor = new Cuboid(a1, a2);
|
||||
|
||||
while(!cursor.containsOnly(Material.AIR)) {
|
||||
while (!cursor.containsOnly(Material.AIR)) {
|
||||
a1.add(new Vector(0, 1, 0));
|
||||
a2.add(new Vector(0, 1, 0));
|
||||
cursor = new Cuboid(a1, a2);
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -19,9 +19,16 @@
|
||||
package com.volmit.iris.core.commands;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.gui.PregeneratorJob;
|
||||
import com.volmit.iris.core.pregenerator.PregenTask;
|
||||
import com.volmit.iris.core.pregenerator.methods.HeadlessPregenMethod;
|
||||
import com.volmit.iris.core.pregenerator.methods.HybridPregenMethod;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.engine.IrisEngine;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.framework.EngineTarget;
|
||||
import com.volmit.iris.engine.object.IrisWorld;
|
||||
import com.volmit.iris.util.decree.DecreeExecutor;
|
||||
import com.volmit.iris.util.decree.annotations.Decree;
|
||||
import com.volmit.iris.util.decree.annotations.Param;
|
||||
@@ -30,34 +37,54 @@ import com.volmit.iris.util.math.Position2;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
@Decree(name = "pregen", aliases = "pregenerate", description = "Pregenerate your Iris worlds!")
|
||||
public class CommandPregen implements DecreeExecutor {
|
||||
@Decree(description = "Pregenerate a world")
|
||||
public void start(
|
||||
@Param(description = "The radius of the pregen in blocks", aliases = "size")
|
||||
@Param(description = "The radius of the pregen in blocks", aliases = "size")
|
||||
int radius,
|
||||
@Param(description = "The world to pregen", contextual = true)
|
||||
@Param(description = "The world to pregen", contextual = true)
|
||||
World world,
|
||||
@Param(aliases = "middle", description = "The center location of the pregen. Use \"me\" for your current location", defaultValue = "0,0")
|
||||
Vector center
|
||||
@Param(aliases = "middle", description = "The center location of the pregen. Use \"me\" for your current location", defaultValue = "0,0")
|
||||
Vector center,
|
||||
@Param(aliases = "headless", description = "Toggle headless pregeneration", defaultValue = "true")
|
||||
boolean headless,
|
||||
@Param(aliases = "gui", description = "Enable or disable the Iris GUI.", defaultValue = "true")
|
||||
boolean gui,
|
||||
@Param(aliases = "resetCache", description = "If it should reset the generated region cache", defaultValue = "false")
|
||||
boolean resetCache
|
||||
|
||||
) {
|
||||
try {
|
||||
if(sender().isPlayer() && access() == null) {
|
||||
if (sender().isPlayer() && access() == null) {
|
||||
sender().sendMessage(C.RED + "The engine access for this world is null!");
|
||||
sender().sendMessage(C.RED + "Please make sure the world is loaded & the engine is initialized. Generate a new chunk, for example.");
|
||||
}
|
||||
radius = Math.max(radius, 1024);
|
||||
int w = (radius >> 9 + 1) * 2;
|
||||
|
||||
Engine engine = IrisToolbelt.access(world).getEngine();
|
||||
if(!engine.setEngineHeadless()) {
|
||||
Iris.error("Failed to enable headless engine!");
|
||||
return;
|
||||
}
|
||||
|
||||
IrisToolbelt.pregenerate(PregenTask
|
||||
.builder()
|
||||
.center(new Position2(center))
|
||||
.width(w)
|
||||
.height(w)
|
||||
.build(), world);
|
||||
.builder()
|
||||
.resetCache(resetCache)
|
||||
.center(new Position2(center.getBlockX() >> 9, center.getBlockZ() >> 9))
|
||||
.gui(!GraphicsEnvironment.isHeadless() && gui)
|
||||
.width(w)
|
||||
.height(w)
|
||||
.build(), headless ? new HeadlessPregenMethod(engine) : new HybridPregenMethod(engine.getWorld().realWorld(),
|
||||
IrisSettings.getThreadCount(IrisSettings.get().getConcurrency().getParallelism())), engine);
|
||||
if (headless) sender().sendMessage("Using the headless Pregenerator.");
|
||||
String msg = C.GREEN + "Pregen started in " + C.GOLD + world.getName() + C.GREEN + " of " + C.GOLD + (radius * 2) + C.GREEN + " by " + C.GOLD + (radius * 2) + C.GREEN + " blocks from " + C.GOLD + center.getX() + "," + center.getZ();
|
||||
sender().sendMessage(msg);
|
||||
Iris.info(msg);
|
||||
} catch(Throwable e) {
|
||||
} catch (Throwable e) {
|
||||
sender().sendMessage(C.RED + "Epic fail. See console.");
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
@@ -66,8 +93,8 @@ public class CommandPregen implements DecreeExecutor {
|
||||
|
||||
@Decree(description = "Stop the active pregeneration task", aliases = "x")
|
||||
public void stop() {
|
||||
if(PregeneratorJob.shutdownInstance()) {
|
||||
sender().sendMessage(C.GREEN + "Stopped pregeneration task");
|
||||
if (PregeneratorJob.shutdownInstance()) {
|
||||
Iris.info(C.BLUE + "Finishing up mca region...");
|
||||
} else {
|
||||
sender().sendMessage(C.YELLOW + "No active pregeneration tasks to stop");
|
||||
}
|
||||
@@ -75,7 +102,7 @@ public class CommandPregen implements DecreeExecutor {
|
||||
|
||||
@Decree(description = "Pause / continue the active pregeneration task", aliases = {"t", "resume", "unpause"})
|
||||
public void pause() {
|
||||
if(PregeneratorJob.pauseResume()) {
|
||||
if (PregeneratorJob.pauseResume()) {
|
||||
sender().sendMessage(C.GREEN + "Paused/unpaused pregeneration task, now: " + (PregeneratorJob.isPaused() ? "Paused" : "Running") + ".");
|
||||
} else {
|
||||
sender().sendMessage(C.YELLOW + "No active pregeneration tasks to pause/unpause.");
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -0,0 +1,705 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.commands;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.gui.NoiseExplorerGUI;
|
||||
import com.volmit.iris.core.gui.VisionGUI;
|
||||
import com.volmit.iris.core.project.IrisProject;
|
||||
import com.volmit.iris.core.service.ConversionSVC;
|
||||
import com.volmit.iris.core.service.StudioSVC;
|
||||
import com.volmit.iris.core.tools.IrisNoiseBenchmark;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.object.*;
|
||||
import com.volmit.iris.engine.platform.PlatformChunkGenerator;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.collection.KSet;
|
||||
import com.volmit.iris.util.decree.DecreeContext;
|
||||
import com.volmit.iris.util.decree.DecreeExecutor;
|
||||
import com.volmit.iris.util.decree.DecreeOrigin;
|
||||
import com.volmit.iris.util.decree.annotations.Decree;
|
||||
import com.volmit.iris.util.decree.annotations.Param;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.function.Function2;
|
||||
import com.volmit.iris.util.json.JSONArray;
|
||||
import com.volmit.iris.util.json.JSONObject;
|
||||
import com.volmit.iris.util.math.M;
|
||||
import com.volmit.iris.util.math.Position2;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import com.volmit.iris.util.math.Spiraler;
|
||||
import com.volmit.iris.util.parallel.BurstExecutor;
|
||||
import com.volmit.iris.util.parallel.MultiBurst;
|
||||
import com.volmit.iris.util.plugin.VolmitSender;
|
||||
import com.volmit.iris.util.scheduling.ChronoLatch;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import com.volmit.iris.util.scheduling.O;
|
||||
import com.volmit.iris.util.scheduling.jobs.QueueJob;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.event.inventory.InventoryType;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
import org.bukkit.util.BlockVector;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.attribute.FileTime;
|
||||
import java.time.Duration;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@Decree(name = "studio", aliases = {"std", "s"}, description = "Studio Commands", studio = true)
|
||||
public class CommandStudio implements DecreeExecutor {
|
||||
private CommandFind find;
|
||||
private CommandEdit edit;
|
||||
|
||||
public static String hrf(Duration duration) {
|
||||
return duration.toString().substring(2).replaceAll("(\\d[HMS])(?!$)", "$1 ").toLowerCase();
|
||||
}
|
||||
|
||||
@Decree(description = "Download a project.", aliases = "dl")
|
||||
public void download(
|
||||
@Param(name = "pack", description = "The pack to download", defaultValue = "overworld", aliases = "project")
|
||||
String pack,
|
||||
@Param(name = "branch", description = "The branch to download from", defaultValue = "master")
|
||||
String branch,
|
||||
@Param(name = "trim", description = "Whether or not to download a trimmed version (do not enable when editing)", defaultValue = "false")
|
||||
boolean trim,
|
||||
@Param(name = "overwrite", description = "Whether or not to overwrite the pack with the downloaded one", aliases = "force", defaultValue = "false")
|
||||
boolean overwrite
|
||||
) {
|
||||
new CommandIris().download(pack, branch, trim, overwrite);
|
||||
}
|
||||
|
||||
@Decree(description = "Open a new studio world", aliases = "o", sync = true)
|
||||
public void open(
|
||||
@Param(defaultValue = "default", description = "The dimension to open a studio for", aliases = "dim")
|
||||
IrisDimension dimension,
|
||||
@Param(defaultValue = "1337", description = "The seed to generate the studio with", aliases = "s")
|
||||
long seed) {
|
||||
sender().sendMessage(C.GREEN + "Opening studio for the \"" + dimension.getName() + "\" pack (seed: " + seed + ")");
|
||||
Iris.service(StudioSVC.class).open(sender(), seed, dimension.getLoadKey());
|
||||
}
|
||||
|
||||
@Decree(description = "Open VSCode for a dimension", aliases = {"vsc", "edit"})
|
||||
public void vscode(
|
||||
@Param(defaultValue = "default", description = "The dimension to open VSCode for", aliases = "dim")
|
||||
IrisDimension dimension
|
||||
) {
|
||||
sender().sendMessage(C.GREEN + "Opening VSCode for the \"" + dimension.getName() + "\" pack");
|
||||
Iris.service(StudioSVC.class).openVSCode(sender(), dimension.getLoadKey());
|
||||
}
|
||||
|
||||
@Decree(description = "Close an open studio project", aliases = {"x", "c"}, sync = true)
|
||||
public void close() {
|
||||
if (!Iris.service(StudioSVC.class).isProjectOpen()) {
|
||||
sender().sendMessage(C.RED + "No open studio projects.");
|
||||
return;
|
||||
}
|
||||
|
||||
Iris.service(StudioSVC.class).close();
|
||||
sender().sendMessage(C.GREEN + "Project Closed.");
|
||||
}
|
||||
|
||||
@Decree(description = "Create a new studio project", aliases = "+", sync = true)
|
||||
public void create(
|
||||
@Param(description = "The name of this new Iris Project.")
|
||||
String name,
|
||||
@Param(description = "Copy the contents of an existing project in your packs folder and use it as a template in this new project.", contextual = true)
|
||||
IrisDimension template) {
|
||||
if (template != null) {
|
||||
Iris.service(StudioSVC.class).create(sender(), name, template.getLoadKey());
|
||||
} else {
|
||||
Iris.service(StudioSVC.class).create(sender(), name);
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(description = "Get the version of a pack")
|
||||
public void version(
|
||||
@Param(defaultValue = "default", description = "The dimension get the version of", aliases = "dim", contextual = true)
|
||||
IrisDimension dimension
|
||||
) {
|
||||
sender().sendMessage(C.GREEN + "The \"" + dimension.getName() + "\" pack has version: " + dimension.getVersion());
|
||||
}
|
||||
|
||||
@Decree(name = "regen", description = "Regenerate nearby chunks.", aliases = "rg", sync = true, origin = DecreeOrigin.PLAYER)
|
||||
public void regen(
|
||||
@Param(name = "radius", description = "The radius of nearby cunks", defaultValue = "5")
|
||||
int radius
|
||||
) {
|
||||
if (IrisToolbelt.isIrisWorld(player().getWorld())) {
|
||||
VolmitSender sender = sender();
|
||||
J.a(() -> {
|
||||
DecreeContext.touch(sender);
|
||||
PlatformChunkGenerator plat = IrisToolbelt.access(player().getWorld());
|
||||
Engine engine = plat.getEngine();
|
||||
try {
|
||||
Chunk cx = player().getLocation().getChunk();
|
||||
KList<Runnable> js = new KList<>();
|
||||
BurstExecutor b = MultiBurst.burst.burst();
|
||||
b.setMulticore(false);
|
||||
int rad = engine.getMantle().getRealRadius();
|
||||
for (int i = -(radius + rad); i <= radius + rad; i++) {
|
||||
for (int j = -(radius + rad); j <= radius + rad; j++) {
|
||||
engine.getMantle().getMantle().deleteChunk(i + cx.getX(), j + cx.getZ());
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = -radius; i <= radius; i++) {
|
||||
for (int j = -radius; j <= radius; j++) {
|
||||
int finalJ = j;
|
||||
int finalI = i;
|
||||
b.queue(() -> plat.injectChunkReplacement(player().getWorld(), finalI + cx.getX(), finalJ + cx.getZ(), (f) -> {
|
||||
synchronized (js) {
|
||||
js.add(f);
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
b.complete();
|
||||
sender().sendMessage(C.GREEN + "Regenerating " + Form.f(js.size()) + " Sections");
|
||||
QueueJob<Runnable> r = new QueueJob<>() {
|
||||
final KList<Future<?>> futures = new KList<>();
|
||||
|
||||
@Override
|
||||
public void execute(Runnable runnable) {
|
||||
futures.add(J.sfut(runnable));
|
||||
|
||||
if (futures.size() > 64) {
|
||||
while (futures.isNotEmpty()) {
|
||||
try {
|
||||
futures.remove(0).get();
|
||||
} catch (InterruptedException |
|
||||
ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Regenerating";
|
||||
}
|
||||
};
|
||||
r.queue(js);
|
||||
r.execute(sender());
|
||||
} catch (Throwable e) {
|
||||
sender().sendMessage("Unable to parse view-distance");
|
||||
}
|
||||
});
|
||||
} else {
|
||||
sender().sendMessage(C.RED + "You must be in an Iris World to use regen!");
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(description = "Convert objects in the \"convert\" folder")
|
||||
public void convert() {
|
||||
Iris.service(ConversionSVC.class).check(sender());
|
||||
//IrisConverter.convertSchematics(sender());
|
||||
}
|
||||
|
||||
@Decree(description = "Execute a script", aliases = "run", origin = DecreeOrigin.PLAYER)
|
||||
public void execute(
|
||||
@Param(description = "The script to run")
|
||||
IrisScript script
|
||||
) {
|
||||
engine().getExecution().execute(script.getLoadKey());
|
||||
}
|
||||
|
||||
@Decree(description = "Open the noise explorer (External GUI)", aliases = {"nmap", "n"})
|
||||
public void noise() {
|
||||
if (noGUI()) return;
|
||||
sender().sendMessage(C.GREEN + "Opening Noise Explorer!");
|
||||
NoiseExplorerGUI.launch();
|
||||
}
|
||||
|
||||
@Decree(description = "Charges all spawners in the area", aliases = "zzt", origin = DecreeOrigin.PLAYER)
|
||||
public void charge() {
|
||||
if (!IrisToolbelt.isIrisWorld(world())) {
|
||||
sender().sendMessage(C.RED + "You must be in an Iris world to charge spawners!");
|
||||
return;
|
||||
}
|
||||
sender().sendMessage(C.GREEN + "Charging spawners!");
|
||||
engine().getWorldManager().chargeEnergy();
|
||||
}
|
||||
|
||||
@Decree(description = "Preview noise gens (External GUI)", aliases = {"generator", "gen"})
|
||||
public void explore(
|
||||
@Param(description = "The generator to explore", contextual = true)
|
||||
IrisGenerator generator,
|
||||
@Param(description = "The seed to generate with", defaultValue = "12345")
|
||||
long seed
|
||||
) {
|
||||
if (noGUI()) return;
|
||||
sender().sendMessage(C.GREEN + "Opening Noise Explorer!");
|
||||
|
||||
Supplier<Function2<Double, Double, Double>> l = () -> {
|
||||
|
||||
if (generator == null) {
|
||||
return (x, z) -> 0D;
|
||||
}
|
||||
|
||||
return (x, z) -> generator.getHeight(x, z, new RNG(seed).nextParallelRNG(3245).lmax());
|
||||
};
|
||||
NoiseExplorerGUI.launch(l, "Custom Generator");
|
||||
}
|
||||
|
||||
@Decree(description = "Hotload a studio", aliases = {"reload", "h"})
|
||||
public void hotload() {
|
||||
if (!Iris.service(StudioSVC.class).isProjectOpen()) {
|
||||
sender().sendMessage(C.RED + "No studio world open!");
|
||||
return;
|
||||
}
|
||||
var provider = Iris.service(StudioSVC.class).getActiveProject().getActiveProvider();
|
||||
provider.getEngine().hotload();
|
||||
}
|
||||
|
||||
@Decree(description = "Show loot if a chest were right here", origin = DecreeOrigin.PLAYER, sync = true)
|
||||
public void loot(
|
||||
@Param(description = "Fast insertion of items in virtual inventory (may cause performance drop)", defaultValue = "false")
|
||||
boolean fast,
|
||||
@Param(description = "Whether or not to append to the inventory currently open (if false, clears opened inventory)", defaultValue = "true")
|
||||
boolean add
|
||||
) {
|
||||
if (noStudio()) return;
|
||||
|
||||
KList<IrisLootTable> tables = engine().getLootTables(RNG.r, player().getLocation().getBlock());
|
||||
Inventory inv = Bukkit.createInventory(null, 27 * 2);
|
||||
|
||||
try {
|
||||
engine().addItems(true, inv, RNG.r, tables, InventorySlotType.STORAGE, player().getLocation().getBlockX(), player().getLocation().getBlockY(), player().getLocation().getBlockZ(), 1);
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
sender().sendMessage(C.RED + "Cannot add items to virtual inventory because of: " + e.getMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
O<Integer> ta = new O<>();
|
||||
ta.set(-1);
|
||||
|
||||
ta.set(Bukkit.getScheduler().scheduleSyncRepeatingTask(Iris.instance, () ->
|
||||
{
|
||||
if (!player().getOpenInventory().getType().equals(InventoryType.CHEST)) {
|
||||
Bukkit.getScheduler().cancelTask(ta.get());
|
||||
sender().sendMessage(C.GREEN + "Opened inventory!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!add) {
|
||||
inv.clear();
|
||||
}
|
||||
|
||||
engine().addItems(true, inv, new RNG(RNG.r.imax()), tables, InventorySlotType.STORAGE, player().getLocation().getBlockX(), player().getLocation().getBlockY(), player().getLocation().getBlockZ(), 1);
|
||||
}, 0, fast ? 5 : 35));
|
||||
|
||||
sender().sendMessage(C.GREEN + "Opening inventory now!");
|
||||
player().openInventory(inv);
|
||||
}
|
||||
|
||||
|
||||
@Decree(description = "Get all structures in a radius of chunks", aliases = "dist", origin = DecreeOrigin.PLAYER)
|
||||
public void distances(@Param(description = "The radius in chunks") int radius) {
|
||||
var engine = engine();
|
||||
if (engine == null) {
|
||||
sender().sendMessage(C.RED + "Only works in an Iris world!");
|
||||
return;
|
||||
}
|
||||
var sender = sender();
|
||||
int d = radius * 2;
|
||||
KMap<String, KList<Position2>> data = new KMap<>();
|
||||
var multiBurst = new MultiBurst("Distance Sampler", Thread.MIN_PRIORITY);
|
||||
var executor = multiBurst.burst(radius * radius);
|
||||
|
||||
sender.sendMessage(C.GRAY + "Generating data...");
|
||||
var loc = player().getLocation();
|
||||
int totalTasks = d * d;
|
||||
AtomicInteger completedTasks = new AtomicInteger(0);
|
||||
int c = J.ar(() -> {
|
||||
sender.sendProgress((double) completedTasks.get() / totalTasks, "Finding structures");
|
||||
}, 0);
|
||||
|
||||
new Spiraler(d, d, (x, z) -> executor.queue(() -> {
|
||||
var struct = engine.getStructureAt(x, z);
|
||||
if (struct != null) {
|
||||
data.computeIfAbsent(struct.getLoadKey(), (k) -> new KList<>()).add(new Position2(x, z));
|
||||
}
|
||||
completedTasks.incrementAndGet();
|
||||
})).setOffset(loc.getBlockX(), loc.getBlockZ()).drain();
|
||||
|
||||
executor.complete();
|
||||
multiBurst.close();
|
||||
J.car(c);
|
||||
|
||||
for (var key : data.keySet()) {
|
||||
var list = data.get(key);
|
||||
KList<Long> distances = new KList<>(list.size() - 1);
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
var pos = list.get(i);
|
||||
double dist = Integer.MAX_VALUE;
|
||||
for (var p : list) {
|
||||
if (p.equals(pos)) continue;
|
||||
dist = Math.min(dist, Math.sqrt(Math.pow(pos.getX() - p.getX(), 2) + Math.pow(pos.getZ() - p.getZ(), 2)));
|
||||
}
|
||||
if (dist == Integer.MAX_VALUE) continue;
|
||||
distances.add(Math.round(dist * 16));
|
||||
}
|
||||
long[] array = new long[distances.size()];
|
||||
for (int i = 0; i < distances.size(); i++) {
|
||||
array[i] = distances.get(i);
|
||||
}
|
||||
Arrays.sort(array);
|
||||
long min = array.length > 0 ? array[0] : 0;
|
||||
long max = array.length > 0 ? array[array.length - 1] : 0;
|
||||
long sum = Arrays.stream(array).sum();
|
||||
long avg = array.length > 0 ? Math.round(sum / (double) array.length) : 0;
|
||||
String msg = "%s: %s => min: %s/max: %s -> avg: %s".formatted(key, list.size(), min, max, avg);
|
||||
sender.sendMessage(msg);
|
||||
}
|
||||
if (data.isEmpty()) {
|
||||
sender.sendMessage(C.RED + "No data found!");
|
||||
} else {
|
||||
sender.sendMessage(C.GREEN + "Done!");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Decree(description = "Render a world map (External GUI)", aliases = "render")
|
||||
public void map() {
|
||||
if (noGUI()) return;
|
||||
if (noStudio()) return;
|
||||
VisionGUI.launch(IrisToolbelt.access(player().getWorld()).getEngine(), 0);
|
||||
sender().sendMessage(C.GREEN + "Opening map!");
|
||||
}
|
||||
|
||||
@Decree(description = "Package a dimension into a compressed format", aliases = "package")
|
||||
public void pkg(
|
||||
@Param(name = "dimension", description = "The dimension pack to compress", contextual = true, defaultValue = "default")
|
||||
IrisDimension dimension,
|
||||
@Param(name = "obfuscate", description = "Whether or not to obfuscate the pack", defaultValue = "false")
|
||||
boolean obfuscate,
|
||||
@Param(name = "minify", description = "Whether or not to minify the pack", defaultValue = "true")
|
||||
boolean minify
|
||||
) {
|
||||
Iris.service(StudioSVC.class).compilePackage(sender(), dimension.getLoadKey(), obfuscate, minify);
|
||||
}
|
||||
|
||||
@Decree(description = "Profiles the performance of a dimension", origin = DecreeOrigin.PLAYER)
|
||||
public void profile(
|
||||
@Param(description = "The dimension to profile", contextual = true, defaultValue = "default")
|
||||
IrisDimension dimension
|
||||
) {
|
||||
IrisNoiseBenchmark noiseBenchmark = new IrisNoiseBenchmark(dimension, sender());
|
||||
noiseBenchmark.runAll();
|
||||
}
|
||||
|
||||
@Decree(description = "Spawn an Iris entity", aliases = "summon", origin = DecreeOrigin.PLAYER)
|
||||
public void spawn(
|
||||
@Param(description = "The entity to spawn")
|
||||
IrisEntity entity,
|
||||
@Param(description = "The location to spawn the entity at", contextual = true)
|
||||
Vector location
|
||||
) {
|
||||
if (!IrisToolbelt.isIrisWorld(player().getWorld())) {
|
||||
sender().sendMessage(C.RED + "You have to be in an Iris world to spawn entities properly. Trying to spawn the best we can do.");
|
||||
}
|
||||
entity.spawn(engine(), new Location(world(), location.getX(), location.getY(), location.getZ()));
|
||||
}
|
||||
|
||||
@Decree(description = "Teleport to the active studio world", aliases = "stp", origin = DecreeOrigin.PLAYER, sync = true)
|
||||
public void tpstudio() {
|
||||
if (!Iris.service(StudioSVC.class).isProjectOpen()) {
|
||||
sender().sendMessage(C.RED + "No studio world is open!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (IrisToolbelt.isIrisWorld(world()) && engine().isStudio()) {
|
||||
sender().sendMessage(C.RED + "You are already in a studio world!");
|
||||
return;
|
||||
}
|
||||
|
||||
sender().sendMessage(C.GREEN + "Sending you to the studio world!");
|
||||
player().teleport(Iris.service(StudioSVC.class).getActiveProject().getActiveProvider().getTarget().getWorld().spawnLocation());
|
||||
player().setGameMode(GameMode.SPECTATOR);
|
||||
}
|
||||
|
||||
@Decree(description = "Update your dimension projects VSCode workspace")
|
||||
public void update(
|
||||
@Param(description = "The dimension to update the workspace of", contextual = true, defaultValue = "default")
|
||||
IrisDimension dimension
|
||||
) {
|
||||
sender().sendMessage(C.GOLD + "Updating Code Workspace for " + dimension.getName() + "...");
|
||||
if (new IrisProject(dimension.getLoader().getDataFolder()).updateWorkspace()) {
|
||||
sender().sendMessage(C.GREEN + "Updated Code Workspace for " + dimension.getName());
|
||||
} else {
|
||||
sender().sendMessage(C.RED + "Invalid project: " + dimension.getName() + ". Try deleting the code-workspace file and try again.");
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(aliases = "find-objects", description = "Get information about nearby structures")
|
||||
public void objects() {
|
||||
if (!IrisToolbelt.isIrisWorld(player().getWorld())) {
|
||||
sender().sendMessage(C.RED + "You must be in an Iris world");
|
||||
return;
|
||||
}
|
||||
|
||||
World world = player().getWorld();
|
||||
|
||||
if (!IrisToolbelt.isIrisWorld(world)) {
|
||||
sender().sendMessage("You must be in an iris world.");
|
||||
return;
|
||||
}
|
||||
KList<Chunk> chunks = new KList<>();
|
||||
int bx = player().getLocation().getChunk().getX();
|
||||
int bz = player().getLocation().getChunk().getZ();
|
||||
|
||||
try {
|
||||
Location l = player().getTargetBlockExact(48, FluidCollisionMode.NEVER).getLocation();
|
||||
|
||||
int cx = l.getChunk().getX();
|
||||
int cz = l.getChunk().getZ();
|
||||
new Spiraler(3, 3, (x, z) -> chunks.addIfMissing(world.getChunkAt(x + cx, z + cz))).drain();
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
}
|
||||
|
||||
new Spiraler(3, 3, (x, z) -> chunks.addIfMissing(world.getChunkAt(x + bx, z + bz))).drain();
|
||||
sender().sendMessage("Capturing IGenData from " + chunks.size() + " nearby chunks.");
|
||||
try {
|
||||
File ff = Iris.instance.getDataFile("reports/" + M.ms() + ".txt");
|
||||
PrintWriter pw = new PrintWriter(ff);
|
||||
pw.println("=== Iris Chunk Report ===");
|
||||
pw.println("== General Info ==");
|
||||
pw.println("Iris Version: " + Iris.instance.getDescription().getVersion());
|
||||
pw.println("Bukkit Version: " + Bukkit.getBukkitVersion());
|
||||
pw.println("MC Version: " + Bukkit.getVersion());
|
||||
pw.println("PaperSpigot: " + (PaperLib.isPaper() ? "Yup!" : "Nope!"));
|
||||
pw.println("Report Captured At: " + new Date());
|
||||
pw.println("Chunks: (" + chunks.size() + "): ");
|
||||
|
||||
for (Chunk i : chunks) {
|
||||
pw.println("- [" + i.getX() + ", " + i.getZ() + "]");
|
||||
}
|
||||
|
||||
int regions = 0;
|
||||
long size = 0;
|
||||
String age = "No idea...";
|
||||
|
||||
try {
|
||||
for (File i : Objects.requireNonNull(new File(world.getWorldFolder(), "region").listFiles())) {
|
||||
if (i.isFile()) {
|
||||
size += i.length();
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
}
|
||||
|
||||
try {
|
||||
FileTime creationTime = (FileTime) Files.getAttribute(world.getWorldFolder().toPath(), "creationTime");
|
||||
age = hrf(Duration.of(M.ms() - creationTime.toMillis(), ChronoUnit.MILLIS));
|
||||
} catch (IOException e) {
|
||||
Iris.reportError(e);
|
||||
}
|
||||
|
||||
KList<String> biomes = new KList<>();
|
||||
KList<String> caveBiomes = new KList<>();
|
||||
KMap<String, KMap<String, KList<String>>> objects = new KMap<>();
|
||||
|
||||
for (Chunk i : chunks) {
|
||||
for (int j = 0; j < 16; j += 3) {
|
||||
|
||||
for (int k = 0; k < 16; k += 3) {
|
||||
|
||||
assert engine() != null;
|
||||
IrisBiome bb = engine().getSurfaceBiome((i.getX() * 16) + j, (i.getZ() * 16) + k);
|
||||
IrisBiome bxf = engine().getCaveBiome((i.getX() * 16) + j, (i.getZ() * 16) + k);
|
||||
biomes.addIfMissing(bb.getName() + " [" + Form.capitalize(bb.getInferredType().name().toLowerCase()) + "] " + " (" + bb.getLoadFile().getName() + ")");
|
||||
caveBiomes.addIfMissing(bxf.getName() + " (" + bxf.getLoadFile().getName() + ")");
|
||||
exportObjects(bb, pw, engine(), objects);
|
||||
exportObjects(bxf, pw, engine(), objects);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
regions = Objects.requireNonNull(new File(world.getWorldFolder().getPath() + "/region").list()).length;
|
||||
|
||||
pw.println();
|
||||
pw.println("== World Info ==");
|
||||
pw.println("World Name: " + world.getName());
|
||||
pw.println("Age: " + age);
|
||||
pw.println("Folder: " + world.getWorldFolder().getPath());
|
||||
pw.println("Regions: " + Form.f(regions));
|
||||
pw.println("Chunks: max. " + Form.f(regions * 32 * 32));
|
||||
pw.println("World Size: min. " + Form.fileSize(size));
|
||||
pw.println();
|
||||
pw.println("== Biome Info ==");
|
||||
pw.println("Found " + biomes.size() + " Biome(s): ");
|
||||
|
||||
for (String i : biomes) {
|
||||
pw.println("- " + i);
|
||||
}
|
||||
pw.println();
|
||||
|
||||
pw.println("== Object Info ==");
|
||||
|
||||
for (String i : objects.k()) {
|
||||
pw.println("- " + i);
|
||||
|
||||
for (String j : objects.get(i).k()) {
|
||||
pw.println(" @ " + j);
|
||||
|
||||
for (String k : objects.get(i).get(j)) {
|
||||
pw.println(" * " + k);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pw.println();
|
||||
pw.close();
|
||||
|
||||
sender().sendMessage("Reported to: " + ff.getPath());
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
Iris.reportError(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void exportObjects(IrisBiome bb, PrintWriter pw, Engine g, KMap<String, KMap<String, KList<String>>> objects) {
|
||||
String n1 = bb.getName() + " [" + Form.capitalize(bb.getInferredType().name().toLowerCase()) + "] " + " (" + bb.getLoadFile().getName() + ")";
|
||||
int m = 0;
|
||||
KSet<String> stop = new KSet<>();
|
||||
for (IrisObjectPlacement f : bb.getObjects()) {
|
||||
m++;
|
||||
String n2 = "Placement #" + m + " (" + f.getPlace().size() + " possible objects)";
|
||||
|
||||
for (String i : f.getPlace()) {
|
||||
String nn3 = i + ": [ERROR] Failed to find object!";
|
||||
|
||||
try {
|
||||
if (stop.contains(i)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
File ff = g.getData().getObjectLoader().findFile(i);
|
||||
BlockVector sz = IrisObject.sampleSize(ff);
|
||||
nn3 = i + ": size=[" + sz.getBlockX() + "," + sz.getBlockY() + "," + sz.getBlockZ() + "] location=[" + ff.getPath() + "]";
|
||||
stop.add(i);
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
}
|
||||
|
||||
String n3 = nn3;
|
||||
objects.computeIfAbsent(n1, (k1) -> new KMap<>())
|
||||
.computeIfAbsent(n2, (k) -> new KList<>()).addIfMissing(n3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if server GUIs are not enabled
|
||||
*/
|
||||
private boolean noGUI() {
|
||||
if (!IrisSettings.get().getGui().isUseServerLaunchedGuis()) {
|
||||
sender().sendMessage(C.RED + "You must have server launched GUIs enabled in the settings!");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if no studio is open or the player is not in one
|
||||
*/
|
||||
private boolean noStudio() {
|
||||
if (!sender().isPlayer()) {
|
||||
sender().sendMessage(C.RED + "Players only!");
|
||||
return true;
|
||||
}
|
||||
if (!Iris.service(StudioSVC.class).isProjectOpen()) {
|
||||
sender().sendMessage(C.RED + "No studio world is open!");
|
||||
return true;
|
||||
}
|
||||
if (!engine().isStudio()) {
|
||||
sender().sendMessage(C.RED + "You must be in a studio world!");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public void files(File clean, KList<File> files) {
|
||||
if (clean.isDirectory()) {
|
||||
for (File i : clean.listFiles()) {
|
||||
files(i, files);
|
||||
}
|
||||
} else if (clean.getName().endsWith(".json")) {
|
||||
try {
|
||||
files.add(clean);
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
Iris.error("Failed to beautify " + clean.getAbsolutePath() + " You may have errors in your json!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void fixBlocks(JSONObject obj) {
|
||||
for (String i : obj.keySet()) {
|
||||
Object o = obj.get(i);
|
||||
|
||||
if (i.equals("block") && o instanceof String && !o.toString().trim().isEmpty() && !o.toString().contains(":")) {
|
||||
obj.put(i, "minecraft:" + o);
|
||||
}
|
||||
|
||||
if (o instanceof JSONObject) {
|
||||
fixBlocks((JSONObject) o);
|
||||
} else if (o instanceof JSONArray) {
|
||||
fixBlocks((JSONArray) o);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void fixBlocks(JSONArray obj) {
|
||||
for (int i = 0; i < obj.length(); i++) {
|
||||
Object o = obj.get(i);
|
||||
|
||||
if (o instanceof JSONObject) {
|
||||
fixBlocks((JSONObject) o);
|
||||
} else if (o instanceof JSONArray) {
|
||||
fixBlocks((JSONArray) o);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.commands;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.util.decree.DecreeExecutor;
|
||||
import com.volmit.iris.util.decree.DecreeOrigin;
|
||||
import com.volmit.iris.util.decree.annotations.Decree;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.misc.Hastebin;
|
||||
|
||||
@Decree(name = "Support", origin = DecreeOrigin.BOTH, description = "Iris World Manager", aliases = {"support"})
|
||||
public class CommandSupport implements DecreeExecutor {
|
||||
|
||||
@Decree(description = "report")
|
||||
public void report() {
|
||||
try {
|
||||
if (sender().isPlayer())
|
||||
sender().sendMessage(C.GOLD + "Creating report..");
|
||||
if (!sender().isPlayer()) Iris.info(C.GOLD + "Creating report..");
|
||||
Hastebin.enviornment(sender());
|
||||
|
||||
} catch (Exception e) {
|
||||
Iris.info(C.RED + "Something went wrong: ");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.commands;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.pregenerator.TurboPregenerator;
|
||||
import com.volmit.iris.util.decree.DecreeExecutor;
|
||||
import com.volmit.iris.util.decree.annotations.Decree;
|
||||
import com.volmit.iris.util.decree.annotations.Param;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
@Decree(name = "turbopregen", aliases = "turbo", description = "Pregenerate your Iris worlds!")
|
||||
public class CommandTurboPregen implements DecreeExecutor {
|
||||
public String worldName;
|
||||
|
||||
@Decree(description = "Pregenerate a world")
|
||||
public void start(
|
||||
@Param(description = "The radius of the pregen in blocks", aliases = "size")
|
||||
int radius,
|
||||
@Param(description = "The world to pregen", contextual = true)
|
||||
World world,
|
||||
@Param(aliases = "middle", description = "The center location of the pregen. Use \"me\" for your current location", defaultValue = "0,0")
|
||||
Vector center
|
||||
) {
|
||||
|
||||
worldName = world.getName();
|
||||
File worldDirectory = new File(Bukkit.getWorldContainer(), world.getName());
|
||||
File TurboFile = new File(worldDirectory, "turbogen.json");
|
||||
if (TurboFile.exists()) {
|
||||
if (TurboPregenerator.getInstance() != null) {
|
||||
sender().sendMessage(C.BLUE + "Turbo pregen is already in progress");
|
||||
Iris.info(C.YELLOW + "Turbo pregen is already in progress");
|
||||
return;
|
||||
} else {
|
||||
try {
|
||||
TurboFile.delete();
|
||||
} catch (Exception e) {
|
||||
Iris.error("Failed to delete the old instance file of Turbo Pregen!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
if (sender().isPlayer() && access() == null) {
|
||||
sender().sendMessage(C.RED + "The engine access for this world is null!");
|
||||
sender().sendMessage(C.RED + "Please make sure the world is loaded & the engine is initialized. Generate a new chunk, for example.");
|
||||
}
|
||||
|
||||
TurboPregenerator.TurboPregenJob pregenJob = TurboPregenerator.TurboPregenJob.builder()
|
||||
.world(worldName)
|
||||
.radiusBlocks(radius)
|
||||
.position(0)
|
||||
.build();
|
||||
|
||||
File TurboGenFile = new File(worldDirectory, "turbogen.json");
|
||||
TurboPregenerator pregenerator = new TurboPregenerator(pregenJob, TurboGenFile);
|
||||
pregenerator.start();
|
||||
|
||||
String msg = C.GREEN + "TurboPregen started in " + C.GOLD + worldName + C.GREEN + " of " + C.GOLD + (radius * 2) + C.GREEN + " by " + C.GOLD + (radius * 2) + C.GREEN + " blocks from " + C.GOLD + center.getX() + "," + center.getZ();
|
||||
sender().sendMessage(msg);
|
||||
Iris.info(msg);
|
||||
} catch (Throwable e) {
|
||||
sender().sendMessage(C.RED + "Epic fail. See console.");
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(description = "Stop the active pregeneration task", aliases = "x")
|
||||
public void stop(@Param(aliases = "world", description = "The world to pause") World world) throws IOException {
|
||||
TurboPregenerator turboPregenInstance = TurboPregenerator.getInstance();
|
||||
File worldDirectory = new File(Bukkit.getWorldContainer(), world.getName());
|
||||
File turboFile = new File(worldDirectory, "turbogen.json");
|
||||
|
||||
if (turboPregenInstance != null) {
|
||||
turboPregenInstance.shutdownInstance(world);
|
||||
sender().sendMessage(C.LIGHT_PURPLE + "Closed Turbogen instance for " + world.getName());
|
||||
} else if (turboFile.exists() && turboFile.delete()) {
|
||||
sender().sendMessage(C.LIGHT_PURPLE + "Closed Turbogen instance for " + world.getName());
|
||||
} else if (turboFile.exists()) {
|
||||
Iris.error("Failed to delete the old instance file of Turbo Pregen!");
|
||||
} else {
|
||||
sender().sendMessage(C.YELLOW + "No active pregeneration tasks to stop");
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(description = "Pause / continue the active pregeneration task", aliases = {"t", "resume", "unpause"})
|
||||
public void pause(
|
||||
@Param(aliases = "world", description = "The world to pause")
|
||||
World world
|
||||
) {
|
||||
if (TurboPregenerator.getInstance() != null) {
|
||||
TurboPregenerator.setPausedTurbo(world);
|
||||
sender().sendMessage(C.GREEN + "Paused/unpaused Turbo Pregen, now: " + (TurboPregenerator.isPausedTurbo(world) ? "Paused" : "Running") + ".");
|
||||
} else {
|
||||
File worldDirectory = new File(Bukkit.getWorldContainer(), world.getName());
|
||||
File TurboFile = new File(worldDirectory, "turbogen.json");
|
||||
if (TurboFile.exists()) {
|
||||
TurboPregenerator.loadTurboGenerator(world.getName());
|
||||
sender().sendMessage(C.YELLOW + "Started Turbo Pregen back up!");
|
||||
} else {
|
||||
sender().sendMessage(C.YELLOW + "No active Turbo Pregen tasks to pause/unpause.");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.commands;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.pregenerator.ChunkUpdater;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.util.decree.DecreeExecutor;
|
||||
import com.volmit.iris.util.decree.DecreeOrigin;
|
||||
import com.volmit.iris.util.decree.annotations.Decree;
|
||||
import com.volmit.iris.util.decree.annotations.Param;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
import org.bukkit.World;
|
||||
|
||||
@Decree(name = "updater", origin = DecreeOrigin.BOTH, description = "Iris World Updater")
|
||||
public class CommandUpdater implements DecreeExecutor {
|
||||
private ChunkUpdater chunkUpdater;
|
||||
|
||||
@Decree(description = "Updates all chunk in the specified world")
|
||||
public void start(
|
||||
@Param(description = "World to update chunks at", contextual = true)
|
||||
World world
|
||||
) {
|
||||
if (!IrisToolbelt.isIrisWorld(world)) {
|
||||
sender().sendMessage(C.GOLD + "This is not an Iris world");
|
||||
return;
|
||||
}
|
||||
chunkUpdater = new ChunkUpdater(world);
|
||||
if (sender().isPlayer()) {
|
||||
sender().sendMessage(C.GREEN + "Updating " + world.getName() + C.GRAY + " Total chunks: " + Form.f(chunkUpdater.getChunks()));
|
||||
} else {
|
||||
Iris.info(C.GREEN + "Updating " + world.getName() + C.GRAY + " Total chunks: " + Form.f(chunkUpdater.getChunks()));
|
||||
}
|
||||
chunkUpdater.start();
|
||||
}
|
||||
|
||||
@Decree(description = "Pause the updater")
|
||||
public void pause(
|
||||
@Param(description = "World to pause the Updater at")
|
||||
World world
|
||||
) {
|
||||
if (!IrisToolbelt.isIrisWorld(world)) {
|
||||
sender().sendMessage(C.GOLD + "This is not an Iris world");
|
||||
return;
|
||||
}
|
||||
if (chunkUpdater == null) {
|
||||
sender().sendMessage(C.GOLD + "You cant pause something that doesnt exist?");
|
||||
return;
|
||||
}
|
||||
boolean status = chunkUpdater.pause();
|
||||
if (sender().isPlayer()) {
|
||||
if (status) {
|
||||
sender().sendMessage(C.IRIS + "Paused task for: " + C.GRAY + world.getName());
|
||||
} else {
|
||||
sender().sendMessage(C.IRIS + "Unpause task for: " + C.GRAY + world.getName());
|
||||
}
|
||||
} else {
|
||||
if (status) {
|
||||
Iris.info(C.IRIS + "Paused task for: " + C.GRAY + world.getName());
|
||||
} else {
|
||||
Iris.info(C.IRIS + "Unpause task for: " + C.GRAY + world.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(description = "Stops the updater")
|
||||
public void stop(
|
||||
@Param(description = "World to stop the Updater at")
|
||||
World world
|
||||
) {
|
||||
if (!IrisToolbelt.isIrisWorld(world)) {
|
||||
sender().sendMessage(C.GOLD + "This is not an Iris world");
|
||||
return;
|
||||
}
|
||||
if (chunkUpdater == null) {
|
||||
sender().sendMessage(C.GOLD + "You cant stop something that doesnt exist?");
|
||||
return;
|
||||
}
|
||||
if (sender().isPlayer()) {
|
||||
sender().sendMessage("Stopping Updater for: " + C.GRAY + world.getName());
|
||||
} else {
|
||||
Iris.info("Stopping Updater for: " + C.GRAY + world.getName());
|
||||
}
|
||||
chunkUpdater.stop();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -23,6 +23,7 @@ import com.volmit.iris.core.edit.BlockSignal;
|
||||
import com.volmit.iris.core.nms.INMS;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.engine.object.IrisBiome;
|
||||
import com.volmit.iris.engine.object.IrisRegion;
|
||||
import com.volmit.iris.util.data.B;
|
||||
import com.volmit.iris.util.decree.DecreeExecutor;
|
||||
import com.volmit.iris.util.decree.DecreeOrigin;
|
||||
@@ -45,16 +46,16 @@ public class CommandWhat implements DecreeExecutor {
|
||||
public void hand() {
|
||||
try {
|
||||
BlockData bd = player().getInventory().getItemInMainHand().getType().createBlockData();
|
||||
if(!bd.getMaterial().equals(Material.AIR)) {
|
||||
if (!bd.getMaterial().equals(Material.AIR)) {
|
||||
sender().sendMessage("Material: " + C.GREEN + bd.getMaterial().name());
|
||||
sender().sendMessage("Full: " + C.WHITE + bd.getAsString(true));
|
||||
} else {
|
||||
sender().sendMessage("Please hold a block/item");
|
||||
}
|
||||
} catch(Throwable e) {
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
Material bd = player().getInventory().getItemInMainHand().getType();
|
||||
if(!bd.equals(Material.AIR)) {
|
||||
if (!bd.equals(Material.AIR)) {
|
||||
sender().sendMessage("Material: " + C.GREEN + bd.name());
|
||||
} else {
|
||||
sender().sendMessage("Please hold a block/item");
|
||||
@@ -65,63 +66,75 @@ public class CommandWhat implements DecreeExecutor {
|
||||
@Decree(description = "What biome am i in?", origin = DecreeOrigin.PLAYER)
|
||||
public void biome() {
|
||||
try {
|
||||
IrisBiome b = engine().getBiome(player().getLocation().getBlockX(), player().getLocation().getBlockY(), player().getLocation().getBlockZ());
|
||||
IrisBiome b = engine().getBiome(player().getLocation().getBlockX(), player().getLocation().getBlockY() - player().getWorld().getMinHeight(), player().getLocation().getBlockZ());
|
||||
sender().sendMessage("IBiome: " + b.getLoadKey() + " (" + b.getDerivative().name() + ")");
|
||||
|
||||
} catch(Throwable e) {
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
sender().sendMessage("Non-Iris Biome: " + player().getLocation().getBlock().getBiome().name());
|
||||
|
||||
if(player().getLocation().getBlock().getBiome().equals(Biome.CUSTOM)) {
|
||||
if (player().getLocation().getBlock().getBiome().equals(Biome.CUSTOM)) {
|
||||
try {
|
||||
sender().sendMessage("Data Pack Biome: " + INMS.get().getTrueBiomeBaseKey(player().getLocation()) + " (ID: " + INMS.get().getTrueBiomeBaseId(INMS.get().getTrueBiomeBase(player().getLocation())) + ")");
|
||||
} catch(Throwable ee) {
|
||||
} catch (Throwable ee) {
|
||||
Iris.reportError(ee);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(description = "What region am i in?", origin = DecreeOrigin.PLAYER)
|
||||
public void region() {
|
||||
try {
|
||||
IrisRegion r = engine().getRegion(player().getLocation());
|
||||
sender().sendMessage("IRegion: " + r.getLoadKey() + " (" + r.getName() + ")");
|
||||
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
sender().sendMessage(C.IRIS + "Iris worlds only.");
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(description = "What block am i looking at?", origin = DecreeOrigin.PLAYER)
|
||||
public void block() {
|
||||
BlockData bd;
|
||||
try {
|
||||
bd = player().getTargetBlockExact(128, FluidCollisionMode.NEVER).getBlockData();
|
||||
} catch(NullPointerException e) {
|
||||
} catch (NullPointerException e) {
|
||||
Iris.reportError(e);
|
||||
sender().sendMessage("Please look at any block, not at the sky");
|
||||
bd = null;
|
||||
}
|
||||
|
||||
if(bd != null) {
|
||||
if (bd != null) {
|
||||
sender().sendMessage("Material: " + C.GREEN + bd.getMaterial().name());
|
||||
sender().sendMessage("Full: " + C.WHITE + bd.getAsString(true));
|
||||
|
||||
if(B.isStorage(bd)) {
|
||||
if (B.isStorage(bd)) {
|
||||
sender().sendMessage(C.YELLOW + "* Storage Block (Loot Capable)");
|
||||
}
|
||||
|
||||
if(B.isLit(bd)) {
|
||||
if (B.isLit(bd)) {
|
||||
sender().sendMessage(C.YELLOW + "* Lit Block (Light Capable)");
|
||||
}
|
||||
|
||||
if(B.isFoliage(bd)) {
|
||||
if (B.isFoliage(bd)) {
|
||||
sender().sendMessage(C.YELLOW + "* Foliage Block");
|
||||
}
|
||||
|
||||
if(B.isDecorant(bd)) {
|
||||
if (B.isDecorant(bd)) {
|
||||
sender().sendMessage(C.YELLOW + "* Decorant Block");
|
||||
}
|
||||
|
||||
if(B.isFluid(bd)) {
|
||||
if (B.isFluid(bd)) {
|
||||
sender().sendMessage(C.YELLOW + "* Fluid Block");
|
||||
}
|
||||
|
||||
if(B.isFoliagePlantable(bd)) {
|
||||
if (B.isFoliagePlantable(bd)) {
|
||||
sender().sendMessage(C.YELLOW + "* Plantable Foliage Block");
|
||||
}
|
||||
|
||||
if(B.isSolid(bd)) {
|
||||
if (B.isSolid(bd)) {
|
||||
sender().sendMessage(C.YELLOW + "* Solid Block");
|
||||
}
|
||||
}
|
||||
@@ -131,23 +144,23 @@ public class CommandWhat implements DecreeExecutor {
|
||||
public void markers(@Param(description = "Marker name such as cave_floor or cave_ceiling") String marker) {
|
||||
Chunk c = player().getLocation().getChunk();
|
||||
|
||||
if(IrisToolbelt.isIrisWorld(c.getWorld())) {
|
||||
if (IrisToolbelt.isIrisWorld(c.getWorld())) {
|
||||
int m = 1;
|
||||
AtomicInteger v = new AtomicInteger(0);
|
||||
|
||||
for(int xxx = c.getX() - 4; xxx <= c.getX() + 4; xxx++) {
|
||||
for(int zzz = c.getZ() - 4; zzz <= c.getZ() + 4; zzz++) {
|
||||
for (int xxx = c.getX() - 4; xxx <= c.getX() + 4; xxx++) {
|
||||
for (int zzz = c.getZ() - 4; zzz <= c.getZ() + 4; zzz++) {
|
||||
IrisToolbelt.access(c.getWorld()).getEngine().getMantle().findMarkers(xxx, zzz, new MatterMarker(marker))
|
||||
.convert((i) -> i.toLocation(c.getWorld())).forEach((i) -> {
|
||||
J.s(() -> BlockSignal.of(i.getBlock(), 100));
|
||||
v.incrementAndGet();
|
||||
});
|
||||
.convert((i) -> i.toLocation(c.getWorld())).forEach((i) -> {
|
||||
J.s(() -> BlockSignal.of(i.getBlock(), 100));
|
||||
v.incrementAndGet();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
sender().sendMessage("Found " + v.get() + " Nearby Markers (" + marker + ")");
|
||||
} else {
|
||||
sender().sendMessage("Iris worlds only.");
|
||||
sender().sendMessage(C.IRIS + "Iris worlds only.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -51,7 +51,7 @@ public class BlockSignal {
|
||||
active.decrementAndGet();
|
||||
BlockData type = block.getBlockData();
|
||||
MultiBurst.burst.lazy(() -> {
|
||||
for(Player i : block.getWorld().getPlayers()) {
|
||||
for (Player i : block.getWorld().getPlayers()) {
|
||||
i.sendBlockChange(block.getLocation(), block.getBlockData());
|
||||
}
|
||||
});
|
||||
@@ -82,7 +82,7 @@ public class BlockSignal {
|
||||
new SR(20) {
|
||||
@Override
|
||||
public void run() {
|
||||
if(e.isDead()) {
|
||||
if (e.isDead()) {
|
||||
cancel();
|
||||
return;
|
||||
}
|
||||
@@ -98,7 +98,7 @@ public class BlockSignal {
|
||||
BlockData type = block.getBlockData();
|
||||
|
||||
MultiBurst.burst.lazy(() -> {
|
||||
for(Player i : block.getWorld().getPlayers()) {
|
||||
for (Player i : block.getWorld().getPlayers()) {
|
||||
i.sendBlockChange(block.getLocation(), block.getBlockData());
|
||||
}
|
||||
});
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -50,11 +50,11 @@ public class DustRevealer {
|
||||
|
||||
J.s(() -> {
|
||||
new BlockSignal(world.getBlockAt(block.getX(), block.getY(), block.getZ()), 10);
|
||||
if(M.r(0.25)) {
|
||||
if (M.r(0.25)) {
|
||||
world.playSound(block.toBlock(world).getLocation(), Sound.BLOCK_AMETHYST_BLOCK_CHIME, 1f, RNG.r.f(0.2f, 2f));
|
||||
}
|
||||
J.a(() -> {
|
||||
while(BlockSignal.active.get() > 128) {
|
||||
while (BlockSignal.active.get() > 128) {
|
||||
J.sleep(5);
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ public class DustRevealer {
|
||||
is(new BlockPosition(block.getX() + 1, block.getY() + 1, block.getZ() + 1));
|
||||
is(new BlockPosition(block.getX() + 1, block.getY() - 1, block.getZ() - 1));
|
||||
is(new BlockPosition(block.getX() + 1, block.getY() - 1, block.getZ() + 1));
|
||||
} catch(Throwable e) {
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
@@ -97,9 +97,9 @@ public class DustRevealer {
|
||||
World world = block.getWorld();
|
||||
Engine access = IrisToolbelt.access(world).getEngine();
|
||||
|
||||
if(access != null) {
|
||||
if (access != null) {
|
||||
String a = access.getObjectPlacementKey(block.getX(), block.getY() - block.getWorld().getMinHeight(), block.getZ());
|
||||
if(a != null) {
|
||||
if (a != null) {
|
||||
world.playSound(block.getLocation(), Sound.ITEM_LODESTONE_COMPASS_LOCK, 1f, 0.1f);
|
||||
|
||||
sender.sendMessage("Found object " + a);
|
||||
@@ -112,7 +112,7 @@ public class DustRevealer {
|
||||
|
||||
private boolean is(BlockPosition a) {
|
||||
int betterY = a.getY() - world.getMinHeight();
|
||||
if(isValidTry(a) && engine.getObjectPlacementKey(a.getX(), betterY, a.getZ()) != null && engine.getObjectPlacementKey(a.getX(), betterY, a.getZ()).equals(key)) {
|
||||
if (isValidTry(a) && engine.getObjectPlacementKey(a.getX(), betterY, a.getZ()) != null && engine.getObjectPlacementKey(a.getX(), betterY, a.getZ()).equals(key)) {
|
||||
hits.add(a);
|
||||
new DustRevealer(engine, world, a, key, hits);
|
||||
return true;
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -19,14 +19,9 @@
|
||||
package com.volmit.iris.core.edit;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.service.WandSVC;
|
||||
import com.volmit.iris.engine.object.IrisDirection;
|
||||
import com.volmit.iris.engine.object.IrisJigsawPiece;
|
||||
import com.volmit.iris.engine.object.IrisJigsawPieceConnector;
|
||||
import com.volmit.iris.engine.object.IrisObject;
|
||||
import com.volmit.iris.engine.object.IrisPosition;
|
||||
import com.volmit.iris.engine.object.*;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.data.Cuboid;
|
||||
@@ -66,13 +61,12 @@ public class JigsawEditor implements Listener {
|
||||
private Location target;
|
||||
|
||||
public JigsawEditor(Player player, IrisJigsawPiece piece, IrisObject object, File saveLocation) {
|
||||
if(editors.containsKey(player)) {
|
||||
if (editors.containsKey(player)) {
|
||||
editors.get(player).close();
|
||||
}
|
||||
|
||||
editors.put(player, this);
|
||||
if(object == null)
|
||||
{
|
||||
if (object == null) {
|
||||
throw new RuntimeException("Object is null! " + piece.getObject());
|
||||
}
|
||||
this.object = object;
|
||||
@@ -90,20 +84,20 @@ public class JigsawEditor implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void on(PlayerMoveEvent e) {
|
||||
if(e.getPlayer().equals(player)) {
|
||||
if (e.getPlayer().equals(player)) {
|
||||
try {
|
||||
target = player.getTargetBlockExact(7).getLocation();
|
||||
} catch(Throwable ex) {
|
||||
} catch (Throwable ex) {
|
||||
Iris.reportError(ex);
|
||||
target = player.getLocation();
|
||||
return;
|
||||
}
|
||||
|
||||
if(cuboid.contains(target)) {
|
||||
for(IrisPosition i : falling.k()) {
|
||||
if (cuboid.contains(target)) {
|
||||
for (IrisPosition i : falling.k()) {
|
||||
Location at = toLocation(i);
|
||||
|
||||
if(at.equals(target)) {
|
||||
if (at.equals(target)) {
|
||||
falling.remove(i).run();
|
||||
}
|
||||
}
|
||||
@@ -113,43 +107,43 @@ public class JigsawEditor implements Listener {
|
||||
|
||||
public Location toLocation(IrisPosition i) {
|
||||
return origin.clone()
|
||||
.add(new Vector(i.getX(), i.getY(), i.getZ()))
|
||||
.add(object.getCenter())
|
||||
.getBlock()
|
||||
.getLocation();
|
||||
.add(new Vector(i.getX(), i.getY(), i.getZ()))
|
||||
.add(object.getCenter())
|
||||
.getBlock()
|
||||
.getLocation();
|
||||
}
|
||||
|
||||
public IrisPosition toPosition(Location l) {
|
||||
return new IrisPosition(l.clone().getBlock().getLocation()
|
||||
.subtract(origin.clone())
|
||||
.subtract(object.getCenter())
|
||||
.add(1, 1, 1)
|
||||
.toVector());
|
||||
.subtract(origin.clone())
|
||||
.subtract(object.getCenter())
|
||||
.add(1, 1, 1)
|
||||
.toVector());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void on(PlayerInteractEvent e) {
|
||||
if(e.getAction().equals(Action.RIGHT_CLICK_BLOCK)) {
|
||||
if(e.getClickedBlock() != null && cuboid.contains(e.getClickedBlock().getLocation()) && e.getPlayer().equals(player)) {
|
||||
if (e.getAction().equals(Action.RIGHT_CLICK_BLOCK)) {
|
||||
if (e.getClickedBlock() != null && cuboid.contains(e.getClickedBlock().getLocation()) && e.getPlayer().equals(player)) {
|
||||
IrisPosition pos = toPosition(e.getClickedBlock().getLocation());
|
||||
IrisJigsawPieceConnector connector = null;
|
||||
for(IrisJigsawPieceConnector i : piece.getConnectors()) {
|
||||
if(i.getPosition().equals(pos)) {
|
||||
for (IrisJigsawPieceConnector i : piece.getConnectors()) {
|
||||
if (i.getPosition().equals(pos)) {
|
||||
connector = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!player.isSneaking() && connector == null) {
|
||||
if (!player.isSneaking() && connector == null) {
|
||||
connector = new IrisJigsawPieceConnector();
|
||||
connector.setDirection(IrisDirection.getDirection(e.getBlockFace()));
|
||||
connector.setPosition(pos);
|
||||
piece.getConnectors().add(connector);
|
||||
player.playSound(e.getClickedBlock().getLocation(), Sound.ENTITY_ITEM_FRAME_ADD_ITEM, 1f, 1f);
|
||||
} else if(player.isSneaking() && connector != null) {
|
||||
} else if (player.isSneaking() && connector != null) {
|
||||
piece.getConnectors().remove(connector);
|
||||
player.playSound(e.getClickedBlock().getLocation(), Sound.ENTITY_ITEM_FRAME_REMOVE_ITEM, 1f, 1f);
|
||||
} else if(connector != null && !player.isSneaking()) {
|
||||
} else if (connector != null && !player.isSneaking()) {
|
||||
connector.setDirection(IrisDirection.getDirection(e.getBlockFace()));
|
||||
player.playSound(e.getClickedBlock().getLocation(), Sound.ENTITY_ITEM_FRAME_ROTATE_ITEM, 1f, 1f);
|
||||
}
|
||||
@@ -157,10 +151,8 @@ public class JigsawEditor implements Listener {
|
||||
}
|
||||
}
|
||||
|
||||
private void removeKey(JSONObject o, String... path)
|
||||
{
|
||||
if(path.length == 1)
|
||||
{
|
||||
private void removeKey(JSONObject o, String... path) {
|
||||
if (path.length == 1) {
|
||||
o.remove(path[0]);
|
||||
return;
|
||||
}
|
||||
@@ -170,13 +162,11 @@ public class JigsawEditor implements Listener {
|
||||
removeKey(o.getJSONObject(path[0]), s.toArray(new String[0]));
|
||||
}
|
||||
|
||||
private List<JSONObject> getObjectsInArray(JSONObject a, String key)
|
||||
{
|
||||
private List<JSONObject> getObjectsInArray(JSONObject a) { // This gets all the objects in an array that are connectors
|
||||
KList<JSONObject> o = new KList<>();
|
||||
|
||||
for(int i = 0; i < a.getJSONArray(key).length(); i++)
|
||||
{
|
||||
o.add(a.getJSONArray(key).getJSONObject(i));
|
||||
for (int i = 0; i < a.getJSONArray("connectors").length(); i++) {
|
||||
o.add(a.getJSONArray("connectors").getJSONObject(i));
|
||||
}
|
||||
|
||||
return o;
|
||||
@@ -192,16 +182,15 @@ public class JigsawEditor implements Listener {
|
||||
|
||||
// remove root key
|
||||
removeKey(j, "placementOptions"); // should work
|
||||
j.remove("placementOptions"); // otherwise
|
||||
j.remove("placementOptions"); // otherwise
|
||||
|
||||
// Remove key in all objects in array
|
||||
for(JSONObject i : getObjectsInArray(j, "connectors"))
|
||||
{
|
||||
removeKey(i, "rotateConnector");
|
||||
}
|
||||
// Remove key in all objects in array
|
||||
for (JSONObject i : getObjectsInArray(j)) {
|
||||
removeKey(i, "rotateConnector");
|
||||
}
|
||||
|
||||
IO.writeAll(targetSaveLocation, j.toString(4));
|
||||
} catch(IOException e) {
|
||||
} catch (IOException e) {
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
@@ -215,20 +204,20 @@ public class JigsawEditor implements Listener {
|
||||
object.unplaceCenterY(origin);
|
||||
falling.v().forEach(Runnable::run);
|
||||
}).get();
|
||||
} catch(InterruptedException | ExecutionException e) {
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
editors.remove(player);
|
||||
}
|
||||
|
||||
public void onTick() {
|
||||
if(cl.flip()) {
|
||||
if (cl.flip()) {
|
||||
Iris.service(WandSVC.class).draw(cuboid, player);
|
||||
|
||||
f:
|
||||
for(IrisPosition i : falling.k()) {
|
||||
for(IrisJigsawPieceConnector j : piece.getConnectors()) {
|
||||
if(j.getPosition().equals(i)) {
|
||||
for (IrisPosition i : falling.k()) {
|
||||
for (IrisJigsawPieceConnector j : piece.getConnectors()) {
|
||||
if (j.getPosition().equals(i)) {
|
||||
continue f;
|
||||
}
|
||||
}
|
||||
@@ -236,23 +225,23 @@ public class JigsawEditor implements Listener {
|
||||
falling.remove(i).run();
|
||||
}
|
||||
|
||||
for(IrisJigsawPieceConnector i : piece.getConnectors()) {
|
||||
for (IrisJigsawPieceConnector i : piece.getConnectors()) {
|
||||
IrisPosition pos = i.getPosition();
|
||||
Location at = toLocation(pos);
|
||||
|
||||
Vector dir = i.getDirection().toVector().clone();
|
||||
|
||||
|
||||
for(int ix = 0; ix < RNG.r.i(1, 3); ix++) {
|
||||
for (int ix = 0; ix < RNG.r.i(1, 3); ix++) {
|
||||
at.getWorld().spawnParticle(Particle.SOUL_FIRE_FLAME, at.clone().getBlock().getLocation().add(0.25, 0.25, 0.25).add(RNG.r.d(0.5), RNG.r.d(0.5), RNG.r.d(0.5)), 0, dir.getX(), dir.getY(), dir.getZ(), 0.092 + RNG.r.d(-0.03, 0.08));
|
||||
}
|
||||
|
||||
if(at.getBlock().getLocation().equals(target)) {
|
||||
if (at.getBlock().getLocation().equals(target)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!falling.containsKey(pos)) {
|
||||
if(at.getBlock().getType().isAir()) {
|
||||
if (!falling.containsKey(pos)) {
|
||||
if (at.getBlock().getType().isAir()) {
|
||||
at.getBlock().setType(Material.STONE);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -19,6 +19,7 @@
|
||||
package com.volmit.iris.core.gui;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.events.IrisEngineHotloadEvent;
|
||||
import com.volmit.iris.engine.object.NoiseStyle;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
@@ -35,24 +36,9 @@ import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLayeredPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JViewport;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseMotionListener;
|
||||
import java.awt.event.MouseWheelEvent;
|
||||
import java.awt.event.MouseWheelListener;
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@@ -76,7 +62,7 @@ public class NoiseExplorerGUI extends JPanel implements MouseWheelListener, List
|
||||
@SuppressWarnings("CanBeFinal")
|
||||
RollingSequence r = new RollingSequence(20);
|
||||
@SuppressWarnings("CanBeFinal")
|
||||
boolean colorMode = true;
|
||||
boolean colorMode = IrisSettings.get().getGui().colorMode;
|
||||
double scale = 1;
|
||||
CNG cng = NoiseStyle.STATIC.create(new RNG(RNG.r.nextLong()));
|
||||
@SuppressWarnings("CanBeFinal")
|
||||
@@ -133,10 +119,10 @@ public class NoiseExplorerGUI extends JPanel implements MouseWheelListener, List
|
||||
frame.add(pane);
|
||||
File file = Iris.getCached("Iris Icon", "https://raw.githubusercontent.com/VolmitSoftware/Iris/master/icon.png");
|
||||
|
||||
if(file != null) {
|
||||
if (file != null) {
|
||||
try {
|
||||
frame.setIconImage(ImageIO.read(file));
|
||||
} catch(IOException e) {
|
||||
} catch (IOException e) {
|
||||
Iris.reportError(e);
|
||||
}
|
||||
}
|
||||
@@ -148,7 +134,7 @@ public class NoiseExplorerGUI extends JPanel implements MouseWheelListener, List
|
||||
JFrame frame = new JFrame("Noise Explorer");
|
||||
NoiseExplorerGUI nv = new NoiseExplorerGUI();
|
||||
frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
|
||||
KList<String> li = new KList<>(NoiseStyle.values()).toStringList();
|
||||
KList<String> li = new KList<>(NoiseStyle.values()).toStringList().sort();
|
||||
combo = new JComboBox<>(li.toArray(new String[0]));
|
||||
combo.setSelectedItem("STATIC");
|
||||
combo.setFocusable(false);
|
||||
@@ -167,10 +153,10 @@ public class NoiseExplorerGUI extends JPanel implements MouseWheelListener, List
|
||||
frame.add(pane);
|
||||
File file = Iris.getCached("Iris Icon", "https://raw.githubusercontent.com/VolmitSoftware/Iris/master/icon.png");
|
||||
|
||||
if(file != null) {
|
||||
if (file != null) {
|
||||
try {
|
||||
frame.setIconImage(ImageIO.read(file));
|
||||
} catch(IOException e) {
|
||||
} catch (IOException e) {
|
||||
Iris.reportError(e);
|
||||
}
|
||||
}
|
||||
@@ -194,14 +180,14 @@ public class NoiseExplorerGUI extends JPanel implements MouseWheelListener, List
|
||||
|
||||
@EventHandler
|
||||
public void on(IrisEngineHotloadEvent e) {
|
||||
if(generator != null)
|
||||
if (generator != null)
|
||||
generator = loader.get();
|
||||
}
|
||||
|
||||
public void mouseWheelMoved(MouseWheelEvent e) {
|
||||
|
||||
int notches = e.getWheelRotation();
|
||||
if(e.isControlDown()) {
|
||||
if (e.isControlDown()) {
|
||||
t = t + ((0.0025 * t) * notches);
|
||||
return;
|
||||
}
|
||||
@@ -212,51 +198,51 @@ public class NoiseExplorerGUI extends JPanel implements MouseWheelListener, List
|
||||
|
||||
@Override
|
||||
public void paint(Graphics g) {
|
||||
if(scale < ascale) {
|
||||
if (scale < ascale) {
|
||||
ascale -= Math.abs(scale - ascale) * 0.16;
|
||||
}
|
||||
|
||||
if(scale > ascale) {
|
||||
if (scale > ascale) {
|
||||
ascale += Math.abs(ascale - scale) * 0.16;
|
||||
}
|
||||
|
||||
if(t < tz) {
|
||||
if (t < tz) {
|
||||
tz -= Math.abs(t - tz) * 0.29;
|
||||
}
|
||||
|
||||
if(t > tz) {
|
||||
if (t > tz) {
|
||||
tz += Math.abs(tz - t) * 0.29;
|
||||
}
|
||||
|
||||
if(ox < oxp) {
|
||||
if (ox < oxp) {
|
||||
oxp -= Math.abs(ox - oxp) * 0.16;
|
||||
}
|
||||
|
||||
if(ox > oxp) {
|
||||
if (ox > oxp) {
|
||||
oxp += Math.abs(oxp - ox) * 0.16;
|
||||
}
|
||||
|
||||
if(oz < ozp) {
|
||||
if (oz < ozp) {
|
||||
ozp -= Math.abs(oz - ozp) * 0.16;
|
||||
}
|
||||
|
||||
if(oz > ozp) {
|
||||
if (oz > ozp) {
|
||||
ozp += Math.abs(ozp - oz) * 0.16;
|
||||
}
|
||||
|
||||
if(mx < mxx) {
|
||||
if (mx < mxx) {
|
||||
mxx -= Math.abs(mx - mxx) * 0.16;
|
||||
}
|
||||
|
||||
if(mx > mxx) {
|
||||
if (mx > mxx) {
|
||||
mxx += Math.abs(mxx - mx) * 0.16;
|
||||
}
|
||||
|
||||
if(mz < mzz) {
|
||||
if (mz < mzz) {
|
||||
mzz -= Math.abs(mz - mzz) * 0.16;
|
||||
}
|
||||
|
||||
if(mz > mzz) {
|
||||
if (mz > mzz) {
|
||||
mzz += Math.abs(mzz - mz) * 0.16;
|
||||
}
|
||||
|
||||
@@ -265,35 +251,37 @@ public class NoiseExplorerGUI extends JPanel implements MouseWheelListener, List
|
||||
accuracy = down ? accuracy * 4 : accuracy;
|
||||
int v = 1000;
|
||||
|
||||
if(g instanceof Graphics2D gg) {
|
||||
if (g instanceof Graphics2D gg) {
|
||||
|
||||
if(getParent().getWidth() != w || getParent().getHeight() != h) {
|
||||
if (getParent().getWidth() != w || getParent().getHeight() != h) {
|
||||
w = getParent().getWidth();
|
||||
h = getParent().getHeight();
|
||||
img = null;
|
||||
}
|
||||
|
||||
if(img == null) {
|
||||
if (img == null) {
|
||||
img = new BufferedImage(w / accuracy, h / accuracy, BufferedImage.TYPE_INT_RGB);
|
||||
}
|
||||
|
||||
BurstExecutor e = gx.burst(w);
|
||||
|
||||
for(int x = 0; x < w / accuracy; x++) {
|
||||
for (int x = 0; x < w / accuracy; x++) {
|
||||
int xx = x;
|
||||
|
||||
int finalAccuracy = accuracy;
|
||||
e.queue(() -> {
|
||||
for(int z = 0; z < h / finalAccuracy; z++) {
|
||||
for (int z = 0; z < h / finalAccuracy; z++) {
|
||||
double n = generator != null ? generator.apply(((xx * finalAccuracy) * ascale) + oxp, ((z * finalAccuracy) * ascale) + ozp) : cng.noise(((xx * finalAccuracy) * ascale) + oxp, ((z * finalAccuracy) * ascale) + ozp);
|
||||
n = n > 1 ? 1 : n < 0 ? 0 : n;
|
||||
|
||||
try {
|
||||
Color color = colorMode ? Color.getHSBColor((float) (n), 1f - (float) (n * n * n * n * n * n), 1f - (float) n) : Color.getHSBColor(0f, 0f, (float) n);
|
||||
//Color color = colorMode ? Color.getHSBColor((float) (n), 1f - (float) (n * n * n * n * n * n), 1f - (float) n) : Color.getHSBColor(0f, 0f, (float) n);
|
||||
//Color color = colorMode ? Color.getHSBColor((float) (n), (float) (n * n * n * n * n * n), (float) n) : Color.getHSBColor(0f, 0f, (float) n);
|
||||
Color color = colorMode ? Color.getHSBColor((float) n, (float) (n * n * n * n * n * n), (float) n) : Color.getHSBColor(0f, 0f, (float) n);
|
||||
|
||||
int rgb = color.getRGB();
|
||||
img.setRGB(xx, z, rgb);
|
||||
} catch(Throwable xxx) {
|
||||
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -308,15 +296,15 @@ public class NoiseExplorerGUI extends JPanel implements MouseWheelListener, List
|
||||
t += 1D;
|
||||
r.put(p.getMilliseconds());
|
||||
|
||||
if(!isVisible()) {
|
||||
if (!isVisible()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(!getParent().isVisible()) {
|
||||
if (!getParent().isVisible()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(!getParent().getParent().isVisible()) {
|
||||
if (!getParent().getParent().isVisible()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -34,13 +34,11 @@ import com.volmit.iris.util.math.M;
|
||||
import com.volmit.iris.util.math.Position2;
|
||||
import com.volmit.iris.util.scheduling.ChronoLatch;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JPanel;
|
||||
import java.awt.Color;
|
||||
import java.awt.Font;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.KeyListener;
|
||||
import java.awt.image.BufferedImage;
|
||||
@@ -66,24 +64,23 @@ public class PregeneratorJob implements PregenListener {
|
||||
private final IrisPregenerator pregenerator;
|
||||
private final Position2 min;
|
||||
private final Position2 max;
|
||||
private final ChronoLatch cl = new ChronoLatch(TimeUnit.MINUTES.toMillis(1));
|
||||
private final Engine engine;
|
||||
private JFrame frame;
|
||||
private PregenRenderer renderer;
|
||||
private int rgc = 0;
|
||||
private final ChronoLatch cl = new ChronoLatch(TimeUnit.MINUTES.toMillis(1));
|
||||
private String[] info;
|
||||
private final Engine engine;
|
||||
|
||||
public PregeneratorJob(PregenTask task, PregeneratorMethod method, Engine engine) {
|
||||
this.engine = engine;
|
||||
instance = this;
|
||||
monitor = new MemoryMonitor(50);
|
||||
saving = false;
|
||||
info = new String[] {"Initializing..."};
|
||||
info = new String[]{"Initializing..."};
|
||||
this.task = task;
|
||||
this.pregenerator = new IrisPregenerator(task, method, this);
|
||||
max = new Position2(0, 0);
|
||||
min = new Position2(0, 0);
|
||||
KList<Runnable> draw = new KList<>();
|
||||
task.iterateRegions((xx, zz) -> {
|
||||
min.setX(Math.min(xx << 5, min.getX()));
|
||||
min.setZ(Math.min(zz << 5, min.getZ()));
|
||||
@@ -91,19 +88,21 @@ public class PregeneratorJob implements PregenListener {
|
||||
max.setZ(Math.max((zz << 5) + 31, max.getZ()));
|
||||
});
|
||||
|
||||
if(IrisSettings.get().getGui().isUseServerLaunchedGuis()) {
|
||||
if (IrisSettings.get().getGui().isUseServerLaunchedGuis() && task.isGui()) {
|
||||
open();
|
||||
}
|
||||
|
||||
J.a(this.pregenerator::start, 20);
|
||||
var t = new Thread(() -> {
|
||||
J.sleep(1000);
|
||||
this.pregenerator.start();
|
||||
}, "Iris Pregenerator");
|
||||
t.setPriority(Thread.MIN_PRIORITY);
|
||||
t.start();
|
||||
}
|
||||
|
||||
public Mantle getMantle() {
|
||||
return pregenerator.getMantle();
|
||||
}
|
||||
|
||||
public static boolean shutdownInstance() {
|
||||
if(instance == null) {
|
||||
if (instance == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -116,11 +115,11 @@ public class PregeneratorJob implements PregenListener {
|
||||
}
|
||||
|
||||
public static boolean pauseResume() {
|
||||
if(instance == null) {
|
||||
if (instance == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(isPaused()) {
|
||||
if (isPaused()) {
|
||||
instance.pregenerator.resume();
|
||||
} else {
|
||||
instance.pregenerator.pause();
|
||||
@@ -129,7 +128,7 @@ public class PregeneratorJob implements PregenListener {
|
||||
}
|
||||
|
||||
public static boolean isPaused() {
|
||||
if(instance == null) {
|
||||
if (instance == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -140,7 +139,7 @@ public class PregeneratorJob implements PregenListener {
|
||||
String v = (c.startsWith("#") ? c : "#" + c).trim();
|
||||
try {
|
||||
return Color.decode(v);
|
||||
} catch(Throwable e) {
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
Iris.error("Error Parsing 'color', (" + c + ")");
|
||||
}
|
||||
@@ -148,6 +147,10 @@ public class PregeneratorJob implements PregenListener {
|
||||
return Color.RED;
|
||||
}
|
||||
|
||||
public Mantle getMantle() {
|
||||
return pregenerator.getMantle();
|
||||
}
|
||||
|
||||
public PregeneratorJob onProgress(Consumer<Double> c) {
|
||||
onProgress.add(c);
|
||||
return this;
|
||||
@@ -159,21 +162,19 @@ public class PregeneratorJob implements PregenListener {
|
||||
}
|
||||
|
||||
public void drawRegion(int x, int z, Color color) {
|
||||
J.a(() -> {
|
||||
PregenTask.iterateRegion(x, z, (xx, zz) -> {
|
||||
draw(xx, zz, color);
|
||||
J.sleep(3);
|
||||
});
|
||||
});
|
||||
J.a(() -> PregenTask.iterateRegion(x, z, (xx, zz) -> {
|
||||
draw(xx, zz, color);
|
||||
J.sleep(3);
|
||||
}));
|
||||
}
|
||||
|
||||
public void draw(int x, int z, Color color) {
|
||||
try {
|
||||
if(renderer != null && frame != null && frame.isVisible()) {
|
||||
if (renderer != null && frame != null && frame.isVisible()) {
|
||||
renderer.func.accept(new Position2(x, z), color);
|
||||
}
|
||||
} catch(Throwable ignored) {
|
||||
|
||||
} catch (Throwable ignored) {
|
||||
Iris.error("Failed to draw pregen");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -191,8 +192,8 @@ public class PregeneratorJob implements PregenListener {
|
||||
monitor.close();
|
||||
J.sleep(3000);
|
||||
frame.setVisible(false);
|
||||
} catch(Throwable e) {
|
||||
|
||||
} catch (Throwable ignored) {
|
||||
Iris.error("Error closing pregen gui");
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -206,8 +207,7 @@ public class PregeneratorJob implements PregenListener {
|
||||
renderer.l = new ReentrantLock();
|
||||
renderer.frame = frame;
|
||||
renderer.job = this;
|
||||
renderer.func = (c, b) ->
|
||||
{
|
||||
renderer.func = (c, b) -> {
|
||||
renderer.l.lock();
|
||||
renderer.order.add(() -> renderer.draw(c, b, renderer.bg));
|
||||
renderer.l.unlock();
|
||||
@@ -215,40 +215,36 @@ public class PregeneratorJob implements PregenListener {
|
||||
frame.add(renderer);
|
||||
frame.setSize(1000, 1000);
|
||||
frame.setVisible(true);
|
||||
} catch(Throwable e) {
|
||||
|
||||
} catch (Throwable ignored) {
|
||||
Iris.error("Error opening pregen gui");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTick(double chunksPerSecond, double chunksPerMinute, double regionsPerMinute, double percent, int generated, int totalChunks, int chunksRemaining, long eta, long elapsed, String method) {
|
||||
info = new String[] {
|
||||
(paused() ? "PAUSED" : (saving ? "Saving... " : "Generating")) + " " + Form.f(generated) + " of " + Form.f(totalChunks) + " (" + Form.pc(percent, 0) + " Complete)",
|
||||
"Speed: " + Form.f(chunksPerSecond, 0) + " Chunks/s, " + Form.f(regionsPerMinute, 1) + " Regions/m, " + Form.f(chunksPerMinute, 0) + " Chunks/m",
|
||||
Form.duration(eta, 2) + " Remaining " + " (" + Form.duration(elapsed, 2) + " Elapsed)",
|
||||
"Generation Method: " + method,
|
||||
"Memory: " + Form.memSize(monitor.getUsedBytes(), 2) + " (" + Form.pc(monitor.getUsagePercent(), 0) + ") Pressure: " + Form.memSize(monitor.getPressure(), 0) + "/s",
|
||||
info = new String[]{
|
||||
(paused() ? "PAUSED" : (saving ? "Saving... " : "Generating")) + " " + Form.f(generated) + " of " + Form.f(totalChunks) + " (" + Form.pc(percent, 0) + " Complete)",
|
||||
"Speed: " + Form.f(chunksPerSecond, 0) + " Chunks/s, " + Form.f(regionsPerMinute, 1) + " Regions/m, " + Form.f(chunksPerMinute, 0) + " Chunks/m",
|
||||
Form.duration(eta, 2) + " Remaining " + " (" + Form.duration(elapsed, 2) + " Elapsed)",
|
||||
"Generation Method: " + method,
|
||||
"Memory: " + Form.memSize(monitor.getUsedBytes(), 2) + " (" + Form.pc(monitor.getUsagePercent(), 0) + ") Pressure: " + Form.memSize(monitor.getPressure(), 0) + "/s",
|
||||
|
||||
};
|
||||
|
||||
for(Consumer<Double> i : onProgress) {
|
||||
for (Consumer<Double> i : onProgress) {
|
||||
i.accept(percent);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChunkGenerating(int x, int z) {
|
||||
if(engine != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
draw(x, z, COLOR_GENERATING);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChunkGenerated(int x, int z) {
|
||||
if(engine != null) {
|
||||
if (engine != null) {
|
||||
draw(x, z, engine.draw((x << 4) + 8, (z << 4) + 8));
|
||||
return;
|
||||
}
|
||||
@@ -260,10 +256,31 @@ public class PregeneratorJob implements PregenListener {
|
||||
public void onRegionGenerated(int x, int z) {
|
||||
shouldGc();
|
||||
rgc++;
|
||||
|
||||
// Each region is 32x32 chunks
|
||||
for (int chunkOffsetX = 0; chunkOffsetX < 32; chunkOffsetX++) {
|
||||
for (int chunkOffsetZ = 0; chunkOffsetZ < 32; chunkOffsetZ++) {
|
||||
// Calculate actual chunk coordinates
|
||||
int chunkX = (x << 5) + chunkOffsetX;
|
||||
int chunkZ = (z << 5) + chunkOffsetZ;
|
||||
|
||||
if (engine != null) {
|
||||
// Calculate the center block of the chunk
|
||||
int centerBlockX = (chunkX << 4) + 8;
|
||||
int centerBlockZ = (chunkZ << 4) + 8;
|
||||
|
||||
// Draw the chunk
|
||||
draw(chunkX, chunkZ, engine.draw(centerBlockX, centerBlockZ));
|
||||
} else {
|
||||
// If engine is null, use the default color
|
||||
draw(chunkX, chunkZ, COLOR_GENERATED);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void shouldGc() {
|
||||
if(cl.flip() && rgc > 16) {
|
||||
if (cl.flip() && rgc > 16) {
|
||||
System.gc();
|
||||
}
|
||||
}
|
||||
@@ -322,7 +339,7 @@ public class PregeneratorJob implements PregenListener {
|
||||
|
||||
@Override
|
||||
public void onChunkExistsInRegionGen(int x, int z) {
|
||||
if(engine != null) {
|
||||
if (engine != null) {
|
||||
draw(x, z, engine.draw((x << 4) + 8, (z << 4) + 8));
|
||||
return;
|
||||
}
|
||||
@@ -371,10 +388,10 @@ public class PregeneratorJob implements PregenListener {
|
||||
bg = (Graphics2D) image.getGraphics();
|
||||
l.lock();
|
||||
|
||||
while(order.isNotEmpty()) {
|
||||
while (order.isNotEmpty()) {
|
||||
try {
|
||||
order.pop().run();
|
||||
} catch(Throwable e) {
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
|
||||
}
|
||||
@@ -388,12 +405,12 @@ public class PregeneratorJob implements PregenListener {
|
||||
int h = g.getFontMetrics().getHeight() + 5;
|
||||
int hh = 20;
|
||||
|
||||
if(job.paused()) {
|
||||
if (job.paused()) {
|
||||
g.drawString("PAUSED", 20, hh += h);
|
||||
|
||||
g.drawString("Press P to Resume", 20, hh += h);
|
||||
} else {
|
||||
for(String i : prog) {
|
||||
for (String i : prog) {
|
||||
g.drawString(i, 20, hh += h);
|
||||
}
|
||||
|
||||
@@ -429,7 +446,7 @@ public class PregeneratorJob implements PregenListener {
|
||||
|
||||
@Override
|
||||
public void keyReleased(KeyEvent e) {
|
||||
if(e.getKeyCode() == KeyEvent.VK_P) {
|
||||
if (e.getKeyCode() == KeyEvent.VK_P) {
|
||||
PregeneratorJob.pauseResume();
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -44,16 +44,10 @@ import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.MouseInputListener;
|
||||
import java.awt.*;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.KeyListener;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseMotionListener;
|
||||
import java.awt.event.MouseWheelEvent;
|
||||
import java.awt.event.MouseWheelListener;
|
||||
import java.awt.event.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@@ -86,6 +80,7 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
||||
private boolean lowtile = false;
|
||||
private boolean follow = false;
|
||||
private boolean alt = false;
|
||||
private boolean dragging = false;
|
||||
private IrisRenderer renderer;
|
||||
private IrisWorld world;
|
||||
private double velocity = 0;
|
||||
@@ -143,7 +138,7 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
||||
J.a(() -> {
|
||||
J.sleep(10000);
|
||||
|
||||
if(!helpIgnored && help) {
|
||||
if (!helpIgnored && help) {
|
||||
help = false;
|
||||
}
|
||||
});
|
||||
@@ -167,11 +162,11 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
||||
frame.setVisible(true);
|
||||
File file = Iris.getCached("Iris Icon", "https://raw.githubusercontent.com/VolmitSoftware/Iris/master/icon.png");
|
||||
|
||||
if(file != null) {
|
||||
if (file != null) {
|
||||
try {
|
||||
nv.texture = ImageIO.read(file);
|
||||
frame.setIconImage(ImageIO.read(file));
|
||||
} catch(IOException e) {
|
||||
} catch (IOException e) {
|
||||
Iris.reportError(e);
|
||||
|
||||
}
|
||||
@@ -180,16 +175,16 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
||||
|
||||
public static void launch(Engine g, int i) {
|
||||
J.a(() ->
|
||||
createAndShowGUI(g, i, g.getWorld()));
|
||||
createAndShowGUI(g, i, g.getWorld()));
|
||||
}
|
||||
|
||||
public boolean updateEngine() {
|
||||
if(engine.isClosed()) {
|
||||
if(world.hasRealWorld()) {
|
||||
if (engine.isClosed()) {
|
||||
if (world.hasRealWorld()) {
|
||||
try {
|
||||
engine = IrisToolbelt.access(world.realWorld()).getEngine();
|
||||
return !engine.isClosed();
|
||||
} catch(Throwable e) {
|
||||
} catch (Throwable e) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -207,6 +202,7 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
||||
|
||||
@Override
|
||||
public void mouseDragged(MouseEvent e) {
|
||||
dragging = true;
|
||||
Point cp = e.getPoint();
|
||||
ox += (lx - cp.getX()) * scale;
|
||||
oz += (lz - cp.getY()) * scale;
|
||||
@@ -217,13 +213,19 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
||||
public int getColor(double wx, double wz) {
|
||||
BiFunction<Double, Double, Integer> colorFunction = (d, dx) -> Color.black.getRGB();
|
||||
|
||||
switch(currentType) {
|
||||
case BIOME, DECORATOR_LOAD, OBJECT_LOAD, LAYER_LOAD -> colorFunction = (x, z) -> engine.getComplex().getTrueBiomeStream().get(x, z).getColor(engine, currentType).getRGB();
|
||||
case BIOME_LAND -> colorFunction = (x, z) -> engine.getComplex().getLandBiomeStream().get(x, z).getColor(engine, currentType).getRGB();
|
||||
case BIOME_SEA -> colorFunction = (x, z) -> engine.getComplex().getSeaBiomeStream().get(x, z).getColor(engine, currentType).getRGB();
|
||||
case REGION -> colorFunction = (x, z) -> engine.getComplex().getRegionStream().get(x, z).getColor(engine.getComplex(), currentType).getRGB();
|
||||
case CAVE_LAND -> colorFunction = (x, z) -> engine.getComplex().getCaveBiomeStream().get(x, z).getColor(engine, currentType).getRGB();
|
||||
case HEIGHT -> colorFunction = (x, z) -> Color.getHSBColor(engine.getComplex().getHeightStream().get(x, z).floatValue(), 100, 100).getRGB();
|
||||
switch (currentType) {
|
||||
case BIOME, DECORATOR_LOAD, OBJECT_LOAD, LAYER_LOAD ->
|
||||
colorFunction = (x, z) -> engine.getComplex().getTrueBiomeStream().get(x, z).getColor(engine, currentType).getRGB();
|
||||
case BIOME_LAND ->
|
||||
colorFunction = (x, z) -> engine.getComplex().getLandBiomeStream().get(x, z).getColor(engine, currentType).getRGB();
|
||||
case BIOME_SEA ->
|
||||
colorFunction = (x, z) -> engine.getComplex().getSeaBiomeStream().get(x, z).getColor(engine, currentType).getRGB();
|
||||
case REGION ->
|
||||
colorFunction = (x, z) -> engine.getComplex().getRegionStream().get(x, z).getColor(engine.getComplex(), currentType).getRGB();
|
||||
case CAVE_LAND ->
|
||||
colorFunction = (x, z) -> engine.getComplex().getCaveBiomeStream().get(x, z).getColor(engine, currentType).getRGB();
|
||||
case HEIGHT ->
|
||||
colorFunction = (x, z) -> Color.getHSBColor(engine.getComplex().getHeightStream().get(x, z).floatValue(), 100, 100).getRGB();
|
||||
}
|
||||
|
||||
return colorFunction.apply(wx, wz);
|
||||
@@ -240,51 +242,51 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
||||
|
||||
@Override
|
||||
public void keyPressed(KeyEvent e) {
|
||||
if(e.getKeyCode() == KeyEvent.VK_SHIFT) {
|
||||
if (e.getKeyCode() == KeyEvent.VK_SHIFT) {
|
||||
shift = true;
|
||||
}
|
||||
if(e.getKeyCode() == KeyEvent.VK_CONTROL) {
|
||||
if (e.getKeyCode() == KeyEvent.VK_CONTROL) {
|
||||
control = true;
|
||||
}
|
||||
if(e.getKeyCode() == KeyEvent.VK_SEMICOLON) {
|
||||
if (e.getKeyCode() == KeyEvent.VK_SEMICOLON) {
|
||||
debug = true;
|
||||
}
|
||||
if(e.getKeyCode() == KeyEvent.VK_SLASH) {
|
||||
if (e.getKeyCode() == KeyEvent.VK_SLASH) {
|
||||
help = true;
|
||||
helpIgnored = true;
|
||||
}
|
||||
if(e.getKeyCode() == KeyEvent.VK_ALT) {
|
||||
if (e.getKeyCode() == KeyEvent.VK_ALT) {
|
||||
alt = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyReleased(KeyEvent e) {
|
||||
if(e.getKeyCode() == KeyEvent.VK_SEMICOLON) {
|
||||
if (e.getKeyCode() == KeyEvent.VK_SEMICOLON) {
|
||||
debug = false;
|
||||
}
|
||||
if(e.getKeyCode() == KeyEvent.VK_SHIFT) {
|
||||
if (e.getKeyCode() == KeyEvent.VK_SHIFT) {
|
||||
shift = false;
|
||||
}
|
||||
|
||||
if(e.getKeyCode() == KeyEvent.VK_CONTROL) {
|
||||
if (e.getKeyCode() == KeyEvent.VK_CONTROL) {
|
||||
control = false;
|
||||
}
|
||||
if(e.getKeyCode() == KeyEvent.VK_SLASH) {
|
||||
if (e.getKeyCode() == KeyEvent.VK_SLASH) {
|
||||
help = false;
|
||||
helpIgnored = true;
|
||||
}
|
||||
if(e.getKeyCode() == KeyEvent.VK_ALT) {
|
||||
if (e.getKeyCode() == KeyEvent.VK_ALT) {
|
||||
alt = false;
|
||||
}
|
||||
|
||||
// Pushes
|
||||
if(e.getKeyCode() == KeyEvent.VK_F) {
|
||||
if (e.getKeyCode() == KeyEvent.VK_F) {
|
||||
follow = !follow;
|
||||
|
||||
if(player != null && follow) {
|
||||
if (player != null && follow) {
|
||||
notify("Following " + player.getName() + ". Press F to disable");
|
||||
} else if(follow) {
|
||||
} else if (follow) {
|
||||
notify("Can't follow, no one is in the world");
|
||||
follow = false;
|
||||
} else {
|
||||
@@ -294,38 +296,38 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
||||
return;
|
||||
}
|
||||
|
||||
if(e.getKeyCode() == KeyEvent.VK_R) {
|
||||
if (e.getKeyCode() == KeyEvent.VK_R) {
|
||||
dump();
|
||||
notify("Refreshing Chunks");
|
||||
return;
|
||||
}
|
||||
|
||||
if(e.getKeyCode() == KeyEvent.VK_P) {
|
||||
if (e.getKeyCode() == KeyEvent.VK_P) {
|
||||
lowtile = !lowtile;
|
||||
dump();
|
||||
notify("Rendering " + (lowtile ? "Low" : "High") + " Quality Tiles");
|
||||
return;
|
||||
}
|
||||
if(e.getKeyCode() == KeyEvent.VK_E) {
|
||||
if (e.getKeyCode() == KeyEvent.VK_E) {
|
||||
eco = !eco;
|
||||
dump();
|
||||
notify("Using " + (eco ? "60" : "Uncapped") + " FPS Limit");
|
||||
return;
|
||||
}
|
||||
if(e.getKeyCode() == KeyEvent.VK_EQUALS) {
|
||||
if (e.getKeyCode() == KeyEvent.VK_EQUALS) {
|
||||
mscale = mscale + ((0.044 * mscale) * -3);
|
||||
mscale = Math.max(mscale, 0.00001);
|
||||
dump();
|
||||
return;
|
||||
}
|
||||
if(e.getKeyCode() == KeyEvent.VK_MINUS) {
|
||||
if (e.getKeyCode() == KeyEvent.VK_MINUS) {
|
||||
mscale = mscale + ((0.044 * mscale) * 3);
|
||||
mscale = Math.max(mscale, 0.00001);
|
||||
dump();
|
||||
return;
|
||||
}
|
||||
|
||||
if(e.getKeyCode() == KeyEvent.VK_BACK_SLASH) {
|
||||
if (e.getKeyCode() == KeyEvent.VK_BACK_SLASH) {
|
||||
mscale = 1D;
|
||||
dump();
|
||||
notify("Zoom Reset");
|
||||
@@ -334,9 +336,9 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
||||
|
||||
int currentMode = currentType.ordinal();
|
||||
|
||||
for(RenderType i : RenderType.values()) {
|
||||
if(e.getKeyChar() == String.valueOf(i.ordinal() + 1).charAt(0)) {
|
||||
if(i.ordinal() != currentMode) {
|
||||
for (RenderType i : RenderType.values()) {
|
||||
if (e.getKeyChar() == String.valueOf(i.ordinal() + 1).charAt(0)) {
|
||||
if (i.ordinal() != currentMode) {
|
||||
currentType = i;
|
||||
dump();
|
||||
notify("Rendering " + Form.capitalizeWords(currentType.name().toLowerCase().replaceAll("\\Q_\\E", " ")));
|
||||
@@ -345,7 +347,7 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
||||
}
|
||||
}
|
||||
|
||||
if(e.getKeyCode() == KeyEvent.VK_M) {
|
||||
if (e.getKeyCode() == KeyEvent.VK_M) {
|
||||
currentType = RenderType.values()[(currentMode + 1) % RenderType.values().length];
|
||||
notify("Rendering " + Form.capitalizeWords(currentType.name().toLowerCase().replaceAll("\\Q_\\E", " ")));
|
||||
dump();
|
||||
@@ -361,15 +363,15 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
||||
BlockPosition key = new BlockPosition((int) mscale, Math.floorDiv(x, div), Math.floorDiv(z, div));
|
||||
fg.add(key);
|
||||
|
||||
if(positions.containsKey(key)) {
|
||||
if (positions.containsKey(key)) {
|
||||
return positions.get(key);
|
||||
}
|
||||
|
||||
if(fastpositions.containsKey(key)) {
|
||||
if(!working.contains(key) && working.size() < 9) {
|
||||
if (fastpositions.containsKey(key)) {
|
||||
if (!working.contains(key) && working.size() < 9) {
|
||||
m.set(m.get() - 1);
|
||||
|
||||
if(m.get() >= 0 && velocity < 50) {
|
||||
if (m.get() >= 0 && velocity < 50) {
|
||||
working.add(key);
|
||||
double mk = mscale;
|
||||
double mkd = scale;
|
||||
@@ -380,7 +382,7 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
||||
rs.put(ps.getMilliseconds());
|
||||
working.remove(key);
|
||||
|
||||
if(mk == mscale && mkd == scale) {
|
||||
if (mk == mscale && mkd == scale) {
|
||||
positions.put(key, b);
|
||||
}
|
||||
});
|
||||
@@ -390,7 +392,7 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
||||
return fastpositions.get(key);
|
||||
}
|
||||
|
||||
if(workingfast.contains(key) || workingfast.size() > Runtime.getRuntime().availableProcessors()) {
|
||||
if (workingfast.contains(key) || workingfast.size() > Runtime.getRuntime().availableProcessors()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -404,7 +406,7 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
||||
rs.put(ps.getMilliseconds());
|
||||
workingfast.remove(key);
|
||||
|
||||
if(mk == mscale && mkd == scale) {
|
||||
if (mk == mscale && mkd == scale) {
|
||||
fastpositions.put(key, b);
|
||||
}
|
||||
});
|
||||
@@ -413,7 +415,7 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
||||
|
||||
private double getWorldX(double screenX) {
|
||||
//return (mscale * screenX) + ((oxp / scale) * mscale);
|
||||
return (mscale * screenX) + ((oxp / scale));
|
||||
return (mscale * screenX) + ((oxp / scale) * mscale);
|
||||
}
|
||||
|
||||
private double getWorldZ(double screenZ) {
|
||||
@@ -431,15 +433,11 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
||||
@Override
|
||||
public void paint(Graphics gx) {
|
||||
|
||||
if(engine.isClosed()) {
|
||||
if (engine.isClosed()) {
|
||||
EventQueue.invokeLater(() -> {
|
||||
try
|
||||
{
|
||||
try {
|
||||
setVisible(false);
|
||||
}
|
||||
|
||||
catch(Throwable e)
|
||||
{
|
||||
} catch (Throwable e) {
|
||||
|
||||
}
|
||||
});
|
||||
@@ -447,49 +445,49 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
||||
return;
|
||||
}
|
||||
|
||||
if(updateEngine()) {
|
||||
if (updateEngine()) {
|
||||
dump();
|
||||
}
|
||||
|
||||
if(ox < oxp) {
|
||||
if (ox < oxp) {
|
||||
velocity = Math.abs(ox - oxp) * 0.36;
|
||||
oxp -= velocity;
|
||||
}
|
||||
|
||||
if(ox > oxp) {
|
||||
if (ox > oxp) {
|
||||
velocity = Math.abs(oxp - ox) * 0.36;
|
||||
oxp += velocity;
|
||||
}
|
||||
|
||||
if(oz < ozp) {
|
||||
if (oz < ozp) {
|
||||
velocity = Math.abs(oz - ozp) * 0.36;
|
||||
ozp -= velocity;
|
||||
}
|
||||
|
||||
if(oz > ozp) {
|
||||
if (oz > ozp) {
|
||||
velocity = Math.abs(ozp - oz) * 0.36;
|
||||
ozp += velocity;
|
||||
}
|
||||
|
||||
if(lx < hx) {
|
||||
if (lx < hx) {
|
||||
hx -= Math.abs(lx - hx) * 0.36;
|
||||
}
|
||||
|
||||
if(lx > hx) {
|
||||
if (lx > hx) {
|
||||
hx += Math.abs(hx - lx) * 0.36;
|
||||
}
|
||||
|
||||
if(lz < hz) {
|
||||
if (lz < hz) {
|
||||
hz -= Math.abs(lz - hz) * 0.36;
|
||||
}
|
||||
|
||||
if(lz > hz) {
|
||||
if (lz > hz) {
|
||||
hz += Math.abs(hz - lz) * 0.36;
|
||||
}
|
||||
|
||||
if(centities.flip()) {
|
||||
if (centities.flip()) {
|
||||
J.s(() -> {
|
||||
synchronized(lastEntities) {
|
||||
synchronized (lastEntities) {
|
||||
lastEntities.clear();
|
||||
lastEntities.addAll(world.getEntitiesByClass(LivingEntity.class));
|
||||
}
|
||||
@@ -503,7 +501,7 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
||||
double vscale = scale;
|
||||
scale = w / 12D;
|
||||
|
||||
if(scale != vscale) {
|
||||
if (scale != vscale) {
|
||||
positions.clear();
|
||||
}
|
||||
|
||||
@@ -515,15 +513,15 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
||||
int posZ = (int) ozp;
|
||||
m.set(3);
|
||||
|
||||
for(int r = 0; r < Math.max(w, h); r += iscale) {
|
||||
for(int i = -iscale; i < w + iscale; i += iscale) {
|
||||
for(int j = -iscale; j < h + iscale; j += iscale) {
|
||||
for (int r = 0; r < Math.max(w, h); r += iscale) {
|
||||
for (int i = -iscale; i < w + iscale; i += iscale) {
|
||||
for (int j = -iscale; j < h + iscale; j += iscale) {
|
||||
int a = i - (w / 2);
|
||||
int b = j - (h / 2);
|
||||
if(a * a + b * b <= r * r) {
|
||||
if (a * a + b * b <= r * r) {
|
||||
BufferedImage t = getTile(gg, iscale, Math.floorDiv((posX / iscale) + i, iscale) * iscale, Math.floorDiv((posZ / iscale) + j, iscale) * iscale, m);
|
||||
|
||||
if(t != null) {
|
||||
if (t != null) {
|
||||
g.drawImage(t, i - ((posX / iscale) % (iscale)), j - ((posZ / iscale) % (iscale)), iscale, iscale, (img, infoflags, x, y, width, height) -> true);
|
||||
}
|
||||
}
|
||||
@@ -533,8 +531,8 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
||||
|
||||
p.end();
|
||||
|
||||
for(BlockPosition i : positions.k()) {
|
||||
if(!gg.contains(i)) {
|
||||
for (BlockPosition i : positions.k()) {
|
||||
if (!gg.contains(i)) {
|
||||
positions.remove(i);
|
||||
}
|
||||
}
|
||||
@@ -542,15 +540,15 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
||||
hanleFollow();
|
||||
renderOverlays(g);
|
||||
|
||||
if(!isVisible()) {
|
||||
if (!isVisible()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(!getParent().isVisible()) {
|
||||
if (!getParent().isVisible()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(!getParent().getParent().isVisible()) {
|
||||
if (!getParent().getParent().isVisible()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -562,7 +560,7 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
||||
}
|
||||
|
||||
private void hanleFollow() {
|
||||
if(follow && player != null) {
|
||||
if (follow && player != null) {
|
||||
animateTo(player.getLocation().getX(), player.getLocation().getZ());
|
||||
}
|
||||
}
|
||||
@@ -570,16 +568,16 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
||||
private void renderOverlays(Graphics2D g) {
|
||||
renderPlayer(g);
|
||||
|
||||
if(help) {
|
||||
if (help) {
|
||||
renderOverlayHelp(g);
|
||||
} else if(debug) {
|
||||
} else if (debug) {
|
||||
renderOverlayDebug(g);
|
||||
}
|
||||
|
||||
renderOverlayLegend(g);
|
||||
|
||||
renderHoverOverlay(g, shift);
|
||||
if(!notifications.isEmpty()) {
|
||||
if (!notifications.isEmpty()) {
|
||||
renderNotification(g);
|
||||
}
|
||||
}
|
||||
@@ -597,8 +595,8 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
||||
private void renderNotification(Graphics2D g) {
|
||||
drawCardCB(g, notifications.k());
|
||||
|
||||
for(String i : notifications.k()) {
|
||||
if(M.ms() > notifications.get(i)) {
|
||||
for (String i : notifications.k()) {
|
||||
if (M.ms() > notifications.get(i)) {
|
||||
notifications.remove(i);
|
||||
}
|
||||
}
|
||||
@@ -607,32 +605,32 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
||||
private void renderPlayer(Graphics2D g) {
|
||||
Player b = null;
|
||||
|
||||
for(Player i : world.getPlayers()) {
|
||||
for (Player i : world.getPlayers()) {
|
||||
b = i;
|
||||
renderPosition(g, i.getLocation().getX(), i.getLocation().getZ());
|
||||
}
|
||||
|
||||
synchronized(lastEntities) {
|
||||
synchronized (lastEntities) {
|
||||
double dist = Double.MAX_VALUE;
|
||||
LivingEntity h = null;
|
||||
|
||||
for(LivingEntity i : lastEntities) {
|
||||
if(i instanceof Player) {
|
||||
for (LivingEntity i : lastEntities) {
|
||||
if (i instanceof Player) {
|
||||
continue;
|
||||
}
|
||||
|
||||
renderMobPosition(g, i, i.getLocation().getX(), i.getLocation().getZ());
|
||||
if(shift) {
|
||||
if (shift) {
|
||||
double d = i.getLocation().distanceSquared(new Location(i.getWorld(), getWorldX(hx), i.getLocation().getY(), getWorldZ(hz)));
|
||||
|
||||
if(d < dist) {
|
||||
if (d < dist) {
|
||||
dist = d;
|
||||
h = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(h != null && shift) {
|
||||
if (h != null && shift) {
|
||||
g.setColor(Color.red);
|
||||
g.fillRoundRect((int) getScreenX(h.getLocation().getX()) - 10, (int) getScreenZ(h.getLocation().getZ()) - 10, 20, 20, 20, 20);
|
||||
KList<String> k = new KList<>();
|
||||
@@ -657,7 +655,7 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
||||
}
|
||||
|
||||
private void renderPosition(Graphics2D g, double x, double z) {
|
||||
if(texture != null) {
|
||||
if (texture != null) {
|
||||
g.drawImage(texture, (int) getScreenX(x), (int) getScreenZ(z), 66, 66, (img, infoflags, xx, xy, width, height) -> true);
|
||||
} else {
|
||||
g.setColor(Color.darkGray);
|
||||
@@ -679,7 +677,7 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
||||
l.add("Biome: " + biome.getName());
|
||||
l.add("Region: " + region.getName() + "(" + region.getLoadKey() + ")");
|
||||
l.add("Block " + (int) getWorldX(hx) + ", " + (int) getWorldZ(hz));
|
||||
if(detailed) {
|
||||
if (detailed) {
|
||||
l.add("Chunk " + ((int) getWorldX(hx) >> 4) + ", " + ((int) getWorldZ(hz) >> 4));
|
||||
l.add("Region " + (((int) getWorldX(hx) >> 4) >> 5) + ", " + (((int) getWorldZ(hz) >> 4) >> 5));
|
||||
l.add("Key: " + biome.getLoadKey());
|
||||
@@ -708,7 +706,7 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
||||
l.add("E to toggle Eco FPS Mode");
|
||||
|
||||
int ff = 0;
|
||||
for(RenderType i : RenderType.values()) {
|
||||
for (RenderType i : RenderType.values()) {
|
||||
ff++;
|
||||
l.add(ff + " to view " + Form.capitalizeWords(i.name().toLowerCase().replaceAll("\\Q_\\E", " ")));
|
||||
}
|
||||
@@ -738,8 +736,9 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
||||
private void open() {
|
||||
IrisComplex complex = engine.getComplex();
|
||||
File r = null;
|
||||
switch(currentType) {
|
||||
case BIOME, LAYER_LOAD, DECORATOR_LOAD, OBJECT_LOAD, HEIGHT -> r = complex.getTrueBiomeStream().get(getWorldX(hx), getWorldZ(hz)).openInVSCode();
|
||||
switch (currentType) {
|
||||
case BIOME, LAYER_LOAD, DECORATOR_LOAD, OBJECT_LOAD, HEIGHT ->
|
||||
r = complex.getTrueBiomeStream().get(getWorldX(hx), getWorldZ(hz)).openInVSCode();
|
||||
case BIOME_LAND -> r = complex.getLandBiomeStream().get(getWorldX(hx), getWorldZ(hz)).openInVSCode();
|
||||
case BIOME_SEA -> r = complex.getSeaBiomeStream().get(getWorldX(hx), getWorldZ(hz)).openInVSCode();
|
||||
case REGION -> r = complex.getRegionStream().get(getWorldX(hx), getWorldZ(hz)).openInVSCode();
|
||||
@@ -751,7 +750,7 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
||||
|
||||
private void teleport() {
|
||||
J.s(() -> {
|
||||
if(player != null) {
|
||||
if (player != null) {
|
||||
int xx = (int) getWorldX(hx);
|
||||
int zz = (int) getWorldZ(hz);
|
||||
int h = engine.getComplex().getRoundedHeighteightStream().get(xx, zz);
|
||||
@@ -776,7 +775,7 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
||||
int h = 0;
|
||||
int w = 0;
|
||||
|
||||
for(String i : text) {
|
||||
for (String i : text) {
|
||||
h += g.getFontMetrics().getHeight();
|
||||
w = Math.max(w, g.getFontMetrics().stringWidth(i));
|
||||
}
|
||||
@@ -796,14 +795,14 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
||||
|
||||
g.setColor(Color.black);
|
||||
int m = 0;
|
||||
for(String i : text) {
|
||||
for (String i : text) {
|
||||
g.drawString(i, x + 14 - cw, y + 14 - ch + (++m * g.getFontMetrics().getHeight()));
|
||||
}
|
||||
}
|
||||
|
||||
public void mouseWheelMoved(MouseWheelEvent e) {
|
||||
int notches = e.getWheelRotation();
|
||||
if(e.isControlDown()) {
|
||||
if (e.isControlDown()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -816,9 +815,9 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
||||
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
if(control) {
|
||||
if (control) {
|
||||
teleport();
|
||||
} else if(alt) {
|
||||
} else if (alt) {
|
||||
open();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.gui.components;
|
||||
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.object.IrisBiome;
|
||||
import com.volmit.iris.engine.object.IrisBiomeGeneratorLink;
|
||||
import com.volmit.iris.util.interpolation.IrisInterpolation;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
public class IrisRenderer {
|
||||
private final Engine renderer;
|
||||
|
||||
public IrisRenderer(Engine renderer) {
|
||||
this.renderer = renderer;
|
||||
}
|
||||
|
||||
public BufferedImage render(double sx, double sz, double size, int resolution, RenderType currentType) {
|
||||
BufferedImage image = new BufferedImage(resolution, resolution, BufferedImage.TYPE_INT_RGB);
|
||||
BiFunction<Double, Double, Integer> colorFunction = (d, dx) -> Color.black.getRGB();
|
||||
|
||||
switch (currentType) {
|
||||
case BIOME, DECORATOR_LOAD, OBJECT_LOAD, LAYER_LOAD ->
|
||||
colorFunction = (x, z) -> renderer.getComplex().getTrueBiomeStream().get(x, z).getColor(renderer, currentType).getRGB();
|
||||
case BIOME_LAND ->
|
||||
colorFunction = (x, z) -> renderer.getComplex().getLandBiomeStream().get(x, z).getColor(renderer, currentType).getRGB();
|
||||
case BIOME_SEA ->
|
||||
colorFunction = (x, z) -> renderer.getComplex().getSeaBiomeStream().get(x, z).getColor(renderer, currentType).getRGB();
|
||||
case REGION ->
|
||||
colorFunction = (x, z) -> renderer.getComplex().getRegionStream().get(x, z).getColor(renderer.getComplex(), currentType).getRGB();
|
||||
case CAVE_LAND ->
|
||||
colorFunction = (x, z) -> renderer.getComplex().getCaveBiomeStream().get(x, z).getColor(renderer, currentType).getRGB();
|
||||
case HEIGHT ->
|
||||
colorFunction = (x, z) -> Color.getHSBColor(renderer.getComplex().getHeightStream().get(x, z).floatValue(), 100, 100).getRGB();
|
||||
case CONTINENT -> colorFunction = (x, z) -> {
|
||||
IrisBiome b = renderer.getBiome((int) Math.round(x), renderer.getMaxHeight() - 1, (int) Math.round(z));
|
||||
IrisBiomeGeneratorLink g = b.getGenerators().get(0);
|
||||
Color c;
|
||||
if (g.getMax(renderer) <= 0) {
|
||||
// Max is below water level, so it is most likely an ocean biome
|
||||
c = Color.BLUE;
|
||||
} else if (g.getMin(renderer) < 0) {
|
||||
// Min is below water level, but max is not, so it is most likely a shore biome
|
||||
c = Color.YELLOW;
|
||||
} else {
|
||||
// Both min and max are above water level, so it is most likely a land biome
|
||||
c = Color.GREEN;
|
||||
}
|
||||
return c.getRGB();
|
||||
};
|
||||
}
|
||||
|
||||
double x, z;
|
||||
int i, j;
|
||||
for (i = 0; i < resolution; i++) {
|
||||
x = IrisInterpolation.lerp(sx, sx + size, (double) i / (double) (resolution));
|
||||
|
||||
for (j = 0; j < resolution; j++) {
|
||||
z = IrisInterpolation.lerp(sz, sz + size, (double) j / (double) (resolution));
|
||||
image.setRGB(i, j, colorFunction.apply(x, z));
|
||||
}
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -19,5 +19,5 @@
|
||||
package com.volmit.iris.core.gui.components;
|
||||
|
||||
public enum RenderType {
|
||||
BIOME, BIOME_LAND, BIOME_SEA, REGION, CAVE_LAND, HEIGHT, OBJECT_LOAD, DECORATOR_LOAD, LAYER_LOAD
|
||||
BIOME, BIOME_LAND, BIOME_SEA, REGION, CAVE_LAND, HEIGHT, OBJECT_LOAD, DECORATOR_LOAD, CONTINENT, LAYER_LOAD
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
package com.volmit.iris.core.gui.components;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.*;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Renderer {
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -0,0 +1,102 @@
|
||||
//package com.volmit.iris.core.link;
|
||||
//
|
||||
//import com.jojodmo.customitems.api.CustomItemsAPI;
|
||||
//import com.jojodmo.customitems.item.custom.CustomItem;
|
||||
//import com.jojodmo.customitems.item.custom.block.CustomMushroomBlock;
|
||||
//import com.jojodmo.customitems.version.SafeMaterial;
|
||||
//import com.volmit.iris.util.collection.KList;
|
||||
//import com.volmit.iris.util.reflect.WrappedField;
|
||||
//import com.volmit.iris.util.reflect.WrappedReturningMethod;
|
||||
//import org.bukkit.block.BlockFace;
|
||||
//import org.bukkit.block.data.BlockData;
|
||||
//import org.bukkit.block.data.MultipleFacing;
|
||||
//import org.bukkit.inventory.ItemStack;
|
||||
//
|
||||
//import java.util.Map;
|
||||
//import java.util.MissingResourceException;
|
||||
//
|
||||
//public class CustomItemsDataProvider extends ExternalDataProvider {
|
||||
//
|
||||
// private static final String FIELD_FACES = "faces";
|
||||
// private static final String METHOD_GET_MATERIAL = "getMaterial";
|
||||
//
|
||||
// private WrappedField<CustomMushroomBlock, Map<Integer, boolean[]>> mushroomFaces;
|
||||
// private WrappedReturningMethod<CustomMushroomBlock, SafeMaterial> mushroomMaterial;
|
||||
//
|
||||
// public CustomItemsDataProvider() {
|
||||
// super("CustomItems");
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void init() {
|
||||
// this.mushroomFaces = new WrappedField<>(CustomMushroomBlock.class, FIELD_FACES);
|
||||
// this.mushroomMaterial = new WrappedReturningMethod<>(CustomMushroomBlock.class, METHOD_GET_MATERIAL);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public BlockData getBlockData(Identifier blockId) throws MissingResourceException {
|
||||
// CustomItem item = CustomItem.get(blockId.key());
|
||||
// if(item == null) {
|
||||
// throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
|
||||
// } else if(item.getBlockTexture().isSpawner()) {
|
||||
// throw new MissingResourceException("Iris does not yet support SpawnerBlocks from CustomItems.", blockId.namespace(), blockId.key());
|
||||
// } else if(item.getBlockTexture() != null && item.getBlockTexture().isValid()) {
|
||||
// throw new MissingResourceException("Tried to fetch BlockData for a CustomItem that is not placeable!", blockId.namespace(), blockId.key());
|
||||
// }
|
||||
// return getMushroomData(item);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public ItemStack getItemStack(Identifier itemId) throws MissingResourceException {
|
||||
// ItemStack stack = CustomItemsAPI.getCustomItem(itemId.key());
|
||||
// if(stack == null) {
|
||||
// throw new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key());
|
||||
// }
|
||||
// return stack;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public Identifier[] getBlockTypes() {
|
||||
// KList<Identifier> names = new KList<>();
|
||||
// for (String name : CustomItemsAPI.listBlockCustomItemIDs()) {
|
||||
// try {
|
||||
// Identifier key = new Identifier("cui", name);
|
||||
// if (getItemStack(key) != null)
|
||||
// names.add(key);
|
||||
// } catch (MissingResourceException ignored) { }
|
||||
// }
|
||||
//
|
||||
// return names.toArray(new Identifier[0]);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public Identifier[] getItemTypes() {
|
||||
// KList<Identifier> names = new KList<>();
|
||||
// for (String name : CustomItemsAPI.listCustomItemIDs()) {
|
||||
// try {
|
||||
// Identifier key = new Identifier("cui", name);
|
||||
// if (getItemStack(key) != null)
|
||||
// names.add(key);
|
||||
// } catch (MissingResourceException ignored) { }
|
||||
// }
|
||||
//
|
||||
// return names.toArray(new Identifier[0]);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean isValidProvider(Identifier key, boolean isItem) {
|
||||
// return key.namespace().equalsIgnoreCase("cui");
|
||||
// }
|
||||
//
|
||||
// private BlockData getMushroomData(CustomItem item) {
|
||||
// MultipleFacing data = (MultipleFacing)mushroomMaterial.invoke(item.getBlockTexture().getMushroomId()).parseMaterial().createBlockData();
|
||||
// boolean[] values = mushroomFaces.get().get(item.getBlockTexture().getMushroomId());
|
||||
// data.setFace(BlockFace.DOWN, values[0]);
|
||||
// data.setFace(BlockFace.EAST, values[1]);
|
||||
// data.setFace(BlockFace.NORTH, values[2]);
|
||||
// data.setFace(BlockFace.SOUTH, values[3]);
|
||||
// data.setFace(BlockFace.UP, values[4]);
|
||||
// data.setFace(BlockFace.WEST, values[5]);
|
||||
// return data;
|
||||
// }
|
||||
//}
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.link;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.reflect.WrappedField;
|
||||
import com.willfp.ecoitems.items.EcoItem;
|
||||
import com.willfp.ecoitems.items.EcoItems;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.MissingResourceException;
|
||||
|
||||
public class EcoItemsDataProvider extends ExternalDataProvider {
|
||||
private WrappedField<EcoItem, ItemStack> itemStack;
|
||||
private WrappedField<EcoItem, NamespacedKey> id;
|
||||
|
||||
public EcoItemsDataProvider() {
|
||||
super("EcoItems");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
Iris.info("Setting up EcoItems Link...");
|
||||
itemStack = new WrappedField<>(EcoItem.class, "_itemStack");
|
||||
if (this.itemStack.hasFailed()) {
|
||||
Iris.error("Failed to set up EcoItems Link: Unable to fetch ItemStack field!");
|
||||
}
|
||||
id = new WrappedField<>(EcoItem.class, "id");
|
||||
if (this.id.hasFailed()) {
|
||||
Iris.error("Failed to set up EcoItems Link: Unable to fetch id field!");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockData getBlockData(Identifier blockId, KMap<String, String> state) throws MissingResourceException {
|
||||
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getItemStack(Identifier itemId, KMap<String, Object> customNbt) throws MissingResourceException {
|
||||
EcoItem item = EcoItems.INSTANCE.getByID(itemId.key());
|
||||
if (item == null)
|
||||
throw new MissingResourceException("Failed to find Item!", itemId.namespace(), itemId.key());
|
||||
return itemStack.get(item).clone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier[] getBlockTypes() {
|
||||
return new Identifier[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier[] getItemTypes() {
|
||||
KList<Identifier> names = new KList<>();
|
||||
for (EcoItem item : EcoItems.INSTANCE.values()) {
|
||||
try {
|
||||
Identifier key = Identifier.fromNamespacedKey(id.get(item));
|
||||
if (getItemStack(key) != null)
|
||||
names.add(key);
|
||||
} catch (MissingResourceException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
return names.toArray(new Identifier[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidProvider(Identifier id, boolean isItem) {
|
||||
return id.namespace().equalsIgnoreCase("ecoitems") && isItem;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.link;
|
||||
|
||||
import com.ssomar.score.api.executableitems.ExecutableItemsAPI;
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.Optional;
|
||||
|
||||
public class ExecutableItemsDataProvider extends ExternalDataProvider {
|
||||
public ExecutableItemsDataProvider() {
|
||||
super("ExecutableItems");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
Iris.info("Setting up ExecutableItems Link...");
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockData getBlockData(Identifier blockId, KMap<String, String> state) throws MissingResourceException {
|
||||
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getItemStack(Identifier itemId, KMap<String, Object> customNbt) throws MissingResourceException {
|
||||
return ExecutableItemsAPI.getExecutableItemsManager().getExecutableItem(itemId.key())
|
||||
.map(item -> item.buildItem(1, Optional.empty()))
|
||||
.orElseThrow(() -> new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier[] getBlockTypes() {
|
||||
return new Identifier[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier[] getItemTypes() {
|
||||
KList<Identifier> names = new KList<>();
|
||||
for (String name : ExecutableItemsAPI.getExecutableItemsManager().getExecutableItemIdsList()) {
|
||||
try {
|
||||
Identifier key = new Identifier("executable_items", name);
|
||||
if (getItemStack(key) != null)
|
||||
names.add(key);
|
||||
} catch (MissingResourceException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
return names.toArray(new Identifier[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidProvider(Identifier key, boolean isItem) {
|
||||
return key.namespace().equalsIgnoreCase("executable_items") && isItem;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.link;
|
||||
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.util.MissingResourceException;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public abstract class ExternalDataProvider {
|
||||
|
||||
@Getter
|
||||
private final String pluginId;
|
||||
|
||||
public Plugin getPlugin() {
|
||||
return Bukkit.getPluginManager().getPlugin(pluginId);
|
||||
}
|
||||
|
||||
public boolean isReady() {
|
||||
return getPlugin() != null && getPlugin().isEnabled();
|
||||
}
|
||||
|
||||
public abstract void init();
|
||||
|
||||
public BlockData getBlockData(Identifier blockId) throws MissingResourceException {
|
||||
return getBlockData(blockId, new KMap<>());
|
||||
}
|
||||
|
||||
public abstract BlockData getBlockData(Identifier blockId, KMap<String, String> state) throws MissingResourceException;
|
||||
|
||||
public ItemStack getItemStack(Identifier itemId) throws MissingResourceException {
|
||||
return getItemStack(itemId, new KMap<>());
|
||||
}
|
||||
|
||||
public abstract ItemStack getItemStack(Identifier itemId, KMap<String, Object> customNbt) throws MissingResourceException;
|
||||
|
||||
public void processUpdate(Engine engine, Block block, Identifier blockId) {
|
||||
}
|
||||
|
||||
public abstract Identifier[] getBlockTypes();
|
||||
|
||||
public abstract Identifier[] getItemTypes();
|
||||
|
||||
public abstract boolean isValidProvider(Identifier id, boolean isItem);
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.link;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.service.ExternalDataSVC;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.data.IrisCustomData;
|
||||
import com.volmit.iris.util.reflect.WrappedField;
|
||||
import com.volmit.iris.util.reflect.WrappedReturningMethod;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.block.data.type.Leaves;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class HMCLeavesDataProvider extends ExternalDataProvider {
|
||||
private Object apiInstance;
|
||||
private WrappedReturningMethod<Object, Material> worldBlockType;
|
||||
private WrappedReturningMethod<Object, Boolean> setCustomBlock;
|
||||
private Map<String, Object> blockDataMap = Map.of();
|
||||
private Map<String, Supplier<ItemStack>> itemDataField = Map.of();
|
||||
|
||||
public HMCLeavesDataProvider() {
|
||||
super("HMCLeaves");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPluginId() {
|
||||
return "HMCLeaves";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
try {
|
||||
worldBlockType = new WrappedReturningMethod<>((Class<Object>) Class.forName("io.github.fisher2911.hmcleaves.data.BlockData"), "worldBlockType");
|
||||
apiInstance = getApiInstance(Class.forName("io.github.fisher2911.hmcleaves.api.HMCLeavesAPI"));
|
||||
setCustomBlock = new WrappedReturningMethod<>((Class<Object>) apiInstance.getClass(), "setCustomBlock", Location.class, String.class, boolean.class);
|
||||
Object config = getLeavesConfig(apiInstance.getClass());
|
||||
blockDataMap = getMap(config, "blockDataMap");
|
||||
itemDataField = getMap(config, "itemSupplierMap");
|
||||
} catch (Throwable e) {
|
||||
Iris.error("Failed to initialize HMCLeavesDataProvider: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockData getBlockData(Identifier blockId, KMap<String, String> state) throws MissingResourceException {
|
||||
Object o = blockDataMap.get(blockId.key());
|
||||
if (o == null)
|
||||
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
|
||||
Material material = worldBlockType.invoke(o, new Object[0]);
|
||||
if (material == null)
|
||||
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
|
||||
BlockData blockData = Bukkit.createBlockData(material);
|
||||
if (IrisSettings.get().getGenerator().preventLeafDecay && blockData instanceof Leaves leaves)
|
||||
leaves.setPersistent(true);
|
||||
return new IrisCustomData(blockData, ExternalDataSVC.buildState(blockId, state));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getItemStack(Identifier itemId, KMap<String, Object> customNbt) throws MissingResourceException {
|
||||
if (!itemDataField.containsKey(itemId.key()))
|
||||
throw new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key());
|
||||
return itemDataField.get(itemId.key()).get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processUpdate(Engine engine, Block block, Identifier blockId) {
|
||||
var pair = ExternalDataSVC.parseState(blockId);
|
||||
blockId = pair.getA();
|
||||
Boolean result = setCustomBlock.invoke(apiInstance, new Object[]{block.getLocation(), blockId.key(), false});
|
||||
if (result == null || !result)
|
||||
Iris.warn("Failed to set custom block! " + blockId.key() + " " + block.getX() + " " + block.getY() + " " + block.getZ());
|
||||
else if (IrisSettings.get().getGenerator().preventLeafDecay) {
|
||||
BlockData blockData = block.getBlockData();
|
||||
if (blockData instanceof Leaves leaves)
|
||||
leaves.setPersistent(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier[] getBlockTypes() {
|
||||
KList<Identifier> names = new KList<>();
|
||||
for (String name : blockDataMap.keySet()) {
|
||||
try {
|
||||
Identifier key = new Identifier("hmcleaves", name);
|
||||
if (getBlockData(key) != null)
|
||||
names.add(key);
|
||||
} catch (MissingResourceException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
return names.toArray(new Identifier[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier[] getItemTypes() {
|
||||
KList<Identifier> names = new KList<>();
|
||||
for (String name : itemDataField.keySet()) {
|
||||
try {
|
||||
Identifier key = new Identifier("hmcleaves", name);
|
||||
if (getItemStack(key) != null)
|
||||
names.add(key);
|
||||
} catch (MissingResourceException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
return names.toArray(new Identifier[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidProvider(Identifier id, boolean isItem) {
|
||||
return (isItem ? itemDataField.keySet() : blockDataMap.keySet()).contains(id.key());
|
||||
}
|
||||
|
||||
private <C, T> Map<String, T> getMap(C config, String name) {
|
||||
WrappedField<C, Map<String, T>> field = new WrappedField<>((Class<C>) config.getClass(), name);
|
||||
return field.get(config);
|
||||
}
|
||||
|
||||
private <A> A getApiInstance(Class<A> apiClass) {
|
||||
WrappedReturningMethod<A, A> instance = new WrappedReturningMethod<>(apiClass, "getInstance");
|
||||
return instance.invoke();
|
||||
}
|
||||
|
||||
private <A, C> C getLeavesConfig(Class<A> apiClass) {
|
||||
WrappedReturningMethod<A, A> instance = new WrappedReturningMethod<>(apiClass, "getInstance");
|
||||
WrappedField<A, C> config = new WrappedField<>(apiClass, "config");
|
||||
return config.get(instance.invoke());
|
||||
}
|
||||
}
|
||||
55
core/src/main/java/com/volmit/iris/core/link/Identifier.java
Normal file
55
core/src/main/java/com/volmit/iris/core/link/Identifier.java
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.link;
|
||||
|
||||
import org.bukkit.NamespacedKey;
|
||||
|
||||
public record Identifier(String namespace, String key) {
|
||||
|
||||
private static final String DEFAULT_NAMESPACE = "minecraft";
|
||||
|
||||
public static Identifier fromNamespacedKey(NamespacedKey key) {
|
||||
return new Identifier(key.getNamespace(), key.getKey());
|
||||
}
|
||||
|
||||
public static Identifier fromString(String id) {
|
||||
String[] strings = id.split(":", 2);
|
||||
if (strings.length == 1) {
|
||||
return new Identifier(DEFAULT_NAMESPACE, strings[0]);
|
||||
} else {
|
||||
return new Identifier(strings[0], strings[1]);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return namespace + ":" + key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof Identifier i) {
|
||||
return i.namespace().equals(this.namespace) && i.key().equals(this.key);
|
||||
} else if (obj instanceof NamespacedKey i) {
|
||||
return i.getNamespace().equals(this.namespace) && i.getKey().equals(this.key);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -20,31 +20,33 @@ package com.volmit.iris.core.link;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.engine.object.IrisBiome;
|
||||
import com.volmit.iris.engine.platform.PlatformChunkGenerator;
|
||||
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
// See/update https://app.gitbook.com/@volmitsoftware/s/iris/compatability/papi/
|
||||
public class IrisPapiExpansion extends PlaceholderExpansion {
|
||||
@Override
|
||||
public String getIdentifier() {
|
||||
public @NotNull String getIdentifier() {
|
||||
return "iris";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAuthor() {
|
||||
public @NotNull String getAuthor() {
|
||||
return "Volmit Software";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
public @NotNull String getVersion() {
|
||||
return Iris.instance.getDescription().getVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean persist() {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -52,59 +54,63 @@ public class IrisPapiExpansion extends PlaceholderExpansion {
|
||||
Location l = null;
|
||||
PlatformChunkGenerator a = null;
|
||||
|
||||
if(player.isOnline()) {
|
||||
l = player.getPlayer().getLocation();
|
||||
if (player.isOnline() && player.getPlayer() != null) {
|
||||
l = player.getPlayer().getLocation().add(0, 2, 0);
|
||||
a = IrisToolbelt.access(l.getWorld());
|
||||
}
|
||||
|
||||
if(p.equalsIgnoreCase("biome_name")) {
|
||||
if(a != null) {
|
||||
return a.getEngine().getBiome(l).getName();
|
||||
if (p.equalsIgnoreCase("biome_name")) {
|
||||
if (a != null) {
|
||||
return getBiome(a, l).getName();
|
||||
}
|
||||
} else if(p.equalsIgnoreCase("biome_id")) {
|
||||
if(a != null) {
|
||||
return a.getEngine().getBiome(l).getLoadKey();
|
||||
} else if (p.equalsIgnoreCase("biome_id")) {
|
||||
if (a != null) {
|
||||
return getBiome(a, l).getLoadKey();
|
||||
}
|
||||
} else if(p.equalsIgnoreCase("biome_file")) {
|
||||
if(a != null) {
|
||||
return a.getEngine().getBiome(l).getLoadFile().getPath();
|
||||
} else if (p.equalsIgnoreCase("biome_file")) {
|
||||
if (a != null) {
|
||||
return getBiome(a, l).getLoadFile().getPath();
|
||||
}
|
||||
} else if(p.equalsIgnoreCase("region_name")) {
|
||||
if(a != null) {
|
||||
} else if (p.equalsIgnoreCase("region_name")) {
|
||||
if (a != null) {
|
||||
return a.getEngine().getRegion(l).getName();
|
||||
}
|
||||
} else if(p.equalsIgnoreCase("region_id")) {
|
||||
if(a != null) {
|
||||
} else if (p.equalsIgnoreCase("region_id")) {
|
||||
if (a != null) {
|
||||
return a.getEngine().getRegion(l).getLoadKey();
|
||||
}
|
||||
} else if(p.equalsIgnoreCase("region_file")) {
|
||||
if(a != null) {
|
||||
} else if (p.equalsIgnoreCase("region_file")) {
|
||||
if (a != null) {
|
||||
return a.getEngine().getRegion(l).getLoadFile().getPath();
|
||||
}
|
||||
} else if(p.equalsIgnoreCase("terrain_slope")) {
|
||||
if(a != null) {
|
||||
} else if (p.equalsIgnoreCase("terrain_slope")) {
|
||||
if (a != null) {
|
||||
return (a.getEngine())
|
||||
.getComplex().getSlopeStream()
|
||||
.get(l.getX(), l.getZ()) + "";
|
||||
.getComplex().getSlopeStream()
|
||||
.get(l.getX(), l.getZ()) + "";
|
||||
}
|
||||
} else if(p.equalsIgnoreCase("terrain_height")) {
|
||||
if(a != null) {
|
||||
} else if (p.equalsIgnoreCase("terrain_height")) {
|
||||
if (a != null) {
|
||||
return Math.round(a.getEngine().getHeight(l.getBlockX(), l.getBlockZ())) + "";
|
||||
}
|
||||
} else if(p.equalsIgnoreCase("world_mode")) {
|
||||
if(a != null) {
|
||||
} else if (p.equalsIgnoreCase("world_mode")) {
|
||||
if (a != null) {
|
||||
return a.isStudio() ? "Studio" : "Production";
|
||||
}
|
||||
} else if(p.equalsIgnoreCase("world_seed")) {
|
||||
if(a != null) {
|
||||
} else if (p.equalsIgnoreCase("world_seed")) {
|
||||
if (a != null) {
|
||||
return a.getEngine().getSeedManager().getSeed() + "";
|
||||
}
|
||||
} else if(p.equalsIgnoreCase("world_speed")) {
|
||||
if(a != null) {
|
||||
} else if (p.equalsIgnoreCase("world_speed")) {
|
||||
if (a != null) {
|
||||
return a.getEngine().getGeneratedPerSecond() + "/s";
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private IrisBiome getBiome(PlatformChunkGenerator a, Location l) {
|
||||
return a.getEngine().getBiome(l.getBlockX(), l.getBlockY() - l.getWorld().getMinHeight(), l.getBlockZ());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.link;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import dev.lone.itemsadder.api.CustomBlock;
|
||||
import dev.lone.itemsadder.api.CustomStack;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.MissingResourceException;
|
||||
|
||||
public class ItemAdderDataProvider extends ExternalDataProvider {
|
||||
|
||||
private KList<String> itemNamespaces, blockNamespaces;
|
||||
|
||||
public ItemAdderDataProvider() {
|
||||
super("ItemsAdder");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
this.itemNamespaces = new KList<>();
|
||||
this.blockNamespaces = new KList<>();
|
||||
|
||||
for (Identifier i : getItemTypes()) {
|
||||
itemNamespaces.addIfMissing(i.namespace());
|
||||
}
|
||||
for (Identifier i : getBlockTypes()) {
|
||||
blockNamespaces.addIfMissing(i.namespace());
|
||||
Iris.info("Found ItemAdder Block: " + i);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockData getBlockData(Identifier blockId, KMap<String, String> state) throws MissingResourceException {
|
||||
return CustomBlock.getBaseBlockData(blockId.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getItemStack(Identifier itemId, KMap<String, Object> customNbt) throws MissingResourceException {
|
||||
CustomStack stack = CustomStack.getInstance(itemId.toString());
|
||||
if (stack == null) {
|
||||
throw new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key());
|
||||
}
|
||||
return stack.getItemStack();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier[] getBlockTypes() {
|
||||
KList<Identifier> keys = new KList<>();
|
||||
for (String s : CustomBlock.getNamespacedIdsInRegistry()) {
|
||||
keys.add(Identifier.fromString(s));
|
||||
}
|
||||
return keys.toArray(new Identifier[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier[] getItemTypes() {
|
||||
KList<Identifier> keys = new KList<>();
|
||||
for (String s : CustomStack.getNamespacedIdsInRegistry()) {
|
||||
keys.add(Identifier.fromString(s));
|
||||
}
|
||||
return keys.toArray(new Identifier[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidProvider(Identifier id, boolean isItem) {
|
||||
return isItem ? this.itemNamespaces.contains(id.namespace()) : this.blockNamespaces.contains(id.namespace());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.link;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import net.Indyuce.mmoitems.MMOItems;
|
||||
import net.Indyuce.mmoitems.api.ItemTier;
|
||||
import net.Indyuce.mmoitems.api.Type;
|
||||
import net.Indyuce.mmoitems.api.block.CustomBlock;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
public class MMOItemsDataProvider extends ExternalDataProvider {
|
||||
|
||||
public MMOItemsDataProvider() {
|
||||
super("MMOItems");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
Iris.info("Setting up MMOItems Link...");
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockData getBlockData(Identifier blockId, KMap<String, String> state) throws MissingResourceException {
|
||||
int id = -1;
|
||||
try {
|
||||
id = Integer.parseInt(blockId.key());
|
||||
} catch (NumberFormatException ignored) {
|
||||
}
|
||||
CustomBlock block = api().getCustomBlocks().getBlock(id);
|
||||
if (block == null)
|
||||
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
|
||||
return block.getState().getBlockData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getItemStack(Identifier itemId, KMap<String, Object> customNbt) throws MissingResourceException {
|
||||
String[] parts = itemId.namespace().split("_", 2);
|
||||
if (parts.length != 2)
|
||||
throw new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key());
|
||||
CompletableFuture<ItemStack> future = new CompletableFuture<>();
|
||||
Runnable run = () -> {
|
||||
try {
|
||||
var type = api().getTypes().get(parts[1]);
|
||||
int level = -1;
|
||||
ItemTier tier = null;
|
||||
|
||||
if (customNbt != null) {
|
||||
level = (int) customNbt.getOrDefault("level", -1);
|
||||
tier = api().getTiers().get(String.valueOf(customNbt.get("tier")));
|
||||
}
|
||||
|
||||
ItemStack itemStack;
|
||||
if (type == null) {
|
||||
future.complete(null);
|
||||
return;
|
||||
}
|
||||
|
||||
if (level != -1 && tier != null) {
|
||||
itemStack = api().getItem(type, itemId.key(), level, tier);
|
||||
} else {
|
||||
itemStack = api().getItem(type, itemId.key());
|
||||
}
|
||||
future.complete(itemStack);
|
||||
} catch (Throwable e) {
|
||||
future.completeExceptionally(e);
|
||||
}
|
||||
};
|
||||
if (Bukkit.isPrimaryThread()) run.run();
|
||||
else J.s(run);
|
||||
ItemStack item = null;
|
||||
try {
|
||||
item = future.get();
|
||||
} catch (InterruptedException | ExecutionException ignored) {
|
||||
}
|
||||
if (item == null)
|
||||
throw new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key());
|
||||
return item;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier[] getBlockTypes() {
|
||||
KList<Identifier> names = new KList<>();
|
||||
for (Integer id : api().getCustomBlocks().getBlockIds()) {
|
||||
try {
|
||||
Identifier key = new Identifier("mmoitems", String.valueOf(id));
|
||||
if (getBlockData(key) != null)
|
||||
names.add(key);
|
||||
} catch (MissingResourceException ignored) {
|
||||
}
|
||||
}
|
||||
return names.toArray(new Identifier[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier[] getItemTypes() {
|
||||
KList<Identifier> names = new KList<>();
|
||||
Runnable run = () -> {
|
||||
for (Type type : api().getTypes().getAll()) {
|
||||
for (String name : api().getTemplates().getTemplateNames(type)) {
|
||||
try {
|
||||
Identifier key = new Identifier("mmoitems_" + type.getId(), name);
|
||||
if (getItemStack(key) != null)
|
||||
names.add(key);
|
||||
} catch (MissingResourceException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
if (Bukkit.isPrimaryThread()) run.run();
|
||||
else {
|
||||
try {
|
||||
J.sfut(run).get();
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
Iris.error("Failed getting MMOItems item types!");
|
||||
Iris.reportError(e);
|
||||
}
|
||||
}
|
||||
return names.toArray(new Identifier[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidProvider(Identifier id, boolean isItem) {
|
||||
return isItem ? id.namespace().split("_", 2).length == 2 : id.namespace().equals("mmoitems");
|
||||
}
|
||||
|
||||
private MMOItems api() {
|
||||
return MMOItems.plugin;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -38,7 +38,7 @@ public class MultiverseCoreLink {
|
||||
}
|
||||
|
||||
public boolean addWorld(String worldName, IrisDimension dim, String seed) {
|
||||
if(!isSupported()) {
|
||||
if (!isSupported()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -47,11 +47,11 @@ public class MultiverseCoreLink {
|
||||
Object mvWorldManager = p.getClass().getDeclaredMethod("getMVWorldManager").invoke(p);
|
||||
Method m = mvWorldManager.getClass().getDeclaredMethod("addWorld",
|
||||
|
||||
String.class, World.Environment.class, String.class, WorldType.class, Boolean.class, String.class, boolean.class);
|
||||
String.class, World.Environment.class, String.class, WorldType.class, Boolean.class, String.class, boolean.class);
|
||||
boolean b = (boolean) m.invoke(mvWorldManager, worldName, dim.getEnvironment(), seed, WorldType.NORMAL, false, "Iris", false);
|
||||
saveConfig();
|
||||
return b;
|
||||
} catch(Throwable e) {
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
@@ -67,7 +67,7 @@ public class MultiverseCoreLink {
|
||||
Field f = mvWorldManager.getClass().getDeclaredField("worldsFromTheConfig");
|
||||
f.setAccessible(true);
|
||||
return (Map<String, ?>) f.get(mvWorldManager);
|
||||
} catch(Throwable e) {
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
@@ -76,7 +76,7 @@ public class MultiverseCoreLink {
|
||||
}
|
||||
|
||||
public void removeFromConfig(World world) {
|
||||
if(!isSupported()) {
|
||||
if (!isSupported()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ public class MultiverseCoreLink {
|
||||
}
|
||||
|
||||
public void removeFromConfig(String world) {
|
||||
if(!isSupported()) {
|
||||
if (!isSupported()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ public class MultiverseCoreLink {
|
||||
Plugin p = getMultiverse();
|
||||
Object mvWorldManager = p.getClass().getDeclaredMethod("getMVWorldManager").invoke(p);
|
||||
mvWorldManager.getClass().getDeclaredMethod("saveWorldsConfig").invoke(mvWorldManager);
|
||||
} catch(Throwable e) {
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
@@ -112,7 +112,7 @@ public class MultiverseCoreLink {
|
||||
try {
|
||||
String t = worldNameTypes.get(worldName);
|
||||
return t == null ? defaultType : t;
|
||||
} catch(Throwable e) {
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
return defaultType;
|
||||
}
|
||||
@@ -128,11 +128,11 @@ public class MultiverseCoreLink {
|
||||
}
|
||||
|
||||
public String envName(World.Environment environment) {
|
||||
if(environment == null) {
|
||||
if (environment == null) {
|
||||
return "normal";
|
||||
}
|
||||
|
||||
return switch(environment) {
|
||||
return switch (environment) {
|
||||
case NORMAL -> "normal";
|
||||
case NETHER -> "nether";
|
||||
case THE_END -> "end";
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.link;
|
||||
|
||||
import io.lumine.mythic.bukkit.MythicBukkit;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Collection;
|
||||
|
||||
public class MythicMobsLink {
|
||||
|
||||
public MythicMobsLink() {
|
||||
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return getPlugin() != null;
|
||||
}
|
||||
|
||||
public Plugin getPlugin() {
|
||||
return Bukkit.getPluginManager().getPlugin("MythicMobs");
|
||||
}
|
||||
|
||||
/**
|
||||
* Spawn a mythic mob at this location
|
||||
*
|
||||
* @param mob The mob
|
||||
* @param location The location
|
||||
* @return The mob, or null if it can't be spawned
|
||||
*/
|
||||
public @Nullable
|
||||
Entity spawnMob(String mob, Location location) {
|
||||
return isEnabled() ? MythicBukkit.inst().getMobManager().spawnMob(mob, location).getEntity().getBukkitEntity() : null;
|
||||
}
|
||||
|
||||
public Collection<String> getMythicMobTypes() {
|
||||
return isEnabled() ? MythicBukkit.inst().getMobManager().getMobNames() : null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,214 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.link;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.nms.INMS;
|
||||
import com.volmit.iris.core.nms.container.BiomeColor;
|
||||
import com.volmit.iris.core.service.ExternalDataSVC;
|
||||
import com.volmit.iris.engine.data.cache.Cache;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.data.B;
|
||||
import com.volmit.iris.util.data.IrisCustomData;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import com.volmit.iris.util.reflect.WrappedField;
|
||||
import io.th0rgal.oraxen.api.OraxenItems;
|
||||
import io.th0rgal.oraxen.items.ItemBuilder;
|
||||
import io.th0rgal.oraxen.mechanics.Mechanic;
|
||||
import io.th0rgal.oraxen.mechanics.MechanicFactory;
|
||||
import io.th0rgal.oraxen.mechanics.MechanicsManager;
|
||||
import io.th0rgal.oraxen.mechanics.provided.gameplay.block.BlockMechanic;
|
||||
import io.th0rgal.oraxen.mechanics.provided.gameplay.block.BlockMechanicFactory;
|
||||
import io.th0rgal.oraxen.mechanics.provided.gameplay.furniture.FurnitureFactory;
|
||||
import io.th0rgal.oraxen.mechanics.provided.gameplay.furniture.FurnitureMechanic;
|
||||
import io.th0rgal.oraxen.mechanics.provided.gameplay.noteblock.NoteBlockMechanicFactory;
|
||||
import io.th0rgal.oraxen.mechanics.provided.gameplay.stringblock.StringBlockMechanicFactory;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Color;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.block.data.MultipleFacing;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.ItemDisplay;
|
||||
import org.bukkit.entity.ItemFrame;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.PotionMeta;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class OraxenDataProvider extends ExternalDataProvider {
|
||||
|
||||
private static final String FIELD_FACTORIES_MAP = "FACTORIES_BY_MECHANIC_ID";
|
||||
|
||||
private WrappedField<MechanicsManager, Map<String, MechanicFactory>> factories;
|
||||
|
||||
public OraxenDataProvider() {
|
||||
super("Oraxen");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
Iris.info("Setting up Oraxen Link...");
|
||||
this.factories = new WrappedField<>(MechanicsManager.class, FIELD_FACTORIES_MAP);
|
||||
if (this.factories.hasFailed()) {
|
||||
Iris.error("Failed to set up Oraxen Link: Unable to fetch MechanicFactoriesMap!");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockData getBlockData(Identifier blockId, KMap<String, String> state) throws MissingResourceException {
|
||||
MechanicFactory factory = getFactory(blockId);
|
||||
if (factory instanceof NoteBlockMechanicFactory f)
|
||||
return f.createNoteBlockData(blockId.key());
|
||||
else if (factory instanceof BlockMechanicFactory f) {
|
||||
MultipleFacing newBlockData = (MultipleFacing) Bukkit.createBlockData(Material.MUSHROOM_STEM);
|
||||
BlockMechanic.setBlockFacing(newBlockData, ((BlockMechanic) f.getMechanic(blockId.key())).getCustomVariation());
|
||||
return newBlockData;
|
||||
} else if (factory instanceof StringBlockMechanicFactory f) {
|
||||
return f.createTripwireData(blockId.key());
|
||||
} else if (factory instanceof FurnitureFactory) {
|
||||
return new IrisCustomData(B.getAir(), ExternalDataSVC.buildState(blockId, state));
|
||||
} else
|
||||
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getItemStack(Identifier itemId, KMap<String, Object> customNbt) throws MissingResourceException {
|
||||
Optional<ItemBuilder> opt = OraxenItems.getOptionalItemById(itemId.key());
|
||||
return opt.orElseThrow(() -> new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key())).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processUpdate(Engine engine, Block block, Identifier blockId) {
|
||||
var pair = ExternalDataSVC.parseState(blockId);
|
||||
var state = pair.getB();
|
||||
blockId = pair.getA();
|
||||
Mechanic mechanic = getFactory(blockId).getMechanic(blockId.key());
|
||||
if (mechanic instanceof FurnitureMechanic f) {
|
||||
float yaw = 0;
|
||||
BlockFace face = BlockFace.NORTH;
|
||||
|
||||
long seed = engine.getSeedManager().getSeed() + Cache.key(block.getX(), block.getZ()) + block.getY();
|
||||
RNG rng = new RNG(seed);
|
||||
if ("true".equals(state.get("randomYaw"))) {
|
||||
yaw = rng.f(0, 360);
|
||||
} else if (state.containsKey("yaw")) {
|
||||
yaw = Float.parseFloat(state.get("yaw"));
|
||||
}
|
||||
if ("true".equals(state.get("randomFace"))) {
|
||||
BlockFace[] faces = BlockFace.values();
|
||||
face = faces[rng.i(0, faces.length - 1)];
|
||||
} else if (state.containsKey("face")) {
|
||||
face = BlockFace.valueOf(state.get("face").toUpperCase());
|
||||
}
|
||||
if (face == BlockFace.SELF) {
|
||||
face = BlockFace.NORTH;
|
||||
}
|
||||
ItemStack itemStack = OraxenItems.getItemById(f.getItemID()).build();
|
||||
Entity entity = f.place(block.getLocation(), itemStack, yaw, face, false);
|
||||
|
||||
Consumer<ItemStack> setter = null;
|
||||
if (entity instanceof ItemFrame frame) {
|
||||
itemStack = frame.getItem();
|
||||
setter = frame::setItem;
|
||||
} else if (entity instanceof ItemDisplay display) {
|
||||
itemStack = display.getItemStack();
|
||||
setter = display::setItemStack;
|
||||
}
|
||||
if (setter == null || itemStack == null) return;
|
||||
|
||||
BiomeColor type = null;
|
||||
try {
|
||||
type = BiomeColor.valueOf(state.get("matchBiome").toUpperCase());
|
||||
} catch (NullPointerException | IllegalArgumentException ignored) {
|
||||
}
|
||||
|
||||
if (type != null) {
|
||||
var biomeColor = INMS.get().getBiomeColor(block.getLocation(), type);
|
||||
if (biomeColor == null) return;
|
||||
var potionColor = Color.fromARGB(biomeColor.getAlpha(), biomeColor.getRed(), biomeColor.getGreen(), biomeColor.getBlue());
|
||||
if (itemStack.getItemMeta() instanceof PotionMeta meta) {
|
||||
meta.setColor(potionColor);
|
||||
itemStack.setItemMeta(meta);
|
||||
}
|
||||
}
|
||||
setter.accept(itemStack);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier[] getBlockTypes() {
|
||||
KList<Identifier> names = new KList<>();
|
||||
for (String name : OraxenItems.getItemNames()) {
|
||||
try {
|
||||
Identifier key = new Identifier("oraxen", name);
|
||||
if (getBlockData(key) != null)
|
||||
names.add(key);
|
||||
} catch (MissingResourceException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
return names.toArray(new Identifier[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier[] getItemTypes() {
|
||||
KList<Identifier> names = new KList<>();
|
||||
for (String name : OraxenItems.getItemNames()) {
|
||||
try {
|
||||
Identifier key = new Identifier("oraxen", name);
|
||||
if (getItemStack(key) != null)
|
||||
names.add(key);
|
||||
} catch (MissingResourceException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
return names.toArray(new Identifier[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReady() {
|
||||
if (super.isReady()) {
|
||||
if (factories == null) {
|
||||
this.factories = new WrappedField<>(MechanicsManager.class, FIELD_FACTORIES_MAP);
|
||||
}
|
||||
return super.isReady() && !factories.hasFailed();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidProvider(Identifier key, boolean isItem) {
|
||||
return key.namespace().equalsIgnoreCase("oraxen");
|
||||
}
|
||||
|
||||
private MechanicFactory getFactory(Identifier key) throws MissingResourceException {
|
||||
return factories.get().values().stream()
|
||||
.filter(i -> i.getItems().contains(key.key()))
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new MissingResourceException("Failed to find BlockData!", key.namespace(), key.key()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.link;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.engine.data.cache.AtomicCache;
|
||||
import com.volmit.iris.util.data.Cuboid;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
public class WorldEditLink {
|
||||
private static final AtomicCache<Boolean> active = new AtomicCache<>();
|
||||
|
||||
public static Cuboid getSelection(Player p) {
|
||||
if (!hasWorldEdit())
|
||||
return null;
|
||||
|
||||
try {
|
||||
Object instance = Class.forName("com.sk89q.worldedit.WorldEdit").getDeclaredMethod("getInstance").invoke(null);
|
||||
Object sessionManager = instance.getClass().getDeclaredMethod("getSessionManager").invoke(instance);
|
||||
Class<?> bukkitAdapter = Class.forName("com.sk89q.worldedit.bukkit.BukkitAdapter");
|
||||
Object world = bukkitAdapter.getDeclaredMethod("adapt", World.class).invoke(null, p.getWorld());
|
||||
Object player = bukkitAdapter.getDeclaredMethod("adapt", Player.class).invoke(null, p);
|
||||
Object localSession = sessionManager.getClass().getDeclaredMethod("getIfPresent", Class.forName("com.sk89q.worldedit.session.SessionOwner")).invoke(sessionManager, player);
|
||||
if (localSession == null) return null;
|
||||
|
||||
Object region = null;
|
||||
try {
|
||||
region = localSession.getClass().getDeclaredMethod("getSelection", Class.forName("com.sk89q.worldedit.world.World")).invoke(localSession, world);
|
||||
} catch (InvocationTargetException ignored) {
|
||||
}
|
||||
if (region == null) return null;
|
||||
|
||||
Object min = region.getClass().getDeclaredMethod("getMinimumPoint").invoke(region);
|
||||
Object max = region.getClass().getDeclaredMethod("getMaximumPoint").invoke(region);
|
||||
return new Cuboid(p.getWorld(),
|
||||
(int) min.getClass().getDeclaredMethod("x").invoke(min),
|
||||
(int) min.getClass().getDeclaredMethod("y").invoke(min),
|
||||
(int) min.getClass().getDeclaredMethod("z").invoke(min),
|
||||
(int) min.getClass().getDeclaredMethod("x").invoke(max),
|
||||
(int) min.getClass().getDeclaredMethod("y").invoke(max),
|
||||
(int) min.getClass().getDeclaredMethod("z").invoke(max)
|
||||
);
|
||||
} catch (Throwable e) {
|
||||
Iris.error("Could not get selection");
|
||||
e.printStackTrace();
|
||||
active.reset();
|
||||
active.aquire(() -> false);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static boolean hasWorldEdit() {
|
||||
return active.aquire(() -> Bukkit.getPluginManager().isPluginEnabled("WorldEdit"));
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -29,6 +29,7 @@ import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.util.Set;
|
||||
|
||||
public class ImageResourceLoader extends ResourceLoader<IrisImage> {
|
||||
public ImageResourceLoader(File root, IrisData idm, String folderName, String resourceTypeName) {
|
||||
@@ -59,57 +60,73 @@ public class ImageResourceLoader extends ResourceLoader<IrisImage> {
|
||||
logLoad(j, img);
|
||||
tlt.addAndGet(p.getMilliseconds());
|
||||
return img;
|
||||
} catch(Throwable e) {
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
Iris.warn("Couldn't read " + resourceTypeName + " file: " + j.getPath() + ": " + e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
void getPNGFiles(File directory, Set<String> m) {
|
||||
for (File file : directory.listFiles()) {
|
||||
if (file.isFile() && file.getName().endsWith(".png")) {
|
||||
m.add(file.getName().replaceAll("\\Q.png\\E", ""));
|
||||
} else if (file.isDirectory()) {
|
||||
getPNGFiles(file, m);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public String[] getPossibleKeys() {
|
||||
if(possibleKeys != null) {
|
||||
if (possibleKeys != null) {
|
||||
return possibleKeys;
|
||||
}
|
||||
|
||||
Iris.debug("Building " + resourceTypeName + " Possibility Lists");
|
||||
KSet<String> m = new KSet<>();
|
||||
|
||||
for(File i : getFolders()) {
|
||||
for(File j : i.listFiles()) {
|
||||
if(j.isFile() && j.getName().endsWith(".png")) {
|
||||
m.add(j.getName().replaceAll("\\Q.png\\E", ""));
|
||||
} else if(j.isDirectory()) {
|
||||
for(File k : j.listFiles()) {
|
||||
if(k.isFile() && k.getName().endsWith(".png")) {
|
||||
m.add(j.getName() + "/" + k.getName().replaceAll("\\Q.png\\E", ""));
|
||||
} else if(k.isDirectory()) {
|
||||
for(File l : k.listFiles()) {
|
||||
if(l.isFile() && l.getName().endsWith(".png")) {
|
||||
m.add(j.getName() + "/" + k.getName() + "/" + l.getName().replaceAll("\\Q.png\\E", ""));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (File i : getFolders()) {
|
||||
getPNGFiles(i, m);
|
||||
}
|
||||
|
||||
// for (File i : getFolders()) {
|
||||
// for (File j : i.listFiles()) {
|
||||
// if (j.isFile() && j.getName().endsWith(".png")) {
|
||||
// m.add(j.getName().replaceAll("\\Q.png\\E", ""));
|
||||
// } else if (j.isDirectory()) {
|
||||
// for (File k : j.listFiles()) {
|
||||
// if (k.isFile() && k.getName().endsWith(".png")) {
|
||||
// m.add(j.getName() + "/" + k.getName().replaceAll("\\Q.png\\E", ""));
|
||||
// } else if (k.isDirectory()) {
|
||||
// for (File l : k.listFiles()) {
|
||||
// if (l.isFile() && l.getName().endsWith(".png")) {
|
||||
// m.add(j.getName() + "/" + k.getName() + "/" + l.getName().replaceAll("\\Q.png\\E", ""));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
KList<String> v = new KList<>(m);
|
||||
possibleKeys = v.toArray(new String[0]);
|
||||
return possibleKeys;
|
||||
}
|
||||
|
||||
public File findFile(String name) {
|
||||
for(File i : getFolders(name)) {
|
||||
for(File j : i.listFiles()) {
|
||||
if(j.isFile() && j.getName().endsWith(".png") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
||||
for (File i : getFolders(name)) {
|
||||
for (File j : i.listFiles()) {
|
||||
if (j.isFile() && j.getName().endsWith(".png") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
||||
return j;
|
||||
}
|
||||
}
|
||||
|
||||
File file = new File(i, name + ".png");
|
||||
|
||||
if(file.exists()) {
|
||||
if (file.exists()) {
|
||||
return file;
|
||||
}
|
||||
}
|
||||
@@ -124,16 +141,16 @@ public class ImageResourceLoader extends ResourceLoader<IrisImage> {
|
||||
}
|
||||
|
||||
private IrisImage loadRaw(String name) {
|
||||
for(File i : getFolders(name)) {
|
||||
for(File j : i.listFiles()) {
|
||||
if(j.isFile() && j.getName().endsWith(".png") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
||||
for (File i : getFolders(name)) {
|
||||
for (File j : i.listFiles()) {
|
||||
if (j.isFile() && j.getName().endsWith(".png") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
||||
return loadFile(j, name);
|
||||
}
|
||||
}
|
||||
|
||||
File file = new File(i, name + ".png");
|
||||
|
||||
if(file.exists()) {
|
||||
if (file.exists()) {
|
||||
return loadFile(file, name);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -18,12 +18,7 @@
|
||||
|
||||
package com.volmit.iris.core.loader;
|
||||
|
||||
import com.google.gson.ExclusionStrategy;
|
||||
import com.google.gson.FieldAttributes;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.TypeAdapter;
|
||||
import com.google.gson.TypeAdapterFactory;
|
||||
import com.google.gson.*;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import com.google.gson.stream.JsonReader;
|
||||
import com.google.gson.stream.JsonToken;
|
||||
@@ -39,6 +34,8 @@ import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.context.IrisContext;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import com.volmit.iris.util.parallel.BurstExecutor;
|
||||
import com.volmit.iris.util.parallel.MultiBurst;
|
||||
import com.volmit.iris.util.scheduling.ChronoLatch;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import lombok.Data;
|
||||
@@ -100,8 +97,8 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
||||
|
||||
public static int cacheSize() {
|
||||
int m = 0;
|
||||
for(IrisData i : dataLoaders.values()) {
|
||||
for(ResourceLoader<?> j : i.getLoaders().values()) {
|
||||
for (IrisData i : dataLoaders.values()) {
|
||||
for (ResourceLoader<?> j : i.getLoaders().values()) {
|
||||
m += j.getLoadCache().getSize();
|
||||
}
|
||||
}
|
||||
@@ -116,6 +113,7 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
||||
public static IrisObject loadAnyObject(String key) {
|
||||
return loadAny(key, (dm) -> dm.getObjectLoader().load(key, false));
|
||||
}
|
||||
|
||||
public static IrisMatterObject loadAnyMatter(String key) {
|
||||
return loadAny(key, (dm) -> dm.getMatterLoader().load(key, false));
|
||||
}
|
||||
@@ -194,17 +192,17 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
||||
|
||||
public static <T extends IrisRegistrant> T loadAny(String key, Function<IrisData, T> v) {
|
||||
try {
|
||||
for(File i : Objects.requireNonNull(Iris.instance.getDataFolder("packs").listFiles())) {
|
||||
if(i.isDirectory()) {
|
||||
for (File i : Objects.requireNonNull(Iris.instance.getDataFolder("packs").listFiles())) {
|
||||
if (i.isDirectory()) {
|
||||
IrisData dm = get(i);
|
||||
T t = v.apply(dm);
|
||||
|
||||
if(t != null) {
|
||||
if (t != null) {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch(Throwable e) {
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
@@ -215,9 +213,9 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
||||
public ResourceLoader<?> getTypedLoaderFor(File f) {
|
||||
String[] k = f.getPath().split("\\Q" + File.separator + "\\E");
|
||||
|
||||
for(String i : k) {
|
||||
for(ResourceLoader<?> j : loaders.values()) {
|
||||
if(j.getFolderName().equals(i)) {
|
||||
for (String i : k) {
|
||||
for (ResourceLoader<?> j : loaders.values()) {
|
||||
if (j.getFolderName().equals(i)) {
|
||||
return j;
|
||||
}
|
||||
}
|
||||
@@ -227,7 +225,7 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
||||
}
|
||||
|
||||
public void cleanupEngine() {
|
||||
if(engine != null && engine.isClosed()) {
|
||||
if (engine != null && engine.isClosed()) {
|
||||
engine = null;
|
||||
Iris.debug("Dereferenced Data<Engine> " + getId() + " " + getDataFolder());
|
||||
}
|
||||
@@ -238,30 +236,30 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
||||
IrisContext ctx = IrisContext.get();
|
||||
Engine engine = this.engine;
|
||||
|
||||
if(engine == null && ctx != null && ctx.getEngine() != null) {
|
||||
if (engine == null && ctx != null && ctx.getEngine() != null) {
|
||||
engine = ctx.getEngine();
|
||||
}
|
||||
|
||||
if(engine == null && t.getPreprocessors().isNotEmpty()) {
|
||||
if (engine == null && t.getPreprocessors().isNotEmpty()) {
|
||||
Iris.error("Failed to preprocess object " + t.getLoadKey() + " because there is no engine context here. (See stack below)");
|
||||
try {
|
||||
throw new RuntimeException();
|
||||
} catch(Throwable ex) {
|
||||
} catch (Throwable ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if(engine != null && t.getPreprocessors().isNotEmpty()) {
|
||||
synchronized(this) {
|
||||
if (engine != null && t.getPreprocessors().isNotEmpty()) {
|
||||
synchronized (this) {
|
||||
engine.getExecution().getAPI().setPreprocessorObject(t);
|
||||
|
||||
for(String i : t.getPreprocessors()) {
|
||||
for (String i : t.getPreprocessors()) {
|
||||
engine.getExecution().execute(i);
|
||||
Iris.debug("Loader<" + C.GREEN + t.getTypeName() + C.LIGHT_PURPLE + "> iprocess " + C.YELLOW + t.getLoadKey() + C.LIGHT_PURPLE + " in <rainbow>" + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch(Throwable e) {
|
||||
} catch (Throwable e) {
|
||||
Iris.error("Failed to preprocess object!");
|
||||
e.printStackTrace();
|
||||
}
|
||||
@@ -280,18 +278,18 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
||||
try {
|
||||
IrisRegistrant rr = registrant.getConstructor().newInstance();
|
||||
ResourceLoader<T> r = null;
|
||||
if(registrant.equals(IrisObject.class)) {
|
||||
if (registrant.equals(IrisObject.class)) {
|
||||
r = (ResourceLoader<T>) new ObjectResourceLoader(dataFolder, this, rr.getFolderName(),
|
||||
rr.getTypeName());
|
||||
} else if(registrant.equals(IrisMatterObject.class)) {
|
||||
rr.getTypeName());
|
||||
} else if (registrant.equals(IrisMatterObject.class)) {
|
||||
r = (ResourceLoader<T>) new MatterObjectResourceLoader(dataFolder, this, rr.getFolderName(),
|
||||
rr.getTypeName());
|
||||
} else if(registrant.equals(IrisScript.class)) {
|
||||
} else if (registrant.equals(IrisScript.class)) {
|
||||
r = (ResourceLoader<T>) new ScriptResourceLoader(dataFolder, this, rr.getFolderName(),
|
||||
rr.getTypeName());
|
||||
} else if(registrant.equals(IrisImage.class)) {
|
||||
} else if (registrant.equals(IrisImage.class)) {
|
||||
r = (ResourceLoader<T>) new ImageResourceLoader(dataFolder, this, rr.getFolderName(),
|
||||
rr.getTypeName());
|
||||
rr.getTypeName());
|
||||
} else {
|
||||
J.attempt(() -> registrant.getConstructor().newInstance().registerTypeAdapters(builder));
|
||||
r = new ResourceLoader<>(dataFolder, this, rr.getFolderName(), rr.getTypeName(), registrant);
|
||||
@@ -300,7 +298,7 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
||||
loaders.put(registrant, r);
|
||||
|
||||
return r;
|
||||
} catch(Throwable e) {
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
Iris.error("Failed to create loader! " + registrant.getCanonicalName());
|
||||
}
|
||||
@@ -311,11 +309,11 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
||||
public synchronized void hotloaded() {
|
||||
possibleSnippets = new KMap<>();
|
||||
builder = new GsonBuilder()
|
||||
.addDeserializationExclusionStrategy(this)
|
||||
.addSerializationExclusionStrategy(this)
|
||||
.setLenient()
|
||||
.registerTypeAdapterFactory(this)
|
||||
.setPrettyPrinting();
|
||||
.addDeserializationExclusionStrategy(this)
|
||||
.addSerializationExclusionStrategy(this)
|
||||
.setLenient()
|
||||
.registerTypeAdapterFactory(this)
|
||||
.setPrettyPrinting();
|
||||
loaders.clear();
|
||||
File packs = dataFolder;
|
||||
packs.mkdirs();
|
||||
@@ -343,26 +341,26 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
||||
}
|
||||
|
||||
public void dump() {
|
||||
for(ResourceLoader<?> i : loaders.values()) {
|
||||
for (ResourceLoader<?> i : loaders.values()) {
|
||||
i.clearCache();
|
||||
}
|
||||
}
|
||||
|
||||
public void clearLists() {
|
||||
for(ResourceLoader<?> i : loaders.values()) {
|
||||
for (ResourceLoader<?> i : loaders.values()) {
|
||||
i.clearList();
|
||||
}
|
||||
}
|
||||
|
||||
public String toLoadKey(File f) {
|
||||
if(f.getPath().startsWith(getDataFolder().getPath())) {
|
||||
if (f.getPath().startsWith(getDataFolder().getPath())) {
|
||||
String[] full = f.getPath().split("\\Q" + File.separator + "\\E");
|
||||
String[] df = getDataFolder().getPath().split("\\Q" + File.separator + "\\E");
|
||||
StringBuilder g = new StringBuilder();
|
||||
boolean m = true;
|
||||
for(int i = 0; i < full.length; i++) {
|
||||
if(i >= df.length) {
|
||||
if(m) {
|
||||
for (int i = 0; i < full.length; i++) {
|
||||
if (i >= df.length) {
|
||||
if (m) {
|
||||
m = false;
|
||||
continue;
|
||||
}
|
||||
@@ -371,8 +369,7 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
||||
}
|
||||
}
|
||||
|
||||
String ff = g.substring(1).split("\\Q.\\E")[0];
|
||||
return ff;
|
||||
return g.substring(1).split("\\Q.\\E")[0];
|
||||
} else {
|
||||
Iris.error("Forign file from loader " + f.getPath() + " (loader realm: " + getDataFolder().getPath() + ")");
|
||||
}
|
||||
@@ -389,14 +386,14 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
||||
|
||||
@Override
|
||||
public boolean shouldSkipClass(Class<?> c) {
|
||||
if(c.equals(AtomicCache.class)) {
|
||||
if (c.equals(AtomicCache.class)) {
|
||||
return true;
|
||||
} else return c.equals(ChronoLatch.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
|
||||
if(!typeToken.getRawType().isAnnotationPresent(Snippet.class)) {
|
||||
if (!typeToken.getRawType().isAnnotationPresent(Snippet.class)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -412,17 +409,17 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
||||
public T read(JsonReader reader) throws IOException {
|
||||
TypeAdapter<T> adapter = gson.getDelegateAdapter(IrisData.this, typeToken);
|
||||
|
||||
if(reader.peek().equals(JsonToken.STRING)) {
|
||||
if (reader.peek().equals(JsonToken.STRING)) {
|
||||
String r = reader.nextString();
|
||||
|
||||
if(r.startsWith("snippet/" + snippetType + "/")) {
|
||||
if (r.startsWith("snippet/" + snippetType + "/")) {
|
||||
File f = new File(getDataFolder(), r + ".json");
|
||||
|
||||
if(f.exists()) {
|
||||
if (f.exists()) {
|
||||
try {
|
||||
JsonReader snippetReader = new JsonReader(new FileReader(f));
|
||||
return adapter.read(snippetReader);
|
||||
} catch(Throwable e) {
|
||||
} catch (Throwable e) {
|
||||
Iris.error("Couldn't read snippet " + r + " in " + reader.getPath() + " (" + e.getMessage() + ")");
|
||||
}
|
||||
} else {
|
||||
@@ -435,11 +432,11 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
||||
|
||||
try {
|
||||
return adapter.read(reader);
|
||||
} catch(Throwable e) {
|
||||
} catch (Throwable e) {
|
||||
Iris.error("Failed to read " + typeToken.getRawType().getCanonicalName() + "... faking objects a little to load the file at least.");
|
||||
try {
|
||||
return (T) typeToken.getRawType().getConstructor().newInstance();
|
||||
} catch(Throwable ignored) {
|
||||
} catch (Throwable ignored) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -454,8 +451,8 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
||||
|
||||
File snippetFolder = new File(getDataFolder(), "snippet/" + f);
|
||||
|
||||
if(snippetFolder.exists() && snippetFolder.isDirectory()) {
|
||||
for(File i : snippetFolder.listFiles()) {
|
||||
if (snippetFolder.exists() && snippetFolder.isDirectory()) {
|
||||
for (File i : snippetFolder.listFiles()) {
|
||||
l.add("snippet/" + f + "/" + i.getName().split("\\Q.\\E")[0]);
|
||||
}
|
||||
}
|
||||
@@ -467,4 +464,38 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
||||
public boolean isClosed() {
|
||||
return closed;
|
||||
}
|
||||
|
||||
public void savePrefetch(Engine engine) {
|
||||
BurstExecutor b = MultiBurst.burst.burst(loaders.size());
|
||||
|
||||
for (ResourceLoader<?> i : loaders.values()) {
|
||||
b.queue(() -> {
|
||||
try {
|
||||
i.saveFirstAccess(engine);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
b.complete();
|
||||
Iris.info("Saved Prefetch Cache to speed up future world startups");
|
||||
}
|
||||
|
||||
public void loadPrefetch(Engine engine) {
|
||||
BurstExecutor b = MultiBurst.burst.burst(loaders.size());
|
||||
|
||||
for (ResourceLoader<?> i : loaders.values()) {
|
||||
b.queue(() -> {
|
||||
try {
|
||||
i.loadFirstAccess(engine);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
b.complete();
|
||||
Iris.info("Loaded Prefetch Cache to reduce generation disk use.");
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -29,7 +29,7 @@ import com.volmit.iris.util.json.JSONObject;
|
||||
import com.volmit.iris.util.plugin.VolmitSender;
|
||||
import lombok.Data;
|
||||
|
||||
import java.awt.Desktop;
|
||||
import java.awt.*;
|
||||
import java.io.File;
|
||||
|
||||
@Data
|
||||
@@ -56,7 +56,7 @@ public abstract class IrisRegistrant {
|
||||
public File openInVSCode() {
|
||||
try {
|
||||
Desktop.getDesktop().open(getLoadFile());
|
||||
} catch(Throwable e) {
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -29,6 +29,8 @@ import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||
import java.io.File;
|
||||
|
||||
public class MatterObjectResourceLoader extends ResourceLoader<IrisMatterObject> {
|
||||
private String[] possibleKeys;
|
||||
|
||||
public MatterObjectResourceLoader(File root, IrisData idm, String folderName, String resourceTypeName) {
|
||||
super(root, idm, folderName, resourceTypeName, IrisMatterObject.class);
|
||||
loadCache = new KCache<>(this::loadRaw, IrisSettings.get().getPerformance().getObjectLoaderCacheSize());
|
||||
@@ -56,39 +58,33 @@ public class MatterObjectResourceLoader extends ResourceLoader<IrisMatterObject>
|
||||
logLoad(j, t);
|
||||
tlt.addAndGet(p.getMilliseconds());
|
||||
return t;
|
||||
} catch(Throwable e) {
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
Iris.warn("Couldn't read " + resourceTypeName + " file: " + j.getPath() + ": " + e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void findMatFiles(File dir, KSet<String> m) {
|
||||
for (File file : dir.listFiles()) {
|
||||
if (file.isFile() && file.getName().endsWith(".mat")) {
|
||||
m.add(file.getName().replaceAll("\\Q.mat\\E", ""));
|
||||
} else if (file.isDirectory()) {
|
||||
findMatFiles(file, m);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String[] getPossibleKeys() {
|
||||
if(possibleKeys != null) {
|
||||
if (possibleKeys != null) {
|
||||
return possibleKeys;
|
||||
}
|
||||
|
||||
Iris.debug("Building " + resourceTypeName + " Possibility Lists");
|
||||
KSet<String> m = new KSet<>();
|
||||
|
||||
for(File i : getFolders()) {
|
||||
for(File j : i.listFiles()) {
|
||||
if(j.isFile() && j.getName().endsWith(".mat")) {
|
||||
m.add(j.getName().replaceAll("\\Q.mat\\E", ""));
|
||||
} else if(j.isDirectory()) {
|
||||
for(File k : j.listFiles()) {
|
||||
if(k.isFile() && k.getName().endsWith(".mat")) {
|
||||
m.add(j.getName() + "/" + k.getName().replaceAll("\\Q.mat\\E", ""));
|
||||
} else if(k.isDirectory()) {
|
||||
for(File l : k.listFiles()) {
|
||||
if(l.isFile() && l.getName().endsWith(".mat")) {
|
||||
m.add(j.getName() + "/" + k.getName() + "/" + l.getName().replaceAll("\\Q.mat\\E", ""));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (File folder : getFolders()) {
|
||||
findMatFiles(folder, m);
|
||||
}
|
||||
|
||||
KList<String> v = new KList<>(m);
|
||||
@@ -96,17 +92,51 @@ public class MatterObjectResourceLoader extends ResourceLoader<IrisMatterObject>
|
||||
return possibleKeys;
|
||||
}
|
||||
|
||||
|
||||
// public String[] getPossibleKeys() {
|
||||
// if (possibleKeys != null) {
|
||||
// return possibleKeys;
|
||||
// }
|
||||
//
|
||||
// Iris.debug("Building " + resourceTypeName + " Possibility Lists");
|
||||
// KSet<String> m = new KSet<>();
|
||||
//
|
||||
// for (File i : getFolders()) {
|
||||
// for (File j : i.listFiles()) {
|
||||
// if (j.isFile() && j.getName().endsWith(".mat")) {
|
||||
// m.add(j.getName().replaceAll("\\Q.mat\\E", ""));
|
||||
// } else if (j.isDirectory()) {
|
||||
// for (File k : j.listFiles()) {
|
||||
// if (k.isFile() && k.getName().endsWith(".mat")) {
|
||||
// m.add(j.getName() + "/" + k.getName().replaceAll("\\Q.mat\\E", ""));
|
||||
// } else if (k.isDirectory()) {
|
||||
// for (File l : k.listFiles()) {
|
||||
// if (l.isFile() && l.getName().endsWith(".mat")) {
|
||||
// m.add(j.getName() + "/" + k.getName() + "/" + l.getName().replaceAll("\\Q.mat\\E", ""));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// KList<String> v = new KList<>(m);
|
||||
// possibleKeys = v.toArray(new String[0]);
|
||||
// return possibleKeys;
|
||||
// }
|
||||
|
||||
public File findFile(String name) {
|
||||
for(File i : getFolders(name)) {
|
||||
for(File j : i.listFiles()) {
|
||||
if(j.isFile() && j.getName().endsWith(".mat") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
||||
for (File i : getFolders(name)) {
|
||||
for (File j : i.listFiles()) {
|
||||
if (j.isFile() && j.getName().endsWith(".mat") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
||||
return j;
|
||||
}
|
||||
}
|
||||
|
||||
File file = new File(i, name + ".mat");
|
||||
|
||||
if(file.exists()) {
|
||||
if (file.exists()) {
|
||||
return file;
|
||||
}
|
||||
}
|
||||
@@ -121,16 +151,16 @@ public class MatterObjectResourceLoader extends ResourceLoader<IrisMatterObject>
|
||||
}
|
||||
|
||||
private IrisMatterObject loadRaw(String name) {
|
||||
for(File i : getFolders(name)) {
|
||||
for(File j : i.listFiles()) {
|
||||
if(j.isFile() && j.getName().endsWith(".mat") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
||||
for (File i : getFolders(name)) {
|
||||
for (File j : i.listFiles()) {
|
||||
if (j.isFile() && j.getName().endsWith(".mat") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
||||
return loadFile(j, name);
|
||||
}
|
||||
}
|
||||
|
||||
File file = new File(i, name + ".mat");
|
||||
|
||||
if(file.exists()) {
|
||||
if (file.exists()) {
|
||||
return loadFile(file, name);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -50,14 +50,14 @@ public class ObjectResourceLoader extends ResourceLoader<IrisObject> {
|
||||
try {
|
||||
PrecisionStopwatch p = PrecisionStopwatch.start();
|
||||
IrisObject t = new IrisObject(0, 0, 0);
|
||||
t.read(j);
|
||||
t.setLoadKey(name);
|
||||
t.setLoader(manager);
|
||||
t.setLoadFile(j);
|
||||
t.read(j);
|
||||
logLoad(j, t);
|
||||
tlt.addAndGet(p.getMilliseconds());
|
||||
return t;
|
||||
} catch(Throwable e) {
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
Iris.warn("Couldn't read " + resourceTypeName + " file: " + j.getPath() + ": " + e.getMessage());
|
||||
return null;
|
||||
@@ -65,49 +65,42 @@ public class ObjectResourceLoader extends ResourceLoader<IrisObject> {
|
||||
}
|
||||
|
||||
public String[] getPossibleKeys() {
|
||||
if(possibleKeys != null) {
|
||||
if (possibleKeys != null) {
|
||||
return possibleKeys;
|
||||
}
|
||||
|
||||
Iris.debug("Building " + resourceTypeName + " Possibility Lists");
|
||||
KSet<String> m = new KSet<>();
|
||||
|
||||
for(File i : getFolders()) {
|
||||
for(File j : i.listFiles()) {
|
||||
if(j.isFile() && j.getName().endsWith(".iob")) {
|
||||
m.add(j.getName().replaceAll("\\Q.iob\\E", ""));
|
||||
} else if(j.isDirectory()) {
|
||||
for(File k : j.listFiles()) {
|
||||
if(k.isFile() && k.getName().endsWith(".iob")) {
|
||||
m.add(j.getName() + "/" + k.getName().replaceAll("\\Q.iob\\E", ""));
|
||||
} else if(k.isDirectory()) {
|
||||
for(File l : k.listFiles()) {
|
||||
if(l.isFile() && l.getName().endsWith(".iob")) {
|
||||
m.add(j.getName() + "/" + k.getName() + "/" + l.getName().replaceAll("\\Q.iob\\E", ""));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (File i : getFolders()) {
|
||||
m.addAll(getFiles(i, ".iob", true));
|
||||
}
|
||||
|
||||
KList<String> v = new KList<>(m);
|
||||
possibleKeys = v.toArray(new String[0]);
|
||||
possibleKeys = m.toArray(new String[0]);
|
||||
return possibleKeys;
|
||||
}
|
||||
|
||||
private KList<String> getFiles(File dir, String ext, boolean skipDirName) {
|
||||
KList<String> paths = new KList<>();
|
||||
String name = skipDirName ? "" : dir.getName() + "/";
|
||||
for (File f : dir.listFiles()) {
|
||||
if (f.isFile() && f.getName().endsWith(ext)) {
|
||||
paths.add(name + f.getName().replaceAll("\\Q" + ext + "\\E", ""));
|
||||
} else if (f.isDirectory()) {
|
||||
getFiles(f, ext, false).forEach(e -> paths.add(name + e));
|
||||
}
|
||||
}
|
||||
return paths;
|
||||
}
|
||||
|
||||
public File findFile(String name) {
|
||||
for(File i : getFolders(name)) {
|
||||
for(File j : i.listFiles()) {
|
||||
if(j.isFile() && j.getName().endsWith(".iob") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
||||
for (File i : getFolders(name)) {
|
||||
for (File j : i.listFiles()) {
|
||||
if (j.isFile() && j.getName().endsWith(".iob") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
||||
return j;
|
||||
}
|
||||
}
|
||||
|
||||
File file = new File(i, name + ".iob");
|
||||
|
||||
if(file.exists()) {
|
||||
if (file.exists()) {
|
||||
return file;
|
||||
}
|
||||
}
|
||||
@@ -122,16 +115,16 @@ public class ObjectResourceLoader extends ResourceLoader<IrisObject> {
|
||||
}
|
||||
|
||||
private IrisObject loadRaw(String name) {
|
||||
for(File i : getFolders(name)) {
|
||||
for(File j : i.listFiles()) {
|
||||
if(j.isFile() && j.getName().endsWith(".iob") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
||||
for (File i : getFolders(name)) {
|
||||
for (File j : i.listFiles()) {
|
||||
if (j.isFile() && j.getName().endsWith(".iob") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
||||
return loadFile(j, name);
|
||||
}
|
||||
}
|
||||
|
||||
File file = new File(i, name + ".iob");
|
||||
|
||||
if(file.exists()) {
|
||||
if (file.exists()) {
|
||||
return loadFile(file, name);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -23,37 +23,48 @@ import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.project.SchemaBuilder;
|
||||
import com.volmit.iris.core.service.PreservationSVC;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.framework.MeteredCache;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KSet;
|
||||
import com.volmit.iris.util.data.KCache;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.io.CustomOutputStream;
|
||||
import com.volmit.iris.util.io.IO;
|
||||
import com.volmit.iris.util.json.JSONArray;
|
||||
import com.volmit.iris.util.json.JSONObject;
|
||||
import com.volmit.iris.util.parallel.BurstExecutor;
|
||||
import com.volmit.iris.util.parallel.MultiBurst;
|
||||
import com.volmit.iris.util.scheduling.ChronoLatch;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.*;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(exclude = "manager")
|
||||
@ToString(exclude = "manager")
|
||||
public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
||||
public static final AtomicDouble tlt = new AtomicDouble(0);
|
||||
private static final int CACHE_SIZE = 100000;
|
||||
protected final AtomicReference<KList<File>> folderCache;
|
||||
protected KSet<String> firstAccess;
|
||||
protected File root;
|
||||
protected String folderName;
|
||||
protected String resourceTypeName;
|
||||
protected KCache<String, T> loadCache;
|
||||
protected final AtomicReference<KList<File>> folderCache;
|
||||
protected Class<? extends T> objectClass;
|
||||
protected String cname;
|
||||
protected String[] possibleKeys = null;
|
||||
@@ -63,6 +74,7 @@ public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
||||
|
||||
public ResourceLoader(File root, IrisData manager, String folderName, String resourceTypeName, Class<? extends T> objectClass) {
|
||||
this.manager = manager;
|
||||
firstAccess = new KSet<>();
|
||||
folderCache = new AtomicReference<>();
|
||||
sec = new ChronoLatch(5000);
|
||||
loads = new AtomicInteger();
|
||||
@@ -81,7 +93,7 @@ public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
||||
JSONObject o = new JSONObject();
|
||||
KList<String> fm = new KList<>();
|
||||
|
||||
for(int g = 1; g < 8; g++) {
|
||||
for (int g = 1; g < 8; g++) {
|
||||
fm.add("/" + folderName + Form.repeat("/*", g) + ".json");
|
||||
}
|
||||
|
||||
@@ -94,16 +106,16 @@ public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
||||
}
|
||||
|
||||
public File findFile(String name) {
|
||||
for(File i : getFolders(name)) {
|
||||
for(File j : i.listFiles()) {
|
||||
if(j.isFile() && j.getName().endsWith(".json") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
||||
for (File i : getFolders(name)) {
|
||||
for (File j : i.listFiles()) {
|
||||
if (j.isFile() && j.getName().endsWith(".json") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
||||
return j;
|
||||
}
|
||||
}
|
||||
|
||||
File file = new File(i, name + ".json");
|
||||
|
||||
if(file.exists()) {
|
||||
if (file.exists()) {
|
||||
return file;
|
||||
}
|
||||
}
|
||||
@@ -116,11 +128,11 @@ public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
||||
public void logLoad(File path, T t) {
|
||||
loads.getAndIncrement();
|
||||
|
||||
if(loads.get() == 1) {
|
||||
if (loads.get() == 1) {
|
||||
sec.flip();
|
||||
}
|
||||
|
||||
if(sec.flip()) {
|
||||
if (sec.flip()) {
|
||||
J.a(() -> {
|
||||
Iris.verbose("Loaded " + C.WHITE + loads.get() + " " + resourceTypeName + (loads.get() == 1 ? "" : "s") + C.GRAY + " (" + Form.f(getLoadCache().getSize()) + " " + resourceTypeName + (loadCache.getSize() == 1 ? "" : "s") + " Loaded)");
|
||||
loads.set(0);
|
||||
@@ -141,32 +153,32 @@ public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
||||
}
|
||||
|
||||
private void matchFiles(File at, KList<File> files, Predicate<File> f) {
|
||||
if(at.isDirectory()) {
|
||||
for(File i : at.listFiles()) {
|
||||
if (at.isDirectory()) {
|
||||
for (File i : at.listFiles()) {
|
||||
matchFiles(i, files, f);
|
||||
}
|
||||
} else {
|
||||
if(f.test(at)) {
|
||||
if (f.test(at)) {
|
||||
files.add(at);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String[] getPossibleKeys() {
|
||||
if(possibleKeys != null) {
|
||||
if (possibleKeys != null) {
|
||||
return possibleKeys;
|
||||
}
|
||||
|
||||
KSet<String> m = new KSet<>();
|
||||
KList<File> files = getFolders();
|
||||
|
||||
if(files == null) {
|
||||
if (files == null) {
|
||||
possibleKeys = new String[0];
|
||||
return possibleKeys;
|
||||
}
|
||||
|
||||
for(File i : files) {
|
||||
for(File j : matchAllFiles(i, (f) -> f.getName().endsWith(".json"))) {
|
||||
for (File i : files) {
|
||||
for (File j : matchAllFiles(i, (f) -> f.getName().endsWith(".json"))) {
|
||||
m.add(i.toURI().relativize(j.toURI()).getPath().replaceAll("\\Q.json\\E", ""));
|
||||
}
|
||||
}
|
||||
@@ -184,7 +196,7 @@ public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
||||
try {
|
||||
PrecisionStopwatch p = PrecisionStopwatch.start();
|
||||
T t = getManager().getGson()
|
||||
.fromJson(preprocess(new JSONObject(IO.readAll(j))).toString(0), objectClass);
|
||||
.fromJson(preprocess(new JSONObject(IO.readAll(j))).toString(0), objectClass);
|
||||
t.setLoadKey(name);
|
||||
t.setLoadFile(j);
|
||||
t.setLoader(manager);
|
||||
@@ -192,7 +204,7 @@ public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
||||
logLoad(j, t);
|
||||
tlt.addAndGet(p.getMilliseconds());
|
||||
return t;
|
||||
} catch(Throwable e) {
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
failLoad(j, e);
|
||||
return null;
|
||||
@@ -210,10 +222,10 @@ public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
||||
public KList<T> loadAll(KList<String> s) {
|
||||
KList<T> m = new KList<>();
|
||||
|
||||
for(String i : s) {
|
||||
for (String i : s) {
|
||||
T t = load(i);
|
||||
|
||||
if(t != null) {
|
||||
if (t != null) {
|
||||
m.add(t);
|
||||
}
|
||||
}
|
||||
@@ -221,13 +233,31 @@ public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
||||
return m;
|
||||
}
|
||||
|
||||
public KList<T> loadAllParallel(KList<String> s) {
|
||||
KList<T> m = new KList<>();
|
||||
BurstExecutor burst = MultiBurst.burst.burst(s.size());
|
||||
|
||||
for (String i : s) {
|
||||
burst.queue(() -> {
|
||||
T t = load(i);
|
||||
|
||||
if (t != null) {
|
||||
m.add(t);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
burst.complete();
|
||||
return m;
|
||||
}
|
||||
|
||||
public KList<T> loadAll(KList<String> s, Consumer<T> postLoad) {
|
||||
KList<T> m = new KList<>();
|
||||
|
||||
for(String i : s) {
|
||||
for (String i : s) {
|
||||
T t = load(i);
|
||||
|
||||
if(t != null) {
|
||||
if (t != null) {
|
||||
m.add(t);
|
||||
postLoad.accept(t);
|
||||
}
|
||||
@@ -239,10 +269,10 @@ public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
||||
public KList<T> loadAll(String[] s) {
|
||||
KList<T> m = new KList<>();
|
||||
|
||||
for(String i : s) {
|
||||
for (String i : s) {
|
||||
T t = load(i);
|
||||
|
||||
if(t != null) {
|
||||
if (t != null) {
|
||||
m.add(t);
|
||||
}
|
||||
}
|
||||
@@ -255,17 +285,17 @@ public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
||||
}
|
||||
|
||||
private T loadRaw(String name) {
|
||||
for(File i : getFolders(name)) {
|
||||
for (File i : getFolders(name)) {
|
||||
//noinspection ConstantConditions
|
||||
for(File j : i.listFiles()) {
|
||||
if(j.isFile() && j.getName().endsWith(".json") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
||||
for (File j : i.listFiles()) {
|
||||
if (j.isFile() && j.getName().endsWith(".json") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
||||
return loadFile(j, name);
|
||||
}
|
||||
}
|
||||
|
||||
File file = new File(i, name + ".json");
|
||||
|
||||
if(file.exists()) {
|
||||
if (file.exists()) {
|
||||
return loadFile(file, name);
|
||||
}
|
||||
}
|
||||
@@ -274,27 +304,72 @@ public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
||||
}
|
||||
|
||||
public T load(String name, boolean warn) {
|
||||
if(name == null) {
|
||||
if (name == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if(name.trim().isEmpty()) {
|
||||
if (name.trim().isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
firstAccess.add(name);
|
||||
return loadCache.get(name);
|
||||
}
|
||||
|
||||
public void loadFirstAccess(Engine engine) throws IOException {
|
||||
String id = "DIM" + Math.abs(engine.getSeedManager().getSeed() + engine.getDimension().getVersion() + engine.getDimension().getLoadKey().hashCode());
|
||||
File file = Iris.instance.getDataFile("prefetch/" + id + "/" + Math.abs(getFolderName().hashCode()) + ".ipfch");
|
||||
|
||||
if (!file.exists()) {
|
||||
return;
|
||||
}
|
||||
|
||||
FileInputStream fin = new FileInputStream(file);
|
||||
GZIPInputStream gzi = new GZIPInputStream(fin);
|
||||
DataInputStream din = new DataInputStream(gzi);
|
||||
int m = din.readInt();
|
||||
KList<String> s = new KList<>();
|
||||
|
||||
for (int i = 0; i < m; i++) {
|
||||
s.add(din.readUTF());
|
||||
}
|
||||
|
||||
din.close();
|
||||
file.deleteOnExit();
|
||||
Iris.info("Loading " + s.size() + " prefetch " + getFolderName());
|
||||
loadAllParallel(s);
|
||||
}
|
||||
|
||||
public void saveFirstAccess(Engine engine) throws IOException {
|
||||
String id = "DIM" + Math.abs(engine.getSeedManager().getSeed() + engine.getDimension().getVersion() + engine.getDimension().getLoadKey().hashCode());
|
||||
File file = Iris.instance.getDataFile("prefetch/" + id + "/" + Math.abs(getFolderName().hashCode()) + ".ipfch");
|
||||
file.getParentFile().mkdirs();
|
||||
FileOutputStream fos = new FileOutputStream(file);
|
||||
GZIPOutputStream gzo = new CustomOutputStream(fos, 9);
|
||||
DataOutputStream dos = new DataOutputStream(gzo);
|
||||
dos.writeInt(firstAccess.size());
|
||||
|
||||
for (String i : firstAccess) {
|
||||
dos.writeUTF(i);
|
||||
}
|
||||
|
||||
dos.flush();
|
||||
dos.close();
|
||||
}
|
||||
|
||||
public KList<File> getFolders() {
|
||||
|
||||
|
||||
synchronized(folderCache) {
|
||||
if(folderCache.get() == null) {
|
||||
synchronized (folderCache) {
|
||||
if (folderCache.get() == null) {
|
||||
KList<File> fc = new KList<>();
|
||||
|
||||
for(File i : root.listFiles()) {
|
||||
if(i.isDirectory()) {
|
||||
if(i.getName().equals(folderName)) {
|
||||
File[] files = root.listFiles();
|
||||
if (files == null) {
|
||||
throw new IllegalStateException("Failed to list files in " + root);
|
||||
}
|
||||
|
||||
for (File i : files) {
|
||||
if (i.isDirectory()) {
|
||||
if (i.getName().equals(folderName)) {
|
||||
fc.add(i);
|
||||
break;
|
||||
}
|
||||
@@ -311,9 +386,9 @@ public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
||||
public KList<File> getFolders(String rc) {
|
||||
KList<File> folders = getFolders().copy();
|
||||
|
||||
if(rc.contains(":")) {
|
||||
for(File i : folders.copy()) {
|
||||
if(!rc.startsWith(i.getName() + ":")) {
|
||||
if (rc.contains(":")) {
|
||||
for (File i : folders.copy()) {
|
||||
if (!rc.startsWith(i.getName() + ":")) {
|
||||
folders.remove(i);
|
||||
}
|
||||
}
|
||||
@@ -329,16 +404,16 @@ public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
||||
}
|
||||
|
||||
public File fileFor(T b) {
|
||||
for(File i : getFolders()) {
|
||||
for(File j : i.listFiles()) {
|
||||
if(j.isFile() && j.getName().endsWith(".json") && j.getName().split("\\Q.\\E")[0].equals(b.getLoadKey())) {
|
||||
for (File i : getFolders()) {
|
||||
for (File j : i.listFiles()) {
|
||||
if (j.isFile() && j.getName().endsWith(".json") && j.getName().split("\\Q.\\E")[0].equals(b.getLoadKey())) {
|
||||
return j;
|
||||
}
|
||||
}
|
||||
|
||||
File file = new File(i, b.getLoadKey() + ".json");
|
||||
|
||||
if(file.exists()) {
|
||||
if (file.exists()) {
|
||||
return file;
|
||||
}
|
||||
}
|
||||
@@ -358,8 +433,8 @@ public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
||||
public KList<String> getPossibleKeys(String arg) {
|
||||
KList<String> f = new KList<>();
|
||||
|
||||
for(String i : getPossibleKeys()) {
|
||||
if(i.equalsIgnoreCase(arg) || i.toLowerCase(Locale.ROOT).startsWith(arg.toLowerCase(Locale.ROOT)) || i.toLowerCase(Locale.ROOT).contains(arg.toLowerCase(Locale.ROOT)) || arg.toLowerCase(Locale.ROOT).contains(i.toLowerCase(Locale.ROOT))) {
|
||||
for (String i : getPossibleKeys()) {
|
||||
if (i.equalsIgnoreCase(arg) || i.toLowerCase(Locale.ROOT).startsWith(arg.toLowerCase(Locale.ROOT)) || i.toLowerCase(Locale.ROOT).contains(arg.toLowerCase(Locale.ROOT)) || arg.toLowerCase(Locale.ROOT).contains(i.toLowerCase(Locale.ROOT))) {
|
||||
f.add(i);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -21,13 +21,13 @@ package com.volmit.iris.core.loader;
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.engine.object.IrisScript;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KSet;
|
||||
import com.volmit.iris.util.data.KCache;
|
||||
import com.volmit.iris.util.io.IO;
|
||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class ScriptResourceLoader extends ResourceLoader<IrisScript> {
|
||||
public ScriptResourceLoader(File root, IrisData idm, String folderName, String resourceTypeName) {
|
||||
@@ -53,57 +53,88 @@ public class ScriptResourceLoader extends ResourceLoader<IrisScript> {
|
||||
logLoad(j, t);
|
||||
tlt.addAndGet(p.getMilliseconds());
|
||||
return t;
|
||||
} catch(Throwable e) {
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
Iris.warn("Couldn't read " + resourceTypeName + " file: " + j.getPath() + ": " + e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public String[] getPossibleKeys() {
|
||||
if(possibleKeys != null) {
|
||||
if (possibleKeys != null) {
|
||||
return possibleKeys;
|
||||
}
|
||||
|
||||
Iris.debug("Building " + resourceTypeName + " Possibility Lists");
|
||||
KSet<String> m = new KSet<>();
|
||||
Set<String> keys = new HashSet<>();
|
||||
|
||||
for(File i : getFolders()) {
|
||||
for(File j : i.listFiles()) {
|
||||
if(j.isFile() && j.getName().endsWith(".js")) {
|
||||
m.add(j.getName().replaceAll("\\Q.js\\E", ""));
|
||||
} else if(j.isDirectory()) {
|
||||
for(File k : j.listFiles()) {
|
||||
if(k.isFile() && k.getName().endsWith(".js")) {
|
||||
m.add(j.getName() + "/" + k.getName().replaceAll("\\Q.js\\E", ""));
|
||||
} else if(k.isDirectory()) {
|
||||
for(File l : k.listFiles()) {
|
||||
if(l.isFile() && l.getName().endsWith(".js")) {
|
||||
m.add(j.getName() + "/" + k.getName() + "/" + l.getName().replaceAll("\\Q.js\\E", ""));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (File i : getFolders()) {
|
||||
if (i.isDirectory()) {
|
||||
keys.addAll(getKeysInDirectory(i));
|
||||
}
|
||||
}
|
||||
|
||||
KList<String> v = new KList<>(m);
|
||||
possibleKeys = v.toArray(new String[0]);
|
||||
possibleKeys = keys.toArray(new String[0]);
|
||||
return possibleKeys;
|
||||
}
|
||||
|
||||
private Set<String> getKeysInDirectory(File directory) {
|
||||
Set<String> keys = new HashSet<>();
|
||||
for (File file : directory.listFiles()) {
|
||||
if (file.isFile() && file.getName().endsWith(".js")) {
|
||||
keys.add(file.getName().replaceAll("\\Q.js\\E", ""));
|
||||
} else if (file.isDirectory()) {
|
||||
keys.addAll(getKeysInDirectory(file));
|
||||
}
|
||||
}
|
||||
return keys;
|
||||
}
|
||||
|
||||
// public String[] getPossibleKeys() {
|
||||
// if (possibleKeys != null) {
|
||||
// return possibleKeys;
|
||||
// }
|
||||
//
|
||||
// Iris.debug("Building " + resourceTypeName + " Possibility Lists");
|
||||
// KSet<String> m = new KSet<>();
|
||||
//
|
||||
// for (File i : getFolders()) {
|
||||
// for (File j : i.listFiles()) {
|
||||
// if (j.isFile() && j.getName().endsWith(".js")) {
|
||||
// m.add(j.getName().replaceAll("\\Q.js\\E", ""));
|
||||
// } else if (j.isDirectory()) {
|
||||
// for (File k : j.listFiles()) {
|
||||
// if (k.isFile() && k.getName().endsWith(".js")) {
|
||||
// m.add(j.getName() + "/" + k.getName().replaceAll("\\Q.js\\E", ""));
|
||||
// } else if (k.isDirectory()) {
|
||||
// for (File l : k.listFiles()) {
|
||||
// if (l.isFile() && l.getName().endsWith(".js")) {
|
||||
// m.add(j.getName() + "/" + k.getName() + "/" + l.getName().replaceAll("\\Q.js\\E", ""));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// KList<String> v = new KList<>(m);
|
||||
// possibleKeys = v.toArray(new String[0]);
|
||||
// return possibleKeys;
|
||||
// }
|
||||
|
||||
public File findFile(String name) {
|
||||
for(File i : getFolders(name)) {
|
||||
for(File j : i.listFiles()) {
|
||||
if(j.isFile() && j.getName().endsWith(".js") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
||||
for (File i : getFolders(name)) {
|
||||
for (File j : i.listFiles()) {
|
||||
if (j.isFile() && j.getName().endsWith(".js") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
||||
return j;
|
||||
}
|
||||
}
|
||||
|
||||
File file = new File(i, name + ".js");
|
||||
|
||||
if(file.exists()) {
|
||||
if (file.exists()) {
|
||||
return file;
|
||||
}
|
||||
}
|
||||
@@ -114,16 +145,16 @@ public class ScriptResourceLoader extends ResourceLoader<IrisScript> {
|
||||
}
|
||||
|
||||
private IrisScript loadRaw(String name) {
|
||||
for(File i : getFolders(name)) {
|
||||
for(File j : i.listFiles()) {
|
||||
if(j.isFile() && j.getName().endsWith(".js") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
||||
for (File i : getFolders(name)) {
|
||||
for (File j : i.listFiles()) {
|
||||
if (j.isFile() && j.getName().endsWith(".js") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
||||
return loadFile(j, name);
|
||||
}
|
||||
}
|
||||
|
||||
File file = new File(i, name + ".js");
|
||||
|
||||
if(file.exists()) {
|
||||
if (file.exists()) {
|
||||
return loadFile(file, name);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
48
core/src/main/java/com/volmit/iris/core/nms/IHeadless.java
Normal file
48
core/src/main/java/com/volmit/iris/core/nms/IHeadless.java
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.nms;
|
||||
|
||||
import com.volmit.iris.core.pregenerator.PregenListener;
|
||||
import com.volmit.iris.server.node.IrisSession;
|
||||
import com.volmit.iris.server.packet.work.ChunkPacket;
|
||||
import com.volmit.iris.util.documentation.ChunkCoordinates;
|
||||
import com.volmit.iris.util.documentation.RegionCoordinates;
|
||||
import com.volmit.iris.util.parallel.MultiBurst;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public interface IHeadless extends Closeable {
|
||||
|
||||
void setSession(IrisSession session);
|
||||
|
||||
int getLoadedChunks();
|
||||
|
||||
@ChunkCoordinates
|
||||
boolean exists(int x, int z);
|
||||
|
||||
@RegionCoordinates
|
||||
CompletableFuture<Void> generateRegion(MultiBurst burst, int x, int z, int maxConcurrent, PregenListener listener);
|
||||
|
||||
@ChunkCoordinates
|
||||
void generateChunk(int x, int z);
|
||||
|
||||
@ChunkCoordinates
|
||||
void addChunk(ChunkPacket packet);
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -20,15 +20,18 @@ package com.volmit.iris.core.nms;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.nms.v19_1.NMSBinding19_1;
|
||||
import com.volmit.iris.core.nms.v1X.NMSBinding1X;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class INMS {
|
||||
//@builder
|
||||
private static final KMap<String, Class<? extends INMSBinding>> bindings = new KMap<String, Class<? extends INMSBinding>>()
|
||||
.qput("v1_19_R1", NMSBinding19_1.class);
|
||||
private static final Map<String, String> REVISION = Map.of(
|
||||
"1.20.5", "v1_20_R4",
|
||||
"1.20.6", "v1_20_R4",
|
||||
"1.21", "v1_21_R1",
|
||||
"1.21.1", "v1_21_R1"
|
||||
);
|
||||
//@done
|
||||
private static final INMSBinding binding = bind();
|
||||
|
||||
@@ -37,13 +40,18 @@ public class INMS {
|
||||
}
|
||||
|
||||
public static String getNMSTag() {
|
||||
if(IrisSettings.get().getGeneral().isDisableNMS()) {
|
||||
if (IrisSettings.get().getGeneral().isDisableNMS()) {
|
||||
return "BUKKIT";
|
||||
}
|
||||
|
||||
try {
|
||||
return Bukkit.getServer().getClass().getCanonicalName().split("\\Q.\\E")[3];
|
||||
} catch(Throwable e) {
|
||||
String name = Bukkit.getServer().getClass().getCanonicalName();
|
||||
if (name.equals("org.bukkit.craftbukkit.CraftServer")) {
|
||||
return REVISION.getOrDefault(Bukkit.getServer().getBukkitVersion().split("-")[0], "BUKKIT");
|
||||
} else {
|
||||
return name.split("\\Q.\\E")[3];
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
Iris.error("Failed to determine server nms version!");
|
||||
e.printStackTrace();
|
||||
@@ -56,16 +64,20 @@ public class INMS {
|
||||
String code = getNMSTag();
|
||||
Iris.info("Locating NMS Binding for " + code);
|
||||
|
||||
if(bindings.containsKey(code)) {
|
||||
try {
|
||||
Class<?> clazz = Class.forName("com.volmit.iris.core.nms." + code + ".NMSBinding");
|
||||
try {
|
||||
INMSBinding b = bindings.get(code).getConstructor().newInstance();
|
||||
Iris.info("Craftbukkit " + code + " <-> " + b.getClass().getSimpleName() + " Successfully Bound");
|
||||
|
||||
return b;
|
||||
} catch(Throwable e) {
|
||||
Object b = clazz.getConstructor().newInstance();
|
||||
if (b instanceof INMSBinding binding) {
|
||||
Iris.info("Craftbukkit " + code + " <-> " + b.getClass().getSimpleName() + " Successfully Bound");
|
||||
return binding;
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
} catch (ClassNotFoundException |
|
||||
NoClassDefFoundError classNotFoundException) {
|
||||
}
|
||||
|
||||
Iris.info("Craftbukkit " + code + " <-> " + NMSBinding1X.class.getSimpleName() + " Successfully Bound");
|
||||
160
core/src/main/java/com/volmit/iris/core/nms/INMSBinding.java
Normal file
160
core/src/main/java/com/volmit/iris/core/nms/INMSBinding.java
Normal file
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.nms;
|
||||
|
||||
import com.volmit.iris.core.nms.container.BiomeColor;
|
||||
import com.volmit.iris.core.nms.container.IPackRepository;
|
||||
import com.volmit.iris.core.nms.datapack.DataVersion;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.object.IrisBiomeCustom;
|
||||
import com.volmit.iris.engine.object.IrisDimension;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.mantle.Mantle;
|
||||
import com.volmit.iris.util.math.Vector3d;
|
||||
import com.volmit.iris.util.nbt.mca.palette.MCABiomeContainer;
|
||||
import com.volmit.iris.util.nbt.mca.palette.MCAPaletteAccess;
|
||||
import com.volmit.iris.util.nbt.tag.CompoundTag;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.entity.Dolphin;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
import org.bukkit.generator.structure.Structure;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.io.File;
|
||||
import java.awt.Color;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
public interface INMSBinding {
|
||||
boolean hasTile(Material material);
|
||||
|
||||
boolean hasTile(Location l);
|
||||
|
||||
KMap<String, Object> serializeTile(Location location);
|
||||
|
||||
void deserializeTile(KMap<String, Object> s, Location newPosition);
|
||||
|
||||
CompoundTag serializeEntity(Entity location);
|
||||
|
||||
Entity deserializeEntity(CompoundTag s, Location newPosition);
|
||||
|
||||
boolean supportsCustomHeight();
|
||||
|
||||
Object getBiomeBaseFromId(int id);
|
||||
|
||||
int getMinHeight(World world);
|
||||
|
||||
boolean supportsCustomBiomes();
|
||||
|
||||
int getTrueBiomeBaseId(Object biomeBase);
|
||||
|
||||
Object getTrueBiomeBase(Location location);
|
||||
|
||||
String getTrueBiomeBaseKey(Location location);
|
||||
|
||||
Object getCustomBiomeBaseFor(String mckey);
|
||||
|
||||
Object getCustomBiomeBaseHolderFor(String mckey);
|
||||
|
||||
int getBiomeBaseIdForKey(String key);
|
||||
|
||||
String getKeyForBiomeBase(Object biomeBase);
|
||||
|
||||
Object getBiomeBase(World world, Biome biome);
|
||||
|
||||
Object getBiomeBase(Object registry, Biome biome);
|
||||
|
||||
KList<Biome> getBiomes();
|
||||
|
||||
boolean isBukkit();
|
||||
|
||||
int getBiomeId(Biome biome);
|
||||
|
||||
MCABiomeContainer newBiomeContainer(int min, int max, int[] data);
|
||||
|
||||
MCABiomeContainer newBiomeContainer(int min, int max);
|
||||
|
||||
default World createWorld(WorldCreator c) {
|
||||
return c.createWorld();
|
||||
}
|
||||
|
||||
int countCustomBiomes();
|
||||
|
||||
void forceBiomeInto(int x, int y, int z, Object somethingVeryDirty, ChunkGenerator.BiomeGrid chunk);
|
||||
|
||||
default boolean supportsDataPacks() {
|
||||
return false;
|
||||
}
|
||||
|
||||
MCAPaletteAccess createPalette();
|
||||
|
||||
void injectBiomesFromMantle(Chunk e, Mantle mantle);
|
||||
|
||||
ItemStack applyCustomNbt(ItemStack itemStack, KMap<String, Object> customNbt) throws IllegalArgumentException;
|
||||
|
||||
void inject(long seed, Engine engine, World world) throws NoSuchFieldException, IllegalAccessException;
|
||||
|
||||
Vector3d getBoundingbox(org.bukkit.entity.EntityType entity);
|
||||
|
||||
default String getMobCategory(EntityType entityType) {
|
||||
// todo: Update to other versions!
|
||||
return null;
|
||||
}
|
||||
|
||||
Entity spawnEntity(Location location, EntityType type, CreatureSpawnEvent.SpawnReason reason);
|
||||
|
||||
Color getBiomeColor(Location location, BiomeColor type);
|
||||
|
||||
default DataVersion getDataVersion() {
|
||||
return DataVersion.V1192;
|
||||
}
|
||||
|
||||
boolean registerDimension(String name, IrisDimension dimension);
|
||||
|
||||
boolean registerBiome(String dimensionId, IrisBiomeCustom biome, boolean replace);
|
||||
|
||||
boolean dumpRegistry(File... folders);
|
||||
|
||||
void injectBukkit();
|
||||
|
||||
default IHeadless createHeadless(Engine engine) {
|
||||
throw new IllegalStateException("Headless mode not supported");
|
||||
}
|
||||
|
||||
default int getSpawnChunkCount(World world) {
|
||||
return 441;
|
||||
}
|
||||
|
||||
IPackRepository getPackRepository();
|
||||
|
||||
KList<String> getStructureKeys();
|
||||
|
||||
default void reconnectAll() {
|
||||
new ArrayList<>(Bukkit.getOnlinePlayers())
|
||||
.forEach(this::reconnect);
|
||||
}
|
||||
|
||||
void reconnect(Player player);
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -16,10 +16,13 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.framework;
|
||||
package com.volmit.iris.core.nms.container;
|
||||
|
||||
public interface EngineEffects extends EngineComponent {
|
||||
void updatePlayerMap();
|
||||
|
||||
void tickRandomPlayer();
|
||||
public enum BiomeColor {
|
||||
FOG,
|
||||
WATER,
|
||||
WATER_FOG,
|
||||
SKY,
|
||||
FOLIAGE,
|
||||
GRASS
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.nms.container;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class BlockPos {
|
||||
private int x;
|
||||
private int y;
|
||||
private int z;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.nms.container;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public interface IPackRepository {
|
||||
void reload();
|
||||
|
||||
void reloadWorldData();
|
||||
|
||||
void setSelected(Collection<String> packs);
|
||||
|
||||
boolean addPack(String packId);
|
||||
|
||||
boolean removePack(String packId);
|
||||
|
||||
Collection<String> getAvailableIds();
|
||||
|
||||
Collection<String> getSelectedIds();
|
||||
|
||||
boolean isAvailable(String packId);
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.nms.container;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class Pair<A, B> {
|
||||
private A a;
|
||||
private B b;
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.nms.datapack;
|
||||
|
||||
import com.volmit.iris.core.nms.INMS;
|
||||
import com.volmit.iris.core.nms.datapack.v1192.DataFixerV1192;
|
||||
import com.volmit.iris.core.nms.datapack.v1206.DataFixerV1206;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
//https://minecraft.wiki/w/Pack_format
|
||||
@Getter
|
||||
public enum DataVersion {
|
||||
V1192("1.19.2", 10, DataFixerV1192::new),
|
||||
V1205("1.20.6", 41, DataFixerV1206::new);
|
||||
private static final KMap<DataVersion, IDataFixer> cache = new KMap<>();
|
||||
@Getter(AccessLevel.NONE)
|
||||
private final Supplier<IDataFixer> constructor;
|
||||
private final String version;
|
||||
private final int packFormat;
|
||||
|
||||
DataVersion(String version, int packFormat, Supplier<IDataFixer> constructor) {
|
||||
this.constructor = constructor;
|
||||
this.packFormat = packFormat;
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public static IDataFixer getDefault() {
|
||||
return INMS.get().getDataVersion().get();
|
||||
}
|
||||
|
||||
public static DataVersion getLatest() {
|
||||
return values()[values().length - 1];
|
||||
}
|
||||
|
||||
public IDataFixer get() {
|
||||
return cache.computeIfAbsent(this, k -> constructor.get());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.nms.datapack;
|
||||
|
||||
import com.volmit.iris.engine.object.IrisBiomeCustom;
|
||||
import com.volmit.iris.util.json.JSONObject;
|
||||
|
||||
public interface IDataFixer {
|
||||
|
||||
JSONObject fixCustomBiome(IrisBiomeCustom biome, JSONObject json);
|
||||
|
||||
JSONObject fixDimension(JSONObject json);
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.nms.datapack.v1192;
|
||||
|
||||
import com.volmit.iris.core.nms.datapack.IDataFixer;
|
||||
import com.volmit.iris.engine.object.IrisBiomeCustom;
|
||||
import com.volmit.iris.util.json.JSONObject;
|
||||
|
||||
public class DataFixerV1192 implements IDataFixer {
|
||||
|
||||
@Override
|
||||
public JSONObject fixCustomBiome(IrisBiomeCustom biome, JSONObject json) {
|
||||
return json;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject fixDimension(JSONObject json) {
|
||||
return json;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.nms.datapack.v1206;
|
||||
|
||||
import com.volmit.iris.core.nms.datapack.IDataFixer;
|
||||
import com.volmit.iris.engine.object.IrisBiomeCustom;
|
||||
import com.volmit.iris.engine.object.IrisBiomeCustomSpawn;
|
||||
import com.volmit.iris.engine.object.IrisBiomeCustomSpawnType;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.json.JSONArray;
|
||||
import com.volmit.iris.util.json.JSONObject;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
public class DataFixerV1206 implements IDataFixer {
|
||||
@Override
|
||||
public JSONObject fixCustomBiome(IrisBiomeCustom biome, JSONObject json) {
|
||||
int spawnRarity = biome.getSpawnRarity();
|
||||
if (spawnRarity > 0) {
|
||||
json.put("creature_spawn_probability", Math.min(spawnRarity / 20d, 0.9999999));
|
||||
}
|
||||
|
||||
var spawns = biome.getSpawns();
|
||||
if (spawns != null && spawns.isNotEmpty()) {
|
||||
JSONObject spawners = new JSONObject();
|
||||
KMap<IrisBiomeCustomSpawnType, JSONArray> groups = new KMap<>();
|
||||
|
||||
for (IrisBiomeCustomSpawn i : spawns) {
|
||||
JSONArray g = groups.computeIfAbsent(i.getGroup(), (k) -> new JSONArray());
|
||||
JSONObject o = new JSONObject();
|
||||
o.put("type", "minecraft:" + i.getType().name().toLowerCase());
|
||||
o.put("weight", i.getWeight());
|
||||
o.put("minCount", Math.min(i.getMinCount() / 20d, 0));
|
||||
o.put("maxCount", Math.min(i.getMaxCount() / 20d, 0.9999999));
|
||||
g.put(o);
|
||||
}
|
||||
|
||||
for (IrisBiomeCustomSpawnType i : groups.k()) {
|
||||
spawners.put(i.name().toLowerCase(Locale.ROOT), groups.get(i));
|
||||
}
|
||||
|
||||
json.put("spawners", spawners);
|
||||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject fixDimension(JSONObject json) {
|
||||
if (!(json.get("monster_spawn_light_level") instanceof JSONObject lightLevel))
|
||||
return json;
|
||||
var value = (JSONObject) lightLevel.remove("value");
|
||||
lightLevel.put("max_inclusive", value.get("max_inclusive"));
|
||||
lightLevel.put("min_inclusive", value.get("min_inclusive"));
|
||||
return json;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,317 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.nms.v1X;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.nms.INMSBinding;
|
||||
import com.volmit.iris.core.nms.container.BiomeColor;
|
||||
import com.volmit.iris.core.nms.container.BlockPos;
|
||||
import com.volmit.iris.core.nms.container.IPackRepository;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.object.IrisBiomeCustom;
|
||||
import com.volmit.iris.engine.object.IrisDimension;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.mantle.Mantle;
|
||||
import com.volmit.iris.util.math.Vector3d;
|
||||
import com.volmit.iris.util.nbt.mca.palette.MCABiomeContainer;
|
||||
import com.volmit.iris.util.nbt.mca.palette.MCAPaletteAccess;
|
||||
import com.volmit.iris.util.nbt.tag.CompoundTag;
|
||||
import net.bytebuddy.ByteBuddy;
|
||||
import net.bytebuddy.asm.Advice;
|
||||
import net.bytebuddy.dynamic.loading.ClassReloadingStrategy;
|
||||
import net.bytebuddy.matcher.ElementMatchers;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.WorldCreator;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.entity.Dolphin;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
import org.bukkit.generator.structure.Structure;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.io.File;
|
||||
|
||||
public class NMSBinding1X implements INMSBinding {
|
||||
private static final boolean supportsCustomHeight = testCustomHeight();
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
private static boolean testCustomHeight() {
|
||||
try {
|
||||
if (World.class.getDeclaredMethod("getMaxHeight") != null && World.class.getDeclaredMethod("getMinHeight") != null)
|
||||
;
|
||||
{
|
||||
return true;
|
||||
}
|
||||
} catch (Throwable ignored) {
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasTile(Material material) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasTile(Location l) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KMap<String, Object> serializeTile(Location location) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserializeTile(KMap<String, Object> s, Location newPosition) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void injectBiomesFromMantle(Chunk e, Mantle mantle) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack applyCustomNbt(ItemStack itemStack, KMap<String, Object> customNbt) throws IllegalArgumentException {
|
||||
return itemStack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inject(long seed, Engine engine, World world) throws NoSuchFieldException, IllegalAccessException {
|
||||
|
||||
}
|
||||
|
||||
public Vector3d getBoundingbox() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Entity spawnEntity(Location location, EntityType type, CreatureSpawnEvent.SpawnReason reason) {
|
||||
return location.getWorld().spawnEntity(location, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean registerDimension(String name, IrisDimension dimension) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean registerBiome(String dimensionId, IrisBiomeCustom biome, boolean replace) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dumpRegistry(File... folders) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Color getBiomeColor(Location location, BiomeColor type) {
|
||||
return Color.GREEN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KList<String> getStructureKeys() {
|
||||
var list = Registry.STRUCTURE.stream()
|
||||
.map(Structure::getKey)
|
||||
.map(NamespacedKey::toString)
|
||||
.toList();
|
||||
return new KList<>(list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reconnect(Player player) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag serializeEntity(Entity location) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Entity deserializeEntity(CompoundTag s, Location newPosition) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsCustomHeight() {
|
||||
return supportsCustomHeight;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getBiomeBaseFromId(int id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinHeight(World world) {
|
||||
return supportsCustomHeight ? world.getMinHeight() : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsCustomBiomes() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTrueBiomeBaseId(Object biomeBase) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getTrueBiomeBase(Location location) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTrueBiomeBaseKey(Location location) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getCustomBiomeBaseFor(String mckey) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getCustomBiomeBaseHolderFor(String mckey) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBiomeBaseIdForKey(String key) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKeyForBiomeBase(Object biomeBase) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Object getBiomeBase(World world, Biome biome) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getBiomeBase(Object registry, Biome biome) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KList<Biome> getBiomes() {
|
||||
return new KList<>(Biome.values()).qdel(Biome.CUSTOM);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBukkit() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBiomeId(Biome biome) {
|
||||
return biome.ordinal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MCABiomeContainer newBiomeContainer(int min, int max) {
|
||||
Iris.error("Cannot use the custom biome data! Iris is incapable of using MCA generation on this version of minecraft!");
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MCABiomeContainer newBiomeContainer(int min, int max, int[] v) {
|
||||
Iris.error("Cannot use the custom biome data! Iris is incapable of using MCA generation on this version of minecraft!");
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int countCustomBiomes() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forceBiomeInto(int x, int y, int z, Object somethingVeryDirty, ChunkGenerator.BiomeGrid chunk) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector3d getBoundingbox(org.bukkit.entity.EntityType entity) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MCAPaletteAccess createPalette() {
|
||||
Iris.error("Cannot use the global data palette! Iris is incapable of using MCA generation on this version of minecraft!");
|
||||
return null;
|
||||
}
|
||||
|
||||
public void injectBukkit() {
|
||||
try {
|
||||
Iris.info("Injecting Bukkit");
|
||||
new ByteBuddy()
|
||||
.redefine(WorldCreator.class)
|
||||
.visit(Advice.to(WorldCreatorAdvice.class).on(ElementMatchers.isConstructor().and(ElementMatchers.takesArguments(String.class))))
|
||||
.make()
|
||||
.load(WorldCreator.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent());
|
||||
Iris.info("Injected Bukkit Successfully!");
|
||||
} catch (Exception e) {
|
||||
Iris.info(C.RED + "Failed to Inject Bukkit!");
|
||||
e.printStackTrace();
|
||||
Iris.reportError(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPackRepository getPackRepository() {
|
||||
return new PackRepository1X();
|
||||
}
|
||||
|
||||
private static class WorldCreatorAdvice {
|
||||
@Advice.OnMethodEnter
|
||||
static void enter(@Advice.Argument(0) String name) {
|
||||
File isIrisWorld = new File(name, "iris");
|
||||
boolean isFromIris = false;
|
||||
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
|
||||
for (StackTraceElement stack : stackTrace) {
|
||||
if (stack.getClassName().contains("Iris")) {
|
||||
isFromIris = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!isFromIris) {
|
||||
Preconditions.checkArgument(!isIrisWorld.exists(), "Only Iris can load Iris Worlds!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.nms.v1X;
|
||||
|
||||
import com.volmit.iris.core.nms.container.IPackRepository;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
class PackRepository1X implements IPackRepository {
|
||||
@Override
|
||||
public void reload() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reloadWorldData() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelected(Collection<String> packs) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addPack(String packId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removePack(String packId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getAvailableIds() {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getSelectedIds() {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable(String packId) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -54,8 +54,7 @@ public class IrisPack {
|
||||
* Create an iris pack backed by a data folder
|
||||
* the data folder is assumed to be in the Iris/packs/NAME folder
|
||||
*
|
||||
* @param name
|
||||
* the name
|
||||
* @param name the name
|
||||
*/
|
||||
public IrisPack(String name) {
|
||||
this(packsPack(name));
|
||||
@@ -64,17 +63,16 @@ public class IrisPack {
|
||||
/**
|
||||
* Create an iris pack backed by a data folder
|
||||
*
|
||||
* @param folder
|
||||
* the folder of the pack. Must be a directory
|
||||
* @param folder the folder of the pack. Must be a directory
|
||||
*/
|
||||
public IrisPack(File folder) {
|
||||
this.folder = folder;
|
||||
|
||||
if(!folder.exists()) {
|
||||
if (!folder.exists()) {
|
||||
throw new RuntimeException("Cannot open Pack " + folder.getPath() + " (directory doesnt exist)");
|
||||
}
|
||||
|
||||
if(!folder.isDirectory()) {
|
||||
if (!folder.isDirectory()) {
|
||||
throw new RuntimeException("Cannot open Pack " + folder.getPath() + " (not a directory)");
|
||||
}
|
||||
|
||||
@@ -84,23 +82,20 @@ public class IrisPack {
|
||||
/**
|
||||
* Create a new pack from the input url
|
||||
*
|
||||
* @param sender
|
||||
* the sender
|
||||
* @param url
|
||||
* the url, or name, or really anything see IrisPackRepository.from(String)
|
||||
* @param sender the sender
|
||||
* @param url the url, or name, or really anything see IrisPackRepository.from(String)
|
||||
* @return the iris pack
|
||||
* @throws IrisException
|
||||
* fails
|
||||
* @throws IrisException fails
|
||||
*/
|
||||
public static Future<IrisPack> from(VolmitSender sender, String url) throws IrisException {
|
||||
IrisPackRepository repo = IrisPackRepository.from(url);
|
||||
if(repo == null) {
|
||||
if (repo == null) {
|
||||
throw new IrisException("Null Repo");
|
||||
}
|
||||
|
||||
try {
|
||||
return from(sender, repo);
|
||||
} catch(MalformedURLException e) {
|
||||
} catch (MalformedURLException e) {
|
||||
throw new IrisException("Malformed URL " + e.getMessage());
|
||||
}
|
||||
}
|
||||
@@ -108,13 +103,10 @@ public class IrisPack {
|
||||
/**
|
||||
* Create a pack from a repo
|
||||
*
|
||||
* @param sender
|
||||
* the sender
|
||||
* @param repo
|
||||
* the repo
|
||||
* @param sender the sender
|
||||
* @param repo the repo
|
||||
* @return the pack
|
||||
* @throws MalformedURLException
|
||||
* shit happens
|
||||
* @throws MalformedURLException shit happens
|
||||
*/
|
||||
public static Future<IrisPack> from(VolmitSender sender, IrisPackRepository repo) throws MalformedURLException {
|
||||
CompletableFuture<IrisPack> pack = new CompletableFuture<>();
|
||||
@@ -127,16 +119,14 @@ public class IrisPack {
|
||||
/**
|
||||
* Create a blank pack with a given name
|
||||
*
|
||||
* @param name
|
||||
* the name of the pack
|
||||
* @param name the name of the pack
|
||||
* @return the pack
|
||||
* @throws IrisException
|
||||
* if the pack already exists or another error
|
||||
* @throws IrisException if the pack already exists or another error
|
||||
*/
|
||||
public static IrisPack blank(String name) throws IrisException {
|
||||
File f = packsPack(name);
|
||||
|
||||
if(f.exists()) {
|
||||
if (f.exists()) {
|
||||
throw new IrisException("Already exists");
|
||||
}
|
||||
|
||||
@@ -144,10 +134,10 @@ public class IrisPack {
|
||||
fd.getParentFile().mkdirs();
|
||||
try {
|
||||
IO.writeAll(fd, "{\n" +
|
||||
" \"name\": \"" + Form.capitalize(name) + "\",\n" +
|
||||
" \"version\": 1\n" +
|
||||
"}\n");
|
||||
} catch(IOException e) {
|
||||
" \"name\": \"" + Form.capitalize(name) + "\",\n" +
|
||||
" \"version\": 1\n" +
|
||||
"}\n");
|
||||
} catch (IOException e) {
|
||||
throw new IrisException(e.getMessage(), e);
|
||||
}
|
||||
|
||||
@@ -159,8 +149,7 @@ public class IrisPack {
|
||||
/**
|
||||
* Get a packs pack folder for a name. Such that overworld would resolve as Iris/packs/overworld
|
||||
*
|
||||
* @param name
|
||||
* the name
|
||||
* @param name the name
|
||||
* @return the file path
|
||||
*/
|
||||
public static File packsPack(String name) {
|
||||
@@ -170,11 +159,11 @@ public class IrisPack {
|
||||
private static KList<File> collectFiles(File f, String fileExtension) {
|
||||
KList<File> l = new KList<>();
|
||||
|
||||
if(f.isDirectory()) {
|
||||
for(File i : f.listFiles()) {
|
||||
if (f.isDirectory()) {
|
||||
for (File i : f.listFiles()) {
|
||||
l.addAll(collectFiles(i, fileExtension));
|
||||
}
|
||||
} else if(f.getName().endsWith("." + fileExtension)) {
|
||||
} else if (f.getName().endsWith("." + fileExtension)) {
|
||||
l.add(f);
|
||||
}
|
||||
|
||||
@@ -225,13 +214,13 @@ public class IrisPack {
|
||||
p.end();
|
||||
Iris.debug("Building Workspace: " + ws.getPath() + " took " + Form.duration(p.getMilliseconds(), 2));
|
||||
return true;
|
||||
} catch(Throwable e) {
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
Iris.warn("Pack invalid: " + ws.getAbsolutePath() + " Re-creating. You may loose some vs-code workspace settings! But not your actual project!");
|
||||
ws.delete();
|
||||
try {
|
||||
IO.writeAll(ws, generateWorkspaceConfig());
|
||||
} catch(IOException e1) {
|
||||
} catch (IOException e1) {
|
||||
Iris.reportError(e1);
|
||||
e1.printStackTrace();
|
||||
}
|
||||
@@ -243,8 +232,7 @@ public class IrisPack {
|
||||
/**
|
||||
* Install this pack into a world
|
||||
*
|
||||
* @param world
|
||||
* the world to install into (world/iris/pack)
|
||||
* @param world the world to install into (world/iris/pack)
|
||||
* @return the installed pack
|
||||
*/
|
||||
public IrisPack install(World world) throws IrisException {
|
||||
@@ -254,8 +242,7 @@ public class IrisPack {
|
||||
/**
|
||||
* Install this pack into a world
|
||||
*
|
||||
* @param world
|
||||
* the world to install into (world/iris/pack)
|
||||
* @param world the world to install into (world/iris/pack)
|
||||
* @return the installed pack
|
||||
*/
|
||||
public IrisPack install(IrisWorld world) throws IrisException {
|
||||
@@ -265,12 +252,11 @@ public class IrisPack {
|
||||
/**
|
||||
* Install this pack into a world
|
||||
*
|
||||
* @param folder
|
||||
* the folder to install this pack into
|
||||
* @param folder the folder to install this pack into
|
||||
* @return the installed pack
|
||||
*/
|
||||
public IrisPack install(File folder) throws IrisException {
|
||||
if(folder.exists()) {
|
||||
if (folder.exists()) {
|
||||
throw new IrisException("Cannot install new pack because the folder " + folder.getName() + " already exists!");
|
||||
}
|
||||
|
||||
@@ -278,7 +264,7 @@ public class IrisPack {
|
||||
|
||||
try {
|
||||
FileUtils.copyDirectory(getFolder(), folder);
|
||||
} catch(IOException e) {
|
||||
} catch (IOException e) {
|
||||
Iris.reportError(e);
|
||||
}
|
||||
|
||||
@@ -289,20 +275,19 @@ public class IrisPack {
|
||||
* Create a new pack using this pack as a template. The new pack will be renamed & have a renamed dimension
|
||||
* to match it.
|
||||
*
|
||||
* @param newName
|
||||
* the new pack name
|
||||
* @param newName the new pack name
|
||||
* @return the new IrisPack
|
||||
*/
|
||||
public IrisPack install(String newName) throws IrisException {
|
||||
File newPack = packsPack(newName);
|
||||
|
||||
if(newPack.exists()) {
|
||||
if (newPack.exists()) {
|
||||
throw new IrisException("Cannot install new pack because the folder " + newName + " already exists!");
|
||||
}
|
||||
|
||||
try {
|
||||
FileUtils.copyDirectory(getFolder(), newPack);
|
||||
} catch(IOException e) {
|
||||
} catch (IOException e) {
|
||||
Iris.reportError(e);
|
||||
}
|
||||
|
||||
@@ -314,7 +299,7 @@ public class IrisPack {
|
||||
try {
|
||||
FileUtils.moveFile(from, to);
|
||||
new File(newPack, getWorkspaceFile().getName()).delete();
|
||||
} catch(Throwable e) {
|
||||
} catch (Throwable e) {
|
||||
throw new IrisException(e);
|
||||
}
|
||||
|
||||
@@ -345,8 +330,7 @@ public class IrisPack {
|
||||
/**
|
||||
* Find all files in this pack with the given extension
|
||||
*
|
||||
* @param fileExtension
|
||||
* the extension
|
||||
* @param fileExtension the extension
|
||||
* @return the list of files
|
||||
*/
|
||||
public KList<File> collectFiles(String fileExtension) {
|
||||
@@ -386,8 +370,8 @@ public class IrisPack {
|
||||
JSONArray schemas = new JSONArray();
|
||||
IrisData dm = IrisData.get(getFolder());
|
||||
|
||||
for(ResourceLoader<?> r : dm.getLoaders().v()) {
|
||||
if(r.supportsSchemas()) {
|
||||
for (ResourceLoader<?> r : dm.getLoaders().v()) {
|
||||
if (r.supportsSchemas()) {
|
||||
schemas.put(r.buildSchema());
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -55,34 +55,34 @@ public class IrisPackRepository {
|
||||
*/
|
||||
public static IrisPackRepository from(String g) {
|
||||
// https://github.com/IrisDimensions/overworld
|
||||
if(g.startsWith("https://github.com/")) {
|
||||
if (g.startsWith("https://github.com/")) {
|
||||
String sub = g.split("\\Qgithub.com/\\E")[1];
|
||||
IrisPackRepository r = IrisPackRepository.builder()
|
||||
.user(sub.split("\\Q/\\E")[0])
|
||||
.repo(sub.split("\\Q/\\E")[1]).build();
|
||||
.user(sub.split("\\Q/\\E")[0])
|
||||
.repo(sub.split("\\Q/\\E")[1]).build();
|
||||
|
||||
if(g.contains("/tree/")) {
|
||||
if (g.contains("/tree/")) {
|
||||
r.setBranch(g.split("/tree/")[1]);
|
||||
}
|
||||
|
||||
return r;
|
||||
} else if(g.contains("/")) {
|
||||
} else if (g.contains("/")) {
|
||||
String[] f = g.split("\\Q/\\E");
|
||||
|
||||
if(f.length == 1) {
|
||||
if (f.length == 1) {
|
||||
return from(g);
|
||||
} else if(f.length == 2) {
|
||||
} else if (f.length == 2) {
|
||||
return IrisPackRepository.builder()
|
||||
.user(f[0])
|
||||
.repo(f[1])
|
||||
.build();
|
||||
} else if(f.length >= 3) {
|
||||
.user(f[0])
|
||||
.repo(f[1])
|
||||
.build();
|
||||
} else if (f.length >= 3) {
|
||||
IrisPackRepository r = IrisPackRepository.builder()
|
||||
.user(f[0])
|
||||
.repo(f[1])
|
||||
.build();
|
||||
.user(f[0])
|
||||
.repo(f[1])
|
||||
.build();
|
||||
|
||||
if(f[2].startsWith("#")) {
|
||||
if (f[2].startsWith("#")) {
|
||||
r.setTag(f[2].substring(1));
|
||||
} else {
|
||||
r.setBranch(f[2]);
|
||||
@@ -92,17 +92,17 @@ public class IrisPackRepository {
|
||||
}
|
||||
} else {
|
||||
return IrisPackRepository.builder()
|
||||
.user("IrisDimensions")
|
||||
.repo(g)
|
||||
.branch(g.equals("overworld") ? "stable" : "master")
|
||||
.build();
|
||||
.user("IrisDimensions")
|
||||
.repo(g)
|
||||
.branch(g.equals("overworld") ? "stable" : "master")
|
||||
.build();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public String toURL() {
|
||||
if(!tag.trim().isEmpty()) {
|
||||
if (!tag.trim().isEmpty()) {
|
||||
return "https://codeload.github.com/" + user + "/" + repo + "/zip/refs/tags/" + tag;
|
||||
}
|
||||
|
||||
@@ -112,19 +112,19 @@ public class IrisPackRepository {
|
||||
public void install(VolmitSender sender, Runnable whenComplete) throws MalformedURLException {
|
||||
File pack = Iris.instance.getDataFolderNoCreate(StudioSVC.WORKSPACE_NAME, getRepo());
|
||||
|
||||
if(!pack.exists()) {
|
||||
if (!pack.exists()) {
|
||||
File dl = new File(Iris.getTemp(), "dltk-" + UUID.randomUUID() + ".zip");
|
||||
File work = new File(Iris.getTemp(), "extk-" + UUID.randomUUID());
|
||||
new JobCollection(Form.capitalize(getRepo()),
|
||||
new DownloadJob(toURL(), pack),
|
||||
new SingleJob("Extracting", () -> ZipUtil.unpack(dl, work)),
|
||||
new SingleJob("Installing", () -> {
|
||||
try {
|
||||
FileUtils.copyDirectory(work.listFiles()[0], pack);
|
||||
} catch(IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
})).execute(sender, whenComplete);
|
||||
new DownloadJob(toURL(), pack),
|
||||
new SingleJob("Extracting", () -> ZipUtil.unpack(dl, work)),
|
||||
new SingleJob("Installing", () -> {
|
||||
try {
|
||||
FileUtils.copyDirectory(work.listFiles()[0], pack);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
})).execute(sender, whenComplete);
|
||||
} else {
|
||||
sender.sendMessage("Pack already exists!");
|
||||
}
|
||||
@@ -0,0 +1,337 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.pregenerator;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.math.M;
|
||||
import com.volmit.iris.util.math.RollingSequence;
|
||||
import com.volmit.iris.util.math.Spiraler;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.World;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
public class ChunkUpdater {
|
||||
private final RollingSequence chunksPerSecond;
|
||||
private final AtomicInteger worldheightsize;
|
||||
private final AtomicInteger worldwidthsize;
|
||||
private final AtomicInteger totalChunks;
|
||||
private final AtomicInteger totalMaxChunks;
|
||||
private final AtomicInteger totalMcaregions;
|
||||
private final AtomicInteger position;
|
||||
private final Object pauseLock;
|
||||
private final Engine engine;
|
||||
private final World world;
|
||||
private AtomicBoolean paused;
|
||||
private AtomicBoolean cancelled;
|
||||
private KMap<Chunk, Long> lastUse;
|
||||
private AtomicInteger chunksProcessed;
|
||||
private AtomicInteger chunksUpdated;
|
||||
private AtomicLong startTime;
|
||||
private ExecutorService executor;
|
||||
private ExecutorService chunkExecutor;
|
||||
private ScheduledExecutorService scheduler;
|
||||
private CompletableFuture future;
|
||||
private CountDownLatch latch;
|
||||
|
||||
public ChunkUpdater(World world) {
|
||||
this.engine = IrisToolbelt.access(world).getEngine();
|
||||
this.chunksPerSecond = new RollingSequence(5);
|
||||
this.world = world;
|
||||
this.lastUse = new KMap();
|
||||
this.worldheightsize = new AtomicInteger(calculateWorldDimensions(new File(world.getWorldFolder(), "region"), 1));
|
||||
this.worldwidthsize = new AtomicInteger(calculateWorldDimensions(new File(world.getWorldFolder(), "region"), 0));
|
||||
int m = Math.max(worldheightsize.get(), worldwidthsize.get());
|
||||
this.executor = Executors.newFixedThreadPool(Math.max(Runtime.getRuntime().availableProcessors() / 3, 1));
|
||||
this.chunkExecutor = Executors.newFixedThreadPool(Math.max(Runtime.getRuntime().availableProcessors() / 3, 1));
|
||||
this.scheduler = Executors.newScheduledThreadPool(1);
|
||||
this.future = new CompletableFuture<>();
|
||||
this.startTime = new AtomicLong();
|
||||
this.worldheightsize.set(m);
|
||||
this.worldwidthsize.set(m);
|
||||
this.totalMaxChunks = new AtomicInteger((worldheightsize.get() / 16) * (worldwidthsize.get() / 16));
|
||||
this.chunksProcessed = new AtomicInteger();
|
||||
this.chunksUpdated = new AtomicInteger();
|
||||
this.position = new AtomicInteger(0);
|
||||
this.latch = new CountDownLatch(totalMaxChunks.get());
|
||||
this.paused = new AtomicBoolean(false);
|
||||
this.pauseLock = new Object();
|
||||
this.cancelled = new AtomicBoolean(false);
|
||||
this.totalChunks = new AtomicInteger(0);
|
||||
this.totalMcaregions = new AtomicInteger(0);
|
||||
}
|
||||
|
||||
public int getChunks() {
|
||||
return totalMaxChunks.get();
|
||||
}
|
||||
|
||||
public void start() {
|
||||
unloadAndSaveAllChunks();
|
||||
update();
|
||||
}
|
||||
|
||||
public boolean pause() {
|
||||
unloadAndSaveAllChunks();
|
||||
if (paused.get()) {
|
||||
paused.set(false);
|
||||
return false;
|
||||
} else {
|
||||
paused.set(true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
unloadAndSaveAllChunks();
|
||||
cancelled.set(true);
|
||||
}
|
||||
|
||||
|
||||
private void update() {
|
||||
Iris.info("Updating..");
|
||||
try {
|
||||
startTime.set(System.currentTimeMillis());
|
||||
scheduler.scheduleAtFixedRate(() -> {
|
||||
try {
|
||||
if (!paused.get()) {
|
||||
long eta = computeETA();
|
||||
long elapsedSeconds = (System.currentTimeMillis() - startTime.get()) / 3000;
|
||||
int processed = chunksProcessed.get();
|
||||
double cps = elapsedSeconds > 0 ? processed / (double) elapsedSeconds : 0;
|
||||
chunksPerSecond.put(cps);
|
||||
double percentage = ((double) chunksProcessed.get() / (double) totalMaxChunks.get()) * 100;
|
||||
if (!cancelled.get()) {
|
||||
Iris.info("Updated: " + Form.f(processed) + " of " + Form.f(totalMaxChunks.get()) + " (%.0f%%) " + Form.f(chunksPerSecond.getAverage()) + "/s, ETA: " + Form.duration(eta,
|
||||
2), percentage);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}, 0, 3, TimeUnit.SECONDS);
|
||||
|
||||
CompletableFuture.runAsync(() -> {
|
||||
for (int i = 0; i < totalMaxChunks.get(); i++) {
|
||||
if (paused.get()) {
|
||||
synchronized (pauseLock) {
|
||||
try {
|
||||
pauseLock.wait();
|
||||
} catch (InterruptedException e) {
|
||||
Iris.error("Interrupted while waiting for executor: ");
|
||||
e.printStackTrace();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
executor.submit(() -> {
|
||||
if (!cancelled.get()) {
|
||||
processNextChunk();
|
||||
}
|
||||
latch.countDown();
|
||||
});
|
||||
}
|
||||
}).thenRun(() -> {
|
||||
try {
|
||||
latch.await();
|
||||
close();
|
||||
} catch (Exception e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
});
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void close() {
|
||||
try {
|
||||
unloadAndSaveAllChunks();
|
||||
executor.shutdown();
|
||||
executor.awaitTermination(5, TimeUnit.SECONDS);
|
||||
chunkExecutor.shutdown();
|
||||
chunkExecutor.awaitTermination(5, TimeUnit.SECONDS);
|
||||
scheduler.shutdownNow();
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
if (cancelled.get()) {
|
||||
Iris.info("Updated: " + Form.f(chunksUpdated.get()) + " Chunks");
|
||||
Iris.info("Irritated: " + Form.f(chunksProcessed.get()) + " of " + Form.f(totalMaxChunks.get()));
|
||||
Iris.info("Stopped updater.");
|
||||
} else {
|
||||
Iris.info("Processed: " + Form.f(chunksProcessed.get()) + " Chunks");
|
||||
Iris.info("Finished Updating: " + Form.f(chunksUpdated.get()) + " Chunks");
|
||||
}
|
||||
}
|
||||
|
||||
private void processNextChunk() {
|
||||
int pos = position.getAndIncrement();
|
||||
int[] coords = getChunk(pos);
|
||||
if (loadChunksIfGenerated(coords[0], coords[1])) {
|
||||
Chunk c = world.getChunkAt(coords[0], coords[1]);
|
||||
engine.updateChunk(c);
|
||||
chunksUpdated.incrementAndGet();
|
||||
}
|
||||
chunksProcessed.getAndIncrement();
|
||||
}
|
||||
|
||||
private boolean loadChunksIfGenerated(int x, int z) {
|
||||
for (int dx = -1; dx <= 1; dx++) {
|
||||
for (int dz = -1; dz <= 1; dz++) {
|
||||
if (!PaperLib.isChunkGenerated(world, x + dx, z + dz)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AtomicBoolean generated = new AtomicBoolean(true);
|
||||
KList<Future<?>> futures = new KList<>(9);
|
||||
for (int dx = -1; dx <= 1; dx++) {
|
||||
for (int dz = -1; dz <= 1; dz++) {
|
||||
int xx = x + dx;
|
||||
int zz = z + dz;
|
||||
futures.add(chunkExecutor.submit(() -> {
|
||||
Chunk c;
|
||||
try {
|
||||
c = PaperLib.getChunkAtAsync(world, xx, zz, false).get();
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
generated.set(false);
|
||||
return;
|
||||
}
|
||||
if (!c.isLoaded()) {
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
J.s(() -> {
|
||||
c.load(false);
|
||||
latch.countDown();
|
||||
});
|
||||
try {
|
||||
latch.await();
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
}
|
||||
if (!c.isGenerated()) {
|
||||
generated.set(false);
|
||||
}
|
||||
lastUse.put(c, M.ms());
|
||||
}));
|
||||
}
|
||||
}
|
||||
while (!futures.isEmpty()) {
|
||||
futures.removeIf(Future::isDone);
|
||||
try {
|
||||
Thread.sleep(50);
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
}
|
||||
return generated.get();
|
||||
}
|
||||
|
||||
private void unloadAndSaveAllChunks() {
|
||||
try {
|
||||
J.sfut(() -> {
|
||||
if (world == null) {
|
||||
Iris.warn("World was null somehow...");
|
||||
return;
|
||||
}
|
||||
|
||||
for (Chunk i : new ArrayList<>(lastUse.keySet())) {
|
||||
Long lastUseTime = lastUse.get(i);
|
||||
if (lastUseTime != null && M.ms() - lastUseTime >= 5000) {
|
||||
i.unload();
|
||||
lastUse.remove(i);
|
||||
}
|
||||
}
|
||||
world.save();
|
||||
}).get();
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private long computeETA() {
|
||||
return (long) (totalMaxChunks.get() > 1024 ? // Generated chunks exceed 1/8th of total?
|
||||
// If yes, use smooth function (which gets more accurate over time since its less sensitive to outliers)
|
||||
((totalMaxChunks.get() - chunksProcessed.get()) * ((double) (M.ms() - startTime.get()) / (double) chunksProcessed.get())) :
|
||||
// If no, use quick function (which is less accurate over time but responds better to the initial delay)
|
||||
((totalMaxChunks.get() - chunksProcessed.get()) / chunksPerSecond.getAverage()) * 1000
|
||||
);
|
||||
}
|
||||
|
||||
private int calculateWorldDimensions(File regionDir, Integer o) {
|
||||
File[] files = regionDir.listFiles((dir, name) -> name.endsWith(".mca"));
|
||||
|
||||
int minX = Integer.MAX_VALUE;
|
||||
int maxX = Integer.MIN_VALUE;
|
||||
int minZ = Integer.MAX_VALUE;
|
||||
int maxZ = Integer.MIN_VALUE;
|
||||
|
||||
for (File file : files) {
|
||||
String[] parts = file.getName().split("\\.");
|
||||
int x = Integer.parseInt(parts[1]);
|
||||
int z = Integer.parseInt(parts[2]);
|
||||
|
||||
if (x < minX) minX = x;
|
||||
if (x > maxX) maxX = x;
|
||||
if (z < minZ) minZ = z;
|
||||
if (z > maxZ) maxZ = z;
|
||||
}
|
||||
|
||||
int height = (maxX - minX + 1) * 32 * 16;
|
||||
int width = (maxZ - minZ + 1) * 32 * 16;
|
||||
|
||||
if (o == 1) {
|
||||
return height;
|
||||
}
|
||||
if (o == 0) {
|
||||
return width;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private int[] getChunk(int position) {
|
||||
int p = -1;
|
||||
AtomicInteger xx = new AtomicInteger();
|
||||
AtomicInteger zz = new AtomicInteger();
|
||||
Spiraler s = new Spiraler(worldheightsize.get() * 2, worldwidthsize.get() * 2, (x, z) -> {
|
||||
xx.set(x);
|
||||
zz.set(z);
|
||||
});
|
||||
|
||||
while (s.hasNext() && p++ < position) {
|
||||
s.next();
|
||||
}
|
||||
int[] coords = new int[2];
|
||||
coords[0] = xx.get();
|
||||
coords[1] = zz.get();
|
||||
|
||||
return coords;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package com.volmit.iris.core.pregenerator;
|
||||
|
||||
public final class EmptyListener implements PregenListener {
|
||||
public static final PregenListener INSTANCE = new EmptyListener();
|
||||
|
||||
private EmptyListener() {}
|
||||
|
||||
@Override
|
||||
public void onTick(double chunksPerSecond, double chunksPerMinute, double regionsPerMinute, double percent, int generated, int totalChunks, int chunksRemaining, long eta, long elapsed, String method) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChunkGenerating(int x, int z) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChunkGenerated(int x, int z) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRegionGenerated(int x, int z) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRegionGenerating(int x, int z) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChunkCleaned(int x, int z) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRegionSkipped(int x, int z) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNetworkStarted(int x, int z) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNetworkFailed(int x, int z) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNetworkReclaim(int revert) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNetworkGeneratedChunk(int x, int z) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNetworkDownloaded(int x, int z) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClose() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaving() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChunkExistsInRegionGen(int x, int z) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -18,23 +18,48 @@
|
||||
|
||||
package com.volmit.iris.core.pregenerator;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.tools.IrisPackBenchmarking;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KSet;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.mantle.Mantle;
|
||||
import com.volmit.iris.util.math.M;
|
||||
import com.volmit.iris.util.math.Position2;
|
||||
import com.volmit.iris.util.math.RollingSequence;
|
||||
import com.volmit.iris.util.nbt.mca.Chunk;
|
||||
import com.volmit.iris.util.nbt.mca.MCAFile;
|
||||
import com.volmit.iris.util.nbt.mca.MCAUtil;
|
||||
import com.volmit.iris.util.parallel.BurstExecutor;
|
||||
import com.volmit.iris.util.parallel.MultiBurst;
|
||||
import com.volmit.iris.util.scheduling.ChronoLatch;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import com.volmit.iris.util.scheduling.Looper;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
|
||||
import java.io.*;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
|
||||
public class IrisPregenerator {
|
||||
private static AtomicInteger generated;
|
||||
private static AtomicInteger totalChunks;
|
||||
private final String saveFile = "regions.json";
|
||||
private final PregenTask task;
|
||||
private final PregeneratorMethod generator;
|
||||
private final PregenListener listener;
|
||||
@@ -44,22 +69,22 @@ public class IrisPregenerator {
|
||||
private final RollingSequence chunksPerSecond;
|
||||
private final RollingSequence chunksPerMinute;
|
||||
private final RollingSequence regionsPerMinute;
|
||||
private final AtomicInteger generated;
|
||||
private final KList<Integer> chunksPerSecondHistory;
|
||||
private final AtomicInteger generatedLast;
|
||||
private final AtomicInteger generatedLastMinute;
|
||||
private final AtomicInteger totalChunks;
|
||||
private final AtomicLong startTime;
|
||||
private final ChronoLatch minuteLatch;
|
||||
private final AtomicReference<String> currentGeneratorMethod;
|
||||
private final KSet<Position2> generatedRegions;
|
||||
private final KSet<Position2> retry;
|
||||
private final KSet<Position2> net;
|
||||
private final ChronoLatch cl;
|
||||
private final ChronoLatch saveLatch = new ChronoLatch(30000);
|
||||
private Set<Position2> generatedRegions;
|
||||
|
||||
public IrisPregenerator(PregenTask task, PregeneratorMethod generator, PregenListener listener) {
|
||||
generatedRegions = ConcurrentHashMap.newKeySet();
|
||||
this.listener = listenify(listener);
|
||||
cl = new ChronoLatch(5000);
|
||||
generatedRegions = new KSet<>();
|
||||
this.shutdown = new AtomicBoolean(false);
|
||||
this.paused = new AtomicBoolean(false);
|
||||
this.task = task;
|
||||
@@ -71,10 +96,15 @@ public class IrisPregenerator {
|
||||
chunksPerSecond = new RollingSequence(10);
|
||||
chunksPerMinute = new RollingSequence(10);
|
||||
regionsPerMinute = new RollingSequence(10);
|
||||
chunksPerSecondHistory = new KList<>();
|
||||
generated = new AtomicInteger(0);
|
||||
generatedLast = new AtomicInteger(0);
|
||||
generatedLastMinute = new AtomicInteger(0);
|
||||
totalChunks = new AtomicInteger(0);
|
||||
if (!IrisPackBenchmarking.benchmarkInProgress) {
|
||||
loadCompletedRegions();
|
||||
IrisToolbelt.access(generator.getWorld()).getEngine().saveEngineData();
|
||||
}
|
||||
task.iterateRegions((_a, _b) -> totalChunks.addAndGet(1024));
|
||||
startTime = new AtomicLong(M.ms());
|
||||
ticker = new Looper() {
|
||||
@@ -84,8 +114,9 @@ public class IrisPregenerator {
|
||||
int secondGenerated = generated.get() - generatedLast.get();
|
||||
generatedLast.set(generated.get());
|
||||
chunksPerSecond.put(secondGenerated);
|
||||
chunksPerSecondHistory.add(secondGenerated);
|
||||
|
||||
if(minuteLatch.flip()) {
|
||||
if (minuteLatch.flip()) {
|
||||
int minuteGenerated = generated.get() - generatedLastMinute.get();
|
||||
generatedLastMinute.set(generated.get());
|
||||
chunksPerMinute.put(minuteGenerated);
|
||||
@@ -93,26 +124,41 @@ public class IrisPregenerator {
|
||||
}
|
||||
|
||||
listener.onTick(chunksPerSecond.getAverage(), chunksPerMinute.getAverage(),
|
||||
regionsPerMinute.getAverage(),
|
||||
(double) generated.get() / (double) totalChunks.get(),
|
||||
generated.get(), totalChunks.get(),
|
||||
totalChunks.get() - generated.get(),
|
||||
eta, M.ms() - startTime.get(), currentGeneratorMethod.get());
|
||||
regionsPerMinute.getAverage(),
|
||||
(double) generated.get() / (double) totalChunks.get(),
|
||||
generated.get(), totalChunks.get(),
|
||||
totalChunks.get() - generated.get(),
|
||||
eta, M.ms() - startTime.get(), currentGeneratorMethod.get());
|
||||
|
||||
if(cl.flip()) {
|
||||
Iris.info("Pregen: " + Form.f(generated.get()) + " of " + Form.f(totalChunks.get()) + " (" + Form.pc((double) generated.get() / (double) totalChunks.get(), 0) + ") " + Form.f((int) chunksPerSecond.getAverage()) + "/s ETA: " + Form.duration((double) eta, 2));
|
||||
if (cl.flip() && !paused.get()) {
|
||||
double percentage = ((double) generated.get() / (double) totalChunks.get()) * 100;
|
||||
if (!IrisPackBenchmarking.benchmarkInProgress) {
|
||||
Iris.info("Pregen: " + Form.f(generated.get()) + " of " + Form.f(totalChunks.get()) + " (%.0f%%) " + Form.f((int) chunksPerSecond.getAverage()) + "/s ETA: " + Form.duration(eta, 2), percentage);
|
||||
} else {
|
||||
Iris.info("Benchmarking: " + Form.f(generated.get()) + " of " + Form.f(totalChunks.get()) + " (%.0f%%) " + Form.f((int) chunksPerSecond.getAverage()) + "/s ETA: " + Form.duration(eta, 2), percentage);
|
||||
}
|
||||
}
|
||||
|
||||
return 1000;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private long computeETA() {
|
||||
return (long) ((totalChunks.get() - generated.get()) *
|
||||
((double) (M.ms() - startTime.get()) / (double) generated.get()));
|
||||
long currentTime = M.ms();
|
||||
long elapsedTime = currentTime - startTime.get();
|
||||
int generatedChunks = generated.get();
|
||||
int remainingChunks = totalChunks.get() - generatedChunks;
|
||||
|
||||
if (generatedChunks <= 12_000) {
|
||||
// quick
|
||||
return (long) (remainingChunks * ((double) elapsedTime / generatedChunks));
|
||||
} else {
|
||||
//smooth
|
||||
return (long) (remainingChunks / chunksPerSecond.getAverage() * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void close() {
|
||||
shutdown.set(true);
|
||||
}
|
||||
@@ -124,6 +170,17 @@ public class IrisPregenerator {
|
||||
task.iterateRegions((x, z) -> visitRegion(x, z, true));
|
||||
task.iterateRegions((x, z) -> visitRegion(x, z, false));
|
||||
shutdown();
|
||||
if (!IrisPackBenchmarking.benchmarkInProgress) {
|
||||
Iris.info(C.IRIS + "Pregen stopped.");
|
||||
// todo: optimizer just takes too long.
|
||||
// if (totalChunks.get() == generated.get() && task.isOptimizer()) {
|
||||
// Iris.info("Starting World Optimizer..");
|
||||
// ChunkUpdater updater = new ChunkUpdater(generator.getWorld());
|
||||
// updater.start();
|
||||
// }
|
||||
} else {
|
||||
IrisPackBenchmarking.getInstance().finishedBenchmark(chunksPerSecondHistory);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkRegions() {
|
||||
@@ -140,53 +197,142 @@ public class IrisPregenerator {
|
||||
generator.close();
|
||||
ticker.interrupt();
|
||||
listener.onClose();
|
||||
saveCompletedRegions();
|
||||
Mantle mantle = getMantle();
|
||||
if (mantle != null) {
|
||||
mantle.trim(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
private void getGeneratedRegions() {
|
||||
World world = generator.getWorld();
|
||||
File[] region = new File(world.getWorldFolder(), "region").listFiles();
|
||||
BurstExecutor b = MultiBurst.burst.burst(region.length);
|
||||
b.setMulticore(true);
|
||||
b.queue(() -> {
|
||||
for (File file : region) {
|
||||
try {
|
||||
String regex = "r\\.(\\d+)\\.(-?\\d+)\\.mca";
|
||||
Pattern pattern = Pattern.compile(regex);
|
||||
Matcher matcher = pattern.matcher(file.getName());
|
||||
if (!matcher.find()) continue;
|
||||
int x = Integer.parseInt(matcher.group(1));
|
||||
int z = Integer.parseInt(matcher.group(2));
|
||||
Position2 pos = new Position2(x, z);
|
||||
generatedRegions.add(pos);
|
||||
|
||||
MCAFile mca = MCAUtil.read(file, 0);
|
||||
|
||||
boolean notFull = false;
|
||||
for (int i = 0; i < 1024; i++) {
|
||||
Chunk chunk = mca.getChunk(i);
|
||||
if (chunk == null) {
|
||||
generatedRegions.remove(pos);
|
||||
notFull = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Iris.info("Completed MCA region: " + file.getName());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
b.complete();
|
||||
}
|
||||
|
||||
private void visitRegion(int x, int z, boolean regions) {
|
||||
while(paused.get() && !shutdown.get()) {
|
||||
while (paused.get() && !shutdown.get()) {
|
||||
J.sleep(50);
|
||||
}
|
||||
|
||||
if(shutdown.get()) {
|
||||
if (shutdown.get()) {
|
||||
listener.onRegionSkipped(x, z);
|
||||
return;
|
||||
}
|
||||
|
||||
Position2 pos = new Position2(x, z);
|
||||
|
||||
if(generatedRegions.contains(pos)) {
|
||||
if (generatedRegions.contains(pos)) {
|
||||
if (regions) {
|
||||
listener.onRegionGenerated(x, z);
|
||||
generated.addAndGet(1024);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
currentGeneratorMethod.set(generator.getMethod(x, z));
|
||||
boolean hit = false;
|
||||
if(generator.supportsRegions(x, z, listener) && regions) {
|
||||
if (generator.supportsRegions(x, z, listener) && regions) {
|
||||
hit = true;
|
||||
listener.onRegionGenerating(x, z);
|
||||
generator.generateRegion(x, z, listener);
|
||||
} else if(!regions) {
|
||||
} else if (!regions) {
|
||||
hit = true;
|
||||
listener.onRegionGenerating(x, z);
|
||||
PregenTask.iterateRegion(x, z, (xx, zz) -> generator.generateChunk(xx, zz, listener));
|
||||
PregenTask.iterateRegion(x, z, (xx, zz) -> {
|
||||
while (paused.get() && !shutdown.get()) {
|
||||
J.sleep(50);
|
||||
}
|
||||
|
||||
generator.generateChunk(xx, zz, listener);
|
||||
});
|
||||
}
|
||||
|
||||
if(hit) {
|
||||
if (hit) {
|
||||
listener.onRegionGenerated(x, z);
|
||||
listener.onSaving();
|
||||
generator.save();
|
||||
|
||||
if (saveLatch.flip()) {
|
||||
listener.onSaving();
|
||||
generator.save();
|
||||
}
|
||||
|
||||
generatedRegions.add(pos);
|
||||
checkRegions();
|
||||
}
|
||||
}
|
||||
|
||||
private void checkRegion(int x, int z) {
|
||||
if(generatedRegions.contains(new Position2(x, z))) {
|
||||
if (generatedRegions.contains(new Position2(x, z))) {
|
||||
return;
|
||||
}
|
||||
|
||||
generator.supportsRegions(x, z, listener);
|
||||
}
|
||||
|
||||
public void saveCompletedRegions() {
|
||||
if (IrisPackBenchmarking.benchmarkInProgress) return;
|
||||
Gson gson = new Gson();
|
||||
try (Writer writer = new FileWriter(generator.getWorld().getWorldFolder().getPath() + "/" + saveFile)) {
|
||||
gson.toJson(new HashSet<>(generatedRegions), writer);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void loadCompletedRegions() {
|
||||
if (task.isResetCache()) {
|
||||
File test = new File(generator.getWorld().getWorldFolder().getPath() + "/" + saveFile);
|
||||
if (!test.delete()) {
|
||||
Iris.info(C.RED + "Failed to reset region cache ");
|
||||
}
|
||||
}
|
||||
Gson gson = new Gson();
|
||||
try (Reader reader = new FileReader(generator.getWorld().getWorldFolder().getPath() + "/" + saveFile)) {
|
||||
Type setType = new TypeToken<HashSet<Position2>>() {
|
||||
}.getType();
|
||||
Set<Position2> loadedSet = gson.fromJson(reader, setType);
|
||||
if (loadedSet != null) {
|
||||
generatedRegions.clear();
|
||||
generatedRegions.addAll(loadedSet);
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
// all fine
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void pause() {
|
||||
paused.set(true);
|
||||
}
|
||||
@@ -215,6 +361,8 @@ public class IrisPregenerator {
|
||||
|
||||
@Override
|
||||
public void onRegionGenerated(int x, int z) {
|
||||
generatedRegions.add(new Position2(x, z));
|
||||
saveCompletedRegions();
|
||||
listener.onRegionGenerated(x, z);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,302 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.pregenerator;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.io.IO;
|
||||
import com.volmit.iris.util.math.M;
|
||||
import com.volmit.iris.util.math.Position2;
|
||||
import com.volmit.iris.util.math.RollingSequence;
|
||||
import com.volmit.iris.util.math.Spiraler;
|
||||
import com.volmit.iris.util.scheduling.ChronoLatch;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.Getter;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.world.WorldUnloadEvent;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
public class LazyPregenerator extends Thread implements Listener {
|
||||
private static final Map<String, LazyPregenJob> jobs = new HashMap<>();
|
||||
@Getter
|
||||
private static LazyPregenerator instance;
|
||||
private static AtomicInteger lazyGeneratedChunks;
|
||||
private final LazyPregenJob job;
|
||||
private final File destination;
|
||||
private final int maxPosition;
|
||||
private final long rate;
|
||||
private final ChronoLatch latch;
|
||||
private final AtomicInteger generatedLast;
|
||||
private final AtomicInteger lazyTotalChunks;
|
||||
private final AtomicLong startTime;
|
||||
private final RollingSequence chunksPerSecond;
|
||||
private final RollingSequence chunksPerMinute;
|
||||
private final ExecutorService executorService = Executors.newSingleThreadExecutor();
|
||||
private World world;
|
||||
|
||||
public LazyPregenerator(LazyPregenJob job, File destination) {
|
||||
this.job = job;
|
||||
this.destination = destination;
|
||||
this.maxPosition = new Spiraler(job.getRadiusBlocks() * 2, job.getRadiusBlocks() * 2, (x, z) -> {
|
||||
}).count();
|
||||
this.world = Bukkit.getWorld(job.getWorld());
|
||||
this.rate = Math.round((1D / (job.getChunksPerMinute() / 60D)) * 1000D);
|
||||
this.latch = new ChronoLatch(15000);
|
||||
this.startTime = new AtomicLong(M.ms());
|
||||
this.chunksPerSecond = new RollingSequence(10);
|
||||
this.chunksPerMinute = new RollingSequence(10);
|
||||
lazyGeneratedChunks = new AtomicInteger(0);
|
||||
this.generatedLast = new AtomicInteger(0);
|
||||
this.lazyTotalChunks = new AtomicInteger((int) Math.ceil(Math.pow((2.0 * job.getRadiusBlocks()) / 16, 2)));
|
||||
jobs.put(job.getWorld(), job);
|
||||
LazyPregenerator.instance = this;
|
||||
}
|
||||
|
||||
public LazyPregenerator(File file) throws IOException {
|
||||
this(new Gson().fromJson(IO.readAll(file), LazyPregenJob.class), file);
|
||||
}
|
||||
|
||||
public static void loadLazyGenerators() {
|
||||
for (World i : Bukkit.getWorlds()) {
|
||||
File lazygen = new File(i.getWorldFolder(), "lazygen.json");
|
||||
if (lazygen.exists()) {
|
||||
try {
|
||||
LazyPregenerator p = new LazyPregenerator(lazygen);
|
||||
p.start();
|
||||
Iris.info("Started Lazy Pregenerator: " + p.job);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void setPausedLazy(World world) {
|
||||
LazyPregenJob job = jobs.get(world.getName());
|
||||
if (isPausedLazy(world)) {
|
||||
job.paused = false;
|
||||
} else {
|
||||
job.paused = true;
|
||||
}
|
||||
|
||||
if (job.paused) {
|
||||
Iris.info(C.BLUE + "LazyGen: " + C.IRIS + world.getName() + C.BLUE + " Paused");
|
||||
} else {
|
||||
Iris.info(C.BLUE + "LazyGen: " + C.IRIS + world.getName() + C.BLUE + " Resumed");
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isPausedLazy(World world) {
|
||||
LazyPregenJob job = jobs.get(world.getName());
|
||||
return job != null && job.isPaused();
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void on(WorldUnloadEvent e) {
|
||||
if (e.getWorld().equals(world)) {
|
||||
interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
public void run() {
|
||||
while (!interrupted()) {
|
||||
J.sleep(rate);
|
||||
tick();
|
||||
}
|
||||
|
||||
try {
|
||||
saveNow();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void tick() {
|
||||
LazyPregenJob job = jobs.get(world.getName());
|
||||
if (latch.flip() && !job.paused) {
|
||||
long eta = computeETA();
|
||||
save();
|
||||
int secondGenerated = lazyGeneratedChunks.get() - generatedLast.get();
|
||||
generatedLast.set(lazyGeneratedChunks.get());
|
||||
secondGenerated = secondGenerated / 15;
|
||||
chunksPerSecond.put(secondGenerated);
|
||||
chunksPerMinute.put(secondGenerated * 60);
|
||||
if (!job.isSilent()) {
|
||||
Iris.info("LazyGen: " + C.IRIS + world.getName() + C.RESET + " RTT: " + Form.f(lazyGeneratedChunks.get()) + " of " + Form.f(lazyTotalChunks.get()) + " " + Form.f((int) chunksPerMinute.getAverage()) + "/m ETA: " + Form.duration((double) eta, 2));
|
||||
}
|
||||
}
|
||||
|
||||
if (lazyGeneratedChunks.get() >= lazyTotalChunks.get()) {
|
||||
if (job.isHealing()) {
|
||||
int pos = (job.getHealingPosition() + 1) % maxPosition;
|
||||
job.setHealingPosition(pos);
|
||||
tickRegenerate(getChunk(pos));
|
||||
} else {
|
||||
Iris.info("Completed Lazy Gen!");
|
||||
interrupt();
|
||||
}
|
||||
} else {
|
||||
int pos = job.getPosition() + 1;
|
||||
job.setPosition(pos);
|
||||
if (!job.paused) {
|
||||
tickGenerate(getChunk(pos));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private long computeETA() {
|
||||
return (long) ((lazyTotalChunks.get() - lazyGeneratedChunks.get()) / chunksPerMinute.getAverage()) * 1000;
|
||||
// todo broken
|
||||
}
|
||||
|
||||
private void tickGenerate(Position2 chunk) {
|
||||
executorService.submit(() -> {
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
if (PaperLib.isPaper()) {
|
||||
PaperLib.getChunkAtAsync(world, chunk.getX(), chunk.getZ(), true)
|
||||
.thenAccept((i) -> {
|
||||
Iris.verbose("Generated Async " + chunk);
|
||||
latch.countDown();
|
||||
});
|
||||
} else {
|
||||
J.s(() -> {
|
||||
world.getChunkAt(chunk.getX(), chunk.getZ());
|
||||
Iris.verbose("Generated " + chunk);
|
||||
latch.countDown();
|
||||
});
|
||||
}
|
||||
try {
|
||||
latch.await();
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
lazyGeneratedChunks.addAndGet(1);
|
||||
});
|
||||
}
|
||||
|
||||
private void tickRegenerate(Position2 chunk) {
|
||||
J.s(() -> world.regenerateChunk(chunk.getX(), chunk.getZ()));
|
||||
Iris.verbose("Regenerated " + chunk);
|
||||
}
|
||||
|
||||
public Position2 getChunk(int position) {
|
||||
int p = -1;
|
||||
AtomicInteger xx = new AtomicInteger();
|
||||
AtomicInteger zz = new AtomicInteger();
|
||||
Spiraler s = new Spiraler(job.getRadiusBlocks() * 2, job.getRadiusBlocks() * 2, (x, z) -> {
|
||||
xx.set(x);
|
||||
zz.set(z);
|
||||
});
|
||||
|
||||
while (s.hasNext() && p++ < position) {
|
||||
s.next();
|
||||
}
|
||||
|
||||
return new Position2(xx.get(), zz.get());
|
||||
}
|
||||
|
||||
public void save() {
|
||||
J.a(() -> {
|
||||
try {
|
||||
saveNow();
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void shutdownInstance(World world) throws IOException {
|
||||
Iris.info("LazyGen: " + C.IRIS + world.getName() + C.BLUE + " Shutting down..");
|
||||
LazyPregenJob job = jobs.get(world.getName());
|
||||
File worldDirectory = new File(Bukkit.getWorldContainer(), world.getName());
|
||||
File lazyFile = new File(worldDirectory, "lazygen.json");
|
||||
|
||||
if (job == null) {
|
||||
Iris.error("No Lazygen job found for world: " + world.getName());
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (!job.isPaused()) {
|
||||
job.setPaused(true);
|
||||
}
|
||||
save();
|
||||
jobs.remove(world.getName());
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
while (lazyFile.exists()) {
|
||||
lazyFile.delete();
|
||||
J.sleep(1000);
|
||||
}
|
||||
Iris.info("LazyGen: " + C.IRIS + world.getName() + C.BLUE + " File deleted and instance closed.");
|
||||
}
|
||||
}.runTaskLater(Iris.instance, 20L);
|
||||
} catch (Exception e) {
|
||||
Iris.error("Failed to shutdown Lazygen for " + world.getName());
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
saveNow();
|
||||
interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void saveNow() throws IOException {
|
||||
IO.writeAll(this.destination, new Gson().toJson(job));
|
||||
}
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
public static class LazyPregenJob {
|
||||
@Builder.Default
|
||||
boolean silent = false;
|
||||
@Builder.Default
|
||||
boolean paused = false;
|
||||
private String world;
|
||||
@Builder.Default
|
||||
private int healingPosition = 0;
|
||||
@Builder.Default
|
||||
private boolean healing = false;
|
||||
@Builder.Default
|
||||
private int chunksPerMinute = 32;
|
||||
@Builder.Default
|
||||
private int radiusBlocks = 5000;
|
||||
@Builder.Default
|
||||
private int position = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -23,6 +23,8 @@ import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.math.Position2;
|
||||
import com.volmit.iris.util.math.Spiraled;
|
||||
import com.volmit.iris.util.math.Spiraler;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
@@ -30,11 +32,17 @@ import java.util.Comparator;
|
||||
|
||||
@Builder
|
||||
@Data
|
||||
@AllArgsConstructor(access = AccessLevel.PROTECTED)
|
||||
public class PregenTask {
|
||||
private static final Position2 ZERO = new Position2(0, 0);
|
||||
private static final KList<Position2> ORDER_CENTER = computeChunkOrder();
|
||||
private static final KMap<Position2, KList<Position2>> ORDERS = new KMap<>();
|
||||
|
||||
|
||||
@Builder.Default
|
||||
private boolean resetCache = false;
|
||||
@Builder.Default
|
||||
private boolean gui = false;
|
||||
@Builder.Default
|
||||
private Position2 center = new Position2(0, 0);
|
||||
@Builder.Default
|
||||
@@ -43,13 +51,13 @@ public class PregenTask {
|
||||
private int height = 1;
|
||||
|
||||
public static void iterateRegion(int xr, int zr, Spiraled s, Position2 pull) {
|
||||
for(Position2 i : ORDERS.computeIfAbsent(pull, PregenTask::computeOrder)) {
|
||||
for (Position2 i : ORDERS.computeIfAbsent(pull, PregenTask::computeOrder)) {
|
||||
s.on(i.getX() + (xr << 5), i.getZ() + (zr << 5));
|
||||
}
|
||||
}
|
||||
|
||||
public static void iterateRegion(int xr, int zr, Spiraled s) {
|
||||
iterateRegion(xr, zr, s, new Position2(0, 0));
|
||||
iterateRegion(xr, zr, s, new Position2(-(xr << 5), -(zr << 5)));
|
||||
}
|
||||
|
||||
private static KList<Position2> computeOrder(Position2 pull) {
|
||||
@@ -57,7 +65,7 @@ public class PregenTask {
|
||||
new Spiraler(33, 33, (x, z) -> {
|
||||
int xx = (x + 15);
|
||||
int zz = (z + 15);
|
||||
if(xx < 0 || xx > 31 || zz < 0 || zz > 31) {
|
||||
if (xx < 0 || xx > 31 || zz < 0 || zz > 31) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -74,7 +82,7 @@ public class PregenTask {
|
||||
new Spiraler(33, 33, (x, z) -> {
|
||||
int xx = x + 15;
|
||||
int zz = z + 15;
|
||||
if(xx < 0 || xx > 31 || zz < 0 || zz > 31) {
|
||||
if (xx < 0 || xx > 31 || zz < 0 || zz > 31) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -86,11 +94,11 @@ public class PregenTask {
|
||||
|
||||
public void iterateRegions(Spiraled s) {
|
||||
new Spiraler(getWidth() * 2, getHeight() * 2, s)
|
||||
.setOffset(center.getX(), center.getZ()).drain();
|
||||
.setOffset(center.getX(), center.getZ()).drain();
|
||||
}
|
||||
|
||||
public void iterateAllChunks(Spiraled s) {
|
||||
new Spiraler(getWidth() * 2, getHeight() * 2, (x, z) -> iterateRegion(x, z, s))
|
||||
.setOffset(center.getX(), center.getZ()).drain();
|
||||
.setOffset(center.getX(), center.getZ()).drain();
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -19,6 +19,7 @@
|
||||
package com.volmit.iris.core.pregenerator;
|
||||
|
||||
import com.volmit.iris.util.mantle.Mantle;
|
||||
import org.bukkit.World;
|
||||
|
||||
/**
|
||||
* Represents something that is capable of generating in chunks or regions, or both
|
||||
@@ -43,10 +44,8 @@ public interface PregeneratorMethod {
|
||||
/**
|
||||
* Return true if regions can be generated
|
||||
*
|
||||
* @param x
|
||||
* the x region
|
||||
* @param z
|
||||
* the z region
|
||||
* @param x the x region
|
||||
* @param z the z region
|
||||
* @return true if they can be
|
||||
*/
|
||||
boolean supportsRegions(int x, int z, PregenListener listener);
|
||||
@@ -54,10 +53,8 @@ public interface PregeneratorMethod {
|
||||
/**
|
||||
* Return the name of the method being used
|
||||
*
|
||||
* @param x
|
||||
* the x region
|
||||
* @param z
|
||||
* the z region
|
||||
* @param x the x region
|
||||
* @param z the z region
|
||||
* @return the name
|
||||
*/
|
||||
String getMethod(int x, int z);
|
||||
@@ -66,24 +63,21 @@ public interface PregeneratorMethod {
|
||||
* Called to generate a region. Execute sync, if multicore internally, wait
|
||||
* for the task to complete
|
||||
*
|
||||
* @param x
|
||||
* the x
|
||||
* @param z
|
||||
* the z
|
||||
* @param listener
|
||||
* signal chunks generating & generated. Parallel capable.
|
||||
* @param x the x
|
||||
* @param z the z
|
||||
* @param listener signal chunks generating & generated. Parallel capable.
|
||||
*/
|
||||
void generateRegion(int x, int z, PregenListener listener);
|
||||
|
||||
/**
|
||||
* Called to generate a chunk. You can go async so long as save will wait on the threads to finish
|
||||
*
|
||||
* @param x
|
||||
* the x
|
||||
* @param z
|
||||
* the z
|
||||
* @param x the x
|
||||
* @param z the z
|
||||
*/
|
||||
void generateChunk(int x, int z, PregenListener listener);
|
||||
|
||||
Mantle getMantle();
|
||||
|
||||
World getWorld();
|
||||
}
|
||||
@@ -0,0 +1,360 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.pregenerator;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.io.IO;
|
||||
import com.volmit.iris.util.math.M;
|
||||
import com.volmit.iris.util.math.Position2;
|
||||
import com.volmit.iris.util.math.RollingSequence;
|
||||
import com.volmit.iris.util.math.Spiraler;
|
||||
import com.volmit.iris.util.parallel.BurstExecutor;
|
||||
import com.volmit.iris.util.parallel.HyperLock;
|
||||
import com.volmit.iris.util.parallel.MultiBurst;
|
||||
import com.volmit.iris.util.scheduling.ChronoLatch;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.Getter;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.world.WorldUnloadEvent;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public class TurboPregenerator extends Thread implements Listener {
|
||||
private static final Map<String, TurboPregenJob> jobs = new HashMap<>();
|
||||
@Getter
|
||||
private static TurboPregenerator instance;
|
||||
private static AtomicInteger turboGeneratedChunks;
|
||||
private final TurboPregenJob job;
|
||||
private final File destination;
|
||||
private final int maxPosition;
|
||||
private final ChronoLatch latch;
|
||||
private final AtomicInteger generatedLast;
|
||||
private final AtomicLong cachedLast;
|
||||
private final RollingSequence cachePerSecond;
|
||||
private final AtomicInteger turboTotalChunks;
|
||||
private final AtomicLong startTime;
|
||||
private final RollingSequence chunksPerSecond;
|
||||
private final RollingSequence chunksPerMinute;
|
||||
private final HyperLock hyperLock;
|
||||
private final ExecutorService executorService = Executors.newFixedThreadPool(10);
|
||||
private World world;
|
||||
private KList<Position2> queue;
|
||||
private ConcurrentHashMap<Integer, Position2> cache;
|
||||
private AtomicInteger maxWaiting;
|
||||
private ReentrantLock cachinglock;
|
||||
private AtomicBoolean caching;
|
||||
private MultiBurst burst;
|
||||
|
||||
public TurboPregenerator(TurboPregenJob job, File destination) {
|
||||
this.job = job;
|
||||
queue = new KList<>(512);
|
||||
this.maxWaiting = new AtomicInteger(128);
|
||||
this.destination = destination;
|
||||
this.maxPosition = new Spiraler(job.getRadiusBlocks() * 2, job.getRadiusBlocks() * 2, (x, z) -> {
|
||||
}).count();
|
||||
this.world = Bukkit.getWorld(job.getWorld());
|
||||
this.latch = new ChronoLatch(3000);
|
||||
this.burst = MultiBurst.burst;
|
||||
this.hyperLock = new HyperLock();
|
||||
this.startTime = new AtomicLong(M.ms());
|
||||
this.cachePerSecond = new RollingSequence(10);
|
||||
this.chunksPerSecond = new RollingSequence(10);
|
||||
this.chunksPerMinute = new RollingSequence(10);
|
||||
turboGeneratedChunks = new AtomicInteger(0);
|
||||
this.generatedLast = new AtomicInteger(0);
|
||||
this.cachedLast = new AtomicLong(0);
|
||||
this.caching = new AtomicBoolean(false);
|
||||
this.turboTotalChunks = new AtomicInteger((int) Math.ceil(Math.pow((2.0 * job.getRadiusBlocks()) / 16, 2)));
|
||||
cache = new ConcurrentHashMap<>(turboTotalChunks.get());
|
||||
this.cachinglock = new ReentrantLock();
|
||||
jobs.put(job.getWorld(), job);
|
||||
TurboPregenerator.instance = this;
|
||||
}
|
||||
|
||||
public TurboPregenerator(File file) throws IOException {
|
||||
this(new Gson().fromJson(IO.readAll(file), TurboPregenerator.TurboPregenJob.class), file);
|
||||
}
|
||||
|
||||
public static void loadTurboGenerator(String i) {
|
||||
World x = Bukkit.getWorld(i);
|
||||
File turbogen = new File(x.getWorldFolder(), "turbogen.json");
|
||||
if (turbogen.exists()) {
|
||||
try {
|
||||
TurboPregenerator p = new TurboPregenerator(turbogen);
|
||||
p.start();
|
||||
Iris.info("Started Turbo Pregenerator: " + p.job);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void setPausedTurbo(World world) {
|
||||
TurboPregenJob job = jobs.get(world.getName());
|
||||
if (isPausedTurbo(world)) {
|
||||
job.paused = false;
|
||||
} else {
|
||||
job.paused = true;
|
||||
}
|
||||
|
||||
if (job.paused) {
|
||||
Iris.info(C.BLUE + "TurboGen: " + C.IRIS + world.getName() + C.BLUE + " Paused");
|
||||
} else {
|
||||
Iris.info(C.BLUE + "TurboGen: " + C.IRIS + world.getName() + C.BLUE + " Resumed");
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isPausedTurbo(World world) {
|
||||
TurboPregenJob job = jobs.get(world.getName());
|
||||
return job != null && job.isPaused();
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void on(WorldUnloadEvent e) {
|
||||
if (e.getWorld().equals(world)) {
|
||||
interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
public void run() {
|
||||
while (!interrupted()) {
|
||||
tick();
|
||||
}
|
||||
|
||||
try {
|
||||
saveNow();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void tick() {
|
||||
TurboPregenJob job = jobs.get(world.getName());
|
||||
if (!cachinglock.isLocked() && cache.isEmpty() && !caching.get()) {
|
||||
ExecutorService cache = Executors.newFixedThreadPool(1);
|
||||
cache.submit(this::cache);
|
||||
}
|
||||
|
||||
if (latch.flip() && caching.get()) {
|
||||
long secondCached = cache.mappingCount() - cachedLast.get();
|
||||
cachedLast.set(cache.mappingCount());
|
||||
secondCached = secondCached / 3;
|
||||
cachePerSecond.put(secondCached);
|
||||
Iris.info("TurboGen: " + C.IRIS + world.getName() + C.RESET + C.BLUE + " Caching: " + Form.f(cache.mappingCount()) + " of " + Form.f(turboTotalChunks.get()) + " " + Form.f((int) cachePerSecond.getAverage()) + "/s");
|
||||
}
|
||||
|
||||
if (latch.flip() && !job.paused && !cachinglock.isLocked()) {
|
||||
long eta = computeETA();
|
||||
save();
|
||||
int secondGenerated = turboGeneratedChunks.get() - generatedLast.get();
|
||||
generatedLast.set(turboGeneratedChunks.get());
|
||||
secondGenerated = secondGenerated / 3;
|
||||
chunksPerSecond.put(secondGenerated);
|
||||
chunksPerMinute.put(secondGenerated * 60);
|
||||
Iris.info("TurboGen: " + C.IRIS + world.getName() + C.RESET + " RTT: " + Form.f(turboGeneratedChunks.get()) + " of " + Form.f(turboTotalChunks.get()) + " " + Form.f((int) chunksPerSecond.getAverage()) + "/s ETA: " + Form.duration((double) eta, 2));
|
||||
|
||||
}
|
||||
if (turboGeneratedChunks.get() >= turboTotalChunks.get()) {
|
||||
Iris.info("Completed Turbo Gen!");
|
||||
interrupt();
|
||||
} else {
|
||||
if (!cachinglock.isLocked()) {
|
||||
int pos = job.getPosition() + 1;
|
||||
job.setPosition(pos);
|
||||
if (!job.paused) {
|
||||
if (queue.size() < maxWaiting.get()) {
|
||||
Position2 chunk = cache.get(pos);
|
||||
queue.add(chunk);
|
||||
}
|
||||
waitForChunksPartial();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void cache() {
|
||||
if (!cachinglock.isLocked()) {
|
||||
cachinglock.lock();
|
||||
caching.set(true);
|
||||
PrecisionStopwatch p = PrecisionStopwatch.start();
|
||||
BurstExecutor b = MultiBurst.burst.burst(turboTotalChunks.get());
|
||||
b.setMulticore(true);
|
||||
int[] list = IntStream.rangeClosed(0, turboTotalChunks.get()).toArray();
|
||||
AtomicInteger order = new AtomicInteger(turboTotalChunks.get());
|
||||
|
||||
int threads = Runtime.getRuntime().availableProcessors();
|
||||
if (threads > 1) threads--;
|
||||
ExecutorService process = Executors.newFixedThreadPool(threads);
|
||||
|
||||
for (int id : list) {
|
||||
b.queue(() -> {
|
||||
cache.put(id, getChunk(id));
|
||||
order.addAndGet(-1);
|
||||
});
|
||||
}
|
||||
b.complete();
|
||||
|
||||
if (order.get() < 0) {
|
||||
cachinglock.unlock();
|
||||
caching.set(false);
|
||||
Iris.info("Completed Caching in: " + Form.duration(p.getMilliseconds(), 2));
|
||||
}
|
||||
} else {
|
||||
Iris.error("TurboCache is locked!");
|
||||
}
|
||||
}
|
||||
|
||||
private void waitForChunksPartial() {
|
||||
while (!queue.isEmpty() && maxWaiting.get() > queue.size()) {
|
||||
try {
|
||||
for (Position2 c : new KList<>(queue)) {
|
||||
tickGenerate(c);
|
||||
queue.remove(c);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private long computeETA() {
|
||||
return (long) ((turboTotalChunks.get() - turboGeneratedChunks.get()) / chunksPerMinute.getAverage()) * 1000;
|
||||
// todo broken
|
||||
}
|
||||
|
||||
private void tickGenerate(Position2 chunk) {
|
||||
executorService.submit(() -> {
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
PaperLib.getChunkAtAsync(world, chunk.getX(), chunk.getZ(), true)
|
||||
.thenAccept((i) -> {
|
||||
latch.countDown();
|
||||
});
|
||||
try {
|
||||
latch.await();
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
turboGeneratedChunks.addAndGet(1);
|
||||
});
|
||||
}
|
||||
|
||||
public Position2 getChunk(int position) {
|
||||
int p = -1;
|
||||
AtomicInteger xx = new AtomicInteger();
|
||||
AtomicInteger zz = new AtomicInteger();
|
||||
Spiraler s = new Spiraler(job.getRadiusBlocks() * 2, job.getRadiusBlocks() * 2, (x, z) -> {
|
||||
xx.set(x);
|
||||
zz.set(z);
|
||||
});
|
||||
|
||||
while (s.hasNext() && p++ < position) {
|
||||
s.next();
|
||||
}
|
||||
|
||||
return new Position2(xx.get(), zz.get());
|
||||
}
|
||||
|
||||
public void save() {
|
||||
J.a(() -> {
|
||||
try {
|
||||
saveNow();
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void shutdownInstance(World world) throws IOException {
|
||||
Iris.info("turboGen: " + C.IRIS + world.getName() + C.BLUE + " Shutting down..");
|
||||
TurboPregenJob job = jobs.get(world.getName());
|
||||
File worldDirectory = new File(Bukkit.getWorldContainer(), world.getName());
|
||||
File turboFile = new File(worldDirectory, "turbogen.json");
|
||||
|
||||
if (job == null) {
|
||||
Iris.error("No turbogen job found for world: " + world.getName());
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (!job.isPaused()) {
|
||||
job.setPaused(true);
|
||||
}
|
||||
save();
|
||||
jobs.remove(world.getName());
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
while (turboFile.exists()) {
|
||||
turboFile.delete();
|
||||
J.sleep(1000);
|
||||
}
|
||||
Iris.info("turboGen: " + C.IRIS + world.getName() + C.BLUE + " File deleted and instance closed.");
|
||||
}
|
||||
}.runTaskLater(Iris.instance, 20L);
|
||||
} catch (Exception e) {
|
||||
Iris.error("Failed to shutdown turbogen for " + world.getName());
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
saveNow();
|
||||
interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void saveNow() throws IOException {
|
||||
IO.writeAll(this.destination, new Gson().toJson(job));
|
||||
}
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
public static class TurboPregenJob {
|
||||
@Builder.Default
|
||||
boolean paused = false;
|
||||
private String world;
|
||||
@Builder.Default
|
||||
private int radiusBlocks = 5000;
|
||||
@Builder.Default
|
||||
private int position = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -26,8 +26,10 @@ import org.bukkit.World;
|
||||
|
||||
public class AsyncOrMedievalPregenMethod implements PregeneratorMethod {
|
||||
private final PregeneratorMethod method;
|
||||
private final World world;
|
||||
|
||||
public AsyncOrMedievalPregenMethod(World world, int threads) {
|
||||
this.world = world;
|
||||
method = PaperLib.isPaper() ? new AsyncPregenMethod(world, threads) : new MedievalPregenMethod(world);
|
||||
}
|
||||
|
||||
@@ -70,4 +72,9 @@ public class AsyncOrMedievalPregenMethod implements PregeneratorMethod {
|
||||
public Mantle getMantle() {
|
||||
return method.getMantle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public World getWorld() {
|
||||
return world;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -19,71 +19,100 @@
|
||||
package com.volmit.iris.core.pregenerator.methods;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.pregenerator.PregenListener;
|
||||
import com.volmit.iris.core.pregenerator.PregeneratorMethod;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.mantle.Mantle;
|
||||
import com.volmit.iris.util.math.M;
|
||||
import com.volmit.iris.util.parallel.MultiBurst;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.World;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
public class AsyncPregenMethod implements PregeneratorMethod {
|
||||
private final World world;
|
||||
private final MultiBurst burst;
|
||||
private final KList<Future<?>> future;
|
||||
private final Map<Chunk, Long> lastUse;
|
||||
|
||||
public AsyncPregenMethod(World world, int threads) {
|
||||
if(!PaperLib.isPaper()) {
|
||||
if (!PaperLib.isPaper()) {
|
||||
throw new UnsupportedOperationException("Cannot use PaperAsync on non paper!");
|
||||
}
|
||||
|
||||
this.world = world;
|
||||
burst = MultiBurst.burst;
|
||||
future = new KList<>(1024);
|
||||
burst = new MultiBurst("Iris Async Pregen", Thread.MIN_PRIORITY);
|
||||
future = new KList<>(256);
|
||||
this.lastUse = new KMap<>();
|
||||
}
|
||||
|
||||
private void unloadAndSaveAllChunks() {
|
||||
try {
|
||||
J.sfut(() -> {
|
||||
if(world == null) {
|
||||
if (world == null) {
|
||||
Iris.warn("World was null somehow...");
|
||||
return;
|
||||
}
|
||||
|
||||
for(Chunk i : world.getLoadedChunks()) {
|
||||
i.unload(true);
|
||||
for (Chunk i : new ArrayList<>(lastUse.keySet())) {
|
||||
Long lastUseTime = lastUse.get(i);
|
||||
if (lastUseTime != null && M.ms() - lastUseTime >= 10000) {
|
||||
i.unload();
|
||||
lastUse.remove(i);
|
||||
}
|
||||
}
|
||||
world.save();
|
||||
}).get();
|
||||
} catch(Throwable e) {
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void completeChunk(int x, int z, PregenListener listener) {
|
||||
try {
|
||||
PaperLib.getChunkAtAsync(world, x, z, true).get();
|
||||
listener.onChunkGenerated(x, z);
|
||||
listener.onChunkCleaned(x, z);
|
||||
} catch(Throwable e) {
|
||||
PaperLib.getChunkAtAsync(world, x, z, true).thenAccept((i) -> {
|
||||
lastUse.put(i, M.ms());
|
||||
listener.onChunkGenerated(x, z);
|
||||
listener.onChunkCleaned(x, z);
|
||||
}).get();
|
||||
} catch (InterruptedException ignored) {
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
J.sleep(5);
|
||||
future.add(burst.complete(() -> completeChunk(x, z, listener)));
|
||||
}
|
||||
}
|
||||
|
||||
private void waitForChunksPartial(int maxWaiting) {
|
||||
while (future.size() > maxWaiting) {
|
||||
try {
|
||||
Future<?> i = future.remove(0);
|
||||
|
||||
if (i == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
i.get();
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void waitForChunks() {
|
||||
for(Future<?> i : future.copy()) {
|
||||
for (Future<?> i : future.copy()) {
|
||||
if (i == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
i.get();
|
||||
future.remove(i);
|
||||
} catch(Throwable e) {
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
@@ -103,11 +132,12 @@ public class AsyncPregenMethod implements PregeneratorMethod {
|
||||
public void close() {
|
||||
waitForChunks();
|
||||
unloadAndSaveAllChunks();
|
||||
burst.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save() {
|
||||
waitForChunks();
|
||||
waitForChunksPartial(256);
|
||||
unloadAndSaveAllChunks();
|
||||
}
|
||||
|
||||
@@ -123,20 +153,24 @@ public class AsyncPregenMethod implements PregeneratorMethod {
|
||||
|
||||
@Override
|
||||
public void generateChunk(int x, int z, PregenListener listener) {
|
||||
if(future.size() > IrisSettings.getThreadCount(IrisSettings.get().getConcurrency().getParallelism())) { // TODO: FIX
|
||||
waitForChunks();
|
||||
}
|
||||
|
||||
listener.onChunkGenerating(x, z);
|
||||
if (future.size() > 256) {
|
||||
waitForChunksPartial(256);
|
||||
}
|
||||
future.add(burst.complete(() -> completeChunk(x, z, listener)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mantle getMantle() {
|
||||
if(IrisToolbelt.isIrisWorld(world)) {
|
||||
if (IrisToolbelt.isIrisWorld(world)) {
|
||||
return IrisToolbelt.access(world).getEngine().getMantle().getMantle();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public World getWorld() {
|
||||
return world;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -21,6 +21,7 @@ package com.volmit.iris.core.pregenerator.methods;
|
||||
import com.volmit.iris.core.pregenerator.PregenListener;
|
||||
import com.volmit.iris.core.pregenerator.PregeneratorMethod;
|
||||
import com.volmit.iris.util.mantle.Mantle;
|
||||
import org.bukkit.World;
|
||||
|
||||
public class DummyPregenMethod implements PregeneratorMethod {
|
||||
@Override
|
||||
@@ -62,4 +63,9 @@ public class DummyPregenMethod implements PregeneratorMethod {
|
||||
public Mantle getMantle() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public World getWorld() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.pregenerator.methods;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.nms.IHeadless;
|
||||
import com.volmit.iris.core.nms.INMS;
|
||||
import com.volmit.iris.core.pregenerator.PregenListener;
|
||||
import com.volmit.iris.core.pregenerator.PregeneratorMethod;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.util.mantle.Mantle;
|
||||
import com.volmit.iris.util.parallel.MultiBurst;
|
||||
import org.bukkit.World;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.Semaphore;
|
||||
|
||||
public class HeadlessPregenMethod implements PregeneratorMethod {
|
||||
private final Engine engine;
|
||||
private final IHeadless headless;
|
||||
private final Semaphore semaphore;
|
||||
private final int max;
|
||||
private final World world;
|
||||
private final MultiBurst burst;
|
||||
|
||||
public HeadlessPregenMethod(Engine engine) {
|
||||
this.world = engine.getWorld().realWorld();
|
||||
this.max = IrisSettings.getThreadCount(IrisSettings.get().getConcurrency().getParallelism());
|
||||
this.engine = engine;
|
||||
this.headless = INMS.get().createHeadless(engine);
|
||||
burst = new MultiBurst("HeadlessPregen", 8 );
|
||||
this.semaphore = new Semaphore(max);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
try {
|
||||
semaphore.acquire(max);
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
try {
|
||||
headless.close();
|
||||
} catch (IOException e) {
|
||||
Iris.error("Failed to close headless");
|
||||
e.printStackTrace();
|
||||
}
|
||||
burst.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsRegions(int x, int z, PregenListener listener) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMethod(int x, int z) {
|
||||
return "Headless";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateRegion(int x, int z, PregenListener listener) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateChunk(int x, int z, PregenListener listener) {
|
||||
try {
|
||||
semaphore.acquire();
|
||||
} catch (InterruptedException ignored) {
|
||||
semaphore.release();
|
||||
return;
|
||||
}
|
||||
burst.complete(() -> {
|
||||
try {
|
||||
listener.onChunkGenerating(x, z);
|
||||
headless.generateChunk(x, z);
|
||||
listener.onChunkGenerated(x, z);
|
||||
} finally {
|
||||
semaphore.release();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mantle getMantle() {
|
||||
return engine.getMantle().getMantle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public World getWorld() {
|
||||
return world;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -18,17 +18,11 @@
|
||||
|
||||
package com.volmit.iris.core.pregenerator.methods;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.pregenerator.PregenListener;
|
||||
import com.volmit.iris.core.pregenerator.PregeneratorMethod;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.util.mantle.Mantle;
|
||||
import com.volmit.iris.util.math.Position2;
|
||||
import org.bukkit.World;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class HybridPregenMethod implements PregeneratorMethod {
|
||||
private final PregeneratorMethod inWorld;
|
||||
private final World world;
|
||||
@@ -60,7 +54,7 @@ public class HybridPregenMethod implements PregeneratorMethod {
|
||||
|
||||
@Override
|
||||
public boolean supportsRegions(int x, int z, PregenListener listener) {
|
||||
return inWorld.supportsRegions(x, z, listener);
|
||||
return inWorld.supportsRegions(x, z, listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -77,4 +71,9 @@ public class HybridPregenMethod implements PregeneratorMethod {
|
||||
public Mantle getMantle() {
|
||||
return inWorld.getMantle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public World getWorld() {
|
||||
return world;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -18,32 +18,39 @@
|
||||
|
||||
package com.volmit.iris.core.pregenerator.methods;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.pregenerator.PregenListener;
|
||||
import com.volmit.iris.core.pregenerator.PregeneratorMethod;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.mantle.Mantle;
|
||||
import com.volmit.iris.util.math.M;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.World;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class MedievalPregenMethod implements PregeneratorMethod {
|
||||
private final World world;
|
||||
private final KList<CompletableFuture<?>> futures;
|
||||
private final Map<Chunk, Long> lastUse;
|
||||
|
||||
public MedievalPregenMethod(World world) {
|
||||
this.world = world;
|
||||
futures = new KList<>();
|
||||
this.lastUse = new KMap<>();
|
||||
}
|
||||
|
||||
private void waitForChunks() {
|
||||
for(CompletableFuture<?> i : futures) {
|
||||
for (CompletableFuture<?> i : futures) {
|
||||
try {
|
||||
i.get();
|
||||
} catch(Throwable e) {
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
@@ -52,15 +59,23 @@ public class MedievalPregenMethod implements PregeneratorMethod {
|
||||
}
|
||||
|
||||
private void unloadAndSaveAllChunks() {
|
||||
waitForChunks();
|
||||
try {
|
||||
J.sfut(() -> {
|
||||
for(Chunk i : world.getLoadedChunks()) {
|
||||
i.unload(true);
|
||||
if (world == null) {
|
||||
Iris.warn("World was null somehow...");
|
||||
return;
|
||||
}
|
||||
|
||||
for (Chunk i : new ArrayList<>(lastUse.keySet())) {
|
||||
Long lastUseTime = lastUse.get(i);
|
||||
if (lastUseTime != null && M.ms() - lastUseTime >= 10) {
|
||||
i.unload();
|
||||
lastUse.remove(i);
|
||||
}
|
||||
}
|
||||
world.save();
|
||||
}).get();
|
||||
} catch(Throwable e) {
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
@@ -97,13 +112,14 @@ public class MedievalPregenMethod implements PregeneratorMethod {
|
||||
|
||||
@Override
|
||||
public void generateChunk(int x, int z, PregenListener listener) {
|
||||
if(futures.size() > IrisSettings.getThreadCount(IrisSettings.get().getConcurrency().getParallelism())) {
|
||||
if (futures.size() > IrisSettings.getThreadCount(IrisSettings.get().getConcurrency().getParallelism())) {
|
||||
waitForChunks();
|
||||
}
|
||||
|
||||
listener.onChunkGenerating(x, z);
|
||||
futures.add(J.sfut(() -> {
|
||||
world.getChunkAt(x, z);
|
||||
Chunk c = world.getChunkAt(x, z);
|
||||
lastUse.put(c, M.ms());
|
||||
listener.onChunkGenerated(x, z);
|
||||
listener.onChunkCleaned(x, z);
|
||||
}));
|
||||
@@ -111,10 +127,15 @@ public class MedievalPregenMethod implements PregeneratorMethod {
|
||||
|
||||
@Override
|
||||
public Mantle getMantle() {
|
||||
if(IrisToolbelt.isIrisWorld(world)) {
|
||||
if (IrisToolbelt.isIrisWorld(world)) {
|
||||
return IrisToolbelt.access(world).getEngine().getMantle().getMantle();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public World getWorld() {
|
||||
return world;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -25,16 +25,7 @@ import com.volmit.iris.core.loader.IrisData;
|
||||
import com.volmit.iris.core.loader.IrisRegistrant;
|
||||
import com.volmit.iris.core.loader.ResourceLoader;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.engine.object.IrisBiome;
|
||||
import com.volmit.iris.engine.object.IrisBlockData;
|
||||
import com.volmit.iris.engine.object.IrisDimension;
|
||||
import com.volmit.iris.engine.object.IrisEntity;
|
||||
import com.volmit.iris.engine.object.IrisGenerator;
|
||||
import com.volmit.iris.engine.object.IrisLootTable;
|
||||
import com.volmit.iris.engine.object.IrisObject;
|
||||
import com.volmit.iris.engine.object.IrisObjectPlacement;
|
||||
import com.volmit.iris.engine.object.IrisRegion;
|
||||
import com.volmit.iris.engine.object.IrisSpawner;
|
||||
import com.volmit.iris.engine.object.*;
|
||||
import com.volmit.iris.engine.object.annotations.Snippet;
|
||||
import com.volmit.iris.engine.platform.PlatformChunkGenerator;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
@@ -60,8 +51,7 @@ import org.bukkit.GameMode;
|
||||
import org.bukkit.World;
|
||||
import org.zeroturnaround.zip.ZipUtil;
|
||||
|
||||
import java.awt.Desktop;
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import java.awt.*;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
@@ -82,14 +72,14 @@ public class IrisProject {
|
||||
|
||||
public static int clean(VolmitSender s, File clean) {
|
||||
int c = 0;
|
||||
if(clean.isDirectory()) {
|
||||
for(File i : clean.listFiles()) {
|
||||
if (clean.isDirectory()) {
|
||||
for (File i : clean.listFiles()) {
|
||||
c += clean(s, i);
|
||||
}
|
||||
} else if(clean.getName().endsWith(".json")) {
|
||||
} else if (clean.getName().endsWith(".json")) {
|
||||
try {
|
||||
clean(clean);
|
||||
} catch(Throwable e) {
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
Iris.error("Failed to beautify " + clean.getAbsolutePath() + " You may have errors in your json!");
|
||||
}
|
||||
@@ -108,29 +98,29 @@ public class IrisProject {
|
||||
}
|
||||
|
||||
public static void fixBlocks(JSONObject obj, File f) {
|
||||
for(String i : obj.keySet()) {
|
||||
for (String i : obj.keySet()) {
|
||||
Object o = obj.get(i);
|
||||
|
||||
if(i.equals("block") && o instanceof String && !o.toString().trim().isEmpty() && !o.toString().contains(":")) {
|
||||
if (i.equals("block") && o instanceof String && !o.toString().trim().isEmpty() && !o.toString().contains(":")) {
|
||||
obj.put(i, "minecraft:" + o);
|
||||
Iris.debug("Updated Block Key: " + o + " to " + obj.getString(i) + " in " + f.getPath());
|
||||
}
|
||||
|
||||
if(o instanceof JSONObject) {
|
||||
if (o instanceof JSONObject) {
|
||||
fixBlocks((JSONObject) o, f);
|
||||
} else if(o instanceof JSONArray) {
|
||||
} else if (o instanceof JSONArray) {
|
||||
fixBlocks((JSONArray) o, f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void fixBlocks(JSONArray obj, File f) {
|
||||
for(int i = 0; i < obj.length(); i++) {
|
||||
for (int i = 0; i < obj.length(); i++) {
|
||||
Object o = obj.get(i);
|
||||
|
||||
if(o instanceof JSONObject) {
|
||||
if (o instanceof JSONObject) {
|
||||
fixBlocks((JSONObject) o, f);
|
||||
} else if(o instanceof JSONArray) {
|
||||
} else if (o instanceof JSONArray) {
|
||||
fixBlocks((JSONArray) o, f);
|
||||
}
|
||||
}
|
||||
@@ -143,11 +133,11 @@ public class IrisProject {
|
||||
public KList<File> collectFiles(File f, String fileExtension) {
|
||||
KList<File> l = new KList<>();
|
||||
|
||||
if(f.isDirectory()) {
|
||||
for(File i : f.listFiles()) {
|
||||
if (f.isDirectory()) {
|
||||
for (File i : f.listFiles()) {
|
||||
l.addAll(collectFiles(i, fileExtension));
|
||||
}
|
||||
} else if(f.getName().endsWith("." + fileExtension)) {
|
||||
} else if (f.getName().endsWith("." + fileExtension)) {
|
||||
l.add(f);
|
||||
}
|
||||
|
||||
@@ -170,28 +160,28 @@ public class IrisProject {
|
||||
J.attemptAsync(() ->
|
||||
{
|
||||
try {
|
||||
if(d.getLoader() == null) {
|
||||
if (d.getLoader() == null) {
|
||||
sender.sendMessage("Could not get dimension loader");
|
||||
return;
|
||||
}
|
||||
File f = d.getLoader().getDataFolder();
|
||||
|
||||
if(!doOpenVSCode(f)) {
|
||||
if (!doOpenVSCode(f)) {
|
||||
File ff = new File(d.getLoader().getDataFolder(), d.getLoadKey() + ".code-workspace");
|
||||
Iris.warn("Project missing code-workspace: " + ff.getAbsolutePath() + " Re-creating code workspace.");
|
||||
|
||||
try {
|
||||
IO.writeAll(ff, createCodeWorkspaceConfig());
|
||||
} catch(IOException e1) {
|
||||
} catch (IOException e1) {
|
||||
Iris.reportError(e1);
|
||||
e1.printStackTrace();
|
||||
}
|
||||
updateWorkspace();
|
||||
if(!doOpenVSCode(f)) {
|
||||
if (!doOpenVSCode(f)) {
|
||||
Iris.warn("Tried creating code workspace but failed a second time. Your project is likely corrupt.");
|
||||
}
|
||||
}
|
||||
} catch(Throwable e) {
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
@@ -200,16 +190,16 @@ public class IrisProject {
|
||||
|
||||
private boolean doOpenVSCode(File f) throws IOException {
|
||||
boolean foundWork = false;
|
||||
for(File i : Objects.requireNonNull(f.listFiles())) {
|
||||
if(i.getName().endsWith(".code-workspace")) {
|
||||
for (File i : Objects.requireNonNull(f.listFiles())) {
|
||||
if (i.getName().endsWith(".code-workspace")) {
|
||||
foundWork = true;
|
||||
J.a(() ->
|
||||
{
|
||||
updateWorkspace();
|
||||
});
|
||||
|
||||
if(IrisSettings.get().getStudio().isOpenVSCode()) {
|
||||
if(!GraphicsEnvironment.isHeadless()) {
|
||||
if (IrisSettings.get().getStudio().isOpenVSCode()) {
|
||||
if (!GraphicsEnvironment.isHeadless()) {
|
||||
Iris.msg("Opening VSCode. You may see the output from VSCode.");
|
||||
Iris.msg("VSCode output always starts with: '(node:#####) electron'");
|
||||
Desktop.getDesktop().open(i);
|
||||
@@ -223,21 +213,21 @@ public class IrisProject {
|
||||
}
|
||||
|
||||
public void open(VolmitSender sender, long seed, Consumer<World> onDone) throws IrisException {
|
||||
if(isOpen()) {
|
||||
if (isOpen()) {
|
||||
close();
|
||||
}
|
||||
|
||||
boolean hasError = false;
|
||||
|
||||
if(hasError) {
|
||||
if (hasError) {
|
||||
return;
|
||||
}
|
||||
|
||||
IrisDimension d = IrisData.loadAnyDimension(getName());
|
||||
if(d == null) {
|
||||
if (d == null) {
|
||||
sender.sendMessage("Can't find dimension: " + getName());
|
||||
return;
|
||||
} else if(sender.isPlayer()) {
|
||||
} else if (sender.isPlayer()) {
|
||||
sender.player().setGameMode(GameMode.SPECTATOR);
|
||||
}
|
||||
|
||||
@@ -247,14 +237,14 @@ public class IrisProject {
|
||||
J.a(() -> {
|
||||
try {
|
||||
activeProvider = (PlatformChunkGenerator) IrisToolbelt.createWorld()
|
||||
.seed(seed)
|
||||
.sender(sender)
|
||||
.studio(true)
|
||||
.name("iris/" + UUID.randomUUID())
|
||||
.dimension(d.getLoadKey())
|
||||
.create().getGenerator();
|
||||
.seed(seed)
|
||||
.sender(sender)
|
||||
.studio(true)
|
||||
.name("iris/" + UUID.randomUUID())
|
||||
.dimension(d.getLoadKey())
|
||||
.create().getGenerator();
|
||||
onDone.accept(activeProvider.getTarget().getWorld().realWorld());
|
||||
} catch(IrisException e) {
|
||||
} catch (IrisException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
@@ -286,13 +276,13 @@ public class IrisProject {
|
||||
IO.writeAll(ws, j.toString(4));
|
||||
p.end();
|
||||
return true;
|
||||
} catch(Throwable e) {
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
Iris.warn("Project invalid: " + ws.getAbsolutePath() + " Re-creating. You may loose some vs-code workspace settings! But not your actual project!");
|
||||
ws.delete();
|
||||
try {
|
||||
IO.writeAll(ws, createCodeWorkspaceConfig());
|
||||
} catch(IOException e1) {
|
||||
} catch (IOException e1) {
|
||||
Iris.reportError(e1);
|
||||
e1.printStackTrace();
|
||||
}
|
||||
@@ -334,19 +324,19 @@ public class IrisProject {
|
||||
JSONArray schemas = new JSONArray();
|
||||
IrisData dm = IrisData.get(getPath());
|
||||
|
||||
for(ResourceLoader<?> r : dm.getLoaders().v()) {
|
||||
if(r.supportsSchemas()) {
|
||||
for (ResourceLoader<?> r : dm.getLoaders().v()) {
|
||||
if (r.supportsSchemas()) {
|
||||
schemas.put(r.buildSchema());
|
||||
}
|
||||
}
|
||||
|
||||
for(Class<?> i : Iris.getClasses("com.volmit.iris.engine.object.", Snippet.class)) {
|
||||
for (Class<?> i : Iris.getClasses("com.volmit.iris.engine.object.", Snippet.class)) {
|
||||
try {
|
||||
String snipType = i.getDeclaredAnnotation(Snippet.class).value();
|
||||
JSONObject o = new JSONObject();
|
||||
KList<String> fm = new KList<>();
|
||||
|
||||
for(int g = 1; g < 8; g++) {
|
||||
for (int g = 1; g < 8; g++) {
|
||||
fm.add("/snippet/" + snipType + Form.repeat("/*", g) + ".json");
|
||||
}
|
||||
|
||||
@@ -357,11 +347,11 @@ public class IrisProject {
|
||||
J.attemptAsync(() -> {
|
||||
try {
|
||||
IO.writeAll(a, new SchemaBuilder(i, dm).construct().toString(4));
|
||||
} catch(Throwable e) {
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
} catch(Throwable e) {
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
@@ -387,7 +377,7 @@ public class IrisProject {
|
||||
KSet<IrisLootTable> loot = new KSet<>();
|
||||
KSet<IrisBlockData> blocks = new KSet<>();
|
||||
|
||||
for(String i : dm.getDimensionLoader().getPossibleKeys()) {
|
||||
for (String i : dm.getDimensionLoader().getPossibleKeys()) {
|
||||
blocks.add(dm.getBlockLoader().load(i));
|
||||
}
|
||||
|
||||
@@ -407,13 +397,13 @@ public class IrisProject {
|
||||
StringBuilder c = new StringBuilder();
|
||||
sender.sendMessage("Serializing Objects");
|
||||
|
||||
for(IrisBiome i : biomes) {
|
||||
for(IrisObjectPlacement j : i.getObjects()) {
|
||||
for (IrisBiome i : biomes) {
|
||||
for (IrisObjectPlacement j : i.getObjects()) {
|
||||
b.append(j.hashCode());
|
||||
KList<String> newNames = new KList<>();
|
||||
|
||||
for(String k : j.getPlace()) {
|
||||
if(renameObjects.containsKey(k)) {
|
||||
for (String k : j.getPlace()) {
|
||||
if (renameObjects.containsKey(k)) {
|
||||
newNames.add(renameObjects.get(k));
|
||||
continue;
|
||||
}
|
||||
@@ -441,12 +431,12 @@ public class IrisProject {
|
||||
gb.append(IO.hash(f));
|
||||
ggg.set(ggg.get() + 1);
|
||||
|
||||
if(cl.flip()) {
|
||||
if (cl.flip()) {
|
||||
int g = ggg.get();
|
||||
ggg.set(0);
|
||||
sender.sendMessage("Wrote another " + g + " Objects");
|
||||
}
|
||||
} catch(Throwable e) {
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
}
|
||||
})));
|
||||
@@ -462,7 +452,7 @@ public class IrisProject {
|
||||
IO.writeAll(new File(folder, "dimensions/" + dimension.getLoadKey() + ".json"), a);
|
||||
b.append(IO.hash(a));
|
||||
|
||||
for(IrisGenerator i : generators) {
|
||||
for (IrisGenerator i : generators) {
|
||||
a = new JSONObject(new Gson().toJson(i)).toString(minify ? 0 : 4);
|
||||
IO.writeAll(new File(folder, "generators/" + i.getLoadKey() + ".json"), a);
|
||||
b.append(IO.hash(a));
|
||||
@@ -471,31 +461,31 @@ public class IrisProject {
|
||||
c.append(IO.hash(b.toString()));
|
||||
b = new StringBuilder();
|
||||
|
||||
for(IrisRegion i : regions) {
|
||||
for (IrisRegion i : regions) {
|
||||
a = new JSONObject(new Gson().toJson(i)).toString(minify ? 0 : 4);
|
||||
IO.writeAll(new File(folder, "regions/" + i.getLoadKey() + ".json"), a);
|
||||
b.append(IO.hash(a));
|
||||
}
|
||||
|
||||
for(IrisBlockData i : blocks) {
|
||||
for (IrisBlockData i : blocks) {
|
||||
a = new JSONObject(new Gson().toJson(i)).toString(minify ? 0 : 4);
|
||||
IO.writeAll(new File(folder, "blocks/" + i.getLoadKey() + ".json"), a);
|
||||
b.append(IO.hash(a));
|
||||
}
|
||||
|
||||
for(IrisBiome i : biomes) {
|
||||
for (IrisBiome i : biomes) {
|
||||
a = new JSONObject(new Gson().toJson(i)).toString(minify ? 0 : 4);
|
||||
IO.writeAll(new File(folder, "biomes/" + i.getLoadKey() + ".json"), a);
|
||||
b.append(IO.hash(a));
|
||||
}
|
||||
|
||||
for(IrisEntity i : entities) {
|
||||
for (IrisEntity i : entities) {
|
||||
a = new JSONObject(new Gson().toJson(i)).toString(minify ? 0 : 4);
|
||||
IO.writeAll(new File(folder, "entities/" + i.getLoadKey() + ".json"), a);
|
||||
b.append(IO.hash(a));
|
||||
}
|
||||
|
||||
for(IrisLootTable i : loot) {
|
||||
for (IrisLootTable i : loot) {
|
||||
a = new JSONObject(new Gson().toJson(i)).toString(minify ? 0 : 4);
|
||||
IO.writeAll(new File(folder, "loot/" + i.getLoadKey() + ".json"), a);
|
||||
b.append(IO.hash(a));
|
||||
@@ -515,7 +505,7 @@ public class IrisProject {
|
||||
|
||||
sender.sendMessage("Package Compiled!");
|
||||
return p;
|
||||
} catch(Throwable e) {
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
@@ -538,18 +528,18 @@ public class IrisProject {
|
||||
IrisObject o = new IrisObject(0, 0, 0);
|
||||
o.read(f);
|
||||
|
||||
if(o.getBlocks().isEmpty()) {
|
||||
if (o.getBlocks().isEmpty()) {
|
||||
sender.sendMessageRaw("<hover:show_text:'Error:\n" +
|
||||
"<yellow>" + f.getPath() +
|
||||
"'><red>- IOB " + f.getName() + " has 0 blocks!");
|
||||
"<yellow>" + f.getPath() +
|
||||
"'><red>- IOB " + f.getName() + " has 0 blocks!");
|
||||
}
|
||||
|
||||
if(o.getW() == 0 || o.getH() == 0 || o.getD() == 0) {
|
||||
if (o.getW() == 0 || o.getH() == 0 || o.getD() == 0) {
|
||||
sender.sendMessageRaw("<hover:show_text:'Error:\n" +
|
||||
"<yellow>" + f.getPath() + "\n<red>The width height or depth has a zero in it (bad format)" +
|
||||
"'><red>- IOB " + f.getName() + " is not 3D!");
|
||||
"<yellow>" + f.getPath() + "\n<red>The width height or depth has a zero in it (bad format)" +
|
||||
"'><red>- IOB " + f.getName() + " is not 3D!");
|
||||
}
|
||||
} catch(IOException e) {
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
@@ -569,11 +559,11 @@ public class IrisProject {
|
||||
scanForErrors(data, f, p, sender);
|
||||
IO.writeAll(f, p.toString(4));
|
||||
|
||||
} catch(Throwable e) {
|
||||
} catch (Throwable e) {
|
||||
sender.sendMessageRaw("<hover:show_text:'Error:\n" +
|
||||
"<yellow>" + f.getPath() +
|
||||
"\n<red>" + e.getMessage() +
|
||||
"'><red>- JSON Error " + f.getName());
|
||||
"<yellow>" + f.getPath() +
|
||||
"\n<red>" + e.getMessage() +
|
||||
"'><red>- JSON Error " + f.getName());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -590,7 +580,7 @@ public class IrisProject {
|
||||
String key = data.toLoadKey(f);
|
||||
ResourceLoader<?> loader = data.getTypedLoaderFor(f);
|
||||
|
||||
if(loader == null) {
|
||||
if (loader == null) {
|
||||
sender.sendMessageBasic("Can't find loader for " + f.getPath());
|
||||
return;
|
||||
}
|
||||
@@ -603,62 +593,62 @@ public class IrisProject {
|
||||
public void compare(Class<?> c, JSONObject j, VolmitSender sender, KList<String> path) {
|
||||
try {
|
||||
Object o = c.getClass().getConstructor().newInstance();
|
||||
} catch(Throwable e) {
|
||||
} catch (Throwable e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void files(File clean, KList<File> files) {
|
||||
if(clean.isDirectory()) {
|
||||
for(File i : clean.listFiles()) {
|
||||
if (clean.isDirectory()) {
|
||||
for (File i : clean.listFiles()) {
|
||||
files(i, files);
|
||||
}
|
||||
} else if(clean.getName().endsWith(".json")) {
|
||||
} else if (clean.getName().endsWith(".json")) {
|
||||
try {
|
||||
files.add(clean);
|
||||
} catch(Throwable e) {
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void filesObjects(File clean, KList<File> files) {
|
||||
if(clean.isDirectory()) {
|
||||
for(File i : clean.listFiles()) {
|
||||
if (clean.isDirectory()) {
|
||||
for (File i : clean.listFiles()) {
|
||||
filesObjects(i, files);
|
||||
}
|
||||
} else if(clean.getName().endsWith(".iob")) {
|
||||
} else if (clean.getName().endsWith(".iob")) {
|
||||
try {
|
||||
files.add(clean);
|
||||
} catch(Throwable e) {
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void fixBlocks(JSONObject obj) {
|
||||
for(String i : obj.keySet()) {
|
||||
for (String i : obj.keySet()) {
|
||||
Object o = obj.get(i);
|
||||
|
||||
if(i.equals("block") && o instanceof String && !o.toString().trim().isEmpty() && !o.toString().contains(":")) {
|
||||
if (i.equals("block") && o instanceof String && !o.toString().trim().isEmpty() && !o.toString().contains(":")) {
|
||||
obj.put(i, "minecraft:" + o);
|
||||
}
|
||||
|
||||
if(o instanceof JSONObject) {
|
||||
if (o instanceof JSONObject) {
|
||||
fixBlocks((JSONObject) o);
|
||||
} else if(o instanceof JSONArray) {
|
||||
} else if (o instanceof JSONArray) {
|
||||
fixBlocks((JSONArray) o);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void fixBlocks(JSONArray obj) {
|
||||
for(int i = 0; i < obj.length(); i++) {
|
||||
for (int i = 0; i < obj.length(); i++) {
|
||||
Object o = obj.get(i);
|
||||
|
||||
if(o instanceof JSONObject) {
|
||||
if (o instanceof JSONObject) {
|
||||
fixBlocks((JSONObject) o);
|
||||
} else if(o instanceof JSONArray) {
|
||||
} else if (o instanceof JSONArray) {
|
||||
fixBlocks((JSONArray) o);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -22,17 +22,8 @@ import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.loader.IrisData;
|
||||
import com.volmit.iris.core.loader.IrisRegistrant;
|
||||
import com.volmit.iris.core.loader.ResourceLoader;
|
||||
import com.volmit.iris.engine.object.annotations.ArrayType;
|
||||
import com.volmit.iris.engine.object.annotations.Desc;
|
||||
import com.volmit.iris.engine.object.annotations.MaxNumber;
|
||||
import com.volmit.iris.engine.object.annotations.MinNumber;
|
||||
import com.volmit.iris.engine.object.annotations.RegistryListBlockType;
|
||||
import com.volmit.iris.engine.object.annotations.RegistryListFont;
|
||||
import com.volmit.iris.engine.object.annotations.RegistryListItemType;
|
||||
import com.volmit.iris.engine.object.annotations.RegistryListResource;
|
||||
import com.volmit.iris.engine.object.annotations.RegistryListSpecialEntity;
|
||||
import com.volmit.iris.engine.object.annotations.Required;
|
||||
import com.volmit.iris.engine.object.annotations.Snippet;
|
||||
import com.volmit.iris.engine.framework.ListFunction;
|
||||
import com.volmit.iris.engine.object.annotations.*;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.data.B;
|
||||
@@ -41,7 +32,7 @@ import com.volmit.iris.util.json.JSONObject;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import java.awt.*;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.List;
|
||||
@@ -52,7 +43,7 @@ public class SchemaBuilder {
|
||||
private static final String SYMBOL_LIMIT__N = "*";
|
||||
private static final String SYMBOL_TYPE__N = "";
|
||||
private static final JSONArray POTION_TYPES = getPotionTypes();
|
||||
private static final JSONArray ENCHANT_TYPES = getEnchantmentTypes();
|
||||
private static final JSONArray ENCHANT_TYPES = getEnchantTypes();
|
||||
private static final JSONArray ITEM_TYPES = new JSONArray(B.getItemTypes());
|
||||
private static final JSONArray FONT_TYPES = new JSONArray(GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames());
|
||||
private final KMap<String, JSONObject> definitions;
|
||||
@@ -67,24 +58,22 @@ public class SchemaBuilder {
|
||||
this.root = root;
|
||||
}
|
||||
|
||||
private static JSONArray getEnchantmentTypes() {
|
||||
private static JSONArray getPotionTypes() {
|
||||
JSONArray a = new JSONArray();
|
||||
|
||||
for(Field gg : Enchantment.class.getDeclaredFields()) {
|
||||
a.put(gg.getName());
|
||||
for (PotionEffectType gg : PotionEffectType.values()) {
|
||||
a.put(gg.getName().toUpperCase().replaceAll("\\Q \\E", "_"));
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
private static JSONArray getPotionTypes() {
|
||||
JSONArray a = new JSONArray();
|
||||
|
||||
for(PotionEffectType gg : PotionEffectType.values()) {
|
||||
a.put(gg.getName().toUpperCase().replaceAll("\\Q \\E", "_"));
|
||||
private static JSONArray getEnchantTypes() {
|
||||
JSONArray array = new JSONArray();
|
||||
for (Enchantment e : Enchantment.values()) {
|
||||
array.put(e.getKey().getKey());
|
||||
}
|
||||
|
||||
return a;
|
||||
return array;
|
||||
}
|
||||
|
||||
public JSONObject construct() {
|
||||
@@ -94,21 +83,21 @@ public class SchemaBuilder {
|
||||
|
||||
JSONObject props = buildProperties(root);
|
||||
|
||||
for(String i : props.keySet()) {
|
||||
if(!schema.has(i)) {
|
||||
for (String i : props.keySet()) {
|
||||
if (!schema.has(i)) {
|
||||
schema.put(i, props.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
JSONObject defs = new JSONObject();
|
||||
|
||||
for(Map.Entry<String, JSONObject> entry : definitions.entrySet()) {
|
||||
for (Map.Entry<String, JSONObject> entry : definitions.entrySet()) {
|
||||
defs.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
schema.put("definitions", defs);
|
||||
|
||||
for(String i : warnings) {
|
||||
for (String i : warnings) {
|
||||
Iris.warn(root.getSimpleName() + ": " + i);
|
||||
}
|
||||
|
||||
@@ -122,17 +111,17 @@ public class SchemaBuilder {
|
||||
o.put("type", getType(c));
|
||||
JSONArray required = new JSONArray();
|
||||
|
||||
if(c.isAssignableFrom(IrisRegistrant.class) || IrisRegistrant.class.isAssignableFrom(c)) {
|
||||
for(Field k : IrisRegistrant.class.getDeclaredFields()) {
|
||||
if (c.isAssignableFrom(IrisRegistrant.class) || IrisRegistrant.class.isAssignableFrom(c)) {
|
||||
for (Field k : IrisRegistrant.class.getDeclaredFields()) {
|
||||
k.setAccessible(true);
|
||||
|
||||
if(Modifier.isStatic(k.getModifiers()) || Modifier.isFinal(k.getModifiers()) || Modifier.isTransient(k.getModifiers())) {
|
||||
if (Modifier.isStatic(k.getModifiers()) || Modifier.isFinal(k.getModifiers()) || Modifier.isTransient(k.getModifiers())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
JSONObject property = buildProperty(k, c);
|
||||
|
||||
if(property.getBoolean("!required")) {
|
||||
if (property.getBoolean("!required")) {
|
||||
required.put(k.getName());
|
||||
}
|
||||
|
||||
@@ -141,10 +130,10 @@ public class SchemaBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
for(Field k : c.getDeclaredFields()) {
|
||||
for (Field k : c.getDeclaredFields()) {
|
||||
k.setAccessible(true);
|
||||
|
||||
if(Modifier.isStatic(k.getModifiers()) || Modifier.isFinal(k.getModifiers()) || Modifier.isTransient(k.getModifiers())) {
|
||||
if (Modifier.isStatic(k.getModifiers()) || Modifier.isFinal(k.getModifiers()) || Modifier.isTransient(k.getModifiers())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -154,14 +143,14 @@ public class SchemaBuilder {
|
||||
properties.put(k.getName(), property);
|
||||
}
|
||||
|
||||
if(required.length() > 0) {
|
||||
if (required.length() > 0) {
|
||||
o.put("required", required);
|
||||
}
|
||||
|
||||
o.put("properties", properties);
|
||||
|
||||
|
||||
if(c.isAnnotationPresent(Snippet.class)) {
|
||||
if (c.isAnnotationPresent(Snippet.class)) {
|
||||
JSONObject anyOf = new JSONObject();
|
||||
JSONArray arr = new JSONArray();
|
||||
JSONObject str = new JSONObject();
|
||||
@@ -184,16 +173,16 @@ public class SchemaBuilder {
|
||||
prop.put("type", type);
|
||||
String fancyType = "Unknown Type";
|
||||
|
||||
switch(type) {
|
||||
switch (type) {
|
||||
case "boolean" -> fancyType = "Boolean";
|
||||
case "integer" -> {
|
||||
fancyType = "Integer";
|
||||
if(k.isAnnotationPresent(MinNumber.class)) {
|
||||
if (k.isAnnotationPresent(MinNumber.class)) {
|
||||
int min = (int) k.getDeclaredAnnotation(MinNumber.class).value();
|
||||
prop.put("minimum", min);
|
||||
description.add(SYMBOL_LIMIT__N + " Minimum allowed is " + min);
|
||||
}
|
||||
if(k.isAnnotationPresent(MaxNumber.class)) {
|
||||
if (k.isAnnotationPresent(MaxNumber.class)) {
|
||||
int max = (int) k.getDeclaredAnnotation(MaxNumber.class).value();
|
||||
prop.put("maximum", max);
|
||||
description.add(SYMBOL_LIMIT__N + " Maximum allowed is " + max);
|
||||
@@ -201,12 +190,12 @@ public class SchemaBuilder {
|
||||
}
|
||||
case "number" -> {
|
||||
fancyType = "Number";
|
||||
if(k.isAnnotationPresent(MinNumber.class)) {
|
||||
if (k.isAnnotationPresent(MinNumber.class)) {
|
||||
double min = k.getDeclaredAnnotation(MinNumber.class).value();
|
||||
prop.put("minimum", min);
|
||||
description.add(SYMBOL_LIMIT__N + " Minimum allowed is " + min);
|
||||
}
|
||||
if(k.isAnnotationPresent(MaxNumber.class)) {
|
||||
if (k.isAnnotationPresent(MaxNumber.class)) {
|
||||
double max = k.getDeclaredAnnotation(MaxNumber.class).value();
|
||||
prop.put("maximum", max);
|
||||
description.add(SYMBOL_LIMIT__N + " Maximum allowed is " + max);
|
||||
@@ -214,26 +203,26 @@ public class SchemaBuilder {
|
||||
}
|
||||
case "string" -> {
|
||||
fancyType = "Text";
|
||||
if(k.isAnnotationPresent(MinNumber.class)) {
|
||||
if (k.isAnnotationPresent(MinNumber.class)) {
|
||||
int min = (int) k.getDeclaredAnnotation(MinNumber.class).value();
|
||||
prop.put("minLength", min);
|
||||
description.add(SYMBOL_LIMIT__N + " Minimum Length allowed is " + min);
|
||||
}
|
||||
if(k.isAnnotationPresent(MaxNumber.class)) {
|
||||
if (k.isAnnotationPresent(MaxNumber.class)) {
|
||||
int max = (int) k.getDeclaredAnnotation(MaxNumber.class).value();
|
||||
prop.put("maxLength", max);
|
||||
description.add(SYMBOL_LIMIT__N + " Maximum Length allowed is " + max);
|
||||
}
|
||||
|
||||
|
||||
if(k.isAnnotationPresent(RegistryListResource.class)) {
|
||||
if (k.isAnnotationPresent(RegistryListResource.class)) {
|
||||
RegistryListResource rr = k.getDeclaredAnnotation(RegistryListResource.class);
|
||||
ResourceLoader<?> loader = data.getLoaders().get(rr.value());
|
||||
|
||||
if(loader != null) {
|
||||
if (loader != null) {
|
||||
String key = "erz" + loader.getFolderName();
|
||||
|
||||
if(!definitions.containsKey(key)) {
|
||||
if (!definitions.containsKey(key)) {
|
||||
JSONObject j = new JSONObject();
|
||||
j.put("enum", new JSONArray(loader.getPossibleKeys()));
|
||||
definitions.put(key, j);
|
||||
@@ -245,18 +234,18 @@ public class SchemaBuilder {
|
||||
} else {
|
||||
Iris.error("Cannot find Registry Loader for type " + rr.value() + " used in " + k.getDeclaringClass().getCanonicalName() + " in field " + k.getName());
|
||||
}
|
||||
} else if(k.isAnnotationPresent(RegistryListBlockType.class)) {
|
||||
} else if (k.isAnnotationPresent(RegistryListBlockType.class)) {
|
||||
String key = "enum-block-type";
|
||||
|
||||
if(!definitions.containsKey(key)) {
|
||||
if (!definitions.containsKey(key)) {
|
||||
JSONObject j = new JSONObject();
|
||||
JSONArray ja = new JSONArray();
|
||||
|
||||
for(String i : data.getBlockLoader().getPossibleKeys()) {
|
||||
for (String i : data.getBlockLoader().getPossibleKeys()) {
|
||||
ja.put(i);
|
||||
}
|
||||
|
||||
for(String i : B.getBlockTypes()) {
|
||||
for (String i : B.getBlockTypes()) {
|
||||
ja.put(i);
|
||||
}
|
||||
|
||||
@@ -268,10 +257,10 @@ public class SchemaBuilder {
|
||||
prop.put("$ref", "#/definitions/" + key);
|
||||
description.add(SYMBOL_TYPE__N + " Must be a valid Block Type (use ctrl+space for auto complete!)");
|
||||
|
||||
} else if(k.isAnnotationPresent(RegistryListItemType.class)) {
|
||||
} else if (k.isAnnotationPresent(RegistryListItemType.class)) {
|
||||
String key = "enum-item-type";
|
||||
|
||||
if(!definitions.containsKey(key)) {
|
||||
if (!definitions.containsKey(key)) {
|
||||
JSONObject j = new JSONObject();
|
||||
j.put("enum", ITEM_TYPES);
|
||||
definitions.put(key, j);
|
||||
@@ -281,10 +270,10 @@ public class SchemaBuilder {
|
||||
prop.put("$ref", "#/definitions/" + key);
|
||||
description.add(SYMBOL_TYPE__N + " Must be a valid Item Type (use ctrl+space for auto complete!)");
|
||||
|
||||
} else if(k.isAnnotationPresent(RegistryListSpecialEntity.class)) {
|
||||
} else if (k.isAnnotationPresent(RegistryListSpecialEntity.class)) {
|
||||
String key = "enum-reg-specialentity";
|
||||
|
||||
if(!definitions.containsKey(key)) {
|
||||
if (!definitions.containsKey(key)) {
|
||||
JSONObject j = new JSONObject();
|
||||
KList<String> list = new KList<>();
|
||||
list.addAll(Iris.linkMythicMobs.getMythicMobTypes().stream().map(s -> "MythicMobs:" + s).collect(Collectors.toList()));
|
||||
@@ -296,10 +285,10 @@ public class SchemaBuilder {
|
||||
fancyType = "Mythic Mob Type";
|
||||
prop.put("$ref", "#/definitions/" + key);
|
||||
description.add(SYMBOL_TYPE__N + " Must be a valid Mythic Mob Type (use ctrl+space for auto complete!) Define mythic mobs with the mythic mobs plugin configuration files.");
|
||||
} else if(k.isAnnotationPresent(RegistryListFont.class)) {
|
||||
} else if (k.isAnnotationPresent(RegistryListFont.class)) {
|
||||
String key = "enum-font";
|
||||
|
||||
if(!definitions.containsKey(key)) {
|
||||
if (!definitions.containsKey(key)) {
|
||||
JSONObject j = new JSONObject();
|
||||
j.put("enum", FONT_TYPES);
|
||||
definitions.put(key, j);
|
||||
@@ -309,10 +298,10 @@ public class SchemaBuilder {
|
||||
prop.put("$ref", "#/definitions/" + key);
|
||||
description.add(SYMBOL_TYPE__N + " Must be a valid Font Family (use ctrl+space for auto complete!)");
|
||||
|
||||
} else if(k.getType().equals(Enchantment.class)) {
|
||||
} else if (k.isAnnotationPresent(RegistryListEnchantment.class)) {
|
||||
String key = "enum-enchantment";
|
||||
|
||||
if(!definitions.containsKey(key)) {
|
||||
if (!definitions.containsKey(key)) {
|
||||
JSONObject j = new JSONObject();
|
||||
j.put("enum", ENCHANT_TYPES);
|
||||
definitions.put(key, j);
|
||||
@@ -321,10 +310,28 @@ public class SchemaBuilder {
|
||||
fancyType = "Enchantment Type";
|
||||
prop.put("$ref", "#/definitions/" + key);
|
||||
description.add(SYMBOL_TYPE__N + " Must be a valid Enchantment Type (use ctrl+space for auto complete!)");
|
||||
} else if(k.getType().equals(PotionEffectType.class)) {
|
||||
} else if (k.isAnnotationPresent(RegistryListFunction.class)) {
|
||||
var functionClass = k.getDeclaredAnnotation(RegistryListFunction.class).value();
|
||||
try {
|
||||
var instance = functionClass.getDeclaredConstructor().newInstance();
|
||||
String key = instance.key();
|
||||
fancyType = instance.fancyName();
|
||||
|
||||
if (!definitions.containsKey(key)) {
|
||||
JSONObject j = new JSONObject();
|
||||
j.put("enum", instance.apply(data));
|
||||
definitions.put(key, j);
|
||||
}
|
||||
|
||||
prop.put("$ref", "#/definitions/" + key);
|
||||
description.add(SYMBOL_TYPE__N + " Must be a valid " + fancyType + " (use ctrl+space for auto complete!)");
|
||||
} catch (Throwable e) {
|
||||
Iris.error("Could not execute apply method in " + functionClass.getName());
|
||||
}
|
||||
} else if (k.getType().equals(PotionEffectType.class)) {
|
||||
String key = "enum-potion-effect-type";
|
||||
|
||||
if(!definitions.containsKey(key)) {
|
||||
if (!definitions.containsKey(key)) {
|
||||
JSONObject j = new JSONObject();
|
||||
j.put("enum", POTION_TYPES);
|
||||
definitions.put(key, j);
|
||||
@@ -334,12 +341,12 @@ public class SchemaBuilder {
|
||||
prop.put("$ref", "#/definitions/" + key);
|
||||
description.add(SYMBOL_TYPE__N + " Must be a valid Potion Effect Type (use ctrl+space for auto complete!)");
|
||||
|
||||
} else if(k.getType().isEnum()) {
|
||||
} else if (k.getType().isEnum()) {
|
||||
fancyType = k.getType().getSimpleName().replaceAll("\\QIris\\E", "");
|
||||
JSONArray a = new JSONArray();
|
||||
boolean advanced = k.getType().isAnnotationPresent(Desc.class);
|
||||
for(Object gg : k.getType().getEnumConstants()) {
|
||||
if(advanced) {
|
||||
for (Object gg : k.getType().getEnumConstants()) {
|
||||
if (advanced) {
|
||||
try {
|
||||
JSONObject j = new JSONObject();
|
||||
String name = ((Enum<?>) gg).name();
|
||||
@@ -347,7 +354,7 @@ public class SchemaBuilder {
|
||||
Desc dd = k.getType().getField(name).getAnnotation(Desc.class);
|
||||
j.put("description", dd == null ? ("No Description for " + name) : dd.value());
|
||||
a.put(j);
|
||||
} catch(Throwable e) {
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
@@ -358,7 +365,7 @@ public class SchemaBuilder {
|
||||
|
||||
String key = (advanced ? "oneof-" : "") + "enum-" + k.getType().getCanonicalName().replaceAll("\\Q.\\E", "-").toLowerCase();
|
||||
|
||||
if(!definitions.containsKey(key)) {
|
||||
if (!definitions.containsKey(key)) {
|
||||
JSONObject j = new JSONObject();
|
||||
j.put(advanced ? "oneOf" : "enum", a);
|
||||
definitions.put(key, j);
|
||||
@@ -372,7 +379,7 @@ public class SchemaBuilder {
|
||||
case "object" -> {
|
||||
fancyType = k.getType().getSimpleName().replaceAll("\\QIris\\E", "") + " (Object)";
|
||||
String key = "obj-" + k.getType().getCanonicalName().replaceAll("\\Q.\\E", "-").toLowerCase();
|
||||
if(!definitions.containsKey(key)) {
|
||||
if (!definitions.containsKey(key)) {
|
||||
definitions.put(key, new JSONObject());
|
||||
definitions.put(key, buildProperties(k.getType()));
|
||||
}
|
||||
@@ -381,10 +388,10 @@ public class SchemaBuilder {
|
||||
case "array" -> {
|
||||
fancyType = "List of Something...?";
|
||||
ArrayType t = k.getDeclaredAnnotation(ArrayType.class);
|
||||
if(t != null) {
|
||||
if(t.min() > 0) {
|
||||
if (t != null) {
|
||||
if (t.min() > 0) {
|
||||
prop.put("minItems", t.min());
|
||||
if(t.min() == 1) {
|
||||
if (t.min() == 1) {
|
||||
description.add(SYMBOL_LIMIT__N + " At least one entry must be defined, or just remove this list.");
|
||||
} else {
|
||||
description.add(SYMBOL_LIMIT__N + " Requires at least " + t.min() + " entries.");
|
||||
@@ -393,13 +400,13 @@ public class SchemaBuilder {
|
||||
|
||||
String arrayType = getType(t.type());
|
||||
|
||||
switch(arrayType) {
|
||||
switch (arrayType) {
|
||||
case "integer" -> fancyType = "List of Integers";
|
||||
case "number" -> fancyType = "List of Numbers";
|
||||
case "object" -> {
|
||||
fancyType = "List of " + t.type().getSimpleName().replaceAll("\\QIris\\E", "") + "s (Objects)";
|
||||
String key = "obj-" + t.type().getCanonicalName().replaceAll("\\Q.\\E", "-").toLowerCase();
|
||||
if(!definitions.containsKey(key)) {
|
||||
if (!definitions.containsKey(key)) {
|
||||
definitions.put(key, new JSONObject());
|
||||
definitions.put(key, buildProperties(t.type()));
|
||||
}
|
||||
@@ -410,15 +417,15 @@ public class SchemaBuilder {
|
||||
case "string" -> {
|
||||
fancyType = "List of Text";
|
||||
|
||||
if(k.isAnnotationPresent(RegistryListResource.class)) {
|
||||
if (k.isAnnotationPresent(RegistryListResource.class)) {
|
||||
RegistryListResource rr = k.getDeclaredAnnotation(RegistryListResource.class);
|
||||
ResourceLoader<?> loader = data.getLoaders().get(rr.value());
|
||||
|
||||
if(loader != null) {
|
||||
if (loader != null) {
|
||||
fancyType = "List<" + loader.getResourceTypeName() + ">";
|
||||
String key = "erz" + loader.getFolderName();
|
||||
|
||||
if(!definitions.containsKey(key)) {
|
||||
if (!definitions.containsKey(key)) {
|
||||
JSONObject j = new JSONObject();
|
||||
j.put("enum", new JSONArray(loader.getPossibleKeys()));
|
||||
definitions.put(key, j);
|
||||
@@ -431,19 +438,19 @@ public class SchemaBuilder {
|
||||
} else {
|
||||
Iris.error("Cannot find Registry Loader for type (list schema) " + rr.value() + " used in " + k.getDeclaringClass().getCanonicalName() + " in field " + k.getName());
|
||||
}
|
||||
} else if(k.isAnnotationPresent(RegistryListBlockType.class)) {
|
||||
} else if (k.isAnnotationPresent(RegistryListBlockType.class)) {
|
||||
fancyType = "List of Block Types";
|
||||
String key = "enum-block-type";
|
||||
|
||||
if(!definitions.containsKey(key)) {
|
||||
if (!definitions.containsKey(key)) {
|
||||
JSONObject j = new JSONObject();
|
||||
JSONArray ja = new JSONArray();
|
||||
|
||||
for(String i : data.getBlockLoader().getPossibleKeys()) {
|
||||
for (String i : data.getBlockLoader().getPossibleKeys()) {
|
||||
ja.put(i);
|
||||
}
|
||||
|
||||
for(String i : B.getBlockTypes()) {
|
||||
for (String i : B.getBlockTypes()) {
|
||||
ja.put(i);
|
||||
}
|
||||
|
||||
@@ -455,11 +462,11 @@ public class SchemaBuilder {
|
||||
items.put("$ref", "#/definitions/" + key);
|
||||
prop.put("items", items);
|
||||
description.add(SYMBOL_TYPE__N + " Must be a valid Block Type (use ctrl+space for auto complete!)");
|
||||
} else if(k.isAnnotationPresent(RegistryListItemType.class)) {
|
||||
} else if (k.isAnnotationPresent(RegistryListItemType.class)) {
|
||||
fancyType = "List of Item Types";
|
||||
String key = "enum-item-type";
|
||||
|
||||
if(!definitions.containsKey(key)) {
|
||||
if (!definitions.containsKey(key)) {
|
||||
JSONObject j = new JSONObject();
|
||||
j.put("enum", ITEM_TYPES);
|
||||
definitions.put(key, j);
|
||||
@@ -469,11 +476,11 @@ public class SchemaBuilder {
|
||||
items.put("$ref", "#/definitions/" + key);
|
||||
prop.put("items", items);
|
||||
description.add(SYMBOL_TYPE__N + " Must be a valid Item Type (use ctrl+space for auto complete!)");
|
||||
} else if(k.isAnnotationPresent(RegistryListFont.class)) {
|
||||
} else if (k.isAnnotationPresent(RegistryListFont.class)) {
|
||||
String key = "enum-font";
|
||||
fancyType = "List of Font Families";
|
||||
|
||||
if(!definitions.containsKey(key)) {
|
||||
if (!definitions.containsKey(key)) {
|
||||
JSONObject j = new JSONObject();
|
||||
j.put("enum", FONT_TYPES);
|
||||
definitions.put(key, j);
|
||||
@@ -483,11 +490,11 @@ public class SchemaBuilder {
|
||||
items.put("$ref", "#/definitions/" + key);
|
||||
prop.put("items", items);
|
||||
description.add(SYMBOL_TYPE__N + " Must be a valid Font Family (use ctrl+space for auto complete!)");
|
||||
} else if(t.type().equals(Enchantment.class)) {
|
||||
} else if (k.isAnnotationPresent(RegistryListEnchantment.class)) {
|
||||
fancyType = "List of Enchantment Types";
|
||||
String key = "enum-enchantment";
|
||||
|
||||
if(!definitions.containsKey(key)) {
|
||||
if (!definitions.containsKey(key)) {
|
||||
JSONObject j = new JSONObject();
|
||||
j.put("enum", ENCHANT_TYPES);
|
||||
definitions.put(key, j);
|
||||
@@ -497,11 +504,11 @@ public class SchemaBuilder {
|
||||
items.put("$ref", "#/definitions/" + key);
|
||||
prop.put("items", items);
|
||||
description.add(SYMBOL_TYPE__N + " Must be a valid Enchantment Type (use ctrl+space for auto complete!)");
|
||||
} else if(t.type().equals(PotionEffectType.class)) {
|
||||
} else if (t.type().equals(PotionEffectType.class)) {
|
||||
fancyType = "List of Potion Effect Types";
|
||||
String key = "enum-potion-effect-type";
|
||||
|
||||
if(!definitions.containsKey(key)) {
|
||||
if (!definitions.containsKey(key)) {
|
||||
JSONObject j = new JSONObject();
|
||||
j.put("enum", POTION_TYPES);
|
||||
definitions.put(key, j);
|
||||
@@ -511,12 +518,12 @@ public class SchemaBuilder {
|
||||
items.put("$ref", "#/definitions/" + key);
|
||||
prop.put("items", items);
|
||||
description.add(SYMBOL_TYPE__N + " Must be a valid Potion Effect Type (use ctrl+space for auto complete!)");
|
||||
} else if(t.type().isEnum()) {
|
||||
} else if (t.type().isEnum()) {
|
||||
fancyType = "List of " + t.type().getSimpleName().replaceAll("\\QIris\\E", "") + "s";
|
||||
JSONArray a = new JSONArray();
|
||||
boolean advanced = t.type().isAnnotationPresent(Desc.class);
|
||||
for(Object gg : t.type().getEnumConstants()) {
|
||||
if(advanced) {
|
||||
for (Object gg : t.type().getEnumConstants()) {
|
||||
if (advanced) {
|
||||
try {
|
||||
JSONObject j = new JSONObject();
|
||||
String name = ((Enum<?>) gg).name();
|
||||
@@ -524,7 +531,7 @@ public class SchemaBuilder {
|
||||
Desc dd = t.type().getField(name).getAnnotation(Desc.class);
|
||||
j.put("description", dd == null ? ("No Description for " + name) : dd.value());
|
||||
a.put(j);
|
||||
} catch(Throwable e) {
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
@@ -535,7 +542,7 @@ public class SchemaBuilder {
|
||||
|
||||
String key = (advanced ? "oneof-" : "") + "enum-" + t.type().getCanonicalName().replaceAll("\\Q.\\E", "-").toLowerCase();
|
||||
|
||||
if(!definitions.containsKey(key)) {
|
||||
if (!definitions.containsKey(key)) {
|
||||
JSONObject j = new JSONObject();
|
||||
j.put(advanced ? "oneOf" : "enum", a);
|
||||
definitions.put(key, j);
|
||||
@@ -552,7 +559,8 @@ public class SchemaBuilder {
|
||||
warnings.add("Undefined array type for field " + k.getName() + " (" + k.getType().getSimpleName() + ") in class " + cl.getSimpleName());
|
||||
}
|
||||
}
|
||||
default -> warnings.add("Unexpected Schema Type: " + type + " for field " + k.getName() + " (" + k.getType().getSimpleName() + ") in class " + cl.getSimpleName());
|
||||
default ->
|
||||
warnings.add("Unexpected Schema Type: " + type + " for field " + k.getName() + " (" + k.getType().getSimpleName() + ") in class " + cl.getSimpleName());
|
||||
}
|
||||
|
||||
KList<String> d = new KList<>();
|
||||
@@ -562,7 +570,7 @@ public class SchemaBuilder {
|
||||
d.add(fancyType);
|
||||
d.add(getDescription(k.getType()));
|
||||
|
||||
if(k.getType().isAnnotationPresent(Snippet.class)) {
|
||||
if (k.getType().isAnnotationPresent(Snippet.class)) {
|
||||
String sm = k.getType().getDeclaredAnnotation(Snippet.class).value();
|
||||
d.add(" ");
|
||||
d.add("You can instead specify \"snippet/" + sm + "/some-name.json\" to use a snippet file instead of specifying it here.");
|
||||
@@ -572,11 +580,11 @@ public class SchemaBuilder {
|
||||
k.setAccessible(true);
|
||||
Object value = k.get(cl.newInstance());
|
||||
|
||||
if(value != null) {
|
||||
if(value instanceof List) {
|
||||
if (value != null) {
|
||||
if (value instanceof List) {
|
||||
d.add(" ");
|
||||
d.add("* Default Value is an empty list");
|
||||
} else if(!cl.isPrimitive() && !(value instanceof Number) && !(value instanceof String) && !(cl.isEnum())) {
|
||||
} else if (!cl.isPrimitive() && !(value instanceof Number) && !(value instanceof String) && !(cl.isEnum())) {
|
||||
d.add(" ");
|
||||
d.add("* Default Value is a default object (create this object to see default properties)");
|
||||
} else {
|
||||
@@ -584,7 +592,7 @@ public class SchemaBuilder {
|
||||
d.add("* Default Value is " + value);
|
||||
}
|
||||
}
|
||||
} catch(Throwable ignored) {
|
||||
} catch (Throwable ignored) {
|
||||
|
||||
}
|
||||
|
||||
@@ -592,7 +600,7 @@ public class SchemaBuilder {
|
||||
prop.put("type", type);
|
||||
prop.put("description", d.toString("\n"));
|
||||
|
||||
if(k.getType().isAnnotationPresent(Snippet.class)) {
|
||||
if (k.getType().isAnnotationPresent(Snippet.class)) {
|
||||
JSONObject anyOf = new JSONObject();
|
||||
JSONArray arr = new JSONArray();
|
||||
JSONObject str = new JSONObject();
|
||||
@@ -600,7 +608,7 @@ public class SchemaBuilder {
|
||||
String key = "enum-snippet-" + k.getType().getDeclaredAnnotation(Snippet.class).value();
|
||||
str.put("$ref", "#/definitions/" + key);
|
||||
|
||||
if(!definitions.containsKey(key)) {
|
||||
if (!definitions.containsKey(key)) {
|
||||
JSONObject j = new JSONObject();
|
||||
JSONArray snl = new JSONArray();
|
||||
data.getPossibleSnippets(k.getType().getDeclaredAnnotation(Snippet.class).value()).forEach(snl::put);
|
||||
@@ -623,31 +631,31 @@ public class SchemaBuilder {
|
||||
}
|
||||
|
||||
private String getType(Class<?> c) {
|
||||
if(c.equals(int.class) || c.equals(Integer.class) || c.equals(long.class) || c.equals(Long.class)) {
|
||||
if (c.equals(int.class) || c.equals(Integer.class) || c.equals(long.class) || c.equals(Long.class)) {
|
||||
return "integer";
|
||||
}
|
||||
|
||||
if(c.equals(float.class) || c.equals(double.class) || c.equals(Float.class) || c.equals(Double.class)) {
|
||||
if (c.equals(float.class) || c.equals(double.class) || c.equals(Float.class) || c.equals(Double.class)) {
|
||||
return "number";
|
||||
}
|
||||
|
||||
if(c.equals(boolean.class) || c.equals(Boolean.class)) {
|
||||
if (c.equals(boolean.class) || c.equals(Boolean.class)) {
|
||||
return "boolean";
|
||||
}
|
||||
|
||||
if(c.equals(String.class) || c.isEnum() || c.equals(Enchantment.class) || c.equals(PotionEffectType.class)) {
|
||||
if (c.equals(String.class) || c.isEnum() || c.equals(Enchantment.class) || c.equals(PotionEffectType.class)) {
|
||||
return "string";
|
||||
}
|
||||
|
||||
if(c.equals(KList.class)) {
|
||||
if (c.equals(KList.class)) {
|
||||
return "array";
|
||||
}
|
||||
|
||||
if(c.equals(KMap.class)) {
|
||||
if (c.equals(KMap.class)) {
|
||||
return "object";
|
||||
}
|
||||
|
||||
if(!c.isAnnotationPresent(Desc.class) && c.getCanonicalName().startsWith("com.volmit.iris.")) {
|
||||
if (!c.isAnnotationPresent(Desc.class) && c.getCanonicalName().startsWith("com.volmit.iris.")) {
|
||||
warnings.addIfMissing("Unsupported Type: " + c.getCanonicalName() + " Did you forget @Desc?");
|
||||
}
|
||||
|
||||
@@ -656,12 +664,12 @@ public class SchemaBuilder {
|
||||
|
||||
private String getFieldDescription(Field r) {
|
||||
|
||||
if(r.isAnnotationPresent(Desc.class)) {
|
||||
if (r.isAnnotationPresent(Desc.class)) {
|
||||
return r.getDeclaredAnnotation(Desc.class).value();
|
||||
}
|
||||
|
||||
// suppress warnings on bukkit classes
|
||||
if(r.getDeclaringClass().getName().startsWith("org.bukkit.")) {
|
||||
if (r.getDeclaringClass().getName().startsWith("org.bukkit.")) {
|
||||
return "Bukkit package classes and enums have no descriptions";
|
||||
}
|
||||
|
||||
@@ -670,11 +678,11 @@ public class SchemaBuilder {
|
||||
}
|
||||
|
||||
private String getDescription(Class<?> r) {
|
||||
if(r.isAnnotationPresent(Desc.class)) {
|
||||
if (r.isAnnotationPresent(Desc.class)) {
|
||||
return r.getDeclaredAnnotation(Desc.class).value();
|
||||
}
|
||||
|
||||
if(!r.isPrimitive() && !r.equals(KList.class) && !r.equals(KMap.class) && r.getCanonicalName().startsWith("com.volmit.")) {
|
||||
if (!r.isPrimitive() && !r.equals(KList.class) && !r.equals(KMap.class) && r.getCanonicalName().startsWith("com.volmit.")) {
|
||||
warnings.addIfMissing("Missing @Desc on " + r.getSimpleName() + " in " + (r.getDeclaringClass() != null ? r.getDeclaringClass().getCanonicalName() : " NOSRC"));
|
||||
}
|
||||
return "";
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.safeguard;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.nms.INMS;
|
||||
import com.volmit.iris.core.safeguard.handler.onCommandWarning;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.misc.getHardware;
|
||||
|
||||
import static org.bukkit.Bukkit.getServer;
|
||||
|
||||
public class IrisSafeguard {
|
||||
public static IrisSafeguard instance;
|
||||
public boolean acceptUnstable = false;
|
||||
public boolean unstablemode = false;
|
||||
public boolean warningmode = false;
|
||||
public boolean stablemode = false;
|
||||
|
||||
public static void InitializeSafeguard() {
|
||||
instance = new IrisSafeguard();
|
||||
}
|
||||
|
||||
public void IrisSafeguardSystem() {
|
||||
acceptUnstable = IrisSettings.get().getSafeguard().ignoreBootMode;
|
||||
getServer().getPluginManager().registerEvents(new onCommandWarning(), Iris.instance);
|
||||
Iris.info("Enabled Iris SafeGuard");
|
||||
ServerBootSFG.BootCheck();
|
||||
}
|
||||
|
||||
public void earlySplash() {
|
||||
String padd = Form.repeat(" ", 8);
|
||||
String padd2 = Form.repeat(" ", 4);
|
||||
String[] info = new String[]{"", "", "", "", "", padd2 + C.RED + " Iris", padd2 + C.GRAY + " by " + C.DARK_RED + "Volmit Software", padd2 + C.GRAY + " v" + C.RED + Iris.instance.getDescription().getVersion()};
|
||||
String[] splashunstable = {
|
||||
padd + C.GRAY + " @@@@@@@@@@@@@@" + C.DARK_GRAY + "@@@",
|
||||
padd + C.GRAY + " @@&&&&&&&&&" + C.DARK_GRAY + "&&&&&&" + C.RED + " .(((()))). ",
|
||||
padd + C.GRAY + "@@@&&&&&&&&" + C.DARK_GRAY + "&&&&&" + C.RED + " .((((((())))))). ",
|
||||
padd + C.GRAY + "@@@&&&&&" + C.DARK_GRAY + "&&&&&&&" + C.RED + " ((((((((())))))))) " + C.GRAY + " @",
|
||||
padd + C.GRAY + "@@@&&&&" + C.DARK_GRAY + "@@@@@&" + C.RED + " ((((((((-))))))))) " + C.GRAY + " @@",
|
||||
padd + C.GRAY + "@@@&&" + C.RED + " ((((((({ })))))))) " + C.GRAY + " &&@@@",
|
||||
padd + C.GRAY + "@@" + C.RED + " ((((((((-))))))))) " + C.DARK_GRAY + "&@@@@@" + C.GRAY + "&&&&@@@",
|
||||
padd + C.GRAY + "@" + C.RED + " ((((((((())))))))) " + C.DARK_GRAY + "&&&&&" + C.GRAY + "&&&&&&&@@@",
|
||||
padd + C.GRAY + "" + C.RED + " '((((((()))))))' " + C.DARK_GRAY + "&&&&&" + C.GRAY + "&&&&&&&&@@@",
|
||||
padd + C.GRAY + "" + C.RED + " '(((())))' " + C.DARK_GRAY + "&&&&&&&&" + C.GRAY + "&&&&&&&@@",
|
||||
padd + C.GRAY + " " + C.DARK_GRAY + "@@@" + C.GRAY + "@@@@@@@@@@@@@@"
|
||||
};
|
||||
|
||||
for (int i = 0; i < info.length; i++) {
|
||||
splashunstable[i] += info[i];
|
||||
}
|
||||
Iris.info("Java: " + Iris.instance.getJava());
|
||||
if (!Iris.instance.getServer().getVersion().contains("Purpur")) {
|
||||
if (Iris.instance.getServer().getVersion().contains("Spigot") && Iris.instance.getServer().getVersion().contains("Bukkit")) {
|
||||
Iris.info(C.RED + " Iris requires paper or above to function properly..");
|
||||
} else {
|
||||
Iris.info(C.YELLOW + "Purpur is recommended to use with iris.");
|
||||
}
|
||||
}
|
||||
if (getHardware.getProcessMemory() < 5999) {
|
||||
Iris.warn("6GB+ Ram is recommended");
|
||||
Iris.warn("Process Memory: " + getHardware.getProcessMemory() + " MB");
|
||||
}
|
||||
Iris.info("Custom Biomes: " + INMS.get().countCustomBiomes());
|
||||
Iris.info("\n\n " + new KList<>(splashunstable).toString("\n") + "\n");
|
||||
UtilsSFG.splash();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.safeguard;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
public class ModesSFG {
|
||||
public static void selectMode() {
|
||||
if (IrisSafeguard.instance.unstablemode) {
|
||||
Iris.safeguard(C.DARK_RED + "Iris is running in Unstable Mode");
|
||||
unstable();
|
||||
}
|
||||
if (IrisSafeguard.instance.warningmode) {
|
||||
Iris.safeguard(C.GOLD + "Iris is running in Warning Mode");
|
||||
warning();
|
||||
}
|
||||
if (IrisSafeguard.instance.stablemode) {
|
||||
stable();
|
||||
}
|
||||
}
|
||||
|
||||
public static void stable() {
|
||||
Iris.safeguard(C.BLUE + "Iris is running Stable");
|
||||
}
|
||||
|
||||
public static void unstable() {
|
||||
|
||||
UtilsSFG.printIncompatibleWarnings();
|
||||
|
||||
if (IrisSafeguard.instance.unstablemode) {
|
||||
Iris.info("");
|
||||
Iris.info(C.DARK_GRAY + "--==<" + C.RED + " IMPORTANT " + C.DARK_GRAY + ">==--");
|
||||
Iris.info(C.RED + "Iris is running in unstable mode which may cause the following issues:");
|
||||
Iris.info(C.DARK_RED + "Server Issues");
|
||||
Iris.info(C.RED + "- Server won't boot");
|
||||
Iris.info(C.RED + "- Data Loss");
|
||||
Iris.info(C.RED + "- Unexpected behavior.");
|
||||
Iris.info(C.RED + "- And More...");
|
||||
Iris.info(C.DARK_RED + "World Issues");
|
||||
Iris.info(C.RED + "- Worlds can't load due to corruption.");
|
||||
Iris.info(C.RED + "- Worlds may slowly corrupt until they can't load.");
|
||||
Iris.info(C.RED + "- World data loss.");
|
||||
Iris.info(C.RED + "- And More...");
|
||||
Iris.info(C.DARK_RED + "ATTENTION: " + C.RED + "While running Iris in unstable mode, you won't be eligible for support.");
|
||||
Iris.info(C.DARK_RED + "CAUSE: " + C.RED + UtilsSFG.MSGIncompatibleWarnings());
|
||||
|
||||
if (IrisSettings.get().getSafeguard().ignoreBootMode) {
|
||||
Iris.info(C.DARK_RED + "Boot Unstable is set to true, continuing with the startup process.");
|
||||
} else {
|
||||
Iris.info(C.DARK_RED + "Go to plugins/iris/settings.json and set DoomsdayAnnihilationSelfDestructMode to true if you wish to proceed.");
|
||||
while (true) {
|
||||
try {
|
||||
Thread.sleep(Long.MAX_VALUE);
|
||||
} catch (InterruptedException e) {
|
||||
// no
|
||||
}
|
||||
}
|
||||
}
|
||||
Iris.info("");
|
||||
}
|
||||
}
|
||||
|
||||
public static void warning() {
|
||||
|
||||
UtilsSFG.printIncompatibleWarnings();
|
||||
|
||||
if (IrisSafeguard.instance.warningmode) {
|
||||
Iris.info("");
|
||||
Iris.info(C.DARK_GRAY + "--==<" + C.GOLD + " IMPORTANT " + C.DARK_GRAY + ">==--");
|
||||
Iris.info(C.GOLD + "Iris is running in warning mode which may cause the following issues:");
|
||||
Iris.info(C.YELLOW + "- Data Loss");
|
||||
Iris.info(C.YELLOW + "- Errors");
|
||||
Iris.info(C.YELLOW + "- Broken worlds");
|
||||
Iris.info(C.YELLOW + "- Unexpected behavior.");
|
||||
Iris.info(C.YELLOW + "- And perhaps further complications.");
|
||||
Iris.info(C.GOLD + "CAUSE: " + C.YELLOW + UtilsSFG.MSGIncompatibleWarnings());
|
||||
Iris.info("");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.safeguard;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.nms.INMS;
|
||||
import com.volmit.iris.core.nms.v1X.NMSBinding1X;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
|
||||
import javax.tools.JavaCompiler;
|
||||
import javax.tools.ToolProvider;
|
||||
import java.io.File;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
import static com.volmit.iris.Iris.getJavaVersion;
|
||||
|
||||
public class ServerBootSFG {
|
||||
public static final Map<String, Boolean> incompatibilities = new HashMap<>();
|
||||
public static boolean isJDK17 = true;
|
||||
public static boolean hasEnoughDiskSpace = true;
|
||||
public static boolean isJRE = false;
|
||||
public static boolean hasPrivileges = true;
|
||||
public static boolean unsuportedversion = false;
|
||||
public static boolean passedserversoftware = true;
|
||||
public static String allIncompatibilities;
|
||||
protected static boolean safeguardPassed;
|
||||
protected static int count;
|
||||
protected static byte severityLow;
|
||||
protected static byte severityMedium;
|
||||
protected static byte severityHigh;
|
||||
|
||||
public static void BootCheck() {
|
||||
//todo: Stop fucking locking the server, this bricks unix/linux instances, this could get us booted.
|
||||
|
||||
Iris.info("Checking for possible conflicts..");
|
||||
PluginManager pluginManager = Bukkit.getPluginManager();
|
||||
Plugin[] plugins = pluginManager.getPlugins();
|
||||
|
||||
incompatibilities.clear();
|
||||
incompatibilities.put("Multiverse-Core", false);
|
||||
// incompatibilities.put("dynmap", false);
|
||||
incompatibilities.put("TerraformGenerator", false);
|
||||
incompatibilities.put("Stratos", false);
|
||||
|
||||
String pluginName;
|
||||
for (Plugin plugin : plugins) {
|
||||
pluginName = plugin.getName();
|
||||
Boolean flag = incompatibilities.get(pluginName);
|
||||
if (flag != null && !flag) {
|
||||
severityHigh++;
|
||||
incompatibilities.put(pluginName, true);
|
||||
}
|
||||
}
|
||||
|
||||
StringJoiner joiner = new StringJoiner(", ");
|
||||
for (Map.Entry<String, Boolean> entry : incompatibilities.entrySet()) {
|
||||
if (entry.getValue()) {
|
||||
joiner.add(entry.getKey());
|
||||
}
|
||||
}
|
||||
// Legacy ServerInfo
|
||||
String distro = Bukkit.getName().toLowerCase();
|
||||
if (
|
||||
!distro.contains("purpur") &&
|
||||
!distro.contains("paper") &&
|
||||
!distro.contains("spigot") &&
|
||||
!distro.contains("pufferfish") &&
|
||||
!distro.contains("bukkit")) {
|
||||
|
||||
|
||||
passedserversoftware = false;
|
||||
joiner.add("Server Software");
|
||||
severityMedium++;
|
||||
}
|
||||
|
||||
|
||||
if (INMS.get() instanceof NMSBinding1X) {
|
||||
unsuportedversion = true;
|
||||
joiner.add("Unsupported Minecraft Version");
|
||||
severityHigh++;
|
||||
}
|
||||
|
||||
if (!List.of(17, 21).contains(getJavaVersion())) {
|
||||
isJDK17 = false;
|
||||
joiner.add("Unsupported Java version");
|
||||
severityMedium++;
|
||||
}
|
||||
|
||||
if (!isJDK()) {
|
||||
isJRE = true;
|
||||
joiner.add("Unsupported JDK");
|
||||
severityMedium++;
|
||||
}
|
||||
|
||||
// if (!hasPrivileges()){
|
||||
// hasPrivileges = false;
|
||||
// joiner.add("Insufficient Privileges");
|
||||
// severityMedium++;
|
||||
// } Some servers dont like this
|
||||
|
||||
if (!enoughDiskSpace()) {
|
||||
hasEnoughDiskSpace = false;
|
||||
joiner.add("Insufficient Disk Space");
|
||||
severityMedium++;
|
||||
}
|
||||
|
||||
allIncompatibilities = joiner.toString();
|
||||
|
||||
safeguardPassed = (severityHigh == 0 && severityMedium == 0 && severityLow == 0);
|
||||
count = severityHigh + severityMedium + severityLow;
|
||||
if (safeguardPassed) {
|
||||
IrisSafeguard.instance.stablemode = true;
|
||||
Iris.safeguard("Stable mode has been activated.");
|
||||
}
|
||||
if (!safeguardPassed) {
|
||||
if (severityMedium >= 1 && severityHigh == 0) {
|
||||
IrisSafeguard.instance.warningmode = true;
|
||||
Iris.safeguard("Warning mode has been activated.");
|
||||
}
|
||||
if (severityHigh >= 1) {
|
||||
IrisSafeguard.instance.unstablemode = true;
|
||||
Iris.safeguard("Unstable mode has been activated.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static boolean isJDK() {
|
||||
try {
|
||||
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
|
||||
// If the compiler is null, it means this is a JRE environment, not a JDK.
|
||||
return compiler != null;
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean hasPrivileges() {
|
||||
Path pv = Paths.get(Bukkit.getWorldContainer() + "iristest.json");
|
||||
try (FileChannel fc = FileChannel.open(pv, StandardOpenOption.CREATE, StandardOpenOption.DELETE_ON_CLOSE, StandardOpenOption.READ, StandardOpenOption.WRITE)) {
|
||||
if (Files.isReadable(pv) && Files.isWritable(pv)) {
|
||||
return true;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean enoughDiskSpace() {
|
||||
File freeSpace = new File(Bukkit.getWorldContainer() + ".");
|
||||
double gigabytes = freeSpace.getFreeSpace() / (1024.0 * 1024.0 * 1024.0);
|
||||
if (gigabytes > 3) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean checkJavac(String path) {
|
||||
return !path.isEmpty() && (new File(path, "javac").exists() || new File(path, "javac.exe").exists());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.safeguard;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.util.format.C;
|
||||
|
||||
public class UtilsSFG {
|
||||
public static void splash() {
|
||||
ModesSFG.selectMode();
|
||||
}
|
||||
|
||||
public static void printIncompatibleWarnings() {
|
||||
// String SupportedIrisVersion = getDescription().getVersion(); //todo Automatic version
|
||||
|
||||
if (ServerBootSFG.safeguardPassed) {
|
||||
Iris.safeguard(C.BLUE + "0 Conflicts found");
|
||||
} else {
|
||||
if (IrisSafeguard.instance.unstablemode) {
|
||||
Iris.safeguard(C.DARK_RED + "" + ServerBootSFG.count + " Conflicts found");
|
||||
}
|
||||
if (IrisSafeguard.instance.warningmode) {
|
||||
Iris.safeguard(C.YELLOW + "" + ServerBootSFG.count + " Conflicts found");
|
||||
}
|
||||
|
||||
if (ServerBootSFG.incompatibilities.get("Multiverse-Core")) {
|
||||
Iris.safeguard(C.RED + "Multiverse");
|
||||
Iris.safeguard(C.RED + "- The plugin Multiverse is not compatible with the server.");
|
||||
Iris.safeguard(C.RED + "- If you want to have a world manager, consider using PhantomWorlds or MyWorlds instead.");
|
||||
}
|
||||
if (ServerBootSFG.incompatibilities.get("dynmap")) {
|
||||
Iris.safeguard(C.RED + "Dynmap");
|
||||
Iris.safeguard(C.RED + "- The plugin Dynmap is not compatible with the server.");
|
||||
Iris.safeguard(C.RED + "- If you want to have a map plugin like Dynmap, consider Bluemap.");
|
||||
}
|
||||
if (ServerBootSFG.incompatibilities.get("TerraformGenerator") || ServerBootSFG.incompatibilities.get("Stratos")) {
|
||||
Iris.safeguard(C.YELLOW + "Terraform Generator / Stratos");
|
||||
Iris.safeguard(C.YELLOW + "- Iris is not compatible with other worldgen plugins.");
|
||||
}
|
||||
if (ServerBootSFG.unsuportedversion) {
|
||||
Iris.safeguard(C.RED + "Server Version");
|
||||
Iris.safeguard(C.RED + "- Iris only supports 1.19.2 > 1.21.1");
|
||||
}
|
||||
if (!ServerBootSFG.passedserversoftware) {
|
||||
Iris.safeguard(C.YELLOW + "Unsupported Server Software");
|
||||
Iris.safeguard(C.YELLOW + "- Please consider using Paper or Purpur instead.");
|
||||
}
|
||||
if (!ServerBootSFG.hasPrivileges) {
|
||||
Iris.safeguard(C.YELLOW + "Insufficient Privileges");
|
||||
Iris.safeguard(C.YELLOW + "- The server has insufficient Privileges to run iris. Please contact support.");
|
||||
}
|
||||
if (!ServerBootSFG.hasEnoughDiskSpace) {
|
||||
Iris.safeguard(C.YELLOW + "Insufficient Disk Space");
|
||||
Iris.safeguard(C.YELLOW + "- The server has insufficient Free DiskSpace to run iris required 3GB+.");
|
||||
}
|
||||
if (!ServerBootSFG.isJDK17) {
|
||||
Iris.safeguard(C.YELLOW + "Unsupported java version");
|
||||
Iris.safeguard(C.YELLOW + "- Please consider using JDK 17 (or 21 for 1.20.6) Instead of JDK " + Iris.getJavaVersion());
|
||||
}
|
||||
if (ServerBootSFG.isJRE) {
|
||||
Iris.safeguard(C.YELLOW + "Unsupported Server JDK");
|
||||
Iris.safeguard(C.YELLOW + "- Please consider using JDK 17 (or 21 for 1.20.6) Instead of JRE " + Iris.getJavaVersion());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static String MSGIncompatibleWarnings() {
|
||||
return ServerBootSFG.allIncompatibilities;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.safeguard.handler;
|
||||
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.safeguard.IrisSafeguard;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.plugin.VolmitSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
|
||||
|
||||
public class onCommandWarning implements Listener {
|
||||
@EventHandler
|
||||
public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event) {
|
||||
if (IrisSettings.get().getSafeguard().userUnstableWarning && IrisSafeguard.instance.unstablemode) {
|
||||
String command = event.getMessage();
|
||||
Player player = event.getPlayer();
|
||||
if (command.startsWith("/iris")) {
|
||||
VolmitSender sender = new VolmitSender(player);
|
||||
boolean perm = sender.hasPermission("iris.all") || sender.isOp();
|
||||
if (perm) {
|
||||
sender.sendMessage(C.DARK_GRAY + "[" + C.RED + "!" + C.DARK_GRAY + "]" + C.DARK_RED + "Iris is running unstably! Please resolve this.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -19,6 +19,7 @@
|
||||
package com.volmit.iris.core.service;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.loader.IrisData;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
@@ -48,9 +49,9 @@ public class BoardSVC implements IrisService, BoardProvider {
|
||||
public void onEnable() {
|
||||
J.ar(this::tick, 20);
|
||||
manager = new BoardManager(Iris.instance, BoardSettings.builder()
|
||||
.boardProvider(this)
|
||||
.scoreDirection(ScoreDirection.DOWN)
|
||||
.build());
|
||||
.boardProvider(this)
|
||||
.scoreDirection(ScoreDirection.DOWN)
|
||||
.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -70,7 +71,7 @@ public class BoardSVC implements IrisService, BoardProvider {
|
||||
}
|
||||
|
||||
public void updatePlayer(Player p) {
|
||||
if(IrisToolbelt.isIrisStudioWorld(p.getWorld())) {
|
||||
if (IrisToolbelt.isIrisStudioWorld(p.getWorld())) {
|
||||
manager.remove(p);
|
||||
manager.setup(p);
|
||||
} else {
|
||||
@@ -85,7 +86,7 @@ public class BoardSVC implements IrisService, BoardProvider {
|
||||
}
|
||||
|
||||
public void tick() {
|
||||
if(!Iris.service(StudioSVC.class).isProjectOpen()) {
|
||||
if (!Iris.service(StudioSVC.class).isProjectOpen()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -95,7 +96,7 @@ public class BoardSVC implements IrisService, BoardProvider {
|
||||
@Override
|
||||
public List<String> getLines(Player player) {
|
||||
PlayerBoard pb = boards.computeIfAbsent(player, PlayerBoard::new);
|
||||
synchronized(pb.lines) {
|
||||
synchronized (pb.lines) {
|
||||
return pb.lines;
|
||||
}
|
||||
}
|
||||
@@ -112,10 +113,10 @@ public class BoardSVC implements IrisService, BoardProvider {
|
||||
}
|
||||
|
||||
public void update() {
|
||||
synchronized(lines) {
|
||||
synchronized (lines) {
|
||||
lines.clear();
|
||||
|
||||
if(!IrisToolbelt.isIrisStudioWorld(player.getWorld())) {
|
||||
if (!IrisToolbelt.isIrisStudioWorld(player.getWorld())) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -128,10 +129,11 @@ public class BoardSVC implements IrisService, BoardProvider {
|
||||
lines.add(C.GREEN + "Speed" + C.GRAY + ": " + Form.f(engine.getGeneratedPerSecond(), 0) + "/s " + Form.duration(1000D / engine.getGeneratedPerSecond(), 0));
|
||||
lines.add(C.AQUA + "Cache" + C.GRAY + ": " + Form.f(IrisData.cacheSize()));
|
||||
lines.add(C.AQUA + "Mantle" + C.GRAY + ": " + engine.getMantle().getLoadedRegionCount());
|
||||
lines.add(C.AQUA + "Energy" + C.GRAY + ": " + C.GOLD + Math.round(engine.getWorldManager().getEnergy()));
|
||||
lines.add("&7&m ");
|
||||
lines.add(C.AQUA + "Region" + C.GRAY + ": " + engine.getRegion(x, z).getName());
|
||||
lines.add(C.AQUA + "Biome" + C.GRAY + ": " + engine.getBiomeOrMantle(x, y, z).getName());
|
||||
lines.add(C.AQUA + "Height" + C.GRAY + ": " + Math.round(engine.getHeight(x, z) + player.getWorld().getMinHeight()));
|
||||
lines.add(C.AQUA + "Height" + C.GRAY + ": " + Math.round(engine.getHeight(x, z)));
|
||||
lines.add(C.AQUA + "Slope" + C.GRAY + ": " + Form.f(engine.getComplex().getSlopeStream().get(x, z), 2));
|
||||
lines.add(C.AQUA + "BUD/s" + C.GRAY + ": " + Form.f(engine.getBlockUpdatesPerSecond()));
|
||||
lines.add("&7&m ");
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -38,8 +38,8 @@ import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class CommandSVC implements IrisService, DecreeSystem {
|
||||
private final KMap<String, CompletableFuture<String>> futures = new KMap<>();
|
||||
private CompletableFuture<String> consoleFuture = null;
|
||||
private final transient AtomicCache<VirtualDecreeCommand> commandCache = new AtomicCache<>();
|
||||
private CompletableFuture<String> consoleFuture = null;
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
@@ -56,18 +56,18 @@ public class CommandSVC implements IrisService, DecreeSystem {
|
||||
public void on(PlayerCommandPreprocessEvent e) {
|
||||
String msg = e.getMessage().startsWith("/") ? e.getMessage().substring(1) : e.getMessage();
|
||||
|
||||
if(msg.startsWith("irisdecree ")) {
|
||||
if (msg.startsWith("irisdecree ")) {
|
||||
String[] args = msg.split("\\Q \\E");
|
||||
CompletableFuture<String> future = futures.get(args[1]);
|
||||
|
||||
if(future != null) {
|
||||
if (future != null) {
|
||||
future.complete(args[2]);
|
||||
e.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if((msg.startsWith("locate ") || msg.startsWith("locatebiome ")) && IrisToolbelt.isIrisWorld(e.getPlayer().getWorld())) {
|
||||
if ((msg.startsWith("locate ") || msg.startsWith("locatebiome ")) && IrisToolbelt.isIrisWorld(e.getPlayer().getWorld())) {
|
||||
new VolmitSender(e.getPlayer()).sendMessage(C.RED + "Locating biomes & objects is disabled in Iris Worlds. Use /iris studio goto <biome>");
|
||||
e.setCancelled(true);
|
||||
}
|
||||
@@ -75,8 +75,8 @@ public class CommandSVC implements IrisService, DecreeSystem {
|
||||
|
||||
@EventHandler
|
||||
public void on(ServerCommandEvent e) {
|
||||
if(consoleFuture != null && !consoleFuture.isCancelled() && !consoleFuture.isDone()) {
|
||||
if(!e.getCommand().contains(" ")) {
|
||||
if (consoleFuture != null && !consoleFuture.isCancelled() && !consoleFuture.isDone()) {
|
||||
if (!e.getCommand().contains(" ")) {
|
||||
String pick = e.getCommand().trim().toLowerCase(Locale.ROOT);
|
||||
consoleFuture.complete(pick);
|
||||
e.setCancelled(true);
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -20,12 +20,7 @@ package com.volmit.iris.core.service;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.engine.object.IrisDirection;
|
||||
import com.volmit.iris.engine.object.IrisJigsawPiece;
|
||||
import com.volmit.iris.engine.object.IrisJigsawPieceConnector;
|
||||
import com.volmit.iris.engine.object.IrisJigsawPool;
|
||||
import com.volmit.iris.engine.object.IrisObject;
|
||||
import com.volmit.iris.engine.object.IrisPosition;
|
||||
import com.volmit.iris.engine.object.*;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
@@ -60,10 +55,10 @@ public class ConversionSVC implements IrisService {
|
||||
converters = new KList<>();
|
||||
|
||||
J.s(() ->
|
||||
J.attemptAsync(() ->
|
||||
{
|
||||
J.attemptAsync(() ->
|
||||
{
|
||||
|
||||
}), 5);
|
||||
}), 5);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -84,13 +79,13 @@ public class ConversionSVC implements IrisService {
|
||||
destPools.mkdirs();
|
||||
findAllNBT(in, (folder, file) -> {
|
||||
total.getAndIncrement();
|
||||
if(roots.addIfMissing(folder)) {
|
||||
if (roots.addIfMissing(folder)) {
|
||||
String b = in.toURI().relativize(folder.toURI()).getPath();
|
||||
if(b.startsWith("/")) {
|
||||
if (b.startsWith("/")) {
|
||||
b = b.substring(1);
|
||||
}
|
||||
|
||||
if(b.endsWith("/")) {
|
||||
if (b.endsWith("/")) {
|
||||
b = b.substring(0, b.length() - 1);
|
||||
}
|
||||
|
||||
@@ -100,11 +95,11 @@ public class ConversionSVC implements IrisService {
|
||||
findAllNBT(in, (folder, file) -> {
|
||||
at.getAndIncrement();
|
||||
String b = in.toURI().relativize(folder.toURI()).getPath();
|
||||
if(b.startsWith("/")) {
|
||||
if (b.startsWith("/")) {
|
||||
b = b.substring(1);
|
||||
}
|
||||
|
||||
if(b.endsWith("/")) {
|
||||
if (b.endsWith("/")) {
|
||||
b = b.substring(0, b.length() - 1);
|
||||
}
|
||||
IrisJigsawPool jpool = pools.get(b);
|
||||
@@ -117,7 +112,7 @@ public class ConversionSVC implements IrisService {
|
||||
NamedTag tag = NBTUtil.read(file);
|
||||
CompoundTag compound = (CompoundTag) tag.getTag();
|
||||
|
||||
if(compound.containsKey("blocks") && compound.containsKey("palette") && compound.containsKey("size")) {
|
||||
if (compound.containsKey("blocks") && compound.containsKey("palette") && compound.containsKey("size")) {
|
||||
String id = in.toURI().relativize(folder.toURI()).getPath() + file.getName().split("\\Q.\\E")[0];
|
||||
@SuppressWarnings("unchecked") ListTag<IntTag> size = (ListTag<IntTag>) compound.getListTag("size");
|
||||
int w = size.get(0).asInt();
|
||||
@@ -125,14 +120,14 @@ public class ConversionSVC implements IrisService {
|
||||
int d = size.get(2).asInt();
|
||||
KList<BlockData> palette = new KList<>();
|
||||
@SuppressWarnings("unchecked") ListTag<CompoundTag> paletteList = (ListTag<CompoundTag>) compound.getListTag("palette");
|
||||
for(int i = 0; i < paletteList.size(); i++) {
|
||||
for (int i = 0; i < paletteList.size(); i++) {
|
||||
CompoundTag cp = paletteList.get(i);
|
||||
palette.add(NBTWorld.getBlockData(cp));
|
||||
}
|
||||
IrisJigsawPiece piece = new IrisJigsawPiece();
|
||||
IrisObject object = new IrisObject(w, h, d);
|
||||
@SuppressWarnings("unchecked") ListTag<CompoundTag> blockList = (ListTag<CompoundTag>) compound.getListTag("blocks");
|
||||
for(int i = 0; i < blockList.size(); i++) {
|
||||
for (int i = 0; i < blockList.size(); i++) {
|
||||
CompoundTag cp = blockList.get(i);
|
||||
@SuppressWarnings("unchecked") ListTag<IntTag> pos = (ListTag<IntTag>) cp.getListTag("pos");
|
||||
int x = pos.get(0).asInt();
|
||||
@@ -140,7 +135,7 @@ public class ConversionSVC implements IrisService {
|
||||
int z = pos.get(2).asInt();
|
||||
BlockData bd = palette.get(cp.getInt("state")).clone();
|
||||
|
||||
if(bd.getMaterial().equals(Material.JIGSAW) && cp.containsKey("nbt")) {
|
||||
if (bd.getMaterial().equals(Material.JIGSAW) && cp.containsKey("nbt")) {
|
||||
piece.setObject(in.toURI().relativize(folder.toURI()).getPath() + file.getName().split("\\Q.\\E")[0]);
|
||||
IrisPosition spos = new IrisPosition(object.getSigned(x, y, z));
|
||||
CompoundTag nbt = cp.getCompoundTag("nbt");
|
||||
@@ -162,14 +157,14 @@ public class ConversionSVC implements IrisService {
|
||||
connector.getPools().add(poolId);
|
||||
connector.setDirection(IrisDirection.getDirection(((Jigsaw) jd).getOrientation()));
|
||||
|
||||
if(target.equals("minecraft:building_entrance")) {
|
||||
if (target.equals("minecraft:building_entrance")) {
|
||||
connector.setInnerConnector(true);
|
||||
}
|
||||
|
||||
piece.getConnectors().add(connector);
|
||||
}
|
||||
|
||||
if(!bd.getMaterial().equals(Material.STRUCTURE_VOID) && !bd.getMaterial().equals(Material.AIR)) {
|
||||
if (!bd.getMaterial().equals(Material.STRUCTURE_VOID) && !bd.getMaterial().equals(Material.AIR)) {
|
||||
object.setUnsigned(x, y, z, bd);
|
||||
}
|
||||
}
|
||||
@@ -179,16 +174,16 @@ public class ConversionSVC implements IrisService {
|
||||
IO.writeAll(new File(destPieces, file.getName().split("\\Q.\\E")[0] + ".json"), new JSONObject(new Gson().toJson(piece)).toString(4));
|
||||
Iris.info("[Jigsaw]: (" + Form.pc((double) at.get() / (double) total.get(), 0) + ") Exported Piece: " + id);
|
||||
}
|
||||
} catch(Throwable e) {
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
Iris.reportError(e);
|
||||
}
|
||||
});
|
||||
|
||||
for(String i : pools.k()) {
|
||||
for (String i : pools.k()) {
|
||||
try {
|
||||
IO.writeAll(new File(destPools, i + ".json"), new JSONObject(new Gson().toJson(pools.get(i))).toString(4));
|
||||
} catch(IOException e) {
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
Iris.reportError(e);
|
||||
}
|
||||
@@ -198,19 +193,19 @@ public class ConversionSVC implements IrisService {
|
||||
}
|
||||
|
||||
public void findAllNBT(File path, Consumer2<File, File> inFile) {
|
||||
if(path == null) {
|
||||
if (path == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(path.isFile() && path.getName().endsWith(".nbt")) {
|
||||
if (path.isFile() && path.getName().endsWith(".nbt")) {
|
||||
inFile.accept(path.getParentFile(), path);
|
||||
return;
|
||||
}
|
||||
|
||||
for(File i : path.listFiles()) {
|
||||
if(i.isDirectory()) {
|
||||
for (File i : path.listFiles()) {
|
||||
if (i.isDirectory()) {
|
||||
findAllNBT(i, inFile);
|
||||
} else if(i.isFile() && i.getName().endsWith(".nbt")) {
|
||||
} else if (i.isFile() && i.getName().endsWith(".nbt")) {
|
||||
inFile.accept(path, i);
|
||||
}
|
||||
}
|
||||
@@ -220,9 +215,9 @@ public class ConversionSVC implements IrisService {
|
||||
int m = 0;
|
||||
Iris.instance.getDataFolder("convert");
|
||||
|
||||
for(File i : folder.listFiles()) {
|
||||
for(Converter j : converters) {
|
||||
if(i.getName().endsWith("." + j.getInExtension())) {
|
||||
for (File i : folder.listFiles()) {
|
||||
for (Converter j : converters) {
|
||||
if (i.getName().endsWith("." + j.getInExtension())) {
|
||||
File out = new File(folder, i.getName().replaceAll("\\Q." + j.getInExtension() + "\\E", "." + j.getOutExtension()));
|
||||
m++;
|
||||
j.convert(i, out);
|
||||
@@ -230,10 +225,10 @@ public class ConversionSVC implements IrisService {
|
||||
}
|
||||
}
|
||||
|
||||
if(i.isDirectory() && i.getName().equals("structures")) {
|
||||
if (i.isDirectory() && i.getName().equals("structures")) {
|
||||
File f = new File(folder, "jigsaw");
|
||||
|
||||
if(!f.exists()) {
|
||||
if (!f.exists()) {
|
||||
s.sendMessage("Converting NBT Structures into Iris Jigsaw Structures...");
|
||||
f.mkdirs();
|
||||
J.a(() -> convertStructures(i, f, s));
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -32,6 +32,7 @@ import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.world.WorldUnloadEvent;
|
||||
|
||||
public class EditSVC implements IrisService {
|
||||
public static boolean deletingWorld = false;
|
||||
private KMap<World, BlockEditor> editors;
|
||||
|
||||
@Override
|
||||
@@ -71,27 +72,28 @@ public class EditSVC implements IrisService {
|
||||
|
||||
@EventHandler
|
||||
public void on(WorldUnloadEvent e) {
|
||||
if(editors.containsKey(e.getWorld())) {
|
||||
if (editors.containsKey(e.getWorld()) && !deletingWorld) {
|
||||
editors.remove(e.getWorld()).close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void update() {
|
||||
for(World i : editors.k()) {
|
||||
if(M.ms() - editors.get(i).last() > 1000) {
|
||||
for (World i : editors.k()) {
|
||||
if (M.ms() - editors.get(i).last() > 1000) {
|
||||
editors.remove(i).close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void flushNow() {
|
||||
for(World i : editors.k()) {
|
||||
for (World i : editors.k()) {
|
||||
editors.remove(i).close();
|
||||
}
|
||||
}
|
||||
|
||||
public BlockEditor open(World world) {
|
||||
if(editors.containsKey(world)) {
|
||||
if (editors.containsKey(world)) {
|
||||
return editors.get(world);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user