mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2025-12-20 07:29:32 +00:00
Compare commits
1009 Commits
old/iris3
...
feat/headl
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eff598d005 | ||
|
|
d86ec7b1cd | ||
|
|
407e51378c | ||
|
|
c468eb1ab1 | ||
|
|
bdb7cc61e5 | ||
|
|
e8f9e841c4 | ||
|
|
1b1b9d97b7 | ||
|
|
24355064ff | ||
|
|
06a45056d9 | ||
|
|
dfe4894be7 | ||
|
|
8eb2287ec0 | ||
|
|
c4f0722614 | ||
|
|
7fa1484b21 | ||
|
|
1c5eb8b910 | ||
|
|
94bf530d93 | ||
|
|
686ae57b5b | ||
|
|
a911685aaf | ||
|
|
0d9a45dfd9 | ||
|
|
8a55bbfd20 | ||
|
|
6899761ca9 | ||
|
|
a58958fd62 | ||
|
|
307f3c9158 | ||
|
|
4f275c2e06 | ||
|
|
7e4e3f3cd8 | ||
|
|
84e5add564 | ||
|
|
4d4adbb76f | ||
|
|
ff2f285784 | ||
|
|
5934c43b70 | ||
|
|
11567b13d3 | ||
|
|
8b1636e78a | ||
|
|
3bdad10562 | ||
|
|
ac03a977aa | ||
|
|
2087ba88b1 | ||
|
|
e9d1b9f18e | ||
|
|
6e84d38680 | ||
|
|
22622f6e8a | ||
|
|
735203aa95 | ||
|
|
013bc365a9 | ||
|
|
c2dfbac641 | ||
|
|
7d472c0b13 | ||
|
|
d7270f66e1 | ||
|
|
b220b1bffa | ||
|
|
4796fe98cb | ||
|
|
ece905ec6e | ||
|
|
53c9e7c04c | ||
|
|
29f6f52443 | ||
|
|
a778cc51a6 | ||
|
|
c6963d0cd3 | ||
|
|
5b4ab0a3c1 | ||
|
|
489844f61b | ||
|
|
4d1b0246ca | ||
|
|
13f3511fa8 | ||
|
|
f6f2766315 | ||
|
|
56530a1245 | ||
|
|
210a1f29a7 | ||
|
|
e8dd81b014 | ||
|
|
d32cc281e3 | ||
|
|
2ff6b59271 | ||
|
|
847bf972ae | ||
|
|
3ff87566f5 | ||
|
|
e5d21fdf7e | ||
|
|
0b2fd3b358 | ||
|
|
10484d1226 | ||
|
|
ce0092c52a | ||
|
|
474e033c2b | ||
|
|
62aad1f497 | ||
|
|
32b5157682 | ||
|
|
70717ea282 | ||
|
|
15975f108c | ||
|
|
66c66e82c1 | ||
|
|
4f6da95d8e | ||
|
|
b37ccbdf01 | ||
|
|
30dbe0881a | ||
|
|
20ad4657a9 | ||
|
|
d4986f42a6 | ||
|
|
8df15c0c2d | ||
|
|
24e1c578c8 | ||
|
|
1c3bff7559 | ||
|
|
a09657b4d0 | ||
|
|
910220d3ca | ||
|
|
fc05c24e3a | ||
|
|
e1a7e772cf | ||
|
|
3c6411c322 | ||
|
|
628761affa | ||
|
|
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.17.1
|
- 1.17.1
|
||||||
- 1.18
|
- 1.18
|
||||||
|
- 1.19
|
||||||
|
- 1.20
|
||||||
|
- 1.21
|
||||||
|
- 1.22
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
- type: input
|
- type: input
|
||||||
|
|||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,5 +1,6 @@
|
|||||||
|
|
||||||
build/
|
build/
|
||||||
|
libs/
|
||||||
|
|
||||||
.gradle/
|
.gradle/
|
||||||
|
|
||||||
@@ -9,4 +10,4 @@ build/
|
|||||||
|
|
||||||
collection/
|
collection/
|
||||||
|
|
||||||
src/main/java/com/volmit/iris/util/uniques/
|
/core/src/main/java/com/volmit/iris/util/uniques/
|
||||||
|
|||||||
18
README.md
18
README.md
@@ -11,32 +11,31 @@ development.
|
|||||||
|
|
||||||
Consider supporting our development by buying Iris on spigot! We work hard to make Iris the best it can be for everyone.
|
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
|
### Command Line Builds
|
||||||
|
|
||||||
1. Install [Java JDK 17](https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html)
|
1. Install [Java JDK 21](https://www.oracle.com/java/technologies/javase/jdk21-archive-downloads.html)
|
||||||
2. Set the JDK installation path to `JAVA_HOME` as an environment variable.
|
2. Set the JDK installation path to `JAVA_HOME` as an environment variable.
|
||||||
* Windows
|
* Windows
|
||||||
1. Start > Type `env` and press Enter
|
1. Start > Type `env` and press Enter
|
||||||
2. Advanced > Environment Variables
|
2. Advanced > Environment Variables
|
||||||
3. Under System Variables, click `New...`
|
3. Under System Variables, click `New...`
|
||||||
4. Variable Name: `JAVA_HOME`
|
4. Variable Name: `JAVA_HOME`
|
||||||
5. Variable Value: `C:\Program Files\Java\jdk-17.0.1` (verify this exists after installing java don't just copy
|
5. Variable Value: `C:\Program Files\Java\jdk-21.0.1` (verify this exists after installing java don't just copy
|
||||||
the example text)
|
the example text)
|
||||||
* MacOS
|
* MacOS
|
||||||
1. Run `/usr/libexec/java_home -V` and look for Java 17
|
1. Run `/usr/libexec/java_home -V` and look for Java 21
|
||||||
2. Run `sudo nano ~/.zshenv`
|
2. Run `sudo nano ~/.zshenv`
|
||||||
3. Add `export JAVA_HOME=$(/usr/libexec/java_home)` as a new line
|
3. Add `export JAVA_HOME=$(/usr/libexec/java_home)` as a new line
|
||||||
4. Use `CTRL + X`, then Press `Y`, Then `ENTER`
|
4. Use `CTRL + X`, then Press `Y`, Then `ENTER`
|
||||||
5. Quit & Reopen Terminal and verify with `echo $JAVA_HOME`. It should print a directory
|
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.
|
3. Once the project has setup, run `gradlew iris`
|
||||||
Otherwise, skip this step. Grab a coffee, this may take up to 5 minutes depending on your cpu & internet connection.
|
4. The Iris jar will be placed in `Iris/build/Iris-XXX-XXX.jar` Enjoy! Consider supporting us by buying it on spigot!
|
||||||
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!
|
|
||||||
|
|
||||||
### IDE Builds (for development)
|
### IDE Builds (for development)
|
||||||
|
|
||||||
* Run `gradlew setup` any time you get dependency issues with craftbukkit
|
* Configure ITJ Gradle to use JDK 21 (in settings, search for gradle)
|
||||||
* 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
|
* Add a build line in the build.gradle for your own build task to directly compile Iris into your plugins folder if you
|
||||||
prefer.
|
prefer.
|
||||||
* Resync the project & run your newly created task (under the development folder in gradle tasks!)
|
* Resync the project & run your newly created task (under the development folder in gradle tasks!)
|
||||||
@@ -67,7 +66,6 @@ IrisAccess access=IrisToolbelt.createWorld() // If you like builders...
|
|||||||
.name("myWorld") // The world name
|
.name("myWorld") // The world name
|
||||||
.dimension("terrifyinghands")
|
.dimension("terrifyinghands")
|
||||||
.seed(69133742) // The world seed
|
.seed(69133742) // The world seed
|
||||||
.headless(true) // Headless make gen go fast
|
|
||||||
.pregen(PregenTask // Define a pregen job to run
|
.pregen(PregenTask // Define a pregen job to run
|
||||||
.builder()
|
.builder()
|
||||||
.center(new Position2(0,0)) // REGION coords (1 region = 32x32 chunks)
|
.center(new Position2(0,0)) // REGION coords (1 region = 32x32 chunks)
|
||||||
|
|||||||
376
build.gradle
376
build.gradle
@@ -16,68 +16,147 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* 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 {
|
plugins {
|
||||||
id 'java'
|
id 'java'
|
||||||
id 'java-library'
|
id 'java-library'
|
||||||
id "io.freefair.lombok" version "6.3.0"
|
id "io.github.goooler.shadow" version "8.1.7"
|
||||||
id "com.github.johnrengelman.shadow" version "7.1.2"
|
|
||||||
id "de.undercouch.download" version "5.0.1"
|
id "de.undercouch.download" version "5.0.1"
|
||||||
}
|
}
|
||||||
|
|
||||||
version '2.2.1-1.19' // Needs to be version specific
|
|
||||||
def nmsVersion = "1.19"
|
version '3.6.5-1.20.1-1.21.4'
|
||||||
def apiVersion = '1.19'
|
|
||||||
def spigotJarVersion = '1.19-R0.1-SNAPSHOT'
|
|
||||||
def name = getRootProject().getName() // Defined in settings.gradle
|
|
||||||
def main = 'com.volmit.iris.Iris'
|
|
||||||
|
|
||||||
// ADD YOURSELF AS A NEW LINE IF YOU WANT YOUR OWN BUILD TASK GENERATED
|
// ADD YOURSELF AS A NEW LINE IF YOU WANT YOUR OWN BUILD TASK GENERATED
|
||||||
// ======================== WINDOWS =============================
|
// ======================== WINDOWS =============================
|
||||||
registerCustomOutputTask('Cyberpwn', 'C://Users/cyberpwn/Documents/development/server/plugins')
|
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('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('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 ==============================
|
// ========================== UNIX ==============================
|
||||||
registerCustomOutputTaskUnix('CyberpwnLT', '/Users/danielmills/development/server/plugins')
|
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')
|
||||||
// ==============================================================
|
// ==============================================================
|
||||||
|
|
||||||
/**
|
def NMS_BINDINGS = Map.of(
|
||||||
* Gradle is weird sometimes, we need to delete the plugin yml from the build folder to actually filter properly.
|
"v1_21_R3", "1.21.4-R0.1-SNAPSHOT",
|
||||||
*/
|
"v1_21_R2", "1.21.3-R0.1-SNAPSHOT",
|
||||||
file(jar.archiveFile.get().getAsFile().getParentFile().getParentFile().getParentFile().getAbsolutePath() + '/build/resources/main/plugin.yml').delete()
|
"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",
|
||||||
* Expand properties into plugin yml
|
"v1_20_R2", "1.20.2-R0.1-SNAPSHOT",
|
||||||
*/
|
"v1_20_R1", "1.20.1-R0.1-SNAPSHOT",
|
||||||
processResources {
|
|
||||||
filesMatching('**/plugin.yml') {
|
|
||||||
expand(
|
|
||||||
'name': name.toString(),
|
|
||||||
'version': version.toString(),
|
|
||||||
'main': main.toString(),
|
|
||||||
'apiversion': apiVersion.toString()
|
|
||||||
)
|
)
|
||||||
|
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")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
shadowJar {
|
||||||
* Unified repo
|
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 {
|
||||||
|
exclude(dependency("org.ow2.asm:asm:"))
|
||||||
|
exclude(dependency("org.jetbrains:"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation project(':core')
|
||||||
|
}
|
||||||
|
|
||||||
|
configurations.configureEach {
|
||||||
|
resolutionStrategy.cacheChangingModulesFor 60, 'minutes'
|
||||||
|
resolutionStrategy.cacheDynamicVersionsFor 60, 'minutes'
|
||||||
|
}
|
||||||
|
|
||||||
|
allprojects {
|
||||||
|
apply plugin: 'java'
|
||||||
|
|
||||||
repositories {
|
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()
|
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://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.8.1'
|
||||||
|
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 +164,64 @@ repositories {
|
|||||||
*/
|
*/
|
||||||
compileJava {
|
compileJava {
|
||||||
options.compilerArgs << '-parameters'
|
options.compilerArgs << '-parameters'
|
||||||
|
options.encoding = "UTF-8"
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
javadoc {
|
||||||
* Configure Iris for shading
|
options.encoding = "UTF-8"
|
||||||
*/
|
options.addStringOption('Xdoclint:none', '-quiet')
|
||||||
shadowJar {
|
}
|
||||||
//minimize()
|
|
||||||
append("plugin.yml")
|
task sourcesJar(type: Jar, dependsOn: classes) {
|
||||||
relocate 'com.dfsek.paralithic', 'com.volmit.iris.util.paralithic'
|
archiveClassifier.set('sources')
|
||||||
relocate 'io.papermc.lib', 'com.volmit.iris.util.paper'
|
from sourceSets.main.allSource
|
||||||
relocate 'net.kyori', 'com.volmit.iris.util.kyori'
|
}
|
||||||
dependencies {
|
|
||||||
include(dependency('io.papermc:paperlib'))
|
task javadocJar(type: Jar, dependsOn: javadoc) {
|
||||||
include(dependency('com.dfsek:Paralithic'))
|
archiveClassifier.set('javadoc')
|
||||||
include(dependency('net.kyori:'))
|
from javadoc.destinationDir
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
configurations.all {
|
if (JavaVersion.current().toString() != "21") {
|
||||||
resolutionStrategy.cacheChangingModulesFor 60, 'minutes'
|
|
||||||
resolutionStrategy.cacheDynamicVersionsFor 60, 'minutes'
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dependencies.
|
|
||||||
*
|
|
||||||
* Provided or classpath dependencies are not shaded and are available on the runtime classpath
|
|
||||||
*
|
|
||||||
* Shaded dependencies are not available at runtime, nor are they available on mvn central so they
|
|
||||||
* need to be shaded into the jar (increasing binary size)
|
|
||||||
*
|
|
||||||
* Dynamically loaded dependencies are defined in the plugin.yml (updating these must be updated in the
|
|
||||||
* plugin.yml also, otherwise they wont be available). These do not increase binary size). Only declare
|
|
||||||
* these dependencies if they are available on mvn central.
|
|
||||||
*/
|
|
||||||
dependencies {
|
|
||||||
// Provided or Classpath
|
|
||||||
compileOnly 'org.projectlombok:lombok:1.18.24'
|
|
||||||
annotationProcessor 'org.projectlombok:lombok:1.18.24'
|
|
||||||
implementation 'org.spigotmc:spigot-api:1.19-R0.1-SNAPSHOT'
|
|
||||||
implementation 'me.clip:placeholderapi:2.11.1'
|
|
||||||
implementation 'io.th0rgal:oraxen:1.94.0'
|
|
||||||
implementation 'org.bukkit:craftbukkit:1.19-R0.1-SNAPSHOT:remapped-mojang'
|
|
||||||
implementation 'com.github.LoneDev6:api-itemsadder:3.1.0b'
|
|
||||||
|
|
||||||
// Shaded
|
|
||||||
implementation 'com.dfsek:Paralithic:0.4.0'
|
|
||||||
implementation 'io.papermc:paperlib:1.0.5'
|
|
||||||
implementation "net.kyori:adventure-text-minimessage:4.11.0"
|
|
||||||
implementation 'net.kyori:adventure-platform-bukkit:4.1.0'
|
|
||||||
implementation 'net.kyori:adventure-api:4.11.0'
|
|
||||||
|
|
||||||
// Dynamically Loaded
|
|
||||||
implementation 'io.timeandspace:smoothie-map:2.0.2'
|
|
||||||
implementation 'it.unimi.dsi:fastutil:8.5.8'
|
|
||||||
implementation 'com.googlecode.concurrentlinkedhashmap:concurrentlinkedhashmap-lru:1.4.2'
|
|
||||||
implementation 'org.zeroturnaround:zt-zip:1.14'
|
|
||||||
implementation 'com.google.code.gson:gson:2.9.0'
|
|
||||||
implementation 'org.ow2.asm:asm:9.2'
|
|
||||||
implementation 'com.google.guava:guava:31.1-jre'
|
|
||||||
implementation 'bsf:bsf:2.4.0'
|
|
||||||
implementation 'rhino:js:1.7R2'
|
|
||||||
implementation 'com.github.ben-manes.caffeine:caffeine:3.0.6'
|
|
||||||
implementation 'org.apache.commons:commons-lang3:3.12.0'
|
|
||||||
}
|
|
||||||
|
|
||||||
if (JavaVersion.current().toString() != "17") {
|
|
||||||
System.err.println()
|
System.err.println()
|
||||||
System.err.println("=========================================================================================================")
|
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()
|
||||||
System.err.println("=== For IDEs ===")
|
System.err.println("=== For IDEs ===")
|
||||||
System.err.println("1. Configure the project for Java 17")
|
System.err.println("1. Configure the project for Java 21")
|
||||||
System.err.println("2. Configure the bundled gradle to use Java 17 in settings")
|
System.err.println("2. Configure the bundled gradle to use Java 21 in settings")
|
||||||
System.err.println()
|
System.err.println()
|
||||||
System.err.println("=== For Command Line (gradlew) ===")
|
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("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-17.0.1")
|
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("3. Open a new command prompt window to get the new environment variables if need be.")
|
||||||
System.err.println("=========================================================================================================")
|
System.err.println("=========================================================================================================")
|
||||||
System.err.println()
|
System.err.println()
|
||||||
System.exit(69);
|
System.exit(69);
|
||||||
}
|
}
|
||||||
|
|
||||||
def buildToolsJar = new File(buildDir, "buildtools/BuildTools.jar");
|
task iris(type: Copy) {
|
||||||
def specialSourceJar = new File(buildDir, "specialsource/SpecialSource.jar");
|
|
||||||
def buildToolsFolder = new File(buildDir, "buildtools");
|
|
||||||
def specialSourceFolder = new File(buildDir, "specialsource");
|
|
||||||
def buildToolsHint = new File(buildDir, "buildtools/craftbukkit-" + nmsVersion + ".jar");
|
|
||||||
def outputShadeJar = new File(buildDir, "libs/Iris-" + version + "-all.jar");
|
|
||||||
def ssiJar = new File(buildDir, "specialsource/Iris-" + version + "-all.jar");
|
|
||||||
def ssobfJar = new File(buildDir, "specialsource/Iris-" + version + "-rmo.jar");
|
|
||||||
def ssJar = new File(buildDir, "specialsource/Iris-" + version + "-rma.jar");
|
|
||||||
def homePath = System.properties['user.home']
|
|
||||||
def m2 = new File(homePath + "/.m2/repository")
|
|
||||||
def m2s = m2.getAbsolutePath();
|
|
||||||
|
|
||||||
// ======================== Building Mapped Jars =============================
|
|
||||||
task downloadBuildtools(type: Download) {
|
|
||||||
group "remapping"
|
|
||||||
src 'https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar'
|
|
||||||
dest buildToolsJar
|
|
||||||
onlyIf {
|
|
||||||
!buildToolsJar.exists()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
task downloadSpecialSource(type: Download) {
|
|
||||||
group "remapping"
|
|
||||||
src 'https://repo.maven.apache.org/maven2/net/md-5/SpecialSource/1.10.0/SpecialSource-1.10.0-shaded.jar'
|
|
||||||
dest specialSourceJar
|
|
||||||
onlyIf {
|
|
||||||
!specialSourceJar.exists()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
task executeBuildTools(dependsOn: downloadBuildtools, type: JavaExec)
|
|
||||||
{
|
|
||||||
group "remapping"
|
|
||||||
classpath = files(buildToolsJar)
|
|
||||||
workingDir = buildToolsFolder
|
|
||||||
args = [
|
|
||||||
"--rev",
|
|
||||||
nmsVersion,
|
|
||||||
"--compile",
|
|
||||||
"craftbukkit",
|
|
||||||
"--remap"
|
|
||||||
]
|
|
||||||
onlyIf {
|
|
||||||
!buildToolsHint.exists()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
task copyBuildToSpecialSource(type: Copy)
|
|
||||||
{
|
|
||||||
group "remapping"
|
|
||||||
from outputShadeJar
|
|
||||||
into specialSourceFolder
|
|
||||||
dependsOn(downloadSpecialSource, shadowJar)
|
|
||||||
}
|
|
||||||
|
|
||||||
task specialSourceRemapObfuscate(type: JavaExec)
|
|
||||||
{
|
|
||||||
group "remapping"
|
|
||||||
dependsOn(copyBuildToSpecialSource, downloadSpecialSource, shadowJar)
|
|
||||||
workingDir = specialSourceFolder
|
|
||||||
classpath = files(specialSourceJar,
|
|
||||||
new File(m2s + "/org/spigotmc/spigot/" + spigotJarVersion + "/spigot-" + spigotJarVersion + "-remapped-mojang.jar"))
|
|
||||||
mainClass = "net.md_5.specialsource.SpecialSource"
|
|
||||||
args = [
|
|
||||||
"--live",
|
|
||||||
"-i",
|
|
||||||
ssiJar.getName(),
|
|
||||||
"-o",
|
|
||||||
ssobfJar.getName(),
|
|
||||||
"-m",
|
|
||||||
m2s + "/org/spigotmc/minecraft-server/" + spigotJarVersion + "/minecraft-server-" + spigotJarVersion + "-maps-mojang.txt",
|
|
||||||
"--reverse",
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
task specialSourceRemap(type: JavaExec)
|
|
||||||
{
|
|
||||||
group "remapping"
|
|
||||||
dependsOn(specialSourceRemapObfuscate)
|
|
||||||
workingDir = specialSourceFolder
|
|
||||||
classpath = files(specialSourceJar,
|
|
||||||
new File(m2s + "/org/spigotmc/spigot/" + spigotJarVersion + "/spigot-" + spigotJarVersion + "-remapped-obf.jar"))
|
|
||||||
mainClass = "net.md_5.specialsource.SpecialSource"
|
|
||||||
args = [
|
|
||||||
"--live",
|
|
||||||
"-i",
|
|
||||||
ssobfJar.getName(),
|
|
||||||
"-o",
|
|
||||||
ssJar.getName(),
|
|
||||||
"-m",
|
|
||||||
m2s + "/org/spigotmc/minecraft-server/" + spigotJarVersion + "/minecraft-server-" + spigotJarVersion + "-maps-spigot.csrg"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.compileJava.dependsOn(executeBuildTools)
|
|
||||||
|
|
||||||
compileJava {
|
|
||||||
options.encoding = "UTF-8"
|
|
||||||
}
|
|
||||||
|
|
||||||
task setup()
|
|
||||||
{
|
|
||||||
group("iris")
|
|
||||||
dependsOn(clean, executeBuildTools)
|
|
||||||
}
|
|
||||||
|
|
||||||
task iris(type: Copy)
|
|
||||||
{
|
|
||||||
group "iris"
|
group "iris"
|
||||||
from ssJar
|
from new File(layout.buildDirectory.asFile.get(), "libs/Iris-${version}.jar")
|
||||||
into buildDir
|
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 ->
|
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) {
|
def registerCustomOutputTask(name, path) {
|
||||||
if (!System.properties['os.name'].toLowerCase().contains('windows')) {
|
if (!System.properties['os.name'].toLowerCase().contains('windows')) {
|
||||||
return;
|
return;
|
||||||
@@ -321,3 +255,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:1.0.0-dev.38'
|
||||||
|
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,29 +23,41 @@ import com.google.gson.JsonParseException;
|
|||||||
import com.google.gson.JsonParser;
|
import com.google.gson.JsonParser;
|
||||||
import com.volmit.iris.core.IrisSettings;
|
import com.volmit.iris.core.IrisSettings;
|
||||||
import com.volmit.iris.core.ServerConfigurator;
|
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.loader.IrisData;
|
||||||
import com.volmit.iris.core.nms.INMS;
|
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.service.StudioSVC;
|
||||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||||
|
import com.volmit.iris.core.tools.IrisWorldCreator;
|
||||||
import com.volmit.iris.engine.EnginePanic;
|
import com.volmit.iris.engine.EnginePanic;
|
||||||
import com.volmit.iris.engine.object.IrisCompat;
|
import com.volmit.iris.engine.object.IrisCompat;
|
||||||
|
import com.volmit.iris.engine.object.IrisContextInjector;
|
||||||
import com.volmit.iris.engine.object.IrisDimension;
|
import com.volmit.iris.engine.object.IrisDimension;
|
||||||
import com.volmit.iris.engine.object.IrisWorld;
|
import com.volmit.iris.engine.object.IrisWorld;
|
||||||
import com.volmit.iris.engine.platform.BukkitChunkGenerator;
|
import com.volmit.iris.engine.platform.BukkitChunkGenerator;
|
||||||
import com.volmit.iris.engine.platform.DummyChunkGenerator;
|
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.KList;
|
||||||
import com.volmit.iris.util.collection.KMap;
|
import com.volmit.iris.util.collection.KMap;
|
||||||
import com.volmit.iris.util.exceptions.IrisException;
|
import com.volmit.iris.util.exceptions.IrisException;
|
||||||
import com.volmit.iris.util.format.C;
|
import com.volmit.iris.util.format.C;
|
||||||
import com.volmit.iris.util.format.Form;
|
import com.volmit.iris.util.format.Form;
|
||||||
import com.volmit.iris.util.function.NastyRunnable;
|
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.M;
|
||||||
import com.volmit.iris.util.math.RNG;
|
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.parallel.MultiBurst;
|
||||||
import com.volmit.iris.util.plugin.IrisService;
|
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.VolmitPlugin;
|
||||||
import com.volmit.iris.util.plugin.VolmitSender;
|
import com.volmit.iris.util.plugin.VolmitSender;
|
||||||
import com.volmit.iris.util.reflect.ShadeFix;
|
import com.volmit.iris.util.reflect.ShadeFix;
|
||||||
@@ -55,37 +67,44 @@ import com.volmit.iris.util.scheduling.ShurikenQueue;
|
|||||||
import io.papermc.lib.PaperLib;
|
import io.papermc.lib.PaperLib;
|
||||||
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
|
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
|
||||||
import net.kyori.adventure.text.serializer.ComponentSerializer;
|
import net.kyori.adventure.text.serializer.ComponentSerializer;
|
||||||
import org.bukkit.Bukkit;
|
import org.bstats.bukkit.Metrics;
|
||||||
import org.bukkit.GameMode;
|
import org.bstats.charts.DrilldownPie;
|
||||||
import org.bukkit.Location;
|
import org.bstats.charts.SimplePie;
|
||||||
import org.bukkit.World;
|
import org.bstats.charts.SingleLineChart;
|
||||||
import org.bukkit.WorldCreator;
|
import org.bukkit.*;
|
||||||
import org.bukkit.block.data.BlockData;
|
import org.bukkit.block.data.BlockData;
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
import org.bukkit.configuration.file.FileConfiguration;
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
import org.bukkit.configuration.file.YamlConfiguration;
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.Event;
|
import org.bukkit.event.*;
|
||||||
import org.bukkit.event.HandlerList;
|
|
||||||
import org.bukkit.event.Listener;
|
|
||||||
import org.bukkit.generator.BiomeProvider;
|
import org.bukkit.generator.BiomeProvider;
|
||||||
import org.bukkit.generator.ChunkGenerator;
|
import org.bukkit.generator.ChunkGenerator;
|
||||||
import org.bukkit.plugin.IllegalPluginAccessException;
|
import org.bukkit.plugin.IllegalPluginAccessException;
|
||||||
import org.bukkit.plugin.Plugin;
|
import org.bukkit.plugin.Plugin;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import oshi.SystemInfo;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
|
import java.math.RoundingMode;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.Date;
|
import java.text.NumberFormat;
|
||||||
import java.util.Map;
|
import java.util.*;
|
||||||
import java.util.Objects;
|
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")
|
@SuppressWarnings("CanBeFinal")
|
||||||
public class Iris extends VolmitPlugin implements Listener {
|
public class Iris extends VolmitPlugin implements Listener {
|
||||||
private static final Queue<Runnable> syncJobs = new ShurikenQueue<>();
|
private static final Queue<Runnable> syncJobs = new ShurikenQueue<>();
|
||||||
|
|
||||||
public static Iris instance;
|
public static Iris instance;
|
||||||
public static BukkitAudiences audiences;
|
public static BukkitAudiences audiences;
|
||||||
public static MultiverseCoreLink linkMultiverseCore;
|
public static MultiverseCoreLink linkMultiverseCore;
|
||||||
@@ -107,6 +126,10 @@ public class Iris extends VolmitPlugin implements Listener {
|
|||||||
private KMap<Class<? extends IrisService>, IrisService> services;
|
private KMap<Class<? extends IrisService>, IrisService> services;
|
||||||
|
|
||||||
public static VolmitSender getSender() {
|
public static VolmitSender getSender() {
|
||||||
|
if (sender == null) {
|
||||||
|
sender = new VolmitSender(Bukkit.getConsoleSender());
|
||||||
|
sender.setTag(instance.getTag());
|
||||||
|
}
|
||||||
return sender;
|
return sender;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,15 +196,16 @@ public class Iris extends VolmitPlugin implements Listener {
|
|||||||
|
|
||||||
public static void msg(String string) {
|
public static void msg(String string) {
|
||||||
try {
|
try {
|
||||||
sender.sendMessage(string);
|
getSender().sendMessage(string);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
try {
|
try {
|
||||||
System.out.println(instance.getTag() + string.replaceAll("(<([^>]+)>)", ""));
|
instance.getLogger().info(instance.getTag() + string.replaceAll("(<([^>]+)>)", ""));
|
||||||
} catch (Throwable ignored1) {
|
} catch (Throwable ignored1) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static File getCached(String name, String url) {
|
public static File getCached(String name, String url) {
|
||||||
String h = IO.hash(name + "@" + url);
|
String h = IO.hash(name + "@" + url);
|
||||||
File f = Iris.instance.getDataFile("cache", h.substring(0, 2), h.substring(3, 5), h);
|
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);
|
msg(C.IRIS + string);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void info(String string) {
|
public static void info(String format, Object... args) {
|
||||||
msg(C.WHITE + string);
|
msg(C.WHITE + String.format(format, args));
|
||||||
|
}
|
||||||
|
public static void safeguard(String format, Object... args) {
|
||||||
|
msg(C.RESET + String.format(format, args));
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
@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");
|
String version = System.getProperty("java.version");
|
||||||
if (version.startsWith("1.")) {
|
if (version.startsWith("1.")) {
|
||||||
version = version.substring(2, 3);
|
version = version.substring(2, 3);
|
||||||
@@ -339,6 +366,13 @@ public class Iris extends VolmitPlugin implements Listener {
|
|||||||
return Integer.parseInt(version);
|
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) {
|
public static void reportErrorChunk(int x, int z, Throwable e, String extra) {
|
||||||
if (IrisSettings.get().getGeneral().isDebug()) {
|
if (IrisSettings.get().getGeneral().isDebug()) {
|
||||||
File f = instance.getDataFile("debug", "chunk-errors", "chunk." + x + "." + z + ".txt");
|
File f = instance.getDataFile("debug", "chunk-errors", "chunk." + x + "." + z + ".txt");
|
||||||
@@ -381,17 +415,56 @@ 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() {
|
private void enable() {
|
||||||
instance = this;
|
instance = this;
|
||||||
services = new KMap<>();
|
services = new KMap<>();
|
||||||
|
setupAudience();
|
||||||
initialize("com.volmit.iris.core.service").forEach((i) -> services.put((Class<? extends IrisService>) i.getClass(), (IrisService) i));
|
initialize("com.volmit.iris.core.service").forEach((i) -> services.put((Class<? extends IrisService>) i.getClass(), (IrisService) i));
|
||||||
INMS.get();
|
INMS.get();
|
||||||
IO.delete(new File("iris"));
|
IO.delete(new File("iris"));
|
||||||
setupAudience();
|
|
||||||
sender = new VolmitSender(Bukkit.getConsoleSender());
|
|
||||||
sender.setTag(getTag());
|
|
||||||
instance = this;
|
|
||||||
compat = IrisCompat.configured(getDataFile("compat.json"));
|
compat = IrisCompat.configured(getDataFile("compat.json"));
|
||||||
|
ServerConfigurator.configure();
|
||||||
|
new IrisContextInjector();
|
||||||
|
IrisSafeguard.IrisSafeguardSystem();
|
||||||
|
getSender().setTag(getTag());
|
||||||
|
IrisSafeguard.earlySplash();
|
||||||
linkMultiverseCore = new MultiverseCoreLink();
|
linkMultiverseCore = new MultiverseCoreLink();
|
||||||
linkMythicMobs = new MythicMobsLink();
|
linkMythicMobs = new MythicMobsLink();
|
||||||
configWatcher = new FileWatcher(getDataFile("settings.json"));
|
configWatcher = new FileWatcher(getDataFile("settings.json"));
|
||||||
@@ -400,12 +473,15 @@ public class Iris extends VolmitPlugin implements Listener {
|
|||||||
J.s(() -> {
|
J.s(() -> {
|
||||||
J.a(() -> PaperLib.suggestPaper(this));
|
J.a(() -> PaperLib.suggestPaper(this));
|
||||||
J.a(() -> IO.delete(getTemp()));
|
J.a(() -> IO.delete(getTemp()));
|
||||||
|
J.a(LazyPregenerator::loadLazyGenerators, 100);
|
||||||
J.a(this::bstats);
|
J.a(this::bstats);
|
||||||
J.ar(this::checkConfigHotload, 60);
|
J.ar(this::checkConfigHotload, 60);
|
||||||
J.sr(this::tickQueue, 0);
|
J.sr(this::tickQueue, 0);
|
||||||
J.s(this::setupPapi);
|
J.s(this::setupPapi);
|
||||||
J.a(ServerConfigurator::configure, 20);
|
J.a(ServerConfigurator::configure, 20);
|
||||||
splash();
|
splash();
|
||||||
|
UtilsSFG.splash();
|
||||||
|
|
||||||
autoStartStudio();
|
autoStartStudio();
|
||||||
checkForBukkitWorlds();
|
checkForBukkitWorlds();
|
||||||
IrisToolbelt.retainMantleDataForSlice(String.class.getCanonicalName());
|
IrisToolbelt.retainMantleDataForSlice(String.class.getCanonicalName());
|
||||||
@@ -417,35 +493,37 @@ public class Iris extends VolmitPlugin implements Listener {
|
|||||||
FileConfiguration fc = new YamlConfiguration();
|
FileConfiguration fc = new YamlConfiguration();
|
||||||
try {
|
try {
|
||||||
fc.load(new File("bukkit.yml"));
|
fc.load(new File("bukkit.yml"));
|
||||||
searching: for(String i : fc.getKeys(true))
|
ConfigurationSection section = fc.getConfigurationSection("worlds");
|
||||||
{
|
if (section == null) {
|
||||||
if(i.startsWith("worlds.") && i.endsWith(".generator")) {
|
return;
|
||||||
String worldName = i.split("\\Q.\\E")[1];
|
}
|
||||||
String generator = IrisSettings.get().getGenerator().getDefaultWorldType();
|
|
||||||
if(fc.getString(i).startsWith("Iris:")) {
|
for (String s : section.getKeys(false)) {
|
||||||
generator = fc.getString(i).split("\\Q:\\E")[1];
|
ConfigurationSection entry = section.getConfigurationSection(s);
|
||||||
} else if(fc.getString(i).equals("Iris")) {
|
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();
|
generator = IrisSettings.get().getGenerator().getDefaultWorldType();
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(World j : Bukkit.getWorlds())
|
if (Bukkit.getWorld(s) != null)
|
||||||
{
|
continue;
|
||||||
if(j.getName().equals(worldName))
|
|
||||||
{
|
|
||||||
continue searching;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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("Loading World: %s | Generator: %s", s, generator);
|
||||||
Iris.info(C.LIGHT_PURPLE + "Preparing Spawn for " + worldName + "' using Iris:" + generator);
|
|
||||||
World world = new WorldCreator(worldName)
|
Iris.info(C.LIGHT_PURPLE + "Preparing Spawn for " + s + "' using Iris:" + generator + "...");
|
||||||
.generator(getDefaultWorldGenerator(worldName, generator))
|
WorldCreator c = new WorldCreator(s)
|
||||||
.environment(IrisData.loadAnyDimension(generator).getEnvironment())
|
.generator(getDefaultWorldGenerator(s, generator))
|
||||||
.createWorld();
|
.environment(IrisData.loadAnyDimension(generator).getEnvironment());
|
||||||
Iris.info(C.LIGHT_PURPLE + "Loaded " + worldName + "!");
|
INMS.get().createWorld(c);
|
||||||
}
|
Iris.info(C.LIGHT_PURPLE + "Loaded " + s + "!");
|
||||||
}
|
}
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
@@ -457,7 +535,7 @@ public class Iris extends VolmitPlugin implements Listener {
|
|||||||
Iris.info("Starting up auto Studio!");
|
Iris.info("Starting up auto Studio!");
|
||||||
try {
|
try {
|
||||||
Player r = new KList<>(getServer().getOnlinePlayers()).getRandom();
|
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(() -> {
|
J.s(() -> {
|
||||||
for (Player i : getServer().getOnlinePlayers()) {
|
for (Player i : getServer().getOnlinePlayers()) {
|
||||||
i.setGameMode(GameMode.SPECTATOR);
|
i.setGameMode(GameMode.SPECTATOR);
|
||||||
@@ -482,48 +560,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) {
|
public void postShutdown(Runnable r) {
|
||||||
postShutdown.add(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() {
|
public void onEnable() {
|
||||||
enable();
|
enable();
|
||||||
super.onEnable();
|
super.onEnable();
|
||||||
Bukkit.getPluginManager().registerEvents(this, this);
|
Bukkit.getPluginManager().registerEvents(this, this);
|
||||||
|
setupChecks();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onDisable() {
|
public void onDisable() {
|
||||||
@@ -536,10 +581,6 @@ public class Iris extends VolmitPlugin implements Listener {
|
|||||||
super.onDisable();
|
super.onDisable();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void fixShading() {
|
|
||||||
ShadeFix.fix(ComponentSerializer.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setupPapi() {
|
private void setupPapi() {
|
||||||
if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null) {
|
if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null) {
|
||||||
new IrisPapiExpansion().register();
|
new IrisPapiExpansion().register();
|
||||||
@@ -558,7 +599,39 @@ public class Iris extends VolmitPlugin implements Listener {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getTag(String subTag) {
|
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 + ": ";
|
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() {
|
private void checkConfigHotload() {
|
||||||
@@ -591,7 +664,50 @@ public class Iris extends VolmitPlugin implements Listener {
|
|||||||
|
|
||||||
private void bstats() {
|
private void bstats() {
|
||||||
if (IrisSettings.get().getGeneral().isPluginMetrics()) {
|
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::getEngine)
|
||||||
|
.collect(Collectors.toMap(engine -> engine.getDimension().getLoadKey(), engine -> {
|
||||||
|
var hash32 = engine.getHash32().getNow(null);
|
||||||
|
if (hash32 == null) return Map.of();
|
||||||
|
int version = engine.getDimension().getVersion();
|
||||||
|
String checksum = Long.toHexString(hash32);
|
||||||
|
|
||||||
|
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 +769,7 @@ public class Iris extends VolmitPlugin implements Listener {
|
|||||||
.name(worldName)
|
.name(worldName)
|
||||||
.seed(1337)
|
.seed(1337)
|
||||||
.environment(dim.getEnvironment())
|
.environment(dim.getEnvironment())
|
||||||
.worldFolder(new File(worldName))
|
.worldFolder(new File(Bukkit.getWorldContainer(), worldName))
|
||||||
.minHeight(dim.getMinHeight())
|
.minHeight(dim.getMinHeight())
|
||||||
.maxHeight(dim.getMaxHeight())
|
.maxHeight(dim.getMaxHeight())
|
||||||
.build();
|
.build();
|
||||||
@@ -663,7 +779,7 @@ public class Iris extends VolmitPlugin implements Listener {
|
|||||||
File ff = new File(w.worldFolder(), "iris/pack");
|
File ff = new File(w.worldFolder(), "iris/pack");
|
||||||
if (!ff.exists() || ff.listFiles().length == 0) {
|
if (!ff.exists() || ff.listFiles().length == 0) {
|
||||||
ff.mkdirs();
|
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());
|
||||||
@@ -674,12 +790,17 @@ public class Iris extends VolmitPlugin implements Listener {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// @NoArgsConstructor
|
|
||||||
String padd = Form.repeat(" ", 8);
|
String padd = Form.repeat(" ", 8);
|
||||||
String padd2 = Form.repeat(" ", 4);
|
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[] info = {"", "", "", "", "", padd2 + C.IRIS + " Iris", padd2 + C.GRAY + " by " + "<rainbow>Volmit Software", padd2 + C.GRAY + " v" + C.IRIS + getDescription().getVersion()};
|
||||||
};
|
if (unstablemode) {
|
||||||
String[] splash = {
|
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 + "@@@",
|
||||||
padd + C.GRAY + " @@&&&&&&&&&" + C.DARK_GRAY + "&&&&&&" + C.IRIS + " .(((()))). ",
|
padd + C.GRAY + " @@&&&&&&&&&" + C.DARK_GRAY + "&&&&&&" + C.IRIS + " .(((()))). ",
|
||||||
padd + C.GRAY + "@@@&&&&&&&&" + C.DARK_GRAY + "&&&&&" + C.IRIS + " .((((((())))))). ",
|
padd + C.GRAY + "@@@&&&&&&&&" + C.DARK_GRAY + "&&&&&" + C.IRIS + " .((((((())))))). ",
|
||||||
@@ -692,11 +813,61 @@ public class Iris extends VolmitPlugin implements Listener {
|
|||||||
padd + C.GRAY + "" + C.IRIS + " '(((())))' " + C.DARK_GRAY + "&&&&&&&&" + C.GRAY + "&&&&&&&@@",
|
padd + C.GRAY + "" + C.IRIS + " '(((())))' " + C.DARK_GRAY + "&&&&&&&&" + C.GRAY + "&&&&&&&@@",
|
||||||
padd + C.GRAY + " " + C.DARK_GRAY + "@@@" + C.GRAY + "@@@@@@@@@@@@@@"
|
padd + C.GRAY + " " + C.DARK_GRAY + "@@@" + C.GRAY + "@@@@@@@@@@@@@@"
|
||||||
};
|
};
|
||||||
//@done
|
|
||||||
Iris.info("Server type & version: " + Bukkit.getVersion());
|
String[] splashunstable = {
|
||||||
Iris.info("Bukkit version: " + Bukkit.getBukkitVersion());
|
padd + C.GRAY + " @@@@@@@@@@@@@@" + C.DARK_GRAY + "@@@",
|
||||||
Iris.info("Java version: " + getJavaVersion());
|
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());
|
Iris.info("Custom Biomes: " + INMS.get().countCustomBiomes());
|
||||||
|
setupChecks();
|
||||||
printPacks();
|
printPacks();
|
||||||
|
|
||||||
for (int i = 0; i < info.length; i++) {
|
for (int i = 0; i < info.length; i++) {
|
||||||
@@ -723,7 +894,37 @@ public class Iris extends VolmitPlugin implements Listener {
|
|||||||
JsonObject json = JsonParser.parseReader(r).getAsJsonObject();
|
JsonObject json = JsonParser.parseReader(r).getAsJsonObject();
|
||||||
if (json.has("version"))
|
if (json.has("version"))
|
||||||
version = json.get("version").getAsString();
|
version = json.get("version").getAsString();
|
||||||
} catch(IOException | JsonParseException ignored) { }
|
} catch (IOException | JsonParseException ignored) {
|
||||||
|
}
|
||||||
Iris.info(" " + dimName + " v" + version);
|
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.JSONException;
|
||||||
import com.volmit.iris.util.json.JSONObject;
|
import com.volmit.iris.util.json.JSONObject;
|
||||||
import com.volmit.iris.util.plugin.VolmitSender;
|
import com.volmit.iris.util.plugin.VolmitSender;
|
||||||
|
import com.volmit.iris.util.scheduling.ChronoLatch;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -41,6 +44,7 @@ public class IrisSettings {
|
|||||||
private IrisSettingsConcurrency concurrency = new IrisSettingsConcurrency();
|
private IrisSettingsConcurrency concurrency = new IrisSettingsConcurrency();
|
||||||
private IrisSettingsStudio studio = new IrisSettingsStudio();
|
private IrisSettingsStudio studio = new IrisSettingsStudio();
|
||||||
private IrisSettingsPerformance performance = new IrisSettingsPerformance();
|
private IrisSettingsPerformance performance = new IrisSettingsPerformance();
|
||||||
|
private IrisSettingsUpdater updater = new IrisSettingsUpdater();
|
||||||
|
|
||||||
public static int getThreadCount(int c) {
|
public static int getThreadCount(int c) {
|
||||||
return switch (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() {
|
public static IrisSettings get() {
|
||||||
if (settings != null) {
|
if (settings != null) {
|
||||||
return settings;
|
return settings;
|
||||||
@@ -183,4 +104,116 @@ public class IrisSettings {
|
|||||||
Iris.reportError(e);
|
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 boolean adjustVanillaHeight = false;
|
||||||
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
287
core/src/main/java/com/volmit/iris/core/ServerConfigurator.java
Normal file
287
core/src/main/java/com/volmit/iris/core/ServerConfigurator.java
Normal file
@@ -0,0 +1,287 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
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.KMap;
|
||||||
|
import com.volmit.iris.util.collection.KSet;
|
||||||
|
import com.volmit.iris.util.format.C;
|
||||||
|
import com.volmit.iris.util.misc.ServerProperties;
|
||||||
|
import com.volmit.iris.util.plugin.VolmitSender;
|
||||||
|
import com.volmit.iris.util.scheduling.J;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NonNull;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.configuration.InvalidConfigurationException;
|
||||||
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import static com.volmit.iris.core.nms.datapack.IDataFixer.Dimension.*;
|
||||||
|
|
||||||
|
public class ServerConfigurator {
|
||||||
|
public static void configure() {
|
||||||
|
IrisSettings.IrisSettingsAutoconfiguration s = IrisSettings.get().getAutoConfiguration();
|
||||||
|
if (s.isConfigureSpigotTimeoutTime()) {
|
||||||
|
J.attempt(ServerConfigurator::increaseKeepAliveSpigot);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s.isConfigurePaperWatchdogDelay()) {
|
||||||
|
J.attempt(ServerConfigurator::increasePaperWatchdog);
|
||||||
|
}
|
||||||
|
|
||||||
|
installDataPacks(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void increaseKeepAliveSpigot() throws IOException, InvalidConfigurationException {
|
||||||
|
File spigotConfig = new File("spigot.yml");
|
||||||
|
FileConfiguration f = new YamlConfiguration();
|
||||||
|
f.load(spigotConfig);
|
||||||
|
long tt = f.getLong("settings.timeout-time");
|
||||||
|
|
||||||
|
if (tt < TimeUnit.MINUTES.toSeconds(5)) {
|
||||||
|
Iris.warn("Updating spigot.yml timeout-time: " + tt + " -> " + TimeUnit.MINUTES.toSeconds(20) + " (5 minutes)");
|
||||||
|
Iris.warn("You can disable this change (autoconfigureServer) in Iris settings, then change back the value.");
|
||||||
|
f.set("settings.timeout-time", TimeUnit.MINUTES.toSeconds(5));
|
||||||
|
f.save(spigotConfig);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private static void increasePaperWatchdog() throws IOException, InvalidConfigurationException {
|
||||||
|
File spigotConfig = new File("config/paper-global.yml");
|
||||||
|
FileConfiguration f = new YamlConfiguration();
|
||||||
|
f.load(spigotConfig);
|
||||||
|
long tt = f.getLong("watchdog.early-warning-delay");
|
||||||
|
|
||||||
|
if (tt < TimeUnit.MINUTES.toMillis(3)) {
|
||||||
|
Iris.warn("Updating paper.yml watchdog early-warning-delay: " + tt + " -> " + TimeUnit.MINUTES.toMillis(15) + " (3 minutes)");
|
||||||
|
Iris.warn("You can disable this change (autoconfigureServer) in Iris settings, then change back the value.");
|
||||||
|
f.set("watchdog.early-warning-delay", TimeUnit.MINUTES.toMillis(3));
|
||||||
|
f.save(spigotConfig);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static KList<File> getDatapacksFolder() {
|
||||||
|
if (!IrisSettings.get().getGeneral().forceMainWorld.isEmpty()) {
|
||||||
|
return new KList<File>().qadd(new File(Bukkit.getWorldContainer(), IrisSettings.get().getGeneral().forceMainWorld + "/datapacks"));
|
||||||
|
}
|
||||||
|
KList<File> worlds = new KList<>();
|
||||||
|
Bukkit.getServer().getWorlds().forEach(w -> worlds.add(new File(w.getWorldFolder(), "datapacks")));
|
||||||
|
if (worlds.isEmpty()) worlds.add(new File(Bukkit.getWorldContainer(), ServerProperties.LEVEL_NAME + "/datapacks"));
|
||||||
|
return worlds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void installDataPacks(boolean fullInstall) {
|
||||||
|
installDataPacks(DataVersion.getDefault(), fullInstall);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void installDataPacks(IDataFixer fixer, boolean fullInstall) {
|
||||||
|
Iris.info("Checking Data Packs...");
|
||||||
|
DimensionHeight height = new DimensionHeight(fixer);
|
||||||
|
KList<File> folders = getDatapacksFolder();
|
||||||
|
KMap<String, KSet<String>> biomes = new KMap<>();
|
||||||
|
|
||||||
|
allPacks().flatMap(height::merge)
|
||||||
|
.parallel()
|
||||||
|
.forEach(dim -> {
|
||||||
|
Iris.verbose(" Checking Dimension " + dim.getLoadFile().getPath());
|
||||||
|
dim.installBiomes(fixer, dim::getLoader, folders, biomes.computeIfAbsent(dim.getLoadKey(), k -> new KSet<>()));
|
||||||
|
});
|
||||||
|
IrisDimension.writeShared(folders, height);
|
||||||
|
|
||||||
|
Iris.info("Data Packs Setup!");
|
||||||
|
|
||||||
|
if (fullInstall)
|
||||||
|
verifyDataPacksPost(IrisSettings.get().getAutoConfiguration().isAutoRestartOnCustomBiomeInstall());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void verifyDataPacksPost(boolean allowRestarting) {
|
||||||
|
boolean bad = allPacks()
|
||||||
|
.map(data -> {
|
||||||
|
Iris.verbose("Checking Pack: " + data.getDataFolder().getPath());
|
||||||
|
var loader = data.getDimensionLoader();
|
||||||
|
return loader.loadAll(loader.getPossibleKeys())
|
||||||
|
.stream()
|
||||||
|
.map(ServerConfigurator::verifyDataPackInstalled)
|
||||||
|
.toList()
|
||||||
|
.contains(false);
|
||||||
|
})
|
||||||
|
.toList()
|
||||||
|
.contains(true);
|
||||||
|
if (!bad) return;
|
||||||
|
|
||||||
|
|
||||||
|
if (allowRestarting) {
|
||||||
|
restart();
|
||||||
|
} else if (INMS.get().supportsDataPacks()) {
|
||||||
|
Iris.error("============================================================================");
|
||||||
|
Iris.error(C.ITALIC + "You need to restart your server to properly generate custom biomes.");
|
||||||
|
Iris.error(C.ITALIC + "By continuing, Iris will use backup biomes in place of the custom biomes.");
|
||||||
|
Iris.error("----------------------------------------------------------------------------");
|
||||||
|
Iris.error(C.UNDERLINE + "IT IS HIGHLY RECOMMENDED YOU RESTART THE SERVER BEFORE GENERATING!");
|
||||||
|
Iris.error("============================================================================");
|
||||||
|
|
||||||
|
for (Player i : Bukkit.getOnlinePlayers()) {
|
||||||
|
if (i.isOp() || i.hasPermission("iris.all")) {
|
||||||
|
VolmitSender sender = new VolmitSender(i, Iris.instance.getTag("WARNING"));
|
||||||
|
sender.sendMessage("There are some Iris Packs that have custom biomes in them");
|
||||||
|
sender.sendMessage("You need to restart your server to use these packs.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
J.sleep(3000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void restart() {
|
||||||
|
J.s(() -> {
|
||||||
|
Iris.warn("New data pack entries have been installed in Iris! Restarting server!");
|
||||||
|
Iris.warn("This will only happen when your pack changes (updates/first time setup)");
|
||||||
|
Iris.warn("(You can disable this auto restart in iris settings)");
|
||||||
|
J.s(() -> {
|
||||||
|
Iris.warn("Looks like the restart command didn't work. Stopping the server instead!");
|
||||||
|
Bukkit.shutdown();
|
||||||
|
}, 100);
|
||||||
|
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "restart");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean verifyDataPackInstalled(IrisDimension dimension) {
|
||||||
|
KSet<String> keys = new KSet<>();
|
||||||
|
boolean warn = false;
|
||||||
|
|
||||||
|
for (IrisBiome i : dimension.getAllBiomes(dimension::getLoader)) {
|
||||||
|
if (i.isCustom()) {
|
||||||
|
for (IrisBiomeCustom j : i.getCustomDerivitives()) {
|
||||||
|
keys.add(dimension.getLoadKey() + ":" + j.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String key = getWorld(dimension.getLoader());
|
||||||
|
if (key == null) key = dimension.getLoadKey();
|
||||||
|
else key += "/" + dimension.getLoadKey();
|
||||||
|
|
||||||
|
if (!INMS.get().supportsDataPacks()) {
|
||||||
|
if (!keys.isEmpty()) {
|
||||||
|
Iris.warn("===================================================================================");
|
||||||
|
Iris.warn("Pack " + key + " has " + keys.size() + " custom biome(s). ");
|
||||||
|
Iris.warn("Your server version does not yet support datapacks for iris.");
|
||||||
|
Iris.warn("The world will generate these biomes as backup biomes.");
|
||||||
|
Iris.warn("====================================================================================");
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String i : keys) {
|
||||||
|
Object o = INMS.get().getCustomBiomeBaseFor(i);
|
||||||
|
|
||||||
|
if (o == null) {
|
||||||
|
Iris.warn("The Biome " + i + " is not registered on the server.");
|
||||||
|
warn = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (warn) {
|
||||||
|
Iris.error("The Pack " + key + " is INCAPABLE of generating custom biomes");
|
||||||
|
Iris.error("If not done automatically, restart your server before generating with this pack!");
|
||||||
|
}
|
||||||
|
|
||||||
|
return !warn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Stream<IrisData> allPacks() {
|
||||||
|
return Stream.concat(listFiles(new File("plugins/Iris/packs")),
|
||||||
|
listFiles(Bukkit.getWorldContainer()).map(w -> new File(w, "iris/pack")))
|
||||||
|
.filter(File::isDirectory)
|
||||||
|
.map(IrisData::get);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static String getWorld(@NonNull IrisData data) {
|
||||||
|
String worldContainer = Bukkit.getWorldContainer().getAbsolutePath();
|
||||||
|
if (!worldContainer.endsWith(File.separator)) worldContainer += File.separator;
|
||||||
|
|
||||||
|
String path = data.getDataFolder().getAbsolutePath();
|
||||||
|
if (!path.startsWith(worldContainer)) return null;
|
||||||
|
int l = path.endsWith(File.separator) ? 11 : 10;
|
||||||
|
return path.substring(worldContainer.length(), path.length() - l);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Stream<File> listFiles(File parent) {
|
||||||
|
var files = parent.listFiles();
|
||||||
|
return files == null ? Stream.empty() : Arrays.stream(files);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class DimensionHeight {
|
||||||
|
private final IDataFixer fixer;
|
||||||
|
private IrisRange overworld = new IrisRange();
|
||||||
|
private IrisRange nether = new IrisRange();
|
||||||
|
private IrisRange end = new IrisRange();
|
||||||
|
private int logicalOverworld = 0;
|
||||||
|
private int logicalNether = 0;
|
||||||
|
private int logicalEnd = 0;
|
||||||
|
|
||||||
|
public Stream<IrisDimension> merge(IrisData data) {
|
||||||
|
Iris.verbose("Checking Pack: " + data.getDataFolder().getPath());
|
||||||
|
var loader = data.getDimensionLoader();
|
||||||
|
return loader.loadAll(loader.getPossibleKeys())
|
||||||
|
.stream()
|
||||||
|
.peek(this::merge);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void merge(IrisDimension dimension) {
|
||||||
|
overworld.merge(dimension.getDimensionHeight());
|
||||||
|
nether.merge(dimension.getDimensionHeight());
|
||||||
|
end.merge(dimension.getDimensionHeight());
|
||||||
|
|
||||||
|
logicalOverworld = Math.max(logicalOverworld, dimension.getLogicalHeight());
|
||||||
|
logicalNether = Math.max(logicalNether, dimension.getLogicalHeightNether());
|
||||||
|
logicalEnd = Math.max(logicalEnd, dimension.getLogicalHeightEnd());
|
||||||
|
}
|
||||||
|
|
||||||
|
public String overworldType() {
|
||||||
|
return fixer.createDimension(OVERRWORLD, overworld, logicalOverworld).toString(4);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String netherType() {
|
||||||
|
return fixer.createDimension(NETHER, nether, logicalNether).toString(4);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String endType() {
|
||||||
|
return fixer.createDimension(THE_END, end, logicalEnd).toString(4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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,360 @@
|
|||||||
|
/*
|
||||||
|
* 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.pregenerator.PregenTask;
|
||||||
|
import com.volmit.iris.core.pregenerator.methods.HeadlessPregenMethod;
|
||||||
|
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.engine.platform.PlatformChunkGenerator;
|
||||||
|
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.math.Position2;
|
||||||
|
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 org.bukkit.util.Vector;
|
||||||
|
|
||||||
|
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 = "Diameter in regions", defaultValue = "2048")
|
||||||
|
int diameter,
|
||||||
|
@Param(description = "Headless", defaultValue = "true")
|
||||||
|
boolean headless,
|
||||||
|
@Param(description = "Open GUI while benchmarking", defaultValue = "false")
|
||||||
|
boolean gui
|
||||||
|
) {
|
||||||
|
int rb = diameter << 9;
|
||||||
|
Iris.info("Benchmarking pack " + dimension.getName() + " with diameter: " + rb + "(" + diameter + ")");
|
||||||
|
new IrisPackBenchmarking(dimension, diameter, headless, 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 = "Pregenerate a world")
|
||||||
|
public void headless(
|
||||||
|
@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
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
var engine = Optional.ofNullable(IrisToolbelt.access(world))
|
||||||
|
.map(PlatformChunkGenerator::getEngine)
|
||||||
|
.orElse(null);
|
||||||
|
|
||||||
|
if (engine == null) {
|
||||||
|
sender().sendMessage(C.RED + "The engine access for this world is null!");
|
||||||
|
sender().sendMessage(C.RED + "Please make sure the world is loaded & the engine is initialized. Generate a new chunk, for example.");
|
||||||
|
}
|
||||||
|
radius = Math.max(radius, 1024);
|
||||||
|
IrisToolbelt.pregenerate(PregenTask
|
||||||
|
.builder()
|
||||||
|
.center(new Position2(center.getBlockX(), center.getBlockZ()))
|
||||||
|
.gui(true)
|
||||||
|
.radiusX(radius)
|
||||||
|
.radiusZ(radius)
|
||||||
|
.build(), new HeadlessPregenMethod(engine), engine);
|
||||||
|
String msg = C.GREEN + "Headless Pregen started in " + C.GOLD + world.getName() + C.GREEN + " of " + C.GOLD + (radius * 2) + C.GREEN + " by " + C.GOLD + (radius * 2) + C.GREEN + " blocks from " + C.GOLD + center.getX() + "," + center.getZ();
|
||||||
|
sender().sendMessage(msg);
|
||||||
|
Iris.info(msg);
|
||||||
|
} catch (Throwable e) {
|
||||||
|
sender().sendMessage(C.RED + "Epic fail. See console.");
|
||||||
|
Iris.reportError(e);
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@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.Iris;
|
||||||
import com.volmit.iris.core.service.StudioSVC;
|
import com.volmit.iris.core.service.StudioSVC;
|
||||||
import com.volmit.iris.engine.object.IrisBiome;
|
import com.volmit.iris.engine.object.*;
|
||||||
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.util.decree.DecreeExecutor;
|
import com.volmit.iris.util.decree.DecreeExecutor;
|
||||||
import com.volmit.iris.util.decree.DecreeOrigin;
|
import com.volmit.iris.util.decree.DecreeOrigin;
|
||||||
import com.volmit.iris.util.decree.annotations.Decree;
|
import com.volmit.iris.util.decree.annotations.Decree;
|
||||||
import com.volmit.iris.util.decree.annotations.Param;
|
import com.volmit.iris.util.decree.annotations.Param;
|
||||||
import com.volmit.iris.util.format.C;
|
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")
|
@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")
|
@Decree(description = "Find a biome")
|
||||||
public void biome(
|
public void biome(
|
||||||
@Param(description = "The biome to look for")
|
@Param(description = "The biome to look for")
|
||||||
IrisBiome biome
|
IrisBiome biome,
|
||||||
|
@Param(description = "Should you be teleported", defaultValue = "true")
|
||||||
|
boolean teleport
|
||||||
) {
|
) {
|
||||||
Engine e = engine();
|
Engine e = engine();
|
||||||
|
|
||||||
@@ -43,13 +45,15 @@ public class CommandFind implements DecreeExecutor {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
e.gotoBiome(biome, player());
|
e.gotoBiome(biome, player(), teleport);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Decree(description = "Find a region")
|
@Decree(description = "Find a region")
|
||||||
public void region(
|
public void region(
|
||||||
@Param(description = "The region to look for")
|
@Param(description = "The region to look for")
|
||||||
IrisRegion region
|
IrisRegion region,
|
||||||
|
@Param(description = "Should you be teleported", defaultValue = "true")
|
||||||
|
boolean teleport
|
||||||
) {
|
) {
|
||||||
Engine e = engine();
|
Engine e = engine();
|
||||||
|
|
||||||
@@ -58,13 +62,15 @@ public class CommandFind implements DecreeExecutor {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
e.gotoRegion(region, player());
|
e.gotoRegion(region, player(), teleport);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Decree(description = "Find a structure")
|
@Decree(description = "Find a structure")
|
||||||
public void structure(
|
public void structure(
|
||||||
@Param(description = "The structure to look for")
|
@Param(description = "The structure to look for")
|
||||||
IrisJigsawStructure structure
|
IrisJigsawStructure structure,
|
||||||
|
@Param(description = "Should you be teleported", defaultValue = "true")
|
||||||
|
boolean teleport
|
||||||
) {
|
) {
|
||||||
Engine e = engine();
|
Engine e = engine();
|
||||||
|
|
||||||
@@ -73,13 +79,31 @@ public class CommandFind implements DecreeExecutor {
|
|||||||
return;
|
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")
|
@Decree(description = "Find an object")
|
||||||
public void object(
|
public void object(
|
||||||
@Param(description = "The object to look for", customHandler = ObjectHandler.class)
|
@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();
|
Engine e = engine();
|
||||||
|
|
||||||
@@ -88,6 +112,6 @@ public class CommandFind implements DecreeExecutor {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
e.gotoObject(object, player());
|
e.gotoObject(object, player(), teleport);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,665 @@
|
|||||||
|
/*
|
||||||
|
* 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.loader.IrisData;
|
||||||
|
import com.volmit.iris.core.nms.INMS;
|
||||||
|
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 org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.WorldCreator;
|
||||||
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.generator.ChunkGenerator;
|
||||||
|
import org.bukkit.scheduler.BukkitRunnable;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.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 radius of chunks to generate in headless mode (-1 to disable)", defaultValue = "10", aliases = "radius")
|
||||||
|
int headlessRadius,
|
||||||
|
@Param(description = "The seed to generate the world with", defaultValue = "1337")
|
||||||
|
long seed
|
||||||
|
) {
|
||||||
|
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)
|
||||||
|
.headlessRadius(headlessRadius)
|
||||||
|
.create();
|
||||||
|
} catch (Throwable e) {
|
||||||
|
sender().sendMessage(C.RED + "Exception raised during creation. See the console for more details.");
|
||||||
|
Iris.error("Exception raised during world creation: " + e.getMessage());
|
||||||
|
Iris.reportError(e);
|
||||||
|
worldCreation = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
worldCreation = false;
|
||||||
|
sender().sendMessage(C.GREEN + "Successfully created your world!");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Decree(description = "Teleport to another world", aliases = {"tp"}, sync = true)
|
||||||
|
public void teleport(
|
||||||
|
@Param(description = "World to teleport to")
|
||||||
|
World world,
|
||||||
|
@Param(description = "Player to teleport", defaultValue = "---", customHandler = NullablePlayerHandler.class)
|
||||||
|
Player player
|
||||||
|
) {
|
||||||
|
if (player == null && sender().isPlayer())
|
||||||
|
player = sender().player();
|
||||||
|
|
||||||
|
final Player target = player;
|
||||||
|
if (target == null) {
|
||||||
|
sender().sendMessage(C.RED + "The specified player does not exist.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
new BukkitRunnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
target.teleport(world.getSpawnLocation());
|
||||||
|
new VolmitSender(target).sendMessage(C.GREEN + "You have been teleported to " + world.getName() + ".");
|
||||||
|
}
|
||||||
|
}.runTask(Iris.instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Decree(description = "Print version information")
|
||||||
|
public void version() {
|
||||||
|
sender().sendMessage(C.GREEN + "Iris v" + Iris.instance.getDescription().getVersion() + " by Volmit Software");
|
||||||
|
}
|
||||||
|
|
||||||
|
//todo 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());
|
||||||
|
|
||||||
|
if (!IrisToolbelt.evacuate(world)) {
|
||||||
|
sender().sendMessage(C.RED + "Failed to evacuate world: " + world.getName());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Bukkit.unloadWorld(world, false)) {
|
||||||
|
sender().sendMessage(C.RED + "Failed to unload world: " + world.getName());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
if (!delete) {
|
||||||
|
deletingWorld = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
VolmitSender sender = sender();
|
||||||
|
J.a(() -> {
|
||||||
|
int retries = 12;
|
||||||
|
|
||||||
|
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/" + INMS.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 + "...");
|
||||||
|
WorldCreator c = new WorldCreator(s)
|
||||||
|
.generator(getDefaultWorldGenerator(s, generator))
|
||||||
|
.environment(IrisData.loadAnyDimension(generator).getEnvironment());
|
||||||
|
INMS.get().createWorld(c);
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,6 +21,7 @@ package com.volmit.iris.core.commands;
|
|||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.Iris;
|
||||||
import com.volmit.iris.core.edit.JigsawEditor;
|
import com.volmit.iris.core.edit.JigsawEditor;
|
||||||
import com.volmit.iris.core.loader.IrisData;
|
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.jigsaw.PlannedStructure;
|
||||||
import com.volmit.iris.engine.object.IrisJigsawPiece;
|
import com.volmit.iris.engine.object.IrisJigsawPiece;
|
||||||
import com.volmit.iris.engine.object.IrisJigsawStructure;
|
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.C;
|
||||||
import com.volmit.iris.util.format.Form;
|
import com.volmit.iris.util.format.Form;
|
||||||
import com.volmit.iris.util.math.RNG;
|
import com.volmit.iris.util.math.RNG;
|
||||||
|
import com.volmit.iris.util.plugin.VolmitSender;
|
||||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@@ -55,9 +57,16 @@ public class CommandJigsaw implements DecreeExecutor {
|
|||||||
IrisJigsawStructure structure
|
IrisJigsawStructure structure
|
||||||
) {
|
) {
|
||||||
PrecisionStopwatch p = PrecisionStopwatch.start();
|
PrecisionStopwatch p = PrecisionStopwatch.start();
|
||||||
PlannedStructure ps = new PlannedStructure(structure, new IrisPosition(player().getLocation()), new RNG());
|
try {
|
||||||
sender().sendMessage(C.GREEN + "Generated " + ps.getPieces().size() + " pieces in " + Form.duration(p.getMilliseconds(), 2));
|
var world = world();
|
||||||
ps.place(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")
|
@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,15 +24,12 @@ import com.volmit.iris.core.loader.IrisData;
|
|||||||
import com.volmit.iris.core.service.ObjectSVC;
|
import com.volmit.iris.core.service.ObjectSVC;
|
||||||
import com.volmit.iris.core.service.StudioSVC;
|
import com.volmit.iris.core.service.StudioSVC;
|
||||||
import com.volmit.iris.core.service.WandSVC;
|
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.framework.Engine;
|
||||||
import com.volmit.iris.engine.object.IObjectPlacer;
|
import com.volmit.iris.engine.object.*;
|
||||||
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.util.data.Cuboid;
|
import com.volmit.iris.util.data.Cuboid;
|
||||||
|
import com.volmit.iris.util.data.IrisCustomData;
|
||||||
|
import com.volmit.iris.util.data.registry.Materials;
|
||||||
import com.volmit.iris.util.decree.DecreeExecutor;
|
import com.volmit.iris.util.decree.DecreeExecutor;
|
||||||
import com.volmit.iris.util.decree.DecreeOrigin;
|
import com.volmit.iris.util.decree.DecreeOrigin;
|
||||||
import com.volmit.iris.util.decree.annotations.Decree;
|
import com.volmit.iris.util.decree.annotations.Decree;
|
||||||
@@ -44,8 +41,6 @@ import com.volmit.iris.util.math.RNG;
|
|||||||
import com.volmit.iris.util.scheduling.Queue;
|
import com.volmit.iris.util.scheduling.Queue;
|
||||||
import org.bukkit.*;
|
import org.bukkit.*;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.block.BlockState;
|
|
||||||
import org.bukkit.block.TileState;
|
|
||||||
import org.bukkit.block.data.BlockData;
|
import org.bukkit.block.data.BlockData;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.bukkit.util.Vector;
|
import org.bukkit.util.Vector;
|
||||||
@@ -53,20 +48,12 @@ import org.bukkit.util.Vector;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.text.NumberFormat;
|
import java.text.NumberFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
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;
|
|
||||||
|
|
||||||
@Decree(name = "object", aliases = "o", origin = DecreeOrigin.PLAYER, studio = true, description = "Iris object manipulation")
|
@Decree(name = "object", aliases = "o", origin = DecreeOrigin.PLAYER, studio = true, description = "Iris object manipulation")
|
||||||
public class CommandObject implements DecreeExecutor {
|
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(Materials.GRASS, Material.SNOW, Material.VINE, Material.TORCH, Material.DEAD_BUSH,
|
||||||
Material.POPPY, Material.DANDELION);
|
Material.POPPY, Material.DANDELION);
|
||||||
|
|
||||||
public static IObjectPlacer createPlacer(World world, Map<Block, BlockData> futureBlockChanges) {
|
public static IObjectPlacer createPlacer(World world, Map<Block, BlockData> futureBlockChanges) {
|
||||||
@@ -91,7 +78,10 @@ public class CommandObject implements DecreeExecutor {
|
|||||||
|
|
||||||
futureBlockChanges.put(block, block.getBlockData());
|
futureBlockChanges.put(block, block.getBlockData());
|
||||||
|
|
||||||
block.setBlockData(d);
|
if (d instanceof IrisCustomData data) {
|
||||||
|
block.setBlockData(data.getBase());
|
||||||
|
Iris.warn("Tried to place custom block at " + x + ", " + y + ", " + z + " which is not supported!");
|
||||||
|
} else block.setBlockData(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -130,10 +120,8 @@ public class CommandObject implements DecreeExecutor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setTile(int xx, int yy, int zz, TileData<? extends TileState> tile) {
|
public void setTile(int xx, int yy, int zz, TileData tile) {
|
||||||
BlockState state = world.getBlockAt(xx, yy, zz).getState();
|
tile.toBukkitTry(world.getBlockAt(xx, yy, zz));
|
||||||
tile.toBukkitTry(state);
|
|
||||||
state.update();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -180,7 +168,7 @@ public class CommandObject implements DecreeExecutor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
List<Material> sortedMatsList = amounts.keySet().stream().map(BlockData::getMaterial)
|
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());
|
Set<Material> sortedMats = new TreeSet<>(Comparator.comparingInt(materials::get).reversed());
|
||||||
sortedMats.addAll(sortedMatsList);
|
sortedMats.addAll(sortedMatsList);
|
||||||
sender().sendMessage("== Blocks in object ==");
|
sender().sendMessage("== Blocks in object ==");
|
||||||
@@ -211,6 +199,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")
|
@Decree(description = "Get a powder that reveals objects", studio = true, aliases = "d")
|
||||||
public void dust() {
|
public void dust() {
|
||||||
player().getInventory().addItem(WandSVC.createDust());
|
player().getInventory().addItem(WandSVC.createDust());
|
||||||
@@ -229,6 +241,9 @@ public class CommandObject implements DecreeExecutor {
|
|||||||
|
|
||||||
|
|
||||||
Location[] b = WandSVC.getCuboid(player());
|
Location[] b = WandSVC.getCuboid(player());
|
||||||
|
if (b == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
Location a1 = b[0].clone();
|
Location a1 = b[0].clone();
|
||||||
Location a2 = b[1].clone();
|
Location a2 = b[1].clone();
|
||||||
Cuboid cursor = new Cuboid(a1, a2);
|
Cuboid cursor = new Cuboid(a1, a2);
|
||||||
@@ -255,6 +270,9 @@ public class CommandObject implements DecreeExecutor {
|
|||||||
if (WandSVC.isHoldingWand(player())) {
|
if (WandSVC.isHoldingWand(player())) {
|
||||||
Location[] g = WandSVC.getCuboid(player());
|
Location[] g = WandSVC.getCuboid(player());
|
||||||
|
|
||||||
|
if (g == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!here) {
|
if (!here) {
|
||||||
// TODO: WARNING HEIGHT
|
// TODO: WARNING HEIGHT
|
||||||
g[1] = player().getTargetBlock(null, 256).getLocation().clone();
|
g[1] = player().getTargetBlock(null, 256).getLocation().clone();
|
||||||
@@ -278,6 +296,10 @@ public class CommandObject implements DecreeExecutor {
|
|||||||
if (WandSVC.isHoldingIrisWand(player())) {
|
if (WandSVC.isHoldingIrisWand(player())) {
|
||||||
Location[] g = WandSVC.getCuboid(player());
|
Location[] g = WandSVC.getCuboid(player());
|
||||||
|
|
||||||
|
if (g == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!here) {
|
if (!here) {
|
||||||
// TODO: WARNING HEIGHT
|
// TODO: WARNING HEIGHT
|
||||||
g[0] = player().getTargetBlock(null, 256).getLocation().clone();
|
g[0] = player().getTargetBlock(null, 256).getLocation().clone();
|
||||||
@@ -319,8 +341,7 @@ public class CommandObject implements DecreeExecutor {
|
|||||||
|
|
||||||
Map<Block, BlockData> futureChanges = new HashMap<>();
|
Map<Block, BlockData> futureChanges = new HashMap<>();
|
||||||
|
|
||||||
if(scale != 1)
|
if (scale != 1) {
|
||||||
{
|
|
||||||
o = o.scaled(scale, IrisObjectPlacementScaleInterpolator.TRICUBIC);
|
o = o.scaled(scale, IrisObjectPlacementScaleInterpolator.TRICUBIC);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -346,7 +367,7 @@ public class CommandObject implements DecreeExecutor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sender().sendMessage("Placed " + object);
|
sender().sendMessage(C.IRIS + "Placed " + object);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -357,9 +378,11 @@ public class CommandObject implements DecreeExecutor {
|
|||||||
@Param(description = "The file to store it in, can use / for subfolders")
|
@Param(description = "The file to store it in, can use / for subfolders")
|
||||||
String name,
|
String name,
|
||||||
@Param(description = "Overwrite existing object files", defaultValue = "false", aliases = "force")
|
@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) {
|
if (o == null) {
|
||||||
sender().sendMessage(C.YELLOW + "You need to hold your wand!");
|
sender().sendMessage(C.YELLOW + "You need to hold your wand!");
|
||||||
@@ -373,7 +396,7 @@ public class CommandObject implements DecreeExecutor {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
o.write(file);
|
o.write(file, sender());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
sender().sendMessage(C.RED + "Failed to save object because of an IOException: " + e.getMessage());
|
sender().sendMessage(C.RED + "Failed to save object because of an IOException: " + e.getMessage());
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
@@ -397,6 +420,9 @@ public class CommandObject implements DecreeExecutor {
|
|||||||
Location a1 = b[0].clone();
|
Location a1 = b[0].clone();
|
||||||
Location a2 = b[1].clone();
|
Location a2 = b[1].clone();
|
||||||
Direction d = Direction.closest(player().getLocation().getDirection()).reverse();
|
Direction d = Direction.closest(player().getLocation().getDirection()).reverse();
|
||||||
|
if (d == null) {
|
||||||
|
return; // HOW DID THIS HAPPEN
|
||||||
|
}
|
||||||
a1.add(d.toVector().multiply(amount));
|
a1.add(d.toVector().multiply(amount));
|
||||||
a2.add(d.toVector().multiply(amount));
|
a2.add(d.toVector().multiply(amount));
|
||||||
Cuboid cursor = new Cuboid(a1, a2);
|
Cuboid cursor = new Cuboid(a1, a2);
|
||||||
@@ -415,7 +441,7 @@ public class CommandObject implements DecreeExecutor {
|
|||||||
ObjectSVC service = Iris.service(ObjectSVC.class);
|
ObjectSVC service = Iris.service(ObjectSVC.class);
|
||||||
int actualReverts = Math.min(service.getUndos().size(), amount);
|
int actualReverts = Math.min(service.getUndos().size(), amount);
|
||||||
service.revertChanges(actualReverts);
|
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)
|
@Decree(description = "Gets an object wand and grabs the current WorldEdit selection.", aliases = "we", origin = DecreeOrigin.PLAYER, studio = true)
|
||||||
@@ -427,8 +453,7 @@ public class CommandObject implements DecreeExecutor {
|
|||||||
|
|
||||||
Cuboid locs = WorldEditLink.getSelection(sender().player());
|
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.");
|
sender().sendMessage(C.RED + "You don't have a WorldEdit selection in this world.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -47,12 +47,12 @@ public class CommandPregen implements DecreeExecutor {
|
|||||||
sender().sendMessage(C.RED + "Please make sure the world is loaded & the engine is initialized. Generate a new chunk, for example.");
|
sender().sendMessage(C.RED + "Please make sure the world is loaded & the engine is initialized. Generate a new chunk, for example.");
|
||||||
}
|
}
|
||||||
radius = Math.max(radius, 1024);
|
radius = Math.max(radius, 1024);
|
||||||
int w = (radius >> 9 + 1) * 2;
|
|
||||||
IrisToolbelt.pregenerate(PregenTask
|
IrisToolbelt.pregenerate(PregenTask
|
||||||
.builder()
|
.builder()
|
||||||
.center(new Position2(center))
|
.center(new Position2(center.getBlockX(), center.getBlockZ()))
|
||||||
.width(w)
|
.gui(true)
|
||||||
.height(w)
|
.radiusX(radius)
|
||||||
|
.radiusZ(radius)
|
||||||
.build(), world);
|
.build(), world);
|
||||||
String msg = C.GREEN + "Pregen started in " + C.GOLD + world.getName() + C.GREEN + " of " + C.GOLD + (radius * 2) + C.GREEN + " by " + C.GOLD + (radius * 2) + C.GREEN + " blocks from " + C.GOLD + center.getX() + "," + center.getZ();
|
String msg = C.GREEN + "Pregen started in " + C.GOLD + world.getName() + C.GREEN + " of " + C.GOLD + (radius * 2) + C.GREEN + " by " + C.GOLD + (radius * 2) + C.GREEN + " blocks from " + C.GOLD + center.getX() + "," + center.getZ();
|
||||||
sender().sendMessage(msg);
|
sender().sendMessage(msg);
|
||||||
@@ -67,7 +67,7 @@ public class CommandPregen implements DecreeExecutor {
|
|||||||
@Decree(description = "Stop the active pregeneration task", aliases = "x")
|
@Decree(description = "Stop the active pregeneration task", aliases = "x")
|
||||||
public void stop() {
|
public void stop() {
|
||||||
if (PregeneratorJob.shutdownInstance()) {
|
if (PregeneratorJob.shutdownInstance()) {
|
||||||
sender().sendMessage(C.GREEN + "Stopped pregeneration task");
|
Iris.info( C.BLUE + "Finishing up mca region...");
|
||||||
} else {
|
} else {
|
||||||
sender().sendMessage(C.YELLOW + "No active pregeneration tasks to stop");
|
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.service.StudioSVC;
|
||||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||||
import com.volmit.iris.engine.framework.Engine;
|
import com.volmit.iris.engine.framework.Engine;
|
||||||
import com.volmit.iris.engine.object.InventorySlotType;
|
import com.volmit.iris.engine.object.*;
|
||||||
import com.volmit.iris.engine.object.IrisBiome;
|
import com.volmit.iris.engine.platform.PlatformChunkGenerator;
|
||||||
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.util.collection.KList;
|
import com.volmit.iris.util.collection.KList;
|
||||||
import com.volmit.iris.util.collection.KMap;
|
import com.volmit.iris.util.collection.KMap;
|
||||||
import com.volmit.iris.util.collection.KSet;
|
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.DecreeExecutor;
|
||||||
import com.volmit.iris.util.decree.DecreeOrigin;
|
import com.volmit.iris.util.decree.DecreeOrigin;
|
||||||
import com.volmit.iris.util.decree.annotations.Decree;
|
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.JSONArray;
|
||||||
import com.volmit.iris.util.json.JSONObject;
|
import com.volmit.iris.util.json.JSONObject;
|
||||||
import com.volmit.iris.util.math.M;
|
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.RNG;
|
||||||
import com.volmit.iris.util.math.Spiraler;
|
import com.volmit.iris.util.math.Spiraler;
|
||||||
import com.volmit.iris.util.noise.CNG;
|
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.parallel.MultiBurst;
|
||||||
|
import com.volmit.iris.util.plugin.VolmitSender;
|
||||||
import com.volmit.iris.util.scheduling.J;
|
import com.volmit.iris.util.scheduling.J;
|
||||||
import com.volmit.iris.util.scheduling.O;
|
import com.volmit.iris.util.scheduling.O;
|
||||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
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.QueueJob;
|
||||||
import com.volmit.iris.util.scheduling.jobs.SingleJob;
|
|
||||||
import io.papermc.lib.PaperLib;
|
import io.papermc.lib.PaperLib;
|
||||||
|
import org.bukkit.*;
|
||||||
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.event.inventory.InventoryType;
|
import org.bukkit.event.inventory.InventoryType;
|
||||||
import org.bukkit.inventory.Inventory;
|
import org.bukkit.inventory.Inventory;
|
||||||
import org.bukkit.util.BlockVector;
|
import org.bukkit.util.BlockVector;
|
||||||
import org.bukkit.util.Vector;
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
import java.awt.*;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -91,23 +73,24 @@ import java.nio.file.Files;
|
|||||||
import java.nio.file.attribute.FileTime;
|
import java.nio.file.attribute.FileTime;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.time.temporal.ChronoUnit;
|
import java.time.temporal.ChronoUnit;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
import java.util.function.Consumer;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
@Decree(name = "studio", aliases = {"std", "s"}, description = "Studio Commands", studio = true)
|
@Decree(name = "studio", aliases = {"std", "s"}, description = "Studio Commands", studio = true)
|
||||||
public class CommandStudio implements DecreeExecutor {
|
public class CommandStudio implements DecreeExecutor {
|
||||||
|
private CommandFind find;
|
||||||
|
private CommandEdit edit;
|
||||||
|
//private CommandDeepSearch deepSearch;
|
||||||
|
|
||||||
public static String hrf(Duration duration) {
|
public static String hrf(Duration duration) {
|
||||||
return duration.toString().substring(2).replaceAll("(\\d[HMS])(?!$)", "$1 ").toLowerCase();
|
return duration.toString().substring(2).replaceAll("(\\d[HMS])(?!$)", "$1 ").toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
private CommandFind find;
|
|
||||||
private CommandEdit edit;
|
|
||||||
|
|
||||||
|
|
||||||
@Decree(description = "Download a project.", aliases = "dl")
|
@Decree(description = "Download a project.", aliases = "dl")
|
||||||
public void download(
|
public void download(
|
||||||
@Param(name = "pack", description = "The pack to download", defaultValue = "overworld", aliases = "project")
|
@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")
|
@Decree(description = "Get the version of a pack")
|
||||||
public void version(
|
public void version(
|
||||||
@Param(defaultValue = "default", description = "The dimension get the version of", aliases = "dim", contextual = true)
|
@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());
|
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")
|
@Decree(description = "Convert objects in the \"convert\" folder")
|
||||||
public void convert() {
|
public void convert() {
|
||||||
Iris.service(ConversionSVC.class).check(sender());
|
Iris.service(ConversionSVC.class).check(sender());
|
||||||
|
//IrisConverter.convertSchematics(sender());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Decree(description = "Execute a script", aliases = "run", origin = DecreeOrigin.PLAYER)
|
@Decree(description = "Execute a script", aliases = "run", origin = DecreeOrigin.PLAYER)
|
||||||
public void execute(
|
public void execute(
|
||||||
@Param(description = "The script to run")
|
@Param(description = "The script to run")
|
||||||
@@ -372,7 +302,7 @@ public class CommandStudio implements DecreeExecutor {
|
|||||||
Inventory inv = Bukkit.createInventory(null, 27 * 2);
|
Inventory inv = Bukkit.createInventory(null, 27 * 2);
|
||||||
|
|
||||||
try {
|
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) {
|
} catch (Throwable e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
sender().sendMessage(C.RED + "Cannot add items to virtual inventory because of: " + e.getMessage());
|
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();
|
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));
|
}, 0, fast ? 5 : 35));
|
||||||
|
|
||||||
sender().sendMessage(C.GREEN + "Opening inventory now!");
|
sender().sendMessage(C.GREEN + "Opening inventory now!");
|
||||||
player().openInventory(inv);
|
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")
|
@Decree(description = "Render a world map (External GUI)", aliases = "render")
|
||||||
public void map(
|
public void map(
|
||||||
@Param(name = "world", description = "The world to open the generator for", contextual = true)
|
@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")
|
@Param(description = "The dimension to profile", contextual = true, defaultValue = "default")
|
||||||
IrisDimension dimension
|
IrisDimension dimension
|
||||||
) {
|
) {
|
||||||
|
// Todo: Make this more accurate
|
||||||
File pack = dimension.getLoadFile().getParentFile().getParentFile();
|
File pack = dimension.getLoadFile().getParentFile().getParentFile();
|
||||||
File report = Iris.instance.getDataFile("profile.txt");
|
File report = Iris.instance.getDataFile("profile.txt");
|
||||||
IrisProject project = new IrisProject(pack);
|
IrisProject project = new IrisProject(pack);
|
||||||
@@ -618,19 +616,16 @@ public class CommandStudio implements DecreeExecutor {
|
|||||||
sender().sendMessage(C.GREEN + "Done! " + report.getPath());
|
sender().sendMessage(C.GREEN + "Done! " + report.getPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Decree(description = "Summon an Iris Entity", origin = DecreeOrigin.PLAYER)
|
@Decree(description = "Spawn an Iris entity", aliases = "summon", origin = DecreeOrigin.PLAYER)
|
||||||
public void summon(
|
public void spawn(
|
||||||
@Param(description = "The Iris Entity to spawn")
|
@Param(description = "The entity to spawn")
|
||||||
IrisEntity entity,
|
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
|
Vector location
|
||||||
) {
|
) {
|
||||||
if(!sender().isPlayer()) {
|
if (!IrisToolbelt.isIrisWorld(player().getWorld())) {
|
||||||
sender().sendMessage(C.RED + "Players only (this is a config error. Ask support to add DecreeOrigin.PLAYER to the command you tried to run)");
|
sender().sendMessage(C.RED + "You have to be in an Iris world to spawn entities properly. Trying to spawn the best we can do.");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sender().sendMessage(C.GREEN + "Spawning entity");
|
|
||||||
entity.spawn(engine(), new Location(world(), location.getX(), location.getY(), location.getZ()));
|
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.edit.BlockSignal;
|
||||||
import com.volmit.iris.core.nms.INMS;
|
import com.volmit.iris.core.nms.INMS;
|
||||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
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.IrisBiome;
|
||||||
|
import com.volmit.iris.engine.object.IrisRegion;
|
||||||
import com.volmit.iris.util.data.B;
|
import com.volmit.iris.util.data.B;
|
||||||
import com.volmit.iris.util.decree.DecreeExecutor;
|
import com.volmit.iris.util.decree.DecreeExecutor;
|
||||||
import com.volmit.iris.util.decree.DecreeOrigin;
|
import com.volmit.iris.util.decree.DecreeOrigin;
|
||||||
@@ -37,6 +39,7 @@ import org.bukkit.Material;
|
|||||||
import org.bukkit.block.Biome;
|
import org.bukkit.block.Biome;
|
||||||
import org.bukkit.block.data.BlockData;
|
import org.bukkit.block.data.BlockData;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
@Decree(name = "what", origin = DecreeOrigin.PLAYER, studio = true, description = "Iris What?")
|
@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)
|
@Decree(description = "What biome am i in?", origin = DecreeOrigin.PLAYER)
|
||||||
public void biome() {
|
public void biome() {
|
||||||
try {
|
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() + ")");
|
sender().sendMessage("IBiome: " + b.getLoadKey() + " (" + b.getDerivative().name() + ")");
|
||||||
|
|
||||||
} catch (Throwable e) {
|
} 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)
|
@Decree(description = "What block am i looking at?", origin = DecreeOrigin.PLAYER)
|
||||||
public void block() {
|
public void block() {
|
||||||
BlockData bd;
|
BlockData bd;
|
||||||
@@ -147,7 +163,7 @@ public class CommandWhat implements DecreeExecutor {
|
|||||||
|
|
||||||
sender().sendMessage("Found " + v.get() + " Nearby Markers (" + marker + ")");
|
sender().sendMessage("Found " + v.get() + " Nearby Markers (" + marker + ")");
|
||||||
} else {
|
} else {
|
||||||
sender().sendMessage("Iris worlds only.");
|
sender().sendMessage(C.IRIS + "Iris worlds only.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -19,14 +19,9 @@
|
|||||||
package com.volmit.iris.core.edit;
|
package com.volmit.iris.core.edit;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.JsonObject;
|
|
||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.Iris;
|
||||||
import com.volmit.iris.core.service.WandSVC;
|
import com.volmit.iris.core.service.WandSVC;
|
||||||
import com.volmit.iris.engine.object.IrisDirection;
|
import com.volmit.iris.engine.object.*;
|
||||||
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.util.collection.KList;
|
import com.volmit.iris.util.collection.KList;
|
||||||
import com.volmit.iris.util.collection.KMap;
|
import com.volmit.iris.util.collection.KMap;
|
||||||
import com.volmit.iris.util.data.Cuboid;
|
import com.volmit.iris.util.data.Cuboid;
|
||||||
@@ -71,8 +66,7 @@ public class JigsawEditor implements Listener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
editors.put(player, this);
|
editors.put(player, this);
|
||||||
if(object == null)
|
if (object == null) {
|
||||||
{
|
|
||||||
throw new RuntimeException("Object is null! " + piece.getObject());
|
throw new RuntimeException("Object is null! " + piece.getObject());
|
||||||
}
|
}
|
||||||
this.object = object;
|
this.object = object;
|
||||||
@@ -157,10 +151,8 @@ public class JigsawEditor implements Listener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeKey(JSONObject o, String... path)
|
private void removeKey(JSONObject o, String... path) {
|
||||||
{
|
if (path.length == 1) {
|
||||||
if(path.length == 1)
|
|
||||||
{
|
|
||||||
o.remove(path[0]);
|
o.remove(path[0]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -170,13 +162,11 @@ public class JigsawEditor implements Listener {
|
|||||||
removeKey(o.getJSONObject(path[0]), s.toArray(new String[0]));
|
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<>();
|
KList<JSONObject> o = new KList<>();
|
||||||
|
|
||||||
for(int i = 0; i < a.getJSONArray(key).length(); i++)
|
for (int i = 0; i < a.getJSONArray("connectors").length(); i++) {
|
||||||
{
|
o.add(a.getJSONArray("connectors").getJSONObject(i));
|
||||||
o.add(a.getJSONArray(key).getJSONObject(i));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return o;
|
return o;
|
||||||
@@ -195,8 +185,7 @@ public class JigsawEditor implements Listener {
|
|||||||
j.remove("placementOptions"); // otherwise
|
j.remove("placementOptions"); // otherwise
|
||||||
|
|
||||||
// Remove key in all objects in array
|
// Remove key in all objects in array
|
||||||
for(JSONObject i : getObjectsInArray(j, "connectors"))
|
for (JSONObject i : getObjectsInArray(j)) {
|
||||||
{
|
|
||||||
removeKey(i, "rotateConnector");
|
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;
|
package com.volmit.iris.core.gui;
|
||||||
|
|
||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.Iris;
|
||||||
|
import com.volmit.iris.core.IrisSettings;
|
||||||
import com.volmit.iris.core.events.IrisEngineHotloadEvent;
|
import com.volmit.iris.core.events.IrisEngineHotloadEvent;
|
||||||
import com.volmit.iris.engine.object.NoiseStyle;
|
import com.volmit.iris.engine.object.NoiseStyle;
|
||||||
import com.volmit.iris.util.collection.KList;
|
import com.volmit.iris.util.collection.KList;
|
||||||
@@ -35,24 +36,9 @@ import org.bukkit.event.EventHandler;
|
|||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
import javax.swing.JComboBox;
|
import javax.swing.*;
|
||||||
import javax.swing.JComponent;
|
import java.awt.*;
|
||||||
import javax.swing.JFrame;
|
import java.awt.event.*;
|
||||||
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 java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -76,7 +62,7 @@ public class NoiseExplorerGUI extends JPanel implements MouseWheelListener, List
|
|||||||
@SuppressWarnings("CanBeFinal")
|
@SuppressWarnings("CanBeFinal")
|
||||||
RollingSequence r = new RollingSequence(20);
|
RollingSequence r = new RollingSequence(20);
|
||||||
@SuppressWarnings("CanBeFinal")
|
@SuppressWarnings("CanBeFinal")
|
||||||
boolean colorMode = true;
|
boolean colorMode = IrisSettings.get().getGui().colorMode;
|
||||||
double scale = 1;
|
double scale = 1;
|
||||||
CNG cng = NoiseStyle.STATIC.create(new RNG(RNG.r.nextLong()));
|
CNG cng = NoiseStyle.STATIC.create(new RNG(RNG.r.nextLong()));
|
||||||
@SuppressWarnings("CanBeFinal")
|
@SuppressWarnings("CanBeFinal")
|
||||||
@@ -148,7 +134,7 @@ public class NoiseExplorerGUI extends JPanel implements MouseWheelListener, List
|
|||||||
JFrame frame = new JFrame("Noise Explorer");
|
JFrame frame = new JFrame("Noise Explorer");
|
||||||
NoiseExplorerGUI nv = new NoiseExplorerGUI();
|
NoiseExplorerGUI nv = new NoiseExplorerGUI();
|
||||||
frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
|
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 = new JComboBox<>(li.toArray(new String[0]));
|
||||||
combo.setSelectedItem("STATIC");
|
combo.setSelectedItem("STATIC");
|
||||||
combo.setFocusable(false);
|
combo.setFocusable(false);
|
||||||
@@ -289,11 +275,11 @@ public class NoiseExplorerGUI extends JPanel implements MouseWheelListener, List
|
|||||||
n = n > 1 ? 1 : n < 0 ? 0 : n;
|
n = n > 1 ? 1 : n < 0 ? 0 : n;
|
||||||
|
|
||||||
try {
|
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();
|
int rgb = color.getRGB();
|
||||||
img.setRGB(xx, z, rgb);
|
img.setRGB(xx, z, rgb);
|
||||||
} catch(Throwable xxx) {
|
} catch (Throwable ignored) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -35,12 +35,8 @@ import com.volmit.iris.util.math.Position2;
|
|||||||
import com.volmit.iris.util.scheduling.ChronoLatch;
|
import com.volmit.iris.util.scheduling.ChronoLatch;
|
||||||
import com.volmit.iris.util.scheduling.J;
|
import com.volmit.iris.util.scheduling.J;
|
||||||
|
|
||||||
import javax.swing.JFrame;
|
import javax.swing.*;
|
||||||
import javax.swing.JPanel;
|
import java.awt.*;
|
||||||
import java.awt.Color;
|
|
||||||
import java.awt.Font;
|
|
||||||
import java.awt.Graphics;
|
|
||||||
import java.awt.Graphics2D;
|
|
||||||
import java.awt.event.KeyEvent;
|
import java.awt.event.KeyEvent;
|
||||||
import java.awt.event.KeyListener;
|
import java.awt.event.KeyListener;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
@@ -66,12 +62,12 @@ public class PregeneratorJob implements PregenListener {
|
|||||||
private final IrisPregenerator pregenerator;
|
private final IrisPregenerator pregenerator;
|
||||||
private final Position2 min;
|
private final Position2 min;
|
||||||
private final Position2 max;
|
private final Position2 max;
|
||||||
|
private final ChronoLatch cl = new ChronoLatch(TimeUnit.MINUTES.toMillis(1));
|
||||||
|
private final Engine engine;
|
||||||
private JFrame frame;
|
private JFrame frame;
|
||||||
private PregenRenderer renderer;
|
private PregenRenderer renderer;
|
||||||
private int rgc = 0;
|
private int rgc = 0;
|
||||||
private final ChronoLatch cl = new ChronoLatch(TimeUnit.MINUTES.toMillis(1));
|
|
||||||
private String[] info;
|
private String[] info;
|
||||||
private final Engine engine;
|
|
||||||
|
|
||||||
public PregeneratorJob(PregenTask task, PregeneratorMethod method, Engine engine) {
|
public PregeneratorJob(PregenTask task, PregeneratorMethod method, Engine engine) {
|
||||||
this.engine = engine;
|
this.engine = engine;
|
||||||
@@ -82,24 +78,24 @@ public class PregeneratorJob implements PregenListener {
|
|||||||
this.task = task;
|
this.task = task;
|
||||||
this.pregenerator = new IrisPregenerator(task, method, this);
|
this.pregenerator = new IrisPregenerator(task, method, this);
|
||||||
max = new Position2(0, 0);
|
max = new Position2(0, 0);
|
||||||
min = new Position2(0, 0);
|
min = new Position2(Integer.MAX_VALUE, Integer.MAX_VALUE);
|
||||||
KList<Runnable> draw = new KList<>();
|
task.iterateAllChunks((xx, zz) -> {
|
||||||
task.iterateRegions((xx, zz) -> {
|
min.setX(Math.min(xx, min.getX()));
|
||||||
min.setX(Math.min(xx << 5, min.getX()));
|
min.setZ(Math.min(zz, min.getZ()));
|
||||||
min.setZ(Math.min(zz << 5, min.getZ()));
|
max.setX(Math.max(xx, max.getX()));
|
||||||
max.setX(Math.max((xx << 5) + 31, max.getX()));
|
max.setZ(Math.max(zz, max.getZ()));
|
||||||
max.setZ(Math.max((zz << 5) + 31, max.getZ()));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if(IrisSettings.get().getGui().isUseServerLaunchedGuis()) {
|
if (IrisSettings.get().getGui().isUseServerLaunchedGuis() && task.isGui()) {
|
||||||
open();
|
open();
|
||||||
}
|
}
|
||||||
|
|
||||||
J.a(this.pregenerator::start, 20);
|
var t = new Thread(() -> {
|
||||||
}
|
J.sleep(1000);
|
||||||
|
this.pregenerator.start();
|
||||||
public Mantle getMantle() {
|
}, "Iris Pregenerator");
|
||||||
return pregenerator.getMantle();
|
t.setPriority(Thread.MIN_PRIORITY);
|
||||||
|
t.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean shutdownInstance() {
|
public static boolean shutdownInstance() {
|
||||||
@@ -148,6 +144,10 @@ public class PregeneratorJob implements PregenListener {
|
|||||||
return Color.RED;
|
return Color.RED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Mantle getMantle() {
|
||||||
|
return pregenerator.getMantle();
|
||||||
|
}
|
||||||
|
|
||||||
public PregeneratorJob onProgress(Consumer<Double> c) {
|
public PregeneratorJob onProgress(Consumer<Double> c) {
|
||||||
onProgress.add(c);
|
onProgress.add(c);
|
||||||
return this;
|
return this;
|
||||||
@@ -159,12 +159,10 @@ public class PregeneratorJob implements PregenListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void drawRegion(int x, int z, Color color) {
|
public void drawRegion(int x, int z, Color color) {
|
||||||
J.a(() -> {
|
J.a(() -> task.iterateChunks(x, z, (xx, zz) -> {
|
||||||
PregenTask.iterateRegion(x, z, (xx, zz) -> {
|
|
||||||
draw(xx, zz, color);
|
draw(xx, zz, color);
|
||||||
J.sleep(3);
|
J.sleep(3);
|
||||||
});
|
}));
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void draw(int x, int z, Color color) {
|
public void draw(int x, int z, Color color) {
|
||||||
@@ -173,7 +171,7 @@ public class PregeneratorJob implements PregenListener {
|
|||||||
renderer.func.accept(new Position2(x, z), color);
|
renderer.func.accept(new Position2(x, z), color);
|
||||||
}
|
}
|
||||||
} catch (Throwable ignored) {
|
} catch (Throwable ignored) {
|
||||||
|
Iris.error("Failed to draw pregen");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,8 +189,8 @@ public class PregeneratorJob implements PregenListener {
|
|||||||
monitor.close();
|
monitor.close();
|
||||||
J.sleep(3000);
|
J.sleep(3000);
|
||||||
frame.setVisible(false);
|
frame.setVisible(false);
|
||||||
} catch(Throwable e) {
|
} catch (Throwable ignored) {
|
||||||
|
Iris.error("Error closing pregen gui");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -206,8 +204,7 @@ public class PregeneratorJob implements PregenListener {
|
|||||||
renderer.l = new ReentrantLock();
|
renderer.l = new ReentrantLock();
|
||||||
renderer.frame = frame;
|
renderer.frame = frame;
|
||||||
renderer.job = this;
|
renderer.job = this;
|
||||||
renderer.func = (c, b) ->
|
renderer.func = (c, b) -> {
|
||||||
{
|
|
||||||
renderer.l.lock();
|
renderer.l.lock();
|
||||||
renderer.order.add(() -> renderer.draw(c, b, renderer.bg));
|
renderer.order.add(() -> renderer.draw(c, b, renderer.bg));
|
||||||
renderer.l.unlock();
|
renderer.l.unlock();
|
||||||
@@ -215,8 +212,8 @@ public class PregeneratorJob implements PregenListener {
|
|||||||
frame.add(renderer);
|
frame.add(renderer);
|
||||||
frame.setSize(1000, 1000);
|
frame.setSize(1000, 1000);
|
||||||
frame.setVisible(true);
|
frame.setVisible(true);
|
||||||
} catch(Throwable e) {
|
} catch (Throwable ignored) {
|
||||||
|
Iris.error("Error opening pregen gui");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -239,10 +236,6 @@ public class PregeneratorJob implements PregenListener {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onChunkGenerating(int x, int z) {
|
public void onChunkGenerating(int x, int z) {
|
||||||
if(engine != null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
draw(x, z, COLOR_GENERATING);
|
draw(x, z, COLOR_GENERATING);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,6 +30,7 @@ import com.volmit.iris.engine.object.IrisWorld;
|
|||||||
import com.volmit.iris.util.collection.KList;
|
import com.volmit.iris.util.collection.KList;
|
||||||
import com.volmit.iris.util.collection.KMap;
|
import com.volmit.iris.util.collection.KMap;
|
||||||
import com.volmit.iris.util.collection.KSet;
|
import com.volmit.iris.util.collection.KSet;
|
||||||
|
import com.volmit.iris.util.data.registry.Attributes;
|
||||||
import com.volmit.iris.util.format.Form;
|
import com.volmit.iris.util.format.Form;
|
||||||
import com.volmit.iris.util.math.BlockPosition;
|
import com.volmit.iris.util.math.BlockPosition;
|
||||||
import com.volmit.iris.util.math.M;
|
import com.volmit.iris.util.math.M;
|
||||||
@@ -44,16 +45,10 @@ import org.bukkit.entity.LivingEntity;
|
|||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
import javax.swing.JFrame;
|
import javax.swing.*;
|
||||||
import javax.swing.JPanel;
|
|
||||||
import javax.swing.event.MouseInputListener;
|
import javax.swing.event.MouseInputListener;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.event.KeyEvent;
|
import java.awt.event.*;
|
||||||
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.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -62,6 +57,8 @@ import java.util.concurrent.ExecutorService;
|
|||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.function.BiFunction;
|
import java.util.function.BiFunction;
|
||||||
|
|
||||||
|
import static com.volmit.iris.util.data.registry.Attributes.MAX_HEALTH;
|
||||||
|
|
||||||
public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener, MouseMotionListener, MouseInputListener {
|
public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener, MouseMotionListener, MouseInputListener {
|
||||||
private static final long serialVersionUID = 2094606939770332040L;
|
private static final long serialVersionUID = 2094606939770332040L;
|
||||||
private final KList<LivingEntity> lastEntities = new KList<>();
|
private final KList<LivingEntity> lastEntities = new KList<>();
|
||||||
@@ -218,12 +215,18 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
|||||||
BiFunction<Double, Double, Integer> colorFunction = (d, dx) -> Color.black.getRGB();
|
BiFunction<Double, Double, Integer> colorFunction = (d, dx) -> Color.black.getRGB();
|
||||||
|
|
||||||
switch (currentType) {
|
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, DECORATOR_LOAD, OBJECT_LOAD, LAYER_LOAD ->
|
||||||
case BIOME_LAND -> colorFunction = (x, z) -> engine.getComplex().getLandBiomeStream().get(x, z).getColor(engine, currentType).getRGB();
|
colorFunction = (x, z) -> engine.getComplex().getTrueBiomeStream().get(x, z).getColor(engine, currentType).getRGB();
|
||||||
case BIOME_SEA -> colorFunction = (x, z) -> engine.getComplex().getSeaBiomeStream().get(x, z).getColor(engine, currentType).getRGB();
|
case BIOME_LAND ->
|
||||||
case REGION -> colorFunction = (x, z) -> engine.getComplex().getRegionStream().get(x, z).getColor(engine.getComplex(), currentType).getRGB();
|
colorFunction = (x, z) -> engine.getComplex().getLandBiomeStream().get(x, z).getColor(engine, currentType).getRGB();
|
||||||
case CAVE_LAND -> colorFunction = (x, z) -> engine.getComplex().getCaveBiomeStream().get(x, z).getColor(engine, currentType).getRGB();
|
case BIOME_SEA ->
|
||||||
case HEIGHT -> colorFunction = (x, z) -> Color.getHSBColor(engine.getComplex().getHeightStream().get(x, z).floatValue(), 100, 100).getRGB();
|
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);
|
return colorFunction.apply(wx, wz);
|
||||||
@@ -433,13 +436,9 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
|||||||
|
|
||||||
if (engine.isClosed()) {
|
if (engine.isClosed()) {
|
||||||
EventQueue.invokeLater(() -> {
|
EventQueue.invokeLater(() -> {
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
setVisible(false);
|
setVisible(false);
|
||||||
}
|
} catch (Throwable e) {
|
||||||
|
|
||||||
catch(Throwable e)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -640,7 +639,7 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
|||||||
|
|
||||||
k.add("Pos: " + h.getLocation().getBlockX() + ", " + h.getLocation().getBlockY() + ", " + h.getLocation().getBlockZ());
|
k.add("Pos: " + h.getLocation().getBlockX() + ", " + h.getLocation().getBlockY() + ", " + h.getLocation().getBlockZ());
|
||||||
k.add("UUID: " + h.getUniqueId());
|
k.add("UUID: " + h.getUniqueId());
|
||||||
k.add("HP: " + h.getHealth() + " / " + h.getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue());
|
k.add("HP: " + h.getHealth() + " / " + h.getAttribute(MAX_HEALTH).getValue());
|
||||||
|
|
||||||
drawCardTR(g, k);
|
drawCardTR(g, k);
|
||||||
}
|
}
|
||||||
@@ -739,7 +738,8 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
|||||||
IrisComplex complex = engine.getComplex();
|
IrisComplex complex = engine.getComplex();
|
||||||
File r = null;
|
File r = null;
|
||||||
switch (currentType) {
|
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_LAND -> r = complex.getLandBiomeStream().get(getWorldX(hx), getWorldZ(hz)).openInVSCode();
|
||||||
case BIOME_SEA -> r = complex.getSeaBiomeStream().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();
|
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() <= 0) {
|
||||||
|
// Max is below water level, so it is most likely an ocean biome
|
||||||
|
c = Color.BLUE;
|
||||||
|
} else if (g.getMin() < 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;
|
package com.volmit.iris.core.gui.components;
|
||||||
|
|
||||||
public enum RenderType {
|
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;
|
package com.volmit.iris.core.gui.components;
|
||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.*;
|
||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface Renderer {
|
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.IrisCustomData;
|
||||||
|
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 IrisCustomData} 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 IrisCustomData}
|
||||||
|
*
|
||||||
|
* @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.IrisCustomData;
|
||||||
|
import com.volmit.iris.util.reflect.WrappedField;
|
||||||
|
import com.volmit.iris.util.reflect.WrappedReturningMethod;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.block.data.BlockData;
|
||||||
|
import org.bukkit.block.data.type.Leaves;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import 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 IrisCustomData(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.Iris;
|
||||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||||
|
import com.volmit.iris.engine.object.IrisBiome;
|
||||||
import com.volmit.iris.engine.platform.PlatformChunkGenerator;
|
import com.volmit.iris.engine.platform.PlatformChunkGenerator;
|
||||||
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.OfflinePlayer;
|
import org.bukkit.OfflinePlayer;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
// See/update https://app.gitbook.com/@volmitsoftware/s/iris/compatability/papi/
|
// See/update https://app.gitbook.com/@volmitsoftware/s/iris/compatability/papi/
|
||||||
public class IrisPapiExpansion extends PlaceholderExpansion {
|
public class IrisPapiExpansion extends PlaceholderExpansion {
|
||||||
@Override
|
@Override
|
||||||
public String getIdentifier() {
|
public @NotNull String getIdentifier() {
|
||||||
return "iris";
|
return "iris";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getAuthor() {
|
public @NotNull String getAuthor() {
|
||||||
return "Volmit Software";
|
return "Volmit Software";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getVersion() {
|
public @NotNull String getVersion() {
|
||||||
return Iris.instance.getDescription().getVersion();
|
return Iris.instance.getDescription().getVersion();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean persist() {
|
public boolean persist() {
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -52,22 +54,22 @@ public class IrisPapiExpansion extends PlaceholderExpansion {
|
|||||||
Location l = null;
|
Location l = null;
|
||||||
PlatformChunkGenerator a = null;
|
PlatformChunkGenerator a = null;
|
||||||
|
|
||||||
if(player.isOnline()) {
|
if (player.isOnline() && player.getPlayer() != null) {
|
||||||
l = player.getPlayer().getLocation();
|
l = player.getPlayer().getLocation().add(0, 2, 0);
|
||||||
a = IrisToolbelt.access(l.getWorld());
|
a = IrisToolbelt.access(l.getWorld());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p.equalsIgnoreCase("biome_name")) {
|
if (p.equalsIgnoreCase("biome_name")) {
|
||||||
if (a != null) {
|
if (a != null) {
|
||||||
return a.getEngine().getBiome(l).getName();
|
return getBiome(a, l).getName();
|
||||||
}
|
}
|
||||||
} else if (p.equalsIgnoreCase("biome_id")) {
|
} else if (p.equalsIgnoreCase("biome_id")) {
|
||||||
if (a != null) {
|
if (a != null) {
|
||||||
return a.getEngine().getBiome(l).getLoadKey();
|
return getBiome(a, l).getLoadKey();
|
||||||
}
|
}
|
||||||
} else if (p.equalsIgnoreCase("biome_file")) {
|
} else if (p.equalsIgnoreCase("biome_file")) {
|
||||||
if (a != null) {
|
if (a != null) {
|
||||||
return a.getEngine().getBiome(l).getLoadFile().getPath();
|
return getBiome(a, l).getLoadFile().getPath();
|
||||||
}
|
}
|
||||||
} else if (p.equalsIgnoreCase("region_name")) {
|
} else if (p.equalsIgnoreCase("region_name")) {
|
||||||
if (a != null) {
|
if (a != null) {
|
||||||
@@ -107,4 +109,8 @@ public class IrisPapiExpansion extends PlaceholderExpansion {
|
|||||||
|
|
||||||
return null;
|
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.IrisCustomData;
|
||||||
|
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 IrisCustomData(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,60 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
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() : List.of();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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.IrisCustomData;
|
||||||
|
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 IrisCustomData(data, blockState);
|
||||||
|
} else if (NexoFurniture.isFurniture(blockId.key())) {
|
||||||
|
return new IrisCustomData(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 NexoItems.itemNames().stream()
|
||||||
|
.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 NexoItems.itemNames().stream()
|
||||||
|
.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 javax.imageio.ImageIO;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
public class ImageResourceLoader extends ResourceLoader<IrisImage> {
|
public class ImageResourceLoader extends ResourceLoader<IrisImage> {
|
||||||
public ImageResourceLoader(File root, IrisData idm, String folderName, String resourceTypeName) {
|
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() {
|
public String[] getPossibleKeys() {
|
||||||
if (possibleKeys != null) {
|
if (possibleKeys != null) {
|
||||||
return possibleKeys;
|
return possibleKeys;
|
||||||
@@ -74,26 +86,31 @@ public class ImageResourceLoader extends ResourceLoader<IrisImage> {
|
|||||||
Iris.debug("Building " + resourceTypeName + " Possibility Lists");
|
Iris.debug("Building " + resourceTypeName + " Possibility Lists");
|
||||||
KSet<String> m = new KSet<>();
|
KSet<String> m = new KSet<>();
|
||||||
|
|
||||||
|
|
||||||
for (File i : getFolders()) {
|
for (File i : getFolders()) {
|
||||||
for(File j : i.listFiles()) {
|
getPNGFiles(i, m);
|
||||||
if(j.isFile() && j.getName().endsWith(".png")) {
|
|
||||||
m.add(j.getName().replaceAll("\\Q.png\\E", ""));
|
|
||||||
} else if(j.isDirectory()) {
|
|
||||||
for(File k : j.listFiles()) {
|
|
||||||
if(k.isFile() && k.getName().endsWith(".png")) {
|
|
||||||
m.add(j.getName() + "/" + k.getName().replaceAll("\\Q.png\\E", ""));
|
|
||||||
} else if(k.isDirectory()) {
|
|
||||||
for(File l : k.listFiles()) {
|
|
||||||
if(l.isFile() && l.getName().endsWith(".png")) {
|
|
||||||
m.add(j.getName() + "/" + k.getName() + "/" + l.getName().replaceAll("\\Q.png\\E", ""));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// for (File i : getFolders()) {
|
||||||
|
// 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);
|
KList<String> v = new KList<>(m);
|
||||||
possibleKeys = v.toArray(new String[0]);
|
possibleKeys = v.toArray(new String[0]);
|
||||||
return possibleKeys;
|
return possibleKeys;
|
||||||
@@ -18,12 +18,7 @@
|
|||||||
|
|
||||||
package com.volmit.iris.core.loader;
|
package com.volmit.iris.core.loader;
|
||||||
|
|
||||||
import com.google.gson.ExclusionStrategy;
|
import com.google.gson.*;
|
||||||
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.reflect.TypeToken;
|
import com.google.gson.reflect.TypeToken;
|
||||||
import com.google.gson.stream.JsonReader;
|
import com.google.gson.stream.JsonReader;
|
||||||
import com.google.gson.stream.JsonToken;
|
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.context.IrisContext;
|
||||||
import com.volmit.iris.util.format.C;
|
import com.volmit.iris.util.format.C;
|
||||||
import com.volmit.iris.util.math.RNG;
|
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.ChronoLatch;
|
||||||
import com.volmit.iris.util.scheduling.J;
|
import com.volmit.iris.util.scheduling.J;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -116,6 +114,7 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
|||||||
public static IrisObject loadAnyObject(String key) {
|
public static IrisObject loadAnyObject(String key) {
|
||||||
return loadAny(key, (dm) -> dm.getObjectLoader().load(key, false));
|
return loadAny(key, (dm) -> dm.getObjectLoader().load(key, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IrisMatterObject loadAnyMatter(String key) {
|
public static IrisMatterObject loadAnyMatter(String key) {
|
||||||
return loadAny(key, (dm) -> dm.getMatterLoader().load(key, false));
|
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.imageLoader = registerLoader(IrisImage.class);
|
||||||
this.scriptLoader = registerLoader(IrisScript.class);
|
this.scriptLoader = registerLoader(IrisScript.class);
|
||||||
this.matterObjectLoader = registerLoader(IrisMatterObject.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();
|
gson = builder.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -371,8 +379,7 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String ff = g.substring(1).split("\\Q.\\E")[0];
|
return g.substring(1).split("\\Q.\\E")[0];
|
||||||
return ff;
|
|
||||||
} else {
|
} else {
|
||||||
Iris.error("Forign file from loader " + f.getPath() + " (loader realm: " + getDataFolder().getPath() + ")");
|
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);
|
return adapter.read(reader);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
Iris.error("Failed to read " + typeToken.getRawType().getCanonicalName() + "... faking objects a little to load the file at least.");
|
Iris.error("Failed to read " + typeToken.getRawType().getCanonicalName() + "... faking objects a little to load the file at least.");
|
||||||
|
Iris.reportError(e);
|
||||||
try {
|
try {
|
||||||
return (T) typeToken.getRawType().getConstructor().newInstance();
|
return (T) typeToken.getRawType().getConstructor().newInstance();
|
||||||
} catch (Throwable ignored) {
|
} catch (Throwable ignored) {
|
||||||
@@ -467,4 +475,38 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
|||||||
public boolean isClosed() {
|
public boolean isClosed() {
|
||||||
return closed;
|
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 com.volmit.iris.util.plugin.VolmitSender;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.awt.Desktop;
|
import java.awt.*;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@@ -29,6 +29,8 @@ import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
public class MatterObjectResourceLoader extends ResourceLoader<IrisMatterObject> {
|
public class MatterObjectResourceLoader extends ResourceLoader<IrisMatterObject> {
|
||||||
|
private String[] possibleKeys;
|
||||||
|
|
||||||
public MatterObjectResourceLoader(File root, IrisData idm, String folderName, String resourceTypeName) {
|
public MatterObjectResourceLoader(File root, IrisData idm, String folderName, String resourceTypeName) {
|
||||||
super(root, idm, folderName, resourceTypeName, IrisMatterObject.class);
|
super(root, idm, folderName, resourceTypeName, IrisMatterObject.class);
|
||||||
loadCache = new KCache<>(this::loadRaw, IrisSettings.get().getPerformance().getObjectLoaderCacheSize());
|
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() {
|
public String[] getPossibleKeys() {
|
||||||
if (possibleKeys != null) {
|
if (possibleKeys != null) {
|
||||||
return possibleKeys;
|
return possibleKeys;
|
||||||
@@ -71,24 +83,8 @@ public class MatterObjectResourceLoader extends ResourceLoader<IrisMatterObject>
|
|||||||
Iris.debug("Building " + resourceTypeName + " Possibility Lists");
|
Iris.debug("Building " + resourceTypeName + " Possibility Lists");
|
||||||
KSet<String> m = new KSet<>();
|
KSet<String> m = new KSet<>();
|
||||||
|
|
||||||
for(File i : getFolders()) {
|
for (File folder : getFolders()) {
|
||||||
for(File j : i.listFiles()) {
|
findMatFiles(folder, m);
|
||||||
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);
|
KList<String> v = new KList<>(m);
|
||||||
@@ -96,6 +92,40 @@ public class MatterObjectResourceLoader extends ResourceLoader<IrisMatterObject>
|
|||||||
return possibleKeys;
|
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) {
|
public File findFile(String name) {
|
||||||
for (File i : getFolders(name)) {
|
for (File i : getFolders(name)) {
|
||||||
for (File j : i.listFiles()) {
|
for (File j : i.listFiles()) {
|
||||||
@@ -50,10 +50,10 @@ public class ObjectResourceLoader extends ResourceLoader<IrisObject> {
|
|||||||
try {
|
try {
|
||||||
PrecisionStopwatch p = PrecisionStopwatch.start();
|
PrecisionStopwatch p = PrecisionStopwatch.start();
|
||||||
IrisObject t = new IrisObject(0, 0, 0);
|
IrisObject t = new IrisObject(0, 0, 0);
|
||||||
t.read(j);
|
|
||||||
t.setLoadKey(name);
|
t.setLoadKey(name);
|
||||||
t.setLoader(manager);
|
t.setLoader(manager);
|
||||||
t.setLoadFile(j);
|
t.setLoadFile(j);
|
||||||
|
t.read(j);
|
||||||
logLoad(j, t);
|
logLoad(j, t);
|
||||||
tlt.addAndGet(p.getMilliseconds());
|
tlt.addAndGet(p.getMilliseconds());
|
||||||
return t;
|
return t;
|
||||||
@@ -68,33 +68,26 @@ public class ObjectResourceLoader extends ResourceLoader<IrisObject> {
|
|||||||
if (possibleKeys != null) {
|
if (possibleKeys != null) {
|
||||||
return possibleKeys;
|
return possibleKeys;
|
||||||
}
|
}
|
||||||
|
|
||||||
Iris.debug("Building " + resourceTypeName + " Possibility Lists");
|
Iris.debug("Building " + resourceTypeName + " Possibility Lists");
|
||||||
KSet<String> m = new KSet<>();
|
KSet<String> m = new KSet<>();
|
||||||
|
|
||||||
for (File i : getFolders()) {
|
for (File i : getFolders()) {
|
||||||
for(File j : i.listFiles()) {
|
m.addAll(getFiles(i, ".iob", true));
|
||||||
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", ""));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
possibleKeys = m.toArray(new String[0]);
|
||||||
|
return possibleKeys;
|
||||||
}
|
}
|
||||||
|
|
||||||
KList<String> v = new KList<>(m);
|
private KList<String> getFiles(File dir, String ext, boolean skipDirName) {
|
||||||
possibleKeys = v.toArray(new String[0]);
|
KList<String> paths = new KList<>();
|
||||||
return possibleKeys;
|
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) {
|
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.IrisSettings;
|
||||||
import com.volmit.iris.core.project.SchemaBuilder;
|
import com.volmit.iris.core.project.SchemaBuilder;
|
||||||
import com.volmit.iris.core.service.PreservationSVC;
|
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.engine.framework.MeteredCache;
|
||||||
import com.volmit.iris.util.collection.KList;
|
import com.volmit.iris.util.collection.KList;
|
||||||
import com.volmit.iris.util.collection.KSet;
|
import com.volmit.iris.util.collection.KSet;
|
||||||
import com.volmit.iris.util.data.KCache;
|
import com.volmit.iris.util.data.KCache;
|
||||||
import com.volmit.iris.util.format.C;
|
import com.volmit.iris.util.format.C;
|
||||||
import com.volmit.iris.util.format.Form;
|
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.io.IO;
|
||||||
import com.volmit.iris.util.json.JSONArray;
|
import com.volmit.iris.util.json.JSONArray;
|
||||||
import com.volmit.iris.util.json.JSONObject;
|
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.ChronoLatch;
|
||||||
import com.volmit.iris.util.scheduling.J;
|
import com.volmit.iris.util.scheduling.J;
|
||||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.*;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
import java.util.zip.GZIPInputStream;
|
||||||
|
import java.util.zip.GZIPOutputStream;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
|
@EqualsAndHashCode(exclude = "manager")
|
||||||
|
@ToString(exclude = "manager")
|
||||||
public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
||||||
public static final AtomicDouble tlt = new AtomicDouble(0);
|
public static final AtomicDouble tlt = new AtomicDouble(0);
|
||||||
private static final int CACHE_SIZE = 100000;
|
private static final int CACHE_SIZE = 100000;
|
||||||
|
protected final AtomicReference<KList<File>> folderCache;
|
||||||
|
protected KSet<String> firstAccess;
|
||||||
protected File root;
|
protected File root;
|
||||||
protected String folderName;
|
protected String folderName;
|
||||||
protected String resourceTypeName;
|
protected String resourceTypeName;
|
||||||
protected KCache<String, T> loadCache;
|
protected KCache<String, T> loadCache;
|
||||||
protected final AtomicReference<KList<File>> folderCache;
|
|
||||||
protected Class<? extends T> objectClass;
|
protected Class<? extends T> objectClass;
|
||||||
protected String cname;
|
protected String cname;
|
||||||
protected String[] possibleKeys = null;
|
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) {
|
public ResourceLoader(File root, IrisData manager, String folderName, String resourceTypeName, Class<? extends T> objectClass) {
|
||||||
this.manager = manager;
|
this.manager = manager;
|
||||||
|
firstAccess = new KSet<>();
|
||||||
folderCache = new AtomicReference<>();
|
folderCache = new AtomicReference<>();
|
||||||
sec = new ChronoLatch(5000);
|
sec = new ChronoLatch(5000);
|
||||||
loads = new AtomicInteger();
|
loads = new AtomicInteger();
|
||||||
@@ -221,6 +233,24 @@ public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
|||||||
return m;
|
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) {
|
public KList<T> loadAll(KList<String> s, Consumer<T> postLoad) {
|
||||||
KList<T> m = new KList<>();
|
KList<T> m = new KList<>();
|
||||||
|
|
||||||
@@ -282,17 +312,62 @@ public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
firstAccess.add(name);
|
||||||
return loadCache.get(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() {
|
public KList<File> getFolders() {
|
||||||
|
|
||||||
|
|
||||||
synchronized (folderCache) {
|
synchronized (folderCache) {
|
||||||
if (folderCache.get() == null) {
|
if (folderCache.get() == null) {
|
||||||
KList<File> fc = new KList<>();
|
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.isDirectory()) {
|
||||||
if (i.getName().equals(folderName)) {
|
if (i.getName().equals(folderName)) {
|
||||||
fc.add(i);
|
fc.add(i);
|
||||||
@@ -21,13 +21,13 @@ package com.volmit.iris.core.loader;
|
|||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.Iris;
|
||||||
import com.volmit.iris.core.IrisSettings;
|
import com.volmit.iris.core.IrisSettings;
|
||||||
import com.volmit.iris.engine.object.IrisScript;
|
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.data.KCache;
|
||||||
import com.volmit.iris.util.io.IO;
|
import com.volmit.iris.util.io.IO;
|
||||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
public class ScriptResourceLoader extends ResourceLoader<IrisScript> {
|
public class ScriptResourceLoader extends ResourceLoader<IrisScript> {
|
||||||
public ScriptResourceLoader(File root, IrisData idm, String folderName, String resourceTypeName) {
|
public ScriptResourceLoader(File root, IrisData idm, String folderName, String resourceTypeName) {
|
||||||
@@ -60,39 +60,70 @@ public class ScriptResourceLoader extends ResourceLoader<IrisScript> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public String[] getPossibleKeys() {
|
public String[] getPossibleKeys() {
|
||||||
if (possibleKeys != null) {
|
if (possibleKeys != null) {
|
||||||
return possibleKeys;
|
return possibleKeys;
|
||||||
}
|
}
|
||||||
|
|
||||||
Iris.debug("Building " + resourceTypeName + " Possibility Lists");
|
Iris.debug("Building " + resourceTypeName + " Possibility Lists");
|
||||||
KSet<String> m = new KSet<>();
|
Set<String> keys = new HashSet<>();
|
||||||
|
|
||||||
for (File i : getFolders()) {
|
for (File i : getFolders()) {
|
||||||
for(File j : i.listFiles()) {
|
if (i.isDirectory()) {
|
||||||
if(j.isFile() && j.getName().endsWith(".js")) {
|
keys.addAll(getKeysInDirectory(i));
|
||||||
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 = keys.toArray(new String[0]);
|
||||||
possibleKeys = v.toArray(new String[0]);
|
|
||||||
return possibleKeys;
|
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) {
|
public File findFile(String name) {
|
||||||
for (File i : getFolders(name)) {
|
for (File i : getFolders(name)) {
|
||||||
for (File j : i.listFiles()) {
|
for (File j : i.listFiles()) {
|
||||||
120
core/src/main/java/com/volmit/iris/core/nms/INMS.java
Normal file
120
core/src/main/java/com/volmit/iris/core/nms/INMS.java
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
/*
|
||||||
|
* 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.nms;
|
||||||
|
|
||||||
|
import com.volmit.iris.Iris;
|
||||||
|
import com.volmit.iris.core.IrisSettings;
|
||||||
|
import com.volmit.iris.core.nms.v1X.NMSBinding1X;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class INMS {
|
||||||
|
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",
|
||||||
|
"1.21.4", "v1_21_R3"
|
||||||
|
);
|
||||||
|
private static final List<Version> PACKS = List.of(
|
||||||
|
new Version(21, 4, "31020"),
|
||||||
|
new Version(21, 2, "31000"),
|
||||||
|
new Version(20, 1, "3910")
|
||||||
|
);
|
||||||
|
|
||||||
|
//@done
|
||||||
|
private static final INMSBinding binding = bind();
|
||||||
|
public static final String OVERWORLD_TAG = getOverworldTag();
|
||||||
|
|
||||||
|
public static INMSBinding get() {
|
||||||
|
return binding;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getNMSTag() {
|
||||||
|
if (IrisSettings.get().getGeneral().isDisableNMS()) {
|
||||||
|
return "BUKKIT";
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
String name = Bukkit.getServer().getClass().getCanonicalName();
|
||||||
|
if (name.equals("org.bukkit.craftbukkit.CraftServer")) {
|
||||||
|
return REVISION.getOrDefault(Bukkit.getServer().getBukkitVersion().split("-")[0], "BUKKIT");
|
||||||
|
} else {
|
||||||
|
return name.split("\\Q.\\E")[3];
|
||||||
|
}
|
||||||
|
} catch (Throwable e) {
|
||||||
|
Iris.reportError(e);
|
||||||
|
Iris.error("Failed to determine server nms version!");
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return "BUKKIT";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static INMSBinding bind() {
|
||||||
|
String code = getNMSTag();
|
||||||
|
Iris.info("Locating NMS Binding for " + code);
|
||||||
|
|
||||||
|
try {
|
||||||
|
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 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.");
|
||||||
|
Iris.warn("Note: If this is a new version, expect an update soon.");
|
||||||
|
|
||||||
|
return new NMSBinding1X();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getOverworldTag() {
|
||||||
|
var version = Bukkit.getServer().getBukkitVersion().split("-")[0].split("\\.", 3);
|
||||||
|
int major = 0;
|
||||||
|
int minor = 0;
|
||||||
|
|
||||||
|
if (version.length > 2) {
|
||||||
|
major = Integer.parseInt(version[1]);
|
||||||
|
minor = Integer.parseInt(version[2]);
|
||||||
|
} else if (version.length == 2) {
|
||||||
|
major = Integer.parseInt(version[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var p : PACKS) {
|
||||||
|
if (p.major > major || p.minor > minor)
|
||||||
|
continue;
|
||||||
|
return p.tag;
|
||||||
|
}
|
||||||
|
return "3910";
|
||||||
|
}
|
||||||
|
|
||||||
|
private record Version(int major, int minor, String tag) {}
|
||||||
|
}
|
||||||
@@ -18,22 +18,37 @@
|
|||||||
|
|
||||||
package com.volmit.iris.core.nms;
|
package com.volmit.iris.core.nms;
|
||||||
|
|
||||||
|
import com.volmit.iris.core.nms.container.AutoClosing;
|
||||||
|
import com.volmit.iris.core.nms.container.BiomeColor;
|
||||||
|
import com.volmit.iris.core.nms.container.Pair;
|
||||||
|
import com.volmit.iris.core.nms.datapack.DataVersion;
|
||||||
|
import com.volmit.iris.core.nms.headless.IRegionStorage;
|
||||||
|
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.MCABiomeContainer;
|
||||||
import com.volmit.iris.util.nbt.mca.palette.MCAPaletteAccess;
|
import com.volmit.iris.util.nbt.mca.palette.MCAPaletteAccess;
|
||||||
import com.volmit.iris.util.nbt.tag.CompoundTag;
|
import com.volmit.iris.util.nbt.tag.CompoundTag;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.*;
|
||||||
import org.bukkit.World;
|
|
||||||
import org.bukkit.WorldCreator;
|
|
||||||
import org.bukkit.block.Biome;
|
import org.bukkit.block.Biome;
|
||||||
import org.bukkit.entity.Entity;
|
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.ChunkGenerator;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
|
||||||
public interface INMSBinding {
|
public interface INMSBinding {
|
||||||
|
boolean hasTile(Material material);
|
||||||
|
|
||||||
boolean hasTile(Location l);
|
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);
|
CompoundTag serializeEntity(Entity location);
|
||||||
|
|
||||||
@@ -54,14 +69,19 @@ public interface INMSBinding {
|
|||||||
String getTrueBiomeBaseKey(Location location);
|
String getTrueBiomeBaseKey(Location location);
|
||||||
|
|
||||||
Object getCustomBiomeBaseFor(String mckey);
|
Object getCustomBiomeBaseFor(String mckey);
|
||||||
|
|
||||||
Object getCustomBiomeBaseHolderFor(String mckey);
|
Object getCustomBiomeBaseHolderFor(String mckey);
|
||||||
|
|
||||||
|
int getBiomeBaseIdForKey(String key);
|
||||||
|
|
||||||
String getKeyForBiomeBase(Object biomeBase);
|
String getKeyForBiomeBase(Object biomeBase);
|
||||||
|
|
||||||
Object getBiomeBase(World world, Biome biome);
|
Object getBiomeBase(World world, Biome biome);
|
||||||
|
|
||||||
Object getBiomeBase(Object registry, Biome biome);
|
Object getBiomeBase(Object registry, Biome biome);
|
||||||
|
|
||||||
|
KList<Biome> getBiomes();
|
||||||
|
|
||||||
boolean isBukkit();
|
boolean isBukkit();
|
||||||
|
|
||||||
int getBiomeId(Biome biome);
|
int getBiomeId(Biome biome);
|
||||||
@@ -71,8 +91,13 @@ public interface INMSBinding {
|
|||||||
MCABiomeContainer newBiomeContainer(int min, int max);
|
MCABiomeContainer newBiomeContainer(int min, int max);
|
||||||
|
|
||||||
default World createWorld(WorldCreator c) {
|
default World createWorld(WorldCreator c) {
|
||||||
|
if (missingDimensionTypes(true, true, true))
|
||||||
|
throw new IllegalStateException("Missing dimenstion types to create world");
|
||||||
|
|
||||||
|
try (var ignored = injectLevelStems()) {
|
||||||
return c.createWorld();
|
return c.createWorld();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int countCustomBiomes();
|
int countCustomBiomes();
|
||||||
|
|
||||||
@@ -83,4 +108,34 @@ public interface INMSBinding {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MCAPaletteAccess createPalette();
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
IRegionStorage createRegionStorage(Engine engine);
|
||||||
|
|
||||||
|
KList<String> getStructureKeys();
|
||||||
|
|
||||||
|
AutoClosing injectLevelStems();
|
||||||
|
|
||||||
|
Pair<Integer, AutoClosing> injectUncached(boolean overworld, boolean nether, boolean end);
|
||||||
|
|
||||||
|
boolean missingDimensionTypes(boolean overworld, boolean nether, boolean end);
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package com.volmit.iris.core.nms.container;
|
||||||
|
|
||||||
|
import com.volmit.iris.util.function.NastyRunnable;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class AutoClosing implements AutoCloseable {
|
||||||
|
private final AtomicBoolean closed = new AtomicBoolean();
|
||||||
|
private final NastyRunnable action;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
if (closed.getAndSet(true)) return;
|
||||||
|
try {
|
||||||
|
action.run();
|
||||||
|
} catch (Throwable e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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,28 @@
|
|||||||
|
package com.volmit.iris.core.nms.datapack;
|
||||||
|
|
||||||
|
import com.volmit.iris.engine.object.IrisBiomeCustom;
|
||||||
|
import com.volmit.iris.engine.object.IrisRange;
|
||||||
|
import com.volmit.iris.util.json.JSONObject;
|
||||||
|
|
||||||
|
public interface IDataFixer {
|
||||||
|
|
||||||
|
default JSONObject fixCustomBiome(IrisBiomeCustom biome, JSONObject json) {
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSONObject rawDimension(Dimension dimension);
|
||||||
|
|
||||||
|
default JSONObject createDimension(Dimension dimension, IrisRange height, int logicalHeight) {
|
||||||
|
JSONObject obj = rawDimension(dimension);
|
||||||
|
obj.put("min_y", height.getMin());
|
||||||
|
obj.put("height", height.getMax() - height.getMin());
|
||||||
|
obj.put("logical_height", logicalHeight);
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Dimension {
|
||||||
|
OVERRWORLD,
|
||||||
|
NETHER,
|
||||||
|
THE_END
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
package com.volmit.iris.core.nms.datapack.v1192;
|
||||||
|
|
||||||
|
import com.volmit.iris.core.nms.datapack.IDataFixer;
|
||||||
|
import com.volmit.iris.util.json.JSONObject;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class DataFixerV1192 implements IDataFixer {
|
||||||
|
|
||||||
|
private static final Map<Dimension, String> DIMENSIONS = Map.of(
|
||||||
|
Dimension.OVERRWORLD, """
|
||||||
|
{
|
||||||
|
"ambient_light": 0.0,
|
||||||
|
"bed_works": true,
|
||||||
|
"coordinate_scale": 1.0,
|
||||||
|
"effects": "minecraft:overworld",
|
||||||
|
"has_ceiling": false,
|
||||||
|
"has_raids": true,
|
||||||
|
"has_skylight": true,
|
||||||
|
"infiniburn": "#minecraft:infiniburn_overworld",
|
||||||
|
"monster_spawn_block_light_limit": 0,
|
||||||
|
"monster_spawn_light_level": {
|
||||||
|
"type": "minecraft:uniform",
|
||||||
|
"value": {
|
||||||
|
"max_inclusive": 7,
|
||||||
|
"min_inclusive": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"natural": true,
|
||||||
|
"piglin_safe": false,
|
||||||
|
"respawn_anchor_works": false,
|
||||||
|
"ultrawarm": false
|
||||||
|
}""",
|
||||||
|
Dimension.NETHER, """
|
||||||
|
{
|
||||||
|
"ambient_light": 0.1,
|
||||||
|
"bed_works": false,
|
||||||
|
"coordinate_scale": 8.0,
|
||||||
|
"effects": "minecraft:the_nether",
|
||||||
|
"fixed_time": 18000,
|
||||||
|
"has_ceiling": true,
|
||||||
|
"has_raids": false,
|
||||||
|
"has_skylight": false,
|
||||||
|
"infiniburn": "#minecraft:infiniburn_nether",
|
||||||
|
"monster_spawn_block_light_limit": 15,
|
||||||
|
"monster_spawn_light_level": 7,
|
||||||
|
"natural": false,
|
||||||
|
"piglin_safe": true,
|
||||||
|
"respawn_anchor_works": true,
|
||||||
|
"ultrawarm": true
|
||||||
|
}""",
|
||||||
|
Dimension.THE_END, """
|
||||||
|
{
|
||||||
|
"ambient_light": 0.0,
|
||||||
|
"bed_works": false,
|
||||||
|
"coordinate_scale": 1.0,
|
||||||
|
"effects": "minecraft:the_end",
|
||||||
|
"fixed_time": 6000,
|
||||||
|
"has_ceiling": false,
|
||||||
|
"has_raids": true,
|
||||||
|
"has_skylight": false,
|
||||||
|
"infiniburn": "#minecraft:infiniburn_end",
|
||||||
|
"monster_spawn_block_light_limit": 0,
|
||||||
|
"monster_spawn_light_level": {
|
||||||
|
"type": "minecraft:uniform",
|
||||||
|
"value": {
|
||||||
|
"max_inclusive": 7,
|
||||||
|
"min_inclusive": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"natural": false,
|
||||||
|
"piglin_safe": false,
|
||||||
|
"respawn_anchor_works": false,
|
||||||
|
"ultrawarm": false
|
||||||
|
}"""
|
||||||
|
);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JSONObject rawDimension(Dimension dimension) {
|
||||||
|
return new JSONObject(DIMENSIONS.get(dimension));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
package com.volmit.iris.core.nms.datapack.v1206;
|
||||||
|
|
||||||
|
import com.volmit.iris.core.nms.datapack.v1192.DataFixerV1192;
|
||||||
|
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 extends DataFixerV1192 {
|
||||||
|
@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 rawDimension(Dimension dimension) {
|
||||||
|
JSONObject json = super.rawDimension(dimension);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package com.volmit.iris.core.nms.headless;
|
||||||
|
|
||||||
|
import com.volmit.iris.util.documentation.ChunkCoordinates;
|
||||||
|
import lombok.NonNull;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public interface IRegion extends AutoCloseable {
|
||||||
|
|
||||||
|
@ChunkCoordinates
|
||||||
|
boolean exists(int x, int z);
|
||||||
|
|
||||||
|
void write(@NonNull SerializableChunk chunk) throws IOException;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void close();
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package com.volmit.iris.core.nms.headless;
|
||||||
|
|
||||||
|
import com.volmit.iris.util.context.ChunkContext;
|
||||||
|
import com.volmit.iris.util.documentation.ChunkCoordinates;
|
||||||
|
import com.volmit.iris.util.documentation.RegionCoordinates;
|
||||||
|
import lombok.NonNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public interface IRegionStorage {
|
||||||
|
|
||||||
|
@ChunkCoordinates
|
||||||
|
boolean exists(int x, int z);
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@RegionCoordinates
|
||||||
|
IRegion getRegion(int x, int z, boolean existingOnly) throws IOException;
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@ChunkCoordinates
|
||||||
|
SerializableChunk createChunk(int x, int z);
|
||||||
|
|
||||||
|
void fillBiomes(@NonNull SerializableChunk chunk, @Nullable ChunkContext ctx);
|
||||||
|
|
||||||
|
void close();
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package com.volmit.iris.core.nms.headless;
|
||||||
|
|
||||||
|
import com.volmit.iris.engine.data.chunk.TerrainChunk;
|
||||||
|
import com.volmit.iris.util.math.Position2;
|
||||||
|
|
||||||
|
public interface SerializableChunk extends TerrainChunk {
|
||||||
|
Position2 getPos();
|
||||||
|
|
||||||
|
Object serialize();
|
||||||
|
|
||||||
|
void mark();
|
||||||
|
}
|
||||||
@@ -20,14 +20,29 @@ package com.volmit.iris.core.nms.v1X;
|
|||||||
|
|
||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.Iris;
|
||||||
import com.volmit.iris.core.nms.INMSBinding;
|
import com.volmit.iris.core.nms.INMSBinding;
|
||||||
|
import com.volmit.iris.core.nms.container.AutoClosing;
|
||||||
|
import com.volmit.iris.core.nms.container.BiomeColor;
|
||||||
|
import com.volmit.iris.core.nms.headless.IRegionStorage;
|
||||||
|
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.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.MCABiomeContainer;
|
||||||
import com.volmit.iris.util.nbt.mca.palette.MCAPaletteAccess;
|
import com.volmit.iris.util.nbt.mca.palette.MCAPaletteAccess;
|
||||||
import com.volmit.iris.util.nbt.tag.CompoundTag;
|
import com.volmit.iris.util.nbt.tag.CompoundTag;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.*;
|
||||||
import org.bukkit.World;
|
|
||||||
import org.bukkit.block.Biome;
|
import org.bukkit.block.Biome;
|
||||||
import org.bukkit.entity.Entity;
|
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.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 {
|
public class NMSBinding1X implements INMSBinding {
|
||||||
private static final boolean supportsCustomHeight = testCustomHeight();
|
private static final boolean supportsCustomHeight = testCustomHeight();
|
||||||
@@ -47,21 +62,85 @@ public class NMSBinding1X implements INMSBinding {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasTile(Material material) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasTile(Location l) {
|
public boolean hasTile(Location l) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompoundTag serializeTile(Location location) {
|
public KMap<String, Object> serializeTile(Location location) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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 IRegionStorage createRegionStorage(Engine engine) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@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 AutoClosing injectLevelStems() {
|
||||||
|
return new AutoClosing(() -> {});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Pair<Integer, AutoClosing> injectUncached(boolean overworld, boolean nether, boolean end) {
|
||||||
|
return new Pair<>(0, new AutoClosing(() -> {}));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean missingDimensionTypes(boolean overworld, boolean nether, boolean end) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompoundTag serializeEntity(Entity location) {
|
public CompoundTag serializeEntity(Entity location) {
|
||||||
return null;
|
return null;
|
||||||
@@ -117,6 +196,11 @@ public class NMSBinding1X implements INMSBinding {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getBiomeBaseIdForKey(String key) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getKeyForBiomeBase(Object biomeBase) {
|
public String getKeyForBiomeBase(Object biomeBase) {
|
||||||
return null;
|
return null;
|
||||||
@@ -131,6 +215,11 @@ public class NMSBinding1X implements INMSBinding {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public KList<Biome> getBiomes() {
|
||||||
|
return new KList<>(Biome.values()).qdel(Biome.CUSTOM);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isBukkit() {
|
public boolean isBukkit() {
|
||||||
return true;
|
return true;
|
||||||
@@ -165,6 +254,11 @@ public class NMSBinding1X implements INMSBinding {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Vector3d getBoundingbox(org.bukkit.entity.EntityType entity) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MCAPaletteAccess createPalette() {
|
public MCAPaletteAccess createPalette() {
|
||||||
Iris.error("Cannot use the global data palette! Iris is incapable of using MCA generation on this version of minecraft!");
|
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
|
* Create an iris pack backed by a data folder
|
||||||
* the data folder is assumed to be in the Iris/packs/NAME folder
|
* the data folder is assumed to be in the Iris/packs/NAME folder
|
||||||
*
|
*
|
||||||
* @param name
|
* @param name the name
|
||||||
* the name
|
|
||||||
*/
|
*/
|
||||||
public IrisPack(String name) {
|
public IrisPack(String name) {
|
||||||
this(packsPack(name));
|
this(packsPack(name));
|
||||||
@@ -64,8 +63,7 @@ public class IrisPack {
|
|||||||
/**
|
/**
|
||||||
* Create an iris pack backed by a data folder
|
* Create an iris pack backed by a data folder
|
||||||
*
|
*
|
||||||
* @param folder
|
* @param folder the folder of the pack. Must be a directory
|
||||||
* the folder of the pack. Must be a directory
|
|
||||||
*/
|
*/
|
||||||
public IrisPack(File folder) {
|
public IrisPack(File folder) {
|
||||||
this.folder = folder;
|
this.folder = folder;
|
||||||
@@ -84,13 +82,10 @@ public class IrisPack {
|
|||||||
/**
|
/**
|
||||||
* Create a new pack from the input url
|
* Create a new pack from the input url
|
||||||
*
|
*
|
||||||
* @param sender
|
* @param sender the sender
|
||||||
* the sender
|
* @param url the url, or name, or really anything see IrisPackRepository.from(String)
|
||||||
* @param url
|
|
||||||
* the url, or name, or really anything see IrisPackRepository.from(String)
|
|
||||||
* @return the iris pack
|
* @return the iris pack
|
||||||
* @throws IrisException
|
* @throws IrisException fails
|
||||||
* fails
|
|
||||||
*/
|
*/
|
||||||
public static Future<IrisPack> from(VolmitSender sender, String url) throws IrisException {
|
public static Future<IrisPack> from(VolmitSender sender, String url) throws IrisException {
|
||||||
IrisPackRepository repo = IrisPackRepository.from(url);
|
IrisPackRepository repo = IrisPackRepository.from(url);
|
||||||
@@ -108,13 +103,10 @@ public class IrisPack {
|
|||||||
/**
|
/**
|
||||||
* Create a pack from a repo
|
* Create a pack from a repo
|
||||||
*
|
*
|
||||||
* @param sender
|
* @param sender the sender
|
||||||
* the sender
|
* @param repo the repo
|
||||||
* @param repo
|
|
||||||
* the repo
|
|
||||||
* @return the pack
|
* @return the pack
|
||||||
* @throws MalformedURLException
|
* @throws MalformedURLException shit happens
|
||||||
* shit happens
|
|
||||||
*/
|
*/
|
||||||
public static Future<IrisPack> from(VolmitSender sender, IrisPackRepository repo) throws MalformedURLException {
|
public static Future<IrisPack> from(VolmitSender sender, IrisPackRepository repo) throws MalformedURLException {
|
||||||
CompletableFuture<IrisPack> pack = new CompletableFuture<>();
|
CompletableFuture<IrisPack> pack = new CompletableFuture<>();
|
||||||
@@ -127,11 +119,9 @@ public class IrisPack {
|
|||||||
/**
|
/**
|
||||||
* Create a blank pack with a given name
|
* Create a blank pack with a given name
|
||||||
*
|
*
|
||||||
* @param name
|
* @param name the name of the pack
|
||||||
* the name of the pack
|
|
||||||
* @return the pack
|
* @return the pack
|
||||||
* @throws IrisException
|
* @throws IrisException if the pack already exists or another error
|
||||||
* if the pack already exists or another error
|
|
||||||
*/
|
*/
|
||||||
public static IrisPack blank(String name) throws IrisException {
|
public static IrisPack blank(String name) throws IrisException {
|
||||||
File f = packsPack(name);
|
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
|
* Get a packs pack folder for a name. Such that overworld would resolve as Iris/packs/overworld
|
||||||
*
|
*
|
||||||
* @param name
|
* @param name the name
|
||||||
* the name
|
|
||||||
* @return the file path
|
* @return the file path
|
||||||
*/
|
*/
|
||||||
public static File packsPack(String name) {
|
public static File packsPack(String name) {
|
||||||
@@ -243,8 +232,7 @@ public class IrisPack {
|
|||||||
/**
|
/**
|
||||||
* Install this pack into a world
|
* Install this pack into a world
|
||||||
*
|
*
|
||||||
* @param world
|
* @param world the world to install into (world/iris/pack)
|
||||||
* the world to install into (world/iris/pack)
|
|
||||||
* @return the installed pack
|
* @return the installed pack
|
||||||
*/
|
*/
|
||||||
public IrisPack install(World world) throws IrisException {
|
public IrisPack install(World world) throws IrisException {
|
||||||
@@ -254,8 +242,7 @@ public class IrisPack {
|
|||||||
/**
|
/**
|
||||||
* Install this pack into a world
|
* Install this pack into a world
|
||||||
*
|
*
|
||||||
* @param world
|
* @param world the world to install into (world/iris/pack)
|
||||||
* the world to install into (world/iris/pack)
|
|
||||||
* @return the installed pack
|
* @return the installed pack
|
||||||
*/
|
*/
|
||||||
public IrisPack install(IrisWorld world) throws IrisException {
|
public IrisPack install(IrisWorld world) throws IrisException {
|
||||||
@@ -265,8 +252,7 @@ public class IrisPack {
|
|||||||
/**
|
/**
|
||||||
* Install this pack into a world
|
* Install this pack into a world
|
||||||
*
|
*
|
||||||
* @param folder
|
* @param folder the folder to install this pack into
|
||||||
* the folder to install this pack into
|
|
||||||
* @return the installed pack
|
* @return the installed pack
|
||||||
*/
|
*/
|
||||||
public IrisPack install(File folder) throws IrisException {
|
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
|
* Create a new pack using this pack as a template. The new pack will be renamed & have a renamed dimension
|
||||||
* to match it.
|
* to match it.
|
||||||
*
|
*
|
||||||
* @param newName
|
* @param newName the new pack name
|
||||||
* the new pack name
|
|
||||||
* @return the new IrisPack
|
* @return the new IrisPack
|
||||||
*/
|
*/
|
||||||
public IrisPack install(String newName) throws IrisException {
|
public IrisPack install(String newName) throws IrisException {
|
||||||
@@ -345,8 +330,7 @@ public class IrisPack {
|
|||||||
/**
|
/**
|
||||||
* Find all files in this pack with the given extension
|
* Find all files in this pack with the given extension
|
||||||
*
|
*
|
||||||
* @param fileExtension
|
* @param fileExtension the extension
|
||||||
* the extension
|
|
||||||
* @return the list of files
|
* @return the list of files
|
||||||
*/
|
*/
|
||||||
public KList<File> collectFiles(String fileExtension) {
|
public KList<File> collectFiles(String fileExtension) {
|
||||||
@@ -0,0 +1,361 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
|
if (!new File(world.getWorldFolder(), "region" + File.separator + rX + "." + rZ + ".mca").exists()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
task.iterateChunks(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()
|
||||||
|
.radiusZ((int) Math.ceil(width / 2d * 512))
|
||||||
|
.radiusX((int) Math.ceil(height / 2d * 512))
|
||||||
|
.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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
package com.volmit.iris.core.pregenerator;
|
||||||
|
|
||||||
|
public class EmptyListener implements PregenListener {
|
||||||
|
public static PregenListener INSTANCE = new EmptyListener();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTick(double chunksPerSecond, double chunksPerMinute, double regionsPerMinute, double percent, int generated, int totalChunks, int chunksRemaining, long eta, long elapsed, String method) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onChunkGenerating(int x, int z) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onChunkGenerated(int x, int z) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRegionGenerated(int x, int z) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRegionGenerating(int x, int z) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onChunkCleaned(int x, int z) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRegionSkipped(int x, int z) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNetworkStarted(int x, int z) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNetworkFailed(int x, int z) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNetworkReclaim(int revert) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNetworkGeneratedChunk(int x, int z) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNetworkDownloaded(int x, int z) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClose() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSaving() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onChunkExistsInRegionGen(int x, int z) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,7 +19,10 @@
|
|||||||
package com.volmit.iris.core.pregenerator;
|
package com.volmit.iris.core.pregenerator;
|
||||||
|
|
||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.Iris;
|
||||||
|
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.collection.KSet;
|
||||||
|
import com.volmit.iris.util.format.C;
|
||||||
import com.volmit.iris.util.format.Form;
|
import com.volmit.iris.util.format.Form;
|
||||||
import com.volmit.iris.util.mantle.Mantle;
|
import com.volmit.iris.util.mantle.Mantle;
|
||||||
import com.volmit.iris.util.math.M;
|
import com.volmit.iris.util.math.M;
|
||||||
@@ -34,6 +37,7 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
|
|
||||||
public class IrisPregenerator {
|
public class IrisPregenerator {
|
||||||
private final PregenTask task;
|
private final PregenTask task;
|
||||||
private final PregeneratorMethod generator;
|
private final PregeneratorMethod generator;
|
||||||
@@ -44,10 +48,11 @@ public class IrisPregenerator {
|
|||||||
private final RollingSequence chunksPerSecond;
|
private final RollingSequence chunksPerSecond;
|
||||||
private final RollingSequence chunksPerMinute;
|
private final RollingSequence chunksPerMinute;
|
||||||
private final RollingSequence regionsPerMinute;
|
private final RollingSequence regionsPerMinute;
|
||||||
private final AtomicInteger generated;
|
private final KList<Integer> chunksPerSecondHistory;
|
||||||
|
private static AtomicInteger generated;
|
||||||
private final AtomicInteger generatedLast;
|
private final AtomicInteger generatedLast;
|
||||||
private final AtomicInteger generatedLastMinute;
|
private final AtomicInteger generatedLastMinute;
|
||||||
private final AtomicInteger totalChunks;
|
private static AtomicInteger totalChunks;
|
||||||
private final AtomicLong startTime;
|
private final AtomicLong startTime;
|
||||||
private final ChronoLatch minuteLatch;
|
private final ChronoLatch minuteLatch;
|
||||||
private final AtomicReference<String> currentGeneratorMethod;
|
private final AtomicReference<String> currentGeneratorMethod;
|
||||||
@@ -55,6 +60,7 @@ public class IrisPregenerator {
|
|||||||
private final KSet<Position2> retry;
|
private final KSet<Position2> retry;
|
||||||
private final KSet<Position2> net;
|
private final KSet<Position2> net;
|
||||||
private final ChronoLatch cl;
|
private final ChronoLatch cl;
|
||||||
|
private final ChronoLatch saveLatch = new ChronoLatch(30000);
|
||||||
|
|
||||||
public IrisPregenerator(PregenTask task, PregeneratorMethod generator, PregenListener listener) {
|
public IrisPregenerator(PregenTask task, PregeneratorMethod generator, PregenListener listener) {
|
||||||
this.listener = listenify(listener);
|
this.listener = listenify(listener);
|
||||||
@@ -71,11 +77,12 @@ public class IrisPregenerator {
|
|||||||
chunksPerSecond = new RollingSequence(10);
|
chunksPerSecond = new RollingSequence(10);
|
||||||
chunksPerMinute = new RollingSequence(10);
|
chunksPerMinute = new RollingSequence(10);
|
||||||
regionsPerMinute = new RollingSequence(10);
|
regionsPerMinute = new RollingSequence(10);
|
||||||
|
chunksPerSecondHistory = new KList<>();
|
||||||
generated = new AtomicInteger(0);
|
generated = new AtomicInteger(0);
|
||||||
generatedLast = new AtomicInteger(0);
|
generatedLast = new AtomicInteger(0);
|
||||||
generatedLastMinute = new AtomicInteger(0);
|
generatedLastMinute = new AtomicInteger(0);
|
||||||
totalChunks = new AtomicInteger(0);
|
totalChunks = new AtomicInteger(0);
|
||||||
task.iterateRegions((_a, _b) -> totalChunks.addAndGet(1024));
|
task.iterateAllChunks((_a, _b) -> totalChunks.incrementAndGet());
|
||||||
startTime = new AtomicLong(M.ms());
|
startTime = new AtomicLong(M.ms());
|
||||||
ticker = new Looper() {
|
ticker = new Looper() {
|
||||||
@Override
|
@Override
|
||||||
@@ -84,6 +91,7 @@ public class IrisPregenerator {
|
|||||||
int secondGenerated = generated.get() - generatedLast.get();
|
int secondGenerated = generated.get() - generatedLast.get();
|
||||||
generatedLast.set(generated.get());
|
generatedLast.set(generated.get());
|
||||||
chunksPerSecond.put(secondGenerated);
|
chunksPerSecond.put(secondGenerated);
|
||||||
|
chunksPerSecondHistory.add(secondGenerated);
|
||||||
|
|
||||||
if (minuteLatch.flip()) {
|
if (minuteLatch.flip()) {
|
||||||
int minuteGenerated = generated.get() - generatedLastMinute.get();
|
int minuteGenerated = generated.get() - generatedLastMinute.get();
|
||||||
@@ -100,19 +108,28 @@ public class IrisPregenerator {
|
|||||||
eta, M.ms() - startTime.get(), currentGeneratorMethod.get());
|
eta, M.ms() - startTime.get(), currentGeneratorMethod.get());
|
||||||
|
|
||||||
if (cl.flip()) {
|
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;
|
return 1000;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private long computeETA() {
|
private long computeETA() {
|
||||||
return (long) ((totalChunks.get() - generated.get()) *
|
return (long) (totalChunks.get() > 1024 ? // Generated chunks exceed 1/8th of total?
|
||||||
((double) (M.ms() - startTime.get()) / (double) generated.get()));
|
// 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() {
|
public void close() {
|
||||||
shutdown.set(true);
|
shutdown.set(true);
|
||||||
}
|
}
|
||||||
@@ -124,6 +141,11 @@ public class IrisPregenerator {
|
|||||||
task.iterateRegions((x, z) -> visitRegion(x, z, true));
|
task.iterateRegions((x, z) -> visitRegion(x, z, true));
|
||||||
task.iterateRegions((x, z) -> visitRegion(x, z, false));
|
task.iterateRegions((x, z) -> visitRegion(x, z, false));
|
||||||
shutdown();
|
shutdown();
|
||||||
|
if (!IrisPackBenchmarking.benchmarkInProgress) {
|
||||||
|
Iris.info(C.IRIS + "Pregen stopped.");
|
||||||
|
} else {
|
||||||
|
IrisPackBenchmarking.instance.finishedBenchmark(chunksPerSecondHistory);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkRegions() {
|
private void checkRegions() {
|
||||||
@@ -140,6 +162,10 @@ public class IrisPregenerator {
|
|||||||
generator.close();
|
generator.close();
|
||||||
ticker.interrupt();
|
ticker.interrupt();
|
||||||
listener.onClose();
|
listener.onClose();
|
||||||
|
Mantle mantle = getMantle();
|
||||||
|
if (mantle != null) {
|
||||||
|
mantle.trim(0, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void visitRegion(int x, int z, boolean regions) {
|
private void visitRegion(int x, int z, boolean regions) {
|
||||||
@@ -167,13 +193,23 @@ public class IrisPregenerator {
|
|||||||
} else if (!regions) {
|
} else if (!regions) {
|
||||||
hit = true;
|
hit = true;
|
||||||
listener.onRegionGenerating(x, z);
|
listener.onRegionGenerating(x, z);
|
||||||
PregenTask.iterateRegion(x, z, (xx, zz) -> generator.generateChunk(xx, zz, listener));
|
task.iterateChunks(x, z, (xx, zz) -> {
|
||||||
|
while (paused.get() && !shutdown.get()) {
|
||||||
|
J.sleep(50);
|
||||||
|
}
|
||||||
|
|
||||||
|
generator.generateChunk(xx, zz, listener);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hit) {
|
if (hit) {
|
||||||
listener.onRegionGenerated(x, z);
|
listener.onRegionGenerated(x, z);
|
||||||
|
|
||||||
|
if (saveLatch.flip()) {
|
||||||
listener.onSaving();
|
listener.onSaving();
|
||||||
generator.save();
|
generator.save();
|
||||||
|
}
|
||||||
|
|
||||||
generatedRegions.add(pos);
|
generatedRegions.add(pos);
|
||||||
checkRegions();
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,150 @@
|
|||||||
|
/*
|
||||||
|
* 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.pregenerator;
|
||||||
|
|
||||||
|
import com.volmit.iris.util.collection.KList;
|
||||||
|
import com.volmit.iris.util.collection.KMap;
|
||||||
|
import com.volmit.iris.util.math.Position2;
|
||||||
|
import com.volmit.iris.util.math.Spiraled;
|
||||||
|
import com.volmit.iris.util.math.Spiraler;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
|
||||||
|
@Builder
|
||||||
|
@Data
|
||||||
|
public class PregenTask {
|
||||||
|
private static final Position2 ZERO = new Position2(0, 0);
|
||||||
|
private static final KMap<Position2, KList<Position2>> ORDERS = new KMap<>();
|
||||||
|
|
||||||
|
@Builder.Default
|
||||||
|
private final boolean gui = false;
|
||||||
|
@Builder.Default
|
||||||
|
private final Position2 center = new Position2(0, 0);
|
||||||
|
@Builder.Default
|
||||||
|
private final int radiusX = 1;
|
||||||
|
@Builder.Default
|
||||||
|
private final int radiusZ = 1;
|
||||||
|
|
||||||
|
private final Bounds bounds = new Bounds();
|
||||||
|
|
||||||
|
protected PregenTask(boolean gui, Position2 center, int radiusX, int radiusZ) {
|
||||||
|
this.gui = gui;
|
||||||
|
this.center = new ProxiedPos(center);
|
||||||
|
this.radiusX = radiusX;
|
||||||
|
this.radiusZ = radiusZ;
|
||||||
|
bounds.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void iterateRegion(int xr, int zr, Spiraled s, Position2 pull) {
|
||||||
|
for (Position2 i : ORDERS.computeIfAbsent(pull, PregenTask::computeOrder)) {
|
||||||
|
s.on(i.getX() + (xr << 5), i.getZ() + (zr << 5));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void iterateRegion(int xr, int zr, Spiraled s) {
|
||||||
|
iterateRegion(xr, zr, s, new Position2(-(xr << 5), -(zr << 5)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static KList<Position2> computeOrder(Position2 pull) {
|
||||||
|
KList<Position2> p = new KList<>();
|
||||||
|
new Spiraler(33, 33, (x, z) -> {
|
||||||
|
int xx = (x + 15);
|
||||||
|
int zz = (z + 15);
|
||||||
|
if (xx < 0 || xx > 31 || zz < 0 || zz > 31) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.add(new Position2(xx, zz));
|
||||||
|
}).drain();
|
||||||
|
p.sort(Comparator.comparing((i) -> i.distance(pull)));
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void iterateRegions(Spiraled s) {
|
||||||
|
var bound = bounds.region();
|
||||||
|
new Spiraler(bound.sizeX, bound.sizeZ, ((x, z) -> {
|
||||||
|
if (bound.check(x, z)) s.on(x, z);
|
||||||
|
})).setOffset(center.getX() >> 9, center.getZ() >> 9).drain();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void iterateChunks(int rX, int rZ, Spiraled s) {
|
||||||
|
var bound = bounds.chunk();
|
||||||
|
iterateRegion(rX, rZ, ((x, z) -> {
|
||||||
|
if (bound.check(x, z)) s.on(x, z);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void iterateAllChunks(Spiraled s) {
|
||||||
|
iterateRegions(((rX, rZ) -> iterateChunks(rX, rZ, s)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Bounds {
|
||||||
|
private Bound chunk = null;
|
||||||
|
private Bound region = null;
|
||||||
|
|
||||||
|
public void update() {
|
||||||
|
int maxX = center.getX() + radiusX;
|
||||||
|
int maxZ = center.getZ() + radiusZ;
|
||||||
|
int minX = center.getX() - radiusX;
|
||||||
|
int minZ = center.getZ() - radiusZ;
|
||||||
|
|
||||||
|
chunk = new Bound(minX >> 4, minZ >> 4, Math.ceilDiv(maxX, 16), Math.ceilDiv(maxZ, 16));
|
||||||
|
region = new Bound(minX >> 9, minZ >> 9, Math.ceilDiv(maxX, 512), Math.ceilDiv(maxZ, 512));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Bound chunk() {
|
||||||
|
if (chunk == null) update();
|
||||||
|
return chunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Bound region() {
|
||||||
|
if (region == null) update();
|
||||||
|
return region;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private record Bound(int minX, int maxX, int minZ, int maxZ, int sizeX, int sizeZ) {
|
||||||
|
private Bound(int minX, int minZ, int maxX, int maxZ) {
|
||||||
|
this(minX, maxX, minZ, maxZ, maxZ - minZ + 1, maxZ - minZ + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean check(int x, int z) {
|
||||||
|
return x >= minX && x <= maxX && z >= minZ && z <= maxZ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ProxiedPos extends Position2 {
|
||||||
|
public ProxiedPos(Position2 p) {
|
||||||
|
super(p.getX(), p.getZ());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setX(int x) {
|
||||||
|
throw new IllegalStateException("This Position2 may not be modified");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setZ(int z) {
|
||||||
|
throw new IllegalStateException("This Position2 may not be modified");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -43,10 +43,8 @@ public interface PregeneratorMethod {
|
|||||||
/**
|
/**
|
||||||
* Return true if regions can be generated
|
* Return true if regions can be generated
|
||||||
*
|
*
|
||||||
* @param x
|
* @param x the x region
|
||||||
* the x region
|
* @param z the z region
|
||||||
* @param z
|
|
||||||
* the z region
|
|
||||||
* @return true if they can be
|
* @return true if they can be
|
||||||
*/
|
*/
|
||||||
boolean supportsRegions(int x, int z, PregenListener listener);
|
boolean supportsRegions(int x, int z, PregenListener listener);
|
||||||
@@ -54,10 +52,8 @@ public interface PregeneratorMethod {
|
|||||||
/**
|
/**
|
||||||
* Return the name of the method being used
|
* Return the name of the method being used
|
||||||
*
|
*
|
||||||
* @param x
|
* @param x the x region
|
||||||
* the x region
|
* @param z the z region
|
||||||
* @param z
|
|
||||||
* the z region
|
|
||||||
* @return the name
|
* @return the name
|
||||||
*/
|
*/
|
||||||
String getMethod(int x, int z);
|
String getMethod(int x, int z);
|
||||||
@@ -66,22 +62,17 @@ public interface PregeneratorMethod {
|
|||||||
* Called to generate a region. Execute sync, if multicore internally, wait
|
* Called to generate a region. Execute sync, if multicore internally, wait
|
||||||
* for the task to complete
|
* for the task to complete
|
||||||
*
|
*
|
||||||
* @param x
|
* @param x the x
|
||||||
* the x
|
* @param z the z
|
||||||
* @param z
|
* @param listener signal chunks generating & generated. Parallel capable.
|
||||||
* the z
|
|
||||||
* @param listener
|
|
||||||
* signal chunks generating & generated. Parallel capable.
|
|
||||||
*/
|
*/
|
||||||
void generateRegion(int x, int z, PregenListener listener);
|
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
|
* Called to generate a chunk. You can go async so long as save will wait on the threads to finish
|
||||||
*
|
*
|
||||||
* @param x
|
* @param x the x
|
||||||
* the x
|
* @param z the z
|
||||||
* @param z
|
|
||||||
* the z
|
|
||||||
*/
|
*/
|
||||||
void generateChunk(int x, int z, PregenListener listener);
|
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;
|
package com.volmit.iris.core.pregenerator.methods;
|
||||||
|
|
||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.Iris;
|
||||||
import com.volmit.iris.core.IrisSettings;
|
|
||||||
import com.volmit.iris.core.pregenerator.PregenListener;
|
import com.volmit.iris.core.pregenerator.PregenListener;
|
||||||
import com.volmit.iris.core.pregenerator.PregeneratorMethod;
|
import com.volmit.iris.core.pregenerator.PregeneratorMethod;
|
||||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
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.mantle.Mantle;
|
||||||
|
import com.volmit.iris.util.math.M;
|
||||||
import com.volmit.iris.util.parallel.MultiBurst;
|
import com.volmit.iris.util.parallel.MultiBurst;
|
||||||
import com.volmit.iris.util.scheduling.J;
|
import com.volmit.iris.util.scheduling.J;
|
||||||
import io.papermc.lib.PaperLib;
|
import io.papermc.lib.PaperLib;
|
||||||
import org.bukkit.Chunk;
|
import org.bukkit.Chunk;
|
||||||
import org.bukkit.World;
|
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 {
|
public class AsyncPregenMethod implements PregeneratorMethod {
|
||||||
private final World world;
|
private final World world;
|
||||||
private final MultiBurst burst;
|
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) {
|
public AsyncPregenMethod(World world, int threads) {
|
||||||
if (!PaperLib.isPaper()) {
|
if (!PaperLib.isPaper()) {
|
||||||
@@ -44,8 +47,9 @@ public class AsyncPregenMethod implements PregeneratorMethod {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.world = world;
|
this.world = world;
|
||||||
burst = MultiBurst.burst;
|
burst = new MultiBurst("Iris Async Pregen", Thread.MIN_PRIORITY);
|
||||||
future = new KList<>(1024);
|
semaphore = new Semaphore(256);
|
||||||
|
this.lastUse = new KMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void unloadAndSaveAllChunks() {
|
private void unloadAndSaveAllChunks() {
|
||||||
@@ -56,8 +60,12 @@ public class AsyncPregenMethod implements PregeneratorMethod {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(Chunk i : world.getLoadedChunks()) {
|
for (Chunk i : new ArrayList<>(lastUse.keySet())) {
|
||||||
i.unload(true);
|
Long lastUseTime = lastUse.get(i);
|
||||||
|
if (!i.isLoaded() || (lastUseTime != null && M.ms() - lastUseTime >= 10000)) {
|
||||||
|
i.unload();
|
||||||
|
lastUse.remove(i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
world.save();
|
world.save();
|
||||||
}).get();
|
}).get();
|
||||||
@@ -68,24 +76,16 @@ public class AsyncPregenMethod implements PregeneratorMethod {
|
|||||||
|
|
||||||
private void completeChunk(int x, int z, PregenListener listener) {
|
private void completeChunk(int x, int z, PregenListener listener) {
|
||||||
try {
|
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.onChunkGenerated(x, z);
|
||||||
listener.onChunkCleaned(x, z);
|
listener.onChunkCleaned(x, z);
|
||||||
|
}).get();
|
||||||
|
} catch (InterruptedException ignored) {
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
J.sleep(5);
|
} finally {
|
||||||
future.add(burst.complete(() -> completeChunk(x, z, listener)));
|
semaphore.release();
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void waitForChunks() {
|
|
||||||
for(Future<?> i : future.copy()) {
|
|
||||||
try {
|
|
||||||
i.get();
|
|
||||||
future.remove(i);
|
|
||||||
} catch(Throwable e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,13 +101,13 @@ public class AsyncPregenMethod implements PregeneratorMethod {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {
|
||||||
waitForChunks();
|
semaphore.acquireUninterruptibly(256);
|
||||||
unloadAndSaveAllChunks();
|
unloadAndSaveAllChunks();
|
||||||
|
burst.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void save() {
|
public void save() {
|
||||||
waitForChunks();
|
|
||||||
unloadAndSaveAllChunks();
|
unloadAndSaveAllChunks();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,12 +123,13 @@ public class AsyncPregenMethod implements PregeneratorMethod {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void generateChunk(int x, int z, PregenListener listener) {
|
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);
|
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
|
@Override
|
||||||
@@ -0,0 +1,112 @@
|
|||||||
|
/*
|
||||||
|
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||||
|
* Copyright (c) 2024 Arcane Arts (Volmit Software)
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.volmit.iris.core.pregenerator.methods;
|
||||||
|
|
||||||
|
import com.volmit.iris.Iris;
|
||||||
|
import com.volmit.iris.core.IrisSettings;
|
||||||
|
import com.volmit.iris.core.pregenerator.PregenListener;
|
||||||
|
import com.volmit.iris.core.pregenerator.PregeneratorMethod;
|
||||||
|
import com.volmit.iris.engine.framework.Engine;
|
||||||
|
import com.volmit.iris.engine.object.IrisHeadless;
|
||||||
|
import com.volmit.iris.util.mantle.Mantle;
|
||||||
|
import com.volmit.iris.util.parallel.MultiBurst;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.concurrent.Semaphore;
|
||||||
|
|
||||||
|
public class HeadlessPregenMethod implements PregeneratorMethod {
|
||||||
|
private final Engine engine;
|
||||||
|
private final IrisHeadless headless;
|
||||||
|
private final Semaphore semaphore;
|
||||||
|
private final int max;
|
||||||
|
private final MultiBurst burst;
|
||||||
|
|
||||||
|
public HeadlessPregenMethod(Engine engine) {
|
||||||
|
this(engine, IrisSettings.getThreadCount(IrisSettings.get().getConcurrency().getParallelism()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public HeadlessPregenMethod(Engine engine, int threads) {
|
||||||
|
this.max = Math.max(threads, 4);
|
||||||
|
this.engine = engine;
|
||||||
|
this.headless = new IrisHeadless(engine);
|
||||||
|
burst = new MultiBurst("HeadlessPregen", 8);
|
||||||
|
this.semaphore = new Semaphore(max);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
try {
|
||||||
|
semaphore.acquire(max);
|
||||||
|
} catch (InterruptedException ignored) {
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
headless.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
Iris.error("Failed to close headless");
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
burst.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void save() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supportsRegions(int x, int z, PregenListener listener) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getMethod(int x, int z) {
|
||||||
|
return "Headless";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void generateRegion(int x, int z, PregenListener listener) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void generateChunk(int x, int z, PregenListener listener) {
|
||||||
|
try {
|
||||||
|
semaphore.acquire();
|
||||||
|
} catch (InterruptedException ignored) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
burst.complete(() -> {
|
||||||
|
try {
|
||||||
|
listener.onChunkGenerating(x, z);
|
||||||
|
headless.generateChunk(x, z);
|
||||||
|
listener.onChunkGenerated(x, z);
|
||||||
|
} finally {
|
||||||
|
semaphore.release();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Mantle getMantle() {
|
||||||
|
return engine.getMantle().getMantle();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,17 +18,11 @@
|
|||||||
|
|
||||||
package com.volmit.iris.core.pregenerator.methods;
|
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.PregenListener;
|
||||||
import com.volmit.iris.core.pregenerator.PregeneratorMethod;
|
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.mantle.Mantle;
|
||||||
import com.volmit.iris.util.math.Position2;
|
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
|
|
||||||
public class HybridPregenMethod implements PregeneratorMethod {
|
public class HybridPregenMethod implements PregeneratorMethod {
|
||||||
private final PregeneratorMethod inWorld;
|
private final PregeneratorMethod inWorld;
|
||||||
private final World world;
|
private final World world;
|
||||||
@@ -18,25 +18,33 @@
|
|||||||
|
|
||||||
package com.volmit.iris.core.pregenerator.methods;
|
package com.volmit.iris.core.pregenerator.methods;
|
||||||
|
|
||||||
|
import com.volmit.iris.Iris;
|
||||||
import com.volmit.iris.core.IrisSettings;
|
import com.volmit.iris.core.IrisSettings;
|
||||||
import com.volmit.iris.core.pregenerator.PregenListener;
|
import com.volmit.iris.core.pregenerator.PregenListener;
|
||||||
import com.volmit.iris.core.pregenerator.PregeneratorMethod;
|
import com.volmit.iris.core.pregenerator.PregeneratorMethod;
|
||||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||||
import com.volmit.iris.util.collection.KList;
|
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.mantle.Mantle;
|
||||||
|
import com.volmit.iris.util.math.M;
|
||||||
import com.volmit.iris.util.scheduling.J;
|
import com.volmit.iris.util.scheduling.J;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Chunk;
|
import org.bukkit.Chunk;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
public class MedievalPregenMethod implements PregeneratorMethod {
|
public class MedievalPregenMethod implements PregeneratorMethod {
|
||||||
private final World world;
|
private final World world;
|
||||||
private final KList<CompletableFuture<?>> futures;
|
private final KList<CompletableFuture<?>> futures;
|
||||||
|
private final Map<Chunk, Long> lastUse;
|
||||||
|
|
||||||
public MedievalPregenMethod(World world) {
|
public MedievalPregenMethod(World world) {
|
||||||
this.world = world;
|
this.world = world;
|
||||||
futures = new KList<>();
|
futures = new KList<>();
|
||||||
|
this.lastUse = new KMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void waitForChunks() {
|
private void waitForChunks() {
|
||||||
@@ -52,11 +60,19 @@ public class MedievalPregenMethod implements PregeneratorMethod {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void unloadAndSaveAllChunks() {
|
private void unloadAndSaveAllChunks() {
|
||||||
waitForChunks();
|
|
||||||
try {
|
try {
|
||||||
J.sfut(() -> {
|
J.sfut(() -> {
|
||||||
for(Chunk i : world.getLoadedChunks()) {
|
if (world == null) {
|
||||||
i.unload(true);
|
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();
|
world.save();
|
||||||
}).get();
|
}).get();
|
||||||
@@ -104,6 +120,8 @@ public class MedievalPregenMethod implements PregeneratorMethod {
|
|||||||
listener.onChunkGenerating(x, z);
|
listener.onChunkGenerating(x, z);
|
||||||
futures.add(J.sfut(() -> {
|
futures.add(J.sfut(() -> {
|
||||||
world.getChunkAt(x, z);
|
world.getChunkAt(x, z);
|
||||||
|
Chunk c = Bukkit.getWorld(world.getUID()).getChunkAt(x, z);
|
||||||
|
lastUse.put(c, M.ms());
|
||||||
listener.onChunkGenerated(x, z);
|
listener.onChunkGenerated(x, z);
|
||||||
listener.onChunkCleaned(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.IrisRegistrant;
|
||||||
import com.volmit.iris.core.loader.ResourceLoader;
|
import com.volmit.iris.core.loader.ResourceLoader;
|
||||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||||
import com.volmit.iris.engine.object.IrisBiome;
|
import com.volmit.iris.engine.object.*;
|
||||||
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.annotations.Snippet;
|
import com.volmit.iris.engine.object.annotations.Snippet;
|
||||||
import com.volmit.iris.engine.platform.PlatformChunkGenerator;
|
import com.volmit.iris.engine.platform.PlatformChunkGenerator;
|
||||||
import com.volmit.iris.util.collection.KList;
|
import com.volmit.iris.util.collection.KList;
|
||||||
@@ -60,8 +51,7 @@ import org.bukkit.GameMode;
|
|||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.zeroturnaround.zip.ZipUtil;
|
import org.zeroturnaround.zip.ZipUtil;
|
||||||
|
|
||||||
import java.awt.Desktop;
|
import java.awt.*;
|
||||||
import java.awt.GraphicsEnvironment;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Objects;
|
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.IrisData;
|
||||||
import com.volmit.iris.core.loader.IrisRegistrant;
|
import com.volmit.iris.core.loader.IrisRegistrant;
|
||||||
import com.volmit.iris.core.loader.ResourceLoader;
|
import com.volmit.iris.core.loader.ResourceLoader;
|
||||||
import com.volmit.iris.engine.object.annotations.ArrayType;
|
import com.volmit.iris.engine.object.annotations.*;
|
||||||
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.util.collection.KList;
|
import com.volmit.iris.util.collection.KList;
|
||||||
import com.volmit.iris.util.collection.KMap;
|
import com.volmit.iris.util.collection.KMap;
|
||||||
import com.volmit.iris.util.data.B;
|
import com.volmit.iris.util.data.B;
|
||||||
import com.volmit.iris.util.json.JSONArray;
|
import com.volmit.iris.util.json.JSONArray;
|
||||||
import com.volmit.iris.util.json.JSONObject;
|
import com.volmit.iris.util.json.JSONObject;
|
||||||
|
import com.volmit.iris.util.reflect.OldEnum;
|
||||||
import org.bukkit.enchantments.Enchantment;
|
import org.bukkit.enchantments.Enchantment;
|
||||||
import org.bukkit.potion.PotionEffectType;
|
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.Field;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class SchemaBuilder {
|
public class SchemaBuilder {
|
||||||
private static final String SYMBOL_LIMIT__N = "*";
|
private static final String SYMBOL_LIMIT__N = "*";
|
||||||
private static final String SYMBOL_TYPE__N = "";
|
private static final String SYMBOL_TYPE__N = "";
|
||||||
private static final JSONArray POTION_TYPES = getPotionTypes();
|
private static final JSONArray POTION_TYPES = getPotionTypes();
|
||||||
private static final JSONArray ENCHANT_TYPES = getEnchantmentTypes();
|
private static final JSONArray ENCHANT_TYPES = getEnchantTypes();
|
||||||
private static final JSONArray ITEM_TYPES = new JSONArray(B.getItemTypes());
|
|
||||||
private static final JSONArray FONT_TYPES = new JSONArray(GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames());
|
private static final JSONArray FONT_TYPES = new JSONArray(GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames());
|
||||||
private final KMap<String, JSONObject> definitions;
|
private final KMap<String, JSONObject> definitions;
|
||||||
private final Class<?> root;
|
private final Class<?> root;
|
||||||
@@ -67,16 +59,6 @@ public class SchemaBuilder {
|
|||||||
this.root = root;
|
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() {
|
private static JSONArray getPotionTypes() {
|
||||||
JSONArray a = new JSONArray();
|
JSONArray a = new JSONArray();
|
||||||
|
|
||||||
@@ -87,6 +69,14 @@ public class SchemaBuilder {
|
|||||||
return a;
|
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() {
|
public JSONObject construct() {
|
||||||
JSONObject schema = new JSONObject();
|
JSONObject schema = new JSONObject();
|
||||||
schema.put("$schema", "http://json-schema.org/draft-07/schema#");
|
schema.put("$schema", "http://json-schema.org/draft-07/schema#");
|
||||||
@@ -273,7 +263,7 @@ public class SchemaBuilder {
|
|||||||
|
|
||||||
if (!definitions.containsKey(key)) {
|
if (!definitions.containsKey(key)) {
|
||||||
JSONObject j = new JSONObject();
|
JSONObject j = new JSONObject();
|
||||||
j.put("enum", ITEM_TYPES);
|
j.put("enum", B.getItemTypes());
|
||||||
definitions.put(key, j);
|
definitions.put(key, j);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -309,7 +299,7 @@ public class SchemaBuilder {
|
|||||||
prop.put("$ref", "#/definitions/" + key);
|
prop.put("$ref", "#/definitions/" + key);
|
||||||
description.add(SYMBOL_TYPE__N + " Must be a valid Font Family (use ctrl+space for auto complete!)");
|
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";
|
String key = "enum-enchantment";
|
||||||
|
|
||||||
if (!definitions.containsKey(key)) {
|
if (!definitions.containsKey(key)) {
|
||||||
@@ -321,6 +311,24 @@ public class SchemaBuilder {
|
|||||||
fancyType = "Enchantment Type";
|
fancyType = "Enchantment Type";
|
||||||
prop.put("$ref", "#/definitions/" + key);
|
prop.put("$ref", "#/definitions/" + key);
|
||||||
description.add(SYMBOL_TYPE__N + " Must be a valid Enchantment Type (use ctrl+space for auto complete!)");
|
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)) {
|
} else if (k.getType().equals(PotionEffectType.class)) {
|
||||||
String key = "enum-potion-effect-type";
|
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!)");
|
description.add(SYMBOL_TYPE__N + " Must be a valid Potion Effect Type (use ctrl+space for auto complete!)");
|
||||||
|
|
||||||
} else if (k.getType().isEnum()) {
|
} else if (k.getType().isEnum()) {
|
||||||
fancyType = k.getType().getSimpleName().replaceAll("\\QIris\\E", "");
|
fancyType = addEnum(k.getType(), prop, description, k.getType().getEnumConstants(), o -> ((Enum<?>) o).name());
|
||||||
JSONArray a = new JSONArray();
|
} else if (OldEnum.isOldEnum(k.getType())) {
|
||||||
boolean advanced = k.getType().isAnnotationPresent(Desc.class);
|
fancyType = addEnum(k.getType(), prop, description, OldEnum.values(k.getType()), OldEnum::name);
|
||||||
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!)");
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case "object" -> {
|
case "object" -> {
|
||||||
@@ -461,7 +440,7 @@ public class SchemaBuilder {
|
|||||||
|
|
||||||
if (!definitions.containsKey(key)) {
|
if (!definitions.containsKey(key)) {
|
||||||
JSONObject j = new JSONObject();
|
JSONObject j = new JSONObject();
|
||||||
j.put("enum", ITEM_TYPES);
|
j.put("enum", B.getItemTypes());
|
||||||
definitions.put(key, j);
|
definitions.put(key, j);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -483,7 +462,7 @@ public class SchemaBuilder {
|
|||||||
items.put("$ref", "#/definitions/" + key);
|
items.put("$ref", "#/definitions/" + key);
|
||||||
prop.put("items", items);
|
prop.put("items", items);
|
||||||
description.add(SYMBOL_TYPE__N + " Must be a valid Font Family (use ctrl+space for auto complete!)");
|
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";
|
fancyType = "List of Enchantment Types";
|
||||||
String key = "enum-enchantment";
|
String key = "enum-enchantment";
|
||||||
|
|
||||||
@@ -512,39 +491,9 @@ public class SchemaBuilder {
|
|||||||
prop.put("items", items);
|
prop.put("items", items);
|
||||||
description.add(SYMBOL_TYPE__N + " Must be a valid Potion Effect Type (use ctrl+space for auto complete!)");
|
description.add(SYMBOL_TYPE__N + " Must be a valid Potion Effect Type (use ctrl+space for auto complete!)");
|
||||||
} else if (t.type().isEnum()) {
|
} else if (t.type().isEnum()) {
|
||||||
fancyType = "List of " + t.type().getSimpleName().replaceAll("\\QIris\\E", "") + "s";
|
fancyType = addEnumList(prop, description, t, t.type().getEnumConstants(), o -> ((Enum<?>) o).name());
|
||||||
JSONArray a = new JSONArray();
|
} else if (OldEnum.isOldEnum(t.type())) {
|
||||||
boolean advanced = t.type().isAnnotationPresent(Desc.class);
|
fancyType = addEnumList(prop, description, t, OldEnum.values(t.type()), OldEnum::name);
|
||||||
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!)");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -552,7 +501,8 @@ public class SchemaBuilder {
|
|||||||
warnings.add("Undefined array type for field " + k.getName() + " (" + k.getType().getSimpleName() + ") in class " + cl.getSimpleName());
|
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<>();
|
KList<String> d = new KList<>();
|
||||||
@@ -576,7 +526,7 @@ public class SchemaBuilder {
|
|||||||
if (value instanceof List) {
|
if (value instanceof List) {
|
||||||
d.add(" ");
|
d.add(" ");
|
||||||
d.add("* Default Value is an empty list");
|
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(" ");
|
||||||
d.add("* Default Value is a default object (create this object to see default properties)");
|
d.add("* Default Value is a default object (create this object to see default properties)");
|
||||||
} else {
|
} else {
|
||||||
@@ -622,6 +572,50 @@ public class SchemaBuilder {
|
|||||||
return prop;
|
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) {
|
private String getType(Class<?> c) {
|
||||||
if (c.equals(int.class) || c.equals(Integer.class) || c.equals(long.class) || c.equals(Long.class)) {
|
if (c.equals(int.class) || c.equals(Integer.class) || c.equals(long.class) || c.equals(Long.class)) {
|
||||||
return "integer";
|
return "integer";
|
||||||
@@ -635,7 +629,7 @@ public class SchemaBuilder {
|
|||||||
return "boolean";
|
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";
|
return "string";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package com.volmit.iris.core.safeguard;
|
||||||
|
|
||||||
|
import com.volmit.iris.Iris;
|
||||||
|
import com.volmit.iris.core.IrisSettings;
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void earlySplash() {
|
||||||
|
if (ServerBootSFG.safeguardPassed || IrisSettings.get().getGeneral().DoomsdayAnnihilationSelfDestructMode)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Iris.instance.splash();
|
||||||
|
UtilsSFG.splash();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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,176 @@
|
|||||||
|
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 com.volmit.iris.engine.object.IrisContextInjector;
|
||||||
|
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;
|
||||||
|
public static boolean missingDimensionTypes = 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++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IrisContextInjector.isMissingDimensionTypes()) {
|
||||||
|
missingDimensionTypes = true;
|
||||||
|
joiner.add("Missing Dimension Types");
|
||||||
|
severityHigh++;
|
||||||
|
}
|
||||||
|
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user