mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-05-20 00:20:24 +00:00
Compare commits
514 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6a1ee51379 | |||
| 637c4a2c91 | |||
| e1a7e772cf | |||
| 3c6411c322 | |||
| 628761affa | |||
| 37d4e69399 | |||
| fa7b0f68ff | |||
| 487d0ac237 | |||
| e79e3fbe45 | |||
| 23a0ab23aa | |||
| c78ffab948 | |||
| d58f497b71 | |||
| 3284ab84c5 | |||
| 5cf0ac9315 | |||
| 4e4e820826 | |||
| cb6e4570f4 | |||
| fb59c7370d | |||
| c16e65f0a8 | |||
| d9681edf62 | |||
| 520c156d5f | |||
| 5c26ec2521 | |||
| d192e2b6d1 | |||
| 5b60b655ed | |||
| 97c7ac0528 | |||
| 090ff730a7 | |||
| c1f797e7c9 | |||
| 4a1a6b80a6 | |||
| e189b2389c | |||
| 3265447536 | |||
| 8c7c9f89e1 | |||
| d7a991b9b3 | |||
| abf6c93f2e | |||
| 1b76a66760 | |||
| c83ac67b47 | |||
| 1dca502a90 | |||
| cacef8c8fc | |||
| 623fd45ef4 | |||
| 007b4b0b53 | |||
| b6bacee095 | |||
| d5251350a1 | |||
| 1f9c72d093 | |||
| a1495a10e5 | |||
| 11ae48bea1 | |||
| b0f4b29a2d | |||
| c38bb1cd01 | |||
| 7faa727bd2 | |||
| 9e40259ca2 | |||
| 94a7692735 | |||
| 8b803a87f0 | |||
| 3ae6e92eaf | |||
| 0f3c52a5aa | |||
| 747be7aa09 | |||
| d651f204f8 | |||
| 2bd3ac7a9b | |||
| 5e437b34e3 | |||
| a5ef89a128 | |||
| 558b8e4eca | |||
| 0a001b8a63 | |||
| 6c6c9654c1 | |||
| e21fdf46e0 | |||
| a2ff5f58ed | |||
| b0eedee519 | |||
| e101155a4c | |||
| 3c9bcc9bb0 | |||
| 6763844030 | |||
| 08fa436885 | |||
| df8fa79209 | |||
| 8041db4f40 | |||
| 18e57e4097 | |||
| cc584ba377 | |||
| 0c92c20c65 | |||
| ec8af56f0d | |||
| 79341bf562 | |||
| 3f24d5c8e1 | |||
| 66a1739666 | |||
| 29007fdbfa | |||
| be3e8ebd51 | |||
| 38ad345f85 | |||
| 414f46a08d | |||
| 9144606688 | |||
| effb0f5b91 | |||
| bb7bbb6379 | |||
| dafca8e9db | |||
| 41b7aec084 | |||
| dfe1cce6de | |||
| fc793592f7 | |||
| c3ac41f894 | |||
| d0688782b1 | |||
| 25b41fe62c | |||
| b468478fcb | |||
| b6dc934198 | |||
| f58078e8a0 | |||
| b6457e47e6 | |||
| d275466e1e | |||
| f9cb107728 | |||
| 68ad206252 | |||
| 288bead792 | |||
| de670ddfd5 | |||
| 79d6f34879 | |||
| ceb6c15c97 | |||
| 7cf43ad7ab | |||
| ab3397a373 | |||
| 8e9f78e982 | |||
| 61bbfee640 | |||
| cf4796bd12 | |||
| bd89d8a308 | |||
| df2186d70f | |||
| f9638e830f | |||
| cd55a7fed4 | |||
| fc890a5ba1 | |||
| 2ea54b7f2f | |||
| e90e3901f5 | |||
| 36d58f29ab | |||
| 864c7ae27c | |||
| 6d104a2d1c | |||
| 89e754245d | |||
| 4c68d99c6f | |||
| f8f0a65f0a | |||
| 6ff74639b5 | |||
| af80f882da | |||
| 84ce7372c3 | |||
| e31d39c5f7 | |||
| 2296c1368b | |||
| 21d7d96dbc | |||
| 956e511fe0 | |||
| e427887f8c | |||
| 88ea43fbbe | |||
| 29526a80a9 | |||
| 48f901fc8c | |||
| 6c3f3dc889 | |||
| 743410d3ee | |||
| acccbb028f | |||
| 8b31fdc780 | |||
| 55017b9ac2 | |||
| 0288d35c85 | |||
| 8b3577dd0b | |||
| ced77ec70d | |||
| e1e90f5c8a | |||
| dc3487583d | |||
| e1d73ebcd5 | |||
| d7cf3b9500 | |||
| 8ce4e3c6b2 | |||
| 76f7d46b22 | |||
| cfc52ed909 | |||
| cee94d40e1 | |||
| cad7166cbe | |||
| c05fdbd0ec | |||
| c9b26ebaff | |||
| bee1973390 | |||
| 57efcab0b5 | |||
| b1ab2b84f8 | |||
| 02601e5ee4 | |||
| 070479acf3 | |||
| 6b2ba74237 | |||
| 619de29710 | |||
| 12556fa98f | |||
| bef4c0497f | |||
| 9193497d36 | |||
| ca6affbde9 | |||
| 81c40ce228 | |||
| 6ba1d571f2 | |||
| b0663f9b6c | |||
| 3ced6f3e9e | |||
| 3146d61efe | |||
| a967b6af85 | |||
| db3bc74364 | |||
| eb19d9a846 | |||
| 96dd299de7 | |||
| aee0806aa8 | |||
| e39f13bbb4 | |||
| 52ec80d384 | |||
| d9f8909bdc | |||
| 65aa9dc343 | |||
| 9bf7fdf174 | |||
| dafb59e5a8 | |||
| 79f86ca87d | |||
| 1749fcf6b5 | |||
| e1a0481cdf | |||
| 4576b95814 | |||
| e113fa6a61 | |||
| 07228afbff | |||
| afdffc2453 | |||
| 6348442962 | |||
| fd10c005b0 | |||
| 44500d6af9 | |||
| 6ddb0b5304 | |||
| 8ce0976f88 | |||
| 8345a58f2b | |||
| f92234297e | |||
| 6a5bcd5990 | |||
| 1fe6d9a636 | |||
| 97f6ab66c3 | |||
| b78c182d94 | |||
| 09a0f83013 | |||
| f68d7420e3 | |||
| 55c0fa5f32 | |||
| 8b5d1d0298 | |||
| b70e94dc65 | |||
| 49a6552168 | |||
| 0dd6892b28 | |||
| fec587edad | |||
| 712937d661 | |||
| ace434e7b0 | |||
| 1e5aa6e8b0 | |||
| 441b27f8f4 | |||
| 3f3bf70212 | |||
| a12eddbedf | |||
| 12abc1709e | |||
| 9e6035e7b4 | |||
| 20b41d65d3 | |||
| 1593bb2088 | |||
| d4f9a20379 | |||
| 6e247597a4 | |||
| 8a8be4545c | |||
| 05f4955989 | |||
| 93469fb3b4 | |||
| a70258d69f | |||
| c653d852e4 | |||
| 40163d25b8 | |||
| 5b4265783e | |||
| 720417b6c8 | |||
| bb78f412e0 | |||
| a919b91efb | |||
| a3dcf031c9 | |||
| 56eb4b6b84 | |||
| 393cb362db | |||
| 64e422036c | |||
| 468e7ef018 | |||
| e3e4ecbc5c | |||
| 545ffc0e9d | |||
| 8125c8d5f4 | |||
| 304b01d0cf | |||
| a5f687fd76 | |||
| fc1761a55b | |||
| e7c9cad7f6 | |||
| 979af82122 | |||
| 71a62b9c73 | |||
| bb020cab25 | |||
| 1ad35c1310 | |||
| 6470b2f4a9 | |||
| c1d5ba55cd | |||
| 100e450514 | |||
| 0f1d1d9860 | |||
| 178a462a4e | |||
| 8f4ae613f0 | |||
| 9e6963b6ce | |||
| cb9a73c60e | |||
| 0e666a4c35 | |||
| c80138a354 | |||
| 79a4ebcf65 | |||
| a7118aa785 | |||
| 2555cd23a0 | |||
| 484fbeca7b | |||
| 9a45e0df10 | |||
| 9175296fc6 | |||
| 5a4a86aeba | |||
| 768fa7beb5 | |||
| 6645eb9806 | |||
| d7a283c99f | |||
| 8f019cd794 | |||
| c1d9cc62cb | |||
| 010a1e9e91 | |||
| 856c926cde | |||
| 72ed312654 | |||
| c7fe4723f7 | |||
| bfbea83a4a | |||
| 55c58fe896 | |||
| 72949e0950 | |||
| 61c0ddb15b | |||
| 9ac4024e4e | |||
| 7fb2a51a33 | |||
| 5b7c0b2bc3 | |||
| fc15175ff9 | |||
| 1eec3a09c1 | |||
| 60d349dd8b | |||
| 0c8d144ffb | |||
| b898f73a05 | |||
| c2b9b0ba0e | |||
| 206a4e9057 | |||
| 83a0a7dd54 | |||
| 63b8a935ae | |||
| 16affd11cc | |||
| 33b0dec9da | |||
| 121a463788 | |||
| 3625e70948 | |||
| 3d90207172 | |||
| ca7dc19c81 | |||
| d0f16dbbc4 | |||
| fd91c223b7 | |||
| 93690b766c | |||
| cc4af9950b | |||
| a6281483dd | |||
| f587816b30 | |||
| eea3c3ab0b | |||
| ba68ab9e06 | |||
| eb94d97ea4 | |||
| 04ad02719c | |||
| f68f25b92f | |||
| 767cca36c8 | |||
| b30172fe89 | |||
| b2934b0cc2 | |||
| 50686795d0 | |||
| 5561a4dc2f | |||
| 15b8780e17 | |||
| 15c4d312cb | |||
| ccbea89253 | |||
| 7b1e666b3b | |||
| 8af212fca8 | |||
| 352ee7a622 | |||
| f26d0fac0b | |||
| 9612fef2a4 | |||
| a691d49abc | |||
| 289eca35ec | |||
| e9ca30257c | |||
| 6b21997baa | |||
| 6d3dbf84ef | |||
| eb45339c81 | |||
| 65e3fdd26c | |||
| 34cad85942 | |||
| e407679d2b | |||
| 8a08a3e148 | |||
| a01d27d273 | |||
| 43f642ae8b | |||
| 93c1265de9 | |||
| d08600fbaa | |||
| fb9f8d28f4 | |||
| cd3e9f772d | |||
| 7a95441799 | |||
| 9345828c97 | |||
| 58d88dd079 | |||
| 6cbc2374b3 | |||
| 12bd11386d | |||
| 0497045388 | |||
| d3f1640855 | |||
| 960e2fcc61 | |||
| 6a012cf400 | |||
| d658ec2099 | |||
| c9a07bd9d7 | |||
| c0136585e6 | |||
| dc4cfc49ad | |||
| 9fc72868d7 | |||
| 7d4c9d6c1e | |||
| e68b1a52ee | |||
| 955e8622b5 | |||
| 82640de06b | |||
| c93cb19563 | |||
| ccb7855d7d | |||
| bad547356c | |||
| 1740bb0021 | |||
| 20f05bf317 | |||
| 669ede5482 | |||
| ab658f58f9 | |||
| 1b3916749a | |||
| e29ec657d3 | |||
| 04f3a226a1 | |||
| 099d1cc362 | |||
| c11e9bf704 | |||
| ffa0b984a0 | |||
| f0f9261ed3 | |||
| ba433bc244 | |||
| 27f8ad982a | |||
| 9b89ae7846 | |||
| c11b5342e3 | |||
| b9c88f5b12 | |||
| 02c7ab71d4 | |||
| 8ec1ac9875 | |||
| e03027a386 | |||
| 387cf566c9 | |||
| dff7665934 | |||
| 9421d788f3 | |||
| d960574b24 | |||
| e8671cbbf0 | |||
| cbf8039eea | |||
| d7415e3711 | |||
| 26e71ee6b5 | |||
| f8c42b3e48 | |||
| 886bed9634 | |||
| 7b7023fc99 | |||
| 701bfe4a54 | |||
| 290d7a93ab | |||
| 729bcc7ba0 | |||
| e46b68e2f3 | |||
| cdf73c4629 | |||
| 2f0dd2d172 | |||
| 7e5704bf80 | |||
| ef96fb9a0e | |||
| f2370ad814 | |||
| 0783620104 | |||
| 2193b02c0a | |||
| aef05bad20 | |||
| e002ab6378 | |||
| a2c2b4a2d4 | |||
| 3ae896457b | |||
| 683a90ed09 | |||
| 5685e25234 | |||
| 6edf083e7b | |||
| 995d1495eb | |||
| d5f74631cd | |||
| dd5b9b2e81 | |||
| ca78200c1c | |||
| d73c2a65ae | |||
| 0ee2cb8e3c | |||
| 5ba429ec73 | |||
| 709825d073 | |||
| 3fe73af5e8 | |||
| ccc0b0dd7d | |||
| 1114ede267 | |||
| 5546f12499 | |||
| 4f38acb592 | |||
| 39f59e023c | |||
| 5ed5322fce | |||
| 33b926d547 | |||
| af8778c6cd | |||
| bb4ad08cc5 | |||
| ee4eb7b3f0 | |||
| 5bc024a6ee | |||
| 0546caeb05 | |||
| a75348d3ee | |||
| 3f3f947f43 | |||
| 5127b7c959 | |||
| a28df78792 | |||
| 4f888f16bc | |||
| 55ed9d7132 | |||
| 779a56c3a1 | |||
| f6440bde07 | |||
| 930dc2fd1c | |||
| 1e96fd529b | |||
| 167c865bb2 | |||
| 4e6b6c11a3 | |||
| bfdb71ca91 | |||
| f590f9824e | |||
| b3a087702d | |||
| 1a786fb418 | |||
| 650d38e212 | |||
| 130cb7ad93 | |||
| 85e8ffeaa3 | |||
| db40f608fa | |||
| a7b471682a | |||
| 4595fea7d7 | |||
| 4580f8d9a4 | |||
| 37f76fa133 | |||
| 5507c35547 | |||
| 350328f99c | |||
| 91ec6b773d | |||
| c0fdf23133 | |||
| 28523a9593 | |||
| 07e0b52ea3 | |||
| 008e758da8 | |||
| 7ce219a6a8 | |||
| 1809d4a53f | |||
| 54ae026c2b | |||
| 57c647fa0e | |||
| 9745f23fb2 | |||
| 7d2062f298 | |||
| 306a1948cf | |||
| ac4c00d3f2 | |||
| db43bc300e | |||
| 6494cded62 | |||
| b5c1e7e2da | |||
| 83e311870f | |||
| 8fc6e3b335 | |||
| 18a69e97b3 | |||
| 80d8449f02 | |||
| d830aa1d1a | |||
| d473126d4c | |||
| 17f8fe69fb | |||
| 7263d102c7 | |||
| 815b2235a2 | |||
| f61247f8bb | |||
| 205d9d528e | |||
| 1044f901bd | |||
| de261a38fd | |||
| 81776e60fb | |||
| 0c179eae86 | |||
| c30de98449 | |||
| 47990cde46 | |||
| b098c210ce | |||
| 6edd8bf119 | |||
| de0e124ebb | |||
| 5fc012a557 | |||
| 32afcc3478 | |||
| a27f37945d | |||
| 0adfe6911f | |||
| 8bb1964b30 | |||
| cc95e1ae63 | |||
| 9843f18c96 | |||
| 18ea61fcc0 | |||
| 5b3fdb6e62 | |||
| c5220c8d06 | |||
| 74e87a7fae | |||
| c809f50c3b | |||
| e7e46f78c7 | |||
| 2b449a1f3d | |||
| f257f2c551 | |||
| 7f91d73d27 | |||
| 15a90edb03 | |||
| b2f1e16d9a | |||
| f544455708 | |||
| 5118997188 | |||
| b6ae649cd1 | |||
| a6d0d85b84 | |||
| c71c2494af | |||
| 4a3a7bc98d | |||
| 4e4f7f693d | |||
| 7a729c39a6 | |||
| 48b757f693 | |||
| b449938730 | |||
| ba55ff6a4b | |||
| 2b4bc621ac | |||
| acac2d0fc5 | |||
| 6ff5975918 | |||
| 8912cfe37b | |||
| 9e02c318a1 | |||
| 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
|
3. Add `export JAVA_HOME=$(/usr/libexec/java_home)` as a new line
|
||||||
4. Use `CTRL + X`, then Press `Y`, Then `ENTER`
|
4. Use `CTRL + X`, then Press `Y`, Then `ENTER`
|
||||||
5. Quit & Reopen Terminal and verify with `echo $JAVA_HOME`. It should print a directory
|
5. Quit & Reopen Terminal and verify with `echo $JAVA_HOME`. It should print a directory
|
||||||
3. If this is your first time building Iris for MC 1.18+ run `gradlew setup` inside the root Iris project folder.
|
3. Once the project has setup, run `gradlew iris`
|
||||||
Otherwise, skip this step. Grab a coffee, this may take up to 5 minutes depending on your cpu & internet connection.
|
4. The Iris jar will be placed in `Iris/build/Iris-XXX-XXX.jar` Enjoy! Consider supporting us by buying it on spigot!
|
||||||
4. Once the project has setup, run `gradlew iris`
|
|
||||||
5. The Iris jar will be placed in `Iris/build/Iris-XXX-XXX.jar` Enjoy! Consider supporting us by buying it on spigot!
|
|
||||||
|
|
||||||
### IDE Builds (for development)
|
### IDE Builds (for development)
|
||||||
|
|
||||||
* Run `gradlew setup` any time you get dependency issues with craftbukkit
|
|
||||||
* Configure ITJ Gradle to use JDK 17 (in settings, search for gradle)
|
* Configure ITJ Gradle to use JDK 17 (in settings, search for gradle)
|
||||||
* Add a build line in the build.gradle for your own build task to directly compile Iris into your plugins folder if you
|
* Add a build line in the build.gradle for your own build task to directly compile Iris into your plugins folder if you
|
||||||
prefer.
|
prefer.
|
||||||
@@ -69,7 +66,6 @@ IrisAccess access=IrisToolbelt.createWorld() // If you like builders...
|
|||||||
.name("myWorld") // The world name
|
.name("myWorld") // The world name
|
||||||
.dimension("terrifyinghands")
|
.dimension("terrifyinghands")
|
||||||
.seed(69133742) // The world seed
|
.seed(69133742) // The world seed
|
||||||
.headless(true) // Headless make gen go fast
|
|
||||||
.pregen(PregenTask // Define a pregen job to run
|
.pregen(PregenTask // Define a pregen job to run
|
||||||
.builder()
|
.builder()
|
||||||
.center(new Position2(0,0)) // REGION coords (1 region = 32x32 chunks)
|
.center(new Position2(0,0)) // REGION coords (1 region = 32x32 chunks)
|
||||||
|
|||||||
+97
-185
@@ -16,15 +16,23 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
buildscript() {
|
||||||
|
repositories {
|
||||||
|
maven { url 'https://jitpack.io'}
|
||||||
|
}
|
||||||
|
dependencies {
|
||||||
|
classpath 'com.github.VolmitSoftware:NMSTools:1.0.1'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id 'java'
|
id 'java'
|
||||||
id 'java-library'
|
id 'java-library'
|
||||||
id "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"
|
id "de.undercouch.download" version "5.0.1"
|
||||||
}
|
}
|
||||||
|
|
||||||
version '3.0.0-1.19.2-1.20.2'
|
version '3.5.2-1.19.2-1.21.3'
|
||||||
def specialSourceVersion = '1.11.0' //[NMS]
|
|
||||||
|
|
||||||
// ADD YOURSELF AS A NEW LINE IF YOU WANT YOUR OWN BUILD TASK GENERATED
|
// ADD YOURSELF AS A NEW LINE IF YOU WANT YOUR OWN BUILD TASK GENERATED
|
||||||
// ======================== WINDOWS =============================
|
// ======================== WINDOWS =============================
|
||||||
@@ -35,235 +43,117 @@ registerCustomOutputTask('Coco', 'D://mcsm/plugins')
|
|||||||
registerCustomOutputTask('Strange', 'D://Servers/1.17 Test Server/plugins')
|
registerCustomOutputTask('Strange', 'D://Servers/1.17 Test Server/plugins')
|
||||||
registerCustomOutputTask('Vatuu', 'D://Minecraft/Servers/1.19.4/plugins')
|
registerCustomOutputTask('Vatuu', 'D://Minecraft/Servers/1.19.4/plugins')
|
||||||
registerCustomOutputTask('CrazyDev22', 'C://Users/Julian/Desktop/server/plugins')
|
registerCustomOutputTask('CrazyDev22', 'C://Users/Julian/Desktop/server/plugins')
|
||||||
registerCustomOutputTask('Pixel', 'C://Users/repix/Iris Dimension Engine/1.20.1 - Iris Coding/plugins')
|
registerCustomOutputTask('PixelFury', 'C://Users/repix/workplace/Iris/1.21.3 - Development-Public-v3/plugins')
|
||||||
|
registerCustomOutputTask('PixelFuryDev', 'C://Users/repix/workplace/Iris/1.21 - Development-v3/plugins')
|
||||||
|
registerCustomOutputTask('PixelFuryEngine', 'C://Users/repix/workplace/Iris/1.21.3 - Development-Engine-v3/plugins')
|
||||||
// ========================== UNIX ==============================
|
// ========================== UNIX ==============================
|
||||||
registerCustomOutputTaskUnix('CyberpwnLT', '/Users/danielmills/development/server/plugins')
|
registerCustomOutputTaskUnix('CyberpwnLT', '/Users/danielmills/development/server/plugins')
|
||||||
registerCustomOutputTaskUnix('PsychoLT', '/Users/brianfopiano/Desktop/REMOTES/RemoteMinecraft/plugins')
|
registerCustomOutputTaskUnix('PsychoLT', '/Users/brianfopiano/Developer/RemoteGit/Server/plugins')
|
||||||
|
registerCustomOutputTaskUnix('PixelMac', '/Users/test/Desktop/mcserver/plugins')
|
||||||
|
registerCustomOutputTaskUnix('CrazyDev22LT', '/home/julian/Desktop/server/plugins')
|
||||||
// ==============================================================
|
// ==============================================================
|
||||||
|
|
||||||
def NMS_BINDINGS = Map.of(
|
def NMS_BINDINGS = Map.of(
|
||||||
|
"v1_21_R2", "1.21.3-R0.1-SNAPSHOT",
|
||||||
|
"v1_21_R1", "1.21.1-R0.1-SNAPSHOT",
|
||||||
|
"v1_20_R4", "1.20.6-R0.1-SNAPSHOT",
|
||||||
|
"v1_20_R3", "1.20.4-R0.1-SNAPSHOT",
|
||||||
"v1_20_R2", "1.20.2-R0.1-SNAPSHOT",
|
"v1_20_R2", "1.20.2-R0.1-SNAPSHOT",
|
||||||
"v1_20_R1", "1.20.1-R0.1-SNAPSHOT",
|
"v1_20_R1", "1.20.1-R0.1-SNAPSHOT",
|
||||||
"v1_19_R3", "1.19.4-R0.1-SNAPSHOT",
|
"v1_19_R3", "1.19.4-R0.1-SNAPSHOT",
|
||||||
"v1_19_R2", "1.19.3-R0.1-SNAPSHOT",
|
"v1_19_R2", "1.19.3-R0.1-SNAPSHOT",
|
||||||
"v1_19_R1", "1.19.2-R0.1-SNAPSHOT"
|
"v1_19_R1", "1.19.2-R0.1-SNAPSHOT"
|
||||||
)
|
)
|
||||||
NMS_BINDINGS.each {
|
def JVM_VERSION = Map.of()
|
||||||
def key = it.key
|
NMS_BINDINGS.each { nms ->
|
||||||
def value = it.value
|
project(":nms:${nms.key}") {
|
||||||
def nms = value.split("-")[0];
|
|
||||||
project(":nms:${key}") {
|
|
||||||
apply plugin: 'java'
|
apply plugin: 'java'
|
||||||
apply plugin: 'java-library'
|
apply plugin: 'com.volmit.nmstools'
|
||||||
apply plugin: 'de.undercouch.download'
|
|
||||||
|
nmsTools {
|
||||||
|
it.jvm = JVM_VERSION.getOrDefault(nms.key, 21)
|
||||||
|
it.version = nms.value
|
||||||
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation project(":core")
|
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 {
|
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()
|
//minimize()
|
||||||
append("plugin.yml")
|
append("plugin.yml")
|
||||||
relocate 'com.dfsek.paralithic', 'com.volmit.iris.util.paralithic'
|
relocate 'com.dfsek.paralithic', 'com.volmit.iris.util.paralithic'
|
||||||
relocate 'io.papermc.lib', 'com.volmit.iris.util.paper'
|
relocate 'io.papermc.lib', 'com.volmit.iris.util.paper'
|
||||||
relocate 'net.kyori', 'com.volmit.iris.util.kyori'
|
relocate 'net.kyori', 'com.volmit.iris.util.kyori'
|
||||||
dependencies {
|
relocate 'org.bstats', 'com.volmit.util.metrics'
|
||||||
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")
|
archiveFileName.set("Iris-${project.version}.jar")
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation project(':core')
|
implementation project(':core')
|
||||||
NMS_BINDINGS.each {
|
|
||||||
implementation project(":nms:${it.key}")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
configurations.all {
|
configurations.configureEach {
|
||||||
resolutionStrategy.cacheChangingModulesFor 60, 'minutes'
|
resolutionStrategy.cacheChangingModulesFor 60, 'minutes'
|
||||||
resolutionStrategy.cacheDynamicVersionsFor 60, 'minutes'
|
resolutionStrategy.cacheDynamicVersionsFor 60, 'minutes'
|
||||||
}
|
}
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
getPlugins().apply("java")
|
apply plugin: 'java'
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenLocal {
|
|
||||||
content {
|
|
||||||
includeGroup("org.bukkit")
|
|
||||||
includeGroup("org.spigotmc")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mavenCentral()
|
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://repo.codemc.org/repository/maven-public" }
|
||||||
maven { url "https://mvn.lumine.io/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://s01.oss.sonatype.org/content/repositories/snapshots" }
|
||||||
maven { url "https://mvn.lumine.io/repository/maven/" }
|
maven { url "https://mvn.lumine.io/repository/maven/" }
|
||||||
maven { url "https://repo.triumphteam.dev/snapshots" }
|
maven { url "https://repo.triumphteam.dev/snapshots" }
|
||||||
maven { url "https://repo.mineinabyss.com/releases" }
|
maven { url "https://repo.mineinabyss.com/releases" }
|
||||||
maven { url 'https://hub.jeff-media.com/nexus/repository/jeff-media-public/' }
|
maven { url 'https://hub.jeff-media.com/nexus/repository/jeff-media-public/' }
|
||||||
|
maven { url "https://repo.nexomc.com/snapshots/" }
|
||||||
|
maven { url "https://libraries.minecraft.net" }
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
// Provided or Classpath
|
// Provided or Classpath
|
||||||
compileOnly 'org.projectlombok:lombok:1.18.24'
|
compileOnly 'org.projectlombok:lombok:1.18.36'
|
||||||
annotationProcessor 'org.projectlombok:lombok:1.18.24'
|
annotationProcessor 'org.projectlombok:lombok:1.18.36'
|
||||||
|
|
||||||
// Shaded
|
// Shaded
|
||||||
implementation 'com.dfsek:Paralithic:0.4.0'
|
implementation 'com.dfsek:Paralithic:0.4.0'
|
||||||
implementation 'io.papermc:paperlib:1.0.5'
|
implementation 'io.papermc:paperlib:1.0.5'
|
||||||
implementation "net.kyori:adventure-text-minimessage:4.13.1"
|
implementation "net.kyori:adventure-text-minimessage:4.17.0"
|
||||||
implementation 'net.kyori:adventure-platform-bukkit:4.3.0'
|
implementation 'net.kyori:adventure-platform-bukkit:4.3.4'
|
||||||
implementation 'net.kyori:adventure-api:4.13.1'
|
implementation 'net.kyori:adventure-api:4.17.0'
|
||||||
implementation 'io.lumine:Mythic-Dist:5.2.1'
|
implementation 'org.bstats:bstats-bukkit:3.1.0'
|
||||||
|
//implementation 'org.bytedeco:javacpp:1.5.10'
|
||||||
|
//implementation 'org.bytedeco:cuda-platform:12.3-8.9-1.5.10'
|
||||||
|
compileOnly 'io.lumine:Mythic-Dist:5.2.1'
|
||||||
|
compileOnly 'io.lumine:MythicCrucible-Dist:2.0.0'
|
||||||
|
|
||||||
// Dynamically Loaded
|
// Dynamically Loaded
|
||||||
implementation 'io.timeandspace:smoothie-map:2.0.2'
|
compileOnly 'io.timeandspace:smoothie-map:2.0.2'
|
||||||
implementation 'it.unimi.dsi:fastutil:8.5.8'
|
compileOnly 'it.unimi.dsi:fastutil:8.5.8'
|
||||||
implementation 'com.googlecode.concurrentlinkedhashmap:concurrentlinkedhashmap-lru:1.4.2'
|
compileOnly 'com.googlecode.concurrentlinkedhashmap:concurrentlinkedhashmap-lru:1.4.2'
|
||||||
implementation 'org.zeroturnaround:zt-zip:1.14'
|
compileOnly 'org.zeroturnaround:zt-zip:1.14'
|
||||||
implementation 'com.google.code.gson:gson:2.9.0'
|
compileOnly 'com.google.code.gson:gson:2.10.1'
|
||||||
implementation 'org.ow2.asm:asm:9.2'
|
compileOnly 'org.ow2.asm:asm:9.2'
|
||||||
implementation 'com.google.guava:guava:31.1-jre'
|
compileOnly 'com.google.guava:guava:33.0.0-jre'
|
||||||
implementation 'bsf:bsf:2.4.0'
|
compileOnly 'bsf:bsf:2.4.0'
|
||||||
implementation 'rhino:js:1.7R2'
|
compileOnly 'rhino:js:1.7R2'
|
||||||
implementation 'com.github.ben-manes.caffeine:caffeine:3.0.6'
|
compileOnly 'com.github.ben-manes.caffeine:caffeine:3.0.6'
|
||||||
implementation 'org.apache.commons:commons-lang3:3.12.0'
|
compileOnly 'org.apache.commons:commons-lang3:3.12.0'
|
||||||
|
compileOnly 'com.github.oshi:oshi-core:6.6.5'
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -273,20 +163,35 @@ allprojects {
|
|||||||
options.compilerArgs << '-parameters'
|
options.compilerArgs << '-parameters'
|
||||||
options.encoding = "UTF-8"
|
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") {
|
if (JavaVersion.current().toString() != "21") {
|
||||||
System.err.println()
|
System.err.println()
|
||||||
System.err.println("=========================================================================================================")
|
System.err.println("=========================================================================================================")
|
||||||
System.err.println("You must run gradle on Java 17. You are using " + JavaVersion.current())
|
System.err.println("You must run gradle on Java 21. You are using " + JavaVersion.current())
|
||||||
System.err.println()
|
System.err.println()
|
||||||
System.err.println("=== For IDEs ===")
|
System.err.println("=== For IDEs ===")
|
||||||
System.err.println("1. Configure the project for Java 17")
|
System.err.println("1. Configure the project for Java 21")
|
||||||
System.err.println("2. Configure the bundled gradle to use Java 17 in settings")
|
System.err.println("2. Configure the bundled gradle to use Java 21 in settings")
|
||||||
System.err.println()
|
System.err.println()
|
||||||
System.err.println("=== For Command Line (gradlew) ===")
|
System.err.println("=== For Command Line (gradlew) ===")
|
||||||
System.err.println("1. Install JDK 17 from https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html")
|
System.err.println("1. Install JDK 21 from https://www.oracle.com/java/technologies/javase/jdk21-archive-downloads.html")
|
||||||
System.err.println("2. Set JAVA_HOME environment variable to the new jdk installation folder such as C:\\Program Files\\Java\\jdk-17.0.1")
|
System.err.println("2. Set JAVA_HOME environment variable to the new jdk installation folder such as C:\\Program Files\\Java\\jdk-21.0.4")
|
||||||
System.err.println("3. Open a new command prompt window to get the new environment variables if need be.")
|
System.err.println("3. Open a new command prompt window to get the new environment variables if need be.")
|
||||||
System.err.println("=========================================================================================================")
|
System.err.println("=========================================================================================================")
|
||||||
System.err.println()
|
System.err.println()
|
||||||
@@ -295,18 +200,25 @@ if (JavaVersion.current().toString() != "17") {
|
|||||||
|
|
||||||
task iris(type: Copy) {
|
task iris(type: Copy) {
|
||||||
group "iris"
|
group "iris"
|
||||||
from new File(buildDir, "libs/Iris-${version}.jar")
|
from new File(layout.buildDirectory.asFile.get(), "libs/Iris-${version}.jar")
|
||||||
into buildDir
|
into layout.buildDirectory.asFile.get()
|
||||||
dependsOn(build)
|
dependsOn(build)
|
||||||
}
|
}
|
||||||
|
|
||||||
task setup() {
|
// with classifier: 'javadoc' and 'sources'
|
||||||
|
task irisDev(type: Copy) {
|
||||||
group "iris"
|
group "iris"
|
||||||
NMS_BINDINGS.each {
|
from("core/build/libs/core-javadoc.jar", "core/build/libs/core-sources.jar")
|
||||||
dependsOn(project(":nms:${it.key}").executeBuildTools)
|
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) {
|
def registerCustomOutputTask(name, path) {
|
||||||
if (!System.properties['os.name'].toLowerCase().contains('windows')) {
|
if (!System.properties['os.name'].toLowerCase().contains('windows')) {
|
||||||
return;
|
return;
|
||||||
@@ -341,4 +253,4 @@ def registerCustomOutputTaskUnix(name, path) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.build.dependsOn(shadowJar)
|
tasks.build.dependsOn(shadowJar)
|
||||||
|
|||||||
+24
-14
@@ -19,7 +19,7 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id 'java'
|
id 'java'
|
||||||
id 'java-library'
|
id 'java-library'
|
||||||
id "io.freefair.lombok" version "6.3.0"
|
id "io.freefair.lombok" version "8.6"
|
||||||
}
|
}
|
||||||
|
|
||||||
def apiVersion = '1.19'
|
def apiVersion = '1.19'
|
||||||
@@ -33,6 +33,11 @@ compileJava {
|
|||||||
options.encoding = "UTF-8"
|
options.encoding = "UTF-8"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
maven { url 'https://nexus.phoenixdevt.fr/repository/maven-public/'}
|
||||||
|
maven { url 'https://repo.auxilor.io/repository/maven-public/' }
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dependencies.
|
* Dependencies.
|
||||||
*
|
*
|
||||||
@@ -47,21 +52,28 @@ compileJava {
|
|||||||
*/
|
*/
|
||||||
dependencies {
|
dependencies {
|
||||||
// Provided or Classpath
|
// Provided or Classpath
|
||||||
implementation 'org.spigotmc:spigot-api:1.20.1-R0.1-SNAPSHOT'
|
compileOnly 'org.spigotmc:spigot-api:1.20.1-R0.1-SNAPSHOT'
|
||||||
implementation 'org.apache.logging.log4j:log4j-api:2.19.0'
|
compileOnly 'org.apache.logging.log4j:log4j-api:2.19.0'
|
||||||
implementation 'org.apache.logging.log4j:log4j-core:2.19.0'
|
compileOnly 'org.apache.logging.log4j:log4j-core:2.19.0'
|
||||||
implementation 'commons-lang:commons-lang:2.6'
|
compileOnly 'commons-io:commons-io:2.13.0'
|
||||||
implementation 'com.github.oshi:oshi-core:5.8.5'
|
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
|
// Third Party Integrations
|
||||||
implementation 'com.ticxo.playeranimator:PlayerAnimator:R1.2.7'
|
compileOnly 'com.ticxo.playeranimator:PlayerAnimator:R1.2.7'
|
||||||
implementation 'com.github.oraxen:oraxen:1.158.0'
|
compileOnly 'com.nexomc:nexo:0.6.0-dev.0'
|
||||||
implementation 'com.github.LoneDev6:api-itemsadder:3.4.1-r4'
|
compileOnly 'com.github.LoneDev6:api-itemsadder:3.4.1-r4'
|
||||||
implementation 'com.github.PlaceholderAPI:placeholderapi:2.11.3'
|
compileOnly 'com.github.PlaceholderAPI:placeholderapi:2.11.3'
|
||||||
implementation 'com.github.Ssomar-Developement:SCore:4.23.10.8'
|
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')
|
//implementation files('libs/CustomItems.jar')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
java {
|
||||||
|
disableAutoTargetJvm()
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gradle is weird sometimes, we need to delete the plugin yml from the build folder to actually filter properly.
|
* Gradle is weird sometimes, we need to delete the plugin yml from the build folder to actually filter properly.
|
||||||
@@ -80,6 +92,4 @@ processResources {
|
|||||||
'apiversion': apiVersion.toString()
|
'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.INMS;
|
||||||
import com.volmit.iris.core.nms.v1X.NMSBinding1X;
|
import com.volmit.iris.core.nms.v1X.NMSBinding1X;
|
||||||
import com.volmit.iris.core.pregenerator.LazyPregenerator;
|
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.service.StudioSVC;
|
||||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||||
import com.volmit.iris.engine.EnginePanic;
|
import com.volmit.iris.engine.EnginePanic;
|
||||||
@@ -39,8 +38,9 @@ import com.volmit.iris.engine.object.IrisDimension;
|
|||||||
import com.volmit.iris.engine.object.IrisWorld;
|
import com.volmit.iris.engine.object.IrisWorld;
|
||||||
import com.volmit.iris.engine.platform.BukkitChunkGenerator;
|
import com.volmit.iris.engine.platform.BukkitChunkGenerator;
|
||||||
import com.volmit.iris.engine.platform.DummyChunkGenerator;
|
import com.volmit.iris.engine.platform.DummyChunkGenerator;
|
||||||
import com.volmit.iris.engine.safeguard.IrisSafeguard;
|
import com.volmit.iris.core.safeguard.IrisSafeguard;
|
||||||
import com.volmit.iris.engine.safeguard.UtilsSFG;
|
import com.volmit.iris.core.safeguard.UtilsSFG;
|
||||||
|
import com.volmit.iris.engine.platform.PlatformChunkGenerator;
|
||||||
import com.volmit.iris.util.collection.KList;
|
import com.volmit.iris.util.collection.KList;
|
||||||
import com.volmit.iris.util.collection.KMap;
|
import com.volmit.iris.util.collection.KMap;
|
||||||
import com.volmit.iris.util.exceptions.IrisException;
|
import com.volmit.iris.util.exceptions.IrisException;
|
||||||
@@ -56,7 +56,6 @@ import com.volmit.iris.util.math.RNG;
|
|||||||
import com.volmit.iris.util.misc.getHardware;
|
import com.volmit.iris.util.misc.getHardware;
|
||||||
import com.volmit.iris.util.parallel.MultiBurst;
|
import com.volmit.iris.util.parallel.MultiBurst;
|
||||||
import com.volmit.iris.util.plugin.IrisService;
|
import com.volmit.iris.util.plugin.IrisService;
|
||||||
import com.volmit.iris.util.plugin.Metrics;
|
|
||||||
import com.volmit.iris.util.plugin.VolmitPlugin;
|
import com.volmit.iris.util.plugin.VolmitPlugin;
|
||||||
import com.volmit.iris.util.plugin.VolmitSender;
|
import com.volmit.iris.util.plugin.VolmitSender;
|
||||||
import com.volmit.iris.util.reflect.ShadeFix;
|
import com.volmit.iris.util.reflect.ShadeFix;
|
||||||
@@ -66,10 +65,11 @@ import com.volmit.iris.util.scheduling.ShurikenQueue;
|
|||||||
import io.papermc.lib.PaperLib;
|
import io.papermc.lib.PaperLib;
|
||||||
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
|
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
|
||||||
import net.kyori.adventure.text.serializer.ComponentSerializer;
|
import net.kyori.adventure.text.serializer.ComponentSerializer;
|
||||||
import org.bukkit.Bukkit;
|
import org.bstats.bukkit.Metrics;
|
||||||
import org.bukkit.GameMode;
|
import org.bstats.charts.DrilldownPie;
|
||||||
import org.bukkit.Location;
|
import org.bstats.charts.SimplePie;
|
||||||
import org.bukkit.WorldCreator;
|
import org.bstats.charts.SingleLineChart;
|
||||||
|
import org.bukkit.*;
|
||||||
import org.bukkit.block.data.BlockData;
|
import org.bukkit.block.data.BlockData;
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
@@ -77,32 +77,31 @@ import org.bukkit.configuration.ConfigurationSection;
|
|||||||
import org.bukkit.configuration.file.FileConfiguration;
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
import org.bukkit.configuration.file.YamlConfiguration;
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.Event;
|
import org.bukkit.event.*;
|
||||||
import org.bukkit.event.HandlerList;
|
|
||||||
import org.bukkit.event.Listener;
|
|
||||||
import org.bukkit.generator.BiomeProvider;
|
import org.bukkit.generator.BiomeProvider;
|
||||||
import org.bukkit.generator.ChunkGenerator;
|
import org.bukkit.generator.ChunkGenerator;
|
||||||
import org.bukkit.plugin.IllegalPluginAccessException;
|
import org.bukkit.plugin.IllegalPluginAccessException;
|
||||||
import org.bukkit.plugin.Plugin;
|
import org.bukkit.plugin.Plugin;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import oshi.SystemInfo;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
import java.lang.management.ManagementFactory;
|
import java.math.RoundingMode;
|
||||||
import java.lang.management.OperatingSystemMXBean;
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.Date;
|
import java.text.NumberFormat;
|
||||||
import java.util.Map;
|
import java.util.*;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static com.volmit.iris.engine.safeguard.IrisSafeguard.unstablemode;
|
import static com.volmit.iris.core.safeguard.IrisSafeguard.*;
|
||||||
import static com.volmit.iris.engine.safeguard.ServerBootSFG.passedserversoftware;
|
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")
|
@SuppressWarnings("CanBeFinal")
|
||||||
public class Iris extends VolmitPlugin implements Listener {
|
public class Iris extends VolmitPlugin implements Listener {
|
||||||
public static final String OVERWORLD_TAG = "3800";
|
public static final String OVERWORLD_TAG = "31000";
|
||||||
|
|
||||||
private static final Queue<Runnable> syncJobs = new ShurikenQueue<>();
|
private static final Queue<Runnable> syncJobs = new ShurikenQueue<>();
|
||||||
|
|
||||||
@@ -127,6 +126,10 @@ public class Iris extends VolmitPlugin implements Listener {
|
|||||||
private KMap<Class<? extends IrisService>, IrisService> services;
|
private KMap<Class<? extends IrisService>, IrisService> services;
|
||||||
|
|
||||||
public static VolmitSender getSender() {
|
public static VolmitSender getSender() {
|
||||||
|
if (sender == null) {
|
||||||
|
sender = new VolmitSender(Bukkit.getConsoleSender());
|
||||||
|
sender.setTag(instance.getTag());
|
||||||
|
}
|
||||||
return sender;
|
return sender;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -193,10 +196,10 @@ public class Iris extends VolmitPlugin implements Listener {
|
|||||||
|
|
||||||
public static void msg(String string) {
|
public static void msg(String string) {
|
||||||
try {
|
try {
|
||||||
sender.sendMessage(string);
|
getSender().sendMessage(string);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
try {
|
try {
|
||||||
System.out.println(instance.getTag() + string.replaceAll("(<([^>]+)>)", ""));
|
instance.getLogger().info(instance.getTag() + string.replaceAll("(<([^>]+)>)", ""));
|
||||||
} catch (Throwable ignored1) {
|
} catch (Throwable ignored1) {
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -350,7 +353,7 @@ public class Iris extends VolmitPlugin implements Listener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int getJavaVersion() {
|
public static int getJavaVersion() {
|
||||||
String version = System.getProperty("java.version");
|
String version = System.getProperty("java.version");
|
||||||
if (version.startsWith("1.")) {
|
if (version.startsWith("1.")) {
|
||||||
version = version.substring(2, 3);
|
version = version.substring(2, 3);
|
||||||
@@ -363,6 +366,13 @@ public class Iris extends VolmitPlugin implements Listener {
|
|||||||
return Integer.parseInt(version);
|
return Integer.parseInt(version);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String getJava() {
|
||||||
|
String javaRuntimeName = System.getProperty("java.vm.name");
|
||||||
|
String javaRuntimeVendor = System.getProperty("java.vendor");
|
||||||
|
String javaRuntimeVersion = System.getProperty("java.vm.version");
|
||||||
|
return String.format("%s %s (build %s)", javaRuntimeName, javaRuntimeVendor, javaRuntimeVersion);
|
||||||
|
}
|
||||||
|
|
||||||
public static void reportErrorChunk(int x, int z, Throwable e, String extra) {
|
public static void reportErrorChunk(int x, int z, Throwable e, String extra) {
|
||||||
if (IrisSettings.get().getGeneral().isDebug()) {
|
if (IrisSettings.get().getGeneral().isDebug()) {
|
||||||
File f = instance.getDataFile("debug", "chunk-errors", "chunk." + x + "." + z + ".txt");
|
File f = instance.getDataFile("debug", "chunk-errors", "chunk." + x + "." + z + ".txt");
|
||||||
@@ -425,7 +435,7 @@ public class Iris extends VolmitPlugin implements Listener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pw.close();
|
pw.close();
|
||||||
System.out.println("DUMPED! See " + fi.getAbsolutePath());
|
Iris.info("DUMPED! See " + fi.getAbsolutePath());
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@@ -442,18 +452,15 @@ public class Iris extends VolmitPlugin implements Listener {
|
|||||||
private static void fixShading() {
|
private static void fixShading() {
|
||||||
ShadeFix.fix(ComponentSerializer.class);
|
ShadeFix.fix(ComponentSerializer.class);
|
||||||
}
|
}
|
||||||
private ChunkHandlerSVC chunkHandlerSVC;
|
|
||||||
private void enable() {
|
private void enable() {
|
||||||
instance = this;
|
instance = this;
|
||||||
services = new KMap<>();
|
services = new KMap<>();
|
||||||
|
setupAudience();
|
||||||
initialize("com.volmit.iris.core.service").forEach((i) -> services.put((Class<? extends IrisService>) i.getClass(), (IrisService) i));
|
initialize("com.volmit.iris.core.service").forEach((i) -> services.put((Class<? extends IrisService>) i.getClass(), (IrisService) i));
|
||||||
INMS.get();
|
INMS.get();
|
||||||
IO.delete(new File("iris"));
|
IO.delete(new File("iris"));
|
||||||
setupAudience();
|
|
||||||
IrisSafeguard.IrisSafeguardSystem();
|
IrisSafeguard.IrisSafeguardSystem();
|
||||||
sender = new VolmitSender(Bukkit.getConsoleSender());
|
getSender().setTag(getTag());
|
||||||
sender.setTag(getTag());
|
|
||||||
instance = this;
|
|
||||||
compat = IrisCompat.configured(getDataFile("compat.json"));
|
compat = IrisCompat.configured(getDataFile("compat.json"));
|
||||||
linkMultiverseCore = new MultiverseCoreLink();
|
linkMultiverseCore = new MultiverseCoreLink();
|
||||||
linkMythicMobs = new MythicMobsLink();
|
linkMythicMobs = new MythicMobsLink();
|
||||||
@@ -470,14 +477,8 @@ public class Iris extends VolmitPlugin implements Listener {
|
|||||||
J.s(this::setupPapi);
|
J.s(this::setupPapi);
|
||||||
J.a(ServerConfigurator::configure, 20);
|
J.a(ServerConfigurator::configure, 20);
|
||||||
splash();
|
splash();
|
||||||
UtilsSFG.UnstableMode();
|
UtilsSFG.splash();
|
||||||
UtilsSFG.SupportedServerSoftware();
|
|
||||||
UtilsSFG.printIncompatibleWarnings();
|
|
||||||
UtilsSFG.unstablePrompt();
|
|
||||||
if(IrisSettings.get().getGeneral().useIntegratedChunkHandler) {
|
|
||||||
chunkHandlerSVC = new ChunkHandlerSVC(this);
|
|
||||||
Iris.info(C.LIGHT_PURPLE + "Started Intergrated ChunkHandlerSVC");
|
|
||||||
}
|
|
||||||
autoStartStudio();
|
autoStartStudio();
|
||||||
checkForBukkitWorlds();
|
checkForBukkitWorlds();
|
||||||
IrisToolbelt.retainMantleDataForSlice(String.class.getCanonicalName());
|
IrisToolbelt.retainMantleDataForSlice(String.class.getCanonicalName());
|
||||||
@@ -509,11 +510,10 @@ public class Iris extends VolmitPlugin implements Listener {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Iris.info("2 World: %s | Generator: %s", s, generator);
|
if (Bukkit.getWorld(s) != null)
|
||||||
|
|
||||||
if (Bukkit.getWorlds().stream().anyMatch(w -> w.getName().equals(s))) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
Iris.info("Loading World: %s | Generator: %s", s, generator);
|
||||||
|
|
||||||
Iris.info(C.LIGHT_PURPLE + "Preparing Spawn for " + s + "' using Iris:" + generator + "...");
|
Iris.info(C.LIGHT_PURPLE + "Preparing Spawn for " + s + "' using Iris:" + generator + "...");
|
||||||
new WorldCreator(s)
|
new WorldCreator(s)
|
||||||
@@ -532,7 +532,7 @@ public class Iris extends VolmitPlugin implements Listener {
|
|||||||
Iris.info("Starting up auto Studio!");
|
Iris.info("Starting up auto Studio!");
|
||||||
try {
|
try {
|
||||||
Player r = new KList<>(getServer().getOnlinePlayers()).getRandom();
|
Player r = new KList<>(getServer().getOnlinePlayers()).getRandom();
|
||||||
Iris.service(StudioSVC.class).open(r != null ? new VolmitSender(r) : sender, 1337, IrisSettings.get().getGenerator().getDefaultWorldType(), (w) -> {
|
Iris.service(StudioSVC.class).open(r != null ? new VolmitSender(r) : getSender(), 1337, IrisSettings.get().getGenerator().getDefaultWorldType(), (w) -> {
|
||||||
J.s(() -> {
|
J.s(() -> {
|
||||||
for (Player i : getServer().getOnlinePlayers()) {
|
for (Player i : getServer().getOnlinePlayers()) {
|
||||||
i.setGameMode(GameMode.SPECTATOR);
|
i.setGameMode(GameMode.SPECTATOR);
|
||||||
@@ -599,9 +599,11 @@ public class Iris extends VolmitPlugin implements Listener {
|
|||||||
if (unstablemode) {
|
if (unstablemode) {
|
||||||
return C.BOLD + "" + C.DARK_GRAY + "[" + C.BOLD + "" + C.RED + "Iris" + C.BOLD + C.DARK_GRAY + "]" + C.RESET + "" + C.GRAY + ": ";
|
return C.BOLD + "" + C.DARK_GRAY + "[" + C.BOLD + "" + C.RED + "Iris" + C.BOLD + C.DARK_GRAY + "]" + C.RESET + "" + C.GRAY + ": ";
|
||||||
}
|
}
|
||||||
else {
|
if (warningmode) {
|
||||||
return C.BOLD + "" + C.DARK_GRAY + "[" + C.BOLD + "" + C.IRIS + "Iris" + C.BOLD + C.DARK_GRAY + "]" + C.RESET + "" + C.GRAY + ": ";
|
return C.BOLD + "" + C.DARK_GRAY + "[" + C.BOLD + "" + C.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() {
|
private boolean setupChecks() {
|
||||||
@@ -659,7 +661,48 @@ public class Iris extends VolmitPlugin implements Listener {
|
|||||||
|
|
||||||
private void bstats() {
|
private void bstats() {
|
||||||
if (IrisSettings.get().getGeneral().isPluginMetrics()) {
|
if (IrisSettings.get().getGeneral().isPluginMetrics()) {
|
||||||
J.s(() -> new Metrics(Iris.instance, 8757));
|
J.s(() -> {
|
||||||
|
var metrics = new Metrics(Iris.instance, 24220);
|
||||||
|
metrics.addCustomChart(new SingleLineChart("custom_dimensions", () -> Bukkit.getWorlds()
|
||||||
|
.stream()
|
||||||
|
.filter(IrisToolbelt::isIrisWorld)
|
||||||
|
.mapToInt(w -> 1)
|
||||||
|
.sum()));
|
||||||
|
|
||||||
|
metrics.addCustomChart(new DrilldownPie("used_packs", () -> Bukkit.getWorlds().stream()
|
||||||
|
.map(IrisToolbelt::access)
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.map(PlatformChunkGenerator::getTarget)
|
||||||
|
.collect(Collectors.toMap(target -> target.getDimension().getLoadKey(), target -> {
|
||||||
|
int version = target.getDimension().getVersion();
|
||||||
|
String checksum = IO.hashRecursive(target.getData().getDataFolder());
|
||||||
|
|
||||||
|
return Map.of("v" + version + " (" + checksum + ")", 1);
|
||||||
|
}, (a, b) -> {
|
||||||
|
Map<String, Integer> merged = new HashMap<>(a);
|
||||||
|
b.forEach((k, v) -> merged.merge(k, v, Integer::sum));
|
||||||
|
return merged;
|
||||||
|
}))));
|
||||||
|
|
||||||
|
|
||||||
|
var info = new SystemInfo().getHardware();
|
||||||
|
var cpu = info.getProcessor().getProcessorIdentifier();
|
||||||
|
var mem = info.getMemory();
|
||||||
|
metrics.addCustomChart(new SimplePie("cpu_model", cpu::getName));
|
||||||
|
|
||||||
|
var nf = NumberFormat.getInstance(Locale.ENGLISH);
|
||||||
|
nf.setMinimumFractionDigits(0);
|
||||||
|
nf.setMaximumFractionDigits(2);
|
||||||
|
nf.setRoundingMode(RoundingMode.HALF_UP);
|
||||||
|
|
||||||
|
metrics.addCustomChart(new DrilldownPie("memory", () -> {
|
||||||
|
double total = mem.getTotal() * 1E-9;
|
||||||
|
double alloc = Math.min(total, Runtime.getRuntime().maxMemory() * 1E-9);
|
||||||
|
return Map.of(nf.format(alloc), Map.of(nf.format(total), 1));
|
||||||
|
}));
|
||||||
|
|
||||||
|
postShutdown.add(metrics::shutdown);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -731,10 +774,10 @@ public class Iris extends VolmitPlugin implements Listener {
|
|||||||
File ff = new File(w.worldFolder(), "iris/pack");
|
File ff = new File(w.worldFolder(), "iris/pack");
|
||||||
if (!ff.exists() || ff.listFiles().length == 0) {
|
if (!ff.exists() || ff.listFiles().length == 0) {
|
||||||
ff.mkdirs();
|
ff.mkdirs();
|
||||||
service(StudioSVC.class).installIntoWorld(sender, dim.getLoadKey(), ff.getParentFile());
|
service(StudioSVC.class).installIntoWorld(getSender(), dim.getLoadKey(), w.worldFolder());
|
||||||
}
|
}
|
||||||
|
|
||||||
return new BukkitChunkGenerator(w, false, ff, dim.getLoadKey());
|
return new BukkitChunkGenerator(w, false, ff, dim.getLoadKey(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void splash() {
|
public void splash() {
|
||||||
@@ -748,6 +791,9 @@ public class Iris extends VolmitPlugin implements Listener {
|
|||||||
if (unstablemode) {
|
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()};
|
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 = {
|
String[] splashstable = {
|
||||||
padd + C.GRAY + " @@@@@@@@@@@@@@" + C.DARK_GRAY + "@@@",
|
padd + C.GRAY + " @@@@@@@@@@@@@@" + C.DARK_GRAY + "@@@",
|
||||||
@@ -776,32 +822,45 @@ public class Iris extends VolmitPlugin implements Listener {
|
|||||||
padd + C.GRAY + "" + C.RED + " '(((())))' " + C.DARK_GRAY + "&&&&&&&&" + C.GRAY + "&&&&&&&@@",
|
padd + C.GRAY + "" + C.RED + " '(((())))' " + C.DARK_GRAY + "&&&&&&&&" + C.GRAY + "&&&&&&&@@",
|
||||||
padd + C.GRAY + " " + C.DARK_GRAY + "@@@" + C.GRAY + "@@@@@@@@@@@@@@"
|
padd + C.GRAY + " " + C.DARK_GRAY + "@@@" + C.GRAY + "@@@@@@@@@@@@@@"
|
||||||
};
|
};
|
||||||
String[] splash = unstablemode ? splashunstable : splashstable; // Choose the appropriate splash array based on unstablemode
|
String[] splashwarning = {
|
||||||
|
padd + C.GRAY + " @@@@@@@@@@@@@@" + C.DARK_GRAY + "@@@",
|
||||||
|
padd + C.GRAY + " @@&&&&&&&&&" + C.DARK_GRAY + "&&&&&&" + C.GOLD + " .(((()))). ",
|
||||||
OperatingSystemMXBean osBean = ManagementFactory.getOperatingSystemMXBean();
|
padd + C.GRAY + "@@@&&&&&&&&" + C.DARK_GRAY + "&&&&&" + C.GOLD + " .((((((())))))). ",
|
||||||
String osArch = osBean.getArch();
|
padd + C.GRAY + "@@@&&&&&" + C.DARK_GRAY + "&&&&&&&" + C.GOLD + " ((((((((())))))))) " + C.GRAY + " @",
|
||||||
String osName = osBean.getName();
|
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) {
|
if (!passedserversoftware) {
|
||||||
Iris.info("Server type & version: " + C.RED + Bukkit.getVersion());
|
Iris.info("Server type & version: " + C.RED + Bukkit.getVersion());
|
||||||
} else { Iris.info("Server type & version: " + Bukkit.getVersion()); }
|
} else { Iris.info("Server type & version: " + Bukkit.getVersion()); }
|
||||||
|
Iris.info("Java: " + getJava());
|
||||||
Iris.info("Server OS: " + osName + " (" + osArch + ")");
|
if (!instance.getServer().getVersion().contains("Purpur")) {
|
||||||
|
if (instance.getServer().getVersion().contains("Spigot") && instance.getServer().getVersion().contains("Bukkit")) {
|
||||||
if(unstablemode) Iris.info("Server Cpu: " + C.DARK_RED + getCPUModel());
|
Iris.info(C.RED + " Iris requires paper or above to function properly..");
|
||||||
|
} else {
|
||||||
if(getCPUModel().contains("Intel")) Iris.info("Server Cpu: " + C.BLUE + getCPUModel());
|
Iris.info(C.YELLOW + "Purpur is recommended to use with iris.");
|
||||||
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");
|
|
||||||
if (getHardware.getProcessMemory() < 5999) {
|
if (getHardware.getProcessMemory() < 5999) {
|
||||||
Iris.warn("6GB+ Ram is recommended");
|
Iris.warn("6GB+ Ram is recommended");
|
||||||
|
Iris.warn("Process Memory: " + getHardware.getProcessMemory() + " MB");
|
||||||
}
|
}
|
||||||
Iris.info("Bukkit version: " + Bukkit.getBukkitVersion());
|
Iris.info("Bukkit distro: " + Bukkit.getName());
|
||||||
Iris.info("Java version: " + getJavaVersion());
|
|
||||||
Iris.info("Custom Biomes: " + INMS.get().countCustomBiomes());
|
Iris.info("Custom Biomes: " + INMS.get().countCustomBiomes());
|
||||||
setupChecks();
|
setupChecks();
|
||||||
printPacks();
|
printPacks();
|
||||||
@@ -834,4 +893,33 @@ public class Iris extends VolmitPlugin implements Listener {
|
|||||||
}
|
}
|
||||||
Iris.info(" " + dimName + " v" + version);
|
Iris.info(" " + dimName + " v" + version);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getIrisVersion() {
|
||||||
|
String input = Iris.instance.getDescription().getVersion();
|
||||||
|
int hyphenIndex = input.indexOf('-');
|
||||||
|
if (hyphenIndex != -1) {
|
||||||
|
String result = input.substring(0, hyphenIndex);
|
||||||
|
result = result.replaceAll("\\.", "");
|
||||||
|
return Integer.parseInt(result);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMCVersion() {
|
||||||
|
try {
|
||||||
|
String version = Bukkit.getVersion();
|
||||||
|
Matcher matcher = Pattern.compile("\\(MC: ([\\d.]+)\\)").matcher(version);
|
||||||
|
if (matcher.find()) {
|
||||||
|
version = matcher.group(1).replaceAll("\\.", "");
|
||||||
|
long versionNumber = Long.parseLong(version);
|
||||||
|
if (versionNumber > Integer.MAX_VALUE) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return (int) versionNumber;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
} catch (Exception e) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,10 @@ import com.volmit.iris.util.io.IO;
|
|||||||
import com.volmit.iris.util.json.JSONException;
|
import com.volmit.iris.util.json.JSONException;
|
||||||
import com.volmit.iris.util.json.JSONObject;
|
import com.volmit.iris.util.json.JSONObject;
|
||||||
import com.volmit.iris.util.plugin.VolmitSender;
|
import com.volmit.iris.util.plugin.VolmitSender;
|
||||||
|
import com.volmit.iris.util.scheduling.ChronoLatch;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -41,6 +44,7 @@ public class IrisSettings {
|
|||||||
private IrisSettingsConcurrency concurrency = new IrisSettingsConcurrency();
|
private IrisSettingsConcurrency concurrency = new IrisSettingsConcurrency();
|
||||||
private IrisSettingsStudio studio = new IrisSettingsStudio();
|
private IrisSettingsStudio studio = new IrisSettingsStudio();
|
||||||
private IrisSettingsPerformance performance = new IrisSettingsPerformance();
|
private IrisSettingsPerformance performance = new IrisSettingsPerformance();
|
||||||
|
private IrisSettingsUpdater updater = new IrisSettingsUpdater();
|
||||||
|
|
||||||
public static int getThreadCount(int c) {
|
public static int getThreadCount(int c) {
|
||||||
return switch (c) {
|
return switch (c) {
|
||||||
@@ -135,7 +139,7 @@ public class IrisSettings {
|
|||||||
|
|
||||||
@Data
|
@Data
|
||||||
public static class IrisSettingsPerformance {
|
public static class IrisSettingsPerformance {
|
||||||
public boolean trimMantleInStudio = false;
|
public boolean trimMantleInStudio = false;
|
||||||
public int mantleKeepAlive = 30;
|
public int mantleKeepAlive = 30;
|
||||||
public int cacheSize = 4_096;
|
public int cacheSize = 4_096;
|
||||||
public int resourceLoaderCacheSize = 1_024;
|
public int resourceLoaderCacheSize = 1_024;
|
||||||
@@ -143,10 +147,33 @@ public class IrisSettings {
|
|||||||
public int scriptLoaderCacheSize = 512;
|
public int scriptLoaderCacheSize = 512;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class IrisSettingsUpdater {
|
||||||
|
public double threadMultiplier = 2;
|
||||||
|
public double chunkLoadSensitivity = 0.7;
|
||||||
|
public MsRange emptyMsRange = new MsRange(80, 100);
|
||||||
|
public MsRange defaultMsRange = new MsRange(20, 40);
|
||||||
|
|
||||||
|
public double getThreadMultiplier() {
|
||||||
|
return Math.min(Math.abs(threadMultiplier), 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getChunkLoadSensitivity() {
|
||||||
|
return Math.min(chunkLoadSensitivity, 0.9);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public static class MsRange {
|
||||||
|
public int min = 20;
|
||||||
|
public int max = 40;
|
||||||
|
}
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public static class IrisSettingsGeneral {
|
public static class IrisSettingsGeneral {
|
||||||
public boolean bootUnstable = false;
|
public boolean DoomsdayAnnihilationSelfDestructMode = false;
|
||||||
public boolean useIntegratedChunkHandler = false;
|
|
||||||
public boolean commandSounds = true;
|
public boolean commandSounds = true;
|
||||||
public boolean debug = false;
|
public boolean debug = false;
|
||||||
public boolean disableNMS = false;
|
public boolean disableNMS = false;
|
||||||
@@ -171,6 +198,7 @@ public class IrisSettings {
|
|||||||
public static class IrisSettingsGUI {
|
public static class IrisSettingsGUI {
|
||||||
public boolean useServerLaunchedGuis = true;
|
public boolean useServerLaunchedGuis = true;
|
||||||
public boolean maximumPregenGuiFPS = false;
|
public boolean maximumPregenGuiFPS = false;
|
||||||
|
public boolean colorMode = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
|
|||||||
@@ -21,9 +21,12 @@ package com.volmit.iris.core;
|
|||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.Iris;
|
||||||
import com.volmit.iris.core.loader.IrisData;
|
import com.volmit.iris.core.loader.IrisData;
|
||||||
import com.volmit.iris.core.nms.INMS;
|
import com.volmit.iris.core.nms.INMS;
|
||||||
|
import com.volmit.iris.core.nms.datapack.DataVersion;
|
||||||
|
import com.volmit.iris.core.nms.datapack.IDataFixer;
|
||||||
import com.volmit.iris.engine.object.IrisBiome;
|
import com.volmit.iris.engine.object.IrisBiome;
|
||||||
import com.volmit.iris.engine.object.IrisBiomeCustom;
|
import com.volmit.iris.engine.object.IrisBiomeCustom;
|
||||||
import com.volmit.iris.engine.object.IrisDimension;
|
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.KList;
|
||||||
import com.volmit.iris.util.collection.KSet;
|
import com.volmit.iris.util.collection.KSet;
|
||||||
import com.volmit.iris.util.format.C;
|
import com.volmit.iris.util.format.C;
|
||||||
@@ -55,7 +58,7 @@ public class ServerConfigurator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void increaseKeepAliveSpigot() throws IOException, InvalidConfigurationException {
|
private static void increaseKeepAliveSpigot() throws IOException, InvalidConfigurationException {
|
||||||
File spigotConfig = new File("config/spigot.yml");
|
File spigotConfig = new File("spigot.yml");
|
||||||
FileConfiguration f = new YamlConfiguration();
|
FileConfiguration f = new YamlConfiguration();
|
||||||
f.load(spigotConfig);
|
f.load(spigotConfig);
|
||||||
long tt = f.getLong("settings.timeout-time");
|
long tt = f.getLong("settings.timeout-time");
|
||||||
@@ -90,10 +93,36 @@ public class ServerConfigurator {
|
|||||||
return worlds;
|
return worlds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void installDataPacks(boolean fullInstall) {
|
public static void installDataPacks(boolean fullInstall) {
|
||||||
|
installDataPacks(DataVersion.getDefault(), fullInstall);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void installDataPacks(IDataFixer fixer, boolean fullInstall) {
|
||||||
Iris.info("Checking Data Packs...");
|
Iris.info("Checking Data Packs...");
|
||||||
File packs = new File("plugins/Iris/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()) {
|
if (packs.exists()) {
|
||||||
for (File i : packs.listFiles()) {
|
for (File i : packs.listFiles()) {
|
||||||
@@ -113,7 +142,7 @@ public class ServerConfigurator {
|
|||||||
|
|
||||||
Iris.verbose(" Checking Dimension " + dim.getLoadFile().getPath());
|
Iris.verbose(" Checking Dimension " + dim.getLoadFile().getPath());
|
||||||
for (File dpack : getDatapacksFolder()) {
|
for (File dpack : getDatapacksFolder()) {
|
||||||
dim.installDataPack(() -> data, dpack);
|
dim.installDataPack(fixer, () -> data, dpack, ultimateMaxHeight, ultimateMinHeight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,134 @@
|
|||||||
|
/*
|
||||||
|
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||||
|
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.volmit.iris.core.commands;
|
||||||
|
|
||||||
|
import com.volmit.iris.Iris;
|
||||||
|
import com.volmit.iris.core.pregenerator.DeepSearchPregenerator;
|
||||||
|
import com.volmit.iris.core.pregenerator.PregenTask;
|
||||||
|
import com.volmit.iris.core.pregenerator.TurboPregenerator;
|
||||||
|
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||||
|
import com.volmit.iris.util.data.Dimension;
|
||||||
|
import com.volmit.iris.util.decree.DecreeExecutor;
|
||||||
|
import com.volmit.iris.util.decree.annotations.Decree;
|
||||||
|
import com.volmit.iris.util.decree.annotations.Param;
|
||||||
|
import com.volmit.iris.util.format.C;
|
||||||
|
import com.volmit.iris.util.math.Position2;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@Decree(name = "DeepSearch", aliases = "search", description = "Pregenerate your Iris worlds!")
|
||||||
|
public class CommandDeepSearch implements DecreeExecutor {
|
||||||
|
public String worldName;
|
||||||
|
@Decree(description = "DeepSearch a world")
|
||||||
|
public void start(
|
||||||
|
@Param(description = "The radius of the pregen in blocks", aliases = "size")
|
||||||
|
int radius,
|
||||||
|
@Param(description = "The world to pregen", contextual = true)
|
||||||
|
World world,
|
||||||
|
@Param(aliases = "middle", description = "The center location of the pregen. Use \"me\" for your current location", defaultValue = "0,0")
|
||||||
|
Vector center
|
||||||
|
) {
|
||||||
|
|
||||||
|
worldName = world.getName();
|
||||||
|
File worldDirectory = new File(Bukkit.getWorldContainer(), world.getName());
|
||||||
|
File TurboFile = new File(worldDirectory, "DeepSearch.json");
|
||||||
|
if (TurboFile.exists()) {
|
||||||
|
if (DeepSearchPregenerator.getInstance() != null) {
|
||||||
|
sender().sendMessage(C.BLUE + "DeepSearch is already in progress");
|
||||||
|
Iris.info(C.YELLOW + "DeepSearch is already in progress");
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
TurboFile.delete();
|
||||||
|
} catch (Exception e){
|
||||||
|
Iris.error("Failed to delete the old instance file of DeepSearch!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (sender().isPlayer() && access() == null) {
|
||||||
|
sender().sendMessage(C.RED + "The engine access for this world is null!");
|
||||||
|
sender().sendMessage(C.RED + "Please make sure the world is loaded & the engine is initialized. Generate a new chunk, for example.");
|
||||||
|
}
|
||||||
|
|
||||||
|
DeepSearchPregenerator.DeepSearchJob DeepSearchJob = DeepSearchPregenerator.DeepSearchJob.builder()
|
||||||
|
.world(world)
|
||||||
|
.radiusBlocks(radius)
|
||||||
|
.position(0)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
File SearchGenFile = new File(worldDirectory, "DeepSearch.json");
|
||||||
|
DeepSearchPregenerator pregenerator = new DeepSearchPregenerator(DeepSearchJob, SearchGenFile);
|
||||||
|
pregenerator.start();
|
||||||
|
|
||||||
|
String msg = C.GREEN + "DeepSearch started in " + C.GOLD + worldName + C.GREEN + " of " + C.GOLD + (radius * 2) + C.GREEN + " by " + C.GOLD + (radius * 2) + C.GREEN + " blocks from " + C.GOLD + center.getX() + "," + center.getZ();
|
||||||
|
sender().sendMessage(msg);
|
||||||
|
Iris.info(msg);
|
||||||
|
} catch (Throwable e) {
|
||||||
|
sender().sendMessage(C.RED + "Epic fail. See console.");
|
||||||
|
Iris.reportError(e);
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Decree(description = "Stop the active DeepSearch task", aliases = "x")
|
||||||
|
public void stop(@Param(aliases = "world", description = "The world to pause") World world) throws IOException {
|
||||||
|
DeepSearchPregenerator DeepSearchInstance = DeepSearchPregenerator.getInstance();
|
||||||
|
File worldDirectory = new File(Bukkit.getWorldContainer(), world.getName());
|
||||||
|
File turboFile = new File(worldDirectory, "DeepSearch.json");
|
||||||
|
|
||||||
|
if (DeepSearchInstance != null) {
|
||||||
|
DeepSearchInstance.shutdownInstance(world);
|
||||||
|
sender().sendMessage(C.LIGHT_PURPLE + "Closed Turbogen instance for " + world.getName());
|
||||||
|
} else if (turboFile.exists() && turboFile.delete()) {
|
||||||
|
sender().sendMessage(C.LIGHT_PURPLE + "Closed Turbogen instance for " + world.getName());
|
||||||
|
} else if (turboFile.exists()) {
|
||||||
|
Iris.error("Failed to delete the old instance file of Turbo Pregen!");
|
||||||
|
} else {
|
||||||
|
sender().sendMessage(C.YELLOW + "No active pregeneration tasks to stop");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Decree(description = "Pause / continue the active pregeneration task", aliases = {"t", "resume", "unpause"})
|
||||||
|
public void pause(
|
||||||
|
@Param(aliases = "world", description = "The world to pause")
|
||||||
|
World world
|
||||||
|
) {
|
||||||
|
if (TurboPregenerator.getInstance() != null) {
|
||||||
|
TurboPregenerator.setPausedTurbo(world);
|
||||||
|
sender().sendMessage(C.GREEN + "Paused/unpaused Turbo Pregen, now: " + (TurboPregenerator.isPausedTurbo(world) ? "Paused" : "Running") + ".");
|
||||||
|
} else {
|
||||||
|
File worldDirectory = new File(Bukkit.getWorldContainer(), world.getName());
|
||||||
|
File TurboFile = new File(worldDirectory, "DeepSearch.json");
|
||||||
|
if (TurboFile.exists()){
|
||||||
|
TurboPregenerator.loadTurboGenerator(world.getName());
|
||||||
|
sender().sendMessage(C.YELLOW + "Started DeepSearch back up!");
|
||||||
|
} else {
|
||||||
|
sender().sendMessage(C.YELLOW + "No active DeepSearch tasks to pause/unpause.");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,315 @@
|
|||||||
|
/*
|
||||||
|
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||||
|
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.volmit.iris.core.commands;
|
||||||
|
|
||||||
|
import com.volmit.iris.Iris;
|
||||||
|
import com.volmit.iris.core.ServerConfigurator;
|
||||||
|
import com.volmit.iris.core.loader.IrisData;
|
||||||
|
import com.volmit.iris.core.nms.datapack.DataVersion;
|
||||||
|
import com.volmit.iris.core.service.IrisEngineSVC;
|
||||||
|
import com.volmit.iris.core.tools.IrisPackBenchmarking;
|
||||||
|
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||||
|
import com.volmit.iris.engine.framework.Engine;
|
||||||
|
import com.volmit.iris.engine.object.IrisDimension;
|
||||||
|
import com.volmit.iris.util.decree.DecreeExecutor;
|
||||||
|
import com.volmit.iris.util.decree.DecreeOrigin;
|
||||||
|
import com.volmit.iris.util.decree.annotations.Decree;
|
||||||
|
import com.volmit.iris.util.decree.annotations.Param;
|
||||||
|
import com.volmit.iris.util.format.C;
|
||||||
|
import com.volmit.iris.util.format.Form;
|
||||||
|
import com.volmit.iris.util.io.CountingDataInputStream;
|
||||||
|
import com.volmit.iris.util.io.IO;
|
||||||
|
import com.volmit.iris.util.mantle.TectonicPlate;
|
||||||
|
import com.volmit.iris.util.nbt.mca.MCAFile;
|
||||||
|
import com.volmit.iris.util.nbt.mca.MCAUtil;
|
||||||
|
import com.volmit.iris.util.parallel.MultiBurst;
|
||||||
|
import com.volmit.iris.util.plugin.VolmitSender;
|
||||||
|
import net.jpountz.lz4.LZ4BlockInputStream;
|
||||||
|
import net.jpountz.lz4.LZ4BlockOutputStream;
|
||||||
|
import net.jpountz.lz4.LZ4FrameInputStream;
|
||||||
|
import net.jpountz.lz4.LZ4FrameOutputStream;
|
||||||
|
import org.apache.commons.lang.RandomStringUtils;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Chunk;
|
||||||
|
import org.bukkit.World;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.NetworkInterface;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import java.util.zip.GZIPInputStream;
|
||||||
|
import java.util.zip.GZIPOutputStream;
|
||||||
|
|
||||||
|
@Decree(name = "Developer", origin = DecreeOrigin.BOTH, description = "Iris World Manager", aliases = {"dev"})
|
||||||
|
public class CommandDeveloper implements DecreeExecutor {
|
||||||
|
private CommandTurboPregen turboPregen;
|
||||||
|
private CommandUpdater updater;
|
||||||
|
|
||||||
|
@Decree(description = "Get Loaded TectonicPlates Count", origin = DecreeOrigin.BOTH, sync = true)
|
||||||
|
public void EngineStatus() {
|
||||||
|
List<World> IrisWorlds = new ArrayList<>();
|
||||||
|
int TotalLoadedChunks = 0;
|
||||||
|
int TotalQueuedTectonicPlates = 0;
|
||||||
|
int TotalNotQueuedTectonicPlates = 0;
|
||||||
|
int TotalTectonicPlates = 0;
|
||||||
|
|
||||||
|
long lowestUnloadDuration = 0;
|
||||||
|
long highestUnloadDuration = 0;
|
||||||
|
|
||||||
|
for (World world : Bukkit.getWorlds()) {
|
||||||
|
try {
|
||||||
|
if (IrisToolbelt.access(world).getEngine() != null) {
|
||||||
|
IrisWorlds.add(world);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
// no
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (World world : IrisWorlds) {
|
||||||
|
Engine engine = IrisToolbelt.access(world).getEngine();
|
||||||
|
TotalQueuedTectonicPlates += (int) engine.getMantle().getToUnload();
|
||||||
|
TotalNotQueuedTectonicPlates += (int) engine.getMantle().getNotQueuedLoadedRegions();
|
||||||
|
TotalTectonicPlates += engine.getMantle().getLoadedRegionCount();
|
||||||
|
if (highestUnloadDuration <= (long) engine.getMantle().getTectonicDuration()) {
|
||||||
|
highestUnloadDuration = (long) engine.getMantle().getTectonicDuration();
|
||||||
|
}
|
||||||
|
if (lowestUnloadDuration >= (long) engine.getMantle().getTectonicDuration()) {
|
||||||
|
lowestUnloadDuration = (long) engine.getMantle().getTectonicDuration();
|
||||||
|
}
|
||||||
|
for (Chunk chunk : world.getLoadedChunks()) {
|
||||||
|
if (chunk.isLoaded()) {
|
||||||
|
TotalLoadedChunks++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Iris.info("-------------------------");
|
||||||
|
Iris.info(C.DARK_PURPLE + "Engine Status");
|
||||||
|
Iris.info(C.DARK_PURPLE + "Total Loaded Chunks: " + C.LIGHT_PURPLE + TotalLoadedChunks);
|
||||||
|
Iris.info(C.DARK_PURPLE + "Tectonic Limit: " + C.LIGHT_PURPLE + IrisEngineSVC.getTectonicLimit());
|
||||||
|
Iris.info(C.DARK_PURPLE + "Tectonic Total Plates: " + C.LIGHT_PURPLE + TotalTectonicPlates);
|
||||||
|
Iris.info(C.DARK_PURPLE + "Tectonic Active Plates: " + C.LIGHT_PURPLE + TotalNotQueuedTectonicPlates);
|
||||||
|
Iris.info(C.DARK_PURPLE + "Tectonic ToUnload: " + C.LIGHT_PURPLE + TotalQueuedTectonicPlates);
|
||||||
|
Iris.info(C.DARK_PURPLE + "Lowest Tectonic Unload Duration: " + C.LIGHT_PURPLE + Form.duration(lowestUnloadDuration));
|
||||||
|
Iris.info(C.DARK_PURPLE + "Highest Tectonic Unload Duration: " + C.LIGHT_PURPLE + Form.duration(highestUnloadDuration));
|
||||||
|
Iris.info(C.DARK_PURPLE + "Cache Size: " + C.LIGHT_PURPLE + Form.f(IrisData.cacheSize()));
|
||||||
|
Iris.info("-------------------------");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Decree(description = "Test")
|
||||||
|
public void benchmarkMantle(
|
||||||
|
@Param(description = "The world to bench", aliases = {"world"})
|
||||||
|
World world
|
||||||
|
) throws IOException, ClassNotFoundException {
|
||||||
|
Engine engine = IrisToolbelt.access(world).getEngine();
|
||||||
|
int maxHeight = engine.getTarget().getHeight();
|
||||||
|
File folder = new File(Bukkit.getWorldContainer(), world.getName());
|
||||||
|
int c = 0;
|
||||||
|
//MCAUtil.read()
|
||||||
|
|
||||||
|
File tectonicplates = new File(folder, "mantle");
|
||||||
|
for (File i : Objects.requireNonNull(tectonicplates.listFiles())) {
|
||||||
|
TectonicPlate.read(maxHeight, i);
|
||||||
|
c++;
|
||||||
|
Iris.info("Loaded count: " + c );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Decree(description = "Test")
|
||||||
|
public void packBenchmark(
|
||||||
|
@Param(description = "The pack to bench", aliases = {"pack"}, defaultValue = "overworld")
|
||||||
|
IrisDimension dimension,
|
||||||
|
@Param(description = "Radius in regions", defaultValue = "5")
|
||||||
|
int radius,
|
||||||
|
@Param(description = "Open GUI while benchmarking", defaultValue = "false")
|
||||||
|
boolean gui
|
||||||
|
) {
|
||||||
|
new IrisPackBenchmarking(dimension, radius, gui);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Decree(description = "Upgrade to another Minecraft version")
|
||||||
|
public void upgrade(
|
||||||
|
@Param(description = "The version to upgrade to", defaultValue = "latest") DataVersion version) {
|
||||||
|
sender().sendMessage(C.GREEN + "Upgrading to " + version.getVersion() + "...");
|
||||||
|
ServerConfigurator.installDataPacks(version.get(), false);
|
||||||
|
sender().sendMessage(C.GREEN + "Done upgrading! You can now update your server version to " + version.getVersion());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Decree(description = "test")
|
||||||
|
public void mca (
|
||||||
|
@Param(description = "String") String world) {
|
||||||
|
try {
|
||||||
|
File[] McaFiles = new File(world, "region").listFiles((dir, name) -> name.endsWith(".mca"));
|
||||||
|
for (File mca : McaFiles) {
|
||||||
|
MCAFile MCARegion = MCAUtil.read(mca);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Decree(description = "UnloadChunks for good reasons.")
|
||||||
|
public void unloadchunks() {
|
||||||
|
List<World> IrisWorlds = new ArrayList<>();
|
||||||
|
int chunksUnloaded = 0;
|
||||||
|
for (World world : Bukkit.getWorlds()) {
|
||||||
|
try {
|
||||||
|
if (IrisToolbelt.access(world).getEngine() != null) {
|
||||||
|
IrisWorlds.add(world);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
// no
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (World world : IrisWorlds) {
|
||||||
|
for (Chunk chunk : world.getLoadedChunks()) {
|
||||||
|
if (chunk.isLoaded()) {
|
||||||
|
chunk.unload();
|
||||||
|
chunksUnloaded++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Iris.info(C.IRIS + "Chunks Unloaded: " + chunksUnloaded);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Decree
|
||||||
|
public void objects(@Param(defaultValue = "overworld") IrisDimension dimension) {
|
||||||
|
var loader = dimension.getLoader().getObjectLoader();
|
||||||
|
var sender = sender();
|
||||||
|
var keys = loader.getPossibleKeys();
|
||||||
|
var burst = MultiBurst.burst.burst(keys.length);
|
||||||
|
AtomicInteger failed = new AtomicInteger();
|
||||||
|
for (String key : keys) {
|
||||||
|
burst.queue(() -> {
|
||||||
|
if (loader.load(key) == null)
|
||||||
|
failed.incrementAndGet();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
burst.complete();
|
||||||
|
sender.sendMessage(C.RED + "Failed to load " + failed.get() + " of " + keys.length + " objects");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Decree(description = "Test", aliases = {"ip"})
|
||||||
|
public void network() {
|
||||||
|
try {
|
||||||
|
Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
|
||||||
|
for (NetworkInterface ni : Collections.list(networkInterfaces)) {
|
||||||
|
Iris.info("Display Name: %s", ni.getDisplayName());
|
||||||
|
Enumeration<InetAddress> inetAddresses = ni.getInetAddresses();
|
||||||
|
for (InetAddress ia : Collections.list(inetAddresses)) {
|
||||||
|
Iris.info("IP: %s", ia.getHostAddress());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Decree(description = "Test the compression algorithms")
|
||||||
|
public void compression(
|
||||||
|
@Param(description = "base IrisWorld") World world,
|
||||||
|
@Param(description = "raw TectonicPlate File") String path,
|
||||||
|
@Param(description = "Algorithm to Test") String algorithm,
|
||||||
|
@Param(description = "Amount of Tests") int amount) {
|
||||||
|
if (!IrisToolbelt.isIrisWorld(world)) {
|
||||||
|
sender().sendMessage(C.RED + "This is not an Iris world. Iris worlds: " + String.join(", ", Bukkit.getServer().getWorlds().stream().filter(IrisToolbelt::isIrisWorld).map(World::getName).toList()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
File file = new File(path);
|
||||||
|
if (!file.exists()) return;
|
||||||
|
|
||||||
|
Engine engine = IrisToolbelt.access(world).getEngine();
|
||||||
|
if(engine != null) {
|
||||||
|
int height = engine.getTarget().getHeight();
|
||||||
|
ExecutorService service = Executors.newFixedThreadPool(1);
|
||||||
|
VolmitSender sender = sender();
|
||||||
|
service.submit(() -> {
|
||||||
|
try {
|
||||||
|
CountingDataInputStream raw = CountingDataInputStream.wrap(new FileInputStream(file));
|
||||||
|
TectonicPlate plate = new TectonicPlate(height, raw);
|
||||||
|
raw.close();
|
||||||
|
|
||||||
|
double d1 = 0;
|
||||||
|
double d2 = 0;
|
||||||
|
long size = 0;
|
||||||
|
File folder = new File("tmp");
|
||||||
|
folder.mkdirs();
|
||||||
|
for (int i = 0; i < amount; i++) {
|
||||||
|
File tmp = new File(folder, RandomStringUtils.randomAlphanumeric(10) + "." + algorithm + ".bin");
|
||||||
|
DataOutputStream dos = createOutput(tmp, algorithm);
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
plate.write(dos);
|
||||||
|
dos.close();
|
||||||
|
d1 += System.currentTimeMillis() - start;
|
||||||
|
if (size == 0)
|
||||||
|
size = tmp.length();
|
||||||
|
start = System.currentTimeMillis();
|
||||||
|
CountingDataInputStream din = createInput(tmp, algorithm);
|
||||||
|
new TectonicPlate(height, din);
|
||||||
|
din.close();
|
||||||
|
d2 += System.currentTimeMillis() - start;
|
||||||
|
tmp.delete();
|
||||||
|
}
|
||||||
|
IO.delete(folder);
|
||||||
|
sender.sendMessage(algorithm + " is " + Form.fileSize(size) + " big after compression");
|
||||||
|
sender.sendMessage(algorithm + " Took " + d2/amount + "ms to read");
|
||||||
|
sender.sendMessage(algorithm + " Took " + d1/amount + "ms to write");
|
||||||
|
} catch (Throwable e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
service.shutdown();
|
||||||
|
} else {
|
||||||
|
Iris.info(C.RED + "Engine is null!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private CountingDataInputStream createInput(File file, String algorithm) throws Throwable {
|
||||||
|
FileInputStream in = new FileInputStream(file);
|
||||||
|
|
||||||
|
return CountingDataInputStream.wrap(switch (algorithm) {
|
||||||
|
case "gzip" -> new GZIPInputStream(in);
|
||||||
|
case "lz4f" -> new LZ4FrameInputStream(in);
|
||||||
|
case "lz4b" -> new LZ4BlockInputStream(in);
|
||||||
|
default -> throw new IllegalStateException("Unexpected value: " + algorithm);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private DataOutputStream createOutput(File file, String algorithm) throws Throwable {
|
||||||
|
FileOutputStream out = new FileOutputStream(file);
|
||||||
|
|
||||||
|
return new DataOutputStream(switch (algorithm) {
|
||||||
|
case "gzip" -> new GZIPOutputStream(out);
|
||||||
|
case "lz4f" -> new LZ4FrameOutputStream(out);
|
||||||
|
case "lz4b" -> new LZ4BlockOutputStream(out);
|
||||||
|
default -> throw new IllegalStateException("Unexpected value: " + algorithm);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -34,7 +34,9 @@ public class CommandFind implements DecreeExecutor {
|
|||||||
@Decree(description = "Find a biome")
|
@Decree(description = "Find a biome")
|
||||||
public void biome(
|
public void biome(
|
||||||
@Param(description = "The biome to look for")
|
@Param(description = "The biome to look for")
|
||||||
IrisBiome biome
|
IrisBiome biome,
|
||||||
|
@Param(description = "Should you be teleported", defaultValue = "true")
|
||||||
|
boolean teleport
|
||||||
) {
|
) {
|
||||||
Engine e = engine();
|
Engine e = engine();
|
||||||
|
|
||||||
@@ -43,13 +45,15 @@ public class CommandFind implements DecreeExecutor {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
e.gotoBiome(biome, player());
|
e.gotoBiome(biome, player(), teleport);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Decree(description = "Find a region")
|
@Decree(description = "Find a region")
|
||||||
public void region(
|
public void region(
|
||||||
@Param(description = "The region to look for")
|
@Param(description = "The region to look for")
|
||||||
IrisRegion region
|
IrisRegion region,
|
||||||
|
@Param(description = "Should you be teleported", defaultValue = "true")
|
||||||
|
boolean teleport
|
||||||
) {
|
) {
|
||||||
Engine e = engine();
|
Engine e = engine();
|
||||||
|
|
||||||
@@ -58,13 +62,15 @@ public class CommandFind implements DecreeExecutor {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
e.gotoRegion(region, player());
|
e.gotoRegion(region, player(), teleport);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Decree(description = "Find a structure")
|
@Decree(description = "Find a structure")
|
||||||
public void structure(
|
public void structure(
|
||||||
@Param(description = "The structure to look for")
|
@Param(description = "The structure to look for")
|
||||||
IrisJigsawStructure structure
|
IrisJigsawStructure structure,
|
||||||
|
@Param(description = "Should you be teleported", defaultValue = "true")
|
||||||
|
boolean teleport
|
||||||
) {
|
) {
|
||||||
Engine e = engine();
|
Engine e = engine();
|
||||||
|
|
||||||
@@ -73,13 +79,15 @@ public class CommandFind implements DecreeExecutor {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
e.gotoJigsaw(structure, player());
|
e.gotoJigsaw(structure, player(), teleport);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Decree(description = "Find a point of interest.")
|
@Decree(description = "Find a point of interest.")
|
||||||
public void poi(
|
public void poi(
|
||||||
@Param(description = "The type of PoI to look for.")
|
@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();
|
Engine e = engine();
|
||||||
if (e == null) {
|
if (e == null) {
|
||||||
@@ -87,13 +95,15 @@ public class CommandFind implements DecreeExecutor {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
e.gotoPOI(type, player());
|
e.gotoPOI(type, player(), teleport);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Decree(description = "Find an object")
|
@Decree(description = "Find an object")
|
||||||
public void object(
|
public void object(
|
||||||
@Param(description = "The object to look for", customHandler = ObjectHandler.class)
|
@Param(description = "The object to look for", customHandler = ObjectHandler.class)
|
||||||
String object
|
String object,
|
||||||
|
@Param(description = "Should you be teleported", defaultValue = "true")
|
||||||
|
boolean teleport
|
||||||
) {
|
) {
|
||||||
Engine e = engine();
|
Engine e = engine();
|
||||||
|
|
||||||
@@ -102,6 +112,6 @@ public class CommandFind implements DecreeExecutor {
|
|||||||
return;
|
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.Iris;
|
||||||
import com.volmit.iris.core.IrisSettings;
|
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.service.StudioSVC;
|
||||||
import com.volmit.iris.core.tools.IrisBenchmarking;
|
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.core.tools.IrisToolbelt;
|
||||||
import com.volmit.iris.engine.framework.Engine;
|
import com.volmit.iris.engine.framework.Engine;
|
||||||
import com.volmit.iris.engine.object.IrisDimension;
|
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.object.IrisWorld;
|
||||||
import com.volmit.iris.engine.platform.PlatformChunkGenerator;
|
import com.volmit.iris.engine.platform.BukkitChunkGenerator;
|
||||||
import com.volmit.iris.engine.safeguard.UtilsSFG;
|
import com.volmit.iris.engine.platform.DummyChunkGenerator;
|
||||||
import com.volmit.iris.util.collection.KList;
|
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.DecreeExecutor;
|
||||||
import com.volmit.iris.util.decree.DecreeOrigin;
|
import com.volmit.iris.util.decree.DecreeOrigin;
|
||||||
import com.volmit.iris.util.decree.annotations.Decree;
|
import com.volmit.iris.util.decree.annotations.Decree;
|
||||||
@@ -38,42 +41,51 @@ import com.volmit.iris.util.decree.annotations.Param;
|
|||||||
import com.volmit.iris.util.decree.specialhandlers.NullablePlayerHandler;
|
import com.volmit.iris.util.decree.specialhandlers.NullablePlayerHandler;
|
||||||
import com.volmit.iris.util.format.C;
|
import com.volmit.iris.util.format.C;
|
||||||
import com.volmit.iris.util.format.Form;
|
import com.volmit.iris.util.format.Form;
|
||||||
import com.volmit.iris.util.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.plugin.VolmitSender;
|
||||||
import com.volmit.iris.util.scheduling.J;
|
import com.volmit.iris.util.scheduling.J;
|
||||||
import com.volmit.iris.util.scheduling.jobs.QueueJob;
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Chunk;
|
import org.bukkit.Difficulty;
|
||||||
import org.bukkit.World;
|
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.entity.Player;
|
||||||
|
import org.bukkit.generator.ChunkGenerator;
|
||||||
import org.bukkit.scheduler.BukkitRunnable;
|
import org.bukkit.scheduler.BukkitRunnable;
|
||||||
|
|
||||||
|
import java.io.Console;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.ArrayList;
|
||||||
import java.util.concurrent.Future;
|
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.service.EditSVC.deletingWorld;
|
||||||
import static com.volmit.iris.core.tools.IrisBenchmarking.inProgress;
|
import static com.volmit.iris.core.tools.IrisBenchmarking.inProgress;
|
||||||
import static com.volmit.iris.engine.safeguard.IrisSafeguard.unstablemode;
|
import static com.volmit.iris.core.safeguard.IrisSafeguard.unstablemode;
|
||||||
import static com.volmit.iris.engine.safeguard.ServerBootSFG.incompatiblePlugins;
|
import static com.volmit.iris.core.safeguard.ServerBootSFG.incompatibilities;
|
||||||
|
import static org.bukkit.Bukkit.getServer;
|
||||||
|
|
||||||
@Decree(name = "iris", aliases = {"ir", "irs"}, description = "Basic Command")
|
@Decree(name = "iris", aliases = {"ir", "irs"}, description = "Basic Command")
|
||||||
public class CommandIris implements DecreeExecutor {
|
public class CommandIris implements DecreeExecutor {
|
||||||
private CommandStudio studio;
|
private CommandStudio studio;
|
||||||
private CommandPregen pregen;
|
private CommandPregen pregen;
|
||||||
|
private CommandLazyPregen lazyPregen;
|
||||||
private CommandSettings settings;
|
private CommandSettings settings;
|
||||||
private CommandObject object;
|
private CommandObject object;
|
||||||
private CommandJigsaw jigsaw;
|
private CommandJigsaw jigsaw;
|
||||||
private CommandWhat what;
|
private CommandWhat what;
|
||||||
private CommandEdit edit;
|
private CommandEdit edit;
|
||||||
private CommandFind find;
|
private CommandFind find;
|
||||||
private CommandWorldManager manager;
|
private CommandSupport support;
|
||||||
|
private CommandDeveloper developer;
|
||||||
public static @Getter String BenchDimension;
|
public static boolean worldCreation = false;
|
||||||
|
String WorldEngine;
|
||||||
|
String worldNameToCheck = "YourWorldName";
|
||||||
|
VolmitSender sender = Iris.getSender();
|
||||||
|
|
||||||
@Decree(description = "Create a new world", aliases = {"+", "c"})
|
@Decree(description = "Create a new world", aliases = {"+", "c"})
|
||||||
public void create(
|
public void create(
|
||||||
@@ -82,10 +94,12 @@ public class CommandIris implements DecreeExecutor {
|
|||||||
@Param(aliases = "dimension", description = "The dimension type to create the world with", defaultValue = "default")
|
@Param(aliases = "dimension", description = "The dimension type to create the world with", defaultValue = "default")
|
||||||
IrisDimension type,
|
IrisDimension type,
|
||||||
@Param(description = "The seed to generate the world with", defaultValue = "1337")
|
@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(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 + "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 + "it is strongly advised for you to take action. see log for full detail");
|
||||||
sender().sendMessage(C.RED + "----------------------------------------------------------------");
|
sender().sendMessage(C.RED + "----------------------------------------------------------------");
|
||||||
@@ -93,7 +107,7 @@ public class CommandIris implements DecreeExecutor {
|
|||||||
sender().sendMessage(C.RED + UtilsSFG.MSGIncompatibleWarnings());
|
sender().sendMessage(C.RED + UtilsSFG.MSGIncompatibleWarnings());
|
||||||
sender().sendMessage(C.RED + "----------------------------------------------------------------");
|
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 + "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 + "Please rectify this problem to avoid further complications.");
|
||||||
sender().sendMessage(C.RED + "----------------------------------------------------------------");
|
sender().sendMessage(C.RED + "----------------------------------------------------------------");
|
||||||
@@ -119,20 +133,23 @@ public class CommandIris implements DecreeExecutor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
worldCreation = true;
|
||||||
IrisToolbelt.createWorld()
|
IrisToolbelt.createWorld()
|
||||||
.dimension(type.getLoadKey())
|
.dimension(type.getLoadKey())
|
||||||
.name(name)
|
.name(name)
|
||||||
.seed(seed)
|
.seed(seed)
|
||||||
.sender(sender())
|
.sender(sender())
|
||||||
.studio(false)
|
.studio(false)
|
||||||
|
.smartVanillaHeight(vanillaheight)
|
||||||
.create();
|
.create();
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
sender().sendMessage(C.RED + "Exception raised during creation. See the console for more details.");
|
sender().sendMessage(C.RED + "Exception raised during creation. See the console for more details.");
|
||||||
Iris.error("Exception raised during world creation: " + e.getMessage());
|
Iris.error("Exception raised during world creation: " + e.getMessage());
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
|
worldCreation = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
worldCreation = false;
|
||||||
sender().sendMessage(C.GREEN + "Successfully created your world!");
|
sender().sendMessage(C.GREEN + "Successfully created your world!");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,6 +182,8 @@ public class CommandIris implements DecreeExecutor {
|
|||||||
public void version() {
|
public void version() {
|
||||||
sender().sendMessage(C.GREEN + "Iris v" + Iris.instance.getDescription().getVersion() + " by Volmit Software");
|
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)
|
@Decree(description = "Benchmark your server", origin = DecreeOrigin.CONSOLE)
|
||||||
public void serverbenchmark() throws InterruptedException {
|
public void serverbenchmark() throws InterruptedException {
|
||||||
if(!inProgress) {
|
if(!inProgress) {
|
||||||
@@ -173,8 +192,9 @@ public class CommandIris implements DecreeExecutor {
|
|||||||
Iris.info(C.RED + "Benchmark already is in progress.");
|
Iris.info(C.RED + "Benchmark already is in progress.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
/todo Fix PREGEN
|
/todo
|
||||||
@Decree(description = "Benchmark a pack", origin = DecreeOrigin.CONSOLE)
|
@Decree(description = "Benchmark a pack", origin = DecreeOrigin.CONSOLE)
|
||||||
public void packbenchmark(
|
public void packbenchmark(
|
||||||
@Param(description = "Dimension to benchmark")
|
@Param(description = "Dimension to benchmark")
|
||||||
@@ -186,28 +206,16 @@ public class CommandIris implements DecreeExecutor {
|
|||||||
IrisPackBenchmarking.runBenchmark();
|
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)
|
@Decree(description = "Print world height information", origin = DecreeOrigin.PLAYER)
|
||||||
public void height() {
|
public void height() {
|
||||||
sender().sendMessage(C.GREEN + "" + sender().player().getWorld().getMinHeight() + " to " + sender().player().getWorld().getMaxHeight());
|
if (sender().isPlayer()) {
|
||||||
sender().sendMessage(C.GREEN + "Total Height: " + (sender().player().getWorld().getMaxHeight() - sender().player().getWorld().getMinHeight()));
|
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)
|
@Decree(description = "QOL command to open a overworld studio world.", sync = true)
|
||||||
@@ -216,6 +224,44 @@ public class CommandIris implements DecreeExecutor {
|
|||||||
Iris.service(StudioSVC.class).open(sender(), 1337, "overworld");
|
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)
|
@Decree(description = "Remove an Iris world", aliases = {"del", "rm", "delete"}, sync = true)
|
||||||
public void remove(
|
public void remove(
|
||||||
@Param(description = "The world to remove")
|
@Param(description = "The world to remove")
|
||||||
@@ -224,7 +270,7 @@ public class CommandIris implements DecreeExecutor {
|
|||||||
boolean delete
|
boolean delete
|
||||||
) {
|
) {
|
||||||
if (!IrisToolbelt.isIrisWorld(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()));
|
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;
|
return;
|
||||||
}
|
}
|
||||||
sender().sendMessage(C.GREEN + "Removing world: " + world.getName());
|
sender().sendMessage(C.GREEN + "Removing world: " + world.getName());
|
||||||
@@ -241,7 +287,7 @@ public class CommandIris implements DecreeExecutor {
|
|||||||
IrisToolbelt.evacuate(world, "Deleting world");
|
IrisToolbelt.evacuate(world, "Deleting world");
|
||||||
deletingWorld = true;
|
deletingWorld = true;
|
||||||
Bukkit.unloadWorld(world, false);
|
Bukkit.unloadWorld(world, false);
|
||||||
int retries = 10;
|
int retries = 12;
|
||||||
if (delete) {
|
if (delete) {
|
||||||
if (deleteDirectory(world.getWorldFolder())) {
|
if (deleteDirectory(world.getWorldFolder())) {
|
||||||
sender().sendMessage(C.GREEN + "Successfully removed world folder");
|
sender().sendMessage(C.GREEN + "Successfully removed world folder");
|
||||||
@@ -251,13 +297,12 @@ public class CommandIris implements DecreeExecutor {
|
|||||||
sender().sendMessage(C.GREEN + "Successfully removed world folder");
|
sender().sendMessage(C.GREEN + "Successfully removed world folder");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
sender().sendMessage(C.GREEN + "DEBUG1");
|
|
||||||
retries--;
|
retries--;
|
||||||
if (retries == 0){
|
if (retries == 0){
|
||||||
sender().sendMessage(C.RED + "Failed to remove world folder");
|
sender().sendMessage(C.RED + "Failed to remove world folder");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
J.sleep(2000);
|
J.sleep(3000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -277,6 +322,24 @@ public class CommandIris implements DecreeExecutor {
|
|||||||
return dir.delete();
|
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")
|
@Decree(description = "Set aura spins")
|
||||||
public void aura(
|
public void aura(
|
||||||
@Param(description = "The h color value", defaultValue = "-20")
|
@Param(description = "The h color value", defaultValue = "-20")
|
||||||
@@ -366,77 +429,6 @@ public class CommandIris implements DecreeExecutor {
|
|||||||
sender().sendMessage(C.GREEN + "Hotloaded settings");
|
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")
|
@Decree(description = "Update the pack of a world (UNSAFE!)", name = "^world", aliases = "update-world")
|
||||||
public void updateWorld(
|
public void updateWorld(
|
||||||
@Param(description = "The world to update", contextual = true)
|
@Param(description = "The world to update", contextual = true)
|
||||||
@@ -472,4 +464,191 @@ public class CommandIris implements DecreeExecutor {
|
|||||||
|
|
||||||
Iris.service(StudioSVC.class).installIntoWorld(sender(), pack.getLoadKey(), folder);
|
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.Iris;
|
||||||
import com.volmit.iris.core.edit.JigsawEditor;
|
import com.volmit.iris.core.edit.JigsawEditor;
|
||||||
import com.volmit.iris.core.loader.IrisData;
|
import com.volmit.iris.core.loader.IrisData;
|
||||||
|
import com.volmit.iris.engine.framework.placer.WorldObjectPlacer;
|
||||||
import com.volmit.iris.engine.jigsaw.PlannedStructure;
|
import com.volmit.iris.engine.jigsaw.PlannedStructure;
|
||||||
import com.volmit.iris.engine.object.IrisJigsawPiece;
|
import com.volmit.iris.engine.object.IrisJigsawPiece;
|
||||||
import com.volmit.iris.engine.object.IrisJigsawStructure;
|
import com.volmit.iris.engine.object.IrisJigsawStructure;
|
||||||
@@ -34,6 +35,7 @@ import com.volmit.iris.util.decree.specialhandlers.ObjectHandler;
|
|||||||
import com.volmit.iris.util.format.C;
|
import com.volmit.iris.util.format.C;
|
||||||
import com.volmit.iris.util.format.Form;
|
import com.volmit.iris.util.format.Form;
|
||||||
import com.volmit.iris.util.math.RNG;
|
import com.volmit.iris.util.math.RNG;
|
||||||
|
import com.volmit.iris.util.plugin.VolmitSender;
|
||||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@@ -55,9 +57,16 @@ public class CommandJigsaw implements DecreeExecutor {
|
|||||||
IrisJigsawStructure structure
|
IrisJigsawStructure structure
|
||||||
) {
|
) {
|
||||||
PrecisionStopwatch p = PrecisionStopwatch.start();
|
PrecisionStopwatch p = PrecisionStopwatch.start();
|
||||||
PlannedStructure ps = new PlannedStructure(structure, new IrisPosition(player().getLocation()), new RNG());
|
try {
|
||||||
sender().sendMessage(C.GREEN + "Generated " + ps.getPieces().size() + " pieces in " + Form.duration(p.getMilliseconds(), 2));
|
var world = world();
|
||||||
ps.place(world());
|
WorldObjectPlacer placer = new WorldObjectPlacer(world);
|
||||||
|
PlannedStructure ps = new PlannedStructure(structure, new IrisPosition(player().getLocation().add(0, world.getMinHeight(), 0)), new RNG(), true);
|
||||||
|
VolmitSender sender = sender();
|
||||||
|
sender.sendMessage(C.GREEN + "Generated " + ps.getPieces().size() + " pieces in " + Form.duration(p.getMilliseconds(), 2));
|
||||||
|
ps.place(placer, failed -> sender.sendMessage(failed ? C.GREEN + "Placed the structure!" : C.RED + "Failed to place the structure!"));
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
sender().sendMessage(C.RED + "Failed to place the structure: " + e.getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Decree(description = "Create a jigsaw piece")
|
@Decree(description = "Create a jigsaw piece")
|
||||||
|
|||||||
@@ -0,0 +1,121 @@
|
|||||||
|
/*
|
||||||
|
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||||
|
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.volmit.iris.core.commands;
|
||||||
|
|
||||||
|
import com.volmit.iris.Iris;
|
||||||
|
import com.volmit.iris.core.IrisSettings;
|
||||||
|
import com.volmit.iris.core.gui.PregeneratorJob;
|
||||||
|
import com.volmit.iris.core.pregenerator.LazyPregenerator;
|
||||||
|
import com.volmit.iris.core.pregenerator.PregenTask;
|
||||||
|
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||||
|
import com.volmit.iris.util.decree.DecreeExecutor;
|
||||||
|
import com.volmit.iris.util.decree.annotations.Decree;
|
||||||
|
import com.volmit.iris.util.decree.annotations.Param;
|
||||||
|
import com.volmit.iris.util.format.C;
|
||||||
|
import com.volmit.iris.util.math.Position2;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@Decree(name = "lazypregen", aliases = "lazy", description = "Pregenerate your Iris worlds!")
|
||||||
|
public class CommandLazyPregen implements DecreeExecutor {
|
||||||
|
public String worldName;
|
||||||
|
@Decree(description = "Pregenerate a world")
|
||||||
|
public void start(
|
||||||
|
@Param(description = "The radius of the pregen in blocks", aliases = "size")
|
||||||
|
int radius,
|
||||||
|
@Param(description = "The world to pregen", contextual = true)
|
||||||
|
World world,
|
||||||
|
@Param(aliases = "middle", description = "The center location of the pregen. Use \"me\" for your current location", defaultValue = "0,0")
|
||||||
|
Vector center,
|
||||||
|
@Param(aliases = "maxcpm", description = "Limit the chunks per minute the pregen will generate", defaultValue = "999999999")
|
||||||
|
int cpm,
|
||||||
|
@Param(aliases = "silent", description = "Silent generation", defaultValue = "false")
|
||||||
|
boolean silent
|
||||||
|
) {
|
||||||
|
|
||||||
|
worldName = world.getName();
|
||||||
|
File worldDirectory = new File(Bukkit.getWorldContainer(), world.getName());
|
||||||
|
File lazyFile = new File(worldDirectory, "lazygen.json");
|
||||||
|
if (lazyFile.exists()) {
|
||||||
|
sender().sendMessage(C.BLUE + "Lazy pregen is already in progress");
|
||||||
|
Iris.info(C.YELLOW + "Lazy pregen is already in progress");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (sender().isPlayer() && access() == null) {
|
||||||
|
sender().sendMessage(C.RED + "The engine access for this world is null!");
|
||||||
|
sender().sendMessage(C.RED + "Please make sure the world is loaded & the engine is initialized. Generate a new chunk, for example.");
|
||||||
|
}
|
||||||
|
|
||||||
|
LazyPregenerator.LazyPregenJob pregenJob = LazyPregenerator.LazyPregenJob.builder()
|
||||||
|
.world(worldName)
|
||||||
|
.healingPosition(0)
|
||||||
|
.healing(false)
|
||||||
|
.chunksPerMinute(cpm)
|
||||||
|
.radiusBlocks(radius)
|
||||||
|
.position(0)
|
||||||
|
.silent(silent)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
File lazyGenFile = new File(worldDirectory, "lazygen.json");
|
||||||
|
LazyPregenerator pregenerator = new LazyPregenerator(pregenJob, lazyGenFile);
|
||||||
|
pregenerator.start();
|
||||||
|
|
||||||
|
String msg = C.GREEN + "LazyPregen started in " + C.GOLD + worldName + C.GREEN + " of " + C.GOLD + (radius * 2) + C.GREEN + " by " + C.GOLD + (radius * 2) + C.GREEN + " blocks from " + C.GOLD + center.getX() + "," + center.getZ();
|
||||||
|
sender().sendMessage(msg);
|
||||||
|
Iris.info(msg);
|
||||||
|
} catch (Throwable e) {
|
||||||
|
sender().sendMessage(C.RED + "Epic fail. See console.");
|
||||||
|
Iris.reportError(e);
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Decree(description = "Stop the active pregeneration task", aliases = "x")
|
||||||
|
public void stop(
|
||||||
|
@Param(aliases = "world", description = "The world to pause")
|
||||||
|
World world
|
||||||
|
) throws IOException {
|
||||||
|
if (LazyPregenerator.getInstance() != null) {
|
||||||
|
LazyPregenerator.getInstance().shutdownInstance(world);
|
||||||
|
sender().sendMessage(C.LIGHT_PURPLE + "Closed lazygen instance for " + world.getName());
|
||||||
|
} else {
|
||||||
|
sender().sendMessage(C.YELLOW + "No active pregeneration tasks to stop");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Decree(description = "Pause / continue the active pregeneration task", aliases = {"t", "resume", "unpause"})
|
||||||
|
public void pause(
|
||||||
|
@Param(aliases = "world", description = "The world to pause")
|
||||||
|
World world
|
||||||
|
) {
|
||||||
|
if (LazyPregenerator.getInstance() != null) {
|
||||||
|
LazyPregenerator.getInstance().setPausedLazy(world);
|
||||||
|
sender().sendMessage(C.GREEN + "Paused/unpaused Lazy Pregen, now: " + (LazyPregenerator.getInstance().isPausedLazy(world) ? "Paused" : "Running") + ".");
|
||||||
|
} else {
|
||||||
|
sender().sendMessage(C.YELLOW + "No active Lazy Pregen tasks to pause/unpause.");
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -24,6 +24,7 @@ import com.volmit.iris.core.loader.IrisData;
|
|||||||
import com.volmit.iris.core.service.ObjectSVC;
|
import com.volmit.iris.core.service.ObjectSVC;
|
||||||
import com.volmit.iris.core.service.StudioSVC;
|
import com.volmit.iris.core.service.StudioSVC;
|
||||||
import com.volmit.iris.core.service.WandSVC;
|
import com.volmit.iris.core.service.WandSVC;
|
||||||
|
import com.volmit.iris.core.tools.IrisConverter;
|
||||||
import com.volmit.iris.engine.framework.Engine;
|
import com.volmit.iris.engine.framework.Engine;
|
||||||
import com.volmit.iris.engine.object.*;
|
import com.volmit.iris.engine.object.*;
|
||||||
import com.volmit.iris.util.data.Cuboid;
|
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.format.C;
|
||||||
import com.volmit.iris.util.math.Direction;
|
import com.volmit.iris.util.math.Direction;
|
||||||
import com.volmit.iris.util.math.RNG;
|
import com.volmit.iris.util.math.RNG;
|
||||||
|
import com.volmit.iris.util.misc.E;
|
||||||
import com.volmit.iris.util.scheduling.Queue;
|
import com.volmit.iris.util.scheduling.Queue;
|
||||||
import org.bukkit.*;
|
import org.bukkit.*;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
@@ -52,7 +54,7 @@ import java.util.*;
|
|||||||
@Decree(name = "object", aliases = "o", origin = DecreeOrigin.PLAYER, studio = true, description = "Iris object manipulation")
|
@Decree(name = "object", aliases = "o", origin = DecreeOrigin.PLAYER, studio = true, description = "Iris object manipulation")
|
||||||
public class CommandObject implements DecreeExecutor {
|
public class CommandObject implements DecreeExecutor {
|
||||||
|
|
||||||
private static final Set<Material> skipBlocks = Set.of(Material.GRASS, Material.SNOW, Material.VINE, Material.TORCH, Material.DEAD_BUSH,
|
private static final Set<Material> skipBlocks = Set.of(E.getOrDefault(Material.class, "GRASS", "SHORT_GRASS"), Material.SNOW, Material.VINE, Material.TORCH, Material.DEAD_BUSH,
|
||||||
Material.POPPY, Material.DANDELION);
|
Material.POPPY, Material.DANDELION);
|
||||||
|
|
||||||
public static IObjectPlacer createPlacer(World world, Map<Block, BlockData> futureBlockChanges) {
|
public static IObjectPlacer createPlacer(World world, Map<Block, BlockData> futureBlockChanges) {
|
||||||
@@ -116,10 +118,8 @@ public class CommandObject implements DecreeExecutor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setTile(int xx, int yy, int zz, TileData<? extends TileState> tile) {
|
public void setTile(int xx, int yy, int zz, TileData tile) {
|
||||||
BlockState state = world.getBlockAt(xx, yy, zz).getState();
|
tile.toBukkitTry(world.getBlockAt(xx, yy, zz));
|
||||||
tile.toBukkitTry(state);
|
|
||||||
state.update();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -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")
|
@Decree(description = "Get a powder that reveals objects", studio = true, aliases = "d")
|
||||||
public void dust() {
|
public void dust() {
|
||||||
player().getInventory().addItem(WandSVC.createDust());
|
player().getInventory().addItem(WandSVC.createDust());
|
||||||
@@ -352,9 +376,11 @@ public class CommandObject implements DecreeExecutor {
|
|||||||
@Param(description = "The file to store it in, can use / for subfolders")
|
@Param(description = "The file to store it in, can use / for subfolders")
|
||||||
String name,
|
String name,
|
||||||
@Param(description = "Overwrite existing object files", defaultValue = "false", aliases = "force")
|
@Param(description = "Overwrite existing object files", defaultValue = "false", aliases = "force")
|
||||||
boolean overwrite
|
boolean overwrite,
|
||||||
|
@Param(description = "Use legacy TileState serialization if possible", defaultValue = "true")
|
||||||
|
boolean legacy
|
||||||
) {
|
) {
|
||||||
IrisObject o = WandSVC.createSchematic(player());
|
IrisObject o = WandSVC.createSchematic(player(), legacy);
|
||||||
|
|
||||||
if (o == null) {
|
if (o == null) {
|
||||||
sender().sendMessage(C.YELLOW + "You need to hold your wand!");
|
sender().sendMessage(C.YELLOW + "You need to hold your wand!");
|
||||||
@@ -368,7 +394,7 @@ public class CommandObject implements DecreeExecutor {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
o.write(file);
|
o.write(file, sender());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
sender().sendMessage(C.RED + "Failed to save object because of an IOException: " + e.getMessage());
|
sender().sendMessage(C.RED + "Failed to save object because of an IOException: " + e.getMessage());
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
package com.volmit.iris.core.commands;
|
package com.volmit.iris.core.commands;
|
||||||
|
|
||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.Iris;
|
||||||
|
import com.volmit.iris.core.IrisSettings;
|
||||||
import com.volmit.iris.core.gui.PregeneratorJob;
|
import com.volmit.iris.core.gui.PregeneratorJob;
|
||||||
import com.volmit.iris.core.pregenerator.LazyPregenerator;
|
import com.volmit.iris.core.pregenerator.LazyPregenerator;
|
||||||
import com.volmit.iris.core.pregenerator.PregenTask;
|
import com.volmit.iris.core.pregenerator.PregenTask;
|
||||||
@@ -43,75 +44,36 @@ public class CommandPregen implements DecreeExecutor {
|
|||||||
@Param(description = "The world to pregen", contextual = true)
|
@Param(description = "The world to pregen", contextual = true)
|
||||||
World world,
|
World world,
|
||||||
@Param(aliases = "middle", description = "The center location of the pregen. Use \"me\" for your current location", defaultValue = "0,0")
|
@Param(aliases = "middle", description = "The center location of the pregen. Use \"me\" for your current location", defaultValue = "0,0")
|
||||||
Vector center,
|
Vector center
|
||||||
@Param(aliases = "method", description = "The pregen method that will get used. Lazy or Async", defaultValue = "async")
|
) {
|
||||||
String method
|
try {
|
||||||
) {
|
if (sender().isPlayer() && access() == null) {
|
||||||
if(method.equals("async") || method.equals("lazy")){
|
sender().sendMessage(C.RED + "The engine access for this world is null!");
|
||||||
if (method.equalsIgnoreCase("async")) {
|
sender().sendMessage(C.RED + "Please make sure the world is loaded & the engine is initialized. Generate a new chunk, for example.");
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (method.equalsIgnoreCase("lazy")) {
|
radius = Math.max(radius, 1024);
|
||||||
String worldName = world.getName();
|
int w = (radius >> 9 + 1) * 2;
|
||||||
try {
|
IrisToolbelt.pregenerate(PregenTask
|
||||||
if (sender().isPlayer() && access() == null) {
|
.builder()
|
||||||
sender().sendMessage(C.RED + "The engine access for this world is null!");
|
.center(new Position2(center.getBlockX() >> 9, center.getBlockZ() >> 9))
|
||||||
sender().sendMessage(C.RED + "Please make sure the world is loaded & the engine is initialized. Generate a new chunk, for example.");
|
.gui(true)
|
||||||
}
|
.width(w)
|
||||||
|
.height(w)
|
||||||
LazyPregenerator.LazyPregenJob pregenJob = LazyPregenerator.LazyPregenJob.builder()
|
.build(), world);
|
||||||
.world(worldName)
|
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();
|
||||||
.healingPosition(0)
|
sender().sendMessage(msg);
|
||||||
.healing(false)
|
Iris.info(msg);
|
||||||
.chunksPerMinute(999999999)
|
} catch (Throwable e) {
|
||||||
.radiusBlocks(radius)
|
sender().sendMessage(C.RED + "Epic fail. See console.");
|
||||||
.position(0)
|
Iris.reportError(e);
|
||||||
.build();
|
e.printStackTrace();
|
||||||
|
|
||||||
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.");
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Decree(description = "Stop the active pregeneration task", aliases = "x")
|
@Decree(description = "Stop the active pregeneration task", aliases = "x")
|
||||||
public void stop() {
|
public void stop() {
|
||||||
if (PregeneratorJob.shutdownInstance()) {
|
if (PregeneratorJob.shutdownInstance()) {
|
||||||
Iris.info( C.BLUE + "Finishing up mca region...");
|
Iris.info( C.BLUE + "Finishing up mca region...");
|
||||||
sender().sendMessage(C.DARK_BLUE + "Stopped pregeneration task");
|
|
||||||
} else {
|
} else {
|
||||||
sender().sendMessage(C.YELLOW + "No active pregeneration tasks to stop");
|
sender().sendMessage(C.YELLOW + "No active pregeneration tasks to stop");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,9 +29,11 @@ import com.volmit.iris.core.service.StudioSVC;
|
|||||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||||
import com.volmit.iris.engine.framework.Engine;
|
import com.volmit.iris.engine.framework.Engine;
|
||||||
import com.volmit.iris.engine.object.*;
|
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.KList;
|
||||||
import com.volmit.iris.util.collection.KMap;
|
import com.volmit.iris.util.collection.KMap;
|
||||||
import com.volmit.iris.util.collection.KSet;
|
import com.volmit.iris.util.collection.KSet;
|
||||||
|
import com.volmit.iris.util.decree.DecreeContext;
|
||||||
import com.volmit.iris.util.decree.DecreeExecutor;
|
import com.volmit.iris.util.decree.DecreeExecutor;
|
||||||
import com.volmit.iris.util.decree.DecreeOrigin;
|
import com.volmit.iris.util.decree.DecreeOrigin;
|
||||||
import com.volmit.iris.util.decree.annotations.Decree;
|
import com.volmit.iris.util.decree.annotations.Decree;
|
||||||
@@ -45,11 +47,17 @@ import com.volmit.iris.util.io.IO;
|
|||||||
import com.volmit.iris.util.json.JSONArray;
|
import com.volmit.iris.util.json.JSONArray;
|
||||||
import com.volmit.iris.util.json.JSONObject;
|
import com.volmit.iris.util.json.JSONObject;
|
||||||
import com.volmit.iris.util.math.M;
|
import com.volmit.iris.util.math.M;
|
||||||
|
import com.volmit.iris.util.math.Position2;
|
||||||
import com.volmit.iris.util.math.RNG;
|
import com.volmit.iris.util.math.RNG;
|
||||||
import com.volmit.iris.util.math.Spiraler;
|
import com.volmit.iris.util.math.Spiraler;
|
||||||
import com.volmit.iris.util.noise.CNG;
|
import com.volmit.iris.util.noise.CNG;
|
||||||
|
import com.volmit.iris.util.parallel.BurstExecutor;
|
||||||
|
import com.volmit.iris.util.parallel.MultiBurst;
|
||||||
|
import com.volmit.iris.util.plugin.VolmitSender;
|
||||||
|
import com.volmit.iris.util.scheduling.J;
|
||||||
import com.volmit.iris.util.scheduling.O;
|
import com.volmit.iris.util.scheduling.O;
|
||||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||||
|
import com.volmit.iris.util.scheduling.jobs.QueueJob;
|
||||||
import io.papermc.lib.PaperLib;
|
import io.papermc.lib.PaperLib;
|
||||||
import org.bukkit.*;
|
import org.bukkit.*;
|
||||||
import org.bukkit.event.inventory.InventoryType;
|
import org.bukkit.event.inventory.InventoryType;
|
||||||
@@ -65,14 +73,19 @@ import java.nio.file.Files;
|
|||||||
import java.nio.file.attribute.FileTime;
|
import java.nio.file.attribute.FileTime;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.time.temporal.ChronoUnit;
|
import java.time.temporal.ChronoUnit;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
@Decree(name = "studio", aliases = {"std", "s"}, description = "Studio Commands", studio = true)
|
@Decree(name = "studio", aliases = {"std", "s"}, description = "Studio Commands", studio = true)
|
||||||
public class CommandStudio implements DecreeExecutor {
|
public class CommandStudio implements DecreeExecutor {
|
||||||
private CommandFind find;
|
private CommandFind find;
|
||||||
private CommandEdit edit;
|
private CommandEdit edit;
|
||||||
|
//private CommandDeepSearch deepSearch;
|
||||||
|
|
||||||
public static String hrf(Duration duration) {
|
public static String hrf(Duration duration) {
|
||||||
return duration.toString().substring(2).replaceAll("(\\d[HMS])(?!$)", "$1 ").toLowerCase();
|
return duration.toString().substring(2).replaceAll("(\\d[HMS])(?!$)", "$1 ").toLowerCase();
|
||||||
@@ -143,12 +156,83 @@ public class CommandStudio implements DecreeExecutor {
|
|||||||
sender().sendMessage(C.GREEN + "The \"" + dimension.getName() + "\" pack has version: " + dimension.getVersion());
|
sender().sendMessage(C.GREEN + "The \"" + dimension.getName() + "\" pack has version: " + dimension.getVersion());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Decree(name = "regen", description = "Regenerate nearby chunks.", aliases = "rg", sync = true, origin = DecreeOrigin.PLAYER)
|
||||||
|
public void regen(
|
||||||
|
@Param(name = "radius", description = "The radius of nearby cunks", defaultValue = "5")
|
||||||
|
int radius
|
||||||
|
) {
|
||||||
|
if (IrisToolbelt.isIrisWorld(player().getWorld())) {
|
||||||
|
VolmitSender sender = sender();
|
||||||
|
J.a(() -> {
|
||||||
|
DecreeContext.touch(sender);
|
||||||
|
PlatformChunkGenerator plat = IrisToolbelt.access(player().getWorld());
|
||||||
|
Engine engine = plat.getEngine();
|
||||||
|
try {
|
||||||
|
Chunk cx = player().getLocation().getChunk();
|
||||||
|
KList<Runnable> js = new KList<>();
|
||||||
|
BurstExecutor b = MultiBurst.burst.burst();
|
||||||
|
b.setMulticore(false);
|
||||||
|
int rad = engine.getMantle().getRadius();
|
||||||
|
for (int i = -(radius + rad); i <= radius + rad; i++) {
|
||||||
|
for (int j = -(radius + rad); j <= radius + rad; j++) {
|
||||||
|
engine.getMantle().getMantle().deleteChunk(i + cx.getX(), j + cx.getZ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = -radius; i <= radius; i++) {
|
||||||
|
for (int j = -radius; j <= radius; j++) {
|
||||||
|
int finalJ = j;
|
||||||
|
int finalI = i;
|
||||||
|
b.queue(() -> plat.injectChunkReplacement(player().getWorld(), finalI + cx.getX(), finalJ + cx.getZ(), (f) -> {
|
||||||
|
synchronized (js) {
|
||||||
|
js.add(f);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
b.complete();
|
||||||
|
sender().sendMessage(C.GREEN + "Regenerating " + Form.f(js.size()) + " Sections");
|
||||||
|
QueueJob<Runnable> r = new QueueJob<>() {
|
||||||
|
final KList<Future<?>> futures = new KList<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(Runnable runnable) {
|
||||||
|
futures.add(J.sfut(runnable));
|
||||||
|
|
||||||
|
if (futures.size() > 64) {
|
||||||
|
while (futures.isNotEmpty()) {
|
||||||
|
try {
|
||||||
|
futures.remove(0).get();
|
||||||
|
} catch (InterruptedException | ExecutionException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "Regenerating";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
r.queue(js);
|
||||||
|
r.execute(sender());
|
||||||
|
} catch (Throwable e) {
|
||||||
|
sender().sendMessage("Unable to parse view-distance");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
sender().sendMessage(C.RED + "You must be in an Iris World to use regen!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Decree(description = "Convert objects in the \"convert\" folder")
|
@Decree(description = "Convert objects in the \"convert\" folder")
|
||||||
public void convert() {
|
public void convert() {
|
||||||
Iris.service(ConversionSVC.class).check(sender());
|
Iris.service(ConversionSVC.class).check(sender());
|
||||||
|
//IrisConverter.convertSchematics(sender());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Decree(description = "Execute a script", aliases = "run", origin = DecreeOrigin.PLAYER)
|
@Decree(description = "Execute a script", aliases = "run", origin = DecreeOrigin.PLAYER)
|
||||||
public void execute(
|
public void execute(
|
||||||
@Param(description = "The script to run")
|
@Param(description = "The script to run")
|
||||||
@@ -218,7 +302,7 @@ public class CommandStudio implements DecreeExecutor {
|
|||||||
Inventory inv = Bukkit.createInventory(null, 27 * 2);
|
Inventory inv = Bukkit.createInventory(null, 27 * 2);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
engine().addItems(true, inv, RNG.r, tables, InventorySlotType.STORAGE, player().getLocation().getBlockX(), player().getLocation().getBlockY(), player().getLocation().getBlockZ(), 1);
|
engine().addItems(true, inv, RNG.r, tables, InventorySlotType.STORAGE, player().getWorld(), player().getLocation().getBlockX(), player().getLocation().getBlockY(), player().getLocation().getBlockZ(), 1);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
sender().sendMessage(C.RED + "Cannot add items to virtual inventory because of: " + e.getMessage());
|
sender().sendMessage(C.RED + "Cannot add items to virtual inventory because of: " + e.getMessage());
|
||||||
@@ -241,13 +325,80 @@ public class CommandStudio implements DecreeExecutor {
|
|||||||
inv.clear();
|
inv.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
engine().addItems(true, inv, new RNG(RNG.r.imax()), tables, InventorySlotType.STORAGE, player().getLocation().getBlockX(), player().getLocation().getBlockY(), player().getLocation().getBlockZ(), 1);
|
engine().addItems(true, inv, new RNG(RNG.r.imax()), tables, InventorySlotType.STORAGE, player().getWorld(), player().getLocation().getBlockX(), player().getLocation().getBlockY(), player().getLocation().getBlockZ(), 1);
|
||||||
}, 0, fast ? 5 : 35));
|
}, 0, fast ? 5 : 35));
|
||||||
|
|
||||||
sender().sendMessage(C.GREEN + "Opening inventory now!");
|
sender().sendMessage(C.GREEN + "Opening inventory now!");
|
||||||
player().openInventory(inv);
|
player().openInventory(inv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Decree(description = "Get all structures in a radius of chunks", aliases = "dist", origin = DecreeOrigin.PLAYER)
|
||||||
|
public void distances(@Param(description = "The radius in chunks") int radius) {
|
||||||
|
var engine = engine();
|
||||||
|
if (engine == null) {
|
||||||
|
sender().sendMessage(C.RED + "Only works in an Iris world!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var sender = sender();
|
||||||
|
int d = radius * 2;
|
||||||
|
KMap<String, KList<Position2>> data = new KMap<>();
|
||||||
|
var multiBurst = new MultiBurst("Distance Sampler", Thread.MIN_PRIORITY);
|
||||||
|
var executor = multiBurst.burst(radius * radius);
|
||||||
|
|
||||||
|
sender.sendMessage(C.GRAY + "Generating data...");
|
||||||
|
var loc = player().getLocation();
|
||||||
|
int totalTasks = d * d;
|
||||||
|
AtomicInteger completedTasks = new AtomicInteger(0);
|
||||||
|
int c = J.ar(() -> {
|
||||||
|
sender.sendProgress((double) completedTasks.get() / totalTasks, "Finding structures");
|
||||||
|
}, 0);
|
||||||
|
|
||||||
|
new Spiraler(d, d, (x, z) -> executor.queue(() -> {
|
||||||
|
var struct = engine.getStructureAt(x, z);
|
||||||
|
if (struct != null) {
|
||||||
|
data.computeIfAbsent(struct.getLoadKey(), (k) -> new KList<>()).add(new Position2(x, z));
|
||||||
|
}
|
||||||
|
completedTasks.incrementAndGet();
|
||||||
|
})).setOffset(loc.getBlockX(), loc.getBlockZ()).drain();
|
||||||
|
|
||||||
|
executor.complete();
|
||||||
|
multiBurst.close();
|
||||||
|
J.car(c);
|
||||||
|
|
||||||
|
for (var key : data.keySet()) {
|
||||||
|
var list = data.get(key);
|
||||||
|
KList<Long> distances = new KList<>(list.size() - 1);
|
||||||
|
for (int i = 0; i < list.size(); i++) {
|
||||||
|
var pos = list.get(i);
|
||||||
|
double dist = Integer.MAX_VALUE;
|
||||||
|
for (var p : list) {
|
||||||
|
if (p.equals(pos)) continue;
|
||||||
|
dist = Math.min(dist, Math.sqrt(Math.pow(pos.getX() - p.getX(), 2) + Math.pow(pos.getZ() - p.getZ(), 2)));
|
||||||
|
}
|
||||||
|
if (dist == Integer.MAX_VALUE) continue;
|
||||||
|
distances.add(Math.round(dist * 16));
|
||||||
|
}
|
||||||
|
long[] array = new long[distances.size()];
|
||||||
|
for (int i = 0; i < distances.size(); i++) {
|
||||||
|
array[i] = distances.get(i);
|
||||||
|
}
|
||||||
|
Arrays.sort(array);
|
||||||
|
long min = array.length > 0 ? array[0] : 0;
|
||||||
|
long max = array.length > 0 ? array[array.length - 1] : 0;
|
||||||
|
long sum = Arrays.stream(array).sum();
|
||||||
|
long avg = array.length > 0 ? Math.round(sum / (double) array.length) : 0;
|
||||||
|
String msg = "%s: %s => min: %s/max: %s -> avg: %s".formatted(key, list.size(), min, max, avg);
|
||||||
|
sender.sendMessage(msg);
|
||||||
|
}
|
||||||
|
if (data.isEmpty()) {
|
||||||
|
sender.sendMessage(C.RED + "No data found!");
|
||||||
|
} else {
|
||||||
|
sender.sendMessage(C.GREEN + "Done!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Decree(description = "Render a world map (External GUI)", aliases = "render")
|
@Decree(description = "Render a world map (External GUI)", aliases = "render")
|
||||||
public void map(
|
public void map(
|
||||||
@Param(name = "world", description = "The world to open the generator for", contextual = true)
|
@Param(name = "world", description = "The world to open the generator for", contextual = true)
|
||||||
|
|||||||
@@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||||
|
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.volmit.iris.core.commands;
|
||||||
|
|
||||||
|
import com.volmit.iris.Iris;
|
||||||
|
import com.volmit.iris.core.loader.IrisData;
|
||||||
|
import com.volmit.iris.core.pregenerator.ChunkUpdater;
|
||||||
|
import com.volmit.iris.core.service.IrisEngineSVC;
|
||||||
|
import com.volmit.iris.core.tools.IrisPackBenchmarking;
|
||||||
|
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||||
|
import com.volmit.iris.engine.framework.Engine;
|
||||||
|
import com.volmit.iris.engine.object.IrisDimension;
|
||||||
|
import com.volmit.iris.util.collection.KList;
|
||||||
|
import com.volmit.iris.util.decree.DecreeExecutor;
|
||||||
|
import com.volmit.iris.util.decree.DecreeOrigin;
|
||||||
|
import com.volmit.iris.util.decree.annotations.Decree;
|
||||||
|
import com.volmit.iris.util.decree.annotations.Param;
|
||||||
|
import com.volmit.iris.util.format.C;
|
||||||
|
import com.volmit.iris.util.format.Form;
|
||||||
|
import com.volmit.iris.util.io.IO;
|
||||||
|
import com.volmit.iris.util.mantle.TectonicPlate;
|
||||||
|
import com.volmit.iris.util.misc.Hastebin;
|
||||||
|
import com.volmit.iris.util.misc.Platform;
|
||||||
|
import com.volmit.iris.util.misc.getHardware;
|
||||||
|
import com.volmit.iris.util.nbt.mca.MCAFile;
|
||||||
|
import com.volmit.iris.util.nbt.mca.MCAUtil;
|
||||||
|
import com.volmit.iris.util.plugin.VolmitSender;
|
||||||
|
import net.jpountz.lz4.LZ4BlockInputStream;
|
||||||
|
import net.jpountz.lz4.LZ4BlockOutputStream;
|
||||||
|
import net.jpountz.lz4.LZ4FrameInputStream;
|
||||||
|
import net.jpountz.lz4.LZ4FrameOutputStream;
|
||||||
|
import org.apache.commons.lang.RandomStringUtils;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Chunk;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import oshi.SystemInfo;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.NetworkInterface;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.zip.GZIPInputStream;
|
||||||
|
import java.util.zip.GZIPOutputStream;
|
||||||
|
|
||||||
|
@Decree(name = "Support", origin = DecreeOrigin.BOTH, description = "Iris World Manager", aliases = {"support"})
|
||||||
|
public class CommandSupport implements DecreeExecutor {
|
||||||
|
|
||||||
|
@Decree(description = "report")
|
||||||
|
public void report() {
|
||||||
|
try {
|
||||||
|
if (sender().isPlayer()) sender().sendMessage(C.GOLD + "Creating report..");
|
||||||
|
if (!sender().isPlayer()) Iris.info(C.GOLD + "Creating report..");
|
||||||
|
Hastebin.enviornment(sender());
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
Iris.info(C.RED + "Something went wrong: ");
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,131 @@
|
|||||||
|
/*
|
||||||
|
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||||
|
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.volmit.iris.core.commands;
|
||||||
|
|
||||||
|
import com.volmit.iris.Iris;
|
||||||
|
import com.volmit.iris.core.pregenerator.LazyPregenerator;
|
||||||
|
import com.volmit.iris.core.pregenerator.TurboPregenerator;
|
||||||
|
import com.volmit.iris.core.pregenerator.TurboPregenerator;
|
||||||
|
import com.volmit.iris.util.decree.DecreeExecutor;
|
||||||
|
import com.volmit.iris.util.decree.annotations.Decree;
|
||||||
|
import com.volmit.iris.util.decree.annotations.Param;
|
||||||
|
import com.volmit.iris.util.format.C;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@Decree(name = "turbopregen", aliases = "turbo", description = "Pregenerate your Iris worlds!")
|
||||||
|
public class CommandTurboPregen implements DecreeExecutor {
|
||||||
|
public String worldName;
|
||||||
|
@Decree(description = "Pregenerate a world")
|
||||||
|
public void start(
|
||||||
|
@Param(description = "The radius of the pregen in blocks", aliases = "size")
|
||||||
|
int radius,
|
||||||
|
@Param(description = "The world to pregen", contextual = true)
|
||||||
|
World world,
|
||||||
|
@Param(aliases = "middle", description = "The center location of the pregen. Use \"me\" for your current location", defaultValue = "0,0")
|
||||||
|
Vector center
|
||||||
|
) {
|
||||||
|
|
||||||
|
worldName = world.getName();
|
||||||
|
File worldDirectory = new File(Bukkit.getWorldContainer(), world.getName());
|
||||||
|
File TurboFile = new File(worldDirectory, "turbogen.json");
|
||||||
|
if (TurboFile.exists()) {
|
||||||
|
if (TurboPregenerator.getInstance() != null) {
|
||||||
|
sender().sendMessage(C.BLUE + "Turbo pregen is already in progress");
|
||||||
|
Iris.info(C.YELLOW + "Turbo pregen is already in progress");
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
TurboFile.delete();
|
||||||
|
} catch (Exception e){
|
||||||
|
Iris.error("Failed to delete the old instance file of Turbo Pregen!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (sender().isPlayer() && access() == null) {
|
||||||
|
sender().sendMessage(C.RED + "The engine access for this world is null!");
|
||||||
|
sender().sendMessage(C.RED + "Please make sure the world is loaded & the engine is initialized. Generate a new chunk, for example.");
|
||||||
|
}
|
||||||
|
|
||||||
|
TurboPregenerator.TurboPregenJob pregenJob = TurboPregenerator.TurboPregenJob.builder()
|
||||||
|
.world(worldName)
|
||||||
|
.radiusBlocks(radius)
|
||||||
|
.position(0)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
File TurboGenFile = new File(worldDirectory, "turbogen.json");
|
||||||
|
TurboPregenerator pregenerator = new TurboPregenerator(pregenJob, TurboGenFile);
|
||||||
|
pregenerator.start();
|
||||||
|
|
||||||
|
String msg = C.GREEN + "TurboPregen started in " + C.GOLD + worldName + C.GREEN + " of " + C.GOLD + (radius * 2) + C.GREEN + " by " + C.GOLD + (radius * 2) + C.GREEN + " blocks from " + C.GOLD + center.getX() + "," + center.getZ();
|
||||||
|
sender().sendMessage(msg);
|
||||||
|
Iris.info(msg);
|
||||||
|
} catch (Throwable e) {
|
||||||
|
sender().sendMessage(C.RED + "Epic fail. See console.");
|
||||||
|
Iris.reportError(e);
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Decree(description = "Stop the active pregeneration task", aliases = "x")
|
||||||
|
public void stop(@Param(aliases = "world", description = "The world to pause") World world) throws IOException {
|
||||||
|
TurboPregenerator turboPregenInstance = TurboPregenerator.getInstance();
|
||||||
|
File worldDirectory = new File(Bukkit.getWorldContainer(), world.getName());
|
||||||
|
File turboFile = new File(worldDirectory, "turbogen.json");
|
||||||
|
|
||||||
|
if (turboPregenInstance != null) {
|
||||||
|
turboPregenInstance.shutdownInstance(world);
|
||||||
|
sender().sendMessage(C.LIGHT_PURPLE + "Closed Turbogen instance for " + world.getName());
|
||||||
|
} else if (turboFile.exists() && turboFile.delete()) {
|
||||||
|
sender().sendMessage(C.LIGHT_PURPLE + "Closed Turbogen instance for " + world.getName());
|
||||||
|
} else if (turboFile.exists()) {
|
||||||
|
Iris.error("Failed to delete the old instance file of Turbo Pregen!");
|
||||||
|
} else {
|
||||||
|
sender().sendMessage(C.YELLOW + "No active pregeneration tasks to stop");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Decree(description = "Pause / continue the active pregeneration task", aliases = {"t", "resume", "unpause"})
|
||||||
|
public void pause(
|
||||||
|
@Param(aliases = "world", description = "The world to pause")
|
||||||
|
World world
|
||||||
|
) {
|
||||||
|
if (TurboPregenerator.getInstance() != null) {
|
||||||
|
TurboPregenerator.setPausedTurbo(world);
|
||||||
|
sender().sendMessage(C.GREEN + "Paused/unpaused Turbo Pregen, now: " + (TurboPregenerator.isPausedTurbo(world) ? "Paused" : "Running") + ".");
|
||||||
|
} else {
|
||||||
|
File worldDirectory = new File(Bukkit.getWorldContainer(), world.getName());
|
||||||
|
File TurboFile = new File(worldDirectory, "turbogen.json");
|
||||||
|
if (TurboFile.exists()){
|
||||||
|
TurboPregenerator.loadTurboGenerator(world.getName());
|
||||||
|
sender().sendMessage(C.YELLOW + "Started Turbo Pregen back up!");
|
||||||
|
} else {
|
||||||
|
sender().sendMessage(C.YELLOW + "No active Turbo Pregen tasks to pause/unpause.");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||||
|
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.volmit.iris.core.commands;
|
||||||
|
|
||||||
|
import org.bukkit.World;
|
||||||
|
|
||||||
|
import com.volmit.iris.Iris;
|
||||||
|
import com.volmit.iris.core.pregenerator.ChunkUpdater;
|
||||||
|
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||||
|
import com.volmit.iris.util.decree.DecreeExecutor;
|
||||||
|
import com.volmit.iris.util.decree.DecreeOrigin;
|
||||||
|
import com.volmit.iris.util.decree.annotations.Decree;
|
||||||
|
import com.volmit.iris.util.decree.annotations.Param;
|
||||||
|
import com.volmit.iris.util.format.C;
|
||||||
|
import com.volmit.iris.util.format.Form;
|
||||||
|
|
||||||
|
@Decree(name = "updater", origin = DecreeOrigin.BOTH, description = "Iris World Updater")
|
||||||
|
public class CommandUpdater implements DecreeExecutor {
|
||||||
|
private ChunkUpdater chunkUpdater;
|
||||||
|
|
||||||
|
@Decree(description = "Updates all chunk in the specified world")
|
||||||
|
public void start(
|
||||||
|
@Param(description = "World to update chunks at", contextual = true)
|
||||||
|
World world
|
||||||
|
) {
|
||||||
|
if (!IrisToolbelt.isIrisWorld(world)) {
|
||||||
|
sender().sendMessage(C.GOLD + "This is not an Iris world");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (chunkUpdater != null) {
|
||||||
|
chunkUpdater.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
chunkUpdater = new ChunkUpdater(world);
|
||||||
|
if (sender().isPlayer()) {
|
||||||
|
sender().sendMessage(C.GREEN + "Updating " + world.getName() + C.GRAY + " Total chunks: " + Form.f(chunkUpdater.getChunks()));
|
||||||
|
} else {
|
||||||
|
Iris.info(C.GREEN + "Updating " + world.getName() + C.GRAY + " Total chunks: " + Form.f(chunkUpdater.getChunks()));
|
||||||
|
}
|
||||||
|
chunkUpdater.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Decree(description = "Pause the updater")
|
||||||
|
public void pause( ) {
|
||||||
|
if (chunkUpdater == null) {
|
||||||
|
sender().sendMessage(C.GOLD + "You cant pause something that doesnt exist?");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
boolean status = chunkUpdater.pause();
|
||||||
|
if (sender().isPlayer()) {
|
||||||
|
if (status) {
|
||||||
|
sender().sendMessage(C.IRIS + "Paused task for: " + C.GRAY + chunkUpdater.getName());
|
||||||
|
} else {
|
||||||
|
sender().sendMessage(C.IRIS + "Unpause task for: " + C.GRAY + chunkUpdater.getName());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (status) {
|
||||||
|
Iris.info(C.IRIS + "Paused task for: " + C.GRAY + chunkUpdater.getName());
|
||||||
|
} else {
|
||||||
|
Iris.info(C.IRIS + "Unpause task for: " + C.GRAY + chunkUpdater.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Decree(description = "Stops the updater")
|
||||||
|
public void stop() {
|
||||||
|
if (chunkUpdater == null) {
|
||||||
|
sender().sendMessage(C.GOLD + "You cant stop something that doesnt exist?");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (sender().isPlayer()) {
|
||||||
|
sender().sendMessage("Stopping Updater for: " + C.GRAY + chunkUpdater.getName());
|
||||||
|
} else {
|
||||||
|
Iris.info("Stopping Updater for: " + C.GRAY + chunkUpdater.getName());
|
||||||
|
}
|
||||||
|
chunkUpdater.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -22,7 +22,9 @@ import com.volmit.iris.Iris;
|
|||||||
import com.volmit.iris.core.edit.BlockSignal;
|
import com.volmit.iris.core.edit.BlockSignal;
|
||||||
import com.volmit.iris.core.nms.INMS;
|
import com.volmit.iris.core.nms.INMS;
|
||||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||||
|
import com.volmit.iris.engine.framework.Engine;
|
||||||
import com.volmit.iris.engine.object.IrisBiome;
|
import com.volmit.iris.engine.object.IrisBiome;
|
||||||
|
import com.volmit.iris.engine.object.IrisRegion;
|
||||||
import com.volmit.iris.util.data.B;
|
import com.volmit.iris.util.data.B;
|
||||||
import com.volmit.iris.util.decree.DecreeExecutor;
|
import com.volmit.iris.util.decree.DecreeExecutor;
|
||||||
import com.volmit.iris.util.decree.DecreeOrigin;
|
import com.volmit.iris.util.decree.DecreeOrigin;
|
||||||
@@ -37,6 +39,7 @@ import org.bukkit.Material;
|
|||||||
import org.bukkit.block.Biome;
|
import org.bukkit.block.Biome;
|
||||||
import org.bukkit.block.data.BlockData;
|
import org.bukkit.block.data.BlockData;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
@Decree(name = "what", origin = DecreeOrigin.PLAYER, studio = true, description = "Iris What?")
|
@Decree(name = "what", origin = DecreeOrigin.PLAYER, studio = true, description = "Iris What?")
|
||||||
@@ -82,6 +85,19 @@ public class CommandWhat implements DecreeExecutor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Decree(description = "What region am i in?", origin = DecreeOrigin.PLAYER)
|
||||||
|
public void region() {
|
||||||
|
try {
|
||||||
|
Chunk chunk = world().getChunkAt(player().getLocation().getBlockZ() / 16, player().getLocation().getBlockZ() / 16);
|
||||||
|
IrisRegion r = engine().getRegion(chunk);
|
||||||
|
sender().sendMessage("IRegion: " + r.getLoadKey() + " (" + r.getName() + ")");
|
||||||
|
|
||||||
|
} catch (Throwable e) {
|
||||||
|
Iris.reportError(e);
|
||||||
|
sender().sendMessage(C.IRIS + "Iris worlds only.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Decree(description = "What block am i looking at?", origin = DecreeOrigin.PLAYER)
|
@Decree(description = "What block am i looking at?", origin = DecreeOrigin.PLAYER)
|
||||||
public void block() {
|
public void block() {
|
||||||
BlockData bd;
|
BlockData bd;
|
||||||
@@ -147,7 +163,7 @@ public class CommandWhat implements DecreeExecutor {
|
|||||||
|
|
||||||
sender().sendMessage("Found " + v.get() + " Nearby Markers (" + marker + ")");
|
sender().sendMessage("Found " + v.get() + " Nearby Markers (" + marker + ")");
|
||||||
} else {
|
} else {
|
||||||
sender().sendMessage("Iris worlds only.");
|
sender().sendMessage(C.IRIS + "Iris worlds only.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
package com.volmit.iris.core.events;
|
||||||
|
|
||||||
|
import com.volmit.iris.Iris;
|
||||||
|
import com.volmit.iris.engine.framework.Engine;
|
||||||
|
import com.volmit.iris.engine.object.InventorySlotType;
|
||||||
|
import com.volmit.iris.engine.object.IrisLootTable;
|
||||||
|
import com.volmit.iris.util.collection.KList;
|
||||||
|
import com.volmit.iris.util.scheduling.J;
|
||||||
|
import lombok.Getter;
|
||||||
|
import org.bukkit.*;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.event.Event;
|
||||||
|
import org.bukkit.event.HandlerList;
|
||||||
|
import org.bukkit.event.world.LootGenerateEvent;
|
||||||
|
|
||||||
|
import org.bukkit.inventory.Inventory;
|
||||||
|
import org.bukkit.inventory.InventoryHolder;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.loot.LootContext;
|
||||||
|
import org.bukkit.loot.LootTable;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public class IrisLootEvent extends Event {
|
||||||
|
private static final HandlerList handlers = new HandlerList();
|
||||||
|
private static final LootTable EMPTY = new LootTable() {
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public NamespacedKey getKey() {
|
||||||
|
return new NamespacedKey(Iris.instance, "empty");
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Collection<ItemStack> populateLoot(@Nullable Random random, @NotNull LootContext context) {
|
||||||
|
return List.of();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fillInventory(@NotNull Inventory inventory, @Nullable Random random, @NotNull LootContext context) {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private final Engine engine;
|
||||||
|
private final Block block;
|
||||||
|
private final InventorySlotType slot;
|
||||||
|
private final KList<IrisLootTable> tables;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for IrisLootEvent with mode selection.
|
||||||
|
*
|
||||||
|
* @param engine The engine instance.
|
||||||
|
* @param block The block associated with the event.
|
||||||
|
* @param slot The inventory slot type.
|
||||||
|
* @param tables The list of IrisLootTables. (mutable*)
|
||||||
|
*/
|
||||||
|
public IrisLootEvent(Engine engine, Block block, InventorySlotType slot, KList<IrisLootTable> tables) {
|
||||||
|
this.engine = engine;
|
||||||
|
this.block = block;
|
||||||
|
this.slot = slot;
|
||||||
|
this.tables = tables;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HandlerList getHandlers() {
|
||||||
|
return handlers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Required method to get the HandlerList for this event.
|
||||||
|
*
|
||||||
|
* @return The HandlerList.
|
||||||
|
*/
|
||||||
|
public static HandlerList getHandlerList() {
|
||||||
|
return handlers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggers the corresponding Bukkit loot event.
|
||||||
|
* This method integrates your custom IrisLootTables with Bukkit's LootGenerateEvent,
|
||||||
|
* allowing other plugins to modify or cancel the loot generation.
|
||||||
|
*
|
||||||
|
* @return true when the event was canceled
|
||||||
|
*/
|
||||||
|
public static boolean callLootEvent(KList<ItemStack> loot, Inventory inv, World world, int x, int y, int z) {
|
||||||
|
InventoryHolder holder = inv.getHolder();
|
||||||
|
Location loc = new Location(world, x, y, z);
|
||||||
|
if (holder == null) {
|
||||||
|
holder = new InventoryHolder() {
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Inventory getInventory() {
|
||||||
|
return inv;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
LootContext context = new LootContext.Builder(loc).build();
|
||||||
|
LootGenerateEvent event = new LootGenerateEvent(world, null, holder, EMPTY, context, loot, true);
|
||||||
|
if (!Bukkit.isPrimaryThread()) {
|
||||||
|
Iris.warn("LootGenerateEvent was not called on the main thread, please report this issue.");
|
||||||
|
Thread.dumpStack();
|
||||||
|
J.sfut(() -> Bukkit.getPluginManager().callEvent(event)).join();
|
||||||
|
} else Bukkit.getPluginManager().callEvent(event);
|
||||||
|
|
||||||
|
return event.isCancelled();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,6 +19,7 @@
|
|||||||
package com.volmit.iris.core.gui;
|
package com.volmit.iris.core.gui;
|
||||||
|
|
||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.Iris;
|
||||||
|
import com.volmit.iris.core.IrisSettings;
|
||||||
import com.volmit.iris.core.events.IrisEngineHotloadEvent;
|
import com.volmit.iris.core.events.IrisEngineHotloadEvent;
|
||||||
import com.volmit.iris.engine.object.NoiseStyle;
|
import com.volmit.iris.engine.object.NoiseStyle;
|
||||||
import com.volmit.iris.util.collection.KList;
|
import com.volmit.iris.util.collection.KList;
|
||||||
@@ -61,7 +62,7 @@ public class NoiseExplorerGUI extends JPanel implements MouseWheelListener, List
|
|||||||
@SuppressWarnings("CanBeFinal")
|
@SuppressWarnings("CanBeFinal")
|
||||||
RollingSequence r = new RollingSequence(20);
|
RollingSequence r = new RollingSequence(20);
|
||||||
@SuppressWarnings("CanBeFinal")
|
@SuppressWarnings("CanBeFinal")
|
||||||
boolean colorMode = true;
|
boolean colorMode = IrisSettings.get().getGui().colorMode;
|
||||||
double scale = 1;
|
double scale = 1;
|
||||||
CNG cng = NoiseStyle.STATIC.create(new RNG(RNG.r.nextLong()));
|
CNG cng = NoiseStyle.STATIC.create(new RNG(RNG.r.nextLong()));
|
||||||
@SuppressWarnings("CanBeFinal")
|
@SuppressWarnings("CanBeFinal")
|
||||||
@@ -274,7 +275,8 @@ public class NoiseExplorerGUI extends JPanel implements MouseWheelListener, List
|
|||||||
n = n > 1 ? 1 : n < 0 ? 0 : n;
|
n = n > 1 ? 1 : n < 0 ? 0 : n;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Color color = colorMode ? Color.getHSBColor((float) (n), 1f - (float) (n * n * n * n * n * n), 1f - (float) n) : Color.getHSBColor(0f, 0f, (float) n);
|
//Color color = colorMode ? Color.getHSBColor((float) (n), 1f - (float) (n * n * n * n * n * n), 1f - (float) n) : Color.getHSBColor(0f, 0f, (float) n);
|
||||||
|
Color color = colorMode ? Color.getHSBColor((float) (0.666f - n * 0.666f), 1f, (float) (1f - n * 0.8f)) : Color.getHSBColor(0f, 0f, (float) n);
|
||||||
int rgb = color.getRGB();
|
int rgb = color.getRGB();
|
||||||
img.setRGB(xx, z, rgb);
|
img.setRGB(xx, z, rgb);
|
||||||
} catch (Throwable ignored) {
|
} 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.PregenListener;
|
||||||
import com.volmit.iris.core.pregenerator.PregenTask;
|
import com.volmit.iris.core.pregenerator.PregenTask;
|
||||||
import com.volmit.iris.core.pregenerator.PregeneratorMethod;
|
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.engine.framework.Engine;
|
||||||
import com.volmit.iris.util.collection.KList;
|
import com.volmit.iris.util.collection.KList;
|
||||||
import com.volmit.iris.util.format.Form;
|
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.concurrent.locks.ReentrantLock;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import static com.volmit.iris.core.tools.IrisPackBenchmarking.benchmarkInProgress;
|
||||||
|
|
||||||
public class PregeneratorJob implements PregenListener {
|
public class PregeneratorJob implements PregenListener {
|
||||||
private static final Color COLOR_EXISTS = parseColor("#4d7d5b");
|
private static final Color COLOR_EXISTS = parseColor("#4d7d5b");
|
||||||
private static final Color COLOR_BLACK = 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()));
|
max.setZ(Math.max((zz << 5) + 31, max.getZ()));
|
||||||
});
|
});
|
||||||
|
|
||||||
if (IrisSettings.get().getGui().isUseServerLaunchedGuis()) {
|
if (IrisSettings.get().getGui().isUseServerLaunchedGuis() && task.isGui()) {
|
||||||
open();
|
open();
|
||||||
}
|
}
|
||||||
|
|
||||||
J.a(this.pregenerator::start, 20);
|
var t = new Thread(() -> {
|
||||||
|
J.sleep(1000);
|
||||||
|
this.pregenerator.start();
|
||||||
|
}, "Iris Pregenerator");
|
||||||
|
t.setPriority(Thread.MIN_PRIORITY);
|
||||||
|
t.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean shutdownInstance() {
|
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));
|
IrisBiome b = renderer.getBiome((int) Math.round(x), renderer.getMaxHeight() - 1, (int) Math.round(z));
|
||||||
IrisBiomeGeneratorLink g = b.getGenerators().get(0);
|
IrisBiomeGeneratorLink g = b.getGenerators().get(0);
|
||||||
Color c;
|
Color c;
|
||||||
if (g.getMax() <= 0) {
|
if (g.getMax(renderer) <= 0) {
|
||||||
// Max is below water level, so it is most likely an ocean biome
|
// Max is below water level, so it is most likely an ocean biome
|
||||||
c = Color.BLUE;
|
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
|
// Min is below water level, but max is not, so it is most likely a shore biome
|
||||||
c = Color.YELLOW;
|
c = Color.YELLOW;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -0,0 +1,77 @@
|
|||||||
|
package com.volmit.iris.core.link;
|
||||||
|
|
||||||
|
import com.volmit.iris.Iris;
|
||||||
|
import com.volmit.iris.util.collection.KList;
|
||||||
|
import com.volmit.iris.util.collection.KMap;
|
||||||
|
import com.volmit.iris.util.reflect.WrappedField;
|
||||||
|
import com.willfp.ecoitems.items.EcoItem;
|
||||||
|
import com.willfp.ecoitems.items.EcoItems;
|
||||||
|
import org.bukkit.NamespacedKey;
|
||||||
|
import org.bukkit.block.data.BlockData;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.MissingResourceException;
|
||||||
|
|
||||||
|
public class EcoItemsDataProvider extends ExternalDataProvider {
|
||||||
|
private WrappedField<EcoItem, ItemStack> itemStack;
|
||||||
|
private WrappedField<EcoItem, NamespacedKey> id;
|
||||||
|
|
||||||
|
public EcoItemsDataProvider() {
|
||||||
|
super("EcoItems");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init() {
|
||||||
|
Iris.info("Setting up EcoItems Link...");
|
||||||
|
itemStack = new WrappedField<>(EcoItem.class, "_itemStack");
|
||||||
|
if (this.itemStack.hasFailed()) {
|
||||||
|
Iris.error("Failed to set up EcoItems Link: Unable to fetch ItemStack field!");
|
||||||
|
}
|
||||||
|
id = new WrappedField<>(EcoItem.class, "id");
|
||||||
|
if (this.id.hasFailed()) {
|
||||||
|
Iris.error("Failed to set up EcoItems Link: Unable to fetch id field!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public BlockData getBlockData(@NotNull Identifier blockId, @NotNull KMap<String, String> state) throws MissingResourceException {
|
||||||
|
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public ItemStack getItemStack(@NotNull Identifier itemId, @NotNull KMap<String, Object> customNbt) throws MissingResourceException {
|
||||||
|
EcoItem item = EcoItems.INSTANCE.getByID(itemId.key());
|
||||||
|
if (item == null) throw new MissingResourceException("Failed to find Item!", itemId.namespace(), itemId.key());
|
||||||
|
return itemStack.get(item).clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Identifier[] getBlockTypes() {
|
||||||
|
return new Identifier[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Identifier[] getItemTypes() {
|
||||||
|
KList<Identifier> names = new KList<>();
|
||||||
|
for (EcoItem item : EcoItems.INSTANCE.values()) {
|
||||||
|
try {
|
||||||
|
Identifier key = Identifier.fromNamespacedKey(id.get(item));
|
||||||
|
if (getItemStack(key) != null)
|
||||||
|
names.add(key);
|
||||||
|
} catch (MissingResourceException ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return names.toArray(new Identifier[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isValidProvider(@NotNull Identifier id, boolean isItem) {
|
||||||
|
return id.namespace().equalsIgnoreCase("ecoitems") && isItem;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,8 +3,10 @@ package com.volmit.iris.core.link;
|
|||||||
import com.ssomar.score.api.executableitems.ExecutableItemsAPI;
|
import com.ssomar.score.api.executableitems.ExecutableItemsAPI;
|
||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.Iris;
|
||||||
import com.volmit.iris.util.collection.KList;
|
import com.volmit.iris.util.collection.KList;
|
||||||
|
import com.volmit.iris.util.collection.KMap;
|
||||||
import org.bukkit.block.data.BlockData;
|
import org.bukkit.block.data.BlockData;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.MissingResourceException;
|
import java.util.MissingResourceException;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
@@ -19,23 +21,27 @@ public class ExecutableItemsDataProvider extends ExternalDataProvider {
|
|||||||
Iris.info("Setting up ExecutableItems Link...");
|
Iris.info("Setting up ExecutableItems Link...");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public BlockData getBlockData(Identifier blockId) throws MissingResourceException {
|
public BlockData getBlockData(@NotNull Identifier blockId, @NotNull KMap<String, String> state) throws MissingResourceException {
|
||||||
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
|
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public ItemStack getItemStack(Identifier itemId) throws MissingResourceException {
|
public ItemStack getItemStack(@NotNull Identifier itemId, @NotNull KMap<String, Object> customNbt) throws MissingResourceException {
|
||||||
return ExecutableItemsAPI.getExecutableItemsManager().getExecutableItem(itemId.key())
|
return ExecutableItemsAPI.getExecutableItemsManager().getExecutableItem(itemId.key())
|
||||||
.map(item -> item.buildItem(1, Optional.empty()))
|
.map(item -> item.buildItem(1, Optional.empty()))
|
||||||
.orElseThrow(() -> new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key()));
|
.orElseThrow(() -> new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public Identifier[] getBlockTypes() {
|
public Identifier[] getBlockTypes() {
|
||||||
return new Identifier[0];
|
return new Identifier[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public Identifier[] getItemTypes() {
|
public Identifier[] getItemTypes() {
|
||||||
KList<Identifier> names = new KList<>();
|
KList<Identifier> names = new KList<>();
|
||||||
@@ -52,7 +58,7 @@ public class ExecutableItemsDataProvider extends ExternalDataProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isValidProvider(Identifier key, boolean isItem) {
|
public boolean isValidProvider(@NotNull Identifier key, boolean isItem) {
|
||||||
return key.namespace().equalsIgnoreCase("executable_items") && isItem;
|
return key.namespace().equalsIgnoreCase("executable_items") && isItem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,29 @@
|
|||||||
package com.volmit.iris.core.link;
|
package com.volmit.iris.core.link;
|
||||||
|
|
||||||
|
import com.volmit.iris.engine.framework.Engine;
|
||||||
|
import com.volmit.iris.util.collection.KMap;
|
||||||
|
import com.volmit.iris.util.data.IrisBlockData;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
import lombok.NonNull;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.block.data.BlockData;
|
import org.bukkit.block.data.BlockData;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.bukkit.plugin.Plugin;
|
import org.bukkit.plugin.Plugin;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.MissingResourceException;
|
import java.util.MissingResourceException;
|
||||||
|
|
||||||
|
@Getter
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public abstract class ExternalDataProvider {
|
public abstract class ExternalDataProvider {
|
||||||
|
|
||||||
@Getter
|
@NonNull
|
||||||
private final String pluginId;
|
private final String pluginId;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
public Plugin getPlugin() {
|
public Plugin getPlugin() {
|
||||||
return Bukkit.getPluginManager().getPlugin(pluginId);
|
return Bukkit.getPluginManager().getPlugin(pluginId);
|
||||||
}
|
}
|
||||||
@@ -25,13 +34,60 @@ public abstract class ExternalDataProvider {
|
|||||||
|
|
||||||
public abstract void init();
|
public abstract void init();
|
||||||
|
|
||||||
public abstract BlockData getBlockData(Identifier blockId) throws MissingResourceException;
|
/**
|
||||||
|
* @see ExternalDataProvider#getBlockData(Identifier, KMap)
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
public BlockData getBlockData(@NotNull Identifier blockId) throws MissingResourceException {
|
||||||
|
return getBlockData(blockId, new KMap<>());
|
||||||
|
}
|
||||||
|
|
||||||
public abstract ItemStack getItemStack(Identifier itemId) throws MissingResourceException;
|
/**
|
||||||
|
* This method returns a {@link BlockData} corresponding to the blockID
|
||||||
|
* it is used in any place Iris accepts {@link BlockData}
|
||||||
|
*
|
||||||
|
* @param blockId The id of the block to get
|
||||||
|
* @param state The state of the block to get
|
||||||
|
* @return Corresponding {@link BlockData} to the blockId
|
||||||
|
* may return {@link IrisBlockData} for blocks that need a world for placement
|
||||||
|
* @throws MissingResourceException when the blockId is invalid
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
public abstract BlockData getBlockData(@NotNull Identifier blockId, @NotNull KMap<String, String> state) throws MissingResourceException;
|
||||||
|
|
||||||
public abstract Identifier[] getBlockTypes();
|
/**
|
||||||
|
* @see ExternalDataProvider#getItemStack(Identifier)
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
public ItemStack getItemStack(@NotNull Identifier itemId) throws MissingResourceException {
|
||||||
|
return getItemStack(itemId, new KMap<>());
|
||||||
|
}
|
||||||
|
|
||||||
public abstract Identifier[] getItemTypes();
|
/**
|
||||||
|
* This method returns a {@link ItemStack} corresponding to the itemID
|
||||||
|
* it is used in loot tables
|
||||||
|
*
|
||||||
|
* @param itemId The id of the item to get
|
||||||
|
* @param customNbt Custom nbt to apply to the item
|
||||||
|
* @return Corresponding {@link ItemStack} to the itemId
|
||||||
|
* @throws MissingResourceException when the itemId is invalid
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
public abstract ItemStack getItemStack(@NotNull Identifier itemId, @NotNull KMap<String, Object> customNbt) throws MissingResourceException;
|
||||||
|
|
||||||
public abstract boolean isValidProvider(Identifier id, boolean isItem);
|
/**
|
||||||
|
* This method is used for placing blocks that need to use the plugins api
|
||||||
|
* it will only be called when the {@link ExternalDataProvider#getBlockData(Identifier, KMap)} returned a {@link IrisBlockData}
|
||||||
|
*
|
||||||
|
* @param engine The engine of the world the block is being placed in
|
||||||
|
* @param block The block where the block should be placed
|
||||||
|
* @param blockId The blockId to place
|
||||||
|
*/
|
||||||
|
public void processUpdate(@NotNull Engine engine, @NotNull Block block, @NotNull Identifier blockId) {}
|
||||||
|
|
||||||
|
public abstract @NotNull Identifier[] getBlockTypes();
|
||||||
|
|
||||||
|
public abstract @NotNull Identifier[] getItemTypes();
|
||||||
|
|
||||||
|
public abstract boolean isValidProvider(@NotNull Identifier id, boolean isItem);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,144 @@
|
|||||||
|
package com.volmit.iris.core.link;
|
||||||
|
|
||||||
|
import com.volmit.iris.Iris;
|
||||||
|
import com.volmit.iris.core.IrisSettings;
|
||||||
|
import com.volmit.iris.core.service.ExternalDataSVC;
|
||||||
|
import com.volmit.iris.engine.framework.Engine;
|
||||||
|
import com.volmit.iris.util.collection.KList;
|
||||||
|
import com.volmit.iris.util.collection.KMap;
|
||||||
|
import com.volmit.iris.util.data.IrisBlockData;
|
||||||
|
import com.volmit.iris.util.reflect.WrappedField;
|
||||||
|
import com.volmit.iris.util.reflect.WrappedReturningMethod;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.block.data.BlockData;
|
||||||
|
import org.bukkit.block.data.type.Leaves;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.MissingResourceException;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
public class HMCLeavesDataProvider extends ExternalDataProvider {
|
||||||
|
private Object apiInstance;
|
||||||
|
private WrappedReturningMethod<Object, Material> worldBlockType;
|
||||||
|
private WrappedReturningMethod<Object, Boolean> setCustomBlock;
|
||||||
|
private Map<String, Object> blockDataMap = Map.of();
|
||||||
|
private Map<String, Supplier<ItemStack>> itemDataField = Map.of();
|
||||||
|
|
||||||
|
public HMCLeavesDataProvider() {
|
||||||
|
super("HMCLeaves");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPluginId() {
|
||||||
|
return "HMCLeaves";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init() {
|
||||||
|
try {
|
||||||
|
worldBlockType = new WrappedReturningMethod<>((Class<Object>) Class.forName("io.github.fisher2911.hmcleaves.data.BlockData"), "worldBlockType");
|
||||||
|
apiInstance = getApiInstance(Class.forName("io.github.fisher2911.hmcleaves.api.HMCLeavesAPI"));
|
||||||
|
setCustomBlock = new WrappedReturningMethod<>((Class<Object>) apiInstance.getClass(), "setCustomBlock", Location.class, String.class, boolean.class);
|
||||||
|
Object config = getLeavesConfig(apiInstance.getClass());
|
||||||
|
blockDataMap = getMap(config, "blockDataMap");
|
||||||
|
itemDataField = getMap(config, "itemSupplierMap");
|
||||||
|
} catch (Throwable e) {
|
||||||
|
Iris.error("Failed to initialize HMCLeavesDataProvider: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public BlockData getBlockData(@NotNull Identifier blockId, @NotNull KMap<String, String> state) throws MissingResourceException {
|
||||||
|
Object o = blockDataMap.get(blockId.key());
|
||||||
|
if (o == null)
|
||||||
|
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
|
||||||
|
Material material = worldBlockType.invoke(o, new Object[0]);
|
||||||
|
if (material == null)
|
||||||
|
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
|
||||||
|
BlockData blockData = Bukkit.createBlockData(material);
|
||||||
|
if (IrisSettings.get().getGenerator().preventLeafDecay && blockData instanceof Leaves leaves)
|
||||||
|
leaves.setPersistent(true);
|
||||||
|
return new IrisBlockData(blockData, ExternalDataSVC.buildState(blockId, state));
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public ItemStack getItemStack(@NotNull Identifier itemId, @NotNull KMap<String, Object> customNbt) throws MissingResourceException {
|
||||||
|
if (!itemDataField.containsKey(itemId.key()))
|
||||||
|
throw new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key());
|
||||||
|
return itemDataField.get(itemId.key()).get();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void processUpdate(@NotNull Engine engine, @NotNull Block block, @NotNull Identifier blockId) {
|
||||||
|
var pair = ExternalDataSVC.parseState(blockId);
|
||||||
|
blockId = pair.getA();
|
||||||
|
Boolean result = setCustomBlock.invoke(apiInstance, new Object[]{block.getLocation(), blockId.key(), false});
|
||||||
|
if (result == null || !result)
|
||||||
|
Iris.warn("Failed to set custom block! " + blockId.key() + " " + block.getX() + " " + block.getY() + " " + block.getZ());
|
||||||
|
else if (IrisSettings.get().getGenerator().preventLeafDecay) {
|
||||||
|
BlockData blockData = block.getBlockData();
|
||||||
|
if (blockData instanceof Leaves leaves)
|
||||||
|
leaves.setPersistent(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Identifier[] getBlockTypes() {
|
||||||
|
KList<Identifier> names = new KList<>();
|
||||||
|
for (String name : blockDataMap.keySet()) {
|
||||||
|
try {
|
||||||
|
Identifier key = new Identifier("hmcleaves", name);
|
||||||
|
if (getBlockData(key) != null)
|
||||||
|
names.add(key);
|
||||||
|
} catch (MissingResourceException ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return names.toArray(new Identifier[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Identifier[] getItemTypes() {
|
||||||
|
KList<Identifier> names = new KList<>();
|
||||||
|
for (String name : itemDataField.keySet()) {
|
||||||
|
try {
|
||||||
|
Identifier key = new Identifier("hmcleaves", name);
|
||||||
|
if (getItemStack(key) != null)
|
||||||
|
names.add(key);
|
||||||
|
} catch (MissingResourceException ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return names.toArray(new Identifier[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isValidProvider(@NotNull Identifier id, boolean isItem) {
|
||||||
|
return (isItem ? itemDataField.keySet() : blockDataMap.keySet()).contains(id.key());
|
||||||
|
}
|
||||||
|
|
||||||
|
private <C, T> Map<String, T> getMap(C config, String name) {
|
||||||
|
WrappedField<C, Map<String, T>> field = new WrappedField<>((Class<C>) config.getClass(), name);
|
||||||
|
return field.get(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
private <A> A getApiInstance(Class<A> apiClass) {
|
||||||
|
WrappedReturningMethod<A, A> instance = new WrappedReturningMethod<>(apiClass, "getInstance");
|
||||||
|
return instance.invoke();
|
||||||
|
}
|
||||||
|
|
||||||
|
private <A, C> C getLeavesConfig(Class<A> apiClass) {
|
||||||
|
WrappedReturningMethod<A, A> instance = new WrappedReturningMethod<>(apiClass, "getInstance");
|
||||||
|
WrappedField<A, C> config = new WrappedField<>(apiClass, "config");
|
||||||
|
return config.get(instance.invoke());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,6 +6,10 @@ public record Identifier(String namespace, String key) {
|
|||||||
|
|
||||||
private static final String DEFAULT_NAMESPACE = "minecraft";
|
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) {
|
public static Identifier fromString(String id) {
|
||||||
String[] strings = id.split(":", 2);
|
String[] strings = id.split(":", 2);
|
||||||
if (strings.length == 1) {
|
if (strings.length == 1) {
|
||||||
|
|||||||
@@ -2,10 +2,12 @@ package com.volmit.iris.core.link;
|
|||||||
|
|
||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.Iris;
|
||||||
import com.volmit.iris.util.collection.KList;
|
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.CustomBlock;
|
||||||
import dev.lone.itemsadder.api.CustomStack;
|
import dev.lone.itemsadder.api.CustomStack;
|
||||||
import org.bukkit.block.data.BlockData;
|
import org.bukkit.block.data.BlockData;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.MissingResourceException;
|
import java.util.MissingResourceException;
|
||||||
|
|
||||||
@@ -31,13 +33,15 @@ public class ItemAdderDataProvider extends ExternalDataProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public BlockData getBlockData(Identifier blockId) throws MissingResourceException {
|
public BlockData getBlockData(@NotNull Identifier blockId, @NotNull KMap<String, String> state) throws MissingResourceException {
|
||||||
return CustomBlock.getBaseBlockData(blockId.toString());
|
return CustomBlock.getBaseBlockData(blockId.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public ItemStack getItemStack(Identifier itemId) throws MissingResourceException {
|
public ItemStack getItemStack(@NotNull Identifier itemId, @NotNull KMap<String, Object> customNbt) throws MissingResourceException {
|
||||||
CustomStack stack = CustomStack.getInstance(itemId.toString());
|
CustomStack stack = CustomStack.getInstance(itemId.toString());
|
||||||
if (stack == null) {
|
if (stack == null) {
|
||||||
throw new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key());
|
throw new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key());
|
||||||
@@ -45,6 +49,7 @@ public class ItemAdderDataProvider extends ExternalDataProvider {
|
|||||||
return stack.getItemStack();
|
return stack.getItemStack();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public Identifier[] getBlockTypes() {
|
public Identifier[] getBlockTypes() {
|
||||||
KList<Identifier> keys = new KList<>();
|
KList<Identifier> keys = new KList<>();
|
||||||
@@ -54,6 +59,7 @@ public class ItemAdderDataProvider extends ExternalDataProvider {
|
|||||||
return keys.toArray(new Identifier[0]);
|
return keys.toArray(new Identifier[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public Identifier[] getItemTypes() {
|
public Identifier[] getItemTypes() {
|
||||||
KList<Identifier> keys = new KList<>();
|
KList<Identifier> keys = new KList<>();
|
||||||
@@ -64,7 +70,7 @@ public class ItemAdderDataProvider extends ExternalDataProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isValidProvider(Identifier id, boolean isItem) {
|
public boolean isValidProvider(@NotNull Identifier id, boolean isItem) {
|
||||||
return isItem ? this.itemNamespaces.contains(id.namespace()) : this.blockNamespaces.contains(id.namespace());
|
return isItem ? this.itemNamespaces.contains(id.namespace()) : this.blockNamespaces.contains(id.namespace());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,139 @@
|
|||||||
|
package com.volmit.iris.core.link;
|
||||||
|
|
||||||
|
import com.volmit.iris.Iris;
|
||||||
|
import com.volmit.iris.util.collection.KList;
|
||||||
|
import com.volmit.iris.util.collection.KMap;
|
||||||
|
import com.volmit.iris.util.scheduling.J;
|
||||||
|
import net.Indyuce.mmoitems.MMOItems;
|
||||||
|
import net.Indyuce.mmoitems.api.ItemTier;
|
||||||
|
import net.Indyuce.mmoitems.api.Type;
|
||||||
|
import net.Indyuce.mmoitems.api.block.CustomBlock;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.block.data.BlockData;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.MissingResourceException;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
|
public class MMOItemsDataProvider extends ExternalDataProvider {
|
||||||
|
|
||||||
|
public MMOItemsDataProvider() {
|
||||||
|
super("MMOItems");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init() {
|
||||||
|
Iris.info("Setting up MMOItems Link...");
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public BlockData getBlockData(@NotNull Identifier blockId, @NotNull KMap<String, String> state) throws MissingResourceException {
|
||||||
|
int id = -1;
|
||||||
|
try {
|
||||||
|
id = Integer.parseInt(blockId.key());
|
||||||
|
} catch (NumberFormatException ignored) {}
|
||||||
|
CustomBlock block = api().getCustomBlocks().getBlock(id);
|
||||||
|
if (block == null) throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
|
||||||
|
return block.getState().getBlockData();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public ItemStack getItemStack(@NotNull Identifier itemId, @NotNull KMap<String, Object> customNbt) throws MissingResourceException {
|
||||||
|
String[] parts = itemId.namespace().split("_", 2);
|
||||||
|
if (parts.length != 2)
|
||||||
|
throw new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key());
|
||||||
|
CompletableFuture<ItemStack> future = new CompletableFuture<>();
|
||||||
|
Runnable run = () -> {
|
||||||
|
try {
|
||||||
|
var type = api().getTypes().get(parts[1]);
|
||||||
|
int level = -1;
|
||||||
|
ItemTier tier = null;
|
||||||
|
|
||||||
|
if (customNbt != null) {
|
||||||
|
level = (int) customNbt.getOrDefault("level", -1);
|
||||||
|
tier = api().getTiers().get(String.valueOf(customNbt.get("tier")));
|
||||||
|
}
|
||||||
|
|
||||||
|
ItemStack itemStack;
|
||||||
|
if (type == null) {
|
||||||
|
future.complete(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (level != -1 && tier != null) {
|
||||||
|
itemStack = api().getItem(type, itemId.key(), level, tier);
|
||||||
|
} else {
|
||||||
|
itemStack = api().getItem(type, itemId.key());
|
||||||
|
}
|
||||||
|
future.complete(itemStack);
|
||||||
|
} catch (Throwable e) {
|
||||||
|
future.completeExceptionally(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (Bukkit.isPrimaryThread()) run.run();
|
||||||
|
else J.s(run);
|
||||||
|
ItemStack item = null;
|
||||||
|
try {
|
||||||
|
item = future.get();
|
||||||
|
} catch (InterruptedException | ExecutionException ignored) {}
|
||||||
|
if (item == null)
|
||||||
|
throw new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key());
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Identifier[] getBlockTypes() {
|
||||||
|
KList<Identifier> names = new KList<>();
|
||||||
|
for (Integer id : api().getCustomBlocks().getBlockIds()) {
|
||||||
|
try {
|
||||||
|
Identifier key = new Identifier("mmoitems", String.valueOf(id));
|
||||||
|
if (getBlockData(key) != null)
|
||||||
|
names.add(key);
|
||||||
|
} catch (MissingResourceException ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return names.toArray(new Identifier[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Identifier[] getItemTypes() {
|
||||||
|
KList<Identifier> names = new KList<>();
|
||||||
|
Runnable run = () -> {
|
||||||
|
for (Type type : api().getTypes().getAll()) {
|
||||||
|
for (String name : api().getTemplates().getTemplateNames(type)) {
|
||||||
|
try {
|
||||||
|
Identifier key = new Identifier("mmoitems_" + type.getId(), name);
|
||||||
|
if (getItemStack(key) != null)
|
||||||
|
names.add(key);
|
||||||
|
} catch (MissingResourceException ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (Bukkit.isPrimaryThread()) run.run();
|
||||||
|
else {
|
||||||
|
try {
|
||||||
|
J.sfut(run).get();
|
||||||
|
} catch (InterruptedException | ExecutionException e) {
|
||||||
|
Iris.error("Failed getting MMOItems item types!");
|
||||||
|
Iris.reportError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return names.toArray(new Identifier[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isValidProvider(@NotNull Identifier id, boolean isItem) {
|
||||||
|
return isItem ? id.namespace().split("_", 2).length == 2 : id.namespace().equals("mmoitems");
|
||||||
|
}
|
||||||
|
|
||||||
|
private MMOItems api() {
|
||||||
|
return MMOItems.plugin;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,171 @@
|
|||||||
|
/*
|
||||||
|
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||||
|
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.volmit.iris.core.link;
|
||||||
|
|
||||||
|
import com.volmit.iris.Iris;
|
||||||
|
import com.volmit.iris.core.nms.INMS;
|
||||||
|
import com.volmit.iris.core.nms.container.BiomeColor;
|
||||||
|
import com.volmit.iris.core.service.ExternalDataSVC;
|
||||||
|
import com.volmit.iris.engine.data.cache.Cache;
|
||||||
|
import com.volmit.iris.engine.framework.Engine;
|
||||||
|
import com.volmit.iris.util.collection.KList;
|
||||||
|
import com.volmit.iris.util.collection.KMap;
|
||||||
|
import com.volmit.iris.util.data.B;
|
||||||
|
import com.volmit.iris.util.data.IrisBlockData;
|
||||||
|
import com.volmit.iris.util.math.RNG;
|
||||||
|
import io.lumine.mythic.bukkit.BukkitAdapter;
|
||||||
|
import io.lumine.mythic.bukkit.utils.serialize.Chroma;
|
||||||
|
import io.lumine.mythiccrucible.MythicCrucible;
|
||||||
|
import io.lumine.mythiccrucible.items.CrucibleItem;
|
||||||
|
import io.lumine.mythiccrucible.items.ItemManager;
|
||||||
|
import io.lumine.mythiccrucible.items.blocks.CustomBlockItemContext;
|
||||||
|
import io.lumine.mythiccrucible.items.furniture.FurnitureItemContext;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.block.BlockFace;
|
||||||
|
import org.bukkit.block.data.BlockData;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.MissingResourceException;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public class MythicCrucibleDataProvider extends ExternalDataProvider {
|
||||||
|
|
||||||
|
private ItemManager itemManager;
|
||||||
|
|
||||||
|
public MythicCrucibleDataProvider() {
|
||||||
|
super("MythicCrucible");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init() {
|
||||||
|
Iris.info("Setting up MythicCrucible Link...");
|
||||||
|
try {
|
||||||
|
this.itemManager = MythicCrucible.inst().getItemManager();
|
||||||
|
} catch (Exception e) {
|
||||||
|
Iris.error("Failed to set up MythicCrucible Link: Unable to fetch MythicCrucible instance!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public BlockData getBlockData(@NotNull Identifier blockId, @NotNull KMap<String, String> state) throws MissingResourceException {
|
||||||
|
CrucibleItem crucibleItem = this.itemManager.getItem(blockId.key())
|
||||||
|
.orElseThrow(() -> new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key()));
|
||||||
|
CustomBlockItemContext blockItemContext = crucibleItem.getBlockData();
|
||||||
|
FurnitureItemContext furnitureItemContext = crucibleItem.getFurnitureData();
|
||||||
|
if (furnitureItemContext != null) {
|
||||||
|
return new IrisBlockData(B.getAir(), ExternalDataSVC.buildState(blockId, state));
|
||||||
|
} else if (blockItemContext != null) {
|
||||||
|
return blockItemContext.getBlockData();
|
||||||
|
}
|
||||||
|
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public ItemStack getItemStack(@NotNull Identifier itemId, @NotNull KMap<String, Object> customNbt) throws MissingResourceException {
|
||||||
|
Optional<CrucibleItem> opt = this.itemManager.getItem(itemId.key());
|
||||||
|
return BukkitAdapter.adapt(opt.orElseThrow(() ->
|
||||||
|
new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key()))
|
||||||
|
.getMythicItem()
|
||||||
|
.generateItemStack(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Identifier[] getBlockTypes() {
|
||||||
|
KList<Identifier> names = new KList<>();
|
||||||
|
for (CrucibleItem item : this.itemManager.getItems()) {
|
||||||
|
if (item.getBlockData() == null) continue;
|
||||||
|
try {
|
||||||
|
Identifier key = new Identifier("crucible", item.getInternalName());
|
||||||
|
if (getBlockData(key) != null) {
|
||||||
|
Iris.info("getBlockTypes: Block loaded '" + item.getInternalName() + "'");
|
||||||
|
names.add(key);
|
||||||
|
}
|
||||||
|
} catch (MissingResourceException ignored) {}
|
||||||
|
}
|
||||||
|
return names.toArray(new Identifier[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Identifier[] getItemTypes() {
|
||||||
|
KList<Identifier> names = new KList<>();
|
||||||
|
for (CrucibleItem item : this.itemManager.getItems()) {
|
||||||
|
try {
|
||||||
|
Identifier key = new Identifier("crucible", item.getInternalName());
|
||||||
|
if (getItemStack(key) != null) {
|
||||||
|
Iris.info("getItemTypes: Item loaded '" + item.getInternalName() + "'");
|
||||||
|
names.add(key);
|
||||||
|
}
|
||||||
|
} catch (MissingResourceException ignored) {}
|
||||||
|
}
|
||||||
|
return names.toArray(new Identifier[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void processUpdate(@NotNull Engine engine, @NotNull Block block, @NotNull Identifier blockId) {
|
||||||
|
var pair = ExternalDataSVC.parseState(blockId);
|
||||||
|
var state = pair.getB();
|
||||||
|
blockId = pair.getA();
|
||||||
|
|
||||||
|
Optional<CrucibleItem> item = itemManager.getItem(blockId.key());
|
||||||
|
if (item.isEmpty()) return;
|
||||||
|
FurnitureItemContext furniture = item.get().getFurnitureData();
|
||||||
|
if (furniture == null) return;
|
||||||
|
|
||||||
|
float yaw = 0;
|
||||||
|
BlockFace face = BlockFace.NORTH;
|
||||||
|
long seed = engine.getSeedManager().getSeed() + Cache.key(block.getX(), block.getZ()) + block.getY();
|
||||||
|
RNG rng = new RNG(seed);
|
||||||
|
if ("true".equals(state.get("randomYaw"))) {
|
||||||
|
yaw = rng.f(0, 360);
|
||||||
|
} else if (state.containsKey("yaw")) {
|
||||||
|
yaw = Float.parseFloat(state.get("yaw"));
|
||||||
|
}
|
||||||
|
if ("true".equals(state.get("randomFace"))) {
|
||||||
|
BlockFace[] faces = BlockFace.values();
|
||||||
|
face = faces[rng.i(0, faces.length - 1)];
|
||||||
|
} else if (state.containsKey("face")) {
|
||||||
|
face = BlockFace.valueOf(state.get("face").toUpperCase());
|
||||||
|
}
|
||||||
|
if (face == BlockFace.SELF) {
|
||||||
|
face = BlockFace.NORTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
BiomeColor type = null;
|
||||||
|
Chroma color = null;
|
||||||
|
try {
|
||||||
|
type = BiomeColor.valueOf(state.get("matchBiome").toUpperCase());
|
||||||
|
} catch (NullPointerException | IllegalArgumentException ignored) {}
|
||||||
|
if (type != null) {
|
||||||
|
var biomeColor = INMS.get().getBiomeColor(block.getLocation(), type);
|
||||||
|
if (biomeColor == null) return;
|
||||||
|
color = Chroma.of(biomeColor.getRGB());
|
||||||
|
}
|
||||||
|
furniture.place(block, face, yaw, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isValidProvider(@NotNull Identifier key, boolean isItem) {
|
||||||
|
return key.namespace().equalsIgnoreCase("crucible");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,164 @@
|
|||||||
|
package com.volmit.iris.core.link;
|
||||||
|
|
||||||
|
import com.nexomc.nexo.api.NexoBlocks;
|
||||||
|
import com.nexomc.nexo.api.NexoFurniture;
|
||||||
|
import com.nexomc.nexo.api.NexoItems;
|
||||||
|
import com.nexomc.nexo.items.ItemBuilder;
|
||||||
|
import com.volmit.iris.core.nms.INMS;
|
||||||
|
import com.volmit.iris.core.nms.container.BiomeColor;
|
||||||
|
import com.volmit.iris.core.service.ExternalDataSVC;
|
||||||
|
import com.volmit.iris.engine.data.cache.Cache;
|
||||||
|
import com.volmit.iris.engine.framework.Engine;
|
||||||
|
import com.volmit.iris.util.collection.KMap;
|
||||||
|
import com.volmit.iris.util.data.B;
|
||||||
|
import com.volmit.iris.util.data.IrisBlockData;
|
||||||
|
import com.volmit.iris.util.math.RNG;
|
||||||
|
import org.bukkit.Color;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.block.BlockFace;
|
||||||
|
import org.bukkit.block.data.BlockData;
|
||||||
|
import org.bukkit.entity.ItemDisplay;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.inventory.meta.PotionMeta;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.MissingResourceException;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
public class NexoDataProvider extends ExternalDataProvider {
|
||||||
|
private final AtomicBoolean failed = new AtomicBoolean(false);
|
||||||
|
|
||||||
|
public NexoDataProvider() {
|
||||||
|
super("Nexo");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public BlockData getBlockData(@NotNull Identifier blockId, @NotNull KMap<String, String> state) throws MissingResourceException {
|
||||||
|
if (!NexoItems.exists(blockId.key())) {
|
||||||
|
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
|
||||||
|
}
|
||||||
|
|
||||||
|
Identifier blockState = ExternalDataSVC.buildState(blockId, state);
|
||||||
|
if (NexoBlocks.isCustomBlock(blockId.key())) {
|
||||||
|
BlockData data = NexoBlocks.blockData(blockId.key());
|
||||||
|
if (data == null)
|
||||||
|
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
|
||||||
|
return new IrisBlockData(data, blockState);
|
||||||
|
} else if (NexoFurniture.isFurniture(blockId.key())) {
|
||||||
|
return new IrisBlockData(B.getAir(), blockState);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public ItemStack getItemStack(@NotNull Identifier itemId, @NotNull KMap<String, Object> customNbt) throws MissingResourceException {
|
||||||
|
ItemBuilder builder = NexoItems.itemFromId(itemId.key());
|
||||||
|
if (builder == null) {
|
||||||
|
throw new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key());
|
||||||
|
}
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void processUpdate(@NotNull Engine engine, @NotNull Block block, @NotNull Identifier blockId) {
|
||||||
|
var pair = ExternalDataSVC.parseState(blockId);
|
||||||
|
var state = pair.getB();
|
||||||
|
blockId = pair.getA();
|
||||||
|
|
||||||
|
if (NexoBlocks.isCustomBlock(blockId.key())) {
|
||||||
|
NexoBlocks.place(blockId.key(), block.getLocation());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!NexoFurniture.isFurniture(blockId.key()))
|
||||||
|
return;
|
||||||
|
|
||||||
|
float yaw = 0;
|
||||||
|
BlockFace face = BlockFace.NORTH;
|
||||||
|
|
||||||
|
long seed = engine.getSeedManager().getSeed() + Cache.key(block.getX(), block.getZ()) + block.getY();
|
||||||
|
RNG rng = new RNG(seed);
|
||||||
|
if ("true".equals(state.get("randomYaw"))) {
|
||||||
|
yaw = rng.f(0, 360);
|
||||||
|
} else if (state.containsKey("yaw")) {
|
||||||
|
yaw = Float.parseFloat(state.get("yaw"));
|
||||||
|
}
|
||||||
|
if ("true".equals(state.get("randomFace"))) {
|
||||||
|
BlockFace[] faces = BlockFace.values();
|
||||||
|
face = faces[rng.i(0, faces.length - 1)];
|
||||||
|
} else if (state.containsKey("face")) {
|
||||||
|
face = BlockFace.valueOf(state.get("face").toUpperCase());
|
||||||
|
}
|
||||||
|
if (face == BlockFace.SELF) {
|
||||||
|
face = BlockFace.NORTH;
|
||||||
|
}
|
||||||
|
ItemDisplay display = NexoFurniture.place(blockId.key(), block.getLocation(), yaw, face);
|
||||||
|
if (display == null) return;
|
||||||
|
ItemStack itemStack = display.getItemStack();
|
||||||
|
if (itemStack == null) return;
|
||||||
|
|
||||||
|
BiomeColor type = null;
|
||||||
|
try {
|
||||||
|
type = BiomeColor.valueOf(state.get("matchBiome").toUpperCase());
|
||||||
|
} catch (NullPointerException | IllegalArgumentException ignored) {}
|
||||||
|
|
||||||
|
if (type != null) {
|
||||||
|
var biomeColor = INMS.get().getBiomeColor(block.getLocation(), type);
|
||||||
|
if (biomeColor == null) return;
|
||||||
|
var potionColor = Color.fromARGB(biomeColor.getAlpha(), biomeColor.getRed(), biomeColor.getGreen(), biomeColor.getBlue());
|
||||||
|
if (itemStack.getItemMeta() instanceof PotionMeta meta) {
|
||||||
|
meta.setColor(potionColor);
|
||||||
|
itemStack.setItemMeta(meta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
display.setItemStack(itemStack);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Identifier[] getBlockTypes() {
|
||||||
|
return Arrays.stream(NexoItems.itemNames())
|
||||||
|
.map(i -> new Identifier("nexo", i))
|
||||||
|
.filter(i -> {
|
||||||
|
try {
|
||||||
|
return getBlockData(i) != null;
|
||||||
|
} catch (MissingResourceException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.toArray(Identifier[]::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Identifier[] getItemTypes() {
|
||||||
|
return Arrays.stream(NexoItems.itemNames())
|
||||||
|
.map(i -> new Identifier("nexo", i))
|
||||||
|
.filter(i -> {
|
||||||
|
try {
|
||||||
|
return getItemStack(i) != null;
|
||||||
|
} catch (MissingResourceException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.toArray(Identifier[]::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isValidProvider(@NotNull Identifier id, boolean isItem) {
|
||||||
|
return "nexo".equalsIgnoreCase(id.namespace());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isReady() {
|
||||||
|
return super.isReady() && !failed.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,134 +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.link;
|
|
||||||
|
|
||||||
import com.volmit.iris.Iris;
|
|
||||||
import com.volmit.iris.util.collection.KList;
|
|
||||||
import com.volmit.iris.util.reflect.WrappedField;
|
|
||||||
import io.th0rgal.oraxen.api.OraxenItems;
|
|
||||||
import io.th0rgal.oraxen.items.ItemBuilder;
|
|
||||||
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.noteblock.NoteBlockMechanicFactory;
|
|
||||||
import io.th0rgal.oraxen.mechanics.provided.gameplay.stringblock.StringBlockMechanicFactory;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.Material;
|
|
||||||
import org.bukkit.block.data.BlockData;
|
|
||||||
import org.bukkit.block.data.MultipleFacing;
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.MissingResourceException;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
public class OraxenDataProvider extends ExternalDataProvider {
|
|
||||||
|
|
||||||
private static final String FIELD_FACTORIES_MAP = "FACTORIES_BY_MECHANIC_ID";
|
|
||||||
|
|
||||||
private WrappedField<MechanicsManager, Map<String, MechanicFactory>> factories;
|
|
||||||
|
|
||||||
public OraxenDataProvider() {
|
|
||||||
super("Oraxen");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void init() {
|
|
||||||
Iris.info("Setting up Oraxen Link...");
|
|
||||||
this.factories = new WrappedField<>(MechanicsManager.class, FIELD_FACTORIES_MAP);
|
|
||||||
if (this.factories.hasFailed()) {
|
|
||||||
Iris.error("Failed to set up Oraxen Link: Unable to fetch MechanicFactoriesMap!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BlockData getBlockData(Identifier blockId) throws MissingResourceException {
|
|
||||||
MechanicFactory factory = getFactory(blockId);
|
|
||||||
if (factory instanceof NoteBlockMechanicFactory f)
|
|
||||||
return f.createNoteBlockData(blockId.key());
|
|
||||||
else if (factory instanceof BlockMechanicFactory f) {
|
|
||||||
MultipleFacing newBlockData = (MultipleFacing) Bukkit.createBlockData(Material.MUSHROOM_STEM);
|
|
||||||
BlockMechanic.setBlockFacing(newBlockData, ((BlockMechanic) f.getMechanic(blockId.key())).getCustomVariation());
|
|
||||||
return newBlockData;
|
|
||||||
} else if (factory instanceof StringBlockMechanicFactory f) {
|
|
||||||
return f.createTripwireData(blockId.key());
|
|
||||||
} else
|
|
||||||
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ItemStack getItemStack(Identifier itemId) 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 Identifier[] getBlockTypes() {
|
|
||||||
KList<Identifier> names = new KList<>();
|
|
||||||
for (String name : OraxenItems.getItemNames()) {
|
|
||||||
try {
|
|
||||||
Identifier key = new Identifier("oraxen", name);
|
|
||||||
if (getBlockData(key) != null)
|
|
||||||
names.add(key);
|
|
||||||
} catch (MissingResourceException ignored) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return names.toArray(new Identifier[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Identifier[] getItemTypes() {
|
|
||||||
KList<Identifier> names = new KList<>();
|
|
||||||
for (String name : OraxenItems.getItemNames()) {
|
|
||||||
try {
|
|
||||||
Identifier key = new Identifier("oraxen", name);
|
|
||||||
if (getItemStack(key) != null)
|
|
||||||
names.add(key);
|
|
||||||
} catch (MissingResourceException ignored) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return names.toArray(new Identifier[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isReady() {
|
|
||||||
if (super.isReady()) {
|
|
||||||
if (factories == null) {
|
|
||||||
this.factories = new WrappedField<>(MechanicsManager.class, FIELD_FACTORIES_MAP);
|
|
||||||
}
|
|
||||||
return super.isReady() && !factories.hasFailed();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isValidProvider(Identifier key, boolean isItem) {
|
|
||||||
return key.namespace().equalsIgnoreCase("oraxen");
|
|
||||||
}
|
|
||||||
|
|
||||||
private MechanicFactory getFactory(Identifier key) throws MissingResourceException {
|
|
||||||
return factories.get().values().stream()
|
|
||||||
.filter(i -> i.getItems().contains(key.key()))
|
|
||||||
.findFirst()
|
|
||||||
.orElseThrow(() -> new MissingResourceException("Failed to find BlockData!", key.namespace(), key.key()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,31 +1,59 @@
|
|||||||
package com.volmit.iris.core.link;
|
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.Cuboid;
|
||||||
|
import com.volmit.iris.util.data.KCache;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
public class WorldEditLink {
|
public class WorldEditLink {
|
||||||
|
private static final AtomicCache<Boolean> active = new AtomicCache<>();
|
||||||
|
|
||||||
public static Cuboid getSelection(Player p) {
|
public static Cuboid getSelection(Player p) {
|
||||||
|
if (!hasWorldEdit())
|
||||||
|
return null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Object instance = Class.forName("com.sk89q.worldedit.WorldEdit").getDeclaredMethod("getInstance").invoke(null);
|
Object instance = Class.forName("com.sk89q.worldedit.WorldEdit").getDeclaredMethod("getInstance").invoke(null);
|
||||||
Object sessionManager = instance.getClass().getDeclaredMethod("getSessionManager").invoke(instance);
|
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 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());
|
if (localSession == null) return null;
|
||||||
Object region = localSession.getClass().getDeclaredMethod("getSelection", world.getClass()).invoke(localSession, world);
|
|
||||||
|
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 min = region.getClass().getDeclaredMethod("getMinimumPoint").invoke(region);
|
||||||
Object max = region.getClass().getDeclaredMethod("getMaximumPoint").invoke(region);
|
Object max = region.getClass().getDeclaredMethod("getMaximumPoint").invoke(region);
|
||||||
return new Cuboid(p.getWorld(),
|
return new Cuboid(p.getWorld(),
|
||||||
(int) min.getClass().getDeclaredMethod("getX").invoke(min),
|
(int) min.getClass().getDeclaredMethod("x").invoke(min),
|
||||||
(int) min.getClass().getDeclaredMethod("getY").invoke(min),
|
(int) min.getClass().getDeclaredMethod("y").invoke(min),
|
||||||
(int) min.getClass().getDeclaredMethod("getZ").invoke(min),
|
(int) min.getClass().getDeclaredMethod("z").invoke(min),
|
||||||
(int) min.getClass().getDeclaredMethod("getX").invoke(max),
|
(int) min.getClass().getDeclaredMethod("x").invoke(max),
|
||||||
(int) min.getClass().getDeclaredMethod("getY").invoke(max),
|
(int) min.getClass().getDeclaredMethod("y").invoke(max),
|
||||||
(int) min.getClass().getDeclaredMethod("getZ").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;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean hasWorldEdit() {
|
||||||
|
return active.aquire(() -> Bukkit.getPluginManager().isPluginEnabled("WorldEdit"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import com.volmit.iris.util.format.C;
|
|||||||
import com.volmit.iris.util.math.RNG;
|
import com.volmit.iris.util.math.RNG;
|
||||||
import com.volmit.iris.util.parallel.BurstExecutor;
|
import com.volmit.iris.util.parallel.BurstExecutor;
|
||||||
import com.volmit.iris.util.parallel.MultiBurst;
|
import com.volmit.iris.util.parallel.MultiBurst;
|
||||||
|
import com.volmit.iris.util.reflect.OldEnum;
|
||||||
import com.volmit.iris.util.scheduling.ChronoLatch;
|
import com.volmit.iris.util.scheduling.ChronoLatch;
|
||||||
import com.volmit.iris.util.scheduling.J;
|
import com.volmit.iris.util.scheduling.J;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -337,6 +338,15 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
|||||||
this.imageLoader = registerLoader(IrisImage.class);
|
this.imageLoader = registerLoader(IrisImage.class);
|
||||||
this.scriptLoader = registerLoader(IrisScript.class);
|
this.scriptLoader = registerLoader(IrisScript.class);
|
||||||
this.matterObjectLoader = registerLoader(IrisMatterObject.class);
|
this.matterObjectLoader = registerLoader(IrisMatterObject.class);
|
||||||
|
if (OldEnum.exists()) {
|
||||||
|
builder.registerTypeAdapterFactory(new TypeAdapterFactory() {
|
||||||
|
@Override
|
||||||
|
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
|
||||||
|
return (TypeAdapter<T>) OldEnum.create(type.getRawType());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
gson = builder.create();
|
gson = builder.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -434,6 +444,7 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
|||||||
return adapter.read(reader);
|
return adapter.read(reader);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
Iris.error("Failed to read " + typeToken.getRawType().getCanonicalName() + "... faking objects a little to load the file at least.");
|
Iris.error("Failed to read " + typeToken.getRawType().getCanonicalName() + "... faking objects a little to load the file at least.");
|
||||||
|
Iris.reportError(e);
|
||||||
try {
|
try {
|
||||||
return (T) typeToken.getRawType().getConstructor().newInstance();
|
return (T) typeToken.getRawType().getConstructor().newInstance();
|
||||||
} catch (Throwable ignored) {
|
} catch (Throwable ignored) {
|
||||||
|
|||||||
@@ -50,10 +50,10 @@ public class ObjectResourceLoader extends ResourceLoader<IrisObject> {
|
|||||||
try {
|
try {
|
||||||
PrecisionStopwatch p = PrecisionStopwatch.start();
|
PrecisionStopwatch p = PrecisionStopwatch.start();
|
||||||
IrisObject t = new IrisObject(0, 0, 0);
|
IrisObject t = new IrisObject(0, 0, 0);
|
||||||
t.read(j);
|
|
||||||
t.setLoadKey(name);
|
t.setLoadKey(name);
|
||||||
t.setLoader(manager);
|
t.setLoader(manager);
|
||||||
t.setLoadFile(j);
|
t.setLoadFile(j);
|
||||||
|
t.read(j);
|
||||||
logLoad(j, t);
|
logLoad(j, t);
|
||||||
tlt.addAndGet(p.getMilliseconds());
|
tlt.addAndGet(p.getMilliseconds());
|
||||||
return t;
|
return t;
|
||||||
|
|||||||
@@ -40,6 +40,8 @@ import com.volmit.iris.util.scheduling.ChronoLatch;
|
|||||||
import com.volmit.iris.util.scheduling.J;
|
import com.volmit.iris.util.scheduling.J;
|
||||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
@@ -52,6 +54,8 @@ import java.util.zip.GZIPInputStream;
|
|||||||
import java.util.zip.GZIPOutputStream;
|
import java.util.zip.GZIPOutputStream;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
|
@EqualsAndHashCode(exclude = "manager")
|
||||||
|
@ToString(exclude = "manager")
|
||||||
public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
||||||
public static final AtomicDouble tlt = new AtomicDouble(0);
|
public static final AtomicDouble tlt = new AtomicDouble(0);
|
||||||
private static final int CACHE_SIZE = 100000;
|
private static final int CACHE_SIZE = 100000;
|
||||||
@@ -358,7 +362,12 @@ public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
|||||||
if (folderCache.get() == null) {
|
if (folderCache.get() == null) {
|
||||||
KList<File> fc = new KList<>();
|
KList<File> fc = new KList<>();
|
||||||
|
|
||||||
for (File i : root.listFiles()) {
|
File[] files = root.listFiles();
|
||||||
|
if (files == null) {
|
||||||
|
throw new IllegalStateException("Failed to list files in " + root);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (File i : files) {
|
||||||
if (i.isDirectory()) {
|
if (i.isDirectory()) {
|
||||||
if (i.getName().equals(folderName)) {
|
if (i.getName().equals(folderName)) {
|
||||||
fc.add(i);
|
fc.add(i);
|
||||||
|
|||||||
@@ -23,7 +23,17 @@ import com.volmit.iris.core.IrisSettings;
|
|||||||
import com.volmit.iris.core.nms.v1X.NMSBinding1X;
|
import com.volmit.iris.core.nms.v1X.NMSBinding1X;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public class INMS {
|
public class INMS {
|
||||||
|
private static final Map<String, String> REVISION = Map.of(
|
||||||
|
"1.20.5", "v1_20_R4",
|
||||||
|
"1.20.6", "v1_20_R4",
|
||||||
|
"1.21", "v1_21_R1",
|
||||||
|
"1.21.1", "v1_21_R1",
|
||||||
|
"1.21.2", "v1_21_R2",
|
||||||
|
"1.21.3", "v1_21_R2"
|
||||||
|
);
|
||||||
//@done
|
//@done
|
||||||
private static final INMSBinding binding = bind();
|
private static final INMSBinding binding = bind();
|
||||||
|
|
||||||
@@ -37,7 +47,12 @@ public class INMS {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
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) {
|
} catch (Throwable e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
Iris.error("Failed to determine server nms version!");
|
Iris.error("Failed to determine server nms version!");
|
||||||
|
|||||||
@@ -18,28 +18,37 @@
|
|||||||
|
|
||||||
package com.volmit.iris.core.nms;
|
package com.volmit.iris.core.nms;
|
||||||
|
|
||||||
|
import com.volmit.iris.core.nms.container.BiomeColor;
|
||||||
|
import com.volmit.iris.core.nms.datapack.DataVersion;
|
||||||
import com.volmit.iris.engine.framework.Engine;
|
import com.volmit.iris.engine.framework.Engine;
|
||||||
|
import com.volmit.iris.util.collection.KList;
|
||||||
import com.volmit.iris.util.collection.KMap;
|
import com.volmit.iris.util.collection.KMap;
|
||||||
import com.volmit.iris.util.mantle.Mantle;
|
import com.volmit.iris.util.mantle.Mantle;
|
||||||
|
import com.volmit.iris.util.math.Vector3d;
|
||||||
import com.volmit.iris.util.nbt.mca.palette.MCABiomeContainer;
|
import com.volmit.iris.util.nbt.mca.palette.MCABiomeContainer;
|
||||||
import com.volmit.iris.util.nbt.mca.palette.MCAPaletteAccess;
|
import com.volmit.iris.util.nbt.mca.palette.MCAPaletteAccess;
|
||||||
import com.volmit.iris.util.nbt.tag.CompoundTag;
|
import com.volmit.iris.util.nbt.tag.CompoundTag;
|
||||||
import org.bukkit.Chunk;
|
import org.bukkit.*;
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.World;
|
|
||||||
import org.bukkit.WorldCreator;
|
|
||||||
import org.bukkit.block.Biome;
|
import org.bukkit.block.Biome;
|
||||||
import org.bukkit.entity.Dolphin;
|
import org.bukkit.entity.Dolphin;
|
||||||
import org.bukkit.entity.Entity;
|
import org.bukkit.entity.Entity;
|
||||||
|
import org.bukkit.entity.EntityType;
|
||||||
|
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||||
import org.bukkit.generator.ChunkGenerator;
|
import org.bukkit.generator.ChunkGenerator;
|
||||||
|
import org.bukkit.generator.structure.Structure;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.Color;
|
||||||
|
|
||||||
public interface INMSBinding {
|
public interface INMSBinding {
|
||||||
|
boolean hasTile(Material material);
|
||||||
|
|
||||||
boolean hasTile(Location l);
|
boolean hasTile(Location l);
|
||||||
|
|
||||||
CompoundTag serializeTile(Location location);
|
KMap<String, Object> serializeTile(Location location);
|
||||||
|
|
||||||
void deserializeTile(CompoundTag s, Location newPosition);
|
void deserializeTile(KMap<String, Object> s, Location newPosition);
|
||||||
|
|
||||||
CompoundTag serializeEntity(Entity location);
|
CompoundTag serializeEntity(Entity location);
|
||||||
|
|
||||||
@@ -71,6 +80,8 @@ public interface INMSBinding {
|
|||||||
|
|
||||||
Object getBiomeBase(Object registry, Biome biome);
|
Object getBiomeBase(Object registry, Biome biome);
|
||||||
|
|
||||||
|
KList<Biome> getBiomes();
|
||||||
|
|
||||||
boolean isBukkit();
|
boolean isBukkit();
|
||||||
|
|
||||||
int getBiomeId(Biome biome);
|
int getBiomeId(Biome biome);
|
||||||
@@ -97,7 +108,21 @@ public interface INMSBinding {
|
|||||||
|
|
||||||
ItemStack applyCustomNbt(ItemStack itemStack, KMap<String, Object> customNbt) throws IllegalArgumentException;
|
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;
|
void inject(long seed, Engine engine, World world) throws NoSuchFieldException, IllegalAccessException;
|
||||||
|
|
||||||
|
Vector3d getBoundingbox(org.bukkit.entity.EntityType entity);
|
||||||
|
|
||||||
|
Entity spawnEntity(Location location, EntityType type, CreatureSpawnEvent.SpawnReason reason);
|
||||||
|
|
||||||
|
Color getBiomeColor(Location location, BiomeColor type);
|
||||||
|
|
||||||
|
default DataVersion getDataVersion() {
|
||||||
|
return DataVersion.V1192;
|
||||||
|
}
|
||||||
|
|
||||||
|
default int getSpawnChunkCount(World world) {
|
||||||
|
return 441;
|
||||||
|
}
|
||||||
|
|
||||||
|
KList<String> getStructureKeys();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package com.volmit.iris.core.nms.container;
|
||||||
|
|
||||||
|
public enum BiomeColor {
|
||||||
|
FOG,
|
||||||
|
WATER,
|
||||||
|
WATER_FOG,
|
||||||
|
SKY,
|
||||||
|
FOLIAGE,
|
||||||
|
GRASS
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package com.volmit.iris.core.nms.datapack;
|
||||||
|
|
||||||
|
import com.volmit.iris.core.nms.INMS;
|
||||||
|
import com.volmit.iris.core.nms.datapack.v1192.DataFixerV1192;
|
||||||
|
import com.volmit.iris.core.nms.datapack.v1206.DataFixerV1206;
|
||||||
|
import com.volmit.iris.core.nms.datapack.v1213.DataFixerV1213;
|
||||||
|
import com.volmit.iris.util.collection.KMap;
|
||||||
|
import lombok.AccessLevel;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
//https://minecraft.wiki/w/Pack_format
|
||||||
|
@Getter
|
||||||
|
public enum DataVersion {
|
||||||
|
V1192("1.19.2", 10, DataFixerV1192::new),
|
||||||
|
V1205("1.20.6", 41, DataFixerV1206::new),
|
||||||
|
V1213("1.21.3", 57, DataFixerV1213::new);
|
||||||
|
private static final KMap<DataVersion, IDataFixer> cache = new KMap<>();
|
||||||
|
@Getter(AccessLevel.NONE)
|
||||||
|
private final Supplier<IDataFixer> constructor;
|
||||||
|
private final String version;
|
||||||
|
private final int packFormat;
|
||||||
|
|
||||||
|
DataVersion(String version, int packFormat, Supplier<IDataFixer> constructor) {
|
||||||
|
this.constructor = constructor;
|
||||||
|
this.packFormat = packFormat;
|
||||||
|
this.version = version;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IDataFixer get() {
|
||||||
|
return cache.computeIfAbsent(this, k -> constructor.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IDataFixer getDefault() {
|
||||||
|
return INMS.get().getDataVersion().get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DataVersion getLatest() {
|
||||||
|
return values()[values().length - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package com.volmit.iris.core.nms.datapack;
|
||||||
|
|
||||||
|
import com.volmit.iris.engine.object.IrisBiomeCustom;
|
||||||
|
import com.volmit.iris.util.json.JSONObject;
|
||||||
|
|
||||||
|
public interface IDataFixer {
|
||||||
|
|
||||||
|
JSONObject fixCustomBiome(IrisBiomeCustom biome, JSONObject json);
|
||||||
|
|
||||||
|
JSONObject fixDimension(JSONObject json);
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package com.volmit.iris.core.nms.datapack.v1192;
|
||||||
|
|
||||||
|
import com.volmit.iris.core.nms.datapack.IDataFixer;
|
||||||
|
import com.volmit.iris.engine.object.IrisBiomeCustom;
|
||||||
|
import com.volmit.iris.util.json.JSONObject;
|
||||||
|
|
||||||
|
public class DataFixerV1192 implements IDataFixer {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JSONObject fixCustomBiome(IrisBiomeCustom biome, JSONObject json) {
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JSONObject fixDimension(JSONObject json) {
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
package com.volmit.iris.core.nms.datapack.v1206;
|
||||||
|
|
||||||
|
import com.volmit.iris.core.nms.datapack.IDataFixer;
|
||||||
|
import com.volmit.iris.engine.object.IrisBiomeCustom;
|
||||||
|
import com.volmit.iris.engine.object.IrisBiomeCustomSpawn;
|
||||||
|
import com.volmit.iris.engine.object.IrisBiomeCustomSpawnType;
|
||||||
|
import com.volmit.iris.util.collection.KMap;
|
||||||
|
import com.volmit.iris.util.json.JSONArray;
|
||||||
|
import com.volmit.iris.util.json.JSONObject;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
public class DataFixerV1206 implements IDataFixer {
|
||||||
|
@Override
|
||||||
|
public JSONObject fixCustomBiome(IrisBiomeCustom biome, JSONObject json) {
|
||||||
|
int spawnRarity = biome.getSpawnRarity();
|
||||||
|
if (spawnRarity > 0) {
|
||||||
|
json.put("creature_spawn_probability", Math.min(spawnRarity/20d, 0.9999999));
|
||||||
|
} else {
|
||||||
|
json.remove("creature_spawn_probability");
|
||||||
|
}
|
||||||
|
|
||||||
|
var spawns = biome.getSpawns();
|
||||||
|
if (spawns != null && spawns.isNotEmpty()) {
|
||||||
|
JSONObject spawners = new JSONObject();
|
||||||
|
KMap<IrisBiomeCustomSpawnType, JSONArray> groups = new KMap<>();
|
||||||
|
|
||||||
|
for (IrisBiomeCustomSpawn i : spawns) {
|
||||||
|
JSONArray g = groups.computeIfAbsent(i.getGroup(), (k) -> new JSONArray());
|
||||||
|
JSONObject o = new JSONObject();
|
||||||
|
o.put("type", i.getType().getKey());
|
||||||
|
o.put("weight", i.getWeight());
|
||||||
|
o.put("minCount", i.getMinCount());
|
||||||
|
o.put("maxCount", i.getMaxCount());
|
||||||
|
g.put(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (IrisBiomeCustomSpawnType i : groups.k()) {
|
||||||
|
spawners.put(i.name().toLowerCase(Locale.ROOT), groups.get(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
json.put("spawners", spawners);
|
||||||
|
}
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JSONObject fixDimension(JSONObject json) {
|
||||||
|
if (!(json.get("monster_spawn_light_level") instanceof JSONObject lightLevel))
|
||||||
|
return json;
|
||||||
|
var value = (JSONObject) lightLevel.remove("value");
|
||||||
|
lightLevel.put("max_inclusive", value.get("max_inclusive"));
|
||||||
|
lightLevel.put("min_inclusive", value.get("min_inclusive"));
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package com.volmit.iris.core.nms.datapack.v1213;
|
||||||
|
|
||||||
|
import com.volmit.iris.core.nms.datapack.v1206.DataFixerV1206;
|
||||||
|
import com.volmit.iris.engine.object.IrisBiomeCustom;
|
||||||
|
import com.volmit.iris.util.json.JSONArray;
|
||||||
|
import com.volmit.iris.util.json.JSONObject;
|
||||||
|
|
||||||
|
public class DataFixerV1213 extends DataFixerV1206 {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JSONObject fixCustomBiome(IrisBiomeCustom biome, JSONObject json) {
|
||||||
|
json = super.fixCustomBiome(biome, json);
|
||||||
|
json.put("carvers", new JSONArray());
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -20,22 +20,27 @@ package com.volmit.iris.core.nms.v1X;
|
|||||||
|
|
||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.Iris;
|
||||||
import com.volmit.iris.core.nms.INMSBinding;
|
import com.volmit.iris.core.nms.INMSBinding;
|
||||||
import com.volmit.iris.core.nms.container.BlockPos;
|
import com.volmit.iris.core.nms.container.BiomeColor;
|
||||||
import com.volmit.iris.engine.framework.Engine;
|
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.collection.KMap;
|
||||||
import com.volmit.iris.util.mantle.Mantle;
|
import com.volmit.iris.util.mantle.Mantle;
|
||||||
|
import com.volmit.iris.util.math.Vector3d;
|
||||||
import com.volmit.iris.util.nbt.mca.palette.MCABiomeContainer;
|
import com.volmit.iris.util.nbt.mca.palette.MCABiomeContainer;
|
||||||
import com.volmit.iris.util.nbt.mca.palette.MCAPaletteAccess;
|
import com.volmit.iris.util.nbt.mca.palette.MCAPaletteAccess;
|
||||||
import com.volmit.iris.util.nbt.tag.CompoundTag;
|
import com.volmit.iris.util.nbt.tag.CompoundTag;
|
||||||
import org.bukkit.Chunk;
|
import org.bukkit.*;
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.World;
|
|
||||||
import org.bukkit.block.Biome;
|
import org.bukkit.block.Biome;
|
||||||
import org.bukkit.entity.Dolphin;
|
|
||||||
import org.bukkit.entity.Entity;
|
import org.bukkit.entity.Entity;
|
||||||
|
import org.bukkit.entity.EntityType;
|
||||||
|
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||||
import org.bukkit.generator.ChunkGenerator;
|
import org.bukkit.generator.ChunkGenerator;
|
||||||
|
import org.bukkit.generator.structure.Structure;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.util.stream.StreamSupport;
|
||||||
|
|
||||||
public class NMSBinding1X implements INMSBinding {
|
public class NMSBinding1X implements INMSBinding {
|
||||||
private static final boolean supportsCustomHeight = testCustomHeight();
|
private static final boolean supportsCustomHeight = testCustomHeight();
|
||||||
|
|
||||||
@@ -54,16 +59,27 @@ public class NMSBinding1X implements INMSBinding {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasTile(Material material) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasTile(Location l) {
|
public boolean hasTile(Location l) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompoundTag serializeTile(Location location) {
|
public KMap<String, Object> serializeTile(Location location) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deserializeTile(KMap<String, Object> s, Location newPosition) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void injectBiomesFromMantle(Chunk e, Mantle mantle) {
|
public void injectBiomesFromMantle(Chunk e, Mantle mantle) {
|
||||||
|
|
||||||
@@ -74,19 +90,32 @@ public class NMSBinding1X implements INMSBinding {
|
|||||||
return itemStack;
|
return itemStack;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setTreasurePos(Dolphin dolphin, BlockPos pos) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void inject(long seed, Engine engine, World world) throws NoSuchFieldException, IllegalAccessException {
|
public void inject(long seed, Engine engine, World world) throws NoSuchFieldException, IllegalAccessException {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public Vector3d getBoundingbox() {
|
||||||
public void deserializeTile(CompoundTag s, Location newPosition) {
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Entity spawnEntity(Location location, EntityType type, CreatureSpawnEvent.SpawnReason reason) {
|
||||||
|
return location.getWorld().spawnEntity(location, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Color getBiomeColor(Location location, BiomeColor type) {
|
||||||
|
return Color.GREEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public KList<String> getStructureKeys() {
|
||||||
|
var list = StreamSupport.stream(Registry.STRUCTURE.spliterator(), false)
|
||||||
|
.map(Structure::getKey)
|
||||||
|
.map(NamespacedKey::toString)
|
||||||
|
.toList();
|
||||||
|
return new KList<>(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -163,6 +192,11 @@ public class NMSBinding1X implements INMSBinding {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public KList<Biome> getBiomes() {
|
||||||
|
return new KList<>(Biome.values()).qdel(Biome.CUSTOM);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isBukkit() {
|
public boolean isBukkit() {
|
||||||
return true;
|
return true;
|
||||||
@@ -197,6 +231,11 @@ public class NMSBinding1X implements INMSBinding {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Vector3d getBoundingbox(org.bukkit.entity.EntityType entity) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MCAPaletteAccess createPalette() {
|
public MCAPaletteAccess createPalette() {
|
||||||
Iris.error("Cannot use the global data palette! Iris is incapable of using MCA generation on this version of minecraft!");
|
Iris.error("Cannot use the global data palette! Iris is incapable of using MCA generation on this version of minecraft!");
|
||||||
|
|||||||
@@ -0,0 +1,358 @@
|
|||||||
|
package com.volmit.iris.core.pregenerator;
|
||||||
|
|
||||||
|
import com.volmit.iris.Iris;
|
||||||
|
import com.volmit.iris.core.IrisSettings;
|
||||||
|
import com.volmit.iris.core.nms.container.Pair;
|
||||||
|
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||||
|
import com.volmit.iris.engine.data.cache.Cache;
|
||||||
|
import com.volmit.iris.engine.framework.Engine;
|
||||||
|
import com.volmit.iris.util.collection.KMap;
|
||||||
|
import com.volmit.iris.util.format.Form;
|
||||||
|
import com.volmit.iris.util.mantle.MantleFlag;
|
||||||
|
import com.volmit.iris.util.math.M;
|
||||||
|
import com.volmit.iris.util.math.Position2;
|
||||||
|
import com.volmit.iris.util.math.RollingSequence;
|
||||||
|
import com.volmit.iris.util.profile.LoadBalancer;
|
||||||
|
import com.volmit.iris.util.scheduling.J;
|
||||||
|
import io.papermc.lib.PaperLib;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Chunk;
|
||||||
|
import org.bukkit.World;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.concurrent.*;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
|
public class ChunkUpdater {
|
||||||
|
private final AtomicBoolean paused = new AtomicBoolean();
|
||||||
|
private final AtomicBoolean cancelled = new AtomicBoolean();
|
||||||
|
private final KMap<Long, Pair<Long, AtomicInteger>> lastUse = new KMap<>();
|
||||||
|
private final RollingSequence chunksPerSecond = new RollingSequence(5);
|
||||||
|
private final AtomicInteger totalMaxChunks = new AtomicInteger();
|
||||||
|
private final AtomicInteger chunksProcessed = new AtomicInteger();
|
||||||
|
private final AtomicInteger chunksProcessedLast = new AtomicInteger();
|
||||||
|
private final AtomicInteger chunksUpdated = new AtomicInteger();
|
||||||
|
private final AtomicBoolean serverEmpty = new AtomicBoolean(true);
|
||||||
|
private final AtomicLong lastCpsTime = new AtomicLong(M.ms());
|
||||||
|
private final int coreLimit = (int) Math.max(Runtime.getRuntime().availableProcessors() * IrisSettings.get().getUpdater().getThreadMultiplier(), 1);
|
||||||
|
private final Semaphore semaphore = new Semaphore(256);
|
||||||
|
private final LoadBalancer loadBalancer = new LoadBalancer(semaphore, 256, IrisSettings.get().getUpdater().emptyMsRange);
|
||||||
|
private final AtomicLong startTime = new AtomicLong();
|
||||||
|
private final Dimensions dimensions;
|
||||||
|
private final PregenTask task;
|
||||||
|
private final ExecutorService executor = Executors.newFixedThreadPool(coreLimit);
|
||||||
|
private final ExecutorService chunkExecutor = Executors.newFixedThreadPool(coreLimit);
|
||||||
|
private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
|
||||||
|
private final CountDownLatch latch;
|
||||||
|
private final Engine engine;
|
||||||
|
private final World world;
|
||||||
|
|
||||||
|
public ChunkUpdater(World world) {
|
||||||
|
this.engine = IrisToolbelt.access(world).getEngine();
|
||||||
|
this.world = world;
|
||||||
|
this.dimensions = calculateWorldDimensions(new File(world.getWorldFolder(), "region"));
|
||||||
|
this.task = dimensions.task();
|
||||||
|
this.totalMaxChunks.set(dimensions.count * 1024);
|
||||||
|
this.latch = new CountDownLatch(totalMaxChunks.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return world.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getChunks() {
|
||||||
|
return totalMaxChunks.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void start() {
|
||||||
|
unloadAndSaveAllChunks();
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean pause() {
|
||||||
|
unloadAndSaveAllChunks();
|
||||||
|
if (paused.get()) {
|
||||||
|
paused.set(false);
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
paused.set(true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stop() {
|
||||||
|
unloadAndSaveAllChunks();
|
||||||
|
cancelled.set(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void update() {
|
||||||
|
Iris.info("Updating..");
|
||||||
|
try {
|
||||||
|
startTime.set(System.currentTimeMillis());
|
||||||
|
scheduler.scheduleAtFixedRate(() -> {
|
||||||
|
try {
|
||||||
|
if (!paused.get()) {
|
||||||
|
long eta = computeETA();
|
||||||
|
int processed = chunksProcessed.get();
|
||||||
|
double last = processed - chunksProcessedLast.getAndSet(processed);
|
||||||
|
double cps = last / ((M.ms() - lastCpsTime.getAndSet(M.ms())) / 1000d);
|
||||||
|
chunksPerSecond.put(cps);
|
||||||
|
double percentage = ((double) processed / (double) totalMaxChunks.get()) * 100;
|
||||||
|
if (!cancelled.get()) {
|
||||||
|
Iris.info("Updated: " + Form.f(processed) + " of " + Form.f(totalMaxChunks.get()) + " (%.0f%%) " + Form.f(chunksPerSecond.getAverage()) + "/s, ETA: " + Form.duration(eta,
|
||||||
|
2), percentage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}, 0, 3, TimeUnit.SECONDS);
|
||||||
|
scheduler.scheduleAtFixedRate(this::unloadChunks, 0, 1, TimeUnit.SECONDS);
|
||||||
|
scheduler.scheduleAtFixedRate(() -> {
|
||||||
|
boolean empty = Bukkit.getOnlinePlayers().isEmpty();
|
||||||
|
if (serverEmpty.getAndSet(empty) == empty)
|
||||||
|
return;
|
||||||
|
loadBalancer.setRange(empty ? IrisSettings.get().getUpdater().emptyMsRange : IrisSettings.get().getUpdater().defaultMsRange);
|
||||||
|
}, 0, 10, TimeUnit.SECONDS);
|
||||||
|
|
||||||
|
var t = new Thread(() -> {
|
||||||
|
run();
|
||||||
|
close();
|
||||||
|
}, "Iris Chunk Updater - " + world.getName());
|
||||||
|
t.setPriority(Thread.MAX_PRIORITY);
|
||||||
|
t.start();
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() {
|
||||||
|
try {
|
||||||
|
loadBalancer.close();
|
||||||
|
semaphore.acquire(256);
|
||||||
|
|
||||||
|
executor.shutdown();
|
||||||
|
executor.awaitTermination(5, TimeUnit.SECONDS);
|
||||||
|
chunkExecutor.shutdown();
|
||||||
|
chunkExecutor.awaitTermination(5, TimeUnit.SECONDS);
|
||||||
|
scheduler.shutdownNow();
|
||||||
|
unloadAndSaveAllChunks();
|
||||||
|
} catch (Exception ignored) {}
|
||||||
|
if (cancelled.get()) {
|
||||||
|
Iris.info("Updated: " + Form.f(chunksUpdated.get()) + " Chunks");
|
||||||
|
Iris.info("Irritated: " + Form.f(chunksProcessed.get()) + " of " + Form.f(totalMaxChunks.get()));
|
||||||
|
Iris.info("Stopped updater.");
|
||||||
|
} else {
|
||||||
|
Iris.info("Processed: " + Form.f(chunksProcessed.get()) + " Chunks");
|
||||||
|
Iris.info("Finished Updating: " + Form.f(chunksUpdated.get()) + " Chunks");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void run() {
|
||||||
|
task.iterateRegions((rX, rZ) -> {
|
||||||
|
if (cancelled.get())
|
||||||
|
return;
|
||||||
|
|
||||||
|
while (paused.get()) {
|
||||||
|
J.sleep(50);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rX < dimensions.min.getX() || rX > dimensions.max.getX() || rZ < dimensions.min.getZ() || rZ > dimensions.max.getZ()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PregenTask.iterateRegion(rX, rZ, (x, z) -> {
|
||||||
|
while (paused.get() && !cancelled.get()) {
|
||||||
|
J.sleep(50);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
semaphore.acquire();
|
||||||
|
} catch (InterruptedException ignored) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
chunkExecutor.submit(() -> {
|
||||||
|
try {
|
||||||
|
if (!cancelled.get())
|
||||||
|
processChunk(x, z);
|
||||||
|
} finally {
|
||||||
|
latch.countDown();
|
||||||
|
semaphore.release();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processChunk(int x, int z) {
|
||||||
|
if (!loadChunksIfGenerated(x, z)) {
|
||||||
|
chunksProcessed.getAndIncrement();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Chunk c = world.getChunkAt(x, z);
|
||||||
|
engine.getMantle().getMantle().getChunk(c);
|
||||||
|
engine.updateChunk(c);
|
||||||
|
|
||||||
|
for (int xx = -1; xx <= 1; xx++) {
|
||||||
|
for (int zz = -1; zz <= 1; zz++) {
|
||||||
|
var counter = lastUse.get(Cache.key(x + xx, z + zz));
|
||||||
|
if (counter != null) counter.getB().decrementAndGet();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
chunksUpdated.incrementAndGet();
|
||||||
|
chunksProcessed.getAndIncrement();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean loadChunksIfGenerated(int x, int z) {
|
||||||
|
if (engine.getMantle().getMantle().hasFlag(x, z, MantleFlag.ETCHED))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (int dx = -1; dx <= 1; dx++) {
|
||||||
|
for (int dz = -1; dz <= 1; dz++) {
|
||||||
|
if (!PaperLib.isChunkGenerated(world, x + dx, z + dz)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AtomicBoolean generated = new AtomicBoolean(true);
|
||||||
|
CountDownLatch latch = new CountDownLatch(9);
|
||||||
|
for (int dx = -1; dx <= 1; dx++) {
|
||||||
|
for (int dz = -1; dz <= 1; dz++) {
|
||||||
|
int xx = x + dx;
|
||||||
|
int zz = z + dz;
|
||||||
|
executor.submit(() -> {
|
||||||
|
try {
|
||||||
|
Chunk c;
|
||||||
|
try {
|
||||||
|
c = PaperLib.getChunkAtAsync(world, xx, zz, false, true)
|
||||||
|
.thenApply(chunk -> {
|
||||||
|
if (chunk != null)
|
||||||
|
chunk.addPluginChunkTicket(Iris.instance);
|
||||||
|
return chunk;
|
||||||
|
}).get();
|
||||||
|
} catch (InterruptedException | ExecutionException e) {
|
||||||
|
generated.set(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c == null) {
|
||||||
|
generated.set(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!c.isLoaded()) {
|
||||||
|
var future = J.sfut(() -> c.load(false));
|
||||||
|
if (future != null) future.join();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!PaperLib.isChunkGenerated(c.getWorld(), xx, zz))
|
||||||
|
generated.set(false);
|
||||||
|
|
||||||
|
var pair = lastUse.computeIfAbsent(Cache.key(c), k -> new Pair<>(0L, new AtomicInteger(-1)));
|
||||||
|
pair.setA(M.ms());
|
||||||
|
pair.getB().updateAndGet(i -> i == -1 ? 1 : ++i);
|
||||||
|
} finally {
|
||||||
|
latch.countDown();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
latch.await();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Iris.info("Interrupted while waiting for chunks to load");
|
||||||
|
}
|
||||||
|
return generated.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
private synchronized void unloadChunks() {
|
||||||
|
for (var key : new ArrayList<>(lastUse.keySet())) {
|
||||||
|
if (key == null) continue;
|
||||||
|
var pair = lastUse.get(key);
|
||||||
|
if (pair == null) continue;
|
||||||
|
var lastUseTime = pair.getA();
|
||||||
|
var counter = pair.getB();
|
||||||
|
if (lastUseTime == null || counter == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (M.ms() - lastUseTime >= 5000 && counter.get() == 0) {
|
||||||
|
int x = Cache.keyX(key);
|
||||||
|
int z = Cache.keyZ(key);
|
||||||
|
J.s(() -> {
|
||||||
|
world.removePluginChunkTicket(x, z, Iris.instance);
|
||||||
|
world.unloadChunk(x, z);
|
||||||
|
lastUse.remove(key);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void unloadAndSaveAllChunks() {
|
||||||
|
try {
|
||||||
|
J.sfut(() -> {
|
||||||
|
if (world == null) {
|
||||||
|
Iris.warn("World was null somehow...");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
unloadChunks();
|
||||||
|
world.save();
|
||||||
|
}).get();
|
||||||
|
} catch (Throwable e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private long computeETA() {
|
||||||
|
return (long) (totalMaxChunks.get() > 1024 ? // Generated chunks exceed 1/8th of total?
|
||||||
|
// If yes, use smooth function (which gets more accurate over time since its less sensitive to outliers)
|
||||||
|
((totalMaxChunks.get() - chunksProcessed.get()) * ((double) (M.ms() - startTime.get()) / (double) chunksProcessed.get())) :
|
||||||
|
// If no, use quick function (which is less accurate over time but responds better to the initial delay)
|
||||||
|
((totalMaxChunks.get() - chunksProcessed.get()) / chunksPerSecond.getAverage()) * 1000
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Dimensions calculateWorldDimensions(File regionDir) {
|
||||||
|
File[] files = regionDir.listFiles((dir, name) -> name.endsWith(".mca"));
|
||||||
|
|
||||||
|
int minX = Integer.MAX_VALUE;
|
||||||
|
int maxX = Integer.MIN_VALUE;
|
||||||
|
int minZ = Integer.MAX_VALUE;
|
||||||
|
int maxZ = Integer.MIN_VALUE;
|
||||||
|
|
||||||
|
for (File file : files) {
|
||||||
|
String[] parts = file.getName().split("\\.");
|
||||||
|
int x = Integer.parseInt(parts[1]);
|
||||||
|
int z = Integer.parseInt(parts[2]);
|
||||||
|
|
||||||
|
minX = Math.min(minX, x);
|
||||||
|
maxX = Math.max(maxX, x);
|
||||||
|
minZ = Math.min(minZ, z);
|
||||||
|
maxZ = Math.max(maxZ, z);
|
||||||
|
}
|
||||||
|
int oX = minX + ((maxX - minX) / 2);
|
||||||
|
int oZ = minZ + ((maxZ - minZ) / 2);
|
||||||
|
|
||||||
|
int height = maxX - minX + 1;
|
||||||
|
int width = maxZ - minZ + 1;
|
||||||
|
|
||||||
|
return new Dimensions(new Position2(minX, minZ), new Position2(maxX, maxZ), height * width, PregenTask.builder()
|
||||||
|
.width((int) Math.ceil(width / 2d))
|
||||||
|
.height((int) Math.ceil(height / 2d))
|
||||||
|
.center(new Position2(oX, oZ))
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
private record Dimensions(Position2 min, Position2 max, int count, PregenTask task) { }
|
||||||
|
}
|
||||||
@@ -0,0 +1,274 @@
|
|||||||
|
package com.volmit.iris.core.pregenerator;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.volmit.iris.Iris;
|
||||||
|
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||||
|
import com.volmit.iris.engine.framework.Engine;
|
||||||
|
import com.volmit.iris.engine.object.IrisBiome;
|
||||||
|
import com.volmit.iris.util.collection.KList;
|
||||||
|
import com.volmit.iris.util.format.C;
|
||||||
|
import com.volmit.iris.util.format.Form;
|
||||||
|
import com.volmit.iris.util.io.IO;
|
||||||
|
import com.volmit.iris.util.math.M;
|
||||||
|
import com.volmit.iris.util.math.Position2;
|
||||||
|
import com.volmit.iris.util.math.RollingSequence;
|
||||||
|
import com.volmit.iris.util.math.Spiraler;
|
||||||
|
import com.volmit.iris.util.scheduling.ChronoLatch;
|
||||||
|
import com.volmit.iris.util.scheduling.J;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.Getter;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.world.WorldUnloadEvent;
|
||||||
|
import org.bukkit.scheduler.BukkitRunnable;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileWriter;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
|
||||||
|
public class DeepSearchPregenerator extends Thread implements Listener {
|
||||||
|
@Getter
|
||||||
|
private static DeepSearchPregenerator instance;
|
||||||
|
private final DeepSearchJob job;
|
||||||
|
private final File destination;
|
||||||
|
private final int maxPosition;
|
||||||
|
private World world;
|
||||||
|
private final ChronoLatch latch;
|
||||||
|
private static AtomicInteger foundChunks;
|
||||||
|
private final AtomicInteger foundLast;
|
||||||
|
private final AtomicInteger foundTotalChunks;
|
||||||
|
private final AtomicLong startTime;
|
||||||
|
private final RollingSequence chunksPerSecond;
|
||||||
|
private final RollingSequence chunksPerMinute;
|
||||||
|
private final AtomicInteger chunkCachePos;
|
||||||
|
private final AtomicInteger chunkCacheSize;
|
||||||
|
private int pos;
|
||||||
|
private final AtomicInteger foundCacheLast;
|
||||||
|
private final AtomicInteger foundCache;
|
||||||
|
private LinkedHashMap<Integer, Position2> chunkCache;
|
||||||
|
private KList<Position2> chunkQueue;
|
||||||
|
private final ReentrantLock cacheLock;
|
||||||
|
|
||||||
|
private static final Map<String, DeepSearchJob> jobs = new HashMap<>();
|
||||||
|
|
||||||
|
public DeepSearchPregenerator(DeepSearchJob job, File destination) {
|
||||||
|
this.job = job;
|
||||||
|
this.chunkCacheSize = new AtomicInteger(); // todo
|
||||||
|
this.chunkCachePos = new AtomicInteger(1000);
|
||||||
|
this.foundCacheLast = new AtomicInteger();
|
||||||
|
this.foundCache = new AtomicInteger();
|
||||||
|
this.cacheLock = new ReentrantLock();
|
||||||
|
this.destination = destination;
|
||||||
|
this.chunkCache = new LinkedHashMap<>();
|
||||||
|
this.maxPosition = new Spiraler(job.getRadiusBlocks() * 2, job.getRadiusBlocks() * 2, (x, z) -> {
|
||||||
|
}).count();
|
||||||
|
this.world = Bukkit.getWorld(job.getWorld().getUID());
|
||||||
|
this.chunkQueue = new KList<>();
|
||||||
|
this.latch = new ChronoLatch(3000);
|
||||||
|
this.startTime = new AtomicLong(M.ms());
|
||||||
|
this.chunksPerSecond = new RollingSequence(10);
|
||||||
|
this.chunksPerMinute = new RollingSequence(10);
|
||||||
|
foundChunks = new AtomicInteger(0);
|
||||||
|
this.foundLast = new AtomicInteger(0);
|
||||||
|
this.foundTotalChunks = new AtomicInteger((int) Math.ceil(Math.pow((2.0 * job.getRadiusBlocks()) / 16, 2)));
|
||||||
|
|
||||||
|
this.pos = 0;
|
||||||
|
jobs.put(job.getWorld().getName(), job);
|
||||||
|
DeepSearchPregenerator.instance = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void on(WorldUnloadEvent e) {
|
||||||
|
if (e.getWorld().equals(world)) {
|
||||||
|
interrupt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
while (!interrupted()) {
|
||||||
|
tick();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
saveNow();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void tick() {
|
||||||
|
DeepSearchJob job = jobs.get(world.getName());
|
||||||
|
// chunkCache(); //todo finish this
|
||||||
|
if (latch.flip() && !job.paused) {
|
||||||
|
if (cacheLock.isLocked()) {
|
||||||
|
Iris.info("DeepFinder: Caching: " + chunkCachePos.get() + " Of " + chunkCacheSize.get());
|
||||||
|
} else {
|
||||||
|
long eta = computeETA();
|
||||||
|
save();
|
||||||
|
int secondGenerated = foundChunks.get() - foundLast.get();
|
||||||
|
foundLast.set(foundChunks.get());
|
||||||
|
secondGenerated = secondGenerated / 3;
|
||||||
|
chunksPerSecond.put(secondGenerated);
|
||||||
|
chunksPerMinute.put(secondGenerated * 60);
|
||||||
|
Iris.info("DeepFinder: " + C.IRIS + world.getName() + C.RESET + " Searching: " + Form.f(foundChunks.get()) + " of " + Form.f(foundTotalChunks.get()) + " " + Form.f((int) chunksPerSecond.getAverage()) + "/s ETA: " + Form.duration((double) eta, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if (foundChunks.get() >= foundTotalChunks.get()) {
|
||||||
|
Iris.info("Completed DeepSearch!");
|
||||||
|
interrupt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private long computeETA() {
|
||||||
|
return (long) ((foundTotalChunks.get() - foundChunks.get()) / chunksPerSecond.getAverage()) * 1000;
|
||||||
|
// todo broken
|
||||||
|
}
|
||||||
|
|
||||||
|
private final ExecutorService executorService = Executors.newSingleThreadExecutor();
|
||||||
|
|
||||||
|
private void queueSystem(Position2 chunk) {
|
||||||
|
if (chunkQueue.isEmpty()) {
|
||||||
|
for (int limit = 512; limit != 0; limit--) {
|
||||||
|
pos = job.getPosition() + 1;
|
||||||
|
chunkQueue.add(getChunk(pos));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//MCAUtil.read();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void findInChunk(World world, int x, int z) throws IOException {
|
||||||
|
int xx = x * 16;
|
||||||
|
int zz = z * 16;
|
||||||
|
Engine engine = IrisToolbelt.access(world).getEngine();
|
||||||
|
for (int i = 0; i < 16; i++) {
|
||||||
|
for (int j = 0; j < 16; j++) {
|
||||||
|
int height = engine.getHeight(xx + i, zz + j);
|
||||||
|
if (height > 300) {
|
||||||
|
File found = new File("plugins" + "iris" + "found.txt");
|
||||||
|
FileWriter writer = new FileWriter(found);
|
||||||
|
if (!found.exists()) {
|
||||||
|
found.createNewFile();
|
||||||
|
}
|
||||||
|
IrisBiome biome = engine.getBiome(xx, engine.getHeight(), zz);
|
||||||
|
Iris.info("Found at! " + xx + ", " + zz + "Biome ID: " + biome.getName() + ", ");
|
||||||
|
writer.write("Biome at: X: " + xx + " Z: " + zz + "Biome ID: " + biome.getName() + ", ");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Position2 getChunk(int position) {
|
||||||
|
int p = -1;
|
||||||
|
AtomicInteger xx = new AtomicInteger();
|
||||||
|
AtomicInteger zz = new AtomicInteger();
|
||||||
|
Spiraler s = new Spiraler(job.getRadiusBlocks() * 2, job.getRadiusBlocks() * 2, (x, z) -> {
|
||||||
|
xx.set(x);
|
||||||
|
zz.set(z);
|
||||||
|
});
|
||||||
|
|
||||||
|
while (s.hasNext() && p++ < position) {
|
||||||
|
s.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Position2(xx.get(), zz.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void save() {
|
||||||
|
J.a(() -> {
|
||||||
|
try {
|
||||||
|
saveNow();
|
||||||
|
} catch (Throwable e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setPausedDeep(World world) {
|
||||||
|
DeepSearchJob job = jobs.get(world.getName());
|
||||||
|
if (isPausedDeep(world)){
|
||||||
|
job.paused = false;
|
||||||
|
} else {
|
||||||
|
job.paused = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( job.paused) {
|
||||||
|
Iris.info(C.BLUE + "DeepSearch: " + C.IRIS + world.getName() + C.BLUE + " Paused");
|
||||||
|
} else {
|
||||||
|
Iris.info(C.BLUE + "DeepSearch: " + C.IRIS + world.getName() + C.BLUE + " Resumed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isPausedDeep(World world) {
|
||||||
|
DeepSearchJob job = jobs.get(world.getName());
|
||||||
|
return job != null && job.isPaused();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void shutdownInstance(World world) throws IOException {
|
||||||
|
Iris.info("DeepSearch: " + C.IRIS + world.getName() + C.BLUE + " Shutting down..");
|
||||||
|
DeepSearchJob job = jobs.get(world.getName());
|
||||||
|
File worldDirectory = new File(Bukkit.getWorldContainer(), world.getName());
|
||||||
|
File deepFile = new File(worldDirectory, "DeepSearch.json");
|
||||||
|
|
||||||
|
if (job == null) {
|
||||||
|
Iris.error("No DeepSearch job found for world: " + world.getName());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (!job.isPaused()) {
|
||||||
|
job.setPaused(true);
|
||||||
|
}
|
||||||
|
save();
|
||||||
|
jobs.remove(world.getName());
|
||||||
|
new BukkitRunnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
while (deepFile.exists()){
|
||||||
|
deepFile.delete();
|
||||||
|
J.sleep(1000);
|
||||||
|
}
|
||||||
|
Iris.info("DeepSearch: " + C.IRIS + world.getName() + C.BLUE + " File deleted and instance closed.");
|
||||||
|
}
|
||||||
|
}.runTaskLater(Iris.instance, 20L);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Iris.error("Failed to shutdown DeepSearch for " + world.getName());
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
saveNow();
|
||||||
|
interrupt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void saveNow() throws IOException {
|
||||||
|
IO.writeAll(this.destination, new Gson().toJson(job));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@lombok.Builder
|
||||||
|
public static class DeepSearchJob {
|
||||||
|
private World world;
|
||||||
|
@lombok.Builder.Default
|
||||||
|
private int radiusBlocks = 5000;
|
||||||
|
@lombok.Builder.Default
|
||||||
|
private int position = 0;
|
||||||
|
@lombok.Builder.Default
|
||||||
|
boolean paused = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -19,7 +19,9 @@
|
|||||||
package com.volmit.iris.core.pregenerator;
|
package com.volmit.iris.core.pregenerator;
|
||||||
|
|
||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.Iris;
|
||||||
|
import com.volmit.iris.core.pack.IrisPack;
|
||||||
import com.volmit.iris.core.tools.IrisPackBenchmarking;
|
import com.volmit.iris.core.tools.IrisPackBenchmarking;
|
||||||
|
import com.volmit.iris.util.collection.KList;
|
||||||
import com.volmit.iris.util.collection.KSet;
|
import com.volmit.iris.util.collection.KSet;
|
||||||
import com.volmit.iris.util.format.C;
|
import com.volmit.iris.util.format.C;
|
||||||
import com.volmit.iris.util.format.Form;
|
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.ChronoLatch;
|
||||||
import com.volmit.iris.util.scheduling.J;
|
import com.volmit.iris.util.scheduling.J;
|
||||||
import com.volmit.iris.util.scheduling.Looper;
|
import com.volmit.iris.util.scheduling.Looper;
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
import static com.volmit.iris.core.tools.IrisPackBenchmarking.benchmark;
|
|
||||||
|
|
||||||
public class IrisPregenerator {
|
public class IrisPregenerator {
|
||||||
private final PregenTask task;
|
private final PregenTask task;
|
||||||
@@ -50,6 +49,7 @@ public class IrisPregenerator {
|
|||||||
private final RollingSequence chunksPerSecond;
|
private final RollingSequence chunksPerSecond;
|
||||||
private final RollingSequence chunksPerMinute;
|
private final RollingSequence chunksPerMinute;
|
||||||
private final RollingSequence regionsPerMinute;
|
private final RollingSequence regionsPerMinute;
|
||||||
|
private final KList<Integer> chunksPerSecondHistory;
|
||||||
private static AtomicInteger generated;
|
private static AtomicInteger generated;
|
||||||
private final AtomicInteger generatedLast;
|
private final AtomicInteger generatedLast;
|
||||||
private final AtomicInteger generatedLastMinute;
|
private final AtomicInteger generatedLastMinute;
|
||||||
@@ -62,8 +62,6 @@ public class IrisPregenerator {
|
|||||||
private final KSet<Position2> net;
|
private final KSet<Position2> net;
|
||||||
private final ChronoLatch cl;
|
private final ChronoLatch cl;
|
||||||
private final ChronoLatch saveLatch = new ChronoLatch(30000);
|
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) {
|
public IrisPregenerator(PregenTask task, PregeneratorMethod generator, PregenListener listener) {
|
||||||
this.listener = listenify(listener);
|
this.listener = listenify(listener);
|
||||||
@@ -80,6 +78,7 @@ public class IrisPregenerator {
|
|||||||
chunksPerSecond = new RollingSequence(10);
|
chunksPerSecond = new RollingSequence(10);
|
||||||
chunksPerMinute = new RollingSequence(10);
|
chunksPerMinute = new RollingSequence(10);
|
||||||
regionsPerMinute = new RollingSequence(10);
|
regionsPerMinute = new RollingSequence(10);
|
||||||
|
chunksPerSecondHistory = new KList<>();
|
||||||
generated = new AtomicInteger(0);
|
generated = new AtomicInteger(0);
|
||||||
generatedLast = new AtomicInteger(0);
|
generatedLast = new AtomicInteger(0);
|
||||||
generatedLastMinute = new AtomicInteger(0);
|
generatedLastMinute = new AtomicInteger(0);
|
||||||
@@ -93,6 +92,7 @@ public class IrisPregenerator {
|
|||||||
int secondGenerated = generated.get() - generatedLast.get();
|
int secondGenerated = generated.get() - generatedLast.get();
|
||||||
generatedLast.set(generated.get());
|
generatedLast.set(generated.get());
|
||||||
chunksPerSecond.put(secondGenerated);
|
chunksPerSecond.put(secondGenerated);
|
||||||
|
chunksPerSecondHistory.add(secondGenerated);
|
||||||
|
|
||||||
if (minuteLatch.flip()) {
|
if (minuteLatch.flip()) {
|
||||||
int minuteGenerated = generated.get() - generatedLastMinute.get();
|
int minuteGenerated = generated.get() - generatedLastMinute.get();
|
||||||
@@ -100,8 +100,6 @@ public class IrisPregenerator {
|
|||||||
chunksPerMinute.put(minuteGenerated);
|
chunksPerMinute.put(minuteGenerated);
|
||||||
regionsPerMinute.put((double) minuteGenerated / 1024D);
|
regionsPerMinute.put((double) minuteGenerated / 1024D);
|
||||||
}
|
}
|
||||||
long_generatedChunks = generated.get();
|
|
||||||
long_totalChunks = totalChunks.get();
|
|
||||||
|
|
||||||
listener.onTick(chunksPerSecond.getAverage(), chunksPerMinute.getAverage(),
|
listener.onTick(chunksPerSecond.getAverage(), chunksPerMinute.getAverage(),
|
||||||
regionsPerMinute.getAverage(),
|
regionsPerMinute.getAverage(),
|
||||||
@@ -112,10 +110,10 @@ public class IrisPregenerator {
|
|||||||
|
|
||||||
if (cl.flip()) {
|
if (cl.flip()) {
|
||||||
double percentage = ((double) generated.get() / (double) totalChunks.get()) * 100;
|
double percentage = ((double) generated.get() / (double) totalChunks.get()) * 100;
|
||||||
if(benchmark) {
|
if (!IrisPackBenchmarking.benchmarkInProgress) {
|
||||||
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);
|
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 {
|
} 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;
|
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)
|
// 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())) :
|
((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)
|
// 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() {
|
public void close() {
|
||||||
shutdown.set(true);
|
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, true));
|
||||||
task.iterateRegions((x, z) -> visitRegion(x, z, false));
|
task.iterateRegions((x, z) -> visitRegion(x, z, false));
|
||||||
shutdown();
|
shutdown();
|
||||||
|
if (!IrisPackBenchmarking.benchmarkInProgress) {
|
||||||
|
Iris.info(C.IRIS + "Pregen stopped.");
|
||||||
|
} else {
|
||||||
|
IrisPackBenchmarking.instance.finishedBenchmark(chunksPerSecondHistory);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkRegions() {
|
private void checkRegions() {
|
||||||
@@ -167,7 +163,10 @@ public class IrisPregenerator {
|
|||||||
generator.close();
|
generator.close();
|
||||||
ticker.interrupt();
|
ticker.interrupt();
|
||||||
listener.onClose();
|
listener.onClose();
|
||||||
getMantle().trim(0);
|
Mantle mantle = getMantle();
|
||||||
|
if (mantle != null) {
|
||||||
|
mantle.trim(0, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void visitRegion(int x, int z, boolean regions) {
|
private void visitRegion(int x, int z, boolean regions) {
|
||||||
|
|||||||
@@ -12,24 +12,33 @@ import com.volmit.iris.util.math.Spiraler;
|
|||||||
import com.volmit.iris.util.scheduling.ChronoLatch;
|
import com.volmit.iris.util.scheduling.ChronoLatch;
|
||||||
import com.volmit.iris.util.scheduling.J;
|
import com.volmit.iris.util.scheduling.J;
|
||||||
import io.papermc.lib.PaperLib;
|
import io.papermc.lib.PaperLib;
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import lombok.Getter;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.event.world.WorldUnloadEvent;
|
import org.bukkit.event.world.WorldUnloadEvent;
|
||||||
|
import org.bukkit.scheduler.BukkitRunnable;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
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.AtomicInteger;
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public class LazyPregenerator extends Thread implements Listener {
|
public class LazyPregenerator extends Thread implements Listener {
|
||||||
|
@Getter
|
||||||
|
private static LazyPregenerator instance;
|
||||||
private final LazyPregenJob job;
|
private final LazyPregenJob job;
|
||||||
private final File destination;
|
private final File destination;
|
||||||
private final int maxPosition;
|
private final int maxPosition;
|
||||||
private final World world;
|
private World world;
|
||||||
private final long rate;
|
private final long rate;
|
||||||
private final ChronoLatch latch;
|
private final ChronoLatch latch;
|
||||||
private static AtomicInteger lazyGeneratedChunks;
|
private static AtomicInteger lazyGeneratedChunks;
|
||||||
@@ -37,6 +46,9 @@ public class LazyPregenerator extends Thread implements Listener {
|
|||||||
private final AtomicInteger lazyTotalChunks;
|
private final AtomicInteger lazyTotalChunks;
|
||||||
private final AtomicLong startTime;
|
private final AtomicLong startTime;
|
||||||
private final RollingSequence chunksPerSecond;
|
private final RollingSequence chunksPerSecond;
|
||||||
|
private final RollingSequence chunksPerMinute;
|
||||||
|
|
||||||
|
private static final Map<String, LazyPregenJob> jobs = new HashMap<>();
|
||||||
|
|
||||||
public LazyPregenerator(LazyPregenJob job, File destination) {
|
public LazyPregenerator(LazyPregenJob job, File destination) {
|
||||||
this.job = job;
|
this.job = job;
|
||||||
@@ -44,16 +56,16 @@ public class LazyPregenerator extends Thread implements Listener {
|
|||||||
this.maxPosition = new Spiraler(job.getRadiusBlocks() * 2, job.getRadiusBlocks() * 2, (x, z) -> {
|
this.maxPosition = new Spiraler(job.getRadiusBlocks() * 2, job.getRadiusBlocks() * 2, (x, z) -> {
|
||||||
}).count();
|
}).count();
|
||||||
this.world = Bukkit.getWorld(job.getWorld());
|
this.world = Bukkit.getWorld(job.getWorld());
|
||||||
this.rate = Math.round((1D / (job.chunksPerMinute / 60D)) * 1000D);
|
this.rate = Math.round((1D / (job.getChunksPerMinute() / 60D)) * 1000D);
|
||||||
this.latch = new ChronoLatch(6000);
|
this.latch = new ChronoLatch(15000);
|
||||||
startTime = new AtomicLong(M.ms());
|
this.startTime = new AtomicLong(M.ms());
|
||||||
chunksPerSecond = new RollingSequence(10);
|
this.chunksPerSecond = new RollingSequence(10);
|
||||||
|
this.chunksPerMinute = new RollingSequence(10);
|
||||||
lazyGeneratedChunks = new AtomicInteger(0);
|
lazyGeneratedChunks = new AtomicInteger(0);
|
||||||
generatedLast = new AtomicInteger(0);
|
this.generatedLast = new AtomicInteger(0);
|
||||||
lazyTotalChunks = new AtomicInteger();
|
this.lazyTotalChunks = new AtomicInteger((int) Math.ceil(Math.pow((2.0 * job.getRadiusBlocks()) / 16, 2)));
|
||||||
|
jobs.put(job.getWorld(), job);
|
||||||
int radius = job.getRadiusBlocks();
|
LazyPregenerator.instance = this;
|
||||||
lazyTotalChunks.set((int) Math.ceil(Math.pow((2.0 * radius) / 16, 2)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public LazyPregenerator(File file) throws IOException {
|
public LazyPregenerator(File file) throws IOException {
|
||||||
@@ -63,7 +75,6 @@ public class LazyPregenerator extends Thread implements Listener {
|
|||||||
public static void loadLazyGenerators() {
|
public static void loadLazyGenerators() {
|
||||||
for (World i : Bukkit.getWorlds()) {
|
for (World i : Bukkit.getWorlds()) {
|
||||||
File lazygen = new File(i.getWorldFolder(), "lazygen.json");
|
File lazygen = new File(i.getWorldFolder(), "lazygen.json");
|
||||||
|
|
||||||
if (lazygen.exists()) {
|
if (lazygen.exists()) {
|
||||||
try {
|
try {
|
||||||
LazyPregenerator p = new LazyPregenerator(lazygen);
|
LazyPregenerator p = new LazyPregenerator(lazygen);
|
||||||
@@ -97,18 +108,18 @@ public class LazyPregenerator extends Thread implements Listener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void tick() {
|
public void tick() {
|
||||||
if (latch.flip()) {
|
LazyPregenJob job = jobs.get(world.getName());
|
||||||
|
if (latch.flip() && !job.paused) {
|
||||||
long eta = computeETA();
|
long eta = computeETA();
|
||||||
save();
|
save();
|
||||||
int secondGenerated = lazyGeneratedChunks.get() - generatedLast.get();
|
int secondGenerated = lazyGeneratedChunks.get() - generatedLast.get();
|
||||||
generatedLast.set(lazyGeneratedChunks.get());
|
generatedLast.set(lazyGeneratedChunks.get());
|
||||||
secondGenerated = secondGenerated / 6;
|
secondGenerated = secondGenerated / 15;
|
||||||
chunksPerSecond.put(secondGenerated);
|
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));
|
chunksPerMinute.put(secondGenerated * 60);
|
||||||
//Iris.info("Debug: " + maxPosition);
|
if (!job.isSilent()) {
|
||||||
//Iris.info("Debug1: " + job.getPosition());
|
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));
|
||||||
|
}
|
||||||
// todo: Maxpos borked
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lazyGeneratedChunks.get() >= lazyTotalChunks.get()) {
|
if (lazyGeneratedChunks.get() >= lazyTotalChunks.get()) {
|
||||||
@@ -123,27 +134,40 @@ public class LazyPregenerator extends Thread implements Listener {
|
|||||||
} else {
|
} else {
|
||||||
int pos = job.getPosition() + 1;
|
int pos = job.getPosition() + 1;
|
||||||
job.setPosition(pos);
|
job.setPosition(pos);
|
||||||
tickGenerate(getChunk(pos));
|
if (!job.paused) {
|
||||||
|
tickGenerate(getChunk(pos));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private long computeETA() {
|
private long computeETA() {
|
||||||
return (long) (lazyTotalChunks.get() > 1024 ? // Generated chunks exceed 1/8th of total?
|
return (long) ((lazyTotalChunks.get() - lazyGeneratedChunks.get()) / chunksPerMinute.getAverage()) * 1000;
|
||||||
// If yes, use smooth function (which gets more accurate over time since its less sensitive to outliers)
|
// todo broken
|
||||||
((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 //
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final ExecutorService executorService = Executors.newSingleThreadExecutor();
|
||||||
|
|
||||||
private void tickGenerate(Position2 chunk) {
|
private void tickGenerate(Position2 chunk) {
|
||||||
if (PaperLib.isPaper()) {
|
executorService.submit(() -> {
|
||||||
PaperLib.getChunkAtAsync(world, chunk.getX(), chunk.getZ(), true).thenAccept((i) -> Iris.verbose("Generated Async " + chunk));
|
CountDownLatch latch = new CountDownLatch(1);
|
||||||
} else {
|
if (PaperLib.isPaper()) {
|
||||||
J.s(() -> world.getChunkAt(chunk.getX(), chunk.getZ()));
|
PaperLib.getChunkAtAsync(world, chunk.getX(), chunk.getZ(), true)
|
||||||
Iris.verbose("Generated " + chunk);
|
.thenAccept((i) -> {
|
||||||
}
|
Iris.verbose("Generated Async " + chunk);
|
||||||
lazyGeneratedChunks.addAndGet(1);
|
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) {
|
private void tickRegenerate(Position2 chunk) {
|
||||||
@@ -177,23 +201,85 @@ 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 {
|
public void saveNow() throws IOException {
|
||||||
IO.writeAll(this.destination, new Gson().toJson(job));
|
IO.writeAll(this.destination, new Gson().toJson(job));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@Builder
|
@lombok.Builder
|
||||||
public static class LazyPregenJob {
|
public static class LazyPregenJob {
|
||||||
private String world;
|
private String world;
|
||||||
@Builder.Default
|
@lombok.Builder.Default
|
||||||
private int healingPosition = 0;
|
private int healingPosition = 0;
|
||||||
@Builder.Default
|
@lombok.Builder.Default
|
||||||
private boolean healing = false;
|
private boolean healing = false;
|
||||||
@Builder.Default
|
@lombok.Builder.Default
|
||||||
private int chunksPerMinute = 32; // 48 hours is roughly 5000 radius
|
private int chunksPerMinute = 32;
|
||||||
@Builder.Default
|
@lombok.Builder.Default
|
||||||
private int radiusBlocks = 5000;
|
private int radiusBlocks = 5000;
|
||||||
@Builder.Default
|
@lombok.Builder.Default
|
||||||
private int position = 0;
|
private int position = 0;
|
||||||
|
@lombok.Builder.Default
|
||||||
|
boolean silent = false;
|
||||||
|
@lombok.Builder.Default
|
||||||
|
boolean paused = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ public class PregenTask {
|
|||||||
private static final KList<Position2> ORDER_CENTER = computeChunkOrder();
|
private static final KList<Position2> ORDER_CENTER = computeChunkOrder();
|
||||||
private static final KMap<Position2, KList<Position2>> ORDERS = new KMap<>();
|
private static final KMap<Position2, KList<Position2>> ORDERS = new KMap<>();
|
||||||
|
|
||||||
|
@Builder.Default
|
||||||
|
private boolean gui = false;
|
||||||
@Builder.Default
|
@Builder.Default
|
||||||
private Position2 center = new Position2(0, 0);
|
private Position2 center = new Position2(0, 0);
|
||||||
@Builder.Default
|
@Builder.Default
|
||||||
|
|||||||
@@ -0,0 +1,341 @@
|
|||||||
|
package com.volmit.iris.core.pregenerator;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.volmit.iris.Iris;
|
||||||
|
import com.volmit.iris.core.IrisSettings;
|
||||||
|
import com.volmit.iris.util.collection.KList;
|
||||||
|
import com.volmit.iris.util.format.C;
|
||||||
|
import com.volmit.iris.util.format.Form;
|
||||||
|
import com.volmit.iris.util.io.IO;
|
||||||
|
import com.volmit.iris.util.math.M;
|
||||||
|
import com.volmit.iris.util.math.Position2;
|
||||||
|
import com.volmit.iris.util.math.RollingSequence;
|
||||||
|
import com.volmit.iris.util.math.Spiraler;
|
||||||
|
import com.volmit.iris.util.parallel.BurstExecutor;
|
||||||
|
import com.volmit.iris.util.parallel.HyperLock;
|
||||||
|
import com.volmit.iris.util.parallel.MultiBurst;
|
||||||
|
import com.volmit.iris.util.scheduling.ChronoLatch;
|
||||||
|
import com.volmit.iris.util.scheduling.J;
|
||||||
|
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||||
|
import io.papermc.lib.PaperLib;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.Getter;
|
||||||
|
import org.apache.logging.log4j.core.util.ExecutorServices;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.world.WorldUnloadEvent;
|
||||||
|
import org.bukkit.scheduler.BukkitRunnable;
|
||||||
|
import org.checkerframework.checker.units.qual.N;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.Array;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.*;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
|
public class TurboPregenerator extends Thread implements Listener {
|
||||||
|
@Getter
|
||||||
|
private static TurboPregenerator instance;
|
||||||
|
private final TurboPregenJob job;
|
||||||
|
private final File destination;
|
||||||
|
private final int maxPosition;
|
||||||
|
private World world;
|
||||||
|
private final ChronoLatch latch;
|
||||||
|
private static AtomicInteger turboGeneratedChunks;
|
||||||
|
private final AtomicInteger generatedLast;
|
||||||
|
private final AtomicLong cachedLast;
|
||||||
|
private final RollingSequence cachePerSecond;
|
||||||
|
private final AtomicInteger turboTotalChunks;
|
||||||
|
private final AtomicLong startTime;
|
||||||
|
private final RollingSequence chunksPerSecond;
|
||||||
|
private final RollingSequence chunksPerMinute;
|
||||||
|
private KList<Position2> queue;
|
||||||
|
private ConcurrentHashMap<Integer, Position2> cache;
|
||||||
|
private AtomicInteger maxWaiting;
|
||||||
|
private ReentrantLock cachinglock;
|
||||||
|
private AtomicBoolean caching;
|
||||||
|
private final HyperLock hyperLock;
|
||||||
|
private MultiBurst burst;
|
||||||
|
private static final Map<String, TurboPregenJob> jobs = new HashMap<>();
|
||||||
|
|
||||||
|
public TurboPregenerator(TurboPregenJob job, File destination) {
|
||||||
|
this.job = job;
|
||||||
|
queue = new KList<>(512);
|
||||||
|
this.maxWaiting = new AtomicInteger(128);
|
||||||
|
this.destination = destination;
|
||||||
|
this.maxPosition = new Spiraler(job.getRadiusBlocks() * 2, job.getRadiusBlocks() * 2, (x, z) -> {
|
||||||
|
}).count();
|
||||||
|
this.world = Bukkit.getWorld(job.getWorld());
|
||||||
|
this.latch = new ChronoLatch(3000);
|
||||||
|
this.burst = MultiBurst.burst;
|
||||||
|
this.hyperLock = new HyperLock();
|
||||||
|
this.startTime = new AtomicLong(M.ms());
|
||||||
|
this.cachePerSecond = new RollingSequence(10);
|
||||||
|
this.chunksPerSecond = new RollingSequence(10);
|
||||||
|
this.chunksPerMinute = new RollingSequence(10);
|
||||||
|
turboGeneratedChunks = new AtomicInteger(0);
|
||||||
|
this.generatedLast = new AtomicInteger(0);
|
||||||
|
this.cachedLast = new AtomicLong(0);
|
||||||
|
this.caching = new AtomicBoolean(false);
|
||||||
|
this.turboTotalChunks = new AtomicInteger((int) Math.ceil(Math.pow((2.0 * job.getRadiusBlocks()) / 16, 2)));
|
||||||
|
cache = new ConcurrentHashMap<>(turboTotalChunks.get());
|
||||||
|
this.cachinglock = new ReentrantLock();
|
||||||
|
jobs.put(job.getWorld(), job);
|
||||||
|
TurboPregenerator.instance = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TurboPregenerator(File file) throws IOException {
|
||||||
|
this(new Gson().fromJson(IO.readAll(file), TurboPregenerator.TurboPregenJob.class), file);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void loadTurboGenerator(String i) {
|
||||||
|
World x = Bukkit.getWorld(i);
|
||||||
|
File turbogen = new File(x.getWorldFolder(), "turbogen.json");
|
||||||
|
if (turbogen.exists()) {
|
||||||
|
try {
|
||||||
|
TurboPregenerator p = new TurboPregenerator(turbogen);
|
||||||
|
p.start();
|
||||||
|
Iris.info("Started Turbo Pregenerator: " + p.job);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void on(WorldUnloadEvent e) {
|
||||||
|
if (e.getWorld().equals(world)) {
|
||||||
|
interrupt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
while (!interrupted()) {
|
||||||
|
tick();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
saveNow();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void tick() {
|
||||||
|
TurboPregenJob job = jobs.get(world.getName());
|
||||||
|
if (!cachinglock.isLocked() && cache.isEmpty() && !caching.get()) {
|
||||||
|
ExecutorService cache = Executors.newFixedThreadPool(1);
|
||||||
|
cache.submit(this::cache);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (latch.flip() && caching.get()) {
|
||||||
|
long secondCached = cache.mappingCount() - cachedLast.get();
|
||||||
|
cachedLast.set(cache.mappingCount());
|
||||||
|
secondCached = secondCached / 3;
|
||||||
|
cachePerSecond.put(secondCached);
|
||||||
|
Iris.info("TurboGen: " + C.IRIS + world.getName() + C.RESET + C.BLUE + " Caching: " + Form.f(cache.mappingCount()) + " of " + Form.f(turboTotalChunks.get()) + " " + Form.f((int) cachePerSecond.getAverage()) + "/s");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (latch.flip() && !job.paused && !cachinglock.isLocked()) {
|
||||||
|
long eta = computeETA();
|
||||||
|
save();
|
||||||
|
int secondGenerated = turboGeneratedChunks.get() - generatedLast.get();
|
||||||
|
generatedLast.set(turboGeneratedChunks.get());
|
||||||
|
secondGenerated = secondGenerated / 3;
|
||||||
|
chunksPerSecond.put(secondGenerated);
|
||||||
|
chunksPerMinute.put(secondGenerated * 60);
|
||||||
|
Iris.info("TurboGen: " + C.IRIS + world.getName() + C.RESET + " RTT: " + Form.f(turboGeneratedChunks.get()) + " of " + Form.f(turboTotalChunks.get()) + " " + Form.f((int) chunksPerSecond.getAverage()) + "/s ETA: " + Form.duration((double) eta, 2));
|
||||||
|
|
||||||
|
}
|
||||||
|
if (turboGeneratedChunks.get() >= turboTotalChunks.get()) {
|
||||||
|
Iris.info("Completed Turbo Gen!");
|
||||||
|
interrupt();
|
||||||
|
} else {
|
||||||
|
if (!cachinglock.isLocked()) {
|
||||||
|
int pos = job.getPosition() + 1;
|
||||||
|
job.setPosition(pos);
|
||||||
|
if (!job.paused) {
|
||||||
|
if (queue.size() < maxWaiting.get()) {
|
||||||
|
Position2 chunk = cache.get(pos);
|
||||||
|
queue.add(chunk);
|
||||||
|
}
|
||||||
|
waitForChunksPartial();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cache() {
|
||||||
|
if (!cachinglock.isLocked()) {
|
||||||
|
cachinglock.lock();
|
||||||
|
caching.set(true);
|
||||||
|
PrecisionStopwatch p = PrecisionStopwatch.start();
|
||||||
|
BurstExecutor b = MultiBurst.burst.burst(turboTotalChunks.get());
|
||||||
|
b.setMulticore(true);
|
||||||
|
int[] list = IntStream.rangeClosed(0, turboTotalChunks.get()).toArray();
|
||||||
|
AtomicInteger order = new AtomicInteger(turboTotalChunks.get());
|
||||||
|
|
||||||
|
int threads = Runtime.getRuntime().availableProcessors();
|
||||||
|
if (threads > 1) threads--;
|
||||||
|
ExecutorService process = Executors.newFixedThreadPool(threads);
|
||||||
|
|
||||||
|
for (int id : list) {
|
||||||
|
b.queue(() -> {
|
||||||
|
cache.put(id, getChunk(id));
|
||||||
|
order.addAndGet(-1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
b.complete();
|
||||||
|
|
||||||
|
if (order.get() < 0) {
|
||||||
|
cachinglock.unlock();
|
||||||
|
caching.set(false);
|
||||||
|
Iris.info("Completed Caching in: " + Form.duration(p.getMilliseconds(), 2));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Iris.error("TurboCache is locked!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void waitForChunksPartial() {
|
||||||
|
while (!queue.isEmpty() && maxWaiting.get() > queue.size()) {
|
||||||
|
try {
|
||||||
|
for (Position2 c : new KList<>(queue)) {
|
||||||
|
tickGenerate(c);
|
||||||
|
queue.remove(c);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private long computeETA() {
|
||||||
|
return (long) ((turboTotalChunks.get() - turboGeneratedChunks.get()) / chunksPerMinute.getAverage()) * 1000;
|
||||||
|
// todo broken
|
||||||
|
}
|
||||||
|
|
||||||
|
private final ExecutorService executorService = Executors.newFixedThreadPool(10);
|
||||||
|
private void tickGenerate(Position2 chunk) {
|
||||||
|
executorService.submit(() -> {
|
||||||
|
CountDownLatch latch = new CountDownLatch(1);
|
||||||
|
PaperLib.getChunkAtAsync(world, chunk.getX(), chunk.getZ(), true)
|
||||||
|
.thenAccept((i) -> {
|
||||||
|
latch.countDown();
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
latch.await();
|
||||||
|
} catch (InterruptedException ignored) {
|
||||||
|
}
|
||||||
|
turboGeneratedChunks.addAndGet(1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public Position2 getChunk(int position) {
|
||||||
|
int p = -1;
|
||||||
|
AtomicInteger xx = new AtomicInteger();
|
||||||
|
AtomicInteger zz = new AtomicInteger();
|
||||||
|
Spiraler s = new Spiraler(job.getRadiusBlocks() * 2, job.getRadiusBlocks() * 2, (x, z) -> {
|
||||||
|
xx.set(x);
|
||||||
|
zz.set(z);
|
||||||
|
});
|
||||||
|
|
||||||
|
while (s.hasNext() && p++ < position) {
|
||||||
|
s.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Position2(xx.get(), zz.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void save() {
|
||||||
|
J.a(() -> {
|
||||||
|
try {
|
||||||
|
saveNow();
|
||||||
|
} catch (Throwable e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setPausedTurbo(World world) {
|
||||||
|
TurboPregenJob job = jobs.get(world.getName());
|
||||||
|
if (isPausedTurbo(world)) {
|
||||||
|
job.paused = false;
|
||||||
|
} else {
|
||||||
|
job.paused = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (job.paused) {
|
||||||
|
Iris.info(C.BLUE + "TurboGen: " + C.IRIS + world.getName() + C.BLUE + " Paused");
|
||||||
|
} else {
|
||||||
|
Iris.info(C.BLUE + "TurboGen: " + C.IRIS + world.getName() + C.BLUE + " Resumed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isPausedTurbo(World world) {
|
||||||
|
TurboPregenJob job = jobs.get(world.getName());
|
||||||
|
return job != null && job.isPaused();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void shutdownInstance(World world) throws IOException {
|
||||||
|
Iris.info("turboGen: " + C.IRIS + world.getName() + C.BLUE + " Shutting down..");
|
||||||
|
TurboPregenJob job = jobs.get(world.getName());
|
||||||
|
File worldDirectory = new File(Bukkit.getWorldContainer(), world.getName());
|
||||||
|
File turboFile = new File(worldDirectory, "turbogen.json");
|
||||||
|
|
||||||
|
if (job == null) {
|
||||||
|
Iris.error("No turbogen job found for world: " + world.getName());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (!job.isPaused()) {
|
||||||
|
job.setPaused(true);
|
||||||
|
}
|
||||||
|
save();
|
||||||
|
jobs.remove(world.getName());
|
||||||
|
new BukkitRunnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
while (turboFile.exists()) {
|
||||||
|
turboFile.delete();
|
||||||
|
J.sleep(1000);
|
||||||
|
}
|
||||||
|
Iris.info("turboGen: " + C.IRIS + world.getName() + C.BLUE + " File deleted and instance closed.");
|
||||||
|
}
|
||||||
|
}.runTaskLater(Iris.instance, 20L);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Iris.error("Failed to shutdown turbogen for " + world.getName());
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
saveNow();
|
||||||
|
interrupt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void saveNow() throws IOException {
|
||||||
|
IO.writeAll(this.destination, new Gson().toJson(job));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@lombok.Builder
|
||||||
|
public static class TurboPregenJob {
|
||||||
|
private String world;
|
||||||
|
@lombok.Builder.Default
|
||||||
|
private int radiusBlocks = 5000;
|
||||||
|
@lombok.Builder.Default
|
||||||
|
private int position = 0;
|
||||||
|
@lombok.Builder.Default
|
||||||
|
boolean paused = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
+29
-55
@@ -22,21 +22,24 @@ import com.volmit.iris.Iris;
|
|||||||
import com.volmit.iris.core.pregenerator.PregenListener;
|
import com.volmit.iris.core.pregenerator.PregenListener;
|
||||||
import com.volmit.iris.core.pregenerator.PregeneratorMethod;
|
import com.volmit.iris.core.pregenerator.PregeneratorMethod;
|
||||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||||
import com.volmit.iris.util.collection.KList;
|
import com.volmit.iris.util.collection.KMap;
|
||||||
import com.volmit.iris.util.mantle.Mantle;
|
import com.volmit.iris.util.mantle.Mantle;
|
||||||
|
import com.volmit.iris.util.math.M;
|
||||||
import com.volmit.iris.util.parallel.MultiBurst;
|
import com.volmit.iris.util.parallel.MultiBurst;
|
||||||
import com.volmit.iris.util.scheduling.J;
|
import com.volmit.iris.util.scheduling.J;
|
||||||
import io.papermc.lib.PaperLib;
|
import io.papermc.lib.PaperLib;
|
||||||
import org.bukkit.Chunk;
|
import org.bukkit.Chunk;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.ArrayList;
|
||||||
import java.util.concurrent.Future;
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.Semaphore;
|
||||||
|
|
||||||
public class AsyncPregenMethod implements PregeneratorMethod {
|
public class AsyncPregenMethod implements PregeneratorMethod {
|
||||||
private final World world;
|
private final World world;
|
||||||
private final MultiBurst burst;
|
private final MultiBurst burst;
|
||||||
private final KList<Future<?>> future;
|
private final Semaphore semaphore;
|
||||||
|
private final Map<Chunk, Long> lastUse;
|
||||||
|
|
||||||
public AsyncPregenMethod(World world, int threads) {
|
public AsyncPregenMethod(World world, int threads) {
|
||||||
if (!PaperLib.isPaper()) {
|
if (!PaperLib.isPaper()) {
|
||||||
@@ -44,8 +47,9 @@ public class AsyncPregenMethod implements PregeneratorMethod {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.world = world;
|
this.world = world;
|
||||||
burst = MultiBurst.burst;
|
burst = new MultiBurst("Iris Async Pregen", Thread.MIN_PRIORITY);
|
||||||
future = new KList<>(1024);
|
semaphore = new Semaphore(256);
|
||||||
|
this.lastUse = new KMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void unloadAndSaveAllChunks() {
|
private void unloadAndSaveAllChunks() {
|
||||||
@@ -56,8 +60,12 @@ public class AsyncPregenMethod implements PregeneratorMethod {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Chunk i : world.getLoadedChunks()) {
|
for (Chunk i : new ArrayList<>(lastUse.keySet())) {
|
||||||
i.unload(true);
|
Long lastUseTime = lastUse.get(i);
|
||||||
|
if (!i.isLoaded() || (lastUseTime != null && M.ms() - lastUseTime >= 10000)) {
|
||||||
|
i.unload();
|
||||||
|
lastUse.remove(i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
world.save();
|
world.save();
|
||||||
}).get();
|
}).get();
|
||||||
@@ -68,55 +76,19 @@ public class AsyncPregenMethod implements PregeneratorMethod {
|
|||||||
|
|
||||||
private void completeChunk(int x, int z, PregenListener listener) {
|
private void completeChunk(int x, int z, PregenListener listener) {
|
||||||
try {
|
try {
|
||||||
future.add(PaperLib.getChunkAtAsync(world, x, z, true).thenApply((i) -> {
|
PaperLib.getChunkAtAsync(world, x, z, true).thenAccept((i) -> {
|
||||||
if (i == null) {
|
lastUse.put(i, M.ms());
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
listener.onChunkGenerated(x, z);
|
listener.onChunkGenerated(x, z);
|
||||||
listener.onChunkCleaned(x, z);
|
listener.onChunkCleaned(x, z);
|
||||||
return 0;
|
}).get();
|
||||||
}));
|
} catch (InterruptedException ignored) {
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
semaphore.release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void waitForChunksPartial(int maxWaiting) {
|
|
||||||
future.removeWhere(Objects::isNull);
|
|
||||||
|
|
||||||
while (future.size() > maxWaiting) {
|
|
||||||
try {
|
|
||||||
Future<?> i = future.remove(0);
|
|
||||||
|
|
||||||
if (i == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
i.get();
|
|
||||||
} catch (Throwable e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void waitForChunks() {
|
|
||||||
for (Future<?> i : future.copy()) {
|
|
||||||
if (i == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
i.get();
|
|
||||||
future.remove(i);
|
|
||||||
} catch (Throwable e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
future.removeWhere(Objects::isNull);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init() {
|
public void init() {
|
||||||
unloadAndSaveAllChunks();
|
unloadAndSaveAllChunks();
|
||||||
@@ -129,13 +101,13 @@ public class AsyncPregenMethod implements PregeneratorMethod {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {
|
||||||
waitForChunks();
|
semaphore.acquireUninterruptibly(256);
|
||||||
unloadAndSaveAllChunks();
|
unloadAndSaveAllChunks();
|
||||||
|
burst.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void save() {
|
public void save() {
|
||||||
waitForChunksPartial(256);
|
|
||||||
unloadAndSaveAllChunks();
|
unloadAndSaveAllChunks();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,10 +124,12 @@ public class AsyncPregenMethod implements PregeneratorMethod {
|
|||||||
@Override
|
@Override
|
||||||
public void generateChunk(int x, int z, PregenListener listener) {
|
public void generateChunk(int x, int z, PregenListener listener) {
|
||||||
listener.onChunkGenerating(x, z);
|
listener.onChunkGenerating(x, z);
|
||||||
if (future.size() > 256) {
|
try {
|
||||||
waitForChunksPartial(256);
|
semaphore.acquire();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
future.add(burst.complete(() -> completeChunk(x, z, listener)));
|
burst.complete(() -> completeChunk(x, z, listener));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+21
-3
@@ -18,25 +18,33 @@
|
|||||||
|
|
||||||
package com.volmit.iris.core.pregenerator.methods;
|
package com.volmit.iris.core.pregenerator.methods;
|
||||||
|
|
||||||
|
import com.volmit.iris.Iris;
|
||||||
import com.volmit.iris.core.IrisSettings;
|
import com.volmit.iris.core.IrisSettings;
|
||||||
import com.volmit.iris.core.pregenerator.PregenListener;
|
import com.volmit.iris.core.pregenerator.PregenListener;
|
||||||
import com.volmit.iris.core.pregenerator.PregeneratorMethod;
|
import com.volmit.iris.core.pregenerator.PregeneratorMethod;
|
||||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||||
import com.volmit.iris.util.collection.KList;
|
import com.volmit.iris.util.collection.KList;
|
||||||
|
import com.volmit.iris.util.collection.KMap;
|
||||||
import com.volmit.iris.util.mantle.Mantle;
|
import com.volmit.iris.util.mantle.Mantle;
|
||||||
|
import com.volmit.iris.util.math.M;
|
||||||
import com.volmit.iris.util.scheduling.J;
|
import com.volmit.iris.util.scheduling.J;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Chunk;
|
import org.bukkit.Chunk;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
public class MedievalPregenMethod implements PregeneratorMethod {
|
public class MedievalPregenMethod implements PregeneratorMethod {
|
||||||
private final World world;
|
private final World world;
|
||||||
private final KList<CompletableFuture<?>> futures;
|
private final KList<CompletableFuture<?>> futures;
|
||||||
|
private final Map<Chunk, Long> lastUse;
|
||||||
|
|
||||||
public MedievalPregenMethod(World world) {
|
public MedievalPregenMethod(World world) {
|
||||||
this.world = world;
|
this.world = world;
|
||||||
futures = new KList<>();
|
futures = new KList<>();
|
||||||
|
this.lastUse = new KMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void waitForChunks() {
|
private void waitForChunks() {
|
||||||
@@ -52,11 +60,19 @@ public class MedievalPregenMethod implements PregeneratorMethod {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void unloadAndSaveAllChunks() {
|
private void unloadAndSaveAllChunks() {
|
||||||
waitForChunks();
|
|
||||||
try {
|
try {
|
||||||
J.sfut(() -> {
|
J.sfut(() -> {
|
||||||
for (Chunk i : world.getLoadedChunks()) {
|
if (world == null) {
|
||||||
i.unload(true);
|
Iris.warn("World was null somehow...");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Chunk i : new ArrayList<>(lastUse.keySet())) {
|
||||||
|
Long lastUseTime = lastUse.get(i);
|
||||||
|
if (lastUseTime != null && M.ms() - lastUseTime >= 10) {
|
||||||
|
i.unload();
|
||||||
|
lastUse.remove(i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
world.save();
|
world.save();
|
||||||
}).get();
|
}).get();
|
||||||
@@ -104,6 +120,8 @@ public class MedievalPregenMethod implements PregeneratorMethod {
|
|||||||
listener.onChunkGenerating(x, z);
|
listener.onChunkGenerating(x, z);
|
||||||
futures.add(J.sfut(() -> {
|
futures.add(J.sfut(() -> {
|
||||||
world.getChunkAt(x, z);
|
world.getChunkAt(x, z);
|
||||||
|
Chunk c = Bukkit.getWorld(world.getUID()).getChunkAt(x, z);
|
||||||
|
lastUse.put(c, M.ms());
|
||||||
listener.onChunkGenerated(x, z);
|
listener.onChunkGenerated(x, z);
|
||||||
listener.onChunkCleaned(x, z);
|
listener.onChunkCleaned(x, z);
|
||||||
}));
|
}));
|
||||||
|
|||||||
@@ -28,14 +28,17 @@ import com.volmit.iris.util.collection.KMap;
|
|||||||
import com.volmit.iris.util.data.B;
|
import com.volmit.iris.util.data.B;
|
||||||
import com.volmit.iris.util.json.JSONArray;
|
import com.volmit.iris.util.json.JSONArray;
|
||||||
import com.volmit.iris.util.json.JSONObject;
|
import com.volmit.iris.util.json.JSONObject;
|
||||||
|
import com.volmit.iris.util.reflect.OldEnum;
|
||||||
import org.bukkit.enchantments.Enchantment;
|
import org.bukkit.enchantments.Enchantment;
|
||||||
import org.bukkit.potion.PotionEffectType;
|
import org.bukkit.potion.PotionEffectType;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class SchemaBuilder {
|
public class SchemaBuilder {
|
||||||
@@ -43,7 +46,6 @@ public class SchemaBuilder {
|
|||||||
private static final String SYMBOL_TYPE__N = "";
|
private static final String SYMBOL_TYPE__N = "";
|
||||||
private static final JSONArray POTION_TYPES = getPotionTypes();
|
private static final JSONArray POTION_TYPES = getPotionTypes();
|
||||||
private static final JSONArray ENCHANT_TYPES = getEnchantTypes();
|
private static final JSONArray ENCHANT_TYPES = getEnchantTypes();
|
||||||
private static final JSONArray ITEM_TYPES = new JSONArray(B.getItemTypes());
|
|
||||||
private static final JSONArray FONT_TYPES = new JSONArray(GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames());
|
private static final JSONArray FONT_TYPES = new JSONArray(GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames());
|
||||||
private final KMap<String, JSONObject> definitions;
|
private final KMap<String, JSONObject> definitions;
|
||||||
private final Class<?> root;
|
private final Class<?> root;
|
||||||
@@ -261,7 +263,7 @@ public class SchemaBuilder {
|
|||||||
|
|
||||||
if (!definitions.containsKey(key)) {
|
if (!definitions.containsKey(key)) {
|
||||||
JSONObject j = new JSONObject();
|
JSONObject j = new JSONObject();
|
||||||
j.put("enum", ITEM_TYPES);
|
j.put("enum", B.getItemTypes());
|
||||||
definitions.put(key, j);
|
definitions.put(key, j);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -309,6 +311,24 @@ public class SchemaBuilder {
|
|||||||
fancyType = "Enchantment Type";
|
fancyType = "Enchantment Type";
|
||||||
prop.put("$ref", "#/definitions/" + key);
|
prop.put("$ref", "#/definitions/" + key);
|
||||||
description.add(SYMBOL_TYPE__N + " Must be a valid Enchantment Type (use ctrl+space for auto complete!)");
|
description.add(SYMBOL_TYPE__N + " Must be a valid Enchantment Type (use ctrl+space for auto complete!)");
|
||||||
|
} else if (k.isAnnotationPresent(RegistryListFunction.class)) {
|
||||||
|
var functionClass = k.getDeclaredAnnotation(RegistryListFunction.class).value();
|
||||||
|
try {
|
||||||
|
var instance = functionClass.getDeclaredConstructor().newInstance();
|
||||||
|
String key = instance.key();
|
||||||
|
fancyType = instance.fancyName();
|
||||||
|
|
||||||
|
if (!definitions.containsKey(key)) {
|
||||||
|
JSONObject j = new JSONObject();
|
||||||
|
j.put("enum", instance.apply(data));
|
||||||
|
definitions.put(key, j);
|
||||||
|
}
|
||||||
|
|
||||||
|
prop.put("$ref", "#/definitions/" + key);
|
||||||
|
description.add(SYMBOL_TYPE__N + " Must be a valid " + fancyType + " (use ctrl+space for auto complete!)");
|
||||||
|
} catch (Throwable e) {
|
||||||
|
Iris.error("Could not execute apply method in " + functionClass.getName());
|
||||||
|
}
|
||||||
} else if (k.getType().equals(PotionEffectType.class)) {
|
} else if (k.getType().equals(PotionEffectType.class)) {
|
||||||
String key = "enum-potion-effect-type";
|
String key = "enum-potion-effect-type";
|
||||||
|
|
||||||
@@ -323,38 +343,9 @@ public class SchemaBuilder {
|
|||||||
description.add(SYMBOL_TYPE__N + " Must be a valid Potion Effect Type (use ctrl+space for auto complete!)");
|
description.add(SYMBOL_TYPE__N + " Must be a valid Potion Effect Type (use ctrl+space for auto complete!)");
|
||||||
|
|
||||||
} else if (k.getType().isEnum()) {
|
} else if (k.getType().isEnum()) {
|
||||||
fancyType = k.getType().getSimpleName().replaceAll("\\QIris\\E", "");
|
fancyType = addEnum(k.getType(), prop, description, k.getType().getEnumConstants(), o -> ((Enum<?>) o).name());
|
||||||
JSONArray a = new JSONArray();
|
} else if (OldEnum.isOldEnum(k.getType())) {
|
||||||
boolean advanced = k.getType().isAnnotationPresent(Desc.class);
|
fancyType = addEnum(k.getType(), prop, description, OldEnum.values(k.getType()), OldEnum::name);
|
||||||
for (Object gg : k.getType().getEnumConstants()) {
|
|
||||||
if (advanced) {
|
|
||||||
try {
|
|
||||||
JSONObject j = new JSONObject();
|
|
||||||
String name = ((Enum<?>) gg).name();
|
|
||||||
j.put("const", name);
|
|
||||||
Desc dd = k.getType().getField(name).getAnnotation(Desc.class);
|
|
||||||
j.put("description", dd == null ? ("No Description for " + name) : dd.value());
|
|
||||||
a.put(j);
|
|
||||||
} catch (Throwable e) {
|
|
||||||
Iris.reportError(e);
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
a.put(((Enum<?>) gg).name());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String key = (advanced ? "oneof-" : "") + "enum-" + k.getType().getCanonicalName().replaceAll("\\Q.\\E", "-").toLowerCase();
|
|
||||||
|
|
||||||
if (!definitions.containsKey(key)) {
|
|
||||||
JSONObject j = new JSONObject();
|
|
||||||
j.put(advanced ? "oneOf" : "enum", a);
|
|
||||||
definitions.put(key, j);
|
|
||||||
}
|
|
||||||
|
|
||||||
prop.put("$ref", "#/definitions/" + key);
|
|
||||||
description.add(SYMBOL_TYPE__N + " Must be a valid " + k.getType().getSimpleName().replaceAll("\\QIris\\E", "") + " (use ctrl+space for auto complete!)");
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case "object" -> {
|
case "object" -> {
|
||||||
@@ -449,7 +440,7 @@ public class SchemaBuilder {
|
|||||||
|
|
||||||
if (!definitions.containsKey(key)) {
|
if (!definitions.containsKey(key)) {
|
||||||
JSONObject j = new JSONObject();
|
JSONObject j = new JSONObject();
|
||||||
j.put("enum", ITEM_TYPES);
|
j.put("enum", B.getItemTypes());
|
||||||
definitions.put(key, j);
|
definitions.put(key, j);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -500,39 +491,9 @@ public class SchemaBuilder {
|
|||||||
prop.put("items", items);
|
prop.put("items", items);
|
||||||
description.add(SYMBOL_TYPE__N + " Must be a valid Potion Effect Type (use ctrl+space for auto complete!)");
|
description.add(SYMBOL_TYPE__N + " Must be a valid Potion Effect Type (use ctrl+space for auto complete!)");
|
||||||
} else if (t.type().isEnum()) {
|
} else if (t.type().isEnum()) {
|
||||||
fancyType = "List of " + t.type().getSimpleName().replaceAll("\\QIris\\E", "") + "s";
|
fancyType = addEnumList(prop, description, t, t.type().getEnumConstants(), o -> ((Enum<?>) o).name());
|
||||||
JSONArray a = new JSONArray();
|
} else if (OldEnum.isOldEnum(t.type())) {
|
||||||
boolean advanced = t.type().isAnnotationPresent(Desc.class);
|
fancyType = addEnumList(prop, description, t, OldEnum.values(t.type()), OldEnum::name);
|
||||||
for (Object gg : t.type().getEnumConstants()) {
|
|
||||||
if (advanced) {
|
|
||||||
try {
|
|
||||||
JSONObject j = new JSONObject();
|
|
||||||
String name = ((Enum<?>) gg).name();
|
|
||||||
j.put("const", name);
|
|
||||||
Desc dd = t.type().getField(name).getAnnotation(Desc.class);
|
|
||||||
j.put("description", dd == null ? ("No Description for " + name) : dd.value());
|
|
||||||
a.put(j);
|
|
||||||
} catch (Throwable e) {
|
|
||||||
Iris.reportError(e);
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
a.put(((Enum<?>) gg).name());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String key = (advanced ? "oneof-" : "") + "enum-" + t.type().getCanonicalName().replaceAll("\\Q.\\E", "-").toLowerCase();
|
|
||||||
|
|
||||||
if (!definitions.containsKey(key)) {
|
|
||||||
JSONObject j = new JSONObject();
|
|
||||||
j.put(advanced ? "oneOf" : "enum", a);
|
|
||||||
definitions.put(key, j);
|
|
||||||
}
|
|
||||||
|
|
||||||
JSONObject items = new JSONObject();
|
|
||||||
items.put("$ref", "#/definitions/" + key);
|
|
||||||
prop.put("items", items);
|
|
||||||
description.add(SYMBOL_TYPE__N + " Must be a valid " + t.type().getSimpleName().replaceAll("\\QIris\\E", "") + " (use ctrl+space for auto complete!)");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -565,7 +526,7 @@ public class SchemaBuilder {
|
|||||||
if (value instanceof List) {
|
if (value instanceof List) {
|
||||||
d.add(" ");
|
d.add(" ");
|
||||||
d.add("* Default Value is an empty list");
|
d.add("* Default Value is an empty list");
|
||||||
} else if (!cl.isPrimitive() && !(value instanceof Number) && !(value instanceof String) && !(cl.isEnum())) {
|
} else if (!cl.isPrimitive() && !(value instanceof Number) && !(value instanceof String) && !(cl.isEnum()) && !OldEnum.isOldEnum(cl)) {
|
||||||
d.add(" ");
|
d.add(" ");
|
||||||
d.add("* Default Value is a default object (create this object to see default properties)");
|
d.add("* Default Value is a default object (create this object to see default properties)");
|
||||||
} else {
|
} else {
|
||||||
@@ -611,6 +572,50 @@ public class SchemaBuilder {
|
|||||||
return prop;
|
return prop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private String addEnumList(JSONObject prop, KList<String> description, ArrayType t, Object[] values, Function<Object, String> function) {
|
||||||
|
JSONObject items = new JSONObject();
|
||||||
|
var s = addEnum(t.type(), items, description, values, function);
|
||||||
|
prop.put("items", items);
|
||||||
|
|
||||||
|
return "List of " + s + "s";
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private String addEnum(Class<?> type, JSONObject prop, KList<String> description, Object[] values, Function<Object, String> function) {
|
||||||
|
JSONArray a = new JSONArray();
|
||||||
|
boolean advanced = type.isAnnotationPresent(Desc.class);
|
||||||
|
for (Object gg : values) {
|
||||||
|
if (advanced) {
|
||||||
|
try {
|
||||||
|
JSONObject j = new JSONObject();
|
||||||
|
String name = function.apply(gg);
|
||||||
|
j.put("const", name);
|
||||||
|
Desc dd = type.getField(name).getAnnotation(Desc.class);
|
||||||
|
j.put("description", dd == null ? ("No Description for " + name) : dd.value());
|
||||||
|
a.put(j);
|
||||||
|
} catch (Throwable e) {
|
||||||
|
Iris.reportError(e);
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
a.put(function.apply(gg));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String key = (advanced ? "oneof-" : "") + "enum-" + type.getCanonicalName().replaceAll("\\Q.\\E", "-").toLowerCase();
|
||||||
|
|
||||||
|
if (!definitions.containsKey(key)) {
|
||||||
|
JSONObject j = new JSONObject();
|
||||||
|
j.put(advanced ? "oneOf" : "enum", a);
|
||||||
|
definitions.put(key, j);
|
||||||
|
}
|
||||||
|
|
||||||
|
prop.put("$ref", "#/definitions/" + key);
|
||||||
|
description.add(SYMBOL_TYPE__N + " Must be a valid " + type.getSimpleName().replaceAll("\\QIris\\E", "") + " (use ctrl+space for auto complete!)");
|
||||||
|
return type.getSimpleName().replaceAll("\\QIris\\E", "");
|
||||||
|
}
|
||||||
|
|
||||||
private String getType(Class<?> c) {
|
private String getType(Class<?> c) {
|
||||||
if (c.equals(int.class) || c.equals(Integer.class) || c.equals(long.class) || c.equals(Long.class)) {
|
if (c.equals(int.class) || c.equals(Integer.class) || c.equals(long.class) || c.equals(Long.class)) {
|
||||||
return "integer";
|
return "integer";
|
||||||
@@ -624,7 +629,7 @@ public class SchemaBuilder {
|
|||||||
return "boolean";
|
return "boolean";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c.equals(String.class) || c.isEnum() || c.equals(Enchantment.class) || c.equals(PotionEffectType.class)) {
|
if (c.equals(String.class) || c.isEnum() || OldEnum.isOldEnum(c) || c.equals(Enchantment.class) || c.equals(PotionEffectType.class)) {
|
||||||
return "string";
|
return "string";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-2
@@ -1,10 +1,12 @@
|
|||||||
package com.volmit.iris.engine.safeguard;
|
package com.volmit.iris.core.safeguard;
|
||||||
|
|
||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.Iris;
|
||||||
|
|
||||||
public class IrisSafeguard {
|
public class IrisSafeguard {
|
||||||
// more planned and WIP
|
|
||||||
public static boolean unstablemode = false;
|
public static boolean unstablemode = false;
|
||||||
|
public static boolean warningmode = false;
|
||||||
|
public static boolean stablemode = false;
|
||||||
|
|
||||||
public static void IrisSafeguardSystem() {
|
public static void IrisSafeguardSystem() {
|
||||||
Iris.info("Enabled Iris SafeGuard");
|
Iris.info("Enabled Iris SafeGuard");
|
||||||
ServerBootSFG.BootCheck();
|
ServerBootSFG.BootCheck();
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
package com.volmit.iris.core.safeguard;
|
||||||
|
|
||||||
|
import com.volmit.iris.Iris;
|
||||||
|
import com.volmit.iris.core.IrisSettings;
|
||||||
|
import com.volmit.iris.util.format.C;
|
||||||
|
|
||||||
|
public class ModesSFG {
|
||||||
|
public static void selectMode() {
|
||||||
|
if (IrisSafeguard.unstablemode) {
|
||||||
|
Iris.safeguard(C.DARK_RED + "Iris is running in Unstable Mode");
|
||||||
|
unstable();
|
||||||
|
}
|
||||||
|
if (IrisSafeguard.warningmode) {
|
||||||
|
Iris.safeguard(C.GOLD + "Iris is running in Warning Mode");
|
||||||
|
warning();
|
||||||
|
}
|
||||||
|
if (IrisSafeguard.stablemode) {
|
||||||
|
stable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void stable() {
|
||||||
|
Iris.safeguard(C.BLUE + "Iris is running Stable");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void unstable() {
|
||||||
|
|
||||||
|
UtilsSFG.printIncompatibleWarnings();
|
||||||
|
|
||||||
|
if (IrisSafeguard.unstablemode) {
|
||||||
|
Iris.info("");
|
||||||
|
Iris.info(C.DARK_GRAY + "--==<" + C.RED + " IMPORTANT " + C.DARK_GRAY + ">==--");
|
||||||
|
Iris.info(C.RED + "Iris is running in unstable mode which may cause the following issues:");
|
||||||
|
Iris.info(C.DARK_RED + "Server Issues");
|
||||||
|
Iris.info(C.RED + "- Server won't boot");
|
||||||
|
Iris.info(C.RED + "- Data Loss");
|
||||||
|
Iris.info(C.RED + "- Unexpected behavior.");
|
||||||
|
Iris.info(C.RED + "- And More...");
|
||||||
|
Iris.info(C.DARK_RED + "World Issues");
|
||||||
|
Iris.info(C.RED + "- Worlds can't load due to corruption.");
|
||||||
|
Iris.info(C.RED + "- Worlds may slowly corrupt until they can't load.");
|
||||||
|
Iris.info(C.RED + "- World data loss.");
|
||||||
|
Iris.info(C.RED + "- And More...");
|
||||||
|
Iris.info(C.DARK_RED + "ATTENTION: " + C.RED + "While running Iris in unstable mode, you won't be eligible for support.");
|
||||||
|
Iris.info(C.DARK_RED + "CAUSE: " + C.RED + UtilsSFG.MSGIncompatibleWarnings());
|
||||||
|
|
||||||
|
if (IrisSettings.get().getGeneral().DoomsdayAnnihilationSelfDestructMode) {
|
||||||
|
Iris.info(C.DARK_RED + "Boot Unstable is set to true, continuing with the startup process.");
|
||||||
|
} else {
|
||||||
|
Iris.info(C.DARK_RED + "Go to plugins/iris/settings.json and set DoomsdayAnnihilationSelfDestructMode to true if you wish to proceed.");
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
Thread.sleep(Long.MAX_VALUE);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
// no
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Iris.info("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void warning() {
|
||||||
|
|
||||||
|
UtilsSFG.printIncompatibleWarnings();
|
||||||
|
|
||||||
|
if (IrisSafeguard.warningmode) {
|
||||||
|
Iris.info("");
|
||||||
|
Iris.info(C.DARK_GRAY + "--==<" + C.GOLD + " IMPORTANT " + C.DARK_GRAY + ">==--");
|
||||||
|
Iris.info(C.GOLD + "Iris is running in warning mode which may cause the following issues:");
|
||||||
|
Iris.info(C.YELLOW + "- Data Loss");
|
||||||
|
Iris.info(C.YELLOW + "- Errors");
|
||||||
|
Iris.info(C.YELLOW + "- Broken worlds");
|
||||||
|
Iris.info(C.YELLOW + "- Unexpected behavior.");
|
||||||
|
Iris.info(C.YELLOW + "- And perhaps further complications.");
|
||||||
|
Iris.info(C.GOLD + "CAUSE: " + C.YELLOW + UtilsSFG.MSGIncompatibleWarnings());
|
||||||
|
Iris.info("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package com.volmit.iris.core.safeguard;
|
||||||
|
|
||||||
|
public class PerformanceSFG {
|
||||||
|
public static void calculatePerformance() {
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,168 @@
|
|||||||
|
package com.volmit.iris.core.safeguard;
|
||||||
|
|
||||||
|
import com.volmit.iris.Iris;
|
||||||
|
import com.volmit.iris.core.nms.INMS;
|
||||||
|
import com.volmit.iris.core.nms.v1X.NMSBinding1X;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
|
import org.bukkit.plugin.PluginManager;
|
||||||
|
import javax.tools.JavaCompiler;
|
||||||
|
import javax.tools.ToolProvider;
|
||||||
|
import java.io.File;
|
||||||
|
import java.nio.channels.FileChannel;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.nio.file.StandardOpenOption;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.StringJoiner;
|
||||||
|
|
||||||
|
import static com.volmit.iris.Iris.getJavaVersion;
|
||||||
|
import static com.volmit.iris.core.safeguard.IrisSafeguard.*;
|
||||||
|
|
||||||
|
public class ServerBootSFG {
|
||||||
|
public static final Map<String, Boolean> incompatibilities = new HashMap<>();
|
||||||
|
public static boolean isCorrectJDK = true;
|
||||||
|
public static boolean hasEnoughDiskSpace = true;
|
||||||
|
public static boolean isJRE = false;
|
||||||
|
public static boolean hasPrivileges = true;
|
||||||
|
public static boolean unsuportedversion = false;
|
||||||
|
protected static boolean safeguardPassed;
|
||||||
|
public static boolean passedserversoftware = true;
|
||||||
|
protected static int count;
|
||||||
|
protected static byte severityLow;
|
||||||
|
protected static byte severityMedium;
|
||||||
|
protected static byte severityHigh;
|
||||||
|
public static String allIncompatibilities;
|
||||||
|
|
||||||
|
public static void BootCheck() {
|
||||||
|
Iris.info("Checking for possible conflicts..");
|
||||||
|
PluginManager pluginManager = Bukkit.getPluginManager();
|
||||||
|
Plugin[] plugins = pluginManager.getPlugins();
|
||||||
|
|
||||||
|
incompatibilities.clear();
|
||||||
|
incompatibilities.put("Multiverse-Core", false);
|
||||||
|
incompatibilities.put("dynmap", false);
|
||||||
|
incompatibilities.put("TerraformGenerator", false);
|
||||||
|
incompatibilities.put("Stratos", false);
|
||||||
|
|
||||||
|
String pluginName;
|
||||||
|
for (Plugin plugin : plugins) {
|
||||||
|
pluginName = plugin.getName();
|
||||||
|
Boolean flag = incompatibilities.get(pluginName);
|
||||||
|
if (flag != null && !flag) {
|
||||||
|
severityHigh++;
|
||||||
|
incompatibilities.put(pluginName, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StringJoiner joiner = new StringJoiner(", ");
|
||||||
|
for (Map.Entry<String, Boolean> entry : incompatibilities.entrySet()) {
|
||||||
|
if (entry.getValue()) {
|
||||||
|
joiner.add(entry.getKey());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Legacy ServerInfo
|
||||||
|
String distro = Bukkit.getName().toLowerCase();
|
||||||
|
if (
|
||||||
|
!distro.contains("purpur") &&
|
||||||
|
!distro.contains("paper") &&
|
||||||
|
!distro.contains("spigot") &&
|
||||||
|
!distro.contains("pufferfish") &&
|
||||||
|
!distro.contains("bukkit")) {
|
||||||
|
|
||||||
|
|
||||||
|
passedserversoftware = false;
|
||||||
|
joiner.add("Server Software");
|
||||||
|
severityMedium++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (INMS.get() instanceof NMSBinding1X) {
|
||||||
|
unsuportedversion = true;
|
||||||
|
joiner.add("Unsupported Minecraft Version");
|
||||||
|
severityHigh++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!List.of(21).contains(getJavaVersion())) {
|
||||||
|
isCorrectJDK = false;
|
||||||
|
joiner.add("Unsupported Java version");
|
||||||
|
severityMedium++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isJDK()) {
|
||||||
|
isJRE = true;
|
||||||
|
joiner.add("Unsupported JDK");
|
||||||
|
severityMedium++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if (!hasPrivileges()){
|
||||||
|
// hasPrivileges = false;
|
||||||
|
// joiner.add("Insufficient Privileges");
|
||||||
|
// severityMedium++;
|
||||||
|
// } Some servers dont like this
|
||||||
|
|
||||||
|
if (!enoughDiskSpace()){
|
||||||
|
hasEnoughDiskSpace = false;
|
||||||
|
joiner.add("Insufficient Disk Space");
|
||||||
|
severityMedium++;
|
||||||
|
}
|
||||||
|
|
||||||
|
allIncompatibilities = joiner.toString();
|
||||||
|
|
||||||
|
safeguardPassed = (severityHigh == 0 && severityMedium == 0 && severityLow == 0);
|
||||||
|
count = severityHigh + severityMedium + severityLow;
|
||||||
|
if (safeguardPassed) {
|
||||||
|
stablemode = true;
|
||||||
|
Iris.safeguard("Stable mode has been activated.");
|
||||||
|
}
|
||||||
|
if (!safeguardPassed) {
|
||||||
|
if (severityMedium >= 1 && severityHigh == 0) {
|
||||||
|
warningmode = true;
|
||||||
|
Iris.safeguard("Warning mode has been activated.");
|
||||||
|
}
|
||||||
|
if (severityHigh >= 1) {
|
||||||
|
unstablemode = true;
|
||||||
|
Iris.safeguard("Unstable mode has been activated.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static boolean isJDK() {
|
||||||
|
try {
|
||||||
|
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
|
||||||
|
// If the compiler is null, it means this is a JRE environment, not a JDK.
|
||||||
|
return compiler != null;
|
||||||
|
} catch (Exception ignored) {}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
public static boolean hasPrivileges() {
|
||||||
|
Path pv = Paths.get(Bukkit.getWorldContainer() + "iristest.json");
|
||||||
|
try (FileChannel fc = FileChannel.open(pv, StandardOpenOption.CREATE, StandardOpenOption.DELETE_ON_CLOSE, StandardOpenOption.READ, StandardOpenOption.WRITE)) {
|
||||||
|
if (Files.isReadable(pv) && Files.isWritable(pv)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean enoughDiskSpace() {
|
||||||
|
File freeSpace = new File(Bukkit.getWorldContainer() + ".");
|
||||||
|
double gigabytes = freeSpace.getFreeSpace() / (1024.0 * 1024.0 * 1024.0);
|
||||||
|
if (gigabytes > 3){
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean checkJavac(String path) {
|
||||||
|
return !path.isEmpty() && (new File(path, "javac").exists() || new File(path, "javac.exe").exists());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
package com.volmit.iris.core.safeguard;
|
||||||
|
|
||||||
|
import com.volmit.iris.Iris;
|
||||||
|
import com.volmit.iris.util.format.C;
|
||||||
|
|
||||||
|
public class UtilsSFG {
|
||||||
|
public static void splash() {
|
||||||
|
ModesSFG.selectMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void printIncompatibleWarnings() {
|
||||||
|
// String SupportedIrisVersion = getDescription().getVersion(); //todo Automatic version
|
||||||
|
|
||||||
|
if (ServerBootSFG.safeguardPassed) {
|
||||||
|
Iris.safeguard(C.BLUE + "0 Conflicts found");
|
||||||
|
} else {
|
||||||
|
if (IrisSafeguard.unstablemode) {
|
||||||
|
Iris.safeguard(C.DARK_RED + "" + ServerBootSFG.count + " Conflicts found");
|
||||||
|
}
|
||||||
|
if (IrisSafeguard.warningmode) {
|
||||||
|
Iris.safeguard(C.YELLOW + "" + ServerBootSFG.count + " Conflicts found");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ServerBootSFG.incompatibilities.get("Multiverse-Core")) {
|
||||||
|
Iris.safeguard(C.RED + "Multiverse");
|
||||||
|
Iris.safeguard(C.RED + "- The plugin Multiverse is not compatible with the server.");
|
||||||
|
Iris.safeguard(C.RED + "- If you want to have a world manager, consider using PhantomWorlds or MyWorlds instead.");
|
||||||
|
}
|
||||||
|
if (ServerBootSFG.incompatibilities.get("dynmap")) {
|
||||||
|
Iris.safeguard(C.RED + "Dynmap");
|
||||||
|
Iris.safeguard(C.RED + "- The plugin Dynmap is not compatible with the server.");
|
||||||
|
Iris.safeguard(C.RED + "- If you want to have a map plugin like Dynmap, consider Bluemap.");
|
||||||
|
}
|
||||||
|
if (ServerBootSFG.incompatibilities.get("TerraformGenerator") || ServerBootSFG.incompatibilities.get("Stratos")) {
|
||||||
|
Iris.safeguard(C.YELLOW + "Terraform Generator / Stratos");
|
||||||
|
Iris.safeguard(C.YELLOW + "- Iris is not compatible with other worldgen plugins.");
|
||||||
|
}
|
||||||
|
if (ServerBootSFG.unsuportedversion) {
|
||||||
|
Iris.safeguard(C.RED + "Server Version");
|
||||||
|
Iris.safeguard(C.RED + "- Iris only supports 1.19.2 > 1.21.3");
|
||||||
|
}
|
||||||
|
if (!ServerBootSFG.passedserversoftware) {
|
||||||
|
Iris.safeguard(C.YELLOW + "Unsupported Server Software");
|
||||||
|
Iris.safeguard(C.YELLOW + "- Please consider using Paper or Purpur instead.");
|
||||||
|
}
|
||||||
|
if (!ServerBootSFG.hasPrivileges) {
|
||||||
|
Iris.safeguard(C.YELLOW + "Insufficient Privileges");
|
||||||
|
Iris.safeguard(C.YELLOW + "- The server has insufficient Privileges to run iris. Please contact support.");
|
||||||
|
}
|
||||||
|
if (!ServerBootSFG.hasEnoughDiskSpace) {
|
||||||
|
Iris.safeguard(C.YELLOW + "Insufficient Disk Space");
|
||||||
|
Iris.safeguard(C.YELLOW + "- The server has insufficient Free DiskSpace to run iris required 3GB+.");
|
||||||
|
}
|
||||||
|
if (!ServerBootSFG.isCorrectJDK) {
|
||||||
|
Iris.safeguard(C.YELLOW + "Unsupported java version");
|
||||||
|
Iris.safeguard(C.YELLOW + "- Please consider using JDK 21 Instead of JDK " + Iris.getJavaVersion());
|
||||||
|
}
|
||||||
|
if (ServerBootSFG.isJRE) {
|
||||||
|
Iris.safeguard(C.YELLOW + "Unsupported Server JDK");
|
||||||
|
Iris.safeguard(C.YELLOW + "- Please consider using JDK 21 Instead of JRE " + Iris.getJavaVersion());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String MSGIncompatibleWarnings() {
|
||||||
|
return ServerBootSFG.allIncompatibilities;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,6 +19,7 @@
|
|||||||
package com.volmit.iris.core.service;
|
package com.volmit.iris.core.service;
|
||||||
|
|
||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.Iris;
|
||||||
|
import com.volmit.iris.core.IrisSettings;
|
||||||
import com.volmit.iris.core.loader.IrisData;
|
import com.volmit.iris.core.loader.IrisData;
|
||||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||||
import com.volmit.iris.engine.framework.Engine;
|
import com.volmit.iris.engine.framework.Engine;
|
||||||
@@ -39,6 +40,7 @@ import org.bukkit.event.player.PlayerChangedWorldEvent;
|
|||||||
import org.bukkit.event.player.PlayerJoinEvent;
|
import org.bukkit.event.player.PlayerJoinEvent;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
|
|
||||||
public class BoardSVC implements IrisService, BoardProvider {
|
public class BoardSVC implements IrisService, BoardProvider {
|
||||||
private final KMap<Player, PlayerBoard> boards = new KMap<>();
|
private final KMap<Player, PlayerBoard> boards = new KMap<>();
|
||||||
@@ -103,11 +105,11 @@ public class BoardSVC implements IrisService, BoardProvider {
|
|||||||
@Data
|
@Data
|
||||||
public static class PlayerBoard {
|
public static class PlayerBoard {
|
||||||
private final Player player;
|
private final Player player;
|
||||||
private final KList<String> lines;
|
private final CopyOnWriteArrayList<String> lines;
|
||||||
|
|
||||||
public PlayerBoard(Player player) {
|
public PlayerBoard(Player player) {
|
||||||
this.player = player;
|
this.player = player;
|
||||||
this.lines = new KList<>();
|
this.lines = new CopyOnWriteArrayList<>();
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,17 +126,32 @@ public class BoardSVC implements IrisService, BoardProvider {
|
|||||||
int y = player.getLocation().getBlockY() - player.getWorld().getMinHeight();
|
int y = player.getLocation().getBlockY() - player.getWorld().getMinHeight();
|
||||||
int z = player.getLocation().getBlockZ();
|
int z = player.getLocation().getBlockZ();
|
||||||
|
|
||||||
lines.add("&7&m ");
|
if(IrisSettings.get().getGeneral().debug){
|
||||||
lines.add(C.GREEN + "Speed" + C.GRAY + ": " + Form.f(engine.getGeneratedPerSecond(), 0) + "/s " + Form.duration(1000D / engine.getGeneratedPerSecond(), 0));
|
lines.add("&7&m ");
|
||||||
lines.add(C.AQUA + "Cache" + C.GRAY + ": " + Form.f(IrisData.cacheSize()));
|
lines.add(C.GREEN + "Speed" + C.GRAY + ": " + Form.f(engine.getGeneratedPerSecond(), 0) + "/s " + Form.duration(1000D / engine.getGeneratedPerSecond(), 0));
|
||||||
lines.add(C.AQUA + "Mantle" + C.GRAY + ": " + engine.getMantle().getLoadedRegionCount());
|
lines.add(C.AQUA + "Cache" + C.GRAY + ": " + Form.f(IrisData.cacheSize()));
|
||||||
lines.add("&7&m ");
|
lines.add(C.AQUA + "Mantle" + C.GRAY + ": " + engine.getMantle().getLoadedRegionCount());
|
||||||
lines.add(C.AQUA + "Region" + C.GRAY + ": " + engine.getRegion(x, z).getName());
|
lines.add(C.LIGHT_PURPLE + "Carving" + C.GRAY + ": " + engine.getMantle().isCarved(x,y,z));
|
||||||
lines.add(C.AQUA + "Biome" + C.GRAY + ": " + engine.getBiomeOrMantle(x, y, z).getName());
|
lines.add("&7&m ");
|
||||||
lines.add(C.AQUA + "Height" + C.GRAY + ": " + Math.round(engine.getHeight(x, z) + player.getWorld().getMinHeight()));
|
lines.add(C.AQUA + "Region" + C.GRAY + ": " + engine.getRegion(x, z).getName());
|
||||||
lines.add(C.AQUA + "Slope" + C.GRAY + ": " + Form.f(engine.getComplex().getSlopeStream().get(x, z), 2));
|
lines.add(C.AQUA + "Biome" + C.GRAY + ": " + engine.getBiomeOrMantle(x, y, z).getName());
|
||||||
lines.add(C.AQUA + "BUD/s" + C.GRAY + ": " + Form.f(engine.getBlockUpdatesPerSecond()));
|
lines.add(C.AQUA + "Height" + C.GRAY + ": " + Math.round(engine.getHeight(x, z)));
|
||||||
lines.add("&7&m ");
|
lines.add(C.AQUA + "Slope" + C.GRAY + ": " + Form.f(engine.getComplex().getSlopeStream().get(x, z), 2));
|
||||||
|
lines.add(C.AQUA + "BUD/s" + C.GRAY + ": " + Form.f(engine.getBlockUpdatesPerSecond()));
|
||||||
|
lines.add("&7&m ");
|
||||||
|
} else {
|
||||||
|
lines.add("&7&m ");
|
||||||
|
lines.add(C.GREEN + "Speed" + C.GRAY + ": " + Form.f(engine.getGeneratedPerSecond(), 0) + "/s " + Form.duration(1000D / engine.getGeneratedPerSecond(), 0));
|
||||||
|
lines.add(C.AQUA + "Cache" + C.GRAY + ": " + Form.f(IrisData.cacheSize()));
|
||||||
|
lines.add(C.AQUA + "Mantle" + C.GRAY + ": " + engine.getMantle().getLoadedRegionCount());
|
||||||
|
lines.add("&7&m ");
|
||||||
|
lines.add(C.AQUA + "Region" + C.GRAY + ": " + engine.getRegion(x, z).getName());
|
||||||
|
lines.add(C.AQUA + "Biome" + C.GRAY + ": " + engine.getBiomeOrMantle(x, y, z).getName());
|
||||||
|
lines.add(C.AQUA + "Height" + C.GRAY + ": " + Math.round(engine.getHeight(x, z)));
|
||||||
|
lines.add(C.AQUA + "Slope" + C.GRAY + ": " + Form.f(engine.getComplex().getSlopeStream().get(x, z), 2));
|
||||||
|
lines.add(C.AQUA + "BUD/s" + C.GRAY + ": " + Form.f(engine.getBlockUpdatesPerSecond()));
|
||||||
|
lines.add("&7&m ");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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,187 @@
|
|||||||
/*
|
/*
|
||||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.volmit.iris.core.service;
|
package com.volmit.iris.core.service;
|
||||||
|
|
||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.Iris;
|
||||||
import com.volmit.iris.core.link.*;
|
import com.volmit.iris.core.link.*;
|
||||||
import com.volmit.iris.util.collection.KList;
|
import com.volmit.iris.core.nms.container.Pair;
|
||||||
import com.volmit.iris.util.plugin.IrisService;
|
import com.volmit.iris.engine.framework.Engine;
|
||||||
import lombok.Data;
|
import com.volmit.iris.util.collection.KList;
|
||||||
import org.bukkit.Bukkit;
|
import com.volmit.iris.util.collection.KMap;
|
||||||
import org.bukkit.block.data.BlockData;
|
import com.volmit.iris.util.plugin.IrisService;
|
||||||
import org.bukkit.event.EventHandler;
|
import lombok.Data;
|
||||||
import org.bukkit.event.server.PluginEnableEvent;
|
import lombok.NonNull;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
import java.util.MissingResourceException;
|
import org.bukkit.block.data.BlockData;
|
||||||
import java.util.Optional;
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.server.PluginEnableEvent;
|
||||||
@Data
|
import org.bukkit.inventory.ItemStack;
|
||||||
public class ExternalDataSVC implements IrisService {
|
|
||||||
|
import java.util.*;
|
||||||
private KList<ExternalDataProvider> providers = new KList<>(), activeProviders = new KList<>();
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Override
|
@Data
|
||||||
public void onEnable() {
|
public class ExternalDataSVC implements IrisService {
|
||||||
Iris.info("Loading ExternalDataProvider...");
|
|
||||||
Bukkit.getPluginManager().registerEvents(this, Iris.instance);
|
private KList<ExternalDataProvider> providers = new KList<>(), activeProviders = new KList<>();
|
||||||
|
|
||||||
providers.add(new OraxenDataProvider());
|
@Override
|
||||||
if (Bukkit.getPluginManager().getPlugin("Oraxen") != null) {
|
public void onEnable() {
|
||||||
Iris.info("Oraxen found, loading OraxenDataProvider...");
|
Iris.info("Loading ExternalDataProvider...");
|
||||||
}
|
Bukkit.getPluginManager().registerEvents(this, Iris.instance);
|
||||||
providers.add(new ItemAdderDataProvider());
|
|
||||||
if (Bukkit.getPluginManager().getPlugin("ItemAdder") != null) {
|
providers.add(new NexoDataProvider());
|
||||||
Iris.info("ItemAdder found, loading ItemAdderDataProvider...");
|
if (Bukkit.getPluginManager().getPlugin("Nexo") != null) {
|
||||||
}
|
Iris.info("Nexo found, loading NexoDataProvider...");
|
||||||
providers.add(new ExecutableItemsDataProvider());
|
}
|
||||||
if (Bukkit.getPluginManager().getPlugin("ExecutableItems") != null) {
|
providers.add(new MythicCrucibleDataProvider());
|
||||||
Iris.info("ExecutableItems found, loading ExecutableItemsDataProvider...");
|
if (Bukkit.getPluginManager().getPlugin("MythicCrucible") != null) {
|
||||||
}
|
Iris.info("MythicCrucible found, loading MythicCrucibleDataProvider...");
|
||||||
|
}
|
||||||
for (ExternalDataProvider p : providers) {
|
providers.add(new ItemAdderDataProvider());
|
||||||
if (p.isReady()) {
|
if (Bukkit.getPluginManager().getPlugin("ItemAdder") != null) {
|
||||||
activeProviders.add(p);
|
Iris.info("ItemAdder found, loading ItemAdderDataProvider...");
|
||||||
p.init();
|
}
|
||||||
Iris.info("Enabled ExternalDataProvider for %s.", p.getPluginId());
|
providers.add(new ExecutableItemsDataProvider());
|
||||||
}
|
if (Bukkit.getPluginManager().getPlugin("ExecutableItems") != null) {
|
||||||
}
|
Iris.info("ExecutableItems found, loading ExecutableItemsDataProvider...");
|
||||||
}
|
}
|
||||||
|
providers.add(new HMCLeavesDataProvider());
|
||||||
@Override
|
if (Bukkit.getPluginManager().getPlugin("HMCLeaves") != null) {
|
||||||
public void onDisable() {
|
Iris.info("BlockAdder found, loading HMCLeavesDataProvider...");
|
||||||
}
|
}
|
||||||
|
providers.add(new MMOItemsDataProvider());
|
||||||
@EventHandler
|
if (Bukkit.getPluginManager().getPlugin("MMOItems") != null) {
|
||||||
public void onPluginEnable(PluginEnableEvent e) {
|
Iris.info("MMOItems found, loading MMOItemsDataProvider...");
|
||||||
if (activeProviders.stream().noneMatch(p -> p.getPlugin().equals(e.getPlugin()))) {
|
}
|
||||||
providers.stream().filter(p -> p.isReady() && p.getPlugin().equals(e.getPlugin())).findFirst().ifPresent(edp -> {
|
providers.add(new EcoItemsDataProvider());
|
||||||
activeProviders.add(edp);
|
if (Bukkit.getPluginManager().getPlugin("EcoItems") != null) {
|
||||||
edp.init();
|
Iris.info("EcoItems found, loading EcoItemsDataProvider...");
|
||||||
Iris.info("Enabled ExternalDataProvider for %s.", edp.getPluginId());
|
}
|
||||||
});
|
|
||||||
}
|
for (ExternalDataProvider p : providers) {
|
||||||
}
|
if (p.isReady()) {
|
||||||
|
activeProviders.add(p);
|
||||||
public Optional<BlockData> getBlockData(Identifier key) {
|
p.init();
|
||||||
Optional<ExternalDataProvider> provider = activeProviders.stream().filter(p -> p.isValidProvider(key, false)).findFirst();
|
Iris.info("Enabled ExternalDataProvider for %s.", p.getPluginId());
|
||||||
if (provider.isEmpty())
|
}
|
||||||
return Optional.empty();
|
}
|
||||||
try {
|
}
|
||||||
return Optional.of(provider.get().getBlockData(key));
|
|
||||||
} catch (MissingResourceException e) {
|
@Override
|
||||||
Iris.error(e.getMessage() + " - [" + e.getClassName() + ":" + e.getKey() + "]");
|
public void onDisable() {
|
||||||
return Optional.empty();
|
}
|
||||||
}
|
|
||||||
}
|
@EventHandler
|
||||||
|
public void onPluginEnable(PluginEnableEvent e) {
|
||||||
public Optional<ItemStack> getItemStack(Identifier key) {
|
if (activeProviders.stream().noneMatch(p -> p.getPlugin().equals(e.getPlugin()))) {
|
||||||
Optional<ExternalDataProvider> provider = activeProviders.stream().filter(p -> p.isValidProvider(key, true)).findFirst();
|
providers.stream().filter(p -> p.isReady() && p.getPlugin().equals(e.getPlugin())).findFirst().ifPresent(edp -> {
|
||||||
if (provider.isEmpty()) {
|
activeProviders.add(edp);
|
||||||
Iris.warn("No matching Provider found for modded material \"%s\"!", key);
|
edp.init();
|
||||||
return Optional.empty();
|
Iris.info("Enabled ExternalDataProvider for %s.", edp.getPluginId());
|
||||||
}
|
});
|
||||||
try {
|
}
|
||||||
return Optional.of(provider.get().getItemStack(key));
|
}
|
||||||
} catch (MissingResourceException e) {
|
|
||||||
Iris.error(e.getMessage() + " - [" + e.getClassName() + ":" + e.getKey() + "]");
|
public void registerProvider(@NonNull ExternalDataProvider provider) {
|
||||||
return Optional.empty();
|
String plugin = provider.getPluginId();
|
||||||
}
|
if (providers.stream().map(ExternalDataProvider::getPluginId).anyMatch(plugin::equals))
|
||||||
}
|
throw new IllegalArgumentException("A provider with the same plugin id already exists.");
|
||||||
|
|
||||||
public Identifier[] getAllBlockIdentifiers() {
|
providers.add(provider);
|
||||||
KList<Identifier> names = new KList<>();
|
if (provider.isReady()) {
|
||||||
activeProviders.forEach(p -> names.add(p.getBlockTypes()));
|
activeProviders.add(provider);
|
||||||
return names.toArray(new Identifier[0]);
|
provider.init();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
public Identifier[] getAllItemIdentifiers() {
|
|
||||||
KList<Identifier> names = new KList<>();
|
public Optional<BlockData> getBlockData(final Identifier key) {
|
||||||
activeProviders.forEach(p -> names.add(p.getItemTypes()));
|
var pair = parseState(key);
|
||||||
return names.toArray(new Identifier[0]);
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -63,7 +63,12 @@ public class StudioSVC implements IrisService {
|
|||||||
|
|
||||||
if (!f.exists()) {
|
if (!f.exists()) {
|
||||||
Iris.info("Downloading Default Pack " + pack);
|
Iris.info("Downloading Default Pack " + pack);
|
||||||
downloadSearch(Iris.getSender(), pack, false);
|
if (pack.equals("overworld")) {
|
||||||
|
String url = "https://github.com/IrisDimensions/overworld/releases/download/" + Iris.OVERWORLD_TAG + "/overworld.zip";
|
||||||
|
Iris.service(StudioSVC.class).downloadRelease(Iris.getSender(), url, false, false);
|
||||||
|
} else {
|
||||||
|
downloadSearch(Iris.getSender(), pack, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -232,7 +237,7 @@ public class StudioSVC implements IrisService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
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) {
|
} catch (NullPointerException e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
sender.sendMessage("Error when finding home directory. Are there any non-text characters in the file name?");
|
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
|
@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);
|
boolean isUseAll = worldAccess.getEngine().getDimension().getTreeSettings().getMode().equals(IrisTreeModes.ALL);
|
||||||
|
|
||||||
// Retrieve objectPlacements of type `species` from biome
|
// 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));
|
placements.addAll(matchObjectPlacements(biome.getObjects(), size, type));
|
||||||
|
|
||||||
// Add more or find any in the region
|
// 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.math.M;
|
||||||
import com.volmit.iris.util.matter.Matter;
|
import com.volmit.iris.util.matter.Matter;
|
||||||
import com.volmit.iris.util.matter.WorldMatter;
|
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.IrisService;
|
||||||
import com.volmit.iris.util.plugin.VolmitSender;
|
import com.volmit.iris.util.plugin.VolmitSender;
|
||||||
import com.volmit.iris.util.scheduling.J;
|
import com.volmit.iris.util.scheduling.J;
|
||||||
|
import com.volmit.iris.util.scheduling.S;
|
||||||
|
import com.volmit.iris.util.scheduling.SR;
|
||||||
|
import com.volmit.iris.util.scheduling.jobs.Job;
|
||||||
import org.bukkit.*;
|
import org.bukkit.*;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.enchantments.Enchantment;
|
import org.bukkit.enchantments.Enchantment;
|
||||||
@@ -51,9 +55,16 @@ import org.bukkit.util.Vector;
|
|||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
public class WandSVC implements IrisService {
|
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 dust;
|
||||||
|
private static ItemStack wand;
|
||||||
|
|
||||||
public static void pasteSchematic(IrisObject s, Location at) {
|
public static void pasteSchematic(IrisObject s, Location at) {
|
||||||
s.place(at);
|
s.place(at);
|
||||||
@@ -65,7 +76,7 @@ public class WandSVC implements IrisService {
|
|||||||
* @param p The wand player
|
* @param p The wand player
|
||||||
* @return The new object
|
* @return The new object
|
||||||
*/
|
*/
|
||||||
public static IrisObject createSchematic(Player p) {
|
public static IrisObject createSchematic(Player p, boolean legacy) {
|
||||||
if (!isHoldingWand(p)) {
|
if (!isHoldingWand(p)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -74,14 +85,81 @@ public class WandSVC implements IrisService {
|
|||||||
Location[] f = getCuboid(p);
|
Location[] f = getCuboid(p);
|
||||||
Cuboid c = new Cuboid(f[0], f[1]);
|
Cuboid c = new Cuboid(f[0], f[1]);
|
||||||
IrisObject s = new IrisObject(c.getSizeX(), c.getSizeY(), c.getSizeZ());
|
IrisObject s = new IrisObject(c.getSizeX(), c.getSizeY(), c.getSizeZ());
|
||||||
for (Block b : c) {
|
|
||||||
if (b.getType().equals(Material.AIR)) {
|
var it = c.chunkedIterator();
|
||||||
continue;
|
|
||||||
|
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();
|
@Override
|
||||||
s.setUnsigned(bv.getBlockX(), bv.getBlockY(), bv.getBlockZ(), b);
|
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, legacy);
|
||||||
|
} 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;
|
return s;
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
@@ -161,11 +239,11 @@ public class WandSVC implements IrisService {
|
|||||||
*/
|
*/
|
||||||
public static ItemStack createDust() {
|
public static ItemStack createDust() {
|
||||||
ItemStack is = new ItemStack(Material.GLOWSTONE_DUST);
|
ItemStack is = new ItemStack(Material.GLOWSTONE_DUST);
|
||||||
is.addUnsafeEnchantment(Enchantment.ARROW_INFINITE, 1);
|
is.addUnsafeEnchantment(Enchantment.FIRE_ASPECT, 1);
|
||||||
ItemMeta im = is.getItemMeta();
|
ItemMeta im = is.getItemMeta();
|
||||||
im.setDisplayName(C.BOLD + "" + C.YELLOW + "Dust of Revealing");
|
im.setDisplayName(C.BOLD + "" + C.YELLOW + "Dust of Revealing");
|
||||||
im.setUnbreakable(true);
|
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!"));
|
im.setLore(new KList<String>().qadd("Right click on a block to reveal it's placement structure!"));
|
||||||
is.setItemMeta(im);
|
is.setItemMeta(im);
|
||||||
|
|
||||||
@@ -205,11 +283,11 @@ public class WandSVC implements IrisService {
|
|||||||
*/
|
*/
|
||||||
public static ItemStack createWand(Location a, Location b) {
|
public static ItemStack createWand(Location a, Location b) {
|
||||||
ItemStack is = new ItemStack(Material.BLAZE_ROD);
|
ItemStack is = new ItemStack(Material.BLAZE_ROD);
|
||||||
is.addUnsafeEnchantment(Enchantment.ARROW_INFINITE, 1);
|
is.addUnsafeEnchantment(Enchantment.FIRE_ASPECT, 1);
|
||||||
ItemMeta im = is.getItemMeta();
|
ItemMeta im = is.getItemMeta();
|
||||||
im.setDisplayName(C.BOLD + "" + C.GOLD + "Wand of Iris");
|
im.setDisplayName(C.BOLD + "" + C.GOLD + "Wand of Iris");
|
||||||
im.setUnbreakable(true);
|
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)));
|
im.setLore(new KList<String>().add(locationToString(a), locationToString(b)));
|
||||||
is.setItemMeta(im);
|
is.setItemMeta(im);
|
||||||
|
|
||||||
@@ -226,17 +304,19 @@ public class WandSVC implements IrisService {
|
|||||||
return getCuboidFromItem(p.getInventory().getItemInMainHand());
|
return getCuboidFromItem(p.getInventory().getItemInMainHand());
|
||||||
}
|
}
|
||||||
|
|
||||||
Cuboid c = WorldEditLink.getSelection(p);
|
if (IrisSettings.get().getWorld().worldEditWandCUI) {
|
||||||
|
Cuboid c = WorldEditLink.getSelection(p);
|
||||||
|
|
||||||
if (c != null) {
|
if (c != null) {
|
||||||
return new Location[]{c.getLowerNE(), c.getUpperSW()};
|
return new Location[]{c.getLowerNE(), c.getUpperSW()};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isHoldingWand(Player p) {
|
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) {
|
public static boolean isHoldingIrisWand(Player p) {
|
||||||
@@ -251,7 +331,6 @@ public class WandSVC implements IrisService {
|
|||||||
* @return True if it is
|
* @return True if it is
|
||||||
*/
|
*/
|
||||||
public static boolean isWand(ItemStack is) {
|
public static boolean isWand(ItemStack is) {
|
||||||
ItemStack wand = createWand();
|
|
||||||
if (is.getItemMeta() == null) return false;
|
if (is.getItemMeta() == null) return false;
|
||||||
return is.getType().equals(wand.getType()) &&
|
return is.getType().equals(wand.getType()) &&
|
||||||
is.getItemMeta().getDisplayName().equals(wand.getItemMeta().getDisplayName()) &&
|
is.getItemMeta().getDisplayName().equals(wand.getItemMeta().getDisplayName()) &&
|
||||||
@@ -261,7 +340,7 @@ public class WandSVC implements IrisService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEnable() {
|
public void onEnable() {
|
||||||
ItemStack wand = createWand();
|
wand = createWand();
|
||||||
dust = createDust();
|
dust = createDust();
|
||||||
|
|
||||||
J.ar(() -> {
|
J.ar(() -> {
|
||||||
@@ -309,9 +388,9 @@ public class WandSVC implements IrisService {
|
|||||||
*/
|
*/
|
||||||
public void draw(Location[] d, Player p) {
|
public void draw(Location[] d, Player p) {
|
||||||
Vector gx = Vector.getRandom().subtract(Vector.getRandom()).normalize().clone().multiply(0.65);
|
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);
|
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())) {
|
if (!d[0].getWorld().equals(d[1].getWorld())) {
|
||||||
return;
|
return;
|
||||||
@@ -368,7 +447,7 @@ public class WandSVC implements IrisService {
|
|||||||
int r = color.getRed();
|
int r = color.getRed();
|
||||||
int g = color.getGreen();
|
int g = color.getGreen();
|
||||||
int b = color.getBlue();
|
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)
|
if (e.getHand() != EquipmentSlot.HAND)
|
||||||
return;
|
return;
|
||||||
try {
|
try {
|
||||||
if (isHoldingWand(e.getPlayer())) {
|
if (isHoldingIrisWand(e.getPlayer())) {
|
||||||
if (e.getAction().equals(Action.LEFT_CLICK_BLOCK)) {
|
if (e.getAction().equals(Action.LEFT_CLICK_BLOCK)) {
|
||||||
e.setCancelled(true);
|
e.setCancelled(true);
|
||||||
e.getPlayer().getInventory().setItemInMainHand(update(true, Objects.requireNonNull(e.getClickedBlock()).getLocation(), e.getPlayer().getInventory().getItemInMainHand()));
|
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.google.common.math.LongMath.isPrime;
|
||||||
import static com.volmit.iris.util.misc.getHardware.getCPUModel;
|
import static com.volmit.iris.util.misc.getHardware.getCPUModel;
|
||||||
import static com.volmit.iris.util.misc.getHardware.getDiskModel;
|
|
||||||
public class IrisBenchmarking {
|
public class IrisBenchmarking {
|
||||||
static String ServerOS;
|
static String ServerOS;
|
||||||
static String filePath = "benchmark.dat";
|
static String filePath = "benchmark.dat";
|
||||||
@@ -180,12 +179,12 @@ public class IrisBenchmarking {
|
|||||||
Iris.info("- Data Compression: " + formatDouble(calculateDataCompression) + " MBytes/Sec");
|
Iris.info("- Data Compression: " + formatDouble(calculateDataCompression) + " MBytes/Sec");
|
||||||
|
|
||||||
if (WindowsDiskSpeed) {
|
if (WindowsDiskSpeed) {
|
||||||
Iris.info("Disk Model: " + getDiskModel());
|
//Iris.info("Disk Model: " + getDiskModel());
|
||||||
Iris.info(C.BLUE + "- Running with Windows System Assessment Tool");
|
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 Write: " + C.BLUE + formatDouble(avgWriteSpeedMBps) + " Mbps");
|
||||||
Iris.info("- Sequential 64.0 Read: " + C.BLUE + formatDouble(avgReadSpeedMBps) + " Mbps");
|
Iris.info("- Sequential 64.0 Read: " + C.BLUE + formatDouble(avgReadSpeedMBps) + " Mbps");
|
||||||
} else {
|
} else {
|
||||||
Iris.info("Disk Model: " + getDiskModel());
|
// Iris.info("Disk Model: " + getDiskModel());
|
||||||
Iris.info(C.GREEN + "- Running in Native Mode");
|
Iris.info(C.GREEN + "- Running in Native Mode");
|
||||||
Iris.info("- Average Write Speed: " + C.GREEN + formatDouble(avgWriteSpeedMBps) + " Mbps");
|
Iris.info("- Average Write Speed: " + C.GREEN + formatDouble(avgWriteSpeedMBps) + " Mbps");
|
||||||
Iris.info("- Average Read Speed: " + C.GREEN + formatDouble(avgReadSpeedMBps) + " Mbps");
|
Iris.info("- Average Read Speed: " + C.GREEN + formatDouble(avgReadSpeedMBps) + " Mbps");
|
||||||
|
|||||||
@@ -0,0 +1,138 @@
|
|||||||
|
package com.volmit.iris.core.tools;
|
||||||
|
|
||||||
|
import com.volmit.iris.Iris;
|
||||||
|
import com.volmit.iris.engine.object.*;
|
||||||
|
import com.volmit.iris.util.format.C;
|
||||||
|
import com.volmit.iris.util.format.Form;
|
||||||
|
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 {
|
||||||
|
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);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -26,7 +26,6 @@ import com.volmit.iris.core.pregenerator.PregenTask;
|
|||||||
import com.volmit.iris.core.service.StudioSVC;
|
import com.volmit.iris.core.service.StudioSVC;
|
||||||
import com.volmit.iris.engine.object.IrisDimension;
|
import com.volmit.iris.engine.object.IrisDimension;
|
||||||
import com.volmit.iris.engine.platform.PlatformChunkGenerator;
|
import com.volmit.iris.engine.platform.PlatformChunkGenerator;
|
||||||
import com.volmit.iris.engine.safeguard.UtilsSFG;
|
|
||||||
import com.volmit.iris.util.exceptions.IrisException;
|
import com.volmit.iris.util.exceptions.IrisException;
|
||||||
import com.volmit.iris.util.format.C;
|
import com.volmit.iris.util.format.C;
|
||||||
import com.volmit.iris.util.format.Form;
|
import com.volmit.iris.util.format.Form;
|
||||||
@@ -46,9 +45,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import static com.volmit.iris.core.tools.IrisPackBenchmarking.benchmark;
|
|
||||||
import static com.volmit.iris.engine.safeguard.IrisSafeguard.unstablemode;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Makes it a lot easier to setup an engine, world, studio or whatever
|
* Makes it a lot easier to setup an engine, world, studio or whatever
|
||||||
*/
|
*/
|
||||||
@@ -83,6 +79,11 @@ public class IrisCreator {
|
|||||||
* the world itself. Studio worlds are deleted when they are unloaded.
|
* the world itself. Studio worlds are deleted when they are unloaded.
|
||||||
*/
|
*/
|
||||||
private boolean studio = false;
|
private boolean studio = false;
|
||||||
|
/**
|
||||||
|
* Benchmark mode
|
||||||
|
*/
|
||||||
|
private boolean benchmark = false;
|
||||||
|
private boolean smartVanillaHeight = false;
|
||||||
|
|
||||||
public static boolean removeFromBukkitYml(String name) throws IOException {
|
public static boolean removeFromBukkitYml(String name) throws IOException {
|
||||||
YamlConfiguration yml = YamlConfiguration.loadConfiguration(BUKKIT_YML);
|
YamlConfiguration yml = YamlConfiguration.loadConfiguration(BUKKIT_YML);
|
||||||
@@ -107,15 +108,8 @@ public class IrisCreator {
|
|||||||
* @return the IrisAccess
|
* @return the IrisAccess
|
||||||
* @throws IrisException shit happens
|
* @throws IrisException shit happens
|
||||||
*/
|
*/
|
||||||
IrisPackBenchmarking PackBench = new IrisPackBenchmarking();
|
|
||||||
public World create() throws IrisException {
|
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()) {
|
if (Bukkit.isPrimaryThread()) {
|
||||||
throw new IrisException("You cannot invoke create() on the main thread.");
|
throw new IrisException("You cannot invoke create() on the main thread.");
|
||||||
}
|
}
|
||||||
@@ -129,14 +123,11 @@ public class IrisCreator {
|
|||||||
if (sender == null)
|
if (sender == null)
|
||||||
sender = Iris.getSender();
|
sender = Iris.getSender();
|
||||||
|
|
||||||
if (!studio()) {
|
if (!studio() || benchmark) {
|
||||||
Iris.service(StudioSVC.class).installIntoWorld(sender, d.getLoadKey(), new File(Bukkit.getWorldContainer(), name()));
|
|
||||||
}
|
|
||||||
if (benchmark) {
|
|
||||||
Iris.service(StudioSVC.class).installIntoWorld(sender, d.getLoadKey(), new File(Bukkit.getWorldContainer(), name()));
|
Iris.service(StudioSVC.class).installIntoWorld(sender, d.getLoadKey(), new File(Bukkit.getWorldContainer(), name()));
|
||||||
}
|
}
|
||||||
|
|
||||||
PlatformChunkGenerator access = null;
|
PlatformChunkGenerator access;
|
||||||
AtomicReference<World> world = new AtomicReference<>();
|
AtomicReference<World> world = new AtomicReference<>();
|
||||||
AtomicDouble pp = new AtomicDouble(0);
|
AtomicDouble pp = new AtomicDouble(0);
|
||||||
O<Boolean> done = new O<>();
|
O<Boolean> done = new O<>();
|
||||||
@@ -146,6 +137,7 @@ public class IrisCreator {
|
|||||||
.name(name)
|
.name(name)
|
||||||
.seed(seed)
|
.seed(seed)
|
||||||
.studio(studio)
|
.studio(studio)
|
||||||
|
.smartVanillaHeight(smartVanillaHeight)
|
||||||
.create();
|
.create();
|
||||||
ServerConfigurator.installDataPacks(false);
|
ServerConfigurator.installDataPacks(false);
|
||||||
|
|
||||||
@@ -154,7 +146,6 @@ public class IrisCreator {
|
|||||||
|
|
||||||
J.a(() ->
|
J.a(() ->
|
||||||
{
|
{
|
||||||
int req = 441;
|
|
||||||
Supplier<Integer> g = () -> {
|
Supplier<Integer> g = () -> {
|
||||||
if (finalAccess1 == null || finalAccess1.getEngine() == null) {
|
if (finalAccess1 == null || finalAccess1.getEngine() == null) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -162,6 +153,9 @@ public class IrisCreator {
|
|||||||
return finalAccess1.getEngine().getGenerated();
|
return finalAccess1.getEngine().getGenerated();
|
||||||
};
|
};
|
||||||
if(!benchmark) {
|
if(!benchmark) {
|
||||||
|
if (finalAccess1 == null) return;
|
||||||
|
int req = finalAccess1.getSpawnChunks().join();
|
||||||
|
|
||||||
while (g.get() < req) {
|
while (g.get() < req) {
|
||||||
double v = (double) g.get() / (double) req;
|
double v = (double) g.get() / (double) req;
|
||||||
if (sender.isPlayer()) {
|
if (sender.isPlayer()) {
|
||||||
@@ -173,7 +167,6 @@ public class IrisCreator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//if (benchmark){loaded = true;}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -191,7 +184,7 @@ public class IrisCreator {
|
|||||||
|
|
||||||
done.set(true);
|
done.set(true);
|
||||||
|
|
||||||
if (sender.isPlayer()) {
|
if (sender.isPlayer() && !benchmark) {
|
||||||
J.s(() -> {
|
J.s(() -> {
|
||||||
sender.player().teleport(new Location(world.get(), 0, world.get().getHighestBlockYAt(0, 0), 0));
|
sender.player().teleport(new Location(world.get(), 0, world.get().getHighestBlockYAt(0, 0), 0));
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,169 +2,202 @@ package com.volmit.iris.core.tools;
|
|||||||
|
|
||||||
|
|
||||||
import com.volmit.iris.Iris;
|
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.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.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 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 org.bukkit.Bukkit;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.io.FileWriter;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.io.IOException;
|
||||||
|
import java.nio.file.FileVisitResult;
|
||||||
import static com.volmit.iris.core.commands.CommandIris.BenchDimension;
|
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;
|
||||||
|
|
||||||
|
|
||||||
public class IrisPackBenchmarking {
|
public class IrisPackBenchmarking {
|
||||||
public static boolean loaded = false;
|
@Getter
|
||||||
public static boolean benchmark = false;
|
public static IrisPackBenchmarking instance;
|
||||||
static boolean cancelled = false;
|
public static boolean benchmarkInProgress = false;
|
||||||
static boolean pregenInProgress = false;
|
private final PrecisionStopwatch stopwatch = new PrecisionStopwatch();
|
||||||
static long startTime;
|
private final IrisDimension dimension;
|
||||||
static long totalChunks;
|
private final int radius;
|
||||||
static long generatedChunks;
|
private final boolean gui;
|
||||||
static double elapsedTimeNs;
|
|
||||||
|
|
||||||
public static void runBenchmark() {
|
public IrisPackBenchmarking(IrisDimension dimension, int radius, boolean gui) {
|
||||||
// IrisPackBenchmarking IrisPackBenchmarking = new IrisPackBenchmarking();
|
instance = this;
|
||||||
benchmark = true;
|
this.dimension = dimension;
|
||||||
Iris.info(C.BLUE + "Benchmarking Dimension: " + C.AQUA + BenchDimension);
|
this.radius = radius;
|
||||||
//progress();
|
this.gui = gui;
|
||||||
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
|
runBenchmark();
|
||||||
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;
|
|
||||||
|
|
||||||
|
private void runBenchmark() {
|
||||||
|
Thread.ofVirtual()
|
||||||
|
.name("PackBenchmarking")
|
||||||
|
.start(() -> {
|
||||||
|
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(profilers, dimension.getName() + " " + LocalDateTime.now(Clock.systemDefaultZone()).toString().replace(':', '-') + ".txt");
|
||||||
|
results.getParentFile().mkdirs();
|
||||||
|
KMap<String, Double> metrics = engine.getMetrics().pull();
|
||||||
|
try (FileWriter writer = new FileWriter(results)) {
|
||||||
|
writer.write("-----------------\n");
|
||||||
|
writer.write("Results:\n");
|
||||||
|
writer.write("Dimension: " + dimension.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) {
|
writer.write("- " + metrics);
|
||||||
throw new RuntimeException();
|
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(() -> {
|
J.s(() -> {
|
||||||
Iris.info(C.GOLD + "Creating Benchmark Environment");
|
var world = Bukkit.getWorld("benchmark");
|
||||||
createBenchmark();
|
if (world == null) return;
|
||||||
|
IrisToolbelt.evacuate(world);
|
||||||
|
Bukkit.unloadWorld(world, true);
|
||||||
|
});
|
||||||
|
|
||||||
}).thenRun(() -> {
|
stopwatch.end();
|
||||||
Iris.info( C.BLUE + "Benchmark Started!");
|
} catch (Exception e) {
|
||||||
boolean done = false;
|
Iris.error("Something has gone wrong!");
|
||||||
startBenchmarkTimer();
|
|
||||||
startBenchmark();
|
|
||||||
basicScheduler();
|
|
||||||
}).thenRun(() -> {
|
|
||||||
|
|
||||||
});
|
|
||||||
// cancelled = future.cancel(true);
|
|
||||||
try {
|
|
||||||
future.get();
|
|
||||||
} catch (InterruptedException | ExecutionException e) {
|
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void results(){
|
private void createBenchmark() {
|
||||||
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(){
|
|
||||||
try {
|
try {
|
||||||
IrisToolbelt.createWorld()
|
IrisToolbelt.createWorld()
|
||||||
.dimension(BenchDimension)
|
.dimension(dimension.getLoadKey())
|
||||||
.name("Benchmark")
|
.name("benchmark")
|
||||||
.seed(1337)
|
.seed(1337)
|
||||||
.studio(false)
|
.studio(false)
|
||||||
|
.benchmark(true)
|
||||||
.create();
|
.create();
|
||||||
} catch (IrisException e) {
|
} catch (IrisException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static void startBenchmark(){
|
|
||||||
int x = 0;
|
|
||||||
int z = 0;
|
|
||||||
IrisToolbelt.pregenerate(PregenTask
|
|
||||||
.builder()
|
|
||||||
.center(new Position2(x, z))
|
|
||||||
.width(5)
|
|
||||||
.height(5)
|
|
||||||
.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"));
|
private void startBenchmark() {
|
||||||
pregenerator.start();
|
IrisToolbelt.pregenerate(PregenTask
|
||||||
}
|
.builder()
|
||||||
public static double calculateAverageCPS() {
|
.gui(gui)
|
||||||
double elapsedTimeSec = elapsedTimeNs / 1_000_000_000.0; // Convert to seconds
|
.width(radius)
|
||||||
return generatedChunks / elapsedTimeSec;
|
.height(radius)
|
||||||
|
.build(), Bukkit.getWorld("benchmark")
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void startBenchmarkTimer() {
|
private double calculateAverage(KList<Integer> list) {
|
||||||
startTime = System.nanoTime();
|
double sum = 0;
|
||||||
}
|
for (int num : list) {
|
||||||
|
sum += num;
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
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<>() {
|
||||||
|
@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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -19,8 +19,7 @@
|
|||||||
package com.volmit.iris.core.tools;
|
package com.volmit.iris.core.tools;
|
||||||
|
|
||||||
import com.volmit.iris.core.loader.IrisData;
|
import com.volmit.iris.core.loader.IrisData;
|
||||||
import com.volmit.iris.engine.object.IrisDimension;
|
import com.volmit.iris.engine.object.*;
|
||||||
import com.volmit.iris.engine.object.IrisWorld;
|
|
||||||
import com.volmit.iris.engine.platform.BukkitChunkGenerator;
|
import com.volmit.iris.engine.platform.BukkitChunkGenerator;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
@@ -33,6 +32,7 @@ public class IrisWorldCreator {
|
|||||||
private String name;
|
private String name;
|
||||||
private boolean studio = false;
|
private boolean studio = false;
|
||||||
private String dimensionName = null;
|
private String dimensionName = null;
|
||||||
|
private boolean smartVanillaHeight = false;
|
||||||
private long seed = 1337;
|
private long seed = 1337;
|
||||||
|
|
||||||
public IrisWorldCreator() {
|
public IrisWorldCreator() {
|
||||||
@@ -64,6 +64,11 @@ public class IrisWorldCreator {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IrisWorldCreator smartVanillaHeight(boolean smartVanillaHeight) {
|
||||||
|
this.smartVanillaHeight = smartVanillaHeight;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public WorldCreator create() {
|
public WorldCreator create() {
|
||||||
IrisDimension dim = IrisData.loadAnyDimension(dimensionName);
|
IrisDimension dim = IrisData.loadAnyDimension(dimensionName);
|
||||||
|
|
||||||
@@ -77,7 +82,8 @@ public class IrisWorldCreator {
|
|||||||
.build();
|
.build();
|
||||||
ChunkGenerator g = new BukkitChunkGenerator(w, studio, studio
|
ChunkGenerator g = new BukkitChunkGenerator(w, studio, studio
|
||||||
? dim.getLoader().getDataFolder() :
|
? dim.getLoader().getDataFolder() :
|
||||||
new File(w.worldFolder(), "iris/pack"), dimensionName);
|
new File(w.worldFolder(), "iris/pack"), dimensionName, smartVanillaHeight);
|
||||||
|
|
||||||
|
|
||||||
return new WorldCreator(name)
|
return new WorldCreator(name)
|
||||||
.environment(findEnvironment())
|
.environment(findEnvironment())
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ package com.volmit.iris.core.wand;
|
|||||||
import com.volmit.iris.util.data.Cuboid;
|
import com.volmit.iris.util.data.Cuboid;
|
||||||
import com.volmit.iris.util.math.M;
|
import com.volmit.iris.util.math.M;
|
||||||
import com.volmit.iris.util.math.RNG;
|
import com.volmit.iris.util.math.RNG;
|
||||||
|
import com.volmit.iris.util.misc.E;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.Particle;
|
import org.bukkit.Particle;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
@@ -29,8 +30,10 @@ import org.bukkit.util.Vector;
|
|||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
|
|
||||||
public class WandSelection {
|
public class WandSelection {
|
||||||
|
private static final Particle REDSTONE = E.getOrDefault(Particle.class, "REDSTONE", "DUST");
|
||||||
private final Cuboid c;
|
private final Cuboid c;
|
||||||
private final Player p;
|
private final Player p;
|
||||||
|
private static final double STEP = 0.10;
|
||||||
|
|
||||||
public WandSelection(Cuboid c, Player p) {
|
public WandSelection(Cuboid c, Player p) {
|
||||||
this.c = c;
|
this.c = c;
|
||||||
@@ -38,77 +41,58 @@ public class WandSelection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void draw() {
|
public void draw() {
|
||||||
double accuracy;
|
Location playerLoc = p.getLocation();
|
||||||
double dist;
|
double maxDistanceSquared = 256 * 256;
|
||||||
|
int particleCount = 0;
|
||||||
|
|
||||||
for (double i = c.getLowerX() - 1; i < c.getUpperX() + 1; i += 0.25) {
|
// cube!
|
||||||
for (double j = c.getLowerY() - 1; j < c.getUpperY() + 1; j += 0.25) {
|
Location[][] edges = {
|
||||||
for (double k = c.getLowerZ() - 1; k < c.getUpperZ() + 1; k += 0.25) {
|
{c.getLowerNE(), new Location(c.getWorld(), c.getUpperX() + 1, c.getLowerY(), c.getLowerZ())},
|
||||||
boolean ii = i == c.getLowerX() || i == c.getUpperX();
|
{c.getLowerNE(), new Location(c.getWorld(), c.getLowerX(), c.getUpperY() + 1, c.getLowerZ())},
|
||||||
boolean jj = j == c.getLowerY() || j == c.getUpperY();
|
{c.getLowerNE(), new Location(c.getWorld(), c.getLowerX(), c.getLowerY(), c.getUpperZ() + 1)},
|
||||||
boolean kk = k == c.getLowerZ() || k == c.getUpperZ();
|
{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)) {
|
for (Location[] edge : edges) {
|
||||||
Vector push = new Vector(0, 0, 0);
|
Vector direction = edge[1].toVector().subtract(edge[0].toVector());
|
||||||
|
double length = direction.length();
|
||||||
|
direction.normalize();
|
||||||
|
|
||||||
if (i == c.getLowerX()) {
|
for (double d = 0; d <= length; d += STEP) {
|
||||||
push.add(new Vector(-0.55, 0, 0));
|
Location particleLoc = edge[0].clone().add(direction.clone().multiply(d));
|
||||||
}
|
|
||||||
|
|
||||||
if (j == c.getLowerY()) {
|
if (playerLoc.distanceSquared(particleLoc) > maxDistanceSquared) {
|
||||||
push.add(new Vector(0, -0.55, 0));
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,12 +29,15 @@ import com.volmit.iris.util.collection.KMap;
|
|||||||
import com.volmit.iris.util.collection.KSet;
|
import com.volmit.iris.util.collection.KSet;
|
||||||
import com.volmit.iris.util.context.IrisContext;
|
import com.volmit.iris.util.context.IrisContext;
|
||||||
import com.volmit.iris.util.data.DataProvider;
|
import com.volmit.iris.util.data.DataProvider;
|
||||||
|
import com.volmit.iris.util.interpolation.IrisInterpolation.NoiseKey;
|
||||||
import com.volmit.iris.util.math.M;
|
import com.volmit.iris.util.math.M;
|
||||||
import com.volmit.iris.util.math.RNG;
|
import com.volmit.iris.util.math.RNG;
|
||||||
import com.volmit.iris.util.noise.CNG;
|
import com.volmit.iris.util.noise.CNG;
|
||||||
import com.volmit.iris.util.stream.ProceduralStream;
|
import com.volmit.iris.util.stream.ProceduralStream;
|
||||||
import com.volmit.iris.util.stream.interpolation.Interpolated;
|
import com.volmit.iris.util.stream.interpolation.Interpolated;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.ToString;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.block.Biome;
|
import org.bukkit.block.Biome;
|
||||||
import org.bukkit.block.data.BlockData;
|
import org.bukkit.block.data.BlockData;
|
||||||
@@ -42,6 +45,8 @@ import org.bukkit.block.data.BlockData;
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
|
@EqualsAndHashCode(exclude = "data")
|
||||||
|
@ToString(exclude = "data")
|
||||||
public class IrisComplex implements DataProvider {
|
public class IrisComplex implements DataProvider {
|
||||||
private static final BlockData AIR = Material.AIR.createBlockData();
|
private static final BlockData AIR = Material.AIR.createBlockData();
|
||||||
private RNG rng;
|
private RNG rng;
|
||||||
@@ -100,6 +105,12 @@ public class IrisComplex implements DataProvider {
|
|||||||
if (focusBiome != null) {
|
if (focusBiome != null) {
|
||||||
focusBiome.setInferredType(InferredType.LAND);
|
focusBiome.setInferredType(InferredType.LAND);
|
||||||
focusRegion = findRegion(focusBiome, engine);
|
focusRegion = findRegion(focusBiome, engine);
|
||||||
|
focusBiome.getGenerators().forEach((c) -> registerGenerator(c.getCachedGenerator(this)));
|
||||||
|
} else if (focusRegion != null) {
|
||||||
|
data.getRegionLoader().load(focusRegion.getLoadKey())
|
||||||
|
.getAllBiomes(this).forEach((b) -> b
|
||||||
|
.getGenerators()
|
||||||
|
.forEach((c) -> registerGenerator(c.getCachedGenerator(this))));
|
||||||
}
|
}
|
||||||
|
|
||||||
//@builder
|
//@builder
|
||||||
@@ -127,6 +138,7 @@ public class IrisComplex implements DataProvider {
|
|||||||
caveBiomeStream = regionStream.contextInjecting((c, x, z) -> IrisContext.getOr(engine).getChunkContext().getRegion().get(x, z))
|
caveBiomeStream = regionStream.contextInjecting((c, x, z) -> IrisContext.getOr(engine).getChunkContext().getRegion().get(x, z))
|
||||||
.convert((r)
|
.convert((r)
|
||||||
-> engine.getDimension().getCaveBiomeStyle().create(rng.nextParallelRNG(InferredType.CAVE.ordinal()), getData()).stream()
|
-> engine.getDimension().getCaveBiomeStyle().create(rng.nextParallelRNG(InferredType.CAVE.ordinal()), getData()).stream()
|
||||||
|
.zoom(engine.getDimension().getBiomeZoom())
|
||||||
.zoom(r.getCaveBiomeZoom())
|
.zoom(r.getCaveBiomeZoom())
|
||||||
.selectRarity(data.getBiomeLoader().loadAll(r.getCaveBiomes()))
|
.selectRarity(data.getBiomeLoader().loadAll(r.getCaveBiomes()))
|
||||||
.onNull(emptyBiome)
|
.onNull(emptyBiome)
|
||||||
@@ -135,6 +147,8 @@ public class IrisComplex implements DataProvider {
|
|||||||
landBiomeStream = regionStream.contextInjecting((c, x, z) -> IrisContext.getOr(engine).getChunkContext().getRegion().get(x, z))
|
landBiomeStream = regionStream.contextInjecting((c, x, z) -> IrisContext.getOr(engine).getChunkContext().getRegion().get(x, z))
|
||||||
.convert((r)
|
.convert((r)
|
||||||
-> engine.getDimension().getLandBiomeStyle().create(rng.nextParallelRNG(InferredType.LAND.ordinal()), getData()).stream()
|
-> engine.getDimension().getLandBiomeStyle().create(rng.nextParallelRNG(InferredType.LAND.ordinal()), getData()).stream()
|
||||||
|
.zoom(engine.getDimension().getBiomeZoom())
|
||||||
|
.zoom(engine.getDimension().getLandZoom())
|
||||||
.zoom(r.getLandBiomeZoom())
|
.zoom(r.getLandBiomeZoom())
|
||||||
.selectRarity(data.getBiomeLoader().loadAll(r.getLandBiomes(), (t) -> t.setInferredType(InferredType.LAND)))
|
.selectRarity(data.getBiomeLoader().loadAll(r.getLandBiomes(), (t) -> t.setInferredType(InferredType.LAND)))
|
||||||
).convertAware2D(ProceduralStream::get)
|
).convertAware2D(ProceduralStream::get)
|
||||||
@@ -143,6 +157,8 @@ public class IrisComplex implements DataProvider {
|
|||||||
seaBiomeStream = regionStream.contextInjecting((c, x, z) -> IrisContext.getOr(engine).getChunkContext().getRegion().get(x, z))
|
seaBiomeStream = regionStream.contextInjecting((c, x, z) -> IrisContext.getOr(engine).getChunkContext().getRegion().get(x, z))
|
||||||
.convert((r)
|
.convert((r)
|
||||||
-> engine.getDimension().getSeaBiomeStyle().create(rng.nextParallelRNG(InferredType.SEA.ordinal()), getData()).stream()
|
-> engine.getDimension().getSeaBiomeStyle().create(rng.nextParallelRNG(InferredType.SEA.ordinal()), getData()).stream()
|
||||||
|
.zoom(engine.getDimension().getBiomeZoom())
|
||||||
|
.zoom(engine.getDimension().getSeaZoom())
|
||||||
.zoom(r.getSeaBiomeZoom())
|
.zoom(r.getSeaBiomeZoom())
|
||||||
.selectRarity(data.getBiomeLoader().loadAll(r.getSeaBiomes(), (t) -> t.setInferredType(InferredType.SEA)))
|
.selectRarity(data.getBiomeLoader().loadAll(r.getSeaBiomes(), (t) -> t.setInferredType(InferredType.SEA)))
|
||||||
).convertAware2D(ProceduralStream::get)
|
).convertAware2D(ProceduralStream::get)
|
||||||
@@ -151,6 +167,7 @@ public class IrisComplex implements DataProvider {
|
|||||||
shoreBiomeStream = regionStream.contextInjecting((c, x, z) -> IrisContext.getOr(engine).getChunkContext().getRegion().get(x, z))
|
shoreBiomeStream = regionStream.contextInjecting((c, x, z) -> IrisContext.getOr(engine).getChunkContext().getRegion().get(x, z))
|
||||||
.convert((r)
|
.convert((r)
|
||||||
-> engine.getDimension().getShoreBiomeStyle().create(rng.nextParallelRNG(InferredType.SHORE.ordinal()), getData()).stream()
|
-> engine.getDimension().getShoreBiomeStyle().create(rng.nextParallelRNG(InferredType.SHORE.ordinal()), getData()).stream()
|
||||||
|
.zoom(engine.getDimension().getBiomeZoom())
|
||||||
.zoom(r.getShoreBiomeZoom())
|
.zoom(r.getShoreBiomeZoom())
|
||||||
.selectRarity(data.getBiomeLoader().loadAll(r.getShoreBiomes(), (t) -> t.setInferredType(InferredType.SHORE)))
|
.selectRarity(data.getBiomeLoader().loadAll(r.getShoreBiomes(), (t) -> t.setInferredType(InferredType.SHORE)))
|
||||||
).convertAware2D(ProceduralStream::get).cache2D("shoreBiomeStream", engine, cacheSize).waste("Shore Biome Stream");
|
).convertAware2D(ProceduralStream::get).cache2D("shoreBiomeStream", engine, cacheSize).waste("Shore Biome Stream");
|
||||||
@@ -282,13 +299,15 @@ public class IrisComplex implements DataProvider {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KMap<NoiseKey, IrisBiome> cache = new KMap<>();
|
||||||
double hi = interpolator.interpolate(x, z, (xx, zz) -> {
|
double hi = interpolator.interpolate(x, z, (xx, zz) -> {
|
||||||
try {
|
try {
|
||||||
IrisBiome bx = baseBiomeStream.get(xx, zz);
|
IrisBiome bx = baseBiomeStream.get(xx, zz);
|
||||||
|
cache.put(new NoiseKey(xx, zz), bx);
|
||||||
double b = 0;
|
double b = 0;
|
||||||
|
|
||||||
for (IrisGenerator gen : generators) {
|
for (IrisGenerator gen : generators) {
|
||||||
b += bx.getGenLinkMax(gen.getLoadKey());
|
b += bx.getGenLinkMax(gen.getLoadKey(), engine);
|
||||||
}
|
}
|
||||||
|
|
||||||
return b;
|
return b;
|
||||||
@@ -303,11 +322,15 @@ public class IrisComplex implements DataProvider {
|
|||||||
|
|
||||||
double lo = interpolator.interpolate(x, z, (xx, zz) -> {
|
double lo = interpolator.interpolate(x, z, (xx, zz) -> {
|
||||||
try {
|
try {
|
||||||
IrisBiome bx = baseBiomeStream.get(xx, zz);
|
IrisBiome bx = cache.get(new NoiseKey(xx, zz));
|
||||||
|
if (bx == null) {
|
||||||
|
bx = baseBiomeStream.get(xx, zz);
|
||||||
|
cache.put(new NoiseKey(xx, zz), bx);
|
||||||
|
}
|
||||||
double b = 0;
|
double b = 0;
|
||||||
|
|
||||||
for (IrisGenerator gen : generators) {
|
for (IrisGenerator gen : generators) {
|
||||||
b += bx.getGenLinkMin(gen.getLoadKey());
|
b += bx.getGenLinkMin(gen.getLoadKey(), engine);
|
||||||
}
|
}
|
||||||
|
|
||||||
return b;
|
return b;
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ package com.volmit.iris.engine;
|
|||||||
import com.google.common.util.concurrent.AtomicDouble;
|
import com.google.common.util.concurrent.AtomicDouble;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.Iris;
|
||||||
|
import com.volmit.iris.core.IrisSettings;
|
||||||
import com.volmit.iris.core.ServerConfigurator;
|
import com.volmit.iris.core.ServerConfigurator;
|
||||||
import com.volmit.iris.core.events.IrisEngineHotloadEvent;
|
import com.volmit.iris.core.events.IrisEngineHotloadEvent;
|
||||||
import com.volmit.iris.core.gui.PregeneratorJob;
|
import com.volmit.iris.core.gui.PregeneratorJob;
|
||||||
@@ -50,6 +51,9 @@ import com.volmit.iris.util.scheduling.ChronoLatch;
|
|||||||
import com.volmit.iris.util.scheduling.J;
|
import com.volmit.iris.util.scheduling.J;
|
||||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.ToString;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.block.Biome;
|
import org.bukkit.block.Biome;
|
||||||
import org.bukkit.block.data.BlockData;
|
import org.bukkit.block.data.BlockData;
|
||||||
@@ -62,8 +66,12 @@ import java.util.Set;
|
|||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
|
@EqualsAndHashCode(exclude = "context")
|
||||||
|
@ToString(exclude = "context")
|
||||||
public class IrisEngine implements Engine {
|
public class IrisEngine implements Engine {
|
||||||
private final AtomicInteger bud;
|
private final AtomicInteger bud;
|
||||||
private final AtomicInteger buds;
|
private final AtomicInteger buds;
|
||||||
@@ -246,23 +254,40 @@ public class IrisEngine implements Engine {
|
|||||||
return engineData.aquire(() -> {
|
return engineData.aquire(() -> {
|
||||||
//TODO: Method this file
|
//TODO: Method this file
|
||||||
File f = new File(getWorld().worldFolder(), "iris/engine-data/" + getDimension().getLoadKey() + ".json");
|
File f = new File(getWorld().worldFolder(), "iris/engine-data/" + getDimension().getLoadKey() + ".json");
|
||||||
|
IrisEngineData data = null;
|
||||||
|
|
||||||
if (!f.exists()) {
|
if (f.exists()) {
|
||||||
try {
|
try {
|
||||||
f.getParentFile().mkdirs();
|
data = new Gson().fromJson(IO.readAll(f), IrisEngineData.class);
|
||||||
IO.writeAll(f, new Gson().toJson(new IrisEngineData()));
|
if (data == null) {
|
||||||
|
Iris.error("Failed to read Engine Data! Corrupted File? recreating...");
|
||||||
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
if (data == null) {
|
||||||
return new Gson().fromJson(IO.readAll(f), IrisEngineData.class);
|
data = new IrisEngineData();
|
||||||
} catch (Throwable e) {
|
data.getStatistics().setVersion(Iris.instance.getIrisVersion());
|
||||||
e.printStackTrace();
|
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 +443,6 @@ public class IrisEngine implements Engine {
|
|||||||
|
|
||||||
J.a(() -> {
|
J.a(() -> {
|
||||||
try {
|
try {
|
||||||
getMantle().trim();
|
|
||||||
getData().getObjectLoader().clean();
|
getData().getObjectLoader().clean();
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
@@ -518,4 +542,19 @@ public class IrisEngine implements Engine {
|
|||||||
public int getCacheID() {
|
public int getCacheID() {
|
||||||
return cacheId;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,9 +18,7 @@
|
|||||||
|
|
||||||
package com.volmit.iris.engine;
|
package com.volmit.iris.engine;
|
||||||
|
|
||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.core.nms.container.Pair;
|
||||||
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.data.cache.AtomicCache;
|
||||||
import com.volmit.iris.engine.framework.Engine;
|
import com.volmit.iris.engine.framework.Engine;
|
||||||
import com.volmit.iris.engine.mantle.EngineMantle;
|
import com.volmit.iris.engine.mantle.EngineMantle;
|
||||||
@@ -29,31 +27,23 @@ import com.volmit.iris.engine.mantle.components.MantleCarvingComponent;
|
|||||||
import com.volmit.iris.engine.mantle.components.MantleFluidBodyComponent;
|
import com.volmit.iris.engine.mantle.components.MantleFluidBodyComponent;
|
||||||
import com.volmit.iris.engine.mantle.components.MantleJigsawComponent;
|
import com.volmit.iris.engine.mantle.components.MantleJigsawComponent;
|
||||||
import com.volmit.iris.engine.mantle.components.MantleObjectComponent;
|
import com.volmit.iris.engine.mantle.components.MantleObjectComponent;
|
||||||
import com.volmit.iris.engine.object.*;
|
|
||||||
import com.volmit.iris.util.collection.KList;
|
import com.volmit.iris.util.collection.KList;
|
||||||
import com.volmit.iris.util.collection.KMap;
|
import com.volmit.iris.util.collection.KMap;
|
||||||
import com.volmit.iris.util.collection.KSet;
|
|
||||||
import com.volmit.iris.util.format.C;
|
|
||||||
import com.volmit.iris.util.format.Form;
|
|
||||||
import com.volmit.iris.util.mantle.Mantle;
|
import com.volmit.iris.util.mantle.Mantle;
|
||||||
import com.volmit.iris.util.parallel.BurstExecutor;
|
import lombok.*;
|
||||||
import lombok.Data;
|
|
||||||
import org.bukkit.util.BlockVector;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.util.stream.Collectors;
|
||||||
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
|
@Data
|
||||||
|
@EqualsAndHashCode(exclude = "engine")
|
||||||
|
@ToString(exclude = "engine")
|
||||||
public class IrisEngineMantle implements EngineMantle {
|
public class IrisEngineMantle implements EngineMantle {
|
||||||
private final Engine engine;
|
private final Engine engine;
|
||||||
private final Mantle mantle;
|
private final Mantle mantle;
|
||||||
private final KList<MantleComponent> components;
|
@Getter(AccessLevel.NONE)
|
||||||
private final int radius;
|
private final KMap<Integer, KList<MantleComponent>> components;
|
||||||
|
private final AtomicCache<KList<Pair<KList<MantleComponent>, Integer>>> componentsCache = new AtomicCache<>();
|
||||||
private final AtomicCache<Integer> radCache = new AtomicCache<>();
|
private final AtomicCache<Integer> radCache = new AtomicCache<>();
|
||||||
private final MantleObjectComponent object;
|
private final MantleObjectComponent object;
|
||||||
private final MantleJigsawComponent jigsaw;
|
private final MantleJigsawComponent jigsaw;
|
||||||
@@ -61,8 +51,7 @@ public class IrisEngineMantle implements EngineMantle {
|
|||||||
public IrisEngineMantle(Engine engine) {
|
public IrisEngineMantle(Engine engine) {
|
||||||
this.engine = engine;
|
this.engine = engine;
|
||||||
this.mantle = new Mantle(new File(engine.getWorld().worldFolder(), "mantle"), engine.getTarget().getHeight());
|
this.mantle = new Mantle(new File(engine.getWorld().worldFolder(), "mantle"), engine.getTarget().getHeight());
|
||||||
radius = radCache.aquire(this::computeParallaxSize);
|
components = new KMap<>();
|
||||||
components = new KList<>();
|
|
||||||
registerComponent(new MantleCarvingComponent(this));
|
registerComponent(new MantleCarvingComponent(this));
|
||||||
registerComponent(new MantleFluidBodyComponent(this));
|
registerComponent(new MantleFluidBodyComponent(this));
|
||||||
jigsaw = new MantleJigsawComponent(this);
|
jigsaw = new MantleJigsawComponent(this);
|
||||||
@@ -71,9 +60,49 @@ public class IrisEngineMantle implements EngineMantle {
|
|||||||
registerComponent(object);
|
registerComponent(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getRadius() {
|
||||||
|
if (components.isEmpty()) return 0;
|
||||||
|
return getComponents().getFirst().getB();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getRealRadius() {
|
||||||
|
if (components.isEmpty()) return 0;
|
||||||
|
return getComponents().getLast().getB();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public KList<Pair<KList<MantleComponent>, Integer>> getComponents() {
|
||||||
|
return componentsCache.aquire(() -> {
|
||||||
|
var list = components.keySet()
|
||||||
|
.stream()
|
||||||
|
.sorted()
|
||||||
|
.map(components::get)
|
||||||
|
.map(components -> {
|
||||||
|
int radius = components.stream()
|
||||||
|
.mapToInt(MantleComponent::getRadius)
|
||||||
|
.max()
|
||||||
|
.orElse(0);
|
||||||
|
return new Pair<>(components, radius);
|
||||||
|
})
|
||||||
|
.collect(Collectors.toCollection(KList::new));
|
||||||
|
|
||||||
|
|
||||||
|
int radius = 0;
|
||||||
|
for (var pair : list.reversed()) {
|
||||||
|
radius += pair.getB();
|
||||||
|
pair.setB(Math.ceilDiv(radius, 16));
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void registerComponent(MantleComponent c) {
|
public void registerComponent(MantleComponent c) {
|
||||||
components.add(c);
|
components.computeIfAbsent(c.getPriority(), k -> new KList<>()).add(c);
|
||||||
|
componentsCache.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -85,255 +114,4 @@ public class IrisEngineMantle implements EngineMantle {
|
|||||||
public MantleObjectComponent getObjectComponent() {
|
public MantleObjectComponent getObjectComponent() {
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
private KList<IrisRegion> getAllRegions() {
|
|
||||||
KList<IrisRegion> r = new KList<>();
|
|
||||||
|
|
||||||
for (String i : getEngine().getDimension().getRegions()) {
|
|
||||||
r.add(getEngine().getData().getRegionLoader().load(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
private KList<IrisBiome> getAllBiomes() {
|
|
||||||
KList<IrisBiome> r = new KList<>();
|
|
||||||
|
|
||||||
for (IrisRegion i : getAllRegions()) {
|
|
||||||
r.addAll(i.getAllBiomes(getEngine()));
|
|
||||||
}
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void warn(String ob, BlockVector bv) {
|
|
||||||
if (Math.max(bv.getBlockX(), bv.getBlockZ()) > 128) {
|
|
||||||
Iris.warn("Object " + ob + " has a large size (" + bv + ") and may increase memory usage!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void warnScaled(String ob, BlockVector bv, double ms) {
|
|
||||||
if (Math.max(bv.getBlockX(), bv.getBlockZ()) > 128) {
|
|
||||||
Iris.warn("Object " + ob + " has a large size (" + bv + ") and may increase memory usage! (Object scaled up to " + Form.pc(ms, 2) + ")");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private int computeParallaxSize() {
|
|
||||||
Iris.verbose("Calculating the Parallax Size in Parallel");
|
|
||||||
AtomicInteger xg = new AtomicInteger(0);
|
|
||||||
AtomicInteger zg = new AtomicInteger();
|
|
||||||
xg.set(0);
|
|
||||||
zg.set(0);
|
|
||||||
int jig = 0;
|
|
||||||
KSet<String> objects = new KSet<>();
|
|
||||||
KMap<IrisObjectScale, KList<String>> scalars = new KMap<>();
|
|
||||||
int x = xg.get();
|
|
||||||
int z = zg.get();
|
|
||||||
|
|
||||||
if (getEngine().getDimension().isUseMantle()) {
|
|
||||||
KList<IrisRegion> r = getAllRegions();
|
|
||||||
KList<IrisBiome> b = getAllBiomes();
|
|
||||||
|
|
||||||
for (IrisBiome i : b) {
|
|
||||||
for (IrisObjectPlacement j : i.getObjects()) {
|
|
||||||
if (j.getScale().canScaleBeyond()) {
|
|
||||||
scalars.put(j.getScale(), j.getPlace());
|
|
||||||
} else {
|
|
||||||
objects.addAll(j.getPlace());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (IrisJigsawStructurePlacement j : i.getJigsawStructures()) {
|
|
||||||
jig = Math.max(jig, getData().getJigsawStructureLoader().load(j.getStructure()).getMaxDimension());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (IrisRegion i : r) {
|
|
||||||
for (IrisObjectPlacement j : i.getObjects()) {
|
|
||||||
if (j.getScale().canScaleBeyond()) {
|
|
||||||
scalars.put(j.getScale(), j.getPlace());
|
|
||||||
} else {
|
|
||||||
objects.addAll(j.getPlace());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (IrisJigsawStructurePlacement j : i.getJigsawStructures()) {
|
|
||||||
jig = Math.max(jig, getData().getJigsawStructureLoader().load(j.getStructure()).getMaxDimension());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (IrisJigsawStructurePlacement j : getEngine().getDimension().getJigsawStructures()) {
|
|
||||||
jig = Math.max(jig, getData().getJigsawStructureLoader().load(j.getStructure()).getMaxDimension());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (getEngine().getDimension().getStronghold() != null) {
|
|
||||||
try {
|
|
||||||
jig = Math.max(jig, getData().getJigsawStructureLoader().load(getEngine().getDimension().getStronghold()).getMaxDimension());
|
|
||||||
} catch (Throwable e) {
|
|
||||||
Iris.reportError(e);
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Iris.verbose("Checking sizes for " + Form.f(objects.size()) + " referenced objects.");
|
|
||||||
BurstExecutor e = getEngine().getTarget().getBurster().burst(objects.size());
|
|
||||||
KMap<String, BlockVector> sizeCache = new KMap<>();
|
|
||||||
for (String i : objects) {
|
|
||||||
e.queue(() -> {
|
|
||||||
try {
|
|
||||||
BlockVector bv = sizeCache.computeIfAbsent(i, (k) -> {
|
|
||||||
try {
|
|
||||||
return IrisObject.sampleSize(getData().getObjectLoader().findFile(i));
|
|
||||||
} catch (IOException ex) {
|
|
||||||
Iris.reportError(ex);
|
|
||||||
ex.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (bv == null) {
|
|
||||||
throw new RuntimeException();
|
|
||||||
}
|
|
||||||
|
|
||||||
warn(i, bv);
|
|
||||||
|
|
||||||
synchronized (xg) {
|
|
||||||
xg.getAndSet(Math.max(bv.getBlockX(), xg.get()));
|
|
||||||
}
|
|
||||||
|
|
||||||
synchronized (zg) {
|
|
||||||
zg.getAndSet(Math.max(bv.getBlockZ(), zg.get()));
|
|
||||||
}
|
|
||||||
} catch (Throwable ed) {
|
|
||||||
Iris.reportError(ed);
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Map.Entry<IrisObjectScale, KList<String>> entry : scalars.entrySet()) {
|
|
||||||
double ms = entry.getKey().getMaximumScale();
|
|
||||||
for (String j : entry.getValue()) {
|
|
||||||
e.queue(() -> {
|
|
||||||
try {
|
|
||||||
BlockVector bv = sizeCache.computeIfAbsent(j, (k) -> {
|
|
||||||
try {
|
|
||||||
return IrisObject.sampleSize(getData().getObjectLoader().findFile(j));
|
|
||||||
} catch (IOException ioException) {
|
|
||||||
Iris.reportError(ioException);
|
|
||||||
ioException.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (bv == null) {
|
|
||||||
throw new RuntimeException();
|
|
||||||
}
|
|
||||||
|
|
||||||
warnScaled(j, bv, ms);
|
|
||||||
|
|
||||||
synchronized (xg) {
|
|
||||||
xg.getAndSet((int) Math.max(Math.ceil(bv.getBlockX() * ms), xg.get()));
|
|
||||||
}
|
|
||||||
|
|
||||||
synchronized (zg) {
|
|
||||||
zg.getAndSet((int) Math.max(Math.ceil(bv.getBlockZ() * ms), zg.get()));
|
|
||||||
}
|
|
||||||
} catch (Throwable ee) {
|
|
||||||
Iris.reportError(ee);
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
e.complete();
|
|
||||||
|
|
||||||
x = xg.get();
|
|
||||||
z = zg.get();
|
|
||||||
|
|
||||||
for (IrisDepositGenerator i : getEngine().getDimension().getDeposits()) {
|
|
||||||
int max = i.getMaxDimension();
|
|
||||||
x = Math.max(max, x);
|
|
||||||
z = Math.max(max, z);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (IrisRegion v : r) {
|
|
||||||
for (IrisDepositGenerator i : v.getDeposits()) {
|
|
||||||
int max = i.getMaxDimension();
|
|
||||||
x = Math.max(max, x);
|
|
||||||
z = Math.max(max, z);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (IrisBiome v : b) {
|
|
||||||
for (IrisDepositGenerator i : v.getDeposits()) {
|
|
||||||
int max = i.getMaxDimension();
|
|
||||||
x = Math.max(max, x);
|
|
||||||
z = Math.max(max, z);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
x = Math.max(z, x);
|
|
||||||
int u = x;
|
|
||||||
int c = Math.max(computeCarvingRange(), computeBodyRange());
|
|
||||||
x = Math.max(jig, x);
|
|
||||||
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) + ")");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int computeBodyRange() {
|
|
||||||
int m = 0;
|
|
||||||
|
|
||||||
m = Math.max(m, getDimension().getFluidBodies().getMaxRange(getData()));
|
|
||||||
|
|
||||||
for (IrisRegion i : getDimension().getAllRegions(getEngine())) {
|
|
||||||
m = Math.max(m, i.getFluidBodies().getMaxRange(getData()));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (IrisBiome i : getDimension().getAllBiomes(getEngine())) {
|
|
||||||
m = Math.max(m, i.getFluidBodies().getMaxRange(getData()));
|
|
||||||
}
|
|
||||||
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int computeCarvingRange() {
|
|
||||||
int m = 0;
|
|
||||||
|
|
||||||
m = Math.max(m, getDimension().getCarving().getMaxRange(getData()));
|
|
||||||
|
|
||||||
for (IrisRegion i : getDimension().getAllRegions(getEngine())) {
|
|
||||||
m = Math.max(m, i.getCarving().getMaxRange(getData()));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (IrisBiome i : getDimension().getAllBiomes(getEngine())) {
|
|
||||||
m = Math.max(m, i.getCarving().getMaxRange(getData()));
|
|
||||||
}
|
|
||||||
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,11 +25,15 @@ import com.volmit.iris.engine.scripting.EngineExecutionEnvironment;
|
|||||||
import com.volmit.iris.engine.scripting.IrisScriptingAPI;
|
import com.volmit.iris.engine.scripting.IrisScriptingAPI;
|
||||||
import com.volmit.iris.util.format.C;
|
import com.volmit.iris.util.format.C;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.ToString;
|
||||||
import org.apache.bsf.BSFException;
|
import org.apache.bsf.BSFException;
|
||||||
import org.apache.bsf.BSFManager;
|
import org.apache.bsf.BSFManager;
|
||||||
import org.apache.bsf.engines.javascript.JavaScriptEngine;
|
import org.apache.bsf.engines.javascript.JavaScriptEngine;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
|
@EqualsAndHashCode(exclude = "engine")
|
||||||
|
@ToString(exclude = "engine")
|
||||||
public class IrisExecutionEnvironment implements EngineExecutionEnvironment {
|
public class IrisExecutionEnvironment implements EngineExecutionEnvironment {
|
||||||
private final BSFManager manager;
|
private final BSFManager manager;
|
||||||
private final Engine engine;
|
private final Engine engine;
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
|
|||||||
private final ChronoLatch ecl;
|
private final ChronoLatch ecl;
|
||||||
private final ChronoLatch cln;
|
private final ChronoLatch cln;
|
||||||
private final ChronoLatch chunkUpdater;
|
private final ChronoLatch chunkUpdater;
|
||||||
|
private final ChronoLatch chunkDiscovery;
|
||||||
private double energy = 25;
|
private double energy = 25;
|
||||||
private int entityCount = 0;
|
private int entityCount = 0;
|
||||||
private long charge = 0;
|
private long charge = 0;
|
||||||
@@ -92,12 +93,14 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
|
|||||||
clw = null;
|
clw = null;
|
||||||
looper = null;
|
looper = null;
|
||||||
chunkUpdater = null;
|
chunkUpdater = null;
|
||||||
|
chunkDiscovery = null;
|
||||||
id = -1;
|
id = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IrisWorldManager(Engine engine) {
|
public IrisWorldManager(Engine engine) {
|
||||||
super(engine);
|
super(engine);
|
||||||
chunkUpdater = new ChronoLatch(3000);
|
chunkUpdater = new ChronoLatch(3000);
|
||||||
|
chunkDiscovery = new ChronoLatch(5000);
|
||||||
cln = new ChronoLatch(60000);
|
cln = new ChronoLatch(60000);
|
||||||
cl = new ChronoLatch(3000);
|
cl = new ChronoLatch(3000);
|
||||||
ecl = new ChronoLatch(250);
|
ecl = new ChronoLatch(250);
|
||||||
@@ -128,6 +131,10 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
|
|||||||
updateChunks();
|
updateChunks();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (chunkDiscovery.flip()) {
|
||||||
|
discoverChunks();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (getDimension().isInfiniteEnergy()) {
|
if (getDimension().isInfiniteEnergy()) {
|
||||||
energy += 1000;
|
energy += 1000;
|
||||||
@@ -174,6 +181,19 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
|
|||||||
looper.start();
|
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() {
|
private void updateChunks() {
|
||||||
for (Player i : getEngine().getWorld().realWorld().getPlayers()) {
|
for (Player i : getEngine().getWorld().realWorld().getPlayers()) {
|
||||||
int r = 1;
|
int r = 1;
|
||||||
@@ -439,7 +459,7 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
|
|||||||
IrisEngineData ed = getEngine().getEngineData();
|
IrisEngineData ed = getEngine().getEngineData();
|
||||||
IrisEngineSpawnerCooldown cd = null;
|
IrisEngineSpawnerCooldown cd = null;
|
||||||
|
|
||||||
for (IrisEngineSpawnerCooldown j : ed.getSpawnerCooldowns()) {
|
for (IrisEngineSpawnerCooldown j : ed.getSpawnerCooldowns().copy()) {
|
||||||
if (j.getSpawner().equals(i.getLoadKey())) {
|
if (j.getSpawner().equals(i.getLoadKey())) {
|
||||||
cd = j;
|
cd = j;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ package com.volmit.iris.engine.data.chunk;
|
|||||||
import com.volmit.iris.core.nms.BiomeBaseInjector;
|
import com.volmit.iris.core.nms.BiomeBaseInjector;
|
||||||
import com.volmit.iris.core.nms.INMS;
|
import com.volmit.iris.core.nms.INMS;
|
||||||
import com.volmit.iris.util.data.IrisBiomeStorage;
|
import com.volmit.iris.util.data.IrisBiomeStorage;
|
||||||
|
import com.volmit.iris.util.data.IrisBlockData;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
@@ -120,6 +121,8 @@ public class LinkedTerrainChunk implements TerrainChunk {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void setBlock(int x, int y, int z, BlockData blockData) {
|
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);
|
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.Iris;
|
||||||
import com.volmit.iris.core.nms.BiomeBaseInjector;
|
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.Chunk;
|
||||||
import com.volmit.iris.util.nbt.mca.NBTWorld;
|
import com.volmit.iris.util.nbt.mca.NBTWorld;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
@@ -88,6 +89,8 @@ public class MCATerrainChunk implements TerrainChunk {
|
|||||||
if (blockData == null) {
|
if (blockData == null) {
|
||||||
Iris.error("NULL BD");
|
Iris.error("NULL BD");
|
||||||
}
|
}
|
||||||
|
if (blockData instanceof IrisBlockData data)
|
||||||
|
blockData = data.getBase();
|
||||||
|
|
||||||
mcaChunk.setBlockStateAt(xx, y, zz, NBTWorld.getCompound(blockData), false);
|
mcaChunk.setBlockStateAt(xx, y, zz, NBTWorld.getCompound(blockData), false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,9 +43,7 @@ public class IrisCeilingDecorator extends IrisEngineDecorator {
|
|||||||
IrisDecorator decorator = getDecorator(biome, realX, realZ);
|
IrisDecorator decorator = getDecorator(biome, realX, realZ);
|
||||||
if (decorator != null) {
|
if (decorator != null) {
|
||||||
if (!decorator.isStacking()) {
|
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));
|
||||||
data.set(x, height, z, fixFaces(decorator.getBlockData100(biome, getRng(), realX, height, realZ, getData()), realX, height, realZ));
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
int stack = decorator.getHeight(getRng().nextParallelRNG(Cache.key(realX, realZ)), realX, realZ, getData());
|
int stack = decorator.getHeight(getRng().nextParallelRNG(Cache.key(realX, realZ)), realX, realZ, getData());
|
||||||
if (decorator.isScaleStack()) {
|
if (decorator.isScaleStack()) {
|
||||||
|
|||||||
@@ -18,14 +18,21 @@
|
|||||||
|
|
||||||
package com.volmit.iris.engine.decorator;
|
package com.volmit.iris.engine.decorator;
|
||||||
|
|
||||||
|
import com.volmit.iris.Iris;
|
||||||
import com.volmit.iris.engine.data.cache.Cache;
|
import com.volmit.iris.engine.data.cache.Cache;
|
||||||
import com.volmit.iris.engine.framework.Engine;
|
import com.volmit.iris.engine.framework.Engine;
|
||||||
import com.volmit.iris.engine.object.IrisBiome;
|
import com.volmit.iris.engine.object.IrisBiome;
|
||||||
import com.volmit.iris.engine.object.IrisDecorationPart;
|
import com.volmit.iris.engine.object.IrisDecorationPart;
|
||||||
import com.volmit.iris.engine.object.IrisDecorator;
|
import com.volmit.iris.engine.object.IrisDecorator;
|
||||||
|
import com.volmit.iris.util.data.B;
|
||||||
import com.volmit.iris.util.documentation.BlockCoordinates;
|
import com.volmit.iris.util.documentation.BlockCoordinates;
|
||||||
import com.volmit.iris.util.hunk.Hunk;
|
import com.volmit.iris.util.hunk.Hunk;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.block.BlockFace;
|
||||||
|
import org.bukkit.block.data.Bisected;
|
||||||
import org.bukkit.block.data.BlockData;
|
import org.bukkit.block.data.BlockData;
|
||||||
|
import org.bukkit.block.data.MultipleFacing;
|
||||||
|
import org.bukkit.block.data.Waterlogged;
|
||||||
|
|
||||||
public class IrisSeaFloorDecorator extends IrisEngineDecorator {
|
public class IrisSeaFloorDecorator extends IrisEngineDecorator {
|
||||||
public IrisSeaFloorDecorator(Engine engine) {
|
public IrisSeaFloorDecorator(Engine engine) {
|
||||||
@@ -38,17 +45,53 @@ public class IrisSeaFloorDecorator extends IrisEngineDecorator {
|
|||||||
IrisDecorator decorator = getDecorator(biome, realX, realZ);
|
IrisDecorator decorator = getDecorator(biome, realX, realZ);
|
||||||
|
|
||||||
if (decorator != null) {
|
if (decorator != null) {
|
||||||
|
var bdx = data.get(x, height - 1, z);
|
||||||
if (!decorator.isStacking()) {
|
if (!decorator.isStacking()) {
|
||||||
|
var bd = decorator.getBlockData100(biome, getRng(), realX, height, realZ, getData());
|
||||||
|
if ((!canGoOn(bd, bdx)
|
||||||
|
|| (bd instanceof Bisected
|
||||||
|
? (data.get(x, height, z).isOccluding() || data.get(x, height + 1, z).isOccluding())
|
||||||
|
: data.get(x, height, z).isOccluding()))
|
||||||
|
&& !decorator.isForcePlace() && decorator.getForceBlock() == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!decorator.isForcePlace() && !decorator.getSlopeCondition().isDefault()
|
||||||
|
&& !decorator.getSlopeCondition().isValid(getComplex().getSlopeStream().get(realX, realZ))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bd instanceof Bisected) {
|
||||||
|
bd = bd.clone();
|
||||||
|
((Bisected) bd).setHalf(Bisected.Half.TOP);
|
||||||
|
try {
|
||||||
|
data.set(x, height + 1, z, bd);
|
||||||
|
} catch (Throwable e) {
|
||||||
|
Iris.reportError(e);
|
||||||
|
}
|
||||||
|
bd = bd.clone();
|
||||||
|
((Bisected) bd).setHalf(Bisected.Half.BOTTOM);
|
||||||
|
}
|
||||||
|
|
||||||
if (height >= 0 || height < getEngine().getHeight()) {
|
if (height >= 0 || height < getEngine().getHeight()) {
|
||||||
data.set(x, height, z, decorator.getBlockData100(biome, getRng(), realX, height, realZ, getData()));
|
data.set(x, height, z, bd);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
var bd = decorator.getBlockData100(biome, getRng(), realX, height, realZ, getData());
|
||||||
|
if (((!canGoOn(bd, bdx) || data.get(x, height, z).isOccluding()) && (!decorator.isForcePlace() && decorator.getForceBlock() == null)))
|
||||||
|
return;
|
||||||
|
|
||||||
int stack = decorator.getHeight(getRng().nextParallelRNG(Cache.key(realX, realZ)), realX, realZ, getData());
|
int stack = decorator.getHeight(getRng().nextParallelRNG(Cache.key(realX, realZ)), realX, realZ, getData());
|
||||||
if (decorator.isScaleStack()) {
|
if (decorator.isScaleStack()) {
|
||||||
int maxStack = max - height;
|
int maxStack = max - height;
|
||||||
stack = (int) Math.ceil((double) maxStack * ((double) stack / 100));
|
stack = (int) Math.ceil((double) maxStack * ((double) stack / 100));
|
||||||
} else stack = Math.min(stack, max - height);
|
} else stack = Math.min(stack, max - height);
|
||||||
|
|
||||||
|
for (int i = 1; i < stack; i++) {
|
||||||
|
var block = data.get(x, height + i + 1, z);
|
||||||
|
if ((block.isOccluding()) && (!decorator.isForcePlace() && decorator.getForceBlock() == null))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (stack == 1) {
|
if (stack == 1) {
|
||||||
data.set(x, height, z, decorator.getBlockDataForTop(biome, getRng(), realX, height, realZ, getData()));
|
data.set(x, height, z, decorator.getBlockDataForTop(biome, getRng(), realX, height, realZ, getData()));
|
||||||
return;
|
return;
|
||||||
@@ -61,12 +104,15 @@ public class IrisSeaFloorDecorator extends IrisEngineDecorator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
double threshold = ((double) i) / (stack - 1);
|
double threshold = ((double) i) / (stack - 1);
|
||||||
data.set(x, h, z, threshold >= decorator.getTopThreshold() ?
|
BlockData block = threshold >= decorator.getTopThreshold() ?
|
||||||
decorator.getBlockDataForTop(biome, getRng(), realX, h, realZ, getData()) :
|
decorator.getBlockDataForTop(biome, getRng(), realX, h, realZ, getData()) :
|
||||||
decorator.getBlockData100(biome, getRng(), realX, h, realZ, getData()));
|
decorator.getBlockData100(biome, getRng(), realX, h, realZ, getData());
|
||||||
|
if (block instanceof Waterlogged wblock)
|
||||||
|
wblock.setWaterlogged(true);
|
||||||
|
|
||||||
|
data.set(x, h, z, block);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,6 +45,11 @@ public class IrisShoreLineDecorator extends IrisEngineDecorator {
|
|||||||
IrisDecorator decorator = getDecorator(biome, realX, realZ);
|
IrisDecorator decorator = getDecorator(biome, realX, realZ);
|
||||||
|
|
||||||
if (decorator != null) {
|
if (decorator != null) {
|
||||||
|
if (!decorator.isForcePlace() && !decorator.getSlopeCondition().isDefault()
|
||||||
|
&& !decorator.getSlopeCondition().isValid(getComplex().getSlopeStream().get(realX, realZ))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!decorator.isStacking()) {
|
if (!decorator.isStacking()) {
|
||||||
data.set(x, height + 1, z, decorator.getBlockData100(biome, getRng(), realX, height, realZ, getData()));
|
data.set(x, height + 1, z, decorator.getBlockData100(biome, getRng(), realX, height, realZ, getData()));
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -53,9 +53,20 @@ public class IrisSurfaceDecorator extends IrisEngineDecorator {
|
|||||||
boolean underwater = height < getDimension().getFluidHeight();
|
boolean underwater = height < getDimension().getFluidHeight();
|
||||||
|
|
||||||
if (decorator != null) {
|
if (decorator != null) {
|
||||||
|
if (!decorator.isForcePlace() && !decorator.getSlopeCondition().isDefault()
|
||||||
|
&& !decorator.getSlopeCondition().isValid(getComplex().getSlopeStream().get(realX, realZ))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!decorator.isStacking()) {
|
if (!decorator.isStacking()) {
|
||||||
bd = decorator.getBlockData100(biome, getRng(), realX, height, realZ, getData());
|
bd = decorator.getBlockData100(biome, getRng(), realX, height, realZ, getData());
|
||||||
|
|
||||||
|
if (((bd instanceof Bisected
|
||||||
|
? (data.get(x, height + 1, z).isOccluding() || data.get(x, height + 2, z).isOccluding())
|
||||||
|
: data.get(x, height + 1, z).isOccluding()))
|
||||||
|
&& !decorator.isForcePlace() && decorator.getForceBlock() == null)
|
||||||
|
return;
|
||||||
|
|
||||||
if (!underwater) {
|
if (!underwater) {
|
||||||
if (!canGoOn(bd, bdx) && (!decorator.isForcePlace() && decorator.getForceBlock() == null)) {
|
if (!canGoOn(bd, bdx) && (!decorator.isForcePlace() && decorator.getForceBlock() == null)) {
|
||||||
return;
|
return;
|
||||||
@@ -106,6 +117,12 @@ public class IrisSurfaceDecorator extends IrisEngineDecorator {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i = 1; i < stack; i++) {
|
||||||
|
var block = data.get(x, height + i + 1, z);
|
||||||
|
if ((block.isOccluding()) && (!decorator.isForcePlace() && decorator.getForceBlock() == null))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < stack; i++) {
|
for (int i = 0; i < stack; i++) {
|
||||||
int h = height + i;
|
int h = height + i;
|
||||||
double threshold = ((double) i) / (stack - 1);
|
double threshold = ((double) i) / (stack - 1);
|
||||||
|
|||||||
@@ -20,12 +20,16 @@ package com.volmit.iris.engine.framework;
|
|||||||
|
|
||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.Iris;
|
||||||
import com.volmit.iris.core.IrisSettings;
|
import com.volmit.iris.core.IrisSettings;
|
||||||
|
import com.volmit.iris.core.events.IrisLootEvent;
|
||||||
import com.volmit.iris.core.gui.components.RenderType;
|
import com.volmit.iris.core.gui.components.RenderType;
|
||||||
import com.volmit.iris.core.gui.components.Renderer;
|
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.IrisData;
|
||||||
import com.volmit.iris.core.loader.IrisRegistrant;
|
import com.volmit.iris.core.loader.IrisRegistrant;
|
||||||
import com.volmit.iris.core.nms.container.BlockPos;
|
import com.volmit.iris.core.nms.container.BlockPos;
|
||||||
import com.volmit.iris.core.nms.container.Pair;
|
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.IrisComplex;
|
||||||
import com.volmit.iris.engine.data.cache.Cache;
|
import com.volmit.iris.engine.data.cache.Cache;
|
||||||
import com.volmit.iris.engine.data.chunk.TerrainChunk;
|
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.context.IrisContext;
|
||||||
import com.volmit.iris.util.data.B;
|
import com.volmit.iris.util.data.B;
|
||||||
import com.volmit.iris.util.data.DataProvider;
|
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.BlockCoordinates;
|
||||||
import com.volmit.iris.util.documentation.ChunkCoordinates;
|
import com.volmit.iris.util.documentation.ChunkCoordinates;
|
||||||
import com.volmit.iris.util.format.C;
|
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.matter.slices.container.JigsawPieceContainer;
|
||||||
import com.volmit.iris.util.parallel.BurstExecutor;
|
import com.volmit.iris.util.parallel.BurstExecutor;
|
||||||
import com.volmit.iris.util.parallel.MultiBurst;
|
import com.volmit.iris.util.parallel.MultiBurst;
|
||||||
|
import com.volmit.iris.util.reflect.W;
|
||||||
import com.volmit.iris.util.scheduling.ChronoLatch;
|
import com.volmit.iris.util.scheduling.ChronoLatch;
|
||||||
import com.volmit.iris.util.scheduling.J;
|
import com.volmit.iris.util.scheduling.J;
|
||||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||||
import com.volmit.iris.util.stream.ProceduralStream;
|
import com.volmit.iris.util.stream.ProceduralStream;
|
||||||
import io.papermc.lib.PaperLib;
|
import io.papermc.lib.PaperLib;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.*;
|
||||||
import org.bukkit.Chunk;
|
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.Material;
|
|
||||||
import org.bukkit.block.Biome;
|
import org.bukkit.block.Biome;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.block.BlockFace;
|
import org.bukkit.block.BlockFace;
|
||||||
@@ -73,10 +76,11 @@ import org.bukkit.inventory.Inventory;
|
|||||||
import org.bukkit.inventory.InventoryHolder;
|
import org.bukkit.inventory.InventoryHolder;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.Color;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.Semaphore;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
@@ -254,6 +258,11 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
|
|||||||
if (B.isUpdatable(data)) {
|
if (B.isUpdatable(data)) {
|
||||||
getMantle().updateBlock(x, y, z);
|
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();
|
void blockUpdatedMetric();
|
||||||
@@ -261,72 +270,106 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
|
|||||||
@ChunkCoordinates
|
@ChunkCoordinates
|
||||||
@Override
|
@Override
|
||||||
default void updateChunk(Chunk c) {
|
default void updateChunk(Chunk c) {
|
||||||
if (c.getWorld().isChunkLoaded(c.getX() + 1, c.getZ() + 1)
|
for (int x = -1; x <= 1; x++) {
|
||||||
&& c.getWorld().isChunkLoaded(c.getX(), c.getZ() + 1)
|
for (int z = -1; z <= 1; z++) {
|
||||||
&& c.getWorld().isChunkLoaded(c.getX() + 1, c.getZ())
|
if (c.getWorld().isChunkLoaded(c.getX() + x, c.getZ() + z))
|
||||||
&& c.getWorld().isChunkLoaded(c.getX() - 1, c.getZ() - 1)
|
continue;
|
||||||
&& c.getWorld().isChunkLoaded(c.getX(), c.getZ() - 1)
|
var msg = "Chunk %s, %s [%s, %s] is not loaded".formatted(c.getX() + x, c.getZ() + z, x, z);
|
||||||
&& c.getWorld().isChunkLoaded(c.getX() - 1, c.getZ())
|
if (W.getStack().getCallerClass().equals(ChunkUpdater.class)) Iris.warn(msg);
|
||||||
&& c.getWorld().isChunkLoaded(c.getX() + 1, c.getZ() - 1)
|
else Iris.debug(msg);
|
||||||
&& c.getWorld().isChunkLoaded(c.getX() - 1, c.getZ() + 1) && getMantle().getMantle().isLoaded(c)) {
|
return;
|
||||||
|
}
|
||||||
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)));
|
|
||||||
}
|
}
|
||||||
|
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
|
@BlockCoordinates
|
||||||
@@ -372,7 +415,7 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
|
|||||||
if (tables.isEmpty())
|
if (tables.isEmpty())
|
||||||
return;
|
return;
|
||||||
InventoryHolder m = (InventoryHolder) block.getState();
|
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) {
|
} catch (Throwable e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
@@ -425,7 +468,10 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
default void injectTables(KList<IrisLootTable> list, IrisLootReference r) {
|
default void injectTables(KList<IrisLootTable> list, IrisLootReference r, boolean fallback) {
|
||||||
|
if (r.getMode().equals(IrisLootMode.FALLBACK) && !fallback)
|
||||||
|
return;
|
||||||
|
|
||||||
if (r.getMode().equals(IrisLootMode.CLEAR) || r.getMode().equals(IrisLootMode.REPLACE)) {
|
if (r.getMode().equals(IrisLootMode.CLEAR) || r.getMode().equals(IrisLootMode.REPLACE)) {
|
||||||
list.clear();
|
list.clear();
|
||||||
}
|
}
|
||||||
@@ -460,10 +506,11 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
|
|||||||
IrisBiome biomeUnder = ry < he ? getComplex().getCaveBiomeStream().get(rx, rz) : biomeSurface;
|
IrisBiome biomeUnder = ry < he ? getComplex().getCaveBiomeStream().get(rx, rz) : biomeSurface;
|
||||||
|
|
||||||
double multiplier = 1D * getDimension().getLoot().getMultiplier() * region.getLoot().getMultiplier() * biomeSurface.getLoot().getMultiplier() * biomeUnder.getLoot().getMultiplier();
|
double multiplier = 1D * getDimension().getLoot().getMultiplier() * region.getLoot().getMultiplier() * biomeSurface.getLoot().getMultiplier() * biomeUnder.getLoot().getMultiplier();
|
||||||
injectTables(tables, getDimension().getLoot());
|
boolean fallback = tables.isEmpty();
|
||||||
injectTables(tables, region.getLoot());
|
injectTables(tables, getDimension().getLoot(), fallback);
|
||||||
injectTables(tables, biomeSurface.getLoot());
|
injectTables(tables, region.getLoot(), fallback);
|
||||||
injectTables(tables, biomeUnder.getLoot());
|
injectTables(tables, biomeSurface.getLoot(), fallback);
|
||||||
|
injectTables(tables, biomeUnder.getLoot(), fallback);
|
||||||
|
|
||||||
if (tables.isNotEmpty()) {
|
if (tables.isNotEmpty()) {
|
||||||
int target = (int) Math.round(tables.size() * multiplier);
|
int target = (int) Math.round(tables.size() * multiplier);
|
||||||
@@ -481,16 +528,16 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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<>();
|
KList<ItemStack> items = new KList<>();
|
||||||
|
|
||||||
int b = 4;
|
|
||||||
for (IrisLootTable i : tables) {
|
for (IrisLootTable i : tables) {
|
||||||
if (i == null)
|
if (i == null)
|
||||||
continue;
|
continue;
|
||||||
b++;
|
items.addAll(i.getLoot(debug, rng, slot, world, x, y, z));
|
||||||
items.addAll(i.getLoot(debug, rng, slot, x, y, z));
|
|
||||||
}
|
}
|
||||||
|
if (IrisLootEvent.callLootEvent(items, inv, world, x, y, z))
|
||||||
|
return;
|
||||||
|
|
||||||
if (PaperLib.isPaper() && getWorld().hasRealWorld()) {
|
if (PaperLib.isPaper() && getWorld().hasRealWorld()) {
|
||||||
PaperLib.getChunkAtAsync(getWorld().realWorld(), x >> 4, z >> 4).thenAccept((c) -> {
|
PaperLib.getChunkAtAsync(getWorld().realWorld(), x >> 4, z >> 4).thenAccept((c) -> {
|
||||||
@@ -523,8 +570,9 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
|
|||||||
return getTarget().getBurster();
|
return getTarget().getBurster();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
default void clean() {
|
default void clean() {
|
||||||
burst().lazy(() -> getMantle().trim());
|
burst().lazy(() -> getMantle().trim(10));
|
||||||
}
|
}
|
||||||
|
|
||||||
@BlockCoordinates
|
@BlockCoordinates
|
||||||
@@ -803,7 +851,7 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
|
|||||||
return getBiomeOrMantle(l.getBlockX(), l.getBlockY(), l.getBlockZ());
|
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()
|
Set<String> regionKeys = getDimension()
|
||||||
.getAllRegions(this).stream()
|
.getAllRegions(this).stream()
|
||||||
.filter((i) -> i.getAllBiomes(this).contains(biome))
|
.filter((i) -> i.getAllBiomes(this).contains(biome))
|
||||||
@@ -815,15 +863,15 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
|
|||||||
&& lb.matches(engine, chunk);
|
&& lb.matches(engine, chunk);
|
||||||
|
|
||||||
if (!regionKeys.isEmpty()) {
|
if (!regionKeys.isEmpty()) {
|
||||||
locator.find(player);
|
locator.find(player, teleport, "Biome " + biome.getName());
|
||||||
} else {
|
} else {
|
||||||
player.sendMessage(C.RED + biome.getName() + " is not in any defined regions!");
|
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())) {
|
if (s.getLoadKey().equals(getDimension().getStronghold())) {
|
||||||
KList<Position2> p = getDimension().getStrongholds(getSeedManager().getSpawn());
|
KList<Position2> p = getDimension().getStrongholds(getSeedManager().getMantle());
|
||||||
|
|
||||||
if (p.isEmpty()) {
|
if (p.isEmpty()) {
|
||||||
player.sendMessage(C.GOLD + "No strongholds in world.");
|
player.sendMessage(C.GOLD + "No strongholds in world.");
|
||||||
@@ -858,7 +906,7 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
|
|||||||
if (getDimension().getJigsawStructures().stream()
|
if (getDimension().getJigsawStructures().stream()
|
||||||
.map(IrisJigsawStructurePlacement::getStructure)
|
.map(IrisJigsawStructurePlacement::getStructure)
|
||||||
.collect(Collectors.toSet()).contains(s.getLoadKey())) {
|
.collect(Collectors.toSet()).contains(s.getLoadKey())) {
|
||||||
Locator.jigsawStructure(s.getLoadKey()).find(player);
|
Locator.jigsawStructure(s.getLoadKey()).find(player, teleport, "Structure " + s.getLoadKey());
|
||||||
} else {
|
} else {
|
||||||
Set<String> biomeKeys = getDimension().getAllBiomes(this).stream()
|
Set<String> biomeKeys = getDimension().getAllBiomes(this).stream()
|
||||||
.filter((i) -> i.getJigsawStructures()
|
.filter((i) -> i.getJigsawStructures()
|
||||||
@@ -885,7 +933,7 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (!regionKeys.isEmpty()) {
|
if (!regionKeys.isEmpty()) {
|
||||||
locator.find(player);
|
locator.find(player, teleport, "Structure " + s.getLoadKey());
|
||||||
} else {
|
} else {
|
||||||
player.sendMessage(C.RED + s.getLoadKey() + " is not in any defined regions, biomes or dimensions!");
|
player.sendMessage(C.RED + s.getLoadKey() + " is not in any defined regions, biomes or dimensions!");
|
||||||
}
|
}
|
||||||
@@ -893,7 +941,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()
|
Set<String> biomeKeys = getDimension().getAllBiomes(this).stream()
|
||||||
.filter((i) -> i.getObjects().stream().anyMatch((f) -> f.getPlace().contains(s)))
|
.filter((i) -> i.getObjects().stream().anyMatch((f) -> f.getPlace().contains(s)))
|
||||||
.map(IrisRegistrant::getLoadKey)
|
.map(IrisRegistrant::getLoadKey)
|
||||||
@@ -916,23 +964,23 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (!regionKeys.isEmpty()) {
|
if (!regionKeys.isEmpty()) {
|
||||||
locator.find(player);
|
locator.find(player, teleport, "Object " + s);
|
||||||
} else {
|
} else {
|
||||||
player.sendMessage(C.RED + s + " is not in any defined regions or biomes!");
|
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)) {
|
if (!getDimension().getAllRegions(this).contains(r)) {
|
||||||
player.sendMessage(C.RED + r.getName() + " is not defined in the dimension!");
|
player.sendMessage(C.RED + r.getName() + " is not defined in the dimension!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Locator.region(r.getLoadKey()).find(player);
|
Locator.region(r.getLoadKey()).find(player, teleport, "Region " + r.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
default void gotoPOI(String type, Player p) {
|
default void gotoPOI(String type, Player p, boolean teleport) {
|
||||||
Locator.poi(type).find(p);
|
Locator.poi(type).find(p, teleport, "POI " + type);
|
||||||
}
|
}
|
||||||
|
|
||||||
default void cleanupMantleChunk(int x, int z) {
|
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.Iris;
|
||||||
import com.volmit.iris.util.math.RollingSequence;
|
import com.volmit.iris.util.math.RollingSequence;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
|
@EqualsAndHashCode(exclude = "engine")
|
||||||
|
@ToString(exclude = "engine")
|
||||||
public class EngineAssignedComponent implements EngineComponent {
|
public class EngineAssignedComponent implements EngineComponent {
|
||||||
private final Engine engine;
|
private final Engine engine;
|
||||||
private final RollingSequence metrics;
|
private final RollingSequence metrics;
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ public abstract class EngineAssignedWorldManager extends EngineAssignedComponent
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
KList<Position2> positions = getEngine().getDimension().getStrongholds(getEngine().getSeedManager().getSpawn());
|
KList<Position2> positions = getEngine().getDimension().getStrongholds(getEngine().getSeedManager().getMantle());
|
||||||
if (positions.isEmpty()) {
|
if (positions.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,8 +23,12 @@ import com.volmit.iris.engine.object.IrisDimension;
|
|||||||
import com.volmit.iris.engine.object.IrisWorld;
|
import com.volmit.iris.engine.object.IrisWorld;
|
||||||
import com.volmit.iris.util.parallel.MultiBurst;
|
import com.volmit.iris.util.parallel.MultiBurst;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
|
@EqualsAndHashCode(exclude = "data")
|
||||||
|
@ToString(exclude = "data")
|
||||||
public class EngineTarget {
|
public class EngineTarget {
|
||||||
private final MultiBurst burster;
|
private final MultiBurst burster;
|
||||||
private final IrisData data;
|
private final IrisData data;
|
||||||
|
|||||||
@@ -1,32 +0,0 @@
|
|||||||
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 lombok.Getter;
|
|
||||||
import org.bukkit.block.Block;
|
|
||||||
import org.bukkit.event.Event;
|
|
||||||
import org.bukkit.event.HandlerList;
|
|
||||||
|
|
||||||
@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;
|
|
||||||
|
|
||||||
public IrisLootEvent(Engine engine, Block block, InventorySlotType slot, KList<IrisLootTable> tables) {
|
|
||||||
this.engine = engine;
|
|
||||||
this.block = block;
|
|
||||||
this.slot = slot;
|
|
||||||
this.tables = tables;
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public HandlerList getHandlers() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
public static HandlerList getHandlerList() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package com.volmit.iris.engine.framework;
|
||||||
|
|
||||||
|
import com.volmit.iris.core.loader.IrisData;
|
||||||
|
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
public interface ListFunction<R> extends Function<IrisData, 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.IrisObject;
|
||||||
import com.volmit.iris.engine.object.IrisRegion;
|
import com.volmit.iris.engine.object.IrisRegion;
|
||||||
import com.volmit.iris.util.context.ChunkContext;
|
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.format.Form;
|
||||||
import com.volmit.iris.util.math.M;
|
import com.volmit.iris.util.math.M;
|
||||||
import com.volmit.iris.util.math.Position2;
|
import com.volmit.iris.util.math.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.PrecisionStopwatch;
|
||||||
import com.volmit.iris.util.scheduling.jobs.SingleJob;
|
import com.volmit.iris.util.scheduling.jobs.SingleJob;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.World;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@@ -109,23 +111,35 @@ public interface Locator<T> {
|
|||||||
|
|
||||||
boolean matches(Engine engine, Position2 chunk);
|
boolean matches(Engine engine, Position2 chunk);
|
||||||
|
|
||||||
default void find(Player player) {
|
default void find(Player player, boolean teleport, String message) {
|
||||||
find(player, 30_000);
|
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();
|
AtomicLong checks = new AtomicLong();
|
||||||
long ms = M.ms();
|
long ms = M.ms();
|
||||||
new SingleJob("Searching", () -> {
|
new SingleJob("Searching", () -> {
|
||||||
try {
|
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) {
|
if (at != null) {
|
||||||
J.s(() -> player.teleport(new Location(player.getWorld(), (at.getX() << 4) + 8,
|
consumer.accept(new Location(world, (at.getX() << 4) + 8,
|
||||||
IrisToolbelt.access(player.getWorld()).getEngine().getHeight(
|
engine.getHeight(
|
||||||
(at.getX() << 4) + 8,
|
(at.getX() << 4) + 8,
|
||||||
(at.getZ() << 4) + 8, false),
|
(at.getZ() << 4) + 8, false),
|
||||||
(at.getZ() << 4) + 8)));
|
(at.getZ() << 4) + 8));
|
||||||
}
|
}
|
||||||
} catch (WrongEngineBroException | InterruptedException | ExecutionException e) {
|
} catch (WrongEngineBroException | InterruptedException | ExecutionException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
|||||||
@@ -23,15 +23,16 @@ import com.volmit.iris.engine.object.IrisLootReference;
|
|||||||
import com.volmit.iris.engine.object.IrisLootTable;
|
import com.volmit.iris.engine.object.IrisLootTable;
|
||||||
import com.volmit.iris.util.collection.KList;
|
import com.volmit.iris.util.collection.KList;
|
||||||
import com.volmit.iris.util.math.RNG;
|
import com.volmit.iris.util.math.RNG;
|
||||||
|
import org.bukkit.World;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.inventory.Inventory;
|
import org.bukkit.inventory.Inventory;
|
||||||
|
|
||||||
public interface LootProvider {
|
public interface LootProvider {
|
||||||
void scramble(Inventory inventory, RNG rng);
|
void scramble(Inventory inventory, RNG rng);
|
||||||
|
|
||||||
void injectTables(KList<IrisLootTable> list, IrisLootReference r);
|
void injectTables(KList<IrisLootTable> list, IrisLootReference r, boolean fallback);
|
||||||
|
|
||||||
KList<IrisLootTable> getLootTables(RNG rng, Block b);
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
-2
@@ -60,7 +60,7 @@ public class HeightmapObjectPlacer implements IObjectPlacer {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isCarved(int x, int y, int z) {
|
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) {
|
public boolean isSolid(int param1Int1, int param1Int2, int param1Int3) {
|
||||||
@@ -79,7 +79,7 @@ public class HeightmapObjectPlacer implements IObjectPlacer {
|
|||||||
return oplacer.isDebugSmartBore();
|
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);
|
oplacer.setTile(param1Int1, param1Int2, param1Int3, param1TileData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,123 @@
|
|||||||
|
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.core.events.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.data.BlockData;
|
||||||
|
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);
|
||||||
|
|
||||||
|
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;
|
package com.volmit.iris.engine.jigsaw;
|
||||||
|
|
||||||
|
import com.volmit.iris.Iris;
|
||||||
import com.volmit.iris.core.loader.IrisData;
|
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.object.*;
|
||||||
import com.volmit.iris.engine.platform.PlatformChunkGenerator;
|
|
||||||
import com.volmit.iris.util.collection.KList;
|
import com.volmit.iris.util.collection.KList;
|
||||||
import com.volmit.iris.util.context.IrisContext;
|
import com.volmit.iris.util.collection.KMap;
|
||||||
import com.volmit.iris.util.math.AxisAlignedBB;
|
import com.volmit.iris.util.math.AxisAlignedBB;
|
||||||
import com.volmit.iris.util.math.BlockPosition;
|
import lombok.AccessLevel;
|
||||||
import com.volmit.iris.util.math.RNG;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.bukkit.Material;
|
import lombok.EqualsAndHashCode;
|
||||||
import org.bukkit.World;
|
import lombok.Setter;
|
||||||
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 org.bukkit.util.BlockVector;
|
import org.bukkit.util.BlockVector;
|
||||||
|
|
||||||
@SuppressWarnings("ALL")
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class PlannedPiece {
|
public class PlannedPiece {
|
||||||
private IrisPosition position;
|
private IrisPosition position;
|
||||||
@@ -46,11 +40,19 @@ public class PlannedPiece {
|
|||||||
private IrisObject ogObject;
|
private IrisObject ogObject;
|
||||||
private IrisJigsawPiece piece;
|
private IrisJigsawPiece piece;
|
||||||
private IrisObjectRotation rotation;
|
private IrisObjectRotation rotation;
|
||||||
|
@EqualsAndHashCode.Exclude
|
||||||
private IrisData data;
|
private IrisData data;
|
||||||
private KList<IrisJigsawPieceConnector> connected;
|
private KList<IrisJigsawPieceConnector> connected;
|
||||||
private boolean dead = false;
|
private boolean dead = false;
|
||||||
private AxisAlignedBB box;
|
private AxisAlignedBB box;
|
||||||
|
@EqualsAndHashCode.Exclude
|
||||||
private PlannedStructure structure;
|
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) {
|
public PlannedPiece(PlannedStructure structure, IrisPosition position, IrisJigsawPiece piece) {
|
||||||
this(structure, position, piece, 0, 0, 0);
|
this(structure, position, piece, 0, 0, 0);
|
||||||
@@ -72,6 +74,8 @@ public class PlannedPiece {
|
|||||||
this.object.setLoadKey(piece.getObject());
|
this.object.setLoadKey(piece.getObject());
|
||||||
this.ogObject.setLoadKey(piece.getObject());
|
this.ogObject.setLoadKey(piece.getObject());
|
||||||
this.connected = new KList<>();
|
this.connected = new KList<>();
|
||||||
|
this.realPositions = new KMap<>();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPosition(IrisPosition p) {
|
public void setPosition(IrisPosition p) {
|
||||||
@@ -89,7 +93,15 @@ public class PlannedPiece {
|
|||||||
}
|
}
|
||||||
|
|
||||||
BlockVector v = getObject().getCenter();
|
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;
|
return box;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,11 +133,21 @@ public class PlannedPiece {
|
|||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean connect(IrisJigsawPieceConnector c) {
|
public KList<IrisJigsawPieceConnector> getChildConnectors() {
|
||||||
if (piece.getConnectors().contains(c)) {
|
ParentConnection pc = getParent();
|
||||||
return connected.addIfMissing(c);
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,113 +155,53 @@ public class PlannedPiece {
|
|||||||
return getWorldPosition(c.getPosition());
|
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) {
|
public IrisPosition getWorldPosition(IrisPosition position) {
|
||||||
return this.position.add(position).add(new IrisPosition(object.getCenter()));
|
return this.position.add(position).add(new IrisPosition(object.getCenter()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isFull() {
|
public void debugPrintConnectorPositions() {
|
||||||
return connected.size() >= piece.getConnectors().size() || isDead();
|
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) {
|
public boolean isFull() {
|
||||||
PlatformChunkGenerator a = IrisToolbelt.access(world);
|
return connected.size() >= piece.getConnectors().size();
|
||||||
|
}
|
||||||
|
|
||||||
int minY = 0;
|
public void setRealPositions(int x, int y, int z, IObjectPlacer placer) {
|
||||||
if (a != null) {
|
boolean isUnderwater = piece.getPlacementOptions().isUnderwater();
|
||||||
minY = a.getEngine().getMinHeight();
|
for (IrisJigsawPieceConnector c : piece.getConnectors()) {
|
||||||
|
var pos = c.getPosition().add(new IrisPosition(x, 0, z));
|
||||||
if (!a.getEngine().getDimension().isBedrock())
|
if (y < 0) {
|
||||||
minY--; //If the dimension has no bedrock, allow it to go a block lower
|
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());
|
public record ParentConnection(PlannedPiece parent, IrisJigsawPieceConnector parentConnector, PlannedPiece self, IrisJigsawPieceConnector connector) {
|
||||||
getPiece().getPlacementOptions().setRotation(rotation);
|
public IrisPosition getTargetPosition() {
|
||||||
int finalMinY = minY;
|
var pos = parent.realPositions.get(parentConnector);
|
||||||
RNG rng = getStructure().getRng().nextParallelRNG(37555);
|
if (pos == null) return null;
|
||||||
|
return pos.add(new IrisPosition(parentConnector.getDirection().toVector()))
|
||||||
// TODO: REAL CLASSES!!!!!!!
|
.sub(connector.getPosition())
|
||||||
getOgObject().place(position.getX() + getObject().getCenter().getBlockX(), position.getY() + getObject().getCenter().getBlockY(), position.getZ() + getObject().getCenter().getBlockZ(), new IObjectPlacer() {
|
.sub(new IrisPosition(self.object.getCenter()));
|
||||||
@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());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,20 +21,21 @@ package com.volmit.iris.engine.jigsaw;
|
|||||||
import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap;
|
import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap;
|
||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.Iris;
|
||||||
import com.volmit.iris.core.loader.IrisData;
|
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.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.engine.object.*;
|
||||||
import com.volmit.iris.util.collection.KList;
|
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.mantle.Mantle;
|
||||||
|
import com.volmit.iris.util.math.Position2;
|
||||||
import com.volmit.iris.util.math.RNG;
|
import com.volmit.iris.util.math.RNG;
|
||||||
import com.volmit.iris.util.matter.slices.JigsawPieceMatter;
|
|
||||||
import com.volmit.iris.util.matter.slices.container.JigsawPieceContainer;
|
import com.volmit.iris.util.matter.slices.container.JigsawPieceContainer;
|
||||||
|
import com.volmit.iris.util.matter.slices.container.JigsawStructuresContainer;
|
||||||
|
import com.volmit.iris.util.scheduling.J;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.bukkit.Axis;
|
import org.bukkit.Axis;
|
||||||
import org.bukkit.World;
|
|
||||||
import org.bukkit.block.TileState;
|
import java.util.function.Consumer;
|
||||||
import org.bukkit.block.data.BlockData;
|
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class PlannedStructure {
|
public class PlannedStructure {
|
||||||
@@ -49,16 +50,18 @@ public class PlannedStructure {
|
|||||||
private IrisPosition position;
|
private IrisPosition position;
|
||||||
private IrisData data;
|
private IrisData data;
|
||||||
private RNG rng;
|
private RNG rng;
|
||||||
|
private boolean forcePlace;
|
||||||
private boolean verbose;
|
private boolean verbose;
|
||||||
private boolean terminating;
|
private boolean terminating;
|
||||||
|
|
||||||
public PlannedStructure(IrisJigsawStructure structure, IrisPosition position, RNG rng) {
|
public PlannedStructure(IrisJigsawStructure structure, IrisPosition position, RNG rng, boolean forcePlace) {
|
||||||
terminating = false;
|
terminating = false;
|
||||||
verbose = true;
|
verbose = true;
|
||||||
this.pieces = new KList<>();
|
this.pieces = new KList<>();
|
||||||
this.structure = structure;
|
this.structure = structure;
|
||||||
this.position = position;
|
this.position = position;
|
||||||
this.rng = rng;
|
this.rng = rng;
|
||||||
|
this.forcePlace = forcePlace || structure.isForcePlace();
|
||||||
this.data = structure.getLoader();
|
this.data = structure.getLoader();
|
||||||
generateStartPiece();
|
generateStartPiece();
|
||||||
|
|
||||||
@@ -75,33 +78,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();
|
IrisObjectPlacement options = new IrisObjectPlacement();
|
||||||
options.getRotation().setEnabled(false);
|
options.setRotation(IrisObjectRotation.of(0,0,0));
|
||||||
int startHeight = pieces.get(0).getPosition().getY();
|
int startHeight = pieces.get(0).getPosition().getY();
|
||||||
|
|
||||||
|
boolean placed = false;
|
||||||
for (PlannedPiece i : pieces) {
|
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;
|
IrisObjectPlacement options = o;
|
||||||
|
|
||||||
if (i.getPiece().getPlacementOptions() != null) {
|
if (i.getPiece().getPlacementOptions() != null) {
|
||||||
options = i.getPiece().getPlacementOptions();
|
options = i.getPiece().getPlacementOptions();
|
||||||
options.getRotation().setEnabled(false);
|
options.getRotation().setEnabled(false);
|
||||||
|
options.setRotateTowardsSlope(false);
|
||||||
|
options.setWarp(new IrisGeneratorStyle(NoiseStyle.FLAT));
|
||||||
} else {
|
} else {
|
||||||
options.setMode(i.getPiece().getPlaceMode());
|
options.setMode(i.getPiece().getPlaceMode());
|
||||||
}
|
}
|
||||||
|
if (forcePlace) {
|
||||||
|
options.setForcePlace(true);
|
||||||
|
}
|
||||||
|
|
||||||
IrisObject vo = i.getOgObject();
|
|
||||||
IrisObject v = i.getObject();
|
IrisObject v = i.getObject();
|
||||||
int sx = (v.getW() / 2);
|
int sx = (v.getW() / 2);
|
||||||
int sz = (v.getD() / 2);
|
int sz = (v.getD() / 2);
|
||||||
int xx = i.getPosition().getX() + sx;
|
int xx = i.getPosition().getX() + sx;
|
||||||
int zz = i.getPosition().getZ() + sz;
|
int zz = i.getPosition().getZ() + sz;
|
||||||
RNG rng = new RNG(Cache.key(xx, zz));
|
|
||||||
int offset = i.getPosition().getY() - startHeight;
|
int offset = i.getPosition().getY() - startHeight;
|
||||||
int height;
|
int height;
|
||||||
|
|
||||||
@@ -109,12 +126,23 @@ public class PlannedStructure {
|
|||||||
if (i.getStructure().getStructure().getOverrideYRange() != null) {
|
if (i.getStructure().getStructure().getOverrideYRange() != null) {
|
||||||
height = (int) i.getStructure().getStructure().getOverrideYRange().get(rng, xx, zz, getData());
|
height = (int) i.getStructure().getStructure().getOverrideYRange().get(rng, xx, zz, getData());
|
||||||
} else {
|
} else {
|
||||||
height = placer.getHighest(xx, zz, getData());
|
height = placer.getHighest(xx, zz, getData(), options.isUnderwater());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
height = i.getStructure().getStructure().getLockY();
|
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);
|
height += offset + (v.getH() / 2);
|
||||||
|
|
||||||
if (options.getMode().equals(ObjectPlaceMode.PAINT)) {
|
if (options.getMode().equals(ObjectPlaceMode.PAINT)) {
|
||||||
@@ -123,75 +151,18 @@ public class PlannedStructure {
|
|||||||
|
|
||||||
int id = rng.i(0, Integer.MAX_VALUE);
|
int id = rng.i(0, Integer.MAX_VALUE);
|
||||||
JigsawPieceContainer container = JigsawPieceContainer.toContainer(i.getPiece());
|
JigsawPieceContainer container = JigsawPieceContainer.toContainer(i.getPiece());
|
||||||
vo.place(xx, height, zz, new IObjectPlacer() {
|
i.setRealPositions(xx, height, zz, placer);
|
||||||
@Override
|
return v.place(xx, height, zz, placer, options, rng, (b, data) -> {
|
||||||
public int getHighest(int x, int z, IrisData data) {
|
e.set(b.getX(), b.getY(), b.getZ(), v.getLoadKey() + "@" + id);
|
||||||
return placer.getHighest(x, z, data);
|
e.set(b.getX(), b.getY(), b.getZ(), container);
|
||||||
|
if (data instanceof IrisBlockData d) {
|
||||||
|
e.set(b.getX(), b.getY(), b.getZ(), d.getCustom());
|
||||||
}
|
}
|
||||||
|
}, null, getData().getEngine() != null ? getData() : eng.getData()) != -1;
|
||||||
@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());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void place(World world) {
|
public void place(WorldObjectPlacer placer, Consumer<Boolean> consumer) {
|
||||||
for (PlannedPiece i : pieces) {
|
J.s(() -> consumer.accept(place(placer, placer.getMantle().getMantle(), placer.getEngine())));
|
||||||
Iris.sq(() -> i.place(world));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateOutwards() {
|
private void generateOutwards() {
|
||||||
@@ -208,6 +179,7 @@ public class PlannedStructure {
|
|||||||
for (IrisJigsawPieceConnector i : piece.getAvailableConnectors().shuffleCopy(rng)) {
|
for (IrisJigsawPieceConnector i : piece.getAvailableConnectors().shuffleCopy(rng)) {
|
||||||
if (generateConnectorOutwards(piece, i)) {
|
if (generateConnectorOutwards(piece, i)) {
|
||||||
b = true;
|
b = true;
|
||||||
|
piece.debugPrintConnectorPositions();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -226,9 +198,7 @@ public class PlannedStructure {
|
|||||||
|
|
||||||
private boolean generateRotatedPiece(PlannedPiece piece, IrisJigsawPieceConnector pieceConnector, IrisJigsawPiece idea) {
|
private boolean generateRotatedPiece(PlannedPiece piece, IrisJigsawPieceConnector pieceConnector, IrisJigsawPiece idea) {
|
||||||
if (!piece.getPiece().getPlacementOptions().getRotation().isEnabled()) {
|
if (!piece.getPiece().getPlacementOptions().getRotation().isEnabled()) {
|
||||||
if (generateRotatedPiece(piece, pieceConnector, idea, 0, 0, 0)) {
|
return generateRotatedPiece(piece, pieceConnector, idea, 0, 0, 0);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
KList<Integer> forder1 = new KList<Integer>().qadd(0).qadd(1).qadd(2).qadd(3).shuffle(rng);
|
KList<Integer> forder1 = new KList<Integer>().qadd(0).qadd(1).qadd(2).qadd(3).shuffle(rng);
|
||||||
@@ -275,7 +245,7 @@ public class PlannedStructure {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean generateRotatedPiece(PlannedPiece piece, IrisJigsawPieceConnector pieceConnector, IrisJigsawPiece idea, int x, int y, int z) {
|
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) {
|
private boolean generatePositionedPiece(PlannedPiece piece, IrisJigsawPieceConnector pieceConnector, PlannedPiece test, IrisJigsawPieceConnector testConnector) {
|
||||||
@@ -299,8 +269,7 @@ public class PlannedStructure {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
piece.connect(pieceConnector);
|
piece.connect(pieceConnector, test, testConnector);
|
||||||
test.connect(testConnector);
|
|
||||||
pieces.add(test);
|
pieces.add(test);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -309,7 +278,8 @@ public class PlannedStructure {
|
|||||||
private KList<IrisJigsawPiece> getShuffledPiecesFor(IrisJigsawPieceConnector c) {
|
private KList<IrisJigsawPiece> getShuffledPiecesFor(IrisJigsawPieceConnector c) {
|
||||||
KList<IrisJigsawPiece> p = new KList<>();
|
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)) {
|
for (String j : getData().getJigsawPoolLoader().load(i).getPieces().shuffleCopy(rng)) {
|
||||||
IrisJigsawPiece pi = getData().getJigsawPieceLoader().load(j);
|
IrisJigsawPiece pi = getData().getJigsawPieceLoader().load(j);
|
||||||
|
|
||||||
@@ -335,7 +305,9 @@ public class PlannedStructure {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public KList<PlannedPiece> getPiecesWithAvailableConnectors() {
|
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() {
|
public int getVolume() {
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user