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)
|
||||||
|
|||||||
582
build.gradle
582
build.gradle
@@ -1,323 +1,259 @@
|
|||||||
/*
|
/*
|
||||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
plugins {
|
buildscript() {
|
||||||
id 'java'
|
repositories {
|
||||||
id 'java-library'
|
maven { url 'https://jitpack.io'}
|
||||||
id "io.freefair.lombok" version "6.3.0"
|
}
|
||||||
id "com.github.johnrengelman.shadow" version "7.1.2"
|
dependencies {
|
||||||
id "de.undercouch.download" version "5.0.1"
|
classpath 'com.github.VolmitSoftware:NMSTools:1.0.1'
|
||||||
}
|
}
|
||||||
|
}
|
||||||
version '2.2.1-1.19' // Needs to be version specific
|
|
||||||
def nmsVersion = "1.19"
|
plugins {
|
||||||
def apiVersion = '1.19'
|
id 'java'
|
||||||
def spigotJarVersion = '1.19-R0.1-SNAPSHOT'
|
id 'java-library'
|
||||||
def name = getRootProject().getName() // Defined in settings.gradle
|
id "io.github.goooler.shadow" version "8.1.7"
|
||||||
def main = 'com.volmit.iris.Iris'
|
id "de.undercouch.download" version "5.0.1"
|
||||||
|
}
|
||||||
// ADD YOURSELF AS A NEW LINE IF YOU WANT YOUR OWN BUILD TASK GENERATED
|
|
||||||
// ======================== WINDOWS =============================
|
|
||||||
registerCustomOutputTask('Cyberpwn', 'C://Users/cyberpwn/Documents/development/server/plugins')
|
version '3.6.5-1.20.1-1.21.4'
|
||||||
registerCustomOutputTask('Psycho', 'D://Dan/MinecraftDevelopment/server/plugins')
|
|
||||||
registerCustomOutputTask('ArcaneArts', 'C://Users/arcane/Documents/development/server/plugins')
|
// ADD YOURSELF AS A NEW LINE IF YOU WANT YOUR OWN BUILD TASK GENERATED
|
||||||
registerCustomOutputTask('Coco', 'D://Documents/MC/plugins')
|
// ======================== WINDOWS =============================
|
||||||
registerCustomOutputTask('Strange', 'D://Servers/1.17 Test Server/plugins')
|
registerCustomOutputTask('Cyberpwn', 'C://Users/cyberpwn/Documents/development/server/plugins')
|
||||||
registerCustomOutputTask('Vatuu', 'D://Minecraft/Servers/1.19/plugins')
|
registerCustomOutputTask('Psycho', 'C://Dan/MinecraftDevelopment/Server/plugins')
|
||||||
// ========================== UNIX ==============================
|
registerCustomOutputTask('ArcaneArts', 'C://Users/arcane/Documents/development/server/plugins')
|
||||||
registerCustomOutputTaskUnix('CyberpwnLT', '/Users/danielmills/development/server/plugins')
|
registerCustomOutputTask('Coco', 'D://mcsm/plugins')
|
||||||
registerCustomOutputTaskUnix('PsychoLT', '/Users/brianfopiano/Desktop/REMOTES/RemoteMinecraft/plugins')
|
registerCustomOutputTask('Strange', 'D://Servers/1.17 Test Server/plugins')
|
||||||
// ==============================================================
|
registerCustomOutputTask('Vatuu', 'D://Minecraft/Servers/1.19.4/plugins')
|
||||||
|
registerCustomOutputTask('CrazyDev22', 'C://Users/Julian/Desktop/server/plugins')
|
||||||
/**
|
registerCustomOutputTask('PixelFury', 'C://Users/repix/workplace/Iris/1.21.3 - Development-Public-v3/plugins')
|
||||||
* Gradle is weird sometimes, we need to delete the plugin yml from the build folder to actually filter properly.
|
registerCustomOutputTask('PixelFuryDev', 'C://Users/repix/workplace/Iris/1.21 - Development-v3/plugins')
|
||||||
*/
|
// ========================== UNIX ==============================
|
||||||
file(jar.archiveFile.get().getAsFile().getParentFile().getParentFile().getParentFile().getAbsolutePath() + '/build/resources/main/plugin.yml').delete()
|
registerCustomOutputTaskUnix('CyberpwnLT', '/Users/danielmills/development/server/plugins')
|
||||||
|
registerCustomOutputTaskUnix('PsychoLT', '/Users/brianfopiano/Developer/RemoteGit/Server/plugins')
|
||||||
/**
|
registerCustomOutputTaskUnix('PixelMac', '/Users/test/Desktop/mcserver/plugins')
|
||||||
* Expand properties into plugin yml
|
registerCustomOutputTaskUnix('CrazyDev22LT', '/home/julian/Desktop/server/plugins')
|
||||||
*/
|
// ==============================================================
|
||||||
processResources {
|
|
||||||
filesMatching('**/plugin.yml') {
|
def NMS_BINDINGS = Map.of(
|
||||||
expand(
|
"v1_21_R3", "1.21.4-R0.1-SNAPSHOT",
|
||||||
'name': name.toString(),
|
"v1_21_R2", "1.21.3-R0.1-SNAPSHOT",
|
||||||
'version': version.toString(),
|
"v1_21_R1", "1.21.1-R0.1-SNAPSHOT",
|
||||||
'main': main.toString(),
|
"v1_20_R4", "1.20.6-R0.1-SNAPSHOT",
|
||||||
'apiversion': apiVersion.toString()
|
"v1_20_R3", "1.20.4-R0.1-SNAPSHOT",
|
||||||
)
|
"v1_20_R2", "1.20.2-R0.1-SNAPSHOT",
|
||||||
}
|
"v1_20_R1", "1.20.1-R0.1-SNAPSHOT",
|
||||||
}
|
)
|
||||||
|
def JVM_VERSION = Map.of()
|
||||||
/**
|
NMS_BINDINGS.each { nms ->
|
||||||
* Unified repo
|
project(":nms:${nms.key}") {
|
||||||
*/
|
apply plugin: 'java'
|
||||||
repositories {
|
apply plugin: 'com.volmit.nmstools'
|
||||||
mavenLocal {
|
|
||||||
content {
|
nmsTools {
|
||||||
includeGroup("org.bukkit")
|
it.jvm = JVM_VERSION.getOrDefault(nms.key, 21)
|
||||||
includeGroup("org.spigotmc")
|
it.version = nms.value
|
||||||
}
|
}
|
||||||
}
|
|
||||||
maven { url "https://dl.cloudsmith.io/public/arcane/archive/maven/" }
|
dependencies {
|
||||||
maven { url "https://maven.enginehub.org/repo/" }
|
implementation project(":core")
|
||||||
mavenCentral()
|
}
|
||||||
mavenLocal()
|
}
|
||||||
maven { url "https://jitpack.io"}
|
}
|
||||||
}
|
|
||||||
|
shadowJar {
|
||||||
/**
|
NMS_BINDINGS.each {
|
||||||
* We need parameter meta for the decree command system
|
dependsOn(":nms:${it.key}:remap")
|
||||||
*/
|
from("${project(":nms:${it.key}").layout.buildDirectory.asFile.get()}/libs/${it.key}-mapped.jar")
|
||||||
compileJava {
|
}
|
||||||
options.compilerArgs << '-parameters'
|
|
||||||
}
|
//minimize()
|
||||||
|
append("plugin.yml")
|
||||||
/**
|
relocate 'com.dfsek.paralithic', 'com.volmit.iris.util.paralithic'
|
||||||
* Configure Iris for shading
|
relocate 'io.papermc.lib', 'com.volmit.iris.util.paper'
|
||||||
*/
|
relocate 'net.kyori', 'com.volmit.iris.util.kyori'
|
||||||
shadowJar {
|
relocate 'org.bstats', 'com.volmit.util.metrics'
|
||||||
//minimize()
|
archiveFileName.set("Iris-${project.version}.jar")
|
||||||
append("plugin.yml")
|
|
||||||
relocate 'com.dfsek.paralithic', 'com.volmit.iris.util.paralithic'
|
dependencies {
|
||||||
relocate 'io.papermc.lib', 'com.volmit.iris.util.paper'
|
exclude(dependency("org.ow2.asm:asm:"))
|
||||||
relocate 'net.kyori', 'com.volmit.iris.util.kyori'
|
exclude(dependency("org.jetbrains:"))
|
||||||
dependencies {
|
}
|
||||||
include(dependency('io.papermc:paperlib'))
|
}
|
||||||
include(dependency('com.dfsek:Paralithic'))
|
|
||||||
include(dependency('net.kyori:'))
|
dependencies {
|
||||||
}
|
implementation project(':core')
|
||||||
}
|
}
|
||||||
|
|
||||||
configurations.all {
|
configurations.configureEach {
|
||||||
resolutionStrategy.cacheChangingModulesFor 60, 'minutes'
|
resolutionStrategy.cacheChangingModulesFor 60, 'minutes'
|
||||||
resolutionStrategy.cacheDynamicVersionsFor 60, 'minutes'
|
resolutionStrategy.cacheDynamicVersionsFor 60, 'minutes'
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
allprojects {
|
||||||
* Dependencies.
|
apply plugin: 'java'
|
||||||
*
|
|
||||||
* Provided or classpath dependencies are not shaded and are available on the runtime classpath
|
repositories {
|
||||||
*
|
mavenCentral()
|
||||||
* Shaded dependencies are not available at runtime, nor are they available on mvn central so they
|
maven { url "https://repo.papermc.io/repository/maven-public/" }
|
||||||
* need to be shaded into the jar (increasing binary size)
|
maven { url "https://repo.codemc.org/repository/maven-public" }
|
||||||
*
|
maven { url "https://mvn.lumine.io/repository/maven-public/" }
|
||||||
* Dynamically loaded dependencies are defined in the plugin.yml (updating these must be updated in the
|
maven { url "https://jitpack.io" }
|
||||||
* 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.
|
maven { url "https://s01.oss.sonatype.org/content/repositories/snapshots" }
|
||||||
*/
|
maven { url "https://mvn.lumine.io/repository/maven/" }
|
||||||
dependencies {
|
maven { url "https://repo.triumphteam.dev/snapshots" }
|
||||||
// Provided or Classpath
|
maven { url "https://repo.mineinabyss.com/releases" }
|
||||||
compileOnly 'org.projectlombok:lombok:1.18.24'
|
maven { url 'https://hub.jeff-media.com/nexus/repository/jeff-media-public/' }
|
||||||
annotationProcessor 'org.projectlombok:lombok:1.18.24'
|
maven { url "https://repo.nexomc.com/snapshots/" }
|
||||||
implementation 'org.spigotmc:spigot-api:1.19-R0.1-SNAPSHOT'
|
maven { url "https://libraries.minecraft.net" }
|
||||||
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'
|
dependencies {
|
||||||
implementation 'com.github.LoneDev6:api-itemsadder:3.1.0b'
|
// Provided or Classpath
|
||||||
|
compileOnly 'org.projectlombok:lombok:1.18.36'
|
||||||
// Shaded
|
annotationProcessor 'org.projectlombok:lombok:1.18.36'
|
||||||
implementation 'com.dfsek:Paralithic:0.4.0'
|
|
||||||
implementation 'io.papermc:paperlib:1.0.5'
|
// Shaded
|
||||||
implementation "net.kyori:adventure-text-minimessage:4.11.0"
|
implementation 'com.dfsek:paralithic:0.8.1'
|
||||||
implementation 'net.kyori:adventure-platform-bukkit:4.1.0'
|
implementation 'io.papermc:paperlib:1.0.5'
|
||||||
implementation 'net.kyori:adventure-api:4.11.0'
|
implementation "net.kyori:adventure-text-minimessage:4.17.0"
|
||||||
|
implementation 'net.kyori:adventure-platform-bukkit:4.3.4'
|
||||||
// Dynamically Loaded
|
implementation 'net.kyori:adventure-api:4.17.0'
|
||||||
implementation 'io.timeandspace:smoothie-map:2.0.2'
|
implementation 'org.bstats:bstats-bukkit:3.1.0'
|
||||||
implementation 'it.unimi.dsi:fastutil:8.5.8'
|
//implementation 'org.bytedeco:javacpp:1.5.10'
|
||||||
implementation 'com.googlecode.concurrentlinkedhashmap:concurrentlinkedhashmap-lru:1.4.2'
|
//implementation 'org.bytedeco:cuda-platform:12.3-8.9-1.5.10'
|
||||||
implementation 'org.zeroturnaround:zt-zip:1.14'
|
compileOnly 'io.lumine:Mythic-Dist:5.2.1'
|
||||||
implementation 'com.google.code.gson:gson:2.9.0'
|
compileOnly 'io.lumine:MythicCrucible-Dist:2.0.0'
|
||||||
implementation 'org.ow2.asm:asm:9.2'
|
|
||||||
implementation 'com.google.guava:guava:31.1-jre'
|
// Dynamically Loaded
|
||||||
implementation 'bsf:bsf:2.4.0'
|
compileOnly 'io.timeandspace:smoothie-map:2.0.2'
|
||||||
implementation 'rhino:js:1.7R2'
|
compileOnly 'it.unimi.dsi:fastutil:8.5.8'
|
||||||
implementation 'com.github.ben-manes.caffeine:caffeine:3.0.6'
|
compileOnly 'com.googlecode.concurrentlinkedhashmap:concurrentlinkedhashmap-lru:1.4.2'
|
||||||
implementation 'org.apache.commons:commons-lang3:3.12.0'
|
compileOnly 'org.zeroturnaround:zt-zip:1.14'
|
||||||
}
|
compileOnly 'com.google.code.gson:gson:2.10.1'
|
||||||
|
compileOnly 'org.ow2.asm:asm:9.2'
|
||||||
if (JavaVersion.current().toString() != "17") {
|
compileOnly 'com.google.guava:guava:33.0.0-jre'
|
||||||
System.err.println()
|
compileOnly 'bsf:bsf:2.4.0'
|
||||||
System.err.println("=========================================================================================================")
|
compileOnly 'rhino:js:1.7R2'
|
||||||
System.err.println("You must run gradle on Java 17. You are using " + JavaVersion.current())
|
compileOnly 'com.github.ben-manes.caffeine:caffeine:3.0.6'
|
||||||
System.err.println()
|
compileOnly 'org.apache.commons:commons-lang3:3.12.0'
|
||||||
System.err.println("=== For IDEs ===")
|
compileOnly 'com.github.oshi:oshi-core:6.6.5'
|
||||||
System.err.println("1. Configure the project for Java 17")
|
}
|
||||||
System.err.println("2. Configure the bundled gradle to use Java 17 in settings")
|
|
||||||
System.err.println()
|
/**
|
||||||
System.err.println("=== For Command Line (gradlew) ===")
|
* We need parameter meta for the decree command system
|
||||||
System.err.println("1. Install JDK 17 from https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html")
|
*/
|
||||||
System.err.println("2. Set JAVA_HOME environment variable to the new jdk installation folder such as C:\\Program Files\\Java\\jdk-17.0.1")
|
compileJava {
|
||||||
System.err.println("3. Open a new command prompt window to get the new environment variables if need be.")
|
options.compilerArgs << '-parameters'
|
||||||
System.err.println("=========================================================================================================")
|
options.encoding = "UTF-8"
|
||||||
System.err.println()
|
}
|
||||||
System.exit(69);
|
|
||||||
}
|
javadoc {
|
||||||
|
options.encoding = "UTF-8"
|
||||||
def buildToolsJar = new File(buildDir, "buildtools/BuildTools.jar");
|
options.addStringOption('Xdoclint:none', '-quiet')
|
||||||
def specialSourceJar = new File(buildDir, "specialsource/SpecialSource.jar");
|
}
|
||||||
def buildToolsFolder = new File(buildDir, "buildtools");
|
|
||||||
def specialSourceFolder = new File(buildDir, "specialsource");
|
task sourcesJar(type: Jar, dependsOn: classes) {
|
||||||
def buildToolsHint = new File(buildDir, "buildtools/craftbukkit-" + nmsVersion + ".jar");
|
archiveClassifier.set('sources')
|
||||||
def outputShadeJar = new File(buildDir, "libs/Iris-" + version + "-all.jar");
|
from sourceSets.main.allSource
|
||||||
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");
|
task javadocJar(type: Jar, dependsOn: javadoc) {
|
||||||
def homePath = System.properties['user.home']
|
archiveClassifier.set('javadoc')
|
||||||
def m2 = new File(homePath + "/.m2/repository")
|
from javadoc.destinationDir
|
||||||
def m2s = m2.getAbsolutePath();
|
}
|
||||||
|
}
|
||||||
// ======================== Building Mapped Jars =============================
|
|
||||||
task downloadBuildtools(type: Download) {
|
if (JavaVersion.current().toString() != "21") {
|
||||||
group "remapping"
|
System.err.println()
|
||||||
src 'https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar'
|
System.err.println("=========================================================================================================")
|
||||||
dest buildToolsJar
|
System.err.println("You must run gradle on Java 21. You are using " + JavaVersion.current())
|
||||||
onlyIf {
|
System.err.println()
|
||||||
!buildToolsJar.exists()
|
System.err.println("=== For IDEs ===")
|
||||||
}
|
System.err.println("1. Configure the project for Java 21")
|
||||||
}
|
System.err.println("2. Configure the bundled gradle to use Java 21 in settings")
|
||||||
|
System.err.println()
|
||||||
task downloadSpecialSource(type: Download) {
|
System.err.println("=== For Command Line (gradlew) ===")
|
||||||
group "remapping"
|
System.err.println("1. Install JDK 21 from https://www.oracle.com/java/technologies/javase/jdk21-archive-downloads.html")
|
||||||
src 'https://repo.maven.apache.org/maven2/net/md-5/SpecialSource/1.10.0/SpecialSource-1.10.0-shaded.jar'
|
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")
|
||||||
dest specialSourceJar
|
System.err.println("3. Open a new command prompt window to get the new environment variables if need be.")
|
||||||
onlyIf {
|
System.err.println("=========================================================================================================")
|
||||||
!specialSourceJar.exists()
|
System.err.println()
|
||||||
}
|
System.exit(69);
|
||||||
}
|
}
|
||||||
|
|
||||||
task executeBuildTools(dependsOn: downloadBuildtools, type: JavaExec)
|
task iris(type: Copy) {
|
||||||
{
|
group "iris"
|
||||||
group "remapping"
|
from new File(layout.buildDirectory.asFile.get(), "libs/Iris-${version}.jar")
|
||||||
classpath = files(buildToolsJar)
|
into layout.buildDirectory.asFile.get()
|
||||||
workingDir = buildToolsFolder
|
dependsOn(build)
|
||||||
args = [
|
}
|
||||||
"--rev",
|
|
||||||
nmsVersion,
|
// with classifier: 'javadoc' and 'sources'
|
||||||
"--compile",
|
task irisDev(type: Copy) {
|
||||||
"craftbukkit",
|
group "iris"
|
||||||
"--remap"
|
from("core/build/libs/core-javadoc.jar", "core/build/libs/core-sources.jar")
|
||||||
]
|
rename { String fileName ->
|
||||||
onlyIf {
|
fileName.replace("core", "Iris-${version}")
|
||||||
!buildToolsHint.exists()
|
}
|
||||||
}
|
into layout.buildDirectory.asFile.get()
|
||||||
}
|
dependsOn(iris)
|
||||||
|
dependsOn("core:sourcesJar")
|
||||||
task copyBuildToSpecialSource(type: Copy)
|
dependsOn("core:javadocJar")
|
||||||
{
|
}
|
||||||
group "remapping"
|
|
||||||
from outputShadeJar
|
|
||||||
into specialSourceFolder
|
def registerCustomOutputTask(name, path) {
|
||||||
dependsOn(downloadSpecialSource, shadowJar)
|
if (!System.properties['os.name'].toLowerCase().contains('windows')) {
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
task specialSourceRemapObfuscate(type: JavaExec)
|
|
||||||
{
|
tasks.register('build' + name, Copy) {
|
||||||
group "remapping"
|
group('development')
|
||||||
dependsOn(copyBuildToSpecialSource, downloadSpecialSource, shadowJar)
|
outputs.upToDateWhen { false }
|
||||||
workingDir = specialSourceFolder
|
dependsOn(iris)
|
||||||
classpath = files(specialSourceJar,
|
from(new File(buildDir, "Iris-" + version + ".jar"))
|
||||||
new File(m2s + "/org/spigotmc/spigot/" + spigotJarVersion + "/spigot-" + spigotJarVersion + "-remapped-mojang.jar"))
|
into(file(path))
|
||||||
mainClass = "net.md_5.specialsource.SpecialSource"
|
rename { String fileName ->
|
||||||
args = [
|
fileName.replace("Iris-" + version + ".jar", "Iris.jar")
|
||||||
"--live",
|
}
|
||||||
"-i",
|
}
|
||||||
ssiJar.getName(),
|
}
|
||||||
"-o",
|
|
||||||
ssobfJar.getName(),
|
def registerCustomOutputTaskUnix(name, path) {
|
||||||
"-m",
|
if (System.properties['os.name'].toLowerCase().contains('windows')) {
|
||||||
m2s + "/org/spigotmc/minecraft-server/" + spigotJarVersion + "/minecraft-server-" + spigotJarVersion + "-maps-mojang.txt",
|
return;
|
||||||
"--reverse",
|
}
|
||||||
]
|
|
||||||
}
|
tasks.register('build' + name, Copy) {
|
||||||
|
group('development')
|
||||||
task specialSourceRemap(type: JavaExec)
|
outputs.upToDateWhen { false }
|
||||||
{
|
dependsOn(iris)
|
||||||
group "remapping"
|
from(new File(buildDir, "Iris-" + version + ".jar"))
|
||||||
dependsOn(specialSourceRemapObfuscate)
|
into(file(path))
|
||||||
workingDir = specialSourceFolder
|
rename { String fileName ->
|
||||||
classpath = files(specialSourceJar,
|
fileName.replace("Iris-" + version + ".jar", "Iris.jar")
|
||||||
new File(m2s + "/org/spigotmc/spigot/" + spigotJarVersion + "/spigot-" + spigotJarVersion + "-remapped-obf.jar"))
|
}
|
||||||
mainClass = "net.md_5.specialsource.SpecialSource"
|
}
|
||||||
args = [
|
}
|
||||||
"--live",
|
|
||||||
"-i",
|
tasks.build.dependsOn(shadowJar)
|
||||||
ssobfJar.getName(),
|
|
||||||
"-o",
|
|
||||||
ssJar.getName(),
|
|
||||||
"-m",
|
|
||||||
m2s + "/org/spigotmc/minecraft-server/" + spigotJarVersion + "/minecraft-server-" + spigotJarVersion + "-maps-spigot.csrg"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.compileJava.dependsOn(executeBuildTools)
|
|
||||||
|
|
||||||
compileJava {
|
|
||||||
options.encoding = "UTF-8"
|
|
||||||
}
|
|
||||||
|
|
||||||
task setup()
|
|
||||||
{
|
|
||||||
group("iris")
|
|
||||||
dependsOn(clean, executeBuildTools)
|
|
||||||
}
|
|
||||||
|
|
||||||
task iris(type: Copy)
|
|
||||||
{
|
|
||||||
group "iris"
|
|
||||||
from ssJar
|
|
||||||
into buildDir
|
|
||||||
rename { String fileName ->
|
|
||||||
fileName.replace('Iris-' + version + '-rma.jar', "Iris-" + version + ".jar")
|
|
||||||
}
|
|
||||||
dependsOn(specialSourceRemap)
|
|
||||||
}
|
|
||||||
|
|
||||||
def registerCustomOutputTask(name, path) {
|
|
||||||
if (!System.properties['os.name'].toLowerCase().contains('windows')) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.register('build' + name, Copy) {
|
|
||||||
group('development')
|
|
||||||
outputs.upToDateWhen { false }
|
|
||||||
dependsOn(iris)
|
|
||||||
from(new File(buildDir, "Iris-" + version + ".jar"))
|
|
||||||
into(file(path))
|
|
||||||
rename { String fileName ->
|
|
||||||
fileName.replace("Iris-" + version + ".jar", "Iris.jar")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def registerCustomOutputTaskUnix(name, path) {
|
|
||||||
if (System.properties['os.name'].toLowerCase().contains('windows')) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.register('build' + name, Copy) {
|
|
||||||
group('development')
|
|
||||||
outputs.upToDateWhen { false }
|
|
||||||
dependsOn(iris)
|
|
||||||
from(new File(buildDir, "Iris-" + version + ".jar"))
|
|
||||||
into(file(path))
|
|
||||||
rename { String fileName ->
|
|
||||||
fileName.replace("Iris-" + version + ".jar", "Iris.jar")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
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()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -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,15 +44,67 @@ 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) {
|
||||||
case -1, -2, -4 -> Runtime.getRuntime().availableProcessors() / -c;
|
case -1, -2, -4 -> Runtime.getRuntime().availableProcessors() / -c;
|
||||||
case 0, 1, 2 -> 1;
|
case 0, 1, 2 -> 1;
|
||||||
default -> Math.max(c, 2);
|
default -> Math.max(c, 2);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static IrisSettings get() {
|
||||||
|
if (settings != null) {
|
||||||
|
return settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
settings = new IrisSettings();
|
||||||
|
|
||||||
|
File s = Iris.instance.getDataFile("settings.json");
|
||||||
|
|
||||||
|
if (!s.exists()) {
|
||||||
|
try {
|
||||||
|
IO.writeAll(s, new JSONObject(new Gson().toJson(settings)).toString(4));
|
||||||
|
} catch (JSONException | IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
Iris.reportError(e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
String ss = IO.readAll(s);
|
||||||
|
settings = new Gson().fromJson(ss, IrisSettings.class);
|
||||||
|
try {
|
||||||
|
IO.writeAll(s, new JSONObject(new Gson().toJson(settings)).toString(4));
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
} catch (Throwable ee) {
|
||||||
|
// Iris.reportError(ee); causes a self-reference & stackoverflow
|
||||||
|
Iris.error("Configuration Error in settings.json! " + ee.getClass().getSimpleName() + ": " + ee.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void invalidate() {
|
||||||
|
synchronized (settings) {
|
||||||
|
settings = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void forceSave() {
|
||||||
|
File s = Iris.instance.getDataFile("settings.json");
|
||||||
|
|
||||||
|
try {
|
||||||
|
IO.writeAll(s, new JSONObject(new Gson().toJson(settings)).toString(4));
|
||||||
|
} catch (JSONException | IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
Iris.reportError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public static class IrisSettingsAutoconfiguration {
|
public static class IrisSettingsAutoconfiguration {
|
||||||
public boolean configureSpigotTimeoutTime = true;
|
public boolean configureSpigotTimeoutTime = true;
|
||||||
@@ -84,7 +139,7 @@ public class IrisSettings {
|
|||||||
|
|
||||||
@Data
|
@Data
|
||||||
public static class IrisSettingsPerformance {
|
public static class IrisSettingsPerformance {
|
||||||
public boolean trimMantleInStudio = false;
|
public boolean trimMantleInStudio = false;
|
||||||
public int mantleKeepAlive = 30;
|
public int mantleKeepAlive = 30;
|
||||||
public int cacheSize = 4_096;
|
public int cacheSize = 4_096;
|
||||||
public int resourceLoaderCacheSize = 1_024;
|
public int resourceLoaderCacheSize = 1_024;
|
||||||
@@ -92,8 +147,33 @@ public class IrisSettings {
|
|||||||
public int scriptLoaderCacheSize = 512;
|
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
|
@Data
|
||||||
public static class IrisSettingsGeneral {
|
public static class IrisSettingsGeneral {
|
||||||
|
public boolean DoomsdayAnnihilationSelfDestructMode = false;
|
||||||
public boolean commandSounds = true;
|
public boolean commandSounds = true;
|
||||||
public boolean debug = false;
|
public boolean debug = false;
|
||||||
public boolean disableNMS = false;
|
public boolean disableNMS = false;
|
||||||
@@ -101,10 +181,13 @@ public class IrisSettings {
|
|||||||
public boolean splashLogoStartup = true;
|
public boolean splashLogoStartup = true;
|
||||||
public boolean useConsoleCustomColors = true;
|
public boolean useConsoleCustomColors = true;
|
||||||
public boolean useCustomColorsIngame = true;
|
public boolean useCustomColorsIngame = true;
|
||||||
|
public boolean adjustVanillaHeight = false;
|
||||||
public String forceMainWorld = "";
|
public String forceMainWorld = "";
|
||||||
public int spinh = -20;
|
public int spinh = -20;
|
||||||
public int spins = 7;
|
public int spins = 7;
|
||||||
public int spinb = 8;
|
public int spinb = 8;
|
||||||
|
public String cartographerMessage = "Iris does not allow cartographers in its world due to crashes.";
|
||||||
|
|
||||||
|
|
||||||
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
|
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
|
||||||
public boolean canUseCustomColors(VolmitSender volmitSender) {
|
public boolean canUseCustomColors(VolmitSender volmitSender) {
|
||||||
@@ -116,6 +199,7 @@ public class IrisSettings {
|
|||||||
public static class IrisSettingsGUI {
|
public static class IrisSettingsGUI {
|
||||||
public boolean useServerLaunchedGuis = true;
|
public boolean useServerLaunchedGuis = true;
|
||||||
public boolean maximumPregenGuiFPS = false;
|
public boolean maximumPregenGuiFPS = false;
|
||||||
|
public boolean colorMode = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@@ -132,55 +216,4 @@ public class IrisSettings {
|
|||||||
public boolean disableTimeAndWeather = true;
|
public boolean disableTimeAndWeather = true;
|
||||||
public boolean autoStartDefaultStudio = false;
|
public boolean autoStartDefaultStudio = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IrisSettings get() {
|
|
||||||
if(settings != null) {
|
|
||||||
return settings;
|
|
||||||
}
|
|
||||||
|
|
||||||
settings = new IrisSettings();
|
|
||||||
|
|
||||||
File s = Iris.instance.getDataFile("settings.json");
|
|
||||||
|
|
||||||
if(!s.exists()) {
|
|
||||||
try {
|
|
||||||
IO.writeAll(s, new JSONObject(new Gson().toJson(settings)).toString(4));
|
|
||||||
} catch(JSONException | IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
Iris.reportError(e);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
String ss = IO.readAll(s);
|
|
||||||
settings = new Gson().fromJson(ss, IrisSettings.class);
|
|
||||||
try {
|
|
||||||
IO.writeAll(s, new JSONObject(new Gson().toJson(settings)).toString(4));
|
|
||||||
} catch(IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
} catch(Throwable ee) {
|
|
||||||
// Iris.reportError(ee); causes a self-reference & stackoverflow
|
|
||||||
Iris.error("Configuration Error in settings.json! " + ee.getClass().getSimpleName() + ": " + ee.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return settings;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void invalidate() {
|
|
||||||
synchronized(settings) {
|
|
||||||
settings = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void forceSave() {
|
|
||||||
File s = Iris.instance.getDataFile("settings.json");
|
|
||||||
|
|
||||||
try {
|
|
||||||
IO.writeAll(s, new JSONObject(new Gson().toJson(settings)).toString(4));
|
|
||||||
} catch(JSONException | IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
Iris.reportError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
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,35 +20,29 @@ 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")
|
||||||
public class CommandEdit implements DecreeExecutor {
|
public class CommandEdit implements DecreeExecutor {
|
||||||
|
|
||||||
private boolean noStudio() {
|
private boolean noStudio() {
|
||||||
if(!sender().isPlayer()) {
|
if (!sender().isPlayer()) {
|
||||||
sender().sendMessage(C.RED + "Players only!");
|
sender().sendMessage(C.RED + "Players only!");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if(!Iris.service(StudioSVC.class).isProjectOpen()) {
|
if (!Iris.service(StudioSVC.class).isProjectOpen()) {
|
||||||
sender().sendMessage(C.RED + "No studio world is open!");
|
sender().sendMessage(C.RED + "No studio world is open!");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if(!engine().isStudio()) {
|
if (!engine().isStudio()) {
|
||||||
sender().sendMessage(C.RED + "You must be in a studio world!");
|
sender().sendMessage(C.RED + "You must be in a studio world!");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -58,17 +52,17 @@ public class CommandEdit implements DecreeExecutor {
|
|||||||
|
|
||||||
@Decree(description = "Edit the biome you specified", aliases = {"b"}, origin = DecreeOrigin.PLAYER)
|
@Decree(description = "Edit the biome you specified", aliases = {"b"}, origin = DecreeOrigin.PLAYER)
|
||||||
public void biome(@Param(contextual = false, description = "The biome to edit") IrisBiome biome) {
|
public void biome(@Param(contextual = false, description = "The biome to edit") IrisBiome biome) {
|
||||||
if(noStudio()) {
|
if (noStudio()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
if(biome == null || biome.getLoadFile() == null) {
|
if (biome == null || biome.getLoadFile() == null) {
|
||||||
sender().sendMessage(C.GOLD + "Cannot find the file; Perhaps it was not loaded directly from a file?");
|
sender().sendMessage(C.GOLD + "Cannot find the file; Perhaps it was not loaded directly from a file?");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Desktop.getDesktop().open(biome.getLoadFile());
|
Desktop.getDesktop().open(biome.getLoadFile());
|
||||||
sender().sendMessage(C.GREEN + "Opening " + biome.getTypeName() + " " + biome.getLoadFile().getName().split("\\Q.\\E")[0] + " in VSCode! ");
|
sender().sendMessage(C.GREEN + "Opening " + biome.getTypeName() + " " + biome.getLoadFile().getName().split("\\Q.\\E")[0] + " in VSCode! ");
|
||||||
} catch(Throwable e) {
|
} catch (Throwable e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
sender().sendMessage(C.RED + "Cant find the file. Or registrant does not exist");
|
sender().sendMessage(C.RED + "Cant find the file. Or registrant does not exist");
|
||||||
}
|
}
|
||||||
@@ -76,17 +70,17 @@ public class CommandEdit implements DecreeExecutor {
|
|||||||
|
|
||||||
@Decree(description = "Edit the region you specified", aliases = {"r"}, origin = DecreeOrigin.PLAYER)
|
@Decree(description = "Edit the region you specified", aliases = {"r"}, origin = DecreeOrigin.PLAYER)
|
||||||
public void region(@Param(contextual = false, description = "The region to edit") IrisRegion region) {
|
public void region(@Param(contextual = false, description = "The region to edit") IrisRegion region) {
|
||||||
if(noStudio()) {
|
if (noStudio()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
if(region == null || region.getLoadFile() == null) {
|
if (region == null || region.getLoadFile() == null) {
|
||||||
sender().sendMessage(C.GOLD + "Cannot find the file; Perhaps it was not loaded directly from a file?");
|
sender().sendMessage(C.GOLD + "Cannot find the file; Perhaps it was not loaded directly from a file?");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Desktop.getDesktop().open(region.getLoadFile());
|
Desktop.getDesktop().open(region.getLoadFile());
|
||||||
sender().sendMessage(C.GREEN + "Opening " + region.getTypeName() + " " + region.getLoadFile().getName().split("\\Q.\\E")[0] + " in VSCode! ");
|
sender().sendMessage(C.GREEN + "Opening " + region.getTypeName() + " " + region.getLoadFile().getName().split("\\Q.\\E")[0] + " in VSCode! ");
|
||||||
} catch(Throwable e) {
|
} catch (Throwable e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
sender().sendMessage(C.RED + "Cant find the file. Or registrant does not exist");
|
sender().sendMessage(C.RED + "Cant find the file. Or registrant does not exist");
|
||||||
}
|
}
|
||||||
@@ -94,17 +88,17 @@ public class CommandEdit implements DecreeExecutor {
|
|||||||
|
|
||||||
@Decree(description = "Edit the dimension you specified", aliases = {"d"}, origin = DecreeOrigin.PLAYER)
|
@Decree(description = "Edit the dimension you specified", aliases = {"d"}, origin = DecreeOrigin.PLAYER)
|
||||||
public void dimension(@Param(contextual = false, description = "The dimension to edit") IrisDimension dimension) {
|
public void dimension(@Param(contextual = false, description = "The dimension to edit") IrisDimension dimension) {
|
||||||
if(noStudio()) {
|
if (noStudio()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
if(dimension == null || dimension.getLoadFile() == null) {
|
if (dimension == null || dimension.getLoadFile() == null) {
|
||||||
sender().sendMessage(C.GOLD + "Cannot find the file; Perhaps it was not loaded directly from a file?");
|
sender().sendMessage(C.GOLD + "Cannot find the file; Perhaps it was not loaded directly from a file?");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Desktop.getDesktop().open(dimension.getLoadFile());
|
Desktop.getDesktop().open(dimension.getLoadFile());
|
||||||
sender().sendMessage(C.GREEN + "Opening " + dimension.getTypeName() + " " + dimension.getLoadFile().getName().split("\\Q.\\E")[0] + " in VSCode! ");
|
sender().sendMessage(C.GREEN + "Opening " + dimension.getTypeName() + " " + dimension.getLoadFile().getName().split("\\Q.\\E")[0] + " in VSCode! ");
|
||||||
} catch(Throwable e) {
|
} catch (Throwable e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
sender().sendMessage(C.RED + "Cant find the file. Or registrant does not exist");
|
sender().sendMessage(C.RED + "Cant find the file. Or registrant does not exist");
|
||||||
}
|
}
|
||||||
@@ -112,17 +106,17 @@ public class CommandEdit implements DecreeExecutor {
|
|||||||
|
|
||||||
@Decree(description = "Edit the cave file you specified", aliases = {"c"}, origin = DecreeOrigin.PLAYER)
|
@Decree(description = "Edit the cave file you specified", aliases = {"c"}, origin = DecreeOrigin.PLAYER)
|
||||||
public void cave(@Param(contextual = false, description = "The cave to edit") IrisCave cave) {
|
public void cave(@Param(contextual = false, description = "The cave to edit") IrisCave cave) {
|
||||||
if(noStudio()) {
|
if (noStudio()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
if(cave == null || cave.getLoadFile() == null) {
|
if (cave == null || cave.getLoadFile() == null) {
|
||||||
sender().sendMessage(C.GOLD + "Cannot find the file; Perhaps it was not loaded directly from a file?");
|
sender().sendMessage(C.GOLD + "Cannot find the file; Perhaps it was not loaded directly from a file?");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Desktop.getDesktop().open(cave.getLoadFile());
|
Desktop.getDesktop().open(cave.getLoadFile());
|
||||||
sender().sendMessage(C.GREEN + "Opening " + cave.getTypeName() + " " + cave.getLoadFile().getName().split("\\Q.\\E")[0] + " in VSCode! ");
|
sender().sendMessage(C.GREEN + "Opening " + cave.getTypeName() + " " + cave.getLoadFile().getName().split("\\Q.\\E")[0] + " in VSCode! ");
|
||||||
} catch(Throwable e) {
|
} catch (Throwable e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
sender().sendMessage(C.RED + "Cant find the file. Or registrant does not exist");
|
sender().sendMessage(C.RED + "Cant find the file. Or registrant does not exist");
|
||||||
}
|
}
|
||||||
@@ -130,17 +124,17 @@ public class CommandEdit implements DecreeExecutor {
|
|||||||
|
|
||||||
@Decree(description = "Edit the structure file you specified", aliases = {"jigsawstructure", "structure"}, origin = DecreeOrigin.PLAYER)
|
@Decree(description = "Edit the structure file you specified", aliases = {"jigsawstructure", "structure"}, origin = DecreeOrigin.PLAYER)
|
||||||
public void jigsaw(@Param(contextual = false, description = "The jigsaw structure to edit") IrisJigsawStructure jigsaw) {
|
public void jigsaw(@Param(contextual = false, description = "The jigsaw structure to edit") IrisJigsawStructure jigsaw) {
|
||||||
if(noStudio()) {
|
if (noStudio()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
if(jigsaw == null || jigsaw.getLoadFile() == null) {
|
if (jigsaw == null || jigsaw.getLoadFile() == null) {
|
||||||
sender().sendMessage(C.GOLD + "Cannot find the file; Perhaps it was not loaded directly from a file?");
|
sender().sendMessage(C.GOLD + "Cannot find the file; Perhaps it was not loaded directly from a file?");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Desktop.getDesktop().open(jigsaw.getLoadFile());
|
Desktop.getDesktop().open(jigsaw.getLoadFile());
|
||||||
sender().sendMessage(C.GREEN + "Opening " + jigsaw.getTypeName() + " " + jigsaw.getLoadFile().getName().split("\\Q.\\E")[0] + " in VSCode! ");
|
sender().sendMessage(C.GREEN + "Opening " + jigsaw.getTypeName() + " " + jigsaw.getLoadFile().getName().split("\\Q.\\E")[0] + " in VSCode! ");
|
||||||
} catch(Throwable e) {
|
} catch (Throwable e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
sender().sendMessage(C.RED + "Cant find the file. Or registrant does not exist");
|
sender().sendMessage(C.RED + "Cant find the file. Or registrant does not exist");
|
||||||
}
|
}
|
||||||
@@ -148,17 +142,17 @@ public class CommandEdit implements DecreeExecutor {
|
|||||||
|
|
||||||
@Decree(description = "Edit the pool file you specified", aliases = {"jigsawpool", "pool"}, origin = DecreeOrigin.PLAYER)
|
@Decree(description = "Edit the pool file you specified", aliases = {"jigsawpool", "pool"}, origin = DecreeOrigin.PLAYER)
|
||||||
public void jigsawPool(@Param(contextual = false, description = "The jigsaw pool to edit") IrisJigsawPool pool) {
|
public void jigsawPool(@Param(contextual = false, description = "The jigsaw pool to edit") IrisJigsawPool pool) {
|
||||||
if(noStudio()) {
|
if (noStudio()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
if(pool == null || pool.getLoadFile() == null) {
|
if (pool == null || pool.getLoadFile() == null) {
|
||||||
sender().sendMessage(C.GOLD + "Cannot find the file; Perhaps it was not loaded directly from a file?");
|
sender().sendMessage(C.GOLD + "Cannot find the file; Perhaps it was not loaded directly from a file?");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Desktop.getDesktop().open(pool.getLoadFile());
|
Desktop.getDesktop().open(pool.getLoadFile());
|
||||||
sender().sendMessage(C.GREEN + "Opening " + pool.getTypeName() + " " + pool.getLoadFile().getName().split("\\Q.\\E")[0] + " in VSCode! ");
|
sender().sendMessage(C.GREEN + "Opening " + pool.getTypeName() + " " + pool.getLoadFile().getName().split("\\Q.\\E")[0] + " in VSCode! ");
|
||||||
} catch(Throwable e) {
|
} catch (Throwable e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
sender().sendMessage(C.RED + "Cant find the file. Or registrant does not exist");
|
sender().sendMessage(C.RED + "Cant find the file. Or registrant does not exist");
|
||||||
}
|
}
|
||||||
@@ -166,17 +160,17 @@ public class CommandEdit implements DecreeExecutor {
|
|||||||
|
|
||||||
@Decree(description = "Edit the jigsaw piece file you specified", aliases = {"jigsawpiece", "piece"}, origin = DecreeOrigin.PLAYER)
|
@Decree(description = "Edit the jigsaw piece file you specified", aliases = {"jigsawpiece", "piece"}, origin = DecreeOrigin.PLAYER)
|
||||||
public void jigsawPiece(@Param(contextual = false, description = "The jigsaw piece to edit") IrisJigsawPiece piece) {
|
public void jigsawPiece(@Param(contextual = false, description = "The jigsaw piece to edit") IrisJigsawPiece piece) {
|
||||||
if(noStudio()) {
|
if (noStudio()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
if(piece == null || piece.getLoadFile() == null) {
|
if (piece == null || piece.getLoadFile() == null) {
|
||||||
sender().sendMessage(C.GOLD + "Cannot find the file; Perhaps it was not loaded directly from a file?");
|
sender().sendMessage(C.GOLD + "Cannot find the file; Perhaps it was not loaded directly from a file?");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Desktop.getDesktop().open(piece.getLoadFile());
|
Desktop.getDesktop().open(piece.getLoadFile());
|
||||||
sender().sendMessage(C.GREEN + "Opening " + piece.getTypeName() + " " + piece.getLoadFile().getName().split("\\Q.\\E")[0] + " in VSCode! ");
|
sender().sendMessage(C.GREEN + "Opening " + piece.getTypeName() + " " + piece.getLoadFile().getName().split("\\Q.\\E")[0] + " in VSCode! ");
|
||||||
} catch(Throwable e) {
|
} catch (Throwable e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
sender().sendMessage(C.RED + "Cant find the file. Or registrant does not exist");
|
sender().sendMessage(C.RED + "Cant find the file. Or registrant does not exist");
|
||||||
}
|
}
|
||||||
@@ -33,61 +33,85 @@ import com.volmit.iris.util.format.C;
|
|||||||
public class CommandFind implements DecreeExecutor {
|
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();
|
||||||
|
|
||||||
if(e == null) {
|
if (e == null) {
|
||||||
sender().sendMessage(C.GOLD + "Not in an Iris World!");
|
sender().sendMessage(C.GOLD + "Not in an Iris World!");
|
||||||
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();
|
||||||
|
|
||||||
if(e == null) {
|
if (e == null) {
|
||||||
sender().sendMessage(C.GOLD + "Not in an Iris World!");
|
sender().sendMessage(C.GOLD + "Not in an Iris World!");
|
||||||
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();
|
||||||
|
|
||||||
if(e == null) {
|
if (e == null) {
|
||||||
sender().sendMessage(C.GOLD + "Not in an Iris World!");
|
sender().sendMessage(C.GOLD + "Not in an Iris World!");
|
||||||
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();
|
||||||
|
|
||||||
if(e == null) {
|
if (e == null) {
|
||||||
sender().sendMessage(C.GOLD + "Not in an Iris World!");
|
sender().sendMessage(C.GOLD + "Not in an Iris World!");
|
||||||
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;
|
||||||
@@ -42,7 +44,7 @@ import java.io.File;
|
|||||||
public class CommandJigsaw implements DecreeExecutor {
|
public class CommandJigsaw implements DecreeExecutor {
|
||||||
@Decree(description = "Edit a jigsaw piece")
|
@Decree(description = "Edit a jigsaw piece")
|
||||||
public void edit(
|
public void edit(
|
||||||
@Param(description = "The jigsaw piece to edit")
|
@Param(description = "The jigsaw piece to edit")
|
||||||
IrisJigsawPiece piece
|
IrisJigsawPiece piece
|
||||||
) {
|
) {
|
||||||
File dest = piece.getLoadFile();
|
File dest = piece.getLoadFile();
|
||||||
@@ -51,27 +53,34 @@ public class CommandJigsaw implements DecreeExecutor {
|
|||||||
|
|
||||||
@Decree(description = "Place a jigsaw structure")
|
@Decree(description = "Place a jigsaw structure")
|
||||||
public void place(
|
public void place(
|
||||||
@Param(description = "The jigsaw structure to place")
|
@Param(description = "The jigsaw structure to place")
|
||||||
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")
|
||||||
public void create(
|
public void create(
|
||||||
@Param(description = "The name of the jigsaw piece")
|
@Param(description = "The name of the jigsaw piece")
|
||||||
String piece,
|
String piece,
|
||||||
@Param(description = "The project to add the jigsaw piece to")
|
@Param(description = "The project to add the jigsaw piece to")
|
||||||
String project,
|
String project,
|
||||||
@Param(description = "The object to use for this piece", customHandler = ObjectHandler.class)
|
@Param(description = "The object to use for this piece", customHandler = ObjectHandler.class)
|
||||||
String object
|
String object
|
||||||
) {
|
) {
|
||||||
IrisObject o = IrisData.loadAnyObject(object);
|
IrisObject o = IrisData.loadAnyObject(object);
|
||||||
|
|
||||||
if(object == null) {
|
if (object == null) {
|
||||||
sender().sendMessage(C.RED + "Failed to find existing object");
|
sender().sendMessage(C.RED + "Failed to find existing object");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -88,7 +97,7 @@ public class CommandJigsaw implements DecreeExecutor {
|
|||||||
public void exit() {
|
public void exit() {
|
||||||
JigsawEditor editor = JigsawEditor.editors.get(player());
|
JigsawEditor editor = JigsawEditor.editors.get(player());
|
||||||
|
|
||||||
if(editor == null) {
|
if (editor == null) {
|
||||||
sender().sendMessage(C.GOLD + "You don't have any pieces open to exit!");
|
sender().sendMessage(C.GOLD + "You don't have any pieces open to exit!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -101,7 +110,7 @@ public class CommandJigsaw implements DecreeExecutor {
|
|||||||
public void save() {
|
public void save() {
|
||||||
JigsawEditor editor = JigsawEditor.editors.get(player());
|
JigsawEditor editor = JigsawEditor.editors.get(player());
|
||||||
|
|
||||||
if(editor == null) {
|
if (editor == null) {
|
||||||
sender().sendMessage(C.GOLD + "You don't have any pieces open to save!");
|
sender().sendMessage(C.GOLD + "You don't have any pieces open to save!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -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,21 +48,13 @@ 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) {
|
||||||
|
|
||||||
@@ -87,11 +74,14 @@ public class CommandObject implements DecreeExecutor {
|
|||||||
Block block = world.getBlockAt(x, y, z);
|
Block block = world.getBlockAt(x, y, z);
|
||||||
|
|
||||||
//Prevent blocks being set in or bellow bedrock
|
//Prevent blocks being set in or bellow bedrock
|
||||||
if(y <= world.getMinHeight() || block.getType() == Material.BEDROCK) return;
|
if (y <= world.getMinHeight() || block.getType() == Material.BEDROCK) return;
|
||||||
|
|
||||||
futureBlockChanges.put(block, block.getBlockData());
|
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
|
||||||
@@ -145,7 +133,7 @@ public class CommandObject implements DecreeExecutor {
|
|||||||
|
|
||||||
@Decree(description = "Check the composition of an object")
|
@Decree(description = "Check the composition of an object")
|
||||||
public void analyze(
|
public void analyze(
|
||||||
@Param(description = "The object to analyze", customHandler = ObjectHandler.class)
|
@Param(description = "The object to analyze", customHandler = ObjectHandler.class)
|
||||||
String object
|
String object
|
||||||
) {
|
) {
|
||||||
IrisObject o = IrisData.loadAnyObject(object);
|
IrisObject o = IrisData.loadAnyObject(object);
|
||||||
@@ -156,19 +144,19 @@ public class CommandObject implements DecreeExecutor {
|
|||||||
Map<Material, Set<BlockData>> unsorted = new HashMap<>();
|
Map<Material, Set<BlockData>> unsorted = new HashMap<>();
|
||||||
Map<BlockData, Integer> amounts = new HashMap<>();
|
Map<BlockData, Integer> amounts = new HashMap<>();
|
||||||
Map<Material, Integer> materials = new HashMap<>();
|
Map<Material, Integer> materials = new HashMap<>();
|
||||||
while(queue.hasNext()) {
|
while (queue.hasNext()) {
|
||||||
BlockData block = queue.next();
|
BlockData block = queue.next();
|
||||||
|
|
||||||
//unsorted.put(block.getMaterial(), block);
|
//unsorted.put(block.getMaterial(), block);
|
||||||
|
|
||||||
if(!amounts.containsKey(block)) {
|
if (!amounts.containsKey(block)) {
|
||||||
amounts.put(block, 1);
|
amounts.put(block, 1);
|
||||||
|
|
||||||
|
|
||||||
} else
|
} else
|
||||||
amounts.put(block, amounts.get(block) + 1);
|
amounts.put(block, amounts.get(block) + 1);
|
||||||
|
|
||||||
if(!materials.containsKey(block.getMaterial())) {
|
if (!materials.containsKey(block.getMaterial())) {
|
||||||
materials.put(block.getMaterial(), 1);
|
materials.put(block.getMaterial(), 1);
|
||||||
unsorted.put(block.getMaterial(), new HashSet<>());
|
unsorted.put(block.getMaterial(), new HashSet<>());
|
||||||
unsorted.get(block.getMaterial()).add(block);
|
unsorted.get(block.getMaterial()).add(block);
|
||||||
@@ -180,13 +168,13 @@ 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 ==");
|
||||||
|
|
||||||
int n = 0;
|
int n = 0;
|
||||||
for(Material mat : sortedMats) {
|
for (Material mat : sortedMats) {
|
||||||
int amount = materials.get(mat);
|
int amount = materials.get(mat);
|
||||||
List<BlockData> set = new ArrayList<>(unsorted.get(mat));
|
List<BlockData> set = new ArrayList<>(unsorted.get(mat));
|
||||||
set.sort(Comparator.comparingInt(amounts::get).reversed());
|
set.sort(Comparator.comparingInt(amounts::get).reversed());
|
||||||
@@ -194,23 +182,47 @@ public class CommandObject implements DecreeExecutor {
|
|||||||
int dataAmount = amounts.get(data);
|
int dataAmount = amounts.get(data);
|
||||||
|
|
||||||
String string = " - " + mat.toString() + "*" + amount;
|
String string = " - " + mat.toString() + "*" + amount;
|
||||||
if(data.getAsString(true).contains("[")) {
|
if (data.getAsString(true).contains("[")) {
|
||||||
string = string + " --> [" + data.getAsString(true).split("\\[")[1]
|
string = string + " --> [" + data.getAsString(true).split("\\[")[1]
|
||||||
.replaceAll("true", ChatColor.GREEN + "true" + ChatColor.GRAY)
|
.replaceAll("true", ChatColor.GREEN + "true" + ChatColor.GRAY)
|
||||||
.replaceAll("false", ChatColor.RED + "false" + ChatColor.GRAY) + "*" + dataAmount;
|
.replaceAll("false", ChatColor.RED + "false" + ChatColor.GRAY) + "*" + dataAmount;
|
||||||
}
|
}
|
||||||
|
|
||||||
sender().sendMessage(string);
|
sender().sendMessage(string);
|
||||||
|
|
||||||
n++;
|
n++;
|
||||||
|
|
||||||
if(n >= 10) {
|
if (n >= 10) {
|
||||||
sender().sendMessage(" + " + (sortedMats.size() - n) + " other block types");
|
sender().sendMessage(" + " + (sortedMats.size() - n) + " other block types");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Decree(description = "Shrink an object to its minimum size")
|
||||||
|
public void shrink(@Param(description = "The object to shrink", customHandler = ObjectHandler.class) String object) {
|
||||||
|
IrisObject o = IrisData.loadAnyObject(object);
|
||||||
|
sender().sendMessage("Current Object Size: " + o.getW() + " * " + o.getH() + " * " + o.getD());
|
||||||
|
o.shrinkwrap();
|
||||||
|
sender().sendMessage("New Object Size: " + o.getW() + " * " + o.getH() + " * " + o.getD());
|
||||||
|
try {
|
||||||
|
o.write(o.getLoadFile());
|
||||||
|
} catch (IOException e) {
|
||||||
|
sender().sendMessage("Failed to save object " + o.getLoadFile() + ": " + e.getMessage());
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Decree(description = "Convert .schem files in the 'convert' folder to .iob files.")
|
||||||
|
public void convert () {
|
||||||
|
try {
|
||||||
|
IrisConverter.convertSchematics(sender());
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Decree(description = "Get a powder that reveals objects", studio = true, aliases = "d")
|
@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());
|
||||||
@@ -219,16 +231,19 @@ public class CommandObject implements DecreeExecutor {
|
|||||||
|
|
||||||
@Decree(description = "Contract a selection based on your looking direction", aliases = "-")
|
@Decree(description = "Contract a selection based on your looking direction", aliases = "-")
|
||||||
public void contract(
|
public void contract(
|
||||||
@Param(description = "The amount to inset by", defaultValue = "1")
|
@Param(description = "The amount to inset by", defaultValue = "1")
|
||||||
int amount
|
int amount
|
||||||
) {
|
) {
|
||||||
if(!WandSVC.isHoldingWand(player())) {
|
if (!WandSVC.isHoldingWand(player())) {
|
||||||
sender().sendMessage("Hold your wand.");
|
sender().sendMessage("Hold your wand.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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);
|
||||||
@@ -244,18 +259,21 @@ public class CommandObject implements DecreeExecutor {
|
|||||||
|
|
||||||
@Decree(description = "Set point 1 to look", aliases = "p1")
|
@Decree(description = "Set point 1 to look", aliases = "p1")
|
||||||
public void position1(
|
public void position1(
|
||||||
@Param(description = "Whether to use your current position, or where you look", defaultValue = "true")
|
@Param(description = "Whether to use your current position, or where you look", defaultValue = "true")
|
||||||
boolean here
|
boolean here
|
||||||
) {
|
) {
|
||||||
if(!WandSVC.isHoldingWand(player())) {
|
if (!WandSVC.isHoldingWand(player())) {
|
||||||
sender().sendMessage("Ready your Wand.");
|
sender().sendMessage("Ready your Wand.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(WandSVC.isHoldingWand(player())) {
|
if (WandSVC.isHoldingWand(player())) {
|
||||||
Location[] g = WandSVC.getCuboid(player());
|
Location[] g = WandSVC.getCuboid(player());
|
||||||
|
|
||||||
if(!here) {
|
if (g == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!here) {
|
||||||
// TODO: WARNING HEIGHT
|
// TODO: WARNING HEIGHT
|
||||||
g[1] = player().getTargetBlock(null, 256).getLocation().clone();
|
g[1] = player().getTargetBlock(null, 256).getLocation().clone();
|
||||||
} else {
|
} else {
|
||||||
@@ -267,18 +285,22 @@ public class CommandObject implements DecreeExecutor {
|
|||||||
|
|
||||||
@Decree(description = "Set point 2 to look", aliases = "p2")
|
@Decree(description = "Set point 2 to look", aliases = "p2")
|
||||||
public void position2(
|
public void position2(
|
||||||
@Param(description = "Whether to use your current position, or where you look", defaultValue = "true")
|
@Param(description = "Whether to use your current position, or where you look", defaultValue = "true")
|
||||||
boolean here
|
boolean here
|
||||||
) {
|
) {
|
||||||
if(!WandSVC.isHoldingWand(player())) {
|
if (!WandSVC.isHoldingWand(player())) {
|
||||||
sender().sendMessage("Ready your Wand.");
|
sender().sendMessage("Ready your Wand.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(WandSVC.isHoldingIrisWand(player())) {
|
if (WandSVC.isHoldingIrisWand(player())) {
|
||||||
Location[] g = WandSVC.getCuboid(player());
|
Location[] g = WandSVC.getCuboid(player());
|
||||||
|
|
||||||
if(!here) {
|
if (g == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!here) {
|
||||||
// TODO: WARNING HEIGHT
|
// TODO: WARNING HEIGHT
|
||||||
g[0] = player().getTargetBlock(null, 256).getLocation().clone();
|
g[0] = player().getTargetBlock(null, 256).getLocation().clone();
|
||||||
} else {
|
} else {
|
||||||
@@ -290,13 +312,13 @@ public class CommandObject implements DecreeExecutor {
|
|||||||
|
|
||||||
@Decree(description = "Paste an object", sync = true)
|
@Decree(description = "Paste an object", sync = true)
|
||||||
public void paste(
|
public void paste(
|
||||||
@Param(description = "The object to paste", customHandler = ObjectHandler.class)
|
@Param(description = "The object to paste", customHandler = ObjectHandler.class)
|
||||||
String object,
|
String object,
|
||||||
@Param(description = "Whether or not to edit the object (need to hold wand)", defaultValue = "false")
|
@Param(description = "Whether or not to edit the object (need to hold wand)", defaultValue = "false")
|
||||||
boolean edit,
|
boolean edit,
|
||||||
@Param(description = "The amount of degrees to rotate by", defaultValue = "0")
|
@Param(description = "The amount of degrees to rotate by", defaultValue = "0")
|
||||||
int rotate,
|
int rotate,
|
||||||
@Param(description = "The factor by which to scale the object placement", defaultValue = "1")
|
@Param(description = "The factor by which to scale the object placement", defaultValue = "1")
|
||||||
double scale
|
double scale
|
||||||
// ,
|
// ,
|
||||||
// @Param(description = "The scale interpolator to use", defaultValue = "none")
|
// @Param(description = "The scale interpolator to use", defaultValue = "none")
|
||||||
@@ -304,7 +326,7 @@ public class CommandObject implements DecreeExecutor {
|
|||||||
) {
|
) {
|
||||||
IrisObject o = IrisData.loadAnyObject(object);
|
IrisObject o = IrisData.loadAnyObject(object);
|
||||||
double maxScale = Double.max(10 - o.getBlocks().size() / 10000d, 1);
|
double maxScale = Double.max(10 - o.getBlocks().size() / 10000d, 1);
|
||||||
if(scale > maxScale) {
|
if (scale > maxScale) {
|
||||||
sender().sendMessage(C.YELLOW + "Indicated scale exceeds maximum. Downscaled to maximum: " + maxScale);
|
sender().sendMessage(C.YELLOW + "Indicated scale exceeds maximum. Downscaled to maximum: " + maxScale);
|
||||||
scale = maxScale;
|
scale = maxScale;
|
||||||
}
|
}
|
||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -328,16 +349,16 @@ public class CommandObject implements DecreeExecutor {
|
|||||||
|
|
||||||
Iris.service(ObjectSVC.class).addChanges(futureChanges);
|
Iris.service(ObjectSVC.class).addChanges(futureChanges);
|
||||||
|
|
||||||
if(edit) {
|
if (edit) {
|
||||||
ItemStack newWand = WandSVC.createWand(block.clone().subtract(o.getCenter()).add(o.getW() - 1,
|
ItemStack newWand = WandSVC.createWand(block.clone().subtract(o.getCenter()).add(o.getW() - 1,
|
||||||
o.getH() + o.getCenter().clone().getY() - 1, o.getD() - 1), block.clone().subtract(o.getCenter().clone().setY(0)));
|
o.getH() + o.getCenter().clone().getY() - 1, o.getD() - 1), block.clone().subtract(o.getCenter().clone().setY(0)));
|
||||||
if(WandSVC.isWand(wand)) {
|
if (WandSVC.isWand(wand)) {
|
||||||
wand = newWand;
|
wand = newWand;
|
||||||
player().getInventory().setItemInMainHand(wand);
|
player().getInventory().setItemInMainHand(wand);
|
||||||
sender().sendMessage("Updated wand for " + "objects/" + o.getLoadKey() + ".iob ");
|
sender().sendMessage("Updated wand for " + "objects/" + o.getLoadKey() + ".iob ");
|
||||||
} else {
|
} else {
|
||||||
int slot = WandSVC.findWand(player().getInventory());
|
int slot = WandSVC.findWand(player().getInventory());
|
||||||
if(slot == -1) {
|
if (slot == -1) {
|
||||||
player().getInventory().addItem(newWand);
|
player().getInventory().addItem(newWand);
|
||||||
sender().sendMessage("Given new wand for " + "objects/" + o.getLoadKey() + ".iob ");
|
sender().sendMessage("Given new wand for " + "objects/" + o.getLoadKey() + ".iob ");
|
||||||
} else {
|
} else {
|
||||||
@@ -346,35 +367,37 @@ public class CommandObject implements DecreeExecutor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sender().sendMessage("Placed " + object);
|
sender().sendMessage(C.IRIS + "Placed " + object);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Decree(description = "Save an object")
|
@Decree(description = "Save an object")
|
||||||
public void save(
|
public void save(
|
||||||
@Param(description = "The dimension to store the object in", contextual = true)
|
@Param(description = "The dimension to store the object in", contextual = true)
|
||||||
IrisDimension dimension,
|
IrisDimension dimension,
|
||||||
@Param(description = "The file to store it in, can use / for subfolders")
|
@Param(description = "The file to store it in, can use / for subfolders")
|
||||||
String name,
|
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!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
File file = Iris.service(StudioSVC.class).getWorkspaceFile(dimension.getLoadKey(), "objects", name + ".iob");
|
File file = Iris.service(StudioSVC.class).getWorkspaceFile(dimension.getLoadKey(), "objects", name + ".iob");
|
||||||
|
|
||||||
if(file.exists() && !overwrite) {
|
if (file.exists() && !overwrite) {
|
||||||
sender().sendMessage(C.RED + "File already exists. Set overwrite=true to overwrite it.");
|
sender().sendMessage(C.RED + "File already exists. Set overwrite=true to overwrite it.");
|
||||||
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);
|
||||||
}
|
}
|
||||||
@@ -385,10 +408,10 @@ public class CommandObject implements DecreeExecutor {
|
|||||||
|
|
||||||
@Decree(description = "Shift a selection in your looking direction", aliases = "-")
|
@Decree(description = "Shift a selection in your looking direction", aliases = "-")
|
||||||
public void shift(
|
public void shift(
|
||||||
@Param(description = "The amount to shift by", defaultValue = "1")
|
@Param(description = "The amount to shift by", defaultValue = "1")
|
||||||
int amount
|
int amount
|
||||||
) {
|
) {
|
||||||
if(!WandSVC.isHoldingWand(player())) {
|
if (!WandSVC.isHoldingWand(player())) {
|
||||||
sender().sendMessage("Hold your wand.");
|
sender().sendMessage("Hold your wand.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -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);
|
||||||
@@ -409,26 +435,25 @@ public class CommandObject implements DecreeExecutor {
|
|||||||
|
|
||||||
@Decree(description = "Undo a number of pastes", aliases = "-")
|
@Decree(description = "Undo a number of pastes", aliases = "-")
|
||||||
public void undo(
|
public void undo(
|
||||||
@Param(description = "The amount of pastes to undo", defaultValue = "1")
|
@Param(description = "The amount of pastes to undo", defaultValue = "1")
|
||||||
int amount
|
int amount
|
||||||
) {
|
) {
|
||||||
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)
|
||||||
public void we() {
|
public void we() {
|
||||||
if(!Bukkit.getPluginManager().isPluginEnabled("WorldEdit")) {
|
if (!Bukkit.getPluginManager().isPluginEnabled("WorldEdit")) {
|
||||||
sender().sendMessage(C.RED + "You can't get a WorldEdit selection without WorldEdit, you know.");
|
sender().sendMessage(C.RED + "You can't get a WorldEdit selection without WorldEdit, you know.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
@@ -446,7 +471,7 @@ public class CommandObject implements DecreeExecutor {
|
|||||||
|
|
||||||
@Decree(name = "x&y", description = "Autoselect up, down & out", sync = true)
|
@Decree(name = "x&y", description = "Autoselect up, down & out", sync = true)
|
||||||
public void xay() {
|
public void xay() {
|
||||||
if(!WandSVC.isHoldingWand(player())) {
|
if (!WandSVC.isHoldingWand(player())) {
|
||||||
sender().sendMessage(C.YELLOW + "Hold your wand!");
|
sender().sendMessage(C.YELLOW + "Hold your wand!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -459,7 +484,7 @@ public class CommandObject implements DecreeExecutor {
|
|||||||
Cuboid cursor = new Cuboid(a1, a2);
|
Cuboid cursor = new Cuboid(a1, a2);
|
||||||
Cuboid cursorx = new Cuboid(a1, a2);
|
Cuboid cursorx = new Cuboid(a1, a2);
|
||||||
|
|
||||||
while(!cursor.containsOnly(Material.AIR)) {
|
while (!cursor.containsOnly(Material.AIR)) {
|
||||||
a1.add(new org.bukkit.util.Vector(0, 1, 0));
|
a1.add(new org.bukkit.util.Vector(0, 1, 0));
|
||||||
a2.add(new org.bukkit.util.Vector(0, 1, 0));
|
a2.add(new org.bukkit.util.Vector(0, 1, 0));
|
||||||
cursor = new Cuboid(a1, a2);
|
cursor = new Cuboid(a1, a2);
|
||||||
@@ -468,7 +493,7 @@ public class CommandObject implements DecreeExecutor {
|
|||||||
a1.add(new org.bukkit.util.Vector(0, -1, 0));
|
a1.add(new org.bukkit.util.Vector(0, -1, 0));
|
||||||
a2.add(new org.bukkit.util.Vector(0, -1, 0));
|
a2.add(new org.bukkit.util.Vector(0, -1, 0));
|
||||||
|
|
||||||
while(!cursorx.containsOnly(Material.AIR)) {
|
while (!cursorx.containsOnly(Material.AIR)) {
|
||||||
a1x.add(new org.bukkit.util.Vector(0, -1, 0));
|
a1x.add(new org.bukkit.util.Vector(0, -1, 0));
|
||||||
a2x.add(new org.bukkit.util.Vector(0, -1, 0));
|
a2x.add(new org.bukkit.util.Vector(0, -1, 0));
|
||||||
cursorx = new Cuboid(a1x, a2x);
|
cursorx = new Cuboid(a1x, a2x);
|
||||||
@@ -493,7 +518,7 @@ public class CommandObject implements DecreeExecutor {
|
|||||||
|
|
||||||
@Decree(name = "x+y", description = "Autoselect up & out", sync = true)
|
@Decree(name = "x+y", description = "Autoselect up & out", sync = true)
|
||||||
public void xpy() {
|
public void xpy() {
|
||||||
if(!WandSVC.isHoldingWand(player())) {
|
if (!WandSVC.isHoldingWand(player())) {
|
||||||
sender().sendMessage(C.YELLOW + "Hold your wand!");
|
sender().sendMessage(C.YELLOW + "Hold your wand!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -505,7 +530,7 @@ public class CommandObject implements DecreeExecutor {
|
|||||||
Location a2 = b[1].clone();
|
Location a2 = b[1].clone();
|
||||||
Cuboid cursor = new Cuboid(a1, a2);
|
Cuboid cursor = new Cuboid(a1, a2);
|
||||||
|
|
||||||
while(!cursor.containsOnly(Material.AIR)) {
|
while (!cursor.containsOnly(Material.AIR)) {
|
||||||
a1.add(new Vector(0, 1, 0));
|
a1.add(new Vector(0, 1, 0));
|
||||||
a2.add(new Vector(0, 1, 0));
|
a2.add(new Vector(0, 1, 0));
|
||||||
cursor = new Cuboid(a1, a2);
|
cursor = new Cuboid(a1, a2);
|
||||||
@@ -34,30 +34,30 @@ import org.bukkit.util.Vector;
|
|||||||
public class CommandPregen implements DecreeExecutor {
|
public class CommandPregen implements DecreeExecutor {
|
||||||
@Decree(description = "Pregenerate a world")
|
@Decree(description = "Pregenerate a world")
|
||||||
public void start(
|
public void start(
|
||||||
@Param(description = "The radius of the pregen in blocks", aliases = "size")
|
@Param(description = "The radius of the pregen in blocks", aliases = "size")
|
||||||
int radius,
|
int radius,
|
||||||
@Param(description = "The world to pregen", contextual = true)
|
@Param(description = "The world to pregen", contextual = true)
|
||||||
World world,
|
World world,
|
||||||
@Param(aliases = "middle", description = "The center location of the pregen. Use \"me\" for your current location", defaultValue = "0,0")
|
@Param(aliases = "middle", description = "The center location of the pregen. Use \"me\" for your current location", defaultValue = "0,0")
|
||||||
Vector center
|
Vector center
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
if(sender().isPlayer() && access() == null) {
|
if (sender().isPlayer() && access() == null) {
|
||||||
sender().sendMessage(C.RED + "The engine access for this world is null!");
|
sender().sendMessage(C.RED + "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.");
|
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)
|
||||||
.build(), world);
|
.radiusZ(radius)
|
||||||
|
.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);
|
||||||
Iris.info(msg);
|
Iris.info(msg);
|
||||||
} catch(Throwable e) {
|
} catch (Throwable e) {
|
||||||
sender().sendMessage(C.RED + "Epic fail. See console.");
|
sender().sendMessage(C.RED + "Epic fail. See console.");
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
@@ -66,8 +66,8 @@ 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");
|
||||||
}
|
}
|
||||||
@@ -75,7 +75,7 @@ public class CommandPregen implements DecreeExecutor {
|
|||||||
|
|
||||||
@Decree(description = "Pause / continue the active pregeneration task", aliases = {"t", "resume", "unpause"})
|
@Decree(description = "Pause / continue the active pregeneration task", aliases = {"t", "resume", "unpause"})
|
||||||
public void pause() {
|
public void pause() {
|
||||||
if(PregeneratorJob.pauseResume()) {
|
if (PregeneratorJob.pauseResume()) {
|
||||||
sender().sendMessage(C.GREEN + "Paused/unpaused pregeneration task, now: " + (PregeneratorJob.isPaused() ? "Paused" : "Running") + ".");
|
sender().sendMessage(C.GREEN + "Paused/unpaused pregeneration task, now: " + (PregeneratorJob.isPaused() ? "Paused" : "Running") + ".");
|
||||||
} else {
|
} else {
|
||||||
sender().sendMessage(C.YELLOW + "No active pregeneration tasks to pause/unpause.");
|
sender().sendMessage(C.YELLOW + "No active pregeneration tasks to pause/unpause.");
|
||||||
@@ -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,32 +73,33 @@ 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")
|
||||||
String pack,
|
String pack,
|
||||||
@Param(name = "branch", description = "The branch to download from", defaultValue = "master")
|
@Param(name = "branch", description = "The branch to download from", defaultValue = "master")
|
||||||
String branch,
|
String branch,
|
||||||
@Param(name = "trim", description = "Whether or not to download a trimmed version (do not enable when editing)", defaultValue = "false")
|
@Param(name = "trim", description = "Whether or not to download a trimmed version (do not enable when editing)", defaultValue = "false")
|
||||||
boolean trim,
|
boolean trim,
|
||||||
@Param(name = "overwrite", description = "Whether or not to overwrite the pack with the downloaded one", aliases = "force", defaultValue = "false")
|
@Param(name = "overwrite", description = "Whether or not to overwrite the pack with the downloaded one", aliases = "force", defaultValue = "false")
|
||||||
boolean overwrite
|
boolean overwrite
|
||||||
) {
|
) {
|
||||||
new CommandIris().download(pack, branch, trim, overwrite);
|
new CommandIris().download(pack, branch, trim, overwrite);
|
||||||
@@ -124,9 +107,9 @@ public class CommandStudio implements DecreeExecutor {
|
|||||||
|
|
||||||
@Decree(description = "Open a new studio world", aliases = "o", sync = true)
|
@Decree(description = "Open a new studio world", aliases = "o", sync = true)
|
||||||
public void open(
|
public void open(
|
||||||
@Param(defaultValue = "default", description = "The dimension to open a studio for", aliases = "dim")
|
@Param(defaultValue = "default", description = "The dimension to open a studio for", aliases = "dim")
|
||||||
IrisDimension dimension,
|
IrisDimension dimension,
|
||||||
@Param(defaultValue = "1337", description = "The seed to generate the studio with", aliases = "s")
|
@Param(defaultValue = "1337", description = "The seed to generate the studio with", aliases = "s")
|
||||||
long seed) {
|
long seed) {
|
||||||
sender().sendMessage(C.GREEN + "Opening studio for the \"" + dimension.getName() + "\" pack (seed: " + seed + ")");
|
sender().sendMessage(C.GREEN + "Opening studio for the \"" + dimension.getName() + "\" pack (seed: " + seed + ")");
|
||||||
Iris.service(StudioSVC.class).open(sender(), seed, dimension.getLoadKey());
|
Iris.service(StudioSVC.class).open(sender(), seed, dimension.getLoadKey());
|
||||||
@@ -134,7 +117,7 @@ public class CommandStudio implements DecreeExecutor {
|
|||||||
|
|
||||||
@Decree(description = "Open VSCode for a dimension", aliases = {"vsc", "edit"})
|
@Decree(description = "Open VSCode for a dimension", aliases = {"vsc", "edit"})
|
||||||
public void vscode(
|
public void vscode(
|
||||||
@Param(defaultValue = "default", description = "The dimension to open VSCode for", aliases = "dim")
|
@Param(defaultValue = "default", description = "The dimension to open VSCode for", aliases = "dim")
|
||||||
IrisDimension dimension
|
IrisDimension dimension
|
||||||
) {
|
) {
|
||||||
sender().sendMessage(C.GREEN + "Opening VSCode for the \"" + dimension.getName() + "\" pack");
|
sender().sendMessage(C.GREEN + "Opening VSCode for the \"" + dimension.getName() + "\" pack");
|
||||||
@@ -143,7 +126,7 @@ public class CommandStudio implements DecreeExecutor {
|
|||||||
|
|
||||||
@Decree(description = "Close an open studio project", aliases = {"x", "c"}, sync = true)
|
@Decree(description = "Close an open studio project", aliases = {"x", "c"}, sync = true)
|
||||||
public void close() {
|
public void close() {
|
||||||
if(!Iris.service(StudioSVC.class).isProjectOpen()) {
|
if (!Iris.service(StudioSVC.class).isProjectOpen()) {
|
||||||
sender().sendMessage(C.RED + "No open studio projects.");
|
sender().sendMessage(C.RED + "No open studio projects.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -154,158 +137,105 @@ public class CommandStudio implements DecreeExecutor {
|
|||||||
|
|
||||||
@Decree(description = "Create a new studio project", aliases = "+", sync = true)
|
@Decree(description = "Create a new studio project", aliases = "+", sync = true)
|
||||||
public void create(
|
public void create(
|
||||||
@Param(description = "The name of this new Iris Project.")
|
@Param(description = "The name of this new Iris Project.")
|
||||||
String name,
|
String name,
|
||||||
@Param(description = "Copy the contents of an existing project in your packs folder and use it as a template in this new project.", contextual = true)
|
@Param(description = "Copy the contents of an existing project in your packs folder and use it as a template in this new project.", contextual = true)
|
||||||
IrisDimension template) {
|
IrisDimension template) {
|
||||||
if(template != null) {
|
if (template != null) {
|
||||||
Iris.service(StudioSVC.class).create(sender(), name, template.getLoadKey());
|
Iris.service(StudioSVC.class).create(sender(), name, template.getLoadKey());
|
||||||
} else {
|
} else {
|
||||||
Iris.service(StudioSVC.class).create(sender(), name);
|
Iris.service(StudioSVC.class).create(sender(), name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@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)
|
||||||
IrisDimension dimension
|
IrisDimension dimension
|
||||||
) {
|
) {
|
||||||
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")
|
||||||
IrisScript script
|
IrisScript script
|
||||||
) {
|
) {
|
||||||
engine().getExecution().execute(script.getLoadKey());
|
engine().getExecution().execute(script.getLoadKey());
|
||||||
@@ -313,14 +243,14 @@ public class CommandStudio implements DecreeExecutor {
|
|||||||
|
|
||||||
@Decree(description = "Open the noise explorer (External GUI)", aliases = {"nmap", "n"})
|
@Decree(description = "Open the noise explorer (External GUI)", aliases = {"nmap", "n"})
|
||||||
public void noise() {
|
public void noise() {
|
||||||
if(noGUI()) return;
|
if (noGUI()) return;
|
||||||
sender().sendMessage(C.GREEN + "Opening Noise Explorer!");
|
sender().sendMessage(C.GREEN + "Opening Noise Explorer!");
|
||||||
NoiseExplorerGUI.launch();
|
NoiseExplorerGUI.launch();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Decree(description = "Charges all spawners in the area", aliases = "zzt", origin = DecreeOrigin.PLAYER)
|
@Decree(description = "Charges all spawners in the area", aliases = "zzt", origin = DecreeOrigin.PLAYER)
|
||||||
public void charge() {
|
public void charge() {
|
||||||
if(!IrisToolbelt.isIrisWorld(world())) {
|
if (!IrisToolbelt.isIrisWorld(world())) {
|
||||||
sender().sendMessage(C.RED + "You must be in an Iris world to charge spawners!");
|
sender().sendMessage(C.RED + "You must be in an Iris world to charge spawners!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -330,17 +260,17 @@ public class CommandStudio implements DecreeExecutor {
|
|||||||
|
|
||||||
@Decree(description = "Preview noise gens (External GUI)", aliases = {"generator", "gen"})
|
@Decree(description = "Preview noise gens (External GUI)", aliases = {"generator", "gen"})
|
||||||
public void explore(
|
public void explore(
|
||||||
@Param(description = "The generator to explore", contextual = true)
|
@Param(description = "The generator to explore", contextual = true)
|
||||||
IrisGenerator generator,
|
IrisGenerator generator,
|
||||||
@Param(description = "The seed to generate with", defaultValue = "12345")
|
@Param(description = "The seed to generate with", defaultValue = "12345")
|
||||||
long seed
|
long seed
|
||||||
) {
|
) {
|
||||||
if(noGUI()) return;
|
if (noGUI()) return;
|
||||||
sender().sendMessage(C.GREEN + "Opening Noise Explorer!");
|
sender().sendMessage(C.GREEN + "Opening Noise Explorer!");
|
||||||
|
|
||||||
Supplier<Function2<Double, Double, Double>> l = () -> {
|
Supplier<Function2<Double, Double, Double>> l = () -> {
|
||||||
|
|
||||||
if(generator == null) {
|
if (generator == null) {
|
||||||
return (x, z) -> 0D;
|
return (x, z) -> 0D;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -351,7 +281,7 @@ public class CommandStudio implements DecreeExecutor {
|
|||||||
|
|
||||||
@Decree(description = "Hotload a studio", aliases = {"reload", "h"})
|
@Decree(description = "Hotload a studio", aliases = {"reload", "h"})
|
||||||
public void hotload() {
|
public void hotload() {
|
||||||
if(!Iris.service(StudioSVC.class).isProjectOpen()) {
|
if (!Iris.service(StudioSVC.class).isProjectOpen()) {
|
||||||
sender().sendMessage(C.RED + "No studio world open!");
|
sender().sendMessage(C.RED + "No studio world open!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -361,19 +291,19 @@ public class CommandStudio implements DecreeExecutor {
|
|||||||
|
|
||||||
@Decree(description = "Show loot if a chest were right here", origin = DecreeOrigin.PLAYER, sync = true)
|
@Decree(description = "Show loot if a chest were right here", origin = DecreeOrigin.PLAYER, sync = true)
|
||||||
public void loot(
|
public void loot(
|
||||||
@Param(description = "Fast insertion of items in virtual inventory (may cause performance drop)", defaultValue = "false")
|
@Param(description = "Fast insertion of items in virtual inventory (may cause performance drop)", defaultValue = "false")
|
||||||
boolean fast,
|
boolean fast,
|
||||||
@Param(description = "Whether or not to append to the inventory currently open (if false, clears opened inventory)", defaultValue = "true")
|
@Param(description = "Whether or not to append to the inventory currently open (if false, clears opened inventory)", defaultValue = "true")
|
||||||
boolean add
|
boolean add
|
||||||
) {
|
) {
|
||||||
if(noStudio()) return;
|
if (noStudio()) return;
|
||||||
|
|
||||||
KList<IrisLootTable> tables = engine().getLootTables(RNG.r, player().getLocation().getBlock());
|
KList<IrisLootTable> tables = engine().getLootTables(RNG.r, player().getLocation().getBlock());
|
||||||
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());
|
||||||
return;
|
return;
|
||||||
@@ -385,31 +315,98 @@ public class CommandStudio implements DecreeExecutor {
|
|||||||
|
|
||||||
ta.set(Bukkit.getScheduler().scheduleSyncRepeatingTask(Iris.instance, () ->
|
ta.set(Bukkit.getScheduler().scheduleSyncRepeatingTask(Iris.instance, () ->
|
||||||
{
|
{
|
||||||
if(!player().getOpenInventory().getType().equals(InventoryType.CHEST)) {
|
if (!player().getOpenInventory().getType().equals(InventoryType.CHEST)) {
|
||||||
Bukkit.getScheduler().cancelTask(ta.get());
|
Bukkit.getScheduler().cancelTask(ta.get());
|
||||||
sender().sendMessage(C.GREEN + "Opened inventory!");
|
sender().sendMessage(C.GREEN + "Opened inventory!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!add) {
|
if (!add) {
|
||||||
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)
|
||||||
World world
|
World world
|
||||||
) {
|
) {
|
||||||
if(noGUI()) return;
|
if (noGUI()) return;
|
||||||
|
|
||||||
if(!IrisToolbelt.isIrisWorld(world)) {
|
if (!IrisToolbelt.isIrisWorld(world)) {
|
||||||
sender().sendMessage(C.RED + "You need to be in or specify an Iris-generated world!");
|
sender().sendMessage(C.RED + "You need to be in or specify an Iris-generated world!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -420,11 +417,11 @@ public class CommandStudio implements DecreeExecutor {
|
|||||||
|
|
||||||
@Decree(description = "Package a dimension into a compressed format", aliases = "package")
|
@Decree(description = "Package a dimension into a compressed format", aliases = "package")
|
||||||
public void pkg(
|
public void pkg(
|
||||||
@Param(name = "dimension", description = "The dimension pack to compress", contextual = true, defaultValue = "default")
|
@Param(name = "dimension", description = "The dimension pack to compress", contextual = true, defaultValue = "default")
|
||||||
IrisDimension dimension,
|
IrisDimension dimension,
|
||||||
@Param(name = "obfuscate", description = "Whether or not to obfuscate the pack", defaultValue = "false")
|
@Param(name = "obfuscate", description = "Whether or not to obfuscate the pack", defaultValue = "false")
|
||||||
boolean obfuscate,
|
boolean obfuscate,
|
||||||
@Param(name = "minify", description = "Whether or not to minify the pack", defaultValue = "true")
|
@Param(name = "minify", description = "Whether or not to minify the pack", defaultValue = "true")
|
||||||
boolean minify
|
boolean minify
|
||||||
) {
|
) {
|
||||||
Iris.service(StudioSVC.class).compilePackage(sender(), dimension.getLoadKey(), obfuscate, minify);
|
Iris.service(StudioSVC.class).compilePackage(sender(), dimension.getLoadKey(), obfuscate, minify);
|
||||||
@@ -432,9 +429,10 @@ public class CommandStudio implements DecreeExecutor {
|
|||||||
|
|
||||||
@Decree(description = "Profiles the performance of a dimension", origin = DecreeOrigin.PLAYER)
|
@Decree(description = "Profiles the performance of a dimension", origin = DecreeOrigin.PLAYER)
|
||||||
public void profile(
|
public void profile(
|
||||||
@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);
|
||||||
@@ -450,17 +448,17 @@ public class CommandStudio implements DecreeExecutor {
|
|||||||
|
|
||||||
sender().sendMessage("Calculating Performance Metrics for Noise generators");
|
sender().sendMessage("Calculating Performance Metrics for Noise generators");
|
||||||
|
|
||||||
for(NoiseStyle i : NoiseStyle.values()) {
|
for (NoiseStyle i : NoiseStyle.values()) {
|
||||||
CNG c = i.create(new RNG(i.hashCode()));
|
CNG c = i.create(new RNG(i.hashCode()));
|
||||||
|
|
||||||
for(int j = 0; j < 3000; j++) {
|
for (int j = 0; j < 3000; j++) {
|
||||||
c.noise(j, j + 1000, j * j);
|
c.noise(j, j + 1000, j * j);
|
||||||
c.noise(j, -j);
|
c.noise(j, -j);
|
||||||
}
|
}
|
||||||
|
|
||||||
PrecisionStopwatch px = PrecisionStopwatch.start();
|
PrecisionStopwatch px = PrecisionStopwatch.start();
|
||||||
|
|
||||||
for(int j = 0; j < 100000; j++) {
|
for (int j = 0; j < 100000; j++) {
|
||||||
c.noise(j, j + 1000, j * j);
|
c.noise(j, j + 1000, j * j);
|
||||||
c.noise(j, -j);
|
c.noise(j, -j);
|
||||||
}
|
}
|
||||||
@@ -470,7 +468,7 @@ public class CommandStudio implements DecreeExecutor {
|
|||||||
|
|
||||||
fileText.add("Noise Style Performance Impacts: ");
|
fileText.add("Noise Style Performance Impacts: ");
|
||||||
|
|
||||||
for(NoiseStyle i : styleTimings.sortKNumber()) {
|
for (NoiseStyle i : styleTimings.sortKNumber()) {
|
||||||
fileText.add(i.name() + ": " + styleTimings.get(i));
|
fileText.add(i.name() + ": " + styleTimings.get(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -478,20 +476,20 @@ public class CommandStudio implements DecreeExecutor {
|
|||||||
|
|
||||||
sender().sendMessage("Calculating Interpolator Timings...");
|
sender().sendMessage("Calculating Interpolator Timings...");
|
||||||
|
|
||||||
for(InterpolationMethod i : InterpolationMethod.values()) {
|
for (InterpolationMethod i : InterpolationMethod.values()) {
|
||||||
IrisInterpolator in = new IrisInterpolator();
|
IrisInterpolator in = new IrisInterpolator();
|
||||||
in.setFunction(i);
|
in.setFunction(i);
|
||||||
in.setHorizontalScale(8);
|
in.setHorizontalScale(8);
|
||||||
|
|
||||||
NoiseProvider np = (x, z) -> Math.random();
|
NoiseProvider np = (x, z) -> Math.random();
|
||||||
|
|
||||||
for(int j = 0; j < 3000; j++) {
|
for (int j = 0; j < 3000; j++) {
|
||||||
in.interpolate(j, -j, np);
|
in.interpolate(j, -j, np);
|
||||||
}
|
}
|
||||||
|
|
||||||
PrecisionStopwatch px = PrecisionStopwatch.start();
|
PrecisionStopwatch px = PrecisionStopwatch.start();
|
||||||
|
|
||||||
for(int j = 0; j < 100000; j++) {
|
for (int j = 0; j < 100000; j++) {
|
||||||
in.interpolate(j + 10000, -j - 100000, np);
|
in.interpolate(j + 10000, -j - 100000, np);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -500,7 +498,7 @@ public class CommandStudio implements DecreeExecutor {
|
|||||||
|
|
||||||
fileText.add("Noise Interpolator Performance Impacts: ");
|
fileText.add("Noise Interpolator Performance Impacts: ");
|
||||||
|
|
||||||
for(InterpolationMethod i : interpolatorTimings.sortKNumber()) {
|
for (InterpolationMethod i : interpolatorTimings.sortKNumber()) {
|
||||||
fileText.add(i.name() + ": " + interpolatorTimings.get(i));
|
fileText.add(i.name() + ": " + interpolatorTimings.get(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -510,13 +508,13 @@ public class CommandStudio implements DecreeExecutor {
|
|||||||
|
|
||||||
KMap<String, KList<String>> btx = new KMap<>();
|
KMap<String, KList<String>> btx = new KMap<>();
|
||||||
|
|
||||||
for(String i : data.getGeneratorLoader().getPossibleKeys()) {
|
for (String i : data.getGeneratorLoader().getPossibleKeys()) {
|
||||||
KList<String> vv = new KList<>();
|
KList<String> vv = new KList<>();
|
||||||
IrisGenerator g = data.getGeneratorLoader().load(i);
|
IrisGenerator g = data.getGeneratorLoader().load(i);
|
||||||
KList<IrisNoiseGenerator> composites = g.getAllComposites();
|
KList<IrisNoiseGenerator> composites = g.getAllComposites();
|
||||||
double score = 0;
|
double score = 0;
|
||||||
int m = 0;
|
int m = 0;
|
||||||
for(IrisNoiseGenerator j : composites) {
|
for (IrisNoiseGenerator j : composites) {
|
||||||
m++;
|
m++;
|
||||||
score += styleTimings.get(j.getStyle().getStyle());
|
score += styleTimings.get(j.getStyle().getStyle());
|
||||||
vv.add("Composite Noise Style " + m + " " + j.getStyle().getStyle().name() + ": " + styleTimings.get(j.getStyle().getStyle()));
|
vv.add("Composite Noise Style " + m + " " + j.getStyle().getStyle().name() + ": " + styleTimings.get(j.getStyle().getStyle()));
|
||||||
@@ -530,7 +528,7 @@ public class CommandStudio implements DecreeExecutor {
|
|||||||
|
|
||||||
fileText.add("Project Generator Performance Impacts: ");
|
fileText.add("Project Generator Performance Impacts: ");
|
||||||
|
|
||||||
for(String i : generatorTimings.sortKNumber()) {
|
for (String i : generatorTimings.sortKNumber()) {
|
||||||
fileText.add(i + ": " + generatorTimings.get(i));
|
fileText.add(i + ": " + generatorTimings.get(i));
|
||||||
|
|
||||||
btx.get(i).forEach((ii) -> fileText.add(" " + ii));
|
btx.get(i).forEach((ii) -> fileText.add(" " + ii));
|
||||||
@@ -540,13 +538,13 @@ public class CommandStudio implements DecreeExecutor {
|
|||||||
|
|
||||||
KMap<String, KList<String>> bt = new KMap<>();
|
KMap<String, KList<String>> bt = new KMap<>();
|
||||||
|
|
||||||
for(String i : data.getBiomeLoader().getPossibleKeys()) {
|
for (String i : data.getBiomeLoader().getPossibleKeys()) {
|
||||||
KList<String> vv = new KList<>();
|
KList<String> vv = new KList<>();
|
||||||
IrisBiome b = data.getBiomeLoader().load(i);
|
IrisBiome b = data.getBiomeLoader().load(i);
|
||||||
double score = 0;
|
double score = 0;
|
||||||
|
|
||||||
int m = 0;
|
int m = 0;
|
||||||
for(IrisBiomePaletteLayer j : b.getLayers()) {
|
for (IrisBiomePaletteLayer j : b.getLayers()) {
|
||||||
m++;
|
m++;
|
||||||
score += styleTimings.get(j.getStyle().getStyle());
|
score += styleTimings.get(j.getStyle().getStyle());
|
||||||
vv.add("Palette Layer " + m + ": " + styleTimings.get(j.getStyle().getStyle()));
|
vv.add("Palette Layer " + m + ": " + styleTimings.get(j.getStyle().getStyle()));
|
||||||
@@ -562,7 +560,7 @@ public class CommandStudio implements DecreeExecutor {
|
|||||||
|
|
||||||
fileText.add("Project Biome Performance Impacts: ");
|
fileText.add("Project Biome Performance Impacts: ");
|
||||||
|
|
||||||
for(String i : biomeTimings.sortKNumber()) {
|
for (String i : biomeTimings.sortKNumber()) {
|
||||||
fileText.add(i + ": " + biomeTimings.get(i));
|
fileText.add(i + ": " + biomeTimings.get(i));
|
||||||
|
|
||||||
bt.get(i).forEach((ff) -> fileText.add(" " + ff));
|
bt.get(i).forEach((ff) -> fileText.add(" " + ff));
|
||||||
@@ -570,7 +568,7 @@ public class CommandStudio implements DecreeExecutor {
|
|||||||
|
|
||||||
fileText.add("");
|
fileText.add("");
|
||||||
|
|
||||||
for(String i : data.getRegionLoader().getPossibleKeys()) {
|
for (String i : data.getRegionLoader().getPossibleKeys()) {
|
||||||
IrisRegion b = data.getRegionLoader().load(i);
|
IrisRegion b = data.getRegionLoader().load(i);
|
||||||
double score = 0;
|
double score = 0;
|
||||||
|
|
||||||
@@ -581,25 +579,25 @@ public class CommandStudio implements DecreeExecutor {
|
|||||||
|
|
||||||
fileText.add("Project Region Performance Impacts: ");
|
fileText.add("Project Region Performance Impacts: ");
|
||||||
|
|
||||||
for(String i : regionTimings.sortKNumber()) {
|
for (String i : regionTimings.sortKNumber()) {
|
||||||
fileText.add(i + ": " + regionTimings.get(i));
|
fileText.add(i + ": " + regionTimings.get(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
fileText.add("");
|
fileText.add("");
|
||||||
|
|
||||||
double m = 0;
|
double m = 0;
|
||||||
for(double i : biomeTimings.v()) {
|
for (double i : biomeTimings.v()) {
|
||||||
m += i;
|
m += i;
|
||||||
}
|
}
|
||||||
m /= biomeTimings.size();
|
m /= biomeTimings.size();
|
||||||
double mm = 0;
|
double mm = 0;
|
||||||
for(double i : generatorTimings.v()) {
|
for (double i : generatorTimings.v()) {
|
||||||
mm += i;
|
mm += i;
|
||||||
}
|
}
|
||||||
mm /= generatorTimings.size();
|
mm /= generatorTimings.size();
|
||||||
m += mm;
|
m += mm;
|
||||||
double mmm = 0;
|
double mmm = 0;
|
||||||
for(double i : regionTimings.v()) {
|
for (double i : regionTimings.v()) {
|
||||||
mmm += i;
|
mmm += i;
|
||||||
}
|
}
|
||||||
mmm /= regionTimings.size();
|
mmm /= regionTimings.size();
|
||||||
@@ -610,7 +608,7 @@ public class CommandStudio implements DecreeExecutor {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
IO.writeAll(report, fileText.toString("\n"));
|
IO.writeAll(report, fileText.toString("\n"));
|
||||||
} catch(IOException e) {
|
} catch (IOException e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@@ -618,30 +616,27 @@ 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()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Decree(description = "Teleport to the active studio world", aliases = "stp", origin = DecreeOrigin.PLAYER, sync = true)
|
@Decree(description = "Teleport to the active studio world", aliases = "stp", origin = DecreeOrigin.PLAYER, sync = true)
|
||||||
public void tpstudio() {
|
public void tpstudio() {
|
||||||
if(!Iris.service(StudioSVC.class).isProjectOpen()) {
|
if (!Iris.service(StudioSVC.class).isProjectOpen()) {
|
||||||
sender().sendMessage(C.RED + "No studio world is open!");
|
sender().sendMessage(C.RED + "No studio world is open!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(IrisToolbelt.isIrisWorld(world()) && engine().isStudio()) {
|
if (IrisToolbelt.isIrisWorld(world()) && engine().isStudio()) {
|
||||||
sender().sendMessage(C.RED + "You are already in a studio world!");
|
sender().sendMessage(C.RED + "You are already in a studio world!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -653,11 +648,11 @@ public class CommandStudio implements DecreeExecutor {
|
|||||||
|
|
||||||
@Decree(description = "Update your dimension projects VSCode workspace")
|
@Decree(description = "Update your dimension projects VSCode workspace")
|
||||||
public void update(
|
public void update(
|
||||||
@Param(description = "The dimension to update the workspace of", contextual = true, defaultValue = "default")
|
@Param(description = "The dimension to update the workspace of", contextual = true, defaultValue = "default")
|
||||||
IrisDimension dimension
|
IrisDimension dimension
|
||||||
) {
|
) {
|
||||||
sender().sendMessage(C.GOLD + "Updating Code Workspace for " + dimension.getName() + "...");
|
sender().sendMessage(C.GOLD + "Updating Code Workspace for " + dimension.getName() + "...");
|
||||||
if(new IrisProject(dimension.getLoader().getDataFolder()).updateWorkspace()) {
|
if (new IrisProject(dimension.getLoader().getDataFolder()).updateWorkspace()) {
|
||||||
sender().sendMessage(C.GREEN + "Updated Code Workspace for " + dimension.getName());
|
sender().sendMessage(C.GREEN + "Updated Code Workspace for " + dimension.getName());
|
||||||
} else {
|
} else {
|
||||||
sender().sendMessage(C.RED + "Invalid project: " + dimension.getName() + ". Try deleting the code-workspace file and try again.");
|
sender().sendMessage(C.RED + "Invalid project: " + dimension.getName() + ". Try deleting the code-workspace file and try again.");
|
||||||
@@ -666,14 +661,14 @@ public class CommandStudio implements DecreeExecutor {
|
|||||||
|
|
||||||
@Decree(aliases = "find-objects", description = "Get information about nearby structures")
|
@Decree(aliases = "find-objects", description = "Get information about nearby structures")
|
||||||
public void objects() {
|
public void objects() {
|
||||||
if(!IrisToolbelt.isIrisWorld(player().getWorld())) {
|
if (!IrisToolbelt.isIrisWorld(player().getWorld())) {
|
||||||
sender().sendMessage(C.RED + "You must be in an Iris world");
|
sender().sendMessage(C.RED + "You must be in an Iris world");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
World world = player().getWorld();
|
World world = player().getWorld();
|
||||||
|
|
||||||
if(!IrisToolbelt.isIrisWorld(world)) {
|
if (!IrisToolbelt.isIrisWorld(world)) {
|
||||||
sender().sendMessage("You must be in an iris world.");
|
sender().sendMessage("You must be in an iris world.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -687,7 +682,7 @@ public class CommandStudio implements DecreeExecutor {
|
|||||||
int cx = l.getChunk().getX();
|
int cx = l.getChunk().getX();
|
||||||
int cz = l.getChunk().getZ();
|
int cz = l.getChunk().getZ();
|
||||||
new Spiraler(3, 3, (x, z) -> chunks.addIfMissing(world.getChunkAt(x + cx, z + cz))).drain();
|
new Spiraler(3, 3, (x, z) -> chunks.addIfMissing(world.getChunkAt(x + cx, z + cz))).drain();
|
||||||
} catch(Throwable e) {
|
} catch (Throwable e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -705,7 +700,7 @@ public class CommandStudio implements DecreeExecutor {
|
|||||||
pw.println("Report Captured At: " + new Date());
|
pw.println("Report Captured At: " + new Date());
|
||||||
pw.println("Chunks: (" + chunks.size() + "): ");
|
pw.println("Chunks: (" + chunks.size() + "): ");
|
||||||
|
|
||||||
for(Chunk i : chunks) {
|
for (Chunk i : chunks) {
|
||||||
pw.println("- [" + i.getX() + ", " + i.getZ() + "]");
|
pw.println("- [" + i.getX() + ", " + i.getZ() + "]");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -714,19 +709,19 @@ public class CommandStudio implements DecreeExecutor {
|
|||||||
String age = "No idea...";
|
String age = "No idea...";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
for(File i : Objects.requireNonNull(new File(world.getWorldFolder(), "region").listFiles())) {
|
for (File i : Objects.requireNonNull(new File(world.getWorldFolder(), "region").listFiles())) {
|
||||||
if(i.isFile()) {
|
if (i.isFile()) {
|
||||||
size += i.length();
|
size += i.length();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch(Throwable e) {
|
} catch (Throwable e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
FileTime creationTime = (FileTime) Files.getAttribute(world.getWorldFolder().toPath(), "creationTime");
|
FileTime creationTime = (FileTime) Files.getAttribute(world.getWorldFolder().toPath(), "creationTime");
|
||||||
age = hrf(Duration.of(M.ms() - creationTime.toMillis(), ChronoUnit.MILLIS));
|
age = hrf(Duration.of(M.ms() - creationTime.toMillis(), ChronoUnit.MILLIS));
|
||||||
} catch(IOException e) {
|
} catch (IOException e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -734,10 +729,10 @@ public class CommandStudio implements DecreeExecutor {
|
|||||||
KList<String> caveBiomes = new KList<>();
|
KList<String> caveBiomes = new KList<>();
|
||||||
KMap<String, KMap<String, KList<String>>> objects = new KMap<>();
|
KMap<String, KMap<String, KList<String>>> objects = new KMap<>();
|
||||||
|
|
||||||
for(Chunk i : chunks) {
|
for (Chunk i : chunks) {
|
||||||
for(int j = 0; j < 16; j += 3) {
|
for (int j = 0; j < 16; j += 3) {
|
||||||
|
|
||||||
for(int k = 0; k < 16; k += 3) {
|
for (int k = 0; k < 16; k += 3) {
|
||||||
|
|
||||||
assert engine() != null;
|
assert engine() != null;
|
||||||
IrisBiome bb = engine().getSurfaceBiome((i.getX() * 16) + j, (i.getZ() * 16) + k);
|
IrisBiome bb = engine().getSurfaceBiome((i.getX() * 16) + j, (i.getZ() * 16) + k);
|
||||||
@@ -764,20 +759,20 @@ public class CommandStudio implements DecreeExecutor {
|
|||||||
pw.println("== Biome Info ==");
|
pw.println("== Biome Info ==");
|
||||||
pw.println("Found " + biomes.size() + " Biome(s): ");
|
pw.println("Found " + biomes.size() + " Biome(s): ");
|
||||||
|
|
||||||
for(String i : biomes) {
|
for (String i : biomes) {
|
||||||
pw.println("- " + i);
|
pw.println("- " + i);
|
||||||
}
|
}
|
||||||
pw.println();
|
pw.println();
|
||||||
|
|
||||||
pw.println("== Object Info ==");
|
pw.println("== Object Info ==");
|
||||||
|
|
||||||
for(String i : objects.k()) {
|
for (String i : objects.k()) {
|
||||||
pw.println("- " + i);
|
pw.println("- " + i);
|
||||||
|
|
||||||
for(String j : objects.get(i).k()) {
|
for (String j : objects.get(i).k()) {
|
||||||
pw.println(" @ " + j);
|
pw.println(" @ " + j);
|
||||||
|
|
||||||
for(String k : objects.get(i).get(j)) {
|
for (String k : objects.get(i).get(j)) {
|
||||||
pw.println(" * " + k);
|
pw.println(" * " + k);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -787,7 +782,7 @@ public class CommandStudio implements DecreeExecutor {
|
|||||||
pw.close();
|
pw.close();
|
||||||
|
|
||||||
sender().sendMessage("Reported to: " + ff.getPath());
|
sender().sendMessage("Reported to: " + ff.getPath());
|
||||||
} catch(FileNotFoundException e) {
|
} catch (FileNotFoundException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
}
|
}
|
||||||
@@ -797,15 +792,15 @@ public class CommandStudio implements DecreeExecutor {
|
|||||||
String n1 = bb.getName() + " [" + Form.capitalize(bb.getInferredType().name().toLowerCase()) + "] " + " (" + bb.getLoadFile().getName() + ")";
|
String n1 = bb.getName() + " [" + Form.capitalize(bb.getInferredType().name().toLowerCase()) + "] " + " (" + bb.getLoadFile().getName() + ")";
|
||||||
int m = 0;
|
int m = 0;
|
||||||
KSet<String> stop = new KSet<>();
|
KSet<String> stop = new KSet<>();
|
||||||
for(IrisObjectPlacement f : bb.getObjects()) {
|
for (IrisObjectPlacement f : bb.getObjects()) {
|
||||||
m++;
|
m++;
|
||||||
String n2 = "Placement #" + m + " (" + f.getPlace().size() + " possible objects)";
|
String n2 = "Placement #" + m + " (" + f.getPlace().size() + " possible objects)";
|
||||||
|
|
||||||
for(String i : f.getPlace()) {
|
for (String i : f.getPlace()) {
|
||||||
String nn3 = i + ": [ERROR] Failed to find object!";
|
String nn3 = i + ": [ERROR] Failed to find object!";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if(stop.contains(i)) {
|
if (stop.contains(i)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -813,13 +808,13 @@ public class CommandStudio implements DecreeExecutor {
|
|||||||
BlockVector sz = IrisObject.sampleSize(ff);
|
BlockVector sz = IrisObject.sampleSize(ff);
|
||||||
nn3 = i + ": size=[" + sz.getBlockX() + "," + sz.getBlockY() + "," + sz.getBlockZ() + "] location=[" + ff.getPath() + "]";
|
nn3 = i + ": size=[" + sz.getBlockX() + "," + sz.getBlockY() + "," + sz.getBlockZ() + "] location=[" + ff.getPath() + "]";
|
||||||
stop.add(i);
|
stop.add(i);
|
||||||
} catch(Throwable e) {
|
} catch (Throwable e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
String n3 = nn3;
|
String n3 = nn3;
|
||||||
objects.computeIfAbsent(n1, (k1) -> new KMap<>())
|
objects.computeIfAbsent(n1, (k1) -> new KMap<>())
|
||||||
.computeIfAbsent(n2, (k) -> new KList<>()).addIfMissing(n3);
|
.computeIfAbsent(n2, (k) -> new KList<>()).addIfMissing(n3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -828,7 +823,7 @@ public class CommandStudio implements DecreeExecutor {
|
|||||||
* @return true if server GUIs are not enabled
|
* @return true if server GUIs are not enabled
|
||||||
*/
|
*/
|
||||||
private boolean noGUI() {
|
private boolean noGUI() {
|
||||||
if(!IrisSettings.get().getGui().isUseServerLaunchedGuis()) {
|
if (!IrisSettings.get().getGui().isUseServerLaunchedGuis()) {
|
||||||
sender().sendMessage(C.RED + "You must have server launched GUIs enabled in the settings!");
|
sender().sendMessage(C.RED + "You must have server launched GUIs enabled in the settings!");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -839,15 +834,15 @@ public class CommandStudio implements DecreeExecutor {
|
|||||||
* @return true if no studio is open or the player is not in one
|
* @return true if no studio is open or the player is not in one
|
||||||
*/
|
*/
|
||||||
private boolean noStudio() {
|
private boolean noStudio() {
|
||||||
if(!sender().isPlayer()) {
|
if (!sender().isPlayer()) {
|
||||||
sender().sendMessage(C.RED + "Players only!");
|
sender().sendMessage(C.RED + "Players only!");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if(!Iris.service(StudioSVC.class).isProjectOpen()) {
|
if (!Iris.service(StudioSVC.class).isProjectOpen()) {
|
||||||
sender().sendMessage(C.RED + "No studio world is open!");
|
sender().sendMessage(C.RED + "No studio world is open!");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if(!engine().isStudio()) {
|
if (!engine().isStudio()) {
|
||||||
sender().sendMessage(C.RED + "You must be in a studio world!");
|
sender().sendMessage(C.RED + "You must be in a studio world!");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -856,14 +851,14 @@ public class CommandStudio implements DecreeExecutor {
|
|||||||
|
|
||||||
|
|
||||||
public void files(File clean, KList<File> files) {
|
public void files(File clean, KList<File> files) {
|
||||||
if(clean.isDirectory()) {
|
if (clean.isDirectory()) {
|
||||||
for(File i : clean.listFiles()) {
|
for (File i : clean.listFiles()) {
|
||||||
files(i, files);
|
files(i, files);
|
||||||
}
|
}
|
||||||
} else if(clean.getName().endsWith(".json")) {
|
} else if (clean.getName().endsWith(".json")) {
|
||||||
try {
|
try {
|
||||||
files.add(clean);
|
files.add(clean);
|
||||||
} catch(Throwable e) {
|
} catch (Throwable e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
Iris.error("Failed to beautify " + clean.getAbsolutePath() + " You may have errors in your json!");
|
Iris.error("Failed to beautify " + clean.getAbsolutePath() + " You may have errors in your json!");
|
||||||
}
|
}
|
||||||
@@ -871,28 +866,28 @@ public class CommandStudio implements DecreeExecutor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void fixBlocks(JSONObject obj) {
|
private void fixBlocks(JSONObject obj) {
|
||||||
for(String i : obj.keySet()) {
|
for (String i : obj.keySet()) {
|
||||||
Object o = obj.get(i);
|
Object o = obj.get(i);
|
||||||
|
|
||||||
if(i.equals("block") && o instanceof String && !o.toString().trim().isEmpty() && !o.toString().contains(":")) {
|
if (i.equals("block") && o instanceof String && !o.toString().trim().isEmpty() && !o.toString().contains(":")) {
|
||||||
obj.put(i, "minecraft:" + o);
|
obj.put(i, "minecraft:" + o);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(o instanceof JSONObject) {
|
if (o instanceof JSONObject) {
|
||||||
fixBlocks((JSONObject) o);
|
fixBlocks((JSONObject) o);
|
||||||
} else if(o instanceof JSONArray) {
|
} else if (o instanceof JSONArray) {
|
||||||
fixBlocks((JSONArray) o);
|
fixBlocks((JSONArray) o);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fixBlocks(JSONArray obj) {
|
private void fixBlocks(JSONArray obj) {
|
||||||
for(int i = 0; i < obj.length(); i++) {
|
for (int i = 0; i < obj.length(); i++) {
|
||||||
Object o = obj.get(i);
|
Object o = obj.get(i);
|
||||||
|
|
||||||
if(o instanceof JSONObject) {
|
if (o instanceof JSONObject) {
|
||||||
fixBlocks((JSONObject) o);
|
fixBlocks((JSONObject) o);
|
||||||
} else if(o instanceof JSONArray) {
|
} else if (o instanceof JSONArray) {
|
||||||
fixBlocks((JSONArray) o);
|
fixBlocks((JSONArray) o);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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?")
|
||||||
@@ -45,16 +48,16 @@ public class CommandWhat implements DecreeExecutor {
|
|||||||
public void hand() {
|
public void hand() {
|
||||||
try {
|
try {
|
||||||
BlockData bd = player().getInventory().getItemInMainHand().getType().createBlockData();
|
BlockData bd = player().getInventory().getItemInMainHand().getType().createBlockData();
|
||||||
if(!bd.getMaterial().equals(Material.AIR)) {
|
if (!bd.getMaterial().equals(Material.AIR)) {
|
||||||
sender().sendMessage("Material: " + C.GREEN + bd.getMaterial().name());
|
sender().sendMessage("Material: " + C.GREEN + bd.getMaterial().name());
|
||||||
sender().sendMessage("Full: " + C.WHITE + bd.getAsString(true));
|
sender().sendMessage("Full: " + C.WHITE + bd.getAsString(true));
|
||||||
} else {
|
} else {
|
||||||
sender().sendMessage("Please hold a block/item");
|
sender().sendMessage("Please hold a block/item");
|
||||||
}
|
}
|
||||||
} catch(Throwable e) {
|
} catch (Throwable e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
Material bd = player().getInventory().getItemInMainHand().getType();
|
Material bd = player().getInventory().getItemInMainHand().getType();
|
||||||
if(!bd.equals(Material.AIR)) {
|
if (!bd.equals(Material.AIR)) {
|
||||||
sender().sendMessage("Material: " + C.GREEN + bd.name());
|
sender().sendMessage("Material: " + C.GREEN + bd.name());
|
||||||
} else {
|
} else {
|
||||||
sender().sendMessage("Please hold a block/item");
|
sender().sendMessage("Please hold a block/item");
|
||||||
@@ -65,63 +68,76 @@ 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) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
sender().sendMessage("Non-Iris Biome: " + player().getLocation().getBlock().getBiome().name());
|
sender().sendMessage("Non-Iris Biome: " + player().getLocation().getBlock().getBiome().name());
|
||||||
|
|
||||||
if(player().getLocation().getBlock().getBiome().equals(Biome.CUSTOM)) {
|
if (player().getLocation().getBlock().getBiome().equals(Biome.CUSTOM)) {
|
||||||
try {
|
try {
|
||||||
sender().sendMessage("Data Pack Biome: " + INMS.get().getTrueBiomeBaseKey(player().getLocation()) + " (ID: " + INMS.get().getTrueBiomeBaseId(INMS.get().getTrueBiomeBase(player().getLocation())) + ")");
|
sender().sendMessage("Data Pack Biome: " + INMS.get().getTrueBiomeBaseKey(player().getLocation()) + " (ID: " + INMS.get().getTrueBiomeBaseId(INMS.get().getTrueBiomeBase(player().getLocation())) + ")");
|
||||||
} catch(Throwable ee) {
|
} catch (Throwable ee) {
|
||||||
Iris.reportError(ee);
|
Iris.reportError(ee);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@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;
|
||||||
try {
|
try {
|
||||||
bd = player().getTargetBlockExact(128, FluidCollisionMode.NEVER).getBlockData();
|
bd = player().getTargetBlockExact(128, FluidCollisionMode.NEVER).getBlockData();
|
||||||
} catch(NullPointerException e) {
|
} catch (NullPointerException e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
sender().sendMessage("Please look at any block, not at the sky");
|
sender().sendMessage("Please look at any block, not at the sky");
|
||||||
bd = null;
|
bd = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(bd != null) {
|
if (bd != null) {
|
||||||
sender().sendMessage("Material: " + C.GREEN + bd.getMaterial().name());
|
sender().sendMessage("Material: " + C.GREEN + bd.getMaterial().name());
|
||||||
sender().sendMessage("Full: " + C.WHITE + bd.getAsString(true));
|
sender().sendMessage("Full: " + C.WHITE + bd.getAsString(true));
|
||||||
|
|
||||||
if(B.isStorage(bd)) {
|
if (B.isStorage(bd)) {
|
||||||
sender().sendMessage(C.YELLOW + "* Storage Block (Loot Capable)");
|
sender().sendMessage(C.YELLOW + "* Storage Block (Loot Capable)");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(B.isLit(bd)) {
|
if (B.isLit(bd)) {
|
||||||
sender().sendMessage(C.YELLOW + "* Lit Block (Light Capable)");
|
sender().sendMessage(C.YELLOW + "* Lit Block (Light Capable)");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(B.isFoliage(bd)) {
|
if (B.isFoliage(bd)) {
|
||||||
sender().sendMessage(C.YELLOW + "* Foliage Block");
|
sender().sendMessage(C.YELLOW + "* Foliage Block");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(B.isDecorant(bd)) {
|
if (B.isDecorant(bd)) {
|
||||||
sender().sendMessage(C.YELLOW + "* Decorant Block");
|
sender().sendMessage(C.YELLOW + "* Decorant Block");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(B.isFluid(bd)) {
|
if (B.isFluid(bd)) {
|
||||||
sender().sendMessage(C.YELLOW + "* Fluid Block");
|
sender().sendMessage(C.YELLOW + "* Fluid Block");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(B.isFoliagePlantable(bd)) {
|
if (B.isFoliagePlantable(bd)) {
|
||||||
sender().sendMessage(C.YELLOW + "* Plantable Foliage Block");
|
sender().sendMessage(C.YELLOW + "* Plantable Foliage Block");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(B.isSolid(bd)) {
|
if (B.isSolid(bd)) {
|
||||||
sender().sendMessage(C.YELLOW + "* Solid Block");
|
sender().sendMessage(C.YELLOW + "* Solid Block");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -131,23 +147,23 @@ public class CommandWhat implements DecreeExecutor {
|
|||||||
public void markers(@Param(description = "Marker name such as cave_floor or cave_ceiling") String marker) {
|
public void markers(@Param(description = "Marker name such as cave_floor or cave_ceiling") String marker) {
|
||||||
Chunk c = player().getLocation().getChunk();
|
Chunk c = player().getLocation().getChunk();
|
||||||
|
|
||||||
if(IrisToolbelt.isIrisWorld(c.getWorld())) {
|
if (IrisToolbelt.isIrisWorld(c.getWorld())) {
|
||||||
int m = 1;
|
int m = 1;
|
||||||
AtomicInteger v = new AtomicInteger(0);
|
AtomicInteger v = new AtomicInteger(0);
|
||||||
|
|
||||||
for(int xxx = c.getX() - 4; xxx <= c.getX() + 4; xxx++) {
|
for (int xxx = c.getX() - 4; xxx <= c.getX() + 4; xxx++) {
|
||||||
for(int zzz = c.getZ() - 4; zzz <= c.getZ() + 4; zzz++) {
|
for (int zzz = c.getZ() - 4; zzz <= c.getZ() + 4; zzz++) {
|
||||||
IrisToolbelt.access(c.getWorld()).getEngine().getMantle().findMarkers(xxx, zzz, new MatterMarker(marker))
|
IrisToolbelt.access(c.getWorld()).getEngine().getMantle().findMarkers(xxx, zzz, new MatterMarker(marker))
|
||||||
.convert((i) -> i.toLocation(c.getWorld())).forEach((i) -> {
|
.convert((i) -> i.toLocation(c.getWorld())).forEach((i) -> {
|
||||||
J.s(() -> BlockSignal.of(i.getBlock(), 100));
|
J.s(() -> BlockSignal.of(i.getBlock(), 100));
|
||||||
v.incrementAndGet();
|
v.incrementAndGet();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -51,7 +51,7 @@ public class BlockSignal {
|
|||||||
active.decrementAndGet();
|
active.decrementAndGet();
|
||||||
BlockData type = block.getBlockData();
|
BlockData type = block.getBlockData();
|
||||||
MultiBurst.burst.lazy(() -> {
|
MultiBurst.burst.lazy(() -> {
|
||||||
for(Player i : block.getWorld().getPlayers()) {
|
for (Player i : block.getWorld().getPlayers()) {
|
||||||
i.sendBlockChange(block.getLocation(), block.getBlockData());
|
i.sendBlockChange(block.getLocation(), block.getBlockData());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -82,7 +82,7 @@ public class BlockSignal {
|
|||||||
new SR(20) {
|
new SR(20) {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if(e.isDead()) {
|
if (e.isDead()) {
|
||||||
cancel();
|
cancel();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -98,7 +98,7 @@ public class BlockSignal {
|
|||||||
BlockData type = block.getBlockData();
|
BlockData type = block.getBlockData();
|
||||||
|
|
||||||
MultiBurst.burst.lazy(() -> {
|
MultiBurst.burst.lazy(() -> {
|
||||||
for(Player i : block.getWorld().getPlayers()) {
|
for (Player i : block.getWorld().getPlayers()) {
|
||||||
i.sendBlockChange(block.getLocation(), block.getBlockData());
|
i.sendBlockChange(block.getLocation(), block.getBlockData());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -50,11 +50,11 @@ public class DustRevealer {
|
|||||||
|
|
||||||
J.s(() -> {
|
J.s(() -> {
|
||||||
new BlockSignal(world.getBlockAt(block.getX(), block.getY(), block.getZ()), 10);
|
new BlockSignal(world.getBlockAt(block.getX(), block.getY(), block.getZ()), 10);
|
||||||
if(M.r(0.25)) {
|
if (M.r(0.25)) {
|
||||||
world.playSound(block.toBlock(world).getLocation(), Sound.BLOCK_AMETHYST_BLOCK_CHIME, 1f, RNG.r.f(0.2f, 2f));
|
world.playSound(block.toBlock(world).getLocation(), Sound.BLOCK_AMETHYST_BLOCK_CHIME, 1f, RNG.r.f(0.2f, 2f));
|
||||||
}
|
}
|
||||||
J.a(() -> {
|
J.a(() -> {
|
||||||
while(BlockSignal.active.get() > 128) {
|
while (BlockSignal.active.get() > 128) {
|
||||||
J.sleep(5);
|
J.sleep(5);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,7 +85,7 @@ public class DustRevealer {
|
|||||||
is(new BlockPosition(block.getX() + 1, block.getY() + 1, block.getZ() + 1));
|
is(new BlockPosition(block.getX() + 1, block.getY() + 1, block.getZ() + 1));
|
||||||
is(new BlockPosition(block.getX() + 1, block.getY() - 1, block.getZ() - 1));
|
is(new BlockPosition(block.getX() + 1, block.getY() - 1, block.getZ() - 1));
|
||||||
is(new BlockPosition(block.getX() + 1, block.getY() - 1, block.getZ() + 1));
|
is(new BlockPosition(block.getX() + 1, block.getY() - 1, block.getZ() + 1));
|
||||||
} catch(Throwable e) {
|
} catch (Throwable e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@@ -97,9 +97,9 @@ public class DustRevealer {
|
|||||||
World world = block.getWorld();
|
World world = block.getWorld();
|
||||||
Engine access = IrisToolbelt.access(world).getEngine();
|
Engine access = IrisToolbelt.access(world).getEngine();
|
||||||
|
|
||||||
if(access != null) {
|
if (access != null) {
|
||||||
String a = access.getObjectPlacementKey(block.getX(), block.getY() - block.getWorld().getMinHeight(), block.getZ());
|
String a = access.getObjectPlacementKey(block.getX(), block.getY() - block.getWorld().getMinHeight(), block.getZ());
|
||||||
if(a != null) {
|
if (a != null) {
|
||||||
world.playSound(block.getLocation(), Sound.ITEM_LODESTONE_COMPASS_LOCK, 1f, 0.1f);
|
world.playSound(block.getLocation(), Sound.ITEM_LODESTONE_COMPASS_LOCK, 1f, 0.1f);
|
||||||
|
|
||||||
sender.sendMessage("Found object " + a);
|
sender.sendMessage("Found object " + a);
|
||||||
@@ -112,7 +112,7 @@ public class DustRevealer {
|
|||||||
|
|
||||||
private boolean is(BlockPosition a) {
|
private boolean is(BlockPosition a) {
|
||||||
int betterY = a.getY() - world.getMinHeight();
|
int betterY = a.getY() - world.getMinHeight();
|
||||||
if(isValidTry(a) && engine.getObjectPlacementKey(a.getX(), betterY, a.getZ()) != null && engine.getObjectPlacementKey(a.getX(), betterY, a.getZ()).equals(key)) {
|
if (isValidTry(a) && engine.getObjectPlacementKey(a.getX(), betterY, a.getZ()) != null && engine.getObjectPlacementKey(a.getX(), betterY, a.getZ()).equals(key)) {
|
||||||
hits.add(a);
|
hits.add(a);
|
||||||
new DustRevealer(engine, world, a, key, hits);
|
new DustRevealer(engine, world, a, key, hits);
|
||||||
return true;
|
return true;
|
||||||
@@ -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;
|
||||||
@@ -66,13 +61,12 @@ public class JigsawEditor implements Listener {
|
|||||||
private Location target;
|
private Location target;
|
||||||
|
|
||||||
public JigsawEditor(Player player, IrisJigsawPiece piece, IrisObject object, File saveLocation) {
|
public JigsawEditor(Player player, IrisJigsawPiece piece, IrisObject object, File saveLocation) {
|
||||||
if(editors.containsKey(player)) {
|
if (editors.containsKey(player)) {
|
||||||
editors.get(player).close();
|
editors.get(player).close();
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
@@ -90,20 +84,20 @@ public class JigsawEditor implements Listener {
|
|||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void on(PlayerMoveEvent e) {
|
public void on(PlayerMoveEvent e) {
|
||||||
if(e.getPlayer().equals(player)) {
|
if (e.getPlayer().equals(player)) {
|
||||||
try {
|
try {
|
||||||
target = player.getTargetBlockExact(7).getLocation();
|
target = player.getTargetBlockExact(7).getLocation();
|
||||||
} catch(Throwable ex) {
|
} catch (Throwable ex) {
|
||||||
Iris.reportError(ex);
|
Iris.reportError(ex);
|
||||||
target = player.getLocation();
|
target = player.getLocation();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(cuboid.contains(target)) {
|
if (cuboid.contains(target)) {
|
||||||
for(IrisPosition i : falling.k()) {
|
for (IrisPosition i : falling.k()) {
|
||||||
Location at = toLocation(i);
|
Location at = toLocation(i);
|
||||||
|
|
||||||
if(at.equals(target)) {
|
if (at.equals(target)) {
|
||||||
falling.remove(i).run();
|
falling.remove(i).run();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -113,43 +107,43 @@ public class JigsawEditor implements Listener {
|
|||||||
|
|
||||||
public Location toLocation(IrisPosition i) {
|
public Location toLocation(IrisPosition i) {
|
||||||
return origin.clone()
|
return origin.clone()
|
||||||
.add(new Vector(i.getX(), i.getY(), i.getZ()))
|
.add(new Vector(i.getX(), i.getY(), i.getZ()))
|
||||||
.add(object.getCenter())
|
.add(object.getCenter())
|
||||||
.getBlock()
|
.getBlock()
|
||||||
.getLocation();
|
.getLocation();
|
||||||
}
|
}
|
||||||
|
|
||||||
public IrisPosition toPosition(Location l) {
|
public IrisPosition toPosition(Location l) {
|
||||||
return new IrisPosition(l.clone().getBlock().getLocation()
|
return new IrisPosition(l.clone().getBlock().getLocation()
|
||||||
.subtract(origin.clone())
|
.subtract(origin.clone())
|
||||||
.subtract(object.getCenter())
|
.subtract(object.getCenter())
|
||||||
.add(1, 1, 1)
|
.add(1, 1, 1)
|
||||||
.toVector());
|
.toVector());
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void on(PlayerInteractEvent e) {
|
public void on(PlayerInteractEvent e) {
|
||||||
if(e.getAction().equals(Action.RIGHT_CLICK_BLOCK)) {
|
if (e.getAction().equals(Action.RIGHT_CLICK_BLOCK)) {
|
||||||
if(e.getClickedBlock() != null && cuboid.contains(e.getClickedBlock().getLocation()) && e.getPlayer().equals(player)) {
|
if (e.getClickedBlock() != null && cuboid.contains(e.getClickedBlock().getLocation()) && e.getPlayer().equals(player)) {
|
||||||
IrisPosition pos = toPosition(e.getClickedBlock().getLocation());
|
IrisPosition pos = toPosition(e.getClickedBlock().getLocation());
|
||||||
IrisJigsawPieceConnector connector = null;
|
IrisJigsawPieceConnector connector = null;
|
||||||
for(IrisJigsawPieceConnector i : piece.getConnectors()) {
|
for (IrisJigsawPieceConnector i : piece.getConnectors()) {
|
||||||
if(i.getPosition().equals(pos)) {
|
if (i.getPosition().equals(pos)) {
|
||||||
connector = i;
|
connector = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!player.isSneaking() && connector == null) {
|
if (!player.isSneaking() && connector == null) {
|
||||||
connector = new IrisJigsawPieceConnector();
|
connector = new IrisJigsawPieceConnector();
|
||||||
connector.setDirection(IrisDirection.getDirection(e.getBlockFace()));
|
connector.setDirection(IrisDirection.getDirection(e.getBlockFace()));
|
||||||
connector.setPosition(pos);
|
connector.setPosition(pos);
|
||||||
piece.getConnectors().add(connector);
|
piece.getConnectors().add(connector);
|
||||||
player.playSound(e.getClickedBlock().getLocation(), Sound.ENTITY_ITEM_FRAME_ADD_ITEM, 1f, 1f);
|
player.playSound(e.getClickedBlock().getLocation(), Sound.ENTITY_ITEM_FRAME_ADD_ITEM, 1f, 1f);
|
||||||
} else if(player.isSneaking() && connector != null) {
|
} else if (player.isSneaking() && connector != null) {
|
||||||
piece.getConnectors().remove(connector);
|
piece.getConnectors().remove(connector);
|
||||||
player.playSound(e.getClickedBlock().getLocation(), Sound.ENTITY_ITEM_FRAME_REMOVE_ITEM, 1f, 1f);
|
player.playSound(e.getClickedBlock().getLocation(), Sound.ENTITY_ITEM_FRAME_REMOVE_ITEM, 1f, 1f);
|
||||||
} else if(connector != null && !player.isSneaking()) {
|
} else if (connector != null && !player.isSneaking()) {
|
||||||
connector.setDirection(IrisDirection.getDirection(e.getBlockFace()));
|
connector.setDirection(IrisDirection.getDirection(e.getBlockFace()));
|
||||||
player.playSound(e.getClickedBlock().getLocation(), Sound.ENTITY_ITEM_FRAME_ROTATE_ITEM, 1f, 1f);
|
player.playSound(e.getClickedBlock().getLocation(), Sound.ENTITY_ITEM_FRAME_ROTATE_ITEM, 1f, 1f);
|
||||||
}
|
}
|
||||||
@@ -157,10 +151,8 @@ public class JigsawEditor implements Listener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeKey(JSONObject o, String... path)
|
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;
|
||||||
@@ -192,16 +182,15 @@ public class JigsawEditor implements Listener {
|
|||||||
|
|
||||||
// remove root key
|
// remove root key
|
||||||
removeKey(j, "placementOptions"); // should work
|
removeKey(j, "placementOptions"); // should work
|
||||||
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");
|
}
|
||||||
}
|
|
||||||
|
|
||||||
IO.writeAll(targetSaveLocation, j.toString(4));
|
IO.writeAll(targetSaveLocation, j.toString(4));
|
||||||
} catch(IOException e) {
|
} catch (IOException e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@@ -215,20 +204,20 @@ public class JigsawEditor implements Listener {
|
|||||||
object.unplaceCenterY(origin);
|
object.unplaceCenterY(origin);
|
||||||
falling.v().forEach(Runnable::run);
|
falling.v().forEach(Runnable::run);
|
||||||
}).get();
|
}).get();
|
||||||
} catch(InterruptedException | ExecutionException e) {
|
} catch (InterruptedException | ExecutionException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
editors.remove(player);
|
editors.remove(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onTick() {
|
public void onTick() {
|
||||||
if(cl.flip()) {
|
if (cl.flip()) {
|
||||||
Iris.service(WandSVC.class).draw(cuboid, player);
|
Iris.service(WandSVC.class).draw(cuboid, player);
|
||||||
|
|
||||||
f:
|
f:
|
||||||
for(IrisPosition i : falling.k()) {
|
for (IrisPosition i : falling.k()) {
|
||||||
for(IrisJigsawPieceConnector j : piece.getConnectors()) {
|
for (IrisJigsawPieceConnector j : piece.getConnectors()) {
|
||||||
if(j.getPosition().equals(i)) {
|
if (j.getPosition().equals(i)) {
|
||||||
continue f;
|
continue f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -236,23 +225,23 @@ public class JigsawEditor implements Listener {
|
|||||||
falling.remove(i).run();
|
falling.remove(i).run();
|
||||||
}
|
}
|
||||||
|
|
||||||
for(IrisJigsawPieceConnector i : piece.getConnectors()) {
|
for (IrisJigsawPieceConnector i : piece.getConnectors()) {
|
||||||
IrisPosition pos = i.getPosition();
|
IrisPosition pos = i.getPosition();
|
||||||
Location at = toLocation(pos);
|
Location at = toLocation(pos);
|
||||||
|
|
||||||
Vector dir = i.getDirection().toVector().clone();
|
Vector dir = i.getDirection().toVector().clone();
|
||||||
|
|
||||||
|
|
||||||
for(int ix = 0; ix < RNG.r.i(1, 3); ix++) {
|
for (int ix = 0; ix < RNG.r.i(1, 3); ix++) {
|
||||||
at.getWorld().spawnParticle(Particle.SOUL_FIRE_FLAME, at.clone().getBlock().getLocation().add(0.25, 0.25, 0.25).add(RNG.r.d(0.5), RNG.r.d(0.5), RNG.r.d(0.5)), 0, dir.getX(), dir.getY(), dir.getZ(), 0.092 + RNG.r.d(-0.03, 0.08));
|
at.getWorld().spawnParticle(Particle.SOUL_FIRE_FLAME, at.clone().getBlock().getLocation().add(0.25, 0.25, 0.25).add(RNG.r.d(0.5), RNG.r.d(0.5), RNG.r.d(0.5)), 0, dir.getX(), dir.getY(), dir.getZ(), 0.092 + RNG.r.d(-0.03, 0.08));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(at.getBlock().getLocation().equals(target)) {
|
if (at.getBlock().getLocation().equals(target)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!falling.containsKey(pos)) {
|
if (!falling.containsKey(pos)) {
|
||||||
if(at.getBlock().getType().isAir()) {
|
if (at.getBlock().getType().isAir()) {
|
||||||
at.getBlock().setType(Material.STONE);
|
at.getBlock().setType(Material.STONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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")
|
||||||
@@ -133,10 +119,10 @@ public class NoiseExplorerGUI extends JPanel implements MouseWheelListener, List
|
|||||||
frame.add(pane);
|
frame.add(pane);
|
||||||
File file = Iris.getCached("Iris Icon", "https://raw.githubusercontent.com/VolmitSoftware/Iris/master/icon.png");
|
File file = Iris.getCached("Iris Icon", "https://raw.githubusercontent.com/VolmitSoftware/Iris/master/icon.png");
|
||||||
|
|
||||||
if(file != null) {
|
if (file != null) {
|
||||||
try {
|
try {
|
||||||
frame.setIconImage(ImageIO.read(file));
|
frame.setIconImage(ImageIO.read(file));
|
||||||
} catch(IOException e) {
|
} catch (IOException e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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);
|
||||||
@@ -167,10 +153,10 @@ public class NoiseExplorerGUI extends JPanel implements MouseWheelListener, List
|
|||||||
frame.add(pane);
|
frame.add(pane);
|
||||||
File file = Iris.getCached("Iris Icon", "https://raw.githubusercontent.com/VolmitSoftware/Iris/master/icon.png");
|
File file = Iris.getCached("Iris Icon", "https://raw.githubusercontent.com/VolmitSoftware/Iris/master/icon.png");
|
||||||
|
|
||||||
if(file != null) {
|
if (file != null) {
|
||||||
try {
|
try {
|
||||||
frame.setIconImage(ImageIO.read(file));
|
frame.setIconImage(ImageIO.read(file));
|
||||||
} catch(IOException e) {
|
} catch (IOException e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -194,14 +180,14 @@ public class NoiseExplorerGUI extends JPanel implements MouseWheelListener, List
|
|||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void on(IrisEngineHotloadEvent e) {
|
public void on(IrisEngineHotloadEvent e) {
|
||||||
if(generator != null)
|
if (generator != null)
|
||||||
generator = loader.get();
|
generator = loader.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void mouseWheelMoved(MouseWheelEvent e) {
|
public void mouseWheelMoved(MouseWheelEvent e) {
|
||||||
|
|
||||||
int notches = e.getWheelRotation();
|
int notches = e.getWheelRotation();
|
||||||
if(e.isControlDown()) {
|
if (e.isControlDown()) {
|
||||||
t = t + ((0.0025 * t) * notches);
|
t = t + ((0.0025 * t) * notches);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -212,51 +198,51 @@ public class NoiseExplorerGUI extends JPanel implements MouseWheelListener, List
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void paint(Graphics g) {
|
public void paint(Graphics g) {
|
||||||
if(scale < ascale) {
|
if (scale < ascale) {
|
||||||
ascale -= Math.abs(scale - ascale) * 0.16;
|
ascale -= Math.abs(scale - ascale) * 0.16;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(scale > ascale) {
|
if (scale > ascale) {
|
||||||
ascale += Math.abs(ascale - scale) * 0.16;
|
ascale += Math.abs(ascale - scale) * 0.16;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(t < tz) {
|
if (t < tz) {
|
||||||
tz -= Math.abs(t - tz) * 0.29;
|
tz -= Math.abs(t - tz) * 0.29;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(t > tz) {
|
if (t > tz) {
|
||||||
tz += Math.abs(tz - t) * 0.29;
|
tz += Math.abs(tz - t) * 0.29;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ox < oxp) {
|
if (ox < oxp) {
|
||||||
oxp -= Math.abs(ox - oxp) * 0.16;
|
oxp -= Math.abs(ox - oxp) * 0.16;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ox > oxp) {
|
if (ox > oxp) {
|
||||||
oxp += Math.abs(oxp - ox) * 0.16;
|
oxp += Math.abs(oxp - ox) * 0.16;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(oz < ozp) {
|
if (oz < ozp) {
|
||||||
ozp -= Math.abs(oz - ozp) * 0.16;
|
ozp -= Math.abs(oz - ozp) * 0.16;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(oz > ozp) {
|
if (oz > ozp) {
|
||||||
ozp += Math.abs(ozp - oz) * 0.16;
|
ozp += Math.abs(ozp - oz) * 0.16;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mx < mxx) {
|
if (mx < mxx) {
|
||||||
mxx -= Math.abs(mx - mxx) * 0.16;
|
mxx -= Math.abs(mx - mxx) * 0.16;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mx > mxx) {
|
if (mx > mxx) {
|
||||||
mxx += Math.abs(mxx - mx) * 0.16;
|
mxx += Math.abs(mxx - mx) * 0.16;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mz < mzz) {
|
if (mz < mzz) {
|
||||||
mzz -= Math.abs(mz - mzz) * 0.16;
|
mzz -= Math.abs(mz - mzz) * 0.16;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mz > mzz) {
|
if (mz > mzz) {
|
||||||
mzz += Math.abs(mzz - mz) * 0.16;
|
mzz += Math.abs(mzz - mz) * 0.16;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -265,35 +251,35 @@ public class NoiseExplorerGUI extends JPanel implements MouseWheelListener, List
|
|||||||
accuracy = down ? accuracy * 4 : accuracy;
|
accuracy = down ? accuracy * 4 : accuracy;
|
||||||
int v = 1000;
|
int v = 1000;
|
||||||
|
|
||||||
if(g instanceof Graphics2D gg) {
|
if (g instanceof Graphics2D gg) {
|
||||||
|
|
||||||
if(getParent().getWidth() != w || getParent().getHeight() != h) {
|
if (getParent().getWidth() != w || getParent().getHeight() != h) {
|
||||||
w = getParent().getWidth();
|
w = getParent().getWidth();
|
||||||
h = getParent().getHeight();
|
h = getParent().getHeight();
|
||||||
img = null;
|
img = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(img == null) {
|
if (img == null) {
|
||||||
img = new BufferedImage(w / accuracy, h / accuracy, BufferedImage.TYPE_INT_RGB);
|
img = new BufferedImage(w / accuracy, h / accuracy, BufferedImage.TYPE_INT_RGB);
|
||||||
}
|
}
|
||||||
|
|
||||||
BurstExecutor e = gx.burst(w);
|
BurstExecutor e = gx.burst(w);
|
||||||
|
|
||||||
for(int x = 0; x < w / accuracy; x++) {
|
for (int x = 0; x < w / accuracy; x++) {
|
||||||
int xx = x;
|
int xx = x;
|
||||||
|
|
||||||
int finalAccuracy = accuracy;
|
int finalAccuracy = accuracy;
|
||||||
e.queue(() -> {
|
e.queue(() -> {
|
||||||
for(int z = 0; z < h / finalAccuracy; z++) {
|
for (int z = 0; z < h / finalAccuracy; z++) {
|
||||||
double n = generator != null ? generator.apply(((xx * finalAccuracy) * ascale) + oxp, ((z * finalAccuracy) * ascale) + ozp) : cng.noise(((xx * finalAccuracy) * ascale) + oxp, ((z * finalAccuracy) * ascale) + ozp);
|
double n = generator != null ? generator.apply(((xx * finalAccuracy) * ascale) + oxp, ((z * finalAccuracy) * ascale) + ozp) : cng.noise(((xx * finalAccuracy) * ascale) + oxp, ((z * finalAccuracy) * ascale) + ozp);
|
||||||
n = n > 1 ? 1 : n < 0 ? 0 : n;
|
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) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -308,15 +294,15 @@ public class NoiseExplorerGUI extends JPanel implements MouseWheelListener, List
|
|||||||
t += 1D;
|
t += 1D;
|
||||||
r.put(p.getMilliseconds());
|
r.put(p.getMilliseconds());
|
||||||
|
|
||||||
if(!isVisible()) {
|
if (!isVisible()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!getParent().isVisible()) {
|
if (!getParent().isVisible()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!getParent().getParent().isVisible()) {
|
if (!getParent().getParent().isVisible()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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,44 +62,44 @@ 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;
|
||||||
instance = this;
|
instance = this;
|
||||||
monitor = new MemoryMonitor(50);
|
monitor = new MemoryMonitor(50);
|
||||||
saving = false;
|
saving = false;
|
||||||
info = new String[] {"Initializing..."};
|
info = new String[]{"Initializing..."};
|
||||||
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() {
|
||||||
if(instance == null) {
|
if (instance == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,11 +112,11 @@ public class PregeneratorJob implements PregenListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static boolean pauseResume() {
|
public static boolean pauseResume() {
|
||||||
if(instance == null) {
|
if (instance == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(isPaused()) {
|
if (isPaused()) {
|
||||||
instance.pregenerator.resume();
|
instance.pregenerator.resume();
|
||||||
} else {
|
} else {
|
||||||
instance.pregenerator.pause();
|
instance.pregenerator.pause();
|
||||||
@@ -129,7 +125,7 @@ public class PregeneratorJob implements PregenListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isPaused() {
|
public static boolean isPaused() {
|
||||||
if(instance == null) {
|
if (instance == null) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,7 +136,7 @@ public class PregeneratorJob implements PregenListener {
|
|||||||
String v = (c.startsWith("#") ? c : "#" + c).trim();
|
String v = (c.startsWith("#") ? c : "#" + c).trim();
|
||||||
try {
|
try {
|
||||||
return Color.decode(v);
|
return Color.decode(v);
|
||||||
} catch(Throwable e) {
|
} catch (Throwable e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
Iris.error("Error Parsing 'color', (" + c + ")");
|
Iris.error("Error Parsing 'color', (" + c + ")");
|
||||||
}
|
}
|
||||||
@@ -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,21 +159,19 @@ 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) {
|
||||||
try {
|
try {
|
||||||
if(renderer != null && frame != null && frame.isVisible()) {
|
if (renderer != null && frame != null && frame.isVisible()) {
|
||||||
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,40 +212,36 @@ 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");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTick(double chunksPerSecond, double chunksPerMinute, double regionsPerMinute, double percent, int generated, int totalChunks, int chunksRemaining, long eta, long elapsed, String method) {
|
public void onTick(double chunksPerSecond, double chunksPerMinute, double regionsPerMinute, double percent, int generated, int totalChunks, int chunksRemaining, long eta, long elapsed, String method) {
|
||||||
info = new String[] {
|
info = new String[]{
|
||||||
(paused() ? "PAUSED" : (saving ? "Saving... " : "Generating")) + " " + Form.f(generated) + " of " + Form.f(totalChunks) + " (" + Form.pc(percent, 0) + " Complete)",
|
(paused() ? "PAUSED" : (saving ? "Saving... " : "Generating")) + " " + Form.f(generated) + " of " + Form.f(totalChunks) + " (" + Form.pc(percent, 0) + " Complete)",
|
||||||
"Speed: " + Form.f(chunksPerSecond, 0) + " Chunks/s, " + Form.f(regionsPerMinute, 1) + " Regions/m, " + Form.f(chunksPerMinute, 0) + " Chunks/m",
|
"Speed: " + Form.f(chunksPerSecond, 0) + " Chunks/s, " + Form.f(regionsPerMinute, 1) + " Regions/m, " + Form.f(chunksPerMinute, 0) + " Chunks/m",
|
||||||
Form.duration(eta, 2) + " Remaining " + " (" + Form.duration(elapsed, 2) + " Elapsed)",
|
Form.duration(eta, 2) + " Remaining " + " (" + Form.duration(elapsed, 2) + " Elapsed)",
|
||||||
"Generation Method: " + method,
|
"Generation Method: " + method,
|
||||||
"Memory: " + Form.memSize(monitor.getUsedBytes(), 2) + " (" + Form.pc(monitor.getUsagePercent(), 0) + ") Pressure: " + Form.memSize(monitor.getPressure(), 0) + "/s",
|
"Memory: " + Form.memSize(monitor.getUsedBytes(), 2) + " (" + Form.pc(monitor.getUsagePercent(), 0) + ") Pressure: " + Form.memSize(monitor.getPressure(), 0) + "/s",
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
for(Consumer<Double> i : onProgress) {
|
for (Consumer<Double> i : onProgress) {
|
||||||
i.accept(percent);
|
i.accept(percent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onChunkGenerated(int x, int z) {
|
public void onChunkGenerated(int x, int z) {
|
||||||
if(engine != null) {
|
if (engine != null) {
|
||||||
draw(x, z, engine.draw((x << 4) + 8, (z << 4) + 8));
|
draw(x, z, engine.draw((x << 4) + 8, (z << 4) + 8));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -263,7 +256,7 @@ public class PregeneratorJob implements PregenListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void shouldGc() {
|
private void shouldGc() {
|
||||||
if(cl.flip() && rgc > 16) {
|
if (cl.flip() && rgc > 16) {
|
||||||
System.gc();
|
System.gc();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -322,7 +315,7 @@ public class PregeneratorJob implements PregenListener {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onChunkExistsInRegionGen(int x, int z) {
|
public void onChunkExistsInRegionGen(int x, int z) {
|
||||||
if(engine != null) {
|
if (engine != null) {
|
||||||
draw(x, z, engine.draw((x << 4) + 8, (z << 4) + 8));
|
draw(x, z, engine.draw((x << 4) + 8, (z << 4) + 8));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -371,10 +364,10 @@ public class PregeneratorJob implements PregenListener {
|
|||||||
bg = (Graphics2D) image.getGraphics();
|
bg = (Graphics2D) image.getGraphics();
|
||||||
l.lock();
|
l.lock();
|
||||||
|
|
||||||
while(order.isNotEmpty()) {
|
while (order.isNotEmpty()) {
|
||||||
try {
|
try {
|
||||||
order.pop().run();
|
order.pop().run();
|
||||||
} catch(Throwable e) {
|
} catch (Throwable e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -388,12 +381,12 @@ public class PregeneratorJob implements PregenListener {
|
|||||||
int h = g.getFontMetrics().getHeight() + 5;
|
int h = g.getFontMetrics().getHeight() + 5;
|
||||||
int hh = 20;
|
int hh = 20;
|
||||||
|
|
||||||
if(job.paused()) {
|
if (job.paused()) {
|
||||||
g.drawString("PAUSED", 20, hh += h);
|
g.drawString("PAUSED", 20, hh += h);
|
||||||
|
|
||||||
g.drawString("Press P to Resume", 20, hh += h);
|
g.drawString("Press P to Resume", 20, hh += h);
|
||||||
} else {
|
} else {
|
||||||
for(String i : prog) {
|
for (String i : prog) {
|
||||||
g.drawString(i, 20, hh += h);
|
g.drawString(i, 20, hh += h);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -429,7 +422,7 @@ public class PregeneratorJob implements PregenListener {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void keyReleased(KeyEvent e) {
|
public void keyReleased(KeyEvent e) {
|
||||||
if(e.getKeyCode() == KeyEvent.VK_P) {
|
if (e.getKeyCode() == KeyEvent.VK_P) {
|
||||||
PregeneratorJob.pauseResume();
|
PregeneratorJob.pauseResume();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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<>();
|
||||||
@@ -143,7 +140,7 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
|||||||
J.a(() -> {
|
J.a(() -> {
|
||||||
J.sleep(10000);
|
J.sleep(10000);
|
||||||
|
|
||||||
if(!helpIgnored && help) {
|
if (!helpIgnored && help) {
|
||||||
help = false;
|
help = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -167,11 +164,11 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
|||||||
frame.setVisible(true);
|
frame.setVisible(true);
|
||||||
File file = Iris.getCached("Iris Icon", "https://raw.githubusercontent.com/VolmitSoftware/Iris/master/icon.png");
|
File file = Iris.getCached("Iris Icon", "https://raw.githubusercontent.com/VolmitSoftware/Iris/master/icon.png");
|
||||||
|
|
||||||
if(file != null) {
|
if (file != null) {
|
||||||
try {
|
try {
|
||||||
nv.texture = ImageIO.read(file);
|
nv.texture = ImageIO.read(file);
|
||||||
frame.setIconImage(ImageIO.read(file));
|
frame.setIconImage(ImageIO.read(file));
|
||||||
} catch(IOException e) {
|
} catch (IOException e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -180,16 +177,16 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
|||||||
|
|
||||||
public static void launch(Engine g, int i) {
|
public static void launch(Engine g, int i) {
|
||||||
J.a(() ->
|
J.a(() ->
|
||||||
createAndShowGUI(g, i, g.getWorld()));
|
createAndShowGUI(g, i, g.getWorld()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean updateEngine() {
|
public boolean updateEngine() {
|
||||||
if(engine.isClosed()) {
|
if (engine.isClosed()) {
|
||||||
if(world.hasRealWorld()) {
|
if (world.hasRealWorld()) {
|
||||||
try {
|
try {
|
||||||
engine = IrisToolbelt.access(world.realWorld()).getEngine();
|
engine = IrisToolbelt.access(world.realWorld()).getEngine();
|
||||||
return !engine.isClosed();
|
return !engine.isClosed();
|
||||||
} catch(Throwable e) {
|
} catch (Throwable e) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -217,13 +214,19 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
|||||||
public int getColor(double wx, double wz) {
|
public int getColor(double wx, double wz) {
|
||||||
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);
|
||||||
@@ -240,51 +243,51 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void keyPressed(KeyEvent e) {
|
public void keyPressed(KeyEvent e) {
|
||||||
if(e.getKeyCode() == KeyEvent.VK_SHIFT) {
|
if (e.getKeyCode() == KeyEvent.VK_SHIFT) {
|
||||||
shift = true;
|
shift = true;
|
||||||
}
|
}
|
||||||
if(e.getKeyCode() == KeyEvent.VK_CONTROL) {
|
if (e.getKeyCode() == KeyEvent.VK_CONTROL) {
|
||||||
control = true;
|
control = true;
|
||||||
}
|
}
|
||||||
if(e.getKeyCode() == KeyEvent.VK_SEMICOLON) {
|
if (e.getKeyCode() == KeyEvent.VK_SEMICOLON) {
|
||||||
debug = true;
|
debug = true;
|
||||||
}
|
}
|
||||||
if(e.getKeyCode() == KeyEvent.VK_SLASH) {
|
if (e.getKeyCode() == KeyEvent.VK_SLASH) {
|
||||||
help = true;
|
help = true;
|
||||||
helpIgnored = true;
|
helpIgnored = true;
|
||||||
}
|
}
|
||||||
if(e.getKeyCode() == KeyEvent.VK_ALT) {
|
if (e.getKeyCode() == KeyEvent.VK_ALT) {
|
||||||
alt = true;
|
alt = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void keyReleased(KeyEvent e) {
|
public void keyReleased(KeyEvent e) {
|
||||||
if(e.getKeyCode() == KeyEvent.VK_SEMICOLON) {
|
if (e.getKeyCode() == KeyEvent.VK_SEMICOLON) {
|
||||||
debug = false;
|
debug = false;
|
||||||
}
|
}
|
||||||
if(e.getKeyCode() == KeyEvent.VK_SHIFT) {
|
if (e.getKeyCode() == KeyEvent.VK_SHIFT) {
|
||||||
shift = false;
|
shift = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(e.getKeyCode() == KeyEvent.VK_CONTROL) {
|
if (e.getKeyCode() == KeyEvent.VK_CONTROL) {
|
||||||
control = false;
|
control = false;
|
||||||
}
|
}
|
||||||
if(e.getKeyCode() == KeyEvent.VK_SLASH) {
|
if (e.getKeyCode() == KeyEvent.VK_SLASH) {
|
||||||
help = false;
|
help = false;
|
||||||
helpIgnored = true;
|
helpIgnored = true;
|
||||||
}
|
}
|
||||||
if(e.getKeyCode() == KeyEvent.VK_ALT) {
|
if (e.getKeyCode() == KeyEvent.VK_ALT) {
|
||||||
alt = false;
|
alt = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pushes
|
// Pushes
|
||||||
if(e.getKeyCode() == KeyEvent.VK_F) {
|
if (e.getKeyCode() == KeyEvent.VK_F) {
|
||||||
follow = !follow;
|
follow = !follow;
|
||||||
|
|
||||||
if(player != null && follow) {
|
if (player != null && follow) {
|
||||||
notify("Following " + player.getName() + ". Press F to disable");
|
notify("Following " + player.getName() + ". Press F to disable");
|
||||||
} else if(follow) {
|
} else if (follow) {
|
||||||
notify("Can't follow, no one is in the world");
|
notify("Can't follow, no one is in the world");
|
||||||
follow = false;
|
follow = false;
|
||||||
} else {
|
} else {
|
||||||
@@ -294,38 +297,38 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(e.getKeyCode() == KeyEvent.VK_R) {
|
if (e.getKeyCode() == KeyEvent.VK_R) {
|
||||||
dump();
|
dump();
|
||||||
notify("Refreshing Chunks");
|
notify("Refreshing Chunks");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(e.getKeyCode() == KeyEvent.VK_P) {
|
if (e.getKeyCode() == KeyEvent.VK_P) {
|
||||||
lowtile = !lowtile;
|
lowtile = !lowtile;
|
||||||
dump();
|
dump();
|
||||||
notify("Rendering " + (lowtile ? "Low" : "High") + " Quality Tiles");
|
notify("Rendering " + (lowtile ? "Low" : "High") + " Quality Tiles");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(e.getKeyCode() == KeyEvent.VK_E) {
|
if (e.getKeyCode() == KeyEvent.VK_E) {
|
||||||
eco = !eco;
|
eco = !eco;
|
||||||
dump();
|
dump();
|
||||||
notify("Using " + (eco ? "60" : "Uncapped") + " FPS Limit");
|
notify("Using " + (eco ? "60" : "Uncapped") + " FPS Limit");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(e.getKeyCode() == KeyEvent.VK_EQUALS) {
|
if (e.getKeyCode() == KeyEvent.VK_EQUALS) {
|
||||||
mscale = mscale + ((0.044 * mscale) * -3);
|
mscale = mscale + ((0.044 * mscale) * -3);
|
||||||
mscale = Math.max(mscale, 0.00001);
|
mscale = Math.max(mscale, 0.00001);
|
||||||
dump();
|
dump();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(e.getKeyCode() == KeyEvent.VK_MINUS) {
|
if (e.getKeyCode() == KeyEvent.VK_MINUS) {
|
||||||
mscale = mscale + ((0.044 * mscale) * 3);
|
mscale = mscale + ((0.044 * mscale) * 3);
|
||||||
mscale = Math.max(mscale, 0.00001);
|
mscale = Math.max(mscale, 0.00001);
|
||||||
dump();
|
dump();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(e.getKeyCode() == KeyEvent.VK_BACK_SLASH) {
|
if (e.getKeyCode() == KeyEvent.VK_BACK_SLASH) {
|
||||||
mscale = 1D;
|
mscale = 1D;
|
||||||
dump();
|
dump();
|
||||||
notify("Zoom Reset");
|
notify("Zoom Reset");
|
||||||
@@ -334,9 +337,9 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
|||||||
|
|
||||||
int currentMode = currentType.ordinal();
|
int currentMode = currentType.ordinal();
|
||||||
|
|
||||||
for(RenderType i : RenderType.values()) {
|
for (RenderType i : RenderType.values()) {
|
||||||
if(e.getKeyChar() == String.valueOf(i.ordinal() + 1).charAt(0)) {
|
if (e.getKeyChar() == String.valueOf(i.ordinal() + 1).charAt(0)) {
|
||||||
if(i.ordinal() != currentMode) {
|
if (i.ordinal() != currentMode) {
|
||||||
currentType = i;
|
currentType = i;
|
||||||
dump();
|
dump();
|
||||||
notify("Rendering " + Form.capitalizeWords(currentType.name().toLowerCase().replaceAll("\\Q_\\E", " ")));
|
notify("Rendering " + Form.capitalizeWords(currentType.name().toLowerCase().replaceAll("\\Q_\\E", " ")));
|
||||||
@@ -345,7 +348,7 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(e.getKeyCode() == KeyEvent.VK_M) {
|
if (e.getKeyCode() == KeyEvent.VK_M) {
|
||||||
currentType = RenderType.values()[(currentMode + 1) % RenderType.values().length];
|
currentType = RenderType.values()[(currentMode + 1) % RenderType.values().length];
|
||||||
notify("Rendering " + Form.capitalizeWords(currentType.name().toLowerCase().replaceAll("\\Q_\\E", " ")));
|
notify("Rendering " + Form.capitalizeWords(currentType.name().toLowerCase().replaceAll("\\Q_\\E", " ")));
|
||||||
dump();
|
dump();
|
||||||
@@ -361,15 +364,15 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
|||||||
BlockPosition key = new BlockPosition((int) mscale, Math.floorDiv(x, div), Math.floorDiv(z, div));
|
BlockPosition key = new BlockPosition((int) mscale, Math.floorDiv(x, div), Math.floorDiv(z, div));
|
||||||
fg.add(key);
|
fg.add(key);
|
||||||
|
|
||||||
if(positions.containsKey(key)) {
|
if (positions.containsKey(key)) {
|
||||||
return positions.get(key);
|
return positions.get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(fastpositions.containsKey(key)) {
|
if (fastpositions.containsKey(key)) {
|
||||||
if(!working.contains(key) && working.size() < 9) {
|
if (!working.contains(key) && working.size() < 9) {
|
||||||
m.set(m.get() - 1);
|
m.set(m.get() - 1);
|
||||||
|
|
||||||
if(m.get() >= 0 && velocity < 50) {
|
if (m.get() >= 0 && velocity < 50) {
|
||||||
working.add(key);
|
working.add(key);
|
||||||
double mk = mscale;
|
double mk = mscale;
|
||||||
double mkd = scale;
|
double mkd = scale;
|
||||||
@@ -380,7 +383,7 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
|||||||
rs.put(ps.getMilliseconds());
|
rs.put(ps.getMilliseconds());
|
||||||
working.remove(key);
|
working.remove(key);
|
||||||
|
|
||||||
if(mk == mscale && mkd == scale) {
|
if (mk == mscale && mkd == scale) {
|
||||||
positions.put(key, b);
|
positions.put(key, b);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -390,7 +393,7 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
|||||||
return fastpositions.get(key);
|
return fastpositions.get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(workingfast.contains(key) || workingfast.size() > Runtime.getRuntime().availableProcessors()) {
|
if (workingfast.contains(key) || workingfast.size() > Runtime.getRuntime().availableProcessors()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -404,7 +407,7 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
|||||||
rs.put(ps.getMilliseconds());
|
rs.put(ps.getMilliseconds());
|
||||||
workingfast.remove(key);
|
workingfast.remove(key);
|
||||||
|
|
||||||
if(mk == mscale && mkd == scale) {
|
if (mk == mscale && mkd == scale) {
|
||||||
fastpositions.put(key, b);
|
fastpositions.put(key, b);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -431,15 +434,11 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
|||||||
@Override
|
@Override
|
||||||
public void paint(Graphics gx) {
|
public void paint(Graphics gx) {
|
||||||
|
|
||||||
if(engine.isClosed()) {
|
if (engine.isClosed()) {
|
||||||
EventQueue.invokeLater(() -> {
|
EventQueue.invokeLater(() -> {
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
setVisible(false);
|
setVisible(false);
|
||||||
}
|
} catch (Throwable e) {
|
||||||
|
|
||||||
catch(Throwable e)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -447,49 +446,49 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(updateEngine()) {
|
if (updateEngine()) {
|
||||||
dump();
|
dump();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ox < oxp) {
|
if (ox < oxp) {
|
||||||
velocity = Math.abs(ox - oxp) * 0.36;
|
velocity = Math.abs(ox - oxp) * 0.36;
|
||||||
oxp -= velocity;
|
oxp -= velocity;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ox > oxp) {
|
if (ox > oxp) {
|
||||||
velocity = Math.abs(oxp - ox) * 0.36;
|
velocity = Math.abs(oxp - ox) * 0.36;
|
||||||
oxp += velocity;
|
oxp += velocity;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(oz < ozp) {
|
if (oz < ozp) {
|
||||||
velocity = Math.abs(oz - ozp) * 0.36;
|
velocity = Math.abs(oz - ozp) * 0.36;
|
||||||
ozp -= velocity;
|
ozp -= velocity;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(oz > ozp) {
|
if (oz > ozp) {
|
||||||
velocity = Math.abs(ozp - oz) * 0.36;
|
velocity = Math.abs(ozp - oz) * 0.36;
|
||||||
ozp += velocity;
|
ozp += velocity;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(lx < hx) {
|
if (lx < hx) {
|
||||||
hx -= Math.abs(lx - hx) * 0.36;
|
hx -= Math.abs(lx - hx) * 0.36;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(lx > hx) {
|
if (lx > hx) {
|
||||||
hx += Math.abs(hx - lx) * 0.36;
|
hx += Math.abs(hx - lx) * 0.36;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(lz < hz) {
|
if (lz < hz) {
|
||||||
hz -= Math.abs(lz - hz) * 0.36;
|
hz -= Math.abs(lz - hz) * 0.36;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(lz > hz) {
|
if (lz > hz) {
|
||||||
hz += Math.abs(hz - lz) * 0.36;
|
hz += Math.abs(hz - lz) * 0.36;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(centities.flip()) {
|
if (centities.flip()) {
|
||||||
J.s(() -> {
|
J.s(() -> {
|
||||||
synchronized(lastEntities) {
|
synchronized (lastEntities) {
|
||||||
lastEntities.clear();
|
lastEntities.clear();
|
||||||
lastEntities.addAll(world.getEntitiesByClass(LivingEntity.class));
|
lastEntities.addAll(world.getEntitiesByClass(LivingEntity.class));
|
||||||
}
|
}
|
||||||
@@ -503,7 +502,7 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
|||||||
double vscale = scale;
|
double vscale = scale;
|
||||||
scale = w / 12D;
|
scale = w / 12D;
|
||||||
|
|
||||||
if(scale != vscale) {
|
if (scale != vscale) {
|
||||||
positions.clear();
|
positions.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -515,15 +514,15 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
|||||||
int posZ = (int) ozp;
|
int posZ = (int) ozp;
|
||||||
m.set(3);
|
m.set(3);
|
||||||
|
|
||||||
for(int r = 0; r < Math.max(w, h); r += iscale) {
|
for (int r = 0; r < Math.max(w, h); r += iscale) {
|
||||||
for(int i = -iscale; i < w + iscale; i += iscale) {
|
for (int i = -iscale; i < w + iscale; i += iscale) {
|
||||||
for(int j = -iscale; j < h + iscale; j += iscale) {
|
for (int j = -iscale; j < h + iscale; j += iscale) {
|
||||||
int a = i - (w / 2);
|
int a = i - (w / 2);
|
||||||
int b = j - (h / 2);
|
int b = j - (h / 2);
|
||||||
if(a * a + b * b <= r * r) {
|
if (a * a + b * b <= r * r) {
|
||||||
BufferedImage t = getTile(gg, iscale, Math.floorDiv((posX / iscale) + i, iscale) * iscale, Math.floorDiv((posZ / iscale) + j, iscale) * iscale, m);
|
BufferedImage t = getTile(gg, iscale, Math.floorDiv((posX / iscale) + i, iscale) * iscale, Math.floorDiv((posZ / iscale) + j, iscale) * iscale, m);
|
||||||
|
|
||||||
if(t != null) {
|
if (t != null) {
|
||||||
g.drawImage(t, i - ((posX / iscale) % (iscale)), j - ((posZ / iscale) % (iscale)), iscale, iscale, (img, infoflags, x, y, width, height) -> true);
|
g.drawImage(t, i - ((posX / iscale) % (iscale)), j - ((posZ / iscale) % (iscale)), iscale, iscale, (img, infoflags, x, y, width, height) -> true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -533,8 +532,8 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
|||||||
|
|
||||||
p.end();
|
p.end();
|
||||||
|
|
||||||
for(BlockPosition i : positions.k()) {
|
for (BlockPosition i : positions.k()) {
|
||||||
if(!gg.contains(i)) {
|
if (!gg.contains(i)) {
|
||||||
positions.remove(i);
|
positions.remove(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -542,15 +541,15 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
|||||||
hanleFollow();
|
hanleFollow();
|
||||||
renderOverlays(g);
|
renderOverlays(g);
|
||||||
|
|
||||||
if(!isVisible()) {
|
if (!isVisible()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!getParent().isVisible()) {
|
if (!getParent().isVisible()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!getParent().getParent().isVisible()) {
|
if (!getParent().getParent().isVisible()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -562,7 +561,7 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void hanleFollow() {
|
private void hanleFollow() {
|
||||||
if(follow && player != null) {
|
if (follow && player != null) {
|
||||||
animateTo(player.getLocation().getX(), player.getLocation().getZ());
|
animateTo(player.getLocation().getX(), player.getLocation().getZ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -570,16 +569,16 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
|||||||
private void renderOverlays(Graphics2D g) {
|
private void renderOverlays(Graphics2D g) {
|
||||||
renderPlayer(g);
|
renderPlayer(g);
|
||||||
|
|
||||||
if(help) {
|
if (help) {
|
||||||
renderOverlayHelp(g);
|
renderOverlayHelp(g);
|
||||||
} else if(debug) {
|
} else if (debug) {
|
||||||
renderOverlayDebug(g);
|
renderOverlayDebug(g);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderOverlayLegend(g);
|
renderOverlayLegend(g);
|
||||||
|
|
||||||
renderHoverOverlay(g, shift);
|
renderHoverOverlay(g, shift);
|
||||||
if(!notifications.isEmpty()) {
|
if (!notifications.isEmpty()) {
|
||||||
renderNotification(g);
|
renderNotification(g);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -597,8 +596,8 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
|||||||
private void renderNotification(Graphics2D g) {
|
private void renderNotification(Graphics2D g) {
|
||||||
drawCardCB(g, notifications.k());
|
drawCardCB(g, notifications.k());
|
||||||
|
|
||||||
for(String i : notifications.k()) {
|
for (String i : notifications.k()) {
|
||||||
if(M.ms() > notifications.get(i)) {
|
if (M.ms() > notifications.get(i)) {
|
||||||
notifications.remove(i);
|
notifications.remove(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -607,32 +606,32 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
|||||||
private void renderPlayer(Graphics2D g) {
|
private void renderPlayer(Graphics2D g) {
|
||||||
Player b = null;
|
Player b = null;
|
||||||
|
|
||||||
for(Player i : world.getPlayers()) {
|
for (Player i : world.getPlayers()) {
|
||||||
b = i;
|
b = i;
|
||||||
renderPosition(g, i.getLocation().getX(), i.getLocation().getZ());
|
renderPosition(g, i.getLocation().getX(), i.getLocation().getZ());
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized(lastEntities) {
|
synchronized (lastEntities) {
|
||||||
double dist = Double.MAX_VALUE;
|
double dist = Double.MAX_VALUE;
|
||||||
LivingEntity h = null;
|
LivingEntity h = null;
|
||||||
|
|
||||||
for(LivingEntity i : lastEntities) {
|
for (LivingEntity i : lastEntities) {
|
||||||
if(i instanceof Player) {
|
if (i instanceof Player) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderMobPosition(g, i, i.getLocation().getX(), i.getLocation().getZ());
|
renderMobPosition(g, i, i.getLocation().getX(), i.getLocation().getZ());
|
||||||
if(shift) {
|
if (shift) {
|
||||||
double d = i.getLocation().distanceSquared(new Location(i.getWorld(), getWorldX(hx), i.getLocation().getY(), getWorldZ(hz)));
|
double d = i.getLocation().distanceSquared(new Location(i.getWorld(), getWorldX(hx), i.getLocation().getY(), getWorldZ(hz)));
|
||||||
|
|
||||||
if(d < dist) {
|
if (d < dist) {
|
||||||
dist = d;
|
dist = d;
|
||||||
h = i;
|
h = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(h != null && shift) {
|
if (h != null && shift) {
|
||||||
g.setColor(Color.red);
|
g.setColor(Color.red);
|
||||||
g.fillRoundRect((int) getScreenX(h.getLocation().getX()) - 10, (int) getScreenZ(h.getLocation().getZ()) - 10, 20, 20, 20, 20);
|
g.fillRoundRect((int) getScreenX(h.getLocation().getX()) - 10, (int) getScreenZ(h.getLocation().getZ()) - 10, 20, 20, 20, 20);
|
||||||
KList<String> k = new KList<>();
|
KList<String> k = new KList<>();
|
||||||
@@ -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);
|
||||||
}
|
}
|
||||||
@@ -657,7 +656,7 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void renderPosition(Graphics2D g, double x, double z) {
|
private void renderPosition(Graphics2D g, double x, double z) {
|
||||||
if(texture != null) {
|
if (texture != null) {
|
||||||
g.drawImage(texture, (int) getScreenX(x), (int) getScreenZ(z), 66, 66, (img, infoflags, xx, xy, width, height) -> true);
|
g.drawImage(texture, (int) getScreenX(x), (int) getScreenZ(z), 66, 66, (img, infoflags, xx, xy, width, height) -> true);
|
||||||
} else {
|
} else {
|
||||||
g.setColor(Color.darkGray);
|
g.setColor(Color.darkGray);
|
||||||
@@ -679,7 +678,7 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
|||||||
l.add("Biome: " + biome.getName());
|
l.add("Biome: " + biome.getName());
|
||||||
l.add("Region: " + region.getName() + "(" + region.getLoadKey() + ")");
|
l.add("Region: " + region.getName() + "(" + region.getLoadKey() + ")");
|
||||||
l.add("Block " + (int) getWorldX(hx) + ", " + (int) getWorldZ(hz));
|
l.add("Block " + (int) getWorldX(hx) + ", " + (int) getWorldZ(hz));
|
||||||
if(detailed) {
|
if (detailed) {
|
||||||
l.add("Chunk " + ((int) getWorldX(hx) >> 4) + ", " + ((int) getWorldZ(hz) >> 4));
|
l.add("Chunk " + ((int) getWorldX(hx) >> 4) + ", " + ((int) getWorldZ(hz) >> 4));
|
||||||
l.add("Region " + (((int) getWorldX(hx) >> 4) >> 5) + ", " + (((int) getWorldZ(hz) >> 4) >> 5));
|
l.add("Region " + (((int) getWorldX(hx) >> 4) >> 5) + ", " + (((int) getWorldZ(hz) >> 4) >> 5));
|
||||||
l.add("Key: " + biome.getLoadKey());
|
l.add("Key: " + biome.getLoadKey());
|
||||||
@@ -708,7 +707,7 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
|||||||
l.add("E to toggle Eco FPS Mode");
|
l.add("E to toggle Eco FPS Mode");
|
||||||
|
|
||||||
int ff = 0;
|
int ff = 0;
|
||||||
for(RenderType i : RenderType.values()) {
|
for (RenderType i : RenderType.values()) {
|
||||||
ff++;
|
ff++;
|
||||||
l.add(ff + " to view " + Form.capitalizeWords(i.name().toLowerCase().replaceAll("\\Q_\\E", " ")));
|
l.add(ff + " to view " + Form.capitalizeWords(i.name().toLowerCase().replaceAll("\\Q_\\E", " ")));
|
||||||
}
|
}
|
||||||
@@ -738,8 +737,9 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
|||||||
private void open() {
|
private void open() {
|
||||||
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();
|
||||||
@@ -751,7 +751,7 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
|||||||
|
|
||||||
private void teleport() {
|
private void teleport() {
|
||||||
J.s(() -> {
|
J.s(() -> {
|
||||||
if(player != null) {
|
if (player != null) {
|
||||||
int xx = (int) getWorldX(hx);
|
int xx = (int) getWorldX(hx);
|
||||||
int zz = (int) getWorldZ(hz);
|
int zz = (int) getWorldZ(hz);
|
||||||
int h = engine.getComplex().getRoundedHeighteightStream().get(xx, zz);
|
int h = engine.getComplex().getRoundedHeighteightStream().get(xx, zz);
|
||||||
@@ -776,7 +776,7 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
|||||||
int h = 0;
|
int h = 0;
|
||||||
int w = 0;
|
int w = 0;
|
||||||
|
|
||||||
for(String i : text) {
|
for (String i : text) {
|
||||||
h += g.getFontMetrics().getHeight();
|
h += g.getFontMetrics().getHeight();
|
||||||
w = Math.max(w, g.getFontMetrics().stringWidth(i));
|
w = Math.max(w, g.getFontMetrics().stringWidth(i));
|
||||||
}
|
}
|
||||||
@@ -796,14 +796,14 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
|||||||
|
|
||||||
g.setColor(Color.black);
|
g.setColor(Color.black);
|
||||||
int m = 0;
|
int m = 0;
|
||||||
for(String i : text) {
|
for (String i : text) {
|
||||||
g.drawString(i, x + 14 - cw, y + 14 - ch + (++m * g.getFontMetrics().getHeight()));
|
g.drawString(i, x + 14 - cw, y + 14 - ch + (++m * g.getFontMetrics().getHeight()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void mouseWheelMoved(MouseWheelEvent e) {
|
public void mouseWheelMoved(MouseWheelEvent e) {
|
||||||
int notches = e.getWheelRotation();
|
int notches = e.getWheelRotation();
|
||||||
if(e.isControlDown()) {
|
if (e.isControlDown()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -816,9 +816,9 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mouseClicked(MouseEvent e) {
|
public void mouseClicked(MouseEvent e) {
|
||||||
if(control) {
|
if (control) {
|
||||||
teleport();
|
teleport();
|
||||||
} else if(alt) {
|
} else if (alt) {
|
||||||
open();
|
open();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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,59 +54,63 @@ 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) {
|
||||||
return a.getEngine().getRegion(l).getName();
|
return a.getEngine().getRegion(l).getName();
|
||||||
}
|
}
|
||||||
} else if(p.equalsIgnoreCase("region_id")) {
|
} else if (p.equalsIgnoreCase("region_id")) {
|
||||||
if(a != null) {
|
if (a != null) {
|
||||||
return a.getEngine().getRegion(l).getLoadKey();
|
return a.getEngine().getRegion(l).getLoadKey();
|
||||||
}
|
}
|
||||||
} else if(p.equalsIgnoreCase("region_file")) {
|
} else if (p.equalsIgnoreCase("region_file")) {
|
||||||
if(a != null) {
|
if (a != null) {
|
||||||
return a.getEngine().getRegion(l).getLoadFile().getPath();
|
return a.getEngine().getRegion(l).getLoadFile().getPath();
|
||||||
}
|
}
|
||||||
} else if(p.equalsIgnoreCase("terrain_slope")) {
|
} else if (p.equalsIgnoreCase("terrain_slope")) {
|
||||||
if(a != null) {
|
if (a != null) {
|
||||||
return (a.getEngine())
|
return (a.getEngine())
|
||||||
.getComplex().getSlopeStream()
|
.getComplex().getSlopeStream()
|
||||||
.get(l.getX(), l.getZ()) + "";
|
.get(l.getX(), l.getZ()) + "";
|
||||||
}
|
}
|
||||||
} else if(p.equalsIgnoreCase("terrain_height")) {
|
} else if (p.equalsIgnoreCase("terrain_height")) {
|
||||||
if(a != null) {
|
if (a != null) {
|
||||||
return Math.round(a.getEngine().getHeight(l.getBlockX(), l.getBlockZ())) + "";
|
return Math.round(a.getEngine().getHeight(l.getBlockX(), l.getBlockZ())) + "";
|
||||||
}
|
}
|
||||||
} else if(p.equalsIgnoreCase("world_mode")) {
|
} else if (p.equalsIgnoreCase("world_mode")) {
|
||||||
if(a != null) {
|
if (a != null) {
|
||||||
return a.isStudio() ? "Studio" : "Production";
|
return a.isStudio() ? "Studio" : "Production";
|
||||||
}
|
}
|
||||||
} else if(p.equalsIgnoreCase("world_seed")) {
|
} else if (p.equalsIgnoreCase("world_seed")) {
|
||||||
if(a != null) {
|
if (a != null) {
|
||||||
return a.getEngine().getSeedManager().getSeed() + "";
|
return a.getEngine().getSeedManager().getSeed() + "";
|
||||||
}
|
}
|
||||||
} else if(p.equalsIgnoreCase("world_speed")) {
|
} else if (p.equalsIgnoreCase("world_speed")) {
|
||||||
if(a != null) {
|
if (a != null) {
|
||||||
return a.getEngine().getGeneratedPerSecond() + "/s";
|
return a.getEngine().getGeneratedPerSecond() + "/s";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -38,7 +38,7 @@ public class MultiverseCoreLink {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean addWorld(String worldName, IrisDimension dim, String seed) {
|
public boolean addWorld(String worldName, IrisDimension dim, String seed) {
|
||||||
if(!isSupported()) {
|
if (!isSupported()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,11 +47,11 @@ public class MultiverseCoreLink {
|
|||||||
Object mvWorldManager = p.getClass().getDeclaredMethod("getMVWorldManager").invoke(p);
|
Object mvWorldManager = p.getClass().getDeclaredMethod("getMVWorldManager").invoke(p);
|
||||||
Method m = mvWorldManager.getClass().getDeclaredMethod("addWorld",
|
Method m = mvWorldManager.getClass().getDeclaredMethod("addWorld",
|
||||||
|
|
||||||
String.class, World.Environment.class, String.class, WorldType.class, Boolean.class, String.class, boolean.class);
|
String.class, World.Environment.class, String.class, WorldType.class, Boolean.class, String.class, boolean.class);
|
||||||
boolean b = (boolean) m.invoke(mvWorldManager, worldName, dim.getEnvironment(), seed, WorldType.NORMAL, false, "Iris", false);
|
boolean b = (boolean) m.invoke(mvWorldManager, worldName, dim.getEnvironment(), seed, WorldType.NORMAL, false, "Iris", false);
|
||||||
saveConfig();
|
saveConfig();
|
||||||
return b;
|
return b;
|
||||||
} catch(Throwable e) {
|
} catch (Throwable e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@@ -67,7 +67,7 @@ public class MultiverseCoreLink {
|
|||||||
Field f = mvWorldManager.getClass().getDeclaredField("worldsFromTheConfig");
|
Field f = mvWorldManager.getClass().getDeclaredField("worldsFromTheConfig");
|
||||||
f.setAccessible(true);
|
f.setAccessible(true);
|
||||||
return (Map<String, ?>) f.get(mvWorldManager);
|
return (Map<String, ?>) f.get(mvWorldManager);
|
||||||
} catch(Throwable e) {
|
} catch (Throwable e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@@ -76,7 +76,7 @@ public class MultiverseCoreLink {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void removeFromConfig(World world) {
|
public void removeFromConfig(World world) {
|
||||||
if(!isSupported()) {
|
if (!isSupported()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,7 +85,7 @@ public class MultiverseCoreLink {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void removeFromConfig(String world) {
|
public void removeFromConfig(String world) {
|
||||||
if(!isSupported()) {
|
if (!isSupported()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,7 +98,7 @@ public class MultiverseCoreLink {
|
|||||||
Plugin p = getMultiverse();
|
Plugin p = getMultiverse();
|
||||||
Object mvWorldManager = p.getClass().getDeclaredMethod("getMVWorldManager").invoke(p);
|
Object mvWorldManager = p.getClass().getDeclaredMethod("getMVWorldManager").invoke(p);
|
||||||
mvWorldManager.getClass().getDeclaredMethod("saveWorldsConfig").invoke(mvWorldManager);
|
mvWorldManager.getClass().getDeclaredMethod("saveWorldsConfig").invoke(mvWorldManager);
|
||||||
} catch(Throwable e) {
|
} catch (Throwable e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@@ -112,7 +112,7 @@ public class MultiverseCoreLink {
|
|||||||
try {
|
try {
|
||||||
String t = worldNameTypes.get(worldName);
|
String t = worldNameTypes.get(worldName);
|
||||||
return t == null ? defaultType : t;
|
return t == null ? defaultType : t;
|
||||||
} catch(Throwable e) {
|
} catch (Throwable e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
return defaultType;
|
return defaultType;
|
||||||
}
|
}
|
||||||
@@ -128,11 +128,11 @@ public class MultiverseCoreLink {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String envName(World.Environment environment) {
|
public String envName(World.Environment environment) {
|
||||||
if(environment == null) {
|
if (environment == null) {
|
||||||
return "normal";
|
return "normal";
|
||||||
}
|
}
|
||||||
|
|
||||||
return switch(environment) {
|
return switch (environment) {
|
||||||
case NORMAL -> "normal";
|
case NORMAL -> "normal";
|
||||||
case NETHER -> "nether";
|
case NETHER -> "nether";
|
||||||
case THE_END -> "end";
|
case THE_END -> "end";
|
||||||
@@ -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) {
|
||||||
@@ -59,57 +60,73 @@ public class ImageResourceLoader extends ResourceLoader<IrisImage> {
|
|||||||
logLoad(j, img);
|
logLoad(j, img);
|
||||||
tlt.addAndGet(p.getMilliseconds());
|
tlt.addAndGet(p.getMilliseconds());
|
||||||
return img;
|
return img;
|
||||||
} catch(Throwable e) {
|
} catch (Throwable e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
Iris.warn("Couldn't read " + resourceTypeName + " file: " + j.getPath() + ": " + e.getMessage());
|
Iris.warn("Couldn't read " + resourceTypeName + " file: " + j.getPath() + ": " + e.getMessage());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void getPNGFiles(File directory, Set<String> m) {
|
||||||
|
for (File file : directory.listFiles()) {
|
||||||
|
if (file.isFile() && file.getName().endsWith(".png")) {
|
||||||
|
m.add(file.getName().replaceAll("\\Q.png\\E", ""));
|
||||||
|
} else if (file.isDirectory()) {
|
||||||
|
getPNGFiles(file, m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public String[] getPossibleKeys() {
|
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<>();
|
KSet<String> m = new KSet<>();
|
||||||
|
|
||||||
for(File i : getFolders()) {
|
|
||||||
for(File j : i.listFiles()) {
|
for (File i : getFolders()) {
|
||||||
if(j.isFile() && j.getName().endsWith(".png")) {
|
getPNGFiles(i, m);
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
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()) {
|
||||||
if(j.isFile() && j.getName().endsWith(".png") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
if (j.isFile() && j.getName().endsWith(".png") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
||||||
return j;
|
return j;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
File file = new File(i, name + ".png");
|
File file = new File(i, name + ".png");
|
||||||
|
|
||||||
if(file.exists()) {
|
if (file.exists()) {
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -124,16 +141,16 @@ public class ImageResourceLoader extends ResourceLoader<IrisImage> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private IrisImage loadRaw(String name) {
|
private IrisImage loadRaw(String name) {
|
||||||
for(File i : getFolders(name)) {
|
for (File i : getFolders(name)) {
|
||||||
for(File j : i.listFiles()) {
|
for (File j : i.listFiles()) {
|
||||||
if(j.isFile() && j.getName().endsWith(".png") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
if (j.isFile() && j.getName().endsWith(".png") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
||||||
return loadFile(j, name);
|
return loadFile(j, name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
File file = new File(i, name + ".png");
|
File file = new File(i, name + ".png");
|
||||||
|
|
||||||
if(file.exists()) {
|
if (file.exists()) {
|
||||||
return loadFile(file, name);
|
return loadFile(file, name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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;
|
||||||
@@ -100,8 +98,8 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
|||||||
|
|
||||||
public static int cacheSize() {
|
public static int cacheSize() {
|
||||||
int m = 0;
|
int m = 0;
|
||||||
for(IrisData i : dataLoaders.values()) {
|
for (IrisData i : dataLoaders.values()) {
|
||||||
for(ResourceLoader<?> j : i.getLoaders().values()) {
|
for (ResourceLoader<?> j : i.getLoaders().values()) {
|
||||||
m += j.getLoadCache().getSize();
|
m += j.getLoadCache().getSize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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));
|
||||||
}
|
}
|
||||||
@@ -194,17 +193,17 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
|||||||
|
|
||||||
public static <T extends IrisRegistrant> T loadAny(String key, Function<IrisData, T> v) {
|
public static <T extends IrisRegistrant> T loadAny(String key, Function<IrisData, T> v) {
|
||||||
try {
|
try {
|
||||||
for(File i : Objects.requireNonNull(Iris.instance.getDataFolder("packs").listFiles())) {
|
for (File i : Objects.requireNonNull(Iris.instance.getDataFolder("packs").listFiles())) {
|
||||||
if(i.isDirectory()) {
|
if (i.isDirectory()) {
|
||||||
IrisData dm = get(i);
|
IrisData dm = get(i);
|
||||||
T t = v.apply(dm);
|
T t = v.apply(dm);
|
||||||
|
|
||||||
if(t != null) {
|
if (t != null) {
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch(Throwable e) {
|
} catch (Throwable e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@@ -215,9 +214,9 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
|||||||
public ResourceLoader<?> getTypedLoaderFor(File f) {
|
public ResourceLoader<?> getTypedLoaderFor(File f) {
|
||||||
String[] k = f.getPath().split("\\Q" + File.separator + "\\E");
|
String[] k = f.getPath().split("\\Q" + File.separator + "\\E");
|
||||||
|
|
||||||
for(String i : k) {
|
for (String i : k) {
|
||||||
for(ResourceLoader<?> j : loaders.values()) {
|
for (ResourceLoader<?> j : loaders.values()) {
|
||||||
if(j.getFolderName().equals(i)) {
|
if (j.getFolderName().equals(i)) {
|
||||||
return j;
|
return j;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -227,7 +226,7 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void cleanupEngine() {
|
public void cleanupEngine() {
|
||||||
if(engine != null && engine.isClosed()) {
|
if (engine != null && engine.isClosed()) {
|
||||||
engine = null;
|
engine = null;
|
||||||
Iris.debug("Dereferenced Data<Engine> " + getId() + " " + getDataFolder());
|
Iris.debug("Dereferenced Data<Engine> " + getId() + " " + getDataFolder());
|
||||||
}
|
}
|
||||||
@@ -238,30 +237,30 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
|||||||
IrisContext ctx = IrisContext.get();
|
IrisContext ctx = IrisContext.get();
|
||||||
Engine engine = this.engine;
|
Engine engine = this.engine;
|
||||||
|
|
||||||
if(engine == null && ctx != null && ctx.getEngine() != null) {
|
if (engine == null && ctx != null && ctx.getEngine() != null) {
|
||||||
engine = ctx.getEngine();
|
engine = ctx.getEngine();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(engine == null && t.getPreprocessors().isNotEmpty()) {
|
if (engine == null && t.getPreprocessors().isNotEmpty()) {
|
||||||
Iris.error("Failed to preprocess object " + t.getLoadKey() + " because there is no engine context here. (See stack below)");
|
Iris.error("Failed to preprocess object " + t.getLoadKey() + " because there is no engine context here. (See stack below)");
|
||||||
try {
|
try {
|
||||||
throw new RuntimeException();
|
throw new RuntimeException();
|
||||||
} catch(Throwable ex) {
|
} catch (Throwable ex) {
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(engine != null && t.getPreprocessors().isNotEmpty()) {
|
if (engine != null && t.getPreprocessors().isNotEmpty()) {
|
||||||
synchronized(this) {
|
synchronized (this) {
|
||||||
engine.getExecution().getAPI().setPreprocessorObject(t);
|
engine.getExecution().getAPI().setPreprocessorObject(t);
|
||||||
|
|
||||||
for(String i : t.getPreprocessors()) {
|
for (String i : t.getPreprocessors()) {
|
||||||
engine.getExecution().execute(i);
|
engine.getExecution().execute(i);
|
||||||
Iris.debug("Loader<" + C.GREEN + t.getTypeName() + C.LIGHT_PURPLE + "> iprocess " + C.YELLOW + t.getLoadKey() + C.LIGHT_PURPLE + " in <rainbow>" + i);
|
Iris.debug("Loader<" + C.GREEN + t.getTypeName() + C.LIGHT_PURPLE + "> iprocess " + C.YELLOW + t.getLoadKey() + C.LIGHT_PURPLE + " in <rainbow>" + i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch(Throwable e) {
|
} catch (Throwable e) {
|
||||||
Iris.error("Failed to preprocess object!");
|
Iris.error("Failed to preprocess object!");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@@ -280,18 +279,18 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
|||||||
try {
|
try {
|
||||||
IrisRegistrant rr = registrant.getConstructor().newInstance();
|
IrisRegistrant rr = registrant.getConstructor().newInstance();
|
||||||
ResourceLoader<T> r = null;
|
ResourceLoader<T> r = null;
|
||||||
if(registrant.equals(IrisObject.class)) {
|
if (registrant.equals(IrisObject.class)) {
|
||||||
r = (ResourceLoader<T>) new ObjectResourceLoader(dataFolder, this, rr.getFolderName(),
|
r = (ResourceLoader<T>) new ObjectResourceLoader(dataFolder, this, rr.getFolderName(),
|
||||||
rr.getTypeName());
|
rr.getTypeName());
|
||||||
} else if(registrant.equals(IrisMatterObject.class)) {
|
} else if (registrant.equals(IrisMatterObject.class)) {
|
||||||
r = (ResourceLoader<T>) new MatterObjectResourceLoader(dataFolder, this, rr.getFolderName(),
|
r = (ResourceLoader<T>) new MatterObjectResourceLoader(dataFolder, this, rr.getFolderName(),
|
||||||
rr.getTypeName());
|
rr.getTypeName());
|
||||||
} else if(registrant.equals(IrisScript.class)) {
|
} else if (registrant.equals(IrisScript.class)) {
|
||||||
r = (ResourceLoader<T>) new ScriptResourceLoader(dataFolder, this, rr.getFolderName(),
|
r = (ResourceLoader<T>) new ScriptResourceLoader(dataFolder, this, rr.getFolderName(),
|
||||||
rr.getTypeName());
|
rr.getTypeName());
|
||||||
} else if(registrant.equals(IrisImage.class)) {
|
} else if (registrant.equals(IrisImage.class)) {
|
||||||
r = (ResourceLoader<T>) new ImageResourceLoader(dataFolder, this, rr.getFolderName(),
|
r = (ResourceLoader<T>) new ImageResourceLoader(dataFolder, this, rr.getFolderName(),
|
||||||
rr.getTypeName());
|
rr.getTypeName());
|
||||||
} else {
|
} else {
|
||||||
J.attempt(() -> registrant.getConstructor().newInstance().registerTypeAdapters(builder));
|
J.attempt(() -> registrant.getConstructor().newInstance().registerTypeAdapters(builder));
|
||||||
r = new ResourceLoader<>(dataFolder, this, rr.getFolderName(), rr.getTypeName(), registrant);
|
r = new ResourceLoader<>(dataFolder, this, rr.getFolderName(), rr.getTypeName(), registrant);
|
||||||
@@ -300,7 +299,7 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
|||||||
loaders.put(registrant, r);
|
loaders.put(registrant, r);
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
} catch(Throwable e) {
|
} catch (Throwable e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
Iris.error("Failed to create loader! " + registrant.getCanonicalName());
|
Iris.error("Failed to create loader! " + registrant.getCanonicalName());
|
||||||
}
|
}
|
||||||
@@ -311,11 +310,11 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
|||||||
public synchronized void hotloaded() {
|
public synchronized void hotloaded() {
|
||||||
possibleSnippets = new KMap<>();
|
possibleSnippets = new KMap<>();
|
||||||
builder = new GsonBuilder()
|
builder = new GsonBuilder()
|
||||||
.addDeserializationExclusionStrategy(this)
|
.addDeserializationExclusionStrategy(this)
|
||||||
.addSerializationExclusionStrategy(this)
|
.addSerializationExclusionStrategy(this)
|
||||||
.setLenient()
|
.setLenient()
|
||||||
.registerTypeAdapterFactory(this)
|
.registerTypeAdapterFactory(this)
|
||||||
.setPrettyPrinting();
|
.setPrettyPrinting();
|
||||||
loaders.clear();
|
loaders.clear();
|
||||||
File packs = dataFolder;
|
File packs = dataFolder;
|
||||||
packs.mkdirs();
|
packs.mkdirs();
|
||||||
@@ -339,30 +338,39 @@ 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();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void dump() {
|
public void dump() {
|
||||||
for(ResourceLoader<?> i : loaders.values()) {
|
for (ResourceLoader<?> i : loaders.values()) {
|
||||||
i.clearCache();
|
i.clearCache();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clearLists() {
|
public void clearLists() {
|
||||||
for(ResourceLoader<?> i : loaders.values()) {
|
for (ResourceLoader<?> i : loaders.values()) {
|
||||||
i.clearList();
|
i.clearList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toLoadKey(File f) {
|
public String toLoadKey(File f) {
|
||||||
if(f.getPath().startsWith(getDataFolder().getPath())) {
|
if (f.getPath().startsWith(getDataFolder().getPath())) {
|
||||||
String[] full = f.getPath().split("\\Q" + File.separator + "\\E");
|
String[] full = f.getPath().split("\\Q" + File.separator + "\\E");
|
||||||
String[] df = getDataFolder().getPath().split("\\Q" + File.separator + "\\E");
|
String[] df = getDataFolder().getPath().split("\\Q" + File.separator + "\\E");
|
||||||
StringBuilder g = new StringBuilder();
|
StringBuilder g = new StringBuilder();
|
||||||
boolean m = true;
|
boolean m = true;
|
||||||
for(int i = 0; i < full.length; i++) {
|
for (int i = 0; i < full.length; i++) {
|
||||||
if(i >= df.length) {
|
if (i >= df.length) {
|
||||||
if(m) {
|
if (m) {
|
||||||
m = false;
|
m = false;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -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() + ")");
|
||||||
}
|
}
|
||||||
@@ -389,14 +396,14 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean shouldSkipClass(Class<?> c) {
|
public boolean shouldSkipClass(Class<?> c) {
|
||||||
if(c.equals(AtomicCache.class)) {
|
if (c.equals(AtomicCache.class)) {
|
||||||
return true;
|
return true;
|
||||||
} else return c.equals(ChronoLatch.class);
|
} else return c.equals(ChronoLatch.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
|
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
|
||||||
if(!typeToken.getRawType().isAnnotationPresent(Snippet.class)) {
|
if (!typeToken.getRawType().isAnnotationPresent(Snippet.class)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -412,17 +419,17 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
|||||||
public T read(JsonReader reader) throws IOException {
|
public T read(JsonReader reader) throws IOException {
|
||||||
TypeAdapter<T> adapter = gson.getDelegateAdapter(IrisData.this, typeToken);
|
TypeAdapter<T> adapter = gson.getDelegateAdapter(IrisData.this, typeToken);
|
||||||
|
|
||||||
if(reader.peek().equals(JsonToken.STRING)) {
|
if (reader.peek().equals(JsonToken.STRING)) {
|
||||||
String r = reader.nextString();
|
String r = reader.nextString();
|
||||||
|
|
||||||
if(r.startsWith("snippet/" + snippetType + "/")) {
|
if (r.startsWith("snippet/" + snippetType + "/")) {
|
||||||
File f = new File(getDataFolder(), r + ".json");
|
File f = new File(getDataFolder(), r + ".json");
|
||||||
|
|
||||||
if(f.exists()) {
|
if (f.exists()) {
|
||||||
try {
|
try {
|
||||||
JsonReader snippetReader = new JsonReader(new FileReader(f));
|
JsonReader snippetReader = new JsonReader(new FileReader(f));
|
||||||
return adapter.read(snippetReader);
|
return adapter.read(snippetReader);
|
||||||
} catch(Throwable e) {
|
} catch (Throwable e) {
|
||||||
Iris.error("Couldn't read snippet " + r + " in " + reader.getPath() + " (" + e.getMessage() + ")");
|
Iris.error("Couldn't read snippet " + r + " in " + reader.getPath() + " (" + e.getMessage() + ")");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -435,11 +442,12 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
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) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -454,8 +462,8 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
|||||||
|
|
||||||
File snippetFolder = new File(getDataFolder(), "snippet/" + f);
|
File snippetFolder = new File(getDataFolder(), "snippet/" + f);
|
||||||
|
|
||||||
if(snippetFolder.exists() && snippetFolder.isDirectory()) {
|
if (snippetFolder.exists() && snippetFolder.isDirectory()) {
|
||||||
for(File i : snippetFolder.listFiles()) {
|
for (File i : snippetFolder.listFiles()) {
|
||||||
l.add("snippet/" + f + "/" + i.getName().split("\\Q.\\E")[0]);
|
l.add("snippet/" + f + "/" + i.getName().split("\\Q.\\E")[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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
|
||||||
@@ -56,7 +56,7 @@ public abstract class IrisRegistrant {
|
|||||||
public File openInVSCode() {
|
public File openInVSCode() {
|
||||||
try {
|
try {
|
||||||
Desktop.getDesktop().open(getLoadFile());
|
Desktop.getDesktop().open(getLoadFile());
|
||||||
} catch(Throwable e) {
|
} catch (Throwable e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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());
|
||||||
@@ -56,39 +58,33 @@ public class MatterObjectResourceLoader extends ResourceLoader<IrisMatterObject>
|
|||||||
logLoad(j, t);
|
logLoad(j, t);
|
||||||
tlt.addAndGet(p.getMilliseconds());
|
tlt.addAndGet(p.getMilliseconds());
|
||||||
return t;
|
return t;
|
||||||
} catch(Throwable e) {
|
} catch (Throwable e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
Iris.warn("Couldn't read " + resourceTypeName + " file: " + j.getPath() + ": " + e.getMessage());
|
Iris.warn("Couldn't read " + resourceTypeName + " file: " + j.getPath() + ": " + e.getMessage());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void findMatFiles(File dir, KSet<String> m) {
|
||||||
|
for (File file : dir.listFiles()) {
|
||||||
|
if (file.isFile() && file.getName().endsWith(".mat")) {
|
||||||
|
m.add(file.getName().replaceAll("\\Q.mat\\E", ""));
|
||||||
|
} else if (file.isDirectory()) {
|
||||||
|
findMatFiles(file, m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public String[] getPossibleKeys() {
|
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<>();
|
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,17 +92,51 @@ 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()) {
|
||||||
if(j.isFile() && j.getName().endsWith(".mat") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
if (j.isFile() && j.getName().endsWith(".mat") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
||||||
return j;
|
return j;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
File file = new File(i, name + ".mat");
|
File file = new File(i, name + ".mat");
|
||||||
|
|
||||||
if(file.exists()) {
|
if (file.exists()) {
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -121,16 +151,16 @@ public class MatterObjectResourceLoader extends ResourceLoader<IrisMatterObject>
|
|||||||
}
|
}
|
||||||
|
|
||||||
private IrisMatterObject loadRaw(String name) {
|
private IrisMatterObject loadRaw(String name) {
|
||||||
for(File i : getFolders(name)) {
|
for (File i : getFolders(name)) {
|
||||||
for(File j : i.listFiles()) {
|
for (File j : i.listFiles()) {
|
||||||
if(j.isFile() && j.getName().endsWith(".mat") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
if (j.isFile() && j.getName().endsWith(".mat") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
||||||
return loadFile(j, name);
|
return loadFile(j, name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
File file = new File(i, name + ".mat");
|
File file = new File(i, name + ".mat");
|
||||||
|
|
||||||
if(file.exists()) {
|
if (file.exists()) {
|
||||||
return loadFile(file, name);
|
return loadFile(file, name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -50,14 +50,14 @@ 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;
|
||||||
} catch(Throwable e) {
|
} catch (Throwable e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
Iris.warn("Couldn't read " + resourceTypeName + " file: " + j.getPath() + ": " + e.getMessage());
|
Iris.warn("Couldn't read " + resourceTypeName + " file: " + j.getPath() + ": " + e.getMessage());
|
||||||
return null;
|
return null;
|
||||||
@@ -65,49 +65,42 @@ public class ObjectResourceLoader extends ResourceLoader<IrisObject> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
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<>();
|
KSet<String> m = new KSet<>();
|
||||||
|
for (File i : getFolders()) {
|
||||||
for(File i : getFolders()) {
|
m.addAll(getFiles(i, ".iob", true));
|
||||||
for(File j : i.listFiles()) {
|
|
||||||
if(j.isFile() && j.getName().endsWith(".iob")) {
|
|
||||||
m.add(j.getName().replaceAll("\\Q.iob\\E", ""));
|
|
||||||
} else if(j.isDirectory()) {
|
|
||||||
for(File k : j.listFiles()) {
|
|
||||||
if(k.isFile() && k.getName().endsWith(".iob")) {
|
|
||||||
m.add(j.getName() + "/" + k.getName().replaceAll("\\Q.iob\\E", ""));
|
|
||||||
} else if(k.isDirectory()) {
|
|
||||||
for(File l : k.listFiles()) {
|
|
||||||
if(l.isFile() && l.getName().endsWith(".iob")) {
|
|
||||||
m.add(j.getName() + "/" + k.getName() + "/" + l.getName().replaceAll("\\Q.iob\\E", ""));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
possibleKeys = m.toArray(new String[0]);
|
||||||
KList<String> v = new KList<>(m);
|
|
||||||
possibleKeys = v.toArray(new String[0]);
|
|
||||||
return possibleKeys;
|
return possibleKeys;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private KList<String> getFiles(File dir, String ext, boolean skipDirName) {
|
||||||
|
KList<String> paths = new KList<>();
|
||||||
|
String name = skipDirName ? "" : dir.getName() + "/";
|
||||||
|
for (File f : dir.listFiles()) {
|
||||||
|
if (f.isFile() && f.getName().endsWith(ext)) {
|
||||||
|
paths.add(name + f.getName().replaceAll("\\Q" + ext + "\\E", ""));
|
||||||
|
} else if (f.isDirectory()) {
|
||||||
|
getFiles(f, ext, false).forEach(e -> paths.add(name + e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return paths;
|
||||||
|
}
|
||||||
|
|
||||||
public File findFile(String name) {
|
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()) {
|
||||||
if(j.isFile() && j.getName().endsWith(".iob") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
if (j.isFile() && j.getName().endsWith(".iob") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
||||||
return j;
|
return j;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
File file = new File(i, name + ".iob");
|
File file = new File(i, name + ".iob");
|
||||||
|
|
||||||
if(file.exists()) {
|
if (file.exists()) {
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -122,16 +115,16 @@ public class ObjectResourceLoader extends ResourceLoader<IrisObject> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private IrisObject loadRaw(String name) {
|
private IrisObject loadRaw(String name) {
|
||||||
for(File i : getFolders(name)) {
|
for (File i : getFolders(name)) {
|
||||||
for(File j : i.listFiles()) {
|
for (File j : i.listFiles()) {
|
||||||
if(j.isFile() && j.getName().endsWith(".iob") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
if (j.isFile() && j.getName().endsWith(".iob") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
||||||
return loadFile(j, name);
|
return loadFile(j, name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
File file = new File(i, name + ".iob");
|
File file = new File(i, name + ".iob");
|
||||||
|
|
||||||
if(file.exists()) {
|
if (file.exists()) {
|
||||||
return loadFile(file, name);
|
return loadFile(file, 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();
|
||||||
@@ -81,7 +93,7 @@ public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
|||||||
JSONObject o = new JSONObject();
|
JSONObject o = new JSONObject();
|
||||||
KList<String> fm = new KList<>();
|
KList<String> fm = new KList<>();
|
||||||
|
|
||||||
for(int g = 1; g < 8; g++) {
|
for (int g = 1; g < 8; g++) {
|
||||||
fm.add("/" + folderName + Form.repeat("/*", g) + ".json");
|
fm.add("/" + folderName + Form.repeat("/*", g) + ".json");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,16 +106,16 @@ public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
|||||||
}
|
}
|
||||||
|
|
||||||
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()) {
|
||||||
if(j.isFile() && j.getName().endsWith(".json") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
if (j.isFile() && j.getName().endsWith(".json") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
||||||
return j;
|
return j;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
File file = new File(i, name + ".json");
|
File file = new File(i, name + ".json");
|
||||||
|
|
||||||
if(file.exists()) {
|
if (file.exists()) {
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -116,11 +128,11 @@ public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
|||||||
public void logLoad(File path, T t) {
|
public void logLoad(File path, T t) {
|
||||||
loads.getAndIncrement();
|
loads.getAndIncrement();
|
||||||
|
|
||||||
if(loads.get() == 1) {
|
if (loads.get() == 1) {
|
||||||
sec.flip();
|
sec.flip();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(sec.flip()) {
|
if (sec.flip()) {
|
||||||
J.a(() -> {
|
J.a(() -> {
|
||||||
Iris.verbose("Loaded " + C.WHITE + loads.get() + " " + resourceTypeName + (loads.get() == 1 ? "" : "s") + C.GRAY + " (" + Form.f(getLoadCache().getSize()) + " " + resourceTypeName + (loadCache.getSize() == 1 ? "" : "s") + " Loaded)");
|
Iris.verbose("Loaded " + C.WHITE + loads.get() + " " + resourceTypeName + (loads.get() == 1 ? "" : "s") + C.GRAY + " (" + Form.f(getLoadCache().getSize()) + " " + resourceTypeName + (loadCache.getSize() == 1 ? "" : "s") + " Loaded)");
|
||||||
loads.set(0);
|
loads.set(0);
|
||||||
@@ -141,32 +153,32 @@ public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void matchFiles(File at, KList<File> files, Predicate<File> f) {
|
private void matchFiles(File at, KList<File> files, Predicate<File> f) {
|
||||||
if(at.isDirectory()) {
|
if (at.isDirectory()) {
|
||||||
for(File i : at.listFiles()) {
|
for (File i : at.listFiles()) {
|
||||||
matchFiles(i, files, f);
|
matchFiles(i, files, f);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(f.test(at)) {
|
if (f.test(at)) {
|
||||||
files.add(at);
|
files.add(at);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String[] getPossibleKeys() {
|
public String[] getPossibleKeys() {
|
||||||
if(possibleKeys != null) {
|
if (possibleKeys != null) {
|
||||||
return possibleKeys;
|
return possibleKeys;
|
||||||
}
|
}
|
||||||
|
|
||||||
KSet<String> m = new KSet<>();
|
KSet<String> m = new KSet<>();
|
||||||
KList<File> files = getFolders();
|
KList<File> files = getFolders();
|
||||||
|
|
||||||
if(files == null) {
|
if (files == null) {
|
||||||
possibleKeys = new String[0];
|
possibleKeys = new String[0];
|
||||||
return possibleKeys;
|
return possibleKeys;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(File i : files) {
|
for (File i : files) {
|
||||||
for(File j : matchAllFiles(i, (f) -> f.getName().endsWith(".json"))) {
|
for (File j : matchAllFiles(i, (f) -> f.getName().endsWith(".json"))) {
|
||||||
m.add(i.toURI().relativize(j.toURI()).getPath().replaceAll("\\Q.json\\E", ""));
|
m.add(i.toURI().relativize(j.toURI()).getPath().replaceAll("\\Q.json\\E", ""));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -184,7 +196,7 @@ public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
|||||||
try {
|
try {
|
||||||
PrecisionStopwatch p = PrecisionStopwatch.start();
|
PrecisionStopwatch p = PrecisionStopwatch.start();
|
||||||
T t = getManager().getGson()
|
T t = getManager().getGson()
|
||||||
.fromJson(preprocess(new JSONObject(IO.readAll(j))).toString(0), objectClass);
|
.fromJson(preprocess(new JSONObject(IO.readAll(j))).toString(0), objectClass);
|
||||||
t.setLoadKey(name);
|
t.setLoadKey(name);
|
||||||
t.setLoadFile(j);
|
t.setLoadFile(j);
|
||||||
t.setLoader(manager);
|
t.setLoader(manager);
|
||||||
@@ -192,7 +204,7 @@ public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
|||||||
logLoad(j, t);
|
logLoad(j, t);
|
||||||
tlt.addAndGet(p.getMilliseconds());
|
tlt.addAndGet(p.getMilliseconds());
|
||||||
return t;
|
return t;
|
||||||
} catch(Throwable e) {
|
} catch (Throwable e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
failLoad(j, e);
|
failLoad(j, e);
|
||||||
return null;
|
return null;
|
||||||
@@ -210,10 +222,10 @@ public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
|||||||
public KList<T> loadAll(KList<String> s) {
|
public KList<T> loadAll(KList<String> s) {
|
||||||
KList<T> m = new KList<>();
|
KList<T> m = new KList<>();
|
||||||
|
|
||||||
for(String i : s) {
|
for (String i : s) {
|
||||||
T t = load(i);
|
T t = load(i);
|
||||||
|
|
||||||
if(t != null) {
|
if (t != null) {
|
||||||
m.add(t);
|
m.add(t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -221,13 +233,31 @@ 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<>();
|
||||||
|
|
||||||
for(String i : s) {
|
for (String i : s) {
|
||||||
T t = load(i);
|
T t = load(i);
|
||||||
|
|
||||||
if(t != null) {
|
if (t != null) {
|
||||||
m.add(t);
|
m.add(t);
|
||||||
postLoad.accept(t);
|
postLoad.accept(t);
|
||||||
}
|
}
|
||||||
@@ -239,10 +269,10 @@ public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
|||||||
public KList<T> loadAll(String[] s) {
|
public KList<T> loadAll(String[] s) {
|
||||||
KList<T> m = new KList<>();
|
KList<T> m = new KList<>();
|
||||||
|
|
||||||
for(String i : s) {
|
for (String i : s) {
|
||||||
T t = load(i);
|
T t = load(i);
|
||||||
|
|
||||||
if(t != null) {
|
if (t != null) {
|
||||||
m.add(t);
|
m.add(t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -255,17 +285,17 @@ public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private T loadRaw(String name) {
|
private T loadRaw(String name) {
|
||||||
for(File i : getFolders(name)) {
|
for (File i : getFolders(name)) {
|
||||||
//noinspection ConstantConditions
|
//noinspection ConstantConditions
|
||||||
for(File j : i.listFiles()) {
|
for (File j : i.listFiles()) {
|
||||||
if(j.isFile() && j.getName().endsWith(".json") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
if (j.isFile() && j.getName().endsWith(".json") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
||||||
return loadFile(j, name);
|
return loadFile(j, name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
File file = new File(i, name + ".json");
|
File file = new File(i, name + ".json");
|
||||||
|
|
||||||
if(file.exists()) {
|
if (file.exists()) {
|
||||||
return loadFile(file, name);
|
return loadFile(file, name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -274,27 +304,72 @@ public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public T load(String name, boolean warn) {
|
public T load(String name, boolean warn) {
|
||||||
if(name == null) {
|
if (name == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(name.trim().isEmpty()) {
|
if (name.trim().isEmpty()) {
|
||||||
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) {
|
||||||
|
if (folderCache.get() == null) {
|
||||||
synchronized(folderCache) {
|
|
||||||
if(folderCache.get() == null) {
|
|
||||||
KList<File> fc = new KList<>();
|
KList<File> fc = new KList<>();
|
||||||
|
|
||||||
for(File i : root.listFiles()) {
|
File[] files = root.listFiles();
|
||||||
if(i.isDirectory()) {
|
if (files == null) {
|
||||||
if(i.getName().equals(folderName)) {
|
throw new IllegalStateException("Failed to list files in " + root);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (File i : files) {
|
||||||
|
if (i.isDirectory()) {
|
||||||
|
if (i.getName().equals(folderName)) {
|
||||||
fc.add(i);
|
fc.add(i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -311,9 +386,9 @@ public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
|||||||
public KList<File> getFolders(String rc) {
|
public KList<File> getFolders(String rc) {
|
||||||
KList<File> folders = getFolders().copy();
|
KList<File> folders = getFolders().copy();
|
||||||
|
|
||||||
if(rc.contains(":")) {
|
if (rc.contains(":")) {
|
||||||
for(File i : folders.copy()) {
|
for (File i : folders.copy()) {
|
||||||
if(!rc.startsWith(i.getName() + ":")) {
|
if (!rc.startsWith(i.getName() + ":")) {
|
||||||
folders.remove(i);
|
folders.remove(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -329,16 +404,16 @@ public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public File fileFor(T b) {
|
public File fileFor(T b) {
|
||||||
for(File i : getFolders()) {
|
for (File i : getFolders()) {
|
||||||
for(File j : i.listFiles()) {
|
for (File j : i.listFiles()) {
|
||||||
if(j.isFile() && j.getName().endsWith(".json") && j.getName().split("\\Q.\\E")[0].equals(b.getLoadKey())) {
|
if (j.isFile() && j.getName().endsWith(".json") && j.getName().split("\\Q.\\E")[0].equals(b.getLoadKey())) {
|
||||||
return j;
|
return j;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
File file = new File(i, b.getLoadKey() + ".json");
|
File file = new File(i, b.getLoadKey() + ".json");
|
||||||
|
|
||||||
if(file.exists()) {
|
if (file.exists()) {
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -358,8 +433,8 @@ public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
|||||||
public KList<String> getPossibleKeys(String arg) {
|
public KList<String> getPossibleKeys(String arg) {
|
||||||
KList<String> f = new KList<>();
|
KList<String> f = new KList<>();
|
||||||
|
|
||||||
for(String i : getPossibleKeys()) {
|
for (String i : getPossibleKeys()) {
|
||||||
if(i.equalsIgnoreCase(arg) || i.toLowerCase(Locale.ROOT).startsWith(arg.toLowerCase(Locale.ROOT)) || i.toLowerCase(Locale.ROOT).contains(arg.toLowerCase(Locale.ROOT)) || arg.toLowerCase(Locale.ROOT).contains(i.toLowerCase(Locale.ROOT))) {
|
if (i.equalsIgnoreCase(arg) || i.toLowerCase(Locale.ROOT).startsWith(arg.toLowerCase(Locale.ROOT)) || i.toLowerCase(Locale.ROOT).contains(arg.toLowerCase(Locale.ROOT)) || arg.toLowerCase(Locale.ROOT).contains(i.toLowerCase(Locale.ROOT))) {
|
||||||
f.add(i);
|
f.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) {
|
||||||
@@ -53,57 +53,88 @@ public class ScriptResourceLoader extends ResourceLoader<IrisScript> {
|
|||||||
logLoad(j, t);
|
logLoad(j, t);
|
||||||
tlt.addAndGet(p.getMilliseconds());
|
tlt.addAndGet(p.getMilliseconds());
|
||||||
return t;
|
return t;
|
||||||
} catch(Throwable e) {
|
} catch (Throwable e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
Iris.warn("Couldn't read " + resourceTypeName + " file: " + j.getPath() + ": " + e.getMessage());
|
Iris.warn("Couldn't read " + resourceTypeName + " file: " + j.getPath() + ": " + e.getMessage());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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()) {
|
||||||
if(j.isFile() && j.getName().endsWith(".js") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
if (j.isFile() && j.getName().endsWith(".js") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
||||||
return j;
|
return j;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
File file = new File(i, name + ".js");
|
File file = new File(i, name + ".js");
|
||||||
|
|
||||||
if(file.exists()) {
|
if (file.exists()) {
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -114,16 +145,16 @@ public class ScriptResourceLoader extends ResourceLoader<IrisScript> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private IrisScript loadRaw(String name) {
|
private IrisScript loadRaw(String name) {
|
||||||
for(File i : getFolders(name)) {
|
for (File i : getFolders(name)) {
|
||||||
for(File j : i.listFiles()) {
|
for (File j : i.listFiles()) {
|
||||||
if(j.isFile() && j.getName().endsWith(".js") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
if (j.isFile() && j.getName().endsWith(".js") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
||||||
return loadFile(j, name);
|
return loadFile(j, name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
File file = new File(i, name + ".js");
|
File file = new File(i, name + ".js");
|
||||||
|
|
||||||
if(file.exists()) {
|
if (file.exists()) {
|
||||||
return loadFile(file, name);
|
return loadFile(file, name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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,7 +91,12 @@ 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) {
|
||||||
return c.createWorld();
|
if (missingDimensionTypes(true, true, true))
|
||||||
|
throw new IllegalStateException("Missing dimenstion types to create world");
|
||||||
|
|
||||||
|
try (var ignored = injectLevelStems()) {
|
||||||
|
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();
|
||||||
@@ -35,33 +50,97 @@ public class NMSBinding1X implements INMSBinding {
|
|||||||
@SuppressWarnings("ConstantConditions")
|
@SuppressWarnings("ConstantConditions")
|
||||||
private static boolean testCustomHeight() {
|
private static boolean testCustomHeight() {
|
||||||
try {
|
try {
|
||||||
if(World.class.getDeclaredMethod("getMaxHeight") != null && World.class.getDeclaredMethod("getMinHeight") != null)
|
if (World.class.getDeclaredMethod("getMaxHeight") != null && World.class.getDeclaredMethod("getMinHeight") != null)
|
||||||
;
|
;
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} catch(Throwable ignored) {
|
} catch (Throwable ignored) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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,17 +63,16 @@ 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;
|
||||||
|
|
||||||
if(!folder.exists()) {
|
if (!folder.exists()) {
|
||||||
throw new RuntimeException("Cannot open Pack " + folder.getPath() + " (directory doesnt exist)");
|
throw new RuntimeException("Cannot open Pack " + folder.getPath() + " (directory doesnt exist)");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!folder.isDirectory()) {
|
if (!folder.isDirectory()) {
|
||||||
throw new RuntimeException("Cannot open Pack " + folder.getPath() + " (not a directory)");
|
throw new RuntimeException("Cannot open Pack " + folder.getPath() + " (not a directory)");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,23 +82,20 @@ public class IrisPack {
|
|||||||
/**
|
/**
|
||||||
* Create a new pack from the input url
|
* 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);
|
||||||
if(repo == null) {
|
if (repo == null) {
|
||||||
throw new IrisException("Null Repo");
|
throw new IrisException("Null Repo");
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return from(sender, repo);
|
return from(sender, repo);
|
||||||
} catch(MalformedURLException e) {
|
} catch (MalformedURLException e) {
|
||||||
throw new IrisException("Malformed URL " + e.getMessage());
|
throw new IrisException("Malformed URL " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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,16 +119,14 @@ 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);
|
||||||
|
|
||||||
if(f.exists()) {
|
if (f.exists()) {
|
||||||
throw new IrisException("Already exists");
|
throw new IrisException("Already exists");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,10 +134,10 @@ public class IrisPack {
|
|||||||
fd.getParentFile().mkdirs();
|
fd.getParentFile().mkdirs();
|
||||||
try {
|
try {
|
||||||
IO.writeAll(fd, "{\n" +
|
IO.writeAll(fd, "{\n" +
|
||||||
" \"name\": \"" + Form.capitalize(name) + "\",\n" +
|
" \"name\": \"" + Form.capitalize(name) + "\",\n" +
|
||||||
" \"version\": 1\n" +
|
" \"version\": 1\n" +
|
||||||
"}\n");
|
"}\n");
|
||||||
} catch(IOException e) {
|
} catch (IOException e) {
|
||||||
throw new IrisException(e.getMessage(), e);
|
throw new IrisException(e.getMessage(), e);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,8 +149,7 @@ public class IrisPack {
|
|||||||
/**
|
/**
|
||||||
* Get a packs pack folder for a name. Such that overworld would resolve as Iris/packs/overworld
|
* 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) {
|
||||||
@@ -170,11 +159,11 @@ public class IrisPack {
|
|||||||
private static KList<File> collectFiles(File f, String fileExtension) {
|
private static KList<File> collectFiles(File f, String fileExtension) {
|
||||||
KList<File> l = new KList<>();
|
KList<File> l = new KList<>();
|
||||||
|
|
||||||
if(f.isDirectory()) {
|
if (f.isDirectory()) {
|
||||||
for(File i : f.listFiles()) {
|
for (File i : f.listFiles()) {
|
||||||
l.addAll(collectFiles(i, fileExtension));
|
l.addAll(collectFiles(i, fileExtension));
|
||||||
}
|
}
|
||||||
} else if(f.getName().endsWith("." + fileExtension)) {
|
} else if (f.getName().endsWith("." + fileExtension)) {
|
||||||
l.add(f);
|
l.add(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -225,13 +214,13 @@ public class IrisPack {
|
|||||||
p.end();
|
p.end();
|
||||||
Iris.debug("Building Workspace: " + ws.getPath() + " took " + Form.duration(p.getMilliseconds(), 2));
|
Iris.debug("Building Workspace: " + ws.getPath() + " took " + Form.duration(p.getMilliseconds(), 2));
|
||||||
return true;
|
return true;
|
||||||
} catch(Throwable e) {
|
} catch (Throwable e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
Iris.warn("Pack invalid: " + ws.getAbsolutePath() + " Re-creating. You may loose some vs-code workspace settings! But not your actual project!");
|
Iris.warn("Pack invalid: " + ws.getAbsolutePath() + " Re-creating. You may loose some vs-code workspace settings! But not your actual project!");
|
||||||
ws.delete();
|
ws.delete();
|
||||||
try {
|
try {
|
||||||
IO.writeAll(ws, generateWorkspaceConfig());
|
IO.writeAll(ws, generateWorkspaceConfig());
|
||||||
} catch(IOException e1) {
|
} catch (IOException e1) {
|
||||||
Iris.reportError(e1);
|
Iris.reportError(e1);
|
||||||
e1.printStackTrace();
|
e1.printStackTrace();
|
||||||
}
|
}
|
||||||
@@ -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,12 +252,11 @@ 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 {
|
||||||
if(folder.exists()) {
|
if (folder.exists()) {
|
||||||
throw new IrisException("Cannot install new pack because the folder " + folder.getName() + " already exists!");
|
throw new IrisException("Cannot install new pack because the folder " + folder.getName() + " already exists!");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -278,7 +264,7 @@ public class IrisPack {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
FileUtils.copyDirectory(getFolder(), folder);
|
FileUtils.copyDirectory(getFolder(), folder);
|
||||||
} catch(IOException e) {
|
} catch (IOException e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -289,20 +275,19 @@ public class IrisPack {
|
|||||||
* Create a new pack using this pack as a template. The new pack will be renamed & have a renamed dimension
|
* 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 {
|
||||||
File newPack = packsPack(newName);
|
File newPack = packsPack(newName);
|
||||||
|
|
||||||
if(newPack.exists()) {
|
if (newPack.exists()) {
|
||||||
throw new IrisException("Cannot install new pack because the folder " + newName + " already exists!");
|
throw new IrisException("Cannot install new pack because the folder " + newName + " already exists!");
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
FileUtils.copyDirectory(getFolder(), newPack);
|
FileUtils.copyDirectory(getFolder(), newPack);
|
||||||
} catch(IOException e) {
|
} catch (IOException e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -314,7 +299,7 @@ public class IrisPack {
|
|||||||
try {
|
try {
|
||||||
FileUtils.moveFile(from, to);
|
FileUtils.moveFile(from, to);
|
||||||
new File(newPack, getWorkspaceFile().getName()).delete();
|
new File(newPack, getWorkspaceFile().getName()).delete();
|
||||||
} catch(Throwable e) {
|
} catch (Throwable e) {
|
||||||
throw new IrisException(e);
|
throw new IrisException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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) {
|
||||||
@@ -386,8 +370,8 @@ public class IrisPack {
|
|||||||
JSONArray schemas = new JSONArray();
|
JSONArray schemas = new JSONArray();
|
||||||
IrisData dm = IrisData.get(getFolder());
|
IrisData dm = IrisData.get(getFolder());
|
||||||
|
|
||||||
for(ResourceLoader<?> r : dm.getLoaders().v()) {
|
for (ResourceLoader<?> r : dm.getLoaders().v()) {
|
||||||
if(r.supportsSchemas()) {
|
if (r.supportsSchemas()) {
|
||||||
schemas.put(r.buildSchema());
|
schemas.put(r.buildSchema());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -55,34 +55,34 @@ public class IrisPackRepository {
|
|||||||
*/
|
*/
|
||||||
public static IrisPackRepository from(String g) {
|
public static IrisPackRepository from(String g) {
|
||||||
// https://github.com/IrisDimensions/overworld
|
// https://github.com/IrisDimensions/overworld
|
||||||
if(g.startsWith("https://github.com/")) {
|
if (g.startsWith("https://github.com/")) {
|
||||||
String sub = g.split("\\Qgithub.com/\\E")[1];
|
String sub = g.split("\\Qgithub.com/\\E")[1];
|
||||||
IrisPackRepository r = IrisPackRepository.builder()
|
IrisPackRepository r = IrisPackRepository.builder()
|
||||||
.user(sub.split("\\Q/\\E")[0])
|
.user(sub.split("\\Q/\\E")[0])
|
||||||
.repo(sub.split("\\Q/\\E")[1]).build();
|
.repo(sub.split("\\Q/\\E")[1]).build();
|
||||||
|
|
||||||
if(g.contains("/tree/")) {
|
if (g.contains("/tree/")) {
|
||||||
r.setBranch(g.split("/tree/")[1]);
|
r.setBranch(g.split("/tree/")[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
} else if(g.contains("/")) {
|
} else if (g.contains("/")) {
|
||||||
String[] f = g.split("\\Q/\\E");
|
String[] f = g.split("\\Q/\\E");
|
||||||
|
|
||||||
if(f.length == 1) {
|
if (f.length == 1) {
|
||||||
return from(g);
|
return from(g);
|
||||||
} else if(f.length == 2) {
|
} else if (f.length == 2) {
|
||||||
return IrisPackRepository.builder()
|
return IrisPackRepository.builder()
|
||||||
.user(f[0])
|
.user(f[0])
|
||||||
.repo(f[1])
|
.repo(f[1])
|
||||||
.build();
|
.build();
|
||||||
} else if(f.length >= 3) {
|
} else if (f.length >= 3) {
|
||||||
IrisPackRepository r = IrisPackRepository.builder()
|
IrisPackRepository r = IrisPackRepository.builder()
|
||||||
.user(f[0])
|
.user(f[0])
|
||||||
.repo(f[1])
|
.repo(f[1])
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
if(f[2].startsWith("#")) {
|
if (f[2].startsWith("#")) {
|
||||||
r.setTag(f[2].substring(1));
|
r.setTag(f[2].substring(1));
|
||||||
} else {
|
} else {
|
||||||
r.setBranch(f[2]);
|
r.setBranch(f[2]);
|
||||||
@@ -92,17 +92,17 @@ public class IrisPackRepository {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return IrisPackRepository.builder()
|
return IrisPackRepository.builder()
|
||||||
.user("IrisDimensions")
|
.user("IrisDimensions")
|
||||||
.repo(g)
|
.repo(g)
|
||||||
.branch(g.equals("overworld") ? "stable" : "master")
|
.branch(g.equals("overworld") ? "stable" : "master")
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toURL() {
|
public String toURL() {
|
||||||
if(!tag.trim().isEmpty()) {
|
if (!tag.trim().isEmpty()) {
|
||||||
return "https://codeload.github.com/" + user + "/" + repo + "/zip/refs/tags/" + tag;
|
return "https://codeload.github.com/" + user + "/" + repo + "/zip/refs/tags/" + tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,19 +112,19 @@ public class IrisPackRepository {
|
|||||||
public void install(VolmitSender sender, Runnable whenComplete) throws MalformedURLException {
|
public void install(VolmitSender sender, Runnable whenComplete) throws MalformedURLException {
|
||||||
File pack = Iris.instance.getDataFolderNoCreate(StudioSVC.WORKSPACE_NAME, getRepo());
|
File pack = Iris.instance.getDataFolderNoCreate(StudioSVC.WORKSPACE_NAME, getRepo());
|
||||||
|
|
||||||
if(!pack.exists()) {
|
if (!pack.exists()) {
|
||||||
File dl = new File(Iris.getTemp(), "dltk-" + UUID.randomUUID() + ".zip");
|
File dl = new File(Iris.getTemp(), "dltk-" + UUID.randomUUID() + ".zip");
|
||||||
File work = new File(Iris.getTemp(), "extk-" + UUID.randomUUID());
|
File work = new File(Iris.getTemp(), "extk-" + UUID.randomUUID());
|
||||||
new JobCollection(Form.capitalize(getRepo()),
|
new JobCollection(Form.capitalize(getRepo()),
|
||||||
new DownloadJob(toURL(), pack),
|
new DownloadJob(toURL(), pack),
|
||||||
new SingleJob("Extracting", () -> ZipUtil.unpack(dl, work)),
|
new SingleJob("Extracting", () -> ZipUtil.unpack(dl, work)),
|
||||||
new SingleJob("Installing", () -> {
|
new SingleJob("Installing", () -> {
|
||||||
try {
|
try {
|
||||||
FileUtils.copyDirectory(work.listFiles()[0], pack);
|
FileUtils.copyDirectory(work.listFiles()[0], pack);
|
||||||
} catch(IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
})).execute(sender, whenComplete);
|
})).execute(sender, whenComplete);
|
||||||
} else {
|
} else {
|
||||||
sender.sendMessage("Pack already exists!");
|
sender.sendMessage("Pack already exists!");
|
||||||
}
|
}
|
||||||
@@ -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,8 +91,9 @@ 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();
|
||||||
generatedLastMinute.set(generated.get());
|
generatedLastMinute.set(generated.get());
|
||||||
chunksPerMinute.put(minuteGenerated);
|
chunksPerMinute.put(minuteGenerated);
|
||||||
@@ -93,26 +101,35 @@ public class IrisPregenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
listener.onTick(chunksPerSecond.getAverage(), chunksPerMinute.getAverage(),
|
listener.onTick(chunksPerSecond.getAverage(), chunksPerMinute.getAverage(),
|
||||||
regionsPerMinute.getAverage(),
|
regionsPerMinute.getAverage(),
|
||||||
(double) generated.get() / (double) totalChunks.get(),
|
(double) generated.get() / (double) totalChunks.get(),
|
||||||
generated.get(), totalChunks.get(),
|
generated.get(), totalChunks.get(),
|
||||||
totalChunks.get() - generated.get(),
|
totalChunks.get() - generated.get(),
|
||||||
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,47 +162,61 @@ 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) {
|
||||||
while(paused.get() && !shutdown.get()) {
|
while (paused.get() && !shutdown.get()) {
|
||||||
J.sleep(50);
|
J.sleep(50);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(shutdown.get()) {
|
if (shutdown.get()) {
|
||||||
listener.onRegionSkipped(x, z);
|
listener.onRegionSkipped(x, z);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Position2 pos = new Position2(x, z);
|
Position2 pos = new Position2(x, z);
|
||||||
|
|
||||||
if(generatedRegions.contains(pos)) {
|
if (generatedRegions.contains(pos)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
currentGeneratorMethod.set(generator.getMethod(x, z));
|
currentGeneratorMethod.set(generator.getMethod(x, z));
|
||||||
boolean hit = false;
|
boolean hit = false;
|
||||||
if(generator.supportsRegions(x, z, listener) && regions) {
|
if (generator.supportsRegions(x, z, listener) && regions) {
|
||||||
hit = true;
|
hit = true;
|
||||||
listener.onRegionGenerating(x, z);
|
listener.onRegionGenerating(x, z);
|
||||||
generator.generateRegion(x, z, listener);
|
generator.generateRegion(x, z, listener);
|
||||||
} 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);
|
||||||
listener.onSaving();
|
|
||||||
generator.save();
|
if (saveLatch.flip()) {
|
||||||
|
listener.onSaving();
|
||||||
|
generator.save();
|
||||||
|
}
|
||||||
|
|
||||||
generatedRegions.add(pos);
|
generatedRegions.add(pos);
|
||||||
checkRegions();
|
checkRegions();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkRegion(int x, int z) {
|
private void checkRegion(int x, int z) {
|
||||||
if(generatedRegions.contains(new Position2(x, z))) {
|
if (generatedRegions.contains(new Position2(x, z))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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,73 +19,73 @@
|
|||||||
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()) {
|
||||||
throw new UnsupportedOperationException("Cannot use PaperAsync on non paper!");
|
throw new UnsupportedOperationException("Cannot use PaperAsync on non paper!");
|
||||||
}
|
}
|
||||||
|
|
||||||
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() {
|
||||||
try {
|
try {
|
||||||
J.sfut(() -> {
|
J.sfut(() -> {
|
||||||
if(world == null) {
|
if (world == null) {
|
||||||
Iris.warn("World was null somehow...");
|
Iris.warn("World was null somehow...");
|
||||||
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();
|
||||||
} catch(Throwable e) {
|
} catch (Throwable e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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) -> {
|
||||||
listener.onChunkGenerated(x, z);
|
lastUse.put(i, M.ms());
|
||||||
listener.onChunkCleaned(x, z);
|
listener.onChunkGenerated(x, z);
|
||||||
} catch(Throwable e) {
|
listener.onChunkCleaned(x, z);
|
||||||
|
}).get();
|
||||||
|
} catch (InterruptedException ignored) {
|
||||||
|
} 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,17 +123,18 @@ 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
|
||||||
public Mantle getMantle() {
|
public Mantle getMantle() {
|
||||||
if(IrisToolbelt.isIrisWorld(world)) {
|
if (IrisToolbelt.isIrisWorld(world)) {
|
||||||
return IrisToolbelt.access(world).getEngine().getMantle().getMantle();
|
return IrisToolbelt.access(world).getEngine().getMantle().getMantle();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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;
|
||||||
@@ -60,7 +54,7 @@ public class HybridPregenMethod implements PregeneratorMethod {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean supportsRegions(int x, int z, PregenListener listener) {
|
public boolean supportsRegions(int x, int z, PregenListener listener) {
|
||||||
return inWorld.supportsRegions(x, z, listener);
|
return inWorld.supportsRegions(x, z, listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -18,32 +18,40 @@
|
|||||||
|
|
||||||
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() {
|
||||||
for(CompletableFuture<?> i : futures) {
|
for (CompletableFuture<?> i : futures) {
|
||||||
try {
|
try {
|
||||||
i.get();
|
i.get();
|
||||||
} catch(Throwable e) {
|
} catch (Throwable e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -52,15 +60,23 @@ 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();
|
||||||
} catch(Throwable e) {
|
} catch (Throwable e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -97,13 +113,15 @@ public class MedievalPregenMethod implements PregeneratorMethod {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void generateChunk(int x, int z, PregenListener listener) {
|
public void generateChunk(int x, int z, PregenListener listener) {
|
||||||
if(futures.size() > IrisSettings.getThreadCount(IrisSettings.get().getConcurrency().getParallelism())) {
|
if (futures.size() > IrisSettings.getThreadCount(IrisSettings.get().getConcurrency().getParallelism())) {
|
||||||
waitForChunks();
|
waitForChunks();
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
}));
|
}));
|
||||||
@@ -111,7 +129,7 @@ public class MedievalPregenMethod implements PregeneratorMethod {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Mantle getMantle() {
|
public Mantle getMantle() {
|
||||||
if(IrisToolbelt.isIrisWorld(world)) {
|
if (IrisToolbelt.isIrisWorld(world)) {
|
||||||
return IrisToolbelt.access(world).getEngine().getMantle().getMantle();
|
return IrisToolbelt.access(world).getEngine().getMantle().getMantle();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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;
|
||||||
@@ -82,14 +72,14 @@ public class IrisProject {
|
|||||||
|
|
||||||
public static int clean(VolmitSender s, File clean) {
|
public static int clean(VolmitSender s, File clean) {
|
||||||
int c = 0;
|
int c = 0;
|
||||||
if(clean.isDirectory()) {
|
if (clean.isDirectory()) {
|
||||||
for(File i : clean.listFiles()) {
|
for (File i : clean.listFiles()) {
|
||||||
c += clean(s, i);
|
c += clean(s, i);
|
||||||
}
|
}
|
||||||
} else if(clean.getName().endsWith(".json")) {
|
} else if (clean.getName().endsWith(".json")) {
|
||||||
try {
|
try {
|
||||||
clean(clean);
|
clean(clean);
|
||||||
} catch(Throwable e) {
|
} catch (Throwable e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
Iris.error("Failed to beautify " + clean.getAbsolutePath() + " You may have errors in your json!");
|
Iris.error("Failed to beautify " + clean.getAbsolutePath() + " You may have errors in your json!");
|
||||||
}
|
}
|
||||||
@@ -108,29 +98,29 @@ public class IrisProject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void fixBlocks(JSONObject obj, File f) {
|
public static void fixBlocks(JSONObject obj, File f) {
|
||||||
for(String i : obj.keySet()) {
|
for (String i : obj.keySet()) {
|
||||||
Object o = obj.get(i);
|
Object o = obj.get(i);
|
||||||
|
|
||||||
if(i.equals("block") && o instanceof String && !o.toString().trim().isEmpty() && !o.toString().contains(":")) {
|
if (i.equals("block") && o instanceof String && !o.toString().trim().isEmpty() && !o.toString().contains(":")) {
|
||||||
obj.put(i, "minecraft:" + o);
|
obj.put(i, "minecraft:" + o);
|
||||||
Iris.debug("Updated Block Key: " + o + " to " + obj.getString(i) + " in " + f.getPath());
|
Iris.debug("Updated Block Key: " + o + " to " + obj.getString(i) + " in " + f.getPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
if(o instanceof JSONObject) {
|
if (o instanceof JSONObject) {
|
||||||
fixBlocks((JSONObject) o, f);
|
fixBlocks((JSONObject) o, f);
|
||||||
} else if(o instanceof JSONArray) {
|
} else if (o instanceof JSONArray) {
|
||||||
fixBlocks((JSONArray) o, f);
|
fixBlocks((JSONArray) o, f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void fixBlocks(JSONArray obj, File f) {
|
public static void fixBlocks(JSONArray obj, File f) {
|
||||||
for(int i = 0; i < obj.length(); i++) {
|
for (int i = 0; i < obj.length(); i++) {
|
||||||
Object o = obj.get(i);
|
Object o = obj.get(i);
|
||||||
|
|
||||||
if(o instanceof JSONObject) {
|
if (o instanceof JSONObject) {
|
||||||
fixBlocks((JSONObject) o, f);
|
fixBlocks((JSONObject) o, f);
|
||||||
} else if(o instanceof JSONArray) {
|
} else if (o instanceof JSONArray) {
|
||||||
fixBlocks((JSONArray) o, f);
|
fixBlocks((JSONArray) o, f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -143,11 +133,11 @@ public class IrisProject {
|
|||||||
public KList<File> collectFiles(File f, String fileExtension) {
|
public KList<File> collectFiles(File f, String fileExtension) {
|
||||||
KList<File> l = new KList<>();
|
KList<File> l = new KList<>();
|
||||||
|
|
||||||
if(f.isDirectory()) {
|
if (f.isDirectory()) {
|
||||||
for(File i : f.listFiles()) {
|
for (File i : f.listFiles()) {
|
||||||
l.addAll(collectFiles(i, fileExtension));
|
l.addAll(collectFiles(i, fileExtension));
|
||||||
}
|
}
|
||||||
} else if(f.getName().endsWith("." + fileExtension)) {
|
} else if (f.getName().endsWith("." + fileExtension)) {
|
||||||
l.add(f);
|
l.add(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,28 +160,28 @@ public class IrisProject {
|
|||||||
J.attemptAsync(() ->
|
J.attemptAsync(() ->
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
if(d.getLoader() == null) {
|
if (d.getLoader() == null) {
|
||||||
sender.sendMessage("Could not get dimension loader");
|
sender.sendMessage("Could not get dimension loader");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
File f = d.getLoader().getDataFolder();
|
File f = d.getLoader().getDataFolder();
|
||||||
|
|
||||||
if(!doOpenVSCode(f)) {
|
if (!doOpenVSCode(f)) {
|
||||||
File ff = new File(d.getLoader().getDataFolder(), d.getLoadKey() + ".code-workspace");
|
File ff = new File(d.getLoader().getDataFolder(), d.getLoadKey() + ".code-workspace");
|
||||||
Iris.warn("Project missing code-workspace: " + ff.getAbsolutePath() + " Re-creating code workspace.");
|
Iris.warn("Project missing code-workspace: " + ff.getAbsolutePath() + " Re-creating code workspace.");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
IO.writeAll(ff, createCodeWorkspaceConfig());
|
IO.writeAll(ff, createCodeWorkspaceConfig());
|
||||||
} catch(IOException e1) {
|
} catch (IOException e1) {
|
||||||
Iris.reportError(e1);
|
Iris.reportError(e1);
|
||||||
e1.printStackTrace();
|
e1.printStackTrace();
|
||||||
}
|
}
|
||||||
updateWorkspace();
|
updateWorkspace();
|
||||||
if(!doOpenVSCode(f)) {
|
if (!doOpenVSCode(f)) {
|
||||||
Iris.warn("Tried creating code workspace but failed a second time. Your project is likely corrupt.");
|
Iris.warn("Tried creating code workspace but failed a second time. Your project is likely corrupt.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch(Throwable e) {
|
} catch (Throwable e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@@ -200,16 +190,16 @@ public class IrisProject {
|
|||||||
|
|
||||||
private boolean doOpenVSCode(File f) throws IOException {
|
private boolean doOpenVSCode(File f) throws IOException {
|
||||||
boolean foundWork = false;
|
boolean foundWork = false;
|
||||||
for(File i : Objects.requireNonNull(f.listFiles())) {
|
for (File i : Objects.requireNonNull(f.listFiles())) {
|
||||||
if(i.getName().endsWith(".code-workspace")) {
|
if (i.getName().endsWith(".code-workspace")) {
|
||||||
foundWork = true;
|
foundWork = true;
|
||||||
J.a(() ->
|
J.a(() ->
|
||||||
{
|
{
|
||||||
updateWorkspace();
|
updateWorkspace();
|
||||||
});
|
});
|
||||||
|
|
||||||
if(IrisSettings.get().getStudio().isOpenVSCode()) {
|
if (IrisSettings.get().getStudio().isOpenVSCode()) {
|
||||||
if(!GraphicsEnvironment.isHeadless()) {
|
if (!GraphicsEnvironment.isHeadless()) {
|
||||||
Iris.msg("Opening VSCode. You may see the output from VSCode.");
|
Iris.msg("Opening VSCode. You may see the output from VSCode.");
|
||||||
Iris.msg("VSCode output always starts with: '(node:#####) electron'");
|
Iris.msg("VSCode output always starts with: '(node:#####) electron'");
|
||||||
Desktop.getDesktop().open(i);
|
Desktop.getDesktop().open(i);
|
||||||
@@ -223,21 +213,21 @@ public class IrisProject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void open(VolmitSender sender, long seed, Consumer<World> onDone) throws IrisException {
|
public void open(VolmitSender sender, long seed, Consumer<World> onDone) throws IrisException {
|
||||||
if(isOpen()) {
|
if (isOpen()) {
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean hasError = false;
|
boolean hasError = false;
|
||||||
|
|
||||||
if(hasError) {
|
if (hasError) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
IrisDimension d = IrisData.loadAnyDimension(getName());
|
IrisDimension d = IrisData.loadAnyDimension(getName());
|
||||||
if(d == null) {
|
if (d == null) {
|
||||||
sender.sendMessage("Can't find dimension: " + getName());
|
sender.sendMessage("Can't find dimension: " + getName());
|
||||||
return;
|
return;
|
||||||
} else if(sender.isPlayer()) {
|
} else if (sender.isPlayer()) {
|
||||||
sender.player().setGameMode(GameMode.SPECTATOR);
|
sender.player().setGameMode(GameMode.SPECTATOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -247,14 +237,14 @@ public class IrisProject {
|
|||||||
J.a(() -> {
|
J.a(() -> {
|
||||||
try {
|
try {
|
||||||
activeProvider = (PlatformChunkGenerator) IrisToolbelt.createWorld()
|
activeProvider = (PlatformChunkGenerator) IrisToolbelt.createWorld()
|
||||||
.seed(seed)
|
.seed(seed)
|
||||||
.sender(sender)
|
.sender(sender)
|
||||||
.studio(true)
|
.studio(true)
|
||||||
.name("iris/" + UUID.randomUUID())
|
.name("iris/" + UUID.randomUUID())
|
||||||
.dimension(d.getLoadKey())
|
.dimension(d.getLoadKey())
|
||||||
.create().getGenerator();
|
.create().getGenerator();
|
||||||
onDone.accept(activeProvider.getTarget().getWorld().realWorld());
|
onDone.accept(activeProvider.getTarget().getWorld().realWorld());
|
||||||
} catch(IrisException e) {
|
} catch (IrisException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -286,13 +276,13 @@ public class IrisProject {
|
|||||||
IO.writeAll(ws, j.toString(4));
|
IO.writeAll(ws, j.toString(4));
|
||||||
p.end();
|
p.end();
|
||||||
return true;
|
return true;
|
||||||
} catch(Throwable e) {
|
} catch (Throwable e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
Iris.warn("Project invalid: " + ws.getAbsolutePath() + " Re-creating. You may loose some vs-code workspace settings! But not your actual project!");
|
Iris.warn("Project invalid: " + ws.getAbsolutePath() + " Re-creating. You may loose some vs-code workspace settings! But not your actual project!");
|
||||||
ws.delete();
|
ws.delete();
|
||||||
try {
|
try {
|
||||||
IO.writeAll(ws, createCodeWorkspaceConfig());
|
IO.writeAll(ws, createCodeWorkspaceConfig());
|
||||||
} catch(IOException e1) {
|
} catch (IOException e1) {
|
||||||
Iris.reportError(e1);
|
Iris.reportError(e1);
|
||||||
e1.printStackTrace();
|
e1.printStackTrace();
|
||||||
}
|
}
|
||||||
@@ -334,19 +324,19 @@ public class IrisProject {
|
|||||||
JSONArray schemas = new JSONArray();
|
JSONArray schemas = new JSONArray();
|
||||||
IrisData dm = IrisData.get(getPath());
|
IrisData dm = IrisData.get(getPath());
|
||||||
|
|
||||||
for(ResourceLoader<?> r : dm.getLoaders().v()) {
|
for (ResourceLoader<?> r : dm.getLoaders().v()) {
|
||||||
if(r.supportsSchemas()) {
|
if (r.supportsSchemas()) {
|
||||||
schemas.put(r.buildSchema());
|
schemas.put(r.buildSchema());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(Class<?> i : Iris.getClasses("com.volmit.iris.engine.object.", Snippet.class)) {
|
for (Class<?> i : Iris.getClasses("com.volmit.iris.engine.object.", Snippet.class)) {
|
||||||
try {
|
try {
|
||||||
String snipType = i.getDeclaredAnnotation(Snippet.class).value();
|
String snipType = i.getDeclaredAnnotation(Snippet.class).value();
|
||||||
JSONObject o = new JSONObject();
|
JSONObject o = new JSONObject();
|
||||||
KList<String> fm = new KList<>();
|
KList<String> fm = new KList<>();
|
||||||
|
|
||||||
for(int g = 1; g < 8; g++) {
|
for (int g = 1; g < 8; g++) {
|
||||||
fm.add("/snippet/" + snipType + Form.repeat("/*", g) + ".json");
|
fm.add("/snippet/" + snipType + Form.repeat("/*", g) + ".json");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -357,11 +347,11 @@ public class IrisProject {
|
|||||||
J.attemptAsync(() -> {
|
J.attemptAsync(() -> {
|
||||||
try {
|
try {
|
||||||
IO.writeAll(a, new SchemaBuilder(i, dm).construct().toString(4));
|
IO.writeAll(a, new SchemaBuilder(i, dm).construct().toString(4));
|
||||||
} catch(Throwable e) {
|
} catch (Throwable e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch(Throwable e) {
|
} catch (Throwable e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -387,7 +377,7 @@ public class IrisProject {
|
|||||||
KSet<IrisLootTable> loot = new KSet<>();
|
KSet<IrisLootTable> loot = new KSet<>();
|
||||||
KSet<IrisBlockData> blocks = new KSet<>();
|
KSet<IrisBlockData> blocks = new KSet<>();
|
||||||
|
|
||||||
for(String i : dm.getDimensionLoader().getPossibleKeys()) {
|
for (String i : dm.getDimensionLoader().getPossibleKeys()) {
|
||||||
blocks.add(dm.getBlockLoader().load(i));
|
blocks.add(dm.getBlockLoader().load(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -407,13 +397,13 @@ public class IrisProject {
|
|||||||
StringBuilder c = new StringBuilder();
|
StringBuilder c = new StringBuilder();
|
||||||
sender.sendMessage("Serializing Objects");
|
sender.sendMessage("Serializing Objects");
|
||||||
|
|
||||||
for(IrisBiome i : biomes) {
|
for (IrisBiome i : biomes) {
|
||||||
for(IrisObjectPlacement j : i.getObjects()) {
|
for (IrisObjectPlacement j : i.getObjects()) {
|
||||||
b.append(j.hashCode());
|
b.append(j.hashCode());
|
||||||
KList<String> newNames = new KList<>();
|
KList<String> newNames = new KList<>();
|
||||||
|
|
||||||
for(String k : j.getPlace()) {
|
for (String k : j.getPlace()) {
|
||||||
if(renameObjects.containsKey(k)) {
|
if (renameObjects.containsKey(k)) {
|
||||||
newNames.add(renameObjects.get(k));
|
newNames.add(renameObjects.get(k));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -441,12 +431,12 @@ public class IrisProject {
|
|||||||
gb.append(IO.hash(f));
|
gb.append(IO.hash(f));
|
||||||
ggg.set(ggg.get() + 1);
|
ggg.set(ggg.get() + 1);
|
||||||
|
|
||||||
if(cl.flip()) {
|
if (cl.flip()) {
|
||||||
int g = ggg.get();
|
int g = ggg.get();
|
||||||
ggg.set(0);
|
ggg.set(0);
|
||||||
sender.sendMessage("Wrote another " + g + " Objects");
|
sender.sendMessage("Wrote another " + g + " Objects");
|
||||||
}
|
}
|
||||||
} catch(Throwable e) {
|
} catch (Throwable e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
}
|
}
|
||||||
})));
|
})));
|
||||||
@@ -462,7 +452,7 @@ public class IrisProject {
|
|||||||
IO.writeAll(new File(folder, "dimensions/" + dimension.getLoadKey() + ".json"), a);
|
IO.writeAll(new File(folder, "dimensions/" + dimension.getLoadKey() + ".json"), a);
|
||||||
b.append(IO.hash(a));
|
b.append(IO.hash(a));
|
||||||
|
|
||||||
for(IrisGenerator i : generators) {
|
for (IrisGenerator i : generators) {
|
||||||
a = new JSONObject(new Gson().toJson(i)).toString(minify ? 0 : 4);
|
a = new JSONObject(new Gson().toJson(i)).toString(minify ? 0 : 4);
|
||||||
IO.writeAll(new File(folder, "generators/" + i.getLoadKey() + ".json"), a);
|
IO.writeAll(new File(folder, "generators/" + i.getLoadKey() + ".json"), a);
|
||||||
b.append(IO.hash(a));
|
b.append(IO.hash(a));
|
||||||
@@ -471,31 +461,31 @@ public class IrisProject {
|
|||||||
c.append(IO.hash(b.toString()));
|
c.append(IO.hash(b.toString()));
|
||||||
b = new StringBuilder();
|
b = new StringBuilder();
|
||||||
|
|
||||||
for(IrisRegion i : regions) {
|
for (IrisRegion i : regions) {
|
||||||
a = new JSONObject(new Gson().toJson(i)).toString(minify ? 0 : 4);
|
a = new JSONObject(new Gson().toJson(i)).toString(minify ? 0 : 4);
|
||||||
IO.writeAll(new File(folder, "regions/" + i.getLoadKey() + ".json"), a);
|
IO.writeAll(new File(folder, "regions/" + i.getLoadKey() + ".json"), a);
|
||||||
b.append(IO.hash(a));
|
b.append(IO.hash(a));
|
||||||
}
|
}
|
||||||
|
|
||||||
for(IrisBlockData i : blocks) {
|
for (IrisBlockData i : blocks) {
|
||||||
a = new JSONObject(new Gson().toJson(i)).toString(minify ? 0 : 4);
|
a = new JSONObject(new Gson().toJson(i)).toString(minify ? 0 : 4);
|
||||||
IO.writeAll(new File(folder, "blocks/" + i.getLoadKey() + ".json"), a);
|
IO.writeAll(new File(folder, "blocks/" + i.getLoadKey() + ".json"), a);
|
||||||
b.append(IO.hash(a));
|
b.append(IO.hash(a));
|
||||||
}
|
}
|
||||||
|
|
||||||
for(IrisBiome i : biomes) {
|
for (IrisBiome i : biomes) {
|
||||||
a = new JSONObject(new Gson().toJson(i)).toString(minify ? 0 : 4);
|
a = new JSONObject(new Gson().toJson(i)).toString(minify ? 0 : 4);
|
||||||
IO.writeAll(new File(folder, "biomes/" + i.getLoadKey() + ".json"), a);
|
IO.writeAll(new File(folder, "biomes/" + i.getLoadKey() + ".json"), a);
|
||||||
b.append(IO.hash(a));
|
b.append(IO.hash(a));
|
||||||
}
|
}
|
||||||
|
|
||||||
for(IrisEntity i : entities) {
|
for (IrisEntity i : entities) {
|
||||||
a = new JSONObject(new Gson().toJson(i)).toString(minify ? 0 : 4);
|
a = new JSONObject(new Gson().toJson(i)).toString(minify ? 0 : 4);
|
||||||
IO.writeAll(new File(folder, "entities/" + i.getLoadKey() + ".json"), a);
|
IO.writeAll(new File(folder, "entities/" + i.getLoadKey() + ".json"), a);
|
||||||
b.append(IO.hash(a));
|
b.append(IO.hash(a));
|
||||||
}
|
}
|
||||||
|
|
||||||
for(IrisLootTable i : loot) {
|
for (IrisLootTable i : loot) {
|
||||||
a = new JSONObject(new Gson().toJson(i)).toString(minify ? 0 : 4);
|
a = new JSONObject(new Gson().toJson(i)).toString(minify ? 0 : 4);
|
||||||
IO.writeAll(new File(folder, "loot/" + i.getLoadKey() + ".json"), a);
|
IO.writeAll(new File(folder, "loot/" + i.getLoadKey() + ".json"), a);
|
||||||
b.append(IO.hash(a));
|
b.append(IO.hash(a));
|
||||||
@@ -515,7 +505,7 @@ public class IrisProject {
|
|||||||
|
|
||||||
sender.sendMessage("Package Compiled!");
|
sender.sendMessage("Package Compiled!");
|
||||||
return p;
|
return p;
|
||||||
} catch(Throwable e) {
|
} catch (Throwable e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@@ -538,18 +528,18 @@ public class IrisProject {
|
|||||||
IrisObject o = new IrisObject(0, 0, 0);
|
IrisObject o = new IrisObject(0, 0, 0);
|
||||||
o.read(f);
|
o.read(f);
|
||||||
|
|
||||||
if(o.getBlocks().isEmpty()) {
|
if (o.getBlocks().isEmpty()) {
|
||||||
sender.sendMessageRaw("<hover:show_text:'Error:\n" +
|
sender.sendMessageRaw("<hover:show_text:'Error:\n" +
|
||||||
"<yellow>" + f.getPath() +
|
"<yellow>" + f.getPath() +
|
||||||
"'><red>- IOB " + f.getName() + " has 0 blocks!");
|
"'><red>- IOB " + f.getName() + " has 0 blocks!");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(o.getW() == 0 || o.getH() == 0 || o.getD() == 0) {
|
if (o.getW() == 0 || o.getH() == 0 || o.getD() == 0) {
|
||||||
sender.sendMessageRaw("<hover:show_text:'Error:\n" +
|
sender.sendMessageRaw("<hover:show_text:'Error:\n" +
|
||||||
"<yellow>" + f.getPath() + "\n<red>The width height or depth has a zero in it (bad format)" +
|
"<yellow>" + f.getPath() + "\n<red>The width height or depth has a zero in it (bad format)" +
|
||||||
"'><red>- IOB " + f.getName() + " is not 3D!");
|
"'><red>- IOB " + f.getName() + " is not 3D!");
|
||||||
}
|
}
|
||||||
} catch(IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -569,11 +559,11 @@ public class IrisProject {
|
|||||||
scanForErrors(data, f, p, sender);
|
scanForErrors(data, f, p, sender);
|
||||||
IO.writeAll(f, p.toString(4));
|
IO.writeAll(f, p.toString(4));
|
||||||
|
|
||||||
} catch(Throwable e) {
|
} catch (Throwable e) {
|
||||||
sender.sendMessageRaw("<hover:show_text:'Error:\n" +
|
sender.sendMessageRaw("<hover:show_text:'Error:\n" +
|
||||||
"<yellow>" + f.getPath() +
|
"<yellow>" + f.getPath() +
|
||||||
"\n<red>" + e.getMessage() +
|
"\n<red>" + e.getMessage() +
|
||||||
"'><red>- JSON Error " + f.getName());
|
"'><red>- JSON Error " + f.getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -590,7 +580,7 @@ public class IrisProject {
|
|||||||
String key = data.toLoadKey(f);
|
String key = data.toLoadKey(f);
|
||||||
ResourceLoader<?> loader = data.getTypedLoaderFor(f);
|
ResourceLoader<?> loader = data.getTypedLoaderFor(f);
|
||||||
|
|
||||||
if(loader == null) {
|
if (loader == null) {
|
||||||
sender.sendMessageBasic("Can't find loader for " + f.getPath());
|
sender.sendMessageBasic("Can't find loader for " + f.getPath());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -603,62 +593,62 @@ public class IrisProject {
|
|||||||
public void compare(Class<?> c, JSONObject j, VolmitSender sender, KList<String> path) {
|
public void compare(Class<?> c, JSONObject j, VolmitSender sender, KList<String> path) {
|
||||||
try {
|
try {
|
||||||
Object o = c.getClass().getConstructor().newInstance();
|
Object o = c.getClass().getConstructor().newInstance();
|
||||||
} catch(Throwable e) {
|
} catch (Throwable e) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void files(File clean, KList<File> files) {
|
public void files(File clean, KList<File> files) {
|
||||||
if(clean.isDirectory()) {
|
if (clean.isDirectory()) {
|
||||||
for(File i : clean.listFiles()) {
|
for (File i : clean.listFiles()) {
|
||||||
files(i, files);
|
files(i, files);
|
||||||
}
|
}
|
||||||
} else if(clean.getName().endsWith(".json")) {
|
} else if (clean.getName().endsWith(".json")) {
|
||||||
try {
|
try {
|
||||||
files.add(clean);
|
files.add(clean);
|
||||||
} catch(Throwable e) {
|
} catch (Throwable e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void filesObjects(File clean, KList<File> files) {
|
public void filesObjects(File clean, KList<File> files) {
|
||||||
if(clean.isDirectory()) {
|
if (clean.isDirectory()) {
|
||||||
for(File i : clean.listFiles()) {
|
for (File i : clean.listFiles()) {
|
||||||
filesObjects(i, files);
|
filesObjects(i, files);
|
||||||
}
|
}
|
||||||
} else if(clean.getName().endsWith(".iob")) {
|
} else if (clean.getName().endsWith(".iob")) {
|
||||||
try {
|
try {
|
||||||
files.add(clean);
|
files.add(clean);
|
||||||
} catch(Throwable e) {
|
} catch (Throwable e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fixBlocks(JSONObject obj) {
|
private void fixBlocks(JSONObject obj) {
|
||||||
for(String i : obj.keySet()) {
|
for (String i : obj.keySet()) {
|
||||||
Object o = obj.get(i);
|
Object o = obj.get(i);
|
||||||
|
|
||||||
if(i.equals("block") && o instanceof String && !o.toString().trim().isEmpty() && !o.toString().contains(":")) {
|
if (i.equals("block") && o instanceof String && !o.toString().trim().isEmpty() && !o.toString().contains(":")) {
|
||||||
obj.put(i, "minecraft:" + o);
|
obj.put(i, "minecraft:" + o);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(o instanceof JSONObject) {
|
if (o instanceof JSONObject) {
|
||||||
fixBlocks((JSONObject) o);
|
fixBlocks((JSONObject) o);
|
||||||
} else if(o instanceof JSONArray) {
|
} else if (o instanceof JSONArray) {
|
||||||
fixBlocks((JSONArray) o);
|
fixBlocks((JSONArray) o);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fixBlocks(JSONArray obj) {
|
private void fixBlocks(JSONArray obj) {
|
||||||
for(int i = 0; i < obj.length(); i++) {
|
for (int i = 0; i < obj.length(); i++) {
|
||||||
Object o = obj.get(i);
|
Object o = obj.get(i);
|
||||||
|
|
||||||
if(o instanceof JSONObject) {
|
if (o instanceof JSONObject) {
|
||||||
fixBlocks((JSONObject) o);
|
fixBlocks((JSONObject) o);
|
||||||
} else if(o instanceof JSONArray) {
|
} else if (o instanceof JSONArray) {
|
||||||
fixBlocks((JSONArray) o);
|
fixBlocks((JSONArray) o);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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,24 +59,22 @@ public class SchemaBuilder {
|
|||||||
this.root = root;
|
this.root = root;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static JSONArray getEnchantmentTypes() {
|
private static JSONArray getPotionTypes() {
|
||||||
JSONArray a = new JSONArray();
|
JSONArray a = new JSONArray();
|
||||||
|
|
||||||
for(Field gg : Enchantment.class.getDeclaredFields()) {
|
for (PotionEffectType gg : PotionEffectType.values()) {
|
||||||
a.put(gg.getName());
|
a.put(gg.getName().toUpperCase().replaceAll("\\Q \\E", "_"));
|
||||||
}
|
}
|
||||||
|
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static JSONArray getPotionTypes() {
|
private static JSONArray getEnchantTypes() {
|
||||||
JSONArray a = new JSONArray();
|
JSONArray array = new JSONArray();
|
||||||
|
for (Enchantment e : Enchantment.values()) {
|
||||||
for(PotionEffectType gg : PotionEffectType.values()) {
|
array.put(e.getKey().getKey());
|
||||||
a.put(gg.getName().toUpperCase().replaceAll("\\Q \\E", "_"));
|
|
||||||
}
|
}
|
||||||
|
return array;
|
||||||
return a;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public JSONObject construct() {
|
public JSONObject construct() {
|
||||||
@@ -94,21 +84,21 @@ public class SchemaBuilder {
|
|||||||
|
|
||||||
JSONObject props = buildProperties(root);
|
JSONObject props = buildProperties(root);
|
||||||
|
|
||||||
for(String i : props.keySet()) {
|
for (String i : props.keySet()) {
|
||||||
if(!schema.has(i)) {
|
if (!schema.has(i)) {
|
||||||
schema.put(i, props.get(i));
|
schema.put(i, props.get(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
JSONObject defs = new JSONObject();
|
JSONObject defs = new JSONObject();
|
||||||
|
|
||||||
for(Map.Entry<String, JSONObject> entry : definitions.entrySet()) {
|
for (Map.Entry<String, JSONObject> entry : definitions.entrySet()) {
|
||||||
defs.put(entry.getKey(), entry.getValue());
|
defs.put(entry.getKey(), entry.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
schema.put("definitions", defs);
|
schema.put("definitions", defs);
|
||||||
|
|
||||||
for(String i : warnings) {
|
for (String i : warnings) {
|
||||||
Iris.warn(root.getSimpleName() + ": " + i);
|
Iris.warn(root.getSimpleName() + ": " + i);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,17 +112,17 @@ public class SchemaBuilder {
|
|||||||
o.put("type", getType(c));
|
o.put("type", getType(c));
|
||||||
JSONArray required = new JSONArray();
|
JSONArray required = new JSONArray();
|
||||||
|
|
||||||
if(c.isAssignableFrom(IrisRegistrant.class) || IrisRegistrant.class.isAssignableFrom(c)) {
|
if (c.isAssignableFrom(IrisRegistrant.class) || IrisRegistrant.class.isAssignableFrom(c)) {
|
||||||
for(Field k : IrisRegistrant.class.getDeclaredFields()) {
|
for (Field k : IrisRegistrant.class.getDeclaredFields()) {
|
||||||
k.setAccessible(true);
|
k.setAccessible(true);
|
||||||
|
|
||||||
if(Modifier.isStatic(k.getModifiers()) || Modifier.isFinal(k.getModifiers()) || Modifier.isTransient(k.getModifiers())) {
|
if (Modifier.isStatic(k.getModifiers()) || Modifier.isFinal(k.getModifiers()) || Modifier.isTransient(k.getModifiers())) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSONObject property = buildProperty(k, c);
|
JSONObject property = buildProperty(k, c);
|
||||||
|
|
||||||
if(property.getBoolean("!required")) {
|
if (property.getBoolean("!required")) {
|
||||||
required.put(k.getName());
|
required.put(k.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,10 +131,10 @@ public class SchemaBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(Field k : c.getDeclaredFields()) {
|
for (Field k : c.getDeclaredFields()) {
|
||||||
k.setAccessible(true);
|
k.setAccessible(true);
|
||||||
|
|
||||||
if(Modifier.isStatic(k.getModifiers()) || Modifier.isFinal(k.getModifiers()) || Modifier.isTransient(k.getModifiers())) {
|
if (Modifier.isStatic(k.getModifiers()) || Modifier.isFinal(k.getModifiers()) || Modifier.isTransient(k.getModifiers())) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,14 +144,14 @@ public class SchemaBuilder {
|
|||||||
properties.put(k.getName(), property);
|
properties.put(k.getName(), property);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(required.length() > 0) {
|
if (required.length() > 0) {
|
||||||
o.put("required", required);
|
o.put("required", required);
|
||||||
}
|
}
|
||||||
|
|
||||||
o.put("properties", properties);
|
o.put("properties", properties);
|
||||||
|
|
||||||
|
|
||||||
if(c.isAnnotationPresent(Snippet.class)) {
|
if (c.isAnnotationPresent(Snippet.class)) {
|
||||||
JSONObject anyOf = new JSONObject();
|
JSONObject anyOf = new JSONObject();
|
||||||
JSONArray arr = new JSONArray();
|
JSONArray arr = new JSONArray();
|
||||||
JSONObject str = new JSONObject();
|
JSONObject str = new JSONObject();
|
||||||
@@ -184,16 +174,16 @@ public class SchemaBuilder {
|
|||||||
prop.put("type", type);
|
prop.put("type", type);
|
||||||
String fancyType = "Unknown Type";
|
String fancyType = "Unknown Type";
|
||||||
|
|
||||||
switch(type) {
|
switch (type) {
|
||||||
case "boolean" -> fancyType = "Boolean";
|
case "boolean" -> fancyType = "Boolean";
|
||||||
case "integer" -> {
|
case "integer" -> {
|
||||||
fancyType = "Integer";
|
fancyType = "Integer";
|
||||||
if(k.isAnnotationPresent(MinNumber.class)) {
|
if (k.isAnnotationPresent(MinNumber.class)) {
|
||||||
int min = (int) k.getDeclaredAnnotation(MinNumber.class).value();
|
int min = (int) k.getDeclaredAnnotation(MinNumber.class).value();
|
||||||
prop.put("minimum", min);
|
prop.put("minimum", min);
|
||||||
description.add(SYMBOL_LIMIT__N + " Minimum allowed is " + min);
|
description.add(SYMBOL_LIMIT__N + " Minimum allowed is " + min);
|
||||||
}
|
}
|
||||||
if(k.isAnnotationPresent(MaxNumber.class)) {
|
if (k.isAnnotationPresent(MaxNumber.class)) {
|
||||||
int max = (int) k.getDeclaredAnnotation(MaxNumber.class).value();
|
int max = (int) k.getDeclaredAnnotation(MaxNumber.class).value();
|
||||||
prop.put("maximum", max);
|
prop.put("maximum", max);
|
||||||
description.add(SYMBOL_LIMIT__N + " Maximum allowed is " + max);
|
description.add(SYMBOL_LIMIT__N + " Maximum allowed is " + max);
|
||||||
@@ -201,12 +191,12 @@ public class SchemaBuilder {
|
|||||||
}
|
}
|
||||||
case "number" -> {
|
case "number" -> {
|
||||||
fancyType = "Number";
|
fancyType = "Number";
|
||||||
if(k.isAnnotationPresent(MinNumber.class)) {
|
if (k.isAnnotationPresent(MinNumber.class)) {
|
||||||
double min = k.getDeclaredAnnotation(MinNumber.class).value();
|
double min = k.getDeclaredAnnotation(MinNumber.class).value();
|
||||||
prop.put("minimum", min);
|
prop.put("minimum", min);
|
||||||
description.add(SYMBOL_LIMIT__N + " Minimum allowed is " + min);
|
description.add(SYMBOL_LIMIT__N + " Minimum allowed is " + min);
|
||||||
}
|
}
|
||||||
if(k.isAnnotationPresent(MaxNumber.class)) {
|
if (k.isAnnotationPresent(MaxNumber.class)) {
|
||||||
double max = k.getDeclaredAnnotation(MaxNumber.class).value();
|
double max = k.getDeclaredAnnotation(MaxNumber.class).value();
|
||||||
prop.put("maximum", max);
|
prop.put("maximum", max);
|
||||||
description.add(SYMBOL_LIMIT__N + " Maximum allowed is " + max);
|
description.add(SYMBOL_LIMIT__N + " Maximum allowed is " + max);
|
||||||
@@ -214,26 +204,26 @@ public class SchemaBuilder {
|
|||||||
}
|
}
|
||||||
case "string" -> {
|
case "string" -> {
|
||||||
fancyType = "Text";
|
fancyType = "Text";
|
||||||
if(k.isAnnotationPresent(MinNumber.class)) {
|
if (k.isAnnotationPresent(MinNumber.class)) {
|
||||||
int min = (int) k.getDeclaredAnnotation(MinNumber.class).value();
|
int min = (int) k.getDeclaredAnnotation(MinNumber.class).value();
|
||||||
prop.put("minLength", min);
|
prop.put("minLength", min);
|
||||||
description.add(SYMBOL_LIMIT__N + " Minimum Length allowed is " + min);
|
description.add(SYMBOL_LIMIT__N + " Minimum Length allowed is " + min);
|
||||||
}
|
}
|
||||||
if(k.isAnnotationPresent(MaxNumber.class)) {
|
if (k.isAnnotationPresent(MaxNumber.class)) {
|
||||||
int max = (int) k.getDeclaredAnnotation(MaxNumber.class).value();
|
int max = (int) k.getDeclaredAnnotation(MaxNumber.class).value();
|
||||||
prop.put("maxLength", max);
|
prop.put("maxLength", max);
|
||||||
description.add(SYMBOL_LIMIT__N + " Maximum Length allowed is " + max);
|
description.add(SYMBOL_LIMIT__N + " Maximum Length allowed is " + max);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if(k.isAnnotationPresent(RegistryListResource.class)) {
|
if (k.isAnnotationPresent(RegistryListResource.class)) {
|
||||||
RegistryListResource rr = k.getDeclaredAnnotation(RegistryListResource.class);
|
RegistryListResource rr = k.getDeclaredAnnotation(RegistryListResource.class);
|
||||||
ResourceLoader<?> loader = data.getLoaders().get(rr.value());
|
ResourceLoader<?> loader = data.getLoaders().get(rr.value());
|
||||||
|
|
||||||
if(loader != null) {
|
if (loader != null) {
|
||||||
String key = "erz" + loader.getFolderName();
|
String key = "erz" + loader.getFolderName();
|
||||||
|
|
||||||
if(!definitions.containsKey(key)) {
|
if (!definitions.containsKey(key)) {
|
||||||
JSONObject j = new JSONObject();
|
JSONObject j = new JSONObject();
|
||||||
j.put("enum", new JSONArray(loader.getPossibleKeys()));
|
j.put("enum", new JSONArray(loader.getPossibleKeys()));
|
||||||
definitions.put(key, j);
|
definitions.put(key, j);
|
||||||
@@ -245,18 +235,18 @@ public class SchemaBuilder {
|
|||||||
} else {
|
} else {
|
||||||
Iris.error("Cannot find Registry Loader for type " + rr.value() + " used in " + k.getDeclaringClass().getCanonicalName() + " in field " + k.getName());
|
Iris.error("Cannot find Registry Loader for type " + rr.value() + " used in " + k.getDeclaringClass().getCanonicalName() + " in field " + k.getName());
|
||||||
}
|
}
|
||||||
} else if(k.isAnnotationPresent(RegistryListBlockType.class)) {
|
} else if (k.isAnnotationPresent(RegistryListBlockType.class)) {
|
||||||
String key = "enum-block-type";
|
String key = "enum-block-type";
|
||||||
|
|
||||||
if(!definitions.containsKey(key)) {
|
if (!definitions.containsKey(key)) {
|
||||||
JSONObject j = new JSONObject();
|
JSONObject j = new JSONObject();
|
||||||
JSONArray ja = new JSONArray();
|
JSONArray ja = new JSONArray();
|
||||||
|
|
||||||
for(String i : data.getBlockLoader().getPossibleKeys()) {
|
for (String i : data.getBlockLoader().getPossibleKeys()) {
|
||||||
ja.put(i);
|
ja.put(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(String i : B.getBlockTypes()) {
|
for (String i : B.getBlockTypes()) {
|
||||||
ja.put(i);
|
ja.put(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -268,12 +258,12 @@ public class SchemaBuilder {
|
|||||||
prop.put("$ref", "#/definitions/" + key);
|
prop.put("$ref", "#/definitions/" + key);
|
||||||
description.add(SYMBOL_TYPE__N + " Must be a valid Block Type (use ctrl+space for auto complete!)");
|
description.add(SYMBOL_TYPE__N + " Must be a valid Block Type (use ctrl+space for auto complete!)");
|
||||||
|
|
||||||
} else if(k.isAnnotationPresent(RegistryListItemType.class)) {
|
} else if (k.isAnnotationPresent(RegistryListItemType.class)) {
|
||||||
String key = "enum-item-type";
|
String key = "enum-item-type";
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -281,10 +271,10 @@ public class SchemaBuilder {
|
|||||||
prop.put("$ref", "#/definitions/" + key);
|
prop.put("$ref", "#/definitions/" + key);
|
||||||
description.add(SYMBOL_TYPE__N + " Must be a valid Item Type (use ctrl+space for auto complete!)");
|
description.add(SYMBOL_TYPE__N + " Must be a valid Item Type (use ctrl+space for auto complete!)");
|
||||||
|
|
||||||
} else if(k.isAnnotationPresent(RegistryListSpecialEntity.class)) {
|
} else if (k.isAnnotationPresent(RegistryListSpecialEntity.class)) {
|
||||||
String key = "enum-reg-specialentity";
|
String key = "enum-reg-specialentity";
|
||||||
|
|
||||||
if(!definitions.containsKey(key)) {
|
if (!definitions.containsKey(key)) {
|
||||||
JSONObject j = new JSONObject();
|
JSONObject j = new JSONObject();
|
||||||
KList<String> list = new KList<>();
|
KList<String> list = new KList<>();
|
||||||
list.addAll(Iris.linkMythicMobs.getMythicMobTypes().stream().map(s -> "MythicMobs:" + s).collect(Collectors.toList()));
|
list.addAll(Iris.linkMythicMobs.getMythicMobTypes().stream().map(s -> "MythicMobs:" + s).collect(Collectors.toList()));
|
||||||
@@ -296,10 +286,10 @@ public class SchemaBuilder {
|
|||||||
fancyType = "Mythic Mob Type";
|
fancyType = "Mythic Mob Type";
|
||||||
prop.put("$ref", "#/definitions/" + key);
|
prop.put("$ref", "#/definitions/" + key);
|
||||||
description.add(SYMBOL_TYPE__N + " Must be a valid Mythic Mob Type (use ctrl+space for auto complete!) Define mythic mobs with the mythic mobs plugin configuration files.");
|
description.add(SYMBOL_TYPE__N + " Must be a valid Mythic Mob Type (use ctrl+space for auto complete!) Define mythic mobs with the mythic mobs plugin configuration files.");
|
||||||
} else if(k.isAnnotationPresent(RegistryListFont.class)) {
|
} else if (k.isAnnotationPresent(RegistryListFont.class)) {
|
||||||
String key = "enum-font";
|
String key = "enum-font";
|
||||||
|
|
||||||
if(!definitions.containsKey(key)) {
|
if (!definitions.containsKey(key)) {
|
||||||
JSONObject j = new JSONObject();
|
JSONObject j = new JSONObject();
|
||||||
j.put("enum", FONT_TYPES);
|
j.put("enum", FONT_TYPES);
|
||||||
definitions.put(key, j);
|
definitions.put(key, j);
|
||||||
@@ -309,10 +299,10 @@ 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)) {
|
||||||
JSONObject j = new JSONObject();
|
JSONObject j = new JSONObject();
|
||||||
j.put("enum", ENCHANT_TYPES);
|
j.put("enum", ENCHANT_TYPES);
|
||||||
definitions.put(key, j);
|
definitions.put(key, j);
|
||||||
@@ -321,10 +311,28 @@ 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.getType().equals(PotionEffectType.class)) {
|
} else if (k.isAnnotationPresent(RegistryListFunction.class)) {
|
||||||
|
var functionClass = k.getDeclaredAnnotation(RegistryListFunction.class).value();
|
||||||
|
try {
|
||||||
|
var instance = functionClass.getDeclaredConstructor().newInstance();
|
||||||
|
String key = instance.key();
|
||||||
|
fancyType = instance.fancyName();
|
||||||
|
|
||||||
|
if (!definitions.containsKey(key)) {
|
||||||
|
JSONObject j = new JSONObject();
|
||||||
|
j.put("enum", instance.apply(data));
|
||||||
|
definitions.put(key, j);
|
||||||
|
}
|
||||||
|
|
||||||
|
prop.put("$ref", "#/definitions/" + key);
|
||||||
|
description.add(SYMBOL_TYPE__N + " Must be a valid " + fancyType + " (use ctrl+space for auto complete!)");
|
||||||
|
} catch (Throwable e) {
|
||||||
|
Iris.error("Could not execute apply method in " + functionClass.getName());
|
||||||
|
}
|
||||||
|
} else if (k.getType().equals(PotionEffectType.class)) {
|
||||||
String key = "enum-potion-effect-type";
|
String key = "enum-potion-effect-type";
|
||||||
|
|
||||||
if(!definitions.containsKey(key)) {
|
if (!definitions.containsKey(key)) {
|
||||||
JSONObject j = new JSONObject();
|
JSONObject j = new JSONObject();
|
||||||
j.put("enum", POTION_TYPES);
|
j.put("enum", POTION_TYPES);
|
||||||
definitions.put(key, j);
|
definitions.put(key, j);
|
||||||
@@ -334,45 +342,16 @@ public class SchemaBuilder {
|
|||||||
prop.put("$ref", "#/definitions/" + key);
|
prop.put("$ref", "#/definitions/" + key);
|
||||||
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" -> {
|
||||||
fancyType = k.getType().getSimpleName().replaceAll("\\QIris\\E", "") + " (Object)";
|
fancyType = k.getType().getSimpleName().replaceAll("\\QIris\\E", "") + " (Object)";
|
||||||
String key = "obj-" + k.getType().getCanonicalName().replaceAll("\\Q.\\E", "-").toLowerCase();
|
String key = "obj-" + k.getType().getCanonicalName().replaceAll("\\Q.\\E", "-").toLowerCase();
|
||||||
if(!definitions.containsKey(key)) {
|
if (!definitions.containsKey(key)) {
|
||||||
definitions.put(key, new JSONObject());
|
definitions.put(key, new JSONObject());
|
||||||
definitions.put(key, buildProperties(k.getType()));
|
definitions.put(key, buildProperties(k.getType()));
|
||||||
}
|
}
|
||||||
@@ -381,10 +360,10 @@ public class SchemaBuilder {
|
|||||||
case "array" -> {
|
case "array" -> {
|
||||||
fancyType = "List of Something...?";
|
fancyType = "List of Something...?";
|
||||||
ArrayType t = k.getDeclaredAnnotation(ArrayType.class);
|
ArrayType t = k.getDeclaredAnnotation(ArrayType.class);
|
||||||
if(t != null) {
|
if (t != null) {
|
||||||
if(t.min() > 0) {
|
if (t.min() > 0) {
|
||||||
prop.put("minItems", t.min());
|
prop.put("minItems", t.min());
|
||||||
if(t.min() == 1) {
|
if (t.min() == 1) {
|
||||||
description.add(SYMBOL_LIMIT__N + " At least one entry must be defined, or just remove this list.");
|
description.add(SYMBOL_LIMIT__N + " At least one entry must be defined, or just remove this list.");
|
||||||
} else {
|
} else {
|
||||||
description.add(SYMBOL_LIMIT__N + " Requires at least " + t.min() + " entries.");
|
description.add(SYMBOL_LIMIT__N + " Requires at least " + t.min() + " entries.");
|
||||||
@@ -393,13 +372,13 @@ public class SchemaBuilder {
|
|||||||
|
|
||||||
String arrayType = getType(t.type());
|
String arrayType = getType(t.type());
|
||||||
|
|
||||||
switch(arrayType) {
|
switch (arrayType) {
|
||||||
case "integer" -> fancyType = "List of Integers";
|
case "integer" -> fancyType = "List of Integers";
|
||||||
case "number" -> fancyType = "List of Numbers";
|
case "number" -> fancyType = "List of Numbers";
|
||||||
case "object" -> {
|
case "object" -> {
|
||||||
fancyType = "List of " + t.type().getSimpleName().replaceAll("\\QIris\\E", "") + "s (Objects)";
|
fancyType = "List of " + t.type().getSimpleName().replaceAll("\\QIris\\E", "") + "s (Objects)";
|
||||||
String key = "obj-" + t.type().getCanonicalName().replaceAll("\\Q.\\E", "-").toLowerCase();
|
String key = "obj-" + t.type().getCanonicalName().replaceAll("\\Q.\\E", "-").toLowerCase();
|
||||||
if(!definitions.containsKey(key)) {
|
if (!definitions.containsKey(key)) {
|
||||||
definitions.put(key, new JSONObject());
|
definitions.put(key, new JSONObject());
|
||||||
definitions.put(key, buildProperties(t.type()));
|
definitions.put(key, buildProperties(t.type()));
|
||||||
}
|
}
|
||||||
@@ -410,15 +389,15 @@ public class SchemaBuilder {
|
|||||||
case "string" -> {
|
case "string" -> {
|
||||||
fancyType = "List of Text";
|
fancyType = "List of Text";
|
||||||
|
|
||||||
if(k.isAnnotationPresent(RegistryListResource.class)) {
|
if (k.isAnnotationPresent(RegistryListResource.class)) {
|
||||||
RegistryListResource rr = k.getDeclaredAnnotation(RegistryListResource.class);
|
RegistryListResource rr = k.getDeclaredAnnotation(RegistryListResource.class);
|
||||||
ResourceLoader<?> loader = data.getLoaders().get(rr.value());
|
ResourceLoader<?> loader = data.getLoaders().get(rr.value());
|
||||||
|
|
||||||
if(loader != null) {
|
if (loader != null) {
|
||||||
fancyType = "List<" + loader.getResourceTypeName() + ">";
|
fancyType = "List<" + loader.getResourceTypeName() + ">";
|
||||||
String key = "erz" + loader.getFolderName();
|
String key = "erz" + loader.getFolderName();
|
||||||
|
|
||||||
if(!definitions.containsKey(key)) {
|
if (!definitions.containsKey(key)) {
|
||||||
JSONObject j = new JSONObject();
|
JSONObject j = new JSONObject();
|
||||||
j.put("enum", new JSONArray(loader.getPossibleKeys()));
|
j.put("enum", new JSONArray(loader.getPossibleKeys()));
|
||||||
definitions.put(key, j);
|
definitions.put(key, j);
|
||||||
@@ -431,19 +410,19 @@ public class SchemaBuilder {
|
|||||||
} else {
|
} else {
|
||||||
Iris.error("Cannot find Registry Loader for type (list schema) " + rr.value() + " used in " + k.getDeclaringClass().getCanonicalName() + " in field " + k.getName());
|
Iris.error("Cannot find Registry Loader for type (list schema) " + rr.value() + " used in " + k.getDeclaringClass().getCanonicalName() + " in field " + k.getName());
|
||||||
}
|
}
|
||||||
} else if(k.isAnnotationPresent(RegistryListBlockType.class)) {
|
} else if (k.isAnnotationPresent(RegistryListBlockType.class)) {
|
||||||
fancyType = "List of Block Types";
|
fancyType = "List of Block Types";
|
||||||
String key = "enum-block-type";
|
String key = "enum-block-type";
|
||||||
|
|
||||||
if(!definitions.containsKey(key)) {
|
if (!definitions.containsKey(key)) {
|
||||||
JSONObject j = new JSONObject();
|
JSONObject j = new JSONObject();
|
||||||
JSONArray ja = new JSONArray();
|
JSONArray ja = new JSONArray();
|
||||||
|
|
||||||
for(String i : data.getBlockLoader().getPossibleKeys()) {
|
for (String i : data.getBlockLoader().getPossibleKeys()) {
|
||||||
ja.put(i);
|
ja.put(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(String i : B.getBlockTypes()) {
|
for (String i : B.getBlockTypes()) {
|
||||||
ja.put(i);
|
ja.put(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -455,13 +434,13 @@ 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 Block Type (use ctrl+space for auto complete!)");
|
description.add(SYMBOL_TYPE__N + " Must be a valid Block Type (use ctrl+space for auto complete!)");
|
||||||
} else if(k.isAnnotationPresent(RegistryListItemType.class)) {
|
} else if (k.isAnnotationPresent(RegistryListItemType.class)) {
|
||||||
fancyType = "List of Item Types";
|
fancyType = "List of Item Types";
|
||||||
String key = "enum-item-type";
|
String key = "enum-item-type";
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -469,11 +448,11 @@ 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 Item Type (use ctrl+space for auto complete!)");
|
description.add(SYMBOL_TYPE__N + " Must be a valid Item Type (use ctrl+space for auto complete!)");
|
||||||
} else if(k.isAnnotationPresent(RegistryListFont.class)) {
|
} else if (k.isAnnotationPresent(RegistryListFont.class)) {
|
||||||
String key = "enum-font";
|
String key = "enum-font";
|
||||||
fancyType = "List of Font Families";
|
fancyType = "List of Font Families";
|
||||||
|
|
||||||
if(!definitions.containsKey(key)) {
|
if (!definitions.containsKey(key)) {
|
||||||
JSONObject j = new JSONObject();
|
JSONObject j = new JSONObject();
|
||||||
j.put("enum", FONT_TYPES);
|
j.put("enum", FONT_TYPES);
|
||||||
definitions.put(key, j);
|
definitions.put(key, j);
|
||||||
@@ -483,11 +462,11 @@ 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";
|
||||||
|
|
||||||
if(!definitions.containsKey(key)) {
|
if (!definitions.containsKey(key)) {
|
||||||
JSONObject j = new JSONObject();
|
JSONObject j = new JSONObject();
|
||||||
j.put("enum", ENCHANT_TYPES);
|
j.put("enum", ENCHANT_TYPES);
|
||||||
definitions.put(key, j);
|
definitions.put(key, j);
|
||||||
@@ -497,11 +476,11 @@ 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 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(t.type().equals(PotionEffectType.class)) {
|
} else if (t.type().equals(PotionEffectType.class)) {
|
||||||
fancyType = "List of Potion Effect Types";
|
fancyType = "List of Potion Effect Types";
|
||||||
String key = "enum-potion-effect-type";
|
String key = "enum-potion-effect-type";
|
||||||
|
|
||||||
if(!definitions.containsKey(key)) {
|
if (!definitions.containsKey(key)) {
|
||||||
JSONObject j = new JSONObject();
|
JSONObject j = new JSONObject();
|
||||||
j.put("enum", POTION_TYPES);
|
j.put("enum", POTION_TYPES);
|
||||||
definitions.put(key, j);
|
definitions.put(key, j);
|
||||||
@@ -511,40 +490,10 @@ 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 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<>();
|
||||||
@@ -562,7 +512,7 @@ public class SchemaBuilder {
|
|||||||
d.add(fancyType);
|
d.add(fancyType);
|
||||||
d.add(getDescription(k.getType()));
|
d.add(getDescription(k.getType()));
|
||||||
|
|
||||||
if(k.getType().isAnnotationPresent(Snippet.class)) {
|
if (k.getType().isAnnotationPresent(Snippet.class)) {
|
||||||
String sm = k.getType().getDeclaredAnnotation(Snippet.class).value();
|
String sm = k.getType().getDeclaredAnnotation(Snippet.class).value();
|
||||||
d.add(" ");
|
d.add(" ");
|
||||||
d.add("You can instead specify \"snippet/" + sm + "/some-name.json\" to use a snippet file instead of specifying it here.");
|
d.add("You can instead specify \"snippet/" + sm + "/some-name.json\" to use a snippet file instead of specifying it here.");
|
||||||
@@ -572,11 +522,11 @@ public class SchemaBuilder {
|
|||||||
k.setAccessible(true);
|
k.setAccessible(true);
|
||||||
Object value = k.get(cl.newInstance());
|
Object value = k.get(cl.newInstance());
|
||||||
|
|
||||||
if(value != null) {
|
if (value != null) {
|
||||||
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 {
|
||||||
@@ -584,7 +534,7 @@ public class SchemaBuilder {
|
|||||||
d.add("* Default Value is " + value);
|
d.add("* Default Value is " + value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch(Throwable ignored) {
|
} catch (Throwable ignored) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -592,7 +542,7 @@ public class SchemaBuilder {
|
|||||||
prop.put("type", type);
|
prop.put("type", type);
|
||||||
prop.put("description", d.toString("\n"));
|
prop.put("description", d.toString("\n"));
|
||||||
|
|
||||||
if(k.getType().isAnnotationPresent(Snippet.class)) {
|
if (k.getType().isAnnotationPresent(Snippet.class)) {
|
||||||
JSONObject anyOf = new JSONObject();
|
JSONObject anyOf = new JSONObject();
|
||||||
JSONArray arr = new JSONArray();
|
JSONArray arr = new JSONArray();
|
||||||
JSONObject str = new JSONObject();
|
JSONObject str = new JSONObject();
|
||||||
@@ -600,7 +550,7 @@ public class SchemaBuilder {
|
|||||||
String key = "enum-snippet-" + k.getType().getDeclaredAnnotation(Snippet.class).value();
|
String key = "enum-snippet-" + k.getType().getDeclaredAnnotation(Snippet.class).value();
|
||||||
str.put("$ref", "#/definitions/" + key);
|
str.put("$ref", "#/definitions/" + key);
|
||||||
|
|
||||||
if(!definitions.containsKey(key)) {
|
if (!definitions.containsKey(key)) {
|
||||||
JSONObject j = new JSONObject();
|
JSONObject j = new JSONObject();
|
||||||
JSONArray snl = new JSONArray();
|
JSONArray snl = new JSONArray();
|
||||||
data.getPossibleSnippets(k.getType().getDeclaredAnnotation(Snippet.class).value()).forEach(snl::put);
|
data.getPossibleSnippets(k.getType().getDeclaredAnnotation(Snippet.class).value()).forEach(snl::put);
|
||||||
@@ -622,32 +572,76 @@ 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";
|
||||||
}
|
}
|
||||||
|
|
||||||
if(c.equals(float.class) || c.equals(double.class) || c.equals(Float.class) || c.equals(Double.class)) {
|
if (c.equals(float.class) || c.equals(double.class) || c.equals(Float.class) || c.equals(Double.class)) {
|
||||||
return "number";
|
return "number";
|
||||||
}
|
}
|
||||||
|
|
||||||
if(c.equals(boolean.class) || c.equals(Boolean.class)) {
|
if (c.equals(boolean.class) || c.equals(Boolean.class)) {
|
||||||
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";
|
||||||
}
|
}
|
||||||
|
|
||||||
if(c.equals(KList.class)) {
|
if (c.equals(KList.class)) {
|
||||||
return "array";
|
return "array";
|
||||||
}
|
}
|
||||||
|
|
||||||
if(c.equals(KMap.class)) {
|
if (c.equals(KMap.class)) {
|
||||||
return "object";
|
return "object";
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!c.isAnnotationPresent(Desc.class) && c.getCanonicalName().startsWith("com.volmit.iris.")) {
|
if (!c.isAnnotationPresent(Desc.class) && c.getCanonicalName().startsWith("com.volmit.iris.")) {
|
||||||
warnings.addIfMissing("Unsupported Type: " + c.getCanonicalName() + " Did you forget @Desc?");
|
warnings.addIfMissing("Unsupported Type: " + c.getCanonicalName() + " Did you forget @Desc?");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -656,12 +650,12 @@ public class SchemaBuilder {
|
|||||||
|
|
||||||
private String getFieldDescription(Field r) {
|
private String getFieldDescription(Field r) {
|
||||||
|
|
||||||
if(r.isAnnotationPresent(Desc.class)) {
|
if (r.isAnnotationPresent(Desc.class)) {
|
||||||
return r.getDeclaredAnnotation(Desc.class).value();
|
return r.getDeclaredAnnotation(Desc.class).value();
|
||||||
}
|
}
|
||||||
|
|
||||||
// suppress warnings on bukkit classes
|
// suppress warnings on bukkit classes
|
||||||
if(r.getDeclaringClass().getName().startsWith("org.bukkit.")) {
|
if (r.getDeclaringClass().getName().startsWith("org.bukkit.")) {
|
||||||
return "Bukkit package classes and enums have no descriptions";
|
return "Bukkit package classes and enums have no descriptions";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -670,11 +664,11 @@ public class SchemaBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private String getDescription(Class<?> r) {
|
private String getDescription(Class<?> r) {
|
||||||
if(r.isAnnotationPresent(Desc.class)) {
|
if (r.isAnnotationPresent(Desc.class)) {
|
||||||
return r.getDeclaredAnnotation(Desc.class).value();
|
return r.getDeclaredAnnotation(Desc.class).value();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!r.isPrimitive() && !r.equals(KList.class) && !r.equals(KMap.class) && r.getCanonicalName().startsWith("com.volmit.")) {
|
if (!r.isPrimitive() && !r.equals(KList.class) && !r.equals(KMap.class) && r.getCanonicalName().startsWith("com.volmit.")) {
|
||||||
warnings.addIfMissing("Missing @Desc on " + r.getSimpleName() + " in " + (r.getDeclaringClass() != null ? r.getDeclaringClass().getCanonicalName() : " NOSRC"));
|
warnings.addIfMissing("Missing @Desc on " + r.getSimpleName() + " in " + (r.getDeclaringClass() != null ? r.getDeclaringClass().getCanonicalName() : " NOSRC"));
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
@@ -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