mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2025-12-31 21:06:29 +00:00
Compare commits
540 Commits
3.0.0-1.19
...
old/v3.4.3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b279bb7716 | ||
|
|
2976390e78 | ||
|
|
578070dffe | ||
|
|
1f9c72d093 | ||
|
|
a1495a10e5 | ||
|
|
a0d91dbc74 | ||
|
|
eb80ae62b1 | ||
|
|
11ae48bea1 | ||
|
|
b0f4b29a2d | ||
|
|
c38bb1cd01 | ||
|
|
7faa727bd2 | ||
|
|
a8751c80ab | ||
|
|
fd38f0d127 | ||
|
|
537b0f8dd6 | ||
|
|
560f2f4fdc | ||
|
|
7c725a9436 | ||
|
|
6532715490 | ||
|
|
b1bb01665a | ||
|
|
6c69c69868 | ||
|
|
9cd7ad6770 | ||
|
|
b70c9fd4d8 | ||
|
|
412f592e1c | ||
|
|
6c0fa9361f | ||
|
|
b7dcdd2921 | ||
|
|
1d8acd2d62 | ||
|
|
05bf92ca50 | ||
|
|
dd598d18bf | ||
|
|
cc6de4a46d | ||
|
|
9950551ecb | ||
|
|
dfd27ecbff | ||
|
|
ac5d5793ab | ||
|
|
2133a03c21 | ||
|
|
8755449c13 | ||
|
|
9e40259ca2 | ||
|
|
94a7692735 | ||
|
|
86ce02789e | ||
|
|
773c8129c9 | ||
|
|
dbe9f81091 | ||
|
|
288e556f2a | ||
|
|
70822e37de | ||
|
|
8b803a87f0 | ||
|
|
3ae6e92eaf | ||
|
|
0f3c52a5aa | ||
|
|
747be7aa09 | ||
|
|
3f994c18ff | ||
|
|
36b99ae4b0 | ||
|
|
25dbc4dfd6 | ||
|
|
c35366caa4 | ||
|
|
76365e7875 | ||
|
|
57649a9ec5 | ||
|
|
03582751c5 | ||
|
|
13369bbf32 | ||
|
|
f3b1109804 | ||
|
|
7f530a4b32 | ||
|
|
eda44a8ace | ||
|
|
f6a354b890 | ||
|
|
db14861b40 | ||
|
|
457b691add | ||
|
|
d651f204f8 | ||
|
|
a61787ecfe | ||
|
|
093d77bf8a | ||
|
|
0101130d7a | ||
|
|
a3b2a17e2d | ||
|
|
ff0a68c4f6 | ||
|
|
e0034dd718 | ||
|
|
7c6df58c15 | ||
|
|
5d5c5ba9f4 | ||
|
|
85aefcd206 | ||
|
|
34a67dc781 | ||
|
|
1a96128321 | ||
|
|
1b0f4e6af6 | ||
|
|
9eb01dd6ca | ||
|
|
bb6778dc63 | ||
|
|
9a24627ceb | ||
|
|
7583b91d46 | ||
|
|
c418962411 | ||
|
|
8e8366b318 | ||
|
|
a4ad83d462 | ||
|
|
ddf0e79a7e | ||
|
|
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 | ||
|
|
df3e4b055f |
@@ -30,14 +30,11 @@ Consider supporting our development by buying Iris on spigot! We work hard to ma
|
||||
3. Add `export JAVA_HOME=$(/usr/libexec/java_home)` as a new line
|
||||
4. Use `CTRL + X`, then Press `Y`, Then `ENTER`
|
||||
5. Quit & Reopen Terminal and verify with `echo $JAVA_HOME`. It should print a directory
|
||||
3. If this is your first time building Iris for MC 1.18+ run `gradlew setup` inside the root Iris project folder.
|
||||
Otherwise, skip this step. Grab a coffee, this may take up to 5 minutes depending on your cpu & internet connection.
|
||||
4. Once the project has setup, run `gradlew iris`
|
||||
5. The Iris jar will be placed in `Iris/build/Iris-XXX-XXX.jar` Enjoy! Consider supporting us by buying it on spigot!
|
||||
3. Once the project has setup, run `gradlew iris`
|
||||
4. The Iris jar will be placed in `Iris/build/Iris-XXX-XXX.jar` Enjoy! Consider supporting us by buying it on spigot!
|
||||
|
||||
### IDE Builds (for development)
|
||||
|
||||
* Run `gradlew setup` any time you get dependency issues with craftbukkit
|
||||
* Configure ITJ Gradle to use JDK 17 (in settings, search for gradle)
|
||||
* Add a build line in the build.gradle for your own build task to directly compile Iris into your plugins folder if you
|
||||
prefer.
|
||||
@@ -69,7 +66,6 @@ IrisAccess access=IrisToolbelt.createWorld() // If you like builders...
|
||||
.name("myWorld") // The world name
|
||||
.dimension("terrifyinghands")
|
||||
.seed(69133742) // The world seed
|
||||
.headless(true) // Headless make gen go fast
|
||||
.pregen(PregenTask // Define a pregen job to run
|
||||
.builder()
|
||||
.center(new Position2(0,0)) // REGION coords (1 region = 32x32 chunks)
|
||||
|
||||
263
build.gradle
263
build.gradle
@@ -16,15 +16,23 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
buildscript() {
|
||||
repositories {
|
||||
maven { url 'https://jitpack.io'}
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.github.VolmitSoftware:NMSTools:1.0.1'
|
||||
}
|
||||
}
|
||||
|
||||
plugins {
|
||||
id 'java'
|
||||
id 'java-library'
|
||||
id "com.github.johnrengelman.shadow" version "7.1.2"
|
||||
id "io.github.goooler.shadow" version "8.1.7"
|
||||
id "de.undercouch.download" version "5.0.1"
|
||||
}
|
||||
|
||||
version '3.0.0-1.19.2-1.20.2'
|
||||
def specialSourceVersion = '1.11.0' //[NMS]
|
||||
version '3.4.3-1.19.2-1.21.1'
|
||||
|
||||
// ADD YOURSELF AS A NEW LINE IF YOU WANT YOUR OWN BUILD TASK GENERATED
|
||||
// ======================== WINDOWS =============================
|
||||
@@ -35,208 +43,84 @@ registerCustomOutputTask('Coco', 'D://mcsm/plugins')
|
||||
registerCustomOutputTask('Strange', 'D://Servers/1.17 Test Server/plugins')
|
||||
registerCustomOutputTask('Vatuu', 'D://Minecraft/Servers/1.19.4/plugins')
|
||||
registerCustomOutputTask('CrazyDev22', 'C://Users/Julian/Desktop/server/plugins')
|
||||
registerCustomOutputTask('Pixel', 'C://Users/repix/Iris Dimension Engine/1.20.1 - Iris Coding/plugins')
|
||||
registerCustomOutputTask('Pixel', 'D://Iris Dimension Engine/1.20.4 - Development/plugins')
|
||||
registerCustomOutputTask('PixelFury', 'C://Users/RePixelatedMC/Iris/1.21 - Development-v3/plugins')
|
||||
// ========================== UNIX ==============================
|
||||
registerCustomOutputTaskUnix('CyberpwnLT', '/Users/danielmills/development/server/plugins')
|
||||
registerCustomOutputTaskUnix('PsychoLT', '/Users/brianfopiano/Desktop/REMOTES/RemoteMinecraft/plugins')
|
||||
registerCustomOutputTaskUnix('PsychoLT', '/Users/brianfopiano/Developer/RemoteGit/Server/plugins')
|
||||
registerCustomOutputTaskUnix('PixelMac', '/Users/test/Desktop/mcserver/plugins')
|
||||
registerCustomOutputTaskUnix('CrazyDev22LT', '/home/julian/Desktop/server/plugins')
|
||||
// ==============================================================
|
||||
|
||||
def NMS_BINDINGS = Map.of(
|
||||
"v1_21_R1", "1.21.1-R0.1-SNAPSHOT",
|
||||
"v1_20_R4", "1.20.6-R0.1-SNAPSHOT",
|
||||
"v1_20_R3", "1.20.4-R0.1-SNAPSHOT",
|
||||
"v1_20_R2", "1.20.2-R0.1-SNAPSHOT",
|
||||
"v1_20_R1", "1.20.1-R0.1-SNAPSHOT",
|
||||
"v1_19_R3", "1.19.4-R0.1-SNAPSHOT",
|
||||
"v1_19_R2", "1.19.3-R0.1-SNAPSHOT",
|
||||
"v1_19_R1", "1.19.2-R0.1-SNAPSHOT"
|
||||
)
|
||||
NMS_BINDINGS.each {
|
||||
def key = it.key
|
||||
def value = it.value
|
||||
def nms = value.split("-")[0];
|
||||
project(":nms:${key}") {
|
||||
def JVM_VERSION = Map.of(
|
||||
"v1_21_R1", 21,
|
||||
"v1_20_R4", 21,
|
||||
)
|
||||
NMS_BINDINGS.each { nms ->
|
||||
project(":nms:${nms.key}") {
|
||||
apply plugin: 'java'
|
||||
apply plugin: 'java-library'
|
||||
apply plugin: 'de.undercouch.download'
|
||||
apply plugin: 'com.volmit.nmstools'
|
||||
|
||||
nmsTools {
|
||||
it.jvm = JVM_VERSION.getOrDefault(nms.key, 17)
|
||||
it.version = nms.value
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation project(":core")
|
||||
implementation "org.spigotmc:spigot-api:${value}"
|
||||
implementation "org.bukkit:craftbukkit:${value}:remapped-mojang" //[NMS]
|
||||
}
|
||||
|
||||
def buildToolsJar = new File(rootProject.buildDir, "tools/BuildTools.jar")
|
||||
def specialSourceJar = new File(rootProject.buildDir, "tools/SpecialSource.jar")
|
||||
|
||||
def buildToolsFolder = new File(buildDir, "buildtools")
|
||||
def specialSourceFolder = new File(buildDir, "specialsource")
|
||||
def buildToolsHint = new File(buildDir, "buildtools/craftbukkit-" + nms + ".jar")
|
||||
|
||||
def outputJar = new File(buildDir, "libs/${key}.jar")
|
||||
def ssiJar = new File(buildDir, "specialsource/${key}.jar")
|
||||
def ssobfJar = new File(buildDir, "specialsource/${key}-rmo.jar")
|
||||
def ssJar = new File(buildDir, "specialsource/${key}-rma.jar")
|
||||
|
||||
def homePath = System.properties['user.home']
|
||||
def m2 = new File(homePath + "/.m2/repository")
|
||||
def m2s = m2.getAbsolutePath();
|
||||
|
||||
// ======================== Building Mapped Jars =============================
|
||||
Runnable downloadBuildtools = () -> {
|
||||
if (!buildToolsJar.exists()) {
|
||||
download.run {
|
||||
src 'https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar'
|
||||
dest buildToolsJar
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Runnable downloadSpecialSource = () -> {
|
||||
if (!specialSourceJar.exists()) {
|
||||
download.run {
|
||||
src 'https://repo.maven.apache.org/maven2/net/md-5/SpecialSource/' + specialSourceVersion + '/SpecialSource-'+specialSourceVersion+'-shaded.jar'
|
||||
dest specialSourceJar
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Runnable executeBuildTools = () -> {
|
||||
if (!buildToolsHint.exists()) {
|
||||
downloadBuildtools.run()
|
||||
buildToolsFolder.mkdirs()
|
||||
javaexec {
|
||||
classpath = files(buildToolsJar)
|
||||
workingDir = buildToolsFolder
|
||||
args = [
|
||||
"--rev",
|
||||
nms,
|
||||
"--compile",
|
||||
"craftbukkit",
|
||||
"--remap"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.register("executeBuildTools") {
|
||||
doFirst {
|
||||
executeBuildTools.run()
|
||||
}
|
||||
}
|
||||
|
||||
tasks.register("copyBuildToSpecialSource", Copy) {
|
||||
doFirst {
|
||||
downloadSpecialSource.run()
|
||||
specialSourceFolder.mkdirs();
|
||||
}
|
||||
|
||||
group "remapping"
|
||||
from outputJar
|
||||
into specialSourceFolder
|
||||
dependsOn(jar)
|
||||
}
|
||||
|
||||
tasks.register("specialSourceRemapObfuscate", JavaExec) {
|
||||
group "remapping"
|
||||
dependsOn(copyBuildToSpecialSource)
|
||||
workingDir = specialSourceFolder
|
||||
classpath = files(specialSourceJar,
|
||||
new File(m2s + "/org/spigotmc/spigot/" + value + "/spigot-" + value + "-remapped-mojang.jar"))
|
||||
mainClass = "net.md_5.specialsource.SpecialSource"
|
||||
args = [
|
||||
"--live",
|
||||
"-i",
|
||||
ssiJar.getName(),
|
||||
"-o",
|
||||
ssobfJar.getName(),
|
||||
"-m",
|
||||
m2s + "/org/spigotmc/minecraft-server/" + value + "/minecraft-server-" + value + "-maps-mojang.txt",
|
||||
"--reverse",
|
||||
]
|
||||
}
|
||||
|
||||
tasks.register("specialSourceRemap", JavaExec) {
|
||||
group "remapping"
|
||||
dependsOn(specialSourceRemapObfuscate)
|
||||
workingDir = specialSourceFolder
|
||||
classpath = files(specialSourceJar,
|
||||
new File(m2s + "/org/spigotmc/spigot/" + value + "/spigot-" + value + "-remapped-obf.jar"))
|
||||
mainClass = "net.md_5.specialsource.SpecialSource"
|
||||
args = [
|
||||
"--live",
|
||||
"-i",
|
||||
ssobfJar.getName(),
|
||||
"-o",
|
||||
ssJar.getName(),
|
||||
"-m",
|
||||
m2s + "/org/spigotmc/minecraft-server/" + value + "/minecraft-server-" + value + "-maps-spigot.csrg"
|
||||
]
|
||||
}
|
||||
|
||||
tasks.register("copySpecialSourceToBuild", Copy) {
|
||||
group "remapping"
|
||||
from ssJar
|
||||
into outputJar.getParentFile()
|
||||
rename {
|
||||
outputJar.getName()
|
||||
}
|
||||
dependsOn(specialSourceRemap)
|
||||
}
|
||||
|
||||
tasks.build.dependsOn(copySpecialSourceToBuild)
|
||||
executeBuildTools.run()
|
||||
}
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
NMS_BINDINGS.each {dependsOn(":nms:${it.key}:build")}
|
||||
NMS_BINDINGS.each {
|
||||
dependsOn(":nms:${it.key}:remap")
|
||||
from("${project(":nms:${it.key}").layout.buildDirectory.asFile.get()}/libs/${it.key}-mapped.jar")
|
||||
}
|
||||
|
||||
//minimize()
|
||||
append("plugin.yml")
|
||||
relocate 'com.dfsek.paralithic', 'com.volmit.iris.util.paralithic'
|
||||
relocate 'io.papermc.lib', 'com.volmit.iris.util.paper'
|
||||
relocate 'net.kyori', 'com.volmit.iris.util.kyori'
|
||||
dependencies {
|
||||
include(dependency('io.papermc:paperlib'))
|
||||
include(dependency('com.dfsek:Paralithic'))
|
||||
include(dependency('net.kyori:'))
|
||||
include(project(":core"))
|
||||
NMS_BINDINGS.each {include(project(":nms:${it.key}"))}
|
||||
}
|
||||
archiveFileName.set("Iris-${project.version}.jar")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation project(':core')
|
||||
NMS_BINDINGS.each {
|
||||
implementation project(":nms:${it.key}")
|
||||
}
|
||||
}
|
||||
|
||||
configurations.all {
|
||||
configurations.configureEach {
|
||||
resolutionStrategy.cacheChangingModulesFor 60, 'minutes'
|
||||
resolutionStrategy.cacheDynamicVersionsFor 60, 'minutes'
|
||||
}
|
||||
|
||||
allprojects {
|
||||
getPlugins().apply("java")
|
||||
apply plugin: 'java'
|
||||
|
||||
repositories {
|
||||
mavenLocal {
|
||||
content {
|
||||
includeGroup("org.bukkit")
|
||||
includeGroup("org.spigotmc")
|
||||
}
|
||||
}
|
||||
mavenCentral()
|
||||
maven { url "https://repo.papermc.io/repository/maven-public/"}
|
||||
maven { url "https://repo.papermc.io/repository/maven-public/" }
|
||||
maven { url "https://repo.codemc.org/repository/maven-public" }
|
||||
maven { url "https://mvn.lumine.io/repository/maven-public/" }
|
||||
maven { url "https://jitpack.io"}
|
||||
maven { url "https://jitpack.io" }
|
||||
|
||||
maven { url "https://s01.oss.sonatype.org/content/repositories/snapshots" }
|
||||
maven { url "https://mvn.lumine.io/repository/maven/" }
|
||||
maven { url "https://repo.triumphteam.dev/snapshots" }
|
||||
maven { url "https://repo.mineinabyss.com/releases" }
|
||||
maven { url 'https://hub.jeff-media.com/nexus/repository/jeff-media-public/' }
|
||||
maven { url "https://repo.oraxen.com/releases" }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
@@ -247,23 +131,26 @@ allprojects {
|
||||
// Shaded
|
||||
implementation 'com.dfsek:Paralithic:0.4.0'
|
||||
implementation 'io.papermc:paperlib:1.0.5'
|
||||
implementation "net.kyori:adventure-text-minimessage:4.13.1"
|
||||
implementation 'net.kyori:adventure-platform-bukkit:4.3.0'
|
||||
implementation 'net.kyori:adventure-api:4.13.1'
|
||||
implementation 'io.lumine:Mythic-Dist:5.2.1'
|
||||
implementation "net.kyori:adventure-text-minimessage:4.17.0"
|
||||
implementation 'net.kyori:adventure-platform-bukkit:4.3.4'
|
||||
implementation 'net.kyori:adventure-api:4.17.0'
|
||||
//implementation 'org.bytedeco:javacpp:1.5.10'
|
||||
//implementation 'org.bytedeco:cuda-platform:12.3-8.9-1.5.10'
|
||||
compileOnly 'io.lumine:Mythic-Dist:5.2.1'
|
||||
compileOnly 'io.lumine:MythicCrucible-Dist:2.0.0'
|
||||
|
||||
// Dynamically Loaded
|
||||
implementation 'io.timeandspace:smoothie-map:2.0.2'
|
||||
implementation 'it.unimi.dsi:fastutil:8.5.8'
|
||||
implementation 'com.googlecode.concurrentlinkedhashmap:concurrentlinkedhashmap-lru:1.4.2'
|
||||
implementation 'org.zeroturnaround:zt-zip:1.14'
|
||||
implementation 'com.google.code.gson:gson:2.9.0'
|
||||
implementation 'org.ow2.asm:asm:9.2'
|
||||
implementation 'com.google.guava:guava:31.1-jre'
|
||||
implementation 'bsf:bsf:2.4.0'
|
||||
implementation 'rhino:js:1.7R2'
|
||||
implementation 'com.github.ben-manes.caffeine:caffeine:3.0.6'
|
||||
implementation 'org.apache.commons:commons-lang3:3.12.0'
|
||||
compileOnly 'io.timeandspace:smoothie-map:2.0.2'
|
||||
compileOnly 'it.unimi.dsi:fastutil:8.5.8'
|
||||
compileOnly 'com.googlecode.concurrentlinkedhashmap:concurrentlinkedhashmap-lru:1.4.2'
|
||||
compileOnly 'org.zeroturnaround:zt-zip:1.14'
|
||||
compileOnly 'com.google.code.gson:gson:2.10.1'
|
||||
compileOnly 'org.ow2.asm:asm:9.2'
|
||||
compileOnly 'com.google.guava:guava:33.0.0-jre'
|
||||
compileOnly 'bsf:bsf:2.4.0'
|
||||
compileOnly 'rhino:js:1.7R2'
|
||||
compileOnly 'com.github.ben-manes.caffeine:caffeine:3.0.6'
|
||||
compileOnly 'org.apache.commons:commons-lang3:3.12.0'
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -273,6 +160,21 @@ allprojects {
|
||||
options.compilerArgs << '-parameters'
|
||||
options.encoding = "UTF-8"
|
||||
}
|
||||
|
||||
javadoc {
|
||||
options.encoding = "UTF-8"
|
||||
options.addStringOption('Xdoclint:none', '-quiet')
|
||||
}
|
||||
|
||||
task sourcesJar(type: Jar, dependsOn: classes) {
|
||||
archiveClassifier.set('sources')
|
||||
from sourceSets.main.allSource
|
||||
}
|
||||
|
||||
task javadocJar(type: Jar, dependsOn: javadoc) {
|
||||
archiveClassifier.set('javadoc')
|
||||
from javadoc.destinationDir
|
||||
}
|
||||
}
|
||||
|
||||
if (JavaVersion.current().toString() != "17") {
|
||||
@@ -295,18 +197,25 @@ if (JavaVersion.current().toString() != "17") {
|
||||
|
||||
task iris(type: Copy) {
|
||||
group "iris"
|
||||
from new File(buildDir, "libs/Iris-${version}.jar")
|
||||
into buildDir
|
||||
from new File(layout.buildDirectory.asFile.get(), "libs/Iris-${version}.jar")
|
||||
into layout.buildDirectory.asFile.get()
|
||||
dependsOn(build)
|
||||
}
|
||||
|
||||
task setup() {
|
||||
// with classifier: 'javadoc' and 'sources'
|
||||
task irisDev(type: Copy) {
|
||||
group "iris"
|
||||
NMS_BINDINGS.each {
|
||||
dependsOn(project(":nms:${it.key}").executeBuildTools)
|
||||
from("core/build/libs/core-javadoc.jar", "core/build/libs/core-sources.jar")
|
||||
rename { String fileName ->
|
||||
fileName.replace("core", "Iris-${version}")
|
||||
}
|
||||
into layout.buildDirectory.asFile.get()
|
||||
dependsOn(iris)
|
||||
dependsOn("core:sourcesJar")
|
||||
dependsOn("core:javadocJar")
|
||||
}
|
||||
|
||||
|
||||
def registerCustomOutputTask(name, path) {
|
||||
if (!System.properties['os.name'].toLowerCase().contains('windows')) {
|
||||
return;
|
||||
@@ -341,4 +250,4 @@ def registerCustomOutputTaskUnix(name, path) {
|
||||
}
|
||||
}
|
||||
|
||||
tasks.build.dependsOn(shadowJar)
|
||||
tasks.build.dependsOn(shadowJar)
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
plugins {
|
||||
id 'java'
|
||||
id 'java-library'
|
||||
id "io.freefair.lombok" version "6.3.0"
|
||||
id "io.freefair.lombok" version "8.6"
|
||||
}
|
||||
|
||||
def apiVersion = '1.19'
|
||||
@@ -33,6 +33,11 @@ compileJava {
|
||||
options.encoding = "UTF-8"
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven { url 'https://nexus.phoenixdevt.fr/repository/maven-public/'}
|
||||
maven { url 'https://repo.auxilor.io/repository/maven-public/' }
|
||||
}
|
||||
|
||||
/**
|
||||
* Dependencies.
|
||||
*
|
||||
@@ -47,18 +52,22 @@ compileJava {
|
||||
*/
|
||||
dependencies {
|
||||
// Provided or Classpath
|
||||
implementation 'org.spigotmc:spigot-api:1.20.1-R0.1-SNAPSHOT'
|
||||
implementation 'org.apache.logging.log4j:log4j-api:2.19.0'
|
||||
implementation 'org.apache.logging.log4j:log4j-core:2.19.0'
|
||||
implementation 'commons-lang:commons-lang:2.6'
|
||||
implementation 'com.github.oshi:oshi-core:5.8.5'
|
||||
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.14.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
|
||||
implementation 'com.ticxo.playeranimator:PlayerAnimator:R1.2.7'
|
||||
implementation 'com.github.oraxen:oraxen:1.158.0'
|
||||
implementation 'com.github.LoneDev6:api-itemsadder:3.4.1-r4'
|
||||
implementation 'com.github.PlaceholderAPI:placeholderapi:2.11.3'
|
||||
implementation 'com.github.Ssomar-Developement:SCore:4.23.10.8'
|
||||
compileOnly 'com.ticxo.playeranimator:PlayerAnimator:R1.2.7'
|
||||
compileOnly 'io.th0rgal:oraxen:1.173.0'
|
||||
compileOnly 'com.github.LoneDev6:api-itemsadder:3.4.1-r4'
|
||||
compileOnly 'com.github.PlaceholderAPI:placeholderapi:2.11.3'
|
||||
compileOnly 'com.github.Ssomar-Developement:SCore:4.23.10.8'
|
||||
compileOnly 'net.Indyuce:MMOItems-API:6.9.5-SNAPSHOT'
|
||||
compileOnly 'com.willfp:EcoItems:5.44.0'
|
||||
//implementation files('libs/CustomItems.jar')
|
||||
}
|
||||
|
||||
@@ -80,6 +89,4 @@ processResources {
|
||||
'apiversion': apiVersion.toString()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
tasks.compileJava.dependsOn(delombok)
|
||||
}
|
||||
@@ -30,7 +30,6 @@ import com.volmit.iris.core.loader.IrisData;
|
||||
import com.volmit.iris.core.nms.INMS;
|
||||
import com.volmit.iris.core.nms.v1X.NMSBinding1X;
|
||||
import com.volmit.iris.core.pregenerator.LazyPregenerator;
|
||||
import com.volmit.iris.core.service.ChunkHandlerSVC;
|
||||
import com.volmit.iris.core.service.StudioSVC;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.engine.EnginePanic;
|
||||
@@ -39,8 +38,8 @@ import com.volmit.iris.engine.object.IrisDimension;
|
||||
import com.volmit.iris.engine.object.IrisWorld;
|
||||
import com.volmit.iris.engine.platform.BukkitChunkGenerator;
|
||||
import com.volmit.iris.engine.platform.DummyChunkGenerator;
|
||||
import com.volmit.iris.engine.safeguard.IrisSafeguard;
|
||||
import com.volmit.iris.engine.safeguard.UtilsSFG;
|
||||
import com.volmit.iris.core.safeguard.IrisSafeguard;
|
||||
import com.volmit.iris.core.safeguard.UtilsSFG;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.exceptions.IrisException;
|
||||
@@ -64,6 +63,7 @@ import com.volmit.iris.util.scheduling.J;
|
||||
import com.volmit.iris.util.scheduling.Queue;
|
||||
import com.volmit.iris.util.scheduling.ShurikenQueue;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import lombok.Getter;
|
||||
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
|
||||
import net.kyori.adventure.text.serializer.ComponentSerializer;
|
||||
import org.bukkit.Bukkit;
|
||||
@@ -91,14 +91,16 @@ import java.io.*;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.lang.management.OperatingSystemMXBean;
|
||||
import java.lang.management.ThreadMXBean;
|
||||
import java.net.URL;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static com.volmit.iris.engine.safeguard.IrisSafeguard.unstablemode;
|
||||
import static com.volmit.iris.engine.safeguard.ServerBootSFG.passedserversoftware;
|
||||
import static com.volmit.iris.core.safeguard.IrisSafeguard.*;
|
||||
import static com.volmit.iris.core.safeguard.ServerBootSFG.passedserversoftware;
|
||||
import static com.volmit.iris.util.misc.getHardware.getCPUModel;
|
||||
import static com.volmit.iris.util.misc.getHardware.getCPUThreads;
|
||||
|
||||
@SuppressWarnings("CanBeFinal")
|
||||
public class Iris extends VolmitPlugin implements Listener {
|
||||
@@ -127,6 +129,10 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
private KMap<Class<? extends IrisService>, IrisService> services;
|
||||
|
||||
public static VolmitSender getSender() {
|
||||
if (sender == null) {
|
||||
sender = new VolmitSender(Bukkit.getConsoleSender());
|
||||
sender.setTag(instance.getTag());
|
||||
}
|
||||
return sender;
|
||||
}
|
||||
|
||||
@@ -193,10 +199,10 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
|
||||
public static void msg(String string) {
|
||||
try {
|
||||
sender.sendMessage(string);
|
||||
getSender().sendMessage(string);
|
||||
} catch (Throwable e) {
|
||||
try {
|
||||
System.out.println(instance.getTag() + string.replaceAll("(<([^>]+)>)", ""));
|
||||
instance.getLogger().info(instance.getTag() + string.replaceAll("(<([^>]+)>)", ""));
|
||||
} catch (Throwable ignored1) {
|
||||
|
||||
}
|
||||
@@ -350,7 +356,7 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
}
|
||||
}
|
||||
|
||||
private static int getJavaVersion() {
|
||||
public static int getJavaVersion() {
|
||||
String version = System.getProperty("java.version");
|
||||
if (version.startsWith("1.")) {
|
||||
version = version.substring(2, 3);
|
||||
@@ -363,6 +369,13 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
return Integer.parseInt(version);
|
||||
}
|
||||
|
||||
public static String getJava() {
|
||||
String javaRuntimeName = System.getProperty("java.vm.name");
|
||||
String javaRuntimeVendor = System.getProperty("java.vendor");
|
||||
String javaRuntimeVersion = System.getProperty("java.vm.version");
|
||||
return String.format("%s %s (build %s)", javaRuntimeName, javaRuntimeVendor, javaRuntimeVersion);
|
||||
}
|
||||
|
||||
public static void reportErrorChunk(int x, int z, Throwable e, String extra) {
|
||||
if (IrisSettings.get().getGeneral().isDebug()) {
|
||||
File f = instance.getDataFile("debug", "chunk-errors", "chunk." + x + "." + z + ".txt");
|
||||
@@ -425,7 +438,7 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
}
|
||||
|
||||
pw.close();
|
||||
System.out.println("DUMPED! See " + fi.getAbsolutePath());
|
||||
Iris.info("DUMPED! See " + fi.getAbsolutePath());
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@@ -442,18 +455,15 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
private static void fixShading() {
|
||||
ShadeFix.fix(ComponentSerializer.class);
|
||||
}
|
||||
private ChunkHandlerSVC chunkHandlerSVC;
|
||||
private void enable() {
|
||||
instance = this;
|
||||
services = new KMap<>();
|
||||
setupAudience();
|
||||
initialize("com.volmit.iris.core.service").forEach((i) -> services.put((Class<? extends IrisService>) i.getClass(), (IrisService) i));
|
||||
INMS.get();
|
||||
IO.delete(new File("iris"));
|
||||
setupAudience();
|
||||
IrisSafeguard.IrisSafeguardSystem();
|
||||
sender = new VolmitSender(Bukkit.getConsoleSender());
|
||||
sender.setTag(getTag());
|
||||
instance = this;
|
||||
getSender().setTag(getTag());
|
||||
compat = IrisCompat.configured(getDataFile("compat.json"));
|
||||
linkMultiverseCore = new MultiverseCoreLink();
|
||||
linkMythicMobs = new MythicMobsLink();
|
||||
@@ -470,14 +480,8 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
J.s(this::setupPapi);
|
||||
J.a(ServerConfigurator::configure, 20);
|
||||
splash();
|
||||
UtilsSFG.UnstableMode();
|
||||
UtilsSFG.SupportedServerSoftware();
|
||||
UtilsSFG.printIncompatibleWarnings();
|
||||
UtilsSFG.unstablePrompt();
|
||||
if(IrisSettings.get().getGeneral().useIntegratedChunkHandler) {
|
||||
chunkHandlerSVC = new ChunkHandlerSVC(this);
|
||||
Iris.info(C.LIGHT_PURPLE + "Started Intergrated ChunkHandlerSVC");
|
||||
}
|
||||
UtilsSFG.splash();
|
||||
|
||||
autoStartStudio();
|
||||
checkForBukkitWorlds();
|
||||
IrisToolbelt.retainMantleDataForSlice(String.class.getCanonicalName());
|
||||
@@ -532,7 +536,7 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
Iris.info("Starting up auto Studio!");
|
||||
try {
|
||||
Player r = new KList<>(getServer().getOnlinePlayers()).getRandom();
|
||||
Iris.service(StudioSVC.class).open(r != null ? new VolmitSender(r) : sender, 1337, IrisSettings.get().getGenerator().getDefaultWorldType(), (w) -> {
|
||||
Iris.service(StudioSVC.class).open(r != null ? new VolmitSender(r) : getSender(), 1337, IrisSettings.get().getGenerator().getDefaultWorldType(), (w) -> {
|
||||
J.s(() -> {
|
||||
for (Player i : getServer().getOnlinePlayers()) {
|
||||
i.setGameMode(GameMode.SPECTATOR);
|
||||
@@ -599,9 +603,11 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
if (unstablemode) {
|
||||
return C.BOLD + "" + C.DARK_GRAY + "[" + C.BOLD + "" + C.RED + "Iris" + C.BOLD + C.DARK_GRAY + "]" + C.RESET + "" + C.GRAY + ": ";
|
||||
}
|
||||
else {
|
||||
return C.BOLD + "" + C.DARK_GRAY + "[" + C.BOLD + "" + C.IRIS + "Iris" + C.BOLD + C.DARK_GRAY + "]" + C.RESET + "" + C.GRAY + ": ";
|
||||
if (warningmode) {
|
||||
return C.BOLD + "" + C.DARK_GRAY + "[" + C.BOLD + "" + C.GOLD + "Iris" + C.BOLD + C.DARK_GRAY + "]" + C.RESET + "" + C.GRAY + ": ";
|
||||
}
|
||||
return C.BOLD + "" + C.DARK_GRAY + "[" + C.BOLD + "" + C.IRIS + "Iris" + C.BOLD + C.DARK_GRAY + "]" + C.RESET + "" + C.GRAY + ": ";
|
||||
|
||||
}
|
||||
|
||||
private boolean setupChecks() {
|
||||
@@ -731,10 +737,10 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
File ff = new File(w.worldFolder(), "iris/pack");
|
||||
if (!ff.exists() || ff.listFiles().length == 0) {
|
||||
ff.mkdirs();
|
||||
service(StudioSVC.class).installIntoWorld(sender, dim.getLoadKey(), ff.getParentFile());
|
||||
service(StudioSVC.class).installIntoWorld(getSender(), dim.getLoadKey(), w.worldFolder());
|
||||
}
|
||||
|
||||
return new BukkitChunkGenerator(w, false, ff, dim.getLoadKey());
|
||||
return new BukkitChunkGenerator(w, false, ff, dim.getLoadKey(), false);
|
||||
}
|
||||
|
||||
public void splash() {
|
||||
@@ -748,6 +754,9 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
if (unstablemode) {
|
||||
info = new String[]{"", "", "", "", "", padd2 + C.RED + " Iris", padd2 + C.GRAY + " by " + C.DARK_RED + "Volmit Software", padd2 + C.GRAY + " v" + C.RED + getDescription().getVersion()};
|
||||
}
|
||||
if (warningmode) {
|
||||
info = new String[]{"", "", "", "", "", padd2 + C.GOLD + " Iris", padd2 + C.GRAY + " by " + C.GOLD + "Volmit Software", padd2 + C.GRAY + " v" + C.GOLD + getDescription().getVersion()};
|
||||
}
|
||||
|
||||
String[] splashstable = {
|
||||
padd + C.GRAY + " @@@@@@@@@@@@@@" + C.DARK_GRAY + "@@@",
|
||||
@@ -776,32 +785,61 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
padd + C.GRAY + "" + C.RED + " '(((())))' " + C.DARK_GRAY + "&&&&&&&&" + C.GRAY + "&&&&&&&@@",
|
||||
padd + C.GRAY + " " + C.DARK_GRAY + "@@@" + C.GRAY + "@@@@@@@@@@@@@@"
|
||||
};
|
||||
String[] splash = unstablemode ? splashunstable : splashstable; // Choose the appropriate splash array based on unstablemode
|
||||
|
||||
|
||||
OperatingSystemMXBean osBean = ManagementFactory.getOperatingSystemMXBean();
|
||||
String osArch = osBean.getArch();
|
||||
String osName = osBean.getName();
|
||||
String[] splashwarning = {
|
||||
padd + C.GRAY + " @@@@@@@@@@@@@@" + C.DARK_GRAY + "@@@",
|
||||
padd + C.GRAY + " @@&&&&&&&&&" + C.DARK_GRAY + "&&&&&&" + C.GOLD + " .(((()))). ",
|
||||
padd + C.GRAY + "@@@&&&&&&&&" + C.DARK_GRAY + "&&&&&" + C.GOLD + " .((((((())))))). ",
|
||||
padd + C.GRAY + "@@@&&&&&" + C.DARK_GRAY + "&&&&&&&" + C.GOLD + " ((((((((())))))))) " + C.GRAY + " @",
|
||||
padd + C.GRAY + "@@@&&&&" + C.DARK_GRAY + "@@@@@&" + C.GOLD + " ((((((((-))))))))) " + C.GRAY + " @@",
|
||||
padd + C.GRAY + "@@@&&" + C.GOLD + " ((((((({ })))))))) " + C.GRAY + " &&@@@",
|
||||
padd + C.GRAY + "@@" + C.GOLD + " ((((((((-))))))))) " + C.DARK_GRAY + "&@@@@@" + C.GRAY + "&&&&@@@",
|
||||
padd + C.GRAY + "@" + C.GOLD + " ((((((((())))))))) " + C.DARK_GRAY + "&&&&&" + C.GRAY + "&&&&&&&@@@",
|
||||
padd + C.GRAY + "" + C.GOLD + " '((((((()))))))' " + C.DARK_GRAY + "&&&&&" + C.GRAY + "&&&&&&&&@@@",
|
||||
padd + C.GRAY + "" + C.GOLD + " '(((())))' " + C.DARK_GRAY + "&&&&&&&&" + C.GRAY + "&&&&&&&@@",
|
||||
padd + C.GRAY + " " + C.DARK_GRAY + "@@@" + C.GRAY + "@@@@@@@@@@@@@@"
|
||||
};
|
||||
String[] splash;
|
||||
File freeSpace = new File(Bukkit.getWorldContainer() + ".");
|
||||
if (unstablemode) {
|
||||
splash = splashunstable;
|
||||
} else if (warningmode) {
|
||||
splash = splashwarning;
|
||||
} else {
|
||||
splash = splashstable;
|
||||
}
|
||||
|
||||
if (!passedserversoftware) {
|
||||
Iris.info("Server type & version: " + C.RED + Bukkit.getVersion());
|
||||
} else { Iris.info("Server type & version: " + Bukkit.getVersion()); }
|
||||
Iris.info("Java: " + getJava());
|
||||
try {
|
||||
if (getCPUModel().contains("Intel")) {
|
||||
Iris.info("Server Cpu: " + C.BLUE + getCPUModel());
|
||||
}
|
||||
if (getCPUModel().contains("Ryzen")) {
|
||||
Iris.info("Server Cpu: " + C.RED + getCPUModel());
|
||||
}
|
||||
if (!getCPUModel().contains("Ryzen") && !getCPUModel().contains("Intel")) {
|
||||
Iris.info("Server Cpu: " + C.GRAY + getCPUModel());
|
||||
}
|
||||
|
||||
Iris.info("Server OS: " + osName + " (" + osArch + ")");
|
||||
} catch (Exception e){
|
||||
Iris.info("Server Cpu: " + C.DARK_RED + "Failed");
|
||||
}
|
||||
|
||||
if(unstablemode) Iris.info("Server Cpu: " + C.DARK_RED + getCPUModel());
|
||||
|
||||
if(getCPUModel().contains("Intel")) Iris.info("Server Cpu: " + C.BLUE + getCPUModel());
|
||||
if(getCPUModel().contains("Ryzen")) Iris.info("Server Cpu: " + C.RED + getCPUModel());
|
||||
if(!getCPUModel().contains("Intel") && !getCPUModel().contains("Ryzen")) Iris.info("Server Cpu: " + C.DARK_GRAY + getCPUModel());
|
||||
|
||||
Iris.info("Process Threads: " + getCPUThreads());
|
||||
Iris.info("Process Memory: " + getHardware.getProcessMemory() + " MB");
|
||||
Iris.info("Threads: " + C.GRAY + Runtime.getRuntime().availableProcessors());
|
||||
if (!instance.getServer().getVersion().contains("Purpur")) {
|
||||
if (instance.getServer().getVersion().contains("Spigot") && instance.getServer().getVersion().contains("Bukkit")) {
|
||||
Iris.info(C.RED + " Iris requires paper or above to function properly..");
|
||||
} else {
|
||||
Iris.info(C.YELLOW + "Purpur is recommended to use with iris.");
|
||||
}
|
||||
}
|
||||
if (getHardware.getProcessMemory() < 5999) {
|
||||
Iris.warn("6GB+ Ram is recommended");
|
||||
Iris.warn("Process Memory: " + getHardware.getProcessMemory() + " MB");
|
||||
}
|
||||
Iris.info("Bukkit version: " + Bukkit.getBukkitVersion());
|
||||
Iris.info("Java version: " + getJavaVersion());
|
||||
Iris.info("Bukkit distro: " + Bukkit.getName());
|
||||
Iris.info("Custom Biomes: " + INMS.get().countCustomBiomes());
|
||||
setupChecks();
|
||||
printPacks();
|
||||
@@ -834,4 +872,33 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
}
|
||||
Iris.info(" " + dimName + " v" + version);
|
||||
}
|
||||
|
||||
public int getIrisVersion() {
|
||||
String input = Iris.instance.getDescription().getVersion();
|
||||
int hyphenIndex = input.indexOf('-');
|
||||
if (hyphenIndex != -1) {
|
||||
String result = input.substring(0, hyphenIndex);
|
||||
result = result.replaceAll("\\.", "");
|
||||
return Integer.parseInt(result);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public int getMCVersion() {
|
||||
try {
|
||||
String version = Bukkit.getVersion();
|
||||
Matcher matcher = Pattern.compile("\\(MC: ([\\d.]+)\\)").matcher(version);
|
||||
if (matcher.find()) {
|
||||
version = matcher.group(1).replaceAll("\\.", "");
|
||||
long versionNumber = Long.parseLong(version);
|
||||
if (versionNumber > Integer.MAX_VALUE) {
|
||||
return -1;
|
||||
}
|
||||
return (int) versionNumber;
|
||||
}
|
||||
return -1;
|
||||
} catch (Exception e) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,10 @@ import com.volmit.iris.util.io.IO;
|
||||
import com.volmit.iris.util.json.JSONException;
|
||||
import com.volmit.iris.util.json.JSONObject;
|
||||
import com.volmit.iris.util.plugin.VolmitSender;
|
||||
import com.volmit.iris.util.scheduling.ChronoLatch;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@@ -41,8 +44,11 @@ public class IrisSettings {
|
||||
private IrisSettingsConcurrency concurrency = new IrisSettingsConcurrency();
|
||||
private IrisSettingsStudio studio = new IrisSettingsStudio();
|
||||
private IrisSettingsPerformance performance = new IrisSettingsPerformance();
|
||||
private IrisSettingsUpdater updater = new IrisSettingsUpdater();
|
||||
|
||||
public static int getThreadCount(int c) {
|
||||
if (System.getProperty("os.name").toLowerCase().contains("win"))
|
||||
return Runtime.getRuntime().availableProcessors();
|
||||
return switch (c) {
|
||||
case -1, -2, -4 -> Runtime.getRuntime().availableProcessors() / -c;
|
||||
case 0, 1, 2 -> 1;
|
||||
@@ -131,11 +137,12 @@ public class IrisSettings {
|
||||
@Data
|
||||
public static class IrisSettingsConcurrency {
|
||||
public int parallelism = -1;
|
||||
public boolean windowsFullPerformance = true;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class IrisSettingsPerformance {
|
||||
public boolean trimMantleInStudio = false;
|
||||
public boolean trimMantleInStudio = false;
|
||||
public int mantleKeepAlive = 30;
|
||||
public int cacheSize = 4_096;
|
||||
public int resourceLoaderCacheSize = 1_024;
|
||||
@@ -143,10 +150,33 @@ public class IrisSettings {
|
||||
public int scriptLoaderCacheSize = 512;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class IrisSettingsUpdater {
|
||||
public double threadMultiplier = 2;
|
||||
public double chunkLoadSensitivity = 0.7;
|
||||
public MsRange emptyMsRange = new MsRange(80, 100);
|
||||
public MsRange defaultMsRange = new MsRange(20, 40);
|
||||
|
||||
public double getThreadMultiplier() {
|
||||
return Math.min(Math.abs(threadMultiplier), 0.1);
|
||||
}
|
||||
|
||||
public double getChunkLoadSensitivity() {
|
||||
return Math.min(chunkLoadSensitivity, 0.9);
|
||||
}
|
||||
}
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class MsRange {
|
||||
public int min = 20;
|
||||
public int max = 40;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class IrisSettingsGeneral {
|
||||
public boolean bootUnstable = false;
|
||||
public boolean useIntegratedChunkHandler = false;
|
||||
public boolean DoomsdayAnnihilationSelfDestructMode = false;
|
||||
public boolean commandSounds = true;
|
||||
public boolean debug = false;
|
||||
public boolean disableNMS = false;
|
||||
@@ -171,6 +201,7 @@ public class IrisSettings {
|
||||
public static class IrisSettingsGUI {
|
||||
public boolean useServerLaunchedGuis = true;
|
||||
public boolean maximumPregenGuiFPS = false;
|
||||
public boolean colorMode = true;
|
||||
}
|
||||
|
||||
@Data
|
||||
|
||||
@@ -21,9 +21,12 @@ package com.volmit.iris.core;
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.loader.IrisData;
|
||||
import com.volmit.iris.core.nms.INMS;
|
||||
import com.volmit.iris.core.nms.datapack.DataVersion;
|
||||
import com.volmit.iris.core.nms.datapack.IDataFixer;
|
||||
import com.volmit.iris.engine.object.IrisBiome;
|
||||
import com.volmit.iris.engine.object.IrisBiomeCustom;
|
||||
import com.volmit.iris.engine.object.IrisDimension;
|
||||
import com.volmit.iris.engine.object.IrisRange;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KSet;
|
||||
import com.volmit.iris.util.format.C;
|
||||
@@ -55,7 +58,7 @@ public class ServerConfigurator {
|
||||
}
|
||||
|
||||
private static void increaseKeepAliveSpigot() throws IOException, InvalidConfigurationException {
|
||||
File spigotConfig = new File("config/spigot.yml");
|
||||
File spigotConfig = new File("spigot.yml");
|
||||
FileConfiguration f = new YamlConfiguration();
|
||||
f.load(spigotConfig);
|
||||
long tt = f.getLong("settings.timeout-time");
|
||||
@@ -90,10 +93,36 @@ public class ServerConfigurator {
|
||||
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...");
|
||||
File packs = new File("plugins/Iris/packs");
|
||||
double ultimateMaxHeight = 0;
|
||||
double ultimateMinHeight = 0;
|
||||
if (packs.exists() && packs.isDirectory()) {
|
||||
for (File pack : packs.listFiles()) {
|
||||
IrisData data = IrisData.get(pack);
|
||||
if (pack.isDirectory()) {
|
||||
File dimensionsFolder = new File(pack, "dimensions");
|
||||
if (dimensionsFolder.exists() && dimensionsFolder.isDirectory()) {
|
||||
for (File file : dimensionsFolder.listFiles()) {
|
||||
if (file.isFile() && file.getName().endsWith(".json")) {
|
||||
IrisDimension dim = data.getDimensionLoader().load(file.getName().split("\\Q.\\E")[0]);
|
||||
if (ultimateMaxHeight < dim.getDimensionHeight().getMax()) {
|
||||
ultimateMaxHeight = dim.getDimensionHeight().getMax();
|
||||
}
|
||||
if (ultimateMinHeight > dim.getDimensionHeight().getMin()) {
|
||||
ultimateMinHeight = dim.getDimensionHeight().getMin();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (packs.exists()) {
|
||||
for (File i : packs.listFiles()) {
|
||||
@@ -113,7 +142,7 @@ public class ServerConfigurator {
|
||||
|
||||
Iris.verbose(" Checking Dimension " + dim.getLoadFile().getPath());
|
||||
for (File dpack : getDatapacksFolder()) {
|
||||
dim.installDataPack(() -> data, dpack);
|
||||
dim.installDataPack(fixer, () -> data, dpack, ultimateMaxHeight, ultimateMinHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,336 @@
|
||||
/*
|
||||
* 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.INMS;
|
||||
import com.volmit.iris.core.nms.datapack.DataVersion;
|
||||
import com.volmit.iris.core.service.IrisEngineSVC;
|
||||
import com.volmit.iris.core.tools.IrisPackBenchmarking;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.core.tools.IrisWorldAnalytics;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.object.IrisDimension;
|
||||
import com.volmit.iris.util.decree.DecreeExecutor;
|
||||
import com.volmit.iris.util.decree.DecreeOrigin;
|
||||
import com.volmit.iris.util.decree.annotations.Decree;
|
||||
import com.volmit.iris.util.decree.annotations.Param;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.io.IO;
|
||||
import com.volmit.iris.util.mantle.TectonicPlate;
|
||||
import com.volmit.iris.util.nbt.mca.MCAFile;
|
||||
import com.volmit.iris.util.nbt.mca.MCAUtil;
|
||||
import com.volmit.iris.util.parallel.MultiBurst;
|
||||
import com.volmit.iris.util.plugin.VolmitSender;
|
||||
import net.jpountz.lz4.LZ4BlockInputStream;
|
||||
import net.jpountz.lz4.LZ4BlockOutputStream;
|
||||
import net.jpountz.lz4.LZ4FrameInputStream;
|
||||
import net.jpountz.lz4.LZ4FrameOutputStream;
|
||||
import org.apache.commons.lang.RandomStringUtils;
|
||||
import org.bukkit.*;
|
||||
|
||||
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 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"})
|
||||
IrisDimension dimension
|
||||
) {
|
||||
Iris.info("test");
|
||||
IrisPackBenchmarking benchmark = new IrisPackBenchmarking(dimension, 1);
|
||||
|
||||
}
|
||||
|
||||
@Decree(description = "gets wg height")
|
||||
public void whatHeight() {
|
||||
Iris.info("test");
|
||||
sender().sendMessage("Height: " + player().getWorld().getHighestBlockAt(player().getLocation(), HeightMap.MOTION_BLOCKING).getY());
|
||||
}
|
||||
|
||||
@Decree(description = "check", aliases = {"ck"} )
|
||||
public void check() {
|
||||
sender().sendMessage("Data Pack Biome: " + INMS.get().getTrueBiomeBaseKey(player().getLocation()) + " (ID: " + INMS.get().getTrueBiomeBaseId(INMS.get().getTrueBiomeBase(player().getLocation())) + ")");
|
||||
}
|
||||
|
||||
@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);
|
||||
int i = 0;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Decree(description = "test")
|
||||
public void anl (
|
||||
@Param(description = "String") String world) {
|
||||
try {
|
||||
IrisWorldAnalytics a = new IrisWorldAnalytics(world);
|
||||
a.execute();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Decree(description = "UnloadChunks for good reasons.")
|
||||
public void unloadchunks() {
|
||||
List<World> IrisWorlds = new ArrayList<>();
|
||||
int chunksUnloaded = 0;
|
||||
for (World world : Bukkit.getWorlds()) {
|
||||
try {
|
||||
if (IrisToolbelt.access(world).getEngine() != null) {
|
||||
IrisWorlds.add(world);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// no
|
||||
}
|
||||
}
|
||||
|
||||
for (World world : IrisWorlds) {
|
||||
for (Chunk chunk : world.getLoadedChunks()) {
|
||||
if (chunk.isLoaded()) {
|
||||
chunk.unload();
|
||||
chunksUnloaded++;
|
||||
}
|
||||
}
|
||||
}
|
||||
Iris.info(C.IRIS + "Chunks Unloaded: " + chunksUnloaded);
|
||||
|
||||
}
|
||||
|
||||
@Decree
|
||||
public void objects(@Param(defaultValue = "overworld") IrisDimension dimension) {
|
||||
var loader = dimension.getLoader().getObjectLoader();
|
||||
var sender = sender();
|
||||
var keys = loader.getPossibleKeys();
|
||||
var burst = MultiBurst.burst.burst(keys.length);
|
||||
AtomicInteger failed = new AtomicInteger();
|
||||
for (String key : keys) {
|
||||
burst.queue(() -> {
|
||||
if (loader.load(key) == null)
|
||||
failed.incrementAndGet();
|
||||
});
|
||||
}
|
||||
burst.complete();
|
||||
sender.sendMessage(C.RED + "Failed to load " + failed.get() + " of " + keys.length + " objects");
|
||||
}
|
||||
|
||||
@Decree(description = "Test", aliases = {"ip"})
|
||||
public void network() {
|
||||
try {
|
||||
Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
|
||||
for (NetworkInterface ni : Collections.list(networkInterfaces)) {
|
||||
Iris.info("Display Name: %s", ni.getDisplayName());
|
||||
Enumeration<InetAddress> inetAddresses = ni.getInetAddresses();
|
||||
for (InetAddress ia : Collections.list(inetAddresses)) {
|
||||
Iris.info("IP: %s", ia.getHostAddress());
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(description = "Test the compression algorithms")
|
||||
public void compression(
|
||||
@Param(description = "base IrisWorld") World world,
|
||||
@Param(description = "raw TectonicPlate File") String path,
|
||||
@Param(description = "Algorithm to Test") String algorithm,
|
||||
@Param(description = "Amount of Tests") int amount) {
|
||||
if (!IrisToolbelt.isIrisWorld(world)) {
|
||||
sender().sendMessage(C.RED + "This is not an Iris world. Iris worlds: " + String.join(", ", Bukkit.getServer().getWorlds().stream().filter(IrisToolbelt::isIrisWorld).map(World::getName).toList()));
|
||||
return;
|
||||
}
|
||||
|
||||
File file = new File(path);
|
||||
if (!file.exists()) return;
|
||||
|
||||
Engine engine = IrisToolbelt.access(world).getEngine();
|
||||
if(engine != null) {
|
||||
int height = engine.getTarget().getHeight();
|
||||
ExecutorService service = Executors.newFixedThreadPool(1);
|
||||
VolmitSender sender = sender();
|
||||
service.submit(() -> {
|
||||
try {
|
||||
DataInputStream raw = new DataInputStream(new FileInputStream(file));
|
||||
TectonicPlate plate = new TectonicPlate(height, raw);
|
||||
raw.close();
|
||||
|
||||
double d1 = 0;
|
||||
double d2 = 0;
|
||||
long size = 0;
|
||||
File folder = new File("tmp");
|
||||
folder.mkdirs();
|
||||
for (int i = 0; i < amount; i++) {
|
||||
File tmp = new File(folder, RandomStringUtils.randomAlphanumeric(10) + "." + algorithm + ".bin");
|
||||
DataOutputStream dos = createOutput(tmp, algorithm);
|
||||
long start = System.currentTimeMillis();
|
||||
plate.write(dos);
|
||||
dos.close();
|
||||
d1 += System.currentTimeMillis() - start;
|
||||
if (size == 0)
|
||||
size = tmp.length();
|
||||
start = System.currentTimeMillis();
|
||||
DataInputStream din = createInput(tmp, algorithm);
|
||||
new TectonicPlate(height, din);
|
||||
din.close();
|
||||
d2 += System.currentTimeMillis() - start;
|
||||
tmp.delete();
|
||||
}
|
||||
IO.delete(folder);
|
||||
sender.sendMessage(algorithm + " is " + Form.fileSize(size) + " big after compression");
|
||||
sender.sendMessage(algorithm + " Took " + d2/amount + "ms to read");
|
||||
sender.sendMessage(algorithm + " Took " + d1/amount + "ms to write");
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
service.shutdown();
|
||||
} else {
|
||||
Iris.info(C.RED + "Engine is null!");
|
||||
}
|
||||
}
|
||||
|
||||
private DataInputStream createInput(File file, String algorithm) throws Throwable {
|
||||
FileInputStream in = new FileInputStream(file);
|
||||
|
||||
return new DataInputStream(switch (algorithm) {
|
||||
case "gzip" -> new GZIPInputStream(in);
|
||||
case "lz4f" -> new LZ4FrameInputStream(in);
|
||||
case "lz4b" -> new LZ4BlockInputStream(in);
|
||||
default -> throw new IllegalStateException("Unexpected value: " + algorithm);
|
||||
});
|
||||
}
|
||||
|
||||
private DataOutputStream createOutput(File file, String algorithm) throws Throwable {
|
||||
FileOutputStream out = new FileOutputStream(file);
|
||||
|
||||
return new DataOutputStream(switch (algorithm) {
|
||||
case "gzip" -> new GZIPOutputStream(out);
|
||||
case "lz4f" -> new LZ4FrameOutputStream(out);
|
||||
case "lz4b" -> new LZ4BlockOutputStream(out);
|
||||
default -> throw new IllegalStateException("Unexpected value: " + algorithm);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,9 @@ public class CommandFind implements DecreeExecutor {
|
||||
@Decree(description = "Find a biome")
|
||||
public void biome(
|
||||
@Param(description = "The biome to look for")
|
||||
IrisBiome biome
|
||||
IrisBiome biome,
|
||||
@Param(description = "Should you be teleported", defaultValue = "true")
|
||||
boolean teleport
|
||||
) {
|
||||
Engine e = engine();
|
||||
|
||||
@@ -43,13 +45,15 @@ public class CommandFind implements DecreeExecutor {
|
||||
return;
|
||||
}
|
||||
|
||||
e.gotoBiome(biome, player());
|
||||
e.gotoBiome(biome, player(), teleport);
|
||||
}
|
||||
|
||||
@Decree(description = "Find a region")
|
||||
public void region(
|
||||
@Param(description = "The region to look for")
|
||||
IrisRegion region
|
||||
IrisRegion region,
|
||||
@Param(description = "Should you be teleported", defaultValue = "true")
|
||||
boolean teleport
|
||||
) {
|
||||
Engine e = engine();
|
||||
|
||||
@@ -58,13 +62,15 @@ public class CommandFind implements DecreeExecutor {
|
||||
return;
|
||||
}
|
||||
|
||||
e.gotoRegion(region, player());
|
||||
e.gotoRegion(region, player(), teleport);
|
||||
}
|
||||
|
||||
@Decree(description = "Find a structure")
|
||||
public void structure(
|
||||
@Param(description = "The structure to look for")
|
||||
IrisJigsawStructure structure
|
||||
IrisJigsawStructure structure,
|
||||
@Param(description = "Should you be teleported", defaultValue = "true")
|
||||
boolean teleport
|
||||
) {
|
||||
Engine e = engine();
|
||||
|
||||
@@ -73,13 +79,15 @@ public class CommandFind implements DecreeExecutor {
|
||||
return;
|
||||
}
|
||||
|
||||
e.gotoJigsaw(structure, player());
|
||||
e.gotoJigsaw(structure, player(), teleport);
|
||||
}
|
||||
|
||||
@Decree(description = "Find a point of interest.")
|
||||
public void poi(
|
||||
@Param(description = "The type of PoI to look for.")
|
||||
String type
|
||||
String type,
|
||||
@Param(description = "Should you be teleported", defaultValue = "true")
|
||||
boolean teleport
|
||||
) {
|
||||
Engine e = engine();
|
||||
if (e == null) {
|
||||
@@ -87,13 +95,15 @@ public class CommandFind implements DecreeExecutor {
|
||||
return;
|
||||
}
|
||||
|
||||
e.gotoPOI(type, player());
|
||||
e.gotoPOI(type, player(), teleport);
|
||||
}
|
||||
|
||||
@Decree(description = "Find an object")
|
||||
public void object(
|
||||
@Param(description = "The object to look for", customHandler = ObjectHandler.class)
|
||||
String object
|
||||
String object,
|
||||
@Param(description = "Should you be teleported", defaultValue = "true")
|
||||
boolean teleport
|
||||
) {
|
||||
Engine e = engine();
|
||||
|
||||
@@ -102,6 +112,6 @@ public class CommandFind implements DecreeExecutor {
|
||||
return;
|
||||
}
|
||||
|
||||
e.gotoObject(object, player());
|
||||
e.gotoObject(object, player(), teleport);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,17 +20,20 @@ package com.volmit.iris.core.commands;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.ServerConfigurator;
|
||||
import com.volmit.iris.core.loader.IrisData;
|
||||
import com.volmit.iris.core.nms.datapack.DataVersion;
|
||||
import com.volmit.iris.core.pregenerator.ChunkUpdater;
|
||||
import com.volmit.iris.core.service.StudioSVC;
|
||||
import com.volmit.iris.core.tools.IrisBenchmarking;
|
||||
import com.volmit.iris.core.tools.IrisCreator;
|
||||
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.PlatformChunkGenerator;
|
||||
import com.volmit.iris.engine.safeguard.UtilsSFG;
|
||||
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.DecreeContext;
|
||||
import com.volmit.iris.util.decree.DecreeExecutor;
|
||||
import com.volmit.iris.util.decree.DecreeOrigin;
|
||||
import com.volmit.iris.util.decree.annotations.Decree;
|
||||
@@ -38,28 +41,33 @@ 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.mantle.MantleChunk;
|
||||
import com.volmit.iris.util.parallel.BurstExecutor;
|
||||
import com.volmit.iris.util.parallel.MultiBurst;
|
||||
import com.volmit.iris.util.plugin.VolmitSender;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import com.volmit.iris.util.scheduling.jobs.QueueJob;
|
||||
import lombok.Getter;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Difficulty;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.WorldCreator;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import java.io.Console;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static com.volmit.iris.Iris.service;
|
||||
import static com.volmit.iris.core.service.EditSVC.deletingWorld;
|
||||
import static com.volmit.iris.core.tools.IrisBenchmarking.inProgress;
|
||||
import static com.volmit.iris.engine.safeguard.IrisSafeguard.unstablemode;
|
||||
import static com.volmit.iris.engine.safeguard.ServerBootSFG.incompatiblePlugins;
|
||||
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 {
|
||||
@@ -71,9 +79,11 @@ public class CommandIris implements DecreeExecutor {
|
||||
private CommandWhat what;
|
||||
private CommandEdit edit;
|
||||
private CommandFind find;
|
||||
private CommandWorldManager manager;
|
||||
|
||||
public static @Getter String BenchDimension;
|
||||
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(
|
||||
@@ -82,10 +92,12 @@ public class CommandIris implements DecreeExecutor {
|
||||
@Param(aliases = "dimension", description = "The dimension type to create the world with", defaultValue = "default")
|
||||
IrisDimension type,
|
||||
@Param(description = "The seed to generate the world with", defaultValue = "1337")
|
||||
long seed
|
||||
long seed,
|
||||
@Param(description = "If it should convert the dimension to match the vanilla height system.", defaultValue = "false")
|
||||
boolean vanillaheight
|
||||
) {
|
||||
if(sender() instanceof Player) {
|
||||
if (incompatiblePlugins.get("Multiverse-Core")) {
|
||||
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 + "----------------------------------------------------------------");
|
||||
@@ -93,7 +105,7 @@ public class CommandIris implements DecreeExecutor {
|
||||
sender().sendMessage(C.RED + UtilsSFG.MSGIncompatibleWarnings());
|
||||
sender().sendMessage(C.RED + "----------------------------------------------------------------");
|
||||
}
|
||||
if (unstablemode && !incompatiblePlugins.get("Multiverse-Core")) {
|
||||
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 + "----------------------------------------------------------------");
|
||||
@@ -119,20 +131,23 @@ public class CommandIris implements DecreeExecutor {
|
||||
}
|
||||
|
||||
try {
|
||||
worldCreation = true;
|
||||
IrisToolbelt.createWorld()
|
||||
.dimension(type.getLoadKey())
|
||||
.name(name)
|
||||
.seed(seed)
|
||||
.sender(sender())
|
||||
.studio(false)
|
||||
.smartVanillaHeight(vanillaheight)
|
||||
.create();
|
||||
} catch (Throwable e) {
|
||||
sender().sendMessage(C.RED + "Exception raised during creation. See the console for more details.");
|
||||
Iris.error("Exception raised during world creation: " + e.getMessage());
|
||||
Iris.reportError(e);
|
||||
worldCreation = false;
|
||||
return;
|
||||
}
|
||||
|
||||
worldCreation = false;
|
||||
sender().sendMessage(C.GREEN + "Successfully created your world!");
|
||||
}
|
||||
|
||||
@@ -165,6 +180,8 @@ public class CommandIris implements DecreeExecutor {
|
||||
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) {
|
||||
@@ -173,8 +190,9 @@ public class CommandIris implements DecreeExecutor {
|
||||
Iris.info(C.RED + "Benchmark already is in progress.");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
/todo Fix PREGEN
|
||||
/todo
|
||||
@Decree(description = "Benchmark a pack", origin = DecreeOrigin.CONSOLE)
|
||||
public void packbenchmark(
|
||||
@Param(description = "Dimension to benchmark")
|
||||
@@ -186,28 +204,16 @@ public class CommandIris implements DecreeExecutor {
|
||||
IrisPackBenchmarking.runBenchmark();
|
||||
} */
|
||||
|
||||
/* /todo Different approach this feels useless atm
|
||||
@Decree(description = "Check for instabilities", origin = DecreeOrigin.CONSOLE)
|
||||
public void fixunstable() throws InterruptedException {
|
||||
if (unstablemode){
|
||||
sender().sendMessage(C.RED + "Incompatibilities are posted in console..");
|
||||
|
||||
Iris.info(C.RED + "Your server is experiencing an incompatibility with the Iris plugin.");
|
||||
Iris.info(C.RED + "Please rectify this problem to avoid further complications.");
|
||||
Iris.info(C.RED + "----------------------------------------------------------------");
|
||||
Iris.info(C.RED + "Command ran: /iris fixunstable");
|
||||
UtilsSFG.printIncompatibleWarnings();
|
||||
Iris.info(C.RED + "----------------------------------------------------------------");
|
||||
} else {
|
||||
Iris.info(C.BLUE + "Iris is running stable..");
|
||||
sender().sendMessage("Iris is running stable..");
|
||||
}
|
||||
} */
|
||||
|
||||
@Decree(description = "Print world height information", origin = DecreeOrigin.PLAYER)
|
||||
public void height() {
|
||||
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()));
|
||||
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)
|
||||
@@ -216,6 +222,44 @@ public class CommandIris implements DecreeExecutor {
|
||||
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")
|
||||
@@ -224,7 +268,7 @@ public class CommandIris implements DecreeExecutor {
|
||||
boolean delete
|
||||
) {
|
||||
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()));
|
||||
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());
|
||||
@@ -241,7 +285,7 @@ public class CommandIris implements DecreeExecutor {
|
||||
IrisToolbelt.evacuate(world, "Deleting world");
|
||||
deletingWorld = true;
|
||||
Bukkit.unloadWorld(world, false);
|
||||
int retries = 10;
|
||||
int retries = 12;
|
||||
if (delete) {
|
||||
if (deleteDirectory(world.getWorldFolder())) {
|
||||
sender().sendMessage(C.GREEN + "Successfully removed world folder");
|
||||
@@ -251,13 +295,12 @@ public class CommandIris implements DecreeExecutor {
|
||||
sender().sendMessage(C.GREEN + "Successfully removed world folder");
|
||||
break;
|
||||
}
|
||||
sender().sendMessage(C.GREEN + "DEBUG1");
|
||||
retries--;
|
||||
if (retries == 0){
|
||||
sender().sendMessage(C.RED + "Failed to remove world folder");
|
||||
break;
|
||||
}
|
||||
J.sleep(2000);
|
||||
J.sleep(3000);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -277,6 +320,24 @@ public class CommandIris implements DecreeExecutor {
|
||||
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")
|
||||
@@ -366,77 +427,6 @@ public class CommandIris implements DecreeExecutor {
|
||||
sender().sendMessage(C.GREEN + "Hotloaded settings");
|
||||
}
|
||||
|
||||
@Decree(name = "regen", description = "Regenerate nearby chunks.", aliases = "rg", sync = true, origin = DecreeOrigin.PLAYER)
|
||||
public void regen(
|
||||
@Param(name = "radius", description = "The radius of nearby cunks", defaultValue = "5")
|
||||
int radius
|
||||
) {
|
||||
if (IrisToolbelt.isIrisWorld(player().getWorld())) {
|
||||
VolmitSender sender = sender();
|
||||
J.a(() -> {
|
||||
DecreeContext.touch(sender);
|
||||
PlatformChunkGenerator plat = IrisToolbelt.access(player().getWorld());
|
||||
Engine engine = plat.getEngine();
|
||||
try {
|
||||
Chunk cx = player().getLocation().getChunk();
|
||||
KList<Runnable> js = new KList<>();
|
||||
BurstExecutor b = MultiBurst.burst.burst();
|
||||
b.setMulticore(false);
|
||||
int rad = engine.getMantle().getRealRadius();
|
||||
for (int i = -(radius + rad); i <= radius + rad; i++) {
|
||||
for (int j = -(radius + rad); j <= radius + rad; j++) {
|
||||
engine.getMantle().getMantle().deleteChunk(i + cx.getX(), j + cx.getZ());
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = -radius; i <= radius; i++) {
|
||||
for (int j = -radius; j <= radius; j++) {
|
||||
int finalJ = j;
|
||||
int finalI = i;
|
||||
b.queue(() -> plat.injectChunkReplacement(player().getWorld(), finalI + cx.getX(), finalJ + cx.getZ(), (f) -> {
|
||||
synchronized (js) {
|
||||
js.add(f);
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
b.complete();
|
||||
sender().sendMessage(C.GREEN + "Regenerating " + Form.f(js.size()) + " Sections");
|
||||
QueueJob<Runnable> r = new QueueJob<>() {
|
||||
final KList<Future<?>> futures = new KList<>();
|
||||
|
||||
@Override
|
||||
public void execute(Runnable runnable) {
|
||||
futures.add(J.sfut(runnable));
|
||||
|
||||
if (futures.size() > 64) {
|
||||
while (futures.isNotEmpty()) {
|
||||
try {
|
||||
futures.remove(0).get();
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Regenerating";
|
||||
}
|
||||
};
|
||||
r.queue(js);
|
||||
r.execute(sender());
|
||||
} catch (Throwable e) {
|
||||
sender().sendMessage("Unable to parse view-distance");
|
||||
}
|
||||
});
|
||||
} else {
|
||||
sender().sendMessage(C.RED + "You must be in an Iris World to use regen!");
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(description = "Update the pack of a world (UNSAFE!)", name = "^world", aliases = "update-world")
|
||||
public void updateWorld(
|
||||
@Param(description = "The world to update", contextual = true)
|
||||
@@ -472,4 +462,191 @@ public class CommandIris implements DecreeExecutor {
|
||||
|
||||
Iris.service(StudioSVC.class).installIntoWorld(sender(), pack.getLoadKey(), folder);
|
||||
}
|
||||
|
||||
@Decree(description = "Unload an Iris World", origin = DecreeOrigin.PLAYER, sync = true)
|
||||
public void unloadWorld(
|
||||
@Param(description = "The world to unload")
|
||||
World world
|
||||
) {
|
||||
if (!IrisToolbelt.isIrisWorld(world)) {
|
||||
sender().sendMessage(C.RED + "This is not an Iris world. Iris worlds: " + String.join(", ", getServer().getWorlds().stream().filter(IrisToolbelt::isIrisWorld).map(World::getName).toList()));
|
||||
return;
|
||||
}
|
||||
sender().sendMessage(C.GREEN + "Unloading world: " + world.getName());
|
||||
try {
|
||||
IrisToolbelt.evacuate(world);
|
||||
Bukkit.unloadWorld(world, false);
|
||||
sender().sendMessage(C.GREEN + "World unloaded successfully.");
|
||||
} catch (Exception e) {
|
||||
sender().sendMessage(C.RED + "Failed to unload the world: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(description = "Load an Iris World", origin = DecreeOrigin.PLAYER, sync = true, aliases = {"import"})
|
||||
public void loadWorld(
|
||||
@Param(description = "The name of the world to load")
|
||||
String world
|
||||
) {
|
||||
World worldloaded = Bukkit.getWorld(world);
|
||||
worldNameToCheck = world;
|
||||
boolean worldExists = doesWorldExist(worldNameToCheck);
|
||||
WorldEngine = world;
|
||||
|
||||
if (!worldExists) {
|
||||
sender().sendMessage(C.YELLOW + world + " Doesnt exist on the server.");
|
||||
return;
|
||||
}
|
||||
|
||||
File BUKKIT_YML = new File("bukkit.yml");
|
||||
String pathtodim = world + File.separator +"iris"+File.separator +"pack"+File.separator +"dimensions"+File.separator;
|
||||
File directory = new File(Bukkit.getWorldContainer(), pathtodim);
|
||||
|
||||
String dimension = null;
|
||||
if (directory.exists() && directory.isDirectory()) {
|
||||
File[] files = directory.listFiles();
|
||||
if (files != null) {
|
||||
for (File file : files) {
|
||||
if (file.isFile()) {
|
||||
String fileName = file.getName();
|
||||
if (fileName.endsWith(".json")) {
|
||||
dimension = fileName.substring(0, fileName.length() - 5);
|
||||
sender().sendMessage(C.BLUE + "Generator: " + dimension);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
sender().sendMessage(C.GOLD + world + " is not an iris world.");
|
||||
return;
|
||||
}
|
||||
sender().sendMessage(C.GREEN + "Loading world: " + world);
|
||||
|
||||
YamlConfiguration yml = YamlConfiguration.loadConfiguration(BUKKIT_YML);
|
||||
String gen = "Iris:" + dimension;
|
||||
ConfigurationSection section = yml.contains("worlds") ? yml.getConfigurationSection("worlds") : yml.createSection("worlds");
|
||||
if (!section.contains(world)) {
|
||||
section.createSection(world).set("generator", gen);
|
||||
try {
|
||||
yml.save(BUKKIT_YML);
|
||||
Iris.info("Registered \"" + world + "\" in bukkit.yml");
|
||||
} catch (IOException e) {
|
||||
Iris.error("Failed to update bukkit.yml!");
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
}
|
||||
checkForBukkitWorlds(world);
|
||||
sender().sendMessage(C.GREEN + world + " loaded successfully.");
|
||||
}
|
||||
@Decree(description = "Evacuate an iris world", origin = DecreeOrigin.PLAYER, sync = true)
|
||||
public void evacuate(
|
||||
@Param(description = "Evacuate the world")
|
||||
World world
|
||||
) {
|
||||
if (!IrisToolbelt.isIrisWorld(world)) {
|
||||
sender().sendMessage(C.RED + "This is not an Iris world. Iris worlds: " + String.join(", ", getServer().getWorlds().stream().filter(IrisToolbelt::isIrisWorld).map(World::getName).toList()));
|
||||
return;
|
||||
}
|
||||
sender().sendMessage(C.GREEN + "Evacuating world" + world.getName());
|
||||
IrisToolbelt.evacuate(world);
|
||||
}
|
||||
|
||||
boolean doesWorldExist(String worldName) {
|
||||
File worldContainer = Bukkit.getWorldContainer();
|
||||
File worldDirectory = new File(worldContainer, worldName);
|
||||
return worldDirectory.exists() && worldDirectory.isDirectory();
|
||||
}
|
||||
private void checkForBukkitWorlds(String world) {
|
||||
FileConfiguration fc = new YamlConfiguration();
|
||||
try {
|
||||
fc.load(new File("bukkit.yml"));
|
||||
ConfigurationSection section = fc.getConfigurationSection("worlds");
|
||||
if (section == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<String> worldsToLoad = Collections.singletonList(world);
|
||||
|
||||
for (String s : section.getKeys(false)) {
|
||||
if (!worldsToLoad.contains(s)) {
|
||||
continue;
|
||||
}
|
||||
ConfigurationSection entry = section.getConfigurationSection(s);
|
||||
if (!entry.contains("generator", true)) {
|
||||
continue;
|
||||
}
|
||||
String generator = entry.getString("generator");
|
||||
if (generator.startsWith("Iris:")) {
|
||||
generator = generator.split("\\Q:\\E")[1];
|
||||
} else if (generator.equalsIgnoreCase("Iris")) {
|
||||
generator = IrisSettings.get().getGenerator().getDefaultWorldType();
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
Iris.info("2 World: %s | Generator: %s", s, generator);
|
||||
if (Bukkit.getWorlds().stream().anyMatch(w -> w.getName().equals(s))) {
|
||||
continue;
|
||||
}
|
||||
Iris.info(C.LIGHT_PURPLE + "Preparing Spawn for " + s + "' using Iris:" + generator + "...");
|
||||
new WorldCreator(s)
|
||||
.generator(getDefaultWorldGenerator(s, generator))
|
||||
.environment(IrisData.loadAnyDimension(generator).getEnvironment())
|
||||
.createWorld();
|
||||
Iris.info(C.LIGHT_PURPLE + "Loaded " + s + "!");
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
public ChunkGenerator getDefaultWorldGenerator(String worldName, String id) {
|
||||
Iris.debug("Default World Generator Called for " + worldName + " using ID: " + id);
|
||||
if (worldName.equals("test")) {
|
||||
try {
|
||||
throw new RuntimeException();
|
||||
} catch (Throwable e) {
|
||||
Iris.info(e.getStackTrace()[1].getClassName());
|
||||
if (e.getStackTrace()[1].getClassName().contains("com.onarandombox.MultiverseCore")) {
|
||||
Iris.debug("MVC Test detected, Quick! Send them the dummy!");
|
||||
return new DummyChunkGenerator();
|
||||
}
|
||||
}
|
||||
}
|
||||
IrisDimension dim;
|
||||
if (id == null || id.isEmpty()) {
|
||||
dim = IrisData.loadAnyDimension(IrisSettings.get().getGenerator().getDefaultWorldType());
|
||||
} else {
|
||||
dim = IrisData.loadAnyDimension(id);
|
||||
}
|
||||
Iris.debug("Generator ID: " + id + " requested by bukkit/plugin");
|
||||
|
||||
if (dim == null) {
|
||||
Iris.warn("Unable to find dimension type " + id + " Looking for online packs...");
|
||||
|
||||
service(StudioSVC.class).downloadSearch(new VolmitSender(Bukkit.getConsoleSender()), id, true);
|
||||
dim = IrisData.loadAnyDimension(id);
|
||||
|
||||
if (dim == null) {
|
||||
throw new RuntimeException("Can't find dimension " + id + "!");
|
||||
} else {
|
||||
Iris.info("Resolved missing dimension, proceeding with generation.");
|
||||
}
|
||||
}
|
||||
Iris.debug("Assuming IrisDimension: " + dim.getName());
|
||||
IrisWorld w = IrisWorld.builder()
|
||||
.name(worldName)
|
||||
.seed(1337)
|
||||
.environment(dim.getEnvironment())
|
||||
.worldFolder(new File(Bukkit.getWorldContainer(), worldName))
|
||||
.minHeight(dim.getMinHeight())
|
||||
.maxHeight(dim.getMaxHeight())
|
||||
.build();
|
||||
Iris.debug("Generator Config: " + w.toString());
|
||||
File ff = new File(w.worldFolder(), "iris/pack");
|
||||
if (!ff.exists() || ff.listFiles().length == 0) {
|
||||
ff.mkdirs();
|
||||
service(StudioSVC.class).installIntoWorld(sender, dim.getLoadKey(), ff.getParentFile());
|
||||
}
|
||||
return new BukkitChunkGenerator(w, false, ff, dim.getLoadKey(), false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ package com.volmit.iris.core.commands;
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.edit.JigsawEditor;
|
||||
import com.volmit.iris.core.loader.IrisData;
|
||||
import com.volmit.iris.engine.framework.placer.WorldObjectPlacer;
|
||||
import com.volmit.iris.engine.jigsaw.PlannedStructure;
|
||||
import com.volmit.iris.engine.object.IrisJigsawPiece;
|
||||
import com.volmit.iris.engine.object.IrisJigsawStructure;
|
||||
@@ -34,6 +35,7 @@ import com.volmit.iris.util.decree.specialhandlers.ObjectHandler;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import com.volmit.iris.util.plugin.VolmitSender;
|
||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||
|
||||
import java.io.File;
|
||||
@@ -55,9 +57,16 @@ public class CommandJigsaw implements DecreeExecutor {
|
||||
IrisJigsawStructure structure
|
||||
) {
|
||||
PrecisionStopwatch p = PrecisionStopwatch.start();
|
||||
PlannedStructure ps = new PlannedStructure(structure, new IrisPosition(player().getLocation()), new RNG());
|
||||
sender().sendMessage(C.GREEN + "Generated " + ps.getPieces().size() + " pieces in " + Form.duration(p.getMilliseconds(), 2));
|
||||
ps.place(world());
|
||||
try {
|
||||
var world = world();
|
||||
WorldObjectPlacer placer = new WorldObjectPlacer(world);
|
||||
PlannedStructure ps = new PlannedStructure(structure, new IrisPosition(player().getLocation().add(0, world.getMinHeight(), 0)), new RNG(), true);
|
||||
VolmitSender sender = sender();
|
||||
sender.sendMessage(C.GREEN + "Generated " + ps.getPieces().size() + " pieces in " + Form.duration(p.getMilliseconds(), 2));
|
||||
ps.place(placer, failed -> sender.sendMessage(failed ? C.GREEN + "Placed the structure!" : C.RED + "Failed to place the structure!"));
|
||||
} catch (IllegalArgumentException e) {
|
||||
sender().sendMessage(C.RED + "Failed to place the structure: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(description = "Create a jigsaw piece")
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.volmit.iris.core.loader.IrisData;
|
||||
import com.volmit.iris.core.service.ObjectSVC;
|
||||
import com.volmit.iris.core.service.StudioSVC;
|
||||
import com.volmit.iris.core.service.WandSVC;
|
||||
import com.volmit.iris.core.tools.IrisConverter;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.object.*;
|
||||
import com.volmit.iris.util.data.Cuboid;
|
||||
@@ -35,6 +36,7 @@ import com.volmit.iris.util.decree.specialhandlers.ObjectHandler;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.math.Direction;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import com.volmit.iris.util.misc.E;
|
||||
import com.volmit.iris.util.scheduling.Queue;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.block.Block;
|
||||
@@ -52,7 +54,7 @@ import java.util.*;
|
||||
@Decree(name = "object", aliases = "o", origin = DecreeOrigin.PLAYER, studio = true, description = "Iris object manipulation")
|
||||
public class CommandObject implements DecreeExecutor {
|
||||
|
||||
private static final Set<Material> skipBlocks = Set.of(Material.GRASS, Material.SNOW, Material.VINE, Material.TORCH, Material.DEAD_BUSH,
|
||||
private static final Set<Material> skipBlocks = Set.of(E.getOrDefault(Material.class, "GRASS", "SHORT_GRASS"), Material.SNOW, Material.VINE, Material.TORCH, Material.DEAD_BUSH,
|
||||
Material.POPPY, Material.DANDELION);
|
||||
|
||||
public static IObjectPlacer createPlacer(World world, Map<Block, BlockData> futureBlockChanges) {
|
||||
@@ -116,10 +118,8 @@ public class CommandObject implements DecreeExecutor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTile(int xx, int yy, int zz, TileData<? extends TileState> tile) {
|
||||
BlockState state = world.getBlockAt(xx, yy, zz).getState();
|
||||
tile.toBukkitTry(state);
|
||||
state.update();
|
||||
public void setTile(int xx, int yy, int zz, TileData tile) {
|
||||
tile.toBukkitTry(world.getBlockAt(xx, yy, zz));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -197,6 +197,30 @@ public class CommandObject implements DecreeExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(description = "Shrink an object to its minimum size")
|
||||
public void shrink(@Param(description = "The object to shrink", customHandler = ObjectHandler.class) String object) {
|
||||
IrisObject o = IrisData.loadAnyObject(object);
|
||||
sender().sendMessage("Current Object Size: " + o.getW() + " * " + o.getH() + " * " + o.getD());
|
||||
o.shrinkwrap();
|
||||
sender().sendMessage("New Object Size: " + o.getW() + " * " + o.getH() + " * " + o.getD());
|
||||
try {
|
||||
o.write(o.getLoadFile());
|
||||
} catch (IOException e) {
|
||||
sender().sendMessage("Failed to save object " + o.getLoadFile() + ": " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(description = "Convert .schem files in the 'convert' folder to .iob files.")
|
||||
public void convert () {
|
||||
try {
|
||||
IrisConverter.convertSchematics(sender());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Decree(description = "Get a powder that reveals objects", studio = true, aliases = "d")
|
||||
public void dust() {
|
||||
player().getInventory().addItem(WandSVC.createDust());
|
||||
@@ -368,7 +392,7 @@ public class CommandObject implements DecreeExecutor {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
o.write(file);
|
||||
o.write(file, sender());
|
||||
} catch (IOException e) {
|
||||
sender().sendMessage(C.RED + "Failed to save object because of an IOException: " + e.getMessage());
|
||||
Iris.reportError(e);
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
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;
|
||||
@@ -43,75 +44,36 @@ public class CommandPregen implements DecreeExecutor {
|
||||
@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 = "method", description = "The pregen method that will get used. Lazy or Async", defaultValue = "async")
|
||||
String method
|
||||
) {
|
||||
if(method.equals("async") || method.equals("lazy")){
|
||||
if (method.equalsIgnoreCase("async")) {
|
||||
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.");
|
||||
}
|
||||
radius = Math.max(radius, 1024);
|
||||
int w = (radius >> 9 + 1) * 2;
|
||||
IrisToolbelt.pregenerate(PregenTask
|
||||
.builder()
|
||||
.center(new Position2(center.getBlockX() >> 9, center.getBlockZ() >> 9))
|
||||
.width(w)
|
||||
.height(w)
|
||||
.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();
|
||||
sender().sendMessage(msg);
|
||||
Iris.info(msg);
|
||||
} catch (Throwable e) {
|
||||
sender().sendMessage(C.RED + "Epic fail. See console.");
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
Vector center
|
||||
) {
|
||||
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.");
|
||||
}
|
||||
if (method.equalsIgnoreCase("lazy")) {
|
||||
String worldName = world.getName();
|
||||
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(999999999)
|
||||
.radiusBlocks(radius)
|
||||
.position(0)
|
||||
.build();
|
||||
|
||||
LazyPregenerator pregenerator = new LazyPregenerator(pregenJob, new File("plugins/Iris/lazygen.json"));
|
||||
pregenerator.start();
|
||||
|
||||
String msg = C.GREEN + "Pregen 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();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
sender().sendMessage(C.RED + "Please use a valid method.");
|
||||
|
||||
radius = Math.max(radius, 1024);
|
||||
int w = (radius >> 9 + 1) * 2;
|
||||
IrisToolbelt.pregenerate(PregenTask
|
||||
.builder()
|
||||
.center(new Position2(center.getBlockX() >> 9, center.getBlockZ() >> 9))
|
||||
.gui(true)
|
||||
.width(w)
|
||||
.height(w)
|
||||
.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();
|
||||
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() {
|
||||
if (PregeneratorJob.shutdownInstance()) {
|
||||
Iris.info( C.BLUE + "Finishing up mca region...");
|
||||
sender().sendMessage(C.DARK_BLUE + "Stopped pregeneration task");
|
||||
} else {
|
||||
sender().sendMessage(C.YELLOW + "No active pregeneration tasks to stop");
|
||||
}
|
||||
|
||||
@@ -26,12 +26,15 @@ import com.volmit.iris.core.loader.IrisData;
|
||||
import com.volmit.iris.core.project.IrisProject;
|
||||
import com.volmit.iris.core.service.ConversionSVC;
|
||||
import com.volmit.iris.core.service.StudioSVC;
|
||||
import com.volmit.iris.core.tools.IrisConverter;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.object.*;
|
||||
import com.volmit.iris.engine.platform.PlatformChunkGenerator;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.collection.KSet;
|
||||
import com.volmit.iris.util.decree.DecreeContext;
|
||||
import com.volmit.iris.util.decree.DecreeExecutor;
|
||||
import com.volmit.iris.util.decree.DecreeOrigin;
|
||||
import com.volmit.iris.util.decree.annotations.Decree;
|
||||
@@ -45,15 +48,23 @@ import com.volmit.iris.util.io.IO;
|
||||
import com.volmit.iris.util.json.JSONArray;
|
||||
import com.volmit.iris.util.json.JSONObject;
|
||||
import com.volmit.iris.util.math.M;
|
||||
import com.volmit.iris.util.math.Position2;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import com.volmit.iris.util.math.Spiraler;
|
||||
import com.volmit.iris.util.noise.CNG;
|
||||
import com.volmit.iris.util.parallel.BurstExecutor;
|
||||
import com.volmit.iris.util.parallel.MultiBurst;
|
||||
import com.volmit.iris.util.plugin.VolmitSender;
|
||||
import com.volmit.iris.util.scheduling.ChronoLatch;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import com.volmit.iris.util.scheduling.O;
|
||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||
import com.volmit.iris.util.scheduling.jobs.QueueJob;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.event.inventory.InventoryType;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
import org.bukkit.util.BlockVector;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
@@ -65,14 +76,20 @@ import java.nio.file.Files;
|
||||
import java.nio.file.attribute.FileTime;
|
||||
import java.time.Duration;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@Decree(name = "studio", aliases = {"std", "s"}, description = "Studio Commands", studio = true)
|
||||
public class CommandStudio implements DecreeExecutor {
|
||||
private CommandFind find;
|
||||
private CommandEdit edit;
|
||||
//private CommandDeepSearch deepSearch;
|
||||
|
||||
public static String hrf(Duration duration) {
|
||||
return duration.toString().substring(2).replaceAll("(\\d[HMS])(?!$)", "$1 ").toLowerCase();
|
||||
@@ -143,12 +160,83 @@ public class CommandStudio implements DecreeExecutor {
|
||||
sender().sendMessage(C.GREEN + "The \"" + dimension.getName() + "\" pack has version: " + dimension.getVersion());
|
||||
}
|
||||
|
||||
@Decree(name = "regen", description = "Regenerate nearby chunks.", aliases = "rg", sync = true, origin = DecreeOrigin.PLAYER)
|
||||
public void regen(
|
||||
@Param(name = "radius", description = "The radius of nearby cunks", defaultValue = "5")
|
||||
int radius
|
||||
) {
|
||||
if (IrisToolbelt.isIrisWorld(player().getWorld())) {
|
||||
VolmitSender sender = sender();
|
||||
J.a(() -> {
|
||||
DecreeContext.touch(sender);
|
||||
PlatformChunkGenerator plat = IrisToolbelt.access(player().getWorld());
|
||||
Engine engine = plat.getEngine();
|
||||
try {
|
||||
Chunk cx = player().getLocation().getChunk();
|
||||
KList<Runnable> js = new KList<>();
|
||||
BurstExecutor b = MultiBurst.burst.burst();
|
||||
b.setMulticore(false);
|
||||
int rad = engine.getMantle().getRealRadius();
|
||||
for (int i = -(radius + rad); i <= radius + rad; i++) {
|
||||
for (int j = -(radius + rad); j <= radius + rad; j++) {
|
||||
engine.getMantle().getMantle().deleteChunk(i + cx.getX(), j + cx.getZ());
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = -radius; i <= radius; i++) {
|
||||
for (int j = -radius; j <= radius; j++) {
|
||||
int finalJ = j;
|
||||
int finalI = i;
|
||||
b.queue(() -> plat.injectChunkReplacement(player().getWorld(), finalI + cx.getX(), finalJ + cx.getZ(), (f) -> {
|
||||
synchronized (js) {
|
||||
js.add(f);
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
b.complete();
|
||||
sender().sendMessage(C.GREEN + "Regenerating " + Form.f(js.size()) + " Sections");
|
||||
QueueJob<Runnable> r = new QueueJob<>() {
|
||||
final KList<Future<?>> futures = new KList<>();
|
||||
|
||||
@Override
|
||||
public void execute(Runnable runnable) {
|
||||
futures.add(J.sfut(runnable));
|
||||
|
||||
if (futures.size() > 64) {
|
||||
while (futures.isNotEmpty()) {
|
||||
try {
|
||||
futures.remove(0).get();
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Regenerating";
|
||||
}
|
||||
};
|
||||
r.queue(js);
|
||||
r.execute(sender());
|
||||
} catch (Throwable e) {
|
||||
sender().sendMessage("Unable to parse view-distance");
|
||||
}
|
||||
});
|
||||
} else {
|
||||
sender().sendMessage(C.RED + "You must be in an Iris World to use regen!");
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(description = "Convert objects in the \"convert\" folder")
|
||||
public void convert() {
|
||||
Iris.service(ConversionSVC.class).check(sender());
|
||||
//IrisConverter.convertSchematics(sender());
|
||||
}
|
||||
|
||||
|
||||
@Decree(description = "Execute a script", aliases = "run", origin = DecreeOrigin.PLAYER)
|
||||
public void execute(
|
||||
@Param(description = "The script to run")
|
||||
@@ -218,7 +306,7 @@ public class CommandStudio implements DecreeExecutor {
|
||||
Inventory inv = Bukkit.createInventory(null, 27 * 2);
|
||||
|
||||
try {
|
||||
engine().addItems(true, inv, RNG.r, tables, InventorySlotType.STORAGE, player().getLocation().getBlockX(), player().getLocation().getBlockY(), player().getLocation().getBlockZ(), 1);
|
||||
engine().addItems(true, inv, RNG.r, tables, InventorySlotType.STORAGE, player().getWorld(), player().getLocation().getBlockX(), player().getLocation().getBlockY(), player().getLocation().getBlockZ(), 1);
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
sender().sendMessage(C.RED + "Cannot add items to virtual inventory because of: " + e.getMessage());
|
||||
@@ -241,13 +329,80 @@ public class CommandStudio implements DecreeExecutor {
|
||||
inv.clear();
|
||||
}
|
||||
|
||||
engine().addItems(true, inv, new RNG(RNG.r.imax()), tables, InventorySlotType.STORAGE, player().getLocation().getBlockX(), player().getLocation().getBlockY(), player().getLocation().getBlockZ(), 1);
|
||||
engine().addItems(true, inv, new RNG(RNG.r.imax()), tables, InventorySlotType.STORAGE, player().getWorld(), player().getLocation().getBlockX(), player().getLocation().getBlockY(), player().getLocation().getBlockZ(), 1);
|
||||
}, 0, fast ? 5 : 35));
|
||||
|
||||
sender().sendMessage(C.GREEN + "Opening inventory now!");
|
||||
player().openInventory(inv);
|
||||
}
|
||||
|
||||
|
||||
@Decree(description = "Get all structures in a radius of chunks", aliases = "dist", origin = DecreeOrigin.PLAYER)
|
||||
public void distances(@Param(description = "The radius in chunks") int radius) {
|
||||
var engine = engine();
|
||||
if (engine == null) {
|
||||
sender().sendMessage(C.RED + "Only works in an Iris world!");
|
||||
return;
|
||||
}
|
||||
var sender = sender();
|
||||
int d = radius * 2;
|
||||
KMap<String, KList<Position2>> data = new KMap<>();
|
||||
var multiBurst = new MultiBurst("Distance Sampler", Thread.MIN_PRIORITY);
|
||||
var executor = multiBurst.burst(radius * radius);
|
||||
|
||||
sender.sendMessage(C.GRAY + "Generating data...");
|
||||
var loc = player().getLocation();
|
||||
int totalTasks = d * d;
|
||||
AtomicInteger completedTasks = new AtomicInteger(0);
|
||||
int c = J.ar(() -> {
|
||||
sender.sendProgress((double) completedTasks.get() / totalTasks, "Finding structures");
|
||||
}, 0);
|
||||
|
||||
new Spiraler(d, d, (x, z) -> executor.queue(() -> {
|
||||
var struct = engine.getStructureAt(x, z);
|
||||
if (struct != null) {
|
||||
data.computeIfAbsent(struct.getLoadKey(), (k) -> new KList<>()).add(new Position2(x, z));
|
||||
}
|
||||
completedTasks.incrementAndGet();
|
||||
})).setOffset(loc.getBlockX(), loc.getBlockZ()).drain();
|
||||
|
||||
executor.complete();
|
||||
multiBurst.close();
|
||||
J.car(c);
|
||||
|
||||
for (var key : data.keySet()) {
|
||||
var list = data.get(key);
|
||||
KList<Long> distances = new KList<>(list.size() - 1);
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
var pos = list.get(i);
|
||||
double dist = Integer.MAX_VALUE;
|
||||
for (var p : list) {
|
||||
if (p.equals(pos)) continue;
|
||||
dist = Math.min(dist, Math.sqrt(Math.pow(pos.getX() - p.getX(), 2) + Math.pow(pos.getZ() - p.getZ(), 2)));
|
||||
}
|
||||
if (dist == Integer.MAX_VALUE) continue;
|
||||
distances.add(Math.round(dist * 16));
|
||||
}
|
||||
long[] array = new long[distances.size()];
|
||||
for (int i = 0; i < distances.size(); i++) {
|
||||
array[i] = distances.get(i);
|
||||
}
|
||||
Arrays.sort(array);
|
||||
long min = array.length > 0 ? array[0] : 0;
|
||||
long max = array.length > 0 ? array[array.length - 1] : 0;
|
||||
long sum = Arrays.stream(array).sum();
|
||||
long avg = array.length > 0 ? Math.round(sum / (double) array.length) : 0;
|
||||
String msg = "%s: %s => min: %s/max: %s -> avg: %s".formatted(key, list.size(), min, max, avg);
|
||||
sender.sendMessage(msg);
|
||||
}
|
||||
if (data.isEmpty()) {
|
||||
sender.sendMessage(C.RED + "No data found!");
|
||||
} else {
|
||||
sender.sendMessage(C.GREEN + "Done!");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Decree(description = "Render a world map (External GUI)", aliases = "render")
|
||||
public void map(
|
||||
@Param(name = "world", description = "The world to open the generator for", contextual = true)
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.commands;
|
||||
|
||||
import org.bukkit.World;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.pregenerator.ChunkUpdater;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.util.decree.DecreeExecutor;
|
||||
import com.volmit.iris.util.decree.DecreeOrigin;
|
||||
import com.volmit.iris.util.decree.annotations.Decree;
|
||||
import com.volmit.iris.util.decree.annotations.Param;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
|
||||
@Decree(name = "updater", origin = DecreeOrigin.BOTH, description = "Iris World Updater")
|
||||
public class CommandUpdater implements DecreeExecutor {
|
||||
private ChunkUpdater chunkUpdater;
|
||||
|
||||
@Decree(description = "Updates all chunk in the specified world")
|
||||
public void start(
|
||||
@Param(description = "World to update chunks at", contextual = true)
|
||||
World world
|
||||
) {
|
||||
if (!IrisToolbelt.isIrisWorld(world)) {
|
||||
sender().sendMessage(C.GOLD + "This is not an Iris world");
|
||||
return;
|
||||
}
|
||||
if (chunkUpdater != null) {
|
||||
chunkUpdater.stop();
|
||||
}
|
||||
|
||||
chunkUpdater = new ChunkUpdater(world);
|
||||
if (sender().isPlayer()) {
|
||||
sender().sendMessage(C.GREEN + "Updating " + world.getName() + C.GRAY + " Total chunks: " + Form.f(chunkUpdater.getChunks()));
|
||||
} else {
|
||||
Iris.info(C.GREEN + "Updating " + world.getName() + C.GRAY + " Total chunks: " + Form.f(chunkUpdater.getChunks()));
|
||||
}
|
||||
chunkUpdater.start();
|
||||
}
|
||||
|
||||
@Decree(description = "Pause the updater")
|
||||
public void pause( ) {
|
||||
if (chunkUpdater == null) {
|
||||
sender().sendMessage(C.GOLD + "You cant pause something that doesnt exist?");
|
||||
return;
|
||||
}
|
||||
boolean status = chunkUpdater.pause();
|
||||
if (sender().isPlayer()) {
|
||||
if (status) {
|
||||
sender().sendMessage(C.IRIS + "Paused task for: " + C.GRAY + chunkUpdater.getName());
|
||||
} else {
|
||||
sender().sendMessage(C.IRIS + "Unpause task for: " + C.GRAY + chunkUpdater.getName());
|
||||
}
|
||||
} else {
|
||||
if (status) {
|
||||
Iris.info(C.IRIS + "Paused task for: " + C.GRAY + chunkUpdater.getName());
|
||||
} else {
|
||||
Iris.info(C.IRIS + "Unpause task for: " + C.GRAY + chunkUpdater.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(description = "Stops the updater")
|
||||
public void stop() {
|
||||
if (chunkUpdater == null) {
|
||||
sender().sendMessage(C.GOLD + "You cant stop something that doesnt exist?");
|
||||
return;
|
||||
}
|
||||
if (sender().isPlayer()) {
|
||||
sender().sendMessage("Stopping Updater for: " + C.GRAY + chunkUpdater.getName());
|
||||
} else {
|
||||
Iris.info("Stopping Updater for: " + C.GRAY + chunkUpdater.getName());
|
||||
}
|
||||
chunkUpdater.stop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,9 @@ import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.edit.BlockSignal;
|
||||
import com.volmit.iris.core.nms.INMS;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.object.IrisBiome;
|
||||
import com.volmit.iris.engine.object.IrisRegion;
|
||||
import com.volmit.iris.util.data.B;
|
||||
import com.volmit.iris.util.decree.DecreeExecutor;
|
||||
import com.volmit.iris.util.decree.DecreeOrigin;
|
||||
@@ -37,6 +39,7 @@ import org.bukkit.Material;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
@Decree(name = "what", origin = DecreeOrigin.PLAYER, studio = true, description = "Iris What?")
|
||||
@@ -82,6 +85,19 @@ public class CommandWhat implements DecreeExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(description = "What region am i in?", origin = DecreeOrigin.PLAYER)
|
||||
public void region() {
|
||||
try {
|
||||
Chunk chunk = world().getChunkAt(player().getLocation().getBlockZ() / 16, player().getLocation().getBlockZ() / 16);
|
||||
IrisRegion r = engine().getRegion(chunk);
|
||||
sender().sendMessage("IRegion: " + r.getLoadKey() + " (" + r.getName() + ")");
|
||||
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
sender().sendMessage(C.IRIS + "Iris worlds only.");
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(description = "What block am i looking at?", origin = DecreeOrigin.PLAYER)
|
||||
public void block() {
|
||||
BlockData bd;
|
||||
@@ -147,7 +163,7 @@ public class CommandWhat implements DecreeExecutor {
|
||||
|
||||
sender().sendMessage("Found " + v.get() + " Nearby Markers (" + marker + ")");
|
||||
} else {
|
||||
sender().sendMessage("Iris worlds only.");
|
||||
sender().sendMessage(C.IRIS + "Iris worlds only.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,250 +0,0 @@
|
||||
/*
|
||||
* 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.service.StudioSVC;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.engine.object.IrisDimension;
|
||||
import com.volmit.iris.engine.object.IrisWorld;
|
||||
import com.volmit.iris.engine.platform.BukkitChunkGenerator;
|
||||
import com.volmit.iris.engine.platform.DummyChunkGenerator;
|
||||
import com.volmit.iris.util.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.plugin.VolmitSender;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Difficulty;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.WorldCreator;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static com.volmit.iris.Iris.service;
|
||||
|
||||
// Not done yet but works
|
||||
@Decree(name = "worldmanager", origin = DecreeOrigin.PLAYER, description = "Iris World Manager", aliases = {"manager"})
|
||||
public class CommandWorldManager implements DecreeExecutor {
|
||||
public Difficulty difficulty = Difficulty.NORMAL;
|
||||
String WorldToLoad;
|
||||
String WorldEngine;
|
||||
String worldNameToCheck = "YourWorldName";
|
||||
VolmitSender sender = Iris.getSender();
|
||||
@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(", ", Bukkit.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;
|
||||
}
|
||||
WorldToLoad = world;
|
||||
File BUKKIT_YML = new File("bukkit.yml");
|
||||
String pathtodim = world + "\\iris\\pack\\dimensions\\";
|
||||
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();
|
||||
}
|
||||
}
|
||||
checkForBukkitWorlds();
|
||||
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(", ", Bukkit.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() {
|
||||
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(WorldToLoad);
|
||||
|
||||
for (String s : section.getKeys(false)) {
|
||||
if (!worldsToLoad.contains(s)) {
|
||||
continue;
|
||||
}
|
||||
ConfigurationSection entry = section.getConfigurationSection(s);
|
||||
if (!entry.contains("generator", true)) {
|
||||
continue;
|
||||
}
|
||||
String generator = entry.getString("generator");
|
||||
if (generator.startsWith("Iris:")) {
|
||||
generator = generator.split("\\Q:\\E")[1];
|
||||
} else if (generator.equalsIgnoreCase("Iris")) {
|
||||
generator = IrisSettings.get().getGenerator().getDefaultWorldType();
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
Iris.info("2 World: %s | Generator: %s", s, generator);
|
||||
if (Bukkit.getWorlds().stream().anyMatch(w -> w.getName().equals(s))) {
|
||||
continue;
|
||||
}
|
||||
Iris.info(C.LIGHT_PURPLE + "Preparing Spawn for " + s + "' using Iris:" + generator + "...");
|
||||
new WorldCreator(s)
|
||||
.generator(getDefaultWorldGenerator(s, generator))
|
||||
.environment(IrisData.loadAnyDimension(generator).getEnvironment())
|
||||
.createWorld();
|
||||
Iris.info(C.LIGHT_PURPLE + "Loaded " + s + "!");
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
public ChunkGenerator getDefaultWorldGenerator(String worldName, String id) {
|
||||
Iris.debug("Default World Generator Called for " + worldName + " using ID: " + id);
|
||||
if (worldName.equals("test")) {
|
||||
try {
|
||||
throw new RuntimeException();
|
||||
} catch (Throwable e) {
|
||||
Iris.info(e.getStackTrace()[1].getClassName());
|
||||
if (e.getStackTrace()[1].getClassName().contains("com.onarandombox.MultiverseCore")) {
|
||||
Iris.debug("MVC Test detected, Quick! Send them the dummy!");
|
||||
return new DummyChunkGenerator();
|
||||
}
|
||||
}
|
||||
}
|
||||
IrisDimension dim;
|
||||
if (id == null || id.isEmpty()) {
|
||||
dim = IrisData.loadAnyDimension(IrisSettings.get().getGenerator().getDefaultWorldType());
|
||||
} else {
|
||||
dim = IrisData.loadAnyDimension(id);
|
||||
}
|
||||
Iris.debug("Generator ID: " + id + " requested by bukkit/plugin");
|
||||
|
||||
if (dim == null) {
|
||||
Iris.warn("Unable to find dimension type " + id + " Looking for online packs...");
|
||||
|
||||
service(StudioSVC.class).downloadSearch(new VolmitSender(Bukkit.getConsoleSender()), id, true);
|
||||
dim = IrisData.loadAnyDimension(id);
|
||||
|
||||
if (dim == null) {
|
||||
throw new RuntimeException("Can't find dimension " + id + "!");
|
||||
} else {
|
||||
Iris.info("Resolved missing dimension, proceeding with generation.");
|
||||
}
|
||||
}
|
||||
Iris.debug("Assuming IrisDimension: " + dim.getName());
|
||||
IrisWorld w = IrisWorld.builder()
|
||||
.name(worldName)
|
||||
.seed(1337)
|
||||
.environment(dim.getEnvironment())
|
||||
.worldFolder(new File(Bukkit.getWorldContainer(), worldName))
|
||||
.minHeight(dim.getMinHeight())
|
||||
.maxHeight(dim.getMaxHeight())
|
||||
.build();
|
||||
Iris.debug("Generator Config: " + w.toString());
|
||||
File ff = new File(w.worldFolder(), "iris/pack");
|
||||
if (!ff.exists() || ff.listFiles().length == 0) {
|
||||
ff.mkdirs();
|
||||
service(StudioSVC.class).installIntoWorld(sender, dim.getLoadKey(), ff.getParentFile());
|
||||
}
|
||||
return new BukkitChunkGenerator(w, false, ff, dim.getLoadKey());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
package com.volmit.iris.core.gui;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.events.IrisEngineHotloadEvent;
|
||||
import com.volmit.iris.engine.object.NoiseStyle;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
@@ -61,7 +62,7 @@ public class NoiseExplorerGUI extends JPanel implements MouseWheelListener, List
|
||||
@SuppressWarnings("CanBeFinal")
|
||||
RollingSequence r = new RollingSequence(20);
|
||||
@SuppressWarnings("CanBeFinal")
|
||||
boolean colorMode = true;
|
||||
boolean colorMode = IrisSettings.get().getGui().colorMode;
|
||||
double scale = 1;
|
||||
CNG cng = NoiseStyle.STATIC.create(new RNG(RNG.r.nextLong()));
|
||||
@SuppressWarnings("CanBeFinal")
|
||||
@@ -275,6 +276,9 @@ public class NoiseExplorerGUI extends JPanel implements MouseWheelListener, List
|
||||
|
||||
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), (float) (n * n * n * n * n * n), (float) n) : Color.getHSBColor(0f, 0f, (float) n);
|
||||
//Color color = colorMode ? Color.getHSBColor((float) n, (float) (n * n * n * n * n * n), (float) n) : Color.getHSBColor(0f, 0f, (float) n);
|
||||
|
||||
int rgb = color.getRGB();
|
||||
img.setRGB(xx, z, rgb);
|
||||
} catch (Throwable ignored) {
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.volmit.iris.core.pregenerator.IrisPregenerator;
|
||||
import com.volmit.iris.core.pregenerator.PregenListener;
|
||||
import com.volmit.iris.core.pregenerator.PregenTask;
|
||||
import com.volmit.iris.core.pregenerator.PregeneratorMethod;
|
||||
import com.volmit.iris.core.tools.IrisPackBenchmarking;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
@@ -44,6 +45,8 @@ import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import static com.volmit.iris.core.tools.IrisPackBenchmarking.benchmarkInProgress;
|
||||
|
||||
public class PregeneratorJob implements PregenListener {
|
||||
private static final Color COLOR_EXISTS = parseColor("#4d7d5b");
|
||||
private static final Color COLOR_BLACK = parseColor("#4d7d5b");
|
||||
@@ -86,11 +89,16 @@ public class PregeneratorJob implements PregenListener {
|
||||
max.setZ(Math.max((zz << 5) + 31, max.getZ()));
|
||||
});
|
||||
|
||||
if (IrisSettings.get().getGui().isUseServerLaunchedGuis()) {
|
||||
if (IrisSettings.get().getGui().isUseServerLaunchedGuis() && task.isGui()) {
|
||||
open();
|
||||
}
|
||||
|
||||
J.a(this.pregenerator::start, 20);
|
||||
var t = new Thread(() -> {
|
||||
J.sleep(1000);
|
||||
this.pregenerator.start();
|
||||
}, "Iris Pregenerator");
|
||||
t.setPriority(Thread.MIN_PRIORITY);
|
||||
t.start();
|
||||
}
|
||||
|
||||
public static boolean shutdownInstance() {
|
||||
|
||||
@@ -55,10 +55,10 @@ public class IrisRenderer {
|
||||
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) {
|
||||
if (g.getMax(renderer) <= 0) {
|
||||
// Max is below water level, so it is most likely an ocean biome
|
||||
c = Color.BLUE;
|
||||
} else if (g.getMin() < 0) {
|
||||
} else if (g.getMin(renderer) < 0) {
|
||||
// Min is below water level, but max is not, so it is most likely a shore biome
|
||||
c = Color.YELLOW;
|
||||
} else {
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
package com.volmit.iris.core.link;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.reflect.WrappedField;
|
||||
import com.willfp.ecoitems.items.EcoItem;
|
||||
import com.willfp.ecoitems.items.EcoItems;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.MissingResourceException;
|
||||
|
||||
public class EcoItemsDataProvider extends ExternalDataProvider {
|
||||
private WrappedField<EcoItem, ItemStack> itemStack;
|
||||
private WrappedField<EcoItem, NamespacedKey> id;
|
||||
|
||||
public EcoItemsDataProvider() {
|
||||
super("EcoItems");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
Iris.info("Setting up EcoItems Link...");
|
||||
itemStack = new WrappedField<>(EcoItem.class, "_itemStack");
|
||||
if (this.itemStack.hasFailed()) {
|
||||
Iris.error("Failed to set up EcoItems Link: Unable to fetch ItemStack field!");
|
||||
}
|
||||
id = new WrappedField<>(EcoItem.class, "id");
|
||||
if (this.id.hasFailed()) {
|
||||
Iris.error("Failed to set up EcoItems Link: Unable to fetch id field!");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockData getBlockData(Identifier blockId, KMap<String, String> state) throws MissingResourceException {
|
||||
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getItemStack(Identifier itemId, KMap<String, Object> customNbt) throws MissingResourceException {
|
||||
EcoItem item = EcoItems.INSTANCE.getByID(itemId.key());
|
||||
if (item == null) throw new MissingResourceException("Failed to find Item!", itemId.namespace(), itemId.key());
|
||||
return itemStack.get(item).clone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier[] getBlockTypes() {
|
||||
return new Identifier[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier[] getItemTypes() {
|
||||
KList<Identifier> names = new KList<>();
|
||||
for (EcoItem item : EcoItems.INSTANCE.values()) {
|
||||
try {
|
||||
Identifier key = Identifier.fromNamespacedKey(id.get(item));
|
||||
if (getItemStack(key) != null)
|
||||
names.add(key);
|
||||
} catch (MissingResourceException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
return names.toArray(new Identifier[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidProvider(Identifier id, boolean isItem) {
|
||||
return id.namespace().equalsIgnoreCase("ecoitems") && isItem;
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ 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;
|
||||
|
||||
@@ -20,12 +21,12 @@ public class ExecutableItemsDataProvider extends ExternalDataProvider {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockData getBlockData(Identifier blockId) throws MissingResourceException {
|
||||
public BlockData getBlockData(Identifier blockId, KMap<String, String> state) throws MissingResourceException {
|
||||
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getItemStack(Identifier itemId) throws MissingResourceException {
|
||||
public ItemStack getItemStack(Identifier itemId, KMap<String, Object> customNbt) throws MissingResourceException {
|
||||
return ExecutableItemsAPI.getExecutableItemsManager().getExecutableItem(itemId.key())
|
||||
.map(item -> item.buildItem(1, Optional.empty()))
|
||||
.orElseThrow(() -> new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key()));
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
package com.volmit.iris.core.link;
|
||||
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
@@ -25,9 +28,19 @@ public abstract class ExternalDataProvider {
|
||||
|
||||
public abstract void init();
|
||||
|
||||
public abstract BlockData getBlockData(Identifier blockId) throws MissingResourceException;
|
||||
public BlockData getBlockData(Identifier blockId) throws MissingResourceException {
|
||||
return getBlockData(blockId, new KMap<>());
|
||||
}
|
||||
|
||||
public abstract ItemStack getItemStack(Identifier itemId) throws MissingResourceException;
|
||||
public abstract BlockData getBlockData(Identifier blockId, KMap<String, String> state) throws MissingResourceException;
|
||||
|
||||
public ItemStack getItemStack(Identifier itemId) throws MissingResourceException {
|
||||
return getItemStack(itemId, new KMap<>());
|
||||
}
|
||||
|
||||
public abstract ItemStack getItemStack(Identifier itemId, KMap<String, Object> customNbt) throws MissingResourceException;
|
||||
|
||||
public void processUpdate(Engine engine, Block block, Identifier blockId) {}
|
||||
|
||||
public abstract Identifier[] getBlockTypes();
|
||||
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
package com.volmit.iris.core.link;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.service.ExternalDataSVC;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.data.IrisBlockData;
|
||||
import com.volmit.iris.util.reflect.WrappedField;
|
||||
import com.volmit.iris.util.reflect.WrappedReturningMethod;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.block.data.type.Leaves;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class HMCLeavesDataProvider extends ExternalDataProvider {
|
||||
private Object apiInstance;
|
||||
private WrappedReturningMethod<Object, Material> worldBlockType;
|
||||
private WrappedReturningMethod<Object, Boolean> setCustomBlock;
|
||||
private Map<String, Object> blockDataMap = Map.of();
|
||||
private Map<String, Supplier<ItemStack>> itemDataField = Map.of();
|
||||
|
||||
public HMCLeavesDataProvider() {
|
||||
super("HMCLeaves");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPluginId() {
|
||||
return "HMCLeaves";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
try {
|
||||
worldBlockType = new WrappedReturningMethod<>((Class<Object>) Class.forName("io.github.fisher2911.hmcleaves.data.BlockData"), "worldBlockType");
|
||||
apiInstance = getApiInstance(Class.forName("io.github.fisher2911.hmcleaves.api.HMCLeavesAPI"));
|
||||
setCustomBlock = new WrappedReturningMethod<>((Class<Object>) apiInstance.getClass(), "setCustomBlock", Location.class, String.class, boolean.class);
|
||||
Object config = getLeavesConfig(apiInstance.getClass());
|
||||
blockDataMap = getMap(config, "blockDataMap");
|
||||
itemDataField = getMap(config, "itemSupplierMap");
|
||||
} catch (Throwable e) {
|
||||
Iris.error("Failed to initialize HMCLeavesDataProvider: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockData getBlockData(Identifier blockId, KMap<String, String> state) throws MissingResourceException {
|
||||
Object o = blockDataMap.get(blockId.key());
|
||||
if (o == null)
|
||||
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
|
||||
Material material = worldBlockType.invoke(o, new Object[0]);
|
||||
if (material == null)
|
||||
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
|
||||
BlockData blockData = Bukkit.createBlockData(material);
|
||||
if (IrisSettings.get().getGenerator().preventLeafDecay && blockData instanceof Leaves leaves)
|
||||
leaves.setPersistent(true);
|
||||
return new IrisBlockData(blockData, ExternalDataSVC.buildState(blockId, state));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getItemStack(Identifier itemId, KMap<String, Object> customNbt) throws MissingResourceException {
|
||||
if (!itemDataField.containsKey(itemId.key()))
|
||||
throw new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key());
|
||||
return itemDataField.get(itemId.key()).get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processUpdate(Engine engine, Block block, Identifier blockId) {
|
||||
var pair = ExternalDataSVC.parseState(blockId);
|
||||
blockId = pair.getA();
|
||||
Boolean result = setCustomBlock.invoke(apiInstance, new Object[]{block.getLocation(), blockId.key(), false});
|
||||
if (result == null || !result)
|
||||
Iris.warn("Failed to set custom block! " + blockId.key() + " " + block.getX() + " " + block.getY() + " " + block.getZ());
|
||||
else if (IrisSettings.get().getGenerator().preventLeafDecay) {
|
||||
BlockData blockData = block.getBlockData();
|
||||
if (blockData instanceof Leaves leaves)
|
||||
leaves.setPersistent(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier[] getBlockTypes() {
|
||||
KList<Identifier> names = new KList<>();
|
||||
for (String name : blockDataMap.keySet()) {
|
||||
try {
|
||||
Identifier key = new Identifier("hmcleaves", name);
|
||||
if (getBlockData(key) != null)
|
||||
names.add(key);
|
||||
} catch (MissingResourceException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
return names.toArray(new Identifier[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier[] getItemTypes() {
|
||||
KList<Identifier> names = new KList<>();
|
||||
for (String name : itemDataField.keySet()) {
|
||||
try {
|
||||
Identifier key = new Identifier("hmcleaves", name);
|
||||
if (getItemStack(key) != null)
|
||||
names.add(key);
|
||||
} catch (MissingResourceException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
return names.toArray(new Identifier[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidProvider(Identifier id, boolean isItem) {
|
||||
return (isItem ? itemDataField.keySet() : blockDataMap.keySet()).contains(id.key());
|
||||
}
|
||||
|
||||
private <C, T> Map<String, T> getMap(C config, String name) {
|
||||
WrappedField<C, Map<String, T>> field = new WrappedField<>((Class<C>) config.getClass(), name);
|
||||
return field.get(config);
|
||||
}
|
||||
|
||||
private <A> A getApiInstance(Class<A> apiClass) {
|
||||
WrappedReturningMethod<A, A> instance = new WrappedReturningMethod<>(apiClass, "getInstance");
|
||||
return instance.invoke();
|
||||
}
|
||||
|
||||
private <A, C> C getLeavesConfig(Class<A> apiClass) {
|
||||
WrappedReturningMethod<A, A> instance = new WrappedReturningMethod<>(apiClass, "getInstance");
|
||||
WrappedField<A, C> config = new WrappedField<>(apiClass, "config");
|
||||
return config.get(instance.invoke());
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,10 @@ 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) {
|
||||
|
||||
@@ -2,6 +2,7 @@ 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;
|
||||
@@ -32,12 +33,12 @@ public class ItemAdderDataProvider extends ExternalDataProvider {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockData getBlockData(Identifier blockId) throws MissingResourceException {
|
||||
public BlockData getBlockData(Identifier blockId, KMap<String, String> state) throws MissingResourceException {
|
||||
return CustomBlock.getBaseBlockData(blockId.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getItemStack(Identifier itemId) throws MissingResourceException {
|
||||
public ItemStack getItemStack(Identifier itemId, KMap<String, Object> customNbt) throws MissingResourceException {
|
||||
CustomStack stack = CustomStack.getInstance(itemId.toString());
|
||||
if (stack == null) {
|
||||
throw new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key());
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
package com.volmit.iris.core.link;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import net.Indyuce.mmoitems.MMOItems;
|
||||
import net.Indyuce.mmoitems.api.ItemTier;
|
||||
import net.Indyuce.mmoitems.api.Type;
|
||||
import net.Indyuce.mmoitems.api.block.CustomBlock;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
public class MMOItemsDataProvider extends ExternalDataProvider {
|
||||
|
||||
public MMOItemsDataProvider() {
|
||||
super("MMOItems");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
Iris.info("Setting up MMOItems Link...");
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockData getBlockData(Identifier blockId, KMap<String, String> state) throws MissingResourceException {
|
||||
int id = -1;
|
||||
try {
|
||||
id = Integer.parseInt(blockId.key());
|
||||
} catch (NumberFormatException ignored) {}
|
||||
CustomBlock block = api().getCustomBlocks().getBlock(id);
|
||||
if (block == null) throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
|
||||
return block.getState().getBlockData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getItemStack(Identifier itemId, KMap<String, Object> customNbt) throws MissingResourceException {
|
||||
String[] parts = itemId.namespace().split("_", 2);
|
||||
if (parts.length != 2)
|
||||
throw new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key());
|
||||
CompletableFuture<ItemStack> future = new CompletableFuture<>();
|
||||
Runnable run = () -> {
|
||||
try {
|
||||
var type = api().getTypes().get(parts[1]);
|
||||
int level = -1;
|
||||
ItemTier tier = null;
|
||||
|
||||
if (customNbt != null) {
|
||||
level = (int) customNbt.getOrDefault("level", -1);
|
||||
tier = api().getTiers().get(String.valueOf(customNbt.get("tier")));
|
||||
}
|
||||
|
||||
ItemStack itemStack;
|
||||
if (type == null) {
|
||||
future.complete(null);
|
||||
return;
|
||||
}
|
||||
|
||||
if (level != -1 && tier != null) {
|
||||
itemStack = api().getItem(type, itemId.key(), level, tier);
|
||||
} else {
|
||||
itemStack = api().getItem(type, itemId.key());
|
||||
}
|
||||
future.complete(itemStack);
|
||||
} catch (Throwable e) {
|
||||
future.completeExceptionally(e);
|
||||
}
|
||||
};
|
||||
if (Bukkit.isPrimaryThread()) run.run();
|
||||
else J.s(run);
|
||||
ItemStack item = null;
|
||||
try {
|
||||
item = future.get();
|
||||
} catch (InterruptedException | ExecutionException ignored) {}
|
||||
if (item == null)
|
||||
throw new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key());
|
||||
return item;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier[] getBlockTypes() {
|
||||
KList<Identifier> names = new KList<>();
|
||||
for (Integer id : api().getCustomBlocks().getBlockIds()) {
|
||||
try {
|
||||
Identifier key = new Identifier("mmoitems", String.valueOf(id));
|
||||
if (getBlockData(key) != null)
|
||||
names.add(key);
|
||||
} catch (MissingResourceException ignored) {
|
||||
}
|
||||
}
|
||||
return names.toArray(new Identifier[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier[] getItemTypes() {
|
||||
KList<Identifier> names = new KList<>();
|
||||
Runnable run = () -> {
|
||||
for (Type type : api().getTypes().getAll()) {
|
||||
for (String name : api().getTemplates().getTemplateNames(type)) {
|
||||
try {
|
||||
Identifier key = new Identifier("mmoitems_" + type.getId(), name);
|
||||
if (getItemStack(key) != null)
|
||||
names.add(key);
|
||||
} catch (MissingResourceException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
if (Bukkit.isPrimaryThread()) run.run();
|
||||
else {
|
||||
try {
|
||||
J.sfut(run).get();
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
Iris.error("Failed getting MMOItems item types!");
|
||||
Iris.reportError(e);
|
||||
}
|
||||
}
|
||||
return names.toArray(new Identifier[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidProvider(Identifier id, boolean isItem) {
|
||||
return isItem ? id.namespace().split("_", 2).length == 2 : id.namespace().equals("mmoitems");
|
||||
}
|
||||
|
||||
private MMOItems api() {
|
||||
return MMOItems.plugin;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.link;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.nms.INMS;
|
||||
import com.volmit.iris.core.nms.container.BiomeColor;
|
||||
import com.volmit.iris.core.service.ExternalDataSVC;
|
||||
import com.volmit.iris.engine.data.cache.Cache;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.data.B;
|
||||
import com.volmit.iris.util.data.IrisBlockData;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import io.lumine.mythic.bukkit.BukkitAdapter;
|
||||
import io.lumine.mythic.bukkit.utils.serialize.Chroma;
|
||||
import io.lumine.mythiccrucible.MythicCrucible;
|
||||
import io.lumine.mythiccrucible.items.CrucibleItem;
|
||||
import io.lumine.mythiccrucible.items.ItemManager;
|
||||
import io.lumine.mythiccrucible.items.blocks.CustomBlockItemContext;
|
||||
import io.lumine.mythiccrucible.items.furniture.FurnitureItemContext;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import 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!");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockData getBlockData(Identifier blockId, KMap<String, String> state) throws MissingResourceException {
|
||||
CrucibleItem crucibleItem = this.itemManager.getItem(blockId.key())
|
||||
.orElseThrow(() -> new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key()));
|
||||
CustomBlockItemContext blockItemContext = crucibleItem.getBlockData();
|
||||
FurnitureItemContext furnitureItemContext = crucibleItem.getFurnitureData();
|
||||
if (furnitureItemContext != null) {
|
||||
return new IrisBlockData(B.getAir(), ExternalDataSVC.buildState(blockId, state));
|
||||
} else if (blockItemContext != null) {
|
||||
return blockItemContext.getBlockData();
|
||||
}
|
||||
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getItemStack(Identifier itemId, 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));
|
||||
}
|
||||
|
||||
@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]);
|
||||
}
|
||||
|
||||
@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(Engine engine, Block block, 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(Identifier key, boolean isItem) {
|
||||
return key.namespace().equalsIgnoreCase("crucible");
|
||||
}
|
||||
}
|
||||
@@ -19,25 +19,45 @@
|
||||
package com.volmit.iris.core.link;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.nms.INMS;
|
||||
import com.volmit.iris.core.nms.container.BiomeColor;
|
||||
import com.volmit.iris.core.service.ExternalDataSVC;
|
||||
import com.volmit.iris.engine.data.cache.Cache;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.data.B;
|
||||
import com.volmit.iris.util.data.IrisBlockData;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import com.volmit.iris.util.reflect.WrappedField;
|
||||
import io.th0rgal.oraxen.api.OraxenItems;
|
||||
import io.th0rgal.oraxen.items.ItemBuilder;
|
||||
import io.th0rgal.oraxen.mechanics.Mechanic;
|
||||
import io.th0rgal.oraxen.mechanics.MechanicFactory;
|
||||
import io.th0rgal.oraxen.mechanics.MechanicsManager;
|
||||
import io.th0rgal.oraxen.mechanics.provided.gameplay.block.BlockMechanic;
|
||||
import io.th0rgal.oraxen.mechanics.provided.gameplay.block.BlockMechanicFactory;
|
||||
import io.th0rgal.oraxen.mechanics.provided.gameplay.furniture.FurnitureFactory;
|
||||
import io.th0rgal.oraxen.mechanics.provided.gameplay.furniture.FurnitureMechanic;
|
||||
import io.th0rgal.oraxen.mechanics.provided.gameplay.noteblock.NoteBlockMechanicFactory;
|
||||
import io.th0rgal.oraxen.mechanics.provided.gameplay.stringblock.StringBlockMechanicFactory;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Color;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.block.data.MultipleFacing;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.ItemDisplay;
|
||||
import org.bukkit.entity.ItemFrame;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.PotionMeta;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class OraxenDataProvider extends ExternalDataProvider {
|
||||
|
||||
@@ -59,7 +79,7 @@ public class OraxenDataProvider extends ExternalDataProvider {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockData getBlockData(Identifier blockId) throws MissingResourceException {
|
||||
public BlockData getBlockData(Identifier blockId, KMap<String, String> state) throws MissingResourceException {
|
||||
MechanicFactory factory = getFactory(blockId);
|
||||
if (factory instanceof NoteBlockMechanicFactory f)
|
||||
return f.createNoteBlockData(blockId.key());
|
||||
@@ -69,16 +89,75 @@ public class OraxenDataProvider extends ExternalDataProvider {
|
||||
return newBlockData;
|
||||
} else if (factory instanceof StringBlockMechanicFactory f) {
|
||||
return f.createTripwireData(blockId.key());
|
||||
} else if (factory instanceof FurnitureFactory) {
|
||||
return new IrisBlockData(B.getAir(), ExternalDataSVC.buildState(blockId, state));
|
||||
} else
|
||||
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getItemStack(Identifier itemId) throws MissingResourceException {
|
||||
public ItemStack getItemStack(Identifier itemId, KMap<String, Object> customNbt) throws MissingResourceException {
|
||||
Optional<ItemBuilder> opt = OraxenItems.getOptionalItemById(itemId.key());
|
||||
return opt.orElseThrow(() -> new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key())).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processUpdate(Engine engine, Block block, Identifier blockId) {
|
||||
var pair = ExternalDataSVC.parseState(blockId);
|
||||
var state = pair.getB();
|
||||
blockId = pair.getA();
|
||||
Mechanic mechanic = getFactory(blockId).getMechanic(blockId.key());
|
||||
if (mechanic instanceof FurnitureMechanic f) {
|
||||
float yaw = 0;
|
||||
BlockFace face = BlockFace.NORTH;
|
||||
|
||||
long seed = engine.getSeedManager().getSeed() + Cache.key(block.getX(), block.getZ()) + block.getY();
|
||||
RNG rng = new RNG(seed);
|
||||
if ("true".equals(state.get("randomYaw"))) {
|
||||
yaw = rng.f(0, 360);
|
||||
} else if (state.containsKey("yaw")) {
|
||||
yaw = Float.parseFloat(state.get("yaw"));
|
||||
}
|
||||
if ("true".equals(state.get("randomFace"))) {
|
||||
BlockFace[] faces = BlockFace.values();
|
||||
face = faces[rng.i(0, faces.length - 1)];
|
||||
} else if (state.containsKey("face")) {
|
||||
face = BlockFace.valueOf(state.get("face").toUpperCase());
|
||||
}
|
||||
if (face == BlockFace.SELF) {
|
||||
face = BlockFace.NORTH;
|
||||
}
|
||||
ItemStack itemStack = OraxenItems.getItemById(f.getItemID()).build();
|
||||
Entity entity = f.place(block.getLocation(), itemStack, yaw, face, false);
|
||||
|
||||
Consumer<ItemStack> setter = null;
|
||||
if (entity instanceof ItemFrame frame) {
|
||||
itemStack = frame.getItem();
|
||||
setter = frame::setItem;
|
||||
} else if (entity instanceof ItemDisplay display) {
|
||||
itemStack = display.getItemStack();
|
||||
setter = display::setItemStack;
|
||||
}
|
||||
if (setter == null || itemStack == null) return;
|
||||
|
||||
BiomeColor type = null;
|
||||
try {
|
||||
type = BiomeColor.valueOf(state.get("matchBiome").toUpperCase());
|
||||
} catch (NullPointerException | IllegalArgumentException ignored) {}
|
||||
|
||||
if (type != null) {
|
||||
var biomeColor = INMS.get().getBiomeColor(block.getLocation(), type);
|
||||
if (biomeColor == null) return;
|
||||
var potionColor = Color.fromARGB(biomeColor.getAlpha(), biomeColor.getRed(), biomeColor.getGreen(), biomeColor.getBlue());
|
||||
if (itemStack.getItemMeta() instanceof PotionMeta meta) {
|
||||
meta.setColor(potionColor);
|
||||
itemStack.setItemMeta(meta);
|
||||
}
|
||||
}
|
||||
setter.accept(itemStack);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier[] getBlockTypes() {
|
||||
KList<Identifier> names = new KList<>();
|
||||
|
||||
@@ -1,31 +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);
|
||||
Object player = Class.forName("com.sk89q.worldedit.bukkit.BukkitAdapter").getDeclaredMethod("adapt", Player.class).invoke(null, p);
|
||||
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);
|
||||
Object world = Class.forName("com.sk89q.worldedit.bukkit.BukkitAdapter").getDeclaredMethod("adapt", World.class).invoke(null, p.getWorld());
|
||||
Object region = localSession.getClass().getDeclaredMethod("getSelection", world.getClass()).invoke(localSession, world);
|
||||
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("getX").invoke(min),
|
||||
(int) min.getClass().getDeclaredMethod("getY").invoke(min),
|
||||
(int) min.getClass().getDeclaredMethod("getZ").invoke(min),
|
||||
(int) min.getClass().getDeclaredMethod("getX").invoke(max),
|
||||
(int) min.getClass().getDeclaredMethod("getY").invoke(max),
|
||||
(int) min.getClass().getDeclaredMethod("getZ").invoke(max)
|
||||
(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 ignored) {
|
||||
|
||||
} 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"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,10 +50,10 @@ public class ObjectResourceLoader extends ResourceLoader<IrisObject> {
|
||||
try {
|
||||
PrecisionStopwatch p = PrecisionStopwatch.start();
|
||||
IrisObject t = new IrisObject(0, 0, 0);
|
||||
t.read(j);
|
||||
t.setLoadKey(name);
|
||||
t.setLoader(manager);
|
||||
t.setLoadFile(j);
|
||||
t.read(j);
|
||||
logLoad(j, t);
|
||||
tlt.addAndGet(p.getMilliseconds());
|
||||
return t;
|
||||
|
||||
@@ -40,6 +40,8 @@ import com.volmit.iris.util.scheduling.ChronoLatch;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.Locale;
|
||||
@@ -52,6 +54,8 @@ import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(exclude = "manager")
|
||||
@ToString(exclude = "manager")
|
||||
public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
||||
public static final AtomicDouble tlt = new AtomicDouble(0);
|
||||
private static final int CACHE_SIZE = 100000;
|
||||
@@ -358,7 +362,12 @@ public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
||||
if (folderCache.get() == null) {
|
||||
KList<File> fc = new KList<>();
|
||||
|
||||
for (File i : root.listFiles()) {
|
||||
File[] files = root.listFiles();
|
||||
if (files == null) {
|
||||
throw new IllegalStateException("Failed to list files in " + root);
|
||||
}
|
||||
|
||||
for (File i : files) {
|
||||
if (i.isDirectory()) {
|
||||
if (i.getName().equals(folderName)) {
|
||||
fc.add(i);
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.volmit.iris.core.nms;
|
||||
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
|
||||
public interface IMemoryWorld extends Listener, AutoCloseable {
|
||||
|
||||
World getBukkit();
|
||||
|
||||
Chunk getChunk(int x, int z);
|
||||
|
||||
ChunkGenerator.ChunkData getChunkData(int x, int z);
|
||||
}
|
||||
@@ -23,7 +23,15 @@ import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.nms.v1X.NMSBinding1X;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
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"
|
||||
);
|
||||
//@done
|
||||
private static final INMSBinding binding = bind();
|
||||
|
||||
@@ -37,7 +45,12 @@ public class INMS {
|
||||
}
|
||||
|
||||
try {
|
||||
return Bukkit.getServer().getClass().getCanonicalName().split("\\Q.\\E")[3];
|
||||
String name = Bukkit.getServer().getClass().getCanonicalName();
|
||||
if (name.equals("org.bukkit.craftbukkit.CraftServer")) {
|
||||
return REVISION.getOrDefault(Bukkit.getServer().getBukkitVersion().split("-")[0], "BUKKIT");
|
||||
} else {
|
||||
return name.split("\\Q.\\E")[3];
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
Iris.error("Failed to determine server nms version!");
|
||||
|
||||
@@ -18,28 +18,40 @@
|
||||
|
||||
package com.volmit.iris.core.nms;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.nms.container.BiomeColor;
|
||||
import com.volmit.iris.core.nms.datapack.DataVersion;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.mantle.Mantle;
|
||||
import com.volmit.iris.util.math.Vector3d;
|
||||
import com.volmit.iris.util.nbt.mca.palette.MCABiomeContainer;
|
||||
import com.volmit.iris.util.nbt.mca.palette.MCAPaletteAccess;
|
||||
import com.volmit.iris.util.nbt.tag.CompoundTag;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.WorldCreator;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.entity.Dolphin;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
import org.bukkit.generator.structure.Structure;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.Color;
|
||||
import java.io.IOException;
|
||||
|
||||
public interface INMSBinding {
|
||||
boolean hasTile(Material material);
|
||||
|
||||
boolean hasTile(Location l);
|
||||
|
||||
CompoundTag serializeTile(Location location);
|
||||
KMap<String, Object> serializeTile(Location location);
|
||||
|
||||
void deserializeTile(CompoundTag s, Location newPosition);
|
||||
void deserializeTile(KMap<String, Object> s, Location newPosition);
|
||||
|
||||
CompoundTag serializeEntity(Entity location);
|
||||
|
||||
@@ -71,6 +83,8 @@ public interface INMSBinding {
|
||||
|
||||
Object getBiomeBase(Object registry, Biome biome);
|
||||
|
||||
KList<Biome> getBiomes();
|
||||
|
||||
boolean isBukkit();
|
||||
|
||||
int getBiomeId(Biome biome);
|
||||
@@ -85,6 +99,10 @@ public interface INMSBinding {
|
||||
|
||||
int countCustomBiomes();
|
||||
|
||||
default boolean setBlock(World world, int x, int y, int z, BlockData data, int flag, int updateDepth) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
void forceBiomeInto(int x, int y, int z, Object somethingVeryDirty, ChunkGenerator.BiomeGrid chunk);
|
||||
|
||||
default boolean supportsDataPacks() {
|
||||
@@ -97,7 +115,37 @@ public interface INMSBinding {
|
||||
|
||||
ItemStack applyCustomNbt(ItemStack itemStack, KMap<String, Object> customNbt) throws IllegalArgumentException;
|
||||
|
||||
void setTreasurePos(Dolphin dolphin, com.volmit.iris.core.nms.container.BlockPos pos);
|
||||
|
||||
void inject(long seed, Engine engine, World world) throws NoSuchFieldException, IllegalAccessException;
|
||||
|
||||
Vector3d getBoundingbox(org.bukkit.entity.EntityType entity);
|
||||
|
||||
Entity spawnEntity(Location location, EntityType type, CreatureSpawnEvent.SpawnReason reason);
|
||||
|
||||
Color getBiomeColor(Location location, BiomeColor type);
|
||||
|
||||
default DataVersion getDataVersion() {
|
||||
return DataVersion.V1192;
|
||||
}
|
||||
|
||||
default int getSpawnChunkCount(World world) {
|
||||
return 441;
|
||||
}
|
||||
|
||||
KList<String> getStructureKeys();
|
||||
|
||||
default BlockData getBlockData(CompoundTag tag) {
|
||||
Iris.error("Unsupported version!");
|
||||
return null;
|
||||
};
|
||||
|
||||
default IMemoryWorld createMemoryWorld(WorldCreator creator) throws IOException {
|
||||
return createMemoryWorld(switch (creator.environment()) {
|
||||
case NORMAL -> NamespacedKey.minecraft("overworld");
|
||||
case NETHER -> NamespacedKey.minecraft("the_nether");
|
||||
case THE_END -> NamespacedKey.minecraft("the_end");
|
||||
default -> throw new IllegalArgumentException("Illegal dimension (" + creator.environment() + ")");
|
||||
}, creator);
|
||||
}
|
||||
|
||||
IMemoryWorld createMemoryWorld(NamespacedKey levelType, WorldCreator creator) throws IOException;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.volmit.iris.core.nms.container;
|
||||
|
||||
public enum BiomeColor {
|
||||
FOG,
|
||||
WATER,
|
||||
WATER_FOG,
|
||||
SKY,
|
||||
FOLIAGE,
|
||||
GRASS
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.volmit.iris.core.nms.datapack;
|
||||
|
||||
import com.volmit.iris.core.nms.INMS;
|
||||
import com.volmit.iris.core.nms.datapack.v1192.DataFixerV1192;
|
||||
import com.volmit.iris.core.nms.datapack.v1206.DataFixerV1206;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
//https://minecraft.wiki/w/Pack_format
|
||||
@Getter
|
||||
public enum DataVersion {
|
||||
V1192("1.19.2", 10, DataFixerV1192::new),
|
||||
V1205("1.20.6", 41, DataFixerV1206::new);
|
||||
private static final KMap<DataVersion, IDataFixer> cache = new KMap<>();
|
||||
@Getter(AccessLevel.NONE)
|
||||
private final Supplier<IDataFixer> constructor;
|
||||
private final String version;
|
||||
private final int packFormat;
|
||||
|
||||
DataVersion(String version, int packFormat, Supplier<IDataFixer> constructor) {
|
||||
this.constructor = constructor;
|
||||
this.packFormat = packFormat;
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public IDataFixer get() {
|
||||
return cache.computeIfAbsent(this, k -> constructor.get());
|
||||
}
|
||||
|
||||
public static IDataFixer getDefault() {
|
||||
return INMS.get().getDataVersion().get();
|
||||
}
|
||||
|
||||
public static DataVersion getLatest() {
|
||||
return values()[values().length - 1];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.volmit.iris.core.nms.datapack;
|
||||
|
||||
import com.volmit.iris.engine.object.IrisBiomeCustom;
|
||||
import com.volmit.iris.util.json.JSONObject;
|
||||
|
||||
public interface IDataFixer {
|
||||
|
||||
JSONObject fixCustomBiome(IrisBiomeCustom biome, JSONObject json);
|
||||
|
||||
JSONObject fixDimension(JSONObject json);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.volmit.iris.core.nms.datapack.v1192;
|
||||
|
||||
import com.volmit.iris.core.nms.datapack.IDataFixer;
|
||||
import com.volmit.iris.engine.object.IrisBiomeCustom;
|
||||
import com.volmit.iris.util.json.JSONObject;
|
||||
|
||||
public class DataFixerV1192 implements IDataFixer {
|
||||
|
||||
@Override
|
||||
public JSONObject fixCustomBiome(IrisBiomeCustom biome, JSONObject json) {
|
||||
return json;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject fixDimension(JSONObject json) {
|
||||
return json;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.volmit.iris.core.nms.datapack.v1206;
|
||||
|
||||
import com.volmit.iris.core.nms.datapack.IDataFixer;
|
||||
import com.volmit.iris.engine.object.IrisBiomeCustom;
|
||||
import com.volmit.iris.engine.object.IrisBiomeCustomSpawn;
|
||||
import com.volmit.iris.engine.object.IrisBiomeCustomSpawnType;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.json.JSONArray;
|
||||
import com.volmit.iris.util.json.JSONObject;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
public class DataFixerV1206 implements IDataFixer {
|
||||
@Override
|
||||
public JSONObject fixCustomBiome(IrisBiomeCustom biome, JSONObject json) {
|
||||
int spawnRarity = biome.getSpawnRarity();
|
||||
if (spawnRarity > 0) {
|
||||
json.put("creature_spawn_probability", Math.min(spawnRarity/20d, 0.9999999));
|
||||
}
|
||||
|
||||
var spawns = biome.getSpawns();
|
||||
if (spawns != null && spawns.isNotEmpty()) {
|
||||
JSONObject spawners = new JSONObject();
|
||||
KMap<IrisBiomeCustomSpawnType, JSONArray> groups = new KMap<>();
|
||||
|
||||
for (IrisBiomeCustomSpawn i : spawns) {
|
||||
JSONArray g = groups.computeIfAbsent(i.getGroup(), (k) -> new JSONArray());
|
||||
JSONObject o = new JSONObject();
|
||||
o.put("type", "minecraft:" + i.getType().name().toLowerCase());
|
||||
o.put("weight", i.getWeight());
|
||||
o.put("minCount", Math.min(i.getMinCount()/20d, 0));
|
||||
o.put("maxCount", Math.min(i.getMaxCount()/20d, 0.9999999));
|
||||
g.put(o);
|
||||
}
|
||||
|
||||
for (IrisBiomeCustomSpawnType i : groups.k()) {
|
||||
spawners.put(i.name().toLowerCase(Locale.ROOT), groups.get(i));
|
||||
}
|
||||
|
||||
json.put("spawners", spawners);
|
||||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject fixDimension(JSONObject json) {
|
||||
if (!(json.get("monster_spawn_light_level") instanceof JSONObject lightLevel))
|
||||
return json;
|
||||
var value = (JSONObject) lightLevel.remove("value");
|
||||
lightLevel.put("max_inclusive", value.get("max_inclusive"));
|
||||
lightLevel.put("min_inclusive", value.get("min_inclusive"));
|
||||
return json;
|
||||
}
|
||||
}
|
||||
@@ -19,23 +19,33 @@
|
||||
package com.volmit.iris.core.nms.v1X;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.nms.IMemoryWorld;
|
||||
import com.volmit.iris.core.nms.INMSBinding;
|
||||
import com.volmit.iris.core.nms.container.BiomeColor;
|
||||
import com.volmit.iris.core.nms.container.BlockPos;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.mantle.Mantle;
|
||||
import com.volmit.iris.util.math.Vector3d;
|
||||
import com.volmit.iris.util.nbt.mca.palette.MCABiomeContainer;
|
||||
import com.volmit.iris.util.nbt.mca.palette.MCAPaletteAccess;
|
||||
import com.volmit.iris.util.nbt.tag.CompoundTag;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.entity.Dolphin;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
import org.bukkit.generator.structure.Structure;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.Color;
|
||||
import java.io.IOException;
|
||||
|
||||
public class NMSBinding1X implements INMSBinding {
|
||||
private static final boolean supportsCustomHeight = testCustomHeight();
|
||||
|
||||
@@ -54,16 +64,27 @@ public class NMSBinding1X implements INMSBinding {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasTile(Material material) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasTile(Location l) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag serializeTile(Location location) {
|
||||
public KMap<String, Object> serializeTile(Location location) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserializeTile(KMap<String, Object> s, Location newPosition) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void injectBiomesFromMantle(Chunk e, Mantle mantle) {
|
||||
|
||||
@@ -74,19 +95,37 @@ public class NMSBinding1X implements INMSBinding {
|
||||
return itemStack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTreasurePos(Dolphin dolphin, BlockPos pos) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inject(long seed, Engine engine, World world) throws NoSuchFieldException, IllegalAccessException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserializeTile(CompoundTag s, Location newPosition) {
|
||||
public Vector3d getBoundingbox() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Entity spawnEntity(Location location, EntityType type, CreatureSpawnEvent.SpawnReason reason) {
|
||||
return location.getWorld().spawnEntity(location, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Color getBiomeColor(Location location, BiomeColor type) {
|
||||
return Color.GREEN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KList<String> getStructureKeys() {
|
||||
var list = Registry.STRUCTURE.stream()
|
||||
.map(Structure::getKey)
|
||||
.map(NamespacedKey::toString)
|
||||
.toList();
|
||||
return new KList<>(list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IMemoryWorld createMemoryWorld(NamespacedKey levelType, WorldCreator creator) throws IOException {
|
||||
throw new IOException("Unsupported version!");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -163,6 +202,11 @@ public class NMSBinding1X implements INMSBinding {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KList<Biome> getBiomes() {
|
||||
return new KList<>(Biome.values()).qdel(Biome.CUSTOM);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBukkit() {
|
||||
return true;
|
||||
@@ -197,6 +241,11 @@ public class NMSBinding1X implements INMSBinding {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector3d getBoundingbox(org.bukkit.entity.EntityType entity) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MCAPaletteAccess createPalette() {
|
||||
Iris.error("Cannot use the global data palette! Iris is incapable of using MCA generation on this version of minecraft!");
|
||||
|
||||
@@ -0,0 +1,352 @@
|
||||
package com.volmit.iris.core.pregenerator;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.nms.container.Pair;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.engine.data.cache.Cache;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.mantle.MantleFlag;
|
||||
import com.volmit.iris.util.math.M;
|
||||
import com.volmit.iris.util.math.Position2;
|
||||
import com.volmit.iris.util.math.RollingSequence;
|
||||
import com.volmit.iris.util.profile.LoadBalancer;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.World;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
public class ChunkUpdater {
|
||||
private final AtomicBoolean paused = new AtomicBoolean();
|
||||
private final AtomicBoolean cancelled = new AtomicBoolean();
|
||||
private final KMap<Long, Pair<Long, AtomicInteger>> lastUse = new KMap<>();
|
||||
private final RollingSequence chunksPerSecond = new RollingSequence(5);
|
||||
private final AtomicInteger totalMaxChunks = new AtomicInteger();
|
||||
private final AtomicInteger chunksProcessed = new AtomicInteger();
|
||||
private final AtomicInteger chunksProcessedLast = new AtomicInteger();
|
||||
private final AtomicInteger chunksUpdated = new AtomicInteger();
|
||||
private final AtomicBoolean serverEmpty = new AtomicBoolean(true);
|
||||
private final AtomicLong lastCpsTime = new AtomicLong(M.ms());
|
||||
private final int coreLimit = (int) Math.max(Runtime.getRuntime().availableProcessors() * IrisSettings.get().getUpdater().getThreadMultiplier(), 1);
|
||||
private final Semaphore semaphore = new Semaphore(256);
|
||||
private final LoadBalancer loadBalancer = new LoadBalancer(semaphore, 256, IrisSettings.get().getUpdater().emptyMsRange);
|
||||
private final AtomicLong startTime = new AtomicLong();
|
||||
private final Dimensions dimensions;
|
||||
private final PregenTask task;
|
||||
private final ExecutorService executor = Executors.newFixedThreadPool(coreLimit);
|
||||
private final ExecutorService chunkExecutor = Executors.newFixedThreadPool(coreLimit);
|
||||
private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
|
||||
private final CountDownLatch latch;
|
||||
private final Engine engine;
|
||||
private final World world;
|
||||
|
||||
public ChunkUpdater(World world) {
|
||||
this.engine = IrisToolbelt.access(world).getEngine();
|
||||
this.world = world;
|
||||
this.dimensions = calculateWorldDimensions(new File(world.getWorldFolder(), "region"));
|
||||
this.task = dimensions.task();
|
||||
this.totalMaxChunks.set(dimensions.count * 1024);
|
||||
this.latch = new CountDownLatch(totalMaxChunks.get());
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return world.getName();
|
||||
}
|
||||
|
||||
public int getChunks() {
|
||||
return totalMaxChunks.get();
|
||||
}
|
||||
|
||||
public void start() {
|
||||
unloadAndSaveAllChunks();
|
||||
update();
|
||||
}
|
||||
|
||||
public boolean pause() {
|
||||
unloadAndSaveAllChunks();
|
||||
if (paused.get()) {
|
||||
paused.set(false);
|
||||
return false;
|
||||
} else {
|
||||
paused.set(true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
unloadAndSaveAllChunks();
|
||||
cancelled.set(true);
|
||||
}
|
||||
|
||||
private void update() {
|
||||
Iris.info("Updating..");
|
||||
try {
|
||||
startTime.set(System.currentTimeMillis());
|
||||
scheduler.scheduleAtFixedRate(() -> {
|
||||
try {
|
||||
if (!paused.get()) {
|
||||
long eta = computeETA();
|
||||
int processed = chunksProcessed.get();
|
||||
double last = processed - chunksProcessedLast.getAndSet(processed);
|
||||
double cps = last / ((M.ms() - lastCpsTime.getAndSet(M.ms())) / 1000d);
|
||||
chunksPerSecond.put(cps);
|
||||
double percentage = ((double) processed / (double) totalMaxChunks.get()) * 100;
|
||||
if (!cancelled.get()) {
|
||||
Iris.info("Updated: " + Form.f(processed) + " of " + Form.f(totalMaxChunks.get()) + " (%.0f%%) " + Form.f(chunksPerSecond.getAverage()) + "/s, ETA: " + Form.duration(eta,
|
||||
2), percentage);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}, 0, 3, TimeUnit.SECONDS);
|
||||
scheduler.scheduleAtFixedRate(this::unloadChunks, 0, 1, TimeUnit.SECONDS);
|
||||
scheduler.scheduleAtFixedRate(() -> {
|
||||
boolean empty = Bukkit.getOnlinePlayers().isEmpty();
|
||||
if (serverEmpty.getAndSet(empty) == empty)
|
||||
return;
|
||||
loadBalancer.setRange(empty ? IrisSettings.get().getUpdater().emptyMsRange : IrisSettings.get().getUpdater().defaultMsRange);
|
||||
}, 0, 10, TimeUnit.SECONDS);
|
||||
|
||||
var t = new Thread(() -> {
|
||||
run();
|
||||
close();
|
||||
}, "Iris Chunk Updater - " + world.getName());
|
||||
t.setPriority(Thread.MAX_PRIORITY);
|
||||
t.start();
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void close() {
|
||||
try {
|
||||
loadBalancer.close();
|
||||
semaphore.acquire(256);
|
||||
|
||||
executor.shutdown();
|
||||
executor.awaitTermination(5, TimeUnit.SECONDS);
|
||||
chunkExecutor.shutdown();
|
||||
chunkExecutor.awaitTermination(5, TimeUnit.SECONDS);
|
||||
scheduler.shutdownNow();
|
||||
unloadAndSaveAllChunks();
|
||||
} catch (Exception ignored) {}
|
||||
if (cancelled.get()) {
|
||||
Iris.info("Updated: " + Form.f(chunksUpdated.get()) + " Chunks");
|
||||
Iris.info("Irritated: " + Form.f(chunksProcessed.get()) + " of " + Form.f(totalMaxChunks.get()));
|
||||
Iris.info("Stopped updater.");
|
||||
} else {
|
||||
Iris.info("Processed: " + Form.f(chunksProcessed.get()) + " Chunks");
|
||||
Iris.info("Finished Updating: " + Form.f(chunksUpdated.get()) + " Chunks");
|
||||
}
|
||||
}
|
||||
|
||||
private void run() {
|
||||
task.iterateRegions((rX, rZ) -> {
|
||||
if (cancelled.get())
|
||||
return;
|
||||
|
||||
while (paused.get()) {
|
||||
J.sleep(50);
|
||||
}
|
||||
|
||||
if (rX < dimensions.min.getX() || rX > dimensions.max.getX() || rZ < dimensions.min.getZ() || rZ > dimensions.max.getZ()) {
|
||||
return;
|
||||
}
|
||||
|
||||
PregenTask.iterateRegion(rX, rZ, (x, z) -> {
|
||||
while (paused.get() && !cancelled.get()) {
|
||||
J.sleep(50);
|
||||
}
|
||||
|
||||
try {
|
||||
semaphore.acquire();
|
||||
} catch (InterruptedException ignored) {
|
||||
return;
|
||||
}
|
||||
chunkExecutor.submit(() -> {
|
||||
try {
|
||||
if (!cancelled.get())
|
||||
processChunk(x, z);
|
||||
} finally {
|
||||
latch.countDown();
|
||||
semaphore.release();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private void processChunk(int x, int z) {
|
||||
if (!loadChunksIfGenerated(x, z)) {
|
||||
chunksProcessed.getAndIncrement();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
Chunk c = world.getChunkAt(x, z);
|
||||
engine.getMantle().getMantle().getChunk(c);
|
||||
engine.updateChunk(c);
|
||||
|
||||
for (int xx = -1; xx <= 1; xx++) {
|
||||
for (int zz = -1; zz <= 1; zz++) {
|
||||
var counter = lastUse.get(Cache.key(x + xx, z + zz));
|
||||
if (counter != null) counter.getB().decrementAndGet();
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
chunksUpdated.incrementAndGet();
|
||||
chunksProcessed.getAndIncrement();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean loadChunksIfGenerated(int x, int z) {
|
||||
if (engine.getMantle().getMantle().hasFlag(x, z, MantleFlag.ETCHED))
|
||||
return false;
|
||||
|
||||
for (int dx = -1; dx <= 1; dx++) {
|
||||
for (int dz = -1; dz <= 1; dz++) {
|
||||
if (!PaperLib.isChunkGenerated(world, x + dx, z + dz)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AtomicBoolean generated = new AtomicBoolean(true);
|
||||
CountDownLatch latch = new CountDownLatch(9);
|
||||
for (int dx = -1; dx <= 1; dx++) {
|
||||
for (int dz = -1; dz <= 1; dz++) {
|
||||
int xx = x + dx;
|
||||
int zz = z + dz;
|
||||
executor.submit(() -> {
|
||||
try {
|
||||
Chunk c;
|
||||
try {
|
||||
c = PaperLib.getChunkAtAsync(world, xx, zz, false, true)
|
||||
.thenApply(chunk -> {
|
||||
chunk.addPluginChunkTicket(Iris.instance);
|
||||
return chunk;
|
||||
}).get();
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
generated.set(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!c.isLoaded()) {
|
||||
var future = J.sfut(() -> c.load(false));
|
||||
if (future != null) future.join();
|
||||
}
|
||||
|
||||
if (!c.isGenerated())
|
||||
generated.set(false);
|
||||
|
||||
var pair = lastUse.computeIfAbsent(Cache.key(c), k -> new Pair<>(0L, new AtomicInteger(-1)));
|
||||
pair.setA(M.ms());
|
||||
pair.getB().updateAndGet(i -> i == -1 ? 1 : ++i);
|
||||
} finally {
|
||||
latch.countDown();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
latch.await();
|
||||
} catch (InterruptedException e) {
|
||||
Iris.info("Interrupted while waiting for chunks to load");
|
||||
}
|
||||
return generated.get();
|
||||
}
|
||||
|
||||
private synchronized void unloadChunks() {
|
||||
for (var key : new ArrayList<>(lastUse.keySet())) {
|
||||
if (key == null) continue;
|
||||
var pair = lastUse.get(key);
|
||||
if (pair == null) continue;
|
||||
var lastUseTime = pair.getA();
|
||||
var counter = pair.getB();
|
||||
if (lastUseTime == null || counter == null)
|
||||
continue;
|
||||
|
||||
if (M.ms() - lastUseTime >= 5000 && counter.get() == 0) {
|
||||
int x = Cache.keyX(key);
|
||||
int z = Cache.keyZ(key);
|
||||
J.s(() -> {
|
||||
world.removePluginChunkTicket(x, z, Iris.instance);
|
||||
world.unloadChunk(x, z);
|
||||
lastUse.remove(key);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void unloadAndSaveAllChunks() {
|
||||
try {
|
||||
J.sfut(() -> {
|
||||
if (world == null) {
|
||||
Iris.warn("World was null somehow...");
|
||||
return;
|
||||
}
|
||||
|
||||
unloadChunks();
|
||||
world.save();
|
||||
}).get();
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private long computeETA() {
|
||||
return (long) (totalMaxChunks.get() > 1024 ? // Generated chunks exceed 1/8th of total?
|
||||
// If yes, use smooth function (which gets more accurate over time since its less sensitive to outliers)
|
||||
((totalMaxChunks.get() - chunksProcessed.get()) * ((double) (M.ms() - startTime.get()) / (double) chunksProcessed.get())) :
|
||||
// If no, use quick function (which is less accurate over time but responds better to the initial delay)
|
||||
((totalMaxChunks.get() - chunksProcessed.get()) / chunksPerSecond.getAverage()) * 1000
|
||||
);
|
||||
}
|
||||
|
||||
private Dimensions calculateWorldDimensions(File regionDir) {
|
||||
File[] files = regionDir.listFiles((dir, name) -> name.endsWith(".mca"));
|
||||
|
||||
int minX = Integer.MAX_VALUE;
|
||||
int maxX = Integer.MIN_VALUE;
|
||||
int minZ = Integer.MAX_VALUE;
|
||||
int maxZ = Integer.MIN_VALUE;
|
||||
|
||||
for (File file : files) {
|
||||
String[] parts = file.getName().split("\\.");
|
||||
int x = Integer.parseInt(parts[1]);
|
||||
int z = Integer.parseInt(parts[2]);
|
||||
|
||||
minX = Math.min(minX, x);
|
||||
maxX = Math.max(maxX, x);
|
||||
minZ = Math.min(minZ, z);
|
||||
maxZ = Math.max(maxZ, z);
|
||||
}
|
||||
int oX = minX + ((maxX - minX) / 2);
|
||||
int oZ = minZ + ((maxZ - minZ) / 2);
|
||||
|
||||
int height = maxX - minX + 1;
|
||||
int width = maxZ - minZ + 1;
|
||||
|
||||
return new Dimensions(new Position2(minX, minZ), new Position2(maxX, maxZ), height * width, PregenTask.builder()
|
||||
.width((int) Math.ceil(width / 2d))
|
||||
.height((int) Math.ceil(height / 2d))
|
||||
.center(new Position2(oX, oZ))
|
||||
.build());
|
||||
}
|
||||
|
||||
private record Dimensions(Position2 min, Position2 max, int count, PregenTask task) { }
|
||||
}
|
||||
@@ -19,7 +19,9 @@
|
||||
package com.volmit.iris.core.pregenerator;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.pack.IrisPack;
|
||||
import com.volmit.iris.core.tools.IrisPackBenchmarking;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KSet;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
@@ -30,15 +32,12 @@ import com.volmit.iris.util.math.RollingSequence;
|
||||
import com.volmit.iris.util.scheduling.ChronoLatch;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import com.volmit.iris.util.scheduling.Looper;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import static com.volmit.iris.core.tools.IrisPackBenchmarking.benchmark;
|
||||
|
||||
public class IrisPregenerator {
|
||||
private final PregenTask task;
|
||||
@@ -50,6 +49,7 @@ public class IrisPregenerator {
|
||||
private final RollingSequence chunksPerSecond;
|
||||
private final RollingSequence chunksPerMinute;
|
||||
private final RollingSequence regionsPerMinute;
|
||||
private final KList<Integer> chunksPerSecondHistory;
|
||||
private static AtomicInteger generated;
|
||||
private final AtomicInteger generatedLast;
|
||||
private final AtomicInteger generatedLastMinute;
|
||||
@@ -62,8 +62,6 @@ public class IrisPregenerator {
|
||||
private final KSet<Position2> net;
|
||||
private final ChronoLatch cl;
|
||||
private final ChronoLatch saveLatch = new ChronoLatch(30000);
|
||||
static long long_generatedChunks = 0;
|
||||
static long long_totalChunks = 0;
|
||||
|
||||
public IrisPregenerator(PregenTask task, PregeneratorMethod generator, PregenListener listener) {
|
||||
this.listener = listenify(listener);
|
||||
@@ -80,6 +78,7 @@ public class IrisPregenerator {
|
||||
chunksPerSecond = new RollingSequence(10);
|
||||
chunksPerMinute = new RollingSequence(10);
|
||||
regionsPerMinute = new RollingSequence(10);
|
||||
chunksPerSecondHistory = new KList<>();
|
||||
generated = new AtomicInteger(0);
|
||||
generatedLast = new AtomicInteger(0);
|
||||
generatedLastMinute = new AtomicInteger(0);
|
||||
@@ -93,6 +92,7 @@ public class IrisPregenerator {
|
||||
int secondGenerated = generated.get() - generatedLast.get();
|
||||
generatedLast.set(generated.get());
|
||||
chunksPerSecond.put(secondGenerated);
|
||||
chunksPerSecondHistory.add(secondGenerated);
|
||||
|
||||
if (minuteLatch.flip()) {
|
||||
int minuteGenerated = generated.get() - generatedLastMinute.get();
|
||||
@@ -100,8 +100,6 @@ public class IrisPregenerator {
|
||||
chunksPerMinute.put(minuteGenerated);
|
||||
regionsPerMinute.put((double) minuteGenerated / 1024D);
|
||||
}
|
||||
long_generatedChunks = generated.get();
|
||||
long_totalChunks = totalChunks.get();
|
||||
|
||||
listener.onTick(chunksPerSecond.getAverage(), chunksPerMinute.getAverage(),
|
||||
regionsPerMinute.getAverage(),
|
||||
@@ -112,10 +110,10 @@ public class IrisPregenerator {
|
||||
|
||||
if (cl.flip()) {
|
||||
double percentage = ((double) generated.get() / (double) totalChunks.get()) * 100;
|
||||
if(benchmark) {
|
||||
Iris.info(C.GREEN +"Benchmark: " + C.WHITE + Form.f(generated.get()) + " of " + Form.f(totalChunks.get()) + " (%.0f%%) " + Form.f((int) chunksPerSecond.getAverage()) + "/s ETA: " + Form.duration((double) eta, 2), percentage);
|
||||
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("Pregen: " + Form.f(generated.get()) + " of " + Form.f(totalChunks.get()) + " (%.0f%%) " + Form.f((int) chunksPerSecond.getAverage()) + "/s ETA: " + Form.duration((double) eta, 2), percentage);
|
||||
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;
|
||||
@@ -128,17 +126,10 @@ public class IrisPregenerator {
|
||||
// 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 //
|
||||
((totalChunks.get() - generated.get()) / chunksPerSecond.getAverage()) * 1000
|
||||
);
|
||||
}
|
||||
|
||||
public static long getLongGeneratedChunks() {
|
||||
return long_generatedChunks;
|
||||
}
|
||||
public static long getLongTotalChunks() {
|
||||
return long_totalChunks;
|
||||
}
|
||||
|
||||
|
||||
public void close() {
|
||||
shutdown.set(true);
|
||||
@@ -151,6 +142,11 @@ public class IrisPregenerator {
|
||||
task.iterateRegions((x, z) -> visitRegion(x, z, true));
|
||||
task.iterateRegions((x, z) -> visitRegion(x, z, false));
|
||||
shutdown();
|
||||
if (!IrisPackBenchmarking.benchmarkInProgress) {
|
||||
Iris.info(C.IRIS + "Pregen stopped.");
|
||||
} else {
|
||||
IrisPackBenchmarking.instance.finishedBenchmark(chunksPerSecondHistory);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkRegions() {
|
||||
@@ -167,7 +163,10 @@ public class IrisPregenerator {
|
||||
generator.close();
|
||||
ticker.interrupt();
|
||||
listener.onClose();
|
||||
getMantle().trim(0);
|
||||
Mantle mantle = getMantle();
|
||||
if (mantle != null) {
|
||||
mantle.trim(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
private void visitRegion(int x, int z, boolean regions) {
|
||||
|
||||
@@ -14,22 +14,32 @@ import com.volmit.iris.util.scheduling.J;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.Getter;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.world.WorldUnloadEvent;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.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 final World world;
|
||||
private World world;
|
||||
private final long rate;
|
||||
private final ChronoLatch latch;
|
||||
private static AtomicInteger lazyGeneratedChunks;
|
||||
@@ -37,6 +47,9 @@ public class LazyPregenerator extends Thread implements Listener {
|
||||
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;
|
||||
@@ -44,16 +57,16 @@ public class LazyPregenerator extends Thread implements Listener {
|
||||
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.chunksPerMinute / 60D)) * 1000D);
|
||||
this.latch = new ChronoLatch(6000);
|
||||
startTime = new AtomicLong(M.ms());
|
||||
chunksPerSecond = new RollingSequence(10);
|
||||
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);
|
||||
generatedLast = new AtomicInteger(0);
|
||||
lazyTotalChunks = new AtomicInteger();
|
||||
|
||||
int radius = job.getRadiusBlocks();
|
||||
lazyTotalChunks.set((int) Math.ceil(Math.pow((2.0 * radius) / 16, 2)));
|
||||
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 {
|
||||
@@ -63,7 +76,6 @@ public class LazyPregenerator extends Thread implements Listener {
|
||||
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);
|
||||
@@ -97,18 +109,18 @@ public class LazyPregenerator extends Thread implements Listener {
|
||||
}
|
||||
|
||||
public void tick() {
|
||||
if (latch.flip()) {
|
||||
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 / 6;
|
||||
secondGenerated = secondGenerated / 15;
|
||||
chunksPerSecond.put(secondGenerated);
|
||||
Iris.info("LazyGen: " + C.IRIS + world.getName() + C.RESET + " RTT: " + Form.f(lazyGeneratedChunks.get()) + " of " + Form.f(lazyTotalChunks.get()) + " " + Form.f((int) chunksPerSecond.getAverage()) + "/s ETA: " + Form.duration((double) eta, 2));
|
||||
//Iris.info("Debug: " + maxPosition);
|
||||
//Iris.info("Debug1: " + job.getPosition());
|
||||
|
||||
// todo: Maxpos borked
|
||||
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()) {
|
||||
@@ -123,27 +135,40 @@ public class LazyPregenerator extends Thread implements Listener {
|
||||
} else {
|
||||
int pos = job.getPosition() + 1;
|
||||
job.setPosition(pos);
|
||||
tickGenerate(getChunk(pos));
|
||||
if (!job.paused) {
|
||||
tickGenerate(getChunk(pos));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private long computeETA() {
|
||||
return (long) (lazyTotalChunks.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)
|
||||
((lazyTotalChunks.get() - lazyGeneratedChunks.get()) * ((double) (M.ms() - startTime.get()) / (double) lazyGeneratedChunks.get())) :
|
||||
// If no, use quick function (which is less accurate over time but responds better to the initial delay)
|
||||
((lazyTotalChunks.get() - lazyGeneratedChunks.get()) / chunksPerSecond.getAverage()) * 1000 //
|
||||
);
|
||||
return (long) ((lazyTotalChunks.get() - lazyGeneratedChunks.get()) / chunksPerMinute.getAverage()) * 1000;
|
||||
// todo broken
|
||||
}
|
||||
|
||||
private final ExecutorService executorService = Executors.newSingleThreadExecutor();
|
||||
|
||||
private void tickGenerate(Position2 chunk) {
|
||||
if (PaperLib.isPaper()) {
|
||||
PaperLib.getChunkAtAsync(world, chunk.getX(), chunk.getZ(), true).thenAccept((i) -> Iris.verbose("Generated Async " + chunk));
|
||||
} else {
|
||||
J.s(() -> world.getChunkAt(chunk.getX(), chunk.getZ()));
|
||||
Iris.verbose("Generated " + chunk);
|
||||
}
|
||||
lazyGeneratedChunks.addAndGet(1);
|
||||
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) {
|
||||
@@ -177,6 +202,63 @@ public class LazyPregenerator extends Thread implements Listener {
|
||||
});
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
@@ -190,10 +272,15 @@ public class LazyPregenerator extends Thread implements Listener {
|
||||
@Builder.Default
|
||||
private boolean healing = false;
|
||||
@Builder.Default
|
||||
private int chunksPerMinute = 32; // 48 hours is roughly 5000 radius
|
||||
private int chunksPerMinute = 32;
|
||||
@Builder.Default
|
||||
private int radiusBlocks = 5000;
|
||||
@Builder.Default
|
||||
private int position = 0;
|
||||
@Builder.Default
|
||||
boolean silent = false;
|
||||
@Builder.Default
|
||||
boolean paused = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -35,6 +35,8 @@ public class PregenTask {
|
||||
private static final KList<Position2> ORDER_CENTER = computeChunkOrder();
|
||||
private static final KMap<Position2, KList<Position2>> ORDERS = new KMap<>();
|
||||
|
||||
@Builder.Default
|
||||
private boolean gui = false;
|
||||
@Builder.Default
|
||||
private Position2 center = new Position2(0, 0);
|
||||
@Builder.Default
|
||||
|
||||
@@ -23,20 +23,24 @@ import com.volmit.iris.core.pregenerator.PregenListener;
|
||||
import com.volmit.iris.core.pregenerator.PregeneratorMethod;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.mantle.Mantle;
|
||||
import com.volmit.iris.util.math.M;
|
||||
import com.volmit.iris.util.parallel.MultiBurst;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.World;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
public class AsyncPregenMethod implements PregeneratorMethod {
|
||||
private final World world;
|
||||
private final MultiBurst burst;
|
||||
private final KList<Future<?>> future;
|
||||
private final Map<Chunk, Long> lastUse;
|
||||
|
||||
public AsyncPregenMethod(World world, int threads) {
|
||||
if (!PaperLib.isPaper()) {
|
||||
@@ -44,8 +48,9 @@ public class AsyncPregenMethod implements PregeneratorMethod {
|
||||
}
|
||||
|
||||
this.world = world;
|
||||
burst = MultiBurst.burst;
|
||||
future = new KList<>(1024);
|
||||
burst = new MultiBurst("Iris Async Pregen", Thread.MIN_PRIORITY);
|
||||
future = new KList<>(256);
|
||||
this.lastUse = new KMap<>();
|
||||
}
|
||||
|
||||
private void unloadAndSaveAllChunks() {
|
||||
@@ -56,8 +61,12 @@ public class AsyncPregenMethod implements PregeneratorMethod {
|
||||
return;
|
||||
}
|
||||
|
||||
for (Chunk i : world.getLoadedChunks()) {
|
||||
i.unload(true);
|
||||
for (Chunk i : new ArrayList<>(lastUse.keySet())) {
|
||||
Long lastUseTime = lastUse.get(i);
|
||||
if (lastUseTime != null && M.ms() - lastUseTime >= 10000) {
|
||||
i.unload();
|
||||
lastUse.remove(i);
|
||||
}
|
||||
}
|
||||
world.save();
|
||||
}).get();
|
||||
@@ -68,23 +77,18 @@ public class AsyncPregenMethod implements PregeneratorMethod {
|
||||
|
||||
private void completeChunk(int x, int z, PregenListener listener) {
|
||||
try {
|
||||
future.add(PaperLib.getChunkAtAsync(world, x, z, true).thenApply((i) -> {
|
||||
if (i == null) {
|
||||
|
||||
}
|
||||
|
||||
PaperLib.getChunkAtAsync(world, x, z, true).thenAccept((i) -> {
|
||||
lastUse.put(i, M.ms());
|
||||
listener.onChunkGenerated(x, z);
|
||||
listener.onChunkCleaned(x, z);
|
||||
return 0;
|
||||
}));
|
||||
}).get();
|
||||
} catch (InterruptedException ignored) {
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void waitForChunksPartial(int maxWaiting) {
|
||||
future.removeWhere(Objects::isNull);
|
||||
|
||||
while (future.size() > maxWaiting) {
|
||||
try {
|
||||
Future<?> i = future.remove(0);
|
||||
@@ -113,8 +117,6 @@ public class AsyncPregenMethod implements PregeneratorMethod {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
future.removeWhere(Objects::isNull);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -131,6 +133,7 @@ public class AsyncPregenMethod implements PregeneratorMethod {
|
||||
public void close() {
|
||||
waitForChunks();
|
||||
unloadAndSaveAllChunks();
|
||||
burst.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -18,25 +18,33 @@
|
||||
|
||||
package com.volmit.iris.core.pregenerator.methods;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.pregenerator.PregenListener;
|
||||
import com.volmit.iris.core.pregenerator.PregeneratorMethod;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.mantle.Mantle;
|
||||
import com.volmit.iris.util.math.M;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.World;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class MedievalPregenMethod implements PregeneratorMethod {
|
||||
private final World world;
|
||||
private final KList<CompletableFuture<?>> futures;
|
||||
private final Map<Chunk, Long> lastUse;
|
||||
|
||||
public MedievalPregenMethod(World world) {
|
||||
this.world = world;
|
||||
futures = new KList<>();
|
||||
this.lastUse = new KMap<>();
|
||||
}
|
||||
|
||||
private void waitForChunks() {
|
||||
@@ -52,11 +60,19 @@ public class MedievalPregenMethod implements PregeneratorMethod {
|
||||
}
|
||||
|
||||
private void unloadAndSaveAllChunks() {
|
||||
waitForChunks();
|
||||
try {
|
||||
J.sfut(() -> {
|
||||
for (Chunk i : world.getLoadedChunks()) {
|
||||
i.unload(true);
|
||||
if (world == null) {
|
||||
Iris.warn("World was null somehow...");
|
||||
return;
|
||||
}
|
||||
|
||||
for (Chunk i : new ArrayList<>(lastUse.keySet())) {
|
||||
Long lastUseTime = lastUse.get(i);
|
||||
if (lastUseTime != null && M.ms() - lastUseTime >= 10) {
|
||||
i.unload();
|
||||
lastUse.remove(i);
|
||||
}
|
||||
}
|
||||
world.save();
|
||||
}).get();
|
||||
@@ -104,6 +120,8 @@ public class MedievalPregenMethod implements PregeneratorMethod {
|
||||
listener.onChunkGenerating(x, z);
|
||||
futures.add(J.sfut(() -> {
|
||||
world.getChunkAt(x, z);
|
||||
Chunk c = Bukkit.getWorld(world.getUID()).getChunkAt(x, z);
|
||||
lastUse.put(c, M.ms());
|
||||
listener.onChunkGenerated(x, z);
|
||||
listener.onChunkCleaned(x, z);
|
||||
}));
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.loader.IrisData;
|
||||
import com.volmit.iris.core.loader.IrisRegistrant;
|
||||
import com.volmit.iris.core.loader.ResourceLoader;
|
||||
import com.volmit.iris.engine.framework.ListFunction;
|
||||
import com.volmit.iris.engine.object.annotations.*;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
@@ -309,6 +310,24 @@ public class SchemaBuilder {
|
||||
fancyType = "Enchantment Type";
|
||||
prop.put("$ref", "#/definitions/" + key);
|
||||
description.add(SYMBOL_TYPE__N + " Must be a valid Enchantment Type (use ctrl+space for auto complete!)");
|
||||
} else if (k.isAnnotationPresent(RegistryListFunction.class)) {
|
||||
var functionClass = k.getDeclaredAnnotation(RegistryListFunction.class).value();
|
||||
try {
|
||||
var instance = functionClass.getDeclaredConstructor().newInstance();
|
||||
String key = instance.key();
|
||||
fancyType = instance.fancyName();
|
||||
|
||||
if (!definitions.containsKey(key)) {
|
||||
JSONObject j = new JSONObject();
|
||||
j.put("enum", instance.apply(data));
|
||||
definitions.put(key, j);
|
||||
}
|
||||
|
||||
prop.put("$ref", "#/definitions/" + key);
|
||||
description.add(SYMBOL_TYPE__N + " Must be a valid " + fancyType + " (use ctrl+space for auto complete!)");
|
||||
} catch (Throwable e) {
|
||||
Iris.error("Could not execute apply method in " + functionClass.getName());
|
||||
}
|
||||
} else if (k.getType().equals(PotionEffectType.class)) {
|
||||
String key = "enum-potion-effect-type";
|
||||
|
||||
@@ -378,6 +397,10 @@ public class SchemaBuilder {
|
||||
description.add(SYMBOL_LIMIT__N + " Requires at least " + t.min() + " entries.");
|
||||
}
|
||||
}
|
||||
if (t.max() > 0) {
|
||||
prop.put("maxItems", t.max());
|
||||
description.add(SYMBOL_LIMIT__N + " Maximum allowed entries are " + t.max() + ".");
|
||||
}
|
||||
|
||||
String arrayType = getType(t.type());
|
||||
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
package com.volmit.iris.engine.safeguard;
|
||||
package com.volmit.iris.core.safeguard;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
|
||||
public class IrisSafeguard {
|
||||
// more planned and WIP
|
||||
public static boolean unstablemode = false;
|
||||
public static boolean warningmode = false;
|
||||
public static boolean stablemode = false;
|
||||
|
||||
public static void IrisSafeguardSystem() {
|
||||
Iris.info("Enabled Iris SafeGuard");
|
||||
ServerBootSFG.BootCheck();
|
||||
@@ -0,0 +1,80 @@
|
||||
package com.volmit.iris.core.safeguard;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.util.format.C;
|
||||
|
||||
public class ModesSFG {
|
||||
public static void selectMode() {
|
||||
if (IrisSafeguard.unstablemode) {
|
||||
Iris.safeguard(C.DARK_RED + "Iris is running in Unstable Mode");
|
||||
unstable();
|
||||
}
|
||||
if (IrisSafeguard.warningmode) {
|
||||
Iris.safeguard(C.GOLD + "Iris is running in Warning Mode");
|
||||
warning();
|
||||
}
|
||||
if (IrisSafeguard.stablemode) {
|
||||
stable();
|
||||
}
|
||||
}
|
||||
|
||||
public static void stable() {
|
||||
Iris.safeguard(C.BLUE + "Iris is running Stable");
|
||||
}
|
||||
|
||||
public static void unstable() {
|
||||
|
||||
UtilsSFG.printIncompatibleWarnings();
|
||||
|
||||
if (IrisSafeguard.unstablemode) {
|
||||
Iris.info("");
|
||||
Iris.info(C.DARK_GRAY + "--==<" + C.RED + " IMPORTANT " + C.DARK_GRAY + ">==--");
|
||||
Iris.info(C.RED + "Iris is running in unstable mode which may cause the following issues:");
|
||||
Iris.info(C.DARK_RED + "Server Issues");
|
||||
Iris.info(C.RED + "- Server won't boot");
|
||||
Iris.info(C.RED + "- Data Loss");
|
||||
Iris.info(C.RED + "- Unexpected behavior.");
|
||||
Iris.info(C.RED + "- And More...");
|
||||
Iris.info(C.DARK_RED + "World Issues");
|
||||
Iris.info(C.RED + "- Worlds can't load due to corruption.");
|
||||
Iris.info(C.RED + "- Worlds may slowly corrupt until they can't load.");
|
||||
Iris.info(C.RED + "- World data loss.");
|
||||
Iris.info(C.RED + "- And More...");
|
||||
Iris.info(C.DARK_RED + "ATTENTION: " + C.RED + "While running Iris in unstable mode, you won't be eligible for support.");
|
||||
Iris.info(C.DARK_RED + "CAUSE: " + C.RED + UtilsSFG.MSGIncompatibleWarnings());
|
||||
|
||||
if (IrisSettings.get().getGeneral().DoomsdayAnnihilationSelfDestructMode) {
|
||||
Iris.info(C.DARK_RED + "Boot Unstable is set to true, continuing with the startup process.");
|
||||
} else {
|
||||
Iris.info(C.DARK_RED + "Go to plugins/iris/settings.json and set DoomsdayAnnihilationSelfDestructMode to true if you wish to proceed.");
|
||||
while (true) {
|
||||
try {
|
||||
Thread.sleep(Long.MAX_VALUE);
|
||||
} catch (InterruptedException e) {
|
||||
// no
|
||||
}
|
||||
}
|
||||
}
|
||||
Iris.info("");
|
||||
}
|
||||
}
|
||||
|
||||
public static void warning() {
|
||||
|
||||
UtilsSFG.printIncompatibleWarnings();
|
||||
|
||||
if (IrisSafeguard.warningmode) {
|
||||
Iris.info("");
|
||||
Iris.info(C.DARK_GRAY + "--==<" + C.GOLD + " IMPORTANT " + C.DARK_GRAY + ">==--");
|
||||
Iris.info(C.GOLD + "Iris is running in warning mode which may cause the following issues:");
|
||||
Iris.info(C.YELLOW + "- Data Loss");
|
||||
Iris.info(C.YELLOW + "- Errors");
|
||||
Iris.info(C.YELLOW + "- Broken worlds");
|
||||
Iris.info(C.YELLOW + "- Unexpected behavior.");
|
||||
Iris.info(C.YELLOW + "- And perhaps further complications.");
|
||||
Iris.info(C.GOLD + "CAUSE: " + C.YELLOW + UtilsSFG.MSGIncompatibleWarnings());
|
||||
Iris.info("");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.volmit.iris.core.safeguard;
|
||||
|
||||
public class PerformanceSFG {
|
||||
public static void calculatePerformance() {
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
package com.volmit.iris.core.safeguard;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.nms.INMS;
|
||||
import com.volmit.iris.core.nms.v1X.NMSBinding1X;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
import javax.tools.JavaCompiler;
|
||||
import javax.tools.ToolProvider;
|
||||
import java.io.File;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
import static com.volmit.iris.Iris.getJavaVersion;
|
||||
import static com.volmit.iris.Iris.instance;
|
||||
import static com.volmit.iris.core.safeguard.IrisSafeguard.*;
|
||||
|
||||
public class ServerBootSFG {
|
||||
public static final Map<String, Boolean> incompatibilities = new HashMap<>();
|
||||
public static boolean isJDK17 = true;
|
||||
public static boolean hasEnoughDiskSpace = true;
|
||||
public static boolean isJRE = false;
|
||||
public static boolean hasPrivileges = true;
|
||||
public static boolean unsuportedversion = false;
|
||||
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(17, 21).contains(getJavaVersion())) {
|
||||
isJDK17 = false;
|
||||
joiner.add("Unsupported Java version");
|
||||
severityMedium++;
|
||||
}
|
||||
|
||||
if (!isJDK()) {
|
||||
isJRE = true;
|
||||
joiner.add("Unsupported JDK");
|
||||
severityMedium++;
|
||||
}
|
||||
|
||||
// if (!hasPrivileges()){
|
||||
// hasPrivileges = false;
|
||||
// joiner.add("Insufficient Privileges");
|
||||
// severityMedium++;
|
||||
// } Some servers dont like this
|
||||
|
||||
if (!enoughDiskSpace()){
|
||||
hasEnoughDiskSpace = false;
|
||||
joiner.add("Insufficient Disk Space");
|
||||
severityMedium++;
|
||||
}
|
||||
|
||||
allIncompatibilities = joiner.toString();
|
||||
|
||||
safeguardPassed = (severityHigh == 0 && severityMedium == 0 && severityLow == 0);
|
||||
count = severityHigh + severityMedium + severityLow;
|
||||
if (safeguardPassed) {
|
||||
stablemode = true;
|
||||
Iris.safeguard("Stable mode has been activated.");
|
||||
}
|
||||
if (!safeguardPassed) {
|
||||
if (severityMedium >= 1 && severityHigh == 0) {
|
||||
warningmode = true;
|
||||
Iris.safeguard("Warning mode has been activated.");
|
||||
}
|
||||
if (severityHigh >= 1) {
|
||||
unstablemode = true;
|
||||
Iris.safeguard("Unstable mode has been activated.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static boolean isJDK() {
|
||||
try {
|
||||
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
|
||||
// If the compiler is null, it means this is a JRE environment, not a JDK.
|
||||
return compiler != null;
|
||||
} catch (Exception ignored) {}
|
||||
return false;
|
||||
}
|
||||
public static boolean hasPrivileges() {
|
||||
Path pv = Paths.get(Bukkit.getWorldContainer() + "iristest.json");
|
||||
try (FileChannel fc = FileChannel.open(pv, StandardOpenOption.CREATE, StandardOpenOption.DELETE_ON_CLOSE, StandardOpenOption.READ, StandardOpenOption.WRITE)) {
|
||||
if (Files.isReadable(pv) && Files.isWritable(pv)) {
|
||||
return true;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean enoughDiskSpace() {
|
||||
File freeSpace = new File(Bukkit.getWorldContainer() + ".");
|
||||
double gigabytes = freeSpace.getFreeSpace() / (1024.0 * 1024.0 * 1024.0);
|
||||
if (gigabytes > 3){
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean checkJavac(String path) {
|
||||
return !path.isEmpty() && (new File(path, "javac").exists() || new File(path, "javac.exe").exists());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package com.volmit.iris.core.safeguard;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.util.format.C;
|
||||
|
||||
public class UtilsSFG {
|
||||
public static void splash() {
|
||||
ModesSFG.selectMode();
|
||||
}
|
||||
|
||||
public static void printIncompatibleWarnings() {
|
||||
// String SupportedIrisVersion = getDescription().getVersion(); //todo Automatic version
|
||||
|
||||
if (ServerBootSFG.safeguardPassed) {
|
||||
Iris.safeguard(C.BLUE + "0 Conflicts found");
|
||||
} else {
|
||||
if (IrisSafeguard.unstablemode) {
|
||||
Iris.safeguard(C.DARK_RED + "" + ServerBootSFG.count + " Conflicts found");
|
||||
}
|
||||
if (IrisSafeguard.warningmode) {
|
||||
Iris.safeguard(C.YELLOW + "" + ServerBootSFG.count + " Conflicts found");
|
||||
}
|
||||
|
||||
if (ServerBootSFG.incompatibilities.get("Multiverse-Core")) {
|
||||
Iris.safeguard(C.RED + "Multiverse");
|
||||
Iris.safeguard(C.RED + "- The plugin Multiverse is not compatible with the server.");
|
||||
Iris.safeguard(C.RED + "- If you want to have a world manager, consider using PhantomWorlds or MyWorlds instead.");
|
||||
}
|
||||
if (ServerBootSFG.incompatibilities.get("dynmap")) {
|
||||
Iris.safeguard(C.RED + "Dynmap");
|
||||
Iris.safeguard(C.RED + "- The plugin Dynmap is not compatible with the server.");
|
||||
Iris.safeguard(C.RED + "- If you want to have a map plugin like Dynmap, consider Bluemap.");
|
||||
}
|
||||
if (ServerBootSFG.incompatibilities.get("TerraformGenerator") || ServerBootSFG.incompatibilities.get("Stratos")) {
|
||||
Iris.safeguard(C.YELLOW + "Terraform Generator / Stratos");
|
||||
Iris.safeguard(C.YELLOW + "- Iris is not compatible with other worldgen plugins.");
|
||||
}
|
||||
if (ServerBootSFG.unsuportedversion) {
|
||||
Iris.safeguard(C.RED + "Server Version");
|
||||
Iris.safeguard(C.RED + "- Iris only supports 1.19.2 > 1.21.1");
|
||||
}
|
||||
if (!ServerBootSFG.passedserversoftware) {
|
||||
Iris.safeguard(C.YELLOW + "Unsupported Server Software");
|
||||
Iris.safeguard(C.YELLOW + "- Please consider using Paper or Purpur instead.");
|
||||
}
|
||||
if (!ServerBootSFG.hasPrivileges) {
|
||||
Iris.safeguard(C.YELLOW + "Insufficient Privileges");
|
||||
Iris.safeguard(C.YELLOW + "- The server has insufficient Privileges to run iris. Please contact support.");
|
||||
}
|
||||
if (!ServerBootSFG.hasEnoughDiskSpace) {
|
||||
Iris.safeguard(C.YELLOW + "Insufficient Disk Space");
|
||||
Iris.safeguard(C.YELLOW + "- The server has insufficient Free DiskSpace to run iris required 3GB+.");
|
||||
}
|
||||
if (!ServerBootSFG.isJDK17) {
|
||||
Iris.safeguard(C.YELLOW + "Unsupported java version");
|
||||
Iris.safeguard(C.YELLOW + "- Please consider using JDK 17 (or 21 for 1.20.6) Instead of JDK " + Iris.getJavaVersion());
|
||||
}
|
||||
if (ServerBootSFG.isJRE) {
|
||||
Iris.safeguard(C.YELLOW + "Unsupported Server JDK");
|
||||
Iris.safeguard(C.YELLOW + "- Please consider using JDK 17 (or 21 for 1.20.6) Instead of JRE " + Iris.getJavaVersion());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static String MSGIncompatibleWarnings() {
|
||||
return ServerBootSFG.allIncompatibilities;
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@
|
||||
package com.volmit.iris.core.service;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.loader.IrisData;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
@@ -124,6 +125,7 @@ public class BoardSVC implements IrisService, BoardProvider {
|
||||
int y = player.getLocation().getBlockY() - player.getWorld().getMinHeight();
|
||||
int z = player.getLocation().getBlockZ();
|
||||
|
||||
|
||||
lines.add("&7&m ");
|
||||
lines.add(C.GREEN + "Speed" + C.GRAY + ": " + Form.f(engine.getGeneratedPerSecond(), 0) + "/s " + Form.duration(1000D / engine.getGeneratedPerSecond(), 0));
|
||||
lines.add(C.AQUA + "Cache" + C.GRAY + ": " + Form.f(IrisData.cacheSize()));
|
||||
@@ -131,10 +133,11 @@ public class BoardSVC implements IrisService, BoardProvider {
|
||||
lines.add("&7&m ");
|
||||
lines.add(C.AQUA + "Region" + C.GRAY + ": " + engine.getRegion(x, z).getName());
|
||||
lines.add(C.AQUA + "Biome" + C.GRAY + ": " + engine.getBiomeOrMantle(x, y, z).getName());
|
||||
lines.add(C.AQUA + "Height" + C.GRAY + ": " + Math.round(engine.getHeight(x, z) + player.getWorld().getMinHeight()));
|
||||
lines.add(C.AQUA + "Height" + C.GRAY + ": " + Math.round(engine.getHeight(x, z)));
|
||||
lines.add(C.AQUA + "Slope" + C.GRAY + ": " + Form.f(engine.getComplex().getSlopeStream().get(x, z), 2));
|
||||
lines.add(C.AQUA + "BUD/s" + C.GRAY + ": " + Form.f(engine.getBlockUpdatesPerSecond()));
|
||||
lines.add("&7&m ");
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,163 +0,0 @@
|
||||
package com.volmit.iris.core.service;
|
||||
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerMoveEvent;
|
||||
import org.bukkit.event.world.ChunkLoadEvent;
|
||||
import org.bukkit.event.world.ChunkUnloadEvent;
|
||||
import org.bukkit.event.world.WorldLoadEvent;
|
||||
import org.bukkit.event.world.WorldUnloadEvent;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
public class ChunkHandlerSVC implements Listener {
|
||||
// Idk how it works but it works lol
|
||||
private final JavaPlugin plugin;
|
||||
private static BukkitTask task;
|
||||
private final Map<World, ChunkUnloader> worlds = new ConcurrentHashMap<>();
|
||||
|
||||
private static final Map<Chunk, Set<Player>> playersInChunk = new ConcurrentHashMap<>();
|
||||
|
||||
public ChunkHandlerSVC(JavaPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
Bukkit.getPluginManager().registerEvents(this, plugin);
|
||||
|
||||
for (World world : Bukkit.getWorlds()) {
|
||||
if (IrisToolbelt.isIrisWorld(world)) {
|
||||
worlds.put(world, new ChunkUnloader(plugin, world));
|
||||
}
|
||||
}
|
||||
|
||||
startTask();
|
||||
}
|
||||
|
||||
private void startTask() {
|
||||
if (task == null) {
|
||||
task = new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
worlds.values().forEach(ChunkUnloader::update);
|
||||
}
|
||||
}.runTaskTimerAsynchronously(plugin, 0L, 1L);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerMove(PlayerMoveEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
Chunk previousChunk = event.getFrom().getChunk();
|
||||
Chunk currentChunk = event.getTo().getChunk();
|
||||
|
||||
if (!previousChunk.equals(currentChunk)) {
|
||||
playersInChunk.computeIfAbsent(previousChunk, k -> ConcurrentHashMap.newKeySet()).remove(player);
|
||||
playersInChunk.computeIfAbsent(currentChunk, k -> ConcurrentHashMap.newKeySet()).add(player);
|
||||
}
|
||||
}
|
||||
|
||||
public static void exit() {
|
||||
if (task != null) {
|
||||
task.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onWorldLoad(WorldLoadEvent event) {
|
||||
World world = event.getWorld();
|
||||
if (IrisToolbelt.isIrisWorld(world)) {
|
||||
worlds.put(world, new ChunkUnloader(plugin, world));
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onWorldUnload(WorldUnloadEvent event) {
|
||||
worlds.remove(event.getWorld());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onChunkLoad(ChunkLoadEvent event) {
|
||||
World world = event.getWorld();
|
||||
if (worlds.containsKey(world)) {
|
||||
worlds.get(world).onChunkLoad(event.getChunk());
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onChunkUnload(ChunkUnloadEvent event) {
|
||||
World world = event.getWorld();
|
||||
if (worlds.containsKey(world)) {
|
||||
worlds.get(world).onChunkUnload(event.getChunk());
|
||||
}
|
||||
}
|
||||
|
||||
private static class ChunkUnloader {
|
||||
private final JavaPlugin plugin;
|
||||
private final World world;
|
||||
private final Map<Chunk, Long> chunks = new ConcurrentHashMap<>();
|
||||
|
||||
private ChunkUnloader(JavaPlugin plugin, World world) {
|
||||
this.plugin = plugin;
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
public void onChunkLoad(Chunk chunk) {
|
||||
// System.out.printf("%s > Loaded Chunk [x=%s, z=%s]%n", world.getName(), chunk.getX(), chunk.getZ());
|
||||
chunks.put(chunk, System.currentTimeMillis() + TimeUnit.MINUTES.toMillis(3));
|
||||
}
|
||||
|
||||
public void onChunkUnload(Chunk chunk) {
|
||||
chunks.remove(chunk);
|
||||
playersInChunk.remove(chunk);
|
||||
}
|
||||
|
||||
public void update() {
|
||||
try {
|
||||
long currentTime = System.currentTimeMillis();
|
||||
Set<Chunk> chunkSet = new HashSet<>(chunks.keySet());
|
||||
for (Chunk chunk : chunkSet) {
|
||||
if (!chunk.isLoaded()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isChunkNearby(chunk)) {
|
||||
chunks.put(chunk, currentTime + TimeUnit.MINUTES.toMillis(3));
|
||||
} else if (chunks.get(chunk) <= currentTime) {
|
||||
unloadChunk(chunk);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Log the error message
|
||||
System.out.println("Error in update method: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private boolean isChunkNearby(Chunk chunk) {
|
||||
Set<Player> players = playersInChunk.get(chunk);
|
||||
if (players == null) {
|
||||
players = ConcurrentHashMap.newKeySet();
|
||||
playersInChunk.put(chunk, players);
|
||||
}
|
||||
return !players.isEmpty();
|
||||
}
|
||||
|
||||
private void unloadChunk(Chunk chunk) {
|
||||
try {
|
||||
// System.out.printf("%s > Unloading Chunk [x=%s, z=%s]%n", world.getName(), chunk.getX(), chunk.getZ());
|
||||
Bukkit.getScheduler().runTask(plugin, () -> chunk.unload(true));
|
||||
} catch (Exception e) {
|
||||
System.out.println("Error unloading chunk: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,9 +20,12 @@ package com.volmit.iris.core.service;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
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.*;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.function.Consumer2;
|
||||
import com.volmit.iris.util.io.Converter;
|
||||
@@ -37,13 +40,16 @@ import com.volmit.iris.util.nbt.tag.ListTag;
|
||||
import com.volmit.iris.util.plugin.IrisService;
|
||||
import com.volmit.iris.util.plugin.VolmitSender;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.block.data.type.Jigsaw;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class ConversionSVC implements IrisService {
|
||||
private KList<Converter> converters;
|
||||
@@ -122,7 +128,7 @@ public class ConversionSVC implements IrisService {
|
||||
@SuppressWarnings("unchecked") ListTag<CompoundTag> paletteList = (ListTag<CompoundTag>) compound.getListTag("palette");
|
||||
for (int i = 0; i < paletteList.size(); i++) {
|
||||
CompoundTag cp = paletteList.get(i);
|
||||
palette.add(NBTWorld.getBlockData(cp));
|
||||
palette.add(INMS.get().getBlockData(cp));
|
||||
}
|
||||
IrisJigsawPiece piece = new IrisJigsawPiece();
|
||||
IrisObject object = new IrisObject(w, h, d);
|
||||
@@ -135,20 +141,37 @@ public class ConversionSVC implements IrisService {
|
||||
int z = pos.get(2).asInt();
|
||||
BlockData bd = palette.get(cp.getInt("state")).clone();
|
||||
|
||||
piece.setObject(in.toURI().relativize(folder.toURI()).getPath() + file.getName().split("\\Q.\\E")[0]);
|
||||
if (bd.getMaterial().equals(Material.JIGSAW) && cp.containsKey("nbt")) {
|
||||
piece.setObject(in.toURI().relativize(folder.toURI()).getPath() + file.getName().split("\\Q.\\E")[0]);
|
||||
//.setObject(in.toURI().relativize(folder.toURI()).getPath() + file.getName().split("\\Q.\\E")[0]);
|
||||
IrisPosition spos = new IrisPosition(object.getSigned(x, y, z));
|
||||
CompoundTag nbt = cp.getCompoundTag("nbt");
|
||||
CompoundTag finalState = new CompoundTag();
|
||||
finalState.putString("Name", nbt.getString("final_state"));
|
||||
BlockData jd = bd.clone();
|
||||
bd = NBTWorld.getBlockData(finalState);
|
||||
bd = INMS.get().getBlockData(finalState);
|
||||
String joint = nbt.getString("joint");
|
||||
String pool = nbt.getString("pool");
|
||||
String poolId = toPoolName(pool);
|
||||
String name = nbt.getString("name");
|
||||
String target = nbt.getString("target");
|
||||
pools.computeIfAbsent(poolId, (k) -> new IrisJigsawPool());
|
||||
pools.computeIfAbsent(poolId, (k) -> {
|
||||
IrisJigsawPool irisPool = new IrisJigsawPool();
|
||||
|
||||
String basePath = in.toURI().relativize(folder.toURI()).getPath();
|
||||
File baseFolder = new File(in.toURI().relativize(folder.toURI()).toString());
|
||||
String[] paths = FileUtils.listFiles(folder, null, true)
|
||||
.stream()
|
||||
.map(path -> path.getPath().replaceAll("\\.nbt$", "")).toArray(String[]::new);
|
||||
|
||||
KList<String> poolList = new KList<>();
|
||||
for (int ii = 0; ii < Objects.requireNonNull(paths).length; ii++) {
|
||||
String lastSegment = paths[ii].substring(paths[ii].lastIndexOf("\\") + 1);
|
||||
poolList.add(basePath + lastSegment);
|
||||
}
|
||||
irisPool.setPieces(poolList);
|
||||
return irisPool;
|
||||
});
|
||||
IrisJigsawPieceConnector connector = new IrisJigsawPieceConnector();
|
||||
connector.setName(name);
|
||||
connector.setTargetName(target);
|
||||
@@ -169,10 +192,14 @@ public class ConversionSVC implements IrisService {
|
||||
}
|
||||
}
|
||||
|
||||
if (piece.getObject().isBlank() || piece.getObject().isEmpty()) {
|
||||
Iris.info(C.RED + "Failed Setting object with path: " + in.toURI().relativize(folder.toURI()).getPath() + file.getName().split("\\Q.\\E")[0]);
|
||||
}
|
||||
jpool.getPieces().addIfMissing(id);
|
||||
object.write(new File(destObjects, file.getName().split("\\Q.\\E")[0] + ".iob"));
|
||||
IO.writeAll(new File(destPieces, file.getName().split("\\Q.\\E")[0] + ".json"), new JSONObject(new Gson().toJson(piece)).toString(4));
|
||||
Iris.info("[Jigsaw]: (" + Form.pc((double) at.get() / (double) total.get(), 0) + ") Exported Piece: " + id);
|
||||
Iris.info("[Jigsaw]: (" + Form.pc((double) at.get() / (double) total.get(), 0).replace("%", "%%") + ") Exported Piece: " + id);
|
||||
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
|
||||
@@ -1,93 +0,0 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.service;
|
||||
|
||||
import com.volmit.iris.core.nms.INMS;
|
||||
import com.volmit.iris.core.nms.container.BlockPos;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.util.documentation.ChunkCoordinates;
|
||||
import com.volmit.iris.util.function.Consumer4;
|
||||
import com.volmit.iris.util.math.Spiraler;
|
||||
import com.volmit.iris.util.matter.MatterStructurePOI;
|
||||
import com.volmit.iris.util.plugin.IrisService;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.SoundCategory;
|
||||
import org.bukkit.entity.Dolphin;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.player.PlayerInteractEntityEvent;
|
||||
import org.bukkit.generator.structure.StructureType;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
public class DolphinSVC implements IrisService {
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void on(PlayerInteractEntityEvent event) {
|
||||
if (!IrisToolbelt.isIrisWorld(event.getPlayer().getWorld())) {
|
||||
return;
|
||||
}
|
||||
|
||||
Material hand = event.getPlayer().getInventory().getItem(event.getHand()).getType();
|
||||
if (event.getRightClicked().getType().equals(EntityType.DOLPHIN) && (hand.equals(Material.TROPICAL_FISH) || hand.equals(Material.PUFFERFISH) || hand.equals(Material.COD) || hand.equals(Material.SALMON))) {
|
||||
Engine e = IrisToolbelt.access(event.getPlayer().getWorld()).getEngine();
|
||||
searchNearestTreasure(e, event.getPlayer().getLocation().getBlockX() >> 4, event.getPlayer().getLocation().getBlockZ() >> 4, e.getMantle().getRadius() - 1, StructureType.BURIED_TREASURE, (x, y, z, p) -> {
|
||||
event.setCancelled(true);
|
||||
Dolphin d = (Dolphin) event.getRightClicked();
|
||||
INMS.get().setTreasurePos(d, new BlockPos(x, y, z));
|
||||
d.getWorld().playSound(d, Sound.ENTITY_DOLPHIN_EAT, SoundCategory.NEUTRAL, 1, 1);
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ChunkCoordinates
|
||||
public void findTreasure(Engine engine, int chunkX, int chunkY, StructureType type, Consumer4<Integer, Integer, Integer, MatterStructurePOI> consumer) {
|
||||
AtomicReference<MatterStructurePOI> ref = new AtomicReference<>();
|
||||
engine.getMantle().getMantle().iterateChunk(chunkX, chunkY, MatterStructurePOI.class, ref.get() == null ? (x, y, z, d) -> {
|
||||
if (d.getType().equals(type.getKey().getKey())) {
|
||||
ref.set(d);
|
||||
consumer.accept(x, y, z, d);
|
||||
}
|
||||
} : (x, y, z, d) -> {
|
||||
});
|
||||
}
|
||||
|
||||
@ChunkCoordinates
|
||||
public void searchNearestTreasure(Engine engine, int chunkX, int chunkY, int radius, StructureType type, Consumer4<Integer, Integer, Integer, MatterStructurePOI> consumer) {
|
||||
AtomicReference<MatterStructurePOI> ref = new AtomicReference<>();
|
||||
new Spiraler(radius * 2, radius * 2, (x, z) -> findTreasure(engine, x, z, type, ref.get() == null ? (i, d, g, a) -> {
|
||||
ref.set(a);
|
||||
consumer.accept(i, d, g, a);
|
||||
} : (i, d, g, a) -> {
|
||||
})).setOffset(chunkX, chunkY).drain();
|
||||
}
|
||||
}
|
||||
@@ -1,119 +1,174 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.service;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.link.*;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.plugin.IrisService;
|
||||
import lombok.Data;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.server.PluginEnableEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.Optional;
|
||||
|
||||
@Data
|
||||
public class ExternalDataSVC implements IrisService {
|
||||
|
||||
private KList<ExternalDataProvider> providers = new KList<>(), activeProviders = new KList<>();
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
Iris.info("Loading ExternalDataProvider...");
|
||||
Bukkit.getPluginManager().registerEvents(this, Iris.instance);
|
||||
|
||||
providers.add(new OraxenDataProvider());
|
||||
if (Bukkit.getPluginManager().getPlugin("Oraxen") != null) {
|
||||
Iris.info("Oraxen found, loading OraxenDataProvider...");
|
||||
}
|
||||
providers.add(new ItemAdderDataProvider());
|
||||
if (Bukkit.getPluginManager().getPlugin("ItemAdder") != null) {
|
||||
Iris.info("ItemAdder found, loading ItemAdderDataProvider...");
|
||||
}
|
||||
providers.add(new ExecutableItemsDataProvider());
|
||||
if (Bukkit.getPluginManager().getPlugin("ExecutableItems") != null) {
|
||||
Iris.info("ExecutableItems found, loading ExecutableItemsDataProvider...");
|
||||
}
|
||||
|
||||
for (ExternalDataProvider p : providers) {
|
||||
if (p.isReady()) {
|
||||
activeProviders.add(p);
|
||||
p.init();
|
||||
Iris.info("Enabled ExternalDataProvider for %s.", p.getPluginId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPluginEnable(PluginEnableEvent e) {
|
||||
if (activeProviders.stream().noneMatch(p -> p.getPlugin().equals(e.getPlugin()))) {
|
||||
providers.stream().filter(p -> p.isReady() && p.getPlugin().equals(e.getPlugin())).findFirst().ifPresent(edp -> {
|
||||
activeProviders.add(edp);
|
||||
edp.init();
|
||||
Iris.info("Enabled ExternalDataProvider for %s.", edp.getPluginId());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public Optional<BlockData> getBlockData(Identifier key) {
|
||||
Optional<ExternalDataProvider> provider = activeProviders.stream().filter(p -> p.isValidProvider(key, false)).findFirst();
|
||||
if (provider.isEmpty())
|
||||
return Optional.empty();
|
||||
try {
|
||||
return Optional.of(provider.get().getBlockData(key));
|
||||
} catch (MissingResourceException e) {
|
||||
Iris.error(e.getMessage() + " - [" + e.getClassName() + ":" + e.getKey() + "]");
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
public Optional<ItemStack> getItemStack(Identifier key) {
|
||||
Optional<ExternalDataProvider> provider = activeProviders.stream().filter(p -> p.isValidProvider(key, true)).findFirst();
|
||||
if (provider.isEmpty()) {
|
||||
Iris.warn("No matching Provider found for modded material \"%s\"!", key);
|
||||
return Optional.empty();
|
||||
}
|
||||
try {
|
||||
return Optional.of(provider.get().getItemStack(key));
|
||||
} catch (MissingResourceException e) {
|
||||
Iris.error(e.getMessage() + " - [" + e.getClassName() + ":" + e.getKey() + "]");
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
public Identifier[] getAllBlockIdentifiers() {
|
||||
KList<Identifier> names = new KList<>();
|
||||
activeProviders.forEach(p -> names.add(p.getBlockTypes()));
|
||||
return names.toArray(new Identifier[0]);
|
||||
}
|
||||
|
||||
public Identifier[] getAllItemIdentifiers() {
|
||||
KList<Identifier> names = new KList<>();
|
||||
activeProviders.forEach(p -> names.add(p.getItemTypes()));
|
||||
return names.toArray(new Identifier[0]);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.service;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.link.*;
|
||||
import com.volmit.iris.core.nms.container.Pair;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.plugin.IrisService;
|
||||
import lombok.Data;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.server.PluginEnableEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Data
|
||||
public class ExternalDataSVC implements IrisService {
|
||||
|
||||
private KList<ExternalDataProvider> providers = new KList<>(), activeProviders = new KList<>();
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
Iris.info("Loading ExternalDataProvider...");
|
||||
Bukkit.getPluginManager().registerEvents(this, Iris.instance);
|
||||
|
||||
providers.add(new OraxenDataProvider());
|
||||
if (Bukkit.getPluginManager().getPlugin("Oraxen") != null) {
|
||||
Iris.info("Oraxen found, loading OraxenDataProvider...");
|
||||
}
|
||||
providers.add(new MythicCrucibleDataProvider());
|
||||
if (Bukkit.getPluginManager().getPlugin("MythicCrucible") != null) {
|
||||
Iris.info("MythicCrucible found, loading MythicCrucibleDataProvider...");
|
||||
}
|
||||
providers.add(new ItemAdderDataProvider());
|
||||
if (Bukkit.getPluginManager().getPlugin("ItemAdder") != null) {
|
||||
Iris.info("ItemAdder found, loading ItemAdderDataProvider...");
|
||||
}
|
||||
providers.add(new ExecutableItemsDataProvider());
|
||||
if (Bukkit.getPluginManager().getPlugin("ExecutableItems") != null) {
|
||||
Iris.info("ExecutableItems found, loading ExecutableItemsDataProvider...");
|
||||
}
|
||||
providers.add(new HMCLeavesDataProvider());
|
||||
if (Bukkit.getPluginManager().getPlugin("HMCLeaves") != null) {
|
||||
Iris.info("BlockAdder found, loading HMCLeavesDataProvider...");
|
||||
}
|
||||
providers.add(new MMOItemsDataProvider());
|
||||
if (Bukkit.getPluginManager().getPlugin("MMOItems") != null) {
|
||||
Iris.info("MMOItems found, loading MMOItemsDataProvider...");
|
||||
}
|
||||
providers.add(new EcoItemsDataProvider());
|
||||
if (Bukkit.getPluginManager().getPlugin("EcoItems") != null) {
|
||||
Iris.info("EcoItems found, loading EcoItemsDataProvider...");
|
||||
}
|
||||
|
||||
for (ExternalDataProvider p : providers) {
|
||||
if (p.isReady()) {
|
||||
activeProviders.add(p);
|
||||
p.init();
|
||||
Iris.info("Enabled ExternalDataProvider for %s.", p.getPluginId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPluginEnable(PluginEnableEvent e) {
|
||||
if (activeProviders.stream().noneMatch(p -> p.getPlugin().equals(e.getPlugin()))) {
|
||||
providers.stream().filter(p -> p.isReady() && p.getPlugin().equals(e.getPlugin())).findFirst().ifPresent(edp -> {
|
||||
activeProviders.add(edp);
|
||||
edp.init();
|
||||
Iris.info("Enabled ExternalDataProvider for %s.", edp.getPluginId());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public Optional<BlockData> getBlockData(final Identifier key) {
|
||||
var pair = parseState(key);
|
||||
Identifier mod = pair.getA();
|
||||
|
||||
Optional<ExternalDataProvider> provider = activeProviders.stream().filter(p -> p.isValidProvider(mod, false)).findFirst();
|
||||
if (provider.isEmpty())
|
||||
return Optional.empty();
|
||||
try {
|
||||
return Optional.of(provider.get().getBlockData(mod, pair.getB()));
|
||||
} catch (MissingResourceException e) {
|
||||
Iris.error(e.getMessage() + " - [" + e.getClassName() + ":" + e.getKey() + "]");
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
public Optional<ItemStack> getItemStack(Identifier key, KMap<String, Object> customNbt) {
|
||||
Optional<ExternalDataProvider> provider = activeProviders.stream().filter(p -> p.isValidProvider(key, true)).findFirst();
|
||||
if (provider.isEmpty()) {
|
||||
Iris.warn("No matching Provider found for modded material \"%s\"!", key);
|
||||
return Optional.empty();
|
||||
}
|
||||
try {
|
||||
return Optional.of(provider.get().getItemStack(key, customNbt));
|
||||
} catch (MissingResourceException e) {
|
||||
Iris.error(e.getMessage() + " - [" + e.getClassName() + ":" + e.getKey() + "]");
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
public void processUpdate(Engine engine, Block block, Identifier blockId) {
|
||||
Optional<ExternalDataProvider> provider = activeProviders.stream().filter(p -> p.isValidProvider(blockId, false)).findFirst();
|
||||
if (provider.isEmpty()) {
|
||||
Iris.warn("No matching Provider found for modded material \"%s\"!", blockId);
|
||||
return;
|
||||
}
|
||||
provider.get().processUpdate(engine, block, blockId);
|
||||
}
|
||||
|
||||
public Identifier[] getAllBlockIdentifiers() {
|
||||
KList<Identifier> names = new KList<>();
|
||||
activeProviders.forEach(p -> names.add(p.getBlockTypes()));
|
||||
return names.toArray(new Identifier[0]);
|
||||
}
|
||||
|
||||
public Identifier[] getAllItemIdentifiers() {
|
||||
KList<Identifier> names = new KList<>();
|
||||
activeProviders.forEach(p -> names.add(p.getItemTypes()));
|
||||
return names.toArray(new Identifier[0]);
|
||||
}
|
||||
|
||||
public static Pair<Identifier, KMap<String, String>> parseState(Identifier key) {
|
||||
if (!key.key().contains("[") || !key.key().contains("]")) {
|
||||
return new Pair<>(key, new KMap<>());
|
||||
}
|
||||
String state = key.key().split("\\Q[\\E")[1].split("\\Q]\\E")[0];
|
||||
KMap<String, String> stateMap = new KMap<>();
|
||||
if (!state.isEmpty()) {
|
||||
Arrays.stream(state.split(",")).forEach(s -> stateMap.put(s.split("=")[0], s.split("=")[1]));
|
||||
}
|
||||
return new Pair<>(new Identifier(key.namespace(), key.key().split("\\Q[\\E")[0]), stateMap);
|
||||
}
|
||||
|
||||
public static Identifier buildState(Identifier key, KMap<String, String> state) {
|
||||
if (state.isEmpty()) {
|
||||
return key;
|
||||
}
|
||||
String path = state.entrySet()
|
||||
.stream()
|
||||
.map(e -> e.getKey() + "=" + e.getValue())
|
||||
.collect(Collectors.joining(",", key.key() + "[", "]"));
|
||||
return new Identifier(key.namespace(), path);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,317 @@
|
||||
package com.volmit.iris.core.service;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.platform.PlatformChunkGenerator;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.mantle.TectonicPlate;
|
||||
import com.volmit.iris.util.misc.getHardware;
|
||||
import com.volmit.iris.util.plugin.IrisService;
|
||||
import com.volmit.iris.util.scheduling.ChronoLatch;
|
||||
import com.volmit.iris.util.scheduling.Looper;
|
||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.server.PluginDisableEvent;
|
||||
import org.bukkit.event.server.ServerLoadEvent;
|
||||
import org.bukkit.event.world.WorldLoadEvent;
|
||||
import org.bukkit.event.world.WorldUnloadEvent;
|
||||
import org.checkerframework.checker.units.qual.A;
|
||||
|
||||
import java.util.*;
|
||||
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.function.Supplier;
|
||||
|
||||
public class IrisEngineSVC implements IrisService {
|
||||
public static IrisEngineSVC instance;
|
||||
public boolean isServerShuttingDown = false;
|
||||
public boolean isServerLoaded = false;
|
||||
private static final AtomicInteger tectonicLimit = new AtomicInteger(30);
|
||||
private ReentrantLock lastUseLock;
|
||||
private KMap<World, Long> lastUse;
|
||||
private List<World> IrisWorlds;
|
||||
private Looper cacheTicker;
|
||||
private Looper trimTicker;
|
||||
private Looper unloadTicker;
|
||||
private Looper updateTicker;
|
||||
private PrecisionStopwatch trimAlive;
|
||||
private PrecisionStopwatch unloadAlive;
|
||||
public PrecisionStopwatch trimActiveAlive;
|
||||
public PrecisionStopwatch unloadActiveAlive;
|
||||
private AtomicInteger TotalTectonicPlates;
|
||||
private AtomicInteger TotalQueuedTectonicPlates;
|
||||
private AtomicInteger TotalNotQueuedTectonicPlates;
|
||||
private AtomicBoolean IsUnloadAlive;
|
||||
private AtomicBoolean IsTrimAlive;
|
||||
ChronoLatch cl;
|
||||
|
||||
public List<World> corruptedIrisWorlds = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
this.cl = new ChronoLatch(5000);
|
||||
lastUse = new KMap<>();
|
||||
lastUseLock = new ReentrantLock();
|
||||
IrisWorlds = new ArrayList<>();
|
||||
IsUnloadAlive = new AtomicBoolean(true);
|
||||
IsTrimAlive = new AtomicBoolean(true);
|
||||
trimActiveAlive = new PrecisionStopwatch();
|
||||
unloadActiveAlive = new PrecisionStopwatch();
|
||||
trimAlive = new PrecisionStopwatch();
|
||||
unloadAlive = new PrecisionStopwatch();
|
||||
TotalTectonicPlates = new AtomicInteger();
|
||||
TotalQueuedTectonicPlates = new AtomicInteger();
|
||||
TotalNotQueuedTectonicPlates = new AtomicInteger();
|
||||
tectonicLimit.set(2);
|
||||
long t = getHardware.getProcessMemory();
|
||||
while (t > 200) {
|
||||
tectonicLimit.getAndAdd(1);
|
||||
t = t - 200;
|
||||
}
|
||||
this.setup();
|
||||
this.TrimLogic();
|
||||
this.UnloadLogic();
|
||||
|
||||
trimAlive.begin();
|
||||
unloadAlive.begin();
|
||||
trimActiveAlive.begin();
|
||||
unloadActiveAlive.begin();
|
||||
|
||||
updateTicker.start();
|
||||
cacheTicker.start();
|
||||
//trimTicker.start();
|
||||
//unloadTicker.start();
|
||||
instance = this;
|
||||
|
||||
}
|
||||
|
||||
public void engineStatus() {
|
||||
boolean trimAlive = trimTicker.isAlive();
|
||||
boolean unloadAlive = unloadTicker.isAlive();
|
||||
Iris.info("Status:");
|
||||
Iris.info("- Trim: " + trimAlive);
|
||||
Iris.info("- Unload: " + unloadAlive);
|
||||
|
||||
}
|
||||
|
||||
public static int getTectonicLimit() {
|
||||
return tectonicLimit.get();
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onWorldUnload(WorldUnloadEvent event) {
|
||||
updateWorlds();
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onWorldLoad(WorldLoadEvent event) {
|
||||
updateWorlds();
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onServerBoot(ServerLoadEvent event) {
|
||||
isServerLoaded = true;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPluginDisable(PluginDisableEvent event) {
|
||||
if (event.getPlugin().equals(Iris.instance)) {
|
||||
isServerShuttingDown = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void updateWorlds() {
|
||||
for (World world : Bukkit.getWorlds()) {
|
||||
try {
|
||||
if (IrisToolbelt.access(world).getEngine() != null) {
|
||||
IrisWorlds.add(world);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// no
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setup() {
|
||||
cacheTicker = new Looper() {
|
||||
@Override
|
||||
protected long loop() {
|
||||
long now = System.currentTimeMillis();
|
||||
lastUseLock.lock();
|
||||
try {
|
||||
for (World key : new ArrayList<>(lastUse.keySet())) {
|
||||
Long last = lastUse.get(key);
|
||||
if (last == null)
|
||||
continue;
|
||||
if (now - last > 60000) {
|
||||
lastUse.remove(key);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
lastUseLock.unlock();
|
||||
}
|
||||
return 1000;
|
||||
}
|
||||
};
|
||||
|
||||
updateTicker = new Looper() {
|
||||
@Override
|
||||
protected long loop() {
|
||||
try {
|
||||
TotalQueuedTectonicPlates.set(0);
|
||||
TotalNotQueuedTectonicPlates.set(0);
|
||||
TotalTectonicPlates.set(0);
|
||||
for (World world : IrisWorlds) {
|
||||
Engine engine = Objects.requireNonNull(IrisToolbelt.access(world)).getEngine();
|
||||
TotalQueuedTectonicPlates.addAndGet((int) engine.getMantle().getToUnload());
|
||||
TotalNotQueuedTectonicPlates.addAndGet((int) engine.getMantle().getNotQueuedLoadedRegions());
|
||||
TotalTectonicPlates.addAndGet(engine.getMantle().getLoadedRegionCount());
|
||||
}
|
||||
if (!isServerShuttingDown && isServerLoaded) {
|
||||
if (!trimTicker.isAlive()) {
|
||||
Iris.info(C.RED + "TrimTicker found dead! Booting it up!");
|
||||
try {
|
||||
TrimLogic();
|
||||
} catch (Exception e) {
|
||||
Iris.error("What happened?");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!unloadTicker.isAlive()) {
|
||||
Iris.info(C.RED + "UnloadTicker found dead! Booting it up!");
|
||||
try {
|
||||
UnloadLogic();
|
||||
} catch (Exception e) {
|
||||
Iris.error("What happened?");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
return -1;
|
||||
}
|
||||
return 1000;
|
||||
}
|
||||
};
|
||||
}
|
||||
public void TrimLogic() {
|
||||
if (trimTicker == null || !trimTicker.isAlive()) {
|
||||
trimTicker = new Looper() {
|
||||
private final Supplier<Engine> supplier = createSupplier();
|
||||
|
||||
@Override
|
||||
protected long loop() {
|
||||
long start = System.currentTimeMillis();
|
||||
trimAlive.reset();
|
||||
try {
|
||||
Engine engine = supplier.get();
|
||||
if (engine != null) {
|
||||
engine.getMantle().trim(tectonicLimit.get() / lastUse.size());
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
Iris.info(C.RED + "EngineSVC: Failed to trim.");
|
||||
e.printStackTrace();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int size = lastUse.size();
|
||||
long time = (size > 0 ? 1000 / size : 1000) - (System.currentTimeMillis() - start);
|
||||
if (time <= 0)
|
||||
return 0;
|
||||
return time;
|
||||
}
|
||||
};
|
||||
trimTicker.start();
|
||||
}
|
||||
}
|
||||
public void UnloadLogic() {
|
||||
if (unloadTicker == null || !unloadTicker.isAlive()) {
|
||||
unloadTicker = new Looper() {
|
||||
private final Supplier<Engine> supplier = createSupplier();
|
||||
|
||||
@Override
|
||||
protected long loop() {
|
||||
long start = System.currentTimeMillis();
|
||||
unloadAlive.reset();
|
||||
try {
|
||||
Engine engine = supplier.get();
|
||||
if (engine != null) {
|
||||
long unloadStart = System.currentTimeMillis();
|
||||
int count = engine.getMantle().unloadTectonicPlate(tectonicLimit.get() / lastUse.size());
|
||||
if (count > 0) {
|
||||
Iris.debug(C.GOLD + "Unloaded " + C.YELLOW + count + " TectonicPlates in " + C.RED + Form.duration(System.currentTimeMillis() - unloadStart, 2));
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
Iris.info(C.RED + "EngineSVC: Failed to unload.");
|
||||
e.printStackTrace();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int size = lastUse.size();
|
||||
long time = (size > 0 ? 1000 / size : 1000) - (System.currentTimeMillis() - start);
|
||||
if (time <= 0)
|
||||
return 0;
|
||||
return time;
|
||||
}
|
||||
};
|
||||
unloadTicker.start();
|
||||
}
|
||||
}
|
||||
|
||||
private Supplier<Engine> createSupplier() {
|
||||
AtomicInteger i = new AtomicInteger();
|
||||
return () -> {
|
||||
List<World> worlds = Bukkit.getWorlds();
|
||||
if (i.get() >= worlds.size()) {
|
||||
i.set(0);
|
||||
}
|
||||
try {
|
||||
for (int j = 0; j < worlds.size(); j++) {
|
||||
World world = worlds.get(i.getAndIncrement());
|
||||
PlatformChunkGenerator generator = IrisToolbelt.access(world);
|
||||
if (i.get() >= worlds.size()) {
|
||||
i.set(0);
|
||||
}
|
||||
|
||||
if (generator != null) {
|
||||
Engine engine = generator.getEngine();
|
||||
boolean closed = engine.getMantle().getData().isClosed();
|
||||
if (engine != null && !engine.isStudio() && !closed) {
|
||||
lastUseLock.lock();
|
||||
lastUse.put(world, System.currentTimeMillis());
|
||||
lastUseLock.unlock();
|
||||
return engine;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
Iris.info(C.RED + "EngineSVC: Failed to create supplier.");
|
||||
e.printStackTrace();
|
||||
Iris.reportError(e);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
cacheTicker.interrupt();
|
||||
trimTicker.interrupt();
|
||||
unloadTicker.interrupt();
|
||||
lastUse.clear();
|
||||
}
|
||||
}
|
||||
@@ -232,7 +232,7 @@ public class StudioSVC implements IrisService {
|
||||
}
|
||||
|
||||
try {
|
||||
dir = zipFiles.length == 1 && zipFiles[0].isDirectory() ? zipFiles[0] : null;
|
||||
dir = zipFiles.length > 1 ? work : zipFiles[0].isDirectory() ? zipFiles[0] : null;
|
||||
} catch (NullPointerException e) {
|
||||
Iris.reportError(e);
|
||||
sender.sendMessage("Error when finding home directory. Are there any non-text characters in the file name?");
|
||||
|
||||
@@ -183,7 +183,7 @@ public class TreeSVC implements IrisService {
|
||||
}
|
||||
|
||||
@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) {
|
||||
|
||||
}
|
||||
|
||||
@@ -240,7 +240,7 @@ public class TreeSVC implements IrisService {
|
||||
boolean isUseAll = worldAccess.getEngine().getDimension().getTreeSettings().getMode().equals(IrisTreeModes.ALL);
|
||||
|
||||
// Retrieve objectPlacements of type `species` from biome
|
||||
IrisBiome biome = worldAccess.getEngine().getBiome(location.getBlockX(), location.getBlockY(), location.getBlockZ());
|
||||
IrisBiome biome = worldAccess.getEngine().getBiome(location.getBlockX(), location.getBlockY()-worldAccess.getTarget().getWorld().minHeight(), location.getBlockZ());
|
||||
placements.addAll(matchObjectPlacements(biome.getObjects(), size, type));
|
||||
|
||||
// Add more or find any in the region
|
||||
|
||||
@@ -1,127 +0,0 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.service;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.engine.object.IrisDimension;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.plugin.IrisService;
|
||||
import com.volmit.iris.util.plugin.VolmitSender;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.Villager;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.entity.VillagerCareerChangeEvent;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class VillageSVC implements IrisService {
|
||||
@Override
|
||||
public void onEnable() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void on(VillagerCareerChangeEvent event) {
|
||||
|
||||
if (!IrisToolbelt.isIrisWorld(event.getEntity().getWorld())) {
|
||||
return;
|
||||
}
|
||||
|
||||
IrisDimension dim = IrisToolbelt.access(event.getEntity().getWorld())
|
||||
.getEngine().getDimension();
|
||||
|
||||
if (!dim.isRemoveCartographersDueToCrash()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.getProfession().equals(Villager.Profession.CARTOGRAPHER)) {
|
||||
event.setCancelled(true);
|
||||
|
||||
Location eventLocation = event.getEntity().getLocation();
|
||||
|
||||
int radius = dim.getNotifyPlayersOfCartographerCancelledRadius();
|
||||
|
||||
if (radius == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<Player> playersInWorld = event.getEntity().getWorld().getPlayers();
|
||||
|
||||
String message = C.GOLD + IrisSettings.get().getGeneral().cartographerMessage;
|
||||
|
||||
Iris.info("Cancelled Cartographer Villager to prevent server crash at " + eventLocation + "!");
|
||||
|
||||
if (radius == -2) {
|
||||
playersInWorld.stream().map(VolmitSender::new).forEach(v -> v.sendMessage(message));
|
||||
} else {
|
||||
playersInWorld.forEach(p -> {
|
||||
if (p.getLocation().distance(eventLocation) < radius) {
|
||||
new VolmitSender(p).sendMessage(message);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Replace or disable villager trade add event to prevent explorer map
|
||||
*/
|
||||
/* Removed due to MC breaking stuff again. This event is now called after the cartographer maps are made,
|
||||
so it can fuck right off.
|
||||
@EventHandler
|
||||
public void on(VillagerAcquireTradeEvent event) {
|
||||
if(!IrisToolbelt.isIrisWorld((event.getEntity().getWorld()))) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Iris.info("Trade event: type " + event.getRecipe().getResult().getType() + " / meta " + event.getRecipe().getResult().getItemMeta() + " / data " + event.getRecipe().getResult().getData());
|
||||
if(!event.getRecipe().getResult().getType().equals(Material.FILLED_MAP)) {
|
||||
return;
|
||||
}
|
||||
|
||||
IrisVillagerOverride override = IrisToolbelt.access(event.getEntity().getWorld()).getEngine()
|
||||
.getDimension().getPatchCartographers();
|
||||
|
||||
if(override.isDisableTrade()) {
|
||||
event.setCancelled(true);
|
||||
Iris.debug("Cancelled cartographer trade @ " + event.getEntity().getLocation());
|
||||
return;
|
||||
}
|
||||
|
||||
if(override.getValidItems() == null) {
|
||||
event.setCancelled(true);
|
||||
Iris.debug("Cancelled cartographer trade because no override items are valid @ " + event.getEntity().getLocation());
|
||||
return;
|
||||
}
|
||||
|
||||
IrisVillagerTrade trade = override.getValidItems().getRandom();
|
||||
event.setRecipe(trade.convert());
|
||||
Iris.debug("Overrode cartographer trade with: " + trade + " to prevent allowing cartography map trades");
|
||||
}
|
||||
*/
|
||||
}
|
||||
@@ -30,9 +30,13 @@ import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.math.M;
|
||||
import com.volmit.iris.util.matter.Matter;
|
||||
import com.volmit.iris.util.matter.WorldMatter;
|
||||
import com.volmit.iris.util.misc.E;
|
||||
import com.volmit.iris.util.plugin.IrisService;
|
||||
import com.volmit.iris.util.plugin.VolmitSender;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import com.volmit.iris.util.scheduling.S;
|
||||
import com.volmit.iris.util.scheduling.SR;
|
||||
import com.volmit.iris.util.scheduling.jobs.Job;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
@@ -51,9 +55,16 @@ import org.bukkit.util.Vector;
|
||||
import java.awt.Color;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class WandSVC implements IrisService {
|
||||
private static final Particle CRIT_MAGIC = E.getOrDefault(Particle.class, "CRIT_MAGIC", "CRIT");
|
||||
private static final Particle REDSTONE = E.getOrDefault(Particle.class, "REDSTONE", "DUST");
|
||||
private static final int MS_PER_TICK = Integer.parseInt(System.getProperty("iris.ms_per_tick", "30"));
|
||||
|
||||
private static ItemStack dust;
|
||||
private static ItemStack wand;
|
||||
|
||||
public static void pasteSchematic(IrisObject s, Location at) {
|
||||
s.place(at);
|
||||
@@ -74,14 +85,81 @@ public class WandSVC implements IrisService {
|
||||
Location[] f = getCuboid(p);
|
||||
Cuboid c = new Cuboid(f[0], f[1]);
|
||||
IrisObject s = new IrisObject(c.getSizeX(), c.getSizeY(), c.getSizeZ());
|
||||
for (Block b : c) {
|
||||
if (b.getType().equals(Material.AIR)) {
|
||||
continue;
|
||||
|
||||
var it = c.chunkedIterator();
|
||||
|
||||
int total = c.getSizeX() * c.getSizeY() * c.getSizeZ();
|
||||
var latch = new CountDownLatch(1);
|
||||
new Job() {
|
||||
private int i;
|
||||
private Chunk chunk;
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Scanning Selection";
|
||||
}
|
||||
|
||||
BlockVector bv = b.getLocation().subtract(c.getLowerNE().toVector()).toVector().toBlockVector();
|
||||
s.setUnsigned(bv.getBlockX(), bv.getBlockY(), bv.getBlockZ(), b);
|
||||
}
|
||||
@Override
|
||||
public void execute() {
|
||||
new SR() {
|
||||
@Override
|
||||
public void run() {
|
||||
var time = M.ms() + MS_PER_TICK;
|
||||
while (time > M.ms()) {
|
||||
if (!it.hasNext()) {
|
||||
if (chunk != null) {
|
||||
chunk.removePluginChunkTicket(Iris.instance);
|
||||
chunk = null;
|
||||
}
|
||||
|
||||
cancel();
|
||||
latch.countDown();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
var b = it.next();
|
||||
var bChunk = b.getChunk();
|
||||
if (chunk == null) {
|
||||
chunk = bChunk;
|
||||
chunk.addPluginChunkTicket(Iris.instance);
|
||||
} else if (chunk != bChunk) {
|
||||
chunk.removePluginChunkTicket(Iris.instance);
|
||||
chunk = bChunk;
|
||||
}
|
||||
|
||||
if (b.getType().equals(Material.AIR))
|
||||
continue;
|
||||
|
||||
BlockVector bv = b.getLocation().subtract(c.getLowerNE().toVector()).toVector().toBlockVector();
|
||||
s.setUnsigned(bv.getBlockX(), bv.getBlockY(), bv.getBlockZ(), b);
|
||||
} finally {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
try {
|
||||
latch.await();
|
||||
} catch (InterruptedException ignored) {}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void completeWork() {}
|
||||
|
||||
@Override
|
||||
public int getTotalWork() {
|
||||
return total;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWorkCompleted() {
|
||||
return i;
|
||||
}
|
||||
}.execute(new VolmitSender(p), true, () -> {});
|
||||
try {
|
||||
latch.await();
|
||||
} catch (InterruptedException ignored) {}
|
||||
|
||||
return s;
|
||||
} catch (Throwable e) {
|
||||
@@ -161,11 +239,11 @@ public class WandSVC implements IrisService {
|
||||
*/
|
||||
public static ItemStack createDust() {
|
||||
ItemStack is = new ItemStack(Material.GLOWSTONE_DUST);
|
||||
is.addUnsafeEnchantment(Enchantment.ARROW_INFINITE, 1);
|
||||
is.addUnsafeEnchantment(Enchantment.FIRE_ASPECT, 1);
|
||||
ItemMeta im = is.getItemMeta();
|
||||
im.setDisplayName(C.BOLD + "" + C.YELLOW + "Dust of Revealing");
|
||||
im.setUnbreakable(true);
|
||||
im.addItemFlags(ItemFlag.HIDE_ATTRIBUTES, ItemFlag.HIDE_PLACED_ON, ItemFlag.HIDE_POTION_EFFECTS, ItemFlag.HIDE_DESTROYS, ItemFlag.HIDE_ENCHANTS);
|
||||
im.addItemFlags(ItemFlag.values());
|
||||
im.setLore(new KList<String>().qadd("Right click on a block to reveal it's placement structure!"));
|
||||
is.setItemMeta(im);
|
||||
|
||||
@@ -205,11 +283,11 @@ public class WandSVC implements IrisService {
|
||||
*/
|
||||
public static ItemStack createWand(Location a, Location b) {
|
||||
ItemStack is = new ItemStack(Material.BLAZE_ROD);
|
||||
is.addUnsafeEnchantment(Enchantment.ARROW_INFINITE, 1);
|
||||
is.addUnsafeEnchantment(Enchantment.FIRE_ASPECT, 1);
|
||||
ItemMeta im = is.getItemMeta();
|
||||
im.setDisplayName(C.BOLD + "" + C.GOLD + "Wand of Iris");
|
||||
im.setUnbreakable(true);
|
||||
im.addItemFlags(ItemFlag.HIDE_ATTRIBUTES, ItemFlag.HIDE_PLACED_ON, ItemFlag.HIDE_POTION_EFFECTS, ItemFlag.HIDE_DESTROYS, ItemFlag.HIDE_ENCHANTS);
|
||||
im.addItemFlags(ItemFlag.values());
|
||||
im.setLore(new KList<String>().add(locationToString(a), locationToString(b)));
|
||||
is.setItemMeta(im);
|
||||
|
||||
@@ -226,17 +304,19 @@ public class WandSVC implements IrisService {
|
||||
return getCuboidFromItem(p.getInventory().getItemInMainHand());
|
||||
}
|
||||
|
||||
Cuboid c = WorldEditLink.getSelection(p);
|
||||
if (IrisSettings.get().getWorld().worldEditWandCUI) {
|
||||
Cuboid c = WorldEditLink.getSelection(p);
|
||||
|
||||
if (c != null) {
|
||||
return new Location[]{c.getLowerNE(), c.getUpperSW()};
|
||||
if (c != null) {
|
||||
return new Location[]{c.getLowerNE(), c.getUpperSW()};
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static boolean isHoldingWand(Player p) {
|
||||
return isHoldingIrisWand(p) || WorldEditLink.getSelection(p) != null;
|
||||
return isHoldingIrisWand(p) || (IrisSettings.get().getWorld().worldEditWandCUI && WorldEditLink.getSelection(p) != null);
|
||||
}
|
||||
|
||||
public static boolean isHoldingIrisWand(Player p) {
|
||||
@@ -251,7 +331,6 @@ public class WandSVC implements IrisService {
|
||||
* @return True if it is
|
||||
*/
|
||||
public static boolean isWand(ItemStack is) {
|
||||
ItemStack wand = createWand();
|
||||
if (is.getItemMeta() == null) return false;
|
||||
return is.getType().equals(wand.getType()) &&
|
||||
is.getItemMeta().getDisplayName().equals(wand.getItemMeta().getDisplayName()) &&
|
||||
@@ -261,7 +340,7 @@ public class WandSVC implements IrisService {
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
ItemStack wand = createWand();
|
||||
wand = createWand();
|
||||
dust = createDust();
|
||||
|
||||
J.ar(() -> {
|
||||
@@ -309,9 +388,9 @@ public class WandSVC implements IrisService {
|
||||
*/
|
||||
public void draw(Location[] d, Player p) {
|
||||
Vector gx = Vector.getRandom().subtract(Vector.getRandom()).normalize().clone().multiply(0.65);
|
||||
d[0].getWorld().spawnParticle(Particle.CRIT_MAGIC, d[0], 1, 0.5 + gx.getX(), 0.5 + gx.getY(), 0.5 + gx.getZ(), 0, null, false);
|
||||
d[0].getWorld().spawnParticle(CRIT_MAGIC, d[0], 1, 0.5 + gx.getX(), 0.5 + gx.getY(), 0.5 + gx.getZ(), 0, null, false);
|
||||
Vector gxx = Vector.getRandom().subtract(Vector.getRandom()).normalize().clone().multiply(0.65);
|
||||
d[1].getWorld().spawnParticle(Particle.CRIT, d[1], 1, 0.5 + gxx.getX(), 0.5 + gxx.getY(), 0.5 + gxx.getZ(), 0, null, false);
|
||||
d[1].getWorld().spawnParticle(CRIT_MAGIC, d[1], 1, 0.5 + gxx.getX(), 0.5 + gxx.getY(), 0.5 + gxx.getZ(), 0, null, false);
|
||||
|
||||
if (!d[0].getWorld().equals(d[1].getWorld())) {
|
||||
return;
|
||||
@@ -368,7 +447,7 @@ public class WandSVC implements IrisService {
|
||||
int r = color.getRed();
|
||||
int g = color.getGreen();
|
||||
int b = color.getBlue();
|
||||
p.spawnParticle(Particle.REDSTONE, lv.getX(), lv.getY(), lv.getZ(), 1, 0, 0, 0, 0, new Particle.DustOptions(org.bukkit.Color.fromRGB(r, g, b), 0.75f));
|
||||
p.spawnParticle(REDSTONE, lv.getX(), lv.getY(), lv.getZ(), 1, 0, 0, 0, 0, new Particle.DustOptions(org.bukkit.Color.fromRGB(r, g, b), 0.75f));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -381,7 +460,7 @@ public class WandSVC implements IrisService {
|
||||
if (e.getHand() != EquipmentSlot.HAND)
|
||||
return;
|
||||
try {
|
||||
if (isHoldingWand(e.getPlayer())) {
|
||||
if (isHoldingIrisWand(e.getPlayer())) {
|
||||
if (e.getAction().equals(Action.LEFT_CLICK_BLOCK)) {
|
||||
e.setCancelled(true);
|
||||
e.getPlayer().getInventory().setItemInMainHand(update(true, Objects.requireNonNull(e.getClickedBlock()).getLocation(), e.getPlayer().getInventory().getItemInMainHand()));
|
||||
|
||||
@@ -28,7 +28,6 @@ import java.io.InputStreamReader;
|
||||
|
||||
import static com.google.common.math.LongMath.isPrime;
|
||||
import static com.volmit.iris.util.misc.getHardware.getCPUModel;
|
||||
import static com.volmit.iris.util.misc.getHardware.getDiskModel;
|
||||
public class IrisBenchmarking {
|
||||
static String ServerOS;
|
||||
static String filePath = "benchmark.dat";
|
||||
@@ -180,12 +179,12 @@ public class IrisBenchmarking {
|
||||
Iris.info("- Data Compression: " + formatDouble(calculateDataCompression) + " MBytes/Sec");
|
||||
|
||||
if (WindowsDiskSpeed) {
|
||||
Iris.info("Disk Model: " + getDiskModel());
|
||||
//Iris.info("Disk Model: " + getDiskModel());
|
||||
Iris.info(C.BLUE + "- Running with Windows System Assessment Tool");
|
||||
Iris.info("- Sequential 64.0 Write: " + C.BLUE + formatDouble(avgWriteSpeedMBps) + " Mbps");
|
||||
Iris.info("- Sequential 64.0 Read: " + C.BLUE + formatDouble(avgReadSpeedMBps) + " Mbps");
|
||||
} else {
|
||||
Iris.info("Disk Model: " + getDiskModel());
|
||||
// Iris.info("Disk Model: " + getDiskModel());
|
||||
Iris.info(C.GREEN + "- Running in Native Mode");
|
||||
Iris.info("- Average Write Speed: " + C.GREEN + formatDouble(avgWriteSpeedMBps) + " Mbps");
|
||||
Iris.info("- Average Read Speed: " + C.GREEN + formatDouble(avgReadSpeedMBps) + " Mbps");
|
||||
|
||||
202
core/src/main/java/com/volmit/iris/core/tools/IrisConverter.java
Normal file
202
core/src/main/java/com/volmit/iris/core/tools/IrisConverter.java
Normal file
@@ -0,0 +1,202 @@
|
||||
package com.volmit.iris.core.tools;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.engine.object.*;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.function.Consumer2;
|
||||
import com.volmit.iris.util.misc.E;
|
||||
import com.volmit.iris.util.nbt.io.NBTUtil;
|
||||
import com.volmit.iris.util.nbt.io.NamedTag;
|
||||
import com.volmit.iris.util.nbt.tag.*;
|
||||
import com.volmit.iris.util.plugin.VolmitSender;
|
||||
import com.volmit.iris.util.reflect.V;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.util.FileUtil;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
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;
|
||||
|
||||
public class IrisConverter {
|
||||
/**
|
||||
* Converts all schematics in the convert folder
|
||||
* @param sender
|
||||
*/
|
||||
public static void convertSchematics(VolmitSender sender) {
|
||||
File folder = Iris.instance.getDataFolder("convert");
|
||||
|
||||
FilenameFilter filter = (dir, name) -> name.endsWith(".schem");
|
||||
File[] fileList = folder.listFiles(filter);
|
||||
if (fileList == null) {
|
||||
sender.sendMessage("No schematic files to convert found in " + folder.getAbsolutePath());
|
||||
return;
|
||||
}
|
||||
ExecutorService executorService = Executors.newFixedThreadPool(1);
|
||||
executorService.submit(() -> {
|
||||
for (File schem : fileList) {
|
||||
try {
|
||||
PrecisionStopwatch p = PrecisionStopwatch.start();
|
||||
boolean largeObject = false;
|
||||
NamedTag tag = null;
|
||||
try {
|
||||
tag = NBTUtil.read(schem);
|
||||
} catch (IOException e) {
|
||||
Iris.info(C.RED + "Failed to read: " + schem.getName());
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
CompoundTag compound = (CompoundTag) tag.getTag();
|
||||
|
||||
if (compound.containsKey("Palette") && compound.containsKey("Width") && compound.containsKey("Height") && compound.containsKey("Length")) {
|
||||
int objW = ((ShortTag) compound.get("Width")).getValue();
|
||||
int objH = ((ShortTag) compound.get("Height")).getValue();
|
||||
int objD = ((ShortTag) compound.get("Length")).getValue();
|
||||
int i = -1;
|
||||
int mv = objW * objH * objD;
|
||||
AtomicInteger v = new AtomicInteger(0);
|
||||
if (mv > 500_000) {
|
||||
largeObject = true;
|
||||
Iris.info(C.GRAY + "Converting.. "+ schem.getName() + " -> " + schem.getName().replace(".schem", ".iob"));
|
||||
Iris.info(C.GRAY + "- It may take a while");
|
||||
if (sender.isPlayer()) {
|
||||
i = J.ar(() -> {
|
||||
sender.sendProgress((double) v.get() / mv, "Converting");
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
|
||||
CompoundTag paletteTag = (CompoundTag) compound.get("Palette");
|
||||
Map<Integer, BlockData> blockmap = new HashMap<>(paletteTag.size(), 0.9f);
|
||||
for (Map.Entry<String, Tag<?>> entry : paletteTag.getValue().entrySet()) {
|
||||
String blockName = entry.getKey();
|
||||
BlockData bd = Bukkit.createBlockData(blockName);
|
||||
Tag<?> blockTag = entry.getValue();
|
||||
int blockId = ((IntTag) blockTag).getValue();
|
||||
blockmap.put(blockId, bd);
|
||||
}
|
||||
|
||||
ByteArrayTag byteArray = (ByteArrayTag) compound.get("BlockData");
|
||||
byte[] originalBlockArray = byteArray.getValue();
|
||||
|
||||
IrisObject object = new IrisObject(objW, objH, objD);
|
||||
for (int h = 0; h < objH; h++) {
|
||||
for (int d = 0; d < objD; d++) {
|
||||
for (int w = 0; w < objW; w++) {
|
||||
BlockData bd = blockmap.get((int) originalBlockArray[v.get()]);
|
||||
if (!bd.getMaterial().isAir()) {
|
||||
object.setUnsigned(w, h, d, bd);
|
||||
}
|
||||
v.getAndAdd(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (i != -1) J.car(i);
|
||||
try {
|
||||
object.shrinkwrap();
|
||||
object.write(new File(folder, schem.getName().replace(".schem", ".iob")));
|
||||
} catch (IOException e) {
|
||||
Iris.info(C.RED + "Failed to save: " + schem.getName());
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
if (sender.isPlayer()) {
|
||||
if (largeObject) {
|
||||
sender.sendMessage(C.IRIS + "Converted "+ schem.getName() + " -> " + schem.getName().replace(".schem", ".iob") + " in " + Form.duration(p.getMillis()));
|
||||
} else {
|
||||
sender.sendMessage(C.IRIS + "Converted " + schem.getName() + " -> " + schem.getName().replace(".schem", ".iob"));
|
||||
}
|
||||
}
|
||||
if (largeObject) {
|
||||
Iris.info(C.GRAY + "Converted "+ schem.getName() + " -> " + schem.getName().replace(".schem", ".iob") + " in " + Form.duration(p.getMillis()));
|
||||
} else {
|
||||
Iris.info(C.GRAY + "Converted " + schem.getName() + " -> " + schem.getName().replace(".schem", ".iob"));
|
||||
}
|
||||
FileUtils.delete(schem);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Iris.info(C.RED + "Failed to convert: " + schem.getName());
|
||||
if (sender.isPlayer()) {
|
||||
sender.sendMessage(C.RED + "Failed to convert: " + schem.getName());
|
||||
}
|
||||
e.printStackTrace();
|
||||
Iris.reportError(e);
|
||||
}
|
||||
}
|
||||
sender.sendMessage(C.GRAY + "converted: " + fileList.length);
|
||||
});
|
||||
}
|
||||
|
||||
// /**
|
||||
// *
|
||||
// * @param sender
|
||||
// */
|
||||
// public static void convertJigsawStructure(File in, File out, VolmitSender sender) {
|
||||
// File dataFolder = Iris.instance.getDataFolder("convert");
|
||||
// try {
|
||||
// KMap<String, IrisJigsawPool> pools = new KMap<>();
|
||||
// KList<File> roots = new KList<>();
|
||||
// AtomicInteger total = new AtomicInteger(0);
|
||||
// AtomicInteger at = new AtomicInteger(0);
|
||||
// File destPools = new File(out.getAbsolutePath() + "/jigsaw-pools");
|
||||
// destPools.mkdirs();
|
||||
// findAllNBT(in, (folder, file) -> {
|
||||
// total.getAndIncrement();
|
||||
// if (roots.addIfMissing(folder)) {
|
||||
// String b = in.toURI().relativize(folder.toURI()).getPath();
|
||||
// if (b.startsWith("/")) {
|
||||
// b = b.substring(1);
|
||||
// }
|
||||
//
|
||||
// if (b.endsWith("/")) {
|
||||
// b = b.substring(0, b.length() - 1);
|
||||
// }
|
||||
//
|
||||
// pools.put(b, new IrisJigsawPool());
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// } catch (Exception e) {
|
||||
// Iris.error(C.RED + "Failed to convert: " + in.getPath());
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
//
|
||||
//
|
||||
//
|
||||
// }
|
||||
|
||||
private static void findAllNBT(File path, Consumer2<File, File> inFile) {
|
||||
if (path == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (path.isFile() && path.getName().endsWith(".nbt")) {
|
||||
inFile.accept(path.getParentFile(), path);
|
||||
return;
|
||||
}
|
||||
for (File i : path.listFiles()) {
|
||||
if (i.isDirectory()) {
|
||||
findAllNBT(i, inFile);
|
||||
} else if (i.isFile() && i.getName().endsWith(".nbt")) {
|
||||
inFile.accept(path, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -24,9 +24,10 @@ import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.ServerConfigurator;
|
||||
import com.volmit.iris.core.pregenerator.PregenTask;
|
||||
import com.volmit.iris.core.service.StudioSVC;
|
||||
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.engine.safeguard.UtilsSFG;
|
||||
import com.volmit.iris.core.safeguard.UtilsSFG;
|
||||
import com.volmit.iris.util.exceptions.IrisException;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
@@ -45,9 +46,7 @@ import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static com.volmit.iris.core.tools.IrisPackBenchmarking.benchmark;
|
||||
import static com.volmit.iris.engine.safeguard.IrisSafeguard.unstablemode;
|
||||
import static com.volmit.iris.core.safeguard.IrisSafeguard.unstablemode;
|
||||
|
||||
/**
|
||||
* Makes it a lot easier to setup an engine, world, studio or whatever
|
||||
@@ -83,6 +82,11 @@ public class IrisCreator {
|
||||
* the world itself. Studio worlds are deleted when they are unloaded.
|
||||
*/
|
||||
private boolean studio = false;
|
||||
/**
|
||||
* Benchmark mode
|
||||
*/
|
||||
private boolean benchmark = false;
|
||||
private boolean smartVanillaHeight = false;
|
||||
|
||||
public static boolean removeFromBukkitYml(String name) throws IOException {
|
||||
YamlConfiguration yml = YamlConfiguration.loadConfiguration(BUKKIT_YML);
|
||||
@@ -107,15 +111,8 @@ public class IrisCreator {
|
||||
* @return the IrisAccess
|
||||
* @throws IrisException shit happens
|
||||
*/
|
||||
IrisPackBenchmarking PackBench = new IrisPackBenchmarking();
|
||||
|
||||
public World create() throws IrisException {
|
||||
if (unstablemode){
|
||||
Iris.info(C.RED + "Your server is experiencing an incompatibility with the Iris plugin. Please rectify this problem to avoid further complications.");
|
||||
Iris.info(C.RED + "----------------------------------------------------------------");
|
||||
Iris.info(C.RED + "Operation ran: Loading Iris World..");
|
||||
UtilsSFG.printIncompatibleWarnings();
|
||||
Iris.info(C.RED + "----------------------------------------------------------------");
|
||||
}
|
||||
if (Bukkit.isPrimaryThread()) {
|
||||
throw new IrisException("You cannot invoke create() on the main thread.");
|
||||
}
|
||||
@@ -146,6 +143,7 @@ public class IrisCreator {
|
||||
.name(name)
|
||||
.seed(seed)
|
||||
.studio(studio)
|
||||
.smartVanillaHeight(smartVanillaHeight)
|
||||
.create();
|
||||
ServerConfigurator.installDataPacks(false);
|
||||
|
||||
@@ -154,7 +152,6 @@ public class IrisCreator {
|
||||
|
||||
J.a(() ->
|
||||
{
|
||||
int req = 441;
|
||||
Supplier<Integer> g = () -> {
|
||||
if (finalAccess1 == null || finalAccess1.getEngine() == null) {
|
||||
return 0;
|
||||
@@ -162,6 +159,9 @@ public class IrisCreator {
|
||||
return finalAccess1.getEngine().getGenerated();
|
||||
};
|
||||
if(!benchmark) {
|
||||
if (finalAccess1 == null) return;
|
||||
int req = finalAccess1.getSpawnChunks().join();
|
||||
|
||||
while (g.get() < req) {
|
||||
double v = (double) g.get() / (double) req;
|
||||
if (sender.isPlayer()) {
|
||||
@@ -173,7 +173,6 @@ public class IrisCreator {
|
||||
}
|
||||
}
|
||||
}
|
||||
//if (benchmark){loaded = true;}
|
||||
});
|
||||
|
||||
|
||||
@@ -191,7 +190,7 @@ public class IrisCreator {
|
||||
|
||||
done.set(true);
|
||||
|
||||
if (sender.isPlayer()) {
|
||||
if (sender.isPlayer() && !benchmark) {
|
||||
J.s(() -> {
|
||||
sender.player().teleport(new Location(world.get(), 0, world.get().getHighestBlockYAt(0, 0), 0));
|
||||
});
|
||||
|
||||
@@ -2,169 +2,200 @@ package com.volmit.iris.core.tools;
|
||||
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.pregenerator.IrisPregenerator;
|
||||
import com.volmit.iris.core.pregenerator.LazyPregenerator;
|
||||
import com.volmit.iris.core.pregenerator.PregenTask;
|
||||
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.collection.KMap;
|
||||
import com.volmit.iris.util.exceptions.IrisException;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.math.Position2;
|
||||
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||
import lombok.Getter;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import static com.volmit.iris.core.commands.CommandIris.BenchDimension;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.FileVisitResult;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.SimpleFileVisitor;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.time.Clock;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
|
||||
public class IrisPackBenchmarking {
|
||||
public static boolean loaded = false;
|
||||
public static boolean benchmark = false;
|
||||
static boolean cancelled = false;
|
||||
static boolean pregenInProgress = false;
|
||||
static long startTime;
|
||||
static long totalChunks;
|
||||
static long generatedChunks;
|
||||
static double elapsedTimeNs;
|
||||
@Getter
|
||||
public static IrisPackBenchmarking instance;
|
||||
public static boolean benchmarkInProgress = false;
|
||||
private IrisDimension IrisDimension;
|
||||
private int radius;
|
||||
private boolean finished = false;
|
||||
PrecisionStopwatch stopwatch;
|
||||
|
||||
public static void runBenchmark() {
|
||||
// IrisPackBenchmarking IrisPackBenchmarking = new IrisPackBenchmarking();
|
||||
benchmark = true;
|
||||
Iris.info(C.BLUE + "Benchmarking Dimension: " + C.AQUA + BenchDimension);
|
||||
//progress();
|
||||
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
|
||||
Iris.info(C.GOLD + "Setting everything up..");
|
||||
try {
|
||||
String BenchmarkFolder = "\\Benchmark";
|
||||
File folder = new File(BenchmarkFolder);
|
||||
if (folder.exists() && folder.isDirectory()) {
|
||||
FileUtils.deleteDirectory(folder);
|
||||
Iris.debug("Deleted old Benchmark");
|
||||
} else {
|
||||
Iris.info(C.GOLD + "Old Benchmark not found!");
|
||||
if(folder.exists()){
|
||||
Iris.info(C.RED + "FAILED To remove old Benchmark!");
|
||||
//cancelled = true;
|
||||
public IrisPackBenchmarking(IrisDimension dimension, int r) {
|
||||
instance = this;
|
||||
this.IrisDimension = dimension;
|
||||
this.radius = r;
|
||||
runBenchmark();
|
||||
}
|
||||
|
||||
}
|
||||
private void runBenchmark() {
|
||||
this.stopwatch = new PrecisionStopwatch();
|
||||
ExecutorService service = Executors.newSingleThreadExecutor();
|
||||
service.submit(() -> {
|
||||
Iris.info("Setting up benchmark environment ");
|
||||
benchmarkInProgress = true;
|
||||
File file = new File("benchmark");
|
||||
if (file.exists()) {
|
||||
deleteDirectory(file.toPath());
|
||||
}
|
||||
createBenchmark();
|
||||
while (!IrisToolbelt.isIrisWorld(Bukkit.getWorld("benchmark"))) {
|
||||
J.sleep(1000);
|
||||
Iris.debug("Iris PackBenchmark: Waiting...");
|
||||
}
|
||||
Iris.info("Starting Benchmark!");
|
||||
stopwatch.begin();
|
||||
startBenchmark();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public boolean getBenchmarkInProgress() {
|
||||
return benchmarkInProgress;
|
||||
}
|
||||
|
||||
public void finishedBenchmark(KList<Integer> cps) {
|
||||
try {
|
||||
String time = Form.duration(stopwatch.getMillis());
|
||||
Engine engine = IrisToolbelt.access(Bukkit.getWorld("benchmark")).getEngine();
|
||||
Iris.info("-----------------");
|
||||
Iris.info("Results:");
|
||||
Iris.info("- Total time: " + time);
|
||||
Iris.info("- Average CPS: " + calculateAverage(cps));
|
||||
Iris.info(" - Median CPS: " + calculateMedian(cps));
|
||||
Iris.info(" - Highest CPS: " + findHighest(cps));
|
||||
Iris.info(" - Lowest CPS: " + findLowest(cps));
|
||||
Iris.info("-----------------");
|
||||
Iris.info("Creating a report..");
|
||||
File profilers = new File("plugins" + File.separator + "Iris" + File.separator + "packbenchmarks");
|
||||
profilers.mkdir();
|
||||
|
||||
File results = new File("plugins " + File.separator + "Iris", IrisDimension.getName() + LocalDateTime.now(Clock.systemDefaultZone()) + ".txt");
|
||||
results.createNewFile();
|
||||
KMap<String, Double> metrics = engine.getMetrics().pull();
|
||||
try (FileWriter writer = new FileWriter(results)) {
|
||||
writer.write("-----------------\n");
|
||||
writer.write("Results:\n");
|
||||
writer.write("Dimension: " + IrisDimension.getName() + "\n");
|
||||
writer.write("- Date of Benchmark: " + LocalDateTime.now(Clock.systemDefaultZone()) + "\n");
|
||||
writer.write("\n");
|
||||
writer.write("Metrics");
|
||||
for (String m : metrics.k()) {
|
||||
double i = metrics.get(m);
|
||||
writer.write("- " + m + ": " + i);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException();
|
||||
writer.write("- " + metrics);
|
||||
writer.write("Benchmark: " + LocalDateTime.now(Clock.systemDefaultZone()) + "\n");
|
||||
writer.write("- Total time: " + time + "\n");
|
||||
writer.write("- Average CPS: " + calculateAverage(cps) + "\n");
|
||||
writer.write(" - Median CPS: " + calculateMedian(cps) + "\n");
|
||||
writer.write(" - Highest CPS: " + findHighest(cps) + "\n");
|
||||
writer.write(" - Lowest CPS: " + findLowest(cps) + "\n");
|
||||
writer.write("-----------------\n");
|
||||
Iris.info("Finished generating a report!");
|
||||
} catch (IOException e) {
|
||||
Iris.error("An error occurred writing to the file.");
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}).thenRun(() -> {
|
||||
Iris.info(C.GOLD + "Creating Benchmark Environment");
|
||||
createBenchmark();
|
||||
|
||||
}).thenRun(() -> {
|
||||
Iris.info( C.BLUE + "Benchmark Started!");
|
||||
boolean done = false;
|
||||
startBenchmarkTimer();
|
||||
startBenchmark();
|
||||
basicScheduler();
|
||||
}).thenRun(() -> {
|
||||
|
||||
});
|
||||
// cancelled = future.cancel(true);
|
||||
try {
|
||||
future.get();
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
Bukkit.getServer().unloadWorld("benchmark", true);
|
||||
stopwatch.end();
|
||||
} catch (Exception e) {
|
||||
Iris.error("Something has gone wrong!");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static void results(){
|
||||
double averageCps = calculateAverageCPS();
|
||||
Iris.info("Benchmark Dimension: " + BenchDimension);
|
||||
Iris.info("Speeds");
|
||||
Iris.info("- Average CPS: " + roundToTwoDecimalPlaces(averageCps));
|
||||
Iris.info("Duration: " + roundToTwoDecimalPlaces(elapsedTimeNs));
|
||||
|
||||
}
|
||||
private static void basicScheduler() {
|
||||
while (true) {
|
||||
totalChunks = IrisPregenerator.getLongTotalChunks();
|
||||
generatedChunks = IrisPregenerator.getLongGeneratedChunks();
|
||||
if(totalChunks > 0) {
|
||||
if (generatedChunks >= totalChunks) {
|
||||
Iris.info("Benchmark Completed!");
|
||||
elapsedTimeNs = stopBenchmarkTimer();
|
||||
results();
|
||||
break;
|
||||
}
|
||||
}
|
||||
//J.sleep(100); test
|
||||
}
|
||||
}
|
||||
static void createBenchmark(){
|
||||
private void createBenchmark(){
|
||||
try {
|
||||
IrisToolbelt.createWorld()
|
||||
.dimension(BenchDimension)
|
||||
.name("Benchmark")
|
||||
.dimension(IrisDimension.getName())
|
||||
.name("benchmark")
|
||||
.seed(1337)
|
||||
.studio(false)
|
||||
.benchmark(true)
|
||||
.create();
|
||||
} catch (IrisException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
static void startBenchmark(){
|
||||
|
||||
private void startBenchmark(){
|
||||
int x = 0;
|
||||
int z = 0;
|
||||
IrisToolbelt.pregenerate(PregenTask
|
||||
.builder()
|
||||
.gui(false)
|
||||
.center(new Position2(x, z))
|
||||
.width(5)
|
||||
.height(5)
|
||||
.build(), Bukkit.getWorld("Benchmark")
|
||||
.build(), Bukkit.getWorld("benchmark")
|
||||
);
|
||||
}
|
||||
static void startLazyBenchmark(){
|
||||
int x = 0;
|
||||
int z = 0;
|
||||
LazyPregenerator.LazyPregenJob pregenJob = LazyPregenerator.LazyPregenJob.builder()
|
||||
//.world("Benchmark")
|
||||
.healingPosition(0)
|
||||
.healing(false)
|
||||
.chunksPerMinute(3200)
|
||||
.radiusBlocks(5000)
|
||||
.position(0)
|
||||
.build();
|
||||
|
||||
LazyPregenerator pregenerator = new LazyPregenerator(pregenJob, new File("plugins/Iris/lazygen.json"));
|
||||
pregenerator.start();
|
||||
}
|
||||
public static double calculateAverageCPS() {
|
||||
double elapsedTimeSec = elapsedTimeNs / 1_000_000_000.0; // Convert to seconds
|
||||
return generatedChunks / elapsedTimeSec;
|
||||
}
|
||||
|
||||
private static void startBenchmarkTimer() {
|
||||
startTime = System.nanoTime();
|
||||
}
|
||||
|
||||
private static double stopBenchmarkTimer() {
|
||||
long endTime = System.nanoTime();
|
||||
return (endTime - startTime) / 1_000_000_000.0;
|
||||
}
|
||||
|
||||
public static void deleteDirectory(File dir) {
|
||||
File[] files = dir.listFiles();
|
||||
if(files != null) {
|
||||
for(File file: files) {
|
||||
if(file.isDirectory()) {
|
||||
deleteDirectory(file);
|
||||
} else {
|
||||
file.delete();
|
||||
}
|
||||
}
|
||||
private double calculateAverage(KList<Integer> list) {
|
||||
double sum = 0;
|
||||
for (int num : list) {
|
||||
sum += num;
|
||||
}
|
||||
dir.delete();
|
||||
return sum / list.size();
|
||||
}
|
||||
private static double roundToTwoDecimalPlaces(double value) {
|
||||
return Double.parseDouble(String.format("%.2f", value));
|
||||
|
||||
private double calculateMedian(KList<Integer> list) {
|
||||
Collections.sort(list);
|
||||
int middle = list.size() / 2;
|
||||
|
||||
if (list.size() % 2 == 1) {
|
||||
return list.get(middle);
|
||||
} else {
|
||||
return (list.get(middle - 1) + list.get(middle)) / 2.0;
|
||||
}
|
||||
}
|
||||
|
||||
private int findLowest(KList<Integer> list) {
|
||||
return Collections.min(list);
|
||||
}
|
||||
|
||||
private int findHighest(KList<Integer> list) {
|
||||
return Collections.max(list);
|
||||
}
|
||||
|
||||
private boolean deleteDirectory(Path dir) {
|
||||
try {
|
||||
Files.walkFileTree(dir, new SimpleFileVisitor<Path>() {
|
||||
@Override
|
||||
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
|
||||
Files.delete(file);
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
|
||||
Files.delete(dir);
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
});
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
package com.volmit.iris.core.tools;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.math.M;
|
||||
import com.volmit.iris.util.math.RollingSequence;
|
||||
import com.volmit.iris.util.nbt.mca.MCAFile;
|
||||
import com.volmit.iris.util.nbt.mca.MCAUtil;
|
||||
import com.volmit.iris.util.parallel.BurstExecutor;
|
||||
import com.volmit.iris.util.parallel.MultiBurst;
|
||||
import com.volmit.iris.util.scheduling.ChronoLatch;
|
||||
import com.volmit.iris.util.scheduling.Looper;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class IrisWorldAnalytics {
|
||||
private final ChronoLatch latch;
|
||||
private final String world;
|
||||
private final AtomicInteger totalChunks;
|
||||
private final AtomicInteger processed;
|
||||
private final RollingSequence chunksPerSecond;
|
||||
private final AtomicLong startTime;
|
||||
private final Looper ticker;
|
||||
|
||||
public IrisWorldAnalytics(String world) {
|
||||
this.world = world;
|
||||
|
||||
totalChunks = new AtomicInteger();
|
||||
processed = new AtomicInteger(0);
|
||||
latch = new ChronoLatch(3000);
|
||||
chunksPerSecond = new RollingSequence(3000);
|
||||
startTime = new AtomicLong(M.ms());
|
||||
index();
|
||||
ticker = new Looper() {
|
||||
@Override
|
||||
protected long loop() {
|
||||
|
||||
|
||||
|
||||
return 1000;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
public void execute() {
|
||||
Iris.info("Starting world analyser..");
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
}
|
||||
|
||||
private long computeETA() {
|
||||
return (long) (totalChunks.get() > 1024 ? // Generated chunks exceed 1/8th of total?
|
||||
// If yes, use smooth function (which gets more accurate over time since its less sensitive to outliers)
|
||||
((totalChunks.get() - processed.get()) * ((double) (M.ms() - startTime.get()) / (double) processed.get())) :
|
||||
// If no, use quick function (which is less accurate over time but responds better to the initial delay)
|
||||
((totalChunks.get() - processed.get()) / chunksPerSecond.getAverage()) * 1000
|
||||
);
|
||||
}
|
||||
|
||||
private void index() {
|
||||
try {
|
||||
AtomicInteger chunks = new AtomicInteger();
|
||||
AtomicInteger pr = new AtomicInteger();
|
||||
AtomicInteger pl = new AtomicInteger(0);
|
||||
RollingSequence rps = new RollingSequence(5);
|
||||
ChronoLatch cl = new ChronoLatch(3000);
|
||||
File[] McaFiles = new File(world, "region").listFiles((dir, name) -> name.endsWith(".mca"));
|
||||
Supplier<Long> eta = () -> (long) ((McaFiles.length - pr.get()) / rps.getAverage()) * 1000;
|
||||
ScheduledFuture<?> sc = Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(() -> {
|
||||
int sp = pr.get() - pl.get();
|
||||
pl.set(pr.get());
|
||||
rps.put(sp);
|
||||
if (cl.flip()) {
|
||||
double pc = ((double) pr.get() / (double) McaFiles.length) * 100;
|
||||
Iris.info("Indexing: " + Form.f(pr.get()) + " of " + Form.f(McaFiles.length) + " (%.0f%%) " + Form.f((int) rps.getAverage()) + "/s ETA: " + Form.duration(eta.get(), 2), pc);
|
||||
}
|
||||
}, 3,1, TimeUnit.SECONDS);
|
||||
BurstExecutor b = MultiBurst.burst.burst(McaFiles.length);
|
||||
for (File mca : McaFiles) {
|
||||
b.queue(() -> {
|
||||
try {
|
||||
MCAFile region = MCAUtil.read(mca, 0);
|
||||
var array = region.getChunks();
|
||||
for (int i = 0; i < array.length(); i++) {
|
||||
if (array.get(i) != null) {
|
||||
chunks.incrementAndGet();
|
||||
}
|
||||
}
|
||||
pr.incrementAndGet();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
b.complete();
|
||||
sc.cancel(true);
|
||||
totalChunks.set(chunks.get());
|
||||
Iris.info("Indexing completed!");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -19,8 +19,7 @@
|
||||
package com.volmit.iris.core.tools;
|
||||
|
||||
import com.volmit.iris.core.loader.IrisData;
|
||||
import com.volmit.iris.engine.object.IrisDimension;
|
||||
import com.volmit.iris.engine.object.IrisWorld;
|
||||
import com.volmit.iris.engine.object.*;
|
||||
import com.volmit.iris.engine.platform.BukkitChunkGenerator;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
@@ -33,6 +32,7 @@ public class IrisWorldCreator {
|
||||
private String name;
|
||||
private boolean studio = false;
|
||||
private String dimensionName = null;
|
||||
private boolean smartVanillaHeight = false;
|
||||
private long seed = 1337;
|
||||
|
||||
public IrisWorldCreator() {
|
||||
@@ -64,6 +64,11 @@ public class IrisWorldCreator {
|
||||
return this;
|
||||
}
|
||||
|
||||
public IrisWorldCreator smartVanillaHeight(boolean smartVanillaHeight) {
|
||||
this.smartVanillaHeight = smartVanillaHeight;
|
||||
return this;
|
||||
}
|
||||
|
||||
public WorldCreator create() {
|
||||
IrisDimension dim = IrisData.loadAnyDimension(dimensionName);
|
||||
|
||||
@@ -77,7 +82,8 @@ public class IrisWorldCreator {
|
||||
.build();
|
||||
ChunkGenerator g = new BukkitChunkGenerator(w, studio, studio
|
||||
? dim.getLoader().getDataFolder() :
|
||||
new File(w.worldFolder(), "iris/pack"), dimensionName);
|
||||
new File(w.worldFolder(), "iris/pack"), dimensionName, smartVanillaHeight);
|
||||
|
||||
|
||||
return new WorldCreator(name)
|
||||
.environment(findEnvironment())
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
package com.volmit.iris.core.tools;
|
||||
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.util.math.Position2;
|
||||
import com.volmit.iris.util.math.Spiraler;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
public class IrisWorldMerger {
|
||||
private Engine engine;
|
||||
private World world;
|
||||
private World selectedWorld;
|
||||
|
||||
/**
|
||||
* @param world > The selected world to get the caves from
|
||||
* @param engine > The engine of the iris world
|
||||
*/
|
||||
public IrisWorldMerger(Engine engine, World world) {
|
||||
this.engine = engine;
|
||||
this.world = this.engine.getWorld().realWorld();
|
||||
this.selectedWorld = world;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges caves from a selected chunk into the corresponding chunk in the outcome world.
|
||||
*
|
||||
* @param selectedChunk The chunk from the selected world.
|
||||
* @param targetChunk The corresponding chunk in the outcome world.
|
||||
*/
|
||||
private void mergeCavesInChunk(Chunk selectedChunk, Chunk targetChunk) {
|
||||
int baseX = selectedChunk.getX() << 4;
|
||||
int baseZ = selectedChunk.getZ() << 4;
|
||||
|
||||
for (int x = 0; x < 16; x++) {
|
||||
int worldX = baseX + x;
|
||||
for (int z = 0; z < 16; z++) {
|
||||
int worldZ = baseZ + z;
|
||||
int surfaceY = engine.getHeight(worldX, worldZ);
|
||||
for (int y = 0; y <= surfaceY; y++) {
|
||||
Block selectedBlock = selectedChunk.getBlock(x, y, z);
|
||||
if (selectedBlock.getType() == Material.AIR) {
|
||||
Block targetBlock = targetChunk.getBlock(x, y, z);
|
||||
targetBlock.setType(Material.AIR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Irritates (merges) caves in a spiral pattern around the specified center chunk coordinates.
|
||||
*
|
||||
* @param centerX The X coordinate of the center chunk.
|
||||
* @param centerZ The Z coordinate of the center chunk.
|
||||
* @param radius The radius (in chunks) to merge caves around.
|
||||
*/
|
||||
public void irritateSpiral(int centerX, int centerZ, int radius) {
|
||||
Spiraler spiraler = new Spiraler(radius * 2, radius * 2, (x, z) -> {
|
||||
int chunkX = centerX + x;
|
||||
int chunkZ = centerZ + z;
|
||||
Chunk selectedChunk = selectedWorld.getChunkAt(chunkX, chunkZ);
|
||||
Chunk targetChunk = world.getChunkAt(chunkX, chunkZ);
|
||||
mergeCavesInChunk(selectedChunk, targetChunk);
|
||||
});
|
||||
|
||||
// Execute the spiral iteration
|
||||
while (spiraler.hasNext()) {
|
||||
spiraler.next(); // The spiraler itself runs the callback defined in its constructor
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,7 @@ package com.volmit.iris.core.wand;
|
||||
import com.volmit.iris.util.data.Cuboid;
|
||||
import com.volmit.iris.util.math.M;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import com.volmit.iris.util.misc.E;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Particle;
|
||||
import org.bukkit.entity.Player;
|
||||
@@ -29,8 +30,10 @@ import org.bukkit.util.Vector;
|
||||
import java.awt.*;
|
||||
|
||||
public class WandSelection {
|
||||
private static final Particle REDSTONE = E.getOrDefault(Particle.class, "REDSTONE", "DUST");
|
||||
private final Cuboid c;
|
||||
private final Player p;
|
||||
private static final double STEP = 0.10;
|
||||
|
||||
public WandSelection(Cuboid c, Player p) {
|
||||
this.c = c;
|
||||
@@ -38,77 +41,58 @@ public class WandSelection {
|
||||
}
|
||||
|
||||
public void draw() {
|
||||
double accuracy;
|
||||
double dist;
|
||||
Location playerLoc = p.getLocation();
|
||||
double maxDistanceSquared = 256 * 256;
|
||||
int particleCount = 0;
|
||||
|
||||
for (double i = c.getLowerX() - 1; i < c.getUpperX() + 1; i += 0.25) {
|
||||
for (double j = c.getLowerY() - 1; j < c.getUpperY() + 1; j += 0.25) {
|
||||
for (double k = c.getLowerZ() - 1; k < c.getUpperZ() + 1; k += 0.25) {
|
||||
boolean ii = i == c.getLowerX() || i == c.getUpperX();
|
||||
boolean jj = j == c.getLowerY() || j == c.getUpperY();
|
||||
boolean kk = k == c.getLowerZ() || k == c.getUpperZ();
|
||||
// cube!
|
||||
Location[][] edges = {
|
||||
{c.getLowerNE(), new Location(c.getWorld(), c.getUpperX() + 1, c.getLowerY(), c.getLowerZ())},
|
||||
{c.getLowerNE(), new Location(c.getWorld(), c.getLowerX(), c.getUpperY() + 1, c.getLowerZ())},
|
||||
{c.getLowerNE(), new Location(c.getWorld(), c.getLowerX(), c.getLowerY(), c.getUpperZ() + 1)},
|
||||
{new Location(c.getWorld(), c.getUpperX() + 1, c.getLowerY(), c.getLowerZ()), new Location(c.getWorld(), c.getUpperX() + 1, c.getUpperY() + 1, c.getLowerZ())},
|
||||
{new Location(c.getWorld(), c.getUpperX() + 1, c.getLowerY(), c.getLowerZ()), new Location(c.getWorld(), c.getUpperX() + 1, c.getLowerY(), c.getUpperZ() + 1)},
|
||||
{new Location(c.getWorld(), c.getLowerX(), c.getUpperY() + 1, c.getLowerZ()), new Location(c.getWorld(), c.getUpperX() + 1, c.getUpperY() + 1, c.getLowerZ())},
|
||||
{new Location(c.getWorld(), c.getLowerX(), c.getUpperY() + 1, c.getLowerZ()), new Location(c.getWorld(), c.getLowerX(), c.getUpperY() + 1, c.getUpperZ() + 1)},
|
||||
{new Location(c.getWorld(), c.getLowerX(), c.getLowerY(), c.getUpperZ() + 1), new Location(c.getWorld(), c.getUpperX() + 1, c.getLowerY(), c.getUpperZ() + 1)},
|
||||
{new Location(c.getWorld(), c.getLowerX(), c.getLowerY(), c.getUpperZ() + 1), new Location(c.getWorld(), c.getLowerX(), c.getUpperY() + 1, c.getUpperZ() + 1)},
|
||||
{new Location(c.getWorld(), c.getUpperX() + 1, c.getUpperY() + 1, c.getLowerZ()), new Location(c.getWorld(), c.getUpperX() + 1, c.getUpperY() + 1, c.getUpperZ() + 1)},
|
||||
{new Location(c.getWorld(), c.getLowerX(), c.getUpperY() + 1, c.getUpperZ() + 1), new Location(c.getWorld(), c.getUpperX() + 1, c.getUpperY() + 1, c.getUpperZ() + 1)},
|
||||
{new Location(c.getWorld(), c.getUpperX() + 1, c.getLowerY(), c.getUpperZ() + 1), new Location(c.getWorld(), c.getUpperX() + 1, c.getUpperY() + 1, c.getUpperZ() + 1)}
|
||||
};
|
||||
|
||||
if ((ii && jj) || (ii && kk) || (kk && jj)) {
|
||||
Vector push = new Vector(0, 0, 0);
|
||||
for (Location[] edge : edges) {
|
||||
Vector direction = edge[1].toVector().subtract(edge[0].toVector());
|
||||
double length = direction.length();
|
||||
direction.normalize();
|
||||
|
||||
if (i == c.getLowerX()) {
|
||||
push.add(new Vector(-0.55, 0, 0));
|
||||
}
|
||||
for (double d = 0; d <= length; d += STEP) {
|
||||
Location particleLoc = edge[0].clone().add(direction.clone().multiply(d));
|
||||
|
||||
if (j == c.getLowerY()) {
|
||||
push.add(new Vector(0, -0.55, 0));
|
||||
}
|
||||
|
||||
if (k == c.getLowerZ()) {
|
||||
push.add(new Vector(0, 0, -0.55));
|
||||
}
|
||||
|
||||
if (i == c.getUpperX()) {
|
||||
push.add(new Vector(0.55, 0, 0));
|
||||
}
|
||||
|
||||
if (j == c.getUpperY()) {
|
||||
push.add(new Vector(0, 0.55, 0));
|
||||
}
|
||||
|
||||
if (k == c.getUpperZ()) {
|
||||
push.add(new Vector(0, 0, 0.55));
|
||||
}
|
||||
|
||||
Location a = new Location(c.getWorld(), i, j, k).add(0.5, 0.5, 0.5).add(push);
|
||||
accuracy = M.lerpInverse(0, 64 * 64, p.getLocation().distanceSquared(a));
|
||||
dist = M.lerp(0.125, 3.5, accuracy);
|
||||
|
||||
if (M.r(M.min(dist * 5, 0.9D) * 0.995)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ii && jj) {
|
||||
a.add(0, 0, RNG.r.d(-0.3, 0.3));
|
||||
}
|
||||
|
||||
if (kk && jj) {
|
||||
a.add(RNG.r.d(-0.3, 0.3), 0, 0);
|
||||
}
|
||||
|
||||
if (ii && kk) {
|
||||
a.add(0, RNG.r.d(-0.3, 0.3), 0);
|
||||
}
|
||||
|
||||
if (p.getLocation().distanceSquared(a) < 256 * 256) {
|
||||
Color color = Color.getHSBColor((float) (0.5f + (Math.sin((i + j + k + (p.getTicksLived() / 2f)) / (20f)) / 2)), 1, 1);
|
||||
int r = color.getRed();
|
||||
int g = color.getGreen();
|
||||
int b = color.getBlue();
|
||||
|
||||
p.spawnParticle(Particle.REDSTONE, a.getX(), a.getY(), a.getZ(),
|
||||
1, 0, 0, 0, 0,
|
||||
new Particle.DustOptions(org.bukkit.Color.fromRGB(r, g, b),
|
||||
(float) dist * 3f));
|
||||
}
|
||||
}
|
||||
if (playerLoc.distanceSquared(particleLoc) > maxDistanceSquared) {
|
||||
continue;
|
||||
}
|
||||
|
||||
spawnParticle(particleLoc, playerLoc);
|
||||
particleCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void spawnParticle(Location particleLoc, Location playerLoc) {
|
||||
double accuracy = M.lerpInverse(0, 64 * 64, playerLoc.distanceSquared(particleLoc));
|
||||
double dist = M.lerp(0.125, 3.5, accuracy);
|
||||
|
||||
if (M.r(Math.min(dist * 5, 0.9D) * 0.995)) {
|
||||
return;
|
||||
}
|
||||
|
||||
float hue = (float) (0.5f + (Math.sin((particleLoc.getX() + particleLoc.getY() + particleLoc.getZ() + (p.getTicksLived() / 2f)) / 20f) / 2));
|
||||
Color color = Color.getHSBColor(hue, 1, 1);
|
||||
|
||||
p.spawnParticle(REDSTONE, particleLoc,
|
||||
0, 0, 0, 0, 1,
|
||||
new Particle.DustOptions(org.bukkit.Color.fromRGB(color.getRed(), color.getGreen(), color.getBlue()),
|
||||
(float) dist * 3f));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,8 @@ import com.volmit.iris.util.noise.CNG;
|
||||
import com.volmit.iris.util.stream.ProceduralStream;
|
||||
import com.volmit.iris.util.stream.interpolation.Interpolated;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
@@ -42,6 +44,8 @@ import org.bukkit.block.data.BlockData;
|
||||
import java.util.UUID;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(exclude = "data")
|
||||
@ToString(exclude = "data")
|
||||
public class IrisComplex implements DataProvider {
|
||||
private static final BlockData AIR = Material.AIR.createBlockData();
|
||||
private RNG rng;
|
||||
@@ -127,6 +131,7 @@ public class IrisComplex implements DataProvider {
|
||||
caveBiomeStream = regionStream.contextInjecting((c, x, z) -> IrisContext.getOr(engine).getChunkContext().getRegion().get(x, z))
|
||||
.convert((r)
|
||||
-> engine.getDimension().getCaveBiomeStyle().create(rng.nextParallelRNG(InferredType.CAVE.ordinal()), getData()).stream()
|
||||
.zoom(engine.getDimension().getBiomeZoom())
|
||||
.zoom(r.getCaveBiomeZoom())
|
||||
.selectRarity(data.getBiomeLoader().loadAll(r.getCaveBiomes()))
|
||||
.onNull(emptyBiome)
|
||||
@@ -135,6 +140,8 @@ public class IrisComplex implements DataProvider {
|
||||
landBiomeStream = regionStream.contextInjecting((c, x, z) -> IrisContext.getOr(engine).getChunkContext().getRegion().get(x, z))
|
||||
.convert((r)
|
||||
-> engine.getDimension().getLandBiomeStyle().create(rng.nextParallelRNG(InferredType.LAND.ordinal()), getData()).stream()
|
||||
.zoom(engine.getDimension().getBiomeZoom())
|
||||
.zoom(engine.getDimension().getLandZoom())
|
||||
.zoom(r.getLandBiomeZoom())
|
||||
.selectRarity(data.getBiomeLoader().loadAll(r.getLandBiomes(), (t) -> t.setInferredType(InferredType.LAND)))
|
||||
).convertAware2D(ProceduralStream::get)
|
||||
@@ -143,6 +150,8 @@ public class IrisComplex implements DataProvider {
|
||||
seaBiomeStream = regionStream.contextInjecting((c, x, z) -> IrisContext.getOr(engine).getChunkContext().getRegion().get(x, z))
|
||||
.convert((r)
|
||||
-> engine.getDimension().getSeaBiomeStyle().create(rng.nextParallelRNG(InferredType.SEA.ordinal()), getData()).stream()
|
||||
.zoom(engine.getDimension().getBiomeZoom())
|
||||
.zoom(engine.getDimension().getSeaZoom())
|
||||
.zoom(r.getSeaBiomeZoom())
|
||||
.selectRarity(data.getBiomeLoader().loadAll(r.getSeaBiomes(), (t) -> t.setInferredType(InferredType.SEA)))
|
||||
).convertAware2D(ProceduralStream::get)
|
||||
@@ -151,6 +160,7 @@ public class IrisComplex implements DataProvider {
|
||||
shoreBiomeStream = regionStream.contextInjecting((c, x, z) -> IrisContext.getOr(engine).getChunkContext().getRegion().get(x, z))
|
||||
.convert((r)
|
||||
-> engine.getDimension().getShoreBiomeStyle().create(rng.nextParallelRNG(InferredType.SHORE.ordinal()), getData()).stream()
|
||||
.zoom(engine.getDimension().getBiomeZoom())
|
||||
.zoom(r.getShoreBiomeZoom())
|
||||
.selectRarity(data.getBiomeLoader().loadAll(r.getShoreBiomes(), (t) -> t.setInferredType(InferredType.SHORE)))
|
||||
).convertAware2D(ProceduralStream::get).cache2D("shoreBiomeStream", engine, cacheSize).waste("Shore Biome Stream");
|
||||
@@ -288,7 +298,7 @@ public class IrisComplex implements DataProvider {
|
||||
double b = 0;
|
||||
|
||||
for (IrisGenerator gen : generators) {
|
||||
b += bx.getGenLinkMax(gen.getLoadKey());
|
||||
b += bx.getGenLinkMax(gen.getLoadKey(), engine);
|
||||
}
|
||||
|
||||
return b;
|
||||
@@ -307,7 +317,7 @@ public class IrisComplex implements DataProvider {
|
||||
double b = 0;
|
||||
|
||||
for (IrisGenerator gen : generators) {
|
||||
b += bx.getGenLinkMin(gen.getLoadKey());
|
||||
b += bx.getGenLinkMin(gen.getLoadKey(), engine);
|
||||
}
|
||||
|
||||
return b;
|
||||
|
||||
@@ -24,6 +24,8 @@ import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.ServerConfigurator;
|
||||
import com.volmit.iris.core.events.IrisEngineHotloadEvent;
|
||||
import com.volmit.iris.core.gui.PregeneratorJob;
|
||||
import com.volmit.iris.core.nms.IMemoryWorld;
|
||||
import com.volmit.iris.core.nms.INMS;
|
||||
import com.volmit.iris.core.nms.container.BlockPos;
|
||||
import com.volmit.iris.core.nms.container.Pair;
|
||||
import com.volmit.iris.core.project.IrisProject;
|
||||
@@ -50,20 +52,30 @@ import com.volmit.iris.util.scheduling.ChronoLatch;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
import org.apache.commons.lang3.function.Failable;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.WorldCreator;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.persistence.PersistentDataContainer;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.HashSet;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(exclude = "context")
|
||||
@ToString(exclude = "context")
|
||||
public class IrisEngine implements Engine {
|
||||
private final AtomicInteger bud;
|
||||
private final AtomicInteger buds;
|
||||
@@ -88,6 +100,8 @@ public class IrisEngine implements Engine {
|
||||
private EngineEffects effects;
|
||||
private EngineExecutionEnvironment execution;
|
||||
private EngineWorldManager worldManager;
|
||||
private IMemoryWorld memoryWorld;
|
||||
private IrisMerger merger;
|
||||
private volatile int parallelism;
|
||||
private volatile int minHeight;
|
||||
private boolean failing;
|
||||
@@ -119,6 +133,9 @@ public class IrisEngine implements Engine {
|
||||
context = new IrisContext(this);
|
||||
cleaning = new AtomicBoolean(false);
|
||||
context.touch();
|
||||
merger = getDimension().getMerger();
|
||||
merger.loadWorld(this);
|
||||
updateMemoryWorld();
|
||||
getData().setEngine(this);
|
||||
getData().loadPrefetch(this);
|
||||
Iris.info("Initializing Engine: " + target.getWorld().name() + "/" + target.getDimension().getLoadKey() + " (" + target.getDimension().getDimensionHeight() + " height) Seed: " + getSeedManager().getSeed());
|
||||
@@ -184,6 +201,34 @@ public class IrisEngine implements Engine {
|
||||
mode = getDimension().getMode().getType().create(this);
|
||||
}
|
||||
|
||||
private void updateMemoryWorld() {
|
||||
try {
|
||||
if(!merger.isUseMemoryWorld() || merger.getGenerator().isEmpty())
|
||||
return;
|
||||
merger = getDimension().getMerger();
|
||||
if (!getDimension().isEnableExperimentalMerger()) return;
|
||||
if (getMerger().getGenerator().isBlank()) return;
|
||||
NamespacedKey dk = NamespacedKey.minecraft("memory_current_creator");
|
||||
PersistentDataContainer per;
|
||||
if (memoryWorld != null) {
|
||||
per = memoryWorld.getBukkit().getPersistentDataContainer();
|
||||
if (Objects.equals(per.get(dk, PersistentDataType.STRING), getMerger().getGenerator()))
|
||||
return;
|
||||
if (memoryWorld != null)
|
||||
memoryWorld.close();
|
||||
}
|
||||
memoryWorld = getMerger().isDatapackMode() ? Failable.get(() ->
|
||||
getMerger().getGenerator() == null ?
|
||||
INMS.get().createMemoryWorld(new WorldCreator("memoryworld").seed(getSeedManager().getSeed())) :
|
||||
INMS.get().createMemoryWorld(NamespacedKey.minecraft(getMerger().getGenerator()), new WorldCreator("memoryworld").seed(getSeedManager().getSeed()))
|
||||
) : null; // todo: experimental
|
||||
per = memoryWorld.getBukkit().getPersistentDataContainer();
|
||||
per.set(dk, PersistentDataType.STRING, getMerger().getGenerator());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateMatter(int x, int z, boolean multicore, ChunkContext context) {
|
||||
getMantle().generateMatter(x, z, multicore, context);
|
||||
@@ -233,6 +278,7 @@ public class IrisEngine implements Engine {
|
||||
getData().clearLists();
|
||||
getTarget().setDimension(getData().getDimensionLoader().load(getDimension().getLoadKey()));
|
||||
prehotload();
|
||||
updateMemoryWorld();
|
||||
setupEngine();
|
||||
J.a(() -> {
|
||||
synchronized (ServerConfigurator.class) {
|
||||
@@ -246,23 +292,40 @@ public class IrisEngine implements Engine {
|
||||
return engineData.aquire(() -> {
|
||||
//TODO: Method this file
|
||||
File f = new File(getWorld().worldFolder(), "iris/engine-data/" + getDimension().getLoadKey() + ".json");
|
||||
IrisEngineData data = null;
|
||||
|
||||
if (!f.exists()) {
|
||||
if (f.exists()) {
|
||||
try {
|
||||
f.getParentFile().mkdirs();
|
||||
IO.writeAll(f, new Gson().toJson(new IrisEngineData()));
|
||||
data = new Gson().fromJson(IO.readAll(f), IrisEngineData.class);
|
||||
if (data == null) {
|
||||
Iris.error("Failed to read Engine Data! Corrupted File? recreating...");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
return new Gson().fromJson(IO.readAll(f), IrisEngineData.class);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
if (data == null) {
|
||||
data = new IrisEngineData();
|
||||
data.getStatistics().setVersion(Iris.instance.getIrisVersion());
|
||||
data.getStatistics().setMCVersion(Iris.instance.getMCVersion());
|
||||
data.getStatistics().setUpgradedVersion(Iris.instance.getIrisVersion());
|
||||
if (data.getStatistics().getVersion() == -1 || data.getStatistics().getMCVersion() == -1 ) {
|
||||
Iris.error("Failed to setup Engine Data!");
|
||||
}
|
||||
|
||||
if (f.getParentFile().exists() || f.getParentFile().mkdirs()) {
|
||||
try {
|
||||
IO.writeAll(f, new Gson().toJson(data));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
Iris.error("Failed to setup Engine Data!");
|
||||
}
|
||||
}
|
||||
|
||||
return new IrisEngineData();
|
||||
return data;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -418,7 +481,6 @@ public class IrisEngine implements Engine {
|
||||
|
||||
J.a(() -> {
|
||||
try {
|
||||
getMantle().trim();
|
||||
getData().getObjectLoader().clean();
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
@@ -518,4 +580,19 @@ public class IrisEngine implements Engine {
|
||||
public int getCacheID() {
|
||||
return cacheId;
|
||||
}
|
||||
|
||||
private boolean EngineSafe() {
|
||||
// Todo: this has potential if done right
|
||||
int EngineMCVersion = getEngineData().getStatistics().getMCVersion();
|
||||
int EngineIrisVersion = getEngineData().getStatistics().getVersion();
|
||||
int MinecraftVersion = Iris.instance.getMCVersion();
|
||||
int IrisVersion = Iris.instance.getIrisVersion();
|
||||
if (EngineIrisVersion != IrisVersion) {
|
||||
return false;
|
||||
}
|
||||
if (EngineMCVersion != MinecraftVersion) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,8 +19,6 @@
|
||||
package com.volmit.iris.engine;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.tools.IrisPackBenchmarking;
|
||||
import com.volmit.iris.engine.data.cache.AtomicCache;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.mantle.EngineMantle;
|
||||
@@ -38,6 +36,8 @@ import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.mantle.Mantle;
|
||||
import com.volmit.iris.util.parallel.BurstExecutor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
import org.bukkit.util.BlockVector;
|
||||
|
||||
import java.io.File;
|
||||
@@ -45,10 +45,9 @@ import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import static com.volmit.iris.core.tools.IrisPackBenchmarking.benchmark;
|
||||
import static com.volmit.iris.engine.safeguard.PerformanceSFG.lowPerformance;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(exclude = "engine")
|
||||
@ToString(exclude = "engine")
|
||||
public class IrisEngineMantle implements EngineMantle {
|
||||
private final Engine engine;
|
||||
private final Mantle mantle;
|
||||
@@ -286,22 +285,10 @@ public class IrisEngineMantle implements EngineMantle {
|
||||
x = Math.max(x, c);
|
||||
x = (Math.max(x, 16) + 16) >> 4;
|
||||
x = x % 2 == 0 ? x + 1 : x;
|
||||
if (benchmark){
|
||||
x = 4;
|
||||
Iris.info("Mantle Size: " + x + " Chunks " + C.BLUE + "BENCHMARK MODE");
|
||||
} else {
|
||||
if(lowPerformance){
|
||||
x = 4;
|
||||
Iris.info("Mantle Size: " + x + " Chunks" + C.GOLD + "LOW PERFORMANCE MODE");
|
||||
} else {
|
||||
Iris.info("Mantle Size: " + x + " Chunks");
|
||||
Iris.info(" Object Mantle Size: " + u + " (" + ((Math.max(u, 16) + 16) >> 4) + ")");
|
||||
Iris.info(" Jigsaw Mantle Size: " + jig + " (" + ((Math.max(jig, 16) + 16) >> 4) + ")");
|
||||
Iris.info(" Carving Mantle Size: " + c + " (" + ((Math.max(c, 16) + 16) >> 4) + ")");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Iris.info("Mantle Size: " + x + " Chunks");
|
||||
Iris.info(" Object Mantle Size: " + u + " (" + ((Math.max(u, 16) + 16) >> 4) + ")");
|
||||
Iris.info(" Jigsaw Mantle Size: " + jig + " (" + ((Math.max(jig, 16) + 16) >> 4) + ")");
|
||||
Iris.info(" Carving Mantle Size: " + c + " (" + ((Math.max(c, 16) + 16) >> 4) + ")");
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,11 +25,15 @@ import com.volmit.iris.engine.scripting.EngineExecutionEnvironment;
|
||||
import com.volmit.iris.engine.scripting.IrisScriptingAPI;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
import org.apache.bsf.BSFException;
|
||||
import org.apache.bsf.BSFManager;
|
||||
import org.apache.bsf.engines.javascript.JavaScriptEngine;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(exclude = "engine")
|
||||
@ToString(exclude = "engine")
|
||||
public class IrisExecutionEnvironment implements EngineExecutionEnvironment {
|
||||
private final BSFManager manager;
|
||||
private final Engine engine;
|
||||
|
||||
@@ -76,6 +76,7 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
|
||||
private final ChronoLatch ecl;
|
||||
private final ChronoLatch cln;
|
||||
private final ChronoLatch chunkUpdater;
|
||||
private final ChronoLatch chunkDiscovery;
|
||||
private double energy = 25;
|
||||
private int entityCount = 0;
|
||||
private long charge = 0;
|
||||
@@ -92,12 +93,14 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
|
||||
clw = null;
|
||||
looper = null;
|
||||
chunkUpdater = null;
|
||||
chunkDiscovery = null;
|
||||
id = -1;
|
||||
}
|
||||
|
||||
public IrisWorldManager(Engine engine) {
|
||||
super(engine);
|
||||
chunkUpdater = new ChronoLatch(3000);
|
||||
chunkDiscovery = new ChronoLatch(5000);
|
||||
cln = new ChronoLatch(60000);
|
||||
cl = new ChronoLatch(3000);
|
||||
ecl = new ChronoLatch(250);
|
||||
@@ -128,6 +131,10 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
|
||||
updateChunks();
|
||||
}
|
||||
|
||||
if (chunkDiscovery.flip()) {
|
||||
discoverChunks();
|
||||
}
|
||||
|
||||
|
||||
if (getDimension().isInfiniteEnergy()) {
|
||||
energy += 1000;
|
||||
@@ -174,6 +181,19 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
|
||||
looper.start();
|
||||
}
|
||||
|
||||
private void discoverChunks() {
|
||||
var mantle = getEngine().getMantle().getMantle();
|
||||
for (Player i : getEngine().getWorld().realWorld().getPlayers()) {
|
||||
int r = 1;
|
||||
|
||||
for (int x = -r; x <= r; x++) {
|
||||
for (int z = -r; z <= r; z++) {
|
||||
mantle.getChunk(i.getLocation().getChunk()).flag(MantleFlag.DISCOVERED, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateChunks() {
|
||||
for (Player i : getEngine().getWorld().realWorld().getPlayers()) {
|
||||
int r = 1;
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
package com.volmit.iris.engine.actuator;
|
||||
|
||||
import com.volmit.iris.core.nms.IMemoryWorld;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.framework.EngineAssignedActuator;
|
||||
import com.volmit.iris.engine.object.IrisBiome;
|
||||
@@ -29,15 +30,18 @@ import com.volmit.iris.util.hunk.Hunk;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||
import lombok.Getter;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
|
||||
public class IrisTerrainNormalActuator extends EngineAssignedActuator<BlockData> {
|
||||
private static final BlockData AIR = Material.AIR.createBlockData();
|
||||
private static final BlockData BEDROCK = Material.BEDROCK.createBlockData();
|
||||
private static final BlockData DEEPSLATE = Material.DEEPSLATE.createBlockData();
|
||||
private static final BlockData LAVA = Material.LAVA.createBlockData();
|
||||
private static final BlockData GLASS = Material.GLASS.createBlockData();
|
||||
private static final BlockData CAVE_AIR = Material.CAVE_AIR.createBlockData();
|
||||
private static final BlockData FILLER = Material.STONE.createBlockData();
|
||||
private IMemoryWorld memoryWorld;
|
||||
@Getter
|
||||
private final RNG rng;
|
||||
@Getter
|
||||
@@ -51,15 +55,21 @@ public class IrisTerrainNormalActuator extends EngineAssignedActuator<BlockData>
|
||||
@BlockCoordinates
|
||||
@Override
|
||||
public void onActuate(int x, int z, Hunk<BlockData> h, boolean multicore, ChunkContext context) {
|
||||
PrecisionStopwatch p = PrecisionStopwatch.start();
|
||||
try {
|
||||
PrecisionStopwatch p = PrecisionStopwatch.start();
|
||||
|
||||
for (int xf = 0; xf < h.getWidth(); xf++) {
|
||||
terrainSliver(x, z, xf, h, context);
|
||||
for (int xf = 0; xf < h.getWidth(); xf++) {
|
||||
terrainSliver(x, z, xf, h, context);
|
||||
}
|
||||
|
||||
getEngine().getMetrics().getTerrain().put(p.getMilliseconds());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
//Iris.error("Fatal Error!", e);
|
||||
}
|
||||
|
||||
getEngine().getMetrics().getTerrain().put(p.getMilliseconds());
|
||||
}
|
||||
|
||||
|
||||
private int fluidOrHeight(int height) {
|
||||
return Math.max(getDimension().getFluidHeight(), height);
|
||||
}
|
||||
@@ -138,6 +148,11 @@ public class IrisTerrainNormalActuator extends EngineAssignedActuator<BlockData>
|
||||
continue;
|
||||
}
|
||||
|
||||
if (getDimension().isEnableExperimentalMerger()) {
|
||||
h.set(xf, i, zf, FILLER);
|
||||
continue;
|
||||
}
|
||||
|
||||
BlockData ore = biome.generateOres(realX, i, realZ, rng, getData());
|
||||
ore = ore == null ? region.generateOres(realX, i, realZ, rng, getData()) : ore;
|
||||
ore = ore == null ? getDimension().generateOres(realX, i, realZ, rng, getData()) : ore;
|
||||
@@ -145,7 +160,11 @@ public class IrisTerrainNormalActuator extends EngineAssignedActuator<BlockData>
|
||||
if (ore != null) {
|
||||
h.set(xf, i, zf, ore);
|
||||
} else {
|
||||
h.set(xf, i, zf, context.getRock().get(xf, zf));
|
||||
if (getDimension().isDeepslateLayer() && i < 64) {
|
||||
h.set(xf, i, zf, DEEPSLATE);
|
||||
} else {
|
||||
h.set(xf, i, zf, context.getRock().get(xf, zf));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ package com.volmit.iris.engine.data.chunk;
|
||||
import com.volmit.iris.core.nms.BiomeBaseInjector;
|
||||
import com.volmit.iris.core.nms.INMS;
|
||||
import com.volmit.iris.util.data.IrisBiomeStorage;
|
||||
import com.volmit.iris.util.data.IrisBlockData;
|
||||
import lombok.Setter;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
@@ -120,6 +121,8 @@ public class LinkedTerrainChunk implements TerrainChunk {
|
||||
|
||||
@Override
|
||||
public synchronized void setBlock(int x, int y, int z, BlockData blockData) {
|
||||
if (blockData instanceof IrisBlockData d)
|
||||
blockData = d.getBase();
|
||||
rawChunkData.setBlock(x, y, z, blockData);
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ package com.volmit.iris.engine.data.chunk;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.nms.BiomeBaseInjector;
|
||||
import com.volmit.iris.util.data.IrisBlockData;
|
||||
import com.volmit.iris.util.nbt.mca.Chunk;
|
||||
import com.volmit.iris.util.nbt.mca.NBTWorld;
|
||||
import lombok.AllArgsConstructor;
|
||||
@@ -88,6 +89,8 @@ public class MCATerrainChunk implements TerrainChunk {
|
||||
if (blockData == null) {
|
||||
Iris.error("NULL BD");
|
||||
}
|
||||
if (blockData instanceof IrisBlockData data)
|
||||
blockData = data.getBase();
|
||||
|
||||
mcaChunk.setBlockStateAt(xx, y, zz, NBTWorld.getCompound(blockData), false);
|
||||
}
|
||||
|
||||
@@ -44,7 +44,13 @@ public class IrisCeilingDecorator extends IrisEngineDecorator {
|
||||
if (decorator != null) {
|
||||
if (!decorator.isStacking()) {
|
||||
if (height >= 0 || height < getEngine().getHeight()) {
|
||||
data.set(x, height, z, fixFaces(decorator.getBlockData100(biome, getRng(), realX, height, realZ, getData()), realX, height, realZ));
|
||||
if (null != decorator.getBlockDataForTop(biome, getRng(), realX, height, realZ, getData())) {
|
||||
data.set(x, height, z, decorator.getBlockData100(biome, getRng(), realX, height, realZ, getData()));
|
||||
height--;
|
||||
data.set(x, height, z, decorator.getBlockDataForTop(biome, getRng(), realX, height, realZ, getData()));
|
||||
} else {
|
||||
data.set(x, height, z, decorator.getBlockData100(biome, getRng(), realX, height, realZ, getData()));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int stack = decorator.getHeight(getRng().nextParallelRNG(Cache.key(realX, realZ)), realX, realZ, getData());
|
||||
|
||||
@@ -39,8 +39,20 @@ public class IrisSeaFloorDecorator extends IrisEngineDecorator {
|
||||
|
||||
if (decorator != null) {
|
||||
if (!decorator.isStacking()) {
|
||||
if (!decorator.isForcePlace() && !decorator.getSlopeCondition().isDefault()
|
||||
&& !decorator.getSlopeCondition().isValid(getComplex().getSlopeStream().get(realX, realZ))) {
|
||||
return;
|
||||
}
|
||||
if (height >= 0 || height < getEngine().getHeight()) {
|
||||
data.set(x, height, z, decorator.getBlockData100(biome, getRng(), realX, height, realZ, getData()));
|
||||
if (null != decorator.getBlockDataForTop(biome, getRng(), realX, height, realZ, getData())) {
|
||||
if (height == getDimension().getFluidHeight() - 1) {
|
||||
data.set(x, height, z, decorator.getBlockData100(biome, getRng(), realX, height, realZ, getData()));
|
||||
height++;
|
||||
data.set(x, height, z, decorator.getBlockDataForTop(biome, getRng(), realX, height, realZ, getData()));
|
||||
}
|
||||
} else {
|
||||
data.set(x, height, z, decorator.getBlockData100(biome, getRng(), realX, height, realZ, getData()));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int stack = decorator.getHeight(getRng().nextParallelRNG(Cache.key(realX, realZ)), realX, realZ, getData());
|
||||
|
||||
@@ -40,7 +40,13 @@ public class IrisSeaSurfaceDecorator extends IrisEngineDecorator {
|
||||
if (decorator != null) {
|
||||
if (!decorator.isStacking()) {
|
||||
if (height >= 0 || height < getEngine().getHeight()) {
|
||||
data.set(x, height + 1, z, decorator.getBlockData100(biome, getRng(), realX, height, realZ, getData()));
|
||||
if (null != decorator.getBlockDataForTop(biome, getRng(), realX, height, realZ, getData())) {
|
||||
data.set(x, height, z, decorator.getBlockData100(biome, getRng(), realX, height, realZ, getData()));
|
||||
height++;
|
||||
data.set(x, height, z, decorator.getBlockDataForTop(biome, getRng(), realX, height, realZ, getData()));
|
||||
} else {
|
||||
data.set(x, height, z, decorator.getBlockData100(biome, getRng(), realX, height, realZ, getData()));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int stack = decorator.getHeight(getRng().nextParallelRNG(Cache.key(realX, realZ)), realX, realZ, getData());
|
||||
|
||||
@@ -45,8 +45,19 @@ public class IrisShoreLineDecorator extends IrisEngineDecorator {
|
||||
IrisDecorator decorator = getDecorator(biome, realX, realZ);
|
||||
|
||||
if (decorator != null) {
|
||||
if (!decorator.isForcePlace() && !decorator.getSlopeCondition().isDefault()
|
||||
&& !decorator.getSlopeCondition().isValid(getComplex().getSlopeStream().get(realX, realZ))) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!decorator.isStacking()) {
|
||||
data.set(x, height + 1, z, decorator.getBlockData100(biome, getRng(), realX, height, realZ, getData()));
|
||||
if (null != decorator.getBlockDataForTop(biome, getRng(), realX, height, realZ, getData())) {
|
||||
data.set(x, height, z, decorator.getBlockData100(biome, getRng(), realX, height, realZ, getData()));
|
||||
height++;
|
||||
data.set(x, height, z, decorator.getBlockDataForTop(biome, getRng(), realX, height, realZ, getData()));
|
||||
} else {
|
||||
data.set(x, height, z, decorator.getBlockData100(biome, getRng(), realX, height, realZ, getData()));
|
||||
}
|
||||
} else {
|
||||
int stack = decorator.getHeight(getRng().nextParallelRNG(Cache.key(realX, realZ)), realX, realZ, getData());
|
||||
if (decorator.isScaleStack()) {
|
||||
|
||||
@@ -53,6 +53,11 @@ public class IrisSurfaceDecorator extends IrisEngineDecorator {
|
||||
boolean underwater = height < getDimension().getFluidHeight();
|
||||
|
||||
if (decorator != null) {
|
||||
if (!decorator.isForcePlace() && !decorator.getSlopeCondition().isDefault()
|
||||
&& !decorator.getSlopeCondition().isValid(getComplex().getSlopeStream().get(realX, realZ))) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!decorator.isStacking()) {
|
||||
bd = decorator.getBlockData100(biome, getRng(), realX, height, realZ, getData());
|
||||
|
||||
|
||||
@@ -22,10 +22,14 @@ import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.gui.components.RenderType;
|
||||
import com.volmit.iris.core.gui.components.Renderer;
|
||||
import com.volmit.iris.core.link.Identifier;
|
||||
import com.volmit.iris.core.loader.IrisData;
|
||||
import com.volmit.iris.core.loader.IrisRegistrant;
|
||||
import com.volmit.iris.core.nms.IMemoryWorld;
|
||||
import com.volmit.iris.core.nms.container.BlockPos;
|
||||
import com.volmit.iris.core.nms.container.Pair;
|
||||
import com.volmit.iris.core.pregenerator.ChunkUpdater;
|
||||
import com.volmit.iris.core.service.ExternalDataSVC;
|
||||
import com.volmit.iris.engine.IrisComplex;
|
||||
import com.volmit.iris.engine.data.cache.Cache;
|
||||
import com.volmit.iris.engine.data.chunk.TerrainChunk;
|
||||
@@ -38,6 +42,7 @@ import com.volmit.iris.util.context.ChunkContext;
|
||||
import com.volmit.iris.util.context.IrisContext;
|
||||
import com.volmit.iris.util.data.B;
|
||||
import com.volmit.iris.util.data.DataProvider;
|
||||
import com.volmit.iris.util.data.IrisBlockData;
|
||||
import com.volmit.iris.util.documentation.BlockCoordinates;
|
||||
import com.volmit.iris.util.documentation.ChunkCoordinates;
|
||||
import com.volmit.iris.util.format.C;
|
||||
@@ -54,15 +59,13 @@ import com.volmit.iris.util.matter.TileWrapper;
|
||||
import com.volmit.iris.util.matter.slices.container.JigsawPieceContainer;
|
||||
import com.volmit.iris.util.parallel.BurstExecutor;
|
||||
import com.volmit.iris.util.parallel.MultiBurst;
|
||||
import com.volmit.iris.util.reflect.W;
|
||||
import com.volmit.iris.util.scheduling.ChronoLatch;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||
import com.volmit.iris.util.stream.ProceduralStream;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
@@ -74,9 +77,11 @@ import org.bukkit.inventory.InventoryHolder;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.Color;
|
||||
import java.util.Arrays;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.Semaphore;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
@@ -107,6 +112,10 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
|
||||
|
||||
EngineExecutionEnvironment getExecution();
|
||||
|
||||
IMemoryWorld getMemoryWorld();
|
||||
|
||||
IrisMerger getMerger();
|
||||
|
||||
double getMaxBiomeObjectDensity();
|
||||
|
||||
double getMaxBiomeDecoratorDensity();
|
||||
@@ -254,6 +263,11 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
|
||||
if (B.isUpdatable(data)) {
|
||||
getMantle().updateBlock(x, y, z);
|
||||
}
|
||||
if (data instanceof IrisBlockData d) {
|
||||
getMantle().getMantle().set(x, y, z, d.getCustom());
|
||||
} else {
|
||||
getMantle().getMantle().remove(x, y, z, Identifier.class);
|
||||
}
|
||||
}
|
||||
|
||||
void blockUpdatedMetric();
|
||||
@@ -261,72 +275,106 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
|
||||
@ChunkCoordinates
|
||||
@Override
|
||||
default void updateChunk(Chunk c) {
|
||||
if (c.getWorld().isChunkLoaded(c.getX() + 1, c.getZ() + 1)
|
||||
&& c.getWorld().isChunkLoaded(c.getX(), c.getZ() + 1)
|
||||
&& c.getWorld().isChunkLoaded(c.getX() + 1, c.getZ())
|
||||
&& c.getWorld().isChunkLoaded(c.getX() - 1, c.getZ() - 1)
|
||||
&& c.getWorld().isChunkLoaded(c.getX(), c.getZ() - 1)
|
||||
&& c.getWorld().isChunkLoaded(c.getX() - 1, c.getZ())
|
||||
&& c.getWorld().isChunkLoaded(c.getX() + 1, c.getZ() - 1)
|
||||
&& c.getWorld().isChunkLoaded(c.getX() - 1, c.getZ() + 1) && getMantle().getMantle().isLoaded(c)) {
|
||||
|
||||
getMantle().getMantle().raiseFlag(c.getX(), c.getZ(), MantleFlag.TILE, () -> J.s(() -> {
|
||||
getMantle().getMantle().iterateChunk(c.getX(), c.getZ(), TileWrapper.class, (x, y, z, tile) -> {
|
||||
int betterY = y + getWorld().minHeight();
|
||||
if (!TileData.setTileState(c.getBlock(x, betterY, z), tile.getData()))
|
||||
Iris.warn("Failed to set tile entity data at [%d %d %d | %s] for tile %s!", x, betterY, z, c.getBlock(x, betterY, z).getBlockData().getMaterial().getKey(), tile.getData().getTileId());
|
||||
});
|
||||
}));
|
||||
|
||||
getMantle().getMantle().raiseFlag(c.getX(), c.getZ(), MantleFlag.UPDATE, () -> J.s(() -> {
|
||||
PrecisionStopwatch p = PrecisionStopwatch.start();
|
||||
KMap<Long, Integer> updates = new KMap<>();
|
||||
RNG r = new RNG(Cache.key(c.getX(), c.getZ()));
|
||||
getMantle().getMantle().iterateChunk(c.getX(), c.getZ(), MatterCavern.class, (x, yf, z, v) -> {
|
||||
int y = yf + getWorld().minHeight();
|
||||
if (!B.isFluid(c.getBlock(x & 15, y, z & 15).getBlockData())) {
|
||||
return;
|
||||
}
|
||||
boolean u = false;
|
||||
if (B.isAir(c.getBlock(x & 15, y, z & 15).getRelative(BlockFace.DOWN).getBlockData())) {
|
||||
u = true;
|
||||
} else if (B.isAir(c.getBlock(x & 15, y, z & 15).getRelative(BlockFace.WEST).getBlockData())) {
|
||||
u = true;
|
||||
} else if (B.isAir(c.getBlock(x & 15, y, z & 15).getRelative(BlockFace.EAST).getBlockData())) {
|
||||
u = true;
|
||||
} else if (B.isAir(c.getBlock(x & 15, y, z & 15).getRelative(BlockFace.SOUTH).getBlockData())) {
|
||||
u = true;
|
||||
} else if (B.isAir(c.getBlock(x & 15, y, z & 15).getRelative(BlockFace.NORTH).getBlockData())) {
|
||||
u = true;
|
||||
}
|
||||
|
||||
if (u) {
|
||||
updates.compute(Cache.key(x & 15, z & 15), (k, vv) -> {
|
||||
if (vv != null) {
|
||||
return Math.max(vv, y);
|
||||
}
|
||||
|
||||
return y;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
updates.forEach((k, v) -> update(Cache.keyX(k), v, Cache.keyZ(k), c, r));
|
||||
getMantle().getMantle().iterateChunk(c.getX(), c.getZ(), MatterUpdate.class, (x, yf, z, v) -> {
|
||||
int y = yf + getWorld().minHeight();
|
||||
if (v != null && v.isUpdate()) {
|
||||
int vx = x & 15;
|
||||
int vz = z & 15;
|
||||
update(x, y, z, c, new RNG(Cache.key(c.getX(), c.getZ())));
|
||||
if (vx > 0 && vx < 15 && vz > 0 && vz < 15) {
|
||||
updateLighting(x, y, z, c);
|
||||
}
|
||||
}
|
||||
});
|
||||
getMantle().getMantle().deleteChunkSlice(c.getX(), c.getZ(), MatterUpdate.class);
|
||||
getMetrics().getUpdates().put(p.getMilliseconds());
|
||||
}, RNG.r.i(0, 20)));
|
||||
for (int x = -1; x <= 1; x++) {
|
||||
for (int z = -1; z <= 1; z++) {
|
||||
if (c.getWorld().isChunkLoaded(c.getX() + x, c.getZ() + z))
|
||||
continue;
|
||||
var msg = "Chunk %s, %s [%s, %s] is not loaded".formatted(c.getX() + x, c.getZ() + z, x, z);
|
||||
if (W.getStack().getCallerClass().equals(ChunkUpdater.class)) Iris.warn(msg);
|
||||
else Iris.debug(msg);
|
||||
return;
|
||||
}
|
||||
}
|
||||
var mantle = getMantle().getMantle();
|
||||
if (!mantle.isLoaded(c)) {
|
||||
var msg = "Mantle Chunk " + c.getX() + c.getX() + " is not loaded";
|
||||
if (W.getStack().getCallerClass().equals(ChunkUpdater.class)) Iris.warn(msg);
|
||||
else Iris.debug(msg);
|
||||
return;
|
||||
}
|
||||
|
||||
var chunk = mantle.getChunk(c);
|
||||
if (chunk.isFlagged(MantleFlag.ETCHED)) return;
|
||||
chunk.flag(MantleFlag.ETCHED, true);
|
||||
|
||||
Semaphore semaphore = new Semaphore(3);
|
||||
chunk.raiseFlag(MantleFlag.TILE, run(semaphore, () -> J.s(() -> {
|
||||
mantle.iterateChunk(c.getX(), c.getZ(), TileWrapper.class, (x, y, z, v) -> {
|
||||
int betterY = y + getWorld().minHeight();
|
||||
if (!TileData.setTileState(c.getBlock(x, betterY, z), v.getData()))
|
||||
Iris.warn("Failed to set tile entity data at [%d %d %d | %s] for tile %s!", x, betterY, z, c.getBlock(x, betterY, z).getBlockData().getMaterial().getKey(), v.getData().getMaterial().name());
|
||||
});
|
||||
})));
|
||||
chunk.raiseFlag(MantleFlag.CUSTOM, run(semaphore, () -> J.s(() -> {
|
||||
mantle.iterateChunk(c.getX(), c.getZ(), Identifier.class, (x, y, z, v) -> {
|
||||
Iris.service(ExternalDataSVC.class).processUpdate(this, c.getBlock(x & 15, y + getWorld().minHeight(), z & 15), v);
|
||||
});
|
||||
})));
|
||||
|
||||
chunk.raiseFlag(MantleFlag.UPDATE, run(semaphore, () -> J.s(() -> {
|
||||
PrecisionStopwatch p = PrecisionStopwatch.start();
|
||||
KMap<Long, Integer> updates = new KMap<>();
|
||||
RNG r = new RNG(Cache.key(c.getX(), c.getZ()));
|
||||
mantle.iterateChunk(c.getX(), c.getZ(), MatterCavern.class, (x, yf, z, v) -> {
|
||||
int y = yf + getWorld().minHeight();
|
||||
if (!B.isFluid(c.getBlock(x & 15, y, z & 15).getBlockData())) {
|
||||
return;
|
||||
}
|
||||
boolean u = false;
|
||||
if (B.isAir(c.getBlock(x & 15, y, z & 15).getRelative(BlockFace.DOWN).getBlockData())) {
|
||||
u = true;
|
||||
} else if (B.isAir(c.getBlock(x & 15, y, z & 15).getRelative(BlockFace.WEST).getBlockData())) {
|
||||
u = true;
|
||||
} else if (B.isAir(c.getBlock(x & 15, y, z & 15).getRelative(BlockFace.EAST).getBlockData())) {
|
||||
u = true;
|
||||
} else if (B.isAir(c.getBlock(x & 15, y, z & 15).getRelative(BlockFace.SOUTH).getBlockData())) {
|
||||
u = true;
|
||||
} else if (B.isAir(c.getBlock(x & 15, y, z & 15).getRelative(BlockFace.NORTH).getBlockData())) {
|
||||
u = true;
|
||||
}
|
||||
|
||||
if (u) {
|
||||
updates.compute(Cache.key(x & 15, z & 15), (k, vv) -> {
|
||||
if (vv != null) {
|
||||
return Math.max(vv, y);
|
||||
}
|
||||
|
||||
return y;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
updates.forEach((k, v) -> update(Cache.keyX(k), v, Cache.keyZ(k), c, r));
|
||||
mantle.iterateChunk(c.getX(), c.getZ(), MatterUpdate.class, (x, yf, z, v) -> {
|
||||
int y = yf + getWorld().minHeight();
|
||||
if (v != null && v.isUpdate()) {
|
||||
int vx = x & 15;
|
||||
int vz = z & 15;
|
||||
update(x, y, z, c, new RNG(Cache.key(c.getX(), c.getZ())));
|
||||
if (vx > 0 && vx < 15 && vz > 0 && vz < 15) {
|
||||
updateLighting(x, y, z, c);
|
||||
}
|
||||
}
|
||||
});
|
||||
mantle.deleteChunkSlice(c.getX(), c.getZ(), MatterUpdate.class);
|
||||
getMetrics().getUpdates().put(p.getMilliseconds());
|
||||
}, RNG.r.i(0, 20))));
|
||||
|
||||
try {
|
||||
semaphore.acquire(3);
|
||||
} catch (InterruptedException ignored) {}
|
||||
}
|
||||
|
||||
private static Runnable run(Semaphore semaphore, Runnable runnable) {
|
||||
return () -> {
|
||||
if (!semaphore.tryAcquire())
|
||||
return;
|
||||
try {
|
||||
runnable.run();
|
||||
} finally {
|
||||
semaphore.release();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@BlockCoordinates
|
||||
@@ -372,7 +420,7 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
|
||||
if (tables.isEmpty())
|
||||
return;
|
||||
InventoryHolder m = (InventoryHolder) block.getState();
|
||||
addItems(false, m.getInventory(), rx, tables, slot, x, y, z, 15);
|
||||
addItems(false, m.getInventory(), rx, tables, slot, c.getWorld(), x, y, z, 15);
|
||||
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
@@ -481,7 +529,7 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
|
||||
}
|
||||
|
||||
@Override
|
||||
default void addItems(boolean debug, Inventory inv, RNG rng, KList<IrisLootTable> tables, InventorySlotType slot, int x, int y, int z, int mgf) {
|
||||
default void addItems(boolean debug, Inventory inv, RNG rng, KList<IrisLootTable> tables, InventorySlotType slot, World world, int x, int y, int z, int mgf) {
|
||||
KList<ItemStack> items = new KList<>();
|
||||
|
||||
int b = 4;
|
||||
@@ -489,10 +537,10 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
|
||||
if (i == null)
|
||||
continue;
|
||||
b++;
|
||||
items.addAll(i.getLoot(debug, rng, slot, x, y, z));
|
||||
items.addAll(i.getLoot(debug, rng, slot, world, x, y, z));
|
||||
}
|
||||
|
||||
if (PaperLib.isPaper() && getWorld().hasRealWorld()) {
|
||||
if (PaperLib.isPaper() && getWorld().hasRealWorld()) {
|
||||
PaperLib.getChunkAtAsync(getWorld().realWorld(), x >> 4, z >> 4).thenAccept((c) -> {
|
||||
Runnable r = () -> {
|
||||
for (ItemStack i : items) {
|
||||
@@ -523,8 +571,9 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
|
||||
return getTarget().getBurster();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
default void clean() {
|
||||
burst().lazy(() -> getMantle().trim());
|
||||
burst().lazy(() -> getMantle().trim(10));
|
||||
}
|
||||
|
||||
@BlockCoordinates
|
||||
@@ -803,7 +852,7 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
|
||||
return getBiomeOrMantle(l.getBlockX(), l.getBlockY(), l.getBlockZ());
|
||||
}
|
||||
|
||||
default void gotoBiome(IrisBiome biome, Player player) {
|
||||
default void gotoBiome(IrisBiome biome, Player player, boolean teleport) {
|
||||
Set<String> regionKeys = getDimension()
|
||||
.getAllRegions(this).stream()
|
||||
.filter((i) -> i.getAllBiomes(this).contains(biome))
|
||||
@@ -815,15 +864,15 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
|
||||
&& lb.matches(engine, chunk);
|
||||
|
||||
if (!regionKeys.isEmpty()) {
|
||||
locator.find(player);
|
||||
locator.find(player, teleport, "Biome " + biome.getName());
|
||||
} else {
|
||||
player.sendMessage(C.RED + biome.getName() + " is not in any defined regions!");
|
||||
}
|
||||
}
|
||||
|
||||
default void gotoJigsaw(IrisJigsawStructure s, Player player) {
|
||||
default void gotoJigsaw(IrisJigsawStructure s, Player player, boolean teleport) {
|
||||
if (s.getLoadKey().equals(getDimension().getStronghold())) {
|
||||
KList<Position2> p = getDimension().getStrongholds(getSeedManager().getSpawn());
|
||||
KList<Position2> p = getDimension().getStrongholds(getSeedManager().getMantle());
|
||||
|
||||
if (p.isEmpty()) {
|
||||
player.sendMessage(C.GOLD + "No strongholds in world.");
|
||||
@@ -858,7 +907,7 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
|
||||
if (getDimension().getJigsawStructures().stream()
|
||||
.map(IrisJigsawStructurePlacement::getStructure)
|
||||
.collect(Collectors.toSet()).contains(s.getLoadKey())) {
|
||||
Locator.jigsawStructure(s.getLoadKey()).find(player);
|
||||
Locator.jigsawStructure(s.getLoadKey()).find(player, teleport, "Structure " + s.getLoadKey());
|
||||
} else {
|
||||
Set<String> biomeKeys = getDimension().getAllBiomes(this).stream()
|
||||
.filter((i) -> i.getJigsawStructures()
|
||||
@@ -885,7 +934,7 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
|
||||
};
|
||||
|
||||
if (!regionKeys.isEmpty()) {
|
||||
locator.find(player);
|
||||
locator.find(player, teleport, "Structure " + s.getLoadKey());
|
||||
} else {
|
||||
player.sendMessage(C.RED + s.getLoadKey() + " is not in any defined regions, biomes or dimensions!");
|
||||
}
|
||||
@@ -893,7 +942,7 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
|
||||
|
||||
}
|
||||
|
||||
default void gotoObject(String s, Player player) {
|
||||
default void gotoObject(String s, Player player, boolean teleport) {
|
||||
Set<String> biomeKeys = getDimension().getAllBiomes(this).stream()
|
||||
.filter((i) -> i.getObjects().stream().anyMatch((f) -> f.getPlace().contains(s)))
|
||||
.map(IrisRegistrant::getLoadKey)
|
||||
@@ -916,23 +965,23 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
|
||||
};
|
||||
|
||||
if (!regionKeys.isEmpty()) {
|
||||
locator.find(player);
|
||||
locator.find(player, teleport, "Object " + s);
|
||||
} else {
|
||||
player.sendMessage(C.RED + s + " is not in any defined regions or biomes!");
|
||||
}
|
||||
}
|
||||
|
||||
default void gotoRegion(IrisRegion r, Player player) {
|
||||
default void gotoRegion(IrisRegion r, Player player, boolean teleport) {
|
||||
if (!getDimension().getAllRegions(this).contains(r)) {
|
||||
player.sendMessage(C.RED + r.getName() + " is not defined in the dimension!");
|
||||
return;
|
||||
}
|
||||
|
||||
Locator.region(r.getLoadKey()).find(player);
|
||||
Locator.region(r.getLoadKey()).find(player, teleport, "Region " + r.getName());
|
||||
}
|
||||
|
||||
default void gotoPOI(String type, Player p) {
|
||||
Locator.poi(type).find(p);
|
||||
default void gotoPOI(String type, Player p, boolean teleport) {
|
||||
Locator.poi(type).find(p, teleport, "POI " + type);
|
||||
}
|
||||
|
||||
default void cleanupMantleChunk(int x, int z) {
|
||||
|
||||
@@ -21,8 +21,12 @@ package com.volmit.iris.engine.framework;
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.util.math.RollingSequence;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(exclude = "engine")
|
||||
@ToString(exclude = "engine")
|
||||
public class EngineAssignedComponent implements EngineComponent {
|
||||
private final Engine engine;
|
||||
private final RollingSequence metrics;
|
||||
|
||||
@@ -110,7 +110,7 @@ public abstract class EngineAssignedWorldManager extends EngineAssignedComponent
|
||||
return;
|
||||
}
|
||||
|
||||
KList<Position2> positions = getEngine().getDimension().getStrongholds(getEngine().getSeedManager().getSpawn());
|
||||
KList<Position2> positions = getEngine().getDimension().getStrongholds(getEngine().getSeedManager().getMantle());
|
||||
if (positions.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -23,8 +23,12 @@ import com.volmit.iris.engine.object.IrisDimension;
|
||||
import com.volmit.iris.engine.object.IrisWorld;
|
||||
import com.volmit.iris.util.parallel.MultiBurst;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(exclude = "data")
|
||||
@ToString(exclude = "data")
|
||||
public class EngineTarget {
|
||||
private final MultiBurst burster;
|
||||
private final IrisData data;
|
||||
|
||||
@@ -3,30 +3,107 @@ package com.volmit.iris.engine.framework;
|
||||
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.math.RNG;
|
||||
import lombok.Getter;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.World;
|
||||
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.bukkit.loot.LootTables;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
public class IrisLootEvent extends Event {
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
|
||||
private final Engine engine;
|
||||
private final Block block;
|
||||
private final InventorySlotType slot;
|
||||
private final KList<IrisLootTable> tables;
|
||||
private final Mode mode; // New field to represent the mode
|
||||
|
||||
// Define the different modes for the event
|
||||
public enum Mode {
|
||||
NORMAL,
|
||||
BUKKIT_LOOT
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
this.mode = Mode.BUKKIT_LOOT;
|
||||
|
||||
if (this.mode == Mode.BUKKIT_LOOT) {
|
||||
triggerBukkitLootEvent();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
private Inventory triggerBukkitLootEvent() {
|
||||
if (block.getState() instanceof InventoryHolder holder) {
|
||||
Inventory inventory = holder.getInventory();
|
||||
inventory.clear();
|
||||
|
||||
List<ItemStack> loot = new ArrayList<>();
|
||||
RNG rng = new RNG();
|
||||
int x = block.getX(), y = block.getY(), z = block.getZ();
|
||||
|
||||
for (IrisLootTable table : tables)
|
||||
loot.addAll(table.getLoot(false, rng, slot, block.getWorld(), x, y, z));
|
||||
|
||||
LootContext context = new LootContext.Builder(block.getLocation()).build();
|
||||
|
||||
LootTable lootTable = LootTables.EMPTY.getLootTable(); // todo: Correct structure
|
||||
|
||||
LootGenerateEvent bukkitEvent = new LootGenerateEvent(engine.getWorld().realWorld(), null, holder, lootTable, context, loot, true); // todo: Use the iris loottable
|
||||
Bukkit.getServer().getPluginManager().callEvent(bukkitEvent);
|
||||
|
||||
if (!bukkitEvent.isCancelled())
|
||||
inventory.setContents(bukkitEvent.getLoot().toArray(new ItemStack[0]));
|
||||
return inventory;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Required method to get the HandlerList for this event.
|
||||
*
|
||||
* @return The HandlerList.
|
||||
*/
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.volmit.iris.engine.framework;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
public interface ListFunction<T, R> extends Function<T, R> {
|
||||
String key();
|
||||
String fancyName();
|
||||
}
|
||||
@@ -27,6 +27,7 @@ import com.volmit.iris.engine.object.IrisJigsawStructure;
|
||||
import com.volmit.iris.engine.object.IrisObject;
|
||||
import com.volmit.iris.engine.object.IrisRegion;
|
||||
import com.volmit.iris.util.context.ChunkContext;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.math.M;
|
||||
import com.volmit.iris.util.math.Position2;
|
||||
@@ -39,6 +40,7 @@ import com.volmit.iris.util.scheduling.J;
|
||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||
import com.volmit.iris.util.scheduling.jobs.SingleJob;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Set;
|
||||
@@ -109,23 +111,35 @@ public interface Locator<T> {
|
||||
|
||||
boolean matches(Engine engine, Position2 chunk);
|
||||
|
||||
default void find(Player player) {
|
||||
find(player, 30_000);
|
||||
default void find(Player player, boolean teleport, String message) {
|
||||
find(player, location -> {
|
||||
if (teleport) {
|
||||
J.s(() -> player.teleport(location));
|
||||
} else {
|
||||
player.sendMessage(C.GREEN + message + " at: " + location.getBlockX() + " " + location.getBlockY() + " " + location.getBlockZ());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
default void find(Player player, long timeout) {
|
||||
default void find(Player player, Consumer<Location> consumer) {
|
||||
find(player, 30_000, consumer);
|
||||
}
|
||||
|
||||
default void find(Player player, long timeout, Consumer<Location> consumer) {
|
||||
AtomicLong checks = new AtomicLong();
|
||||
long ms = M.ms();
|
||||
new SingleJob("Searching", () -> {
|
||||
try {
|
||||
Position2 at = find(IrisToolbelt.access(player.getWorld()).getEngine(), new Position2(player.getLocation().getBlockX() >> 4, player.getLocation().getBlockZ() >> 4), timeout, checks::set).get();
|
||||
World world = player.getWorld();
|
||||
Engine engine = IrisToolbelt.access(world).getEngine();
|
||||
Position2 at = find(engine, new Position2(player.getLocation().getBlockX() >> 4, player.getLocation().getBlockZ() >> 4), timeout, checks::set).get();
|
||||
|
||||
if (at != null) {
|
||||
J.s(() -> player.teleport(new Location(player.getWorld(), (at.getX() << 4) + 8,
|
||||
IrisToolbelt.access(player.getWorld()).getEngine().getHeight(
|
||||
consumer.accept(new Location(world, (at.getX() << 4) + 8,
|
||||
engine.getHeight(
|
||||
(at.getX() << 4) + 8,
|
||||
(at.getZ() << 4) + 8, false),
|
||||
(at.getZ() << 4) + 8)));
|
||||
(at.getZ() << 4) + 8));
|
||||
}
|
||||
} catch (WrongEngineBroException | InterruptedException | ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.volmit.iris.engine.object.IrisLootReference;
|
||||
import com.volmit.iris.engine.object.IrisLootTable;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
|
||||
@@ -33,5 +34,5 @@ public interface LootProvider {
|
||||
|
||||
KList<IrisLootTable> getLootTables(RNG rng, Block b);
|
||||
|
||||
void addItems(boolean debug, Inventory inv, RNG rng, KList<IrisLootTable> tables, InventorySlotType slot, int x, int y, int z, int mgf);
|
||||
void addItems(boolean debug, Inventory inv, RNG rng, KList<IrisLootTable> tables, InventorySlotType slot, World world, int x, int y, int z, int mgf);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
package com.volmit.iris.engine.framework;
|
||||
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.engine.object.IrisJigsawStructure;
|
||||
import com.volmit.iris.engine.object.IrisObject;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.math.Position2;
|
||||
import com.volmit.iris.util.math.Spiraler;
|
||||
import com.volmit.iris.util.parallel.BurstExecutor;
|
||||
import com.volmit.iris.util.parallel.MultiBurst;
|
||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||
import org.apache.commons.lang3.function.TriFunction;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ResultLocator<T> {
|
||||
static void cancelSearch() {
|
||||
if (LocatorCanceller.cancel != null) {
|
||||
LocatorCanceller.cancel.run();
|
||||
LocatorCanceller.cancel = null;
|
||||
}
|
||||
}
|
||||
|
||||
static ResultLocator<IrisJigsawStructure> locateStructure(Collection<String> keys) {
|
||||
return (e, pos) -> {
|
||||
var structure = e.getStructureAt(pos.getX(), pos.getZ());
|
||||
return structure != null && keys.contains(structure.getLoadKey()) ? structure : null;
|
||||
};
|
||||
}
|
||||
|
||||
static ResultLocator<IrisObject> locateObject(Collection<String> keys) {
|
||||
return (e, pos) -> {
|
||||
Set<String> objects = e.getObjectsAt(pos.getX(), pos.getZ());
|
||||
for (String object : objects) {
|
||||
if (!keys.contains(object)) continue;
|
||||
return e.getData().getObjectLoader().load(object);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
}
|
||||
|
||||
T find(Engine e, Position2 chunkPos);
|
||||
|
||||
default <R> ResultLocator<R> then(TriFunction<Engine, Position2, T, R> filter) {
|
||||
return (e, pos) -> {
|
||||
var t = find(e, pos);
|
||||
return t != null ? filter.apply(e, pos, t) : null;
|
||||
};
|
||||
}
|
||||
|
||||
default Future<Result<T>> find(Engine engine, Position2 pos, long timeout, Consumer<Integer> checks, boolean cancelable) throws WrongEngineBroException {
|
||||
if (engine.isClosed()) {
|
||||
throw new WrongEngineBroException();
|
||||
}
|
||||
|
||||
cancelSearch();
|
||||
|
||||
return MultiBurst.burst.completeValue(() -> {
|
||||
int tc = IrisSettings.getThreadCount(IrisSettings.get().getConcurrency().getParallelism()) * 17;
|
||||
MultiBurst burst = MultiBurst.burst;
|
||||
AtomicBoolean found = new AtomicBoolean(false);
|
||||
AtomicReference<Result<T>> foundObj = new AtomicReference<>();
|
||||
Position2 cursor = pos;
|
||||
AtomicInteger searched = new AtomicInteger();
|
||||
AtomicBoolean stop = new AtomicBoolean(false);
|
||||
PrecisionStopwatch px = PrecisionStopwatch.start();
|
||||
if (cancelable) LocatorCanceller.cancel = () -> stop.set(true);
|
||||
AtomicReference<Position2> next = new AtomicReference<>(cursor);
|
||||
Spiraler s = new Spiraler(100000, 100000, (x, z) -> next.set(new Position2(x, z)));
|
||||
s.setOffset(cursor.getX(), cursor.getZ());
|
||||
s.next();
|
||||
while (!found.get() && !stop.get() && px.getMilliseconds() < timeout) {
|
||||
BurstExecutor e = burst.burst(tc);
|
||||
|
||||
for (int i = 0; i < tc; i++) {
|
||||
Position2 p = next.get();
|
||||
s.next();
|
||||
e.queue(() -> {
|
||||
var o = find(engine, p);
|
||||
if (o != null) {
|
||||
if (foundObj.get() == null) {
|
||||
foundObj.set(new Result<>(o, p));
|
||||
}
|
||||
|
||||
found.set(true);
|
||||
}
|
||||
searched.incrementAndGet();
|
||||
});
|
||||
}
|
||||
|
||||
e.complete();
|
||||
checks.accept(searched.get());
|
||||
}
|
||||
|
||||
LocatorCanceller.cancel = null;
|
||||
|
||||
if (found.get() && foundObj.get() != null) {
|
||||
return foundObj.get();
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
record Result<T>(T obj, Position2 pos) {
|
||||
public int getBlockX() {
|
||||
return (pos.getX() << 4) + 8;
|
||||
}
|
||||
|
||||
public int getBlockZ() {
|
||||
return (pos.getZ() << 4) + 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -60,7 +60,7 @@ public class HeightmapObjectPlacer implements IObjectPlacer {
|
||||
|
||||
@Override
|
||||
public boolean isCarved(int x, int y, int z) {
|
||||
return false;
|
||||
return oplacer.isCarved(x,y,z);
|
||||
}
|
||||
|
||||
public boolean isSolid(int param1Int1, int param1Int2, int param1Int3) {
|
||||
@@ -79,7 +79,7 @@ public class HeightmapObjectPlacer implements IObjectPlacer {
|
||||
return oplacer.isDebugSmartBore();
|
||||
}
|
||||
|
||||
public void setTile(int param1Int1, int param1Int2, int param1Int3, TileData<? extends TileState> param1TileData) {
|
||||
public void setTile(int param1Int1, int param1Int2, int param1Int3, TileData param1TileData) {
|
||||
oplacer.setTile(param1Int1, param1Int2, param1Int3, param1TileData);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
package com.volmit.iris.engine.framework.placer;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.loader.IrisData;
|
||||
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.engine.framework.IrisLootEvent;
|
||||
import com.volmit.iris.engine.mantle.EngineMantle;
|
||||
import com.volmit.iris.engine.object.IObjectPlacer;
|
||||
import com.volmit.iris.engine.object.InventorySlotType;
|
||||
import com.volmit.iris.engine.object.IrisLootTable;
|
||||
import com.volmit.iris.engine.object.TileData;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.data.B;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.block.TileState;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.InventoryHolder;
|
||||
|
||||
@Getter
|
||||
@EqualsAndHashCode(exclude = {"engine", "mantle"})
|
||||
public class WorldObjectPlacer implements IObjectPlacer {
|
||||
private final World world;
|
||||
private final Engine engine;
|
||||
private final EngineMantle mantle;
|
||||
|
||||
public WorldObjectPlacer(World world) {
|
||||
var a = IrisToolbelt.access(world);
|
||||
if (a == null || a.getEngine() == null) throw new IllegalStateException(world.getName() + " is not an Iris World!");
|
||||
this.world = world;
|
||||
this.engine = a.getEngine();
|
||||
this.mantle = engine.getMantle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHighest(int x, int z, IrisData data) {
|
||||
return mantle.getHighest(x, z, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHighest(int x, int z, IrisData data, boolean ignoreFluid) {
|
||||
return mantle.getHighest(x, z, data, ignoreFluid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(int x, int y, int z, BlockData d) {
|
||||
Block block = world.getBlockAt(x, y + world.getMinHeight(), z);
|
||||
|
||||
if (y <= world.getMinHeight() || block.getType() == Material.BEDROCK) return;
|
||||
InventorySlotType slot = null;
|
||||
if (B.isStorageChest(d)) {
|
||||
slot = InventorySlotType.STORAGE;
|
||||
}
|
||||
|
||||
if (slot != null) {
|
||||
RNG rx = new RNG(Cache.key(x, z));
|
||||
KList<IrisLootTable> tables = engine.getLootTables(rx, block);
|
||||
|
||||
Inventory inventory = null;
|
||||
|
||||
try {
|
||||
Bukkit.getPluginManager().callEvent(new IrisLootEvent(engine, block, slot, tables));
|
||||
|
||||
if (!tables.isEmpty()){
|
||||
Iris.debug("IrisLootEvent has been accessed");
|
||||
}
|
||||
|
||||
if (tables.isEmpty())
|
||||
return;
|
||||
InventoryHolder m = (InventoryHolder) block.getState();
|
||||
engine.addItems(false, m.getInventory(), rx, tables, slot, world, x, y, z, 15);
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
}
|
||||
}
|
||||
|
||||
block.setBlockData(d);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockData get(int x, int y, int z) {
|
||||
return world.getBlockAt(x, y + world.getMinHeight(), z).getBlockData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPreventingDecay() {
|
||||
return mantle.isPreventingDecay();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCarved(int x, int y, int z) {
|
||||
return mantle.isCarved(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSolid(int x, int y, int z) {
|
||||
return world.getBlockAt(x, y + world.getMinHeight(), z).getType().isSolid();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUnderwater(int x, int z) {
|
||||
return mantle.isUnderwater(x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFluidHeight() {
|
||||
return mantle.getFluidHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDebugSmartBore() {
|
||||
return mantle.isDebugSmartBore();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTile(int xx, int yy, int zz, TileData tile) {
|
||||
tile.toBukkitTry(world.getBlockAt(xx, yy + world.getMinHeight(), zz));
|
||||
}
|
||||
}
|
||||
@@ -18,27 +18,21 @@
|
||||
|
||||
package com.volmit.iris.engine.jigsaw;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.loader.IrisData;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.object.*;
|
||||
import com.volmit.iris.engine.platform.PlatformChunkGenerator;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.context.IrisContext;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.math.AxisAlignedBB;
|
||||
import com.volmit.iris.util.math.BlockPosition;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Data;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.block.TileState;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.inventory.InventoryHolder;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Setter;
|
||||
import org.bukkit.util.BlockVector;
|
||||
|
||||
@SuppressWarnings("ALL")
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class PlannedPiece {
|
||||
private IrisPosition position;
|
||||
@@ -46,11 +40,19 @@ public class PlannedPiece {
|
||||
private IrisObject ogObject;
|
||||
private IrisJigsawPiece piece;
|
||||
private IrisObjectRotation rotation;
|
||||
@EqualsAndHashCode.Exclude
|
||||
private IrisData data;
|
||||
private KList<IrisJigsawPieceConnector> connected;
|
||||
private boolean dead = false;
|
||||
private AxisAlignedBB box;
|
||||
@EqualsAndHashCode.Exclude
|
||||
private PlannedStructure structure;
|
||||
@EqualsAndHashCode.Exclude
|
||||
@Setter(AccessLevel.NONE)
|
||||
private ParentConnection parent = null;
|
||||
@EqualsAndHashCode.Exclude
|
||||
@Setter(AccessLevel.NONE)
|
||||
private KMap<IrisJigsawPieceConnector, IrisPosition> realPositions;
|
||||
|
||||
public PlannedPiece(PlannedStructure structure, IrisPosition position, IrisJigsawPiece piece) {
|
||||
this(structure, position, piece, 0, 0, 0);
|
||||
@@ -72,6 +74,8 @@ public class PlannedPiece {
|
||||
this.object.setLoadKey(piece.getObject());
|
||||
this.ogObject.setLoadKey(piece.getObject());
|
||||
this.connected = new KList<>();
|
||||
this.realPositions = new KMap<>();
|
||||
|
||||
}
|
||||
|
||||
public void setPosition(IrisPosition p) {
|
||||
@@ -89,7 +93,15 @@ public class PlannedPiece {
|
||||
}
|
||||
|
||||
BlockVector v = getObject().getCenter();
|
||||
box = object.getAABB().shifted(position.add(new IrisPosition(object.getCenter())));
|
||||
IrisPosition pos = new IrisPosition();
|
||||
IrisObjectPlacement options = piece.getPlacementOptions();
|
||||
if (options != null && options.getTranslate() != null) {
|
||||
IrisObjectTranslate translate = options.getTranslate();
|
||||
pos.setX(translate.getX());
|
||||
pos.setY(translate.getY());
|
||||
pos.setZ(translate.getZ());
|
||||
}
|
||||
box = object.getAABB().shifted(position.add(new IrisPosition(object.getCenter())).add(pos));
|
||||
return box;
|
||||
}
|
||||
|
||||
@@ -121,11 +133,21 @@ public class PlannedPiece {
|
||||
return c;
|
||||
}
|
||||
|
||||
public boolean connect(IrisJigsawPieceConnector c) {
|
||||
if (piece.getConnectors().contains(c)) {
|
||||
return connected.addIfMissing(c);
|
||||
}
|
||||
public KList<IrisJigsawPieceConnector> getChildConnectors() {
|
||||
ParentConnection pc = getParent();
|
||||
KList<IrisJigsawPieceConnector> c = getConnected().copy();
|
||||
if (pc != null) c.removeIf(i -> i.equals(pc.connector));
|
||||
return c;
|
||||
}
|
||||
|
||||
public boolean connect(IrisJigsawPieceConnector c, PlannedPiece p, IrisJigsawPieceConnector pc) {
|
||||
if (piece.getConnectors().contains(c) && p.getPiece().getConnectors().contains(pc)) {
|
||||
if (connected.contains(c) || p.connected.contains(pc)) return false;
|
||||
connected.add(c);
|
||||
p.connected.add(pc);
|
||||
p.parent = new ParentConnection(this, c, p, pc);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -133,113 +155,53 @@ public class PlannedPiece {
|
||||
return getWorldPosition(c.getPosition());
|
||||
}
|
||||
|
||||
public List<IrisPosition> getConnectorWorldPositions() {
|
||||
List<IrisPosition> worldPositions = new ArrayList<>();
|
||||
|
||||
for (IrisJigsawPieceConnector connector : this.piece.getConnectors()) {
|
||||
IrisPosition worldPosition = getWorldPosition(connector.getPosition());
|
||||
worldPositions.add(worldPosition);
|
||||
}
|
||||
|
||||
return worldPositions;
|
||||
}
|
||||
|
||||
public IrisPosition getWorldPosition(IrisPosition position) {
|
||||
return this.position.add(position).add(new IrisPosition(object.getCenter()));
|
||||
}
|
||||
|
||||
public boolean isFull() {
|
||||
return connected.size() >= piece.getConnectors().size() || isDead();
|
||||
public void debugPrintConnectorPositions() {
|
||||
Iris.debug("Connector World Positions for PlannedPiece at " + position + ":");
|
||||
List<IrisPosition> connectorPositions = getConnectorWorldPositions();
|
||||
for (IrisPosition pos : connectorPositions) {
|
||||
Iris.debug(" - Connector at: " + pos);
|
||||
}
|
||||
}
|
||||
|
||||
public void place(World world) {
|
||||
PlatformChunkGenerator a = IrisToolbelt.access(world);
|
||||
public boolean isFull() {
|
||||
return connected.size() >= piece.getConnectors().size();
|
||||
}
|
||||
|
||||
int minY = 0;
|
||||
if (a != null) {
|
||||
minY = a.getEngine().getMinHeight();
|
||||
|
||||
if (!a.getEngine().getDimension().isBedrock())
|
||||
minY--; //If the dimension has no bedrock, allow it to go a block lower
|
||||
public void setRealPositions(int x, int y, int z, IObjectPlacer placer) {
|
||||
boolean isUnderwater = piece.getPlacementOptions().isUnderwater();
|
||||
for (IrisJigsawPieceConnector c : piece.getConnectors()) {
|
||||
var pos = c.getPosition().add(new IrisPosition(x, 0, z));
|
||||
if (y < 0) {
|
||||
pos.setY(pos.getY() + placer.getHighest(pos.getX(), pos.getZ(), getData(), isUnderwater) + (object.getH() / 2));
|
||||
} else {
|
||||
pos.setY(pos.getY() + y);
|
||||
}
|
||||
realPositions.put(c, pos);
|
||||
}
|
||||
}
|
||||
|
||||
getPiece().getPlacementOptions().setTranslate(new IrisObjectTranslate());
|
||||
getPiece().getPlacementOptions().setRotation(rotation);
|
||||
int finalMinY = minY;
|
||||
RNG rng = getStructure().getRng().nextParallelRNG(37555);
|
||||
|
||||
// TODO: REAL CLASSES!!!!!!!
|
||||
getOgObject().place(position.getX() + getObject().getCenter().getBlockX(), position.getY() + getObject().getCenter().getBlockY(), position.getZ() + getObject().getCenter().getBlockZ(), new IObjectPlacer() {
|
||||
@Override
|
||||
public int getHighest(int x, int z, IrisData data) {
|
||||
return position.getY();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHighest(int x, int z, IrisData data, boolean ignoreFluid) {
|
||||
return position.getY();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(int x, int y, int z, BlockData d) {
|
||||
Block block = world.getBlockAt(x, y, z);
|
||||
|
||||
//Prevent blocks being set in or bellow bedrock
|
||||
if (y <= finalMinY || block.getType() == Material.BEDROCK) return;
|
||||
|
||||
block.setBlockData(d);
|
||||
|
||||
if (a != null && getPiece().getPlacementOptions().getLoot().isNotEmpty() &&
|
||||
block.getState() instanceof InventoryHolder) {
|
||||
|
||||
IrisLootTable table = getPiece().getPlacementOptions().getTable(block.getBlockData(), getData());
|
||||
if (table == null) return;
|
||||
Engine engine = a.getEngine();
|
||||
engine.addItems(false, ((InventoryHolder) block.getState()).getInventory(),
|
||||
rng.nextParallelRNG(BlockPosition.toLong(x, y, z)),
|
||||
new KList<>(table), InventorySlotType.STORAGE, x, y, z, 15);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockData get(int x, int y, int z) {
|
||||
return world.getBlockAt(x, y, z).getBlockData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPreventingDecay() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCarved(int x, int y, int z) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSolid(int x, int y, int z) {
|
||||
return world.getBlockAt(x, y, z).getType().isSolid();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUnderwater(int x, int z) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFluidHeight() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDebugSmartBore() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTile(int xx, int yy, int zz, TileData<? extends TileState> tile) {
|
||||
BlockState state = world.getBlockAt(xx, yy, zz).getState();
|
||||
tile.toBukkitTry(state);
|
||||
state.update();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Engine getEngine() {
|
||||
if (IrisToolbelt.isIrisWorld(world)) {
|
||||
return IrisToolbelt.access(world).getEngine();
|
||||
}
|
||||
|
||||
return IrisContext.get().getEngine();
|
||||
}
|
||||
}, piece.getPlacementOptions(), rng, getData());
|
||||
public record ParentConnection(PlannedPiece parent, IrisJigsawPieceConnector parentConnector, PlannedPiece self, IrisJigsawPieceConnector connector) {
|
||||
public IrisPosition getTargetPosition() {
|
||||
var pos = parent.realPositions.get(parentConnector);
|
||||
if (pos == null) return null;
|
||||
return pos.add(new IrisPosition(parentConnector.getDirection().toVector()))
|
||||
.sub(connector.getPosition())
|
||||
.sub(new IrisPosition(self.object.getCenter()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,20 +21,22 @@ package com.volmit.iris.engine.jigsaw;
|
||||
import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap;
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.loader.IrisData;
|
||||
import com.volmit.iris.engine.data.cache.Cache;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.mantle.MantleWriter;
|
||||
import com.volmit.iris.engine.framework.placer.WorldObjectPlacer;
|
||||
import com.volmit.iris.engine.object.*;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.data.IrisBlockData;
|
||||
import com.volmit.iris.util.mantle.Mantle;
|
||||
import com.volmit.iris.util.math.Position2;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import com.volmit.iris.util.matter.slices.JigsawPieceMatter;
|
||||
import com.volmit.iris.util.matter.slices.container.JigsawPieceContainer;
|
||||
import com.volmit.iris.util.matter.slices.container.JigsawStructureContainer;
|
||||
import com.volmit.iris.util.matter.slices.container.JigsawStructuresContainer;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import lombok.Data;
|
||||
import org.bukkit.Axis;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.TileState;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@Data
|
||||
public class PlannedStructure {
|
||||
@@ -49,16 +51,18 @@ public class PlannedStructure {
|
||||
private IrisPosition position;
|
||||
private IrisData data;
|
||||
private RNG rng;
|
||||
private boolean forcePlace;
|
||||
private boolean verbose;
|
||||
private boolean terminating;
|
||||
|
||||
public PlannedStructure(IrisJigsawStructure structure, IrisPosition position, RNG rng) {
|
||||
public PlannedStructure(IrisJigsawStructure structure, IrisPosition position, RNG rng, boolean forcePlace) {
|
||||
terminating = false;
|
||||
verbose = true;
|
||||
this.pieces = new KList<>();
|
||||
this.structure = structure;
|
||||
this.position = position;
|
||||
this.rng = rng;
|
||||
this.forcePlace = forcePlace;
|
||||
this.data = structure.getLoader();
|
||||
generateStartPiece();
|
||||
|
||||
@@ -75,33 +79,47 @@ public class PlannedStructure {
|
||||
}
|
||||
}
|
||||
|
||||
public void place(MantleWriter placer, Mantle e, Engine eng) {
|
||||
public boolean place(IObjectPlacer placer, Mantle e, Engine eng) {
|
||||
IrisObjectPlacement options = new IrisObjectPlacement();
|
||||
options.getRotation().setEnabled(false);
|
||||
options.setRotation(IrisObjectRotation.of(0,0,0));
|
||||
int startHeight = pieces.get(0).getPosition().getY();
|
||||
|
||||
boolean placed = false;
|
||||
for (PlannedPiece i : pieces) {
|
||||
place(i, startHeight, options, placer, e, eng);
|
||||
if (place(i, startHeight, options, placer, e, eng))
|
||||
placed = true;
|
||||
}
|
||||
if (placed) {
|
||||
Position2 chunkPos = new Position2(position.getX() >> 4, position.getZ() >> 4);
|
||||
Position2 regionPos = new Position2(chunkPos.getX() >> 5, chunkPos.getZ() >> 5);
|
||||
JigsawStructuresContainer slice = e.get(regionPos.getX(), 0, regionPos.getZ(), JigsawStructuresContainer.class);
|
||||
if (slice == null) slice = new JigsawStructuresContainer();
|
||||
slice.add(structure, chunkPos);
|
||||
e.set(regionPos.getX(), 0, regionPos.getZ(), slice);
|
||||
}
|
||||
return placed;
|
||||
}
|
||||
|
||||
public void place(PlannedPiece i, int startHeight, IrisObjectPlacement o, MantleWriter placer, Mantle e, Engine eng) {
|
||||
public boolean place(PlannedPiece i, int startHeight, IrisObjectPlacement o, IObjectPlacer placer, Mantle e, Engine eng) {
|
||||
IrisObjectPlacement options = o;
|
||||
|
||||
if (i.getPiece().getPlacementOptions() != null) {
|
||||
options = i.getPiece().getPlacementOptions();
|
||||
options.getRotation().setEnabled(false);
|
||||
options.setRotateTowardsSlope(false);
|
||||
options.setWarp(new IrisGeneratorStyle(NoiseStyle.FLAT));
|
||||
} else {
|
||||
options.setMode(i.getPiece().getPlaceMode());
|
||||
}
|
||||
if (forcePlace) {
|
||||
options.setForcePlace(true);
|
||||
}
|
||||
|
||||
IrisObject vo = i.getOgObject();
|
||||
IrisObject v = i.getObject();
|
||||
int sx = (v.getW() / 2);
|
||||
int sz = (v.getD() / 2);
|
||||
int xx = i.getPosition().getX() + sx;
|
||||
int zz = i.getPosition().getZ() + sz;
|
||||
RNG rng = new RNG(Cache.key(xx, zz));
|
||||
int offset = i.getPosition().getY() - startHeight;
|
||||
int height;
|
||||
|
||||
@@ -109,12 +127,23 @@ public class PlannedStructure {
|
||||
if (i.getStructure().getStructure().getOverrideYRange() != null) {
|
||||
height = (int) i.getStructure().getStructure().getOverrideYRange().get(rng, xx, zz, getData());
|
||||
} else {
|
||||
height = placer.getHighest(xx, zz, getData());
|
||||
height = placer.getHighest(xx, zz, getData(), options.isUnderwater());
|
||||
}
|
||||
} else {
|
||||
height = i.getStructure().getStructure().getLockY();
|
||||
}
|
||||
|
||||
PlannedPiece.ParentConnection connection = i.getParent();
|
||||
if (connection != null && connection.connector().isLockY()) {
|
||||
var pos = connection.getTargetPosition();
|
||||
if (pos != null) {
|
||||
height = pos.getY();
|
||||
offset = 0;
|
||||
} else {
|
||||
Iris.warn("Failed to get target position for " + v.getLoadKey());
|
||||
}
|
||||
}
|
||||
|
||||
height += offset + (v.getH() / 2);
|
||||
|
||||
if (options.getMode().equals(ObjectPlaceMode.PAINT)) {
|
||||
@@ -123,75 +152,20 @@ public class PlannedStructure {
|
||||
|
||||
int id = rng.i(0, Integer.MAX_VALUE);
|
||||
JigsawPieceContainer container = JigsawPieceContainer.toContainer(i.getPiece());
|
||||
vo.place(xx, height, zz, new IObjectPlacer() {
|
||||
@Override
|
||||
public int getHighest(int x, int z, IrisData data) {
|
||||
return placer.getHighest(x, z, data);
|
||||
JigsawStructureContainer structureContainer = JigsawStructureContainer.toContainer(structure);
|
||||
i.setRealPositions(xx, height, zz, placer);
|
||||
return v.place(xx, height, zz, placer, options, rng, (b, data) -> {
|
||||
e.set(b.getX(), b.getY(), b.getZ(), v.getLoadKey() + "@" + id);
|
||||
e.set(b.getX(), b.getY(), b.getZ(), container);
|
||||
e.set(b.getX(), b.getY(), b.getZ(), structureContainer);
|
||||
if (data instanceof IrisBlockData d) {
|
||||
e.set(b.getX(), b.getY(), b.getZ(), d.getCustom());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHighest(int x, int z, IrisData data, boolean ignoreFluid) {
|
||||
return placer.getHighest(x, z, data, ignoreFluid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(int x, int y, int z, BlockData d) {
|
||||
placer.setData(x, y, z, container);
|
||||
placer.set(x, y, z, d);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockData get(int x, int y, int z) {
|
||||
placer.setData(x, y, z, container);
|
||||
return placer.get(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPreventingDecay() {
|
||||
return placer.isPreventingDecay();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCarved(int x, int y, int z) {
|
||||
return placer.isCarved(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSolid(int x, int y, int z) {
|
||||
return placer.isSolid(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUnderwater(int x, int z) {
|
||||
return placer.isUnderwater(x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFluidHeight() {
|
||||
return placer.getFluidHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDebugSmartBore() {
|
||||
return placer.isDebugSmartBore();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTile(int xx, int yy, int zz, TileData<? extends TileState> tile) {
|
||||
placer.setTile(xx, yy, zz, tile);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Engine getEngine() {
|
||||
return placer.getEngine();
|
||||
}
|
||||
}, options, rng, (b, data) -> e.set(b.getX(), b.getY(), b.getZ(), v.getLoadKey() + "@" + id), null, getData());
|
||||
}, null, getData().getEngine() != null ? getData() : eng.getData()) != -1;
|
||||
}
|
||||
|
||||
public void place(World world) {
|
||||
for (PlannedPiece i : pieces) {
|
||||
Iris.sq(() -> i.place(world));
|
||||
}
|
||||
public void place(WorldObjectPlacer placer, Consumer<Boolean> consumer) {
|
||||
J.s(() -> consumer.accept(place(placer, placer.getMantle().getMantle(), placer.getEngine())));
|
||||
}
|
||||
|
||||
private void generateOutwards() {
|
||||
@@ -208,6 +182,7 @@ public class PlannedStructure {
|
||||
for (IrisJigsawPieceConnector i : piece.getAvailableConnectors().shuffleCopy(rng)) {
|
||||
if (generateConnectorOutwards(piece, i)) {
|
||||
b = true;
|
||||
piece.debugPrintConnectorPositions();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -226,9 +201,7 @@ public class PlannedStructure {
|
||||
|
||||
private boolean generateRotatedPiece(PlannedPiece piece, IrisJigsawPieceConnector pieceConnector, IrisJigsawPiece idea) {
|
||||
if (!piece.getPiece().getPlacementOptions().getRotation().isEnabled()) {
|
||||
if (generateRotatedPiece(piece, pieceConnector, idea, 0, 0, 0)) {
|
||||
return true;
|
||||
}
|
||||
return generateRotatedPiece(piece, pieceConnector, idea, 0, 0, 0);
|
||||
}
|
||||
|
||||
KList<Integer> forder1 = new KList<Integer>().qadd(0).qadd(1).qadd(2).qadd(3).shuffle(rng);
|
||||
@@ -275,7 +248,7 @@ public class PlannedStructure {
|
||||
}
|
||||
|
||||
private boolean generateRotatedPiece(PlannedPiece piece, IrisJigsawPieceConnector pieceConnector, IrisJigsawPiece idea, int x, int y, int z) {
|
||||
return generateRotatedPiece(piece, pieceConnector, idea, IrisObjectRotation.of(x, y, z));
|
||||
return generateRotatedPiece(piece, pieceConnector, idea, IrisObjectRotation.of(x * 90D, y * 90D, z * 90D));
|
||||
}
|
||||
|
||||
private boolean generatePositionedPiece(PlannedPiece piece, IrisJigsawPieceConnector pieceConnector, PlannedPiece test, IrisJigsawPieceConnector testConnector) {
|
||||
@@ -299,8 +272,7 @@ public class PlannedStructure {
|
||||
return false;
|
||||
}
|
||||
|
||||
piece.connect(pieceConnector);
|
||||
test.connect(testConnector);
|
||||
piece.connect(pieceConnector, test, testConnector);
|
||||
pieces.add(test);
|
||||
|
||||
return true;
|
||||
@@ -309,7 +281,8 @@ public class PlannedStructure {
|
||||
private KList<IrisJigsawPiece> getShuffledPiecesFor(IrisJigsawPieceConnector c) {
|
||||
KList<IrisJigsawPiece> p = new KList<>();
|
||||
|
||||
for (String i : c.getPools().shuffleCopy(rng)) {
|
||||
KList<String> pools = terminating && getStructure().getTerminatePool() != null ? new KList<>(getStructure().getTerminatePool()) : c.getPools().shuffleCopy(rng);
|
||||
for (String i : pools) {
|
||||
for (String j : getData().getJigsawPoolLoader().load(i).getPieces().shuffleCopy(rng)) {
|
||||
IrisJigsawPiece pi = getData().getJigsawPieceLoader().load(j);
|
||||
|
||||
@@ -335,7 +308,9 @@ public class PlannedStructure {
|
||||
}
|
||||
|
||||
public KList<PlannedPiece> getPiecesWithAvailableConnectors() {
|
||||
return pieces.copy().removeWhere(PlannedPiece::isFull);
|
||||
KList<PlannedPiece> available = pieces.copy().removeWhere(PlannedPiece::isFull);
|
||||
if (!terminating) available.removeIf(PlannedPiece::isDead);
|
||||
return available;
|
||||
}
|
||||
|
||||
public int getVolume() {
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.volmit.iris.core.loader.IrisData;
|
||||
import com.volmit.iris.engine.IrisComplex;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.framework.EngineTarget;
|
||||
import com.volmit.iris.engine.framework.SeedManager;
|
||||
import com.volmit.iris.engine.mantle.components.MantleJigsawComponent;
|
||||
import com.volmit.iris.engine.mantle.components.MantleObjectComponent;
|
||||
import com.volmit.iris.engine.object.IObjectPlacer;
|
||||
@@ -106,7 +107,7 @@ public interface EngineMantle extends IObjectPlacer {
|
||||
}
|
||||
|
||||
@Override
|
||||
default void setTile(int x, int y, int z, TileData<? extends TileState> d) {
|
||||
default void setTile(int x, int y, int z, TileData d) {
|
||||
getMantle().set(x, y, z, new TileWrapper(d));
|
||||
}
|
||||
|
||||
@@ -143,8 +144,8 @@ public interface EngineMantle extends IObjectPlacer {
|
||||
return getEngine().getDimension().isDebugSmartBore();
|
||||
}
|
||||
|
||||
default void trim(long dur) {
|
||||
getMantle().trim(dur);
|
||||
default void trim(long dur, int limit) {
|
||||
getMantle().trim(dur, limit);
|
||||
}
|
||||
|
||||
default IrisData getData() {
|
||||
@@ -175,8 +176,11 @@ public interface EngineMantle extends IObjectPlacer {
|
||||
|
||||
}
|
||||
|
||||
default void trim() {
|
||||
getMantle().trim(TimeUnit.SECONDS.toMillis(IrisSettings.get().getPerformance().getMantleKeepAlive()));
|
||||
default void trim(int limit) {
|
||||
getMantle().trim(TimeUnit.SECONDS.toMillis(IrisSettings.get().getPerformance().getMantleKeepAlive()), limit);
|
||||
}
|
||||
default int unloadTectonicPlate(int tectonicLimit){
|
||||
return getMantle().unloadTectonicPlate(tectonicLimit);
|
||||
}
|
||||
|
||||
default MultiBurst burst() {
|
||||
@@ -257,6 +261,9 @@ public interface EngineMantle extends IObjectPlacer {
|
||||
default int getLoadedRegionCount() {
|
||||
return getMantle().getLoadedRegionCount();
|
||||
}
|
||||
default long getLastUseMapMemoryUsage(){
|
||||
return getMantle().LastUseMapMemoryUsage();
|
||||
}
|
||||
|
||||
MantleJigsawComponent getJigsawComponent();
|
||||
|
||||
@@ -288,4 +295,14 @@ public interface EngineMantle extends IObjectPlacer {
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
default long getToUnload(){
|
||||
return getMantle().getToUnload().size();
|
||||
}
|
||||
default long getNotQueuedLoadedRegions(){
|
||||
return getMantle().getLoadedRegions().size() - getMantle().getToUnload().size();
|
||||
}
|
||||
default double getTectonicDuration(){
|
||||
return getMantle().getAdjustedIdleDuration().get();
|
||||
}
|
||||
}
|
||||
@@ -20,8 +20,12 @@ package com.volmit.iris.engine.mantle;
|
||||
|
||||
import com.volmit.iris.util.mantle.MantleFlag;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(exclude = "engineMantle")
|
||||
@ToString(exclude = "engineMantle")
|
||||
public abstract class IrisMantleComponent implements MantleComponent {
|
||||
private final EngineMantle engineMantle;
|
||||
private final MantleFlag flag;
|
||||
|
||||
@@ -206,7 +206,7 @@ public class MantleWriter implements IObjectPlacer {
|
||||
}
|
||||
|
||||
@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) {
|
||||
getEngineMantle().setTile(xx, yy, zz, tile);
|
||||
}
|
||||
|
||||
|
||||
@@ -23,13 +23,18 @@ import com.volmit.iris.engine.mantle.EngineMantle;
|
||||
import com.volmit.iris.engine.mantle.IrisMantleComponent;
|
||||
import com.volmit.iris.engine.mantle.MantleWriter;
|
||||
import com.volmit.iris.engine.object.*;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.collection.KSet;
|
||||
import com.volmit.iris.util.context.ChunkContext;
|
||||
import com.volmit.iris.util.documentation.BlockCoordinates;
|
||||
import com.volmit.iris.util.documentation.ChunkCoordinates;
|
||||
import com.volmit.iris.util.mantle.MantleFlag;
|
||||
import com.volmit.iris.util.math.Position2;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import com.volmit.iris.util.matter.slices.container.JigsawStructuresContainer;
|
||||
import com.volmit.iris.util.noise.CNG;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -38,22 +43,21 @@ public class MantleJigsawComponent extends IrisMantleComponent {
|
||||
|
||||
public MantleJigsawComponent(EngineMantle engineMantle) {
|
||||
super(engineMantle, MantleFlag.JIGSAW);
|
||||
cng = NoiseStyle.STATIC.create(new RNG(engineMantle.getEngine().getSeedManager().getJigsaw()));
|
||||
cng = NoiseStyle.STATIC.create(new RNG(jigsaw()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateLayer(MantleWriter writer, int x, int z, ChunkContext context) {
|
||||
RNG rng = new RNG(cng.fit(-Integer.MAX_VALUE, Integer.MAX_VALUE, x, z));
|
||||
int xxx = 8 + (x << 4);
|
||||
int zzz = 8 + (z << 4);
|
||||
IrisRegion region = getComplex().getRegionStream().get(xxx, zzz);
|
||||
IrisBiome biome = getComplex().getTrueBiomeStream().get(xxx, zzz);
|
||||
generateJigsaw(writer, rng, x, z, biome, region);
|
||||
generateJigsaw(writer, x, z, biome, region);
|
||||
}
|
||||
|
||||
@ChunkCoordinates
|
||||
private void generateJigsaw(MantleWriter writer, RNG rng, int x, int z, IrisBiome biome, IrisRegion region) {
|
||||
boolean placed = false;
|
||||
private void generateJigsaw(MantleWriter writer, int x, int z, IrisBiome biome, IrisRegion region) {
|
||||
long seed = cng.fit(Integer.MIN_VALUE, Integer.MAX_VALUE, x, z);
|
||||
|
||||
if (getDimension().getStronghold() != null) {
|
||||
List<Position2> poss = getDimension().getStrongholds(seed());
|
||||
@@ -62,49 +66,71 @@ public class MantleJigsawComponent extends IrisMantleComponent {
|
||||
for (Position2 pos : poss) {
|
||||
if (x == pos.getX() >> 4 && z == pos.getZ() >> 4) {
|
||||
IrisJigsawStructure structure = getData().getJigsawStructureLoader().load(getDimension().getStronghold());
|
||||
place(writer, pos.toIris(), structure, rng);
|
||||
placed = true;
|
||||
place(writer, pos.toIris(), structure, new RNG(seed), true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!placed) {
|
||||
for (IrisJigsawStructurePlacement i : biome.getJigsawStructures()) {
|
||||
if (rng.nextInt(i.getRarity()) == 0) {
|
||||
IrisPosition position = new IrisPosition((x << 4) + rng.nextInt(15), 0, (z << 4) + rng.nextInt(15));
|
||||
IrisJigsawStructure structure = getData().getJigsawStructureLoader().load(i.getStructure());
|
||||
place(writer, position, structure, rng);
|
||||
placed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
KSet<Position2> cachedRegions = new KSet<>();
|
||||
KMap<String, KSet<Position2>> cache = new KMap<>();
|
||||
KMap<Position2, Double> distanceCache = new KMap<>();
|
||||
boolean placed = placeStructures(writer, seed, x, z, biome.getJigsawStructures(), cachedRegions, cache, distanceCache);
|
||||
if (!placed)
|
||||
placed = placeStructures(writer, seed, x, z, region.getJigsawStructures(), cachedRegions, cache, distanceCache);
|
||||
if (!placed)
|
||||
placeStructures(writer, seed, x, z, getDimension().getJigsawStructures(), cachedRegions, cache, distanceCache);
|
||||
}
|
||||
|
||||
if (!placed) {
|
||||
for (IrisJigsawStructurePlacement i : region.getJigsawStructures()) {
|
||||
if (rng.nextInt(i.getRarity()) == 0) {
|
||||
IrisPosition position = new IrisPosition((x << 4) + rng.nextInt(15), 0, (z << 4) + rng.nextInt(15));
|
||||
IrisJigsawStructure structure = getData().getJigsawStructureLoader().load(i.getStructure());
|
||||
place(writer, position, structure, rng);
|
||||
placed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ChunkCoordinates
|
||||
private boolean placeStructures(MantleWriter writer, long seed, int x, int z, KList<IrisJigsawStructurePlacement> structures,
|
||||
KSet<Position2> cachedRegions, KMap<String, KSet<Position2>> cache, KMap<Position2, Double> distanceCache) {
|
||||
IrisJigsawStructurePlacement i = pick(structures, seed, x, z);
|
||||
if (i == null || checkMinDistances(i.collectMinDistances(), x, z, cachedRegions, cache, distanceCache))
|
||||
return false;
|
||||
RNG rng = new RNG(seed);
|
||||
IrisPosition position = new IrisPosition((x << 4) + rng.nextInt(15), 0, (z << 4) + rng.nextInt(15));
|
||||
IrisJigsawStructure structure = getData().getJigsawStructureLoader().load(i.getStructure());
|
||||
return place(writer, position, structure, rng, false);
|
||||
}
|
||||
|
||||
if (!placed) {
|
||||
for (IrisJigsawStructurePlacement i : getDimension().getJigsawStructures()) {
|
||||
if (rng.nextInt(i.getRarity()) == 0) {
|
||||
IrisPosition position = new IrisPosition((x << 4) + rng.nextInt(15), 0, (z << 4) + rng.nextInt(15));
|
||||
IrisJigsawStructure structure = getData().getJigsawStructureLoader().load(i.getStructure());
|
||||
place(writer, position, structure, rng);
|
||||
@ChunkCoordinates
|
||||
private boolean checkMinDistances(KMap<String, Integer> minDistances, int x, int z, KSet<Position2> cachedRegions, KMap<String, KSet<Position2>> cache, KMap<Position2, Double> distanceCache) {
|
||||
int range = 0;
|
||||
for (int d : minDistances.values())
|
||||
range = Math.max(range, d);
|
||||
|
||||
for (int xx = -range; xx <= range; xx++) {
|
||||
for (int zz = -range; zz <= range; zz++) {
|
||||
Position2 pos = new Position2((xx + x) >> 5, (zz + z) >> 5);
|
||||
if (cachedRegions.contains(pos)) continue;
|
||||
cachedRegions.add(pos);
|
||||
JigsawStructuresContainer container = getMantle().get(pos.getX(), 0, pos.getZ(), JigsawStructuresContainer.class);
|
||||
if (container == null) continue;
|
||||
for (String key : container.getStructures()) {
|
||||
cache.computeIfAbsent(key, k -> new KSet<>()).addAll(container.getPositions(key));
|
||||
}
|
||||
}
|
||||
}
|
||||
Position2 pos = new Position2(x, z);
|
||||
for (String structure : minDistances.keySet()) {
|
||||
if (!cache.containsKey(structure)) continue;
|
||||
double minDist = minDistances.get(structure);
|
||||
minDist = minDist * minDist;
|
||||
for (Position2 sPos : cache.get(structure)) {
|
||||
double dist = distanceCache.computeIfAbsent(sPos, position2 -> position2.distance(pos));
|
||||
if (minDist > dist) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@ChunkCoordinates
|
||||
public IrisJigsawStructure guess(int x, int z) {
|
||||
RNG rng = new RNG(cng.fit(-Integer.MAX_VALUE, Integer.MAX_VALUE, x, z));
|
||||
// todo The guess doesnt bring into account that the placer may return -1
|
||||
// todo doesnt bring skipped placements into account
|
||||
long seed = cng.fit(Integer.MIN_VALUE, Integer.MAX_VALUE, x, z);
|
||||
IrisBiome biome = getEngineMantle().getEngine().getSurfaceBiome((x << 4) + 8, (z << 4) + 8);
|
||||
IrisRegion region = getEngineMantle().getEngine().getRegion((x << 4) + 8, (z << 4) + 8);
|
||||
|
||||
@@ -120,29 +146,26 @@ public class MantleJigsawComponent extends IrisMantleComponent {
|
||||
}
|
||||
}
|
||||
|
||||
for (IrisJigsawStructurePlacement i : biome.getJigsawStructures()) {
|
||||
if (rng.nextInt(i.getRarity()) == 0) {
|
||||
return getData().getJigsawStructureLoader().load(i.getStructure());
|
||||
}
|
||||
}
|
||||
IrisJigsawStructurePlacement i = pick(biome.getJigsawStructures(), seed, x, z);
|
||||
if (i == null) i = pick(region.getJigsawStructures(), seed, x, z);
|
||||
if (i == null) i = pick(getDimension().getJigsawStructures(), seed, x, z);
|
||||
return i != null ? getData().getJigsawStructureLoader().load(i.getStructure()) : null;
|
||||
}
|
||||
|
||||
for (IrisJigsawStructurePlacement i : region.getJigsawStructures()) {
|
||||
if (rng.nextInt(i.getRarity()) == 0) {
|
||||
return getData().getJigsawStructureLoader().load(i.getStructure());
|
||||
}
|
||||
}
|
||||
|
||||
for (IrisJigsawStructurePlacement i : getDimension().getJigsawStructures()) {
|
||||
if (rng.nextInt(i.getRarity()) == 0) {
|
||||
return getData().getJigsawStructureLoader().load(i.getStructure());
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
@Nullable
|
||||
@ChunkCoordinates
|
||||
private IrisJigsawStructurePlacement pick(List<IrisJigsawStructurePlacement> structures, long seed, int x, int z) {
|
||||
return IRare.pick(structures.stream()
|
||||
.filter(p -> p.shouldPlace(getDimension().getJigsawStructureDivisor(), jigsaw(), x, z))
|
||||
.toList(), new RNG(seed).nextDouble());
|
||||
}
|
||||
|
||||
@BlockCoordinates
|
||||
private void place(MantleWriter writer, IrisPosition position, IrisJigsawStructure structure, RNG rng) {
|
||||
new PlannedStructure(structure, position, rng).place(writer, getMantle(), writer.getEngine());
|
||||
private boolean place(MantleWriter writer, IrisPosition position, IrisJigsawStructure structure, RNG rng, boolean forcePlace) {
|
||||
return new PlannedStructure(structure, position, rng, forcePlace).place(writer, getMantle(), writer.getEngine());
|
||||
}
|
||||
|
||||
private long jigsaw() {
|
||||
return getEngineMantle().getEngine().getSeedManager().getJigsaw();
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user