mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2025-12-19 23:19:21 +00:00
Compare commits
931 Commits
old/iris3
...
feat/stati
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3a74164627 | ||
|
|
894de013dd | ||
|
|
e1a7e772cf | ||
|
|
3c6411c322 | ||
|
|
628761affa | ||
|
|
9a81905fdd | ||
|
|
fa7b0f68ff | ||
|
|
487d0ac237 | ||
|
|
e79e3fbe45 | ||
|
|
23a0ab23aa | ||
|
|
c78ffab948 | ||
|
|
d58f497b71 | ||
|
|
3284ab84c5 | ||
|
|
5cf0ac9315 | ||
|
|
4e4e820826 | ||
|
|
cb6e4570f4 | ||
|
|
fb59c7370d | ||
|
|
c16e65f0a8 | ||
|
|
d9681edf62 | ||
|
|
520c156d5f | ||
|
|
5c26ec2521 | ||
|
|
d192e2b6d1 | ||
|
|
5b60b655ed | ||
|
|
97c7ac0528 | ||
|
|
090ff730a7 | ||
|
|
c1f797e7c9 | ||
|
|
4a1a6b80a6 | ||
|
|
e189b2389c | ||
|
|
3265447536 | ||
|
|
8c7c9f89e1 | ||
|
|
d7a991b9b3 | ||
|
|
abf6c93f2e | ||
|
|
1b76a66760 | ||
|
|
c83ac67b47 | ||
|
|
1dca502a90 | ||
|
|
cacef8c8fc | ||
|
|
623fd45ef4 | ||
|
|
007b4b0b53 | ||
|
|
b6bacee095 | ||
|
|
d5251350a1 | ||
|
|
1f9c72d093 | ||
|
|
a1495a10e5 | ||
|
|
11ae48bea1 | ||
|
|
b0f4b29a2d | ||
|
|
c38bb1cd01 | ||
|
|
7faa727bd2 | ||
|
|
9e40259ca2 | ||
|
|
94a7692735 | ||
|
|
8b803a87f0 | ||
|
|
3ae6e92eaf | ||
|
|
0f3c52a5aa | ||
|
|
747be7aa09 | ||
|
|
d651f204f8 | ||
|
|
2bd3ac7a9b | ||
|
|
5e437b34e3 | ||
|
|
a5ef89a128 | ||
|
|
558b8e4eca | ||
|
|
0a001b8a63 | ||
|
|
6c6c9654c1 | ||
|
|
e21fdf46e0 | ||
|
|
a2ff5f58ed | ||
|
|
b0eedee519 | ||
|
|
e101155a4c | ||
|
|
3c9bcc9bb0 | ||
|
|
6763844030 | ||
|
|
08fa436885 | ||
|
|
df8fa79209 | ||
|
|
8041db4f40 | ||
|
|
18e57e4097 | ||
|
|
cc584ba377 | ||
|
|
0c92c20c65 | ||
|
|
ec8af56f0d | ||
|
|
79341bf562 | ||
|
|
3f24d5c8e1 | ||
|
|
66a1739666 | ||
|
|
29007fdbfa | ||
|
|
be3e8ebd51 | ||
|
|
38ad345f85 | ||
|
|
414f46a08d | ||
|
|
9144606688 | ||
|
|
effb0f5b91 | ||
|
|
bb7bbb6379 | ||
|
|
dafca8e9db | ||
|
|
41b7aec084 | ||
|
|
dfe1cce6de | ||
|
|
fc793592f7 | ||
|
|
c3ac41f894 | ||
|
|
d0688782b1 | ||
|
|
25b41fe62c | ||
|
|
b468478fcb | ||
|
|
b6dc934198 | ||
|
|
f58078e8a0 | ||
|
|
b6457e47e6 | ||
|
|
d275466e1e | ||
|
|
f9cb107728 | ||
|
|
68ad206252 | ||
|
|
288bead792 | ||
|
|
de670ddfd5 | ||
|
|
79d6f34879 | ||
|
|
ceb6c15c97 | ||
|
|
7cf43ad7ab | ||
|
|
ab3397a373 | ||
|
|
8e9f78e982 | ||
|
|
61bbfee640 | ||
|
|
cf4796bd12 | ||
|
|
bd89d8a308 | ||
|
|
df2186d70f | ||
|
|
f9638e830f | ||
|
|
cd55a7fed4 | ||
|
|
fc890a5ba1 | ||
|
|
2ea54b7f2f | ||
|
|
e90e3901f5 | ||
|
|
36d58f29ab | ||
|
|
864c7ae27c | ||
|
|
6d104a2d1c | ||
|
|
89e754245d | ||
|
|
4c68d99c6f | ||
|
|
f8f0a65f0a | ||
|
|
6ff74639b5 | ||
|
|
af80f882da | ||
|
|
84ce7372c3 | ||
|
|
e31d39c5f7 | ||
|
|
2296c1368b | ||
|
|
21d7d96dbc | ||
|
|
956e511fe0 | ||
|
|
e427887f8c | ||
|
|
88ea43fbbe | ||
|
|
29526a80a9 | ||
|
|
48f901fc8c | ||
|
|
6c3f3dc889 | ||
|
|
743410d3ee | ||
|
|
acccbb028f | ||
|
|
8b31fdc780 | ||
|
|
55017b9ac2 | ||
|
|
0288d35c85 | ||
|
|
8b3577dd0b | ||
|
|
ced77ec70d | ||
|
|
e1e90f5c8a | ||
|
|
dc3487583d | ||
|
|
e1d73ebcd5 | ||
|
|
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)
|
||||
|
||||
372
build.gradle
372
build.gradle
@@ -16,68 +16,143 @@
|
||||
* 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.freefair.lombok" version "6.3.0"
|
||||
id "com.github.johnrengelman.shadow" version "7.1.2"
|
||||
id "io.github.goooler.shadow" version "8.1.7"
|
||||
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'
|
||||
version '3.5.2-1.19.2-1.21.3'
|
||||
|
||||
// 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('Psycho', 'C://Dan/MinecraftDevelopment/Server/plugins')
|
||||
registerCustomOutputTask('ArcaneArts', 'C://Users/arcane/Documents/development/server/plugins')
|
||||
registerCustomOutputTask('Coco', 'D://Documents/MC/plugins')
|
||||
registerCustomOutputTask('Coco', 'D://mcsm/plugins')
|
||||
registerCustomOutputTask('Strange', 'D://Servers/1.17 Test Server/plugins')
|
||||
registerCustomOutputTask('Vatuu', 'D://Minecraft/Servers/1.19/plugins')
|
||||
registerCustomOutputTask('Vatuu', 'D://Minecraft/Servers/1.19.4/plugins')
|
||||
registerCustomOutputTask('CrazyDev22', 'C://Users/Julian/Desktop/server/plugins')
|
||||
registerCustomOutputTask('PixelFury', 'C://Users/repix/workplace/Iris/1.21.3 - Development-Public-v3/plugins')
|
||||
registerCustomOutputTask('PixelFuryDev', 'C://Users/repix/workplace/Iris/1.21 - Development-v3/plugins')
|
||||
// ========================== UNIX ==============================
|
||||
registerCustomOutputTaskUnix('CyberpwnLT', '/Users/danielmills/development/server/plugins')
|
||||
registerCustomOutputTaskUnix('PsychoLT', '/Users/brianfopiano/Desktop/REMOTES/RemoteMinecraft/plugins')
|
||||
registerCustomOutputTaskUnix('PsychoLT', '/Users/brianfopiano/Developer/RemoteGit/Server/plugins')
|
||||
registerCustomOutputTaskUnix('PixelMac', '/Users/test/Desktop/mcserver/plugins')
|
||||
registerCustomOutputTaskUnix('CrazyDev22LT', '/home/julian/Desktop/server/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()
|
||||
def NMS_BINDINGS = Map.of(
|
||||
"v1_21_R2", "1.21.3-R0.1-SNAPSHOT",
|
||||
"v1_21_R1", "1.21.1-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()
|
||||
NMS_BINDINGS.each { nms ->
|
||||
project(":nms:${nms.key}") {
|
||||
apply plugin: 'java'
|
||||
apply plugin: 'com.volmit.nmstools'
|
||||
|
||||
nmsTools {
|
||||
it.jvm = JVM_VERSION.getOrDefault(nms.key, 21)
|
||||
it.version = nms.value
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation project(":core")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unified repo
|
||||
*/
|
||||
shadowJar {
|
||||
NMS_BINDINGS.each {
|
||||
dependsOn(":nms:${it.key}:remap")
|
||||
from("${project(":nms:${it.key}").layout.buildDirectory.asFile.get()}/libs/${it.key}-mapped.jar")
|
||||
}
|
||||
|
||||
//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'
|
||||
relocate 'org.bstats', 'com.volmit.util.metrics'
|
||||
archiveFileName.set("Iris-${project.version}.jar")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation project(':core')
|
||||
}
|
||||
|
||||
configurations.configureEach {
|
||||
resolutionStrategy.cacheChangingModulesFor 60, 'minutes'
|
||||
resolutionStrategy.cacheDynamicVersionsFor 60, 'minutes'
|
||||
}
|
||||
|
||||
allprojects {
|
||||
apply plugin: 'java'
|
||||
|
||||
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://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.nexomc.com/snapshots/" }
|
||||
maven { url "https://libraries.minecraft.net" }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// Provided or Classpath
|
||||
compileOnly 'org.projectlombok:lombok:1.18.36'
|
||||
annotationProcessor 'org.projectlombok:lombok:1.18.36'
|
||||
|
||||
// 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.bstats:bstats-bukkit:3.1.0'
|
||||
//implementation 'org.bytedeco:javacpp:1.5.10'
|
||||
//implementation 'org.bytedeco:cuda-platform:12.3-8.9-1.5.10'
|
||||
compileOnly 'io.lumine:Mythic-Dist:5.2.1'
|
||||
compileOnly 'io.lumine:MythicCrucible-Dist:2.0.0'
|
||||
|
||||
// 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 'com.github.oshi:oshi-core:6.6.5'
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -85,209 +160,64 @@ repositories {
|
||||
*/
|
||||
compileJava {
|
||||
options.compilerArgs << '-parameters'
|
||||
options.encoding = "UTF-8"
|
||||
}
|
||||
|
||||
/**
|
||||
* 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:'))
|
||||
javadoc {
|
||||
options.encoding = "UTF-8"
|
||||
options.addStringOption('Xdoclint:none', '-quiet')
|
||||
}
|
||||
|
||||
task sourcesJar(type: Jar, dependsOn: classes) {
|
||||
archiveClassifier.set('sources')
|
||||
from sourceSets.main.allSource
|
||||
}
|
||||
|
||||
task javadocJar(type: Jar, dependsOn: javadoc) {
|
||||
archiveClassifier.set('javadoc')
|
||||
from javadoc.destinationDir
|
||||
}
|
||||
}
|
||||
|
||||
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") {
|
||||
if (JavaVersion.current().toString() != "21") {
|
||||
System.err.println()
|
||||
System.err.println("=========================================================================================================")
|
||||
System.err.println("You must run gradle on Java 17. You are using " + JavaVersion.current())
|
||||
System.err.println("You must run gradle on Java 21. 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("1. Configure the project for Java 21")
|
||||
System.err.println("2. Configure the bundled gradle to use Java 21 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("1. Install JDK 21 from https://www.oracle.com/java/technologies/javase/jdk21-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-21.0.4")
|
||||
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)
|
||||
{
|
||||
task iris(type: Copy) {
|
||||
group "iris"
|
||||
from ssJar
|
||||
into buildDir
|
||||
from new File(layout.buildDirectory.asFile.get(), "libs/Iris-${version}.jar")
|
||||
into layout.buildDirectory.asFile.get()
|
||||
dependsOn(build)
|
||||
}
|
||||
|
||||
// with classifier: 'javadoc' and 'sources'
|
||||
task irisDev(type: Copy) {
|
||||
group "iris"
|
||||
from("core/build/libs/core-javadoc.jar", "core/build/libs/core-sources.jar")
|
||||
rename { String fileName ->
|
||||
fileName.replace('Iris-' + version + '-rma.jar', "Iris-" + version + ".jar")
|
||||
fileName.replace("core", "Iris-${version}")
|
||||
}
|
||||
dependsOn(specialSourceRemap)
|
||||
into layout.buildDirectory.asFile.get()
|
||||
dependsOn(iris)
|
||||
dependsOn("core:sourcesJar")
|
||||
dependsOn("core:javadocJar")
|
||||
}
|
||||
|
||||
|
||||
def registerCustomOutputTask(name, path) {
|
||||
if (!System.properties['os.name'].toLowerCase().contains('windows')) {
|
||||
return;
|
||||
@@ -321,3 +251,5 @@ def registerCustomOutputTaskUnix(name, path) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.build.dependsOn(shadowJar)
|
||||
|
||||
95
core/build.gradle
Normal file
95
core/build.gradle
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* 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 "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 'com.nexomc:nexo:0.6.0-dev.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')
|
||||
}
|
||||
|
||||
java {
|
||||
disableAutoTargetJvm()
|
||||
}
|
||||
|
||||
/**
|
||||
* 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()
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -23,9 +23,13 @@ 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.*;
|
||||
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.service.StudioSVC;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.engine.EnginePanic;
|
||||
@@ -34,18 +38,24 @@ 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.core.safeguard.IrisSafeguard;
|
||||
import com.volmit.iris.core.safeguard.UtilsSFG;
|
||||
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.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.*;
|
||||
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;
|
||||
@@ -55,37 +65,46 @@ import com.volmit.iris.util.scheduling.ShurikenQueue;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
|
||||
import net.kyori.adventure.text.serializer.ComponentSerializer;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.WorldCreator;
|
||||
import org.bstats.bukkit.Metrics;
|
||||
import org.bstats.charts.DrilldownPie;
|
||||
import org.bstats.charts.SimplePie;
|
||||
import org.bstats.charts.SingleLineChart;
|
||||
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.event.*;
|
||||
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 oshi.SystemInfo;
|
||||
|
||||
import java.io.*;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.math.RoundingMode;
|
||||
import java.net.URL;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.text.NumberFormat;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.volmit.iris.core.safeguard.IrisSafeguard.*;
|
||||
import static com.volmit.iris.core.safeguard.ServerBootSFG.passedserversoftware;
|
||||
|
||||
@SuppressWarnings("CanBeFinal")
|
||||
public class Iris extends VolmitPlugin implements Listener {
|
||||
public static final String OVERWORLD_TAG = "31000";
|
||||
|
||||
private static final Queue<Runnable> syncJobs = new ShurikenQueue<>();
|
||||
|
||||
public static Iris instance;
|
||||
public static BukkitAudiences audiences;
|
||||
public static MultiverseCoreLink linkMultiverseCore;
|
||||
@@ -107,6 +126,10 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -173,15 +196,16 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
|
||||
public static void msg(String string) {
|
||||
try {
|
||||
sender.sendMessage(string);
|
||||
getSender().sendMessage(string);
|
||||
} catch (Throwable e) {
|
||||
try {
|
||||
System.out.println(instance.getTag() + string.replaceAll("(<([^>]+)>)", ""));
|
||||
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);
|
||||
@@ -295,8 +319,11 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
msg(C.IRIS + string);
|
||||
}
|
||||
|
||||
public static void info(String string) {
|
||||
msg(C.WHITE + 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")
|
||||
@@ -326,7 +353,7 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
}
|
||||
}
|
||||
|
||||
private static int getJavaVersion() {
|
||||
public static int getJavaVersion() {
|
||||
String version = System.getProperty("java.version");
|
||||
if (version.startsWith("1.")) {
|
||||
version = version.substring(2, 3);
|
||||
@@ -339,6 +366,13 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
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");
|
||||
@@ -381,16 +415,52 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
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"));
|
||||
setupAudience();
|
||||
sender = new VolmitSender(Bukkit.getConsoleSender());
|
||||
sender.setTag(getTag());
|
||||
instance = this;
|
||||
IrisSafeguard.IrisSafeguardSystem();
|
||||
getSender().setTag(getTag());
|
||||
compat = IrisCompat.configured(getDataFile("compat.json"));
|
||||
linkMultiverseCore = new MultiverseCoreLink();
|
||||
linkMythicMobs = new MythicMobsLink();
|
||||
@@ -400,12 +470,15 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
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());
|
||||
@@ -417,35 +490,37 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
FileConfiguration fc = new YamlConfiguration();
|
||||
try {
|
||||
fc.load(new File("bukkit.yml"));
|
||||
searching: for(String i : fc.getKeys(true))
|
||||
{
|
||||
if(i.startsWith("worlds.") && i.endsWith(".generator")) {
|
||||
String worldName = i.split("\\Q.\\E")[1];
|
||||
String generator = IrisSettings.get().getGenerator().getDefaultWorldType();
|
||||
if(fc.getString(i).startsWith("Iris:")) {
|
||||
generator = fc.getString(i).split("\\Q:\\E")[1];
|
||||
} else if(fc.getString(i).equals("Iris")) {
|
||||
ConfigurationSection section = fc.getConfigurationSection("worlds");
|
||||
if (section == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (String s : section.getKeys(false)) {
|
||||
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;
|
||||
}
|
||||
|
||||
for(World j : Bukkit.getWorlds())
|
||||
{
|
||||
if(j.getName().equals(worldName))
|
||||
{
|
||||
continue searching;
|
||||
}
|
||||
}
|
||||
if (Bukkit.getWorld(s) != null)
|
||||
continue;
|
||||
|
||||
Iris.warn("Detected an Iris World in the bukkit yml '" + worldName + "' using Iris that was not loaded by bukkit. Good Guy Iris will load it up for you!");
|
||||
Iris.info(C.LIGHT_PURPLE + "Preparing Spawn for " + worldName + "' using Iris:" + generator);
|
||||
World world = new WorldCreator(worldName)
|
||||
.generator(getDefaultWorldGenerator(worldName, generator))
|
||||
Iris.info("Loading World: %s | Generator: %s", s, generator);
|
||||
|
||||
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 " + worldName + "!");
|
||||
}
|
||||
Iris.info(C.LIGHT_PURPLE + "Loaded " + s + "!");
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
@@ -457,7 +532,7 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
Iris.info("Starting up auto Studio!");
|
||||
try {
|
||||
Player r = new KList<>(getServer().getOnlinePlayers()).getRandom();
|
||||
Iris.service(StudioSVC.class).open(r != null ? new VolmitSender(r) : sender, 1337, IrisSettings.get().getGenerator().getDefaultWorldType(), (w) -> {
|
||||
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);
|
||||
@@ -482,48 +557,15 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
System.out.println("DUMPED! See " + fi.getAbsolutePath());
|
||||
} catch(Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void postShutdown(Runnable r) {
|
||||
postShutdown.add(r);
|
||||
}
|
||||
|
||||
public static void panic() {
|
||||
EnginePanic.panic();
|
||||
}
|
||||
|
||||
public static void addPanic(String s, String v) {
|
||||
EnginePanic.add(s, v);
|
||||
}
|
||||
|
||||
public void onEnable() {
|
||||
enable();
|
||||
super.onEnable();
|
||||
Bukkit.getPluginManager().registerEvents(this, this);
|
||||
setupChecks();
|
||||
}
|
||||
|
||||
public void onDisable() {
|
||||
@@ -536,10 +578,6 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
super.onDisable();
|
||||
}
|
||||
|
||||
private static void fixShading() {
|
||||
ShadeFix.fix(ComponentSerializer.class);
|
||||
}
|
||||
|
||||
private void setupPapi() {
|
||||
if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null) {
|
||||
new IrisPapiExpansion().register();
|
||||
@@ -558,7 +596,39 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
|
||||
@Override
|
||||
public String getTag(String subTag) {
|
||||
if (unstablemode) {
|
||||
return C.BOLD + "" + C.DARK_GRAY + "[" + C.BOLD + "" + C.RED + "Iris" + C.BOLD + C.DARK_GRAY + "]" + C.RESET + "" + C.GRAY + ": ";
|
||||
}
|
||||
if (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("Version Information: " + 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() {
|
||||
@@ -591,7 +661,48 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
|
||||
private void bstats() {
|
||||
if (IrisSettings.get().getGeneral().isPluginMetrics()) {
|
||||
J.s(() -> new Metrics(Iris.instance, 8757));
|
||||
J.s(() -> {
|
||||
var metrics = new Metrics(Iris.instance, 24220);
|
||||
metrics.addCustomChart(new SingleLineChart("custom_dimensions", () -> Bukkit.getWorlds()
|
||||
.stream()
|
||||
.filter(IrisToolbelt::isIrisWorld)
|
||||
.mapToInt(w -> 1)
|
||||
.sum()));
|
||||
|
||||
metrics.addCustomChart(new DrilldownPie("used_packs", () -> Bukkit.getWorlds().stream()
|
||||
.map(IrisToolbelt::access)
|
||||
.filter(Objects::nonNull)
|
||||
.map(PlatformChunkGenerator::getTarget)
|
||||
.collect(Collectors.toMap(target -> target.getDimension().getLoadKey(), target -> {
|
||||
int version = target.getDimension().getVersion();
|
||||
String checksum = IO.hashRecursive(target.getData().getDataFolder());
|
||||
|
||||
return Map.of("v" + version + " (" + checksum + ")", 1);
|
||||
}, (a, b) -> {
|
||||
Map<String, Integer> merged = new HashMap<>(a);
|
||||
b.forEach((k, v) -> merged.merge(k, v, Integer::sum));
|
||||
return merged;
|
||||
}))));
|
||||
|
||||
|
||||
var info = new SystemInfo().getHardware();
|
||||
var cpu = info.getProcessor().getProcessorIdentifier();
|
||||
var mem = info.getMemory();
|
||||
metrics.addCustomChart(new SimplePie("cpu_model", cpu::getName));
|
||||
|
||||
var nf = NumberFormat.getInstance(Locale.ENGLISH);
|
||||
nf.setMinimumFractionDigits(0);
|
||||
nf.setMaximumFractionDigits(2);
|
||||
nf.setRoundingMode(RoundingMode.HALF_UP);
|
||||
|
||||
metrics.addCustomChart(new DrilldownPie("memory", () -> {
|
||||
double total = mem.getTotal() * 1E-9;
|
||||
double alloc = Math.min(total, Runtime.getRuntime().maxMemory() * 1E-9);
|
||||
return Map.of(nf.format(alloc), Map.of(nf.format(total), 1));
|
||||
}));
|
||||
|
||||
postShutdown.add(metrics::shutdown);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -653,7 +764,7 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
.name(worldName)
|
||||
.seed(1337)
|
||||
.environment(dim.getEnvironment())
|
||||
.worldFolder(new File(worldName))
|
||||
.worldFolder(new File(Bukkit.getWorldContainer(), worldName))
|
||||
.minHeight(dim.getMinHeight())
|
||||
.maxHeight(dim.getMaxHeight())
|
||||
.build();
|
||||
@@ -663,10 +774,10 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
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());
|
||||
service(StudioSVC.class).installIntoWorld(getSender(), dim.getLoadKey(), w.worldFolder());
|
||||
}
|
||||
|
||||
return new BukkitChunkGenerator(w, false, ff, dim.getLoadKey());
|
||||
return new BukkitChunkGenerator(w, false, ff, dim.getLoadKey(), false);
|
||||
}
|
||||
|
||||
public void splash() {
|
||||
@@ -674,12 +785,17 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
return;
|
||||
}
|
||||
|
||||
// @NoArgsConstructor
|
||||
String padd = Form.repeat(" ", 8);
|
||||
String padd2 = Form.repeat(" ", 4);
|
||||
String[] info = {"", "", "", "", "", padd2 + C.IRIS + " Iris", padd2 + C.GRAY + " by " + "<rainbow>Volmit Software", padd2 + C.GRAY + " v" + C.IRIS + getDescription().getVersion(),
|
||||
};
|
||||
String[] splash = {
|
||||
String[] info = {"", "", "", "", "", padd2 + C.IRIS + " Iris", padd2 + C.GRAY + " by " + "<rainbow>Volmit Software", padd2 + C.GRAY + " v" + C.IRIS + getDescription().getVersion()};
|
||||
if (unstablemode) {
|
||||
info = new String[]{"", "", "", "", "", padd2 + C.RED + " Iris", padd2 + C.GRAY + " by " + C.DARK_RED + "Volmit Software", padd2 + C.GRAY + " v" + C.RED + getDescription().getVersion()};
|
||||
}
|
||||
if (warningmode) {
|
||||
info = new String[]{"", "", "", "", "", padd2 + C.GOLD + " Iris", padd2 + C.GRAY + " by " + C.GOLD + "Volmit Software", padd2 + C.GRAY + " v" + C.GOLD + getDescription().getVersion()};
|
||||
}
|
||||
|
||||
String[] splashstable = {
|
||||
padd + C.GRAY + " @@@@@@@@@@@@@@" + C.DARK_GRAY + "@@@",
|
||||
padd + C.GRAY + " @@&&&&&&&&&" + C.DARK_GRAY + "&&&&&&" + C.IRIS + " .(((()))). ",
|
||||
padd + C.GRAY + "@@@&&&&&&&&" + C.DARK_GRAY + "&&&&&" + C.IRIS + " .((((((())))))). ",
|
||||
@@ -692,11 +808,61 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
padd + C.GRAY + "" + C.IRIS + " '(((())))' " + C.DARK_GRAY + "&&&&&&&&" + C.GRAY + "&&&&&&&@@",
|
||||
padd + C.GRAY + " " + C.DARK_GRAY + "@@@" + C.GRAY + "@@@@@@@@@@@@@@"
|
||||
};
|
||||
//@done
|
||||
Iris.info("Server type & version: " + Bukkit.getVersion());
|
||||
Iris.info("Bukkit version: " + Bukkit.getBukkitVersion());
|
||||
Iris.info("Java version: " + getJavaVersion());
|
||||
|
||||
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 + "@@@@@@@@@@@@@@"
|
||||
};
|
||||
String[] splashwarning = {
|
||||
padd + C.GRAY + " @@@@@@@@@@@@@@" + C.DARK_GRAY + "@@@",
|
||||
padd + C.GRAY + " @@&&&&&&&&&" + C.DARK_GRAY + "&&&&&&" + C.GOLD + " .(((()))). ",
|
||||
padd + C.GRAY + "@@@&&&&&&&&" + C.DARK_GRAY + "&&&&&" + C.GOLD + " .((((((())))))). ",
|
||||
padd + C.GRAY + "@@@&&&&&" + C.DARK_GRAY + "&&&&&&&" + C.GOLD + " ((((((((())))))))) " + C.GRAY + " @",
|
||||
padd + C.GRAY + "@@@&&&&" + C.DARK_GRAY + "@@@@@&" + C.GOLD + " ((((((((-))))))))) " + C.GRAY + " @@",
|
||||
padd + C.GRAY + "@@@&&" + C.GOLD + " ((((((({ })))))))) " + C.GRAY + " &&@@@",
|
||||
padd + C.GRAY + "@@" + C.GOLD + " ((((((((-))))))))) " + C.DARK_GRAY + "&@@@@@" + C.GRAY + "&&&&@@@",
|
||||
padd + C.GRAY + "@" + C.GOLD + " ((((((((())))))))) " + C.DARK_GRAY + "&&&&&" + C.GRAY + "&&&&&&&@@@",
|
||||
padd + C.GRAY + "" + C.GOLD + " '((((((()))))))' " + C.DARK_GRAY + "&&&&&" + C.GRAY + "&&&&&&&&@@@",
|
||||
padd + C.GRAY + "" + C.GOLD + " '(((())))' " + C.DARK_GRAY + "&&&&&&&&" + C.GRAY + "&&&&&&&@@",
|
||||
padd + C.GRAY + " " + C.DARK_GRAY + "@@@" + C.GRAY + "@@@@@@@@@@@@@@"
|
||||
};
|
||||
String[] splash;
|
||||
File freeSpace = new File(Bukkit.getWorldContainer() + ".");
|
||||
if (unstablemode) {
|
||||
splash = splashunstable;
|
||||
} else if (warningmode) {
|
||||
splash = splashwarning;
|
||||
} else {
|
||||
splash = splashstable;
|
||||
}
|
||||
|
||||
if (!passedserversoftware) {
|
||||
Iris.info("Server type & version: " + C.RED + Bukkit.getVersion());
|
||||
} else { Iris.info("Server type & version: " + Bukkit.getVersion()); }
|
||||
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());
|
||||
setupChecks();
|
||||
printPacks();
|
||||
|
||||
for (int i = 0; i < info.length; i++) {
|
||||
@@ -723,7 +889,37 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
JsonObject json = JsonParser.parseReader(r).getAsJsonObject();
|
||||
if (json.has("version"))
|
||||
version = json.get("version").getAsString();
|
||||
} catch(IOException | JsonParseException ignored) { }
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,10 @@ import com.volmit.iris.util.io.IO;
|
||||
import com.volmit.iris.util.json.JSONException;
|
||||
import com.volmit.iris.util.json.JSONObject;
|
||||
import com.volmit.iris.util.plugin.VolmitSender;
|
||||
import com.volmit.iris.util.scheduling.ChronoLatch;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@@ -41,6 +44,7 @@ public class IrisSettings {
|
||||
private IrisSettingsConcurrency concurrency = new IrisSettingsConcurrency();
|
||||
private IrisSettingsStudio studio = new IrisSettingsStudio();
|
||||
private IrisSettingsPerformance performance = new IrisSettingsPerformance();
|
||||
private IrisSettingsUpdater updater = new IrisSettingsUpdater();
|
||||
|
||||
public static int getThreadCount(int c) {
|
||||
return switch (c) {
|
||||
@@ -50,89 +54,6 @@ public class IrisSettings {
|
||||
};
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class IrisSettingsAutoconfiguration {
|
||||
public boolean configureSpigotTimeoutTime = true;
|
||||
public boolean configurePaperWatchdogDelay = true;
|
||||
public boolean autoRestartOnCustomBiomeInstall = true;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class IrisAsyncTeleport {
|
||||
public boolean enabled = false;
|
||||
public int loadViewDistance = 2;
|
||||
public boolean urgent = false;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class IrisSettingsWorld {
|
||||
public IrisAsyncTeleport asyncTeleport = new IrisAsyncTeleport();
|
||||
public boolean postLoadBlockUpdates = true;
|
||||
public boolean forcePersistEntities = true;
|
||||
public boolean anbientEntitySpawningSystem = true;
|
||||
public long asyncTickIntervalMS = 700;
|
||||
public double targetSpawnEntitiesPerChunk = 0.95;
|
||||
public boolean markerEntitySpawningSystem = true;
|
||||
public boolean effectSystem = true;
|
||||
public boolean worldEditWandCUI = true;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class IrisSettingsConcurrency {
|
||||
public int parallelism = -1;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class IrisSettingsPerformance {
|
||||
public boolean trimMantleInStudio = false;
|
||||
public int mantleKeepAlive = 30;
|
||||
public int cacheSize = 4_096;
|
||||
public int resourceLoaderCacheSize = 1_024;
|
||||
public int objectLoaderCacheSize = 4_096;
|
||||
public int scriptLoaderCacheSize = 512;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class IrisSettingsGeneral {
|
||||
public boolean commandSounds = true;
|
||||
public boolean debug = false;
|
||||
public boolean disableNMS = false;
|
||||
public boolean pluginMetrics = true;
|
||||
public boolean splashLogoStartup = true;
|
||||
public boolean useConsoleCustomColors = true;
|
||||
public boolean useCustomColorsIngame = true;
|
||||
public String forceMainWorld = "";
|
||||
public int spinh = -20;
|
||||
public int spins = 7;
|
||||
public int spinb = 8;
|
||||
|
||||
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
|
||||
public boolean canUseCustomColors(VolmitSender volmitSender) {
|
||||
return volmitSender.isPlayer() ? useCustomColorsIngame : useConsoleCustomColors;
|
||||
}
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class IrisSettingsGUI {
|
||||
public boolean useServerLaunchedGuis = true;
|
||||
public boolean maximumPregenGuiFPS = false;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class IrisSettingsGenerator {
|
||||
public String defaultWorldType = "overworld";
|
||||
public int maxBiomeChildDepth = 4;
|
||||
public boolean preventLeafDecay = true;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class IrisSettingsStudio {
|
||||
public boolean studio = true;
|
||||
public boolean openVSCode = true;
|
||||
public boolean disableTimeAndWeather = true;
|
||||
public boolean autoStartDefaultStudio = false;
|
||||
}
|
||||
|
||||
public static IrisSettings get() {
|
||||
if (settings != null) {
|
||||
return settings;
|
||||
@@ -183,4 +104,115 @@ public class IrisSettings {
|
||||
Iris.reportError(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class IrisSettingsAutoconfiguration {
|
||||
public boolean configureSpigotTimeoutTime = true;
|
||||
public boolean configurePaperWatchdogDelay = true;
|
||||
public boolean autoRestartOnCustomBiomeInstall = true;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class IrisAsyncTeleport {
|
||||
public boolean enabled = false;
|
||||
public int loadViewDistance = 2;
|
||||
public boolean urgent = false;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class IrisSettingsWorld {
|
||||
public IrisAsyncTeleport asyncTeleport = new IrisAsyncTeleport();
|
||||
public boolean postLoadBlockUpdates = true;
|
||||
public boolean forcePersistEntities = true;
|
||||
public boolean anbientEntitySpawningSystem = true;
|
||||
public long asyncTickIntervalMS = 700;
|
||||
public double targetSpawnEntitiesPerChunk = 0.95;
|
||||
public boolean markerEntitySpawningSystem = true;
|
||||
public boolean effectSystem = true;
|
||||
public boolean worldEditWandCUI = true;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class IrisSettingsConcurrency {
|
||||
public int parallelism = -1;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class IrisSettingsPerformance {
|
||||
public boolean trimMantleInStudio = false;
|
||||
public int mantleKeepAlive = 30;
|
||||
public int cacheSize = 4_096;
|
||||
public int resourceLoaderCacheSize = 1_024;
|
||||
public int objectLoaderCacheSize = 4_096;
|
||||
public int scriptLoaderCacheSize = 512;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class IrisSettingsUpdater {
|
||||
public double threadMultiplier = 2;
|
||||
public double chunkLoadSensitivity = 0.7;
|
||||
public MsRange emptyMsRange = new MsRange(80, 100);
|
||||
public MsRange defaultMsRange = new MsRange(20, 40);
|
||||
|
||||
public double getThreadMultiplier() {
|
||||
return Math.min(Math.abs(threadMultiplier), 0.1);
|
||||
}
|
||||
|
||||
public double getChunkLoadSensitivity() {
|
||||
return Math.min(chunkLoadSensitivity, 0.9);
|
||||
}
|
||||
}
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class MsRange {
|
||||
public int min = 20;
|
||||
public int max = 40;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class IrisSettingsGeneral {
|
||||
public boolean DoomsdayAnnihilationSelfDestructMode = false;
|
||||
public boolean commandSounds = true;
|
||||
public boolean debug = false;
|
||||
public boolean disableNMS = false;
|
||||
public boolean pluginMetrics = true;
|
||||
public boolean splashLogoStartup = true;
|
||||
public boolean useConsoleCustomColors = true;
|
||||
public boolean useCustomColorsIngame = true;
|
||||
public String forceMainWorld = "";
|
||||
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.";
|
||||
|
||||
|
||||
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
|
||||
public boolean canUseCustomColors(VolmitSender volmitSender) {
|
||||
return volmitSender.isPlayer() ? useCustomColorsIngame : useConsoleCustomColors;
|
||||
}
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class IrisSettingsGUI {
|
||||
public boolean useServerLaunchedGuis = true;
|
||||
public boolean maximumPregenGuiFPS = false;
|
||||
public boolean colorMode = true;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class IrisSettingsGenerator {
|
||||
public String defaultWorldType = "overworld";
|
||||
public int maxBiomeChildDepth = 4;
|
||||
public boolean preventLeafDecay = true;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class IrisSettingsStudio {
|
||||
public boolean studio = true;
|
||||
public boolean openVSCode = true;
|
||||
public boolean disableTimeAndWeather = true;
|
||||
public boolean autoStartDefaultStudio = false;
|
||||
}
|
||||
}
|
||||
@@ -21,13 +21,15 @@ 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.core.nms.datapack.DataVersion;
|
||||
import com.volmit.iris.core.nms.datapack.IDataFixer;
|
||||
import com.volmit.iris.engine.object.IrisBiome;
|
||||
import com.volmit.iris.engine.object.IrisBiomeCustom;
|
||||
import com.volmit.iris.engine.object.IrisDimension;
|
||||
import com.volmit.iris.engine.object.IrisRange;
|
||||
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.io.IO;
|
||||
import com.volmit.iris.util.plugin.VolmitSender;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import org.bukkit.Bukkit;
|
||||
@@ -38,6 +40,7 @@ import org.bukkit.entity.Player;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class ServerConfigurator {
|
||||
@@ -55,19 +58,18 @@ public class ServerConfigurator {
|
||||
}
|
||||
|
||||
private static void increaseKeepAliveSpigot() throws IOException, InvalidConfigurationException {
|
||||
File spigotConfig = new File("config/spigot.yml");
|
||||
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(5) + " (5 minutes)");
|
||||
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();
|
||||
@@ -75,47 +77,51 @@ public class ServerConfigurator {
|
||||
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(3) + " (3 minutes)");
|
||||
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() {
|
||||
private static List<File> getDatapacksFolder() {
|
||||
if (!IrisSettings.get().getGeneral().forceMainWorld.isEmpty()) {
|
||||
return new File(IrisSettings.get().getGeneral().forceMainWorld + "/datapacks");
|
||||
return new KList<File>().qadd(new File(Bukkit.getWorldContainer(), IrisSettings.get().getGeneral().forceMainWorld + "/datapacks"));
|
||||
}
|
||||
|
||||
File props = new File("server.properties");
|
||||
|
||||
if(props.exists()) {
|
||||
try {
|
||||
KList<String> m = new KList<>(IO.readAll(props).split("\\Q\n\\E"));
|
||||
|
||||
for(String i : m) {
|
||||
if(i.trim().startsWith("level-name=")) {
|
||||
return new File(i.trim().split("\\Q=\\E")[1] + "/datapacks");
|
||||
}
|
||||
}
|
||||
} catch(IOException e) {
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
KList<File> worlds = new KList<>();
|
||||
Bukkit.getServer().getWorlds().forEach(w -> worlds.add(new File(w.getWorldFolder(), "datapacks")));
|
||||
return worlds;
|
||||
}
|
||||
|
||||
public static void installDataPacks(boolean fullInstall) {
|
||||
Iris.info("Checking Data Packs...");
|
||||
boolean reboot = false;
|
||||
File packs = new File("plugins/Iris/packs");
|
||||
File dpacks = getDatapacksFolder();
|
||||
installDataPacks(DataVersion.getDefault(), fullInstall);
|
||||
}
|
||||
|
||||
if(dpacks == null) {
|
||||
Iris.error("Cannot find the datapacks folder! Please try generating a default world first maybe? Is this a new server?");
|
||||
return;
|
||||
public static void installDataPacks(IDataFixer fixer, boolean fullInstall) {
|
||||
Iris.info("Checking Data Packs...");
|
||||
File packs = new File("plugins/Iris/packs");
|
||||
double ultimateMaxHeight = 0;
|
||||
double ultimateMinHeight = 0;
|
||||
if (packs.exists() && packs.isDirectory()) {
|
||||
for (File pack : packs.listFiles()) {
|
||||
IrisData data = IrisData.get(pack);
|
||||
if (pack.isDirectory()) {
|
||||
File dimensionsFolder = new File(pack, "dimensions");
|
||||
if (dimensionsFolder.exists() && dimensionsFolder.isDirectory()) {
|
||||
for (File file : dimensionsFolder.listFiles()) {
|
||||
if (file.isFile() && file.getName().endsWith(".json")) {
|
||||
IrisDimension dim = data.getDimensionLoader().load(file.getName().split("\\Q.\\E")[0]);
|
||||
if (ultimateMaxHeight < dim.getDimensionHeight().getMax()) {
|
||||
ultimateMaxHeight = dim.getDimensionHeight().getMax();
|
||||
}
|
||||
if (ultimateMinHeight > dim.getDimensionHeight().getMin()) {
|
||||
ultimateMinHeight = dim.getDimensionHeight().getMin();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (packs.exists()) {
|
||||
@@ -135,8 +141,8 @@ public class ServerConfigurator {
|
||||
}
|
||||
|
||||
Iris.verbose(" Checking Dimension " + dim.getLoadFile().getPath());
|
||||
if(dim.installDataPack(() -> data, dpacks)) {
|
||||
reboot = true;
|
||||
for (File dpack : getDatapacksFolder()) {
|
||||
dim.installDataPack(fixer, () -> data, dpack, ultimateMaxHeight, ultimateMinHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -147,19 +153,12 @@ public class ServerConfigurator {
|
||||
|
||||
Iris.info("Data Packs Setup!");
|
||||
|
||||
if(fullInstall) {
|
||||
if (fullInstall)
|
||||
verifyDataPacksPost(IrisSettings.get().getAutoConfiguration().isAutoRestartOnCustomBiomeInstall());
|
||||
}
|
||||
}
|
||||
|
||||
private static void verifyDataPacksPost(boolean allowRestarting) {
|
||||
File packs = new File("plugins/Iris/packs");
|
||||
File dpacks = getDatapacksFolder();
|
||||
|
||||
if(dpacks == null) {
|
||||
Iris.error("Cannot find the datapacks folder! Please try generating a default world first maybe? Is this a new server?");
|
||||
return;
|
||||
}
|
||||
|
||||
boolean bad = false;
|
||||
if (packs.exists()) {
|
||||
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 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.DeepSearchPregenerator;
|
||||
import com.volmit.iris.core.pregenerator.PregenTask;
|
||||
import com.volmit.iris.core.pregenerator.TurboPregenerator;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.util.data.Dimension;
|
||||
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 com.volmit.iris.util.math.Position2;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
@Decree(name = "DeepSearch", aliases = "search", description = "Pregenerate your Iris worlds!")
|
||||
public class CommandDeepSearch implements DecreeExecutor {
|
||||
public String worldName;
|
||||
@Decree(description = "DeepSearch 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, "DeepSearch.json");
|
||||
if (TurboFile.exists()) {
|
||||
if (DeepSearchPregenerator.getInstance() != null) {
|
||||
sender().sendMessage(C.BLUE + "DeepSearch is already in progress");
|
||||
Iris.info(C.YELLOW + "DeepSearch is already in progress");
|
||||
return;
|
||||
} else {
|
||||
try {
|
||||
TurboFile.delete();
|
||||
} catch (Exception e){
|
||||
Iris.error("Failed to delete the old instance file of DeepSearch!");
|
||||
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.");
|
||||
}
|
||||
|
||||
DeepSearchPregenerator.DeepSearchJob DeepSearchJob = DeepSearchPregenerator.DeepSearchJob.builder()
|
||||
.world(world)
|
||||
.radiusBlocks(radius)
|
||||
.position(0)
|
||||
.build();
|
||||
|
||||
File SearchGenFile = new File(worldDirectory, "DeepSearch.json");
|
||||
DeepSearchPregenerator pregenerator = new DeepSearchPregenerator(DeepSearchJob, SearchGenFile);
|
||||
pregenerator.start();
|
||||
|
||||
String msg = C.GREEN + "DeepSearch 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 DeepSearch task", aliases = "x")
|
||||
public void stop(@Param(aliases = "world", description = "The world to pause") World world) throws IOException {
|
||||
DeepSearchPregenerator DeepSearchInstance = DeepSearchPregenerator.getInstance();
|
||||
File worldDirectory = new File(Bukkit.getWorldContainer(), world.getName());
|
||||
File turboFile = new File(worldDirectory, "DeepSearch.json");
|
||||
|
||||
if (DeepSearchInstance != null) {
|
||||
DeepSearchInstance.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, "DeepSearch.json");
|
||||
if (TurboFile.exists()){
|
||||
TurboPregenerator.loadTurboGenerator(world.getName());
|
||||
sender().sendMessage(C.YELLOW + "Started DeepSearch back up!");
|
||||
} else {
|
||||
sender().sendMessage(C.YELLOW + "No active DeepSearch tasks to pause/unpause.");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,315 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 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.ServerConfigurator;
|
||||
import com.volmit.iris.core.loader.IrisData;
|
||||
import com.volmit.iris.core.nms.datapack.DataVersion;
|
||||
import com.volmit.iris.core.service.IrisEngineSVC;
|
||||
import com.volmit.iris.core.tools.IrisPackBenchmarking;
|
||||
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.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.CountingDataInputStream;
|
||||
import com.volmit.iris.util.io.IO;
|
||||
import com.volmit.iris.util.mantle.TectonicPlate;
|
||||
import com.volmit.iris.util.nbt.mca.MCAFile;
|
||||
import com.volmit.iris.util.nbt.mca.MCAUtil;
|
||||
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.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
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, sync = true)
|
||||
public void EngineStatus() {
|
||||
List<World> IrisWorlds = new ArrayList<>();
|
||||
int TotalLoadedChunks = 0;
|
||||
int TotalQueuedTectonicPlates = 0;
|
||||
int TotalNotQueuedTectonicPlates = 0;
|
||||
int TotalTectonicPlates = 0;
|
||||
|
||||
long lowestUnloadDuration = 0;
|
||||
long highestUnloadDuration = 0;
|
||||
|
||||
for (World world : Bukkit.getWorlds()) {
|
||||
try {
|
||||
if (IrisToolbelt.access(world).getEngine() != null) {
|
||||
IrisWorlds.add(world);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// no
|
||||
}
|
||||
}
|
||||
|
||||
for (World world : IrisWorlds) {
|
||||
Engine engine = IrisToolbelt.access(world).getEngine();
|
||||
TotalQueuedTectonicPlates += (int) engine.getMantle().getToUnload();
|
||||
TotalNotQueuedTectonicPlates += (int) engine.getMantle().getNotQueuedLoadedRegions();
|
||||
TotalTectonicPlates += engine.getMantle().getLoadedRegionCount();
|
||||
if (highestUnloadDuration <= (long) engine.getMantle().getTectonicDuration()) {
|
||||
highestUnloadDuration = (long) engine.getMantle().getTectonicDuration();
|
||||
}
|
||||
if (lowestUnloadDuration >= (long) engine.getMantle().getTectonicDuration()) {
|
||||
lowestUnloadDuration = (long) engine.getMantle().getTectonicDuration();
|
||||
}
|
||||
for (Chunk chunk : world.getLoadedChunks()) {
|
||||
if (chunk.isLoaded()) {
|
||||
TotalLoadedChunks++;
|
||||
}
|
||||
}
|
||||
}
|
||||
Iris.info("-------------------------");
|
||||
Iris.info(C.DARK_PURPLE + "Engine Status");
|
||||
Iris.info(C.DARK_PURPLE + "Total Loaded Chunks: " + C.LIGHT_PURPLE + TotalLoadedChunks);
|
||||
Iris.info(C.DARK_PURPLE + "Tectonic Limit: " + C.LIGHT_PURPLE + IrisEngineSVC.getTectonicLimit());
|
||||
Iris.info(C.DARK_PURPLE + "Tectonic Total Plates: " + C.LIGHT_PURPLE + TotalTectonicPlates);
|
||||
Iris.info(C.DARK_PURPLE + "Tectonic Active Plates: " + C.LIGHT_PURPLE + TotalNotQueuedTectonicPlates);
|
||||
Iris.info(C.DARK_PURPLE + "Tectonic ToUnload: " + C.LIGHT_PURPLE + TotalQueuedTectonicPlates);
|
||||
Iris.info(C.DARK_PURPLE + "Lowest Tectonic Unload Duration: " + C.LIGHT_PURPLE + Form.duration(lowestUnloadDuration));
|
||||
Iris.info(C.DARK_PURPLE + "Highest Tectonic Unload Duration: " + C.LIGHT_PURPLE + Form.duration(highestUnloadDuration));
|
||||
Iris.info(C.DARK_PURPLE + "Cache Size: " + C.LIGHT_PURPLE + Form.f(IrisData.cacheSize()));
|
||||
Iris.info("-------------------------");
|
||||
}
|
||||
|
||||
@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++;
|
||||
Iris.info("Loaded count: " + c );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Decree(description = "Test")
|
||||
public void packBenchmark(
|
||||
@Param(description = "The pack to bench", aliases = {"pack"}, defaultValue = "overworld")
|
||||
IrisDimension dimension,
|
||||
@Param(description = "Radius in regions", defaultValue = "5")
|
||||
int radius,
|
||||
@Param(description = "Open GUI while benchmarking", defaultValue = "false")
|
||||
boolean gui
|
||||
) {
|
||||
new IrisPackBenchmarking(dimension, radius, gui);
|
||||
}
|
||||
|
||||
@Decree(description = "Upgrade to another Minecraft version")
|
||||
public void upgrade(
|
||||
@Param(description = "The version to upgrade to", defaultValue = "latest") DataVersion version) {
|
||||
sender().sendMessage(C.GREEN + "Upgrading to " + version.getVersion() + "...");
|
||||
ServerConfigurator.installDataPacks(version.get(), false);
|
||||
sender().sendMessage(C.GREEN + "Done upgrading! You can now update your server version to " + version.getVersion());
|
||||
}
|
||||
|
||||
@Decree(description = "test")
|
||||
public void mca (
|
||||
@Param(description = "String") String world) {
|
||||
try {
|
||||
File[] McaFiles = new File(world, "region").listFiles((dir, name) -> name.endsWith(".mca"));
|
||||
for (File mca : McaFiles) {
|
||||
MCAFile MCARegion = MCAUtil.read(mca);
|
||||
}
|
||||
} 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 = "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();
|
||||
ExecutorService service = Executors.newFixedThreadPool(1);
|
||||
VolmitSender sender = sender();
|
||||
service.submit(() -> {
|
||||
try {
|
||||
CountingDataInputStream raw = CountingDataInputStream.wrap(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();
|
||||
CountingDataInputStream 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();
|
||||
}
|
||||
});
|
||||
service.shutdown();
|
||||
} else {
|
||||
Iris.info(C.RED + "Engine is null!");
|
||||
}
|
||||
}
|
||||
|
||||
private CountingDataInputStream createInput(File file, String algorithm) throws Throwable {
|
||||
FileInputStream in = new FileInputStream(file);
|
||||
|
||||
return CountingDataInputStream.wrap(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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,20 +20,14 @@ package com.volmit.iris.core.commands;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
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.format.C;
|
||||
|
||||
import java.awt.Desktop;
|
||||
import java.awt.*;
|
||||
|
||||
|
||||
@Decree(name = "edit", origin = DecreeOrigin.PLAYER, studio = true, description = "Edit something")
|
||||
@@ -34,7 +34,9 @@ public class CommandFind implements DecreeExecutor {
|
||||
@Decree(description = "Find a biome")
|
||||
public void biome(
|
||||
@Param(description = "The biome to look for")
|
||||
IrisBiome biome
|
||||
IrisBiome biome,
|
||||
@Param(description = "Should you be teleported", defaultValue = "true")
|
||||
boolean teleport
|
||||
) {
|
||||
Engine e = engine();
|
||||
|
||||
@@ -43,13 +45,15 @@ public class CommandFind implements DecreeExecutor {
|
||||
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
|
||||
IrisRegion region,
|
||||
@Param(description = "Should you be teleported", defaultValue = "true")
|
||||
boolean teleport
|
||||
) {
|
||||
Engine e = engine();
|
||||
|
||||
@@ -58,13 +62,15 @@ public class CommandFind implements DecreeExecutor {
|
||||
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
|
||||
IrisJigsawStructure structure,
|
||||
@Param(description = "Should you be teleported", defaultValue = "true")
|
||||
boolean teleport
|
||||
) {
|
||||
Engine e = engine();
|
||||
|
||||
@@ -73,13 +79,31 @@ public class CommandFind implements DecreeExecutor {
|
||||
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
|
||||
String object,
|
||||
@Param(description = "Should you be teleported", defaultValue = "true")
|
||||
boolean teleport
|
||||
) {
|
||||
Engine e = engine();
|
||||
|
||||
@@ -88,6 +112,6 @@ public class CommandFind implements DecreeExecutor {
|
||||
return;
|
||||
}
|
||||
|
||||
e.gotoObject(object, player());
|
||||
e.gotoObject(object, player(), teleport);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,654 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 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.ServerConfigurator;
|
||||
import com.volmit.iris.core.loader.IrisData;
|
||||
import com.volmit.iris.core.nms.datapack.DataVersion;
|
||||
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.core.safeguard.UtilsSFG;
|
||||
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 lombok.Getter;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Difficulty;
|
||||
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.Console;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
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 com.volmit.iris.core.safeguard.IrisSafeguard.unstablemode;
|
||||
import static com.volmit.iris.core.safeguard.ServerBootSFG.incompatibilities;
|
||||
import static org.bukkit.Bukkit.getServer;
|
||||
|
||||
@Decree(name = "iris", aliases = {"ir", "irs"}, description = "Basic Command")
|
||||
public class CommandIris implements DecreeExecutor {
|
||||
private CommandStudio studio;
|
||||
private CommandPregen pregen;
|
||||
private CommandLazyPregen lazyPregen;
|
||||
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 worldCreation = false;
|
||||
String WorldEngine;
|
||||
String worldNameToCheck = "YourWorldName";
|
||||
VolmitSender sender = Iris.getSender();
|
||||
|
||||
@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 = "If it should convert the dimension to match the vanilla height system.", defaultValue = "false")
|
||||
boolean vanillaheight
|
||||
) {
|
||||
if(sender() instanceof Player) {
|
||||
if (incompatibilities.get("Multiverse-Core")) {
|
||||
sender().sendMessage(C.RED + "Your server has an incompatibility that may corrupt all worlds on the server if not handled properly.");
|
||||
sender().sendMessage(C.RED + "it is strongly advised for you to take action. see log for full detail");
|
||||
sender().sendMessage(C.RED + "----------------------------------------------------------------");
|
||||
sender().sendMessage(C.RED + "Command ran: /iris create");
|
||||
sender().sendMessage(C.RED + UtilsSFG.MSGIncompatibleWarnings());
|
||||
sender().sendMessage(C.RED + "----------------------------------------------------------------");
|
||||
}
|
||||
if (unstablemode && !incompatibilities.get("Multiverse-Core")) {
|
||||
sender().sendMessage(C.RED + "Your server is experiencing an incompatibility with the Iris plugin.");
|
||||
sender().sendMessage(C.RED + "Please rectify this problem to avoid further complications.");
|
||||
sender().sendMessage(C.RED + "----------------------------------------------------------------");
|
||||
sender().sendMessage(C.RED + "Command ran: /iris create");
|
||||
sender().sendMessage(C.RED + UtilsSFG.MSGIncompatibleWarnings());
|
||||
sender().sendMessage(C.RED + "----------------------------------------------------------------");
|
||||
}
|
||||
}
|
||||
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)
|
||||
.smartVanillaHeight(vanillaheight)
|
||||
.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 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.");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
/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();
|
||||
} */
|
||||
|
||||
@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;
|
||||
}
|
||||
|
||||
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 = "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", origin = DecreeOrigin.PLAYER, sync = true)
|
||||
public void unloadWorld(
|
||||
@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 loadWorld(
|
||||
@Param(description = "The name of the world to load")
|
||||
String world
|
||||
) {
|
||||
World worldloaded = Bukkit.getWorld(world);
|
||||
worldNameToCheck = world;
|
||||
boolean worldExists = doesWorldExist(worldNameToCheck);
|
||||
WorldEngine = world;
|
||||
|
||||
if (!worldExists) {
|
||||
sender().sendMessage(C.YELLOW + world + " Doesnt exist on the server.");
|
||||
return;
|
||||
}
|
||||
|
||||
File BUKKIT_YML = new File("bukkit.yml");
|
||||
String pathtodim = world + File.separator +"iris"+File.separator +"pack"+File.separator +"dimensions"+File.separator;
|
||||
File directory = new File(Bukkit.getWorldContainer(), pathtodim);
|
||||
|
||||
String dimension = null;
|
||||
if (directory.exists() && directory.isDirectory()) {
|
||||
File[] files = directory.listFiles();
|
||||
if (files != null) {
|
||||
for (File file : files) {
|
||||
if (file.isFile()) {
|
||||
String fileName = file.getName();
|
||||
if (fileName.endsWith(".json")) {
|
||||
dimension = fileName.substring(0, fileName.length() - 5);
|
||||
sender().sendMessage(C.BLUE + "Generator: " + dimension);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
sender().sendMessage(C.GOLD + world + " is not an iris world.");
|
||||
return;
|
||||
}
|
||||
sender().sendMessage(C.GREEN + "Loading world: " + world);
|
||||
|
||||
YamlConfiguration yml = YamlConfiguration.loadConfiguration(BUKKIT_YML);
|
||||
String gen = "Iris:" + dimension;
|
||||
ConfigurationSection section = yml.contains("worlds") ? yml.getConfigurationSection("worlds") : yml.createSection("worlds");
|
||||
if (!section.contains(world)) {
|
||||
section.createSection(world).set("generator", gen);
|
||||
try {
|
||||
yml.save(BUKKIT_YML);
|
||||
Iris.info("Registered \"" + world + "\" in bukkit.yml");
|
||||
} catch (IOException e) {
|
||||
Iris.error("Failed to update bukkit.yml!");
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
}
|
||||
checkForBukkitWorlds(world);
|
||||
sender().sendMessage(C.GREEN + world + " loaded successfully.");
|
||||
}
|
||||
@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(), false);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
@@ -55,9 +57,16 @@ public class CommandJigsaw implements DecreeExecutor {
|
||||
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(), true);
|
||||
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")
|
||||
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 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.PregeneratorJob;
|
||||
import com.volmit.iris.core.pregenerator.LazyPregenerator;
|
||||
import com.volmit.iris.core.pregenerator.PregenTask;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
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 com.volmit.iris.util.math.Position2;
|
||||
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.");
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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,20 +49,12 @@ 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,
|
||||
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) {
|
||||
@@ -130,10 +118,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
|
||||
@@ -180,7 +166,7 @@ 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 ==");
|
||||
@@ -211,6 +197,30 @@ public class CommandObject implements DecreeExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
@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());
|
||||
@@ -229,6 +239,9 @@ public class CommandObject implements DecreeExecutor {
|
||||
|
||||
|
||||
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);
|
||||
@@ -255,6 +268,9 @@ public class CommandObject implements DecreeExecutor {
|
||||
if (WandSVC.isHoldingWand(player())) {
|
||||
Location[] g = WandSVC.getCuboid(player());
|
||||
|
||||
if (g == null) {
|
||||
return;
|
||||
}
|
||||
if (!here) {
|
||||
// TODO: WARNING HEIGHT
|
||||
g[1] = player().getTargetBlock(null, 256).getLocation().clone();
|
||||
@@ -278,6 +294,10 @@ public class CommandObject implements DecreeExecutor {
|
||||
if (WandSVC.isHoldingIrisWand(player())) {
|
||||
Location[] g = WandSVC.getCuboid(player());
|
||||
|
||||
if (g == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!here) {
|
||||
// TODO: WARNING HEIGHT
|
||||
g[0] = player().getTargetBlock(null, 256).getLocation().clone();
|
||||
@@ -319,8 +339,7 @@ public class CommandObject implements DecreeExecutor {
|
||||
|
||||
Map<Block, BlockData> futureChanges = new HashMap<>();
|
||||
|
||||
if(scale != 1)
|
||||
{
|
||||
if (scale != 1) {
|
||||
o = o.scaled(scale, IrisObjectPlacementScaleInterpolator.TRICUBIC);
|
||||
}
|
||||
|
||||
@@ -346,7 +365,7 @@ public class CommandObject implements DecreeExecutor {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
sender().sendMessage("Placed " + object);
|
||||
sender().sendMessage(C.IRIS + "Placed " + object);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -357,9 +376,11 @@ public class CommandObject implements DecreeExecutor {
|
||||
@Param(description = "The file to store it in, can use / for subfolders")
|
||||
String name,
|
||||
@Param(description = "Overwrite existing object files", defaultValue = "false", aliases = "force")
|
||||
boolean overwrite
|
||||
boolean overwrite,
|
||||
@Param(description = "Use legacy TileState serialization if possible", defaultValue = "true")
|
||||
boolean legacy
|
||||
) {
|
||||
IrisObject o = WandSVC.createSchematic(player());
|
||||
IrisObject o = WandSVC.createSchematic(player(), legacy);
|
||||
|
||||
if (o == null) {
|
||||
sender().sendMessage(C.YELLOW + "You need to hold your wand!");
|
||||
@@ -373,7 +394,7 @@ public class CommandObject implements DecreeExecutor {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
o.write(file);
|
||||
o.write(file, sender());
|
||||
} catch (IOException e) {
|
||||
sender().sendMessage(C.RED + "Failed to save object because of an IOException: " + e.getMessage());
|
||||
Iris.reportError(e);
|
||||
@@ -397,6 +418,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);
|
||||
@@ -415,7 +439,7 @@ public class CommandObject implements DecreeExecutor {
|
||||
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)
|
||||
@@ -427,8 +451,7 @@ public class CommandObject implements DecreeExecutor {
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -19,7 +19,9 @@
|
||||
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.LazyPregenerator;
|
||||
import com.volmit.iris.core.pregenerator.PregenTask;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.util.decree.DecreeExecutor;
|
||||
@@ -27,9 +29,12 @@ 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.math.Position2;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
@Decree(name = "pregen", aliases = "pregenerate", description = "Pregenerate your Iris worlds!")
|
||||
public class CommandPregen implements DecreeExecutor {
|
||||
@Decree(description = "Pregenerate a world")
|
||||
@@ -50,7 +55,8 @@ public class CommandPregen implements DecreeExecutor {
|
||||
int w = (radius >> 9 + 1) * 2;
|
||||
IrisToolbelt.pregenerate(PregenTask
|
||||
.builder()
|
||||
.center(new Position2(center))
|
||||
.center(new Position2(center.getBlockX() >> 9, center.getBlockZ() >> 9))
|
||||
.gui(true)
|
||||
.width(w)
|
||||
.height(w)
|
||||
.build(), world);
|
||||
@@ -67,7 +73,7 @@ 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");
|
||||
Iris.info( C.BLUE + "Finishing up mca region...");
|
||||
} else {
|
||||
sender().sendMessage(C.YELLOW + "No active pregeneration tasks to stop");
|
||||
}
|
||||
@@ -28,23 +28,12 @@ import com.volmit.iris.core.service.ConversionSVC;
|
||||
import com.volmit.iris.core.service.StudioSVC;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.object.InventorySlotType;
|
||||
import com.volmit.iris.engine.object.IrisBiome;
|
||||
import com.volmit.iris.engine.object.IrisBiomePaletteLayer;
|
||||
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.IrisInterpolator;
|
||||
import com.volmit.iris.engine.object.IrisLootTable;
|
||||
import com.volmit.iris.engine.object.IrisNoiseGenerator;
|
||||
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.IrisScript;
|
||||
import com.volmit.iris.engine.object.NoiseStyle;
|
||||
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;
|
||||
@@ -58,31 +47,24 @@ 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.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.noise.CNG;
|
||||
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.J;
|
||||
import com.volmit.iris.util.scheduling.O;
|
||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||
import com.volmit.iris.util.scheduling.jobs.Job;
|
||||
import com.volmit.iris.util.scheduling.jobs.JobCollection;
|
||||
import com.volmit.iris.util.scheduling.jobs.QueueJob;
|
||||
import com.volmit.iris.util.scheduling.jobs.SingleJob;
|
||||
import io.papermc.lib.PaperLib;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.FluidCollisionMode;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.event.inventory.InventoryType;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.util.BlockVector;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
@@ -91,23 +73,24 @@ 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.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.function.Consumer;
|
||||
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;
|
||||
//private CommandDeepSearch deepSearch;
|
||||
|
||||
public static String hrf(Duration duration) {
|
||||
return duration.toString().substring(2).replaceAll("(\\d[HMS])(?!$)", "$1 ").toLowerCase();
|
||||
}
|
||||
|
||||
private CommandFind find;
|
||||
private CommandEdit edit;
|
||||
|
||||
|
||||
@Decree(description = "Download a project.", aliases = "dl")
|
||||
public void download(
|
||||
@Param(name = "pack", description = "The pack to download", defaultValue = "overworld", aliases = "project")
|
||||
@@ -165,130 +148,6 @@ public class CommandStudio implements DecreeExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(description = "Clean an Iris Project, optionally beautifying JSON & fixing block ids with missing keys. Also rebuilds the vscode schemas. ")
|
||||
public void clean(
|
||||
@Param(description = "The project to update", contextual = true)
|
||||
IrisDimension project,
|
||||
|
||||
@Param(defaultValue = "true", description = "Filters all valid JSON files with a beautifier (indentation: 4)")
|
||||
boolean beautify,
|
||||
|
||||
@Param(name = "fix-ids", defaultValue = "true", description = "Fixes any block ids used such as \"dirt\" will be converted to \"minecraft:dirt\"")
|
||||
boolean fixIds,
|
||||
|
||||
@Param(name = "rewrite-objects", defaultValue = "false", description = "Imports all objects and re-writes them cleaning up positions & block data in the process.")
|
||||
boolean rewriteObjects
|
||||
) {
|
||||
KList<Job> jobs = new KList<>();
|
||||
KList<File> files = new KList<File>();
|
||||
files(Iris.instance.getDataFolder("packs", project.getLoadKey()), files);
|
||||
MultiBurst burst = MultiBurst.burst;
|
||||
|
||||
jobs.add(new SingleJob("Updating Workspace", () -> {
|
||||
if(!new IrisProject(Iris.service(StudioSVC.class).getWorkspaceFolder(project.getLoadKey())).updateWorkspace()) {
|
||||
sender().sendMessage(C.GOLD + "Invalid project: " + project.getLoadKey() + ". Try deleting the code-workspace file and try again.");
|
||||
}
|
||||
J.sleep(250);
|
||||
}));
|
||||
|
||||
sender().sendMessage("Files: " + files.size());
|
||||
|
||||
if(fixIds) {
|
||||
QueueJob<File> r = new QueueJob<>() {
|
||||
@Override
|
||||
public void execute(File f) {
|
||||
try {
|
||||
JSONObject p = new JSONObject(IO.readAll(f));
|
||||
fixBlocks(p);
|
||||
J.sleep(1);
|
||||
IO.writeAll(f, p.toString(4));
|
||||
|
||||
} catch(IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Fixing IDs";
|
||||
}
|
||||
};
|
||||
|
||||
r.queue(files);
|
||||
jobs.add(r);
|
||||
}
|
||||
|
||||
if(beautify) {
|
||||
QueueJob<File> r = new QueueJob<>() {
|
||||
@Override
|
||||
public void execute(File f) {
|
||||
try {
|
||||
JSONObject p = new JSONObject(IO.readAll(f));
|
||||
IO.writeAll(f, p.toString(4));
|
||||
J.sleep(1);
|
||||
} catch(IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Beautify";
|
||||
}
|
||||
};
|
||||
|
||||
r.queue(files);
|
||||
jobs.add(r);
|
||||
}
|
||||
|
||||
if(rewriteObjects) {
|
||||
QueueJob<Runnable> q = new QueueJob<>() {
|
||||
@Override
|
||||
public void execute(Runnable runnable) {
|
||||
runnable.run();
|
||||
J.sleep(50);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Rewriting Objects";
|
||||
}
|
||||
};
|
||||
|
||||
IrisData data = IrisData.get(Iris.service(StudioSVC.class).getWorkspaceFolder(project.getLoadKey()));
|
||||
for(String f : data.getObjectLoader().getPossibleKeys()) {
|
||||
Future<?> gg = burst.complete(() -> {
|
||||
File ff = data.getObjectLoader().findFile(f);
|
||||
IrisObject oo = new IrisObject(0, 0, 0);
|
||||
try {
|
||||
oo.read(ff);
|
||||
} catch(Throwable e) {
|
||||
Iris.error("FAILER TO READ: " + f);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
oo.write(ff);
|
||||
} catch(IOException e) {
|
||||
Iris.error("FAILURE TO WRITE: " + oo.getLoadFile());
|
||||
}
|
||||
});
|
||||
|
||||
q.queue(() -> {
|
||||
try {
|
||||
gg.get();
|
||||
} catch(InterruptedException | ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
jobs.add(q);
|
||||
}
|
||||
|
||||
new JobCollection("Cleaning", jobs).execute(sender());
|
||||
}
|
||||
|
||||
@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)
|
||||
@@ -297,12 +156,83 @@ public class CommandStudio implements DecreeExecutor {
|
||||
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().getRadius();
|
||||
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")
|
||||
@@ -372,7 +302,7 @@ public class CommandStudio implements DecreeExecutor {
|
||||
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);
|
||||
engine().addItems(true, inv, RNG.r, tables, InventorySlotType.STORAGE, player().getWorld(), 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());
|
||||
@@ -395,13 +325,80 @@ public class CommandStudio implements DecreeExecutor {
|
||||
inv.clear();
|
||||
}
|
||||
|
||||
engine().addItems(true, inv, new RNG(RNG.r.imax()), tables, InventorySlotType.STORAGE, player().getLocation().getBlockX(), player().getLocation().getBlockY(), player().getLocation().getBlockZ(), 1);
|
||||
engine().addItems(true, inv, new RNG(RNG.r.imax()), tables, InventorySlotType.STORAGE, player().getWorld(), 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(
|
||||
@Param(name = "world", description = "The world to open the generator for", contextual = true)
|
||||
@@ -435,6 +432,7 @@ public class CommandStudio implements DecreeExecutor {
|
||||
@Param(description = "The dimension to profile", contextual = true, defaultValue = "default")
|
||||
IrisDimension dimension
|
||||
) {
|
||||
// Todo: Make this more accurate
|
||||
File pack = dimension.getLoadFile().getParentFile().getParentFile();
|
||||
File report = Iris.instance.getDataFile("profile.txt");
|
||||
IrisProject project = new IrisProject(pack);
|
||||
@@ -618,19 +616,16 @@ public class CommandStudio implements DecreeExecutor {
|
||||
sender().sendMessage(C.GREEN + "Done! " + report.getPath());
|
||||
}
|
||||
|
||||
@Decree(description = "Summon an Iris Entity", origin = DecreeOrigin.PLAYER)
|
||||
public void summon(
|
||||
@Param(description = "The Iris Entity to spawn")
|
||||
@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 at which to spawn the entity", defaultValue = "self")
|
||||
@Param(description = "The location to spawn the entity at", contextual = true)
|
||||
Vector location
|
||||
) {
|
||||
if(!sender().isPlayer()) {
|
||||
sender().sendMessage(C.RED + "Players only (this is a config error. Ask support to add DecreeOrigin.PLAYER to the command you tried to run)");
|
||||
return;
|
||||
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.");
|
||||
}
|
||||
|
||||
sender().sendMessage(C.GREEN + "Spawning entity");
|
||||
entity.spawn(engine(), new Location(world(), location.getX(), location.getY(), location.getZ()));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 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.pregenerator.ChunkUpdater;
|
||||
import com.volmit.iris.core.service.IrisEngineSVC;
|
||||
import com.volmit.iris.core.tools.IrisPackBenchmarking;
|
||||
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.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.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.misc.Hastebin;
|
||||
import com.volmit.iris.util.misc.Platform;
|
||||
import com.volmit.iris.util.misc.getHardware;
|
||||
import com.volmit.iris.util.nbt.mca.MCAFile;
|
||||
import com.volmit.iris.util.nbt.mca.MCAUtil;
|
||||
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 oshi.SystemInfo;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.InetAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
@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,131 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 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.core.pregenerator.TurboPregenerator;
|
||||
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,96 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 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 org.bukkit.World;
|
||||
|
||||
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;
|
||||
|
||||
@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;
|
||||
}
|
||||
if (chunkUpdater != null) {
|
||||
chunkUpdater.stop();
|
||||
}
|
||||
|
||||
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( ) {
|
||||
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 + chunkUpdater.getName());
|
||||
} else {
|
||||
sender().sendMessage(C.IRIS + "Unpause task for: " + C.GRAY + chunkUpdater.getName());
|
||||
}
|
||||
} else {
|
||||
if (status) {
|
||||
Iris.info(C.IRIS + "Paused task for: " + C.GRAY + chunkUpdater.getName());
|
||||
} else {
|
||||
Iris.info(C.IRIS + "Unpause task for: " + C.GRAY + chunkUpdater.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(description = "Stops the updater")
|
||||
public void stop() {
|
||||
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 + chunkUpdater.getName());
|
||||
} else {
|
||||
Iris.info("Stopping Updater for: " + C.GRAY + chunkUpdater.getName());
|
||||
}
|
||||
chunkUpdater.stop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,9 @@ import com.volmit.iris.Iris;
|
||||
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.framework.Engine;
|
||||
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;
|
||||
@@ -37,6 +39,7 @@ import org.bukkit.Material;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
@Decree(name = "what", origin = DecreeOrigin.PLAYER, studio = true, description = "Iris What?")
|
||||
@@ -65,7 +68,7 @@ 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) {
|
||||
@@ -82,6 +85,19 @@ public class CommandWhat implements DecreeExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(description = "What region am i in?", origin = DecreeOrigin.PLAYER)
|
||||
public void region() {
|
||||
try {
|
||||
Chunk chunk = world().getChunkAt(player().getLocation().getBlockZ() / 16, player().getLocation().getBlockZ() / 16);
|
||||
IrisRegion r = engine().getRegion(chunk);
|
||||
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;
|
||||
@@ -147,7 +163,7 @@ public class CommandWhat implements DecreeExecutor {
|
||||
|
||||
sender().sendMessage("Found " + v.get() + " Nearby Markers (" + marker + ")");
|
||||
} else {
|
||||
sender().sendMessage("Iris worlds only.");
|
||||
sender().sendMessage(C.IRIS + "Iris worlds only.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
@@ -71,8 +66,7 @@ public class JigsawEditor implements Listener {
|
||||
}
|
||||
|
||||
editors.put(player, this);
|
||||
if(object == null)
|
||||
{
|
||||
if (object == null) {
|
||||
throw new RuntimeException("Object is null! " + piece.getObject());
|
||||
}
|
||||
this.object = object;
|
||||
@@ -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;
|
||||
@@ -195,8 +185,7 @@ public class JigsawEditor implements Listener {
|
||||
j.remove("placementOptions"); // otherwise
|
||||
|
||||
// Remove key in all objects in array
|
||||
for(JSONObject i : getObjectsInArray(j, "connectors"))
|
||||
{
|
||||
for (JSONObject i : getObjectsInArray(j)) {
|
||||
removeKey(i, "rotateConnector");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
package com.volmit.iris.core.events;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.object.InventorySlotType;
|
||||
import com.volmit.iris.engine.object.IrisLootTable;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import lombok.Getter;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.world.LootGenerateEvent;
|
||||
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.InventoryHolder;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.loot.LootContext;
|
||||
import org.bukkit.loot.LootTable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
@Getter
|
||||
public class IrisLootEvent extends Event {
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
private static final LootTable EMPTY = new LootTable() {
|
||||
@NotNull
|
||||
@Override
|
||||
public NamespacedKey getKey() {
|
||||
return new NamespacedKey(Iris.instance, "empty");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<ItemStack> populateLoot(@Nullable Random random, @NotNull LootContext context) {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fillInventory(@NotNull Inventory inventory, @Nullable Random random, @NotNull LootContext context) {
|
||||
}
|
||||
};
|
||||
|
||||
private final Engine engine;
|
||||
private final Block block;
|
||||
private final InventorySlotType slot;
|
||||
private final KList<IrisLootTable> tables;
|
||||
|
||||
/**
|
||||
* Constructor for IrisLootEvent with mode selection.
|
||||
*
|
||||
* @param engine The engine instance.
|
||||
* @param block The block associated with the event.
|
||||
* @param slot The inventory slot type.
|
||||
* @param tables The list of IrisLootTables. (mutable*)
|
||||
*/
|
||||
public IrisLootEvent(Engine engine, Block block, InventorySlotType slot, KList<IrisLootTable> tables) {
|
||||
this.engine = engine;
|
||||
this.block = block;
|
||||
this.slot = slot;
|
||||
this.tables = tables;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Required method to get the HandlerList for this event.
|
||||
*
|
||||
* @return The HandlerList.
|
||||
*/
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers the corresponding Bukkit loot event.
|
||||
* This method integrates your custom IrisLootTables with Bukkit's LootGenerateEvent,
|
||||
* allowing other plugins to modify or cancel the loot generation.
|
||||
*
|
||||
* @return true when the event was canceled
|
||||
*/
|
||||
public static boolean callLootEvent(KList<ItemStack> loot, Inventory inv, World world, int x, int y, int z) {
|
||||
InventoryHolder holder = inv.getHolder();
|
||||
Location loc = new Location(world, x, y, z);
|
||||
if (holder == null) {
|
||||
holder = new InventoryHolder() {
|
||||
@NotNull
|
||||
@Override
|
||||
public Inventory getInventory() {
|
||||
return inv;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
LootContext context = new LootContext.Builder(loc).build();
|
||||
LootGenerateEvent event = new LootGenerateEvent(world, null, holder, EMPTY, context, loot, true);
|
||||
if (!Bukkit.isPrimaryThread()) {
|
||||
Iris.warn("LootGenerateEvent was not called on the main thread, please report this issue.");
|
||||
Thread.dumpStack();
|
||||
J.sfut(() -> Bukkit.getPluginManager().callEvent(event)).join();
|
||||
} else Bukkit.getPluginManager().callEvent(event);
|
||||
|
||||
return event.isCancelled();
|
||||
}
|
||||
}
|
||||
@@ -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")
|
||||
@@ -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);
|
||||
@@ -289,11 +275,11 @@ public class NoiseExplorerGUI extends JPanel implements MouseWheelListener, List
|
||||
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) (0.666f - n * 0.666f), 1f, (float) (1f - n * 0.8f)) : Color.getHSBColor(0f, 0f, (float) n);
|
||||
int rgb = color.getRGB();
|
||||
img.setRGB(xx, z, rgb);
|
||||
} catch(Throwable xxx) {
|
||||
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -24,6 +24,7 @@ import com.volmit.iris.core.pregenerator.IrisPregenerator;
|
||||
import com.volmit.iris.core.pregenerator.PregenListener;
|
||||
import com.volmit.iris.core.pregenerator.PregenTask;
|
||||
import com.volmit.iris.core.pregenerator.PregeneratorMethod;
|
||||
import com.volmit.iris.core.tools.IrisPackBenchmarking;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
@@ -35,12 +36,8 @@ import com.volmit.iris.util.math.Position2;
|
||||
import com.volmit.iris.util.scheduling.ChronoLatch;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
|
||||
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;
|
||||
@@ -48,6 +45,8 @@ import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import static com.volmit.iris.core.tools.IrisPackBenchmarking.benchmarkInProgress;
|
||||
|
||||
public class PregeneratorJob implements PregenListener {
|
||||
private static final Color COLOR_EXISTS = parseColor("#4d7d5b");
|
||||
private static final Color COLOR_BLACK = parseColor("#4d7d5b");
|
||||
@@ -66,12 +65,12 @@ 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;
|
||||
@@ -83,7 +82,6 @@ public class PregeneratorJob implements PregenListener {
|
||||
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,15 +89,16 @@ 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);
|
||||
}
|
||||
|
||||
public Mantle getMantle() {
|
||||
return pregenerator.getMantle();
|
||||
var t = new Thread(() -> {
|
||||
J.sleep(1000);
|
||||
this.pregenerator.start();
|
||||
}, "Iris Pregenerator");
|
||||
t.setPriority(Thread.MIN_PRIORITY);
|
||||
t.start();
|
||||
}
|
||||
|
||||
public static boolean shutdownInstance() {
|
||||
@@ -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,12 +162,10 @@ public class PregeneratorJob implements PregenListener {
|
||||
}
|
||||
|
||||
public void drawRegion(int x, int z, Color color) {
|
||||
J.a(() -> {
|
||||
PregenTask.iterateRegion(x, z, (xx, zz) -> {
|
||||
J.a(() -> PregenTask.iterateRegion(x, z, (xx, zz) -> {
|
||||
draw(xx, zz, color);
|
||||
J.sleep(3);
|
||||
});
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
public void draw(int x, int z, Color color) {
|
||||
@@ -173,7 +174,7 @@ public class PregeneratorJob implements PregenListener {
|
||||
renderer.func.accept(new Position2(x, z), color);
|
||||
}
|
||||
} 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,8 +215,8 @@ 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");
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -239,10 +239,6 @@ public class PregeneratorJob implements PregenListener {
|
||||
|
||||
@Override
|
||||
public void onChunkGenerating(int x, int z) {
|
||||
if(engine != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
draw(x, z, COLOR_GENERATING);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -218,12 +212,18 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
||||
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();
|
||||
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);
|
||||
@@ -433,13 +433,9 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
||||
|
||||
if (engine.isClosed()) {
|
||||
EventQueue.invokeLater(() -> {
|
||||
try
|
||||
{
|
||||
try {
|
||||
setVisible(false);
|
||||
}
|
||||
|
||||
catch(Throwable e)
|
||||
{
|
||||
} catch (Throwable e) {
|
||||
|
||||
}
|
||||
});
|
||||
@@ -739,7 +735,8 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
||||
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();
|
||||
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();
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 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;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
package com.volmit.iris.core.gui.components;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.*;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Renderer {
|
||||
@@ -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,77 @@
|
||||
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 org.jetbrains.annotations.NotNull;
|
||||
|
||||
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!");
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public BlockData getBlockData(@NotNull Identifier blockId, @NotNull KMap<String, String> state) throws MissingResourceException {
|
||||
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ItemStack getItemStack(@NotNull Identifier itemId, @NotNull 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();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Identifier[] getBlockTypes() {
|
||||
return new Identifier[0];
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@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(@NotNull Identifier id, boolean isItem) {
|
||||
return id.namespace().equalsIgnoreCase("ecoitems") && isItem;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
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 org.jetbrains.annotations.NotNull;
|
||||
|
||||
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...");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public BlockData getBlockData(@NotNull Identifier blockId, @NotNull KMap<String, String> state) throws MissingResourceException {
|
||||
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ItemStack getItemStack(@NotNull Identifier itemId, @NotNull 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()));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Identifier[] getBlockTypes() {
|
||||
return new Identifier[0];
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@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(@NotNull Identifier key, boolean isItem) {
|
||||
return key.namespace().equalsIgnoreCase("executable_items") && isItem;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
package com.volmit.iris.core.link;
|
||||
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.data.IrisBlockData;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
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 org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.MissingResourceException;
|
||||
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public abstract class ExternalDataProvider {
|
||||
|
||||
@NonNull
|
||||
private final String pluginId;
|
||||
|
||||
@Nullable
|
||||
public Plugin getPlugin() {
|
||||
return Bukkit.getPluginManager().getPlugin(pluginId);
|
||||
}
|
||||
|
||||
public boolean isReady() {
|
||||
return getPlugin() != null && getPlugin().isEnabled();
|
||||
}
|
||||
|
||||
public abstract void init();
|
||||
|
||||
/**
|
||||
* @see ExternalDataProvider#getBlockData(Identifier, KMap)
|
||||
*/
|
||||
@NotNull
|
||||
public BlockData getBlockData(@NotNull Identifier blockId) throws MissingResourceException {
|
||||
return getBlockData(blockId, new KMap<>());
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns a {@link BlockData} corresponding to the blockID
|
||||
* it is used in any place Iris accepts {@link BlockData}
|
||||
*
|
||||
* @param blockId The id of the block to get
|
||||
* @param state The state of the block to get
|
||||
* @return Corresponding {@link BlockData} to the blockId
|
||||
* may return {@link IrisBlockData} for blocks that need a world for placement
|
||||
* @throws MissingResourceException when the blockId is invalid
|
||||
*/
|
||||
@NotNull
|
||||
public abstract BlockData getBlockData(@NotNull Identifier blockId, @NotNull KMap<String, String> state) throws MissingResourceException;
|
||||
|
||||
/**
|
||||
* @see ExternalDataProvider#getItemStack(Identifier)
|
||||
*/
|
||||
@NotNull
|
||||
public ItemStack getItemStack(@NotNull Identifier itemId) throws MissingResourceException {
|
||||
return getItemStack(itemId, new KMap<>());
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns a {@link ItemStack} corresponding to the itemID
|
||||
* it is used in loot tables
|
||||
*
|
||||
* @param itemId The id of the item to get
|
||||
* @param customNbt Custom nbt to apply to the item
|
||||
* @return Corresponding {@link ItemStack} to the itemId
|
||||
* @throws MissingResourceException when the itemId is invalid
|
||||
*/
|
||||
@NotNull
|
||||
public abstract ItemStack getItemStack(@NotNull Identifier itemId, @NotNull KMap<String, Object> customNbt) throws MissingResourceException;
|
||||
|
||||
/**
|
||||
* This method is used for placing blocks that need to use the plugins api
|
||||
* it will only be called when the {@link ExternalDataProvider#getBlockData(Identifier, KMap)} returned a {@link IrisBlockData}
|
||||
*
|
||||
* @param engine The engine of the world the block is being placed in
|
||||
* @param block The block where the block should be placed
|
||||
* @param blockId The blockId to place
|
||||
*/
|
||||
public void processUpdate(@NotNull Engine engine, @NotNull Block block, @NotNull Identifier blockId) {}
|
||||
|
||||
public abstract @NotNull Identifier[] getBlockTypes();
|
||||
|
||||
public abstract @NotNull Identifier[] getItemTypes();
|
||||
|
||||
public abstract boolean isValidProvider(@NotNull Identifier id, boolean isItem);
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
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.IrisBlockData;
|
||||
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 org.jetbrains.annotations.NotNull;
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public BlockData getBlockData(@NotNull Identifier blockId, @NotNull 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 IrisBlockData(blockData, ExternalDataSVC.buildState(blockId, state));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ItemStack getItemStack(@NotNull Identifier itemId, @NotNull 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(@NotNull Engine engine, @NotNull Block block, @NotNull 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);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@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]);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@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(@NotNull 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());
|
||||
}
|
||||
}
|
||||
37
core/src/main/java/com/volmit/iris/core/link/Identifier.java
Normal file
37
core/src/main/java/com/volmit/iris/core/link/Identifier.java
Normal file
@@ -0,0 +1,37 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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,22 +54,22 @@ 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();
|
||||
return getBiome(a, l).getName();
|
||||
}
|
||||
} else if (p.equalsIgnoreCase("biome_id")) {
|
||||
if (a != null) {
|
||||
return a.getEngine().getBiome(l).getLoadKey();
|
||||
return getBiome(a, l).getLoadKey();
|
||||
}
|
||||
} else if (p.equalsIgnoreCase("biome_file")) {
|
||||
if (a != null) {
|
||||
return a.getEngine().getBiome(l).getLoadFile().getPath();
|
||||
return getBiome(a, l).getLoadFile().getPath();
|
||||
}
|
||||
} else if (p.equalsIgnoreCase("region_name")) {
|
||||
if (a != null) {
|
||||
@@ -107,4 +109,8 @@ public class IrisPapiExpansion extends PlaceholderExpansion {
|
||||
|
||||
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,76 @@
|
||||
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 org.jetbrains.annotations.NotNull;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public BlockData getBlockData(@NotNull Identifier blockId, @NotNull KMap<String, String> state) throws MissingResourceException {
|
||||
return CustomBlock.getBaseBlockData(blockId.toString());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ItemStack getItemStack(@NotNull Identifier itemId, @NotNull 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();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@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]);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@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(@NotNull Identifier id, boolean isItem) {
|
||||
return isItem ? this.itemNamespaces.contains(id.namespace()) : this.blockNamespaces.contains(id.namespace());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
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 org.jetbrains.annotations.NotNull;
|
||||
|
||||
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...");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public BlockData getBlockData(@NotNull Identifier blockId, @NotNull 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();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ItemStack getItemStack(@NotNull Identifier itemId, @NotNull 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;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@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]);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@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(@NotNull Identifier id, boolean isItem) {
|
||||
return isItem ? id.namespace().split("_", 2).length == 2 : id.namespace().equals("mmoitems");
|
||||
}
|
||||
|
||||
private MMOItems api() {
|
||||
return MMOItems.plugin;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 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.IrisBlockData;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import io.lumine.mythic.bukkit.BukkitAdapter;
|
||||
import io.lumine.mythic.bukkit.utils.serialize.Chroma;
|
||||
import io.lumine.mythiccrucible.MythicCrucible;
|
||||
import io.lumine.mythiccrucible.items.CrucibleItem;
|
||||
import io.lumine.mythiccrucible.items.ItemManager;
|
||||
import io.lumine.mythiccrucible.items.blocks.CustomBlockItemContext;
|
||||
import io.lumine.mythiccrucible.items.furniture.FurnitureItemContext;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.Optional;
|
||||
|
||||
public class MythicCrucibleDataProvider extends ExternalDataProvider {
|
||||
|
||||
private ItemManager itemManager;
|
||||
|
||||
public MythicCrucibleDataProvider() {
|
||||
super("MythicCrucible");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
Iris.info("Setting up MythicCrucible Link...");
|
||||
try {
|
||||
this.itemManager = MythicCrucible.inst().getItemManager();
|
||||
} catch (Exception e) {
|
||||
Iris.error("Failed to set up MythicCrucible Link: Unable to fetch MythicCrucible instance!");
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public BlockData getBlockData(@NotNull Identifier blockId, @NotNull KMap<String, String> state) throws MissingResourceException {
|
||||
CrucibleItem crucibleItem = this.itemManager.getItem(blockId.key())
|
||||
.orElseThrow(() -> new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key()));
|
||||
CustomBlockItemContext blockItemContext = crucibleItem.getBlockData();
|
||||
FurnitureItemContext furnitureItemContext = crucibleItem.getFurnitureData();
|
||||
if (furnitureItemContext != null) {
|
||||
return new IrisBlockData(B.getAir(), ExternalDataSVC.buildState(blockId, state));
|
||||
} else if (blockItemContext != null) {
|
||||
return blockItemContext.getBlockData();
|
||||
}
|
||||
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ItemStack getItemStack(@NotNull Identifier itemId, @NotNull KMap<String, Object> customNbt) throws MissingResourceException {
|
||||
Optional<CrucibleItem> opt = this.itemManager.getItem(itemId.key());
|
||||
return BukkitAdapter.adapt(opt.orElseThrow(() ->
|
||||
new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key()))
|
||||
.getMythicItem()
|
||||
.generateItemStack(1));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Identifier[] getBlockTypes() {
|
||||
KList<Identifier> names = new KList<>();
|
||||
for (CrucibleItem item : this.itemManager.getItems()) {
|
||||
if (item.getBlockData() == null) continue;
|
||||
try {
|
||||
Identifier key = new Identifier("crucible", item.getInternalName());
|
||||
if (getBlockData(key) != null) {
|
||||
Iris.info("getBlockTypes: Block loaded '" + item.getInternalName() + "'");
|
||||
names.add(key);
|
||||
}
|
||||
} catch (MissingResourceException ignored) {}
|
||||
}
|
||||
return names.toArray(new Identifier[0]);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Identifier[] getItemTypes() {
|
||||
KList<Identifier> names = new KList<>();
|
||||
for (CrucibleItem item : this.itemManager.getItems()) {
|
||||
try {
|
||||
Identifier key = new Identifier("crucible", item.getInternalName());
|
||||
if (getItemStack(key) != null) {
|
||||
Iris.info("getItemTypes: Item loaded '" + item.getInternalName() + "'");
|
||||
names.add(key);
|
||||
}
|
||||
} catch (MissingResourceException ignored) {}
|
||||
}
|
||||
return names.toArray(new Identifier[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processUpdate(@NotNull Engine engine, @NotNull Block block, @NotNull Identifier blockId) {
|
||||
var pair = ExternalDataSVC.parseState(blockId);
|
||||
var state = pair.getB();
|
||||
blockId = pair.getA();
|
||||
|
||||
Optional<CrucibleItem> item = itemManager.getItem(blockId.key());
|
||||
if (item.isEmpty()) return;
|
||||
FurnitureItemContext furniture = item.get().getFurnitureData();
|
||||
if (furniture == null) return;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
BiomeColor type = null;
|
||||
Chroma color = 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;
|
||||
color = Chroma.of(biomeColor.getRGB());
|
||||
}
|
||||
furniture.place(block, face, yaw, color);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidProvider(@NotNull Identifier key, boolean isItem) {
|
||||
return key.namespace().equalsIgnoreCase("crucible");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 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,164 @@
|
||||
package com.volmit.iris.core.link;
|
||||
|
||||
import com.nexomc.nexo.api.NexoBlocks;
|
||||
import com.nexomc.nexo.api.NexoFurniture;
|
||||
import com.nexomc.nexo.api.NexoItems;
|
||||
import com.nexomc.nexo.items.ItemBuilder;
|
||||
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.KMap;
|
||||
import com.volmit.iris.util.data.B;
|
||||
import com.volmit.iris.util.data.IrisBlockData;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import org.bukkit.Color;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.entity.ItemDisplay;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.PotionMeta;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public class NexoDataProvider extends ExternalDataProvider {
|
||||
private final AtomicBoolean failed = new AtomicBoolean(false);
|
||||
|
||||
public NexoDataProvider() {
|
||||
super("Nexo");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public BlockData getBlockData(@NotNull Identifier blockId, @NotNull KMap<String, String> state) throws MissingResourceException {
|
||||
if (!NexoItems.exists(blockId.key())) {
|
||||
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
|
||||
}
|
||||
|
||||
Identifier blockState = ExternalDataSVC.buildState(blockId, state);
|
||||
if (NexoBlocks.isCustomBlock(blockId.key())) {
|
||||
BlockData data = NexoBlocks.blockData(blockId.key());
|
||||
if (data == null)
|
||||
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
|
||||
return new IrisBlockData(data, blockState);
|
||||
} else if (NexoFurniture.isFurniture(blockId.key())) {
|
||||
return new IrisBlockData(B.getAir(), blockState);
|
||||
}
|
||||
|
||||
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ItemStack getItemStack(@NotNull Identifier itemId, @NotNull KMap<String, Object> customNbt) throws MissingResourceException {
|
||||
ItemBuilder builder = NexoItems.itemFromId(itemId.key());
|
||||
if (builder == null) {
|
||||
throw new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key());
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processUpdate(@NotNull Engine engine, @NotNull Block block, @NotNull Identifier blockId) {
|
||||
var pair = ExternalDataSVC.parseState(blockId);
|
||||
var state = pair.getB();
|
||||
blockId = pair.getA();
|
||||
|
||||
if (NexoBlocks.isCustomBlock(blockId.key())) {
|
||||
NexoBlocks.place(blockId.key(), block.getLocation());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!NexoFurniture.isFurniture(blockId.key()))
|
||||
return;
|
||||
|
||||
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;
|
||||
}
|
||||
ItemDisplay display = NexoFurniture.place(blockId.key(), block.getLocation(), yaw, face);
|
||||
if (display == null) return;
|
||||
ItemStack itemStack = display.getItemStack();
|
||||
if (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);
|
||||
}
|
||||
}
|
||||
display.setItemStack(itemStack);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Identifier[] getBlockTypes() {
|
||||
return Arrays.stream(NexoItems.itemNames())
|
||||
.map(i -> new Identifier("nexo", i))
|
||||
.filter(i -> {
|
||||
try {
|
||||
return getBlockData(i) != null;
|
||||
} catch (MissingResourceException e) {
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.toArray(Identifier[]::new);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Identifier[] getItemTypes() {
|
||||
return Arrays.stream(NexoItems.itemNames())
|
||||
.map(i -> new Identifier("nexo", i))
|
||||
.filter(i -> {
|
||||
try {
|
||||
return getItemStack(i) != null;
|
||||
} catch (MissingResourceException e) {
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.toArray(Identifier[]::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidProvider(@NotNull Identifier id, boolean isItem) {
|
||||
return "nexo".equalsIgnoreCase(id.namespace());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReady() {
|
||||
return super.isReady() && !failed.get();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
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 com.volmit.iris.util.data.KCache;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.time.Duration;
|
||||
import java.util.UUID;
|
||||
|
||||
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"));
|
||||
}
|
||||
}
|
||||
@@ -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) {
|
||||
@@ -66,6 +67,17 @@ public class ImageResourceLoader extends ResourceLoader<IrisImage> {
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
return possibleKeys;
|
||||
@@ -74,26 +86,31 @@ public class ImageResourceLoader extends ResourceLoader<IrisImage> {
|
||||
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", ""));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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;
|
||||
@@ -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,9 @@ 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.reflect.OldEnum;
|
||||
import com.volmit.iris.util.scheduling.ChronoLatch;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import lombok.Data;
|
||||
@@ -116,6 +114,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));
|
||||
}
|
||||
@@ -339,6 +338,15 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
||||
this.imageLoader = registerLoader(IrisImage.class);
|
||||
this.scriptLoader = registerLoader(IrisScript.class);
|
||||
this.matterObjectLoader = registerLoader(IrisMatterObject.class);
|
||||
if (OldEnum.exists()) {
|
||||
builder.registerTypeAdapterFactory(new TypeAdapterFactory() {
|
||||
@Override
|
||||
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
|
||||
return (TypeAdapter<T>) OldEnum.create(type.getRawType());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
gson = builder.create();
|
||||
}
|
||||
|
||||
@@ -371,8 +379,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() + ")");
|
||||
}
|
||||
@@ -437,6 +444,7 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
||||
return adapter.read(reader);
|
||||
} catch (Throwable e) {
|
||||
Iris.error("Failed to read " + typeToken.getRawType().getCanonicalName() + "... faking objects a little to load the file at least.");
|
||||
Iris.reportError(e);
|
||||
try {
|
||||
return (T) typeToken.getRawType().getConstructor().newInstance();
|
||||
} catch (Throwable ignored) {
|
||||
@@ -467,4 +475,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.");
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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());
|
||||
@@ -63,6 +65,16 @@ public class MatterObjectResourceLoader extends ResourceLoader<IrisMatterObject>
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
return possibleKeys;
|
||||
@@ -71,24 +83,8 @@ public class MatterObjectResourceLoader extends ResourceLoader<IrisMatterObject>
|
||||
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,6 +92,40 @@ 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()) {
|
||||
@@ -50,10 +50,10 @@ 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;
|
||||
@@ -68,33 +68,26 @@ public class ObjectResourceLoader extends ResourceLoader<IrisObject> {
|
||||
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", ""));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
m.addAll(getFiles(i, ".iob", true));
|
||||
}
|
||||
possibleKeys = m.toArray(new String[0]);
|
||||
return possibleKeys;
|
||||
}
|
||||
|
||||
KList<String> v = new KList<>(m);
|
||||
possibleKeys = v.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) {
|
||||
@@ -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();
|
||||
@@ -221,6 +233,24 @@ 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<>();
|
||||
|
||||
@@ -282,17 +312,62 @@ public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
||||
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) {
|
||||
KList<File> fc = new KList<>();
|
||||
|
||||
for(File i : root.listFiles()) {
|
||||
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);
|
||||
@@ -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) {
|
||||
@@ -60,39 +60,70 @@ public class ScriptResourceLoader extends ResourceLoader<IrisScript> {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public String[] getPossibleKeys() {
|
||||
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", ""));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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()) {
|
||||
@@ -20,15 +20,20 @@ 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",
|
||||
"1.21.2", "v1_21_R2",
|
||||
"1.21.3", "v1_21_R2"
|
||||
);
|
||||
//@done
|
||||
private static final INMSBinding binding = bind();
|
||||
|
||||
@@ -42,7 +47,12 @@ public class INMS {
|
||||
}
|
||||
|
||||
try {
|
||||
return Bukkit.getServer().getClass().getCanonicalName().split("\\Q.\\E")[3];
|
||||
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!");
|
||||
@@ -56,17 +66,19 @@ public class INMS {
|
||||
String code = getNMSTag();
|
||||
Iris.info("Locating NMS Binding for " + code);
|
||||
|
||||
if(bindings.containsKey(code)) {
|
||||
try {
|
||||
INMSBinding b = bindings.get(code).getConstructor().newInstance();
|
||||
Class<?> clazz = Class.forName("com.volmit.iris.core.nms."+code+".NMSBinding");
|
||||
try {
|
||||
Object b = clazz.getConstructor().newInstance();
|
||||
if (b instanceof INMSBinding binding) {
|
||||
Iris.info("Craftbukkit " + code + " <-> " + b.getClass().getSimpleName() + " Successfully Bound");
|
||||
|
||||
return b;
|
||||
return binding;
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
} catch (ClassNotFoundException|NoClassDefFoundError classNotFoundException) {}
|
||||
|
||||
Iris.info("Craftbukkit " + code + " <-> " + NMSBinding1X.class.getSimpleName() + " Successfully Bound");
|
||||
Iris.warn("Note: Some features of Iris may not work the same since you are on an unsupported version of Minecraft.");
|
||||
@@ -18,22 +18,37 @@
|
||||
|
||||
package com.volmit.iris.core.nms;
|
||||
|
||||
import com.volmit.iris.core.nms.container.BiomeColor;
|
||||
import com.volmit.iris.core.nms.datapack.DataVersion;
|
||||
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.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.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.WorldCreator;
|
||||
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.event.entity.CreatureSpawnEvent;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
import org.bukkit.generator.structure.Structure;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.Color;
|
||||
|
||||
public interface INMSBinding {
|
||||
boolean hasTile(Material material);
|
||||
|
||||
boolean hasTile(Location l);
|
||||
|
||||
CompoundTag serializeTile(Location location);
|
||||
KMap<String, Object> serializeTile(Location location);
|
||||
|
||||
void deserializeTile(CompoundTag s, Location newPosition);
|
||||
void deserializeTile(KMap<String, Object> s, Location newPosition);
|
||||
|
||||
CompoundTag serializeEntity(Entity location);
|
||||
|
||||
@@ -54,14 +69,19 @@ public interface INMSBinding {
|
||||
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);
|
||||
@@ -83,4 +103,26 @@ public interface INMSBinding {
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
Entity spawnEntity(Location location, EntityType type, CreatureSpawnEvent.SpawnReason reason);
|
||||
|
||||
Color getBiomeColor(Location location, BiomeColor type);
|
||||
|
||||
default DataVersion getDataVersion() {
|
||||
return DataVersion.V1192;
|
||||
}
|
||||
|
||||
default int getSpawnChunkCount(World world) {
|
||||
return 441;
|
||||
}
|
||||
|
||||
KList<String> getStructureKeys();
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.volmit.iris.core.nms.container;
|
||||
|
||||
public enum BiomeColor {
|
||||
FOG,
|
||||
WATER,
|
||||
WATER_FOG,
|
||||
SKY,
|
||||
FOLIAGE,
|
||||
GRASS
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
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,13 @@
|
||||
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,42 @@
|
||||
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.core.nms.datapack.v1213.DataFixerV1213;
|
||||
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),
|
||||
V1213("1.21.3", 57, DataFixerV1213::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 IDataFixer get() {
|
||||
return cache.computeIfAbsent(this, k -> constructor.get());
|
||||
}
|
||||
|
||||
public static IDataFixer getDefault() {
|
||||
return INMS.get().getDataVersion().get();
|
||||
}
|
||||
|
||||
public static DataVersion getLatest() {
|
||||
return values()[values().length - 1];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
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,18 @@
|
||||
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,56 @@
|
||||
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));
|
||||
} else {
|
||||
json.remove("creature_spawn_probability");
|
||||
}
|
||||
|
||||
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", i.getType().getKey());
|
||||
o.put("weight", i.getWeight());
|
||||
o.put("minCount", i.getMinCount());
|
||||
o.put("maxCount", i.getMaxCount());
|
||||
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,16 @@
|
||||
package com.volmit.iris.core.nms.datapack.v1213;
|
||||
|
||||
import com.volmit.iris.core.nms.datapack.v1206.DataFixerV1206;
|
||||
import com.volmit.iris.engine.object.IrisBiomeCustom;
|
||||
import com.volmit.iris.util.json.JSONArray;
|
||||
import com.volmit.iris.util.json.JSONObject;
|
||||
|
||||
public class DataFixerV1213 extends DataFixerV1206 {
|
||||
|
||||
@Override
|
||||
public JSONObject fixCustomBiome(IrisBiomeCustom biome, JSONObject json) {
|
||||
json = super.fixCustomBiome(biome, json);
|
||||
json.put("carvers", new JSONArray());
|
||||
return json;
|
||||
}
|
||||
}
|
||||
@@ -20,14 +20,26 @@ package com.volmit.iris.core.nms.v1X;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.nms.INMSBinding;
|
||||
import com.volmit.iris.core.nms.container.BiomeColor;
|
||||
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.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.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
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.util.stream.StreamSupport;
|
||||
|
||||
public class NMSBinding1X implements INMSBinding {
|
||||
private static final boolean supportsCustomHeight = testCustomHeight();
|
||||
@@ -47,21 +59,65 @@ public class NMSBinding1X implements INMSBinding {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasTile(Material material) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasTile(Location l) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag serializeTile(Location location) {
|
||||
public KMap<String, Object> serializeTile(Location location) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserializeTile(CompoundTag s, Location newPosition) {
|
||||
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 Color getBiomeColor(Location location, BiomeColor type) {
|
||||
return Color.GREEN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KList<String> getStructureKeys() {
|
||||
var list = StreamSupport.stream(Registry.STRUCTURE.spliterator(), false)
|
||||
.map(Structure::getKey)
|
||||
.map(NamespacedKey::toString)
|
||||
.toList();
|
||||
return new KList<>(list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag serializeEntity(Entity location) {
|
||||
return null;
|
||||
@@ -117,6 +173,11 @@ public class NMSBinding1X implements INMSBinding {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBiomeBaseIdForKey(String key) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKeyForBiomeBase(Object biomeBase) {
|
||||
return null;
|
||||
@@ -131,6 +192,11 @@ public class NMSBinding1X implements INMSBinding {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KList<Biome> getBiomes() {
|
||||
return new KList<>(Biome.values()).qdel(Biome.CUSTOM);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBukkit() {
|
||||
return true;
|
||||
@@ -165,6 +231,11 @@ public class NMSBinding1X implements INMSBinding {
|
||||
|
||||
}
|
||||
|
||||
@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!");
|
||||
@@ -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,8 +63,7 @@ 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;
|
||||
@@ -84,13 +82,10 @@ 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);
|
||||
@@ -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,11 +119,9 @@ 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);
|
||||
@@ -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) {
|
||||
@@ -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,8 +252,7 @@ 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 {
|
||||
@@ -289,8 +275,7 @@ 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 {
|
||||
@@ -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) {
|
||||
@@ -0,0 +1,358 @@
|
||||
package com.volmit.iris.core.pregenerator;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.nms.container.Pair;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.engine.data.cache.Cache;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.mantle.MantleFlag;
|
||||
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.profile.LoadBalancer;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import org.bukkit.Bukkit;
|
||||
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 AtomicBoolean paused = new AtomicBoolean();
|
||||
private final AtomicBoolean cancelled = new AtomicBoolean();
|
||||
private final KMap<Long, Pair<Long, AtomicInteger>> lastUse = new KMap<>();
|
||||
private final RollingSequence chunksPerSecond = new RollingSequence(5);
|
||||
private final AtomicInteger totalMaxChunks = new AtomicInteger();
|
||||
private final AtomicInteger chunksProcessed = new AtomicInteger();
|
||||
private final AtomicInteger chunksProcessedLast = new AtomicInteger();
|
||||
private final AtomicInteger chunksUpdated = new AtomicInteger();
|
||||
private final AtomicBoolean serverEmpty = new AtomicBoolean(true);
|
||||
private final AtomicLong lastCpsTime = new AtomicLong(M.ms());
|
||||
private final int coreLimit = (int) Math.max(Runtime.getRuntime().availableProcessors() * IrisSettings.get().getUpdater().getThreadMultiplier(), 1);
|
||||
private final Semaphore semaphore = new Semaphore(256);
|
||||
private final LoadBalancer loadBalancer = new LoadBalancer(semaphore, 256, IrisSettings.get().getUpdater().emptyMsRange);
|
||||
private final AtomicLong startTime = new AtomicLong();
|
||||
private final Dimensions dimensions;
|
||||
private final PregenTask task;
|
||||
private final ExecutorService executor = Executors.newFixedThreadPool(coreLimit);
|
||||
private final ExecutorService chunkExecutor = Executors.newFixedThreadPool(coreLimit);
|
||||
private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
|
||||
private final CountDownLatch latch;
|
||||
private final Engine engine;
|
||||
private final World world;
|
||||
|
||||
public ChunkUpdater(World world) {
|
||||
this.engine = IrisToolbelt.access(world).getEngine();
|
||||
this.world = world;
|
||||
this.dimensions = calculateWorldDimensions(new File(world.getWorldFolder(), "region"));
|
||||
this.task = dimensions.task();
|
||||
this.totalMaxChunks.set(dimensions.count * 1024);
|
||||
this.latch = new CountDownLatch(totalMaxChunks.get());
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return world.getName();
|
||||
}
|
||||
|
||||
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();
|
||||
int processed = chunksProcessed.get();
|
||||
double last = processed - chunksProcessedLast.getAndSet(processed);
|
||||
double cps = last / ((M.ms() - lastCpsTime.getAndSet(M.ms())) / 1000d);
|
||||
chunksPerSecond.put(cps);
|
||||
double percentage = ((double) processed / (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);
|
||||
scheduler.scheduleAtFixedRate(this::unloadChunks, 0, 1, TimeUnit.SECONDS);
|
||||
scheduler.scheduleAtFixedRate(() -> {
|
||||
boolean empty = Bukkit.getOnlinePlayers().isEmpty();
|
||||
if (serverEmpty.getAndSet(empty) == empty)
|
||||
return;
|
||||
loadBalancer.setRange(empty ? IrisSettings.get().getUpdater().emptyMsRange : IrisSettings.get().getUpdater().defaultMsRange);
|
||||
}, 0, 10, TimeUnit.SECONDS);
|
||||
|
||||
var t = new Thread(() -> {
|
||||
run();
|
||||
close();
|
||||
}, "Iris Chunk Updater - " + world.getName());
|
||||
t.setPriority(Thread.MAX_PRIORITY);
|
||||
t.start();
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void close() {
|
||||
try {
|
||||
loadBalancer.close();
|
||||
semaphore.acquire(256);
|
||||
|
||||
executor.shutdown();
|
||||
executor.awaitTermination(5, TimeUnit.SECONDS);
|
||||
chunkExecutor.shutdown();
|
||||
chunkExecutor.awaitTermination(5, TimeUnit.SECONDS);
|
||||
scheduler.shutdownNow();
|
||||
unloadAndSaveAllChunks();
|
||||
} 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 run() {
|
||||
task.iterateRegions((rX, rZ) -> {
|
||||
if (cancelled.get())
|
||||
return;
|
||||
|
||||
while (paused.get()) {
|
||||
J.sleep(50);
|
||||
}
|
||||
|
||||
if (rX < dimensions.min.getX() || rX > dimensions.max.getX() || rZ < dimensions.min.getZ() || rZ > dimensions.max.getZ()) {
|
||||
return;
|
||||
}
|
||||
|
||||
PregenTask.iterateRegion(rX, rZ, (x, z) -> {
|
||||
while (paused.get() && !cancelled.get()) {
|
||||
J.sleep(50);
|
||||
}
|
||||
|
||||
try {
|
||||
semaphore.acquire();
|
||||
} catch (InterruptedException ignored) {
|
||||
return;
|
||||
}
|
||||
chunkExecutor.submit(() -> {
|
||||
try {
|
||||
if (!cancelled.get())
|
||||
processChunk(x, z);
|
||||
} finally {
|
||||
latch.countDown();
|
||||
semaphore.release();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private void processChunk(int x, int z) {
|
||||
if (!loadChunksIfGenerated(x, z)) {
|
||||
chunksProcessed.getAndIncrement();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
Chunk c = world.getChunkAt(x, z);
|
||||
engine.getMantle().getMantle().getChunk(c);
|
||||
engine.updateChunk(c);
|
||||
|
||||
for (int xx = -1; xx <= 1; xx++) {
|
||||
for (int zz = -1; zz <= 1; zz++) {
|
||||
var counter = lastUse.get(Cache.key(x + xx, z + zz));
|
||||
if (counter != null) counter.getB().decrementAndGet();
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
chunksUpdated.incrementAndGet();
|
||||
chunksProcessed.getAndIncrement();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean loadChunksIfGenerated(int x, int z) {
|
||||
if (engine.getMantle().getMantle().hasFlag(x, z, MantleFlag.ETCHED))
|
||||
return false;
|
||||
|
||||
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);
|
||||
CountDownLatch latch = new CountDownLatch(9);
|
||||
for (int dx = -1; dx <= 1; dx++) {
|
||||
for (int dz = -1; dz <= 1; dz++) {
|
||||
int xx = x + dx;
|
||||
int zz = z + dz;
|
||||
executor.submit(() -> {
|
||||
try {
|
||||
Chunk c;
|
||||
try {
|
||||
c = PaperLib.getChunkAtAsync(world, xx, zz, false, true)
|
||||
.thenApply(chunk -> {
|
||||
if (chunk != null)
|
||||
chunk.addPluginChunkTicket(Iris.instance);
|
||||
return chunk;
|
||||
}).get();
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
generated.set(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (c == null) {
|
||||
generated.set(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!c.isLoaded()) {
|
||||
var future = J.sfut(() -> c.load(false));
|
||||
if (future != null) future.join();
|
||||
}
|
||||
|
||||
if (!PaperLib.isChunkGenerated(c.getWorld(), xx, zz))
|
||||
generated.set(false);
|
||||
|
||||
var pair = lastUse.computeIfAbsent(Cache.key(c), k -> new Pair<>(0L, new AtomicInteger(-1)));
|
||||
pair.setA(M.ms());
|
||||
pair.getB().updateAndGet(i -> i == -1 ? 1 : ++i);
|
||||
} finally {
|
||||
latch.countDown();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
latch.await();
|
||||
} catch (InterruptedException e) {
|
||||
Iris.info("Interrupted while waiting for chunks to load");
|
||||
}
|
||||
return generated.get();
|
||||
}
|
||||
|
||||
private synchronized void unloadChunks() {
|
||||
for (var key : new ArrayList<>(lastUse.keySet())) {
|
||||
if (key == null) continue;
|
||||
var pair = lastUse.get(key);
|
||||
if (pair == null) continue;
|
||||
var lastUseTime = pair.getA();
|
||||
var counter = pair.getB();
|
||||
if (lastUseTime == null || counter == null)
|
||||
continue;
|
||||
|
||||
if (M.ms() - lastUseTime >= 5000 && counter.get() == 0) {
|
||||
int x = Cache.keyX(key);
|
||||
int z = Cache.keyZ(key);
|
||||
J.s(() -> {
|
||||
world.removePluginChunkTicket(x, z, Iris.instance);
|
||||
world.unloadChunk(x, z);
|
||||
lastUse.remove(key);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void unloadAndSaveAllChunks() {
|
||||
try {
|
||||
J.sfut(() -> {
|
||||
if (world == null) {
|
||||
Iris.warn("World was null somehow...");
|
||||
return;
|
||||
}
|
||||
|
||||
unloadChunks();
|
||||
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 Dimensions calculateWorldDimensions(File regionDir) {
|
||||
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]);
|
||||
|
||||
minX = Math.min(minX, x);
|
||||
maxX = Math.max(maxX, x);
|
||||
minZ = Math.min(minZ, z);
|
||||
maxZ = Math.max(maxZ, z);
|
||||
}
|
||||
int oX = minX + ((maxX - minX) / 2);
|
||||
int oZ = minZ + ((maxZ - minZ) / 2);
|
||||
|
||||
int height = maxX - minX + 1;
|
||||
int width = maxZ - minZ + 1;
|
||||
|
||||
return new Dimensions(new Position2(minX, minZ), new Position2(maxX, maxZ), height * width, PregenTask.builder()
|
||||
.width((int) Math.ceil(width / 2d))
|
||||
.height((int) Math.ceil(height / 2d))
|
||||
.center(new Position2(oX, oZ))
|
||||
.build());
|
||||
}
|
||||
|
||||
private record Dimensions(Position2 min, Position2 max, int count, PregenTask task) { }
|
||||
}
|
||||
@@ -0,0 +1,274 @@
|
||||
package com.volmit.iris.core.pregenerator;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.object.IrisBiome;
|
||||
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.scheduling.ChronoLatch;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
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.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
public class DeepSearchPregenerator extends Thread implements Listener {
|
||||
@Getter
|
||||
private static DeepSearchPregenerator instance;
|
||||
private final DeepSearchJob job;
|
||||
private final File destination;
|
||||
private final int maxPosition;
|
||||
private World world;
|
||||
private final ChronoLatch latch;
|
||||
private static AtomicInteger foundChunks;
|
||||
private final AtomicInteger foundLast;
|
||||
private final AtomicInteger foundTotalChunks;
|
||||
private final AtomicLong startTime;
|
||||
private final RollingSequence chunksPerSecond;
|
||||
private final RollingSequence chunksPerMinute;
|
||||
private final AtomicInteger chunkCachePos;
|
||||
private final AtomicInteger chunkCacheSize;
|
||||
private int pos;
|
||||
private final AtomicInteger foundCacheLast;
|
||||
private final AtomicInteger foundCache;
|
||||
private LinkedHashMap<Integer, Position2> chunkCache;
|
||||
private KList<Position2> chunkQueue;
|
||||
private final ReentrantLock cacheLock;
|
||||
|
||||
private static final Map<String, DeepSearchJob> jobs = new HashMap<>();
|
||||
|
||||
public DeepSearchPregenerator(DeepSearchJob job, File destination) {
|
||||
this.job = job;
|
||||
this.chunkCacheSize = new AtomicInteger(); // todo
|
||||
this.chunkCachePos = new AtomicInteger(1000);
|
||||
this.foundCacheLast = new AtomicInteger();
|
||||
this.foundCache = new AtomicInteger();
|
||||
this.cacheLock = new ReentrantLock();
|
||||
this.destination = destination;
|
||||
this.chunkCache = new LinkedHashMap<>();
|
||||
this.maxPosition = new Spiraler(job.getRadiusBlocks() * 2, job.getRadiusBlocks() * 2, (x, z) -> {
|
||||
}).count();
|
||||
this.world = Bukkit.getWorld(job.getWorld().getUID());
|
||||
this.chunkQueue = new KList<>();
|
||||
this.latch = new ChronoLatch(3000);
|
||||
this.startTime = new AtomicLong(M.ms());
|
||||
this.chunksPerSecond = new RollingSequence(10);
|
||||
this.chunksPerMinute = new RollingSequence(10);
|
||||
foundChunks = new AtomicInteger(0);
|
||||
this.foundLast = new AtomicInteger(0);
|
||||
this.foundTotalChunks = new AtomicInteger((int) Math.ceil(Math.pow((2.0 * job.getRadiusBlocks()) / 16, 2)));
|
||||
|
||||
this.pos = 0;
|
||||
jobs.put(job.getWorld().getName(), job);
|
||||
DeepSearchPregenerator.instance = this;
|
||||
}
|
||||
|
||||
@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() {
|
||||
DeepSearchJob job = jobs.get(world.getName());
|
||||
// chunkCache(); //todo finish this
|
||||
if (latch.flip() && !job.paused) {
|
||||
if (cacheLock.isLocked()) {
|
||||
Iris.info("DeepFinder: Caching: " + chunkCachePos.get() + " Of " + chunkCacheSize.get());
|
||||
} else {
|
||||
long eta = computeETA();
|
||||
save();
|
||||
int secondGenerated = foundChunks.get() - foundLast.get();
|
||||
foundLast.set(foundChunks.get());
|
||||
secondGenerated = secondGenerated / 3;
|
||||
chunksPerSecond.put(secondGenerated);
|
||||
chunksPerMinute.put(secondGenerated * 60);
|
||||
Iris.info("DeepFinder: " + C.IRIS + world.getName() + C.RESET + " Searching: " + Form.f(foundChunks.get()) + " of " + Form.f(foundTotalChunks.get()) + " " + Form.f((int) chunksPerSecond.getAverage()) + "/s ETA: " + Form.duration((double) eta, 2));
|
||||
}
|
||||
|
||||
}
|
||||
if (foundChunks.get() >= foundTotalChunks.get()) {
|
||||
Iris.info("Completed DeepSearch!");
|
||||
interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
private long computeETA() {
|
||||
return (long) ((foundTotalChunks.get() - foundChunks.get()) / chunksPerSecond.getAverage()) * 1000;
|
||||
// todo broken
|
||||
}
|
||||
|
||||
private final ExecutorService executorService = Executors.newSingleThreadExecutor();
|
||||
|
||||
private void queueSystem(Position2 chunk) {
|
||||
if (chunkQueue.isEmpty()) {
|
||||
for (int limit = 512; limit != 0; limit--) {
|
||||
pos = job.getPosition() + 1;
|
||||
chunkQueue.add(getChunk(pos));
|
||||
}
|
||||
} else {
|
||||
//MCAUtil.read();
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void findInChunk(World world, int x, int z) throws IOException {
|
||||
int xx = x * 16;
|
||||
int zz = z * 16;
|
||||
Engine engine = IrisToolbelt.access(world).getEngine();
|
||||
for (int i = 0; i < 16; i++) {
|
||||
for (int j = 0; j < 16; j++) {
|
||||
int height = engine.getHeight(xx + i, zz + j);
|
||||
if (height > 300) {
|
||||
File found = new File("plugins" + "iris" + "found.txt");
|
||||
FileWriter writer = new FileWriter(found);
|
||||
if (!found.exists()) {
|
||||
found.createNewFile();
|
||||
}
|
||||
IrisBiome biome = engine.getBiome(xx, engine.getHeight(), zz);
|
||||
Iris.info("Found at! " + xx + ", " + zz + "Biome ID: " + biome.getName() + ", ");
|
||||
writer.write("Biome at: X: " + xx + " Z: " + zz + "Biome ID: " + biome.getName() + ", ");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 static void setPausedDeep(World world) {
|
||||
DeepSearchJob job = jobs.get(world.getName());
|
||||
if (isPausedDeep(world)){
|
||||
job.paused = false;
|
||||
} else {
|
||||
job.paused = true;
|
||||
}
|
||||
|
||||
if ( job.paused) {
|
||||
Iris.info(C.BLUE + "DeepSearch: " + C.IRIS + world.getName() + C.BLUE + " Paused");
|
||||
} else {
|
||||
Iris.info(C.BLUE + "DeepSearch: " + C.IRIS + world.getName() + C.BLUE + " Resumed");
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isPausedDeep(World world) {
|
||||
DeepSearchJob job = jobs.get(world.getName());
|
||||
return job != null && job.isPaused();
|
||||
}
|
||||
|
||||
public void shutdownInstance(World world) throws IOException {
|
||||
Iris.info("DeepSearch: " + C.IRIS + world.getName() + C.BLUE + " Shutting down..");
|
||||
DeepSearchJob job = jobs.get(world.getName());
|
||||
File worldDirectory = new File(Bukkit.getWorldContainer(), world.getName());
|
||||
File deepFile = new File(worldDirectory, "DeepSearch.json");
|
||||
|
||||
if (job == null) {
|
||||
Iris.error("No DeepSearch 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 (deepFile.exists()){
|
||||
deepFile.delete();
|
||||
J.sleep(1000);
|
||||
}
|
||||
Iris.info("DeepSearch: " + C.IRIS + world.getName() + C.BLUE + " File deleted and instance closed.");
|
||||
}
|
||||
}.runTaskLater(Iris.instance, 20L);
|
||||
} catch (Exception e) {
|
||||
Iris.error("Failed to shutdown DeepSearch for " + world.getName());
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
saveNow();
|
||||
interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void saveNow() throws IOException {
|
||||
IO.writeAll(this.destination, new Gson().toJson(job));
|
||||
}
|
||||
|
||||
@Data
|
||||
@lombok.Builder
|
||||
public static class DeepSearchJob {
|
||||
private World world;
|
||||
@lombok.Builder.Default
|
||||
private int radiusBlocks = 5000;
|
||||
@lombok.Builder.Default
|
||||
private int position = 0;
|
||||
@lombok.Builder.Default
|
||||
boolean paused = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,11 @@
|
||||
package com.volmit.iris.core.pregenerator;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.pack.IrisPack;
|
||||
import com.volmit.iris.core.tools.IrisPackBenchmarking;
|
||||
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;
|
||||
@@ -34,6 +38,7 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
|
||||
public class IrisPregenerator {
|
||||
private final PregenTask task;
|
||||
private final PregeneratorMethod generator;
|
||||
@@ -44,10 +49,11 @@ 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 static AtomicInteger generated;
|
||||
private final AtomicInteger generatedLast;
|
||||
private final AtomicInteger generatedLastMinute;
|
||||
private final AtomicInteger totalChunks;
|
||||
private static AtomicInteger totalChunks;
|
||||
private final AtomicLong startTime;
|
||||
private final ChronoLatch minuteLatch;
|
||||
private final AtomicReference<String> currentGeneratorMethod;
|
||||
@@ -55,6 +61,7 @@ public class IrisPregenerator {
|
||||
private final KSet<Position2> retry;
|
||||
private final KSet<Position2> net;
|
||||
private final ChronoLatch cl;
|
||||
private final ChronoLatch saveLatch = new ChronoLatch(30000);
|
||||
|
||||
public IrisPregenerator(PregenTask task, PregeneratorMethod generator, PregenListener listener) {
|
||||
this.listener = listenify(listener);
|
||||
@@ -71,6 +78,7 @@ 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);
|
||||
@@ -84,6 +92,7 @@ public class IrisPregenerator {
|
||||
int secondGenerated = generated.get() - generatedLast.get();
|
||||
generatedLast.set(generated.get());
|
||||
chunksPerSecond.put(secondGenerated);
|
||||
chunksPerSecondHistory.add(secondGenerated);
|
||||
|
||||
if (minuteLatch.flip()) {
|
||||
int minuteGenerated = generated.get() - generatedLastMinute.get();
|
||||
@@ -100,19 +109,28 @@ public class IrisPregenerator {
|
||||
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));
|
||||
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()));
|
||||
return (long) (totalChunks.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)
|
||||
((totalChunks.get() - generated.get()) * ((double) (M.ms() - startTime.get()) / (double) generated.get())) :
|
||||
// If no, use quick function (which is less accurate over time but responds better to the initial delay)
|
||||
((totalChunks.get() - generated.get()) / chunksPerSecond.getAverage()) * 1000
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public void close() {
|
||||
shutdown.set(true);
|
||||
}
|
||||
@@ -124,6 +142,11 @@ 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.");
|
||||
} else {
|
||||
IrisPackBenchmarking.instance.finishedBenchmark(chunksPerSecondHistory);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkRegions() {
|
||||
@@ -140,6 +163,10 @@ public class IrisPregenerator {
|
||||
generator.close();
|
||||
ticker.interrupt();
|
||||
listener.onClose();
|
||||
Mantle mantle = getMantle();
|
||||
if (mantle != null) {
|
||||
mantle.trim(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
private void visitRegion(int x, int z, boolean regions) {
|
||||
@@ -167,13 +194,23 @@ public class IrisPregenerator {
|
||||
} 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) {
|
||||
listener.onRegionGenerated(x, z);
|
||||
|
||||
if (saveLatch.flip()) {
|
||||
listener.onSaving();
|
||||
generator.save();
|
||||
}
|
||||
|
||||
generatedRegions.add(pos);
|
||||
checkRegions();
|
||||
}
|
||||
@@ -0,0 +1,285 @@
|
||||
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.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.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class LazyPregenerator extends Thread implements Listener {
|
||||
@Getter
|
||||
private static LazyPregenerator instance;
|
||||
private final LazyPregenJob job;
|
||||
private final File destination;
|
||||
private final int maxPosition;
|
||||
private World world;
|
||||
private final long rate;
|
||||
private final ChronoLatch latch;
|
||||
private static AtomicInteger lazyGeneratedChunks;
|
||||
private final AtomicInteger generatedLast;
|
||||
private final AtomicInteger lazyTotalChunks;
|
||||
private final AtomicLong startTime;
|
||||
private final RollingSequence chunksPerSecond;
|
||||
private final RollingSequence chunksPerMinute;
|
||||
|
||||
private static final Map<String, LazyPregenJob> jobs = new HashMap<>();
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@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 final ExecutorService executorService = Executors.newSingleThreadExecutor();
|
||||
|
||||
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 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();
|
||||
}
|
||||
|
||||
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
|
||||
@lombok.Builder
|
||||
public static class LazyPregenJob {
|
||||
private String world;
|
||||
@lombok.Builder.Default
|
||||
private int healingPosition = 0;
|
||||
@lombok.Builder.Default
|
||||
private boolean healing = false;
|
||||
@lombok.Builder.Default
|
||||
private int chunksPerMinute = 32;
|
||||
@lombok.Builder.Default
|
||||
private int radiusBlocks = 5000;
|
||||
@lombok.Builder.Default
|
||||
private int position = 0;
|
||||
@lombok.Builder.Default
|
||||
boolean silent = false;
|
||||
@lombok.Builder.Default
|
||||
boolean paused = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,8 @@ public class PregenTask {
|
||||
private static final KList<Position2> ORDER_CENTER = computeChunkOrder();
|
||||
private static final KMap<Position2, KList<Position2>> ORDERS = new KMap<>();
|
||||
|
||||
@Builder.Default
|
||||
private boolean gui = false;
|
||||
@Builder.Default
|
||||
private Position2 center = new Position2(0, 0);
|
||||
@Builder.Default
|
||||
@@ -49,7 +51,7 @@ public class PregenTask {
|
||||
}
|
||||
|
||||
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) {
|
||||
@@ -43,10 +43,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 +52,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,22 +62,17 @@ 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);
|
||||
|
||||
@@ -0,0 +1,341 @@
|
||||
package com.volmit.iris.core.pregenerator;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
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.Data;
|
||||
import lombok.Getter;
|
||||
import org.apache.logging.log4j.core.util.ExecutorServices;
|
||||
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 org.checkerframework.checker.units.qual.N;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
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 {
|
||||
@Getter
|
||||
private static TurboPregenerator instance;
|
||||
private final TurboPregenJob job;
|
||||
private final File destination;
|
||||
private final int maxPosition;
|
||||
private World world;
|
||||
private final ChronoLatch latch;
|
||||
private static AtomicInteger turboGeneratedChunks;
|
||||
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 KList<Position2> queue;
|
||||
private ConcurrentHashMap<Integer, Position2> cache;
|
||||
private AtomicInteger maxWaiting;
|
||||
private ReentrantLock cachinglock;
|
||||
private AtomicBoolean caching;
|
||||
private final HyperLock hyperLock;
|
||||
private MultiBurst burst;
|
||||
private static final Map<String, TurboPregenJob> jobs = new HashMap<>();
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@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 final ExecutorService executorService = Executors.newFixedThreadPool(10);
|
||||
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 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();
|
||||
}
|
||||
|
||||
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
|
||||
@lombok.Builder
|
||||
public static class TurboPregenJob {
|
||||
private String world;
|
||||
@lombok.Builder.Default
|
||||
private int radiusBlocks = 5000;
|
||||
@lombok.Builder.Default
|
||||
private int position = 0;
|
||||
@lombok.Builder.Default
|
||||
boolean paused = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,24 +19,27 @@
|
||||
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.concurrent.Future;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Semaphore;
|
||||
|
||||
public class AsyncPregenMethod implements PregeneratorMethod {
|
||||
private final World world;
|
||||
private final MultiBurst burst;
|
||||
private final KList<Future<?>> future;
|
||||
private final Semaphore semaphore;
|
||||
private final Map<Chunk, Long> lastUse;
|
||||
|
||||
public AsyncPregenMethod(World world, int threads) {
|
||||
if (!PaperLib.isPaper()) {
|
||||
@@ -44,8 +47,9 @@ public class AsyncPregenMethod implements PregeneratorMethod {
|
||||
}
|
||||
|
||||
this.world = world;
|
||||
burst = MultiBurst.burst;
|
||||
future = new KList<>(1024);
|
||||
burst = new MultiBurst("Iris Async Pregen", Thread.MIN_PRIORITY);
|
||||
semaphore = new Semaphore(256);
|
||||
this.lastUse = new KMap<>();
|
||||
}
|
||||
|
||||
private void unloadAndSaveAllChunks() {
|
||||
@@ -56,8 +60,12 @@ public class AsyncPregenMethod implements PregeneratorMethod {
|
||||
return;
|
||||
}
|
||||
|
||||
for(Chunk i : world.getLoadedChunks()) {
|
||||
i.unload(true);
|
||||
for (Chunk i : new ArrayList<>(lastUse.keySet())) {
|
||||
Long lastUseTime = lastUse.get(i);
|
||||
if (!i.isLoaded() || (lastUseTime != null && M.ms() - lastUseTime >= 10000)) {
|
||||
i.unload();
|
||||
lastUse.remove(i);
|
||||
}
|
||||
}
|
||||
world.save();
|
||||
}).get();
|
||||
@@ -68,24 +76,16 @@ public class AsyncPregenMethod implements PregeneratorMethod {
|
||||
|
||||
private void completeChunk(int x, int z, PregenListener listener) {
|
||||
try {
|
||||
PaperLib.getChunkAtAsync(world, x, z, true).get();
|
||||
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 waitForChunks() {
|
||||
for(Future<?> i : future.copy()) {
|
||||
try {
|
||||
i.get();
|
||||
future.remove(i);
|
||||
} catch(Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} finally {
|
||||
semaphore.release();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,13 +101,13 @@ public class AsyncPregenMethod implements PregeneratorMethod {
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
waitForChunks();
|
||||
semaphore.acquireUninterruptibly(256);
|
||||
unloadAndSaveAllChunks();
|
||||
burst.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save() {
|
||||
waitForChunks();
|
||||
unloadAndSaveAllChunks();
|
||||
}
|
||||
|
||||
@@ -123,12 +123,13 @@ 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);
|
||||
future.add(burst.complete(() -> completeChunk(x, z, listener)));
|
||||
try {
|
||||
semaphore.acquire();
|
||||
} catch (InterruptedException e) {
|
||||
return;
|
||||
}
|
||||
burst.complete(() -> completeChunk(x, z, listener));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -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;
|
||||
@@ -18,25 +18,33 @@
|
||||
|
||||
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.Bukkit;
|
||||
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() {
|
||||
@@ -52,11 +60,19 @@ 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();
|
||||
@@ -104,6 +120,8 @@ public class MedievalPregenMethod implements PregeneratorMethod {
|
||||
listener.onChunkGenerating(x, z);
|
||||
futures.add(J.sfut(() -> {
|
||||
world.getChunkAt(x, z);
|
||||
Chunk c = Bukkit.getWorld(world.getUID()).getChunkAt(x, z);
|
||||
lastUse.put(c, M.ms());
|
||||
listener.onChunkGenerated(x, z);
|
||||
listener.onChunkCleaned(x, z);
|
||||
}));
|
||||
@@ -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;
|
||||
@@ -22,38 +22,30 @@ 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.object.annotations.*;
|
||||
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.json.JSONArray;
|
||||
import com.volmit.iris.util.json.JSONObject;
|
||||
import com.volmit.iris.util.reflect.OldEnum;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import java.awt.*;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
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 ITEM_TYPES = new JSONArray(B.getItemTypes());
|
||||
private static final JSONArray ENCHANT_TYPES = getEnchantTypes();
|
||||
private static final JSONArray FONT_TYPES = new JSONArray(GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames());
|
||||
private final KMap<String, JSONObject> definitions;
|
||||
private final Class<?> root;
|
||||
@@ -67,16 +59,6 @@ public class SchemaBuilder {
|
||||
this.root = root;
|
||||
}
|
||||
|
||||
private static JSONArray getEnchantmentTypes() {
|
||||
JSONArray a = new JSONArray();
|
||||
|
||||
for(Field gg : Enchantment.class.getDeclaredFields()) {
|
||||
a.put(gg.getName());
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
private static JSONArray getPotionTypes() {
|
||||
JSONArray a = new JSONArray();
|
||||
|
||||
@@ -87,6 +69,14 @@ public class SchemaBuilder {
|
||||
return a;
|
||||
}
|
||||
|
||||
private static JSONArray getEnchantTypes() {
|
||||
JSONArray array = new JSONArray();
|
||||
for (Enchantment e : Enchantment.values()) {
|
||||
array.put(e.getKey().getKey());
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
public JSONObject construct() {
|
||||
JSONObject schema = new JSONObject();
|
||||
schema.put("$schema", "http://json-schema.org/draft-07/schema#");
|
||||
@@ -273,7 +263,7 @@ public class SchemaBuilder {
|
||||
|
||||
if (!definitions.containsKey(key)) {
|
||||
JSONObject j = new JSONObject();
|
||||
j.put("enum", ITEM_TYPES);
|
||||
j.put("enum", B.getItemTypes());
|
||||
definitions.put(key, j);
|
||||
}
|
||||
|
||||
@@ -309,7 +299,7 @@ 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)) {
|
||||
@@ -321,6 +311,24 @@ 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.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";
|
||||
|
||||
@@ -335,38 +343,9 @@ public class SchemaBuilder {
|
||||
description.add(SYMBOL_TYPE__N + " Must be a valid Potion Effect Type (use ctrl+space for auto complete!)");
|
||||
|
||||
} 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) {
|
||||
try {
|
||||
JSONObject j = new JSONObject();
|
||||
String name = ((Enum<?>) gg).name();
|
||||
j.put("const", name);
|
||||
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) {
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
a.put(((Enum<?>) gg).name());
|
||||
}
|
||||
}
|
||||
|
||||
String key = (advanced ? "oneof-" : "") + "enum-" + k.getType().getCanonicalName().replaceAll("\\Q.\\E", "-").toLowerCase();
|
||||
|
||||
if(!definitions.containsKey(key)) {
|
||||
JSONObject j = new JSONObject();
|
||||
j.put(advanced ? "oneOf" : "enum", a);
|
||||
definitions.put(key, j);
|
||||
}
|
||||
|
||||
prop.put("$ref", "#/definitions/" + key);
|
||||
description.add(SYMBOL_TYPE__N + " Must be a valid " + k.getType().getSimpleName().replaceAll("\\QIris\\E", "") + " (use ctrl+space for auto complete!)");
|
||||
|
||||
fancyType = addEnum(k.getType(), prop, description, k.getType().getEnumConstants(), o -> ((Enum<?>) o).name());
|
||||
} else if (OldEnum.isOldEnum(k.getType())) {
|
||||
fancyType = addEnum(k.getType(), prop, description, OldEnum.values(k.getType()), OldEnum::name);
|
||||
}
|
||||
}
|
||||
case "object" -> {
|
||||
@@ -461,7 +440,7 @@ public class SchemaBuilder {
|
||||
|
||||
if (!definitions.containsKey(key)) {
|
||||
JSONObject j = new JSONObject();
|
||||
j.put("enum", ITEM_TYPES);
|
||||
j.put("enum", B.getItemTypes());
|
||||
definitions.put(key, j);
|
||||
}
|
||||
|
||||
@@ -483,7 +462,7 @@ 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";
|
||||
|
||||
@@ -512,39 +491,9 @@ public class SchemaBuilder {
|
||||
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()) {
|
||||
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) {
|
||||
try {
|
||||
JSONObject j = new JSONObject();
|
||||
String name = ((Enum<?>) gg).name();
|
||||
j.put("const", name);
|
||||
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) {
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
a.put(((Enum<?>) gg).name());
|
||||
}
|
||||
}
|
||||
|
||||
String key = (advanced ? "oneof-" : "") + "enum-" + t.type().getCanonicalName().replaceAll("\\Q.\\E", "-").toLowerCase();
|
||||
|
||||
if(!definitions.containsKey(key)) {
|
||||
JSONObject j = new JSONObject();
|
||||
j.put(advanced ? "oneOf" : "enum", a);
|
||||
definitions.put(key, j);
|
||||
}
|
||||
|
||||
JSONObject items = new JSONObject();
|
||||
items.put("$ref", "#/definitions/" + key);
|
||||
prop.put("items", items);
|
||||
description.add(SYMBOL_TYPE__N + " Must be a valid " + t.type().getSimpleName().replaceAll("\\QIris\\E", "") + " (use ctrl+space for auto complete!)");
|
||||
fancyType = addEnumList(prop, description, t, t.type().getEnumConstants(), o -> ((Enum<?>) o).name());
|
||||
} else if (OldEnum.isOldEnum(t.type())) {
|
||||
fancyType = addEnumList(prop, description, t, OldEnum.values(t.type()), OldEnum::name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -552,7 +501,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<>();
|
||||
@@ -576,7 +526,7 @@ public class SchemaBuilder {
|
||||
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()) && !OldEnum.isOldEnum(cl)) {
|
||||
d.add(" ");
|
||||
d.add("* Default Value is a default object (create this object to see default properties)");
|
||||
} else {
|
||||
@@ -622,6 +572,50 @@ public class SchemaBuilder {
|
||||
return prop;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private String addEnumList(JSONObject prop, KList<String> description, ArrayType t, Object[] values, Function<Object, String> function) {
|
||||
JSONObject items = new JSONObject();
|
||||
var s = addEnum(t.type(), items, description, values, function);
|
||||
prop.put("items", items);
|
||||
|
||||
return "List of " + s + "s";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private String addEnum(Class<?> type, JSONObject prop, KList<String> description, Object[] values, Function<Object, String> function) {
|
||||
JSONArray a = new JSONArray();
|
||||
boolean advanced = type.isAnnotationPresent(Desc.class);
|
||||
for (Object gg : values) {
|
||||
if (advanced) {
|
||||
try {
|
||||
JSONObject j = new JSONObject();
|
||||
String name = function.apply(gg);
|
||||
j.put("const", name);
|
||||
Desc dd = type.getField(name).getAnnotation(Desc.class);
|
||||
j.put("description", dd == null ? ("No Description for " + name) : dd.value());
|
||||
a.put(j);
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
a.put(function.apply(gg));
|
||||
}
|
||||
}
|
||||
|
||||
String key = (advanced ? "oneof-" : "") + "enum-" + type.getCanonicalName().replaceAll("\\Q.\\E", "-").toLowerCase();
|
||||
|
||||
if (!definitions.containsKey(key)) {
|
||||
JSONObject j = new JSONObject();
|
||||
j.put(advanced ? "oneOf" : "enum", a);
|
||||
definitions.put(key, j);
|
||||
}
|
||||
|
||||
prop.put("$ref", "#/definitions/" + key);
|
||||
description.add(SYMBOL_TYPE__N + " Must be a valid " + type.getSimpleName().replaceAll("\\QIris\\E", "") + " (use ctrl+space for auto complete!)");
|
||||
return type.getSimpleName().replaceAll("\\QIris\\E", "");
|
||||
}
|
||||
|
||||
private String getType(Class<?> c) {
|
||||
if (c.equals(int.class) || c.equals(Integer.class) || c.equals(long.class) || c.equals(Long.class)) {
|
||||
return "integer";
|
||||
@@ -635,7 +629,7 @@ public class SchemaBuilder {
|
||||
return "boolean";
|
||||
}
|
||||
|
||||
if(c.equals(String.class) || c.isEnum() || c.equals(Enchantment.class) || c.equals(PotionEffectType.class)) {
|
||||
if (c.equals(String.class) || c.isEnum() || OldEnum.isOldEnum(c) || c.equals(Enchantment.class) || c.equals(PotionEffectType.class)) {
|
||||
return "string";
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.volmit.iris.core.safeguard;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
|
||||
public class IrisSafeguard {
|
||||
public static boolean unstablemode = false;
|
||||
public static boolean warningmode = false;
|
||||
public static boolean stablemode = false;
|
||||
|
||||
public static void IrisSafeguardSystem() {
|
||||
Iris.info("Enabled Iris SafeGuard");
|
||||
ServerBootSFG.BootCheck();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
package com.volmit.iris.core.safeguard;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.util.format.C;
|
||||
|
||||
public class ModesSFG {
|
||||
public static void selectMode() {
|
||||
if (IrisSafeguard.unstablemode) {
|
||||
Iris.safeguard(C.DARK_RED + "Iris is running in Unstable Mode");
|
||||
unstable();
|
||||
}
|
||||
if (IrisSafeguard.warningmode) {
|
||||
Iris.safeguard(C.GOLD + "Iris is running in Warning Mode");
|
||||
warning();
|
||||
}
|
||||
if (IrisSafeguard.stablemode) {
|
||||
stable();
|
||||
}
|
||||
}
|
||||
|
||||
public static void stable() {
|
||||
Iris.safeguard(C.BLUE + "Iris is running Stable");
|
||||
}
|
||||
|
||||
public static void unstable() {
|
||||
|
||||
UtilsSFG.printIncompatibleWarnings();
|
||||
|
||||
if (IrisSafeguard.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().getGeneral().DoomsdayAnnihilationSelfDestructMode) {
|
||||
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.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,8 @@
|
||||
package com.volmit.iris.core.safeguard;
|
||||
|
||||
public class PerformanceSFG {
|
||||
public static void calculatePerformance() {
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
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;
|
||||
import static com.volmit.iris.core.safeguard.IrisSafeguard.*;
|
||||
|
||||
public class ServerBootSFG {
|
||||
public static final Map<String, Boolean> incompatibilities = new HashMap<>();
|
||||
public static boolean isCorrectJDK = true;
|
||||
public static boolean hasEnoughDiskSpace = true;
|
||||
public static boolean isJRE = false;
|
||||
public static boolean hasPrivileges = true;
|
||||
public static boolean unsuportedversion = false;
|
||||
protected static boolean safeguardPassed;
|
||||
public static boolean passedserversoftware = true;
|
||||
protected static int count;
|
||||
protected static byte severityLow;
|
||||
protected static byte severityMedium;
|
||||
protected static byte severityHigh;
|
||||
public static String allIncompatibilities;
|
||||
|
||||
public static void BootCheck() {
|
||||
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(21).contains(getJavaVersion())) {
|
||||
isCorrectJDK = 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) {
|
||||
stablemode = true;
|
||||
Iris.safeguard("Stable mode has been activated.");
|
||||
}
|
||||
if (!safeguardPassed) {
|
||||
if (severityMedium >= 1 && severityHigh == 0) {
|
||||
warningmode = true;
|
||||
Iris.safeguard("Warning mode has been activated.");
|
||||
}
|
||||
if (severityHigh >= 1) {
|
||||
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,68 @@
|
||||
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.unstablemode) {
|
||||
Iris.safeguard(C.DARK_RED + "" + ServerBootSFG.count + " Conflicts found");
|
||||
}
|
||||
if (IrisSafeguard.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.3");
|
||||
}
|
||||
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.isCorrectJDK) {
|
||||
Iris.safeguard(C.YELLOW + "Unsupported java version");
|
||||
Iris.safeguard(C.YELLOW + "- Please consider using JDK 21 Instead of JDK " + Iris.getJavaVersion());
|
||||
}
|
||||
if (ServerBootSFG.isJRE) {
|
||||
Iris.safeguard(C.YELLOW + "Unsupported Server JDK");
|
||||
Iris.safeguard(C.YELLOW + "- Please consider using JDK 21 Instead of JRE " + Iris.getJavaVersion());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static String MSGIncompatibleWarnings() {
|
||||
return ServerBootSFG.allIncompatibilities;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
@@ -39,6 +40,7 @@ import org.bukkit.event.player.PlayerChangedWorldEvent;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
public class BoardSVC implements IrisService, BoardProvider {
|
||||
private final KMap<Player, PlayerBoard> boards = new KMap<>();
|
||||
@@ -103,11 +105,11 @@ public class BoardSVC implements IrisService, BoardProvider {
|
||||
@Data
|
||||
public static class PlayerBoard {
|
||||
private final Player player;
|
||||
private final KList<String> lines;
|
||||
private final CopyOnWriteArrayList<String> lines;
|
||||
|
||||
public PlayerBoard(Player player) {
|
||||
this.player = player;
|
||||
this.lines = new KList<>();
|
||||
this.lines = new CopyOnWriteArrayList<>();
|
||||
update();
|
||||
}
|
||||
|
||||
@@ -124,6 +126,20 @@ public class BoardSVC implements IrisService, BoardProvider {
|
||||
int y = player.getLocation().getBlockY() - player.getWorld().getMinHeight();
|
||||
int z = player.getLocation().getBlockZ();
|
||||
|
||||
if(IrisSettings.get().getGeneral().debug){
|
||||
lines.add("&7&m ");
|
||||
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.LIGHT_PURPLE + "Carving" + C.GRAY + ": " + engine.getMantle().isCarved(x,y,z));
|
||||
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)));
|
||||
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 ");
|
||||
} else {
|
||||
lines.add("&7&m ");
|
||||
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()));
|
||||
@@ -131,7 +147,7 @@ public class BoardSVC implements IrisService, BoardProvider {
|
||||
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 ");
|
||||
@@ -139,3 +155,4 @@ public class BoardSVC implements IrisService, BoardProvider {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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() {
|
||||
@@ -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;
|
||||
@@ -33,6 +33,7 @@ import org.bukkit.event.world.WorldUnloadEvent;
|
||||
|
||||
public class EditSVC implements IrisService {
|
||||
private KMap<World, BlockEditor> editors;
|
||||
public static boolean deletingWorld = false;
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
@@ -71,11 +72,12 @@ 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) {
|
||||
@@ -0,0 +1,187 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 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.service;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.link.*;
|
||||
import com.volmit.iris.core.nms.container.Pair;
|
||||
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.plugin.IrisService;
|
||||
import lombok.Data;
|
||||
import lombok.NonNull;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.server.PluginEnableEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Data
|
||||
public class ExternalDataSVC implements IrisService {
|
||||
|
||||
private KList<ExternalDataProvider> providers = new KList<>(), activeProviders = new KList<>();
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
Iris.info("Loading ExternalDataProvider...");
|
||||
Bukkit.getPluginManager().registerEvents(this, Iris.instance);
|
||||
|
||||
providers.add(new NexoDataProvider());
|
||||
if (Bukkit.getPluginManager().getPlugin("Nexo") != null) {
|
||||
Iris.info("Nexo found, loading NexoDataProvider...");
|
||||
}
|
||||
providers.add(new MythicCrucibleDataProvider());
|
||||
if (Bukkit.getPluginManager().getPlugin("MythicCrucible") != null) {
|
||||
Iris.info("MythicCrucible found, loading MythicCrucibleDataProvider...");
|
||||
}
|
||||
providers.add(new ItemAdderDataProvider());
|
||||
if (Bukkit.getPluginManager().getPlugin("ItemAdder") != null) {
|
||||
Iris.info("ItemAdder found, loading ItemAdderDataProvider...");
|
||||
}
|
||||
providers.add(new ExecutableItemsDataProvider());
|
||||
if (Bukkit.getPluginManager().getPlugin("ExecutableItems") != null) {
|
||||
Iris.info("ExecutableItems found, loading ExecutableItemsDataProvider...");
|
||||
}
|
||||
providers.add(new HMCLeavesDataProvider());
|
||||
if (Bukkit.getPluginManager().getPlugin("HMCLeaves") != null) {
|
||||
Iris.info("BlockAdder found, loading HMCLeavesDataProvider...");
|
||||
}
|
||||
providers.add(new MMOItemsDataProvider());
|
||||
if (Bukkit.getPluginManager().getPlugin("MMOItems") != null) {
|
||||
Iris.info("MMOItems found, loading MMOItemsDataProvider...");
|
||||
}
|
||||
providers.add(new EcoItemsDataProvider());
|
||||
if (Bukkit.getPluginManager().getPlugin("EcoItems") != null) {
|
||||
Iris.info("EcoItems found, loading EcoItemsDataProvider...");
|
||||
}
|
||||
|
||||
for (ExternalDataProvider p : providers) {
|
||||
if (p.isReady()) {
|
||||
activeProviders.add(p);
|
||||
p.init();
|
||||
Iris.info("Enabled ExternalDataProvider for %s.", p.getPluginId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPluginEnable(PluginEnableEvent e) {
|
||||
if (activeProviders.stream().noneMatch(p -> p.getPlugin().equals(e.getPlugin()))) {
|
||||
providers.stream().filter(p -> p.isReady() && p.getPlugin().equals(e.getPlugin())).findFirst().ifPresent(edp -> {
|
||||
activeProviders.add(edp);
|
||||
edp.init();
|
||||
Iris.info("Enabled ExternalDataProvider for %s.", edp.getPluginId());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void registerProvider(@NonNull ExternalDataProvider provider) {
|
||||
String plugin = provider.getPluginId();
|
||||
if (providers.stream().map(ExternalDataProvider::getPluginId).anyMatch(plugin::equals))
|
||||
throw new IllegalArgumentException("A provider with the same plugin id already exists.");
|
||||
|
||||
providers.add(provider);
|
||||
if (provider.isReady()) {
|
||||
activeProviders.add(provider);
|
||||
provider.init();
|
||||
}
|
||||
}
|
||||
|
||||
public Optional<BlockData> getBlockData(final Identifier key) {
|
||||
var pair = parseState(key);
|
||||
Identifier mod = pair.getA();
|
||||
|
||||
Optional<ExternalDataProvider> provider = activeProviders.stream().filter(p -> p.isValidProvider(mod, false)).findFirst();
|
||||
if (provider.isEmpty())
|
||||
return Optional.empty();
|
||||
try {
|
||||
return Optional.of(provider.get().getBlockData(mod, pair.getB()));
|
||||
} catch (MissingResourceException e) {
|
||||
Iris.error(e.getMessage() + " - [" + e.getClassName() + ":" + e.getKey() + "]");
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
public Optional<ItemStack> getItemStack(Identifier key, KMap<String, Object> customNbt) {
|
||||
Optional<ExternalDataProvider> provider = activeProviders.stream().filter(p -> p.isValidProvider(key, true)).findFirst();
|
||||
if (provider.isEmpty()) {
|
||||
Iris.warn("No matching Provider found for modded material \"%s\"!", key);
|
||||
return Optional.empty();
|
||||
}
|
||||
try {
|
||||
return Optional.of(provider.get().getItemStack(key, customNbt));
|
||||
} catch (MissingResourceException e) {
|
||||
Iris.error(e.getMessage() + " - [" + e.getClassName() + ":" + e.getKey() + "]");
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
public void processUpdate(Engine engine, Block block, Identifier blockId) {
|
||||
Optional<ExternalDataProvider> provider = activeProviders.stream().filter(p -> p.isValidProvider(blockId, false)).findFirst();
|
||||
if (provider.isEmpty()) {
|
||||
Iris.warn("No matching Provider found for modded material \"%s\"!", blockId);
|
||||
return;
|
||||
}
|
||||
provider.get().processUpdate(engine, block, blockId);
|
||||
}
|
||||
|
||||
public Identifier[] getAllBlockIdentifiers() {
|
||||
KList<Identifier> names = new KList<>();
|
||||
activeProviders.forEach(p -> names.add(p.getBlockTypes()));
|
||||
return names.toArray(new Identifier[0]);
|
||||
}
|
||||
|
||||
public Identifier[] getAllItemIdentifiers() {
|
||||
KList<Identifier> names = new KList<>();
|
||||
activeProviders.forEach(p -> names.add(p.getItemTypes()));
|
||||
return names.toArray(new Identifier[0]);
|
||||
}
|
||||
|
||||
public static Pair<Identifier, KMap<String, String>> parseState(Identifier key) {
|
||||
if (!key.key().contains("[") || !key.key().contains("]")) {
|
||||
return new Pair<>(key, new KMap<>());
|
||||
}
|
||||
String state = key.key().split("\\Q[\\E")[1].split("\\Q]\\E")[0];
|
||||
KMap<String, String> stateMap = new KMap<>();
|
||||
if (!state.isEmpty()) {
|
||||
Arrays.stream(state.split(",")).forEach(s -> stateMap.put(s.split("=")[0], s.split("=")[1]));
|
||||
}
|
||||
return new Pair<>(new Identifier(key.namespace(), key.key().split("\\Q[\\E")[0]), stateMap);
|
||||
}
|
||||
|
||||
public static Identifier buildState(Identifier key, KMap<String, String> state) {
|
||||
if (state.isEmpty()) {
|
||||
return key;
|
||||
}
|
||||
String path = state.entrySet()
|
||||
.stream()
|
||||
.map(e -> e.getKey() + "=" + e.getValue())
|
||||
.collect(Collectors.joining(",", key.key() + "[", "]"));
|
||||
return new Identifier(key.namespace(), path);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user