mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2025-12-20 07:29:32 +00:00
Compare commits
281 Commits
feat/headl
...
feat/craft
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a7eb3bed13 | ||
|
|
a7d874d37f | ||
|
|
7c41f86fb3 | ||
|
|
e5e0561d5a | ||
|
|
d50cdfec3e | ||
|
|
00997c1902 | ||
|
|
3095a92522 | ||
|
|
fca309dec7 | ||
|
|
2793ed1035 | ||
|
|
e5908285af | ||
|
|
a8ee321eb8 | ||
|
|
aa14242b54 | ||
|
|
f6968269b4 | ||
|
|
0d0251e2f1 | ||
|
|
81b8fb02ae | ||
|
|
77842489e5 | ||
|
|
eda1f59d3a | ||
|
|
5418868559 | ||
|
|
1d81daafbb | ||
|
|
609a3585c1 | ||
|
|
571dde608c | ||
|
|
3a13f5a7c1 | ||
|
|
e5654b74d4 | ||
|
|
a75738dd7a | ||
|
|
003be1f88b | ||
|
|
1eaafae20d | ||
|
|
79088c0305 | ||
|
|
9e147774bd | ||
|
|
e51b632c8f | ||
|
|
1aa64c9a02 | ||
|
|
1e148d8fcd | ||
|
|
f63cabd8b8 | ||
|
|
176d3a5f9f | ||
|
|
eb184983de | ||
|
|
d1c307865d | ||
|
|
4a26b8b34f | ||
|
|
33fd01c3ac | ||
|
|
34874080e7 | ||
|
|
43131ed8f6 | ||
|
|
9ea425aee4 | ||
|
|
709f05c1a5 | ||
|
|
ec74add5de | ||
|
|
d5b706764a | ||
|
|
ca4c205a4a | ||
|
|
7b9c2ae6ad | ||
|
|
d0e9d44152 | ||
|
|
2cdffaae33 | ||
|
|
d4a8beac95 | ||
|
|
0e0e4075d8 | ||
|
|
9c492a2e66 | ||
|
|
96bf83684c | ||
|
|
25ea9ae62d | ||
|
|
7938c150dd | ||
|
|
a7b4bf3ff2 | ||
|
|
693a05f2cb | ||
|
|
e48cbe1f69 | ||
|
|
558f6fa8dd | ||
|
|
67b29cc363 | ||
|
|
4702534f9c | ||
|
|
29390c5e0a | ||
|
|
e8bfce469d | ||
|
|
770e2f47a2 | ||
|
|
747e7b3330 | ||
|
|
8662f3b47a | ||
|
|
6e738e69e7 | ||
|
|
4bf14c83e1 | ||
|
|
837674c295 | ||
|
|
e5f3bbd69e | ||
|
|
2885a39299 | ||
|
|
bd1b06c761 | ||
|
|
3e1143112a | ||
|
|
834b214fbf | ||
|
|
768e569400 | ||
|
|
a5d04333dd | ||
|
|
ebe8da0fd5 | ||
|
|
5eb25f3977 | ||
|
|
a5bca0a9bb | ||
|
|
a82882c1c1 | ||
|
|
05193bd0d9 | ||
|
|
96efc15c36 | ||
|
|
67f456cf53 | ||
|
|
58b1bd115f | ||
|
|
8ddc8abdb9 | ||
|
|
12c2c71739 | ||
|
|
8705ca6e47 | ||
|
|
a610d0a7a9 | ||
|
|
0648cfd3fa | ||
|
|
fba9c17e3f | ||
|
|
74128d58cf | ||
|
|
70130e976d | ||
|
|
501c426302 | ||
|
|
8471f15bc8 | ||
|
|
c4539441a0 | ||
|
|
472a98da16 | ||
|
|
76a6f1465a | ||
|
|
b0ca0e3617 | ||
|
|
08b9058c8f | ||
|
|
556bef6e43 | ||
|
|
16a4d20c90 | ||
|
|
e5f2fee926 | ||
|
|
3949468a60 | ||
|
|
fc54fcb7eb | ||
|
|
9d6e4e87d8 | ||
|
|
f50e964d4f | ||
|
|
8262e52893 | ||
|
|
1c41dc69ce | ||
|
|
dee46a4284 | ||
|
|
a8892b04ef | ||
|
|
d49f7d7821 | ||
|
|
106a3834ab | ||
|
|
387e8adfe2 | ||
|
|
9ade90d9ca | ||
|
|
3d2392843a | ||
|
|
a9891e819a | ||
|
|
02c13a9391 | ||
|
|
f6590c26e7 | ||
|
|
64bb81626c | ||
|
|
343dc429d5 | ||
|
|
8f5f44bc96 | ||
|
|
6964b99744 | ||
|
|
11cfd85f6a | ||
|
|
c5416f54fa | ||
|
|
94c5782490 | ||
|
|
cc49b0f540 | ||
|
|
1bc6192c8b | ||
|
|
4b0766c097 | ||
|
|
ec5cb2d646 | ||
|
|
0edaeeec99 | ||
|
|
a0543bbbf2 | ||
|
|
0b1af51227 | ||
|
|
03c5998c02 | ||
|
|
6b193f695a | ||
|
|
0a30881f87 | ||
|
|
c01a7def5d | ||
|
|
50db1d11a7 | ||
|
|
2e2ea8f1e4 | ||
|
|
badf108d56 | ||
|
|
f9888d19a5 | ||
|
|
fbc5cee300 | ||
|
|
12777bc3f0 | ||
|
|
9324b1b5c0 | ||
|
|
2ecb555619 | ||
|
|
20c7891c2f | ||
|
|
c35c858eee | ||
|
|
cb93e78242 | ||
|
|
c9ed4519a8 | ||
|
|
86d986dfbc | ||
|
|
54402faea8 | ||
|
|
77b4253624 | ||
|
|
44af23ba2e | ||
|
|
4e8079e431 | ||
|
|
39f65d02bf | ||
|
|
8c025a9ba2 | ||
|
|
7119fa8ef7 | ||
|
|
6f0b2b6bba | ||
|
|
0ae1334a57 | ||
|
|
5d28563b7c | ||
|
|
cf8243a000 | ||
|
|
cca0bed482 | ||
|
|
a802edc375 | ||
|
|
3677931114 | ||
|
|
e38dae0a32 | ||
|
|
d537459c5a | ||
|
|
67398174bb | ||
|
|
0a0f77ff58 | ||
|
|
e5cb4d82a3 | ||
|
|
9d44ac0b47 | ||
|
|
7f6d65a13e | ||
|
|
ad720f4aa2 | ||
|
|
80548f753c | ||
|
|
c9c8a9e412 | ||
|
|
d048c073ac | ||
|
|
2929a1f0a7 | ||
|
|
b6f9f68b9f | ||
|
|
da2dd42e28 | ||
|
|
88360ef772 | ||
|
|
73787e21d2 | ||
|
|
840608a40f | ||
|
|
fcedc35635 | ||
|
|
32d9a5e40a | ||
|
|
8df6253604 | ||
|
|
01b62c13b6 | ||
|
|
f32f73e65a | ||
|
|
7b7118fe0d | ||
|
|
851ac18f0d | ||
|
|
37be7ca847 | ||
|
|
ed67b4d3c2 | ||
|
|
b62ac875d5 | ||
|
|
4c3f95b0e1 | ||
|
|
8712c8874c | ||
|
|
ccc3bab8e0 | ||
|
|
113f25dab8 | ||
|
|
cd80acdc7d | ||
|
|
9316ea9e5b | ||
|
|
e2a3f25dcb | ||
|
|
944cc19ebc | ||
|
|
172e234514 | ||
|
|
f9dac8a3a1 | ||
|
|
eefbbab7ee | ||
|
|
9cf567e1ff | ||
|
|
b8ee7561dd | ||
|
|
c0d17742e8 | ||
|
|
a88d389e0f | ||
|
|
b341089996 | ||
|
|
9cbfd5a10b | ||
|
|
fdaf8ff9d3 | ||
|
|
e63d84c052 | ||
|
|
0d103a934a | ||
|
|
8119207254 | ||
|
|
b66e6d8335 | ||
|
|
ce2b62f5ae | ||
|
|
c767b6c8e8 | ||
|
|
67328d7d10 | ||
|
|
329e136a66 | ||
|
|
52f87befa2 | ||
|
|
2ee22db072 | ||
|
|
cc27e87376 | ||
|
|
abb1d9cd62 | ||
|
|
e0ad029c3d | ||
|
|
5705caa1ba | ||
|
|
a56cd4c268 | ||
|
|
48cc6bb49c | ||
|
|
635ee02459 | ||
|
|
2c7b7c8c91 | ||
|
|
ad0662be54 | ||
|
|
835c8422f1 | ||
|
|
2c60192de3 | ||
|
|
adb7188eb9 | ||
|
|
2436ebb857 | ||
|
|
ad85a0bbd1 | ||
|
|
22ac9ebf47 | ||
|
|
3cb9585dd8 | ||
|
|
f4d1177c51 | ||
|
|
b132862a60 | ||
|
|
2452a2f633 | ||
|
|
f0476fea9b | ||
|
|
90c6457d37 | ||
|
|
61301ffd4d | ||
|
|
e42317139d | ||
|
|
f68600464b | ||
|
|
97ddfd309b | ||
|
|
5d42c5cae0 | ||
|
|
52fecb48d8 | ||
|
|
ce29dc98c3 | ||
|
|
463e3d9658 | ||
|
|
9152b25d51 | ||
|
|
bb9c72e414 | ||
|
|
976648340e | ||
|
|
5958bcb22e | ||
|
|
8eb35aa8be | ||
|
|
49ce84a9e9 | ||
|
|
6724b0f4c5 | ||
|
|
e72abc8c39 | ||
|
|
0a2f35dd8d | ||
|
|
c597c55c2c | ||
|
|
f93995e152 | ||
|
|
7a5a2e5909 | ||
|
|
e15d31a0ed | ||
|
|
09cdd61a68 | ||
|
|
0575cd85c8 | ||
|
|
2008975a8a | ||
|
|
aad1d3815a | ||
|
|
86c64f99e9 | ||
|
|
6577f4a5de | ||
|
|
3415e7c7af | ||
|
|
f1c72974fd | ||
|
|
26e2e20840 | ||
|
|
c00dcf205b | ||
|
|
a10a784c3b | ||
|
|
f99cc61042 | ||
|
|
d2a1e5cc1e | ||
|
|
3e2c0fa025 | ||
|
|
9c151abac7 | ||
|
|
ab4770400e | ||
|
|
1a810d5d62 | ||
|
|
536d20bca7 | ||
|
|
9a691ac5b4 | ||
|
|
71078a20a9 | ||
|
|
566fca2b52 | ||
|
|
74e2576ca2 | ||
|
|
fb0bc112e3 |
254
build.gradle
254
build.gradle
@@ -1,254 +0,0 @@
|
|||||||
/*
|
|
||||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
|
||||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
buildscript() {
|
|
||||||
repositories {
|
|
||||||
maven { url 'https://jitpack.io'}
|
|
||||||
}
|
|
||||||
dependencies {
|
|
||||||
classpath 'com.github.VolmitSoftware:NMSTools:1.0.1'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
plugins {
|
|
||||||
id 'java'
|
|
||||||
id 'java-library'
|
|
||||||
id "io.github.goooler.shadow" version "8.1.7"
|
|
||||||
id "de.undercouch.download" version "5.0.1"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
version '3.6.5-1.20.1-1.21.4'
|
|
||||||
|
|
||||||
// ADD YOURSELF AS A NEW LINE IF YOU WANT YOUR OWN BUILD TASK GENERATED
|
|
||||||
// ======================== WINDOWS =============================
|
|
||||||
registerCustomOutputTask('Cyberpwn', 'C://Users/cyberpwn/Documents/development/server/plugins')
|
|
||||||
registerCustomOutputTask('Psycho', 'C://Dan/MinecraftDevelopment/Server/plugins')
|
|
||||||
registerCustomOutputTask('ArcaneArts', 'C://Users/arcane/Documents/development/server/plugins')
|
|
||||||
registerCustomOutputTask('Coco', 'D://mcsm/plugins')
|
|
||||||
registerCustomOutputTask('Strange', 'D://Servers/1.17 Test Server/plugins')
|
|
||||||
registerCustomOutputTask('Vatuu', 'D://Minecraft/Servers/1.19.4/plugins')
|
|
||||||
registerCustomOutputTask('CrazyDev22', 'C://Users/Julian/Desktop/server/plugins')
|
|
||||||
registerCustomOutputTask('PixelFury', 'C://Users/repix/workplace/Iris/1.21.3 - Development-Public-v3/plugins')
|
|
||||||
registerCustomOutputTask('PixelFuryDev', 'C://Users/repix/workplace/Iris/1.21 - Development-v3/plugins')
|
|
||||||
// ========================== UNIX ==============================
|
|
||||||
registerCustomOutputTaskUnix('CyberpwnLT', '/Users/danielmills/development/server/plugins')
|
|
||||||
registerCustomOutputTaskUnix('PsychoLT', '/Users/brianfopiano/Developer/RemoteGit/Server/plugins')
|
|
||||||
registerCustomOutputTaskUnix('PixelMac', '/Users/test/Desktop/mcserver/plugins')
|
|
||||||
registerCustomOutputTaskUnix('CrazyDev22LT', '/home/julian/Desktop/server/plugins')
|
|
||||||
// ==============================================================
|
|
||||||
|
|
||||||
def NMS_BINDINGS = Map.of(
|
|
||||||
"v1_21_R3", "1.21.4-R0.1-SNAPSHOT",
|
|
||||||
"v1_21_R2", "1.21.3-R0.1-SNAPSHOT",
|
|
||||||
"v1_21_R1", "1.21.1-R0.1-SNAPSHOT",
|
|
||||||
"v1_20_R4", "1.20.6-R0.1-SNAPSHOT",
|
|
||||||
"v1_20_R3", "1.20.4-R0.1-SNAPSHOT",
|
|
||||||
"v1_20_R2", "1.20.2-R0.1-SNAPSHOT",
|
|
||||||
"v1_20_R1", "1.20.1-R0.1-SNAPSHOT",
|
|
||||||
)
|
|
||||||
def JVM_VERSION = Map.of()
|
|
||||||
NMS_BINDINGS.each { nms ->
|
|
||||||
project(":nms:${nms.key}") {
|
|
||||||
apply plugin: 'java'
|
|
||||||
apply plugin: 'com.volmit.nmstools'
|
|
||||||
|
|
||||||
nmsTools {
|
|
||||||
it.jvm = JVM_VERSION.getOrDefault(nms.key, 21)
|
|
||||||
it.version = nms.value
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
implementation project(":core")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
shadowJar {
|
|
||||||
NMS_BINDINGS.each {
|
|
||||||
dependsOn(":nms:${it.key}:remap")
|
|
||||||
from("${project(":nms:${it.key}").layout.buildDirectory.asFile.get()}/libs/${it.key}-mapped.jar")
|
|
||||||
}
|
|
||||||
|
|
||||||
//minimize()
|
|
||||||
append("plugin.yml")
|
|
||||||
relocate 'com.dfsek.paralithic', 'com.volmit.iris.util.paralithic'
|
|
||||||
relocate 'io.papermc.lib', 'com.volmit.iris.util.paper'
|
|
||||||
relocate 'net.kyori', 'com.volmit.iris.util.kyori'
|
|
||||||
relocate 'org.bstats', 'com.volmit.util.metrics'
|
|
||||||
archiveFileName.set("Iris-${project.version}.jar")
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
implementation project(':core')
|
|
||||||
}
|
|
||||||
|
|
||||||
configurations.configureEach {
|
|
||||||
resolutionStrategy.cacheChangingModulesFor 60, 'minutes'
|
|
||||||
resolutionStrategy.cacheDynamicVersionsFor 60, 'minutes'
|
|
||||||
}
|
|
||||||
|
|
||||||
allprojects {
|
|
||||||
apply plugin: 'java'
|
|
||||||
|
|
||||||
repositories {
|
|
||||||
mavenCentral()
|
|
||||||
maven { url "https://repo.papermc.io/repository/maven-public/" }
|
|
||||||
maven { url "https://repo.codemc.org/repository/maven-public" }
|
|
||||||
maven { url "https://mvn.lumine.io/repository/maven-public/" }
|
|
||||||
maven { url "https://jitpack.io" }
|
|
||||||
|
|
||||||
maven { url "https://s01.oss.sonatype.org/content/repositories/snapshots" }
|
|
||||||
maven { url "https://mvn.lumine.io/repository/maven/" }
|
|
||||||
maven { url "https://repo.triumphteam.dev/snapshots" }
|
|
||||||
maven { url "https://repo.mineinabyss.com/releases" }
|
|
||||||
maven { url 'https://hub.jeff-media.com/nexus/repository/jeff-media-public/' }
|
|
||||||
maven { url "https://repo.nexomc.com/snapshots/" }
|
|
||||||
maven { url "https://libraries.minecraft.net" }
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
// Provided or Classpath
|
|
||||||
compileOnly 'org.projectlombok:lombok:1.18.36'
|
|
||||||
annotationProcessor 'org.projectlombok:lombok:1.18.36'
|
|
||||||
|
|
||||||
// Shaded
|
|
||||||
implementation 'com.dfsek:paralithic:0.8.1'
|
|
||||||
implementation 'io.papermc:paperlib:1.0.5'
|
|
||||||
implementation "net.kyori:adventure-text-minimessage:4.17.0"
|
|
||||||
implementation 'net.kyori:adventure-platform-bukkit:4.3.4'
|
|
||||||
implementation 'net.kyori:adventure-api:4.17.0'
|
|
||||||
implementation 'org.bstats:bstats-bukkit:3.1.0'
|
|
||||||
//implementation 'org.bytedeco:javacpp:1.5.10'
|
|
||||||
//implementation 'org.bytedeco:cuda-platform:12.3-8.9-1.5.10'
|
|
||||||
compileOnly 'io.lumine:Mythic-Dist:5.2.1'
|
|
||||||
compileOnly 'io.lumine:MythicCrucible-Dist:2.0.0'
|
|
||||||
|
|
||||||
// Dynamically Loaded
|
|
||||||
compileOnly 'io.timeandspace:smoothie-map:2.0.2'
|
|
||||||
compileOnly 'it.unimi.dsi:fastutil:8.5.8'
|
|
||||||
compileOnly 'com.googlecode.concurrentlinkedhashmap:concurrentlinkedhashmap-lru:1.4.2'
|
|
||||||
compileOnly 'org.zeroturnaround:zt-zip:1.14'
|
|
||||||
compileOnly 'com.google.code.gson:gson:2.10.1'
|
|
||||||
compileOnly 'org.ow2.asm:asm:9.2'
|
|
||||||
compileOnly 'com.google.guava:guava:33.0.0-jre'
|
|
||||||
compileOnly 'bsf:bsf:2.4.0'
|
|
||||||
compileOnly 'rhino:js:1.7R2'
|
|
||||||
compileOnly 'com.github.ben-manes.caffeine:caffeine:3.0.6'
|
|
||||||
compileOnly 'org.apache.commons:commons-lang3:3.12.0'
|
|
||||||
compileOnly 'com.github.oshi:oshi-core:6.6.5'
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* We need parameter meta for the decree command system
|
|
||||||
*/
|
|
||||||
compileJava {
|
|
||||||
options.compilerArgs << '-parameters'
|
|
||||||
options.encoding = "UTF-8"
|
|
||||||
}
|
|
||||||
|
|
||||||
javadoc {
|
|
||||||
options.encoding = "UTF-8"
|
|
||||||
options.addStringOption('Xdoclint:none', '-quiet')
|
|
||||||
}
|
|
||||||
|
|
||||||
task sourcesJar(type: Jar, dependsOn: classes) {
|
|
||||||
archiveClassifier.set('sources')
|
|
||||||
from sourceSets.main.allSource
|
|
||||||
}
|
|
||||||
|
|
||||||
task javadocJar(type: Jar, dependsOn: javadoc) {
|
|
||||||
archiveClassifier.set('javadoc')
|
|
||||||
from javadoc.destinationDir
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (JavaVersion.current().toString() != "21") {
|
|
||||||
System.err.println()
|
|
||||||
System.err.println("=========================================================================================================")
|
|
||||||
System.err.println("You must run gradle on Java 21. You are using " + JavaVersion.current())
|
|
||||||
System.err.println()
|
|
||||||
System.err.println("=== For IDEs ===")
|
|
||||||
System.err.println("1. Configure the project for Java 21")
|
|
||||||
System.err.println("2. Configure the bundled gradle to use Java 21 in settings")
|
|
||||||
System.err.println()
|
|
||||||
System.err.println("=== For Command Line (gradlew) ===")
|
|
||||||
System.err.println("1. Install JDK 21 from https://www.oracle.com/java/technologies/javase/jdk21-archive-downloads.html")
|
|
||||||
System.err.println("2. Set JAVA_HOME environment variable to the new jdk installation folder such as C:\\Program Files\\Java\\jdk-21.0.4")
|
|
||||||
System.err.println("3. Open a new command prompt window to get the new environment variables if need be.")
|
|
||||||
System.err.println("=========================================================================================================")
|
|
||||||
System.err.println()
|
|
||||||
System.exit(69);
|
|
||||||
}
|
|
||||||
|
|
||||||
task iris(type: Copy) {
|
|
||||||
group "iris"
|
|
||||||
from new File(layout.buildDirectory.asFile.get(), "libs/Iris-${version}.jar")
|
|
||||||
into layout.buildDirectory.asFile.get()
|
|
||||||
dependsOn(build)
|
|
||||||
}
|
|
||||||
|
|
||||||
// with classifier: 'javadoc' and 'sources'
|
|
||||||
task irisDev(type: Copy) {
|
|
||||||
group "iris"
|
|
||||||
from("core/build/libs/core-javadoc.jar", "core/build/libs/core-sources.jar")
|
|
||||||
rename { String fileName ->
|
|
||||||
fileName.replace("core", "Iris-${version}")
|
|
||||||
}
|
|
||||||
into layout.buildDirectory.asFile.get()
|
|
||||||
dependsOn(iris)
|
|
||||||
dependsOn("core:sourcesJar")
|
|
||||||
dependsOn("core:javadocJar")
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def registerCustomOutputTask(name, path) {
|
|
||||||
if (!System.properties['os.name'].toLowerCase().contains('windows')) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.register('build' + name, Copy) {
|
|
||||||
group('development')
|
|
||||||
outputs.upToDateWhen { false }
|
|
||||||
dependsOn(iris)
|
|
||||||
from(new File(buildDir, "Iris-" + version + ".jar"))
|
|
||||||
into(file(path))
|
|
||||||
rename { String fileName ->
|
|
||||||
fileName.replace("Iris-" + version + ".jar", "Iris.jar")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def registerCustomOutputTaskUnix(name, path) {
|
|
||||||
if (System.properties['os.name'].toLowerCase().contains('windows')) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.register('build' + name, Copy) {
|
|
||||||
group('development')
|
|
||||||
outputs.upToDateWhen { false }
|
|
||||||
dependsOn(iris)
|
|
||||||
from(new File(buildDir, "Iris-" + version + ".jar"))
|
|
||||||
into(file(path))
|
|
||||||
rename { String fileName ->
|
|
||||||
fileName.replace("Iris-" + version + ".jar", "Iris.jar")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.build.dependsOn(shadowJar)
|
|
||||||
281
build.gradle.kts
Normal file
281
build.gradle.kts
Normal file
@@ -0,0 +1,281 @@
|
|||||||
|
import com.volmit.nmstools.NMSToolsExtension
|
||||||
|
import com.volmit.nmstools.NMSToolsPlugin
|
||||||
|
import de.undercouch.gradle.tasks.download.Download
|
||||||
|
import xyz.jpenilla.runpaper.task.RunServer
|
||||||
|
import kotlin.system.exitProcess
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||||
|
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
buildscript {
|
||||||
|
repositories.maven("https://jitpack.io")
|
||||||
|
dependencies.classpath("com.github.VolmitSoftware:NMSTools:c5cbc46ce6")
|
||||||
|
}
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
java
|
||||||
|
`java-library`
|
||||||
|
alias(libs.plugins.shadow)
|
||||||
|
alias(libs.plugins.download)
|
||||||
|
alias(libs.plugins.runPaper)
|
||||||
|
}
|
||||||
|
|
||||||
|
group = "com.volmit"
|
||||||
|
version = "3.7.2-1.20.1-1.21.8"
|
||||||
|
|
||||||
|
apply<ApiGenerator>()
|
||||||
|
|
||||||
|
// ADD YOURSELF AS A NEW LINE IF YOU WANT YOUR OWN BUILD TASK GENERATED
|
||||||
|
// ======================== WINDOWS =============================
|
||||||
|
registerCustomOutputTask("Cyberpwn", "C://Users/cyberpwn/Documents/development/server/plugins")
|
||||||
|
registerCustomOutputTask("Psycho", "C://Dan/MinecraftDevelopment/Server/plugins")
|
||||||
|
registerCustomOutputTask("ArcaneArts", "C://Users/arcane/Documents/development/server/plugins")
|
||||||
|
registerCustomOutputTask("Coco", "D://mcsm/plugins")
|
||||||
|
registerCustomOutputTask("Strange", "D://Servers/1.17 Test Server/plugins")
|
||||||
|
registerCustomOutputTask("Vatuu", "D://Minecraft/Servers/1.19.4/plugins")
|
||||||
|
registerCustomOutputTask("CrazyDev22", "C://Users/Julian/Desktop/server/plugins")
|
||||||
|
registerCustomOutputTask("PixelFury", "C://Users/repix/workplace/Iris/1.21.3 - Development-Public-v3/plugins")
|
||||||
|
registerCustomOutputTask("PixelFuryDev", "C://Users/repix/workplace/Iris/1.21 - Development-v3/plugins")
|
||||||
|
// ========================== UNIX ==============================
|
||||||
|
registerCustomOutputTaskUnix("CyberpwnLT", "/Users/danielmills/development/server/plugins")
|
||||||
|
registerCustomOutputTaskUnix("PsychoLT", "/Users/brianfopiano/Developer/RemoteGit/Server/plugins")
|
||||||
|
registerCustomOutputTaskUnix("PixelMac", "/Users/test/Desktop/mcserver/plugins")
|
||||||
|
registerCustomOutputTaskUnix("CrazyDev22LT", "/home/julian/Desktop/server/plugins")
|
||||||
|
// ==============================================================
|
||||||
|
|
||||||
|
val serverMinHeap = "2G"
|
||||||
|
val serverMaxHeap = "8G"
|
||||||
|
//Valid values are: none, truecolor, indexed256, indexed16, indexed8
|
||||||
|
val color = "truecolor"
|
||||||
|
val errorReporting = findProperty("errorReporting") as Boolean? ?: false
|
||||||
|
|
||||||
|
val nmsBindings = mapOf(
|
||||||
|
"v1_21_R5" to "1.21.7-R0.1-SNAPSHOT",
|
||||||
|
"v1_21_R4" to "1.21.5-R0.1-SNAPSHOT",
|
||||||
|
"v1_21_R3" to "1.21.4-R0.1-SNAPSHOT",
|
||||||
|
"v1_21_R2" to "1.21.3-R0.1-SNAPSHOT",
|
||||||
|
"v1_21_R1" to "1.21.1-R0.1-SNAPSHOT",
|
||||||
|
"v1_20_R4" to "1.20.6-R0.1-SNAPSHOT",
|
||||||
|
"v1_20_R3" to "1.20.4-R0.1-SNAPSHOT",
|
||||||
|
"v1_20_R2" to "1.20.2-R0.1-SNAPSHOT",
|
||||||
|
"v1_20_R1" to "1.20.1-R0.1-SNAPSHOT",
|
||||||
|
)
|
||||||
|
val jvmVersion = mapOf<String, Int>()
|
||||||
|
nmsBindings.forEach { key, value ->
|
||||||
|
project(":nms:$key") {
|
||||||
|
apply<JavaPlugin>()
|
||||||
|
apply<NMSToolsPlugin>()
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
maven("https://libraries.minecraft.net")
|
||||||
|
}
|
||||||
|
|
||||||
|
extensions.configure(NMSToolsExtension::class) {
|
||||||
|
jvm = jvmVersion.getOrDefault(key, 21)
|
||||||
|
version = value
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compileOnly(project(":core"))
|
||||||
|
compileOnly(rootProject.libs.annotations)
|
||||||
|
compileOnly(rootProject.libs.byteBuddy.core)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.register<RunServer>("runServer-$key") {
|
||||||
|
group = "servers"
|
||||||
|
minecraftVersion(value.split("-")[0])
|
||||||
|
minHeapSize = serverMinHeap
|
||||||
|
maxHeapSize = serverMaxHeap
|
||||||
|
pluginJars(tasks.jar.flatMap { it.archiveFile })
|
||||||
|
javaLauncher = javaToolchains.launcherFor { languageVersion = JavaLanguageVersion.of(jvmVersion.getOrDefault(key, 21))}
|
||||||
|
runDirectory.convention(layout.buildDirectory.dir("run/$key"))
|
||||||
|
systemProperty("disable.watchdog", "true")
|
||||||
|
systemProperty("net.kyori.ansi.colorLevel", color)
|
||||||
|
systemProperty("com.mojang.eula.agree", true)
|
||||||
|
systemProperty("iris.suppressReporting", !errorReporting)
|
||||||
|
jvmArgs("-javaagent:${project(":core:agent").tasks.jar.flatMap { it.archiveFile }.get().asFile.absolutePath}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks {
|
||||||
|
jar {
|
||||||
|
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||||
|
nmsBindings.forEach { key, _ ->
|
||||||
|
from(project(":nms:$key").tasks.named("remap").map { zipTree(it.outputs.files.singleFile) })
|
||||||
|
}
|
||||||
|
from(project(":core").tasks.shadowJar.flatMap { it.archiveFile }.map { zipTree(it) })
|
||||||
|
from(project(":core:agent").tasks.jar.flatMap { it.archiveFile })
|
||||||
|
archiveFileName.set("Iris-${project.version}.jar")
|
||||||
|
}
|
||||||
|
|
||||||
|
register<Copy>("iris") {
|
||||||
|
group = "iris"
|
||||||
|
dependsOn("jar")
|
||||||
|
from(layout.buildDirectory.file("libs/Iris-${project.version}.jar"))
|
||||||
|
into(layout.buildDirectory)
|
||||||
|
}
|
||||||
|
|
||||||
|
register<Copy>("irisDev") {
|
||||||
|
group = "iris"
|
||||||
|
from(project(":core").layout.buildDirectory.files("libs/core-javadoc.jar", "libs/core-sources.jar"))
|
||||||
|
rename { it.replace("core", "Iris-${project.version}") }
|
||||||
|
into(layout.buildDirectory)
|
||||||
|
dependsOn(":core:sourcesJar")
|
||||||
|
dependsOn(":core:javadocJar")
|
||||||
|
}
|
||||||
|
|
||||||
|
val cli = file("sentry-cli.exe")
|
||||||
|
register<Download>("downloadCli") {
|
||||||
|
group = "io.sentry"
|
||||||
|
src("https://release-registry.services.sentry.io/apps/sentry-cli/latest?response=download&arch=x86_64&platform=${System.getProperty("os.name")}&package=sentry-cli")
|
||||||
|
dest(cli)
|
||||||
|
|
||||||
|
doLast {
|
||||||
|
cli.setExecutable(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
register("release") {
|
||||||
|
group = "io.sentry"
|
||||||
|
dependsOn("downloadCli")
|
||||||
|
doLast {
|
||||||
|
val url = "http://sentry.volmit.com:8080"
|
||||||
|
val authToken = project.findProperty("sentry.auth.token") ?: System.getenv("SENTRY_AUTH_TOKEN")
|
||||||
|
val org = "sentry"
|
||||||
|
val projectName = "iris"
|
||||||
|
exec(cli, "--url", url , "--auth-token", authToken, "releases", "new", "-o", org, "-p", projectName, version)
|
||||||
|
exec(cli, "--url", url , "--auth-token", authToken, "releases", "set-commits", "-o", org, "-p", projectName, version, "--auto", "--ignore-missing")
|
||||||
|
//exec(cli, "--url", url, "--auth-token", authToken, "releases", "finalize", "-o", org, "-p", projectName, version)
|
||||||
|
cli.delete()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun exec(vararg command: Any) {
|
||||||
|
val p = ProcessBuilder(command.map { it.toString() })
|
||||||
|
.start()
|
||||||
|
p.inputStream.reader().useLines { it.forEach(::println) }
|
||||||
|
p.errorStream.reader().useLines { it.forEach(::println) }
|
||||||
|
p.waitFor()
|
||||||
|
}
|
||||||
|
|
||||||
|
configurations.configureEach {
|
||||||
|
resolutionStrategy.cacheChangingModulesFor(60, "minutes")
|
||||||
|
resolutionStrategy.cacheDynamicVersionsFor(60, "minutes")
|
||||||
|
}
|
||||||
|
|
||||||
|
allprojects {
|
||||||
|
apply<JavaPlugin>()
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
maven("https://repo.papermc.io/repository/maven-public/")
|
||||||
|
maven("https://repo.codemc.org/repository/maven-public/")
|
||||||
|
|
||||||
|
maven("https://jitpack.io") // EcoItems, score
|
||||||
|
maven("https://repo.nexomc.com/releases/") // nexo
|
||||||
|
maven("https://maven.devs.beer/") // itemsadder
|
||||||
|
maven("https://repo.extendedclip.com/releases/") // placeholderapi
|
||||||
|
maven("https://mvn.lumine.io/repository/maven-public/") // mythic
|
||||||
|
maven("https://nexus.phoenixdevt.fr/repository/maven-public/") //MMOItems
|
||||||
|
maven("https://repo.onarandombox.com/content/groups/public/") //Multiverse Core
|
||||||
|
maven("https://repo.momirealms.net/releases/") //CraftEngine
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
// Provided or Classpath
|
||||||
|
compileOnly(rootProject.libs.lombok)
|
||||||
|
annotationProcessor(rootProject.libs.lombok)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We need parameter meta for the decree command system
|
||||||
|
*/
|
||||||
|
tasks {
|
||||||
|
compileJava {
|
||||||
|
options.compilerArgs.add("-parameters")
|
||||||
|
options.encoding = "UTF-8"
|
||||||
|
}
|
||||||
|
|
||||||
|
javadoc {
|
||||||
|
options.encoding = "UTF-8"
|
||||||
|
options.quiet()
|
||||||
|
//options.addStringOption("Xdoclint:none") // TODO: Re-enable this
|
||||||
|
}
|
||||||
|
|
||||||
|
register<Jar>("sourcesJar") {
|
||||||
|
archiveClassifier.set("sources")
|
||||||
|
from(sourceSets.main.map { it.allSource })
|
||||||
|
}
|
||||||
|
|
||||||
|
register<Jar>("javadocJar") {
|
||||||
|
archiveClassifier.set("javadoc")
|
||||||
|
from(javadoc.map { it.destinationDir!! })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (JavaVersion.current().toString() != "21") {
|
||||||
|
System.err.println()
|
||||||
|
System.err.println("=========================================================================================================")
|
||||||
|
System.err.println("You must run gradle on Java 21. You are using " + JavaVersion.current())
|
||||||
|
System.err.println()
|
||||||
|
System.err.println("=== For IDEs ===")
|
||||||
|
System.err.println("1. Configure the project for Java 21")
|
||||||
|
System.err.println("2. Configure the bundled gradle to use Java 21 in settings")
|
||||||
|
System.err.println()
|
||||||
|
System.err.println("=== For Command Line (gradlew) ===")
|
||||||
|
System.err.println("1. Install JDK 21 from https://www.oracle.com/java/technologies/javase/jdk21-archive-downloads.html")
|
||||||
|
System.err.println("2. Set JAVA_HOME environment variable to the new jdk installation folder such as C:\\Program Files\\Java\\jdk-21.0.4")
|
||||||
|
System.err.println("3. Open a new command prompt window to get the new environment variables if need be.")
|
||||||
|
System.err.println("=========================================================================================================")
|
||||||
|
System.err.println()
|
||||||
|
exitProcess(69)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun registerCustomOutputTask(name: String, path: String) {
|
||||||
|
if (!System.getProperty("os.name").lowercase().contains("windows")) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.register<Copy>("build$name") {
|
||||||
|
group = "development"
|
||||||
|
outputs.upToDateWhen { false }
|
||||||
|
dependsOn("iris")
|
||||||
|
from(layout.buildDirectory.file("Iris-${project.version}.jar"))
|
||||||
|
into(file(path))
|
||||||
|
rename { "Iris.jar" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun registerCustomOutputTaskUnix(name: String, path: String) {
|
||||||
|
if (System.getProperty("os.name").lowercase().contains("windows")) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.register<Copy>("build$name") {
|
||||||
|
group = "development"
|
||||||
|
outputs.upToDateWhen { false }
|
||||||
|
dependsOn("iris")
|
||||||
|
from(layout.buildDirectory.file("Iris-${project.version}.jar"))
|
||||||
|
into(file(path))
|
||||||
|
rename { "Iris.jar" }
|
||||||
|
}
|
||||||
|
}
|
||||||
11
buildSrc/build.gradle.kts
Normal file
11
buildSrc/build.gradle.kts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
plugins {
|
||||||
|
kotlin("jvm") version "2.0.20"
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation("org.ow2.asm:asm:9.8")
|
||||||
|
}
|
||||||
121
buildSrc/src/main/kotlin/ApiGenerator.kt
Normal file
121
buildSrc/src/main/kotlin/ApiGenerator.kt
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
import org.gradle.api.DefaultTask
|
||||||
|
import org.gradle.api.Plugin
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.api.publish.PublishingExtension
|
||||||
|
import org.gradle.api.publish.maven.MavenPublication
|
||||||
|
import org.gradle.api.tasks.InputFile
|
||||||
|
import org.gradle.api.tasks.OutputFile
|
||||||
|
import org.gradle.api.tasks.TaskAction
|
||||||
|
import org.gradle.jvm.tasks.Jar
|
||||||
|
import org.objectweb.asm.*
|
||||||
|
import java.io.File
|
||||||
|
import java.util.jar.JarFile
|
||||||
|
import java.util.jar.JarOutputStream
|
||||||
|
|
||||||
|
class ApiGenerator : Plugin<Project> {
|
||||||
|
override fun apply(target: Project): Unit = with(target) {
|
||||||
|
plugins.apply("maven-publish")
|
||||||
|
val task = tasks.register("irisApi", GenerateApiTask::class.java)
|
||||||
|
extensions.findByType(PublishingExtension::class.java)!!.apply {
|
||||||
|
repositories.maven {
|
||||||
|
it.name = "deployDir"
|
||||||
|
it.url = targetDirectory.toURI()
|
||||||
|
}
|
||||||
|
|
||||||
|
publications.create("maven", MavenPublication::class.java) {
|
||||||
|
it.groupId = name
|
||||||
|
it.version = version.toString()
|
||||||
|
it.artifact(task)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class GenerateApiTask : DefaultTask() {
|
||||||
|
init {
|
||||||
|
group = "iris"
|
||||||
|
dependsOn("jar")
|
||||||
|
finalizedBy("publishMavenPublicationToDeployDirRepository")
|
||||||
|
doLast {
|
||||||
|
logger.lifecycle("The API is located at ${outputFile.absolutePath}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@InputFile
|
||||||
|
val inputFile: File = project.tasks
|
||||||
|
.named("jar", Jar::class.java)
|
||||||
|
.get()
|
||||||
|
.archiveFile
|
||||||
|
.get()
|
||||||
|
.asFile
|
||||||
|
|
||||||
|
@OutputFile
|
||||||
|
val outputFile: File = project.targetDirectory.resolve(inputFile.name)
|
||||||
|
|
||||||
|
@TaskAction
|
||||||
|
fun generate() {
|
||||||
|
JarFile(inputFile).use { jar ->
|
||||||
|
JarOutputStream(outputFile.apply { parentFile?.mkdirs() }.outputStream()).use { out ->
|
||||||
|
jar.stream()
|
||||||
|
.parallel()
|
||||||
|
.filter { !it.isDirectory }
|
||||||
|
.filter { it.name.endsWith(".class") }
|
||||||
|
.forEach {
|
||||||
|
val bytes = jar.getInputStream(it).use { input ->
|
||||||
|
val writer = ClassWriter(ClassWriter.COMPUTE_MAXS)
|
||||||
|
val visitor = MethodClearingVisitor(writer)
|
||||||
|
ClassReader(input).accept(visitor, 0)
|
||||||
|
writer.toByteArray()
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized(out) {
|
||||||
|
out.putNextEntry(it)
|
||||||
|
out.write(bytes)
|
||||||
|
out.closeEntry()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val Project.targetDirectory: File get() {
|
||||||
|
val dir = System.getenv("DEPLOY_DIR") ?: return project.layout.buildDirectory.dir("api").get().asFile
|
||||||
|
return File(dir)
|
||||||
|
}
|
||||||
|
|
||||||
|
private class MethodClearingVisitor(
|
||||||
|
cv: ClassVisitor
|
||||||
|
) : ClassVisitor(Opcodes.ASM9, cv) {
|
||||||
|
|
||||||
|
override fun visitMethod(
|
||||||
|
access: Int,
|
||||||
|
name: String?,
|
||||||
|
descriptor: String?,
|
||||||
|
signature: String?,
|
||||||
|
exceptions: Array<out String>?
|
||||||
|
) = ExceptionThrowingMethodVisitor(super.visitMethod(access, name, descriptor, signature, exceptions))
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ExceptionThrowingMethodVisitor(
|
||||||
|
mv: MethodVisitor
|
||||||
|
) : MethodVisitor(Opcodes.ASM9, mv) {
|
||||||
|
|
||||||
|
override fun visitCode() {
|
||||||
|
if (mv == null) return
|
||||||
|
mv.visitCode()
|
||||||
|
|
||||||
|
mv.visitTypeInsn(Opcodes.NEW, "java/lang/IllegalStateException")
|
||||||
|
mv.visitInsn(Opcodes.DUP)
|
||||||
|
mv.visitLdcInsn("Only API")
|
||||||
|
mv.visitMethodInsn(
|
||||||
|
Opcodes.INVOKESPECIAL,
|
||||||
|
"java/lang/IllegalStateException",
|
||||||
|
"<init>", "(Ljava/lang/String;)V", false
|
||||||
|
)
|
||||||
|
mv.visitInsn(Opcodes.ATHROW)
|
||||||
|
|
||||||
|
mv.visitMaxs(0, 0)
|
||||||
|
mv.visitEnd()
|
||||||
|
}
|
||||||
|
}
|
||||||
12
core/agent/build.gradle.kts
Normal file
12
core/agent/build.gradle.kts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
plugins {
|
||||||
|
java
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.jar {
|
||||||
|
manifest.attributes(
|
||||||
|
"Agent-Class" to "com.volmit.iris.util.agent.Installer",
|
||||||
|
"Premain-Class" to "com.volmit.iris.util.agent.Installer",
|
||||||
|
"Can-Redefine-Classes" to true,
|
||||||
|
"Can-Retransform-Classes" to true
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package com.volmit.iris.util.agent;
|
||||||
|
|
||||||
|
import java.lang.instrument.Instrumentation;
|
||||||
|
|
||||||
|
public class Installer {
|
||||||
|
private static volatile Instrumentation instrumentation;
|
||||||
|
|
||||||
|
public static Instrumentation getInstrumentation() {
|
||||||
|
Instrumentation instrumentation = Installer.instrumentation;
|
||||||
|
if (instrumentation == null) {
|
||||||
|
throw new IllegalStateException("The agent is not loaded or this method is not called via the system class loader");
|
||||||
|
}
|
||||||
|
return instrumentation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void premain(String arguments, Instrumentation instrumentation) {
|
||||||
|
doMain(instrumentation);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void agentmain(String arguments, Instrumentation instrumentation) {
|
||||||
|
doMain(instrumentation);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static synchronized void doMain(Instrumentation instrumentation) {
|
||||||
|
if (Installer.instrumentation != null)
|
||||||
|
return;
|
||||||
|
Installer.instrumentation = instrumentation;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
/*
|
|
||||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
|
||||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
plugins {
|
|
||||||
id 'java'
|
|
||||||
id 'java-library'
|
|
||||||
id "io.freefair.lombok" version "8.6"
|
|
||||||
}
|
|
||||||
|
|
||||||
def apiVersion = '1.19'
|
|
||||||
def main = 'com.volmit.iris.Iris'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* We need parameter meta for the decree command system
|
|
||||||
*/
|
|
||||||
compileJava {
|
|
||||||
options.compilerArgs << '-parameters'
|
|
||||||
options.encoding = "UTF-8"
|
|
||||||
}
|
|
||||||
|
|
||||||
repositories {
|
|
||||||
maven { url 'https://nexus.phoenixdevt.fr/repository/maven-public/'}
|
|
||||||
maven { url 'https://repo.auxilor.io/repository/maven-public/' }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dependencies.
|
|
||||||
*
|
|
||||||
* Provided or classpath dependencies are not shaded and are available on the runtime classpath
|
|
||||||
*
|
|
||||||
* Shaded dependencies are not available at runtime, nor are they available on mvn central so they
|
|
||||||
* need to be shaded into the jar (increasing binary size)
|
|
||||||
*
|
|
||||||
* Dynamically loaded dependencies are defined in the plugin.yml (updating these must be updated in the
|
|
||||||
* plugin.yml also, otherwise they wont be available). These do not increase binary size). Only declare
|
|
||||||
* these dependencies if they are available on mvn central.
|
|
||||||
*/
|
|
||||||
dependencies {
|
|
||||||
// Provided or Classpath
|
|
||||||
compileOnly 'org.spigotmc:spigot-api:1.20.1-R0.1-SNAPSHOT'
|
|
||||||
compileOnly 'org.apache.logging.log4j:log4j-api:2.19.0'
|
|
||||||
compileOnly 'org.apache.logging.log4j:log4j-core:2.19.0'
|
|
||||||
compileOnly 'commons-io:commons-io:2.13.0'
|
|
||||||
compileOnly 'commons-lang:commons-lang:2.6'
|
|
||||||
compileOnly 'com.github.oshi:oshi-core:5.8.5'
|
|
||||||
compileOnly 'org.lz4:lz4-java:1.8.0'
|
|
||||||
|
|
||||||
// Third Party Integrations
|
|
||||||
compileOnly 'com.ticxo.playeranimator:PlayerAnimator:R1.2.7'
|
|
||||||
compileOnly 'com.nexomc:nexo:1.0.0-dev.38'
|
|
||||||
compileOnly 'com.github.LoneDev6:api-itemsadder:3.4.1-r4'
|
|
||||||
compileOnly 'com.github.PlaceholderAPI:placeholderapi:2.11.3'
|
|
||||||
compileOnly 'com.github.Ssomar-Developement:SCore:4.23.10.8'
|
|
||||||
compileOnly 'net.Indyuce:MMOItems-API:6.9.5-SNAPSHOT'
|
|
||||||
compileOnly 'com.willfp:EcoItems:5.44.0'
|
|
||||||
//implementation files('libs/CustomItems.jar')
|
|
||||||
}
|
|
||||||
|
|
||||||
java {
|
|
||||||
disableAutoTargetJvm()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gradle is weird sometimes, we need to delete the plugin yml from the build folder to actually filter properly.
|
|
||||||
*/
|
|
||||||
file(jar.archiveFile.get().getAsFile().getParentFile().getParentFile().getParentFile().getAbsolutePath() + '/build/resources/main/plugin.yml').delete()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Expand properties into plugin yml
|
|
||||||
*/
|
|
||||||
processResources {
|
|
||||||
filesMatching('**/plugin.yml') {
|
|
||||||
expand(
|
|
||||||
'name': rootProject.name.toString(),
|
|
||||||
'version': rootProject.version.toString(),
|
|
||||||
'main': main.toString(),
|
|
||||||
'apiversion': apiVersion.toString()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
196
core/build.gradle.kts
Normal file
196
core/build.gradle.kts
Normal file
@@ -0,0 +1,196 @@
|
|||||||
|
import io.github.slimjar.func.slimjarHelper
|
||||||
|
import io.github.slimjar.resolver.data.Mirror
|
||||||
|
import org.ajoberstar.grgit.Grgit
|
||||||
|
import java.net.URI
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||||
|
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
java
|
||||||
|
`java-library`
|
||||||
|
alias(libs.plugins.shadow)
|
||||||
|
alias(libs.plugins.sentry)
|
||||||
|
alias(libs.plugins.slimjar)
|
||||||
|
alias(libs.plugins.grgit)
|
||||||
|
alias(libs.plugins.kotlin.jvm)
|
||||||
|
alias(libs.plugins.kotlin.lombok)
|
||||||
|
}
|
||||||
|
|
||||||
|
val apiVersion = "1.19"
|
||||||
|
val main = "com.volmit.iris.Iris"
|
||||||
|
val lib = "com.volmit.iris.util"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dependencies.
|
||||||
|
*
|
||||||
|
* Provided or classpath dependencies are not shaded and are available on the runtime classpath
|
||||||
|
*
|
||||||
|
* Shaded dependencies are not available at runtime, nor are they available on mvn central so they
|
||||||
|
* need to be shaded into the jar (increasing binary size)
|
||||||
|
*
|
||||||
|
* Dynamically loaded dependencies are defined in the plugin.yml (updating these must be updated in the
|
||||||
|
* plugin.yml also, otherwise they wont be available). These do not increase binary size). Only declare
|
||||||
|
* these dependencies if they are available on mvn central.
|
||||||
|
*/
|
||||||
|
dependencies {
|
||||||
|
// Provided or Classpath
|
||||||
|
compileOnly(libs.spigot)
|
||||||
|
compileOnly(libs.log4j.api)
|
||||||
|
compileOnly(libs.log4j.core)
|
||||||
|
|
||||||
|
// Third Party Integrations
|
||||||
|
compileOnly(libs.nexo)
|
||||||
|
compileOnly(libs.itemsadder)
|
||||||
|
compileOnly(libs.placeholderApi)
|
||||||
|
compileOnly(libs.score)
|
||||||
|
compileOnly(libs.mmoitems)
|
||||||
|
compileOnly(libs.ecoitems)
|
||||||
|
compileOnly(libs.mythic)
|
||||||
|
compileOnly(libs.mythicChrucible)
|
||||||
|
compileOnly(libs.kgenerators) {
|
||||||
|
isTransitive = false
|
||||||
|
}
|
||||||
|
compileOnly(libs.multiverseCore)
|
||||||
|
compileOnly(libs.craftengine.core)
|
||||||
|
compileOnly(libs.craftengine.bukkit)
|
||||||
|
//compileOnly(libs.sparrowNbt)
|
||||||
|
|
||||||
|
// Shaded
|
||||||
|
implementation(slimjarHelper("spigot"))
|
||||||
|
|
||||||
|
// Dynamically Loaded
|
||||||
|
slim(libs.paralithic)
|
||||||
|
slim(libs.paperlib)
|
||||||
|
slim(libs.adventure.api)
|
||||||
|
slim(libs.adventure.minimessage)
|
||||||
|
slim(libs.adventure.platform)
|
||||||
|
slim(libs.bstats)
|
||||||
|
slim(libs.sentry)
|
||||||
|
|
||||||
|
slim(libs.commons.io)
|
||||||
|
slim(libs.commons.lang)
|
||||||
|
slim(libs.commons.lang3)
|
||||||
|
slim(libs.commons.math3)
|
||||||
|
slim(libs.oshi)
|
||||||
|
slim(libs.lz4)
|
||||||
|
slim(libs.fastutil)
|
||||||
|
slim(libs.lru)
|
||||||
|
slim(libs.zip)
|
||||||
|
slim(libs.gson)
|
||||||
|
slim(libs.asm)
|
||||||
|
slim(libs.caffeine)
|
||||||
|
slim(libs.byteBuddy.core)
|
||||||
|
slim(libs.byteBuddy.agent)
|
||||||
|
slim(libs.dom4j)
|
||||||
|
slim(libs.jaxen)
|
||||||
|
|
||||||
|
// Script Engine
|
||||||
|
slim(libs.kotlin.stdlib)
|
||||||
|
slim(libs.kotlin.coroutines)
|
||||||
|
slim(libs.kotlin.scripting.common)
|
||||||
|
slim(libs.kotlin.scripting.jvm)
|
||||||
|
slim(libs.kotlin.scripting.jvm.host)
|
||||||
|
slim(libs.kotlin.scripting.dependencies.maven) {
|
||||||
|
constraints {
|
||||||
|
slim(libs.mavenCore)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
java {
|
||||||
|
disableAutoTargetJvm()
|
||||||
|
}
|
||||||
|
|
||||||
|
sentry {
|
||||||
|
url = "http://sentry.volmit.com:8080/"
|
||||||
|
autoInstallation.enabled = false
|
||||||
|
includeSourceContext = true
|
||||||
|
|
||||||
|
org = "sentry"
|
||||||
|
projectName = "iris"
|
||||||
|
authToken = findProperty("sentry.auth.token") as String? ?: System.getenv("SENTRY_AUTH_TOKEN")
|
||||||
|
}
|
||||||
|
|
||||||
|
slimJar {
|
||||||
|
mirrors = listOf(Mirror(
|
||||||
|
URI.create("https://maven-central.storage-download.googleapis.com/maven2").toURL(),
|
||||||
|
URI.create("https://repo.maven.apache.org/maven2/").toURL()
|
||||||
|
))
|
||||||
|
|
||||||
|
relocate("com.dfsek.paralithic", "$lib.paralithic")
|
||||||
|
relocate("io.papermc.lib", "$lib.paper")
|
||||||
|
relocate("net.kyori", "$lib.kyori")
|
||||||
|
relocate("org.bstats", "$lib.metrics")
|
||||||
|
relocate("io.sentry", "$lib.sentry")
|
||||||
|
relocate("org.apache.maven", "$lib.maven")
|
||||||
|
relocate("org.codehaus.plexus", "$lib.plexus")
|
||||||
|
relocate("org.eclipse.sisu", "$lib.sisu")
|
||||||
|
relocate("org.eclipse.aether", "$lib.aether")
|
||||||
|
relocate("com.google.inject", "$lib.guice")
|
||||||
|
relocate("org.dom4j", "$lib.dom4j")
|
||||||
|
relocate("org.jaxen", "$lib.jaxen")
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks {
|
||||||
|
/**
|
||||||
|
* We need parameter meta for the decree command system
|
||||||
|
*/
|
||||||
|
compileJava {
|
||||||
|
options.compilerArgs.add("-parameters")
|
||||||
|
options.encoding = "UTF-8"
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expand properties into plugin yml
|
||||||
|
*/
|
||||||
|
processResources {
|
||||||
|
inputs.properties(
|
||||||
|
"name" to rootProject.name,
|
||||||
|
"version" to rootProject.version,
|
||||||
|
"apiVersion" to apiVersion,
|
||||||
|
"main" to main,
|
||||||
|
"environment" to if (project.hasProperty("release")) "production" else "development",
|
||||||
|
"commit" to provider {
|
||||||
|
val res = runCatching { project.extensions.getByType<Grgit>().head().id }
|
||||||
|
res.getOrDefault("")
|
||||||
|
.takeIf { it.length == 40 } ?: {
|
||||||
|
logger.error("Git commit hash not found", res.exceptionOrNull())
|
||||||
|
"unknown"
|
||||||
|
}()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
filesMatching("**/plugin.yml") {
|
||||||
|
expand(inputs.properties)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
shadowJar {
|
||||||
|
mergeServiceFiles()
|
||||||
|
//minimize()
|
||||||
|
relocate("io.github.slimjar", "$lib.slimjar")
|
||||||
|
exclude("modules/loader-agent.isolated-jar")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gradle is weird sometimes, we need to delete the plugin yml from the build folder to actually filter properly.
|
||||||
|
*/
|
||||||
|
afterEvaluate {
|
||||||
|
layout.buildDirectory.file("resources/main/plugin.yml").get().asFile.delete()
|
||||||
|
}
|
||||||
@@ -22,26 +22,22 @@ import com.google.gson.JsonObject;
|
|||||||
import com.google.gson.JsonParseException;
|
import com.google.gson.JsonParseException;
|
||||||
import com.google.gson.JsonParser;
|
import com.google.gson.JsonParser;
|
||||||
import com.volmit.iris.core.IrisSettings;
|
import com.volmit.iris.core.IrisSettings;
|
||||||
|
import com.volmit.iris.core.IrisWorlds;
|
||||||
import com.volmit.iris.core.ServerConfigurator;
|
import com.volmit.iris.core.ServerConfigurator;
|
||||||
import com.volmit.iris.core.link.IrisPapiExpansion;
|
import com.volmit.iris.core.link.IrisPapiExpansion;
|
||||||
import com.volmit.iris.core.link.MultiverseCoreLink;
|
import com.volmit.iris.core.link.MultiverseCoreLink;
|
||||||
import com.volmit.iris.core.link.MythicMobsLink;
|
|
||||||
import com.volmit.iris.core.loader.IrisData;
|
import com.volmit.iris.core.loader.IrisData;
|
||||||
import com.volmit.iris.core.nms.INMS;
|
import com.volmit.iris.core.nms.INMS;
|
||||||
import com.volmit.iris.core.nms.v1X.NMSBinding1X;
|
import com.volmit.iris.core.nms.v1X.NMSBinding1X;
|
||||||
import com.volmit.iris.core.pregenerator.LazyPregenerator;
|
import com.volmit.iris.core.pregenerator.LazyPregenerator;
|
||||||
import com.volmit.iris.core.service.StudioSVC;
|
import com.volmit.iris.core.service.StudioSVC;
|
||||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||||
import com.volmit.iris.core.tools.IrisWorldCreator;
|
|
||||||
import com.volmit.iris.engine.EnginePanic;
|
import com.volmit.iris.engine.EnginePanic;
|
||||||
import com.volmit.iris.engine.object.IrisCompat;
|
import com.volmit.iris.engine.object.IrisCompat;
|
||||||
import com.volmit.iris.engine.object.IrisContextInjector;
|
|
||||||
import com.volmit.iris.engine.object.IrisDimension;
|
import com.volmit.iris.engine.object.IrisDimension;
|
||||||
import com.volmit.iris.engine.object.IrisWorld;
|
import com.volmit.iris.engine.object.IrisWorld;
|
||||||
import com.volmit.iris.engine.platform.BukkitChunkGenerator;
|
import com.volmit.iris.engine.platform.BukkitChunkGenerator;
|
||||||
import com.volmit.iris.engine.platform.DummyChunkGenerator;
|
|
||||||
import com.volmit.iris.core.safeguard.IrisSafeguard;
|
import com.volmit.iris.core.safeguard.IrisSafeguard;
|
||||||
import com.volmit.iris.core.safeguard.UtilsSFG;
|
|
||||||
import com.volmit.iris.engine.platform.PlatformChunkGenerator;
|
import com.volmit.iris.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;
|
||||||
@@ -55,29 +51,21 @@ import com.volmit.iris.util.io.InstanceState;
|
|||||||
import com.volmit.iris.util.io.JarScanner;
|
import com.volmit.iris.util.io.JarScanner;
|
||||||
import com.volmit.iris.util.math.M;
|
import com.volmit.iris.util.math.M;
|
||||||
import com.volmit.iris.util.math.RNG;
|
import com.volmit.iris.util.math.RNG;
|
||||||
|
import com.volmit.iris.util.misc.Bindings;
|
||||||
|
import com.volmit.iris.util.misc.SlimJar;
|
||||||
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.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.scheduling.J;
|
import com.volmit.iris.util.scheduling.J;
|
||||||
import com.volmit.iris.util.scheduling.Queue;
|
import com.volmit.iris.util.scheduling.Queue;
|
||||||
import com.volmit.iris.util.scheduling.ShurikenQueue;
|
import com.volmit.iris.util.scheduling.ShurikenQueue;
|
||||||
import io.papermc.lib.PaperLib;
|
import lombok.NonNull;
|
||||||
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
|
|
||||||
import net.kyori.adventure.text.serializer.ComponentSerializer;
|
|
||||||
import org.bstats.bukkit.Metrics;
|
|
||||||
import org.bstats.charts.DrilldownPie;
|
|
||||||
import org.bstats.charts.SimplePie;
|
|
||||||
import org.bstats.charts.SingleLineChart;
|
|
||||||
import org.bukkit.*;
|
import org.bukkit.*;
|
||||||
import org.bukkit.block.data.BlockData;
|
import org.bukkit.block.data.BlockData;
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.configuration.ConfigurationSection;
|
|
||||||
import org.bukkit.configuration.file.FileConfiguration;
|
|
||||||
import org.bukkit.configuration.file.YamlConfiguration;
|
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.*;
|
import org.bukkit.event.*;
|
||||||
import org.bukkit.generator.BiomeProvider;
|
import org.bukkit.generator.BiomeProvider;
|
||||||
@@ -86,17 +74,14 @@ import org.bukkit.plugin.IllegalPluginAccessException;
|
|||||||
import org.bukkit.plugin.Plugin;
|
import org.bukkit.plugin.Plugin;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import oshi.SystemInfo;
|
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
import java.math.RoundingMode;
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.text.NumberFormat;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.function.Predicate;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import static com.volmit.iris.core.safeguard.IrisSafeguard.*;
|
import static com.volmit.iris.core.safeguard.IrisSafeguard.*;
|
||||||
import static com.volmit.iris.core.safeguard.ServerBootSFG.passedserversoftware;
|
import static com.volmit.iris.core.safeguard.ServerBootSFG.passedserversoftware;
|
||||||
@@ -106,16 +91,15 @@ public class Iris extends VolmitPlugin implements Listener {
|
|||||||
private static final Queue<Runnable> syncJobs = new ShurikenQueue<>();
|
private static final Queue<Runnable> syncJobs = new ShurikenQueue<>();
|
||||||
|
|
||||||
public static Iris instance;
|
public static Iris instance;
|
||||||
public static BukkitAudiences audiences;
|
public static Bindings.Adventure audiences;
|
||||||
public static MultiverseCoreLink linkMultiverseCore;
|
public static MultiverseCoreLink linkMultiverseCore;
|
||||||
public static MythicMobsLink linkMythicMobs;
|
|
||||||
public static IrisCompat compat;
|
public static IrisCompat compat;
|
||||||
public static FileWatcher configWatcher;
|
public static FileWatcher configWatcher;
|
||||||
private static VolmitSender sender;
|
private static VolmitSender sender;
|
||||||
|
private static Thread shutdownHook;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
try {
|
try {
|
||||||
fixShading();
|
|
||||||
InstanceState.updateInstanceId();
|
InstanceState.updateInstanceId();
|
||||||
} catch (Throwable ignored) {
|
} catch (Throwable ignored) {
|
||||||
|
|
||||||
@@ -392,6 +376,7 @@ public class Iris extends VolmitPlugin implements Listener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void reportError(Throwable e) {
|
public static void reportError(Throwable e) {
|
||||||
|
Bindings.capture(e);
|
||||||
if (IrisSettings.get().getGeneral().isDebug()) {
|
if (IrisSettings.get().getGeneral().isDebug()) {
|
||||||
String n = e.getClass().getCanonicalName() + "-" + e.getStackTrace()[0].getClassName() + "-" + e.getStackTrace()[0].getLineNumber();
|
String n = e.getClass().getCanonicalName() + "-" + e.getStackTrace()[0].getClassName() + "-" + e.getStackTrace()[0].getLineNumber();
|
||||||
|
|
||||||
@@ -449,29 +434,29 @@ public class Iris extends VolmitPlugin implements Listener {
|
|||||||
EnginePanic.add(s, v);
|
EnginePanic.add(s, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void fixShading() {
|
public Iris() {
|
||||||
ShadeFix.fix(ComponentSerializer.class);
|
|
||||||
}
|
|
||||||
private void enable() {
|
|
||||||
instance = this;
|
instance = this;
|
||||||
|
SlimJar.load();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void enable() {
|
||||||
services = new KMap<>();
|
services = new KMap<>();
|
||||||
setupAudience();
|
setupAudience();
|
||||||
|
Bindings.setupSentry();
|
||||||
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();
|
|
||||||
IO.delete(new File("iris"));
|
IO.delete(new File("iris"));
|
||||||
compat = IrisCompat.configured(getDataFile("compat.json"));
|
compat = IrisCompat.configured(getDataFile("compat.json"));
|
||||||
ServerConfigurator.configure();
|
ServerConfigurator.configure();
|
||||||
new IrisContextInjector();
|
|
||||||
IrisSafeguard.IrisSafeguardSystem();
|
IrisSafeguard.IrisSafeguardSystem();
|
||||||
getSender().setTag(getTag());
|
getSender().setTag(getTag());
|
||||||
IrisSafeguard.earlySplash();
|
IrisSafeguard.splash(true);
|
||||||
linkMultiverseCore = new MultiverseCoreLink();
|
linkMultiverseCore = new MultiverseCoreLink();
|
||||||
linkMythicMobs = new MythicMobsLink();
|
|
||||||
configWatcher = new FileWatcher(getDataFile("settings.json"));
|
configWatcher = new FileWatcher(getDataFile("settings.json"));
|
||||||
services.values().forEach(IrisService::onEnable);
|
services.values().forEach(IrisService::onEnable);
|
||||||
services.values().forEach(this::registerListener);
|
services.values().forEach(this::registerListener);
|
||||||
|
addShutdownHook();
|
||||||
J.s(() -> {
|
J.s(() -> {
|
||||||
J.a(() -> PaperLib.suggestPaper(this));
|
J.a(IrisSafeguard::suggestPaper);
|
||||||
J.a(() -> IO.delete(getTemp()));
|
J.a(() -> IO.delete(getTemp()));
|
||||||
J.a(LazyPregenerator::loadLazyGenerators, 100);
|
J.a(LazyPregenerator::loadLazyGenerators, 100);
|
||||||
J.a(this::bstats);
|
J.a(this::bstats);
|
||||||
@@ -479,54 +464,58 @@ public class Iris extends VolmitPlugin implements Listener {
|
|||||||
J.sr(this::tickQueue, 0);
|
J.sr(this::tickQueue, 0);
|
||||||
J.s(this::setupPapi);
|
J.s(this::setupPapi);
|
||||||
J.a(ServerConfigurator::configure, 20);
|
J.a(ServerConfigurator::configure, 20);
|
||||||
splash();
|
IrisSafeguard.splash(false);
|
||||||
UtilsSFG.splash();
|
|
||||||
|
|
||||||
autoStartStudio();
|
autoStartStudio();
|
||||||
checkForBukkitWorlds();
|
checkForBukkitWorlds(s -> true);
|
||||||
IrisToolbelt.retainMantleDataForSlice(String.class.getCanonicalName());
|
IrisToolbelt.retainMantleDataForSlice(String.class.getCanonicalName());
|
||||||
IrisToolbelt.retainMantleDataForSlice(BlockData.class.getCanonicalName());
|
IrisToolbelt.retainMantleDataForSlice(BlockData.class.getCanonicalName());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkForBukkitWorlds() {
|
public void addShutdownHook() {
|
||||||
FileConfiguration fc = new YamlConfiguration();
|
if (shutdownHook != null) {
|
||||||
|
Runtime.getRuntime().removeShutdownHook(shutdownHook);
|
||||||
|
}
|
||||||
|
shutdownHook = new Thread(() -> {
|
||||||
|
Bukkit.getWorlds()
|
||||||
|
.stream()
|
||||||
|
.map(IrisToolbelt::access)
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.forEach(PlatformChunkGenerator::close);
|
||||||
|
|
||||||
|
MultiBurst.burst.close();
|
||||||
|
MultiBurst.ioBurst.close();
|
||||||
|
services.clear();
|
||||||
|
});
|
||||||
|
Runtime.getRuntime().addShutdownHook(shutdownHook);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void checkForBukkitWorlds(Predicate<String> filter) {
|
||||||
try {
|
try {
|
||||||
fc.load(new File("bukkit.yml"));
|
IrisWorlds.readBukkitWorlds().forEach((s, generator) -> {
|
||||||
ConfigurationSection section = fc.getConfigurationSection("worlds");
|
try {
|
||||||
if (section == null) {
|
if (Bukkit.getWorld(s) != null || !filter.test(s)) return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (String s : section.getKeys(false)) {
|
Iris.info("Loading World: %s | Generator: %s", s, generator);
|
||||||
ConfigurationSection entry = section.getConfigurationSection(s);
|
var gen = getDefaultWorldGenerator(s, generator);
|
||||||
if (!entry.contains("generator", true)) {
|
var dim = loadDimension(s, generator);
|
||||||
continue;
|
assert dim != null && gen != null;
|
||||||
|
|
||||||
|
Iris.info(C.LIGHT_PURPLE + "Preparing Spawn for " + s + "' using Iris:" + generator + "...");
|
||||||
|
WorldCreator c = new WorldCreator(s)
|
||||||
|
.generator(gen)
|
||||||
|
.environment(dim.getEnvironment());
|
||||||
|
INMS.get().createWorld(c);
|
||||||
|
Iris.info(C.LIGHT_PURPLE + "Loaded " + s + "!");
|
||||||
|
} catch (Throwable e) {
|
||||||
|
Iris.error("Failed to load world " + s + "!");
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
});
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Bukkit.getWorld(s) != null)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
Iris.info("Loading World: %s | Generator: %s", s, generator);
|
|
||||||
|
|
||||||
Iris.info(C.LIGHT_PURPLE + "Preparing Spawn for " + s + "' using Iris:" + generator + "...");
|
|
||||||
WorldCreator c = new WorldCreator(s)
|
|
||||||
.generator(getDefaultWorldGenerator(s, generator))
|
|
||||||
.environment(IrisData.loadAnyDimension(generator).getEnvironment());
|
|
||||||
INMS.get().createWorld(c);
|
|
||||||
Iris.info(C.LIGHT_PURPLE + "Loaded " + s + "!");
|
|
||||||
}
|
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
reportError(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -544,14 +533,14 @@ public class Iris extends VolmitPlugin implements Listener {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
} catch (IrisException e) {
|
} catch (IrisException e) {
|
||||||
e.printStackTrace();
|
reportError(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupAudience() {
|
private void setupAudience() {
|
||||||
try {
|
try {
|
||||||
audiences = BukkitAudiences.create(this);
|
audiences = new Bindings.Adventure(this);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
IrisSettings.get().getGeneral().setUseConsoleCustomColors(false);
|
IrisSettings.get().getGeneral().setUseConsoleCustomColors(false);
|
||||||
@@ -576,9 +565,9 @@ public class Iris extends VolmitPlugin implements Listener {
|
|||||||
Bukkit.getScheduler().cancelTasks(this);
|
Bukkit.getScheduler().cancelTasks(this);
|
||||||
HandlerList.unregisterAll((Plugin) this);
|
HandlerList.unregisterAll((Plugin) this);
|
||||||
postShutdown.forEach(Runnable::run);
|
postShutdown.forEach(Runnable::run);
|
||||||
services.clear();
|
|
||||||
MultiBurst.burst.close();
|
|
||||||
super.onDisable();
|
super.onDisable();
|
||||||
|
|
||||||
|
J.attempt(new JarScanner(instance.getJarFile(), "", false)::scanAll);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupPapi() {
|
private void setupPapi() {
|
||||||
@@ -624,12 +613,22 @@ public class Iris extends VolmitPlugin implements Listener {
|
|||||||
Iris.warn("=");
|
Iris.warn("=");
|
||||||
Iris.warn("============================================");
|
Iris.warn("============================================");
|
||||||
}
|
}
|
||||||
if (!instance.getServer().getVersion().contains("Purpur")) {
|
|
||||||
passed = false;
|
try {
|
||||||
|
Class.forName("io.papermc.paper.configuration.PaperConfigurations");
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
Iris.info(C.RED + "Iris requires paper or above to function properly..");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Class.forName("org.purpurmc.purpur.PurpurConfig");
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
Iris.info("We recommend using Purpur for the best experience with Iris.");
|
Iris.info("We recommend using Purpur for the best experience with Iris.");
|
||||||
Iris.info("Purpur is a fork of Paper that is optimized for performance and stability.");
|
Iris.info("Purpur is a fork of Paper that is optimized for performance and stability.");
|
||||||
Iris.info("Plugins that work on Spigot / Paper work on Purpur.");
|
Iris.info("Plugins that work on Spigot / Paper work on Purpur.");
|
||||||
Iris.info("You can download it here: https://purpurmc.org");
|
Iris.info("You can download it here: https://purpurmc.org");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
return passed;
|
return passed;
|
||||||
}
|
}
|
||||||
@@ -664,50 +663,7 @@ 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(() -> {
|
Bindings.setupBstats(this);
|
||||||
var metrics = new Metrics(Iris.instance, 24220);
|
|
||||||
metrics.addCustomChart(new SingleLineChart("custom_dimensions", () -> Bukkit.getWorlds()
|
|
||||||
.stream()
|
|
||||||
.filter(IrisToolbelt::isIrisWorld)
|
|
||||||
.mapToInt(w -> 1)
|
|
||||||
.sum()));
|
|
||||||
|
|
||||||
metrics.addCustomChart(new DrilldownPie("used_packs", () -> Bukkit.getWorlds().stream()
|
|
||||||
.map(IrisToolbelt::access)
|
|
||||||
.filter(Objects::nonNull)
|
|
||||||
.map(PlatformChunkGenerator::getEngine)
|
|
||||||
.collect(Collectors.toMap(engine -> engine.getDimension().getLoadKey(), engine -> {
|
|
||||||
var hash32 = engine.getHash32().getNow(null);
|
|
||||||
if (hash32 == null) return Map.of();
|
|
||||||
int version = engine.getDimension().getVersion();
|
|
||||||
String checksum = Long.toHexString(hash32);
|
|
||||||
|
|
||||||
return Map.of("v" + version + " (" + checksum + ")", 1);
|
|
||||||
}, (a, b) -> {
|
|
||||||
Map<String, Integer> merged = new HashMap<>(a);
|
|
||||||
b.forEach((k, v) -> merged.merge(k, v, Integer::sum));
|
|
||||||
return merged;
|
|
||||||
}))));
|
|
||||||
|
|
||||||
|
|
||||||
var info = new SystemInfo().getHardware();
|
|
||||||
var cpu = info.getProcessor().getProcessorIdentifier();
|
|
||||||
var mem = info.getMemory();
|
|
||||||
metrics.addCustomChart(new SimplePie("cpu_model", cpu::getName));
|
|
||||||
|
|
||||||
var nf = NumberFormat.getInstance(Locale.ENGLISH);
|
|
||||||
nf.setMinimumFractionDigits(0);
|
|
||||||
nf.setMaximumFractionDigits(2);
|
|
||||||
nf.setRoundingMode(RoundingMode.HALF_UP);
|
|
||||||
|
|
||||||
metrics.addCustomChart(new DrilldownPie("memory", () -> {
|
|
||||||
double total = mem.getTotal() * 1E-9;
|
|
||||||
double alloc = Math.min(total, Runtime.getRuntime().maxMemory() * 1E-9);
|
|
||||||
return Map.of(nf.format(alloc), Map.of(nf.format(total), 1));
|
|
||||||
}));
|
|
||||||
|
|
||||||
postShutdown.add(metrics::shutdown);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -730,37 +686,11 @@ public class Iris extends VolmitPlugin implements Listener {
|
|||||||
@Override
|
@Override
|
||||||
public ChunkGenerator getDefaultWorldGenerator(String worldName, String id) {
|
public ChunkGenerator getDefaultWorldGenerator(String worldName, String id) {
|
||||||
Iris.debug("Default World Generator Called for " + worldName + " using ID: " + id);
|
Iris.debug("Default World Generator Called for " + worldName + " using ID: " + id);
|
||||||
if (worldName.equals("test")) {
|
if (id == null || id.isEmpty()) id = IrisSettings.get().getGenerator().getDefaultWorldType();
|
||||||
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");
|
Iris.debug("Generator ID: " + id + " requested by bukkit/plugin");
|
||||||
|
IrisDimension dim = loadDimension(worldName, id);
|
||||||
if (dim == null) {
|
if (dim == null) {
|
||||||
Iris.warn("Unable to find dimension type " + id + " Looking for online packs...");
|
throw new RuntimeException("Can't find dimension " + id + "!");
|
||||||
|
|
||||||
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());
|
Iris.debug("Assuming IrisDimension: " + dim.getName());
|
||||||
@@ -785,6 +715,24 @@ public class Iris extends VolmitPlugin implements Listener {
|
|||||||
return new BukkitChunkGenerator(w, false, ff, dim.getLoadKey());
|
return new BukkitChunkGenerator(w, false, ff, dim.getLoadKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static IrisDimension loadDimension(@NonNull String worldName, @NonNull String id) {
|
||||||
|
var data = IrisData.get(new File(Bukkit.getWorldContainer(), String.join(File.separator, worldName, "iris", "pack")));
|
||||||
|
var dimension = data.getDimensionLoader().load(id);
|
||||||
|
if (dimension == null) dimension = IrisData.loadAnyDimension(id);
|
||||||
|
if (dimension == null) {
|
||||||
|
Iris.warn("Unable to find dimension type " + id + " Looking for online packs...");
|
||||||
|
Iris.service(StudioSVC.class).downloadSearch(new VolmitSender(Bukkit.getConsoleSender()), id, false);
|
||||||
|
dimension = IrisData.loadAnyDimension(id);
|
||||||
|
|
||||||
|
if (dimension != null) {
|
||||||
|
Iris.info("Resolved missing dimension, proceeding.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dimension;
|
||||||
|
}
|
||||||
|
|
||||||
public void splash() {
|
public void splash() {
|
||||||
if (!IrisSettings.get().getGeneral().isSplashLogoStartup()) {
|
if (!IrisSettings.get().getGeneral().isSplashLogoStartup()) {
|
||||||
return;
|
return;
|
||||||
@@ -794,7 +742,7 @@ public class Iris extends VolmitPlugin implements Listener {
|
|||||||
String padd2 = Form.repeat(" ", 4);
|
String padd2 = Form.repeat(" ", 4);
|
||||||
String[] info = {"", "", "", "", "", padd2 + C.IRIS + " Iris", padd2 + C.GRAY + " by " + "<rainbow>Volmit Software", padd2 + C.GRAY + " v" + C.IRIS + getDescription().getVersion()};
|
String[] info = {"", "", "", "", "", padd2 + C.IRIS + " Iris", padd2 + C.GRAY + " by " + "<rainbow>Volmit Software", padd2 + C.GRAY + " v" + C.IRIS + getDescription().getVersion()};
|
||||||
if (unstablemode) {
|
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) {
|
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()};
|
info = new String[]{"", "", "", "", "", padd2 + C.GOLD + " Iris", padd2 + C.GRAY + " by " + C.GOLD + "Volmit Software", padd2 + C.GRAY + " v" + C.GOLD + getDescription().getVersion()};
|
||||||
@@ -854,13 +802,6 @@ public class Iris extends VolmitPlugin implements Listener {
|
|||||||
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("Java: " + getJava());
|
||||||
if (!instance.getServer().getVersion().contains("Purpur")) {
|
|
||||||
if (instance.getServer().getVersion().contains("Spigot") && instance.getServer().getVersion().contains("Bukkit")) {
|
|
||||||
Iris.info(C.RED + " Iris requires paper or above to function properly..");
|
|
||||||
} else {
|
|
||||||
Iris.info(C.YELLOW + "Purpur is recommended to use with iris.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (getHardware.getProcessMemory() < 5999) {
|
if (getHardware.getProcessMemory() < 5999) {
|
||||||
Iris.warn("6GB+ Ram is recommended");
|
Iris.warn("6GB+ Ram is recommended");
|
||||||
Iris.warn("Process Memory: " + getHardware.getProcessMemory() + " MB");
|
Iris.warn("Process Memory: " + getHardware.getProcessMemory() + " MB");
|
||||||
|
|||||||
@@ -23,8 +23,8 @@ import com.volmit.iris.Iris;
|
|||||||
import com.volmit.iris.util.io.IO;
|
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.misc.getHardware;
|
||||||
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.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
@@ -45,13 +45,14 @@ public class IrisSettings {
|
|||||||
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();
|
private IrisSettingsUpdater updater = new IrisSettingsUpdater();
|
||||||
|
private IrisSettingsPregen pregen = new IrisSettingsPregen();
|
||||||
|
private IrisSettingsSentry sentry = new IrisSettingsSentry();
|
||||||
|
|
||||||
public static int getThreadCount(int c) {
|
public static int getThreadCount(int c) {
|
||||||
return switch (c) {
|
return Math.max(switch (c) {
|
||||||
case -1, -2, -4 -> Runtime.getRuntime().availableProcessors() / -c;
|
case -1, -2, -4 -> Runtime.getRuntime().availableProcessors() / -c;
|
||||||
case 0, 1, 2 -> 1;
|
|
||||||
default -> Math.max(c, 2);
|
default -> Math.max(c, 2);
|
||||||
};
|
}, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IrisSettings get() {
|
public static IrisSettings get() {
|
||||||
@@ -130,32 +131,58 @@ public class IrisSettings {
|
|||||||
public boolean markerEntitySpawningSystem = true;
|
public boolean markerEntitySpawningSystem = true;
|
||||||
public boolean effectSystem = true;
|
public boolean effectSystem = true;
|
||||||
public boolean worldEditWandCUI = true;
|
public boolean worldEditWandCUI = true;
|
||||||
|
public boolean globalPregenCache = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public static class IrisSettingsConcurrency {
|
public static class IrisSettingsConcurrency {
|
||||||
public int parallelism = -1;
|
public int parallelism = -1;
|
||||||
|
public int ioParallelism = -2;
|
||||||
|
public int worldGenParallelism = -1;
|
||||||
|
|
||||||
|
public int getWorldGenThreads() {
|
||||||
|
return getThreadCount(worldGenParallelism);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class IrisSettingsPregen {
|
||||||
|
public boolean useCacheByDefault = true;
|
||||||
|
public boolean useHighPriority = false;
|
||||||
|
public boolean useVirtualThreads = false;
|
||||||
|
public boolean useTicketQueue = true;
|
||||||
|
public int maxConcurrency = 256;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public static class IrisSettingsPerformance {
|
public static class IrisSettingsPerformance {
|
||||||
|
private IrisSettingsEngineSVC engineSVC = new IrisSettingsEngineSVC();
|
||||||
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;
|
||||||
public int objectLoaderCacheSize = 4_096;
|
public int objectLoaderCacheSize = 4_096;
|
||||||
public int scriptLoaderCacheSize = 512;
|
public int scriptLoaderCacheSize = 512;
|
||||||
|
public int tectonicPlateSize = -1;
|
||||||
|
public int mantleCleanupDelay = 200;
|
||||||
|
|
||||||
|
public int getTectonicPlateSize() {
|
||||||
|
if (tectonicPlateSize > 0)
|
||||||
|
return tectonicPlateSize;
|
||||||
|
|
||||||
|
return (int) (getHardware.getProcessMemory() / 200L);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public static class IrisSettingsUpdater {
|
public static class IrisSettingsUpdater {
|
||||||
public double threadMultiplier = 2;
|
public int maxConcurrency = 256;
|
||||||
public double chunkLoadSensitivity = 0.7;
|
public double chunkLoadSensitivity = 0.7;
|
||||||
public MsRange emptyMsRange = new MsRange(80, 100);
|
public MsRange emptyMsRange = new MsRange(80, 100);
|
||||||
public MsRange defaultMsRange = new MsRange(20, 40);
|
public MsRange defaultMsRange = new MsRange(20, 40);
|
||||||
|
|
||||||
public double getThreadMultiplier() {
|
public int getMaxConcurrency() {
|
||||||
return Math.min(Math.abs(threadMultiplier), 0.1);
|
return Math.max(Math.abs(maxConcurrency), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public double getChunkLoadSensitivity() {
|
public double getChunkLoadSensitivity() {
|
||||||
@@ -176,6 +203,7 @@ public class IrisSettings {
|
|||||||
public boolean DoomsdayAnnihilationSelfDestructMode = false;
|
public boolean DoomsdayAnnihilationSelfDestructMode = false;
|
||||||
public boolean commandSounds = true;
|
public boolean commandSounds = true;
|
||||||
public boolean debug = false;
|
public boolean debug = false;
|
||||||
|
public boolean dumpMantleOnError = false;
|
||||||
public boolean disableNMS = false;
|
public boolean disableNMS = false;
|
||||||
public boolean pluginMetrics = true;
|
public boolean pluginMetrics = true;
|
||||||
public boolean splashLogoStartup = true;
|
public boolean splashLogoStartup = true;
|
||||||
@@ -195,6 +223,13 @@ public class IrisSettings {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class IrisSettingsSentry {
|
||||||
|
public boolean includeServerId = true;
|
||||||
|
public boolean disableAutoReporting = false;
|
||||||
|
public boolean debug = false;
|
||||||
|
}
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public static class IrisSettingsGUI {
|
public static class IrisSettingsGUI {
|
||||||
public boolean useServerLaunchedGuis = true;
|
public boolean useServerLaunchedGuis = true;
|
||||||
@@ -207,6 +242,9 @@ public class IrisSettings {
|
|||||||
public String defaultWorldType = "overworld";
|
public String defaultWorldType = "overworld";
|
||||||
public int maxBiomeChildDepth = 4;
|
public int maxBiomeChildDepth = 4;
|
||||||
public boolean preventLeafDecay = true;
|
public boolean preventLeafDecay = true;
|
||||||
|
public boolean useMulticore = false;
|
||||||
|
public boolean offsetNoiseTypes = false;
|
||||||
|
public boolean earlyCustomBlocks = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@@ -216,4 +254,15 @@ public class IrisSettings {
|
|||||||
public boolean disableTimeAndWeather = true;
|
public boolean disableTimeAndWeather = true;
|
||||||
public boolean autoStartDefaultStudio = false;
|
public boolean autoStartDefaultStudio = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class IrisSettingsEngineSVC {
|
||||||
|
public boolean useVirtualThreads = true;
|
||||||
|
public boolean forceMulticoreWrite = false;
|
||||||
|
public int priority = Thread.NORM_PRIORITY;
|
||||||
|
|
||||||
|
public int getPriority() {
|
||||||
|
return Math.max(Math.min(priority, Thread.MAX_PRIORITY), Thread.MIN_PRIORITY);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
126
core/src/main/java/com/volmit/iris/core/IrisWorlds.java
Normal file
126
core/src/main/java/com/volmit/iris/core/IrisWorlds.java
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
package com.volmit.iris.core;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.GsonBuilder;
|
||||||
|
import com.google.gson.reflect.TypeToken;
|
||||||
|
import com.volmit.iris.Iris;
|
||||||
|
import com.volmit.iris.core.loader.IrisData;
|
||||||
|
import com.volmit.iris.engine.data.cache.AtomicCache;
|
||||||
|
import com.volmit.iris.engine.object.IrisDimension;
|
||||||
|
import com.volmit.iris.util.collection.KMap;
|
||||||
|
import com.volmit.iris.util.io.IO;
|
||||||
|
import com.volmit.iris.util.misc.ServerProperties;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStreamWriter;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
public class IrisWorlds {
|
||||||
|
private static final AtomicCache<IrisWorlds> cache = new AtomicCache<>();
|
||||||
|
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
|
||||||
|
private static final Type TYPE = TypeToken.getParameterized(KMap.class, String.class, String.class).getType();
|
||||||
|
private final KMap<String, String> worlds;
|
||||||
|
private volatile boolean dirty = false;
|
||||||
|
|
||||||
|
private IrisWorlds(KMap<String, String> worlds) {
|
||||||
|
this.worlds = worlds;
|
||||||
|
readBukkitWorlds().forEach(this::put0);
|
||||||
|
save();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IrisWorlds get() {
|
||||||
|
return cache.aquire(() -> {
|
||||||
|
File file = Iris.instance.getDataFile("worlds.json");
|
||||||
|
if (!file.exists()) {
|
||||||
|
return new IrisWorlds(new KMap<>());
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
String json = IO.readAll(file);
|
||||||
|
KMap<String, String> worlds = GSON.fromJson(json, TYPE);
|
||||||
|
return new IrisWorlds(Objects.requireNonNullElseGet(worlds, KMap::new));
|
||||||
|
} catch (Throwable e) {
|
||||||
|
Iris.error("Failed to load worlds.json!");
|
||||||
|
e.printStackTrace();
|
||||||
|
Iris.reportError(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new IrisWorlds(new KMap<>());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void put(String name, String type) {
|
||||||
|
put0(name, type);
|
||||||
|
save();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void put0(String name, String type) {
|
||||||
|
String old = worlds.put(name, type);
|
||||||
|
if (!type.equals(old))
|
||||||
|
dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public KMap<String, String> getWorlds() {
|
||||||
|
clean();
|
||||||
|
return readBukkitWorlds().put(worlds);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Stream<IrisData> getPacks() {
|
||||||
|
return getDimensions()
|
||||||
|
.map(IrisDimension::getLoader)
|
||||||
|
.filter(Objects::nonNull);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Stream<IrisDimension> getDimensions() {
|
||||||
|
return getWorlds()
|
||||||
|
.entrySet()
|
||||||
|
.stream()
|
||||||
|
.map(entry -> Iris.loadDimension(entry.getKey(), entry.getValue()))
|
||||||
|
.filter(Objects::nonNull);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clean() {
|
||||||
|
dirty = worlds.entrySet().removeIf(entry -> !new File(Bukkit.getWorldContainer(), entry.getKey() + "/iris/pack/dimensions/" + entry.getValue() + ".json").exists());
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void save() {
|
||||||
|
clean();
|
||||||
|
if (!dirty) return;
|
||||||
|
try {
|
||||||
|
IO.write(Iris.instance.getDataFile("worlds.json"), OutputStreamWriter::new, writer -> GSON.toJson(worlds, TYPE, writer));
|
||||||
|
dirty = false;
|
||||||
|
} catch (IOException e) {
|
||||||
|
Iris.error("Failed to save worlds.json!");
|
||||||
|
e.printStackTrace();
|
||||||
|
Iris.reportError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static KMap<String, String> readBukkitWorlds() {
|
||||||
|
var bukkit = YamlConfiguration.loadConfiguration(ServerProperties.BUKKIT_YML);
|
||||||
|
var worlds = bukkit.getConfigurationSection("worlds");
|
||||||
|
if (worlds == null) return new KMap<>();
|
||||||
|
|
||||||
|
var result = new KMap<String, String>();
|
||||||
|
for (String world : worlds.getKeys(false)) {
|
||||||
|
var gen = worlds.getString(world + ".generator");
|
||||||
|
if (gen == null) continue;
|
||||||
|
|
||||||
|
String loadKey;
|
||||||
|
if (gen.equalsIgnoreCase("iris")) {
|
||||||
|
loadKey = IrisSettings.get().getGenerator().getDefaultWorldType();
|
||||||
|
} else if (gen.startsWith("Iris:")) {
|
||||||
|
loadKey = gen.substring(5);
|
||||||
|
} else continue;
|
||||||
|
|
||||||
|
result.put(world, loadKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -23,10 +23,7 @@ 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.DataVersion;
|
||||||
import com.volmit.iris.core.nms.datapack.IDataFixer;
|
import com.volmit.iris.core.nms.datapack.IDataFixer;
|
||||||
import com.volmit.iris.engine.object.IrisBiome;
|
import com.volmit.iris.engine.object.*;
|
||||||
import com.volmit.iris.engine.object.IrisBiomeCustom;
|
|
||||||
import com.volmit.iris.engine.object.IrisDimension;
|
|
||||||
import com.volmit.iris.engine.object.IrisRange;
|
|
||||||
import com.volmit.iris.util.collection.KList;
|
import com.volmit.iris.util.collection.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;
|
||||||
@@ -34,8 +31,8 @@ import com.volmit.iris.util.format.C;
|
|||||||
import com.volmit.iris.util.misc.ServerProperties;
|
import com.volmit.iris.util.misc.ServerProperties;
|
||||||
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 lombok.Data;
|
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.configuration.InvalidConfigurationException;
|
import org.bukkit.configuration.InvalidConfigurationException;
|
||||||
import org.bukkit.configuration.file.FileConfiguration;
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
@@ -45,12 +42,13 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.atomic.AtomicIntegerArray;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import static com.volmit.iris.core.nms.datapack.IDataFixer.Dimension.*;
|
|
||||||
|
|
||||||
public class ServerConfigurator {
|
public class ServerConfigurator {
|
||||||
public static void configure() {
|
public static void configure() {
|
||||||
IrisSettings.IrisSettingsAutoconfiguration s = IrisSettings.get().getAutoConfiguration();
|
IrisSettings.IrisSettingsAutoconfiguration s = IrisSettings.get().getAutoConfiguration();
|
||||||
@@ -71,10 +69,12 @@ public class ServerConfigurator {
|
|||||||
f.load(spigotConfig);
|
f.load(spigotConfig);
|
||||||
long tt = f.getLong("settings.timeout-time");
|
long tt = f.getLong("settings.timeout-time");
|
||||||
|
|
||||||
if (tt < TimeUnit.MINUTES.toSeconds(5)) {
|
long spigotTimeout = TimeUnit.MINUTES.toSeconds(5);
|
||||||
Iris.warn("Updating spigot.yml timeout-time: " + tt + " -> " + TimeUnit.MINUTES.toSeconds(20) + " (5 minutes)");
|
|
||||||
|
if (tt < spigotTimeout) {
|
||||||
|
Iris.warn("Updating spigot.yml timeout-time: " + tt + " -> " + spigotTimeout + " (5 minutes)");
|
||||||
Iris.warn("You can disable this change (autoconfigureServer) in Iris settings, then change back the value.");
|
Iris.warn("You can disable this change (autoconfigureServer) in Iris settings, then change back the value.");
|
||||||
f.set("settings.timeout-time", TimeUnit.MINUTES.toSeconds(5));
|
f.set("settings.timeout-time", spigotTimeout);
|
||||||
f.save(spigotConfig);
|
f.save(spigotConfig);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -84,10 +84,11 @@ public class ServerConfigurator {
|
|||||||
f.load(spigotConfig);
|
f.load(spigotConfig);
|
||||||
long tt = f.getLong("watchdog.early-warning-delay");
|
long tt = f.getLong("watchdog.early-warning-delay");
|
||||||
|
|
||||||
if (tt < TimeUnit.MINUTES.toMillis(3)) {
|
long watchdog = TimeUnit.MINUTES.toMillis(3);
|
||||||
Iris.warn("Updating paper.yml watchdog early-warning-delay: " + tt + " -> " + TimeUnit.MINUTES.toMillis(15) + " (3 minutes)");
|
if (tt < watchdog) {
|
||||||
|
Iris.warn("Updating paper.yml watchdog early-warning-delay: " + tt + " -> " + watchdog + " (3 minutes)");
|
||||||
Iris.warn("You can disable this change (autoconfigureServer) in Iris settings, then change back the value.");
|
Iris.warn("You can disable this change (autoconfigureServer) in Iris settings, then change back the value.");
|
||||||
f.set("watchdog.early-warning-delay", TimeUnit.MINUTES.toMillis(3));
|
f.set("watchdog.early-warning-delay", watchdog);
|
||||||
f.save(spigotConfig);
|
f.save(spigotConfig);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -102,44 +103,52 @@ public class ServerConfigurator {
|
|||||||
return worlds;
|
return worlds;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void installDataPacks(boolean fullInstall) {
|
public static boolean installDataPacks(boolean fullInstall) {
|
||||||
installDataPacks(DataVersion.getDefault(), fullInstall);
|
return installDataPacks(DataVersion.getDefault(), fullInstall);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void installDataPacks(IDataFixer fixer, boolean fullInstall) {
|
public static boolean installDataPacks(IDataFixer fixer, boolean fullInstall) {
|
||||||
|
if (fixer == null) {
|
||||||
|
Iris.error("Unable to install datapacks, fixer is null!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
Iris.info("Checking Data Packs...");
|
Iris.info("Checking Data Packs...");
|
||||||
DimensionHeight height = new DimensionHeight(fixer);
|
DimensionHeight height = new DimensionHeight(fixer);
|
||||||
KList<File> folders = getDatapacksFolder();
|
KList<File> folders = getDatapacksFolder();
|
||||||
KMap<String, KSet<String>> biomes = new KMap<>();
|
KMap<String, KSet<String>> biomes = new KMap<>();
|
||||||
|
|
||||||
allPacks().flatMap(height::merge)
|
try (Stream<IrisData> stream = allPacks()) {
|
||||||
.parallel()
|
stream.flatMap(height::merge)
|
||||||
.forEach(dim -> {
|
.parallel()
|
||||||
Iris.verbose(" Checking Dimension " + dim.getLoadFile().getPath());
|
.forEach(dim -> {
|
||||||
dim.installBiomes(fixer, dim::getLoader, folders, biomes.computeIfAbsent(dim.getLoadKey(), k -> new KSet<>()));
|
Iris.verbose(" Checking Dimension " + dim.getLoadFile().getPath());
|
||||||
});
|
dim.installBiomes(fixer, dim::getLoader, folders, biomes.computeIfAbsent(dim.getLoadKey(), k -> new KSet<>()));
|
||||||
|
dim.installDimensionType(fixer, folders);
|
||||||
|
});
|
||||||
|
}
|
||||||
IrisDimension.writeShared(folders, height);
|
IrisDimension.writeShared(folders, height);
|
||||||
|
|
||||||
Iris.info("Data Packs Setup!");
|
Iris.info("Data Packs Setup!");
|
||||||
|
|
||||||
if (fullInstall)
|
return fullInstall && verifyDataPacksPost(IrisSettings.get().getAutoConfiguration().isAutoRestartOnCustomBiomeInstall());
|
||||||
verifyDataPacksPost(IrisSettings.get().getAutoConfiguration().isAutoRestartOnCustomBiomeInstall());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void verifyDataPacksPost(boolean allowRestarting) {
|
private static boolean verifyDataPacksPost(boolean allowRestarting) {
|
||||||
boolean bad = allPacks()
|
try (Stream<IrisData> stream = allPacks()) {
|
||||||
.map(data -> {
|
boolean bad = stream
|
||||||
Iris.verbose("Checking Pack: " + data.getDataFolder().getPath());
|
.map(data -> {
|
||||||
var loader = data.getDimensionLoader();
|
Iris.verbose("Checking Pack: " + data.getDataFolder().getPath());
|
||||||
return loader.loadAll(loader.getPossibleKeys())
|
var loader = data.getDimensionLoader();
|
||||||
.stream()
|
return loader.loadAll(loader.getPossibleKeys())
|
||||||
.map(ServerConfigurator::verifyDataPackInstalled)
|
.stream()
|
||||||
.toList()
|
.filter(Objects::nonNull)
|
||||||
.contains(false);
|
.map(ServerConfigurator::verifyDataPackInstalled)
|
||||||
})
|
.toList()
|
||||||
.toList()
|
.contains(false);
|
||||||
.contains(true);
|
})
|
||||||
if (!bad) return;
|
.toList()
|
||||||
|
.contains(true);
|
||||||
|
if (!bad) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (allowRestarting) {
|
if (allowRestarting) {
|
||||||
@@ -162,6 +171,7 @@ public class ServerConfigurator {
|
|||||||
|
|
||||||
J.sleep(3000);
|
J.sleep(3000);
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void restart() {
|
public static void restart() {
|
||||||
@@ -213,6 +223,11 @@ public class ServerConfigurator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (INMS.get().missingDimensionTypes(dimension.getDimensionTypeKey())) {
|
||||||
|
Iris.warn("The Dimension Type for " + dimension.getLoadFile() + " is not registered on the server.");
|
||||||
|
warn = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (warn) {
|
if (warn) {
|
||||||
Iris.error("The Pack " + key + " is INCAPABLE of generating custom biomes");
|
Iris.error("The Pack " + key + " is INCAPABLE of generating custom biomes");
|
||||||
Iris.error("If not done automatically, restart your server before generating with this pack!");
|
Iris.error("If not done automatically, restart your server before generating with this pack!");
|
||||||
@@ -222,10 +237,13 @@ public class ServerConfigurator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static Stream<IrisData> allPacks() {
|
public static Stream<IrisData> allPacks() {
|
||||||
return Stream.concat(listFiles(new File("plugins/Iris/packs")),
|
return Stream.concat(listFiles(Iris.instance.getDataFolder("packs"))
|
||||||
listFiles(Bukkit.getWorldContainer()).map(w -> new File(w, "iris/pack")))
|
|
||||||
.filter(File::isDirectory)
|
.filter(File::isDirectory)
|
||||||
.map(IrisData::get);
|
.filter( base -> {
|
||||||
|
var content = new File(base, "dimensions").listFiles();
|
||||||
|
return content != null && content.length > 0;
|
||||||
|
})
|
||||||
|
.map(IrisData::get), IrisWorlds.get().getPacks());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@@ -239,49 +257,58 @@ public class ServerConfigurator {
|
|||||||
return path.substring(worldContainer.length(), path.length() - l);
|
return path.substring(worldContainer.length(), path.length() - l);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
private static Stream<File> listFiles(File parent) {
|
private static Stream<File> listFiles(File parent) {
|
||||||
var files = parent.listFiles();
|
if (!parent.isDirectory()) return Stream.empty();
|
||||||
return files == null ? Stream.empty() : Arrays.stream(files);
|
return Files.walk(parent.toPath()).map(Path::toFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Data
|
|
||||||
public static class DimensionHeight {
|
public static class DimensionHeight {
|
||||||
private final IDataFixer fixer;
|
private final IDataFixer fixer;
|
||||||
private IrisRange overworld = new IrisRange();
|
private final AtomicIntegerArray[] dimensions = new AtomicIntegerArray[3];
|
||||||
private IrisRange nether = new IrisRange();
|
|
||||||
private IrisRange end = new IrisRange();
|
public DimensionHeight(IDataFixer fixer) {
|
||||||
private int logicalOverworld = 0;
|
this.fixer = fixer;
|
||||||
private int logicalNether = 0;
|
for (int i = 0; i < 3; i++) {
|
||||||
private int logicalEnd = 0;
|
dimensions[i] = new AtomicIntegerArray(new int[]{
|
||||||
|
Integer.MAX_VALUE, Integer.MIN_VALUE, Integer.MIN_VALUE
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public Stream<IrisDimension> merge(IrisData data) {
|
public Stream<IrisDimension> merge(IrisData data) {
|
||||||
Iris.verbose("Checking Pack: " + data.getDataFolder().getPath());
|
Iris.verbose("Checking Pack: " + data.getDataFolder().getPath());
|
||||||
var loader = data.getDimensionLoader();
|
var loader = data.getDimensionLoader();
|
||||||
return loader.loadAll(loader.getPossibleKeys())
|
return loader.loadAll(loader.getPossibleKeys())
|
||||||
.stream()
|
.stream()
|
||||||
|
.filter(Objects::nonNull)
|
||||||
.peek(this::merge);
|
.peek(this::merge);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void merge(IrisDimension dimension) {
|
public void merge(IrisDimension dimension) {
|
||||||
overworld.merge(dimension.getDimensionHeight());
|
AtomicIntegerArray array = dimensions[dimension.getBaseDimension().ordinal()];
|
||||||
nether.merge(dimension.getDimensionHeight());
|
array.updateAndGet(0, min -> Math.min(min, dimension.getMinHeight()));
|
||||||
end.merge(dimension.getDimensionHeight());
|
array.updateAndGet(1, max -> Math.max(max, dimension.getMaxHeight()));
|
||||||
|
array.updateAndGet(2, logical -> Math.max(logical, dimension.getLogicalHeight()));
|
||||||
logicalOverworld = Math.max(logicalOverworld, dimension.getLogicalHeight());
|
|
||||||
logicalNether = Math.max(logicalNether, dimension.getLogicalHeightNether());
|
|
||||||
logicalEnd = Math.max(logicalEnd, dimension.getLogicalHeightEnd());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String overworldType() {
|
public String[] jsonStrings() {
|
||||||
return fixer.createDimension(OVERRWORLD, overworld, logicalOverworld).toString(4);
|
var dims = IDataFixer.Dimension.values();
|
||||||
|
var arr = new String[3];
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
arr[i] = jsonString(dims[i]);
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String netherType() {
|
public String jsonString(IDataFixer.Dimension dimension) {
|
||||||
return fixer.createDimension(NETHER, nether, logicalNether).toString(4);
|
var data = dimensions[dimension.ordinal()];
|
||||||
}
|
int minY = data.get(0);
|
||||||
|
int maxY = data.get(1);
|
||||||
public String endType() {
|
int logicalHeight = data.get(2);
|
||||||
return fixer.createDimension(THE_END, end, logicalEnd).toString(4);
|
if (minY == Integer.MAX_VALUE || maxY == Integer.MIN_VALUE || Integer.MIN_VALUE == logicalHeight)
|
||||||
|
return null;
|
||||||
|
return fixer.createDimension(dimension, minY, maxY - minY, logicalHeight, null).toString(4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.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.");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -18,28 +18,41 @@
|
|||||||
|
|
||||||
package com.volmit.iris.core.commands;
|
package com.volmit.iris.core.commands;
|
||||||
|
|
||||||
|
import com.google.gson.JsonArray;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.Iris;
|
||||||
import com.volmit.iris.core.ServerConfigurator;
|
import com.volmit.iris.core.ServerConfigurator;
|
||||||
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.datapack.DataVersion;
|
import com.volmit.iris.core.nms.datapack.DataVersion;
|
||||||
import com.volmit.iris.core.service.IrisEngineSVC;
|
import com.volmit.iris.core.service.IrisEngineSVC;
|
||||||
import com.volmit.iris.core.tools.IrisPackBenchmarking;
|
import com.volmit.iris.core.tools.IrisPackBenchmarking;
|
||||||
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.engine.object.annotations.Snippet;
|
||||||
|
import com.volmit.iris.util.collection.KSet;
|
||||||
|
import com.volmit.iris.util.context.IrisContext;
|
||||||
|
import com.volmit.iris.engine.object.IrisJigsawStructurePlacement;
|
||||||
|
import com.volmit.iris.util.collection.KList;
|
||||||
import com.volmit.iris.util.decree.DecreeExecutor;
|
import com.volmit.iris.util.decree.DecreeExecutor;
|
||||||
import com.volmit.iris.util.decree.DecreeOrigin;
|
import com.volmit.iris.util.decree.DecreeOrigin;
|
||||||
import com.volmit.iris.util.decree.annotations.Decree;
|
import com.volmit.iris.util.decree.annotations.Decree;
|
||||||
import com.volmit.iris.util.decree.annotations.Param;
|
import com.volmit.iris.util.decree.annotations.Param;
|
||||||
|
import com.volmit.iris.util.decree.specialhandlers.NullableDimensionHandler;
|
||||||
import com.volmit.iris.util.format.C;
|
import com.volmit.iris.util.format.C;
|
||||||
import com.volmit.iris.util.format.Form;
|
import com.volmit.iris.util.format.Form;
|
||||||
import com.volmit.iris.util.io.CountingDataInputStream;
|
import com.volmit.iris.util.io.CountingDataInputStream;
|
||||||
import com.volmit.iris.util.io.IO;
|
import com.volmit.iris.util.io.IO;
|
||||||
import com.volmit.iris.util.mantle.TectonicPlate;
|
import com.volmit.iris.util.mantle.TectonicPlate;
|
||||||
|
import com.volmit.iris.util.math.M;
|
||||||
|
import com.volmit.iris.util.matter.Matter;
|
||||||
import com.volmit.iris.util.nbt.mca.MCAFile;
|
import com.volmit.iris.util.nbt.mca.MCAFile;
|
||||||
import com.volmit.iris.util.nbt.mca.MCAUtil;
|
import com.volmit.iris.util.nbt.mca.MCAUtil;
|
||||||
import com.volmit.iris.util.parallel.MultiBurst;
|
import com.volmit.iris.util.parallel.MultiBurst;
|
||||||
import com.volmit.iris.util.plugin.VolmitSender;
|
import com.volmit.iris.util.plugin.VolmitSender;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
import net.jpountz.lz4.LZ4BlockInputStream;
|
import net.jpountz.lz4.LZ4BlockInputStream;
|
||||||
import net.jpountz.lz4.LZ4BlockOutputStream;
|
import net.jpountz.lz4.LZ4BlockOutputStream;
|
||||||
import net.jpountz.lz4.LZ4FrameInputStream;
|
import net.jpountz.lz4.LZ4FrameInputStream;
|
||||||
@@ -52,88 +65,219 @@ import org.bukkit.World;
|
|||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.NetworkInterface;
|
import java.net.NetworkInterface;
|
||||||
|
import java.nio.file.Files;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
import java.util.zip.GZIPInputStream;
|
import java.util.zip.GZIPInputStream;
|
||||||
import java.util.zip.GZIPOutputStream;
|
import java.util.zip.GZIPOutputStream;
|
||||||
|
|
||||||
@Decree(name = "Developer", origin = DecreeOrigin.BOTH, description = "Iris World Manager", aliases = {"dev"})
|
@Decree(name = "Developer", origin = DecreeOrigin.BOTH, description = "Iris World Manager", aliases = {"dev"})
|
||||||
public class CommandDeveloper implements DecreeExecutor {
|
public class CommandDeveloper implements DecreeExecutor {
|
||||||
private CommandTurboPregen turboPregen;
|
private CommandTurboPregen turboPregen;
|
||||||
private CommandUpdater updater;
|
private CommandLazyPregen lazyPregen;
|
||||||
|
|
||||||
@Decree(description = "Get Loaded TectonicPlates Count", origin = DecreeOrigin.BOTH, sync = true)
|
@Decree(description = "Get Loaded TectonicPlates Count", origin = DecreeOrigin.BOTH, sync = true)
|
||||||
public void EngineStatus() {
|
public void EngineStatus() {
|
||||||
List<World> IrisWorlds = new ArrayList<>();
|
Iris.service(IrisEngineSVC.class)
|
||||||
int TotalLoadedChunks = 0;
|
.engineStatus(sender());
|
||||||
int TotalQueuedTectonicPlates = 0;
|
}
|
||||||
int TotalNotQueuedTectonicPlates = 0;
|
|
||||||
int TotalTectonicPlates = 0;
|
|
||||||
|
|
||||||
long lowestUnloadDuration = 0;
|
@Decree(description = "Send a test exception to sentry")
|
||||||
long highestUnloadDuration = 0;
|
public void Sentry() {
|
||||||
|
Engine engine = engine();
|
||||||
for (World world : Bukkit.getWorlds()) {
|
if (engine != null) IrisContext.getOr(engine);
|
||||||
try {
|
Iris.reportError(new Exception("This is a test"));
|
||||||
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")
|
@Decree(description = "Test")
|
||||||
public void benchmarkMantle(
|
public void mantle(@Param(defaultValue = "false") boolean plate, @Param(defaultValue = "21474836474") String name) throws Throwable {
|
||||||
@Param(description = "The world to bench", aliases = {"world"})
|
var base = Iris.instance.getDataFile("dump", "pv." + name + ".ttp.lz4b.bin");
|
||||||
World world
|
var section = Iris.instance.getDataFile("dump", "pv." + name + ".section.bin");
|
||||||
) 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");
|
//extractSection(base, section, 5604930, 4397);
|
||||||
for (File i : Objects.requireNonNull(tectonicplates.listFiles())) {
|
|
||||||
TectonicPlate.read(maxHeight, i);
|
|
||||||
c++;
|
|
||||||
Iris.info("Loaded count: " + c );
|
|
||||||
|
|
||||||
|
if (plate) {
|
||||||
|
try (var in = CountingDataInputStream.wrap(new BufferedInputStream(new FileInputStream(base)))) {
|
||||||
|
new TectonicPlate(1088, in, true);
|
||||||
|
} catch (Throwable e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
} else Matter.read(section);
|
||||||
|
if (!TectonicPlate.hasError())
|
||||||
|
Iris.info("Read " + (plate ? base : section).length() + " bytes from " + (plate ? base : section).getAbsolutePath());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void extractSection(File source, File target, long offset, int length) throws IOException {
|
||||||
|
var raf = new RandomAccessFile(source, "r");
|
||||||
|
var bytes = new byte[length];
|
||||||
|
raf.seek(offset);
|
||||||
|
raf.readFully(bytes);
|
||||||
|
raf.close();
|
||||||
|
Files.write(target.toPath(), bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Decree(description = "Test")
|
||||||
|
public void dumpThreads() {
|
||||||
|
try {
|
||||||
|
File fi = Iris.instance.getDataFile("dump", "td-" + new java.sql.Date(M.ms()) + ".txt");
|
||||||
|
FileOutputStream fos = new FileOutputStream(fi);
|
||||||
|
Map<Thread, StackTraceElement[]> f = Thread.getAllStackTraces();
|
||||||
|
PrintWriter pw = new PrintWriter(fos);
|
||||||
|
|
||||||
|
pw.println(Thread.activeCount() + "/" + f.size());
|
||||||
|
var run = Runtime.getRuntime();
|
||||||
|
pw.println("Memory:");
|
||||||
|
pw.println("\tMax: " + run.maxMemory());
|
||||||
|
pw.println("\tTotal: " + run.totalMemory());
|
||||||
|
pw.println("\tFree: " + run.freeMemory());
|
||||||
|
pw.println("\tUsed: " + (run.totalMemory() - run.freeMemory()));
|
||||||
|
|
||||||
|
for (Thread i : f.keySet()) {
|
||||||
|
pw.println("========================================");
|
||||||
|
pw.println("Thread: '" + i.getName() + "' ID: " + i.getId() + " STATUS: " + i.getState().name());
|
||||||
|
|
||||||
|
for (StackTraceElement j : f.get(i)) {
|
||||||
|
pw.println(" @ " + j.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
pw.println("========================================");
|
||||||
|
pw.println();
|
||||||
|
pw.println();
|
||||||
|
}
|
||||||
|
|
||||||
|
pw.close();
|
||||||
|
Iris.info("DUMPED! See " + fi.getAbsolutePath());
|
||||||
|
} catch (Throwable e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
@Decree(description = "Generate Iris structures for all loaded datapack structures")
|
||||||
|
public void generateStructures(
|
||||||
|
@Param(description = "The pack to add the generated structures to", aliases = "pack", defaultValue = "---", customHandler = NullableDimensionHandler.class)
|
||||||
|
IrisDimension dimension,
|
||||||
|
@Param(description = "Ignore existing structures", defaultValue = "false")
|
||||||
|
boolean force
|
||||||
|
) {
|
||||||
|
var map = INMS.get().collectStructures();
|
||||||
|
if (map.isEmpty()) {
|
||||||
|
sender().sendMessage(C.IRIS + "No structures found");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sender().sendMessage(C.IRIS + "Found " + map.size() + " structures");
|
||||||
|
|
||||||
|
final File dataDir;
|
||||||
|
final IrisData data;
|
||||||
|
final Set<String> existingStructures;
|
||||||
|
final Map<String, Set<String>> snippets;
|
||||||
|
final File dimensionFile;
|
||||||
|
final File structuresFolder;
|
||||||
|
final File snippetsFolder;
|
||||||
|
|
||||||
|
var dimensionObj = new JsonObject();
|
||||||
|
|
||||||
|
if (dimension == null) {
|
||||||
|
dataDir = Iris.instance.getDataFolder("structures");
|
||||||
|
IO.delete(dataDir);
|
||||||
|
data = IrisData.get(dataDir);
|
||||||
|
existingStructures = Set.of();
|
||||||
|
snippets = Map.of();
|
||||||
|
dimensionFile = new File(dataDir, "structures.json");
|
||||||
|
} else {
|
||||||
|
data = dimension.getLoader();
|
||||||
|
dataDir = data.getDataFolder();
|
||||||
|
existingStructures = new KSet<>(data.getJigsawStructureLoader().getPossibleKeys());
|
||||||
|
|
||||||
|
dimensionObj = data.getGson().fromJson(IO.readAll(dimension.getLoadFile()), JsonObject.class);
|
||||||
|
snippets = Optional.ofNullable(dimensionObj.getAsJsonArray("jigsawStructures"))
|
||||||
|
.map(array -> array.asList()
|
||||||
|
.stream()
|
||||||
|
.filter(JsonElement::isJsonPrimitive)
|
||||||
|
.collect(Collectors.toMap(element -> data.getGson()
|
||||||
|
.fromJson(element, IrisJigsawStructurePlacement.class)
|
||||||
|
.getStructure(),
|
||||||
|
element -> Set.of(element.getAsString()),
|
||||||
|
KSet::merge)))
|
||||||
|
.orElse(Map.of());
|
||||||
|
|
||||||
|
dimensionFile = dimension.getLoadFile();
|
||||||
|
}
|
||||||
|
structuresFolder = new File(dataDir, "jigsaw-structures");
|
||||||
|
snippetsFolder = new File(dataDir, "snippet" + "/" + IrisJigsawStructurePlacement.class.getAnnotation(Snippet.class).value());
|
||||||
|
|
||||||
|
var gson = data.getGson();
|
||||||
|
var jigsawStructures = Optional.ofNullable(dimensionObj.getAsJsonArray("jigsawStructures"))
|
||||||
|
.orElse(new JsonArray(map.size()));
|
||||||
|
|
||||||
|
map.forEach((key, placement) -> {
|
||||||
|
String loadKey = "datapack/" + key.namespace() + "/" + key.key();
|
||||||
|
if (existingStructures.contains(loadKey) && !force)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var structures = placement.structures();
|
||||||
|
var obj = placement.toJson(loadKey);
|
||||||
|
if (obj == null || structures.isEmpty()) {
|
||||||
|
sender().sendMessage(C.RED + "Failed to generate hook for " + key);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
File snippetFile = new File(snippetsFolder, loadKey + ".json");
|
||||||
|
try {
|
||||||
|
IO.writeAll(snippetFile, gson.toJson(obj));
|
||||||
|
} catch (IOException e) {
|
||||||
|
sender().sendMessage(C.RED + "Failed to generate snippet for " + key);
|
||||||
|
e.printStackTrace();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<String> loadKeys = snippets.getOrDefault(loadKey, Set.of(loadKey));
|
||||||
|
jigsawStructures.asList().removeIf(e -> loadKeys.contains((e.isJsonObject() ? e.getAsJsonObject().get("structure") : e).getAsString()));
|
||||||
|
jigsawStructures.add("snippet/" + loadKey);
|
||||||
|
|
||||||
|
String structureKey;
|
||||||
|
if (structures.size() > 1) {
|
||||||
|
KList<String> common = new KList<>();
|
||||||
|
for (int i = 0; i < structures.size(); i++) {
|
||||||
|
var tags = structures.get(i).tags();
|
||||||
|
if (i == 0) common.addAll(tags);
|
||||||
|
else common.removeIf(tag -> !tags.contains(tag));
|
||||||
|
}
|
||||||
|
structureKey = common.isNotEmpty() ? "#" + common.getFirst() : structures.getFirst().key();
|
||||||
|
} else structureKey = structures.getFirst().key();
|
||||||
|
|
||||||
|
JsonArray array = new JsonArray();
|
||||||
|
if (structures.size() > 1) {
|
||||||
|
structures.stream()
|
||||||
|
.flatMap(structure -> {
|
||||||
|
String[] arr = new String[structure.weight()];
|
||||||
|
Arrays.fill(arr, structure.key());
|
||||||
|
return Arrays.stream(arr);
|
||||||
|
})
|
||||||
|
.forEach(array::add);
|
||||||
|
} else array.add(structureKey);
|
||||||
|
|
||||||
|
obj = new JsonObject();
|
||||||
|
obj.addProperty("structureKey", structureKey);
|
||||||
|
obj.add("datapackStructures", array);
|
||||||
|
|
||||||
|
File out = new File(structuresFolder, loadKey + ".json");
|
||||||
|
out.getParentFile().mkdirs();
|
||||||
|
try {
|
||||||
|
IO.writeAll(out, gson.toJson(obj));
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
dimensionObj.add("jigsawStructures", jigsawStructures);
|
||||||
|
IO.writeAll(dimensionFile, gson.toJson(dimensionObj));
|
||||||
|
|
||||||
|
data.hotloaded();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Decree(description = "Test")
|
@Decree(description = "Test")
|
||||||
@@ -234,7 +378,8 @@ public class CommandDeveloper implements DecreeExecutor {
|
|||||||
@Param(description = "base IrisWorld") World world,
|
@Param(description = "base IrisWorld") World world,
|
||||||
@Param(description = "raw TectonicPlate File") String path,
|
@Param(description = "raw TectonicPlate File") String path,
|
||||||
@Param(description = "Algorithm to Test") String algorithm,
|
@Param(description = "Algorithm to Test") String algorithm,
|
||||||
@Param(description = "Amount of Tests") int amount) {
|
@Param(description = "Amount of Tests") int amount,
|
||||||
|
@Param(description = "Is versioned", defaultValue = "false") boolean versioned) {
|
||||||
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(", ", Bukkit.getServer().getWorlds().stream().filter(IrisToolbelt::isIrisWorld).map(World::getName).toList()));
|
||||||
return;
|
return;
|
||||||
@@ -251,7 +396,7 @@ public class CommandDeveloper implements DecreeExecutor {
|
|||||||
service.submit(() -> {
|
service.submit(() -> {
|
||||||
try {
|
try {
|
||||||
CountingDataInputStream raw = CountingDataInputStream.wrap(new FileInputStream(file));
|
CountingDataInputStream raw = CountingDataInputStream.wrap(new FileInputStream(file));
|
||||||
TectonicPlate plate = new TectonicPlate(height, raw);
|
TectonicPlate plate = new TectonicPlate(height, raw, versioned);
|
||||||
raw.close();
|
raw.close();
|
||||||
|
|
||||||
double d1 = 0;
|
double d1 = 0;
|
||||||
@@ -270,7 +415,7 @@ public class CommandDeveloper implements DecreeExecutor {
|
|||||||
size = tmp.length();
|
size = tmp.length();
|
||||||
start = System.currentTimeMillis();
|
start = System.currentTimeMillis();
|
||||||
CountingDataInputStream din = createInput(tmp, algorithm);
|
CountingDataInputStream din = createInput(tmp, algorithm);
|
||||||
new TectonicPlate(height, din);
|
new TectonicPlate(height, din, true);
|
||||||
din.close();
|
din.close();
|
||||||
d2 += System.currentTimeMillis() - start;
|
d2 += System.currentTimeMillis() - start;
|
||||||
tmp.delete();
|
tmp.delete();
|
||||||
|
|||||||
@@ -20,18 +20,11 @@ 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.loader.IrisData;
|
|
||||||
import com.volmit.iris.core.nms.INMS;
|
import com.volmit.iris.core.nms.INMS;
|
||||||
import com.volmit.iris.core.pregenerator.ChunkUpdater;
|
|
||||||
import com.volmit.iris.core.service.StudioSVC;
|
import com.volmit.iris.core.service.StudioSVC;
|
||||||
import com.volmit.iris.core.tools.IrisBenchmarking;
|
|
||||||
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.platform.BukkitChunkGenerator;
|
|
||||||
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.DecreeExecutor;
|
import com.volmit.iris.util.decree.DecreeExecutor;
|
||||||
import com.volmit.iris.util.decree.DecreeOrigin;
|
import com.volmit.iris.util.decree.DecreeOrigin;
|
||||||
@@ -39,45 +32,40 @@ import com.volmit.iris.util.decree.annotations.Decree;
|
|||||||
import com.volmit.iris.util.decree.annotations.Param;
|
import com.volmit.iris.util.decree.annotations.Param;
|
||||||
import com.volmit.iris.util.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.io.IO;
|
||||||
|
import com.volmit.iris.util.misc.ServerProperties;
|
||||||
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 lombok.SneakyThrows;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.WorldCreator;
|
|
||||||
import org.bukkit.configuration.ConfigurationSection;
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
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.generator.ChunkGenerator;
|
|
||||||
import org.bukkit.scheduler.BukkitRunnable;
|
import org.bukkit.scheduler.BukkitRunnable;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.*;
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
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.util.misc.ServerProperties.BUKKIT_YML;
|
||||||
import static com.volmit.iris.core.safeguard.IrisSafeguard.unstablemode;
|
|
||||||
import static com.volmit.iris.core.safeguard.ServerBootSFG.incompatibilities;
|
|
||||||
import static org.bukkit.Bukkit.getServer;
|
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 CommandUpdater updater;
|
||||||
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 CommandSupport support;
|
|
||||||
private CommandDeveloper developer;
|
private CommandDeveloper developer;
|
||||||
public static boolean worldCreation = false;
|
public static boolean worldCreation = false;
|
||||||
|
private static final AtomicReference<Thread> mainWorld = new AtomicReference<>();
|
||||||
String WorldEngine;
|
String WorldEngine;
|
||||||
String worldNameToCheck = "YourWorldName";
|
String worldNameToCheck = "YourWorldName";
|
||||||
VolmitSender sender = Iris.getSender();
|
VolmitSender sender = Iris.getSender();
|
||||||
@@ -89,36 +77,21 @@ 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(aliases = "main-world", description = "Whether or not to automatically use this world as the main world", defaultValue = "false")
|
||||||
|
boolean main
|
||||||
) {
|
) {
|
||||||
if(sender() instanceof Player) {
|
if (name.equalsIgnoreCase("iris")) {
|
||||||
if (incompatibilities.get("Multiverse-Core")) {
|
sender().sendMessage(C.RED + "You cannot use the world name \"iris\" for creating worlds as Iris uses this directory for studio worlds.");
|
||||||
sender().sendMessage(C.RED + "Your server has an incompatibility that may corrupt all worlds on the server if not handled properly.");
|
sender().sendMessage(C.RED + "May we suggest the name \"IrisWorld\" instead?");
|
||||||
sender().sendMessage(C.RED + "it is strongly advised for you to take action. see log for full detail");
|
return;
|
||||||
sender().sendMessage(C.RED + "----------------------------------------------------------------");
|
}
|
||||||
sender().sendMessage(C.RED + "Command ran: /iris create");
|
|
||||||
sender().sendMessage(C.RED + UtilsSFG.MSGIncompatibleWarnings());
|
if (name.equalsIgnoreCase("benchmark")) {
|
||||||
sender().sendMessage(C.RED + "----------------------------------------------------------------");
|
sender().sendMessage(C.RED + "You cannot use the world name \"benchmark\" for creating worlds as Iris uses this directory for Benchmarking Packs.");
|
||||||
}
|
sender().sendMessage(C.RED + "May we suggest the name \"IrisWorld\" instead?");
|
||||||
if (unstablemode && !incompatibilities.get("Multiverse-Core")) {
|
return;
|
||||||
sender().sendMessage(C.RED + "Your server is experiencing an incompatibility with the Iris plugin.");
|
|
||||||
sender().sendMessage(C.RED + "Please rectify this problem to avoid further complications.");
|
|
||||||
sender().sendMessage(C.RED + "----------------------------------------------------------------");
|
|
||||||
sender().sendMessage(C.RED + "Command ran: /iris create");
|
|
||||||
sender().sendMessage(C.RED + UtilsSFG.MSGIncompatibleWarnings());
|
|
||||||
sender().sendMessage(C.RED + "----------------------------------------------------------------");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (name.equals("iris")) {
|
|
||||||
sender().sendMessage(C.RED + "You cannot use the world name \"iris\" for creating worlds as Iris uses this directory for studio worlds.");
|
|
||||||
sender().sendMessage(C.RED + "May we suggest the name \"IrisWorld\" instead?");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (name.equals("Benchmark")) {
|
|
||||||
sender().sendMessage(C.RED + "You cannot use the world name \"Benchmark\" for creating worlds as Iris uses this directory for Benchmarking Packs.");
|
|
||||||
sender().sendMessage(C.RED + "May we suggest the name \"IrisWorld\" instead?");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (new File(Bukkit.getWorldContainer(), name).exists()) {
|
if (new File(Bukkit.getWorldContainer(), name).exists()) {
|
||||||
sender().sendMessage(C.RED + "That folder already exists!");
|
sender().sendMessage(C.RED + "That folder already exists!");
|
||||||
@@ -134,6 +107,12 @@ public class CommandIris implements DecreeExecutor {
|
|||||||
.sender(sender())
|
.sender(sender())
|
||||||
.studio(false)
|
.studio(false)
|
||||||
.create();
|
.create();
|
||||||
|
if (main) {
|
||||||
|
Runtime.getRuntime().addShutdownHook(mainWorld.updateAndGet(old -> {
|
||||||
|
if (old != null) Runtime.getRuntime().removeShutdownHook(old);
|
||||||
|
return new Thread(() -> updateMainWorld(name));
|
||||||
|
}));
|
||||||
|
}
|
||||||
} 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());
|
||||||
@@ -143,6 +122,24 @@ public class CommandIris implements DecreeExecutor {
|
|||||||
}
|
}
|
||||||
worldCreation = false;
|
worldCreation = false;
|
||||||
sender().sendMessage(C.GREEN + "Successfully created your world!");
|
sender().sendMessage(C.GREEN + "Successfully created your world!");
|
||||||
|
if (main) sender().sendMessage(C.GREEN + "Your world will automatically be set as the main world when the server restarts.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
private void updateMainWorld(String newName) {
|
||||||
|
File worlds = Bukkit.getWorldContainer();
|
||||||
|
var data = ServerProperties.DATA;
|
||||||
|
try (var in = new FileInputStream(ServerProperties.SERVER_PROPERTIES)) {
|
||||||
|
data.load(in);
|
||||||
|
}
|
||||||
|
for (String sub : List.of("datapacks", "playerdata", "advancements", "stats")) {
|
||||||
|
IO.copyDirectory(new File(worlds, ServerProperties.LEVEL_NAME + "/" + sub).toPath(), new File(worlds, newName + "/" + sub).toPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
data.setProperty("level-name", newName);
|
||||||
|
try (var out = new FileOutputStream(ServerProperties.SERVER_PROPERTIES)) {
|
||||||
|
data.store(out, null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Decree(description = "Teleport to another world", aliases = {"tp"}, sync = true)
|
@Decree(description = "Teleport to another world", aliases = {"tp"}, sync = true)
|
||||||
@@ -175,16 +172,6 @@ public class CommandIris implements DecreeExecutor {
|
|||||||
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)
|
|
||||||
public void serverbenchmark() throws InterruptedException {
|
|
||||||
if(!inProgress) {
|
|
||||||
IrisBenchmarking.runBenchmark();
|
|
||||||
} else {
|
|
||||||
Iris.info(C.RED + "Benchmark already is in progress.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
/todo
|
/todo
|
||||||
@Decree(description = "Benchmark a pack", origin = DecreeOrigin.CONSOLE)
|
@Decree(description = "Benchmark a pack", origin = DecreeOrigin.CONSOLE)
|
||||||
@@ -330,24 +317,6 @@ 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")
|
||||||
@@ -400,17 +369,19 @@ public class CommandIris implements DecreeExecutor {
|
|||||||
sender().sendMessage(C.GREEN + "Set debug to: " + to);
|
sender().sendMessage(C.GREEN + "Set debug to: " + to);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO fix pack trimming
|
||||||
@Decree(description = "Download a project.", aliases = "dl")
|
@Decree(description = "Download a project.", aliases = "dl")
|
||||||
public void download(
|
public void download(
|
||||||
@Param(name = "pack", description = "The pack to download", defaultValue = "overworld", aliases = "project")
|
@Param(name = "pack", description = "The pack to download", defaultValue = "overworld", aliases = "project")
|
||||||
String pack,
|
String pack,
|
||||||
@Param(name = "branch", description = "The branch to download from", defaultValue = "main")
|
@Param(name = "branch", description = "The branch to download from", defaultValue = "main")
|
||||||
String branch,
|
String branch,
|
||||||
@Param(name = "trim", description = "Whether or not to download a trimmed version (do not enable when editing)", defaultValue = "false")
|
//@Param(name = "trim", description = "Whether or not to download a trimmed version (do not enable when editing)", defaultValue = "false")
|
||||||
boolean trim,
|
//boolean trim,
|
||||||
@Param(name = "overwrite", description = "Whether or not to overwrite the pack with the downloaded one", aliases = "force", defaultValue = "false")
|
@Param(name = "overwrite", description = "Whether or not to overwrite the pack with the downloaded one", aliases = "force", defaultValue = "false")
|
||||||
boolean overwrite
|
boolean overwrite
|
||||||
) {
|
) {
|
||||||
|
boolean trim = false;
|
||||||
sender().sendMessage(C.GREEN + "Downloading pack: " + pack + "/" + branch + (trim ? " trimmed" : "") + (overwrite ? " overwriting" : ""));
|
sender().sendMessage(C.GREEN + "Downloading pack: " + pack + "/" + branch + (trim ? " trimmed" : "") + (overwrite ? " overwriting" : ""));
|
||||||
if (pack.equals("overworld")) {
|
if (pack.equals("overworld")) {
|
||||||
String url = "https://github.com/IrisDimensions/overworld/releases/download/" + INMS.OVERWORLD_TAG + "/overworld.zip";
|
String url = "https://github.com/IrisDimensions/overworld/releases/download/" + INMS.OVERWORLD_TAG + "/overworld.zip";
|
||||||
@@ -508,7 +479,6 @@ public class CommandIris implements DecreeExecutor {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
File BUKKIT_YML = new File("bukkit.yml");
|
|
||||||
String pathtodim = world + File.separator +"iris"+File.separator +"pack"+File.separator +"dimensions"+File.separator;
|
String pathtodim = world + File.separator +"iris"+File.separator +"pack"+File.separator +"dimensions"+File.separator;
|
||||||
File directory = new File(Bukkit.getWorldContainer(), pathtodim);
|
File directory = new File(Bukkit.getWorldContainer(), pathtodim);
|
||||||
|
|
||||||
@@ -546,7 +516,7 @@ public class CommandIris implements DecreeExecutor {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
checkForBukkitWorlds(world);
|
Iris.instance.checkForBukkitWorlds(world::equals);
|
||||||
sender().sendMessage(C.GREEN + world + " loaded successfully.");
|
sender().sendMessage(C.GREEN + world + " loaded successfully.");
|
||||||
}
|
}
|
||||||
@Decree(description = "Evacuate an iris world", origin = DecreeOrigin.PLAYER, sync = true)
|
@Decree(description = "Evacuate an iris world", origin = DecreeOrigin.PLAYER, sync = true)
|
||||||
@@ -567,96 +537,4 @@ public class CommandIris implements DecreeExecutor {
|
|||||||
File worldDirectory = new File(worldContainer, worldName);
|
File worldDirectory = new File(worldContainer, worldName);
|
||||||
return worldDirectory.exists() && worldDirectory.isDirectory();
|
return worldDirectory.exists() && worldDirectory.isDirectory();
|
||||||
}
|
}
|
||||||
private void checkForBukkitWorlds(String world) {
|
|
||||||
FileConfiguration fc = new YamlConfiguration();
|
|
||||||
try {
|
|
||||||
fc.load(new File("bukkit.yml"));
|
|
||||||
ConfigurationSection section = fc.getConfigurationSection("worlds");
|
|
||||||
if (section == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<String> worldsToLoad = Collections.singletonList(world);
|
|
||||||
|
|
||||||
for (String s : section.getKeys(false)) {
|
|
||||||
if (!worldsToLoad.contains(s)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
ConfigurationSection entry = section.getConfigurationSection(s);
|
|
||||||
if (!entry.contains("generator", true)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
String generator = entry.getString("generator");
|
|
||||||
if (generator.startsWith("Iris:")) {
|
|
||||||
generator = generator.split("\\Q:\\E")[1];
|
|
||||||
} else if (generator.equalsIgnoreCase("Iris")) {
|
|
||||||
generator = IrisSettings.get().getGenerator().getDefaultWorldType();
|
|
||||||
} else {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
Iris.info("2 World: %s | Generator: %s", s, generator);
|
|
||||||
if (Bukkit.getWorlds().stream().anyMatch(w -> w.getName().equals(s))) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
Iris.info(C.LIGHT_PURPLE + "Preparing Spawn for " + s + "' using Iris:" + generator + "...");
|
|
||||||
WorldCreator c = new WorldCreator(s)
|
|
||||||
.generator(getDefaultWorldGenerator(s, generator))
|
|
||||||
.environment(IrisData.loadAnyDimension(generator).getEnvironment());
|
|
||||||
INMS.get().createWorld(c);
|
|
||||||
Iris.info(C.LIGHT_PURPLE + "Loaded " + s + "!");
|
|
||||||
}
|
|
||||||
} catch (Throwable e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public ChunkGenerator getDefaultWorldGenerator(String worldName, String id) {
|
|
||||||
Iris.debug("Default World Generator Called for " + worldName + " using ID: " + id);
|
|
||||||
if (worldName.equals("test")) {
|
|
||||||
try {
|
|
||||||
throw new RuntimeException();
|
|
||||||
} catch (Throwable e) {
|
|
||||||
Iris.info(e.getStackTrace()[1].getClassName());
|
|
||||||
if (e.getStackTrace()[1].getClassName().contains("com.onarandombox.MultiverseCore")) {
|
|
||||||
Iris.debug("MVC Test detected, Quick! Send them the dummy!");
|
|
||||||
return new DummyChunkGenerator();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
IrisDimension dim;
|
|
||||||
if (id == null || id.isEmpty()) {
|
|
||||||
dim = IrisData.loadAnyDimension(IrisSettings.get().getGenerator().getDefaultWorldType());
|
|
||||||
} else {
|
|
||||||
dim = IrisData.loadAnyDimension(id);
|
|
||||||
}
|
|
||||||
Iris.debug("Generator ID: " + id + " requested by bukkit/plugin");
|
|
||||||
|
|
||||||
if (dim == null) {
|
|
||||||
Iris.warn("Unable to find dimension type " + id + " Looking for online packs...");
|
|
||||||
|
|
||||||
service(StudioSVC.class).downloadSearch(new VolmitSender(Bukkit.getConsoleSender()), id, true);
|
|
||||||
dim = IrisData.loadAnyDimension(id);
|
|
||||||
|
|
||||||
if (dim == null) {
|
|
||||||
throw new RuntimeException("Can't find dimension " + id + "!");
|
|
||||||
} else {
|
|
||||||
Iris.info("Resolved missing dimension, proceeding with generation.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Iris.debug("Assuming IrisDimension: " + dim.getName());
|
|
||||||
IrisWorld w = IrisWorld.builder()
|
|
||||||
.name(worldName)
|
|
||||||
.seed(1337)
|
|
||||||
.environment(dim.getEnvironment())
|
|
||||||
.worldFolder(new File(Bukkit.getWorldContainer(), worldName))
|
|
||||||
.minHeight(dim.getMinHeight())
|
|
||||||
.maxHeight(dim.getMaxHeight())
|
|
||||||
.build();
|
|
||||||
Iris.debug("Generator Config: " + w.toString());
|
|
||||||
File ff = new File(w.worldFolder(), "iris/pack");
|
|
||||||
if (!ff.exists() || ff.listFiles().length == 0) {
|
|
||||||
ff.mkdirs();
|
|
||||||
service(StudioSVC.class).installIntoWorld(sender, dim.getLoadKey(), ff.getParentFile());
|
|
||||||
}
|
|
||||||
return new BukkitChunkGenerator(w, false, ff, dim.getLoadKey());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -241,7 +241,8 @@ public class CommandObject implements DecreeExecutor {
|
|||||||
|
|
||||||
|
|
||||||
Location[] b = WandSVC.getCuboid(player());
|
Location[] b = WandSVC.getCuboid(player());
|
||||||
if (b == null) {
|
if (b == null || b[0] == null || b[1] == null) {
|
||||||
|
sender().sendMessage("No area selected.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Location a1 = b[0].clone();
|
Location a1 = b[0].clone();
|
||||||
@@ -417,6 +418,10 @@ public class CommandObject implements DecreeExecutor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Location[] b = WandSVC.getCuboid(player());
|
Location[] b = WandSVC.getCuboid(player());
|
||||||
|
if (b == null || b[0] == null || b[1] == null) {
|
||||||
|
sender().sendMessage("No area selected.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
Location a1 = b[0].clone();
|
Location a1 = b[0].clone();
|
||||||
Location a2 = b[1].clone();
|
Location a2 = b[1].clone();
|
||||||
Direction d = Direction.closest(player().getLocation().getDirection()).reverse();
|
Direction d = Direction.closest(player().getLocation().getDirection()).reverse();
|
||||||
@@ -477,6 +482,10 @@ public class CommandObject implements DecreeExecutor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Location[] b = WandSVC.getCuboid(player());
|
Location[] b = WandSVC.getCuboid(player());
|
||||||
|
if (b == null || b[0] == null || b[1] == null) {
|
||||||
|
sender().sendMessage("No area selected.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
Location a1 = b[0].clone();
|
Location a1 = b[0].clone();
|
||||||
Location a2 = b[1].clone();
|
Location a2 = b[1].clone();
|
||||||
Location a1x = b[0].clone();
|
Location a1x = b[0].clone();
|
||||||
@@ -524,6 +533,10 @@ public class CommandObject implements DecreeExecutor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Location[] b = WandSVC.getCuboid(player());
|
Location[] b = WandSVC.getCuboid(player());
|
||||||
|
if (b == null || b[0] == null || b[1] == null) {
|
||||||
|
sender().sendMessage("No area selected.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
b[0].add(new Vector(0, 1, 0));
|
b[0].add(new Vector(0, 1, 0));
|
||||||
b[1].add(new Vector(0, 1, 0));
|
b[1].add(new Vector(0, 1, 0));
|
||||||
Location a1 = b[0].clone();
|
Location a1 = b[0].clone();
|
||||||
|
|||||||
@@ -39,7 +39,9 @@ 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(description = "Open the Iris pregen gui", defaultValue = "true")
|
||||||
|
boolean gui
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
if (sender().isPlayer() && access() == null) {
|
if (sender().isPlayer() && access() == null) {
|
||||||
@@ -50,7 +52,7 @@ public class CommandPregen implements DecreeExecutor {
|
|||||||
IrisToolbelt.pregenerate(PregenTask
|
IrisToolbelt.pregenerate(PregenTask
|
||||||
.builder()
|
.builder()
|
||||||
.center(new Position2(center.getBlockX(), center.getBlockZ()))
|
.center(new Position2(center.getBlockX(), center.getBlockZ()))
|
||||||
.gui(true)
|
.gui(gui)
|
||||||
.radiusX(radius)
|
.radiusX(radius)
|
||||||
.radiusZ(radius)
|
.radiusZ(radius)
|
||||||
.build(), world);
|
.build(), world);
|
||||||
|
|||||||
@@ -46,18 +46,19 @@ import com.volmit.iris.util.interpolation.InterpolationMethod;
|
|||||||
import com.volmit.iris.util.io.IO;
|
import com.volmit.iris.util.io.IO;
|
||||||
import com.volmit.iris.util.json.JSONArray;
|
import com.volmit.iris.util.json.JSONArray;
|
||||||
import com.volmit.iris.util.json.JSONObject;
|
import com.volmit.iris.util.json.JSONObject;
|
||||||
|
import com.volmit.iris.util.mantle.MantleChunk;
|
||||||
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;
|
||||||
import com.volmit.iris.util.math.RNG;
|
import com.volmit.iris.util.math.RNG;
|
||||||
import com.volmit.iris.util.math.Spiraler;
|
import com.volmit.iris.util.math.Spiraler;
|
||||||
import com.volmit.iris.util.noise.CNG;
|
import com.volmit.iris.util.noise.CNG;
|
||||||
import com.volmit.iris.util.parallel.BurstExecutor;
|
|
||||||
import com.volmit.iris.util.parallel.MultiBurst;
|
import com.volmit.iris.util.parallel.MultiBurst;
|
||||||
|
import com.volmit.iris.util.parallel.SyncExecutor;
|
||||||
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.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 com.volmit.iris.util.scheduling.jobs.ParallelQueueJob;
|
||||||
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;
|
||||||
@@ -76,8 +77,7 @@ import java.time.temporal.ChronoUnit;
|
|||||||
import java.util.Arrays;
|
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.CountDownLatch;
|
||||||
import java.util.concurrent.Future;
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
@@ -91,18 +91,19 @@ public class CommandStudio implements DecreeExecutor {
|
|||||||
return duration.toString().substring(2).replaceAll("(\\d[HMS])(?!$)", "$1 ").toLowerCase();
|
return duration.toString().substring(2).replaceAll("(\\d[HMS])(?!$)", "$1 ").toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO fix pack trimming
|
||||||
@Decree(description = "Download a project.", aliases = "dl")
|
@Decree(description = "Download a project.", aliases = "dl")
|
||||||
public void download(
|
public void download(
|
||||||
@Param(name = "pack", description = "The pack to download", defaultValue = "overworld", aliases = "project")
|
@Param(name = "pack", description = "The pack to download", defaultValue = "overworld", aliases = "project")
|
||||||
String pack,
|
String pack,
|
||||||
@Param(name = "branch", description = "The branch to download from", defaultValue = "master")
|
@Param(name = "branch", description = "The branch to download from", defaultValue = "master")
|
||||||
String branch,
|
String branch,
|
||||||
@Param(name = "trim", description = "Whether or not to download a trimmed version (do not enable when editing)", defaultValue = "false")
|
//@Param(name = "trim", description = "Whether or not to download a trimmed version (do not enable when editing)", defaultValue = "false")
|
||||||
boolean trim,
|
//boolean trim,
|
||||||
@Param(name = "overwrite", description = "Whether or not to overwrite the pack with the downloaded one", aliases = "force", defaultValue = "false")
|
@Param(name = "overwrite", description = "Whether or not to overwrite the pack with the downloaded one", aliases = "force", defaultValue = "false")
|
||||||
boolean overwrite
|
boolean overwrite
|
||||||
) {
|
) {
|
||||||
new CommandIris().download(pack, branch, trim, overwrite);
|
new CommandIris().download(pack, branch, overwrite);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Decree(description = "Open a new studio world", aliases = "o", sync = true)
|
@Decree(description = "Open a new studio world", aliases = "o", sync = true)
|
||||||
@@ -161,70 +162,93 @@ public class CommandStudio implements DecreeExecutor {
|
|||||||
@Param(name = "radius", description = "The radius of nearby cunks", defaultValue = "5")
|
@Param(name = "radius", description = "The radius of nearby cunks", defaultValue = "5")
|
||||||
int radius
|
int radius
|
||||||
) {
|
) {
|
||||||
if (IrisToolbelt.isIrisWorld(player().getWorld())) {
|
World world = player().getWorld();
|
||||||
VolmitSender sender = sender();
|
if (!IrisToolbelt.isIrisWorld(world)) {
|
||||||
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!");
|
sender().sendMessage(C.RED + "You must be in an Iris World to use regen!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VolmitSender sender = sender();
|
||||||
|
var loc = player().getLocation().clone();
|
||||||
|
|
||||||
|
J.a(() -> {
|
||||||
|
DecreeContext.touch(sender);
|
||||||
|
PlatformChunkGenerator plat = IrisToolbelt.access(world);
|
||||||
|
Engine engine = plat.getEngine();
|
||||||
|
try (SyncExecutor executor = new SyncExecutor(20)) {
|
||||||
|
int x = loc.getBlockX() >> 4;
|
||||||
|
int z = loc.getBlockZ() >> 4;
|
||||||
|
|
||||||
|
int rad = engine.getMantle().getRadius();
|
||||||
|
var mantle = engine.getMantle().getMantle();
|
||||||
|
var chunkMap = new KMap<Position2, MantleChunk>();
|
||||||
|
ParallelQueueJob<Position2> prep = new ParallelQueueJob<>() {
|
||||||
|
@Override
|
||||||
|
public void execute(Position2 pos) {
|
||||||
|
var cpos = pos.add(x, z);
|
||||||
|
if (Math.abs(pos.getX()) <= radius && Math.abs(pos.getZ()) <= radius) {
|
||||||
|
mantle.deleteChunk(cpos.getX(), cpos.getZ());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
chunkMap.put(cpos, mantle.getChunk(cpos.getX(), cpos.getZ()));
|
||||||
|
mantle.deleteChunk(cpos.getX(), cpos.getZ());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "Preparing Mantle";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
for (int xx = -(radius + rad); xx <= radius + rad; xx++) {
|
||||||
|
for (int zz = -(radius + rad); zz <= radius + rad; zz++) {
|
||||||
|
prep.queue(new Position2(xx, zz));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CountDownLatch pLatch = new CountDownLatch(1);
|
||||||
|
prep.execute(sender(), pLatch::countDown);
|
||||||
|
pLatch.await();
|
||||||
|
|
||||||
|
|
||||||
|
ParallelQueueJob<Position2> job = new ParallelQueueJob<>() {
|
||||||
|
@Override
|
||||||
|
public void execute(Position2 p) {
|
||||||
|
plat.injectChunkReplacement(world, p.getX(), p.getZ(), executor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "Regenerating";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
for (int i = -radius; i <= radius; i++) {
|
||||||
|
for (int j = -radius; j <= radius; j++) {
|
||||||
|
job.queue(new Position2(i + x, j + z));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CountDownLatch latch = new CountDownLatch(1);
|
||||||
|
job.execute(sender(), latch::countDown);
|
||||||
|
latch.await();
|
||||||
|
|
||||||
|
int sections = mantle.getWorldHeight() >> 4;
|
||||||
|
chunkMap.forEach((pos, chunk) -> {
|
||||||
|
var c = mantle.getChunk(pos.getX(), pos.getZ()).use();
|
||||||
|
try {
|
||||||
|
c.copyFlags(chunk);
|
||||||
|
c.clear();
|
||||||
|
for (int y = 0; y < sections; y++) {
|
||||||
|
var slice = chunk.get(y);
|
||||||
|
if (slice == null) continue;
|
||||||
|
var s = c.getOrCreate(y);
|
||||||
|
slice.getSliceMap().forEach(s::putSlice);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
c.release();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (Throwable e) {
|
||||||
|
sender().sendMessage("Error while regenerating chunks");
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Decree(description = "Convert objects in the \"convert\" folder")
|
@Decree(description = "Convert objects in the \"convert\" folder")
|
||||||
@@ -332,6 +356,42 @@ public class CommandStudio implements DecreeExecutor {
|
|||||||
player().openInventory(inv);
|
player().openInventory(inv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Decree(description = "Calculate the chance for each region to generate", origin = DecreeOrigin.PLAYER)
|
||||||
|
public void regions(@Param(description = "The radius in chunks", defaultValue = "500") int radius) {
|
||||||
|
var engine = engine();
|
||||||
|
if (engine == null) {
|
||||||
|
sender().sendMessage(C.RED + "Only works in an Iris world!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var sender = sender();
|
||||||
|
var player = player();
|
||||||
|
Thread.ofVirtual()
|
||||||
|
.start(() -> {
|
||||||
|
int d = radius * 2;
|
||||||
|
KMap<String, AtomicInteger> data = new KMap<>();
|
||||||
|
engine.getDimension().getRegions().forEach(key -> data.put(key, new AtomicInteger(0)));
|
||||||
|
var multiBurst = new MultiBurst("Region Sampler");
|
||||||
|
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 regions"), 0);
|
||||||
|
new Spiraler(d, d, (x, z) -> executor.queue(() -> {
|
||||||
|
var region = engine.getRegion((x << 4) + 8, (z << 4) + 8);
|
||||||
|
data.computeIfAbsent(region.getLoadKey(), (k) -> new AtomicInteger(0))
|
||||||
|
.incrementAndGet();
|
||||||
|
completedTasks.incrementAndGet();
|
||||||
|
})).setOffset(loc.getBlockX(), loc.getBlockZ()).drain();
|
||||||
|
executor.complete();
|
||||||
|
multiBurst.close();
|
||||||
|
J.car(c);
|
||||||
|
|
||||||
|
sender.sendMessage(C.GREEN + "Done!");
|
||||||
|
var loader = engine.getData().getRegionLoader();
|
||||||
|
data.forEach((k, v) -> sender.sendMessage(C.GREEN + k + ": " + loader.load(k).getRarity() + " / " + Form.f((double) v.get() / totalTasks * 100, 2) + "%"));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Decree(description = "Get all structures in a radius of chunks", aliases = "dist", origin = DecreeOrigin.PLAYER)
|
@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) {
|
public void distances(@Param(description = "The radius in chunks") int radius) {
|
||||||
@@ -343,7 +403,7 @@ public class CommandStudio implements DecreeExecutor {
|
|||||||
var sender = sender();
|
var sender = sender();
|
||||||
int d = radius * 2;
|
int d = radius * 2;
|
||||||
KMap<String, KList<Position2>> data = new KMap<>();
|
KMap<String, KList<Position2>> data = new KMap<>();
|
||||||
var multiBurst = new MultiBurst("Distance Sampler", Thread.MIN_PRIORITY);
|
var multiBurst = new MultiBurst("Distance Sampler");
|
||||||
var executor = multiBurst.burst(radius * radius);
|
var executor = multiBurst.burst(radius * radius);
|
||||||
|
|
||||||
sender.sendMessage(C.GRAY + "Generating data...");
|
sender.sendMessage(C.GRAY + "Generating data...");
|
||||||
|
|||||||
@@ -1,82 +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.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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
package com.volmit.iris.core.commands;
|
package com.volmit.iris.core.commands;
|
||||||
|
|
||||||
|
import lombok.Synchronized;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
|
|
||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.Iris;
|
||||||
@@ -32,7 +33,8 @@ import com.volmit.iris.util.format.Form;
|
|||||||
|
|
||||||
@Decree(name = "updater", origin = DecreeOrigin.BOTH, description = "Iris World Updater")
|
@Decree(name = "updater", origin = DecreeOrigin.BOTH, description = "Iris World Updater")
|
||||||
public class CommandUpdater implements DecreeExecutor {
|
public class CommandUpdater implements DecreeExecutor {
|
||||||
private ChunkUpdater chunkUpdater;
|
private final Object lock = new Object();
|
||||||
|
private transient ChunkUpdater chunkUpdater;
|
||||||
|
|
||||||
@Decree(description = "Updates all chunk in the specified world")
|
@Decree(description = "Updates all chunk in the specified world")
|
||||||
public void start(
|
public void start(
|
||||||
@@ -43,19 +45,22 @@ public class CommandUpdater implements DecreeExecutor {
|
|||||||
sender().sendMessage(C.GOLD + "This is not an Iris world");
|
sender().sendMessage(C.GOLD + "This is not an Iris world");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (chunkUpdater != null) {
|
synchronized (lock) {
|
||||||
chunkUpdater.stop();
|
if (chunkUpdater != null) {
|
||||||
}
|
chunkUpdater.stop();
|
||||||
|
}
|
||||||
|
|
||||||
chunkUpdater = new ChunkUpdater(world);
|
chunkUpdater = new ChunkUpdater(world);
|
||||||
if (sender().isPlayer()) {
|
if (sender().isPlayer()) {
|
||||||
sender().sendMessage(C.GREEN + "Updating " + world.getName() + C.GRAY + " Total chunks: " + Form.f(chunkUpdater.getChunks()));
|
sender().sendMessage(C.GREEN + "Updating " + world.getName() + C.GRAY + " Total chunks: " + Form.f(chunkUpdater.getChunks()));
|
||||||
} else {
|
} else {
|
||||||
Iris.info(C.GREEN + "Updating " + world.getName() + C.GRAY + " Total chunks: " + Form.f(chunkUpdater.getChunks()));
|
Iris.info(C.GREEN + "Updating " + world.getName() + C.GRAY + " Total chunks: " + Form.f(chunkUpdater.getChunks()));
|
||||||
|
}
|
||||||
|
chunkUpdater.start();
|
||||||
}
|
}
|
||||||
chunkUpdater.start();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Synchronized("lock")
|
||||||
@Decree(description = "Pause the updater")
|
@Decree(description = "Pause the updater")
|
||||||
public void pause( ) {
|
public void pause( ) {
|
||||||
if (chunkUpdater == null) {
|
if (chunkUpdater == null) {
|
||||||
@@ -78,6 +83,7 @@ public class CommandUpdater implements DecreeExecutor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Synchronized("lock")
|
||||||
@Decree(description = "Stops the updater")
|
@Decree(description = "Stops the updater")
|
||||||
public void stop() {
|
public void stop() {
|
||||||
if (chunkUpdater == null) {
|
if (chunkUpdater == null) {
|
||||||
|
|||||||
@@ -40,7 +40,10 @@ import java.awt.*;
|
|||||||
import java.awt.event.KeyEvent;
|
import java.awt.event.KeyEvent;
|
||||||
import java.awt.event.KeyListener;
|
import java.awt.event.KeyListener;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
@@ -53,7 +56,7 @@ public class PregeneratorJob implements PregenListener {
|
|||||||
private static final Color COLOR_NETWORK_GENERATING = parseColor("#836b8c");
|
private static final Color COLOR_NETWORK_GENERATING = parseColor("#836b8c");
|
||||||
private static final Color COLOR_GENERATED = parseColor("#65c295");
|
private static final Color COLOR_GENERATED = parseColor("#65c295");
|
||||||
private static final Color COLOR_CLEANED = parseColor("#34eb93");
|
private static final Color COLOR_CLEANED = parseColor("#34eb93");
|
||||||
public static PregeneratorJob instance;
|
private static final AtomicReference<PregeneratorJob> instance = new AtomicReference<>();
|
||||||
private final MemoryMonitor monitor;
|
private final MemoryMonitor monitor;
|
||||||
private final PregenTask task;
|
private final PregenTask task;
|
||||||
private final boolean saving;
|
private final boolean saving;
|
||||||
@@ -64,14 +67,21 @@ public class PregeneratorJob implements PregenListener {
|
|||||||
private final Position2 max;
|
private final Position2 max;
|
||||||
private final ChronoLatch cl = new ChronoLatch(TimeUnit.MINUTES.toMillis(1));
|
private final ChronoLatch cl = new ChronoLatch(TimeUnit.MINUTES.toMillis(1));
|
||||||
private final Engine engine;
|
private final Engine engine;
|
||||||
|
private final ExecutorService service;
|
||||||
private JFrame frame;
|
private JFrame frame;
|
||||||
private PregenRenderer renderer;
|
private PregenRenderer renderer;
|
||||||
private int rgc = 0;
|
private int rgc = 0;
|
||||||
private String[] info;
|
private String[] info;
|
||||||
|
|
||||||
public PregeneratorJob(PregenTask task, PregeneratorMethod method, Engine engine) {
|
public PregeneratorJob(PregenTask task, PregeneratorMethod method, Engine engine) {
|
||||||
|
instance.updateAndGet(old -> {
|
||||||
|
if (old != null) {
|
||||||
|
old.pregenerator.close();
|
||||||
|
old.close();
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
});
|
||||||
this.engine = engine;
|
this.engine = engine;
|
||||||
instance = this;
|
|
||||||
monitor = new MemoryMonitor(50);
|
monitor = new MemoryMonitor(50);
|
||||||
saving = false;
|
saving = false;
|
||||||
info = new String[]{"Initializing..."};
|
info = new String[]{"Initializing..."};
|
||||||
@@ -96,40 +106,44 @@ public class PregeneratorJob implements PregenListener {
|
|||||||
}, "Iris Pregenerator");
|
}, "Iris Pregenerator");
|
||||||
t.setPriority(Thread.MIN_PRIORITY);
|
t.setPriority(Thread.MIN_PRIORITY);
|
||||||
t.start();
|
t.start();
|
||||||
|
service = Executors.newVirtualThreadPerTaskExecutor();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean shutdownInstance() {
|
public static boolean shutdownInstance() {
|
||||||
if (instance == null) {
|
PregeneratorJob inst = instance.get();
|
||||||
|
if (inst == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
J.a(() -> instance.pregenerator.close());
|
J.a(inst.pregenerator::close);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PregeneratorJob getInstance() {
|
public static PregeneratorJob getInstance() {
|
||||||
return instance;
|
return instance.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean pauseResume() {
|
public static boolean pauseResume() {
|
||||||
if (instance == null) {
|
PregeneratorJob inst = instance.get();
|
||||||
|
if (inst == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isPaused()) {
|
if (isPaused()) {
|
||||||
instance.pregenerator.resume();
|
inst.pregenerator.resume();
|
||||||
} else {
|
} else {
|
||||||
instance.pregenerator.pause();
|
inst.pregenerator.pause();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isPaused() {
|
public static boolean isPaused() {
|
||||||
if (instance == null) {
|
PregeneratorJob inst = instance.get();
|
||||||
|
if (inst == null) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return instance.paused();
|
return inst.paused();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Color parseColor(String c) {
|
private static Color parseColor(String c) {
|
||||||
@@ -179,7 +193,7 @@ public class PregeneratorJob implements PregenListener {
|
|||||||
J.a(() -> {
|
J.a(() -> {
|
||||||
pregenerator.close();
|
pregenerator.close();
|
||||||
close();
|
close();
|
||||||
instance = null;
|
instance.compareAndSet(this, null);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -219,10 +233,10 @@ public class PregeneratorJob implements PregenListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTick(double chunksPerSecond, double chunksPerMinute, double regionsPerMinute, double percent, int generated, int totalChunks, int chunksRemaining, long eta, long elapsed, String method) {
|
public void onTick(double chunksPerSecond, double chunksPerMinute, double regionsPerMinute, double percent, long generated, long totalChunks, long chunksRemaining, long eta, long elapsed, String method, boolean cached) {
|
||||||
info = new String[]{
|
info = new String[]{
|
||||||
(paused() ? "PAUSED" : (saving ? "Saving... " : "Generating")) + " " + Form.f(generated) + " of " + Form.f(totalChunks) + " (" + Form.pc(percent, 0) + " Complete)",
|
(paused() ? "PAUSED" : (saving ? "Saving... " : "Generating")) + " " + Form.f(generated) + " of " + Form.f(totalChunks) + " (" + Form.pc(percent, 0) + " Complete)",
|
||||||
"Speed: " + Form.f(chunksPerSecond, 0) + " Chunks/s, " + Form.f(regionsPerMinute, 1) + " Regions/m, " + Form.f(chunksPerMinute, 0) + " Chunks/m",
|
"Speed: " + (cached ? "Cached " : "") + Form.f(chunksPerSecond, 0) + " Chunks/s, " + Form.f(regionsPerMinute, 1) + " Regions/m, " + Form.f(chunksPerMinute, 0) + " Chunks/m",
|
||||||
Form.duration(eta, 2) + " Remaining " + " (" + Form.duration(elapsed, 2) + " Elapsed)",
|
Form.duration(eta, 2) + " Remaining " + " (" + Form.duration(elapsed, 2) + " Elapsed)",
|
||||||
"Generation Method: " + method,
|
"Generation Method: " + method,
|
||||||
"Memory: " + Form.memSize(monitor.getUsedBytes(), 2) + " (" + Form.pc(monitor.getUsagePercent(), 0) + ") Pressure: " + Form.memSize(monitor.getPressure(), 0) + "/s",
|
"Memory: " + Form.memSize(monitor.getUsedBytes(), 2) + " (" + Form.pc(monitor.getUsagePercent(), 0) + ") Pressure: " + Form.memSize(monitor.getPressure(), 0) + "/s",
|
||||||
@@ -240,13 +254,16 @@ public class PregeneratorJob implements PregenListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onChunkGenerated(int x, int z) {
|
public void onChunkGenerated(int x, int z, boolean cached) {
|
||||||
if (engine != null) {
|
if (renderer == null || frame == null || !frame.isVisible()) return;
|
||||||
draw(x, z, engine.draw((x << 4) + 8, (z << 4) + 8));
|
service.submit(() -> {
|
||||||
return;
|
if (engine != null) {
|
||||||
}
|
draw(x, z, engine.draw((x << 4) + 8, (z << 4) + 8));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
draw(x, z, COLOR_GENERATED);
|
draw(x, z, COLOR_GENERATED);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -304,8 +321,9 @@ public class PregeneratorJob implements PregenListener {
|
|||||||
@Override
|
@Override
|
||||||
public void onClose() {
|
public void onClose() {
|
||||||
close();
|
close();
|
||||||
instance = null;
|
instance.compareAndSet(this, null);
|
||||||
whenDone.forEach(Runnable::run);
|
whenDone.forEach(Runnable::run);
|
||||||
|
service.shutdownNow();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ import com.volmit.iris.engine.object.IrisWorld;
|
|||||||
import com.volmit.iris.util.collection.KList;
|
import com.volmit.iris.util.collection.KList;
|
||||||
import com.volmit.iris.util.collection.KMap;
|
import com.volmit.iris.util.collection.KMap;
|
||||||
import com.volmit.iris.util.collection.KSet;
|
import com.volmit.iris.util.collection.KSet;
|
||||||
import com.volmit.iris.util.data.registry.Attributes;
|
|
||||||
import com.volmit.iris.util.format.Form;
|
import com.volmit.iris.util.format.Form;
|
||||||
import com.volmit.iris.util.math.BlockPosition;
|
import com.volmit.iris.util.math.BlockPosition;
|
||||||
import com.volmit.iris.util.math.M;
|
import com.volmit.iris.util.math.M;
|
||||||
@@ -40,7 +39,6 @@ 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 org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.attribute.Attribute;
|
|
||||||
import org.bukkit.entity.LivingEntity;
|
import org.bukkit.entity.LivingEntity;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
@@ -415,8 +413,7 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
|||||||
}
|
}
|
||||||
|
|
||||||
private double getWorldX(double screenX) {
|
private double getWorldX(double screenX) {
|
||||||
//return (mscale * screenX) + ((oxp / scale) * mscale);
|
return (mscale * screenX) + ((oxp / scale) * mscale);
|
||||||
return (mscale * screenX) + ((oxp / scale));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private double getWorldZ(double screenZ) {
|
private double getWorldZ(double screenZ) {
|
||||||
@@ -486,6 +483,13 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
|||||||
hz += Math.abs(hz - lz) * 0.36;
|
hz += Math.abs(hz - lz) * 0.36;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Math.abs(lx - hx) < 0.5) {
|
||||||
|
hx = lx;
|
||||||
|
}
|
||||||
|
if (Math.abs(lz - hz) < 0.5) {
|
||||||
|
hz = lz;
|
||||||
|
}
|
||||||
|
|
||||||
if (centities.flip()) {
|
if (centities.flip()) {
|
||||||
J.s(() -> {
|
J.s(() -> {
|
||||||
synchronized (lastEntities) {
|
synchronized (lastEntities) {
|
||||||
@@ -510,8 +514,8 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
|||||||
int iscale = (int) scale;
|
int iscale = (int) scale;
|
||||||
g.setColor(Color.white);
|
g.setColor(Color.white);
|
||||||
g.clearRect(0, 0, w, h);
|
g.clearRect(0, 0, w, h);
|
||||||
int posX = (int) oxp;
|
double offsetX = oxp / scale;
|
||||||
int posZ = (int) ozp;
|
double offsetZ = ozp / scale;
|
||||||
m.set(3);
|
m.set(3);
|
||||||
|
|
||||||
for (int r = 0; r < Math.max(w, h); r += iscale) {
|
for (int r = 0; r < Math.max(w, h); r += iscale) {
|
||||||
@@ -520,10 +524,14 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
|||||||
int a = i - (w / 2);
|
int a = i - (w / 2);
|
||||||
int b = j - (h / 2);
|
int b = j - (h / 2);
|
||||||
if (a * a + b * b <= r * r) {
|
if (a * a + b * b <= r * r) {
|
||||||
BufferedImage t = getTile(gg, iscale, Math.floorDiv((posX / iscale) + i, iscale) * iscale, Math.floorDiv((posZ / iscale) + j, iscale) * iscale, m);
|
int tx = (int) (Math.floor((offsetX + i) / iscale) * iscale);
|
||||||
|
int tz = (int) (Math.floor((offsetZ + j) / iscale) * iscale);
|
||||||
|
BufferedImage t = getTile(gg, iscale, tx, tz, m);
|
||||||
|
|
||||||
if (t != null) {
|
if (t != null) {
|
||||||
g.drawImage(t, i - ((posX / iscale) % (iscale)), j - ((posZ / iscale) % (iscale)), iscale, iscale, (img, infoflags, x, y, width, height) -> true);
|
int rx = Math.floorMod((int) Math.floor(offsetX), iscale);
|
||||||
|
int rz = Math.floorMod((int) Math.floor(offsetZ), iscale);
|
||||||
|
g.drawImage(t, i - rx, j - rz, iscale, iscale, (img, infoflags, x, y, width, height) -> true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -651,8 +659,8 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
|||||||
private void animateTo(double wx, double wz) {
|
private void animateTo(double wx, double wz) {
|
||||||
double cx = getWorldX(getWidth() / 2);
|
double cx = getWorldX(getWidth() / 2);
|
||||||
double cz = getWorldZ(getHeight() / 2);
|
double cz = getWorldZ(getHeight() / 2);
|
||||||
ox += (wx - cx);
|
ox += ((wx - cx) / mscale) * scale;
|
||||||
oz += (wz - cz);
|
oz += ((wz - cz) / mscale) * scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderPosition(Graphics2D g, double x, double z) {
|
private void renderPosition(Graphics2D g, double x, double z) {
|
||||||
@@ -807,11 +815,28 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Iris.info("Blocks/Pixel: " + (mscale) + ", Blocks Wide: " + (w * mscale));
|
double m0 = mscale;
|
||||||
|
double m1 = m0 + ((0.25 * m0) * notches);
|
||||||
|
m1 = Math.max(m1, 0.00001);
|
||||||
|
if (m1 == m0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
positions.clear();
|
positions.clear();
|
||||||
fastpositions.clear();
|
fastpositions.clear();
|
||||||
mscale = mscale + ((0.25 * mscale) * notches);
|
|
||||||
mscale = Math.max(mscale, 0.00001);
|
Point p = e.getPoint();
|
||||||
|
double sx = p.getX();
|
||||||
|
double sz = p.getY();
|
||||||
|
|
||||||
|
double newOxp = scale * ((m0 / m1) * (sx + (oxp / scale)) - sx);
|
||||||
|
double newOzp = scale * ((m0 / m1) * (sz + (ozp / scale)) - sz);
|
||||||
|
|
||||||
|
mscale = m1;
|
||||||
|
oxp = newOxp;
|
||||||
|
ozp = newOzp;
|
||||||
|
ox = oxp;
|
||||||
|
oz = ozp;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -1,24 +1,37 @@
|
|||||||
package com.volmit.iris.core.link;
|
package com.volmit.iris.core.link;
|
||||||
|
|
||||||
|
import com.volmit.iris.core.link.data.DataType;
|
||||||
|
import com.volmit.iris.core.nms.container.BiomeColor;
|
||||||
|
import com.volmit.iris.core.nms.container.BlockProperty;
|
||||||
|
import com.volmit.iris.core.nms.container.Pair;
|
||||||
|
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.util.collection.KMap;
|
import com.volmit.iris.util.collection.KMap;
|
||||||
import com.volmit.iris.util.data.IrisCustomData;
|
import com.volmit.iris.util.data.IrisCustomData;
|
||||||
|
import com.volmit.iris.util.math.RNG;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Location;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.block.BlockFace;
|
||||||
import org.bukkit.block.data.BlockData;
|
import org.bukkit.block.data.BlockData;
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
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.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
import java.util.MissingResourceException;
|
import java.util.MissingResourceException;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public abstract class ExternalDataProvider {
|
public abstract class ExternalDataProvider implements Listener {
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private final String pluginId;
|
private final String pluginId;
|
||||||
@@ -53,7 +66,21 @@ public abstract class ExternalDataProvider {
|
|||||||
* @throws MissingResourceException when the blockId is invalid
|
* @throws MissingResourceException when the blockId is invalid
|
||||||
*/
|
*/
|
||||||
@NotNull
|
@NotNull
|
||||||
public abstract BlockData getBlockData(@NotNull Identifier blockId, @NotNull KMap<String, String> state) 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());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves a list of all {@link BlockProperty} objects associated with the specified block identifier.
|
||||||
|
*
|
||||||
|
* @param blockId The identifier of the block whose properties are to be retrieved. Must not be null.
|
||||||
|
* @return A list of {@link BlockProperty} objects representing the properties of the block.
|
||||||
|
* @throws MissingResourceException If the specified block identifier is invalid or cannot be found.
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
public List<BlockProperty> getBlockProperties(@NotNull Identifier blockId) throws MissingResourceException {
|
||||||
|
return List.of();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see ExternalDataProvider#getItemStack(Identifier)
|
* @see ExternalDataProvider#getItemStack(Identifier)
|
||||||
@@ -73,7 +100,9 @@ public abstract class ExternalDataProvider {
|
|||||||
* @throws MissingResourceException when the itemId is invalid
|
* @throws MissingResourceException when the itemId is invalid
|
||||||
*/
|
*/
|
||||||
@NotNull
|
@NotNull
|
||||||
public abstract ItemStack getItemStack(@NotNull Identifier itemId, @NotNull KMap<String, Object> customNbt) throws MissingResourceException;
|
public ItemStack getItemStack(@NotNull Identifier itemId, @NotNull KMap<String, Object> customNbt) throws MissingResourceException {
|
||||||
|
throw new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is used for placing blocks that need to use the plugins api
|
* This method is used for placing blocks that need to use the plugins api
|
||||||
@@ -85,9 +114,57 @@ public abstract class ExternalDataProvider {
|
|||||||
*/
|
*/
|
||||||
public void processUpdate(@NotNull Engine engine, @NotNull Block block, @NotNull Identifier blockId) {}
|
public void processUpdate(@NotNull Engine engine, @NotNull Block block, @NotNull Identifier blockId) {}
|
||||||
|
|
||||||
public abstract @NotNull Identifier[] getBlockTypes();
|
/**
|
||||||
|
* Spawns a mob in the specified location using the given engine and entity identifier.
|
||||||
|
*
|
||||||
|
* @param location The location in the world where the mob should spawn. Must not be null.
|
||||||
|
* @param entityId The identifier of the mob entity to spawn. Must not be null.
|
||||||
|
* @return The spawned {@link Entity} if successful, or null if the mob could not be spawned.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public Entity spawnMob(@NotNull Location location, @NotNull Identifier entityId) throws MissingResourceException {
|
||||||
|
throw new MissingResourceException("Failed to find Entity!", entityId.namespace(), entityId.key());
|
||||||
|
}
|
||||||
|
|
||||||
public abstract @NotNull Identifier[] getItemTypes();
|
public abstract @NotNull Collection<@NotNull Identifier> getTypes(@NotNull DataType dataType);
|
||||||
|
|
||||||
public abstract boolean isValidProvider(@NotNull Identifier id, boolean isItem);
|
public abstract boolean isValidProvider(@NotNull Identifier id, DataType dataType);
|
||||||
|
|
||||||
|
protected static Pair<Float, BlockFace> parseYawAndFace(@NotNull Engine engine, @NotNull Block block, @NotNull KMap<@NotNull String, @NotNull String> state) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Pair<>(yaw, face);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static List<BlockProperty> YAW_FACE_BIOME_PROPERTIES = List.of(
|
||||||
|
BlockProperty.ofEnum(BiomeColor.class, "matchBiome", null),
|
||||||
|
BlockProperty.ofBoolean("randomYaw", false),
|
||||||
|
BlockProperty.ofDouble("yaw", 0, 0, 360f, false, true),
|
||||||
|
BlockProperty.ofBoolean("randomFace", true),
|
||||||
|
new BlockProperty(
|
||||||
|
"face",
|
||||||
|
BlockFace.class,
|
||||||
|
BlockFace.NORTH,
|
||||||
|
Arrays.asList(BlockFace.values()).subList(0, BlockFace.values().length - 1),
|
||||||
|
BlockFace::name
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,76 +0,0 @@
|
|||||||
package com.volmit.iris.core.link;
|
|
||||||
|
|
||||||
import com.volmit.iris.Iris;
|
|
||||||
import com.volmit.iris.util.collection.KList;
|
|
||||||
import com.volmit.iris.util.collection.KMap;
|
|
||||||
import dev.lone.itemsadder.api.CustomBlock;
|
|
||||||
import dev.lone.itemsadder.api.CustomStack;
|
|
||||||
import org.bukkit.block.data.BlockData;
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.util.MissingResourceException;
|
|
||||||
|
|
||||||
public class ItemAdderDataProvider extends ExternalDataProvider {
|
|
||||||
|
|
||||||
private KList<String> itemNamespaces, blockNamespaces;
|
|
||||||
|
|
||||||
public ItemAdderDataProvider() {
|
|
||||||
super("ItemsAdder");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void init() {
|
|
||||||
this.itemNamespaces = new KList<>();
|
|
||||||
this.blockNamespaces = new KList<>();
|
|
||||||
|
|
||||||
for (Identifier i : getItemTypes()) {
|
|
||||||
itemNamespaces.addIfMissing(i.namespace());
|
|
||||||
}
|
|
||||||
for (Identifier i : getBlockTypes()) {
|
|
||||||
blockNamespaces.addIfMissing(i.namespace());
|
|
||||||
Iris.info("Found ItemAdder Block: " + i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public BlockData getBlockData(@NotNull Identifier blockId, @NotNull KMap<String, String> state) throws MissingResourceException {
|
|
||||||
return CustomBlock.getBaseBlockData(blockId.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public ItemStack getItemStack(@NotNull Identifier itemId, @NotNull KMap<String, Object> customNbt) throws MissingResourceException {
|
|
||||||
CustomStack stack = CustomStack.getInstance(itemId.toString());
|
|
||||||
if (stack == null) {
|
|
||||||
throw new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key());
|
|
||||||
}
|
|
||||||
return stack.getItemStack();
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public Identifier[] getBlockTypes() {
|
|
||||||
KList<Identifier> keys = new KList<>();
|
|
||||||
for (String s : CustomBlock.getNamespacedIdsInRegistry()) {
|
|
||||||
keys.add(Identifier.fromString(s));
|
|
||||||
}
|
|
||||||
return keys.toArray(new Identifier[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public Identifier[] getItemTypes() {
|
|
||||||
KList<Identifier> keys = new KList<>();
|
|
||||||
for (String s : CustomStack.getNamespacedIdsInRegistry()) {
|
|
||||||
keys.add(Identifier.fromString(s));
|
|
||||||
}
|
|
||||||
return keys.toArray(new Identifier[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isValidProvider(@NotNull Identifier id, boolean isItem) {
|
|
||||||
return isItem ? this.itemNamespaces.contains(id.namespace()) : this.blockNamespaces.contains(id.namespace());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -18,126 +18,60 @@
|
|||||||
|
|
||||||
package com.volmit.iris.core.link;
|
package com.volmit.iris.core.link;
|
||||||
|
|
||||||
import com.volmit.iris.Iris;
|
import lombok.SneakyThrows;
|
||||||
import com.volmit.iris.engine.object.IrisDimension;
|
|
||||||
import com.volmit.iris.util.collection.KMap;
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.WorldType;
|
import org.mvplugins.multiverse.core.MultiverseCoreApi;
|
||||||
import org.bukkit.plugin.Plugin;
|
import org.mvplugins.multiverse.core.world.MultiverseWorld;
|
||||||
|
import org.mvplugins.multiverse.core.world.WorldManager;
|
||||||
import java.lang.reflect.Field;
|
import org.mvplugins.multiverse.core.world.options.ImportWorldOptions;
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class MultiverseCoreLink {
|
public class MultiverseCoreLink {
|
||||||
private final KMap<String, String> worldNameTypes = new KMap<>();
|
private final boolean active;
|
||||||
|
|
||||||
public MultiverseCoreLink() {
|
public MultiverseCoreLink() {
|
||||||
|
active = Bukkit.getPluginManager().getPlugin("Multiverse-Core") != null;
|
||||||
}
|
|
||||||
|
|
||||||
public boolean addWorld(String worldName, IrisDimension dim, String seed) {
|
|
||||||
if (!isSupported()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
Plugin p = getMultiverse();
|
|
||||||
Object mvWorldManager = p.getClass().getDeclaredMethod("getMVWorldManager").invoke(p);
|
|
||||||
Method m = mvWorldManager.getClass().getDeclaredMethod("addWorld",
|
|
||||||
|
|
||||||
String.class, World.Environment.class, String.class, WorldType.class, Boolean.class, String.class, boolean.class);
|
|
||||||
boolean b = (boolean) m.invoke(mvWorldManager, worldName, dim.getEnvironment(), seed, WorldType.NORMAL, false, "Iris", false);
|
|
||||||
saveConfig();
|
|
||||||
return b;
|
|
||||||
} catch (Throwable e) {
|
|
||||||
Iris.reportError(e);
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public Map<String, ?> getList() {
|
|
||||||
try {
|
|
||||||
Plugin p = getMultiverse();
|
|
||||||
Object mvWorldManager = p.getClass().getDeclaredMethod("getMVWorldManager").invoke(p);
|
|
||||||
Field f = mvWorldManager.getClass().getDeclaredField("worldsFromTheConfig");
|
|
||||||
f.setAccessible(true);
|
|
||||||
return (Map<String, ?>) f.get(mvWorldManager);
|
|
||||||
} catch (Throwable e) {
|
|
||||||
Iris.reportError(e);
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeFromConfig(World world) {
|
public void removeFromConfig(World world) {
|
||||||
if (!isSupported()) {
|
removeFromConfig(world.getName());
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
getList().remove(world.getName());
|
|
||||||
saveConfig();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeFromConfig(String world) {
|
public void removeFromConfig(String world) {
|
||||||
if (!isSupported()) {
|
if (!active) return;
|
||||||
return;
|
var manager = worldManager();
|
||||||
|
manager.removeWorld(world).onSuccess(manager::saveWorldsConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
public void updateWorld(World bukkitWorld, String pack) {
|
||||||
|
if (!active) return;
|
||||||
|
var generator = "Iris:" + pack;
|
||||||
|
var manager = worldManager();
|
||||||
|
var world = manager.getWorld(bukkitWorld).getOrElse(() -> {
|
||||||
|
var options = ImportWorldOptions.worldName(bukkitWorld.getName())
|
||||||
|
.generator(generator)
|
||||||
|
.environment(bukkitWorld.getEnvironment())
|
||||||
|
.useSpawnAdjust(false);
|
||||||
|
return manager.importWorld(options).get();
|
||||||
|
});
|
||||||
|
|
||||||
|
world.setAutoLoad(false);
|
||||||
|
if (!generator.equals(world.getGenerator())) {
|
||||||
|
var field = MultiverseWorld.class.getDeclaredField("worldConfig");
|
||||||
|
field.setAccessible(true);
|
||||||
|
|
||||||
|
var config = field.get(world);
|
||||||
|
config.getClass()
|
||||||
|
.getDeclaredMethod("setGenerator", String.class)
|
||||||
|
.invoke(config, generator);
|
||||||
}
|
}
|
||||||
|
|
||||||
getList().remove(world);
|
manager.saveWorldsConfig();
|
||||||
saveConfig();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void saveConfig() {
|
private WorldManager worldManager() {
|
||||||
try {
|
var api = MultiverseCoreApi.get();
|
||||||
Plugin p = getMultiverse();
|
return api.getWorldManager();
|
||||||
Object mvWorldManager = p.getClass().getDeclaredMethod("getMVWorldManager").invoke(p);
|
|
||||||
mvWorldManager.getClass().getDeclaredMethod("saveWorldsConfig").invoke(mvWorldManager);
|
|
||||||
} catch (Throwable e) {
|
|
||||||
Iris.reportError(e);
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void assignWorldType(String worldName, String type) {
|
|
||||||
worldNameTypes.put(worldName, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getWorldNameType(String worldName, String defaultType) {
|
|
||||||
try {
|
|
||||||
String t = worldNameTypes.get(worldName);
|
|
||||||
return t == null ? defaultType : t;
|
|
||||||
} catch (Throwable e) {
|
|
||||||
Iris.reportError(e);
|
|
||||||
return defaultType;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isSupported() {
|
|
||||||
return getMultiverse() != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Plugin getMultiverse() {
|
|
||||||
|
|
||||||
return Bukkit.getPluginManager().getPlugin("Multiverse-Core");
|
|
||||||
}
|
|
||||||
|
|
||||||
public String envName(World.Environment environment) {
|
|
||||||
if (environment == null) {
|
|
||||||
return "normal";
|
|
||||||
}
|
|
||||||
|
|
||||||
return switch (environment) {
|
|
||||||
case NORMAL -> "normal";
|
|
||||||
case NETHER -> "nether";
|
|
||||||
case THE_END -> "end";
|
|
||||||
default -> environment.toString().toLowerCase();
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,60 +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 io.lumine.mythic.bukkit.MythicBukkit;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.entity.Entity;
|
|
||||||
import org.bukkit.plugin.Plugin;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class MythicMobsLink {
|
|
||||||
|
|
||||||
public MythicMobsLink() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isEnabled() {
|
|
||||||
return getPlugin() != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Plugin getPlugin() {
|
|
||||||
return Bukkit.getPluginManager().getPlugin("MythicMobs");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Spawn a mythic mob at this location
|
|
||||||
*
|
|
||||||
* @param mob The mob
|
|
||||||
* @param location The location
|
|
||||||
* @return The mob, or null if it can't be spawned
|
|
||||||
*/
|
|
||||||
public @Nullable
|
|
||||||
Entity spawnMob(String mob, Location location) {
|
|
||||||
return isEnabled() ? MythicBukkit.inst().getMobManager().spawnMob(mob, location).getEntity().getBukkitEntity() : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Collection<String> getMythicMobTypes() {
|
|
||||||
return isEnabled() ? MythicBukkit.inst().getMobManager().getMobNames() : List.of();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -47,6 +47,7 @@ public class WorldEditLink {
|
|||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
Iris.error("Could not get selection");
|
Iris.error("Could not get selection");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
Iris.reportError(e);
|
||||||
active.reset();
|
active.reset();
|
||||||
active.aquire(() -> false);
|
active.aquire(() -> false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,117 @@
|
|||||||
|
package com.volmit.iris.core.link.data;
|
||||||
|
|
||||||
|
import com.volmit.iris.core.link.ExternalDataProvider;
|
||||||
|
import com.volmit.iris.core.link.Identifier;
|
||||||
|
import com.volmit.iris.core.nms.container.BlockProperty;
|
||||||
|
import com.volmit.iris.core.service.ExternalDataSVC;
|
||||||
|
import com.volmit.iris.engine.framework.Engine;
|
||||||
|
import com.volmit.iris.util.collection.KMap;
|
||||||
|
import com.volmit.iris.util.data.B;
|
||||||
|
import com.volmit.iris.util.data.IrisCustomData;
|
||||||
|
import net.momirealms.craftengine.bukkit.api.CraftEngineBlocks;
|
||||||
|
import net.momirealms.craftengine.bukkit.api.CraftEngineFurniture;
|
||||||
|
import net.momirealms.craftengine.bukkit.api.CraftEngineItems;
|
||||||
|
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||||
|
import net.momirealms.craftengine.core.block.properties.BooleanProperty;
|
||||||
|
import net.momirealms.craftengine.core.block.properties.IntegerProperty;
|
||||||
|
import net.momirealms.craftengine.core.block.properties.Property;
|
||||||
|
import net.momirealms.craftengine.core.util.Key;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.block.data.BlockData;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.MissingResourceException;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
public class CraftEngineDataProvider extends ExternalDataProvider {
|
||||||
|
|
||||||
|
public CraftEngineDataProvider() {
|
||||||
|
super("CraftEngine");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull List<BlockProperty> getBlockProperties(@NotNull Identifier blockId) throws MissingResourceException {
|
||||||
|
var block = CraftEngineBlocks.byId(Key.of(blockId.namespace(), blockId.key()));
|
||||||
|
if (block == null) throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
|
||||||
|
return block.properties()
|
||||||
|
.stream()
|
||||||
|
.map(CraftEngineDataProvider::convert)
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull ItemStack getItemStack(@NotNull Identifier itemId, @NotNull KMap<String, Object> customNbt) throws MissingResourceException {
|
||||||
|
var item = CraftEngineItems.byId(Key.of(itemId.namespace(), itemId.key()));
|
||||||
|
if (item == null) throw new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key());
|
||||||
|
return item.buildItemStack();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull BlockData getBlockData(@NotNull Identifier blockId, @NotNull KMap<String, String> state) throws MissingResourceException {
|
||||||
|
var key = Key.of(blockId.namespace(), blockId.key());
|
||||||
|
if (CraftEngineBlocks.byId(key) == null && CraftEngineFurniture.byId(key) == null)
|
||||||
|
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
|
||||||
|
return new IrisCustomData(B.getAir(), ExternalDataSVC.buildState(blockId, state));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void processUpdate(@NotNull Engine engine, @NotNull Block block, @NotNull Identifier blockId) {
|
||||||
|
var pair = ExternalDataSVC.parseState(blockId);
|
||||||
|
var key = Key.of(blockId.namespace(), blockId.key());
|
||||||
|
var state = pair.getB();
|
||||||
|
|
||||||
|
var customBlock = CraftEngineBlocks.byId(key);
|
||||||
|
if (customBlock != null) {
|
||||||
|
ImmutableBlockState blockState = customBlock.defaultState();
|
||||||
|
|
||||||
|
for (var entry : state.entrySet()) {
|
||||||
|
var property = customBlock.getProperty(entry.getKey());
|
||||||
|
if (property == null) continue;
|
||||||
|
var tag = property.optional(entry.getValue()).orElse(null);
|
||||||
|
if (tag == null) continue;
|
||||||
|
blockState = ImmutableBlockState.with(blockState, property, tag);
|
||||||
|
}
|
||||||
|
CraftEngineBlocks.place(block.getLocation(), blockState, false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var furniture = CraftEngineFurniture.byId(key);
|
||||||
|
if (furniture == null) return;
|
||||||
|
CraftEngineFurniture.place(block.getLocation(), furniture, furniture.getAnyAnchorType(), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull Collection<@NotNull Identifier> getTypes(@NotNull DataType dataType) {
|
||||||
|
return (switch (dataType) {
|
||||||
|
case ENTITY -> Stream.<Key>empty();
|
||||||
|
case ITEM -> CraftEngineItems.loadedItems().keySet().stream();
|
||||||
|
case BLOCK -> Stream.concat(CraftEngineBlocks.loadedBlocks().keySet().stream(),
|
||||||
|
CraftEngineFurniture.loadedFurniture().keySet().stream());
|
||||||
|
}).map(key -> new Identifier(key.namespace(), key.value())).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isValidProvider(@NotNull Identifier id, DataType dataType) {
|
||||||
|
Key key = Key.of(id.namespace(), id.key());
|
||||||
|
return switch (dataType) {
|
||||||
|
case ENTITY -> false;
|
||||||
|
case ITEM -> CraftEngineItems.byId(key) != null;
|
||||||
|
case BLOCK -> (CraftEngineBlocks.byId(key) != null || CraftEngineFurniture.byId(key) != null);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <T extends Comparable<T>> BlockProperty convert(Property<T> raw) {
|
||||||
|
return switch (raw) {
|
||||||
|
case BooleanProperty property -> BlockProperty.ofBoolean(property.name(), property.defaultValue());
|
||||||
|
case IntegerProperty property -> BlockProperty.ofLong(property.name(), property.defaultValue(), property.min, property.max, false, false);
|
||||||
|
default -> new BlockProperty(raw.name(), raw.valueClass(), raw.defaultValue(), raw.possibleValues(), raw::valueName);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package com.volmit.iris.core.link.data;
|
||||||
|
|
||||||
|
import com.volmit.iris.core.link.ExternalDataProvider;
|
||||||
|
import com.volmit.iris.core.link.Identifier;
|
||||||
|
|
||||||
|
import java.util.MissingResourceException;
|
||||||
|
import java.util.function.BiPredicate;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
public enum DataType implements BiPredicate<ExternalDataProvider, Identifier> {
|
||||||
|
ITEM,
|
||||||
|
BLOCK,
|
||||||
|
ENTITY;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean test(ExternalDataProvider dataProvider, Identifier identifier) {
|
||||||
|
if (!dataProvider.isValidProvider(identifier, this)) return false;
|
||||||
|
try {
|
||||||
|
switch (this) {
|
||||||
|
case ITEM -> dataProvider.getItemStack(identifier);
|
||||||
|
case BLOCK -> dataProvider.getBlockData(identifier);
|
||||||
|
case ENTITY -> {}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} catch (MissingResourceException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Predicate<Identifier> asPredicate(ExternalDataProvider dataProvider) {
|
||||||
|
return i -> test(dataProvider, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,16 +1,18 @@
|
|||||||
package com.volmit.iris.core.link;
|
package com.volmit.iris.core.link.data;
|
||||||
|
|
||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.Iris;
|
||||||
import com.volmit.iris.util.collection.KList;
|
import com.volmit.iris.core.link.ExternalDataProvider;
|
||||||
|
import com.volmit.iris.core.link.Identifier;
|
||||||
import com.volmit.iris.util.collection.KMap;
|
import com.volmit.iris.util.collection.KMap;
|
||||||
import com.volmit.iris.util.reflect.WrappedField;
|
import com.volmit.iris.util.reflect.WrappedField;
|
||||||
import com.willfp.ecoitems.items.EcoItem;
|
import com.willfp.ecoitems.items.EcoItem;
|
||||||
import com.willfp.ecoitems.items.EcoItems;
|
import com.willfp.ecoitems.items.EcoItems;
|
||||||
import org.bukkit.NamespacedKey;
|
import org.bukkit.NamespacedKey;
|
||||||
import org.bukkit.block.data.BlockData;
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
import java.util.MissingResourceException;
|
import java.util.MissingResourceException;
|
||||||
|
|
||||||
public class EcoItemsDataProvider extends ExternalDataProvider {
|
public class EcoItemsDataProvider extends ExternalDataProvider {
|
||||||
@@ -34,12 +36,6 @@ public class EcoItemsDataProvider extends ExternalDataProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@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
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public ItemStack getItemStack(@NotNull Identifier itemId, @NotNull KMap<String, Object> customNbt) throws MissingResourceException {
|
public ItemStack getItemStack(@NotNull Identifier itemId, @NotNull KMap<String, Object> customNbt) throws MissingResourceException {
|
||||||
@@ -48,30 +44,18 @@ public class EcoItemsDataProvider extends ExternalDataProvider {
|
|||||||
return itemStack.get(item).clone();
|
return itemStack.get(item).clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
@Override
|
||||||
public Identifier[] getBlockTypes() {
|
public @NotNull Collection<@NotNull Identifier> getTypes(@NotNull DataType dataType) {
|
||||||
return new Identifier[0];
|
if (dataType != DataType.ITEM) return List.of();
|
||||||
}
|
return EcoItems.INSTANCE.values()
|
||||||
|
.stream()
|
||||||
@NotNull
|
.map(x -> Identifier.fromNamespacedKey(id.get(x)))
|
||||||
@Override
|
.filter(dataType.asPredicate(this))
|
||||||
public Identifier[] getItemTypes() {
|
.toList();
|
||||||
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
|
@Override
|
||||||
public boolean isValidProvider(@NotNull Identifier id, boolean isItem) {
|
public boolean isValidProvider(@NotNull Identifier id, DataType dataType) {
|
||||||
return id.namespace().equalsIgnoreCase("ecoitems") && isItem;
|
return id.namespace().equalsIgnoreCase("ecoitems") && dataType == DataType.ITEM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,13 +1,15 @@
|
|||||||
package com.volmit.iris.core.link;
|
package com.volmit.iris.core.link.data;
|
||||||
|
|
||||||
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.core.link.ExternalDataProvider;
|
||||||
|
import com.volmit.iris.core.link.Identifier;
|
||||||
import com.volmit.iris.util.collection.KMap;
|
import com.volmit.iris.util.collection.KMap;
|
||||||
import org.bukkit.block.data.BlockData;
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
import java.util.MissingResourceException;
|
import java.util.MissingResourceException;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
@@ -21,12 +23,6 @@ public class ExecutableItemsDataProvider extends ExternalDataProvider {
|
|||||||
Iris.info("Setting up ExecutableItems Link...");
|
Iris.info("Setting up ExecutableItems Link...");
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public BlockData getBlockData(@NotNull Identifier blockId, @NotNull KMap<String, String> state) throws MissingResourceException {
|
|
||||||
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public ItemStack getItemStack(@NotNull Identifier itemId, @NotNull KMap<String, Object> customNbt) throws MissingResourceException {
|
public ItemStack getItemStack(@NotNull Identifier itemId, @NotNull KMap<String, Object> customNbt) throws MissingResourceException {
|
||||||
@@ -35,30 +31,19 @@ public class ExecutableItemsDataProvider extends ExternalDataProvider {
|
|||||||
.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 @NotNull Collection<@NotNull Identifier> getTypes(@NotNull DataType dataType) {
|
||||||
return new Identifier[0];
|
if (dataType != DataType.ITEM) return List.of();
|
||||||
}
|
return ExecutableItemsAPI.getExecutableItemsManager()
|
||||||
|
.getExecutableItemIdsList()
|
||||||
@NotNull
|
.stream()
|
||||||
@Override
|
.map(name -> new Identifier("executable_items", name))
|
||||||
public Identifier[] getItemTypes() {
|
.filter(dataType.asPredicate(this))
|
||||||
KList<Identifier> names = new KList<>();
|
.toList();
|
||||||
for (String name : ExecutableItemsAPI.getExecutableItemsManager().getExecutableItemIdsList()) {
|
|
||||||
try {
|
|
||||||
Identifier key = new Identifier("executable_items", name);
|
|
||||||
if (getItemStack(key) != null)
|
|
||||||
names.add(key);
|
|
||||||
} catch (MissingResourceException ignored) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return names.toArray(new Identifier[0]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isValidProvider(@NotNull Identifier key, boolean isItem) {
|
public boolean isValidProvider(@NotNull Identifier key, DataType dataType) {
|
||||||
return key.namespace().equalsIgnoreCase("executable_items") && isItem;
|
return key.namespace().equalsIgnoreCase("executable_items") && dataType == DataType.ITEM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,10 +1,11 @@
|
|||||||
package com.volmit.iris.core.link;
|
package com.volmit.iris.core.link.data;
|
||||||
|
|
||||||
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.link.ExternalDataProvider;
|
||||||
|
import com.volmit.iris.core.link.Identifier;
|
||||||
import com.volmit.iris.core.service.ExternalDataSVC;
|
import com.volmit.iris.core.service.ExternalDataSVC;
|
||||||
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.data.IrisCustomData;
|
import com.volmit.iris.util.data.IrisCustomData;
|
||||||
import com.volmit.iris.util.reflect.WrappedField;
|
import com.volmit.iris.util.reflect.WrappedField;
|
||||||
@@ -18,6 +19,8 @@ import org.bukkit.block.data.type.Leaves;
|
|||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.MissingResourceException;
|
import java.util.MissingResourceException;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
@@ -89,41 +92,20 @@ public class HMCLeavesDataProvider extends ExternalDataProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
@Override
|
||||||
public Identifier[] getBlockTypes() {
|
public @NotNull Collection<@NotNull Identifier> getTypes(@NotNull DataType dataType) {
|
||||||
KList<Identifier> names = new KList<>();
|
if (dataType == DataType.ENTITY) return List.of();
|
||||||
for (String name : blockDataMap.keySet()) {
|
return (dataType == DataType.BLOCK ? blockDataMap.keySet() : itemDataField.keySet())
|
||||||
try {
|
.stream()
|
||||||
Identifier key = new Identifier("hmcleaves", name);
|
.map(x -> new Identifier("hmcleaves", x))
|
||||||
if (getBlockData(key) != null)
|
.filter(dataType.asPredicate(this))
|
||||||
names.add(key);
|
.toList();
|
||||||
} 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
|
@Override
|
||||||
public boolean isValidProvider(@NotNull Identifier id, boolean isItem) {
|
public boolean isValidProvider(@NotNull Identifier id, DataType dataType) {
|
||||||
return (isItem ? itemDataField.keySet() : blockDataMap.keySet()).contains(id.key());
|
if (dataType == DataType.ENTITY) return false;
|
||||||
|
return (dataType == DataType.ITEM ? itemDataField.keySet() : blockDataMap.keySet()).contains(id.key());
|
||||||
}
|
}
|
||||||
|
|
||||||
private <C, T> Map<String, T> getMap(C config, String name) {
|
private <C, T> Map<String, T> getMap(C config, String name) {
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
package com.volmit.iris.core.link.data;
|
||||||
|
|
||||||
|
import com.volmit.iris.Iris;
|
||||||
|
import com.volmit.iris.core.link.ExternalDataProvider;
|
||||||
|
import com.volmit.iris.core.link.Identifier;
|
||||||
|
import com.volmit.iris.engine.framework.Engine;
|
||||||
|
import com.volmit.iris.util.collection.KMap;
|
||||||
|
import com.volmit.iris.util.collection.KSet;
|
||||||
|
import com.volmit.iris.util.data.IrisCustomData;
|
||||||
|
import dev.lone.itemsadder.api.CustomBlock;
|
||||||
|
import dev.lone.itemsadder.api.CustomStack;
|
||||||
|
import dev.lone.itemsadder.api.Events.ItemsAdderLoadDataEvent;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.block.data.BlockData;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.MissingResourceException;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class ItemAdderDataProvider extends ExternalDataProvider {
|
||||||
|
|
||||||
|
private final KSet<String> itemNamespaces = new KSet<>();
|
||||||
|
private final KSet<String> blockNamespaces = new KSet<>();
|
||||||
|
|
||||||
|
public ItemAdderDataProvider() {
|
||||||
|
super("ItemsAdder");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init() {
|
||||||
|
updateNamespaces();
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onLoadData(ItemsAdderLoadDataEvent event) {
|
||||||
|
updateNamespaces();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public BlockData getBlockData(@NotNull Identifier blockId, @NotNull KMap<String, String> state) throws MissingResourceException {
|
||||||
|
CustomBlock block = CustomBlock.getInstance(blockId.toString());
|
||||||
|
if (block == null) {
|
||||||
|
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
|
||||||
|
}
|
||||||
|
return new IrisCustomData(block.getBaseBlockData(), blockId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public ItemStack getItemStack(@NotNull Identifier itemId, @NotNull KMap<String, Object> customNbt) throws MissingResourceException {
|
||||||
|
CustomStack stack = CustomStack.getInstance(itemId.toString());
|
||||||
|
if (stack == null) {
|
||||||
|
throw new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key());
|
||||||
|
}
|
||||||
|
return stack.getItemStack();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void processUpdate(@NotNull Engine engine, @NotNull Block block, @NotNull Identifier blockId) {
|
||||||
|
CustomBlock custom;
|
||||||
|
if ((custom = CustomBlock.place(blockId.toString(), block.getLocation())) == null)
|
||||||
|
return;
|
||||||
|
block.setBlockData(custom.getBaseBlockData(), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull Collection<@NotNull Identifier> getTypes(@NotNull DataType dataType) {
|
||||||
|
return switch (dataType) {
|
||||||
|
case ENTITY -> List.of();
|
||||||
|
case ITEM -> CustomStack.getNamespacedIdsInRegistry()
|
||||||
|
.stream()
|
||||||
|
.map(Identifier::fromString)
|
||||||
|
.toList();
|
||||||
|
case BLOCK -> CustomBlock.getNamespacedIdsInRegistry()
|
||||||
|
.stream()
|
||||||
|
.map(Identifier::fromString)
|
||||||
|
.toList();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateNamespaces() {
|
||||||
|
try {
|
||||||
|
updateNamespaces(DataType.ITEM);
|
||||||
|
updateNamespaces(DataType.BLOCK);
|
||||||
|
} catch (Throwable e) {
|
||||||
|
Iris.warn("Failed to update ItemAdder namespaces: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateNamespaces(DataType dataType) {
|
||||||
|
var namespaces = getTypes(dataType).stream().map(Identifier::namespace).collect(Collectors.toSet());
|
||||||
|
var currentNamespaces = dataType == DataType.ITEM ? itemNamespaces : blockNamespaces;
|
||||||
|
currentNamespaces.removeIf(n -> !namespaces.contains(n));
|
||||||
|
currentNamespaces.addAll(namespaces);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isValidProvider(@NotNull Identifier id, DataType dataType) {
|
||||||
|
if (dataType == DataType.ENTITY) return false;
|
||||||
|
return dataType == DataType.ITEM ? itemNamespaces.contains(id.namespace()) : blockNamespaces.contains(id.namespace());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
package com.volmit.iris.core.link.data;
|
||||||
|
|
||||||
|
import com.volmit.iris.core.link.ExternalDataProvider;
|
||||||
|
import com.volmit.iris.core.link.Identifier;
|
||||||
|
import com.volmit.iris.core.service.ExternalDataSVC;
|
||||||
|
import com.volmit.iris.engine.framework.Engine;
|
||||||
|
import com.volmit.iris.util.collection.KMap;
|
||||||
|
import com.volmit.iris.util.data.B;
|
||||||
|
import com.volmit.iris.util.data.IrisCustomData;
|
||||||
|
import me.kryniowesegryderiusz.kgenerators.Main;
|
||||||
|
import me.kryniowesegryderiusz.kgenerators.api.KGeneratorsAPI;
|
||||||
|
import me.kryniowesegryderiusz.kgenerators.generators.locations.objects.GeneratorLocation;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.block.data.BlockData;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.MissingResourceException;
|
||||||
|
|
||||||
|
public class KGeneratorsDataProvider extends ExternalDataProvider {
|
||||||
|
public KGeneratorsDataProvider() {
|
||||||
|
super("KGenerators");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull BlockData getBlockData(@NotNull Identifier blockId, @NotNull KMap<String, String> state) throws MissingResourceException {
|
||||||
|
if (Main.getGenerators().get(blockId.key()) == null) throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
|
||||||
|
return new IrisCustomData(Material.STRUCTURE_VOID.createBlockData(), ExternalDataSVC.buildState(blockId, state));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull ItemStack getItemStack(@NotNull Identifier itemId, @NotNull KMap<String, Object> customNbt) throws MissingResourceException {
|
||||||
|
var gen = Main.getGenerators().get(itemId.key());
|
||||||
|
if (gen == null) throw new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key());
|
||||||
|
return gen.getGeneratorItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void processUpdate(@NotNull Engine engine, @NotNull Block block, @NotNull Identifier blockId) {
|
||||||
|
if (block.getType() != Material.STRUCTURE_VOID) return;
|
||||||
|
var existing = KGeneratorsAPI.getLoadedGeneratorLocation(block.getLocation());
|
||||||
|
if (existing != null) return;
|
||||||
|
block.setBlockData(B.getAir(), false);
|
||||||
|
var gen = Main.getGenerators().get(blockId.key());
|
||||||
|
if (gen == null) return;
|
||||||
|
var loc = new GeneratorLocation(-1, gen, block.getLocation(), Main.getPlacedGenerators().getChunkInfo(block.getChunk()), null, null);
|
||||||
|
Main.getDatabases().getDb().saveGenerator(loc);
|
||||||
|
Main.getPlacedGenerators().addLoaded(loc);
|
||||||
|
Main.getSchedules().schedule(loc, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull Collection<@NotNull Identifier> getTypes(@NotNull DataType dataType) {
|
||||||
|
if (dataType == DataType.ENTITY) return List.of();
|
||||||
|
return Main.getGenerators().getAll().stream()
|
||||||
|
.map(gen -> new Identifier("kgenerators", gen.getId()))
|
||||||
|
.filter(dataType.asPredicate(this))
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isValidProvider(@NotNull Identifier id, DataType dataType) {
|
||||||
|
if (dataType == DataType.ENTITY) return false;
|
||||||
|
return "kgenerators".equalsIgnoreCase(id.namespace());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,21 +1,24 @@
|
|||||||
package com.volmit.iris.core.link;
|
package com.volmit.iris.core.link.data;
|
||||||
|
|
||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.Iris;
|
||||||
import com.volmit.iris.util.collection.KList;
|
import com.volmit.iris.core.link.ExternalDataProvider;
|
||||||
|
import com.volmit.iris.core.link.Identifier;
|
||||||
import com.volmit.iris.util.collection.KMap;
|
import com.volmit.iris.util.collection.KMap;
|
||||||
import com.volmit.iris.util.scheduling.J;
|
import com.volmit.iris.util.scheduling.J;
|
||||||
import net.Indyuce.mmoitems.MMOItems;
|
import net.Indyuce.mmoitems.MMOItems;
|
||||||
import net.Indyuce.mmoitems.api.ItemTier;
|
import net.Indyuce.mmoitems.api.ItemTier;
|
||||||
import net.Indyuce.mmoitems.api.Type;
|
|
||||||
import net.Indyuce.mmoitems.api.block.CustomBlock;
|
import net.Indyuce.mmoitems.api.block.CustomBlock;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
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 org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
import java.util.MissingResourceException;
|
import java.util.MissingResourceException;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public class MMOItemsDataProvider extends ExternalDataProvider {
|
public class MMOItemsDataProvider extends ExternalDataProvider {
|
||||||
|
|
||||||
@@ -85,52 +88,35 @@ public class MMOItemsDataProvider extends ExternalDataProvider {
|
|||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
@Override
|
||||||
public Identifier[] getBlockTypes() {
|
public @NotNull Collection<@NotNull Identifier> getTypes(@NotNull DataType dataType) {
|
||||||
KList<Identifier> names = new KList<>();
|
return switch (dataType) {
|
||||||
for (Integer id : api().getCustomBlocks().getBlockIds()) {
|
case ENTITY -> List.of();
|
||||||
try {
|
case BLOCK -> api().getCustomBlocks().getBlockIds().stream().map(id -> new Identifier("mmoitems", String.valueOf(id)))
|
||||||
Identifier key = new Identifier("mmoitems", String.valueOf(id));
|
.filter(dataType.asPredicate(this))
|
||||||
if (getBlockData(key) != null)
|
.toList();
|
||||||
names.add(key);
|
case ITEM -> {
|
||||||
} catch (MissingResourceException ignored) {
|
Supplier<Collection<Identifier>> supplier = () -> api().getTypes()
|
||||||
}
|
.getAll()
|
||||||
}
|
.stream()
|
||||||
return names.toArray(new Identifier[0]);
|
.flatMap(type -> api()
|
||||||
}
|
.getTemplates()
|
||||||
|
.getTemplateNames(type)
|
||||||
|
.stream()
|
||||||
|
.map(name -> new Identifier("mmoitems_" + type.getId(), name)))
|
||||||
|
.filter(dataType.asPredicate(this))
|
||||||
|
.toList();
|
||||||
|
|
||||||
@NotNull
|
if (Bukkit.isPrimaryThread()) yield supplier.get();
|
||||||
@Override
|
else yield J.sfut(supplier).join();
|
||||||
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
|
@Override
|
||||||
public boolean isValidProvider(@NotNull Identifier id, boolean isItem) {
|
public boolean isValidProvider(@NotNull Identifier id, DataType dataType) {
|
||||||
return isItem ? id.namespace().split("_", 2).length == 2 : id.namespace().equals("mmoitems");
|
if (dataType == DataType.ENTITY) return false;
|
||||||
|
return dataType == DataType.ITEM ? id.namespace().split("_", 2).length == 2 : id.namespace().equals("mmoitems");
|
||||||
}
|
}
|
||||||
|
|
||||||
private MMOItems api() {
|
private MMOItems api() {
|
||||||
@@ -16,19 +16,19 @@
|
|||||||
* 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.link;
|
package com.volmit.iris.core.link.data;
|
||||||
|
|
||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.Iris;
|
||||||
|
import com.volmit.iris.core.link.ExternalDataProvider;
|
||||||
|
import com.volmit.iris.core.link.Identifier;
|
||||||
import com.volmit.iris.core.nms.INMS;
|
import com.volmit.iris.core.nms.INMS;
|
||||||
import com.volmit.iris.core.nms.container.BiomeColor;
|
import com.volmit.iris.core.nms.container.BiomeColor;
|
||||||
|
import com.volmit.iris.core.nms.container.BlockProperty;
|
||||||
import com.volmit.iris.core.service.ExternalDataSVC;
|
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.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.data.B;
|
import com.volmit.iris.util.data.B;
|
||||||
import com.volmit.iris.util.data.IrisCustomData;
|
import com.volmit.iris.util.data.IrisCustomData;
|
||||||
import com.volmit.iris.util.math.RNG;
|
|
||||||
import io.lumine.mythic.bukkit.BukkitAdapter;
|
import io.lumine.mythic.bukkit.BukkitAdapter;
|
||||||
import io.lumine.mythic.bukkit.utils.serialize.Chroma;
|
import io.lumine.mythic.bukkit.utils.serialize.Chroma;
|
||||||
import io.lumine.mythiccrucible.MythicCrucible;
|
import io.lumine.mythiccrucible.MythicCrucible;
|
||||||
@@ -37,11 +37,12 @@ import io.lumine.mythiccrucible.items.ItemManager;
|
|||||||
import io.lumine.mythiccrucible.items.blocks.CustomBlockItemContext;
|
import io.lumine.mythiccrucible.items.blocks.CustomBlockItemContext;
|
||||||
import io.lumine.mythiccrucible.items.furniture.FurnitureItemContext;
|
import io.lumine.mythiccrucible.items.furniture.FurnitureItemContext;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.block.BlockFace;
|
|
||||||
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 org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
import java.util.MissingResourceException;
|
import java.util.MissingResourceException;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
@@ -78,6 +79,19 @@ public class MythicCrucibleDataProvider extends ExternalDataProvider {
|
|||||||
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
|
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull List<BlockProperty> getBlockProperties(@NotNull Identifier blockId) throws MissingResourceException {
|
||||||
|
CrucibleItem crucibleItem = this.itemManager.getItem(blockId.key())
|
||||||
|
.orElseThrow(() -> new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key()));
|
||||||
|
|
||||||
|
if (crucibleItem.getFurnitureData() != null) {
|
||||||
|
return YAW_FACE_BIOME_PROPERTIES;
|
||||||
|
} else if (crucibleItem.getBlockData() != null) {
|
||||||
|
return List.of();
|
||||||
|
}
|
||||||
|
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public ItemStack getItemStack(@NotNull Identifier itemId, @NotNull KMap<String, Object> customNbt) throws MissingResourceException {
|
public ItemStack getItemStack(@NotNull Identifier itemId, @NotNull KMap<String, Object> customNbt) throws MissingResourceException {
|
||||||
@@ -88,69 +102,27 @@ public class MythicCrucibleDataProvider extends ExternalDataProvider {
|
|||||||
.generateItemStack(1));
|
.generateItemStack(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
@Override
|
||||||
public Identifier[] getBlockTypes() {
|
public @NotNull Collection<@NotNull Identifier> getTypes(@NotNull DataType dataType) {
|
||||||
KList<Identifier> names = new KList<>();
|
return itemManager.getItems()
|
||||||
for (CrucibleItem item : this.itemManager.getItems()) {
|
.stream()
|
||||||
if (item.getBlockData() == null) continue;
|
.map(i -> new Identifier("crucible", i.getInternalName()))
|
||||||
try {
|
.filter(dataType.asPredicate(this))
|
||||||
Identifier key = new Identifier("crucible", item.getInternalName());
|
.toList();
|
||||||
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
|
@Override
|
||||||
public void processUpdate(@NotNull Engine engine, @NotNull Block block, @NotNull Identifier blockId) {
|
public void processUpdate(@NotNull Engine engine, @NotNull Block block, @NotNull Identifier blockId) {
|
||||||
var pair = ExternalDataSVC.parseState(blockId);
|
var parsedState = ExternalDataSVC.parseState(blockId);
|
||||||
var state = pair.getB();
|
var state = parsedState.getB();
|
||||||
blockId = pair.getA();
|
blockId = parsedState.getA();
|
||||||
|
|
||||||
Optional<CrucibleItem> item = itemManager.getItem(blockId.key());
|
Optional<CrucibleItem> item = itemManager.getItem(blockId.key());
|
||||||
if (item.isEmpty()) return;
|
if (item.isEmpty()) return;
|
||||||
FurnitureItemContext furniture = item.get().getFurnitureData();
|
FurnitureItemContext furniture = item.get().getFurnitureData();
|
||||||
if (furniture == null) return;
|
if (furniture == null) return;
|
||||||
|
|
||||||
float yaw = 0;
|
var pair = parseYawAndFace(engine, block, state);
|
||||||
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;
|
BiomeColor type = null;
|
||||||
Chroma color = null;
|
Chroma color = null;
|
||||||
try {
|
try {
|
||||||
@@ -161,11 +133,12 @@ public class MythicCrucibleDataProvider extends ExternalDataProvider {
|
|||||||
if (biomeColor == null) return;
|
if (biomeColor == null) return;
|
||||||
color = Chroma.of(biomeColor.getRGB());
|
color = Chroma.of(biomeColor.getRGB());
|
||||||
}
|
}
|
||||||
furniture.place(block, face, yaw, color);
|
furniture.place(block, pair.getB(), pair.getA(), color);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isValidProvider(@NotNull Identifier key, boolean isItem) {
|
public boolean isValidProvider(@NotNull Identifier key, DataType dataType) {
|
||||||
|
if (dataType == DataType.ENTITY) return false;
|
||||||
return key.namespace().equalsIgnoreCase("crucible");
|
return key.namespace().equalsIgnoreCase("crucible");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
package com.volmit.iris.core.link.data;
|
||||||
|
|
||||||
|
import com.volmit.iris.core.link.ExternalDataProvider;
|
||||||
|
import com.volmit.iris.core.link.Identifier;
|
||||||
|
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||||
|
import io.lumine.mythic.api.adapters.AbstractLocation;
|
||||||
|
import io.lumine.mythic.api.config.MythicLineConfig;
|
||||||
|
import io.lumine.mythic.api.skills.conditions.ILocationCondition;
|
||||||
|
import io.lumine.mythic.bukkit.MythicBukkit;
|
||||||
|
import io.lumine.mythic.bukkit.adapters.BukkitWorld;
|
||||||
|
import io.lumine.mythic.bukkit.events.MythicConditionLoadEvent;
|
||||||
|
import io.lumine.mythic.core.skills.SkillCondition;
|
||||||
|
import io.lumine.mythic.core.utils.annotations.MythicCondition;
|
||||||
|
import io.lumine.mythic.core.utils.annotations.MythicField;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
public class MythicMobsDataProvider extends ExternalDataProvider {
|
||||||
|
public MythicMobsDataProvider() {
|
||||||
|
super("MythicMobs");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable Entity spawnMob(@NotNull Location location, @NotNull Identifier entityId) throws MissingResourceException {
|
||||||
|
var mm = MythicBukkit.inst().getMobManager().spawnMob(entityId.key(), location);
|
||||||
|
if (mm == null) throw new MissingResourceException("Failed to find mob!", entityId.namespace(), entityId.key());
|
||||||
|
return mm.getEntity().getBukkitEntity();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull Collection<@NotNull Identifier> getTypes(@NotNull DataType dataType) {
|
||||||
|
if (dataType != DataType.ENTITY) return List.of();
|
||||||
|
return MythicBukkit.inst()
|
||||||
|
.getMobManager()
|
||||||
|
.getMobNames()
|
||||||
|
.stream()
|
||||||
|
.map(name -> new Identifier("mythicmobs", name))
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isValidProvider(@NotNull Identifier id, DataType dataType) {
|
||||||
|
return id.namespace().equalsIgnoreCase("mythicmobs") && dataType == DataType.ENTITY;
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void on(MythicConditionLoadEvent event) {
|
||||||
|
switch (event.getConditionName()) {
|
||||||
|
case "irisbiome" -> event.register(new IrisBiomeCondition(event.getConditionName(), event.getConfig()));
|
||||||
|
case "irisregion" -> event.register(new IrisRegionCondition(event.getConditionName(), event.getConfig()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@MythicCondition(author = "CrazyDev22", name = "irisbiome", description = "Tests if the target is within the given list of biomes")
|
||||||
|
public static class IrisBiomeCondition extends SkillCondition implements ILocationCondition {
|
||||||
|
@MythicField(name = "biome", aliases = {"b"}, description = "A list of biomes to check")
|
||||||
|
private Set<String> biomes = ConcurrentHashMap.newKeySet();
|
||||||
|
@MythicField(name = "surface", aliases = {"s"}, description = "If the biome check should only be performed on the surface")
|
||||||
|
private boolean surface;
|
||||||
|
|
||||||
|
public IrisBiomeCondition(String line, MythicLineConfig mlc) {
|
||||||
|
super(line);
|
||||||
|
String b = mlc.getString(new String[]{"biome", "b"}, "");
|
||||||
|
biomes.addAll(Arrays.asList(b.split(",")));
|
||||||
|
surface = mlc.getBoolean(new String[]{"surface", "s"}, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean check(AbstractLocation target) {
|
||||||
|
var access = IrisToolbelt.access(((BukkitWorld) target.getWorld()).getBukkitWorld());
|
||||||
|
if (access == null) return false;
|
||||||
|
var engine = access.getEngine();
|
||||||
|
if (engine == null) return false;
|
||||||
|
var biome = surface ?
|
||||||
|
engine.getSurfaceBiome(target.getBlockX(), target.getBlockZ()) :
|
||||||
|
engine.getBiomeOrMantle(target.getBlockX(), target.getBlockY() - engine.getMinHeight(), target.getBlockZ());
|
||||||
|
return biomes.contains(biome.getLoadKey());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@MythicCondition(author = "CrazyDev22", name = "irisregion", description = "Tests if the target is within the given list of biomes")
|
||||||
|
public static class IrisRegionCondition extends SkillCondition implements ILocationCondition {
|
||||||
|
@MythicField(name = "region", aliases = {"r"}, description = "A list of regions to check")
|
||||||
|
private Set<String> regions = ConcurrentHashMap.newKeySet();
|
||||||
|
|
||||||
|
public IrisRegionCondition(String line, MythicLineConfig mlc) {
|
||||||
|
super(line);
|
||||||
|
String b = mlc.getString(new String[]{"region", "r"}, "");
|
||||||
|
regions.addAll(Arrays.asList(b.split(",")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean check(AbstractLocation target) {
|
||||||
|
var access = IrisToolbelt.access(((BukkitWorld) target.getWorld()).getBukkitWorld());
|
||||||
|
if (access == null) return false;
|
||||||
|
var engine = access.getEngine();
|
||||||
|
if (engine == null) return false;
|
||||||
|
var region = engine.getRegion(target.getBlockX(), target.getBlockZ());
|
||||||
|
return regions.contains(region.getLoadKey());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,34 +1,34 @@
|
|||||||
package com.volmit.iris.core.link;
|
package com.volmit.iris.core.link.data;
|
||||||
|
|
||||||
import com.nexomc.nexo.api.NexoBlocks;
|
import com.nexomc.nexo.api.NexoBlocks;
|
||||||
import com.nexomc.nexo.api.NexoFurniture;
|
import com.nexomc.nexo.api.NexoFurniture;
|
||||||
import com.nexomc.nexo.api.NexoItems;
|
import com.nexomc.nexo.api.NexoItems;
|
||||||
import com.nexomc.nexo.items.ItemBuilder;
|
import com.nexomc.nexo.items.ItemBuilder;
|
||||||
|
import com.volmit.iris.core.link.ExternalDataProvider;
|
||||||
|
import com.volmit.iris.core.link.Identifier;
|
||||||
import com.volmit.iris.core.nms.INMS;
|
import com.volmit.iris.core.nms.INMS;
|
||||||
import com.volmit.iris.core.nms.container.BiomeColor;
|
import com.volmit.iris.core.nms.container.BiomeColor;
|
||||||
|
import com.volmit.iris.core.nms.container.BlockProperty;
|
||||||
import com.volmit.iris.core.service.ExternalDataSVC;
|
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.engine.framework.Engine;
|
||||||
import com.volmit.iris.util.collection.KMap;
|
import com.volmit.iris.util.collection.KMap;
|
||||||
import com.volmit.iris.util.data.B;
|
import com.volmit.iris.util.data.B;
|
||||||
import com.volmit.iris.util.data.IrisCustomData;
|
import com.volmit.iris.util.data.IrisCustomData;
|
||||||
import com.volmit.iris.util.math.RNG;
|
|
||||||
import org.bukkit.Color;
|
import org.bukkit.Color;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.block.BlockFace;
|
|
||||||
import org.bukkit.block.data.BlockData;
|
import org.bukkit.block.data.BlockData;
|
||||||
import org.bukkit.entity.ItemDisplay;
|
import org.bukkit.entity.ItemDisplay;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.inventory.meta.LeatherArmorMeta;
|
||||||
|
import org.bukkit.inventory.meta.MapMeta;
|
||||||
import org.bukkit.inventory.meta.PotionMeta;
|
import org.bukkit.inventory.meta.PotionMeta;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
import java.util.MissingResourceException;
|
import java.util.MissingResourceException;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
|
|
||||||
public class NexoDataProvider extends ExternalDataProvider {
|
public class NexoDataProvider extends ExternalDataProvider {
|
||||||
private final AtomicBoolean failed = new AtomicBoolean(false);
|
|
||||||
|
|
||||||
public NexoDataProvider() {
|
public NexoDataProvider() {
|
||||||
super("Nexo");
|
super("Nexo");
|
||||||
}
|
}
|
||||||
@@ -57,6 +57,15 @@ public class NexoDataProvider extends ExternalDataProvider {
|
|||||||
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
|
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull List<BlockProperty> getBlockProperties(@NotNull Identifier blockId) throws MissingResourceException {
|
||||||
|
if (!NexoItems.exists(blockId.key())) {
|
||||||
|
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
|
||||||
|
}
|
||||||
|
|
||||||
|
return NexoFurniture.isFurniture(blockId.key()) ? YAW_FACE_BIOME_PROPERTIES : List.of();
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public ItemStack getItemStack(@NotNull Identifier itemId, @NotNull KMap<String, Object> customNbt) throws MissingResourceException {
|
public ItemStack getItemStack(@NotNull Identifier itemId, @NotNull KMap<String, Object> customNbt) throws MissingResourceException {
|
||||||
@@ -64,14 +73,19 @@ public class NexoDataProvider extends ExternalDataProvider {
|
|||||||
if (builder == null) {
|
if (builder == null) {
|
||||||
throw new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key());
|
throw new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key());
|
||||||
}
|
}
|
||||||
return builder.build();
|
try {
|
||||||
|
return builder.build();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
throw new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processUpdate(@NotNull Engine engine, @NotNull Block block, @NotNull Identifier blockId) {
|
public void processUpdate(@NotNull Engine engine, @NotNull Block block, @NotNull Identifier blockId) {
|
||||||
var pair = ExternalDataSVC.parseState(blockId);
|
var statePair = ExternalDataSVC.parseState(blockId);
|
||||||
var state = pair.getB();
|
var state = statePair.getB();
|
||||||
blockId = pair.getA();
|
blockId = statePair.getA();
|
||||||
|
|
||||||
if (NexoBlocks.isCustomBlock(blockId.key())) {
|
if (NexoBlocks.isCustomBlock(blockId.key())) {
|
||||||
NexoBlocks.place(blockId.key(), block.getLocation());
|
NexoBlocks.place(blockId.key(), block.getLocation());
|
||||||
@@ -81,26 +95,8 @@ public class NexoDataProvider extends ExternalDataProvider {
|
|||||||
if (!NexoFurniture.isFurniture(blockId.key()))
|
if (!NexoFurniture.isFurniture(blockId.key()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
float yaw = 0;
|
var pair = parseYawAndFace(engine, block, state);
|
||||||
BlockFace face = BlockFace.NORTH;
|
ItemDisplay display = NexoFurniture.place(blockId.key(), block.getLocation(), pair.getA(), pair.getB());
|
||||||
|
|
||||||
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;
|
if (display == null) return;
|
||||||
ItemStack itemStack = display.getItemStack();
|
ItemStack itemStack = display.getItemStack();
|
||||||
if (itemStack == null) return;
|
if (itemStack == null) return;
|
||||||
@@ -114,51 +110,31 @@ public class NexoDataProvider extends ExternalDataProvider {
|
|||||||
var biomeColor = INMS.get().getBiomeColor(block.getLocation(), type);
|
var biomeColor = INMS.get().getBiomeColor(block.getLocation(), type);
|
||||||
if (biomeColor == null) return;
|
if (biomeColor == null) return;
|
||||||
var potionColor = Color.fromARGB(biomeColor.getAlpha(), biomeColor.getRed(), biomeColor.getGreen(), biomeColor.getBlue());
|
var potionColor = Color.fromARGB(biomeColor.getAlpha(), biomeColor.getRed(), biomeColor.getGreen(), biomeColor.getBlue());
|
||||||
if (itemStack.getItemMeta() instanceof PotionMeta meta) {
|
var meta = itemStack.getItemMeta();
|
||||||
meta.setColor(potionColor);
|
switch (meta) {
|
||||||
itemStack.setItemMeta(meta);
|
case LeatherArmorMeta armor -> armor.setColor(potionColor);
|
||||||
|
case PotionMeta potion -> potion.setColor(potionColor);
|
||||||
|
case MapMeta map -> map.setColor(potionColor);
|
||||||
|
case null, default -> {}
|
||||||
}
|
}
|
||||||
|
itemStack.setItemMeta(meta);
|
||||||
}
|
}
|
||||||
display.setItemStack(itemStack);
|
display.setItemStack(itemStack);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
@Override
|
||||||
public Identifier[] getBlockTypes() {
|
public @NotNull Collection<@NotNull Identifier> getTypes(@NotNull DataType dataType) {
|
||||||
return NexoItems.itemNames().stream()
|
if (dataType == DataType.ENTITY) return List.of();
|
||||||
|
return NexoItems.itemNames()
|
||||||
|
.stream()
|
||||||
.map(i -> new Identifier("nexo", i))
|
.map(i -> new Identifier("nexo", i))
|
||||||
.filter(i -> {
|
.filter(dataType.asPredicate(this))
|
||||||
try {
|
.toList();
|
||||||
return getBlockData(i) != null;
|
|
||||||
} catch (MissingResourceException e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.toArray(Identifier[]::new);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public Identifier[] getItemTypes() {
|
|
||||||
return NexoItems.itemNames().stream()
|
|
||||||
.map(i -> new Identifier("nexo", i))
|
|
||||||
.filter(i -> {
|
|
||||||
try {
|
|
||||||
return getItemStack(i) != null;
|
|
||||||
} catch (MissingResourceException e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.toArray(Identifier[]::new);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isValidProvider(@NotNull Identifier id, boolean isItem) {
|
public boolean isValidProvider(@NotNull Identifier id, DataType dataType) {
|
||||||
|
if (dataType == DataType.ENTITY) return false;
|
||||||
return "nexo".equalsIgnoreCase(id.namespace());
|
return "nexo".equalsIgnoreCase(id.namespace());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isReady() {
|
|
||||||
return super.isReady() && !failed.get();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -24,6 +24,7 @@ import com.google.gson.stream.JsonReader;
|
|||||||
import com.google.gson.stream.JsonToken;
|
import com.google.gson.stream.JsonToken;
|
||||||
import com.google.gson.stream.JsonWriter;
|
import com.google.gson.stream.JsonWriter;
|
||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.Iris;
|
||||||
|
import com.volmit.iris.core.scripting.environment.PackEnvironment;
|
||||||
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.object.*;
|
import com.volmit.iris.engine.object.*;
|
||||||
@@ -33,10 +34,12 @@ 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.context.IrisContext;
|
import com.volmit.iris.util.context.IrisContext;
|
||||||
import com.volmit.iris.util.format.C;
|
import com.volmit.iris.util.format.C;
|
||||||
|
import com.volmit.iris.util.mantle.flag.MantleFlagAdapter;
|
||||||
|
import com.volmit.iris.util.mantle.flag.MantleFlag;
|
||||||
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.reflect.KeyedType;
|
||||||
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;
|
||||||
@@ -44,6 +47,8 @@ import lombok.Data;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileReader;
|
import java.io.FileReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
@@ -52,6 +57,7 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
|||||||
private static final KMap<File, IrisData> dataLoaders = new KMap<>();
|
private static final KMap<File, IrisData> dataLoaders = new KMap<>();
|
||||||
private final File dataFolder;
|
private final File dataFolder;
|
||||||
private final int id;
|
private final int id;
|
||||||
|
private final PackEnvironment environment;
|
||||||
private boolean closed = false;
|
private boolean closed = false;
|
||||||
private ResourceLoader<IrisBiome> biomeLoader;
|
private ResourceLoader<IrisBiome> biomeLoader;
|
||||||
private ResourceLoader<IrisLootTable> lootLoader;
|
private ResourceLoader<IrisLootTable> lootLoader;
|
||||||
@@ -85,6 +91,7 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
|||||||
this.engine = null;
|
this.engine = null;
|
||||||
this.dataFolder = dataFolder;
|
this.dataFolder = dataFolder;
|
||||||
this.id = RNG.r.imax();
|
this.id = RNG.r.imax();
|
||||||
|
this.environment = PackEnvironment.create(this);
|
||||||
hotloaded();
|
hotloaded();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -250,12 +257,20 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (engine != null && t.getPreprocessors().isNotEmpty()) {
|
if (engine == null) return;
|
||||||
|
var global = engine.getDimension().getPreProcessors(t.getFolderName());
|
||||||
|
var local = t.getPreprocessors();
|
||||||
|
if ((global != null && global.isNotEmpty()) || local.isNotEmpty()) {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
engine.getExecution().getAPI().setPreprocessorObject(t);
|
if (global != null) {
|
||||||
|
for (String i : global) {
|
||||||
|
engine.getExecution().preprocessObject(i, t);
|
||||||
|
Iris.debug("Loader<" + C.GREEN + t.getTypeName() + C.LIGHT_PURPLE + "> iprocess " + C.YELLOW + t.getLoadKey() + C.LIGHT_PURPLE + " in <rainbow>" + i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (String i : t.getPreprocessors()) {
|
for (String i : local) {
|
||||||
engine.getExecution().execute(i);
|
engine.getExecution().preprocessObject(i, t);
|
||||||
Iris.debug("Loader<" + C.GREEN + t.getTypeName() + C.LIGHT_PURPLE + "> iprocess " + C.YELLOW + t.getLoadKey() + C.LIGHT_PURPLE + " in <rainbow>" + i);
|
Iris.debug("Loader<" + C.GREEN + t.getTypeName() + C.LIGHT_PURPLE + "> iprocess " + C.YELLOW + t.getLoadKey() + C.LIGHT_PURPLE + " in <rainbow>" + i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -269,6 +284,7 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
|||||||
public void close() {
|
public void close() {
|
||||||
closed = true;
|
closed = true;
|
||||||
dump();
|
dump();
|
||||||
|
dataLoaders.remove(dataFolder);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IrisData copy() {
|
public IrisData copy() {
|
||||||
@@ -300,6 +316,7 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
|||||||
|
|
||||||
return r;
|
return r;
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
|
Iris.reportError(e);
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
Iris.error("Failed to create loader! " + registrant.getCanonicalName());
|
Iris.error("Failed to create loader! " + registrant.getCanonicalName());
|
||||||
}
|
}
|
||||||
@@ -308,12 +325,14 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void hotloaded() {
|
public synchronized void hotloaded() {
|
||||||
|
environment.close();
|
||||||
possibleSnippets = new KMap<>();
|
possibleSnippets = new KMap<>();
|
||||||
builder = new GsonBuilder()
|
builder = new GsonBuilder()
|
||||||
.addDeserializationExclusionStrategy(this)
|
.addDeserializationExclusionStrategy(this)
|
||||||
.addSerializationExclusionStrategy(this)
|
.addSerializationExclusionStrategy(this)
|
||||||
.setLenient()
|
.setLenient()
|
||||||
.registerTypeAdapterFactory(this)
|
.registerTypeAdapterFactory(this)
|
||||||
|
.registerTypeAdapter(MantleFlag.class, new MantleFlagAdapter())
|
||||||
.setPrettyPrinting();
|
.setPrettyPrinting();
|
||||||
loaders.clear();
|
loaders.clear();
|
||||||
File packs = dataFolder;
|
File packs = dataFolder;
|
||||||
@@ -338,16 +357,13 @@ 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(KeyedType::createTypeAdapter);
|
||||||
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();
|
||||||
|
dimensionLoader.streamAll()
|
||||||
|
.map(IrisDimension::getDataScripts)
|
||||||
|
.flatMap(KList::stream)
|
||||||
|
.forEach(environment::execute);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void dump() {
|
public void dump() {
|
||||||
@@ -360,6 +376,7 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
|||||||
for (ResourceLoader<?> i : loaders.values()) {
|
for (ResourceLoader<?> i : loaders.values()) {
|
||||||
i.clearList();
|
i.clearList();
|
||||||
}
|
}
|
||||||
|
possibleSnippets.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toLoadKey(File f) {
|
public String toLoadKey(File f) {
|
||||||
@@ -408,6 +425,7 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String snippetType = typeToken.getRawType().getDeclaredAnnotation(Snippet.class).value();
|
String snippetType = typeToken.getRawType().getDeclaredAnnotation(Snippet.class).value();
|
||||||
|
String snippedBase = "snippet/" + snippetType + "/";
|
||||||
|
|
||||||
return new TypeAdapter<>() {
|
return new TypeAdapter<>() {
|
||||||
@Override
|
@Override
|
||||||
@@ -421,20 +439,20 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
|||||||
|
|
||||||
if (reader.peek().equals(JsonToken.STRING)) {
|
if (reader.peek().equals(JsonToken.STRING)) {
|
||||||
String r = reader.nextString();
|
String r = reader.nextString();
|
||||||
|
if (!r.startsWith("snippet/"))
|
||||||
|
return null;
|
||||||
|
if (!r.startsWith(snippedBase))
|
||||||
|
r = snippedBase + r.substring(8);
|
||||||
|
|
||||||
if (r.startsWith("snippet/" + snippetType + "/")) {
|
File f = new File(getDataFolder(), r + ".json");
|
||||||
File f = new File(getDataFolder(), r + ".json");
|
if (f.exists()) {
|
||||||
|
try (JsonReader snippetReader = new JsonReader(new FileReader(f))){
|
||||||
if (f.exists()) {
|
return adapter.read(snippetReader);
|
||||||
try {
|
} catch (Throwable e) {
|
||||||
JsonReader snippetReader = new JsonReader(new FileReader(f));
|
Iris.error("Couldn't read snippet " + r + " in " + reader.getPath() + " (" + e.getMessage() + ")");
|
||||||
return adapter.read(snippetReader);
|
|
||||||
} catch (Throwable e) {
|
|
||||||
Iris.error("Couldn't read snippet " + r + " in " + reader.getPath() + " (" + e.getMessage() + ")");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Iris.error("Couldn't find snippet " + r + " in " + reader.getPath());
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
Iris.error("Couldn't find snippet " + r + " in " + reader.getPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@@ -461,11 +479,20 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
|||||||
KList<String> l = new KList<>();
|
KList<String> l = new KList<>();
|
||||||
|
|
||||||
File snippetFolder = new File(getDataFolder(), "snippet/" + f);
|
File snippetFolder = new File(getDataFolder(), "snippet/" + f);
|
||||||
|
if (!snippetFolder.exists()) return l;
|
||||||
|
|
||||||
if (snippetFolder.exists() && snippetFolder.isDirectory()) {
|
String absPath = snippetFolder.getAbsolutePath();
|
||||||
for (File i : snippetFolder.listFiles()) {
|
try (var stream = Files.walk(snippetFolder.toPath())) {
|
||||||
l.add("snippet/" + f + "/" + i.getName().split("\\Q.\\E")[0]);
|
stream.filter(Files::isRegularFile)
|
||||||
}
|
.map(Path::toAbsolutePath)
|
||||||
|
.map(Path::toString)
|
||||||
|
.filter(s -> s.endsWith(".json"))
|
||||||
|
.map(s -> s.substring(absPath.length() + 1))
|
||||||
|
.map(s -> s.replace("\\", "/"))
|
||||||
|
.map(s -> s.split("\\Q.\\E")[0])
|
||||||
|
.forEach(s -> l.add("snippet/" + s));
|
||||||
|
} catch (Throwable e) {
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
return l;
|
return l;
|
||||||
@@ -477,7 +504,7 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void savePrefetch(Engine engine) {
|
public void savePrefetch(Engine engine) {
|
||||||
BurstExecutor b = MultiBurst.burst.burst(loaders.size());
|
BurstExecutor b = MultiBurst.ioBurst.burst(loaders.size());
|
||||||
|
|
||||||
for (ResourceLoader<?> i : loaders.values()) {
|
for (ResourceLoader<?> i : loaders.values()) {
|
||||||
b.queue(() -> {
|
b.queue(() -> {
|
||||||
@@ -494,7 +521,7 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void loadPrefetch(Engine engine) {
|
public void loadPrefetch(Engine engine) {
|
||||||
BurstExecutor b = MultiBurst.burst.burst(loaders.size());
|
BurstExecutor b = MultiBurst.ioBurst.burst(loaders.size());
|
||||||
|
|
||||||
for (ResourceLoader<?> i : loaders.values()) {
|
for (ResourceLoader<?> i : loaders.values()) {
|
||||||
b.queue(() -> {
|
b.queue(() -> {
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import com.volmit.iris.util.collection.KList;
|
|||||||
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 lombok.Data;
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@@ -39,6 +40,7 @@ public abstract class IrisRegistrant {
|
|||||||
@ArrayType(min = 1, type = String.class)
|
@ArrayType(min = 1, type = String.class)
|
||||||
private KList<String> preprocessors = new KList<>();
|
private KList<String> preprocessors = new KList<>();
|
||||||
|
|
||||||
|
@EqualsAndHashCode.Exclude
|
||||||
private transient IrisData loader;
|
private transient IrisData loader;
|
||||||
|
|
||||||
private transient String loadKey;
|
private transient String loadKey;
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import com.volmit.iris.Iris;
|
|||||||
import com.volmit.iris.core.IrisSettings;
|
import com.volmit.iris.core.IrisSettings;
|
||||||
import com.volmit.iris.core.project.SchemaBuilder;
|
import com.volmit.iris.core.project.SchemaBuilder;
|
||||||
import com.volmit.iris.core.service.PreservationSVC;
|
import com.volmit.iris.core.service.PreservationSVC;
|
||||||
|
import com.volmit.iris.engine.data.cache.AtomicCache;
|
||||||
import com.volmit.iris.engine.framework.Engine;
|
import com.volmit.iris.engine.framework.Engine;
|
||||||
import com.volmit.iris.engine.framework.MeteredCache;
|
import com.volmit.iris.engine.framework.MeteredCache;
|
||||||
import com.volmit.iris.util.collection.KList;
|
import com.volmit.iris.util.collection.KList;
|
||||||
@@ -44,9 +45,9 @@ import lombok.EqualsAndHashCode;
|
|||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
@@ -59,7 +60,7 @@ import java.util.zip.GZIPOutputStream;
|
|||||||
public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
||||||
public static final AtomicDouble tlt = new AtomicDouble(0);
|
public static final AtomicDouble tlt = new AtomicDouble(0);
|
||||||
private static final int CACHE_SIZE = 100000;
|
private static final int CACHE_SIZE = 100000;
|
||||||
protected final AtomicReference<KList<File>> folderCache;
|
protected final AtomicCache<KList<File>> folderCache;
|
||||||
protected KSet<String> firstAccess;
|
protected KSet<String> firstAccess;
|
||||||
protected File root;
|
protected File root;
|
||||||
protected String folderName;
|
protected String folderName;
|
||||||
@@ -75,7 +76,7 @@ public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
|||||||
public ResourceLoader(File root, IrisData manager, String folderName, String resourceTypeName, Class<? extends T> objectClass) {
|
public ResourceLoader(File root, IrisData manager, String folderName, String resourceTypeName, Class<? extends T> objectClass) {
|
||||||
this.manager = manager;
|
this.manager = manager;
|
||||||
firstAccess = new KSet<>();
|
firstAccess = new KSet<>();
|
||||||
folderCache = new AtomicReference<>();
|
folderCache = new AtomicCache<>();
|
||||||
sec = new ChronoLatch(5000);
|
sec = new ChronoLatch(5000);
|
||||||
loads = new AtomicInteger();
|
loads = new AtomicInteger();
|
||||||
this.objectClass = objectClass;
|
this.objectClass = objectClass;
|
||||||
@@ -215,6 +216,10 @@ public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
|||||||
return j;
|
return j;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Stream<T> streamAll() {
|
||||||
|
return streamAll(Arrays.stream(getPossibleKeys()));
|
||||||
|
}
|
||||||
|
|
||||||
public Stream<T> streamAll(Stream<String> s) {
|
public Stream<T> streamAll(Stream<String> s) {
|
||||||
return s.map(this::load);
|
return s.map(this::load);
|
||||||
}
|
}
|
||||||
@@ -235,13 +240,15 @@ public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
|||||||
|
|
||||||
public KList<T> loadAllParallel(KList<String> s) {
|
public KList<T> loadAllParallel(KList<String> s) {
|
||||||
KList<T> m = new KList<>();
|
KList<T> m = new KList<>();
|
||||||
BurstExecutor burst = MultiBurst.burst.burst(s.size());
|
BurstExecutor burst = MultiBurst.ioBurst.burst(s.size());
|
||||||
|
|
||||||
for (String i : s) {
|
for (String i : s) {
|
||||||
burst.queue(() -> {
|
burst.queue(() -> {
|
||||||
T t = load(i);
|
T t = load(i);
|
||||||
|
if (t == null)
|
||||||
|
return;
|
||||||
|
|
||||||
if (t != null) {
|
synchronized (m) {
|
||||||
m.add(t);
|
m.add(t);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -358,29 +365,24 @@ public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public KList<File> getFolders() {
|
public KList<File> getFolders() {
|
||||||
synchronized (folderCache) {
|
return folderCache.aquire(() -> {
|
||||||
if (folderCache.get() == null) {
|
KList<File> fc = new KList<>();
|
||||||
KList<File> fc = new KList<>();
|
|
||||||
|
|
||||||
File[] files = root.listFiles();
|
File[] files = root.listFiles();
|
||||||
if (files == null) {
|
if (files == null) {
|
||||||
throw new IllegalStateException("Failed to list files in " + root);
|
throw new IllegalStateException("Failed to list files in " + root);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (File i : files) {
|
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);
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
folderCache.set(fc);
|
|
||||||
}
|
}
|
||||||
}
|
return fc;
|
||||||
|
});
|
||||||
return folderCache.get();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public KList<File> getFolders(String rc) {
|
public KList<File> getFolders(String rc) {
|
||||||
@@ -400,7 +402,7 @@ public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
|||||||
public void clearCache() {
|
public void clearCache() {
|
||||||
possibleKeys = null;
|
possibleKeys = null;
|
||||||
loadCache.invalidate();
|
loadCache.invalidate();
|
||||||
folderCache.set(null);
|
folderCache.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
public File fileFor(T b) {
|
public File fileFor(T b) {
|
||||||
@@ -426,7 +428,7 @@ public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void clearList() {
|
public void clearList() {
|
||||||
folderCache.set(null);
|
folderCache.reset();
|
||||||
possibleKeys = null;
|
possibleKeys = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -82,8 +82,8 @@ public class ScriptResourceLoader extends ResourceLoader<IrisScript> {
|
|||||||
private Set<String> getKeysInDirectory(File directory) {
|
private Set<String> getKeysInDirectory(File directory) {
|
||||||
Set<String> keys = new HashSet<>();
|
Set<String> keys = new HashSet<>();
|
||||||
for (File file : directory.listFiles()) {
|
for (File file : directory.listFiles()) {
|
||||||
if (file.isFile() && file.getName().endsWith(".js")) {
|
if (file.isFile() && file.getName().endsWith(".kts")) {
|
||||||
keys.add(file.getName().replaceAll("\\Q.js\\E", ""));
|
keys.add(file.getName().replaceAll("\\Q.kts\\E", ""));
|
||||||
} else if (file.isDirectory()) {
|
} else if (file.isDirectory()) {
|
||||||
keys.addAll(getKeysInDirectory(file));
|
keys.addAll(getKeysInDirectory(file));
|
||||||
}
|
}
|
||||||
@@ -127,12 +127,12 @@ public class ScriptResourceLoader extends ResourceLoader<IrisScript> {
|
|||||||
public File findFile(String name) {
|
public File findFile(String name) {
|
||||||
for (File i : getFolders(name)) {
|
for (File i : getFolders(name)) {
|
||||||
for (File j : i.listFiles()) {
|
for (File j : i.listFiles()) {
|
||||||
if (j.isFile() && j.getName().endsWith(".js") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
if (j.isFile() && j.getName().endsWith(".kts") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
||||||
return j;
|
return j;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
File file = new File(i, name + ".js");
|
File file = new File(i, name + ".kts");
|
||||||
|
|
||||||
if (file.exists()) {
|
if (file.exists()) {
|
||||||
return file;
|
return file;
|
||||||
@@ -147,12 +147,12 @@ public class ScriptResourceLoader extends ResourceLoader<IrisScript> {
|
|||||||
private IrisScript loadRaw(String name) {
|
private IrisScript loadRaw(String name) {
|
||||||
for (File i : getFolders(name)) {
|
for (File i : getFolders(name)) {
|
||||||
for (File j : i.listFiles()) {
|
for (File j : i.listFiles()) {
|
||||||
if (j.isFile() && j.getName().endsWith(".js") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
if (j.isFile() && j.getName().endsWith(".kts") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
||||||
return loadFile(j, name);
|
return loadFile(j, name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
File file = new File(i, name + ".js");
|
File file = new File(i, name + ".kts");
|
||||||
|
|
||||||
if (file.exists()) {
|
if (file.exists()) {
|
||||||
return loadFile(file, name);
|
return loadFile(file, name);
|
||||||
|
|||||||
@@ -24,19 +24,23 @@ import com.volmit.iris.core.nms.v1X.NMSBinding1X;
|
|||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class INMS {
|
public class INMS {
|
||||||
private static final Map<String, String> REVISION = Map.of(
|
private static final Version CURRENT = Boolean.getBoolean("iris.no-version-limit") ?
|
||||||
"1.20.5", "v1_20_R4",
|
new Version(Integer.MAX_VALUE, Integer.MAX_VALUE, null) :
|
||||||
"1.20.6", "v1_20_R4",
|
new Version(21, 8, null);
|
||||||
"1.21", "v1_21_R1",
|
|
||||||
"1.21.1", "v1_21_R1",
|
private static final List<Version> REVISION = List.of(
|
||||||
"1.21.2", "v1_21_R2",
|
new Version(21, 6, "v1_21_R5"),
|
||||||
"1.21.3", "v1_21_R2",
|
new Version(21, 5, "v1_21_R4"),
|
||||||
"1.21.4", "v1_21_R3"
|
new Version(21, 4, "v1_21_R3"),
|
||||||
|
new Version(21, 2, "v1_21_R2"),
|
||||||
|
new Version(21, 0, "v1_21_R1"),
|
||||||
|
new Version(20, 5, "v1_20_R4")
|
||||||
);
|
);
|
||||||
|
|
||||||
private static final List<Version> PACKS = List.of(
|
private static final List<Version> PACKS = List.of(
|
||||||
|
new Version(21, 5, "31100"),
|
||||||
new Version(21, 4, "31020"),
|
new Version(21, 4, "31020"),
|
||||||
new Version(21, 2, "31000"),
|
new Version(21, 2, "31000"),
|
||||||
new Version(20, 1, "3910")
|
new Version(20, 1, "3910")
|
||||||
@@ -44,7 +48,7 @@ public class INMS {
|
|||||||
|
|
||||||
//@done
|
//@done
|
||||||
private static final INMSBinding binding = bind();
|
private static final INMSBinding binding = bind();
|
||||||
public static final String OVERWORLD_TAG = getOverworldTag();
|
public static final String OVERWORLD_TAG = getTag(PACKS, "3910");
|
||||||
|
|
||||||
public static INMSBinding get() {
|
public static INMSBinding get() {
|
||||||
return binding;
|
return binding;
|
||||||
@@ -58,7 +62,7 @@ public class INMS {
|
|||||||
try {
|
try {
|
||||||
String name = Bukkit.getServer().getClass().getCanonicalName();
|
String name = Bukkit.getServer().getClass().getCanonicalName();
|
||||||
if (name.equals("org.bukkit.craftbukkit.CraftServer")) {
|
if (name.equals("org.bukkit.craftbukkit.CraftServer")) {
|
||||||
return REVISION.getOrDefault(Bukkit.getServer().getBukkitVersion().split("-")[0], "BUKKIT");
|
return getTag(REVISION, "BUKKIT");
|
||||||
} else {
|
} else {
|
||||||
return name.split("\\Q.\\E")[3];
|
return name.split("\\Q.\\E")[3];
|
||||||
}
|
}
|
||||||
@@ -96,7 +100,7 @@ public class INMS {
|
|||||||
return new NMSBinding1X();
|
return new NMSBinding1X();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getOverworldTag() {
|
private static String getTag(List<Version> versions, String def) {
|
||||||
var version = Bukkit.getServer().getBukkitVersion().split("-")[0].split("\\.", 3);
|
var version = Bukkit.getServer().getBukkitVersion().split("-")[0].split("\\.", 3);
|
||||||
int major = 0;
|
int major = 0;
|
||||||
int minor = 0;
|
int minor = 0;
|
||||||
@@ -107,13 +111,16 @@ public class INMS {
|
|||||||
} else if (version.length == 2) {
|
} else if (version.length == 2) {
|
||||||
major = Integer.parseInt(version[1]);
|
major = Integer.parseInt(version[1]);
|
||||||
}
|
}
|
||||||
|
if (CURRENT.major < major || CURRENT.minor < minor) {
|
||||||
|
return versions.getFirst().tag;
|
||||||
|
}
|
||||||
|
|
||||||
for (var p : PACKS) {
|
for (var p : versions) {
|
||||||
if (p.major > major || p.minor > minor)
|
if (p.major > major || p.minor > minor)
|
||||||
continue;
|
continue;
|
||||||
return p.tag;
|
return p.tag;
|
||||||
}
|
}
|
||||||
return "3910";
|
return def;
|
||||||
}
|
}
|
||||||
|
|
||||||
private record Version(int major, int minor, String tag) {}
|
private record Version(int major, int minor, String tag) {}
|
||||||
|
|||||||
@@ -18,11 +18,15 @@
|
|||||||
|
|
||||||
package com.volmit.iris.core.nms;
|
package com.volmit.iris.core.nms;
|
||||||
|
|
||||||
|
import com.volmit.iris.core.link.Identifier;
|
||||||
import com.volmit.iris.core.nms.container.AutoClosing;
|
import com.volmit.iris.core.nms.container.AutoClosing;
|
||||||
import com.volmit.iris.core.nms.container.BiomeColor;
|
import com.volmit.iris.core.nms.container.BiomeColor;
|
||||||
|
import com.volmit.iris.core.nms.container.BlockProperty;
|
||||||
import com.volmit.iris.core.nms.container.Pair;
|
import com.volmit.iris.core.nms.container.Pair;
|
||||||
|
import com.volmit.iris.core.nms.container.StructurePlacement;
|
||||||
import com.volmit.iris.core.nms.datapack.DataVersion;
|
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.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.mantle.Mantle;
|
import com.volmit.iris.util.mantle.Mantle;
|
||||||
@@ -39,6 +43,7 @@ import org.bukkit.generator.ChunkGenerator;
|
|||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public interface INMSBinding {
|
public interface INMSBinding {
|
||||||
boolean hasTile(Material material);
|
boolean hasTile(Material material);
|
||||||
@@ -90,12 +95,10 @@ public interface INMSBinding {
|
|||||||
MCABiomeContainer newBiomeContainer(int min, int max);
|
MCABiomeContainer newBiomeContainer(int min, int max);
|
||||||
|
|
||||||
default World createWorld(WorldCreator c) {
|
default World createWorld(WorldCreator c) {
|
||||||
if (missingDimensionTypes(true, true, true))
|
if (c.generator() instanceof PlatformChunkGenerator gen
|
||||||
throw new IllegalStateException("Missing dimenstion types to create world");
|
&& missingDimensionTypes(gen.getTarget().getDimension().getDimensionTypeKey()))
|
||||||
|
throw new IllegalStateException("Missing dimension types to create world");
|
||||||
try (var ignored = injectLevelStems()) {
|
return c.createWorld();
|
||||||
return c.createWorld();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int countCustomBiomes();
|
int countCustomBiomes();
|
||||||
@@ -130,9 +133,15 @@ public interface INMSBinding {
|
|||||||
|
|
||||||
KList<String> getStructureKeys();
|
KList<String> getStructureKeys();
|
||||||
|
|
||||||
AutoClosing injectLevelStems();
|
boolean missingDimensionTypes(String... keys);
|
||||||
|
|
||||||
Pair<Integer, AutoClosing> injectUncached(boolean overworld, boolean nether, boolean end);
|
default boolean injectBukkit() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
boolean missingDimensionTypes(boolean overworld, boolean nether, boolean end);
|
KMap<Material, List<BlockProperty>> getBlockProperties();
|
||||||
|
|
||||||
|
void placeStructures(Chunk chunk);
|
||||||
|
|
||||||
|
KMap<Identifier, StructurePlacement> collectStructures();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.volmit.iris.core.nms.container;
|
package com.volmit.iris.core.nms.container;
|
||||||
|
|
||||||
|
import com.volmit.iris.util.collection.KMap;
|
||||||
import com.volmit.iris.util.function.NastyRunnable;
|
import com.volmit.iris.util.function.NastyRunnable;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
|
|
||||||
@@ -7,6 +8,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
|
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public class AutoClosing implements AutoCloseable {
|
public class AutoClosing implements AutoCloseable {
|
||||||
|
private static final KMap<Thread, AutoClosing> CONTEXTS = new KMap<>();
|
||||||
private final AtomicBoolean closed = new AtomicBoolean();
|
private final AtomicBoolean closed = new AtomicBoolean();
|
||||||
private final NastyRunnable action;
|
private final NastyRunnable action;
|
||||||
|
|
||||||
@@ -14,9 +16,24 @@ public class AutoClosing implements AutoCloseable {
|
|||||||
public void close() {
|
public void close() {
|
||||||
if (closed.getAndSet(true)) return;
|
if (closed.getAndSet(true)) return;
|
||||||
try {
|
try {
|
||||||
|
removeContext();
|
||||||
action.run();
|
action.run();
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void storeContext() {
|
||||||
|
CONTEXTS.put(Thread.currentThread(), this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeContext() {
|
||||||
|
CONTEXTS.values().removeIf(c -> c == this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void closeContext() {
|
||||||
|
AutoClosing closing = CONTEXTS.remove(Thread.currentThread());
|
||||||
|
if (closing == null) return;
|
||||||
|
closing.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,196 @@
|
|||||||
|
package com.volmit.iris.core.nms.container;
|
||||||
|
|
||||||
|
import com.volmit.iris.util.json.JSONArray;
|
||||||
|
import com.volmit.iris.util.json.JSONObject;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
public class BlockProperty {
|
||||||
|
private static final Set<Class<?>> NATIVES = Set.of(Byte.class, Short.class, Integer.class, Long.class, Float.class, Double.class, Boolean.class, String.class);
|
||||||
|
private final String name;
|
||||||
|
private final Class<?> type;
|
||||||
|
|
||||||
|
private final Object defaultValue;
|
||||||
|
private final Set<Object> values;
|
||||||
|
private final Function<Object, String> nameFunction;
|
||||||
|
private final Function<Object, Object> jsonFunction;
|
||||||
|
|
||||||
|
public <T extends Comparable<T>> BlockProperty(
|
||||||
|
String name,
|
||||||
|
Class<T> type,
|
||||||
|
T defaultValue,
|
||||||
|
Collection<T> values,
|
||||||
|
Function<T, String> nameFunction
|
||||||
|
) {
|
||||||
|
this.name = name;
|
||||||
|
this.type = type;
|
||||||
|
this.defaultValue = defaultValue;
|
||||||
|
this.values = Collections.unmodifiableSet(new TreeSet<>(values));
|
||||||
|
this.nameFunction = (Function<Object, String>) (Object) nameFunction;
|
||||||
|
jsonFunction = NATIVES.contains(type) ? Function.identity() : this.nameFunction::apply;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T extends Enum<T>> BlockProperty ofEnum(Class<T> type, String name, T defaultValue) {
|
||||||
|
return new BlockProperty(
|
||||||
|
name,
|
||||||
|
type,
|
||||||
|
defaultValue,
|
||||||
|
Arrays.asList(type.getEnumConstants()),
|
||||||
|
val -> val == null ? "null" : val.name()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BlockProperty ofDouble(String name, float defaultValue, float min, float max, boolean exclusiveMin, boolean exclusiveMax) {
|
||||||
|
return new BoundedDouble(
|
||||||
|
name,
|
||||||
|
defaultValue,
|
||||||
|
min,
|
||||||
|
max,
|
||||||
|
exclusiveMin,
|
||||||
|
exclusiveMax,
|
||||||
|
(f) -> String.format("%.2f", f)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BlockProperty ofLong(String name, long defaultValue, long min, long max, boolean exclusiveMin, boolean exclusiveMax) {
|
||||||
|
return new BoundedLong(
|
||||||
|
name,
|
||||||
|
defaultValue,
|
||||||
|
min,
|
||||||
|
max,
|
||||||
|
exclusiveMin,
|
||||||
|
exclusiveMax,
|
||||||
|
(l) -> Long.toString(l)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BlockProperty ofBoolean(String name, boolean defaultValue) {
|
||||||
|
return new BlockProperty(
|
||||||
|
name,
|
||||||
|
Boolean.class,
|
||||||
|
defaultValue,
|
||||||
|
List.of(true, false),
|
||||||
|
(b) -> b ? "true" : "false"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull String toString() {
|
||||||
|
return name + "=" + nameFunction.apply(defaultValue) + " [" + String.join(",", names()) + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String name() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String defaultValue() {
|
||||||
|
return nameFunction.apply(defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> names() {
|
||||||
|
return values.stream().map(nameFunction).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object defaultValueAsJson() {
|
||||||
|
return jsonFunction.apply(defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JSONArray valuesAsJson() {
|
||||||
|
return new JSONArray(values.stream().map(jsonFunction).toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
public JSONObject buildJson() {
|
||||||
|
var json = new JSONObject();
|
||||||
|
json.put("type", jsonType());
|
||||||
|
json.put("default", defaultValueAsJson());
|
||||||
|
if (!values.isEmpty()) json.put("enum", valuesAsJson());
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String jsonType() {
|
||||||
|
if (type == Boolean.class)
|
||||||
|
return "boolean";
|
||||||
|
if (type == Byte.class || type == Short.class || type == Integer.class || type == Long.class)
|
||||||
|
return "integer";
|
||||||
|
if (type == Float.class || type == Double.class)
|
||||||
|
return "number";
|
||||||
|
return "string";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (obj == this) return true;
|
||||||
|
if (obj == null || obj.getClass() != this.getClass()) return false;
|
||||||
|
var that = (BlockProperty) obj;
|
||||||
|
return Objects.equals(this.name, that.name) &&
|
||||||
|
Objects.equals(this.values, that.values) &&
|
||||||
|
Objects.equals(this.type, that.type);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(name, values, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class BoundedLong extends BlockProperty {
|
||||||
|
private final long min, max;
|
||||||
|
private final boolean exclusiveMin, exclusiveMax;
|
||||||
|
|
||||||
|
public BoundedLong(
|
||||||
|
String name,
|
||||||
|
long defaultValue,
|
||||||
|
long min,
|
||||||
|
long max,
|
||||||
|
boolean exclusiveMin,
|
||||||
|
boolean exclusiveMax,
|
||||||
|
Function<Long, String> nameFunction
|
||||||
|
) {
|
||||||
|
super(name, Long.class, defaultValue, List.of(), nameFunction);
|
||||||
|
this.min = min;
|
||||||
|
this.max = max;
|
||||||
|
this.exclusiveMin = exclusiveMin;
|
||||||
|
this.exclusiveMax = exclusiveMax;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JSONObject buildJson() {
|
||||||
|
return super.buildJson()
|
||||||
|
.put("minimum", min)
|
||||||
|
.put("maximum", max)
|
||||||
|
.put("exclusiveMinimum", exclusiveMin)
|
||||||
|
.put("exclusiveMaximum", exclusiveMax);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class BoundedDouble extends BlockProperty {
|
||||||
|
private final double min, max;
|
||||||
|
private final boolean exclusiveMin, exclusiveMax;
|
||||||
|
|
||||||
|
public BoundedDouble(
|
||||||
|
String name,
|
||||||
|
double defaultValue,
|
||||||
|
double min,
|
||||||
|
double max,
|
||||||
|
boolean exclusiveMin,
|
||||||
|
boolean exclusiveMax,
|
||||||
|
Function<Double, String> nameFunction
|
||||||
|
) {
|
||||||
|
super(name, Double.class, defaultValue, List.of(), nameFunction);
|
||||||
|
this.min = min;
|
||||||
|
this.max = max;
|
||||||
|
this.exclusiveMin = exclusiveMin;
|
||||||
|
this.exclusiveMax = exclusiveMax;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JSONObject buildJson() {
|
||||||
|
return super.buildJson()
|
||||||
|
.put("minimum", min)
|
||||||
|
.put("maximum", max)
|
||||||
|
.put("exclusiveMinimum", exclusiveMin)
|
||||||
|
.put("exclusiveMaximum", exclusiveMax);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
package com.volmit.iris.core.nms.container;
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.volmit.iris.engine.object.IrisJigsawStructurePlacement.SpreadType;
|
||||||
|
import lombok.*;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
import lombok.experimental.SuperBuilder;
|
||||||
|
import org.apache.commons.math3.fraction.Fraction;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@SuperBuilder
|
||||||
|
@Accessors(fluent = true, chain = true)
|
||||||
|
public abstract class StructurePlacement {
|
||||||
|
private final int salt;
|
||||||
|
private final float frequency;
|
||||||
|
private final List<Structure> structures;
|
||||||
|
|
||||||
|
public abstract JsonObject toJson(String structure);
|
||||||
|
|
||||||
|
protected JsonObject createBase(String structure) {
|
||||||
|
JsonObject object = new JsonObject();
|
||||||
|
object.addProperty("structure", structure);
|
||||||
|
object.addProperty("salt", salt);
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int frequencyToSpacing() {
|
||||||
|
var frac = new Fraction(Math.max(Math.min(frequency, 1), 0.000000001f));
|
||||||
|
return (int) Math.round(Math.sqrt((double) frac.getDenominator() / frac.getNumerator()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Accessors(chain = true, fluent = true)
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@SuperBuilder
|
||||||
|
public static class RandomSpread extends StructurePlacement {
|
||||||
|
private final int spacing;
|
||||||
|
private final int separation;
|
||||||
|
private final SpreadType spreadType;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JsonObject toJson(String structure) {
|
||||||
|
JsonObject object = createBase(structure);
|
||||||
|
object.addProperty("spacing", Math.max(spacing, frequencyToSpacing()));
|
||||||
|
object.addProperty("separation", separation);
|
||||||
|
object.addProperty("spreadType", spreadType.name());
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@SuperBuilder
|
||||||
|
public static class ConcentricRings extends StructurePlacement {
|
||||||
|
private final int distance;
|
||||||
|
private final int spread;
|
||||||
|
private final int count;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JsonObject toJson(String structure) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public record Structure(
|
||||||
|
int weight,
|
||||||
|
String key,
|
||||||
|
List<String> tags
|
||||||
|
) {
|
||||||
|
|
||||||
|
public boolean isValid() {
|
||||||
|
return weight > 0 && key != null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,6 +13,7 @@ import java.util.function.Supplier;
|
|||||||
//https://minecraft.wiki/w/Pack_format
|
//https://minecraft.wiki/w/Pack_format
|
||||||
@Getter
|
@Getter
|
||||||
public enum DataVersion {
|
public enum DataVersion {
|
||||||
|
UNSUPPORTED("0.0.0", 0, () -> null),
|
||||||
V1192("1.19.2", 10, DataFixerV1192::new),
|
V1192("1.19.2", 10, DataFixerV1192::new),
|
||||||
V1205("1.20.6", 41, DataFixerV1206::new),
|
V1205("1.20.6", 41, DataFixerV1206::new),
|
||||||
V1213("1.21.3", 57, DataFixerV1213::new);
|
V1213("1.21.3", 57, DataFixerV1213::new);
|
||||||
|
|||||||
@@ -1,28 +1,31 @@
|
|||||||
package com.volmit.iris.core.nms.datapack;
|
package com.volmit.iris.core.nms.datapack;
|
||||||
|
|
||||||
import com.volmit.iris.engine.object.IrisBiomeCustom;
|
import com.volmit.iris.engine.object.IrisBiomeCustom;
|
||||||
import com.volmit.iris.engine.object.IrisRange;
|
import com.volmit.iris.engine.object.IrisDimensionTypeOptions;
|
||||||
import com.volmit.iris.util.json.JSONObject;
|
import com.volmit.iris.util.json.JSONObject;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
public interface IDataFixer {
|
public interface IDataFixer {
|
||||||
|
|
||||||
default JSONObject fixCustomBiome(IrisBiomeCustom biome, JSONObject json) {
|
default JSONObject fixCustomBiome(IrisBiomeCustom biome, JSONObject json) {
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSONObject rawDimension(Dimension dimension);
|
JSONObject resolve(Dimension dimension, @Nullable IrisDimensionTypeOptions options);
|
||||||
|
|
||||||
default JSONObject createDimension(Dimension dimension, IrisRange height, int logicalHeight) {
|
void fixDimension(Dimension dimension, JSONObject json);
|
||||||
JSONObject obj = rawDimension(dimension);
|
|
||||||
obj.put("min_y", height.getMin());
|
default JSONObject createDimension(Dimension base, int minY, int height, int logicalHeight, @Nullable IrisDimensionTypeOptions options) {
|
||||||
obj.put("height", height.getMax() - height.getMin());
|
JSONObject obj = resolve(base, options);
|
||||||
|
obj.put("min_y", minY);
|
||||||
|
obj.put("height", height);
|
||||||
obj.put("logical_height", logicalHeight);
|
obj.put("logical_height", logicalHeight);
|
||||||
|
fixDimension(base, obj);
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Dimension {
|
enum Dimension {
|
||||||
OVERRWORLD,
|
OVERWORLD,
|
||||||
NETHER,
|
NETHER,
|
||||||
THE_END
|
END
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,81 +1,104 @@
|
|||||||
package com.volmit.iris.core.nms.datapack.v1192;
|
package com.volmit.iris.core.nms.datapack.v1192;
|
||||||
|
|
||||||
import com.volmit.iris.core.nms.datapack.IDataFixer;
|
import com.volmit.iris.core.nms.datapack.IDataFixer;
|
||||||
|
import com.volmit.iris.engine.object.IrisDimensionTypeOptions;
|
||||||
import com.volmit.iris.util.json.JSONObject;
|
import com.volmit.iris.util.json.JSONObject;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static com.volmit.iris.engine.object.IrisDimensionTypeOptions.TriState.*;
|
||||||
|
|
||||||
public class DataFixerV1192 implements IDataFixer {
|
public class DataFixerV1192 implements IDataFixer {
|
||||||
|
private static final Map<Dimension, IrisDimensionTypeOptions> OPTIONS = Map.of(
|
||||||
|
Dimension.OVERWORLD, new IrisDimensionTypeOptions(
|
||||||
|
FALSE,
|
||||||
|
TRUE,
|
||||||
|
FALSE,
|
||||||
|
FALSE,
|
||||||
|
TRUE,
|
||||||
|
TRUE,
|
||||||
|
TRUE,
|
||||||
|
FALSE,
|
||||||
|
1d,
|
||||||
|
0f,
|
||||||
|
null,
|
||||||
|
192,
|
||||||
|
0),
|
||||||
|
Dimension.NETHER, new IrisDimensionTypeOptions(
|
||||||
|
TRUE,
|
||||||
|
FALSE,
|
||||||
|
TRUE,
|
||||||
|
TRUE,
|
||||||
|
FALSE,
|
||||||
|
FALSE,
|
||||||
|
FALSE,
|
||||||
|
TRUE,
|
||||||
|
8d,
|
||||||
|
0.1f,
|
||||||
|
18000L,
|
||||||
|
null,
|
||||||
|
15),
|
||||||
|
Dimension.END, new IrisDimensionTypeOptions(
|
||||||
|
FALSE,
|
||||||
|
FALSE,
|
||||||
|
FALSE,
|
||||||
|
FALSE,
|
||||||
|
FALSE,
|
||||||
|
TRUE,
|
||||||
|
FALSE,
|
||||||
|
FALSE,
|
||||||
|
1d,
|
||||||
|
0f,
|
||||||
|
6000L,
|
||||||
|
null,
|
||||||
|
0)
|
||||||
|
);
|
||||||
|
|
||||||
private static final Map<Dimension, String> DIMENSIONS = Map.of(
|
private static final Map<Dimension, String> DIMENSIONS = Map.of(
|
||||||
Dimension.OVERRWORLD, """
|
Dimension.OVERWORLD, """
|
||||||
{
|
{
|
||||||
"ambient_light": 0.0,
|
|
||||||
"bed_works": true,
|
|
||||||
"coordinate_scale": 1.0,
|
|
||||||
"effects": "minecraft:overworld",
|
"effects": "minecraft:overworld",
|
||||||
"has_ceiling": false,
|
|
||||||
"has_raids": true,
|
|
||||||
"has_skylight": true,
|
|
||||||
"infiniburn": "#minecraft:infiniburn_overworld",
|
"infiniburn": "#minecraft:infiniburn_overworld",
|
||||||
"monster_spawn_block_light_limit": 0,
|
|
||||||
"monster_spawn_light_level": {
|
"monster_spawn_light_level": {
|
||||||
"type": "minecraft:uniform",
|
"type": "minecraft:uniform",
|
||||||
"value": {
|
"value": {
|
||||||
"max_inclusive": 7,
|
"max_inclusive": 7,
|
||||||
"min_inclusive": 0
|
"min_inclusive": 0
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"natural": true,
|
|
||||||
"piglin_safe": false,
|
|
||||||
"respawn_anchor_works": false,
|
|
||||||
"ultrawarm": false
|
|
||||||
}""",
|
}""",
|
||||||
Dimension.NETHER, """
|
Dimension.NETHER, """
|
||||||
{
|
{
|
||||||
"ambient_light": 0.1,
|
|
||||||
"bed_works": false,
|
|
||||||
"coordinate_scale": 8.0,
|
|
||||||
"effects": "minecraft:the_nether",
|
"effects": "minecraft:the_nether",
|
||||||
"fixed_time": 18000,
|
|
||||||
"has_ceiling": true,
|
|
||||||
"has_raids": false,
|
|
||||||
"has_skylight": false,
|
|
||||||
"infiniburn": "#minecraft:infiniburn_nether",
|
"infiniburn": "#minecraft:infiniburn_nether",
|
||||||
"monster_spawn_block_light_limit": 15,
|
|
||||||
"monster_spawn_light_level": 7,
|
"monster_spawn_light_level": 7,
|
||||||
"natural": false,
|
|
||||||
"piglin_safe": true,
|
|
||||||
"respawn_anchor_works": true,
|
|
||||||
"ultrawarm": true
|
|
||||||
}""",
|
}""",
|
||||||
Dimension.THE_END, """
|
Dimension.END, """
|
||||||
{
|
{
|
||||||
"ambient_light": 0.0,
|
|
||||||
"bed_works": false,
|
|
||||||
"coordinate_scale": 1.0,
|
|
||||||
"effects": "minecraft:the_end",
|
"effects": "minecraft:the_end",
|
||||||
"fixed_time": 6000,
|
|
||||||
"has_ceiling": false,
|
|
||||||
"has_raids": true,
|
|
||||||
"has_skylight": false,
|
|
||||||
"infiniburn": "#minecraft:infiniburn_end",
|
"infiniburn": "#minecraft:infiniburn_end",
|
||||||
"monster_spawn_block_light_limit": 0,
|
|
||||||
"monster_spawn_light_level": {
|
"monster_spawn_light_level": {
|
||||||
"type": "minecraft:uniform",
|
"type": "minecraft:uniform",
|
||||||
"value": {
|
"value": {
|
||||||
"max_inclusive": 7,
|
"max_inclusive": 7,
|
||||||
"min_inclusive": 0
|
"min_inclusive": 0
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"natural": false,
|
|
||||||
"piglin_safe": false,
|
|
||||||
"respawn_anchor_works": false,
|
|
||||||
"ultrawarm": false
|
|
||||||
}"""
|
}"""
|
||||||
);
|
);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JSONObject rawDimension(Dimension dimension) {
|
public JSONObject resolve(Dimension dimension, @Nullable IrisDimensionTypeOptions options) {
|
||||||
return new JSONObject(DIMENSIONS.get(dimension));
|
return options == null ? OPTIONS.get(dimension).toJson() : options.resolve(OPTIONS.get(dimension)).toJson();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fixDimension(Dimension dimension, JSONObject json) {
|
||||||
|
var missing = new JSONObject(DIMENSIONS.get(dimension));
|
||||||
|
for (String key : missing.keySet()) {
|
||||||
|
if (json.has(key)) continue;
|
||||||
|
json.put(key, missing.get(key));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,13 +45,12 @@ public class DataFixerV1206 extends DataFixerV1192 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JSONObject rawDimension(Dimension dimension) {
|
public void fixDimension(Dimension dimension, JSONObject json) {
|
||||||
JSONObject json = super.rawDimension(dimension);
|
super.fixDimension(dimension, json);
|
||||||
if (!(json.get("monster_spawn_light_level") instanceof JSONObject lightLevel))
|
if (!(json.get("monster_spawn_light_level") instanceof JSONObject lightLevel))
|
||||||
return json;
|
return;
|
||||||
var value = (JSONObject) lightLevel.remove("value");
|
var value = (JSONObject) lightLevel.remove("value");
|
||||||
lightLevel.put("max_inclusive", value.get("max_inclusive"));
|
lightLevel.put("max_inclusive", value.get("max_inclusive"));
|
||||||
lightLevel.put("min_inclusive", value.get("min_inclusive"));
|
lightLevel.put("min_inclusive", value.get("min_inclusive"));
|
||||||
return json;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,10 +19,13 @@
|
|||||||
package com.volmit.iris.core.nms.v1X;
|
package com.volmit.iris.core.nms.v1X;
|
||||||
|
|
||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.Iris;
|
||||||
|
import com.volmit.iris.core.link.Identifier;
|
||||||
import com.volmit.iris.core.nms.INMSBinding;
|
import com.volmit.iris.core.nms.INMSBinding;
|
||||||
import com.volmit.iris.core.nms.container.AutoClosing;
|
|
||||||
import com.volmit.iris.core.nms.container.BiomeColor;
|
import com.volmit.iris.core.nms.container.BiomeColor;
|
||||||
|
import com.volmit.iris.core.nms.container.BlockProperty;
|
||||||
|
import com.volmit.iris.core.nms.datapack.DataVersion;
|
||||||
import com.volmit.iris.core.nms.container.Pair;
|
import com.volmit.iris.core.nms.container.Pair;
|
||||||
|
import com.volmit.iris.core.nms.container.StructurePlacement;
|
||||||
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.collection.KMap;
|
import com.volmit.iris.util.collection.KMap;
|
||||||
@@ -41,6 +44,7 @@ import org.bukkit.generator.structure.Structure;
|
|||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
|
import java.util.List;
|
||||||
import java.util.stream.StreamSupport;
|
import java.util.stream.StreamSupport;
|
||||||
|
|
||||||
public class NMSBinding1X implements INMSBinding {
|
public class NMSBinding1X implements INMSBinding {
|
||||||
@@ -121,20 +125,29 @@ public class NMSBinding1X implements INMSBinding {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AutoClosing injectLevelStems() {
|
public boolean missingDimensionTypes(String... keys) {
|
||||||
return new AutoClosing(() -> {});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Pair<Integer, AutoClosing> injectUncached(boolean overworld, boolean nether, boolean end) {
|
|
||||||
return new Pair<>(0, new AutoClosing(() -> {}));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean missingDimensionTypes(boolean overworld, boolean nether, boolean end) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public KMap<Material, List<BlockProperty>> getBlockProperties() {
|
||||||
|
KMap<Material, List<BlockProperty>> map = new KMap<>();
|
||||||
|
for (Material m : Material.values()) {
|
||||||
|
if (m.isBlock()) map.put(m, List.of());
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void placeStructures(Chunk chunk) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public KMap<Identifier, StructurePlacement> collectStructures() {
|
||||||
|
return new KMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompoundTag serializeEntity(Entity location) {
|
public CompoundTag serializeEntity(Entity location) {
|
||||||
return null;
|
return null;
|
||||||
@@ -219,6 +232,11 @@ public class NMSBinding1X implements INMSBinding {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataVersion getDataVersion() {
|
||||||
|
return DataVersion.UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getBiomeId(Biome biome) {
|
public int getBiomeId(Biome biome) {
|
||||||
return biome.ordinal();
|
return biome.ordinal();
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ 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.util.collection.KMap;
|
import com.volmit.iris.util.collection.KMap;
|
||||||
import com.volmit.iris.util.format.Form;
|
import com.volmit.iris.util.format.Form;
|
||||||
import com.volmit.iris.util.mantle.MantleFlag;
|
import com.volmit.iris.util.mantle.flag.MantleFlag;
|
||||||
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;
|
||||||
import com.volmit.iris.util.math.RollingSequence;
|
import com.volmit.iris.util.math.RollingSequence;
|
||||||
@@ -28,6 +28,7 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
public class ChunkUpdater {
|
public class ChunkUpdater {
|
||||||
|
private static final String REGION_PATH = "region" + File.separator + "r.";
|
||||||
private final AtomicBoolean paused = new AtomicBoolean();
|
private final AtomicBoolean paused = new AtomicBoolean();
|
||||||
private final AtomicBoolean cancelled = new AtomicBoolean();
|
private final AtomicBoolean cancelled = new AtomicBoolean();
|
||||||
private final KMap<Long, Pair<Long, AtomicInteger>> lastUse = new KMap<>();
|
private final KMap<Long, Pair<Long, AtomicInteger>> lastUse = new KMap<>();
|
||||||
@@ -38,14 +39,14 @@ public class ChunkUpdater {
|
|||||||
private final AtomicInteger chunksUpdated = new AtomicInteger();
|
private final AtomicInteger chunksUpdated = new AtomicInteger();
|
||||||
private final AtomicBoolean serverEmpty = new AtomicBoolean(true);
|
private final AtomicBoolean serverEmpty = new AtomicBoolean(true);
|
||||||
private final AtomicLong lastCpsTime = new AtomicLong(M.ms());
|
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 int maxConcurrency = IrisSettings.get().getUpdater().getMaxConcurrency();
|
||||||
private final Semaphore semaphore = new Semaphore(256);
|
private final Semaphore semaphore = new Semaphore(maxConcurrency);
|
||||||
private final LoadBalancer loadBalancer = new LoadBalancer(semaphore, 256, IrisSettings.get().getUpdater().emptyMsRange);
|
private final LoadBalancer loadBalancer = new LoadBalancer(semaphore, maxConcurrency, IrisSettings.get().getUpdater().emptyMsRange);
|
||||||
private final AtomicLong startTime = new AtomicLong();
|
private final AtomicLong startTime = new AtomicLong();
|
||||||
private final Dimensions dimensions;
|
private final Dimensions dimensions;
|
||||||
private final PregenTask task;
|
private final PregenTask task;
|
||||||
private final ExecutorService executor = Executors.newFixedThreadPool(coreLimit);
|
private final ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor();
|
||||||
private final ExecutorService chunkExecutor = Executors.newFixedThreadPool(coreLimit);
|
private final ExecutorService chunkExecutor = Executors.newVirtualThreadPerTaskExecutor();
|
||||||
private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
|
private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
|
||||||
private final CountDownLatch latch;
|
private final CountDownLatch latch;
|
||||||
private final Engine engine;
|
private final Engine engine;
|
||||||
@@ -108,6 +109,7 @@ public class ChunkUpdater {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
Iris.reportError(e);
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}, 0, 3, TimeUnit.SECONDS);
|
}, 0, 3, TimeUnit.SECONDS);
|
||||||
@@ -136,10 +138,10 @@ public class ChunkUpdater {
|
|||||||
loadBalancer.close();
|
loadBalancer.close();
|
||||||
semaphore.acquire(256);
|
semaphore.acquire(256);
|
||||||
|
|
||||||
executor.shutdown();
|
|
||||||
executor.awaitTermination(5, TimeUnit.SECONDS);
|
|
||||||
chunkExecutor.shutdown();
|
chunkExecutor.shutdown();
|
||||||
chunkExecutor.awaitTermination(5, TimeUnit.SECONDS);
|
chunkExecutor.awaitTermination(5, TimeUnit.SECONDS);
|
||||||
|
executor.shutdown();
|
||||||
|
executor.awaitTermination(5, TimeUnit.SECONDS);
|
||||||
scheduler.shutdownNow();
|
scheduler.shutdownNow();
|
||||||
unloadAndSaveAllChunks();
|
unloadAndSaveAllChunks();
|
||||||
} catch (Exception ignored) {}
|
} catch (Exception ignored) {}
|
||||||
@@ -162,12 +164,12 @@ public class ChunkUpdater {
|
|||||||
J.sleep(50);
|
J.sleep(50);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rX < dimensions.min.getX() || rX > dimensions.max.getX() || rZ < dimensions.min.getZ() || rZ > dimensions.max.getZ()) {
|
if (rX < dimensions.min.getX() ||
|
||||||
return;
|
rX > dimensions.max.getX() ||
|
||||||
}
|
rZ < dimensions.min.getZ() ||
|
||||||
if (!new File(world.getWorldFolder(), "region" + File.separator + rX + "." + rZ + ".mca").exists()) {
|
rZ > dimensions.max.getZ() ||
|
||||||
return;
|
!new File(world.getWorldFolder(), REGION_PATH + rX + "." + rZ + ".mca").exists()
|
||||||
}
|
) return;
|
||||||
|
|
||||||
task.iterateChunks(rX, rZ, (x, z) -> {
|
task.iterateChunks(rX, rZ, (x, z) -> {
|
||||||
while (paused.get() && !cancelled.get()) {
|
while (paused.get() && !cancelled.get()) {
|
||||||
@@ -313,6 +315,7 @@ public class ChunkUpdater {
|
|||||||
world.save();
|
world.save();
|
||||||
}).get();
|
}).get();
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
|
Iris.reportError(e);
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,28 +31,33 @@ 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 com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||||
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
|
|
||||||
public class IrisPregenerator {
|
public class IrisPregenerator {
|
||||||
|
private static final double INVALID = 9223372036854775807d;
|
||||||
private final PregenTask task;
|
private final PregenTask task;
|
||||||
private final PregeneratorMethod generator;
|
private final PregeneratorMethod generator;
|
||||||
private final PregenListener listener;
|
private final PregenListener listener;
|
||||||
private final Looper ticker;
|
private final Looper ticker;
|
||||||
private final AtomicBoolean paused;
|
private final AtomicBoolean paused;
|
||||||
private final AtomicBoolean shutdown;
|
private final AtomicBoolean shutdown;
|
||||||
|
private final RollingSequence cachedPerSecond;
|
||||||
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 final KList<Integer> chunksPerSecondHistory;
|
||||||
private static AtomicInteger generated;
|
private final AtomicLong generated;
|
||||||
private final AtomicInteger generatedLast;
|
private final AtomicLong generatedLast;
|
||||||
private final AtomicInteger generatedLastMinute;
|
private final AtomicLong generatedLastMinute;
|
||||||
private static AtomicInteger totalChunks;
|
private final AtomicLong cached;
|
||||||
|
private final AtomicLong cachedLast;
|
||||||
|
private final AtomicLong cachedLastMinute;
|
||||||
|
private final AtomicLong totalChunks;
|
||||||
private final AtomicLong startTime;
|
private final AtomicLong startTime;
|
||||||
private final ChronoLatch minuteLatch;
|
private final ChronoLatch minuteLatch;
|
||||||
private final AtomicReference<String> currentGeneratorMethod;
|
private final AtomicReference<String> currentGeneratorMethod;
|
||||||
@@ -61,8 +66,10 @@ 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);
|
||||||
|
private final IrisPackBenchmarking benchmarking;
|
||||||
|
|
||||||
public IrisPregenerator(PregenTask task, PregeneratorMethod generator, PregenListener listener) {
|
public IrisPregenerator(PregenTask task, PregeneratorMethod generator, PregenListener listener) {
|
||||||
|
benchmarking = IrisPackBenchmarking.getInstance();
|
||||||
this.listener = listenify(listener);
|
this.listener = listenify(listener);
|
||||||
cl = new ChronoLatch(5000);
|
cl = new ChronoLatch(5000);
|
||||||
generatedRegions = new KSet<>();
|
generatedRegions = new KSet<>();
|
||||||
@@ -74,46 +81,71 @@ public class IrisPregenerator {
|
|||||||
net = new KSet<>();
|
net = new KSet<>();
|
||||||
currentGeneratorMethod = new AtomicReference<>("Void");
|
currentGeneratorMethod = new AtomicReference<>("Void");
|
||||||
minuteLatch = new ChronoLatch(60000, false);
|
minuteLatch = new ChronoLatch(60000, false);
|
||||||
|
cachedPerSecond = new RollingSequence(5);
|
||||||
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<>();
|
chunksPerSecondHistory = new KList<>();
|
||||||
generated = new AtomicInteger(0);
|
generated = new AtomicLong(0);
|
||||||
generatedLast = new AtomicInteger(0);
|
generatedLast = new AtomicLong(0);
|
||||||
generatedLastMinute = new AtomicInteger(0);
|
generatedLastMinute = new AtomicLong(0);
|
||||||
totalChunks = new AtomicInteger(0);
|
cached = new AtomicLong();
|
||||||
|
cachedLast = new AtomicLong(0);
|
||||||
|
cachedLastMinute = new AtomicLong(0);
|
||||||
|
totalChunks = new AtomicLong(0);
|
||||||
task.iterateAllChunks((_a, _b) -> totalChunks.incrementAndGet());
|
task.iterateAllChunks((_a, _b) -> totalChunks.incrementAndGet());
|
||||||
startTime = new AtomicLong(M.ms());
|
startTime = new AtomicLong(M.ms());
|
||||||
ticker = new Looper() {
|
ticker = new Looper() {
|
||||||
@Override
|
@Override
|
||||||
protected long loop() {
|
protected long loop() {
|
||||||
long eta = computeETA();
|
long eta = computeETA();
|
||||||
int secondGenerated = generated.get() - generatedLast.get();
|
|
||||||
generatedLast.set(generated.get());
|
|
||||||
chunksPerSecond.put(secondGenerated);
|
|
||||||
chunksPerSecondHistory.add(secondGenerated);
|
|
||||||
|
|
||||||
if (minuteLatch.flip()) {
|
long secondCached = cached.get() - cachedLast.get();
|
||||||
int minuteGenerated = generated.get() - generatedLastMinute.get();
|
cachedLast.set(cached.get());
|
||||||
generatedLastMinute.set(generated.get());
|
cachedPerSecond.put(secondCached);
|
||||||
chunksPerMinute.put(minuteGenerated);
|
|
||||||
regionsPerMinute.put((double) minuteGenerated / 1024D);
|
long secondGenerated = generated.get() - generatedLast.get() - secondCached;
|
||||||
|
generatedLast.set(generated.get());
|
||||||
|
if (secondCached == 0 || secondGenerated != 0) {
|
||||||
|
chunksPerSecond.put(secondGenerated);
|
||||||
|
chunksPerSecondHistory.add((int) secondGenerated);
|
||||||
}
|
}
|
||||||
|
|
||||||
listener.onTick(chunksPerSecond.getAverage(), chunksPerMinute.getAverage(),
|
if (minuteLatch.flip()) {
|
||||||
|
long minuteCached = cached.get() - cachedLastMinute.get();
|
||||||
|
cachedLastMinute.set(cached.get());
|
||||||
|
|
||||||
|
long minuteGenerated = generated.get() - generatedLastMinute.get() - minuteCached;
|
||||||
|
generatedLastMinute.set(generated.get());
|
||||||
|
if (minuteCached == 0 || minuteGenerated != 0) {
|
||||||
|
chunksPerMinute.put(minuteGenerated);
|
||||||
|
regionsPerMinute.put((double) minuteGenerated / 1024D);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
boolean cached = cachedPerSecond.getAverage() != 0;
|
||||||
|
|
||||||
|
listener.onTick(
|
||||||
|
cached ? cachedPerSecond.getAverage() : chunksPerSecond.getAverage(),
|
||||||
|
chunksPerMinute.getAverage(),
|
||||||
regionsPerMinute.getAverage(),
|
regionsPerMinute.getAverage(),
|
||||||
(double) generated.get() / (double) totalChunks.get(),
|
(double) generated.get() / (double) totalChunks.get(), generated.get(),
|
||||||
generated.get(), totalChunks.get(),
|
totalChunks.get(),
|
||||||
totalChunks.get() - generated.get(),
|
totalChunks.get() - generated.get(), eta, M.ms() - startTime.get(), currentGeneratorMethod.get(),
|
||||||
eta, M.ms() - startTime.get(), currentGeneratorMethod.get());
|
cached);
|
||||||
|
|
||||||
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 (!IrisPackBenchmarking.benchmarkInProgress) {
|
|
||||||
Iris.info("Pregen: " + Form.f(generated.get()) + " of " + Form.f(totalChunks.get()) + " (%.0f%%) " + Form.f((int) chunksPerSecond.getAverage()) + "/s ETA: " + Form.duration(eta, 2), percentage);
|
Iris.info("%s: %s of %s (%.0f%%), %s/s ETA: %s",
|
||||||
} else {
|
benchmarking != null ? "Benchmarking" : "Pregen",
|
||||||
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);
|
Form.f(generated.get()),
|
||||||
}
|
Form.f(totalChunks.get()),
|
||||||
|
percentage,
|
||||||
|
cached ?
|
||||||
|
"Cached " + Form.f((int) cachedPerSecond.getAverage()) :
|
||||||
|
Form.f((int) chunksPerSecond.getAverage()),
|
||||||
|
Form.duration(eta, 2)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return 1000;
|
return 1000;
|
||||||
}
|
}
|
||||||
@@ -121,12 +153,12 @@ public class IrisPregenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private long computeETA() {
|
private long computeETA() {
|
||||||
return (long) (totalChunks.get() > 1024 ? // Generated chunks exceed 1/8th of total?
|
double d = (long) (generated.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)
|
// 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);
|
||||||
);
|
return Double.isFinite(d) && d != INVALID ? (long) d : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -138,13 +170,15 @@ public class IrisPregenerator {
|
|||||||
init();
|
init();
|
||||||
ticker.start();
|
ticker.start();
|
||||||
checkRegions();
|
checkRegions();
|
||||||
|
var p = PrecisionStopwatch.start();
|
||||||
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));
|
||||||
|
Iris.info("Pregen took " + Form.duration((long) p.getMilliseconds()));
|
||||||
shutdown();
|
shutdown();
|
||||||
if (!IrisPackBenchmarking.benchmarkInProgress) {
|
if (benchmarking == null) {
|
||||||
Iris.info(C.IRIS + "Pregen stopped.");
|
Iris.info(C.IRIS + "Pregen stopped.");
|
||||||
} else {
|
} else {
|
||||||
IrisPackBenchmarking.instance.finishedBenchmark(chunksPerSecondHistory);
|
benchmarking.finishedBenchmark(chunksPerSecondHistory);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -234,8 +268,8 @@ public class IrisPregenerator {
|
|||||||
private PregenListener listenify(PregenListener listener) {
|
private PregenListener listenify(PregenListener listener) {
|
||||||
return new PregenListener() {
|
return new PregenListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onTick(double chunksPerSecond, double chunksPerMinute, double regionsPerMinute, double percent, int generated, int totalChunks, int chunksRemaining, long eta, long elapsed, String method) {
|
public void onTick(double chunksPerSecond, double chunksPerMinute, double regionsPerMinute, double percent, long generated, long totalChunks, long chunksRemaining, long eta, long elapsed, String method, boolean cached) {
|
||||||
listener.onTick(chunksPerSecond, chunksPerMinute, regionsPerMinute, percent, generated, totalChunks, chunksRemaining, eta, elapsed, method);
|
listener.onTick(chunksPerSecond, chunksPerMinute, regionsPerMinute, percent, generated, totalChunks, chunksRemaining, eta, elapsed, method, cached);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -244,9 +278,10 @@ public class IrisPregenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onChunkGenerated(int x, int z) {
|
public void onChunkGenerated(int x, int z, boolean c) {
|
||||||
listener.onChunkGenerated(x, z);
|
listener.onChunkGenerated(x, z, c);
|
||||||
generated.addAndGet(1);
|
generated.addAndGet(1);
|
||||||
|
if (c) cached.addAndGet(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -19,11 +19,15 @@
|
|||||||
package com.volmit.iris.core.pregenerator;
|
package com.volmit.iris.core.pregenerator;
|
||||||
|
|
||||||
public interface PregenListener {
|
public interface PregenListener {
|
||||||
void onTick(double chunksPerSecond, double chunksPerMinute, double regionsPerMinute, double percent, int generated, int totalChunks, int chunksRemaining, long eta, long elapsed, String method);
|
void onTick(double chunksPerSecond, double chunksPerMinute, double regionsPerMinute, double percent, long generated, long totalChunks, long chunksRemaining, long eta, long elapsed, String method, boolean cached);
|
||||||
|
|
||||||
void onChunkGenerating(int x, int z);
|
void onChunkGenerating(int x, int z);
|
||||||
|
|
||||||
void onChunkGenerated(int x, int z);
|
default void onChunkGenerated(int x, int z) {
|
||||||
|
onChunkGenerated(x, z, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void onChunkGenerated(int x, int z, boolean cached);
|
||||||
|
|
||||||
void onRegionGenerated(int x, int z);
|
void onRegionGenerated(int x, int z);
|
||||||
|
|
||||||
|
|||||||
70
core/src/main/java/com/volmit/iris/core/pregenerator/cache/PregenCache.java
vendored
Normal file
70
core/src/main/java/com/volmit/iris/core/pregenerator/cache/PregenCache.java
vendored
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
package com.volmit.iris.core.pregenerator.cache;
|
||||||
|
|
||||||
|
import com.volmit.iris.util.documentation.ChunkCoordinates;
|
||||||
|
import com.volmit.iris.util.documentation.RegionCoordinates;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
public interface PregenCache {
|
||||||
|
default boolean isThreadSafe() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ChunkCoordinates
|
||||||
|
boolean isChunkCached(int x, int z);
|
||||||
|
|
||||||
|
@RegionCoordinates
|
||||||
|
boolean isRegionCached(int x, int z);
|
||||||
|
|
||||||
|
@ChunkCoordinates
|
||||||
|
void cacheChunk(int x, int z);
|
||||||
|
|
||||||
|
@RegionCoordinates
|
||||||
|
void cacheRegion(int x, int z);
|
||||||
|
|
||||||
|
void write();
|
||||||
|
|
||||||
|
static PregenCache create(File directory) {
|
||||||
|
if (directory == null) return EMPTY;
|
||||||
|
return new PregenCacheImpl(directory);
|
||||||
|
}
|
||||||
|
|
||||||
|
default PregenCache sync() {
|
||||||
|
if (isThreadSafe()) return this;
|
||||||
|
return new SynchronizedCache(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
PregenCache EMPTY = new PregenCache() {
|
||||||
|
@Override
|
||||||
|
public boolean isThreadSafe() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isChunkCached(int x, int z) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isRegionCached(int x, int z) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cacheChunk(int x, int z) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cacheRegion(int x, int z) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write() {
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
220
core/src/main/java/com/volmit/iris/core/pregenerator/cache/PregenCacheImpl.java
vendored
Normal file
220
core/src/main/java/com/volmit/iris/core/pregenerator/cache/PregenCacheImpl.java
vendored
Normal file
@@ -0,0 +1,220 @@
|
|||||||
|
package com.volmit.iris.core.pregenerator.cache;
|
||||||
|
|
||||||
|
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||||
|
import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||||
|
import com.github.benmanes.caffeine.cache.RemovalCause;
|
||||||
|
import com.github.benmanes.caffeine.cache.Scheduler;
|
||||||
|
import com.volmit.iris.Iris;
|
||||||
|
import com.volmit.iris.util.data.KCache;
|
||||||
|
import com.volmit.iris.util.data.Varint;
|
||||||
|
import com.volmit.iris.util.documentation.ChunkCoordinates;
|
||||||
|
import com.volmit.iris.util.documentation.RegionCoordinates;
|
||||||
|
import com.volmit.iris.util.io.IO;
|
||||||
|
import com.volmit.iris.util.parallel.HyperLock;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import net.jpountz.lz4.LZ4BlockInputStream;
|
||||||
|
import net.jpountz.lz4.LZ4BlockOutputStream;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
class PregenCacheImpl implements PregenCache {
|
||||||
|
private static final int SIZE = 32;
|
||||||
|
private final File directory;
|
||||||
|
private final HyperLock hyperLock = new HyperLock(SIZE * 2, true);
|
||||||
|
private final LoadingCache<Pos, Plate> cache = Caffeine.newBuilder()
|
||||||
|
.expireAfterAccess(10, TimeUnit.SECONDS)
|
||||||
|
.executor(KCache.EXECUTOR)
|
||||||
|
.scheduler(Scheduler.systemScheduler())
|
||||||
|
.maximumSize(SIZE)
|
||||||
|
.removalListener(this::onRemoval)
|
||||||
|
.evictionListener(this::onRemoval)
|
||||||
|
.build(this::load);
|
||||||
|
|
||||||
|
@ChunkCoordinates
|
||||||
|
public boolean isChunkCached(int x, int z) {
|
||||||
|
var plate = cache.get(new Pos(x >> 10, z >> 10));
|
||||||
|
if (plate == null) return false;
|
||||||
|
return plate.isCached((x >> 5) & 31, (z >> 5) & 31, r -> r.isCached(x & 31, z & 31));
|
||||||
|
}
|
||||||
|
|
||||||
|
@RegionCoordinates
|
||||||
|
public boolean isRegionCached(int x, int z) {
|
||||||
|
var plate = cache.get(new Pos(x >> 5, z >> 5));
|
||||||
|
if (plate == null) return false;
|
||||||
|
return plate.isCached(x & 31, z & 31, Region::isCached);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ChunkCoordinates
|
||||||
|
public void cacheChunk(int x, int z) {
|
||||||
|
var plate = cache.get(new Pos(x >> 10, z >> 10));
|
||||||
|
plate.cache((x >> 5) & 31, (z >> 5) & 31, r -> r.cache(x & 31, z & 31));
|
||||||
|
}
|
||||||
|
|
||||||
|
@RegionCoordinates
|
||||||
|
public void cacheRegion(int x, int z) {
|
||||||
|
var plate = cache.get(new Pos(x >> 5, z >> 5));
|
||||||
|
plate.cache(x & 31, z & 31, Region::cache);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write() {
|
||||||
|
cache.asMap().values().forEach(this::write);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Plate load(Pos key) {
|
||||||
|
hyperLock.lock(key.x, key.z);
|
||||||
|
try {
|
||||||
|
File file = fileForPlate(key);
|
||||||
|
if (!file.exists()) return new Plate(key);
|
||||||
|
try (var in = new DataInputStream(new LZ4BlockInputStream(new FileInputStream(file)))) {
|
||||||
|
return new Plate(key, in);
|
||||||
|
} catch (IOException e){
|
||||||
|
Iris.error("Failed to read pregen cache " + file);
|
||||||
|
Iris.reportError(e);
|
||||||
|
e.printStackTrace();
|
||||||
|
return new Plate(key);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
hyperLock.unlock(key.x, key.z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void write(Plate plate) {
|
||||||
|
hyperLock.lock(plate.pos.x, plate.pos.z);
|
||||||
|
try {
|
||||||
|
File file = fileForPlate(plate.pos);
|
||||||
|
try {
|
||||||
|
IO.write(file, out -> new DataOutputStream(new LZ4BlockOutputStream(out)), plate::write);
|
||||||
|
} catch (IOException e) {
|
||||||
|
Iris.error("Failed to write pregen cache " + file);
|
||||||
|
Iris.reportError(e);
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
hyperLock.unlock(plate.pos.x, plate.pos.z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onRemoval(@Nullable Pos key, @Nullable Plate plate, RemovalCause cause) {
|
||||||
|
if (plate == null) return;
|
||||||
|
write(plate);
|
||||||
|
}
|
||||||
|
|
||||||
|
private File fileForPlate(Pos pos) {
|
||||||
|
if (!directory.exists() && !directory.mkdirs())
|
||||||
|
throw new IllegalStateException("Cannot create directory: " + directory.getAbsolutePath());
|
||||||
|
return new File(directory, "c." + pos.x + "." + pos.z + ".lz4b");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Plate {
|
||||||
|
private final Pos pos;
|
||||||
|
private short count;
|
||||||
|
private Region[] regions;
|
||||||
|
|
||||||
|
public Plate(Pos pos) {
|
||||||
|
this.pos = pos;
|
||||||
|
count = 0;
|
||||||
|
regions = new Region[1024];
|
||||||
|
}
|
||||||
|
|
||||||
|
public Plate(Pos pos, DataInput in) throws IOException {
|
||||||
|
this.pos = pos;
|
||||||
|
count = (short) Varint.readSignedVarInt(in);
|
||||||
|
if (count == 1024) return;
|
||||||
|
regions = new Region[1024];
|
||||||
|
for (int i = 0; i < 1024; i++) {
|
||||||
|
if (in.readBoolean()) continue;
|
||||||
|
regions[i] = new Region(in);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCached(int x, int z, Predicate<Region> predicate) {
|
||||||
|
if (count == 1024) return true;
|
||||||
|
Region region = regions[x * 32 + z];
|
||||||
|
if (region == null) return false;
|
||||||
|
return predicate.test(region);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cache(int x, int z, Predicate<Region> predicate) {
|
||||||
|
if (count == 1024) return;
|
||||||
|
Region region = regions[x * 32 + z];
|
||||||
|
if (region == null) regions[x * 32 + z] = region = new Region();
|
||||||
|
if (predicate.test(region)) count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(DataOutput out) throws IOException {
|
||||||
|
Varint.writeSignedVarInt(count, out);
|
||||||
|
if (count == 1024) return;
|
||||||
|
for (Region region : regions) {
|
||||||
|
out.writeBoolean(region == null);
|
||||||
|
if (region == null) continue;
|
||||||
|
region.write(out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Region {
|
||||||
|
private short count;
|
||||||
|
private long[] words;
|
||||||
|
|
||||||
|
public Region() {
|
||||||
|
count = 0;
|
||||||
|
words = new long[64];
|
||||||
|
}
|
||||||
|
|
||||||
|
public Region(DataInput in) throws IOException {
|
||||||
|
count = (short) Varint.readSignedVarInt(in);
|
||||||
|
if (count == 1024) return;
|
||||||
|
words = new long[64];
|
||||||
|
for (int i = 0; i < 64; i++) {
|
||||||
|
words[i] = Varint.readUnsignedVarLong(in);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean cache() {
|
||||||
|
if (count == 1024) return false;
|
||||||
|
count = 1024;
|
||||||
|
words = null;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean cache(int x, int z) {
|
||||||
|
if (count == 1024) return false;
|
||||||
|
|
||||||
|
int i = x * 32 + z;
|
||||||
|
int w = i >> 6;
|
||||||
|
long b = 1L << (i & 63);
|
||||||
|
|
||||||
|
var cur = (words[w] & b) != 0;
|
||||||
|
if (cur) return false;
|
||||||
|
|
||||||
|
if (++count == 1024) {
|
||||||
|
words = null;
|
||||||
|
return true;
|
||||||
|
} else words[w] |= b;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCached() {
|
||||||
|
return count == 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCached(int x, int z) {
|
||||||
|
int i = x * 32 + z;
|
||||||
|
return count == 1024 || (words[i >> 6] & 1L << (i & 63)) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(DataOutput out) throws IOException {
|
||||||
|
Varint.writeSignedVarInt(count, out);
|
||||||
|
if (isCached()) return;
|
||||||
|
for (long word : words) {
|
||||||
|
Varint.writeUnsignedVarLong(word, out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private record Pos(int x, int z) {}
|
||||||
|
}
|
||||||
48
core/src/main/java/com/volmit/iris/core/pregenerator/cache/SynchronizedCache.java
vendored
Normal file
48
core/src/main/java/com/volmit/iris/core/pregenerator/cache/SynchronizedCache.java
vendored
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
package com.volmit.iris.core.pregenerator.cache;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
class SynchronizedCache implements PregenCache {
|
||||||
|
private final PregenCache cache;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isThreadSafe() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isChunkCached(int x, int z) {
|
||||||
|
synchronized (cache) {
|
||||||
|
return cache.isChunkCached(x, z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isRegionCached(int x, int z) {
|
||||||
|
synchronized (cache) {
|
||||||
|
return cache.isRegionCached(x, z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cacheChunk(int x, int z) {
|
||||||
|
synchronized (cache) {
|
||||||
|
cache.cacheChunk(x, z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cacheRegion(int x, int z) {
|
||||||
|
synchronized (cache) {
|
||||||
|
cache.cacheRegion(x, z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write() {
|
||||||
|
synchronized (cache) {
|
||||||
|
cache.write();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,6 +19,7 @@
|
|||||||
package com.volmit.iris.core.pregenerator.methods;
|
package com.volmit.iris.core.pregenerator.methods;
|
||||||
|
|
||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.Iris;
|
||||||
|
import com.volmit.iris.core.IrisSettings;
|
||||||
import com.volmit.iris.core.pregenerator.PregenListener;
|
import com.volmit.iris.core.pregenerator.PregenListener;
|
||||||
import com.volmit.iris.core.pregenerator.PregeneratorMethod;
|
import com.volmit.iris.core.pregenerator.PregeneratorMethod;
|
||||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||||
@@ -31,24 +32,32 @@ import io.papermc.lib.PaperLib;
|
|||||||
import org.bukkit.Chunk;
|
import org.bukkit.Chunk;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.Semaphore;
|
import java.util.concurrent.Semaphore;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
public class AsyncPregenMethod implements PregeneratorMethod {
|
public class AsyncPregenMethod implements PregeneratorMethod {
|
||||||
|
private static final AtomicInteger THREAD_COUNT = new AtomicInteger();
|
||||||
private final World world;
|
private final World world;
|
||||||
private final MultiBurst burst;
|
private final Executor executor;
|
||||||
private final Semaphore semaphore;
|
private final Semaphore semaphore;
|
||||||
|
private final int threads;
|
||||||
|
private final boolean urgent;
|
||||||
private final Map<Chunk, Long> lastUse;
|
private final Map<Chunk, Long> lastUse;
|
||||||
|
|
||||||
public AsyncPregenMethod(World world, int threads) {
|
public AsyncPregenMethod(World world, int unusedThreads) {
|
||||||
if (!PaperLib.isPaper()) {
|
if (!PaperLib.isPaper()) {
|
||||||
throw new UnsupportedOperationException("Cannot use PaperAsync on non paper!");
|
throw new UnsupportedOperationException("Cannot use PaperAsync on non paper!");
|
||||||
}
|
}
|
||||||
|
|
||||||
this.world = world;
|
this.world = world;
|
||||||
burst = new MultiBurst("Iris Async Pregen", Thread.MIN_PRIORITY);
|
this.executor = IrisSettings.get().getPregen().isUseTicketQueue() ? new TicketExecutor() : new ServiceExecutor();
|
||||||
semaphore = new Semaphore(256);
|
this.threads = IrisSettings.get().getPregen().getMaxConcurrency();
|
||||||
|
this.semaphore = new Semaphore(this.threads, true);
|
||||||
|
this.urgent = IrisSettings.get().getPregen().useHighPriority;
|
||||||
this.lastUse = new KMap<>();
|
this.lastUse = new KMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,13 +69,18 @@ public class AsyncPregenMethod implements PregeneratorMethod {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Chunk i : new ArrayList<>(lastUse.keySet())) {
|
long minTime = M.ms() - 10_000;
|
||||||
Long lastUseTime = lastUse.get(i);
|
lastUse.entrySet().removeIf(i -> {
|
||||||
if (!i.isLoaded() || (lastUseTime != null && M.ms() - lastUseTime >= 10000)) {
|
final Chunk chunk = i.getKey();
|
||||||
i.unload();
|
final Long lastUseTime = i.getValue();
|
||||||
lastUse.remove(i);
|
if (!chunk.isLoaded() || lastUseTime == null)
|
||||||
|
return true;
|
||||||
|
if (lastUseTime < minTime) {
|
||||||
|
chunk.unload();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
return false;
|
||||||
|
});
|
||||||
world.save();
|
world.save();
|
||||||
}).get();
|
}).get();
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
@@ -74,24 +88,10 @@ public class AsyncPregenMethod implements PregeneratorMethod {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void completeChunk(int x, int z, PregenListener listener) {
|
|
||||||
try {
|
|
||||||
PaperLib.getChunkAtAsync(world, x, z, true).thenAccept((i) -> {
|
|
||||||
lastUse.put(i, M.ms());
|
|
||||||
listener.onChunkGenerated(x, z);
|
|
||||||
listener.onChunkCleaned(x, z);
|
|
||||||
}).get();
|
|
||||||
} catch (InterruptedException ignored) {
|
|
||||||
} catch (Throwable e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} finally {
|
|
||||||
semaphore.release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init() {
|
public void init() {
|
||||||
unloadAndSaveAllChunks();
|
unloadAndSaveAllChunks();
|
||||||
|
increaseWorkerThreads();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -101,9 +101,10 @@ public class AsyncPregenMethod implements PregeneratorMethod {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {
|
||||||
semaphore.acquireUninterruptibly(256);
|
semaphore.acquireUninterruptibly(threads);
|
||||||
unloadAndSaveAllChunks();
|
unloadAndSaveAllChunks();
|
||||||
burst.close();
|
executor.shutdown();
|
||||||
|
resetWorkerThreads();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -129,7 +130,7 @@ public class AsyncPregenMethod implements PregeneratorMethod {
|
|||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
burst.complete(() -> completeChunk(x, z, listener));
|
executor.generate(x, z, listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -140,4 +141,100 @@ public class AsyncPregenMethod implements PregeneratorMethod {
|
|||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void increaseWorkerThreads() {
|
||||||
|
THREAD_COUNT.updateAndGet(i -> {
|
||||||
|
if (i > 0) return 1;
|
||||||
|
var adjusted = IrisSettings.get().getConcurrency().getWorldGenThreads();
|
||||||
|
try {
|
||||||
|
var field = Class.forName("ca.spottedleaf.moonrise.common.util.MoonriseCommon").getDeclaredField("WORKER_POOL");
|
||||||
|
var pool = field.get(null);
|
||||||
|
var threads = ((Thread[]) pool.getClass().getDeclaredMethod("getCoreThreads").invoke(pool)).length;
|
||||||
|
if (threads >= adjusted) return 0;
|
||||||
|
|
||||||
|
pool.getClass().getDeclaredMethod("adjustThreadCount", int.class).invoke(pool, adjusted);
|
||||||
|
return threads;
|
||||||
|
} catch (Throwable e) {
|
||||||
|
Iris.warn("Failed to increase worker threads, if you are on paper or a fork of it please increase it manually to " + adjusted);
|
||||||
|
Iris.warn("For more information see https://docs.papermc.io/paper/reference/global-configuration#chunk_system_worker_threads");
|
||||||
|
if (e instanceof InvocationTargetException) {
|
||||||
|
Iris.reportError(e);
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void resetWorkerThreads() {
|
||||||
|
THREAD_COUNT.updateAndGet(i -> {
|
||||||
|
if (i == 0) return 0;
|
||||||
|
try {
|
||||||
|
var field = Class.forName("ca.spottedleaf.moonrise.common.util.MoonriseCommon").getDeclaredField("WORKER_POOL");
|
||||||
|
var pool = field.get(null);
|
||||||
|
var method = pool.getClass().getDeclaredMethod("adjustThreadCount", int.class);
|
||||||
|
method.invoke(pool, i);
|
||||||
|
return 0;
|
||||||
|
} catch (Throwable e) {
|
||||||
|
Iris.reportError(e);
|
||||||
|
Iris.error("Failed to reset worker threads");
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private interface Executor {
|
||||||
|
void generate(int x, int z, PregenListener listener);
|
||||||
|
default void shutdown() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ServiceExecutor implements Executor {
|
||||||
|
private final ExecutorService service = IrisSettings.get().getPregen().isUseVirtualThreads() ?
|
||||||
|
Executors.newVirtualThreadPerTaskExecutor() :
|
||||||
|
new MultiBurst("Iris Async Pregen");
|
||||||
|
|
||||||
|
public void generate(int x, int z, PregenListener listener) {
|
||||||
|
service.submit(() -> {
|
||||||
|
try {
|
||||||
|
PaperLib.getChunkAtAsync(world, x, z, true, urgent).thenAccept((i) -> {
|
||||||
|
listener.onChunkGenerated(x, z);
|
||||||
|
listener.onChunkCleaned(x, z);
|
||||||
|
if (i == null) return;
|
||||||
|
lastUse.put(i, M.ms());
|
||||||
|
}).get();
|
||||||
|
} catch (InterruptedException ignored) {
|
||||||
|
} catch (Throwable e) {
|
||||||
|
Iris.reportError(e);
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
semaphore.release();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void shutdown() {
|
||||||
|
service.shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TicketExecutor implements Executor {
|
||||||
|
@Override
|
||||||
|
public void generate(int x, int z, PregenListener listener) {
|
||||||
|
PaperLib.getChunkAtAsync(world, x, z, true, urgent)
|
||||||
|
.exceptionally(e -> {
|
||||||
|
Iris.reportError(e);
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
})
|
||||||
|
.thenAccept(i -> {
|
||||||
|
semaphore.release();
|
||||||
|
listener.onChunkGenerated(x, z);
|
||||||
|
listener.onChunkCleaned(x, z);
|
||||||
|
if (i == null) return;
|
||||||
|
lastUse.put(i, M.ms());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,86 @@
|
|||||||
|
package com.volmit.iris.core.pregenerator.methods;
|
||||||
|
|
||||||
|
import com.volmit.iris.Iris;
|
||||||
|
import com.volmit.iris.core.pregenerator.PregenListener;
|
||||||
|
import com.volmit.iris.core.pregenerator.PregeneratorMethod;
|
||||||
|
import com.volmit.iris.core.pregenerator.cache.PregenCache;
|
||||||
|
import com.volmit.iris.core.service.GlobalCacheSVC;
|
||||||
|
import com.volmit.iris.util.mantle.Mantle;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class CachedPregenMethod implements PregeneratorMethod {
|
||||||
|
private final PregeneratorMethod method;
|
||||||
|
private final PregenCache cache;
|
||||||
|
|
||||||
|
public CachedPregenMethod(PregeneratorMethod method, String worldName) {
|
||||||
|
this.method = method;
|
||||||
|
var cache = Iris.service(GlobalCacheSVC.class).get(worldName);
|
||||||
|
if (cache == null) {
|
||||||
|
Iris.debug("Could not find existing cache for " + worldName + " creating fallback");
|
||||||
|
cache = GlobalCacheSVC.createDefault(worldName);
|
||||||
|
}
|
||||||
|
this.cache = cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init() {
|
||||||
|
method.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
method.close();
|
||||||
|
cache.write();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void save() {
|
||||||
|
method.save();
|
||||||
|
cache.write();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supportsRegions(int x, int z, PregenListener listener) {
|
||||||
|
return cache.isRegionCached(x, z) || method.supportsRegions(x, z, listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getMethod(int x, int z) {
|
||||||
|
return method.getMethod(x, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void generateRegion(int x, int z, PregenListener listener) {
|
||||||
|
if (cache.isRegionCached(x, z)) {
|
||||||
|
listener.onRegionGenerated(x, z);
|
||||||
|
|
||||||
|
int rX = x << 5, rZ = z << 5;
|
||||||
|
for (int cX = 0; cX < 32; cX++) {
|
||||||
|
for (int cZ = 0; cZ < 32; cZ++) {
|
||||||
|
listener.onChunkGenerated(rX + cX, rZ + cZ, true);
|
||||||
|
listener.onChunkCleaned(rX + cX, rZ + cZ);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
method.generateRegion(x, z, listener);
|
||||||
|
cache.cacheRegion(x, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void generateChunk(int x, int z, PregenListener listener) {
|
||||||
|
if (cache.isChunkCached(x, z)) {
|
||||||
|
listener.onChunkGenerated(x, z, true);
|
||||||
|
listener.onChunkCleaned(x, z);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
method.generateChunk(x, z, listener);
|
||||||
|
cache.cacheChunk(x, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Mantle getMantle() {
|
||||||
|
return method.getMantle();
|
||||||
|
}
|
||||||
|
}
|
||||||
104
core/src/main/java/com/volmit/iris/core/project/Gradle.java
Normal file
104
core/src/main/java/com/volmit/iris/core/project/Gradle.java
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
package com.volmit.iris.core.project;
|
||||||
|
|
||||||
|
import com.volmit.iris.Iris;
|
||||||
|
import com.volmit.iris.util.io.IO;
|
||||||
|
import org.zeroturnaround.zip.ZipUtil;
|
||||||
|
|
||||||
|
import java.io.BufferedInputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Scanner;
|
||||||
|
|
||||||
|
public class Gradle {
|
||||||
|
private static final boolean WINDOWS = System.getProperty("os.name").toLowerCase().contains("win");
|
||||||
|
private static final String[] ENVIRONMENT = createEnvironment();
|
||||||
|
private static final String VERSION = "8.14.2";
|
||||||
|
private static final String DISTRIBUTION_URL = "https://services.gradle.org/distributions/gradle-" + VERSION + "-bin.zip";
|
||||||
|
private static final String HASH = IO.hash(DISTRIBUTION_URL);
|
||||||
|
|
||||||
|
public static synchronized void wrapper(File projectDir) {
|
||||||
|
try {
|
||||||
|
File settings = new File(projectDir, "settings.gradle.kts");
|
||||||
|
if (!settings.exists()) settings.createNewFile();
|
||||||
|
runGradle(projectDir, "wrapper");
|
||||||
|
} catch (Throwable e) {
|
||||||
|
Iris.error("Failed to install gradle wrapper!");
|
||||||
|
e.printStackTrace();
|
||||||
|
Iris.reportError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void runGradle(File projectDir, String... args) throws IOException, InterruptedException {
|
||||||
|
File gradle = downloadGradle(false);
|
||||||
|
String[] cmd = new String[args.length + 1];
|
||||||
|
cmd[0] = gradle.getAbsolutePath();
|
||||||
|
System.arraycopy(args, 0, cmd, 1, args.length);
|
||||||
|
var process = Runtime.getRuntime().exec(cmd, ENVIRONMENT, projectDir);
|
||||||
|
attach(process.getInputStream());
|
||||||
|
attach(process.getErrorStream());
|
||||||
|
var code = process.waitFor();
|
||||||
|
if (code == 0) return;
|
||||||
|
throw new RuntimeException("Gradle exited with code " + code);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static synchronized File downloadGradle(boolean force) {
|
||||||
|
var folder = Iris.instance.getDataFolder("cache", HASH.substring(0, 2), HASH);
|
||||||
|
if (force) {
|
||||||
|
IO.delete(folder);
|
||||||
|
folder.mkdirs();
|
||||||
|
}
|
||||||
|
|
||||||
|
var bin = new File(folder, "gradle-" + VERSION + "/bin/gradle" + (WINDOWS ? ".bat" : ""));
|
||||||
|
if (bin.exists()) {
|
||||||
|
bin.setExecutable(true);
|
||||||
|
return bin;
|
||||||
|
}
|
||||||
|
|
||||||
|
try (var input = new BufferedInputStream(URI.create(DISTRIBUTION_URL).toURL().openStream())) {
|
||||||
|
ZipUtil.unpack(input, folder);
|
||||||
|
} catch (Throwable e) {
|
||||||
|
throw new RuntimeException("Failed to download gradle", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
bin.setExecutable(true);
|
||||||
|
return bin;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String[] createEnvironment() {
|
||||||
|
var env = new HashMap<>(System.getenv());
|
||||||
|
env.put("JAVA_HOME", findJavaHome());
|
||||||
|
return env.entrySet()
|
||||||
|
.stream()
|
||||||
|
.map(e -> e.getKey() + "=" + e.getValue())
|
||||||
|
.toArray(String[]::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String findJavaHome() {
|
||||||
|
String javaHome = System.getProperty("java.home");
|
||||||
|
if (javaHome != null && new File(javaHome + "/bin/java" + (WINDOWS ? ".exe" : "")).exists()) {
|
||||||
|
return javaHome;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ProcessHandle.current()
|
||||||
|
.info()
|
||||||
|
.command()
|
||||||
|
.map(s -> new File(s).getAbsoluteFile().getParentFile().getParentFile())
|
||||||
|
.flatMap(f -> f.exists() ? Optional.of(f.getAbsolutePath()) : Optional.empty())
|
||||||
|
.orElseThrow(() -> new RuntimeException("Failed to find java home, please set java.home system property"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void attach(InputStream stream) {
|
||||||
|
Thread.ofVirtual().start(() -> {
|
||||||
|
try (var in = new Scanner(stream)) {
|
||||||
|
while (in.hasNextLine()) {
|
||||||
|
String line = in.nextLine();
|
||||||
|
Iris.debug("[GRADLE] " + line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -24,6 +24,7 @@ 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.loader.IrisRegistrant;
|
import com.volmit.iris.core.loader.IrisRegistrant;
|
||||||
import com.volmit.iris.core.loader.ResourceLoader;
|
import com.volmit.iris.core.loader.ResourceLoader;
|
||||||
|
import com.volmit.iris.core.scripting.environment.SimpleEnvironment;
|
||||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||||
import com.volmit.iris.engine.object.*;
|
import com.volmit.iris.engine.object.*;
|
||||||
import com.volmit.iris.engine.object.annotations.Snippet;
|
import com.volmit.iris.engine.object.annotations.Snippet;
|
||||||
@@ -49,6 +50,8 @@ import lombok.Data;
|
|||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.GameMode;
|
import org.bukkit.GameMode;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
|
import org.dom4j.Document;
|
||||||
|
import org.dom4j.Element;
|
||||||
import org.zeroturnaround.zip.ZipUtil;
|
import org.zeroturnaround.zip.ZipUtil;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
@@ -217,24 +220,15 @@ public class IrisProject {
|
|||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean hasError = false;
|
|
||||||
|
|
||||||
if (hasError) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
IrisDimension d = IrisData.loadAnyDimension(getName());
|
|
||||||
if (d == null) {
|
|
||||||
sender.sendMessage("Can't find dimension: " + getName());
|
|
||||||
return;
|
|
||||||
} else if (sender.isPlayer()) {
|
|
||||||
sender.player().setGameMode(GameMode.SPECTATOR);
|
|
||||||
}
|
|
||||||
|
|
||||||
openVSCode(sender);
|
|
||||||
|
|
||||||
|
|
||||||
J.a(() -> {
|
J.a(() -> {
|
||||||
|
IrisDimension d = IrisData.loadAnyDimension(getName());
|
||||||
|
if (d == null) {
|
||||||
|
sender.sendMessage("Can't find dimension: " + getName());
|
||||||
|
return;
|
||||||
|
} else if (sender.isPlayer()) {
|
||||||
|
sender.player().setGameMode(GameMode.SPECTATOR);
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
activeProvider = (PlatformChunkGenerator) IrisToolbelt.createWorld()
|
activeProvider = (PlatformChunkGenerator) IrisToolbelt.createWorld()
|
||||||
.seed(seed)
|
.seed(seed)
|
||||||
@@ -247,6 +241,8 @@ public class IrisProject {
|
|||||||
} catch (IrisException e) {
|
} catch (IrisException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
openVSCode(sender);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -359,6 +355,74 @@ public class IrisProject {
|
|||||||
settings.put("json.schemas", schemas);
|
settings.put("json.schemas", schemas);
|
||||||
ws.put("settings", settings);
|
ws.put("settings", settings);
|
||||||
|
|
||||||
|
dm.getEnvironment().configureProject();
|
||||||
|
File schemasFile = new File(path, ".idea" + File.separator + "jsonSchemas.xml");
|
||||||
|
Document doc = IO.read(schemasFile);
|
||||||
|
Element mappings = (Element) doc.selectSingleNode("//component[@name='JsonSchemaMappingsProjectConfiguration']");
|
||||||
|
if (mappings == null) {
|
||||||
|
mappings = doc.getRootElement()
|
||||||
|
.addElement("component")
|
||||||
|
.addAttribute("name", "JsonSchemaMappingsProjectConfiguration");
|
||||||
|
}
|
||||||
|
|
||||||
|
Element state = (Element) mappings.selectSingleNode("state");
|
||||||
|
if (state == null) state = mappings.addElement("state");
|
||||||
|
|
||||||
|
Element map = (Element) state.selectSingleNode("map");
|
||||||
|
if (map == null) map = state.addElement("map");
|
||||||
|
var schemaMap = new KMap<String, String>();
|
||||||
|
schemas.forEach(element -> {
|
||||||
|
if (!(element instanceof JSONObject obj))
|
||||||
|
return;
|
||||||
|
|
||||||
|
String url = obj.getString("url");
|
||||||
|
String dir = obj.getJSONArray("fileMatch").getString(0);
|
||||||
|
schemaMap.put(url, dir.substring(1, dir.indexOf("/*")));
|
||||||
|
});
|
||||||
|
|
||||||
|
map.selectNodes("entry/value/SchemaInfo/option[@name='relativePathToSchema']")
|
||||||
|
.stream()
|
||||||
|
.map(node -> node.valueOf("@value"))
|
||||||
|
.forEach(schemaMap::remove);
|
||||||
|
|
||||||
|
var ideaSchemas = map;
|
||||||
|
schemaMap.forEach((url, dir) -> {
|
||||||
|
var genName = UUID.randomUUID().toString();
|
||||||
|
|
||||||
|
var info = ideaSchemas.addElement("entry")
|
||||||
|
.addAttribute("key", genName)
|
||||||
|
.addElement("value")
|
||||||
|
.addElement("SchemaInfo");
|
||||||
|
info.addElement("option")
|
||||||
|
.addAttribute("name", "generatedName")
|
||||||
|
.addAttribute("value", genName);
|
||||||
|
info.addElement("option")
|
||||||
|
.addAttribute("name", "name")
|
||||||
|
.addAttribute("value", dir);
|
||||||
|
info.addElement("option")
|
||||||
|
.addAttribute("name", "relativePathToSchema")
|
||||||
|
.addAttribute("value", url);
|
||||||
|
|
||||||
|
|
||||||
|
var item = info.addElement("option")
|
||||||
|
.addAttribute("name", "patterns")
|
||||||
|
.addElement("list")
|
||||||
|
.addElement("Item");
|
||||||
|
item.addElement("option")
|
||||||
|
.addAttribute("name", "directory")
|
||||||
|
.addAttribute("value", "true");
|
||||||
|
item.addElement("option")
|
||||||
|
.addAttribute("name", "path")
|
||||||
|
.addAttribute("value", dir);
|
||||||
|
item.addElement("option")
|
||||||
|
.addAttribute("name", "mappingKind")
|
||||||
|
.addAttribute("value", "Directory");
|
||||||
|
});
|
||||||
|
if (!schemaMap.isEmpty()) {
|
||||||
|
IO.write(schemasFile, doc);
|
||||||
|
}
|
||||||
|
Gradle.wrapper(path);
|
||||||
|
|
||||||
return ws;
|
return ws;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -377,17 +441,17 @@ public class IrisProject {
|
|||||||
KSet<IrisLootTable> loot = new KSet<>();
|
KSet<IrisLootTable> loot = new KSet<>();
|
||||||
KSet<IrisBlockData> blocks = new KSet<>();
|
KSet<IrisBlockData> blocks = new KSet<>();
|
||||||
|
|
||||||
for (String i : dm.getDimensionLoader().getPossibleKeys()) {
|
for (String i : dm.getBlockLoader().getPossibleKeys()) {
|
||||||
blocks.add(dm.getBlockLoader().load(i));
|
blocks.add(dm.getBlockLoader().load(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
dimension.getRegions().forEach((i) -> regions.add(dm.getRegionLoader().load(i)));
|
dimension.getRegions().forEach((i) -> regions.add(dm.getRegionLoader().load(i)));
|
||||||
dimension.getLoot().getTables().forEach((i) -> loot.add(dm.getLootLoader().load(i)));
|
dimension.getLoot().getTables().forEach((i) -> loot.add(dm.getLootLoader().load(i)));
|
||||||
regions.forEach((i) -> biomes.addAll(i.getAllBiomes(null)));
|
regions.forEach((i) -> biomes.addAll(i.getAllBiomes(() -> dm)));
|
||||||
regions.forEach((r) -> r.getLoot().getTables().forEach((i) -> loot.add(dm.getLootLoader().load(i))));
|
regions.forEach((r) -> r.getLoot().getTables().forEach((i) -> loot.add(dm.getLootLoader().load(i))));
|
||||||
regions.forEach((r) -> r.getEntitySpawners().forEach((sp) -> spawners.add(dm.getSpawnerLoader().load(sp))));
|
regions.forEach((r) -> r.getEntitySpawners().forEach((sp) -> spawners.add(dm.getSpawnerLoader().load(sp))));
|
||||||
dimension.getEntitySpawners().forEach((sp) -> spawners.add(dm.getSpawnerLoader().load(sp)));
|
dimension.getEntitySpawners().forEach((sp) -> spawners.add(dm.getSpawnerLoader().load(sp)));
|
||||||
biomes.forEach((i) -> i.getGenerators().forEach((j) -> generators.add(j.getCachedGenerator(null))));
|
biomes.forEach((i) -> i.getGenerators().forEach((j) -> generators.add(j.getCachedGenerator(() -> dm))));
|
||||||
biomes.forEach((r) -> r.getLoot().getTables().forEach((i) -> loot.add(dm.getLootLoader().load(i))));
|
biomes.forEach((r) -> r.getLoot().getTables().forEach((i) -> loot.add(dm.getLootLoader().load(i))));
|
||||||
biomes.forEach((r) -> r.getEntitySpawners().forEach((sp) -> spawners.add(dm.getSpawnerLoader().load(sp))));
|
biomes.forEach((r) -> r.getEntitySpawners().forEach((sp) -> spawners.add(dm.getSpawnerLoader().load(sp))));
|
||||||
spawners.forEach((i) -> i.getSpawns().forEach((j) -> entities.add(dm.getEntityLoader().load(j.getEntity()))));
|
spawners.forEach((i) -> i.getSpawns().forEach((j) -> entities.add(dm.getEntityLoader().load(j.getEntity()))));
|
||||||
|
|||||||
@@ -19,16 +19,19 @@
|
|||||||
package com.volmit.iris.core.project;
|
package com.volmit.iris.core.project;
|
||||||
|
|
||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.Iris;
|
||||||
|
import com.volmit.iris.core.link.Identifier;
|
||||||
|
import com.volmit.iris.core.link.data.DataType;
|
||||||
import com.volmit.iris.core.loader.IrisData;
|
import com.volmit.iris.core.loader.IrisData;
|
||||||
import com.volmit.iris.core.loader.IrisRegistrant;
|
import com.volmit.iris.core.loader.IrisRegistrant;
|
||||||
import com.volmit.iris.core.loader.ResourceLoader;
|
import com.volmit.iris.core.loader.ResourceLoader;
|
||||||
|
import com.volmit.iris.core.service.ExternalDataSVC;
|
||||||
import com.volmit.iris.engine.object.annotations.*;
|
import com.volmit.iris.engine.object.annotations.*;
|
||||||
import com.volmit.iris.util.collection.KList;
|
import com.volmit.iris.util.collection.KList;
|
||||||
import com.volmit.iris.util.collection.KMap;
|
import com.volmit.iris.util.collection.KMap;
|
||||||
import com.volmit.iris.util.data.B;
|
import com.volmit.iris.util.data.B;
|
||||||
import com.volmit.iris.util.json.JSONArray;
|
import com.volmit.iris.util.json.JSONArray;
|
||||||
import com.volmit.iris.util.json.JSONObject;
|
import com.volmit.iris.util.json.JSONObject;
|
||||||
import com.volmit.iris.util.reflect.OldEnum;
|
import com.volmit.iris.util.reflect.KeyedType;
|
||||||
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 org.jetbrains.annotations.NotNull;
|
||||||
@@ -39,7 +42,6 @@ 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.function.Function;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public class SchemaBuilder {
|
public class SchemaBuilder {
|
||||||
private static final String SYMBOL_LIMIT__N = "*";
|
private static final String SYMBOL_LIMIT__N = "*";
|
||||||
@@ -108,9 +110,12 @@ public class SchemaBuilder {
|
|||||||
private JSONObject buildProperties(Class<?> c) {
|
private JSONObject buildProperties(Class<?> c) {
|
||||||
JSONObject o = new JSONObject();
|
JSONObject o = new JSONObject();
|
||||||
JSONObject properties = new JSONObject();
|
JSONObject properties = new JSONObject();
|
||||||
o.put("description", getDescription(c));
|
String desc = getDescription(c);
|
||||||
|
o.put("description", desc);
|
||||||
|
o.put("x-intellij-html-description", desc.replace("\n", "<br>"));
|
||||||
o.put("type", getType(c));
|
o.put("type", getType(c));
|
||||||
JSONArray required = new JSONArray();
|
JSONArray required = new JSONArray();
|
||||||
|
JSONArray extended = new JSONArray();
|
||||||
|
|
||||||
if (c.isAssignableFrom(IrisRegistrant.class) || IrisRegistrant.class.isAssignableFrom(c)) {
|
if (c.isAssignableFrom(IrisRegistrant.class) || IrisRegistrant.class.isAssignableFrom(c)) {
|
||||||
for (Field k : IrisRegistrant.class.getDeclaredFields()) {
|
for (Field k : IrisRegistrant.class.getDeclaredFields()) {
|
||||||
@@ -122,11 +127,15 @@ public class SchemaBuilder {
|
|||||||
|
|
||||||
JSONObject property = buildProperty(k, c);
|
JSONObject property = buildProperty(k, c);
|
||||||
|
|
||||||
if (property.getBoolean("!required")) {
|
if (Boolean.TRUE == property.remove("!required")) {
|
||||||
required.put(k.getName());
|
required.put(k.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
property.remove("!required");
|
if (Boolean.TRUE == property.remove("!top")) {
|
||||||
|
extended.put(property);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
properties.put(k.getName(), property);
|
properties.put(k.getName(), property);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -140,30 +149,29 @@ public class SchemaBuilder {
|
|||||||
|
|
||||||
JSONObject property = buildProperty(k, c);
|
JSONObject property = buildProperty(k, c);
|
||||||
|
|
||||||
property.remove("!required");
|
if (Boolean.TRUE == property.remove("!required")) {
|
||||||
|
required.put(k.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Boolean.TRUE == property.remove("!top")) {
|
||||||
|
extended.put(property);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
properties.put(k.getName(), property);
|
properties.put(k.getName(), property);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (required.length() > 0) {
|
if (required.length() > 0) {
|
||||||
o.put("required", required);
|
o.put("required", required);
|
||||||
}
|
}
|
||||||
|
if (extended.length() > 0) {
|
||||||
|
o.put("allOf", extended);
|
||||||
|
}
|
||||||
|
|
||||||
o.put("properties", properties);
|
o.put("properties", properties);
|
||||||
|
|
||||||
|
|
||||||
if (c.isAnnotationPresent(Snippet.class)) {
|
return buildSnippet(o, c);
|
||||||
JSONObject anyOf = new JSONObject();
|
|
||||||
JSONArray arr = new JSONArray();
|
|
||||||
JSONObject str = new JSONObject();
|
|
||||||
str.put("type", "string");
|
|
||||||
arr.put(o);
|
|
||||||
arr.put(str);
|
|
||||||
anyOf.put("anyOf", arr);
|
|
||||||
|
|
||||||
return anyOf;
|
|
||||||
}
|
|
||||||
|
|
||||||
return o;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private JSONObject buildProperty(Field k, Class<?> cl) {
|
private JSONObject buildProperty(Field k, Class<?> cl) {
|
||||||
@@ -276,16 +284,18 @@ public class SchemaBuilder {
|
|||||||
|
|
||||||
if (!definitions.containsKey(key)) {
|
if (!definitions.containsKey(key)) {
|
||||||
JSONObject j = new JSONObject();
|
JSONObject j = new JSONObject();
|
||||||
KList<String> list = new KList<>();
|
KList<String> list = Iris.service(ExternalDataSVC.class)
|
||||||
list.addAll(Iris.linkMythicMobs.getMythicMobTypes().stream().map(s -> "MythicMobs:" + s).collect(Collectors.toList()));
|
.getAllIdentifiers(DataType.ENTITY)
|
||||||
//TODO add Citizens stuff here too
|
.stream()
|
||||||
|
.map(Identifier::toString)
|
||||||
|
.collect(KList.collector());
|
||||||
j.put("enum", list.toJSONStringArray());
|
j.put("enum", list.toJSONStringArray());
|
||||||
definitions.put(key, j);
|
definitions.put(key, j);
|
||||||
}
|
}
|
||||||
|
|
||||||
fancyType = "Mythic Mob Type";
|
fancyType = "Custom Mob Type";
|
||||||
prop.put("$ref", "#/definitions/" + key);
|
prop.put("$ref", "#/definitions/" + key);
|
||||||
description.add(SYMBOL_TYPE__N + " Must be a valid Mythic Mob Type (use ctrl+space for auto complete!) Define mythic mobs with the mythic mobs plugin configuration files.");
|
description.add(SYMBOL_TYPE__N + " Must be a valid Custom Mob Type (use ctrl+space for auto complete!)");
|
||||||
} else if (k.isAnnotationPresent(RegistryListFont.class)) {
|
} else if (k.isAnnotationPresent(RegistryListFont.class)) {
|
||||||
String key = "enum-font";
|
String key = "enum-font";
|
||||||
|
|
||||||
@@ -342,20 +352,70 @@ public class SchemaBuilder {
|
|||||||
prop.put("$ref", "#/definitions/" + key);
|
prop.put("$ref", "#/definitions/" + key);
|
||||||
description.add(SYMBOL_TYPE__N + " Must be a valid Potion Effect Type (use ctrl+space for auto complete!)");
|
description.add(SYMBOL_TYPE__N + " Must be a valid Potion Effect Type (use ctrl+space for auto complete!)");
|
||||||
|
|
||||||
|
} else if (KeyedType.isKeyed(k.getType())) {
|
||||||
|
fancyType = addEnum(k.getType(), prop, description, KeyedType.values(k.getType()), Function.identity());
|
||||||
} else if (k.getType().isEnum()) {
|
} else if (k.getType().isEnum()) {
|
||||||
fancyType = addEnum(k.getType(), prop, description, k.getType().getEnumConstants(), o -> ((Enum<?>) o).name());
|
fancyType = addEnum(k.getType(), prop, description, k.getType().getEnumConstants(), o -> ((Enum<?>) o).name());
|
||||||
} else if (OldEnum.isOldEnum(k.getType())) {
|
|
||||||
fancyType = addEnum(k.getType(), prop, description, OldEnum.values(k.getType()), OldEnum::name);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case "object" -> {
|
case "object" -> {
|
||||||
fancyType = k.getType().getSimpleName().replaceAll("\\QIris\\E", "") + " (Object)";
|
//TODO add back descriptions
|
||||||
String key = "obj-" + k.getType().getCanonicalName().replaceAll("\\Q.\\E", "-").toLowerCase();
|
if (k.isAnnotationPresent(RegistryMapBlockState.class)) {
|
||||||
if (!definitions.containsKey(key)) {
|
String blockType = k.getDeclaredAnnotation(RegistryMapBlockState.class).value();
|
||||||
definitions.put(key, new JSONObject());
|
fancyType = "Block State";
|
||||||
definitions.put(key, buildProperties(k.getType()));
|
prop.put("!top", true);
|
||||||
|
JSONArray any = new JSONArray();
|
||||||
|
prop.put("anyOf", any);
|
||||||
|
|
||||||
|
B.getBlockStates().forEach((blocks, properties) -> {
|
||||||
|
if (blocks.isEmpty()) return;
|
||||||
|
|
||||||
|
String raw = blocks.getFirst().replace(':', '_');
|
||||||
|
String enumKey = "enum-block-state-" + raw;
|
||||||
|
String propertiesKey = "obj-block-state-" + raw;
|
||||||
|
|
||||||
|
any.put(new JSONObject()
|
||||||
|
.put("if", new JSONObject()
|
||||||
|
.put("properties", new JSONObject()
|
||||||
|
.put(blockType, new JSONObject()
|
||||||
|
.put("type", "string")
|
||||||
|
.put("$ref", "#/definitions/" + enumKey))))
|
||||||
|
.put("then", new JSONObject()
|
||||||
|
.put("properties", new JSONObject()
|
||||||
|
.put(k.getName(), new JSONObject()
|
||||||
|
.put("type", "object")
|
||||||
|
.put("$ref", "#/definitions/" + propertiesKey))))
|
||||||
|
.put("else", false));
|
||||||
|
|
||||||
|
if (!definitions.containsKey(enumKey)) {
|
||||||
|
JSONArray filters = new JSONArray();
|
||||||
|
blocks.forEach(filters::put);
|
||||||
|
|
||||||
|
definitions.put(enumKey, new JSONObject()
|
||||||
|
.put("type", "string")
|
||||||
|
.put("enum", filters));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!definitions.containsKey(propertiesKey)) {
|
||||||
|
JSONObject props = new JSONObject();
|
||||||
|
properties.forEach(property -> {
|
||||||
|
props.put(property.name(), property.buildJson());
|
||||||
|
});
|
||||||
|
|
||||||
|
definitions.put(propertiesKey, new JSONObject()
|
||||||
|
.put("type", "object")
|
||||||
|
.put("properties", props));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
fancyType = k.getType().getSimpleName().replaceAll("\\QIris\\E", "") + " (Object)";
|
||||||
|
String key = "obj-" + k.getType().getCanonicalName().replaceAll("\\Q.\\E", "-").toLowerCase();
|
||||||
|
if (!definitions.containsKey(key)) {
|
||||||
|
definitions.put(key, new JSONObject());
|
||||||
|
definitions.put(key, buildProperties(k.getType()));
|
||||||
|
}
|
||||||
|
prop.put("$ref", "#/definitions/" + key);
|
||||||
}
|
}
|
||||||
prop.put("$ref", "#/definitions/" + key);
|
|
||||||
}
|
}
|
||||||
case "array" -> {
|
case "array" -> {
|
||||||
fancyType = "List of Something...?";
|
fancyType = "List of Something...?";
|
||||||
@@ -476,6 +536,26 @@ public class SchemaBuilder {
|
|||||||
items.put("$ref", "#/definitions/" + key);
|
items.put("$ref", "#/definitions/" + key);
|
||||||
prop.put("items", items);
|
prop.put("items", items);
|
||||||
description.add(SYMBOL_TYPE__N + " Must be a valid Enchantment Type (use ctrl+space for auto complete!)");
|
description.add(SYMBOL_TYPE__N + " Must be a valid Enchantment Type (use ctrl+space for auto complete!)");
|
||||||
|
} else if (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);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSONObject items = new JSONObject();
|
||||||
|
items.put("$ref", "#/definitions/" + key);
|
||||||
|
prop.put("items", items);
|
||||||
|
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 (t.type().equals(PotionEffectType.class)) {
|
} else if (t.type().equals(PotionEffectType.class)) {
|
||||||
fancyType = "List of Potion Effect Types";
|
fancyType = "List of Potion Effect Types";
|
||||||
String key = "enum-potion-effect-type";
|
String key = "enum-potion-effect-type";
|
||||||
@@ -490,10 +570,10 @@ public class SchemaBuilder {
|
|||||||
items.put("$ref", "#/definitions/" + key);
|
items.put("$ref", "#/definitions/" + key);
|
||||||
prop.put("items", items);
|
prop.put("items", items);
|
||||||
description.add(SYMBOL_TYPE__N + " Must be a valid Potion Effect Type (use ctrl+space for auto complete!)");
|
description.add(SYMBOL_TYPE__N + " Must be a valid Potion Effect Type (use ctrl+space for auto complete!)");
|
||||||
|
} else if (KeyedType.isKeyed(t.type())) {
|
||||||
|
fancyType = addEnumList(prop, description, t, KeyedType.values(t.type()), Function.identity());
|
||||||
} else if (t.type().isEnum()) {
|
} else if (t.type().isEnum()) {
|
||||||
fancyType = addEnumList(prop, description, t, t.type().getEnumConstants(), o -> ((Enum<?>) o).name());
|
fancyType = addEnumList(prop, description, t, t.type().getEnumConstants(), o -> ((Enum<?>) o).name());
|
||||||
} else if (OldEnum.isOldEnum(t.type())) {
|
|
||||||
fancyType = addEnumList(prop, description, t, OldEnum.values(t.type()), OldEnum::name);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -506,16 +586,26 @@ public class SchemaBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
KList<String> d = new KList<>();
|
KList<String> d = new KList<>();
|
||||||
d.add(k.getName());
|
d.add("<h>" + k.getName() + "</h>");
|
||||||
d.add(getFieldDescription(k));
|
d.add(getFieldDescription(k) + "<hr></hr>");
|
||||||
d.add(" ");
|
d.add("<h>" + fancyType + "</h>");
|
||||||
d.add(fancyType);
|
String typeDesc = getDescription(k.getType());
|
||||||
d.add(getDescription(k.getType()));
|
boolean present = !typeDesc.isBlank();
|
||||||
|
if (present) d.add(typeDesc);
|
||||||
|
|
||||||
if (k.getType().isAnnotationPresent(Snippet.class)) {
|
Snippet snippet = k.getType().getDeclaredAnnotation(Snippet.class);
|
||||||
String sm = k.getType().getDeclaredAnnotation(Snippet.class).value();
|
if (snippet == null) {
|
||||||
d.add(" ");
|
ArrayType array = k.getType().getDeclaredAnnotation(ArrayType.class);
|
||||||
|
if (array != null) {
|
||||||
|
snippet = array.type().getDeclaredAnnotation(Snippet.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (snippet != null) {
|
||||||
|
String sm = snippet.value();
|
||||||
|
if (present) d.add(" ");
|
||||||
d.add("You can instead specify \"snippet/" + sm + "/some-name.json\" to use a snippet file instead of specifying it here.");
|
d.add("You can instead specify \"snippet/" + sm + "/some-name.json\" to use a snippet file instead of specifying it here.");
|
||||||
|
present = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -523,15 +613,13 @@ public class SchemaBuilder {
|
|||||||
Object value = k.get(cl.newInstance());
|
Object value = k.get(cl.newInstance());
|
||||||
|
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
|
if (present) d.add(" ");
|
||||||
if (value instanceof List) {
|
if (value instanceof List) {
|
||||||
d.add(" ");
|
d.add(SYMBOL_LIMIT__N + " 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()) && !KeyedType.isKeyed(cl)) {
|
||||||
} else if (!cl.isPrimitive() && !(value instanceof Number) && !(value instanceof String) && !(cl.isEnum()) && !OldEnum.isOldEnum(cl)) {
|
d.add(SYMBOL_LIMIT__N + " Default Value is a default object (create this object to see default properties)");
|
||||||
d.add(" ");
|
|
||||||
d.add("* Default Value is a default object (create this object to see default properties)");
|
|
||||||
} else {
|
} else {
|
||||||
d.add(" ");
|
d.add(SYMBOL_LIMIT__N + " Default Value is " + value);
|
||||||
d.add("* Default Value is " + value);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Throwable ignored) {
|
} catch (Throwable ignored) {
|
||||||
@@ -539,41 +627,50 @@ public class SchemaBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
description.forEach((g) -> d.add(g.trim()));
|
description.forEach((g) -> d.add(g.trim()));
|
||||||
|
String desc = d.toString("\n")
|
||||||
|
.replace("<hr></hr>", "\n")
|
||||||
|
.replace("<h>", "")
|
||||||
|
.replace("</h>", "");
|
||||||
|
String hDesc = d.toString("<br>");
|
||||||
prop.put("type", type);
|
prop.put("type", type);
|
||||||
prop.put("description", d.toString("\n"));
|
prop.put("description", desc);
|
||||||
|
prop.put("x-intellij-html-description", hDesc);
|
||||||
|
return buildSnippet(prop, k.getType());
|
||||||
|
}
|
||||||
|
|
||||||
if (k.getType().isAnnotationPresent(Snippet.class)) {
|
private JSONObject buildSnippet(JSONObject prop, Class<?> type) {
|
||||||
JSONObject anyOf = new JSONObject();
|
Snippet snippet = type.getDeclaredAnnotation(Snippet.class);
|
||||||
JSONArray arr = new JSONArray();
|
if (snippet == null) return prop;
|
||||||
JSONObject str = new JSONObject();
|
|
||||||
str.put("type", "string");
|
|
||||||
String key = "enum-snippet-" + k.getType().getDeclaredAnnotation(Snippet.class).value();
|
|
||||||
str.put("$ref", "#/definitions/" + key);
|
|
||||||
|
|
||||||
if (!definitions.containsKey(key)) {
|
JSONObject anyOf = new JSONObject();
|
||||||
JSONObject j = new JSONObject();
|
JSONArray arr = new JSONArray();
|
||||||
JSONArray snl = new JSONArray();
|
JSONObject str = new JSONObject();
|
||||||
data.getPossibleSnippets(k.getType().getDeclaredAnnotation(Snippet.class).value()).forEach(snl::put);
|
str.put("type", "string");
|
||||||
j.put("enum", snl);
|
String key = "enum-snippet-" + snippet.value();
|
||||||
definitions.put(key, j);
|
str.put("$ref", "#/definitions/" + key);
|
||||||
}
|
|
||||||
|
|
||||||
arr.put(prop);
|
if (!definitions.containsKey(key)) {
|
||||||
arr.put(str);
|
JSONObject j = new JSONObject();
|
||||||
prop.put("description", d.toString("\n"));
|
JSONArray snl = new JSONArray();
|
||||||
str.put("description", d.toString("\n"));
|
data.getPossibleSnippets(snippet.value()).forEach(snl::put);
|
||||||
anyOf.put("anyOf", arr);
|
j.put("enum", snl);
|
||||||
anyOf.put("description", d.toString("\n"));
|
definitions.put(key, j);
|
||||||
anyOf.put("!required", k.isAnnotationPresent(Required.class));
|
|
||||||
|
|
||||||
return anyOf;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return prop;
|
arr.put(prop);
|
||||||
|
arr.put(str);
|
||||||
|
str.put("description", prop.getString("description"));
|
||||||
|
str.put("x-intellij-html-description", prop.getString("x-intellij-html-description"));
|
||||||
|
anyOf.put("anyOf", arr);
|
||||||
|
anyOf.put("description", prop.getString("description"));
|
||||||
|
anyOf.put("x-intellij-html-description", prop.getString("x-intellij-html-description"));
|
||||||
|
anyOf.put("!required", type.isAnnotationPresent(Required.class));
|
||||||
|
|
||||||
|
return anyOf;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private String addEnumList(JSONObject prop, KList<String> description, ArrayType t, Object[] values, Function<Object, String> function) {
|
private <T> String addEnumList(JSONObject prop, KList<String> description, ArrayType t, T[] values, Function<T, String> function) {
|
||||||
JSONObject items = new JSONObject();
|
JSONObject items = new JSONObject();
|
||||||
var s = addEnum(t.type(), items, description, values, function);
|
var s = addEnum(t.type(), items, description, values, function);
|
||||||
prop.put("items", items);
|
prop.put("items", items);
|
||||||
@@ -582,17 +679,19 @@ public class SchemaBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private String addEnum(Class<?> type, JSONObject prop, KList<String> description, Object[] values, Function<Object, String> function) {
|
private <T> String addEnum(Class<?> type, JSONObject prop, KList<String> description, T[] values, Function<T, String> function) {
|
||||||
JSONArray a = new JSONArray();
|
JSONArray a = new JSONArray();
|
||||||
boolean advanced = type.isAnnotationPresent(Desc.class);
|
boolean advanced = type.isAnnotationPresent(Desc.class);
|
||||||
for (Object gg : values) {
|
for (T gg : values) {
|
||||||
if (advanced) {
|
if (advanced) {
|
||||||
try {
|
try {
|
||||||
JSONObject j = new JSONObject();
|
JSONObject j = new JSONObject();
|
||||||
String name = function.apply(gg);
|
String name = function.apply(gg);
|
||||||
j.put("const", name);
|
j.put("const", name);
|
||||||
Desc dd = type.getField(name).getAnnotation(Desc.class);
|
Desc dd = type.getField(name).getAnnotation(Desc.class);
|
||||||
j.put("description", dd == null ? ("No Description for " + name) : dd.value());
|
String desc = dd == null ? ("No Description for " + name) : dd.value();
|
||||||
|
j.put("description", desc);
|
||||||
|
j.put("x-intellij-html-description", desc.replace("\n", "<br>"));
|
||||||
a.put(j);
|
a.put(j);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
@@ -629,7 +728,7 @@ public class SchemaBuilder {
|
|||||||
return "boolean";
|
return "boolean";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c.equals(String.class) || c.isEnum() || OldEnum.isOldEnum(c) || c.equals(Enchantment.class) || c.equals(PotionEffectType.class)) {
|
if (c.equals(String.class) || c.isEnum() || KeyedType.isKeyed(c)) {
|
||||||
return "string";
|
return "string";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,14 @@ package com.volmit.iris.core.safeguard;
|
|||||||
|
|
||||||
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.util.collection.KList;
|
||||||
|
import com.volmit.iris.util.collection.KMap;
|
||||||
|
import io.papermc.lib.PaperLib;
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
public class IrisSafeguard {
|
public class IrisSafeguard {
|
||||||
|
private static final AtomicBoolean sfg = new AtomicBoolean(false);
|
||||||
public static boolean unstablemode = false;
|
public static boolean unstablemode = false;
|
||||||
public static boolean warningmode = false;
|
public static boolean warningmode = false;
|
||||||
public static boolean stablemode = false;
|
public static boolean stablemode = false;
|
||||||
@@ -13,12 +19,46 @@ public class IrisSafeguard {
|
|||||||
ServerBootSFG.BootCheck();
|
ServerBootSFG.BootCheck();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void earlySplash() {
|
public static void splash(boolean early) {
|
||||||
if (ServerBootSFG.safeguardPassed || IrisSettings.get().getGeneral().DoomsdayAnnihilationSelfDestructMode)
|
if (early && (ServerBootSFG.safeguardPassed || IrisSettings.get().getGeneral().DoomsdayAnnihilationSelfDestructMode))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Iris.instance.splash();
|
if (!sfg.getAndSet(true)) {
|
||||||
UtilsSFG.splash();
|
Iris.instance.splash();
|
||||||
|
UtilsSFG.splash();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String mode() {
|
||||||
|
if (unstablemode) {
|
||||||
|
return "unstable";
|
||||||
|
} else if (warningmode) {
|
||||||
|
return "warning";
|
||||||
|
} else {
|
||||||
|
return "stable";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void suggestPaper() {
|
||||||
|
PaperLib.suggestPaper(Iris.instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static KMap<String, Object> asContext() {
|
||||||
|
KMap<String, Object> m = new KMap<>();
|
||||||
|
m.put("diskSpace", !ServerBootSFG.hasEnoughDiskSpace);
|
||||||
|
m.put("javaVersion", !ServerBootSFG.isCorrectJDK);
|
||||||
|
m.put("jre", ServerBootSFG.isJRE);
|
||||||
|
m.put("missingAgent", ServerBootSFG.missingAgent);
|
||||||
|
m.put("missingDimensionTypes", ServerBootSFG.missingDimensionTypes);
|
||||||
|
m.put("failedInjection", ServerBootSFG.failedInjection);
|
||||||
|
m.put("unsupportedVersion", ServerBootSFG.unsuportedversion);
|
||||||
|
m.put("serverSoftware", !ServerBootSFG.passedserversoftware);
|
||||||
|
KList<String> incompatiblePlugins = new KList<>();
|
||||||
|
ServerBootSFG.incompatibilities.forEach((plugin, present) -> {
|
||||||
|
if (present) incompatiblePlugins.add(plugin);
|
||||||
|
});
|
||||||
|
m.put("plugins", incompatiblePlugins);
|
||||||
|
return m;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
package com.volmit.iris.core.safeguard;
|
package com.volmit.iris.core.safeguard;
|
||||||
|
|
||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.Iris;
|
||||||
|
import com.volmit.iris.core.IrisWorlds;
|
||||||
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.engine.object.IrisContextInjector;
|
import com.volmit.iris.engine.object.IrisDimension;
|
||||||
|
import com.volmit.iris.util.agent.Agent;
|
||||||
|
import com.volmit.iris.util.collection.KSet;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.plugin.Plugin;
|
import org.bukkit.plugin.Plugin;
|
||||||
import org.bukkit.plugin.PluginManager;
|
import org.bukkit.plugin.PluginManager;
|
||||||
@@ -15,10 +18,8 @@ import java.nio.file.Files;
|
|||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.nio.file.StandardOpenOption;
|
import java.nio.file.StandardOpenOption;
|
||||||
import java.util.HashMap;
|
import java.util.*;
|
||||||
import java.util.List;
|
import java.util.stream.Collectors;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.StringJoiner;
|
|
||||||
|
|
||||||
import static com.volmit.iris.Iris.getJavaVersion;
|
import static com.volmit.iris.Iris.getJavaVersion;
|
||||||
import static com.volmit.iris.core.safeguard.IrisSafeguard.*;
|
import static com.volmit.iris.core.safeguard.IrisSafeguard.*;
|
||||||
@@ -31,6 +32,8 @@ public class ServerBootSFG {
|
|||||||
public static boolean hasPrivileges = true;
|
public static boolean hasPrivileges = true;
|
||||||
public static boolean unsuportedversion = false;
|
public static boolean unsuportedversion = false;
|
||||||
public static boolean missingDimensionTypes = false;
|
public static boolean missingDimensionTypes = false;
|
||||||
|
public static boolean missingAgent = false;
|
||||||
|
public static boolean failedInjection = false;
|
||||||
protected static boolean safeguardPassed;
|
protected static boolean safeguardPassed;
|
||||||
public static boolean passedserversoftware = true;
|
public static boolean passedserversoftware = true;
|
||||||
protected static int count;
|
protected static int count;
|
||||||
@@ -45,9 +48,7 @@ public class ServerBootSFG {
|
|||||||
Plugin[] plugins = pluginManager.getPlugins();
|
Plugin[] plugins = pluginManager.getPlugins();
|
||||||
|
|
||||||
incompatibilities.clear();
|
incompatibilities.clear();
|
||||||
incompatibilities.put("Multiverse-Core", false);
|
|
||||||
incompatibilities.put("dynmap", false);
|
incompatibilities.put("dynmap", false);
|
||||||
incompatibilities.put("TerraformGenerator", false);
|
|
||||||
incompatibilities.put("Stratos", false);
|
incompatibilities.put("Stratos", false);
|
||||||
|
|
||||||
String pluginName;
|
String pluginName;
|
||||||
@@ -112,10 +113,21 @@ public class ServerBootSFG {
|
|||||||
severityMedium++;
|
severityMedium++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IrisContextInjector.isMissingDimensionTypes()) {
|
if (!Agent.install()) {
|
||||||
missingDimensionTypes = true;
|
missingAgent = true;
|
||||||
joiner.add("Missing Dimension Types");
|
joiner.add("Missing Java Agent");
|
||||||
severityHigh++;
|
severityHigh++;
|
||||||
|
} else {
|
||||||
|
if (missingDimensionTypes()) {
|
||||||
|
missingDimensionTypes = true;
|
||||||
|
joiner.add("Missing Dimension Types");
|
||||||
|
severityHigh++;
|
||||||
|
}
|
||||||
|
if (!INMS.get().injectBukkit()) {
|
||||||
|
failedInjection = true;
|
||||||
|
joiner.add("Failed Bukkit Injection");
|
||||||
|
severityHigh++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
allIncompatibilities = joiner.toString();
|
allIncompatibilities = joiner.toString();
|
||||||
@@ -160,17 +172,23 @@ public class ServerBootSFG {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static boolean enoughDiskSpace() {
|
public static boolean enoughDiskSpace() {
|
||||||
File freeSpace = new File(Bukkit.getWorldContainer() + ".");
|
File freeSpace = Bukkit.getWorldContainer();
|
||||||
double gigabytes = freeSpace.getFreeSpace() / (1024.0 * 1024.0 * 1024.0);
|
double gigabytes = freeSpace.getFreeSpace() / (1024.0 * 1024.0 * 1024.0);
|
||||||
if (gigabytes > 3){
|
return gigabytes > 3;
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean checkJavac(String path) {
|
private static boolean checkJavac(String path) {
|
||||||
return !path.isEmpty() && (new File(path, "javac").exists() || new File(path, "javac.exe").exists());
|
return !path.isEmpty() && (new File(path, "javac").exists() || new File(path, "javac.exe").exists());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean missingDimensionTypes() {
|
||||||
|
return INMS.get().missingDimensionTypes(getDimensionTypes().toArray(String[]::new));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static KSet<String> getDimensionTypes() {
|
||||||
|
return IrisWorlds.get()
|
||||||
|
.getDimensions()
|
||||||
|
.map(IrisDimension::getDimensionTypeKey)
|
||||||
|
.collect(Collectors.toCollection(KSet::new));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.volmit.iris.core.safeguard;
|
package com.volmit.iris.core.safeguard;
|
||||||
|
|
||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.Iris;
|
||||||
|
import com.volmit.iris.util.agent.Agent;
|
||||||
import com.volmit.iris.util.format.C;
|
import com.volmit.iris.util.format.C;
|
||||||
|
|
||||||
public class UtilsSFG {
|
public class UtilsSFG {
|
||||||
@@ -9,7 +10,9 @@ public class UtilsSFG {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void printIncompatibleWarnings() {
|
public static void printIncompatibleWarnings() {
|
||||||
// String SupportedIrisVersion = getDescription().getVersion(); //todo Automatic version
|
String[] parts = Iris.instance.getDescription().getVersion().split("-");
|
||||||
|
String minVersion = parts[1];
|
||||||
|
String maxVersion = parts[2];
|
||||||
|
|
||||||
if (ServerBootSFG.safeguardPassed) {
|
if (ServerBootSFG.safeguardPassed) {
|
||||||
Iris.safeguard(C.BLUE + "0 Conflicts found");
|
Iris.safeguard(C.BLUE + "0 Conflicts found");
|
||||||
@@ -21,29 +24,29 @@ public class UtilsSFG {
|
|||||||
Iris.safeguard(C.YELLOW + "" + ServerBootSFG.count + " Conflicts found");
|
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")) {
|
if (ServerBootSFG.incompatibilities.get("dynmap")) {
|
||||||
Iris.safeguard(C.RED + "Dynmap");
|
Iris.safeguard(C.RED + "Dynmap");
|
||||||
Iris.safeguard(C.RED + "- The plugin Dynmap is not compatible with the server.");
|
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.");
|
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")) {
|
if (ServerBootSFG.incompatibilities.get("Stratos")) {
|
||||||
Iris.safeguard(C.YELLOW + "Terraform Generator / Stratos");
|
Iris.safeguard(C.YELLOW + "Stratos");
|
||||||
Iris.safeguard(C.YELLOW + "- Iris is not compatible with other worldgen plugins.");
|
Iris.safeguard(C.YELLOW + "- Iris is not compatible with other worldgen plugins.");
|
||||||
}
|
}
|
||||||
if (ServerBootSFG.unsuportedversion) {
|
if (ServerBootSFG.unsuportedversion) {
|
||||||
Iris.safeguard(C.RED + "Server Version");
|
Iris.safeguard(C.RED + "Server Version");
|
||||||
Iris.safeguard(C.RED + "- Iris only supports 1.20.1 > 1.21.4");
|
Iris.safeguard(C.RED + "- Iris only supports " + minVersion + " > " + maxVersion);
|
||||||
}
|
}
|
||||||
if (ServerBootSFG.missingDimensionTypes) {
|
if (ServerBootSFG.missingDimensionTypes) {
|
||||||
Iris.safeguard(C.RED + "Dimension Types");
|
Iris.safeguard(C.RED + "Dimension Types");
|
||||||
Iris.safeguard(C.RED + "- Required Iris dimension types were not loaded.");
|
Iris.safeguard(C.RED + "- Required Iris dimension types were not loaded.");
|
||||||
Iris.safeguard(C.RED + "- If this still happens after a restart please contact support.");
|
Iris.safeguard(C.RED + "- If this still happens after a restart please contact support.");
|
||||||
}
|
}
|
||||||
|
if (ServerBootSFG.missingAgent) {
|
||||||
|
Iris.safeguard(C.RED + "Java Agent");
|
||||||
|
Iris.safeguard(C.RED + "- Please enable dynamic agent loading by adding -XX:+EnableDynamicAgentLoading to your jvm arguments.");
|
||||||
|
Iris.safeguard(C.RED + "- or add the jvm argument -javaagent:" + Agent.AGENT_JAR.getPath());
|
||||||
|
}
|
||||||
if (!ServerBootSFG.passedserversoftware) {
|
if (!ServerBootSFG.passedserversoftware) {
|
||||||
Iris.safeguard(C.YELLOW + "Unsupported Server Software");
|
Iris.safeguard(C.YELLOW + "Unsupported Server Software");
|
||||||
Iris.safeguard(C.YELLOW + "- Please consider using Paper or Purpur instead.");
|
Iris.safeguard(C.YELLOW + "- Please consider using Paper or Purpur instead.");
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package com.volmit.iris.core.scripting.environment;
|
||||||
|
|
||||||
|
import com.volmit.iris.core.loader.IrisRegistrant;
|
||||||
|
import com.volmit.iris.core.scripting.kotlin.environment.IrisExecutionEnvironment;
|
||||||
|
import com.volmit.iris.engine.framework.Engine;
|
||||||
|
import lombok.NonNull;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
public interface EngineEnvironment extends PackEnvironment {
|
||||||
|
static EngineEnvironment create(@NonNull Engine engine) {
|
||||||
|
return new IrisExecutionEnvironment(engine);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
Engine getEngine();
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
Object spawnMob(@NonNull String script, @NonNull Location location);
|
||||||
|
|
||||||
|
void postSpawnMob(@NonNull String script, @NonNull Location location, @NonNull Entity mob);
|
||||||
|
|
||||||
|
void preprocessObject(@NonNull String script, @NonNull IrisRegistrant object);
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package com.volmit.iris.core.scripting.environment;
|
||||||
|
|
||||||
|
import com.volmit.iris.core.loader.IrisData;
|
||||||
|
import com.volmit.iris.core.scripting.kotlin.environment.IrisPackExecutionEnvironment;
|
||||||
|
import com.volmit.iris.util.math.RNG;
|
||||||
|
import lombok.NonNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
public interface PackEnvironment extends SimpleEnvironment {
|
||||||
|
static PackEnvironment create(@NonNull IrisData data) {
|
||||||
|
return new IrisPackExecutionEnvironment(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
IrisData getData();
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
Object createNoise(@NonNull String script, @NonNull RNG rng);
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package com.volmit.iris.core.scripting.environment;
|
||||||
|
|
||||||
|
import com.volmit.iris.core.scripting.kotlin.environment.IrisSimpleExecutionEnvironment;
|
||||||
|
import lombok.NonNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public interface SimpleEnvironment {
|
||||||
|
static SimpleEnvironment create() {
|
||||||
|
return new IrisSimpleExecutionEnvironment();
|
||||||
|
}
|
||||||
|
|
||||||
|
static SimpleEnvironment create(@NonNull File projectDir) {
|
||||||
|
return new IrisSimpleExecutionEnvironment(projectDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
void configureProject();
|
||||||
|
|
||||||
|
void execute(@NonNull String script);
|
||||||
|
|
||||||
|
void execute(@NonNull String script, @NonNull Class<?> type, @Nullable Map<@NonNull String, Object> vars);
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
Object evaluate(@NonNull String script);
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
Object evaluate(@NonNull String script, @NonNull Class<?> type, @Nullable Map<@NonNull String, Object> vars);
|
||||||
|
|
||||||
|
default void close() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package com.volmit.iris.core.scripting.func;
|
||||||
|
|
||||||
|
import com.volmit.iris.engine.object.IrisBiome;
|
||||||
|
import com.volmit.iris.util.documentation.BlockCoordinates;
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface BiomeLookup {
|
||||||
|
@BlockCoordinates
|
||||||
|
IrisBiome at(int x, int z);
|
||||||
|
}
|
||||||
@@ -22,33 +22,39 @@ import com.volmit.iris.Iris;
|
|||||||
import com.volmit.iris.core.IrisSettings;
|
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.util.board.BoardManager;
|
import com.volmit.iris.util.board.BoardManager;
|
||||||
import com.volmit.iris.util.board.BoardProvider;
|
import com.volmit.iris.util.board.BoardProvider;
|
||||||
import com.volmit.iris.util.board.BoardSettings;
|
import com.volmit.iris.util.board.BoardSettings;
|
||||||
import com.volmit.iris.util.board.ScoreDirection;
|
import com.volmit.iris.util.board.ScoreDirection;
|
||||||
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.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.plugin.IrisService;
|
import com.volmit.iris.util.plugin.IrisService;
|
||||||
import com.volmit.iris.util.scheduling.J;
|
import com.volmit.iris.util.scheduling.J;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.World;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.player.PlayerChangedWorldEvent;
|
import org.bukkit.event.player.PlayerChangedWorldEvent;
|
||||||
import org.bukkit.event.player.PlayerJoinEvent;
|
import org.bukkit.event.player.PlayerJoinEvent;
|
||||||
|
import org.bukkit.event.player.PlayerQuitEvent;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
import java.util.concurrent.ScheduledFuture;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
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<>();
|
||||||
private com.volmit.iris.util.board.BoardManager manager;
|
private ScheduledExecutorService executor;
|
||||||
|
private BoardManager manager;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEnable() {
|
public void onEnable() {
|
||||||
J.ar(this::tick, 20);
|
executor = Executors.newScheduledThreadPool(0, Thread.ofVirtual().factory());
|
||||||
manager = new BoardManager(Iris.instance, BoardSettings.builder()
|
manager = new BoardManager(Iris.instance, BoardSettings.builder()
|
||||||
.boardProvider(this)
|
.boardProvider(this)
|
||||||
.scoreDirection(ScoreDirection.DOWN)
|
.scoreDirection(ScoreDirection.DOWN)
|
||||||
@@ -57,6 +63,7 @@ public class BoardSVC implements IrisService, BoardProvider {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDisable() {
|
public void onDisable() {
|
||||||
|
executor.shutdownNow();
|
||||||
manager.onDisable();
|
manager.onDisable();
|
||||||
boards.clear();
|
boards.clear();
|
||||||
}
|
}
|
||||||
@@ -71,14 +78,22 @@ public class BoardSVC implements IrisService, BoardProvider {
|
|||||||
J.s(() -> updatePlayer(e.getPlayer()));
|
J.s(() -> updatePlayer(e.getPlayer()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void on(PlayerQuitEvent e) {
|
||||||
|
remove(e.getPlayer());
|
||||||
|
}
|
||||||
|
|
||||||
public void updatePlayer(Player p) {
|
public void updatePlayer(Player p) {
|
||||||
if (IrisToolbelt.isIrisStudioWorld(p.getWorld())) {
|
if (IrisToolbelt.isIrisStudioWorld(p.getWorld())) {
|
||||||
manager.remove(p);
|
manager.remove(p);
|
||||||
manager.setup(p);
|
manager.setup(p);
|
||||||
} else {
|
} else remove(p);
|
||||||
manager.remove(p);
|
}
|
||||||
boards.remove(p);
|
|
||||||
}
|
private void remove(Player player) {
|
||||||
|
manager.remove(player);
|
||||||
|
var board = boards.remove(player);
|
||||||
|
if (board != null) board.task.cancel(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -86,73 +101,63 @@ public class BoardSVC implements IrisService, BoardProvider {
|
|||||||
return C.GREEN + "Iris";
|
return C.GREEN + "Iris";
|
||||||
}
|
}
|
||||||
|
|
||||||
public void tick() {
|
|
||||||
if (!Iris.service(StudioSVC.class).isProjectOpen()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
boards.forEach((k, v) -> v.update());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getLines(Player player) {
|
public List<String> getLines(Player player) {
|
||||||
PlayerBoard pb = boards.computeIfAbsent(player, PlayerBoard::new);
|
return boards.computeIfAbsent(player, PlayerBoard::new).lines;
|
||||||
synchronized (pb.lines) {
|
|
||||||
return pb.lines;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public static class PlayerBoard {
|
public class PlayerBoard {
|
||||||
private final Player player;
|
private final Player player;
|
||||||
private final CopyOnWriteArrayList<String> lines;
|
private final ScheduledFuture<?> task;
|
||||||
|
private volatile List<String> lines;
|
||||||
|
|
||||||
public PlayerBoard(Player player) {
|
public PlayerBoard(Player player) {
|
||||||
this.player = player;
|
this.player = player;
|
||||||
this.lines = new CopyOnWriteArrayList<>();
|
this.lines = new ArrayList<>();
|
||||||
|
this.task = executor.scheduleAtFixedRate(this::tick, 0, 1, TimeUnit.SECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void tick() {
|
||||||
|
if (!Iris.service(StudioSVC.class).isProjectOpen()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update() {
|
public void update() {
|
||||||
synchronized (lines) {
|
final World world = player.getWorld();
|
||||||
lines.clear();
|
final Location loc = player.getLocation();
|
||||||
|
|
||||||
if (!IrisToolbelt.isIrisStudioWorld(player.getWorld())) {
|
final var access = IrisToolbelt.access(world);
|
||||||
return;
|
if (access == null) return;
|
||||||
}
|
|
||||||
|
|
||||||
Engine engine = IrisToolbelt.access(player.getWorld()).getEngine();
|
final var engine = access.getEngine();
|
||||||
int x = player.getLocation().getBlockX();
|
if (engine == null) return;
|
||||||
int y = player.getLocation().getBlockY() - player.getWorld().getMinHeight();
|
|
||||||
int z = player.getLocation().getBlockZ();
|
|
||||||
|
|
||||||
if(IrisSettings.get().getGeneral().debug){
|
int x = loc.getBlockX();
|
||||||
lines.add("&7&m ");
|
int y = loc.getBlockY() - world.getMinHeight();
|
||||||
lines.add(C.GREEN + "Speed" + C.GRAY + ": " + Form.f(engine.getGeneratedPerSecond(), 0) + "/s " + Form.duration(1000D / engine.getGeneratedPerSecond(), 0));
|
int z = loc.getBlockZ();
|
||||||
lines.add(C.AQUA + "Cache" + C.GRAY + ": " + Form.f(IrisData.cacheSize()));
|
|
||||||
lines.add(C.AQUA + "Mantle" + C.GRAY + ": " + engine.getMantle().getLoadedRegionCount());
|
List<String> lines = new ArrayList<>(this.lines.size());
|
||||||
lines.add(C.LIGHT_PURPLE + "Carving" + C.GRAY + ": " + engine.getMantle().isCarved(x,y,z));
|
lines.add("&7&m ");
|
||||||
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 + "Region" + C.GRAY + ": " + engine.getRegion(x, z).getName());
|
lines.add(C.AQUA + "Cache" + C.GRAY + ": " + Form.f(IrisData.cacheSize()));
|
||||||
lines.add(C.AQUA + "Biome" + C.GRAY + ": " + engine.getBiomeOrMantle(x, y, z).getName());
|
lines.add(C.AQUA + "Mantle" + C.GRAY + ": " + engine.getMantle().getLoadedRegionCount());
|
||||||
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));
|
if (IrisSettings.get().getGeneral().debug) {
|
||||||
lines.add(C.AQUA + "BUD/s" + C.GRAY + ": " + Form.f(engine.getBlockUpdatesPerSecond()));
|
lines.add(C.LIGHT_PURPLE + "Carving" + C.GRAY + ": " + engine.getMantle().isCarved(x,y,z));
|
||||||
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 ");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 ");
|
||||||
|
this.lines = lines;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,16 +20,22 @@ 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.core.link.data.DataType;
|
||||||
|
import com.volmit.iris.core.nms.container.BlockProperty;
|
||||||
import com.volmit.iris.core.nms.container.Pair;
|
import com.volmit.iris.core.nms.container.Pair;
|
||||||
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.collection.KMap;
|
import com.volmit.iris.util.collection.KMap;
|
||||||
|
import com.volmit.iris.util.io.JarScanner;
|
||||||
import com.volmit.iris.util.plugin.IrisService;
|
import com.volmit.iris.util.plugin.IrisService;
|
||||||
|
import com.volmit.iris.util.scheduling.J;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Location;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.block.data.BlockData;
|
import org.bukkit.block.data.BlockData;
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.server.PluginEnableEvent;
|
import org.bukkit.event.server.PluginEnableEvent;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
@@ -47,39 +53,12 @@ public class ExternalDataSVC implements IrisService {
|
|||||||
Iris.info("Loading ExternalDataProvider...");
|
Iris.info("Loading ExternalDataProvider...");
|
||||||
Bukkit.getPluginManager().registerEvents(this, Iris.instance);
|
Bukkit.getPluginManager().registerEvents(this, Iris.instance);
|
||||||
|
|
||||||
providers.add(new NexoDataProvider());
|
providers.addAll(createProviders());
|
||||||
if (Bukkit.getPluginManager().getPlugin("Nexo") != null) {
|
|
||||||
Iris.info("Nexo found, loading NexoDataProvider...");
|
|
||||||
}
|
|
||||||
providers.add(new MythicCrucibleDataProvider());
|
|
||||||
if (Bukkit.getPluginManager().getPlugin("MythicCrucible") != null) {
|
|
||||||
Iris.info("MythicCrucible found, loading MythicCrucibleDataProvider...");
|
|
||||||
}
|
|
||||||
providers.add(new ItemAdderDataProvider());
|
|
||||||
if (Bukkit.getPluginManager().getPlugin("ItemAdder") != null) {
|
|
||||||
Iris.info("ItemAdder found, loading ItemAdderDataProvider...");
|
|
||||||
}
|
|
||||||
providers.add(new ExecutableItemsDataProvider());
|
|
||||||
if (Bukkit.getPluginManager().getPlugin("ExecutableItems") != null) {
|
|
||||||
Iris.info("ExecutableItems found, loading ExecutableItemsDataProvider...");
|
|
||||||
}
|
|
||||||
providers.add(new HMCLeavesDataProvider());
|
|
||||||
if (Bukkit.getPluginManager().getPlugin("HMCLeaves") != null) {
|
|
||||||
Iris.info("BlockAdder found, loading HMCLeavesDataProvider...");
|
|
||||||
}
|
|
||||||
providers.add(new MMOItemsDataProvider());
|
|
||||||
if (Bukkit.getPluginManager().getPlugin("MMOItems") != null) {
|
|
||||||
Iris.info("MMOItems found, loading MMOItemsDataProvider...");
|
|
||||||
}
|
|
||||||
providers.add(new EcoItemsDataProvider());
|
|
||||||
if (Bukkit.getPluginManager().getPlugin("EcoItems") != null) {
|
|
||||||
Iris.info("EcoItems found, loading EcoItemsDataProvider...");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (ExternalDataProvider p : providers) {
|
for (ExternalDataProvider p : providers) {
|
||||||
if (p.isReady()) {
|
if (p.isReady()) {
|
||||||
activeProviders.add(p);
|
activeProviders.add(p);
|
||||||
p.init();
|
p.init();
|
||||||
|
Iris.instance.registerListener(p);
|
||||||
Iris.info("Enabled ExternalDataProvider for %s.", p.getPluginId());
|
Iris.info("Enabled ExternalDataProvider for %s.", p.getPluginId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -91,10 +70,11 @@ public class ExternalDataSVC implements IrisService {
|
|||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onPluginEnable(PluginEnableEvent e) {
|
public void onPluginEnable(PluginEnableEvent e) {
|
||||||
if (activeProviders.stream().noneMatch(p -> p.getPlugin().equals(e.getPlugin()))) {
|
if (activeProviders.stream().noneMatch(p -> e.getPlugin().equals(p.getPlugin()))) {
|
||||||
providers.stream().filter(p -> p.isReady() && p.getPlugin().equals(e.getPlugin())).findFirst().ifPresent(edp -> {
|
providers.stream().filter(p -> p.isReady() && e.getPlugin().equals(p.getPlugin())).findFirst().ifPresent(edp -> {
|
||||||
activeProviders.add(edp);
|
activeProviders.add(edp);
|
||||||
edp.init();
|
edp.init();
|
||||||
|
Iris.instance.registerListener(edp);
|
||||||
Iris.info("Enabled ExternalDataProvider for %s.", edp.getPluginId());
|
Iris.info("Enabled ExternalDataProvider for %s.", edp.getPluginId());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -109,6 +89,7 @@ public class ExternalDataSVC implements IrisService {
|
|||||||
if (provider.isReady()) {
|
if (provider.isReady()) {
|
||||||
activeProviders.add(provider);
|
activeProviders.add(provider);
|
||||||
provider.init();
|
provider.init();
|
||||||
|
Iris.instance.registerListener(provider);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,7 +97,7 @@ public class ExternalDataSVC implements IrisService {
|
|||||||
var pair = parseState(key);
|
var pair = parseState(key);
|
||||||
Identifier mod = pair.getA();
|
Identifier mod = pair.getA();
|
||||||
|
|
||||||
Optional<ExternalDataProvider> provider = activeProviders.stream().filter(p -> p.isValidProvider(mod, false)).findFirst();
|
Optional<ExternalDataProvider> provider = activeProviders.stream().filter(p -> p.isValidProvider(mod, DataType.BLOCK)).findFirst();
|
||||||
if (provider.isEmpty())
|
if (provider.isEmpty())
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
try {
|
try {
|
||||||
@@ -127,8 +108,20 @@ public class ExternalDataSVC implements IrisService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Optional<List<BlockProperty>> getBlockProperties(final Identifier key) {
|
||||||
|
Optional<ExternalDataProvider> provider = activeProviders.stream().filter(p -> p.isValidProvider(key, DataType.BLOCK)).findFirst();
|
||||||
|
if (provider.isEmpty())
|
||||||
|
return Optional.empty();
|
||||||
|
try {
|
||||||
|
return Optional.of(provider.get().getBlockProperties(key));
|
||||||
|
} catch (MissingResourceException e) {
|
||||||
|
Iris.error(e.getMessage() + " - [" + e.getClassName() + ":" + e.getKey() + "]");
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public Optional<ItemStack> getItemStack(Identifier key, KMap<String, Object> customNbt) {
|
public Optional<ItemStack> getItemStack(Identifier key, KMap<String, Object> customNbt) {
|
||||||
Optional<ExternalDataProvider> provider = activeProviders.stream().filter(p -> p.isValidProvider(key, true)).findFirst();
|
Optional<ExternalDataProvider> provider = activeProviders.stream().filter(p -> p.isValidProvider(key, DataType.ITEM)).findFirst();
|
||||||
if (provider.isEmpty()) {
|
if (provider.isEmpty()) {
|
||||||
Iris.warn("No matching Provider found for modded material \"%s\"!", key);
|
Iris.warn("No matching Provider found for modded material \"%s\"!", key);
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
@@ -142,7 +135,7 @@ public class ExternalDataSVC implements IrisService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void processUpdate(Engine engine, Block block, Identifier blockId) {
|
public void processUpdate(Engine engine, Block block, Identifier blockId) {
|
||||||
Optional<ExternalDataProvider> provider = activeProviders.stream().filter(p -> p.isValidProvider(blockId, false)).findFirst();
|
Optional<ExternalDataProvider> provider = activeProviders.stream().filter(p -> p.isValidProvider(blockId, DataType.BLOCK)).findFirst();
|
||||||
if (provider.isEmpty()) {
|
if (provider.isEmpty()) {
|
||||||
Iris.warn("No matching Provider found for modded material \"%s\"!", blockId);
|
Iris.warn("No matching Provider found for modded material \"%s\"!", blockId);
|
||||||
return;
|
return;
|
||||||
@@ -150,16 +143,32 @@ public class ExternalDataSVC implements IrisService {
|
|||||||
provider.get().processUpdate(engine, block, blockId);
|
provider.get().processUpdate(engine, block, blockId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Identifier[] getAllBlockIdentifiers() {
|
public Entity spawnMob(Location location, Identifier mobId) {
|
||||||
KList<Identifier> names = new KList<>();
|
Optional<ExternalDataProvider> provider = activeProviders.stream().filter(p -> p.isValidProvider(mobId, DataType.ENTITY)).findFirst();
|
||||||
activeProviders.forEach(p -> names.add(p.getBlockTypes()));
|
if (provider.isEmpty()) {
|
||||||
return names.toArray(new Identifier[0]);
|
Iris.warn("No matching Provider found for modded mob \"%s\"!", mobId);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return provider.get().spawnMob(location, mobId);
|
||||||
|
} catch (MissingResourceException e) {
|
||||||
|
Iris.error(e.getMessage() + " - [" + e.getClassName() + ":" + e.getKey() + "]");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Identifier[] getAllItemIdentifiers() {
|
public Collection<Identifier> getAllIdentifiers(DataType dataType) {
|
||||||
KList<Identifier> names = new KList<>();
|
return activeProviders.stream()
|
||||||
activeProviders.forEach(p -> names.add(p.getItemTypes()));
|
.flatMap(p -> p.getTypes(dataType).stream())
|
||||||
return names.toArray(new Identifier[0]);
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<Pair<Identifier, List<BlockProperty>>> getAllBlockProperties() {
|
||||||
|
return activeProviders.stream()
|
||||||
|
.flatMap(p -> p.getTypes(DataType.BLOCK)
|
||||||
|
.stream()
|
||||||
|
.map(id -> new Pair<>(id, p.getBlockProperties(id))))
|
||||||
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Pair<Identifier, KMap<String, String>> parseState(Identifier key) {
|
public static Pair<Identifier, KMap<String, String>> parseState(Identifier key) {
|
||||||
@@ -184,4 +193,21 @@ public class ExternalDataSVC implements IrisService {
|
|||||||
.collect(Collectors.joining(",", key.key() + "[", "]"));
|
.collect(Collectors.joining(",", key.key() + "[", "]"));
|
||||||
return new Identifier(key.namespace(), path);
|
return new Identifier(key.namespace(), path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static KList<ExternalDataProvider> createProviders() {
|
||||||
|
JarScanner jar = new JarScanner(Iris.instance.getJarFile(), "com.volmit.iris.core.link.data", false);
|
||||||
|
J.attempt(jar::scan);
|
||||||
|
KList<ExternalDataProvider> providers = new KList<>();
|
||||||
|
|
||||||
|
for (Class<?> c : jar.getClasses()) {
|
||||||
|
if (ExternalDataProvider.class.isAssignableFrom(c)) {
|
||||||
|
try {
|
||||||
|
ExternalDataProvider p = (ExternalDataProvider) c.getDeclaredConstructor().newInstance();
|
||||||
|
if (p.getPlugin() != null) Iris.info(p.getPluginId() + " found, loading " + c.getSimpleName() + "...");
|
||||||
|
providers.add(p);
|
||||||
|
} catch (Throwable ignored) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return providers;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,114 @@
|
|||||||
|
package com.volmit.iris.core.service;
|
||||||
|
|
||||||
|
import com.github.benmanes.caffeine.cache.Cache;
|
||||||
|
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||||
|
import com.github.benmanes.caffeine.cache.Scheduler;
|
||||||
|
import com.volmit.iris.core.IrisSettings;
|
||||||
|
import com.volmit.iris.core.pregenerator.cache.PregenCache;
|
||||||
|
import com.volmit.iris.util.collection.KMap;
|
||||||
|
import com.volmit.iris.util.data.KCache;
|
||||||
|
import com.volmit.iris.util.plugin.IrisService;
|
||||||
|
import lombok.NonNull;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.EventPriority;
|
||||||
|
import org.bukkit.event.world.ChunkLoadEvent;
|
||||||
|
import org.bukkit.event.world.WorldInitEvent;
|
||||||
|
import org.bukkit.event.world.WorldUnloadEvent;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
public class GlobalCacheSVC implements IrisService {
|
||||||
|
private static final Cache<String, PregenCache> REFERENCE_CACHE = Caffeine.newBuilder()
|
||||||
|
.executor(KCache.EXECUTOR)
|
||||||
|
.scheduler(Scheduler.systemScheduler())
|
||||||
|
.weakValues()
|
||||||
|
.build();
|
||||||
|
private final KMap<String, PregenCache> globalCache = new KMap<>();
|
||||||
|
private transient boolean lastState;
|
||||||
|
private static boolean disabled = true;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onEnable() {
|
||||||
|
disabled = false;
|
||||||
|
lastState = !IrisSettings.get().getWorld().isGlobalPregenCache();
|
||||||
|
if (lastState) return;
|
||||||
|
Bukkit.getWorlds().forEach(this::createCache);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDisable() {
|
||||||
|
disabled = true;
|
||||||
|
globalCache.qclear((world, cache) -> cache.write());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public PregenCache get(@NonNull World world) {
|
||||||
|
return globalCache.get(world.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public PregenCache get(@NonNull String world) {
|
||||||
|
return globalCache.get(world);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.MONITOR)
|
||||||
|
public void on(WorldInitEvent event) {
|
||||||
|
if (isDisabled()) return;
|
||||||
|
createCache(event.getWorld());
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.MONITOR)
|
||||||
|
public void on(WorldUnloadEvent event) {
|
||||||
|
var cache = globalCache.remove(event.getWorld().getName());
|
||||||
|
if (cache == null) return;
|
||||||
|
cache.write();
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.MONITOR)
|
||||||
|
public void on(ChunkLoadEvent event) {
|
||||||
|
var cache = get(event.getWorld());
|
||||||
|
if (cache == null) return;
|
||||||
|
cache.cacheChunk(event.getChunk().getX(), event.getChunk().getZ());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createCache(World world) {
|
||||||
|
globalCache.computeIfAbsent(world.getName(), GlobalCacheSVC::createDefault);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isDisabled() {
|
||||||
|
boolean conf = IrisSettings.get().getWorld().isGlobalPregenCache();
|
||||||
|
if (lastState != conf)
|
||||||
|
return lastState;
|
||||||
|
|
||||||
|
if (conf) {
|
||||||
|
Bukkit.getWorlds().forEach(this::createCache);
|
||||||
|
} else {
|
||||||
|
globalCache.values().removeIf(cache -> {
|
||||||
|
cache.write();
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return lastState = !conf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public static PregenCache createCache(@NonNull String worldName, @NonNull Function<String, PregenCache> provider) {
|
||||||
|
return REFERENCE_CACHE.get(worldName, provider);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public static PregenCache createDefault(@NonNull String worldName) {
|
||||||
|
return createCache(worldName, GlobalCacheSVC::createDefault0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static PregenCache createDefault0(String worldName) {
|
||||||
|
if (disabled) return PregenCache.EMPTY;
|
||||||
|
return PregenCache.create(new File(Bukkit.getWorldContainer(), String.join(File.separator, worldName, "iris", "pregen"))).sync();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,317 +1,247 @@
|
|||||||
package com.volmit.iris.core.service;
|
package com.volmit.iris.core.service;
|
||||||
|
|
||||||
|
import com.google.common.util.concurrent.AtomicDouble;
|
||||||
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.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;
|
||||||
import com.volmit.iris.engine.platform.PlatformChunkGenerator;
|
import com.volmit.iris.engine.platform.PlatformChunkGenerator;
|
||||||
import com.volmit.iris.util.collection.KList;
|
|
||||||
import com.volmit.iris.util.collection.KMap;
|
import com.volmit.iris.util.collection.KMap;
|
||||||
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.TectonicPlate;
|
import com.volmit.iris.util.math.RNG;
|
||||||
import com.volmit.iris.util.misc.getHardware;
|
|
||||||
import com.volmit.iris.util.plugin.IrisService;
|
import com.volmit.iris.util.plugin.IrisService;
|
||||||
import com.volmit.iris.util.scheduling.ChronoLatch;
|
import com.volmit.iris.util.plugin.VolmitSender;
|
||||||
import com.volmit.iris.util.scheduling.Looper;
|
import com.volmit.iris.util.scheduling.Looper;
|
||||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
import lombok.Synchronized;
|
||||||
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.server.PluginDisableEvent;
|
|
||||||
import org.bukkit.event.server.ServerLoadEvent;
|
|
||||||
import org.bukkit.event.world.WorldLoadEvent;
|
import org.bukkit.event.world.WorldLoadEvent;
|
||||||
import org.bukkit.event.world.WorldUnloadEvent;
|
import org.bukkit.event.world.WorldUnloadEvent;
|
||||||
import org.checkerframework.checker.units.qual.A;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.concurrent.*;
|
||||||
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.locks.ReentrantLock;
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
|
|
||||||
public class IrisEngineSVC implements IrisService {
|
public class IrisEngineSVC implements IrisService {
|
||||||
public static IrisEngineSVC instance;
|
private final AtomicInteger tectonicLimit = new AtomicInteger(30);
|
||||||
public boolean isServerShuttingDown = false;
|
private final AtomicInteger tectonicPlates = new AtomicInteger();
|
||||||
public boolean isServerLoaded = false;
|
private final AtomicInteger queuedTectonicPlates = new AtomicInteger();
|
||||||
private static final AtomicInteger tectonicLimit = new AtomicInteger(30);
|
private final AtomicInteger trimmerAlive = new AtomicInteger();
|
||||||
private ReentrantLock lastUseLock;
|
private final AtomicInteger unloaderAlive = new AtomicInteger();
|
||||||
private KMap<World, Long> lastUse;
|
private final AtomicInteger totalWorlds = new AtomicInteger();
|
||||||
private List<World> IrisWorlds;
|
private final AtomicDouble maxIdleDuration = new AtomicDouble();
|
||||||
private Looper cacheTicker;
|
private final AtomicDouble minIdleDuration = new AtomicDouble();
|
||||||
private Looper trimTicker;
|
private final AtomicLong loadedChunks = new AtomicLong();
|
||||||
private Looper unloadTicker;
|
private final KMap<World, Registered> worlds = new KMap<>();
|
||||||
|
private ScheduledExecutorService service;
|
||||||
private Looper updateTicker;
|
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
|
@Override
|
||||||
public void onEnable() {
|
public void onEnable() {
|
||||||
this.cl = new ChronoLatch(5000);
|
var settings = IrisSettings.get().getPerformance();
|
||||||
lastUse = new KMap<>();
|
var engine = settings.getEngineSVC();
|
||||||
lastUseLock = new ReentrantLock();
|
service = Executors.newScheduledThreadPool(0,
|
||||||
IrisWorlds = new ArrayList<>();
|
(engine.isUseVirtualThreads()
|
||||||
IsUnloadAlive = new AtomicBoolean(true);
|
? Thread.ofVirtual()
|
||||||
IsTrimAlive = new AtomicBoolean(true);
|
: Thread.ofPlatform().priority(engine.getPriority()))
|
||||||
trimActiveAlive = new PrecisionStopwatch();
|
.name("Iris EngineSVC-", 0)
|
||||||
unloadActiveAlive = new PrecisionStopwatch();
|
.factory());
|
||||||
trimAlive = new PrecisionStopwatch();
|
tectonicLimit.set(settings.getTectonicPlateSize());
|
||||||
unloadAlive = new PrecisionStopwatch();
|
Bukkit.getWorlds().forEach(this::add);
|
||||||
TotalTectonicPlates = new AtomicInteger();
|
setup();
|
||||||
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() {
|
@Override
|
||||||
boolean trimAlive = trimTicker.isAlive();
|
public void onDisable() {
|
||||||
boolean unloadAlive = unloadTicker.isAlive();
|
service.shutdown();
|
||||||
Iris.info("Status:");
|
updateTicker.interrupt();
|
||||||
Iris.info("- Trim: " + trimAlive);
|
worlds.keySet().forEach(this::remove);
|
||||||
Iris.info("- Unload: " + unloadAlive);
|
worlds.clear();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getTectonicLimit() {
|
public void engineStatus(VolmitSender sender) {
|
||||||
return tectonicLimit.get();
|
sender.sendMessage(C.DARK_PURPLE + "-------------------------");
|
||||||
|
sender.sendMessage(C.DARK_PURPLE + "Status:");
|
||||||
|
sender.sendMessage(C.DARK_PURPLE + "- Service: " + C.LIGHT_PURPLE + (service.isShutdown() ? "Shutdown" : "Running"));
|
||||||
|
sender.sendMessage(C.DARK_PURPLE + "- Updater: " + C.LIGHT_PURPLE + (updateTicker.isAlive() ? "Running" : "Stopped"));
|
||||||
|
sender.sendMessage(C.DARK_PURPLE + "- Trimmers: " + C.LIGHT_PURPLE + trimmerAlive.get());
|
||||||
|
sender.sendMessage(C.DARK_PURPLE + "- Unloaders: " + C.LIGHT_PURPLE + unloaderAlive.get());
|
||||||
|
sender.sendMessage(C.DARK_PURPLE + "Tectonic Plates:");
|
||||||
|
sender.sendMessage(C.DARK_PURPLE + "- Limit: " + C.LIGHT_PURPLE + tectonicLimit.get());
|
||||||
|
sender.sendMessage(C.DARK_PURPLE + "- Total: " + C.LIGHT_PURPLE + tectonicPlates.get());
|
||||||
|
sender.sendMessage(C.DARK_PURPLE + "- Queued: " + C.LIGHT_PURPLE + queuedTectonicPlates.get());
|
||||||
|
sender.sendMessage(C.DARK_PURPLE + "- Max Idle Duration: " + C.LIGHT_PURPLE + Form.duration(maxIdleDuration.get(), 2));
|
||||||
|
sender.sendMessage(C.DARK_PURPLE + "- Min Idle Duration: " + C.LIGHT_PURPLE + Form.duration(minIdleDuration.get(), 2));
|
||||||
|
sender.sendMessage(C.DARK_PURPLE + "Other:");
|
||||||
|
sender.sendMessage(C.DARK_PURPLE + "- Iris Worlds: " + C.LIGHT_PURPLE + totalWorlds.get());
|
||||||
|
sender.sendMessage(C.DARK_PURPLE + "- Loaded Chunks: " + C.LIGHT_PURPLE + loadedChunks.get());
|
||||||
|
sender.sendMessage(C.DARK_PURPLE + "- Cache Size: " + C.LIGHT_PURPLE + Form.f(IrisData.cacheSize()));
|
||||||
|
sender.sendMessage(C.DARK_PURPLE + "-------------------------");
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onWorldUnload(WorldUnloadEvent event) {
|
public void onWorldUnload(WorldUnloadEvent event) {
|
||||||
updateWorlds();
|
remove(event.getWorld());
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onWorldLoad(WorldLoadEvent event) {
|
public void onWorldLoad(WorldLoadEvent event) {
|
||||||
updateWorlds();
|
add(event.getWorld());
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
private void remove(World world) {
|
||||||
public void onServerBoot(ServerLoadEvent event) {
|
var entry = worlds.remove(world);
|
||||||
isServerLoaded = true;
|
if (entry == null) return;
|
||||||
|
entry.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
private void add(World world) {
|
||||||
public void onPluginDisable(PluginDisableEvent event) {
|
var access = IrisToolbelt.access(world);
|
||||||
if (event.getPlugin().equals(Iris.instance)) {
|
if (access == null) return;
|
||||||
isServerShuttingDown = true;
|
worlds.put(world, new Registered(world.getName(), access));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateWorlds() {
|
private synchronized void setup() {
|
||||||
for (World world : Bukkit.getWorlds()) {
|
if (updateTicker != null && updateTicker.isAlive())
|
||||||
try {
|
return;
|
||||||
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() {
|
updateTicker = new Looper() {
|
||||||
@Override
|
@Override
|
||||||
protected long loop() {
|
protected long loop() {
|
||||||
try {
|
try {
|
||||||
TotalQueuedTectonicPlates.set(0);
|
queuedTectonicPlates.set(0);
|
||||||
TotalNotQueuedTectonicPlates.set(0);
|
tectonicPlates.set(0);
|
||||||
TotalTectonicPlates.set(0);
|
loadedChunks.set(0);
|
||||||
for (World world : IrisWorlds) {
|
unloaderAlive.set(0);
|
||||||
Engine engine = Objects.requireNonNull(IrisToolbelt.access(world)).getEngine();
|
trimmerAlive.set(0);
|
||||||
TotalQueuedTectonicPlates.addAndGet((int) engine.getMantle().getToUnload());
|
totalWorlds.set(0);
|
||||||
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()) {
|
double maxDuration = Long.MIN_VALUE;
|
||||||
Iris.info(C.RED + "UnloadTicker found dead! Booting it up!");
|
double minDuration = Long.MAX_VALUE;
|
||||||
try {
|
for (var entry : worlds.entrySet()) {
|
||||||
UnloadLogic();
|
var registered = entry.getValue();
|
||||||
} catch (Exception e) {
|
if (registered.closed) continue;
|
||||||
Iris.error("What happened?");
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
totalWorlds.incrementAndGet();
|
||||||
return -1;
|
unloaderAlive.addAndGet(registered.unloaderAlive() ? 1 : 0);
|
||||||
|
trimmerAlive.addAndGet(registered.trimmerAlive() ? 1 : 0);
|
||||||
|
|
||||||
|
var engine = registered.getEngine();
|
||||||
|
if (engine == null) continue;
|
||||||
|
|
||||||
|
queuedTectonicPlates.addAndGet((int) engine.getMantle().getUnloadRegionCount());
|
||||||
|
tectonicPlates.addAndGet(engine.getMantle().getLoadedRegionCount());
|
||||||
|
loadedChunks.addAndGet(entry.getKey().getLoadedChunks().length);
|
||||||
|
|
||||||
|
double duration = engine.getMantle().getAdjustedIdleDuration();
|
||||||
|
if (duration > maxDuration) maxDuration = duration;
|
||||||
|
if (duration < minDuration) minDuration = duration;
|
||||||
|
}
|
||||||
|
maxIdleDuration.set(maxDuration);
|
||||||
|
minIdleDuration.set(minDuration);
|
||||||
|
|
||||||
|
worlds.values().forEach(Registered::update);
|
||||||
|
} catch (Throwable e) {
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
return 1000;
|
return 1000;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
updateTicker.start();
|
||||||
}
|
}
|
||||||
public void TrimLogic() {
|
|
||||||
if (trimTicker == null || !trimTicker.isAlive()) {
|
|
||||||
trimTicker = new Looper() {
|
|
||||||
private final Supplier<Engine> supplier = createSupplier();
|
|
||||||
|
|
||||||
@Override
|
private final class Registered {
|
||||||
protected long loop() {
|
private final String name;
|
||||||
long start = System.currentTimeMillis();
|
private final PlatformChunkGenerator access;
|
||||||
trimAlive.reset();
|
private final int offset = RNG.r.nextInt(1000);
|
||||||
|
private transient ScheduledFuture<?> trimmer;
|
||||||
|
private transient ScheduledFuture<?> unloader;
|
||||||
|
private transient boolean closed;
|
||||||
|
|
||||||
|
private Registered(String name, PlatformChunkGenerator access) {
|
||||||
|
this.name = name;
|
||||||
|
this.access = access;
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean unloaderAlive() {
|
||||||
|
return unloader != null && !unloader.isDone() && !unloader.isCancelled();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean trimmerAlive() {
|
||||||
|
return trimmer != null && !trimmer.isDone() && !trimmer.isCancelled();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Synchronized
|
||||||
|
private void update() {
|
||||||
|
if (closed || service == null || service.isShutdown())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (trimmer == null || trimmer.isDone() || trimmer.isCancelled()) {
|
||||||
|
trimmer = service.scheduleAtFixedRate(() -> {
|
||||||
|
Engine engine = getEngine();
|
||||||
|
if (engine == null || !engine.getMantle().getMantle().shouldReduce(engine))
|
||||||
|
return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Engine engine = supplier.get();
|
engine.getMantle().trim(tectonicLimit());
|
||||||
if (engine != null) {
|
} catch (Throwable e) {
|
||||||
engine.getMantle().trim(tectonicLimit.get() / lastUse.size());
|
Iris.reportError(e);
|
||||||
|
Iris.error("EngineSVC: Failed to trim for " + name);
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}, offset, 2000, TimeUnit.MILLISECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unloader == null || unloader.isDone() || unloader.isCancelled()) {
|
||||||
|
unloader = service.scheduleAtFixedRate(() -> {
|
||||||
|
Engine engine = getEngine();
|
||||||
|
if (engine == null || !engine.getMantle().getMantle().shouldReduce(engine))
|
||||||
|
return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
long unloadStart = System.currentTimeMillis();
|
||||||
|
int count = engine.getMantle().unloadTectonicPlate(IrisSettings.get().getPerformance().getEngineSVC().forceMulticoreWrite ? 0 : tectonicLimit());
|
||||||
|
if (count > 0) {
|
||||||
|
Iris.debug(C.GOLD + "Unloaded " + C.YELLOW + count + " TectonicPlates in " + C.RED + Form.duration(System.currentTimeMillis() - unloadStart, 2));
|
||||||
}
|
}
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
Iris.info(C.RED + "EngineSVC: Failed to trim.");
|
Iris.error("EngineSVC: Failed to unload for " + name);
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
}, offset + 1000, 2000, TimeUnit.MILLISECONDS);
|
||||||
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) {
|
private int tectonicLimit() {
|
||||||
Engine engine = generator.getEngine();
|
return tectonicLimit.get() / Math.max(worlds.size(), 1);
|
||||||
boolean closed = engine.getMantle().getData().isClosed();
|
}
|
||||||
if (engine != null && !engine.isStudio() && !closed) {
|
|
||||||
lastUseLock.lock();
|
@Synchronized
|
||||||
lastUse.put(world, System.currentTimeMillis());
|
private void close() {
|
||||||
lastUseLock.unlock();
|
if (closed) return;
|
||||||
return engine;
|
closed = true;
|
||||||
}
|
|
||||||
}
|
if (trimmer != null) {
|
||||||
}
|
trimmer.cancel(false);
|
||||||
} catch (Throwable e) {
|
trimmer = null;
|
||||||
Iris.info(C.RED + "EngineSVC: Failed to create supplier.");
|
|
||||||
e.printStackTrace();
|
|
||||||
Iris.reportError(e);
|
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
if (unloader != null) {
|
||||||
public void onDisable() {
|
unloader.cancel(false);
|
||||||
cacheTicker.interrupt();
|
unloader = null;
|
||||||
trimTicker.interrupt();
|
}
|
||||||
unloadTicker.interrupt();
|
}
|
||||||
lastUse.clear();
|
|
||||||
|
@Nullable
|
||||||
|
private Engine getEngine() {
|
||||||
|
if (closed) return null;
|
||||||
|
return access.getEngine();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,10 +43,6 @@ public class PreservationSVC implements IrisService {
|
|||||||
threads.add(t);
|
threads.add(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void register(MultiBurst burst) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void register(ExecutorService service) {
|
public void register(ExecutorService service) {
|
||||||
services.add(service);
|
services.add(service);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
|
|
||||||
package com.volmit.iris.core.service;
|
package com.volmit.iris.core.service;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
|
||||||
import com.google.gson.JsonSyntaxException;
|
import com.google.gson.JsonSyntaxException;
|
||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.Iris;
|
||||||
import com.volmit.iris.core.IrisSettings;
|
import com.volmit.iris.core.IrisSettings;
|
||||||
@@ -89,16 +88,18 @@ public class StudioSVC implements IrisService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public IrisDimension installIntoWorld(VolmitSender sender, String type, File folder) {
|
public IrisDimension installIntoWorld(VolmitSender sender, String type, File folder) {
|
||||||
|
return installInto(sender, type, new File(folder, "iris/pack"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public IrisDimension installInto(VolmitSender sender, String type, File folder) {
|
||||||
sender.sendMessage("Looking for Package: " + type);
|
sender.sendMessage("Looking for Package: " + type);
|
||||||
File iris = new File(folder, "iris");
|
|
||||||
File irispack = new File(folder, "iris/pack");
|
|
||||||
IrisDimension dim = IrisData.loadAnyDimension(type);
|
IrisDimension dim = IrisData.loadAnyDimension(type);
|
||||||
|
|
||||||
if (dim == null) {
|
if (dim == null) {
|
||||||
for (File i : getWorkspaceFolder().listFiles()) {
|
for (File i : getWorkspaceFolder().listFiles()) {
|
||||||
if (i.isFile() && i.getName().equals(type + ".iris")) {
|
if (i.isFile() && i.getName().equals(type + ".iris")) {
|
||||||
sender.sendMessage("Found " + type + ".iris in " + WORKSPACE_NAME + " folder");
|
sender.sendMessage("Found " + type + ".iris in " + WORKSPACE_NAME + " folder");
|
||||||
ZipUtil.unpack(i, irispack);
|
ZipUtil.unpack(i, folder);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -107,29 +108,29 @@ public class StudioSVC implements IrisService {
|
|||||||
File f = new IrisProject(new File(getWorkspaceFolder(), type)).getPath();
|
File f = new IrisProject(new File(getWorkspaceFolder(), type)).getPath();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
FileUtils.copyDirectory(f, irispack);
|
FileUtils.copyDirectory(f, folder);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
File dimf = new File(irispack, "dimensions/" + type + ".json");
|
File dimensionFile = new File(folder, "dimensions/" + type + ".json");
|
||||||
|
|
||||||
if (!dimf.exists() || !dimf.isFile()) {
|
if (!dimensionFile.exists() || !dimensionFile.isFile()) {
|
||||||
downloadSearch(sender, type, false);
|
downloadSearch(sender, type, false);
|
||||||
File downloaded = getWorkspaceFolder(type);
|
File downloaded = getWorkspaceFolder(type);
|
||||||
|
|
||||||
for (File i : downloaded.listFiles()) {
|
for (File i : downloaded.listFiles()) {
|
||||||
if (i.isFile()) {
|
if (i.isFile()) {
|
||||||
try {
|
try {
|
||||||
FileUtils.copyFile(i, new File(irispack, i.getName()));
|
FileUtils.copyFile(i, new File(folder, i.getName()));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
FileUtils.copyDirectory(i, new File(irispack, i.getName()));
|
FileUtils.copyDirectory(i, new File(folder, i.getName()));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
@@ -140,12 +141,14 @@ public class StudioSVC implements IrisService {
|
|||||||
IO.delete(downloaded);
|
IO.delete(downloaded);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!dimf.exists() || !dimf.isFile()) {
|
if (!dimensionFile.exists() || !dimensionFile.isFile()) {
|
||||||
sender.sendMessage("Can't find the " + dimf.getName() + " in the dimensions folder of this pack! Failed!");
|
sender.sendMessage("Can't find the " + dimensionFile.getName() + " in the dimensions folder of this pack! Failed!");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
IrisData dm = IrisData.get(irispack);
|
IrisData dm = IrisData.get(folder);
|
||||||
|
dm.dump();
|
||||||
|
dm.clearLists();
|
||||||
dim = dm.getDimensionLoader().load(type);
|
dim = dm.getDimensionLoader().load(type);
|
||||||
|
|
||||||
if (dim == null) {
|
if (dim == null) {
|
||||||
@@ -250,30 +253,25 @@ public class StudioSVC implements IrisService {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
File dimensions = new File(dir, "dimensions");
|
IrisData data = IrisData.get(dir);
|
||||||
|
String[] dimensions = data.getDimensionLoader().getPossibleKeys();
|
||||||
|
|
||||||
if (!(dimensions.exists() && dimensions.isDirectory())) {
|
if (dimensions == null || dimensions.length == 0) {
|
||||||
sender.sendMessage("Invalid Format. Missing dimensions folder");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dimensions.listFiles() == null) {
|
|
||||||
sender.sendMessage("No dimension file found in the extracted zip file.");
|
sender.sendMessage("No dimension file found in the extracted zip file.");
|
||||||
sender.sendMessage("Check it is there on GitHub and report this to staff!");
|
sender.sendMessage("Check it is there on GitHub and report this to staff!");
|
||||||
} else if (dimensions.listFiles().length != 1) {
|
} else if (dimensions.length != 1) {
|
||||||
sender.sendMessage("Dimensions folder must have 1 file in it");
|
sender.sendMessage("Dimensions folder must have 1 file in it");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
File dim = dimensions.listFiles()[0];
|
IrisDimension d = data.getDimensionLoader().load(dimensions[0]);
|
||||||
|
|
||||||
if (!dim.isFile()) {
|
if (d == null) {
|
||||||
sender.sendMessage("Invalid dimension (folder) in dimensions folder");
|
sender.sendMessage("Invalid dimension (folder) in dimensions folder");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
String key = dim.getName().split("\\Q.\\E")[0];
|
String key = d.getLoadKey();
|
||||||
IrisDimension d = new Gson().fromJson(IO.readAll(dim), IrisDimension.class);
|
|
||||||
sender.sendMessage("Importing " + d.getName() + " (" + key + ")");
|
sender.sendMessage("Importing " + d.getName() + " (" + key + ")");
|
||||||
File packEntry = new File(packs, key);
|
File packEntry = new File(packs, key);
|
||||||
|
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ import org.bukkit.util.Vector;
|
|||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
|
||||||
@@ -80,6 +81,8 @@ public class WandSVC implements IrisService {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
Location[] f = getCuboid(p);
|
Location[] f = getCuboid(p);
|
||||||
|
if (f == null || f[0] == null || f[1] == null)
|
||||||
|
return null;
|
||||||
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());
|
||||||
|
|
||||||
@@ -198,7 +201,9 @@ public class WandSVC implements IrisService {
|
|||||||
public static Location stringToLocation(String s) {
|
public static Location stringToLocation(String s) {
|
||||||
try {
|
try {
|
||||||
String[] f = s.split("\\Q in \\E");
|
String[] f = s.split("\\Q in \\E");
|
||||||
|
if (f.length != 2) return null;
|
||||||
String[] g = f[0].split("\\Q,\\E");
|
String[] g = f[0].split("\\Q,\\E");
|
||||||
|
if (g.length != 3) return null;
|
||||||
return new Location(Bukkit.getWorld(f[1]), Integer.parseInt(g[0]), Integer.parseInt(g[1]), Integer.parseInt(g[2]));
|
return new Location(Bukkit.getWorld(f[1]), Integer.parseInt(g[0]), Integer.parseInt(g[1]), Integer.parseInt(g[2]));
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
@@ -357,6 +362,7 @@ public class WandSVC implements IrisService {
|
|||||||
try {
|
try {
|
||||||
if ((IrisSettings.get().getWorld().worldEditWandCUI && isHoldingWand(p)) || isWand(p.getInventory().getItemInMainHand())) {
|
if ((IrisSettings.get().getWorld().worldEditWandCUI && isHoldingWand(p)) || isWand(p.getInventory().getItemInMainHand())) {
|
||||||
Location[] d = getCuboid(p);
|
Location[] d = getCuboid(p);
|
||||||
|
if (d == null || d[0] == null || d[1] == null) return;
|
||||||
new WandSelection(new Cuboid(d[0], d[1]), p).draw();
|
new WandSelection(new Cuboid(d[0], d[1]), p).draw();
|
||||||
}
|
}
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
|
|||||||
@@ -1,625 +0,0 @@
|
|||||||
package com.volmit.iris.core.tools;
|
|
||||||
|
|
||||||
import com.volmit.iris.Iris;
|
|
||||||
import com.volmit.iris.util.format.C;
|
|
||||||
import oshi.SystemInfo;
|
|
||||||
import oshi.hardware.CentralProcessor;
|
|
||||||
import oshi.hardware.GlobalMemory;
|
|
||||||
import oshi.hardware.HWDiskStore;
|
|
||||||
import oshi.software.os.OperatingSystem;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.lang.management.ManagementFactory;
|
|
||||||
import java.lang.management.MemoryMXBean;
|
|
||||||
import java.lang.management.MemoryUsage;
|
|
||||||
import java.security.SecureRandom;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Base64;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
|
||||||
import java.util.stream.IntStream;
|
|
||||||
import java.util.zip.Deflater;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
|
||||||
import java.util.concurrent.ExecutionException;
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
|
|
||||||
import static com.google.common.math.LongMath.isPrime;
|
|
||||||
import static com.volmit.iris.util.misc.getHardware.getCPUModel;
|
|
||||||
public class IrisBenchmarking {
|
|
||||||
static String ServerOS;
|
|
||||||
static String filePath = "benchmark.dat";
|
|
||||||
static double avgWriteSpeedMBps;
|
|
||||||
static double avgReadSpeedMBps;
|
|
||||||
static double highestWriteSpeedMBps;
|
|
||||||
static double highestReadSpeedMBps;
|
|
||||||
static double lowestWriteSpeedMBps;
|
|
||||||
static double lowestReadSpeedMBps;
|
|
||||||
static double calculateIntegerMath;
|
|
||||||
static double calculateFloatingPoint;
|
|
||||||
static double calculatePrimeNumbers;
|
|
||||||
static double calculateStringSorting;
|
|
||||||
static double calculateDataEncryption;
|
|
||||||
static double calculateDataCompression;
|
|
||||||
static String currentRunning = "None";
|
|
||||||
static int BenchmarksCompleted = 0;
|
|
||||||
static int BenchmarksTotal = 7;
|
|
||||||
static int totalTasks = 10;
|
|
||||||
static int currentTasks = 0;
|
|
||||||
static double WindowsCPUCompression;
|
|
||||||
static double WindowsCPUEncryption;
|
|
||||||
static double WindowsCPUCSHA1;
|
|
||||||
static double elapsedTimeNs;
|
|
||||||
static boolean Winsat = false;
|
|
||||||
static boolean WindowsDiskSpeed = false;
|
|
||||||
public static boolean inProgress = false;
|
|
||||||
static double startTime;
|
|
||||||
// Good enough for now. . .
|
|
||||||
|
|
||||||
public static void runBenchmark() throws InterruptedException {
|
|
||||||
inProgress = true;
|
|
||||||
getServerOS();
|
|
||||||
deleteTestFile(filePath);
|
|
||||||
AtomicReference<Double> doneCalculateDiskSpeed = new AtomicReference<>((double) 0);
|
|
||||||
startBenchmarkTimer();
|
|
||||||
Iris.info("Benchmark Started!");
|
|
||||||
Iris.warn("Although it may seem momentarily paused, it's actively processing.");
|
|
||||||
BenchmarksCompleted = 0;
|
|
||||||
|
|
||||||
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
|
|
||||||
currentRunning = "calculateDiskSpeed";
|
|
||||||
progressBar();
|
|
||||||
if (ServerOS.contains("Windows") && isRunningAsAdmin()) {
|
|
||||||
WindowsDiskSpeed = true;
|
|
||||||
WindowsDiskSpeedTest();
|
|
||||||
} else {
|
|
||||||
warningFallback();
|
|
||||||
try {
|
|
||||||
Thread.sleep(10);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
doneCalculateDiskSpeed.set(roundToTwoDecimalPlaces(calculateDiskSpeed()));
|
|
||||||
BenchmarksCompleted++;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}).thenRun(() -> {
|
|
||||||
currentRunning = "WindowsCpuSpeedTest";
|
|
||||||
progressBar();
|
|
||||||
if (ServerOS.contains("Windows") && isRunningAsAdmin()) {
|
|
||||||
Winsat = true;
|
|
||||||
WindowsCpuSpeedTest();
|
|
||||||
} else {
|
|
||||||
Iris.info("Skipping:" + C.BLUE + " Windows System Assessment Tool Benchmarks");
|
|
||||||
if (!ServerOS.contains("Windows")) {
|
|
||||||
Iris.info("Required Software:" + C.BLUE + " Windows");
|
|
||||||
BenchmarksTotal = 6;
|
|
||||||
}
|
|
||||||
if (!isRunningAsAdmin()) {
|
|
||||||
Iris.info(C.RED + "ERROR: " + C.DARK_RED + "Elevated privileges missing");
|
|
||||||
BenchmarksTotal = 6;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}).thenRun(() -> {
|
|
||||||
currentRunning = "calculateIntegerMath";
|
|
||||||
progressBar();
|
|
||||||
calculateIntegerMath = roundToTwoDecimalPlaces(calculateIntegerMath());
|
|
||||||
BenchmarksCompleted++;
|
|
||||||
}).thenRun(() -> {
|
|
||||||
currentRunning = "calculateFloatingPoint";
|
|
||||||
progressBar();
|
|
||||||
calculateFloatingPoint = roundToTwoDecimalPlaces(calculateFloatingPoint());
|
|
||||||
BenchmarksCompleted++;
|
|
||||||
}).thenRun(() -> {
|
|
||||||
currentRunning = "calculateStringSorting";
|
|
||||||
progressBar();
|
|
||||||
calculateStringSorting = roundToTwoDecimalPlaces(calculateStringSorting());
|
|
||||||
BenchmarksCompleted++;
|
|
||||||
}).thenRun(() -> {
|
|
||||||
currentRunning = "calculatePrimeNumbers";
|
|
||||||
progressBar();
|
|
||||||
calculatePrimeNumbers = roundToTwoDecimalPlaces(calculatePrimeNumbers());
|
|
||||||
BenchmarksCompleted++;
|
|
||||||
}).thenRun(() -> {
|
|
||||||
currentRunning = "calculateDataEncryption";
|
|
||||||
progressBar();
|
|
||||||
calculateDataEncryption = roundToTwoDecimalPlaces(calculateDataEncryption());
|
|
||||||
BenchmarksCompleted++;
|
|
||||||
}).thenRun(() -> {
|
|
||||||
currentRunning = "calculateDataCompression";
|
|
||||||
progressBar();
|
|
||||||
calculateDataCompression = roundToTwoDecimalPlaces(calculateDataCompression());
|
|
||||||
BenchmarksCompleted++;
|
|
||||||
}).thenRun(() -> {
|
|
||||||
elapsedTimeNs = stopBenchmarkTimer();
|
|
||||||
results();
|
|
||||||
inProgress = false;
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
|
||||||
future.get();
|
|
||||||
} catch (InterruptedException | ExecutionException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void progressBar() {
|
|
||||||
Iris.info("-----------------------------------------------------");
|
|
||||||
Iris.info("Currently Running: " + C.BLUE + currentRunning);
|
|
||||||
// Iris.info("Tasks: " + "Current Tasks: " + C.BLUE + currentTasks + C.WHITE + " / " + "Total Tasks: " + C.BLUE + totalTasks);
|
|
||||||
Iris.info("Benchmarks Completed: " + C.BLUE + BenchmarksCompleted + C.WHITE + " / " + "Total: " + C.BLUE + BenchmarksTotal);
|
|
||||||
Iris.info("-----------------------------------------------------");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void results() {
|
|
||||||
|
|
||||||
SystemInfo systemInfo = new SystemInfo();
|
|
||||||
GlobalMemory globalMemory = systemInfo.getHardware().getMemory();
|
|
||||||
long totalMemoryMB = globalMemory.getTotal() / (1024 * 1024);
|
|
||||||
long availableMemoryMB = globalMemory.getAvailable() / (1024 * 1024);
|
|
||||||
long totalPageSize = globalMemory.getPageSize() / (1024 * 1024);
|
|
||||||
long usedMemoryMB = totalMemoryMB - availableMemoryMB;
|
|
||||||
MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
|
|
||||||
|
|
||||||
Iris.info("OS: " + ServerOS);
|
|
||||||
if (!isRunningAsAdmin() || !ServerOS.contains("Windows")) {
|
|
||||||
Iris.info(C.GOLD + "For the full results use Windows + Admin Rights..");
|
|
||||||
}
|
|
||||||
Iris.info("CPU Model: " + getCPUModel());
|
|
||||||
Iris.info("CPU Score: " + "WIP");
|
|
||||||
Iris.info("- Integer Math: " + calculateIntegerMath + " MOps/Sec");
|
|
||||||
Iris.info("- Floating Point Math: " + calculateFloatingPoint + " MOps/Sec");
|
|
||||||
Iris.info("- Find Prime Numbers: " + calculatePrimeNumbers + " Primes/Sec");
|
|
||||||
Iris.info("- Random String Sorting: " + calculateStringSorting + " Thousand Strings/Sec");
|
|
||||||
Iris.info("- Data Encryption: " + formatDouble(calculateDataEncryption) + " MBytes/Sec");
|
|
||||||
Iris.info("- Data Compression: " + formatDouble(calculateDataCompression) + " MBytes/Sec");
|
|
||||||
|
|
||||||
if (WindowsDiskSpeed) {
|
|
||||||
//Iris.info("Disk Model: " + getDiskModel());
|
|
||||||
Iris.info(C.BLUE + "- Running with Windows System Assessment Tool");
|
|
||||||
Iris.info("- Sequential 64.0 Write: " + C.BLUE + formatDouble(avgWriteSpeedMBps) + " Mbps");
|
|
||||||
Iris.info("- Sequential 64.0 Read: " + C.BLUE + formatDouble(avgReadSpeedMBps) + " Mbps");
|
|
||||||
} else {
|
|
||||||
// Iris.info("Disk Model: " + getDiskModel());
|
|
||||||
Iris.info(C.GREEN + "- Running in Native Mode");
|
|
||||||
Iris.info("- Average Write Speed: " + C.GREEN + formatDouble(avgWriteSpeedMBps) + " Mbps");
|
|
||||||
Iris.info("- Average Read Speed: " + C.GREEN + formatDouble(avgReadSpeedMBps) + " Mbps");
|
|
||||||
Iris.info("- Highest Write Speed: " + formatDouble(highestWriteSpeedMBps) + " Mbps");
|
|
||||||
Iris.info("- Highest Read Speed: " + formatDouble(highestReadSpeedMBps) + " Mbps");
|
|
||||||
Iris.info("- Lowest Write Speed: " + formatDouble(lowestWriteSpeedMBps) + " Mbps");
|
|
||||||
Iris.info("- Lowest Read Speed: " + formatDouble(lowestReadSpeedMBps) + " Mbps");
|
|
||||||
}
|
|
||||||
Iris.info("Ram Usage: ");
|
|
||||||
Iris.info("- Total Ram: " + totalMemoryMB + " MB");
|
|
||||||
Iris.info("- Used Ram: " + usedMemoryMB + " MB");
|
|
||||||
Iris.info("- Total Process Ram: " + C.BLUE + getMaxMemoryUsage() + " MB");
|
|
||||||
Iris.info("- Total Paging Size: " + totalPageSize + " MB");
|
|
||||||
if (Winsat) {
|
|
||||||
Iris.info(C.BLUE + "Windows System Assessment Tool: ");
|
|
||||||
Iris.info("- CPU LZW Compression:" + C.BLUE + formatDouble(WindowsCPUCompression) + " MB/s");
|
|
||||||
Iris.info("- CPU AES256 Encryption: " + C.BLUE + formatDouble(WindowsCPUEncryption) + " MB/s");
|
|
||||||
Iris.info("- CPU SHA1 Hash: " + C.BLUE + formatDouble(WindowsCPUCSHA1) + " MB/s");
|
|
||||||
Iris.info("Duration: " + roundToTwoDecimalPlaces(elapsedTimeNs) + " Seconds");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static long getMaxMemoryUsage() {
|
|
||||||
MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
|
|
||||||
MemoryUsage heapMemoryUsage = memoryMXBean.getHeapMemoryUsage();
|
|
||||||
MemoryUsage nonHeapMemoryUsage = memoryMXBean.getNonHeapMemoryUsage();
|
|
||||||
long maxHeapMemory = heapMemoryUsage.getMax();
|
|
||||||
long maxNonHeapMemory = nonHeapMemoryUsage.getMax();
|
|
||||||
long maxMemoryUsageMB = (maxHeapMemory + maxNonHeapMemory) / (1024 * 1024);
|
|
||||||
return maxMemoryUsageMB;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void getServerOS() {
|
|
||||||
SystemInfo systemInfo = new SystemInfo();
|
|
||||||
OperatingSystem os = systemInfo.getOperatingSystem();
|
|
||||||
ServerOS = os.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isRunningAsAdmin() {
|
|
||||||
if (ServerOS.contains("Windows")) {
|
|
||||||
try {
|
|
||||||
Process process = Runtime.getRuntime().exec("winsat disk");
|
|
||||||
process.waitFor();
|
|
||||||
return process.exitValue() == 0;
|
|
||||||
} catch (IOException | InterruptedException e) {
|
|
||||||
// Hmm
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void warningFallback() {
|
|
||||||
Iris.info(C.RED + "Using the " + C.DARK_RED + "FALLBACK" + C.RED + " method due to compatibility issues. ");
|
|
||||||
Iris.info(C.RED + "Please note that this may result in less accurate results.");
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String formatDouble(double value) {
|
|
||||||
return String.format("%.2f", value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void startBenchmarkTimer() {
|
|
||||||
startTime = System.nanoTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static double stopBenchmarkTimer() {
|
|
||||||
long endTime = System.nanoTime();
|
|
||||||
return (endTime - startTime) / 1_000_000_000.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static double calculateIntegerMath() {
|
|
||||||
final int numIterations = 1_000_000_000;
|
|
||||||
final int numRuns = 30;
|
|
||||||
double totalMopsPerSec = 0;
|
|
||||||
|
|
||||||
for (int run = 0; run < numRuns; run++) {
|
|
||||||
long startTime = System.nanoTime();
|
|
||||||
int result = 0;
|
|
||||||
|
|
||||||
for (int i = 0; i < numIterations; i++) {
|
|
||||||
result += i * 2;
|
|
||||||
result -= i / 2;
|
|
||||||
result ^= i;
|
|
||||||
result <<= 1;
|
|
||||||
result >>= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
long endTime = System.nanoTime();
|
|
||||||
double elapsedSeconds = (endTime - startTime) / 1_000_000_000.0;
|
|
||||||
double mopsPerSec = (numIterations / elapsedSeconds) / 1_000_000.0;
|
|
||||||
|
|
||||||
totalMopsPerSec += mopsPerSec;
|
|
||||||
}
|
|
||||||
|
|
||||||
double averageMopsPerSec = totalMopsPerSec / numRuns;
|
|
||||||
return averageMopsPerSec;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static double calculateFloatingPoint() {
|
|
||||||
long numIterations = 85_000_000;
|
|
||||||
int numRuns = 30;
|
|
||||||
double totalMopsPerSec = 0;
|
|
||||||
for (int run = 0; run < numRuns; run++) {
|
|
||||||
double result = 0;
|
|
||||||
long startTime = System.nanoTime();
|
|
||||||
|
|
||||||
for (int i = 0; i < numIterations; i++) {
|
|
||||||
result += Math.sqrt(i) * Math.sin(i) / (i + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
long endTime = System.nanoTime();
|
|
||||||
double elapsedSeconds = (endTime - startTime) / 1_000_000_000.0;
|
|
||||||
double mopsPerSec = (numIterations / elapsedSeconds) / 1_000_000.0;
|
|
||||||
|
|
||||||
totalMopsPerSec += mopsPerSec;
|
|
||||||
}
|
|
||||||
|
|
||||||
double averageMopsPerSec = totalMopsPerSec / numRuns;
|
|
||||||
return averageMopsPerSec;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static double calculatePrimeNumbers() {
|
|
||||||
int primeCount;
|
|
||||||
long numIterations = 1_000_000;
|
|
||||||
int numRuns = 30;
|
|
||||||
double totalMopsPerSec = 0;
|
|
||||||
|
|
||||||
for (int run = 0; run < numRuns; run++) {
|
|
||||||
primeCount = 0;
|
|
||||||
long startTime = System.nanoTime();
|
|
||||||
|
|
||||||
for (int num = 2; primeCount < numIterations; num++) {
|
|
||||||
if (isPrime(num)) {
|
|
||||||
primeCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
long endTime = System.nanoTime();
|
|
||||||
double elapsedSeconds = (endTime - startTime) / 1_000_000_000.0;
|
|
||||||
double mopsPerSec = (primeCount / elapsedSeconds) / 1_000_000.0;
|
|
||||||
|
|
||||||
totalMopsPerSec += mopsPerSec;
|
|
||||||
}
|
|
||||||
|
|
||||||
double averageMopsPerSec = totalMopsPerSec / numRuns;
|
|
||||||
return averageMopsPerSec;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static double calculateStringSorting() {
|
|
||||||
int stringCount = 1_000_000;
|
|
||||||
int stringLength = 100;
|
|
||||||
int numRuns = 30;
|
|
||||||
double totalMopsPerSec = 0;
|
|
||||||
|
|
||||||
for (int run = 0; run < numRuns; run++) {
|
|
||||||
List<String> randomStrings = generateRandomStrings(stringCount, stringLength);
|
|
||||||
long startTime = System.nanoTime();
|
|
||||||
randomStrings.sort(String::compareTo);
|
|
||||||
long endTime = System.nanoTime();
|
|
||||||
|
|
||||||
double elapsedSeconds = (endTime - startTime) / 1_000_000_000.0;
|
|
||||||
double mopsPerSec = (stringCount / elapsedSeconds) / 1_000.0;
|
|
||||||
|
|
||||||
totalMopsPerSec += mopsPerSec;
|
|
||||||
}
|
|
||||||
|
|
||||||
double averageMopsPerSec = totalMopsPerSec / numRuns;
|
|
||||||
return averageMopsPerSec;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static double calculateDataEncryption() {
|
|
||||||
int dataSizeMB = 100;
|
|
||||||
byte[] dataToEncrypt = generateRandomData(dataSizeMB * 1024 * 1024);
|
|
||||||
int numRuns = 20;
|
|
||||||
double totalMBytesPerSec = 0;
|
|
||||||
|
|
||||||
for (int run = 0; run < numRuns; run++) {
|
|
||||||
long startTime = System.nanoTime();
|
|
||||||
byte[] encryptedData = performEncryption(dataToEncrypt, 1);
|
|
||||||
|
|
||||||
long endTime = System.nanoTime();
|
|
||||||
double elapsedSeconds = (endTime - startTime) / 1_000_000_000.0;
|
|
||||||
double mbytesPerSec = (dataToEncrypt.length / (1024 * 1024.0)) / elapsedSeconds;
|
|
||||||
|
|
||||||
totalMBytesPerSec += mbytesPerSec;
|
|
||||||
}
|
|
||||||
|
|
||||||
double averageMBytesPerSec = totalMBytesPerSec / numRuns;
|
|
||||||
return averageMBytesPerSec;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static byte[] performEncryption(byte[] data, int numRuns) {
|
|
||||||
byte[] key = "MyEncryptionKey".getBytes();
|
|
||||||
byte[] result = Arrays.copyOf(data, data.length);
|
|
||||||
for (int run = 0; run < numRuns; run++) {
|
|
||||||
for (int i = 0; i < result.length; i++) {
|
|
||||||
result[i] ^= key[i % key.length];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static double calculateDataCompression() {
|
|
||||||
int dataSizeMB = 500;
|
|
||||||
byte[] dataToCompress = generateRandomData(dataSizeMB * 1024 * 1024);
|
|
||||||
long startTime = System.nanoTime();
|
|
||||||
byte[] compressedData = performCompression(dataToCompress);
|
|
||||||
long endTime = System.nanoTime();
|
|
||||||
|
|
||||||
double elapsedSeconds = (endTime - startTime) / 1e9;
|
|
||||||
double mbytesPerSec = (compressedData.length / (1024.0 * 1024.0)) / elapsedSeconds;
|
|
||||||
|
|
||||||
return mbytesPerSec;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static byte[] performCompression(byte[] data) {
|
|
||||||
Deflater deflater = new Deflater();
|
|
||||||
deflater.setInput(data);
|
|
||||||
deflater.finish();
|
|
||||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(data.length);
|
|
||||||
|
|
||||||
byte[] buffer = new byte[1024];
|
|
||||||
while (!deflater.finished()) {
|
|
||||||
int count = deflater.deflate(buffer);
|
|
||||||
outputStream.write(buffer, 0, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
deflater.end();
|
|
||||||
return outputStream.toByteArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<String> generateRandomStrings(int count, int length) {
|
|
||||||
SecureRandom random = new SecureRandom();
|
|
||||||
List<String> randomStrings = new ArrayList<>();
|
|
||||||
|
|
||||||
IntStream.range(0, count).forEach(i -> {
|
|
||||||
byte[] bytes = new byte[length];
|
|
||||||
random.nextBytes(bytes);
|
|
||||||
randomStrings.add(Base64.getEncoder().encodeToString(bytes));
|
|
||||||
});
|
|
||||||
return randomStrings;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static byte[] generateRandomData(int size) {
|
|
||||||
SecureRandom random = new SecureRandom();
|
|
||||||
byte[] data = new byte[size];
|
|
||||||
random.nextBytes(data);
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static double roundToTwoDecimalPlaces(double value) {
|
|
||||||
return Double.parseDouble(String.format("%.2f", value));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static double calculateCPUScore(long elapsedTimeNs) {
|
|
||||||
return 1.0 / (elapsedTimeNs / 1_000_000.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static double calculateDiskSpeed() {
|
|
||||||
int numRuns = 10;
|
|
||||||
int fileSizeMB = 1000;
|
|
||||||
|
|
||||||
double[] writeSpeeds = new double[numRuns];
|
|
||||||
double[] readSpeeds = new double[numRuns];
|
|
||||||
|
|
||||||
for (int run = 0; run < numRuns; run++) {
|
|
||||||
long writeStartTime = System.nanoTime();
|
|
||||||
deleteTestFile(filePath);
|
|
||||||
createTestFile(filePath, fileSizeMB);
|
|
||||||
long writeEndTime = System.nanoTime();
|
|
||||||
|
|
||||||
long readStartTime = System.nanoTime();
|
|
||||||
readTestFile(filePath);
|
|
||||||
long readEndTime = System.nanoTime();
|
|
||||||
|
|
||||||
double writeSpeed = calculateDiskSpeedMBps(fileSizeMB, writeStartTime, writeEndTime);
|
|
||||||
double readSpeed = calculateDiskSpeedMBps(fileSizeMB, readStartTime, readEndTime);
|
|
||||||
|
|
||||||
writeSpeeds[run] = writeSpeed;
|
|
||||||
readSpeeds[run] = readSpeed;
|
|
||||||
|
|
||||||
if (run == 0) {
|
|
||||||
lowestWriteSpeedMBps = writeSpeed;
|
|
||||||
highestWriteSpeedMBps = writeSpeed;
|
|
||||||
lowestReadSpeedMBps = readSpeed;
|
|
||||||
highestReadSpeedMBps = readSpeed;
|
|
||||||
} else {
|
|
||||||
if (writeSpeed < lowestWriteSpeedMBps) {
|
|
||||||
lowestWriteSpeedMBps = writeSpeed;
|
|
||||||
}
|
|
||||||
if (writeSpeed > highestWriteSpeedMBps) {
|
|
||||||
highestWriteSpeedMBps = writeSpeed;
|
|
||||||
}
|
|
||||||
if (readSpeed < lowestReadSpeedMBps) {
|
|
||||||
lowestReadSpeedMBps = readSpeed;
|
|
||||||
}
|
|
||||||
if (readSpeed > highestReadSpeedMBps) {
|
|
||||||
highestReadSpeedMBps = readSpeed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
avgWriteSpeedMBps = calculateAverage(writeSpeeds);
|
|
||||||
avgReadSpeedMBps = calculateAverage(readSpeeds);
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void createTestFile(String filePath, int fileSizeMB) {
|
|
||||||
try {
|
|
||||||
File file = new File(filePath);
|
|
||||||
byte[] data = new byte[1024 * 1024];
|
|
||||||
Arrays.fill(data, (byte) 0);
|
|
||||||
FileOutputStream fos = new FileOutputStream(file);
|
|
||||||
for (int i = 0; i < fileSizeMB; i++) {
|
|
||||||
fos.write(data);
|
|
||||||
}
|
|
||||||
fos.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void readTestFile(String filePath) {
|
|
||||||
try {
|
|
||||||
File file = new File(filePath);
|
|
||||||
FileInputStream fis = new FileInputStream(file);
|
|
||||||
byte[] buffer = new byte[1024];
|
|
||||||
while (fis.read(buffer) != -1) {
|
|
||||||
}
|
|
||||||
fis.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void deleteTestFile(String filePath) {
|
|
||||||
File file = new File(filePath);
|
|
||||||
file.delete();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static double calculateDiskSpeedMBps(int fileSizeMB, long startTime, long endTime) {
|
|
||||||
double elapsedSeconds = (endTime - startTime) / 1_000_000_000.0;
|
|
||||||
double writeSpeed = (fileSizeMB / elapsedSeconds);
|
|
||||||
return writeSpeed;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static double calculateAverage(double[] values) {
|
|
||||||
double sum = 0;
|
|
||||||
for (double value : values) {
|
|
||||||
sum += value;
|
|
||||||
}
|
|
||||||
return sum / values.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void WindowsDiskSpeedTest() {
|
|
||||||
try {
|
|
||||||
String command = "winsat disk";
|
|
||||||
Process process = Runtime.getRuntime().exec(command);
|
|
||||||
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
|
||||||
String line;
|
|
||||||
|
|
||||||
while ((line = reader.readLine()) != null) {
|
|
||||||
Iris.debug(line);
|
|
||||||
|
|
||||||
if (line.contains("Disk Sequential 64.0 Read")) {
|
|
||||||
avgReadSpeedMBps = extractSpeed(line);
|
|
||||||
} else if (line.contains("Disk Sequential 64.0 Write")) {
|
|
||||||
avgWriteSpeedMBps = extractSpeed(line);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
process.waitFor();
|
|
||||||
process.destroy();
|
|
||||||
|
|
||||||
Iris.debug("Sequential Read Speed: " + avgReadSpeedMBps + " MB/s");
|
|
||||||
Iris.debug("Sequential Write Speed: " + avgWriteSpeedMBps + " MB/s");
|
|
||||||
} catch (IOException | InterruptedException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static double extractSpeed(String line) {
|
|
||||||
String[] tokens = line.split("\\s+");
|
|
||||||
for (int i = 0; i < tokens.length; i++) {
|
|
||||||
if (tokens[i].endsWith("MB/s") && i > 0) {
|
|
||||||
try {
|
|
||||||
return Double.parseDouble(tokens[i - 1]);
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void WindowsCpuSpeedTest() {
|
|
||||||
try {
|
|
||||||
String command = "winsat cpuformal";
|
|
||||||
Process process = Runtime.getRuntime().exec(command);
|
|
||||||
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
|
||||||
String line;
|
|
||||||
|
|
||||||
while ((line = reader.readLine()) != null) {
|
|
||||||
Iris.debug(line);
|
|
||||||
|
|
||||||
if (line.contains("CPU AES256 Encryption")) {
|
|
||||||
WindowsCPUEncryption = extractCpuInfo(line);
|
|
||||||
}
|
|
||||||
if (line.contains("CPU LZW Compression")) {
|
|
||||||
WindowsCPUCompression = extractCpuInfo(line);
|
|
||||||
}
|
|
||||||
if (line.contains("CPU SHA1 Hash")) {
|
|
||||||
WindowsCPUCSHA1 = extractCpuInfo(line);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
process.waitFor();
|
|
||||||
process.destroy();
|
|
||||||
|
|
||||||
Iris.debug("Winsat Encryption: " + WindowsCPUEncryption + " MB/s");
|
|
||||||
} catch (IOException | InterruptedException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static double extractCpuInfo(String line) {
|
|
||||||
String[] tokens = line.split("\\s+");
|
|
||||||
for (int i = 0; i < tokens.length; i++) {
|
|
||||||
if (tokens[i].endsWith("MB/s") && i > 0) {
|
|
||||||
try {
|
|
||||||
return Double.parseDouble(tokens[i - 1]);
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -43,8 +43,9 @@ import java.io.File;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.function.IntSupplier;
|
||||||
import java.util.function.Supplier;
|
|
||||||
|
import static com.volmit.iris.util.misc.ServerProperties.BUKKIT_YML;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
@@ -52,7 +53,6 @@ import java.util.function.Supplier;
|
|||||||
@Data
|
@Data
|
||||||
@Accessors(fluent = true, chain = true)
|
@Accessors(fluent = true, chain = true)
|
||||||
public class IrisCreator {
|
public class IrisCreator {
|
||||||
private static final File BUKKIT_YML = new File("bukkit.yml");
|
|
||||||
/**
|
/**
|
||||||
* Specify an area to pregenerate during creation
|
* Specify an area to pregenerate during creation
|
||||||
*/
|
*/
|
||||||
@@ -127,8 +127,6 @@ public class IrisCreator {
|
|||||||
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;
|
|
||||||
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<>();
|
||||||
done.set(false);
|
done.set(false);
|
||||||
@@ -138,30 +136,29 @@ public class IrisCreator {
|
|||||||
.seed(seed)
|
.seed(seed)
|
||||||
.studio(studio)
|
.studio(studio)
|
||||||
.create();
|
.create();
|
||||||
ServerConfigurator.installDataPacks(false);
|
if (ServerConfigurator.installDataPacks(true)) {
|
||||||
|
throw new IrisException("Datapacks were missing!");
|
||||||
|
}
|
||||||
|
|
||||||
access = (PlatformChunkGenerator) wc.generator();
|
PlatformChunkGenerator access = (PlatformChunkGenerator) wc.generator();
|
||||||
PlatformChunkGenerator finalAccess1 = access;
|
if (access == null) throw new IrisException("Access is null. Something bad happened.");
|
||||||
|
|
||||||
J.a(() ->
|
J.a(() -> {
|
||||||
{
|
IntSupplier g = () -> {
|
||||||
Supplier<Integer> g = () -> {
|
if (access.getEngine() == null) {
|
||||||
if (finalAccess1 == null || finalAccess1.getEngine() == null) {
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return finalAccess1.getEngine().getGenerated();
|
return access.getEngine().getGenerated();
|
||||||
};
|
};
|
||||||
if(!benchmark) {
|
if(!benchmark) {
|
||||||
if (finalAccess1 == null) return;
|
int req = access.getSpawnChunks().join();
|
||||||
int req = finalAccess1.getSpawnChunks().join();
|
for (int c = 0; c < req && !done.get(); c = g.getAsInt()) {
|
||||||
|
double v = (double) c / req;
|
||||||
while (g.get() < req) {
|
|
||||||
double v = (double) g.get() / (double) req;
|
|
||||||
if (sender.isPlayer()) {
|
if (sender.isPlayer()) {
|
||||||
sender.sendProgress(v, "Generating");
|
sender.sendProgress(v, "Generating");
|
||||||
J.sleep(16);
|
J.sleep(16);
|
||||||
} else {
|
} else {
|
||||||
sender.sendMessage(C.WHITE + "Generating " + Form.pc(v) + ((C.GRAY + " (" + (req - g.get()) + " Left)")));
|
sender.sendMessage(C.WHITE + "Generating " + Form.pc(v) + ((C.GRAY + " (" + (req - c) + " Left)")));
|
||||||
J.sleep(1000);
|
J.sleep(1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -169,38 +166,34 @@ public class IrisCreator {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
World world;
|
||||||
try {
|
try {
|
||||||
J.sfut(() -> {
|
world = J.sfut(() -> INMS.get().createWorld(wc)).get();
|
||||||
world.set(INMS.get().createWorld(wc));
|
|
||||||
}).get();
|
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
e.printStackTrace();
|
done.set(true);
|
||||||
}
|
throw new IrisException("Failed to create world!", e);
|
||||||
|
|
||||||
if (access == null) {
|
|
||||||
throw new IrisException("Access is null. Something bad happened.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
done.set(true);
|
done.set(true);
|
||||||
|
|
||||||
if (sender.isPlayer() && !benchmark) {
|
if (sender.isPlayer() && !benchmark) {
|
||||||
J.s(() -> {
|
J.s(() -> sender.player().teleport(new Location(world, 0, world.getHighestBlockYAt(0, 0) + 1, 0)));
|
||||||
sender.player().teleport(new Location(world.get(), 0, world.get().getHighestBlockYAt(0, 0), 0));
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (studio || benchmark) {
|
if (studio || benchmark) {
|
||||||
J.s(() -> {
|
J.s(() -> {
|
||||||
Iris.linkMultiverseCore.removeFromConfig(world.get());
|
Iris.linkMultiverseCore.removeFromConfig(world);
|
||||||
|
|
||||||
if (IrisSettings.get().getStudio().isDisableTimeAndWeather()) {
|
if (IrisSettings.get().getStudio().isDisableTimeAndWeather()) {
|
||||||
world.get().setGameRule(GameRule.DO_WEATHER_CYCLE, false);
|
world.setGameRule(GameRule.DO_WEATHER_CYCLE, false);
|
||||||
world.get().setGameRule(GameRule.DO_DAYLIGHT_CYCLE, false);
|
world.setGameRule(GameRule.DO_DAYLIGHT_CYCLE, false);
|
||||||
world.get().setTime(6000);
|
world.setTime(6000);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else
|
} else {
|
||||||
addToBukkitYml();
|
addToBukkitYml();
|
||||||
|
J.s(() -> Iris.linkMultiverseCore.updateWorld(world, dimension));
|
||||||
|
}
|
||||||
|
|
||||||
if (pregen != null) {
|
if (pregen != null) {
|
||||||
CompletableFuture<Boolean> ff = new CompletableFuture<>();
|
CompletableFuture<Boolean> ff = new CompletableFuture<>();
|
||||||
@@ -230,7 +223,7 @@ public class IrisCreator {
|
|||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return world.get();
|
return world;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addToBukkitYml() {
|
private void addToBukkitYml() {
|
||||||
|
|||||||
@@ -9,51 +9,43 @@ import com.volmit.iris.util.collection.KList;
|
|||||||
import com.volmit.iris.util.collection.KMap;
|
import com.volmit.iris.util.collection.KMap;
|
||||||
import com.volmit.iris.util.exceptions.IrisException;
|
import com.volmit.iris.util.exceptions.IrisException;
|
||||||
import com.volmit.iris.util.format.Form;
|
import com.volmit.iris.util.format.Form;
|
||||||
|
import com.volmit.iris.util.io.IO;
|
||||||
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.Getter;
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileWriter;
|
import java.io.FileWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.FileVisitResult;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.nio.file.SimpleFileVisitor;
|
|
||||||
import java.nio.file.attribute.BasicFileAttributes;
|
|
||||||
import java.time.Clock;
|
import java.time.Clock;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
|
|
||||||
public class IrisPackBenchmarking {
|
public class IrisPackBenchmarking {
|
||||||
@Getter
|
private static final ThreadLocal<IrisPackBenchmarking> instance = new ThreadLocal<>();
|
||||||
public static IrisPackBenchmarking instance;
|
|
||||||
public static boolean benchmarkInProgress = false;
|
|
||||||
private final PrecisionStopwatch stopwatch = new PrecisionStopwatch();
|
private final PrecisionStopwatch stopwatch = new PrecisionStopwatch();
|
||||||
private final IrisDimension dimension;
|
private final IrisDimension dimension;
|
||||||
private final int radius;
|
private final int radius;
|
||||||
private final boolean gui;
|
private final boolean gui;
|
||||||
|
|
||||||
public IrisPackBenchmarking(IrisDimension dimension, int radius, boolean gui) {
|
public IrisPackBenchmarking(IrisDimension dimension, int radius, boolean gui) {
|
||||||
instance = this;
|
|
||||||
this.dimension = dimension;
|
this.dimension = dimension;
|
||||||
this.radius = radius;
|
this.radius = radius;
|
||||||
this.gui = gui;
|
this.gui = gui;
|
||||||
runBenchmark();
|
runBenchmark();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static IrisPackBenchmarking getInstance() {
|
||||||
|
return instance.get();
|
||||||
|
}
|
||||||
|
|
||||||
private void runBenchmark() {
|
private void runBenchmark() {
|
||||||
Thread.ofVirtual()
|
Thread.ofVirtual()
|
||||||
.name("PackBenchmarking")
|
.name("PackBenchmarking")
|
||||||
.start(() -> {
|
.start(() -> {
|
||||||
Iris.info("Setting up benchmark environment ");
|
Iris.info("Setting up benchmark environment ");
|
||||||
benchmarkInProgress = true;
|
IO.delete(new File(Bukkit.getWorldContainer(), "benchmark"));
|
||||||
File file = new File("benchmark");
|
|
||||||
if (file.exists()) {
|
|
||||||
deleteDirectory(file.toPath());
|
|
||||||
}
|
|
||||||
createBenchmark();
|
createBenchmark();
|
||||||
while (!IrisToolbelt.isIrisWorld(Bukkit.getWorld("benchmark"))) {
|
while (!IrisToolbelt.isIrisWorld(Bukkit.getWorld("benchmark"))) {
|
||||||
J.sleep(1000);
|
J.sleep(1000);
|
||||||
@@ -66,13 +58,9 @@ public class IrisPackBenchmarking {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getBenchmarkInProgress() {
|
|
||||||
return benchmarkInProgress;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void finishedBenchmark(KList<Integer> cps) {
|
public void finishedBenchmark(KList<Integer> cps) {
|
||||||
try {
|
try {
|
||||||
String time = Form.duration(stopwatch.getMillis());
|
String time = Form.duration((long) stopwatch.getMilliseconds());
|
||||||
Engine engine = IrisToolbelt.access(Bukkit.getWorld("benchmark")).getEngine();
|
Engine engine = IrisToolbelt.access(Bukkit.getWorld("benchmark")).getEngine();
|
||||||
Iris.info("-----------------");
|
Iris.info("-----------------");
|
||||||
Iris.info("Results:");
|
Iris.info("Results:");
|
||||||
@@ -83,11 +71,7 @@ public class IrisPackBenchmarking {
|
|||||||
Iris.info(" - Lowest CPS: " + findLowest(cps));
|
Iris.info(" - Lowest CPS: " + findLowest(cps));
|
||||||
Iris.info("-----------------");
|
Iris.info("-----------------");
|
||||||
Iris.info("Creating a report..");
|
Iris.info("Creating a report..");
|
||||||
File profilers = new File("plugins" + File.separator + "Iris" + File.separator + "packbenchmarks");
|
File results = Iris.instance.getDataFile("packbenchmarks", dimension.getName() + " " + LocalDateTime.now(Clock.systemDefaultZone()).toString().replace(':', '-') + ".txt");
|
||||||
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();
|
KMap<String, Double> metrics = engine.getMetrics().pull();
|
||||||
try (FileWriter writer = new FileWriter(results)) {
|
try (FileWriter writer = new FileWriter(results)) {
|
||||||
writer.write("-----------------\n");
|
writer.write("-----------------\n");
|
||||||
@@ -143,13 +127,18 @@ public class IrisPackBenchmarking {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void startBenchmark() {
|
private void startBenchmark() {
|
||||||
IrisToolbelt.pregenerate(PregenTask
|
try {
|
||||||
.builder()
|
instance.set(this);
|
||||||
.gui(gui)
|
IrisToolbelt.pregenerate(PregenTask
|
||||||
.radiusX(radius)
|
.builder()
|
||||||
.radiusZ(radius)
|
.gui(gui)
|
||||||
.build(), Bukkit.getWorld("benchmark")
|
.radiusX(radius)
|
||||||
);
|
.radiusZ(radius)
|
||||||
|
.build(), Bukkit.getWorld("benchmark")
|
||||||
|
);
|
||||||
|
} finally {
|
||||||
|
instance.remove();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private double calculateAverage(KList<Integer> list) {
|
private double calculateAverage(KList<Integer> list) {
|
||||||
@@ -178,26 +167,4 @@ public class IrisPackBenchmarking {
|
|||||||
private int findHighest(KList<Integer> list) {
|
private int findHighest(KList<Integer> list) {
|
||||||
return Collections.max(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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -24,6 +24,7 @@ import com.volmit.iris.core.gui.PregeneratorJob;
|
|||||||
import com.volmit.iris.core.loader.IrisData;
|
import com.volmit.iris.core.loader.IrisData;
|
||||||
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.pregenerator.methods.CachedPregenMethod;
|
||||||
import com.volmit.iris.core.pregenerator.methods.HybridPregenMethod;
|
import com.volmit.iris.core.pregenerator.methods.HybridPregenMethod;
|
||||||
import com.volmit.iris.core.service.StudioSVC;
|
import com.volmit.iris.core.service.StudioSVC;
|
||||||
import com.volmit.iris.engine.framework.Engine;
|
import com.volmit.iris.engine.framework.Engine;
|
||||||
@@ -141,7 +142,18 @@ public class IrisToolbelt {
|
|||||||
* @return the pregenerator job (already started)
|
* @return the pregenerator job (already started)
|
||||||
*/
|
*/
|
||||||
public static PregeneratorJob pregenerate(PregenTask task, PregeneratorMethod method, Engine engine) {
|
public static PregeneratorJob pregenerate(PregenTask task, PregeneratorMethod method, Engine engine) {
|
||||||
return new PregeneratorJob(task, method, engine);
|
return pregenerate(task, method, engine, IrisSettings.get().getPregen().useCacheByDefault);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start a pregenerator task
|
||||||
|
*
|
||||||
|
* @param task the scheduled task
|
||||||
|
* @param method the method to execute the task
|
||||||
|
* @return the pregenerator job (already started)
|
||||||
|
*/
|
||||||
|
public static PregeneratorJob pregenerate(PregenTask task, PregeneratorMethod method, Engine engine, boolean cached) {
|
||||||
|
return new PregeneratorJob(task, cached && engine != null ? new CachedPregenMethod(method, engine.getWorld().name()) : method, engine);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -21,13 +21,10 @@ 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.*;
|
import com.volmit.iris.engine.object.*;
|
||||||
import com.volmit.iris.engine.platform.BukkitChunkGenerator;
|
import com.volmit.iris.engine.platform.BukkitChunkGenerator;
|
||||||
import com.volmit.iris.util.reflect.WrappedField;
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.WorldCreator;
|
import org.bukkit.WorldCreator;
|
||||||
import org.bukkit.WorldType;
|
|
||||||
import org.bukkit.generator.ChunkGenerator;
|
import org.bukkit.generator.ChunkGenerator;
|
||||||
import sun.misc.Unsafe;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
@@ -83,7 +80,7 @@ public class IrisWorldCreator {
|
|||||||
|
|
||||||
|
|
||||||
return new WorldCreator(name)
|
return new WorldCreator(name)
|
||||||
.environment(findEnvironment())
|
.environment(w.environment())
|
||||||
.generateStructures(true)
|
.generateStructures(true)
|
||||||
.generator(g).seed(seed);
|
.generator(g).seed(seed);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,8 +25,6 @@ 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.*;
|
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.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.interpolation.IrisInterpolation.NoiseKey;
|
||||||
@@ -42,7 +40,8 @@ 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.UUID;
|
import java.io.File;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@EqualsAndHashCode(exclude = "data")
|
@EqualsAndHashCode(exclude = "data")
|
||||||
@@ -52,7 +51,7 @@ public class IrisComplex implements DataProvider {
|
|||||||
private RNG rng;
|
private RNG rng;
|
||||||
private double fluidHeight;
|
private double fluidHeight;
|
||||||
private IrisData data;
|
private IrisData data;
|
||||||
private KMap<IrisInterpolator, KSet<IrisGenerator>> generators;
|
private Map<IrisInterpolator, Set<IrisGenerator>> generators;
|
||||||
private ProceduralStream<IrisRegion> regionStream;
|
private ProceduralStream<IrisRegion> regionStream;
|
||||||
private ProceduralStream<Double> regionStyleStream;
|
private ProceduralStream<Double> regionStyleStream;
|
||||||
private ProceduralStream<Double> regionIdentityStream;
|
private ProceduralStream<Double> regionIdentityStream;
|
||||||
@@ -97,10 +96,10 @@ public class IrisComplex implements DataProvider {
|
|||||||
this.data = engine.getData();
|
this.data = engine.getData();
|
||||||
double height = engine.getMaxHeight();
|
double height = engine.getMaxHeight();
|
||||||
fluidHeight = engine.getDimension().getFluidHeight();
|
fluidHeight = engine.getDimension().getFluidHeight();
|
||||||
generators = new KMap<>();
|
generators = new HashMap<>();
|
||||||
focusBiome = engine.getFocus();
|
focusBiome = engine.getFocus();
|
||||||
focusRegion = engine.getFocusRegion();
|
focusRegion = engine.getFocusRegion();
|
||||||
KMap<InferredType, ProceduralStream<IrisBiome>> inferredStreams = new KMap<>();
|
Map<InferredType, ProceduralStream<IrisBiome>> inferredStreams = new HashMap<>();
|
||||||
|
|
||||||
if (focusBiome != null) {
|
if (focusBiome != null) {
|
||||||
focusBiome.setInferredType(InferredType.LAND);
|
focusBiome.setInferredType(InferredType.LAND);
|
||||||
@@ -108,10 +107,16 @@ public class IrisComplex implements DataProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//@builder
|
//@builder
|
||||||
engine.getDimension().getRegions().forEach((i) -> data.getRegionLoader().load(i)
|
if (focusRegion != null) {
|
||||||
.getAllBiomes(this).forEach((b) -> b
|
focusRegion.getAllBiomes(this).forEach(this::registerGenerators);
|
||||||
.getGenerators()
|
} else {
|
||||||
.forEach((c) -> registerGenerator(c.getCachedGenerator(this)))));
|
engine.getDimension()
|
||||||
|
.getRegions()
|
||||||
|
.forEach(i -> data.getRegionLoader().load(i)
|
||||||
|
.getAllBiomes(this)
|
||||||
|
.forEach(this::registerGenerators));
|
||||||
|
}
|
||||||
|
boolean legacy = engine.getDimension().isLegacyRarity();
|
||||||
overlayStream = ProceduralStream.ofDouble((x, z) -> 0.0D).waste("Overlay Stream");
|
overlayStream = ProceduralStream.ofDouble((x, z) -> 0.0D).waste("Overlay Stream");
|
||||||
engine.getDimension().getOverlayNoise().forEach(i -> overlayStream = overlayStream.add((x, z) -> i.get(rng, getData(), x, z)));
|
engine.getDimension().getOverlayNoise().forEach(i -> overlayStream = overlayStream.add((x, z) -> i.get(rng, getData(), x, z)));
|
||||||
rockStream = engine.getDimension().getRockPalette().getLayerGenerator(rng.nextParallelRNG(45), data).stream()
|
rockStream = engine.getDimension().getRockPalette().getLayerGenerator(rng.nextParallelRNG(45), data).stream()
|
||||||
@@ -125,7 +130,7 @@ public class IrisComplex implements DataProvider {
|
|||||||
ProceduralStream.of((x, z) -> focusRegion,
|
ProceduralStream.of((x, z) -> focusRegion,
|
||||||
Interpolated.of(a -> 0D, a -> focusRegion))
|
Interpolated.of(a -> 0D, a -> focusRegion))
|
||||||
: regionStyleStream
|
: regionStyleStream
|
||||||
.selectRarity(data.getRegionLoader().loadAll(engine.getDimension().getRegions()))
|
.selectRarity(data.getRegionLoader().loadAll(engine.getDimension().getRegions()), legacy)
|
||||||
.cache2D("regionStream", engine, cacheSize).waste("Region Stream");
|
.cache2D("regionStream", engine, cacheSize).waste("Region Stream");
|
||||||
regionIDStream = regionIdentityStream.convertCached((i) -> new UUID(Double.doubleToLongBits(i),
|
regionIDStream = regionIdentityStream.convertCached((i) -> new UUID(Double.doubleToLongBits(i),
|
||||||
String.valueOf(i * 38445).hashCode() * 3245556666L)).waste("Region ID Stream");
|
String.valueOf(i * 38445).hashCode() * 3245556666L)).waste("Region ID Stream");
|
||||||
@@ -134,7 +139,7 @@ public class IrisComplex implements DataProvider {
|
|||||||
-> 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(engine.getDimension().getBiomeZoom())
|
||||||
.zoom(r.getCaveBiomeZoom())
|
.zoom(r.getCaveBiomeZoom())
|
||||||
.selectRarity(data.getBiomeLoader().loadAll(r.getCaveBiomes()))
|
.selectRarity(data.getBiomeLoader().loadAll(r.getCaveBiomes()), legacy)
|
||||||
.onNull(emptyBiome)
|
.onNull(emptyBiome)
|
||||||
).convertAware2D(ProceduralStream::get).cache2D("caveBiomeStream", engine, cacheSize).waste("Cave Biome Stream");
|
).convertAware2D(ProceduralStream::get).cache2D("caveBiomeStream", engine, cacheSize).waste("Cave Biome Stream");
|
||||||
inferredStreams.put(InferredType.CAVE, caveBiomeStream);
|
inferredStreams.put(InferredType.CAVE, caveBiomeStream);
|
||||||
@@ -144,7 +149,7 @@ public class IrisComplex implements DataProvider {
|
|||||||
.zoom(engine.getDimension().getBiomeZoom())
|
.zoom(engine.getDimension().getBiomeZoom())
|
||||||
.zoom(engine.getDimension().getLandZoom())
|
.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)), legacy)
|
||||||
).convertAware2D(ProceduralStream::get)
|
).convertAware2D(ProceduralStream::get)
|
||||||
.cache2D("landBiomeStream", engine, cacheSize).waste("Land Biome Stream");
|
.cache2D("landBiomeStream", engine, cacheSize).waste("Land Biome Stream");
|
||||||
inferredStreams.put(InferredType.LAND, landBiomeStream);
|
inferredStreams.put(InferredType.LAND, landBiomeStream);
|
||||||
@@ -154,7 +159,7 @@ public class IrisComplex implements DataProvider {
|
|||||||
.zoom(engine.getDimension().getBiomeZoom())
|
.zoom(engine.getDimension().getBiomeZoom())
|
||||||
.zoom(engine.getDimension().getSeaZoom())
|
.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)), legacy)
|
||||||
).convertAware2D(ProceduralStream::get)
|
).convertAware2D(ProceduralStream::get)
|
||||||
.cache2D("seaBiomeStream", engine, cacheSize).waste("Sea Biome Stream");
|
.cache2D("seaBiomeStream", engine, cacheSize).waste("Sea Biome Stream");
|
||||||
inferredStreams.put(InferredType.SEA, seaBiomeStream);
|
inferredStreams.put(InferredType.SEA, seaBiomeStream);
|
||||||
@@ -163,7 +168,7 @@ public class IrisComplex implements DataProvider {
|
|||||||
-> 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(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)), legacy)
|
||||||
).convertAware2D(ProceduralStream::get).cache2D("shoreBiomeStream", engine, cacheSize).waste("Shore Biome Stream");
|
).convertAware2D(ProceduralStream::get).cache2D("shoreBiomeStream", engine, cacheSize).waste("Shore Biome Stream");
|
||||||
inferredStreams.put(InferredType.SHORE, shoreBiomeStream);
|
inferredStreams.put(InferredType.SHORE, shoreBiomeStream);
|
||||||
bridgeStream = focusBiome != null ? ProceduralStream.of((x, z) -> focusBiome.getInferredType(),
|
bridgeStream = focusBiome != null ? ProceduralStream.of((x, z) -> focusBiome.getInferredType(),
|
||||||
@@ -245,7 +250,15 @@ public class IrisComplex implements DataProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
String key = UUID.randomUUID().toString();
|
||||||
|
IrisRegion region = new IrisRegion();
|
||||||
|
region.getLandBiomes().add(focus.getLoadKey());
|
||||||
|
region.getSeaBiomes().add(focus.getLoadKey());
|
||||||
|
region.getShoreBiomes().add(focus.getLoadKey());
|
||||||
|
region.setLoadKey(key);
|
||||||
|
region.setLoader(data);
|
||||||
|
region.setLoadFile(new File(data.getDataFolder(), data.getRegionLoader().getFolderName() + "/" + key + ".json"));
|
||||||
|
return region;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IrisDecorator decorateFor(IrisBiome b, double x, double z, IrisDecorationPart part) {
|
private IrisDecorator decorateFor(IrisBiome b, double x, double z, IrisDecorationPart part) {
|
||||||
@@ -288,12 +301,12 @@ public class IrisComplex implements DataProvider {
|
|||||||
return biome;
|
return biome;
|
||||||
}
|
}
|
||||||
|
|
||||||
private double interpolateGenerators(Engine engine, IrisInterpolator interpolator, KSet<IrisGenerator> generators, double x, double z, long seed) {
|
private double interpolateGenerators(Engine engine, IrisInterpolator interpolator, Set<IrisGenerator> generators, double x, double z, long seed) {
|
||||||
if (generators.isEmpty()) {
|
if (generators.isEmpty()) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
KMap<NoiseKey, IrisBiome> cache = new KMap<>();
|
HashMap<NoiseKey, IrisBiome> cache = new HashMap<>(64);
|
||||||
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);
|
||||||
@@ -360,8 +373,12 @@ public class IrisComplex implements DataProvider {
|
|||||||
return Math.max(Math.min(getInterpolatedHeight(engine, x, z, seed) + fluidHeight + overlayStream.get(x, z), engine.getHeight()), 0);
|
return Math.max(Math.min(getInterpolatedHeight(engine, x, z, seed) + fluidHeight + overlayStream.get(x, z), engine.getHeight()), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void registerGenerators(IrisBiome biome) {
|
||||||
|
biome.getGenerators().forEach(c -> registerGenerator(c.getCachedGenerator(this)));
|
||||||
|
}
|
||||||
|
|
||||||
private void registerGenerator(IrisGenerator cachedGenerator) {
|
private void registerGenerator(IrisGenerator cachedGenerator) {
|
||||||
generators.computeIfAbsent(cachedGenerator.getInterpolator(), (k) -> new KSet<>()).add(cachedGenerator);
|
generators.computeIfAbsent(cachedGenerator.getInterpolator(), (k) -> new HashSet<>()).add(cachedGenerator);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IrisBiome implode(IrisBiome b, Double x, Double z) {
|
private IrisBiome implode(IrisBiome b, Double x, Double z) {
|
||||||
|
|||||||
@@ -28,12 +28,12 @@ import com.volmit.iris.core.loader.ResourceLoader;
|
|||||||
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.project.IrisProject;
|
import com.volmit.iris.core.project.IrisProject;
|
||||||
|
import com.volmit.iris.core.scripting.environment.EngineEnvironment;
|
||||||
import com.volmit.iris.core.service.PreservationSVC;
|
import com.volmit.iris.core.service.PreservationSVC;
|
||||||
import com.volmit.iris.engine.data.cache.AtomicCache;
|
import com.volmit.iris.engine.data.cache.AtomicCache;
|
||||||
import com.volmit.iris.engine.framework.*;
|
import com.volmit.iris.engine.framework.*;
|
||||||
import com.volmit.iris.engine.mantle.EngineMantle;
|
import com.volmit.iris.engine.mantle.EngineMantle;
|
||||||
import com.volmit.iris.engine.object.*;
|
import com.volmit.iris.engine.object.*;
|
||||||
import com.volmit.iris.engine.scripting.EngineExecutionEnvironment;
|
|
||||||
import com.volmit.iris.util.atomics.AtomicRollingSequence;
|
import com.volmit.iris.util.atomics.AtomicRollingSequence;
|
||||||
import com.volmit.iris.util.collection.KMap;
|
import com.volmit.iris.util.collection.KMap;
|
||||||
import com.volmit.iris.util.context.ChunkContext;
|
import com.volmit.iris.util.context.ChunkContext;
|
||||||
@@ -43,10 +43,11 @@ 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.hunk.Hunk;
|
import com.volmit.iris.util.hunk.Hunk;
|
||||||
import com.volmit.iris.util.io.IO;
|
import com.volmit.iris.util.io.IO;
|
||||||
import com.volmit.iris.util.mantle.MantleFlag;
|
import com.volmit.iris.util.mantle.flag.MantleFlag;
|
||||||
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.matter.MatterStructurePOI;
|
import com.volmit.iris.util.matter.MatterStructurePOI;
|
||||||
|
import com.volmit.iris.util.matter.slices.container.JigsawStructureContainer;
|
||||||
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;
|
||||||
@@ -93,10 +94,9 @@ public class IrisEngine implements Engine {
|
|||||||
private CompletableFuture<Long> hash32;
|
private CompletableFuture<Long> hash32;
|
||||||
private EngineMode mode;
|
private EngineMode mode;
|
||||||
private EngineEffects effects;
|
private EngineEffects effects;
|
||||||
private EngineExecutionEnvironment execution;
|
private EngineEnvironment execution;
|
||||||
private EngineWorldManager worldManager;
|
private EngineWorldManager worldManager;
|
||||||
private volatile int parallelism;
|
private volatile int parallelism;
|
||||||
private volatile int minHeight;
|
|
||||||
private boolean failing;
|
private boolean failing;
|
||||||
private boolean closed;
|
private boolean closed;
|
||||||
private int cacheId;
|
private int cacheId;
|
||||||
@@ -129,7 +129,6 @@ public class IrisEngine implements Engine {
|
|||||||
getData().setEngine(this);
|
getData().setEngine(this);
|
||||||
getData().loadPrefetch(this);
|
getData().loadPrefetch(this);
|
||||||
Iris.info("Initializing Engine: " + target.getWorld().name() + "/" + target.getDimension().getLoadKey() + " (" + target.getDimension().getDimensionHeight() + " height) Seed: " + getSeedManager().getSeed());
|
Iris.info("Initializing Engine: " + target.getWorld().name() + "/" + target.getDimension().getLoadKey() + " (" + target.getDimension().getDimensionHeight() + " height) Seed: " + getSeedManager().getSeed());
|
||||||
minHeight = 0;
|
|
||||||
failing = false;
|
failing = false;
|
||||||
closed = false;
|
closed = false;
|
||||||
art = J.ar(this::tickRandomPlayer, 0);
|
art = J.ar(this::tickRandomPlayer, 0);
|
||||||
@@ -171,16 +170,21 @@ public class IrisEngine implements Engine {
|
|||||||
cacheId = RNG.r.nextInt();
|
cacheId = RNG.r.nextInt();
|
||||||
worldManager = new IrisWorldManager(this);
|
worldManager = new IrisWorldManager(this);
|
||||||
complex = new IrisComplex(this);
|
complex = new IrisComplex(this);
|
||||||
execution = new IrisExecutionEnvironment(this);
|
execution = EngineEnvironment.create(this);
|
||||||
effects = new IrisEngineEffects(this);
|
effects = new IrisEngineEffects(this);
|
||||||
hash32 = new CompletableFuture<>();
|
hash32 = new CompletableFuture<>();
|
||||||
|
mantle.hotload();
|
||||||
setupMode();
|
setupMode();
|
||||||
|
getDimension().getEngineScripts().forEach(execution::execute);
|
||||||
J.a(this::computeBiomeMaxes);
|
J.a(this::computeBiomeMaxes);
|
||||||
J.a(() -> {
|
J.a(() -> {
|
||||||
File[] roots = getData().getLoaders()
|
File[] roots = getData().getLoaders()
|
||||||
.values()
|
.values()
|
||||||
.stream()
|
.stream()
|
||||||
.map(ResourceLoader::getRoot)
|
.map(ResourceLoader::getFolderName)
|
||||||
|
.map(n -> new File(getData().getDataFolder(), n))
|
||||||
|
.filter(File::exists)
|
||||||
|
.filter(File::isDirectory)
|
||||||
.toArray(File[]::new);
|
.toArray(File[]::new);
|
||||||
hash32.complete(IO.hashRecursive(roots));
|
hash32.complete(IO.hashRecursive(roots));
|
||||||
});
|
});
|
||||||
@@ -197,7 +201,7 @@ public class IrisEngine implements Engine {
|
|||||||
mode.close();
|
mode.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
mode = getDimension().getMode().getType().create(this);
|
mode = getDimension().getMode().create(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -222,6 +226,12 @@ public class IrisEngine implements Engine {
|
|||||||
return getMantle().getJigsawComponent().guess(x, z);
|
return getMantle().getJigsawComponent().guess(x, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IrisJigsawStructure getStructureAt(int x, int y, int z) {
|
||||||
|
var container = getMantle().getMantle().get(x, y, z, JigsawStructureContainer.class);
|
||||||
|
return container == null ? null : container.load(getData());
|
||||||
|
}
|
||||||
|
|
||||||
private void warmupChunk(int x, int z) {
|
private void warmupChunk(int x, int z) {
|
||||||
for (int i = 0; i < 16; i++) {
|
for (int i = 0; i < 16; i++) {
|
||||||
for (int j = 0; j < 16; j++) {
|
for (int j = 0; j < 16; j++) {
|
||||||
@@ -472,7 +482,7 @@ public class IrisEngine implements Engine {
|
|||||||
getEngineData().getStatistics().generatedChunk();
|
getEngineData().getStatistics().generatedChunk();
|
||||||
try {
|
try {
|
||||||
PrecisionStopwatch p = PrecisionStopwatch.start();
|
PrecisionStopwatch p = PrecisionStopwatch.start();
|
||||||
Hunk<BlockData> blocks = vblocks.listen((xx, y, zz, t) -> catchBlockUpdates(x + xx, y + getMinHeight(), z + zz, t));
|
Hunk<BlockData> blocks = vblocks.listen((xx, y, zz, t) -> catchBlockUpdates(x + xx, y, z + zz, t));
|
||||||
|
|
||||||
if (getDimension().isDebugChunkCrossSections() && ((x >> 4) % getDimension().getDebugCrossSectionsMod() == 0 || (z >> 4) % getDimension().getDebugCrossSectionsMod() == 0)) {
|
if (getDimension().isDebugChunkCrossSections() && ((x >> 4) % getDimension().getDebugCrossSectionsMod() == 0 || (z >> 4) % getDimension().getDebugCrossSectionsMod() == 0)) {
|
||||||
for (int i = 0; i < 16; i++) {
|
for (int i = 0; i < 16; i++) {
|
||||||
|
|||||||
@@ -30,10 +30,14 @@ import com.volmit.iris.engine.mantle.components.MantleObjectComponent;
|
|||||||
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.mantle.Mantle;
|
import com.volmit.iris.util.mantle.Mantle;
|
||||||
|
import com.volmit.iris.util.mantle.flag.MantleFlag;
|
||||||
import lombok.*;
|
import lombok.*;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.stream.Collectors;
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@EqualsAndHashCode(exclude = "engine")
|
@EqualsAndHashCode(exclude = "engine")
|
||||||
@@ -43,8 +47,9 @@ public class IrisEngineMantle implements EngineMantle {
|
|||||||
private final Mantle mantle;
|
private final Mantle mantle;
|
||||||
@Getter(AccessLevel.NONE)
|
@Getter(AccessLevel.NONE)
|
||||||
private final KMap<Integer, KList<MantleComponent>> components;
|
private final KMap<Integer, KList<MantleComponent>> components;
|
||||||
private final AtomicCache<KList<Pair<KList<MantleComponent>, Integer>>> componentsCache = new AtomicCache<>();
|
private final KMap<MantleFlag, MantleComponent> registeredComponents = new KMap<>();
|
||||||
private final AtomicCache<Integer> radCache = new AtomicCache<>();
|
private final AtomicCache<List<Pair<List<MantleComponent>, Integer>>> componentsCache = new AtomicCache<>();
|
||||||
|
private final AtomicCache<Set<MantleFlag>> disabledFlags = new AtomicCache<>();
|
||||||
private final MantleObjectComponent object;
|
private final MantleObjectComponent object;
|
||||||
private final MantleJigsawComponent jigsaw;
|
private final MantleJigsawComponent jigsaw;
|
||||||
|
|
||||||
@@ -73,7 +78,7 @@ public class IrisEngineMantle implements EngineMantle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public KList<Pair<KList<MantleComponent>, Integer>> getComponents() {
|
public List<Pair<List<MantleComponent>, Integer>> getComponents() {
|
||||||
return componentsCache.aquire(() -> {
|
return componentsCache.aquire(() -> {
|
||||||
var list = components.keySet()
|
var list = components.keySet()
|
||||||
.stream()
|
.stream()
|
||||||
@@ -84,10 +89,9 @@ public class IrisEngineMantle implements EngineMantle {
|
|||||||
.mapToInt(MantleComponent::getRadius)
|
.mapToInt(MantleComponent::getRadius)
|
||||||
.max()
|
.max()
|
||||||
.orElse(0);
|
.orElse(0);
|
||||||
return new Pair<>(components, radius);
|
return new Pair<>(List.copyOf(components), radius);
|
||||||
})
|
})
|
||||||
.collect(Collectors.toCollection(KList::new));
|
.toList();
|
||||||
|
|
||||||
|
|
||||||
int radius = 0;
|
int radius = 0;
|
||||||
for (var pair : list.reversed()) {
|
for (var pair : list.reversed()) {
|
||||||
@@ -100,9 +104,36 @@ public class IrisEngineMantle implements EngineMantle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void registerComponent(MantleComponent c) {
|
public Map<MantleFlag, MantleComponent> getRegisteredComponents() {
|
||||||
|
return Collections.unmodifiableMap(registeredComponents);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean registerComponent(MantleComponent c) {
|
||||||
|
if (registeredComponents.putIfAbsent(c.getFlag(), c) != null) return false;
|
||||||
|
c.setEnabled(!getDisabledFlags().contains(c.getFlag()));
|
||||||
components.computeIfAbsent(c.getPriority(), k -> new KList<>()).add(c);
|
components.computeIfAbsent(c.getPriority(), k -> new KList<>()).add(c);
|
||||||
componentsCache.reset();
|
componentsCache.reset();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public KList<MantleFlag> getComponentFlags() {
|
||||||
|
return new KList<>(registeredComponents.keySet());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void hotload() {
|
||||||
|
disabledFlags.reset();
|
||||||
|
for (var component : registeredComponents.values()) {
|
||||||
|
component.hotload();
|
||||||
|
component.setEnabled(!getDisabledFlags().contains(component.getFlag()));
|
||||||
|
}
|
||||||
|
componentsCache.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Set<MantleFlag> getDisabledFlags() {
|
||||||
|
return disabledFlags.aquire(() -> Set.copyOf(getDimension().getDisabledComponents()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -1,84 +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.engine;
|
|
||||||
|
|
||||||
import com.volmit.iris.Iris;
|
|
||||||
import com.volmit.iris.engine.framework.Engine;
|
|
||||||
import com.volmit.iris.engine.object.IrisScript;
|
|
||||||
import com.volmit.iris.engine.scripting.EngineExecutionEnvironment;
|
|
||||||
import com.volmit.iris.engine.scripting.IrisScriptingAPI;
|
|
||||||
import com.volmit.iris.util.format.C;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
import lombok.ToString;
|
|
||||||
import org.apache.bsf.BSFException;
|
|
||||||
import org.apache.bsf.BSFManager;
|
|
||||||
import org.apache.bsf.engines.javascript.JavaScriptEngine;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
@EqualsAndHashCode(exclude = "engine")
|
|
||||||
@ToString(exclude = "engine")
|
|
||||||
public class IrisExecutionEnvironment implements EngineExecutionEnvironment {
|
|
||||||
private final BSFManager manager;
|
|
||||||
private final Engine engine;
|
|
||||||
private final IrisScriptingAPI api;
|
|
||||||
private JavaScriptEngine javaScriptEngine;
|
|
||||||
|
|
||||||
public IrisExecutionEnvironment(Engine engine) {
|
|
||||||
this.engine = engine;
|
|
||||||
this.api = new IrisScriptingAPI(engine);
|
|
||||||
this.manager = new BSFManager();
|
|
||||||
this.manager.setClassLoader(Iris.class.getClassLoader());
|
|
||||||
try {
|
|
||||||
this.manager.declareBean("Iris", api, api.getClass());
|
|
||||||
this.javaScriptEngine = (JavaScriptEngine) this.manager.loadScriptingEngine("javascript");
|
|
||||||
} catch (Throwable e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IrisScriptingAPI getAPI() {
|
|
||||||
return api;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void execute(String script) {
|
|
||||||
execute(getEngine().getData().getScriptLoader().load(script));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void execute(IrisScript script) {
|
|
||||||
Iris.debug("Execute Script (void) " + C.DARK_GREEN + script.getLoadKey());
|
|
||||||
try {
|
|
||||||
javaScriptEngine.exec("", 0, 0, script);
|
|
||||||
} catch (BSFException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object evaluate(String script) {
|
|
||||||
Iris.debug("Execute Script (for result) " + C.DARK_GREEN + script);
|
|
||||||
try {
|
|
||||||
return javaScriptEngine.eval("", 0, 0, getEngine().getData().getScriptLoader().load(script));
|
|
||||||
} catch (BSFException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -20,7 +20,9 @@ package com.volmit.iris.engine;
|
|||||||
|
|
||||||
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.link.Identifier;
|
||||||
import com.volmit.iris.core.loader.IrisData;
|
import com.volmit.iris.core.loader.IrisData;
|
||||||
|
import com.volmit.iris.core.service.ExternalDataSVC;
|
||||||
import com.volmit.iris.engine.framework.Engine;
|
import com.volmit.iris.engine.framework.Engine;
|
||||||
import com.volmit.iris.engine.framework.EngineAssignedWorldManager;
|
import com.volmit.iris.engine.framework.EngineAssignedWorldManager;
|
||||||
import com.volmit.iris.engine.object.*;
|
import com.volmit.iris.engine.object.*;
|
||||||
@@ -29,7 +31,7 @@ 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.format.Form;
|
import com.volmit.iris.util.format.Form;
|
||||||
import com.volmit.iris.util.mantle.Mantle;
|
import com.volmit.iris.util.mantle.Mantle;
|
||||||
import com.volmit.iris.util.mantle.MantleFlag;
|
import com.volmit.iris.util.mantle.flag.MantleFlag;
|
||||||
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;
|
||||||
import com.volmit.iris.util.math.RNG;
|
import com.volmit.iris.util.math.RNG;
|
||||||
@@ -55,6 +57,7 @@ import org.bukkit.event.block.BlockPlaceEvent;
|
|||||||
import org.bukkit.event.player.PlayerTeleportEvent;
|
import org.bukkit.event.player.PlayerTeleportEvent;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@@ -367,7 +370,7 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
|
|||||||
|
|
||||||
private void spawn(IrisPosition pos, IrisEntitySpawn i) {
|
private void spawn(IrisPosition pos, IrisEntitySpawn i) {
|
||||||
IrisSpawner ref = i.getReferenceSpawner();
|
IrisSpawner ref = i.getReferenceSpawner();
|
||||||
if (!ref.canSpawn(getEngine(), pos.getX() >> 4, pos.getZ()))
|
if (!ref.canSpawn(getEngine(), pos.getX() >> 4, pos.getZ() >> 4))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int s = i.spawn(getEngine(), pos, RNG.r);
|
int s = i.spawn(getEngine(), pos, RNG.r);
|
||||||
@@ -422,12 +425,36 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
energy += 0.3;
|
var ref = new WeakReference<>(e.getWorld());
|
||||||
fixEnergy();
|
int cX = e.getX(), cZ = e.getZ();
|
||||||
getEngine().cleanupMantleChunk(e.getX(), e.getZ());
|
J.s(() -> {
|
||||||
|
World world = ref.get();
|
||||||
|
if (world == null || !world.isChunkLoaded(cX, cZ))
|
||||||
|
return;
|
||||||
|
energy += 0.3;
|
||||||
|
fixEnergy();
|
||||||
|
getEngine().cleanupMantleChunk(cX, cZ);
|
||||||
|
}, IrisSettings.get().getPerformance().mantleCleanupDelay);
|
||||||
|
|
||||||
if (generated) {
|
if (generated) {
|
||||||
//INMS.get().injectBiomesFromMantle(e, getMantle());
|
//INMS.get().injectBiomesFromMantle(e, getMantle());
|
||||||
|
|
||||||
|
if (!IrisSettings.get().getGenerator().earlyCustomBlocks) return;
|
||||||
|
e.addPluginChunkTicket(Iris.instance);
|
||||||
|
J.s(() -> {
|
||||||
|
var chunk = getMantle().getChunk(e).use();
|
||||||
|
int minY = getTarget().getWorld().minHeight();
|
||||||
|
try {
|
||||||
|
chunk.raiseFlagUnchecked(MantleFlag.CUSTOM, () -> {
|
||||||
|
chunk.iterate(Identifier.class, (x, y, z, v) -> {
|
||||||
|
Iris.service(ExternalDataSVC.class).processUpdate(getEngine(), e.getBlock(x & 15, y + minY, z & 15), v);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
chunk.release();
|
||||||
|
e.removePluginChunkTicket(Iris.instance);
|
||||||
|
}
|
||||||
|
}, RNG.r.i(20, 60));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -106,6 +106,14 @@ public class IrisTerrainNormalActuator extends EngineAssignedActuator<BlockData>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BlockData ore = biome.generateOres(realX, i, realZ, rng, getData(), true);
|
||||||
|
ore = ore == null ? region.generateOres(realX, i, realZ, rng, getData(), true) : ore;
|
||||||
|
ore = ore == null ? getDimension().generateOres(realX, i, realZ, rng, getData(), true) : ore;
|
||||||
|
if (ore != null) {
|
||||||
|
h.set(xf, i, zf, ore);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (i > he && i <= hf) {
|
if (i > he && i <= hf) {
|
||||||
fdepth = hf - i;
|
fdepth = hf - i;
|
||||||
|
|
||||||
@@ -138,9 +146,9 @@ public class IrisTerrainNormalActuator extends EngineAssignedActuator<BlockData>
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
BlockData ore = biome.generateOres(realX, i, realZ, rng, getData());
|
ore = biome.generateOres(realX, i, realZ, rng, getData(), false);
|
||||||
ore = ore == null ? region.generateOres(realX, i, realZ, rng, getData()) : ore;
|
ore = ore == null ? region.generateOres(realX, i, realZ, rng, getData(), false) : ore;
|
||||||
ore = ore == null ? getDimension().generateOres(realX, i, realZ, rng, getData()) : ore;
|
ore = ore == null ? getDimension().generateOres(realX, i, realZ, rng, getData(), false) : ore;
|
||||||
|
|
||||||
if (ore != null) {
|
if (ore != null) {
|
||||||
h.set(xf, i, zf, ore);
|
h.set(xf, i, zf, ore);
|
||||||
|
|||||||
@@ -29,13 +29,13 @@ 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.pregenerator.ChunkUpdater;
|
||||||
|
import com.volmit.iris.core.scripting.environment.EngineEnvironment;
|
||||||
import com.volmit.iris.core.service.ExternalDataSVC;
|
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;
|
||||||
import com.volmit.iris.engine.mantle.EngineMantle;
|
import com.volmit.iris.engine.mantle.EngineMantle;
|
||||||
import com.volmit.iris.engine.object.*;
|
import com.volmit.iris.engine.object.*;
|
||||||
import com.volmit.iris.engine.scripting.EngineExecutionEnvironment;
|
|
||||||
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.context.ChunkContext;
|
import com.volmit.iris.util.context.ChunkContext;
|
||||||
@@ -48,7 +48,7 @@ import com.volmit.iris.util.documentation.ChunkCoordinates;
|
|||||||
import com.volmit.iris.util.format.C;
|
import com.volmit.iris.util.format.C;
|
||||||
import com.volmit.iris.util.function.Function2;
|
import com.volmit.iris.util.function.Function2;
|
||||||
import com.volmit.iris.util.hunk.Hunk;
|
import com.volmit.iris.util.hunk.Hunk;
|
||||||
import com.volmit.iris.util.mantle.MantleFlag;
|
import com.volmit.iris.util.mantle.flag.MantleFlag;
|
||||||
import com.volmit.iris.util.math.BlockPosition;
|
import com.volmit.iris.util.math.BlockPosition;
|
||||||
import com.volmit.iris.util.math.M;
|
import com.volmit.iris.util.math.M;
|
||||||
import com.volmit.iris.util.math.Position2;
|
import com.volmit.iris.util.math.Position2;
|
||||||
@@ -75,9 +75,9 @@ import org.bukkit.entity.Player;
|
|||||||
import org.bukkit.inventory.Inventory;
|
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 org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
@@ -110,7 +110,7 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
|
|||||||
|
|
||||||
IrisContext getContext();
|
IrisContext getContext();
|
||||||
|
|
||||||
EngineExecutionEnvironment getExecution();
|
EngineEnvironment getExecution();
|
||||||
|
|
||||||
double getMaxBiomeObjectDensity();
|
double getMaxBiomeObjectDensity();
|
||||||
|
|
||||||
@@ -140,7 +140,9 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
|
|||||||
return getTarget().getWorld().minHeight();
|
return getTarget().getWorld().minHeight();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setMinHeight(int min);
|
default void setMinHeight(int min) {
|
||||||
|
getTarget().getWorld().minHeight(min);
|
||||||
|
}
|
||||||
|
|
||||||
@BlockCoordinates
|
@BlockCoordinates
|
||||||
default void generate(int x, int z, TerrainChunk tc, boolean multicore) throws WrongEngineBroException {
|
default void generate(int x, int z, TerrainChunk tc, boolean multicore) throws WrongEngineBroException {
|
||||||
@@ -229,6 +231,9 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
|
|||||||
@ChunkCoordinates
|
@ChunkCoordinates
|
||||||
IrisJigsawStructure getStructureAt(int x, int z);
|
IrisJigsawStructure getStructureAt(int x, int z);
|
||||||
|
|
||||||
|
@BlockCoordinates
|
||||||
|
IrisJigsawStructure getStructureAt(int x, int y, int z);
|
||||||
|
|
||||||
@BlockCoordinates
|
@BlockCoordinates
|
||||||
default IrisBiome getCaveBiome(int x, int z) {
|
default IrisBiome getCaveBiome(int x, int z) {
|
||||||
return getComplex().getCaveBiomeStream().get(x, z);
|
return getComplex().getCaveBiomeStream().get(x, z);
|
||||||
@@ -260,7 +265,7 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
|
|||||||
getMantle().updateBlock(x, y, z);
|
getMantle().updateBlock(x, y, z);
|
||||||
}
|
}
|
||||||
if (data instanceof IrisCustomData) {
|
if (data instanceof IrisCustomData) {
|
||||||
getMantle().getMantle().flag(x >> 4, z >> 4, MantleFlag.CUSTOM, true);
|
getMantle().getMantle().flag(x >> 4, z >> 4, MantleFlag.CUSTOM_ACTIVE, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -287,105 +292,92 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var chunk = mantle.getChunk(c);
|
var chunk = mantle.getChunk(c).use();
|
||||||
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 {
|
try {
|
||||||
semaphore.acquire(3);
|
Semaphore semaphore = new Semaphore(3);
|
||||||
} catch (InterruptedException ignored) {}
|
chunk.raiseFlag(MantleFlag.ETCHED, () -> {
|
||||||
|
chunk.raiseFlagUnchecked(MantleFlag.TILE, run(semaphore, () -> {
|
||||||
|
chunk.iterate(TileWrapper.class, (x, y, z, v) -> {
|
||||||
|
Block block = c.getBlock(x & 15, y + getWorld().minHeight(), z & 15);
|
||||||
|
if (!TileData.setTileState(block, v.getData()))
|
||||||
|
Iris.warn("Failed to set tile entity data at [%d %d %d | %s] for tile %s!", block.getX(), block.getY(), block.getZ(), block.getType().getKey(), v.getData().getMaterial().getKey());
|
||||||
|
});
|
||||||
|
}, 0));
|
||||||
|
chunk.raiseFlagUnchecked(MantleFlag.CUSTOM, run(semaphore, () -> {
|
||||||
|
chunk.iterate(Identifier.class, (x, y, z, v) -> {
|
||||||
|
Iris.service(ExternalDataSVC.class).processUpdate(this, c.getBlock(x & 15, y + getWorld().minHeight(), z & 15), v);
|
||||||
|
});
|
||||||
|
}, 0));
|
||||||
|
|
||||||
|
chunk.raiseFlagUnchecked(MantleFlag.UPDATE, run(semaphore, () -> {
|
||||||
|
PrecisionStopwatch p = PrecisionStopwatch.start();
|
||||||
|
int[][] grid = new int[16][16];
|
||||||
|
for (int x = 0; x < 16; x++) {
|
||||||
|
for (int z = 0; z < 16; z++) {
|
||||||
|
grid[x][z] = Integer.MIN_VALUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RNG rng = new RNG(Cache.key(c.getX(), c.getZ()));
|
||||||
|
chunk.iterate(MatterCavern.class, (x, yf, z, v) -> {
|
||||||
|
int y = yf + getWorld().minHeight();
|
||||||
|
x &= 15;
|
||||||
|
z &= 15;
|
||||||
|
Block block = c.getBlock(x, y, z);
|
||||||
|
if (!B.isFluid(block.getBlockData())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
boolean u = B.isAir(block.getRelative(BlockFace.DOWN).getBlockData())
|
||||||
|
|| B.isAir(block.getRelative(BlockFace.WEST).getBlockData())
|
||||||
|
|| B.isAir(block.getRelative(BlockFace.EAST).getBlockData())
|
||||||
|
|| B.isAir(block.getRelative(BlockFace.SOUTH).getBlockData())
|
||||||
|
|| B.isAir(block.getRelative(BlockFace.NORTH).getBlockData());
|
||||||
|
|
||||||
|
if (u) grid[x][z] = Math.max(grid[x][z], y);
|
||||||
|
});
|
||||||
|
|
||||||
|
for (int x = 0; x < 16; x++) {
|
||||||
|
for (int z = 0; z < 16; z++) {
|
||||||
|
if (grid[x][z] == Integer.MIN_VALUE)
|
||||||
|
continue;
|
||||||
|
update(x, grid[x][z], z, c, rng);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
chunk.iterate(MatterUpdate.class, (x, yf, z, v) -> {
|
||||||
|
int y = yf + getWorld().minHeight();
|
||||||
|
if (v != null && v.isUpdate()) {
|
||||||
|
update(x, y, z, c, rng);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
chunk.deleteSlices(MatterUpdate.class);
|
||||||
|
getMetrics().getUpdates().put(p.getMilliseconds());
|
||||||
|
}, RNG.r.i(1, 20))); //Why is there a random delay here?
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
semaphore.acquire(3);
|
||||||
|
} catch (InterruptedException ignored) {}
|
||||||
|
} finally {
|
||||||
|
chunk.release();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Runnable run(Semaphore semaphore, Runnable runnable) {
|
private static Runnable run(Semaphore semaphore, Runnable runnable, int delay) {
|
||||||
return () -> {
|
return () -> {
|
||||||
if (!semaphore.tryAcquire())
|
if (!semaphore.tryAcquire())
|
||||||
return;
|
return;
|
||||||
try {
|
|
||||||
runnable.run();
|
J.s(() -> {
|
||||||
} finally {
|
try {
|
||||||
semaphore.release();
|
runnable.run();
|
||||||
}
|
} finally {
|
||||||
|
semaphore.release();
|
||||||
|
}
|
||||||
|
}, delay);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@BlockCoordinates
|
|
||||||
default void updateLighting(int x, int y, int z, Chunk c) {
|
|
||||||
Block block = c.getBlock(x, y, z);
|
|
||||||
BlockData data = block.getBlockData();
|
|
||||||
|
|
||||||
if (B.isLit(data)) {
|
|
||||||
try {
|
|
||||||
block.setType(Material.AIR, false);
|
|
||||||
block.setBlockData(data, true);
|
|
||||||
} catch (Exception e) {
|
|
||||||
Iris.reportError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@BlockCoordinates
|
@BlockCoordinates
|
||||||
@Override
|
@Override
|
||||||
|
|
||||||
@@ -453,14 +445,11 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = nitems.length; i > 1; i--) {
|
||||||
try {
|
int j = rng.nextInt(i);
|
||||||
Arrays.parallelSort(nitems, (a, b) -> rng.nextInt());
|
ItemStack tmp = nitems[i - 1];
|
||||||
break;
|
nitems[i - 1] = nitems[j];
|
||||||
} catch (Throwable e) {
|
nitems[j] = tmp;
|
||||||
Iris.reportError(e);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inventory.setContents(nitems);
|
inventory.setContents(nitems);
|
||||||
@@ -852,6 +841,25 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
|
|||||||
return getBiomeOrMantle(l.getBlockX(), l.getBlockY(), l.getBlockZ());
|
return getBiomeOrMantle(l.getBlockX(), l.getBlockY(), l.getBlockZ());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@BlockCoordinates
|
||||||
|
default Position2 getNearestStronghold(Position2 pos) {
|
||||||
|
KList<Position2> p = getDimension().getStrongholds(getSeedManager().getMantle());
|
||||||
|
if (p.isEmpty()) return null;
|
||||||
|
|
||||||
|
Position2 pr = null;
|
||||||
|
double d = Double.MAX_VALUE;
|
||||||
|
|
||||||
|
for (Position2 i : p) {
|
||||||
|
double dx = i.distance(pos);
|
||||||
|
if (dx < d) {
|
||||||
|
d = dx;
|
||||||
|
pr = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pr;
|
||||||
|
}
|
||||||
|
|
||||||
default void gotoBiome(IrisBiome biome, Player player, boolean teleport) {
|
default void gotoBiome(IrisBiome biome, Player player, boolean teleport) {
|
||||||
Set<String> regionKeys = getDimension()
|
Set<String> regionKeys = getDimension()
|
||||||
.getAllRegions(this).stream()
|
.getAllRegions(this).stream()
|
||||||
@@ -872,31 +880,10 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
|
|||||||
|
|
||||||
default void gotoJigsaw(IrisJigsawStructure s, Player player, boolean teleport) {
|
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().getMantle());
|
Position2 pr = getNearestStronghold(new Position2(player.getLocation().getBlockX(), player.getLocation().getBlockZ()));
|
||||||
|
if (pr == null) {
|
||||||
if (p.isEmpty()) {
|
|
||||||
player.sendMessage(C.GOLD + "No strongholds in world.");
|
player.sendMessage(C.GOLD + "No strongholds in world.");
|
||||||
}
|
} else {
|
||||||
|
|
||||||
Position2 px = new Position2(player.getLocation().getBlockX(), player.getLocation().getBlockZ());
|
|
||||||
Position2 pr = null;
|
|
||||||
double d = Double.MAX_VALUE;
|
|
||||||
|
|
||||||
Iris.debug("Ps: " + p.size());
|
|
||||||
|
|
||||||
for (Position2 i : p) {
|
|
||||||
Iris.debug("- " + i.getX() + " " + i.getZ());
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Position2 i : p) {
|
|
||||||
double dx = i.distance(px);
|
|
||||||
if (dx < d) {
|
|
||||||
d = dx;
|
|
||||||
pr = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pr != null) {
|
|
||||||
Location ll = new Location(player.getWorld(), pr.getX(), 40, pr.getZ());
|
Location ll = new Location(player.getWorld(), pr.getX(), 40, pr.getZ());
|
||||||
J.s(() -> player.teleport(ll));
|
J.s(() -> player.teleport(ll));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -97,51 +97,6 @@ public abstract class EngineAssignedWorldManager extends EngineAssignedComponent
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onItemUse(PlayerInteractEvent e) {
|
|
||||||
if (e.getItem() == null || e.getHand() != EquipmentSlot.HAND) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (e.getAction() == Action.LEFT_CLICK_BLOCK || e.getAction() == Action.LEFT_CLICK_AIR) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (e.getPlayer().getWorld().equals(getTarget().getWorld().realWorld()) && e.getItem().getType() == Material.ENDER_EYE) {
|
|
||||||
if (e.getClickedBlock() != null && e.getClickedBlock().getType() == Material.END_PORTAL_FRAME) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
KList<Position2> positions = getEngine().getDimension().getStrongholds(getEngine().getSeedManager().getMantle());
|
|
||||||
if (positions.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Position2 playerPos = new Position2(e.getPlayer().getLocation().getBlockX(), e.getPlayer().getLocation().getBlockZ());
|
|
||||||
Position2 pr = positions.get(0);
|
|
||||||
double d = pr.distance(playerPos);
|
|
||||||
|
|
||||||
for (Position2 pos : positions) {
|
|
||||||
double distance = pos.distance(playerPos);
|
|
||||||
if (distance < d) {
|
|
||||||
d = distance;
|
|
||||||
pr = pos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e.getPlayer().getGameMode() != GameMode.CREATIVE) {
|
|
||||||
if (e.getItem().getAmount() > 1) {
|
|
||||||
e.getPlayer().getInventory().getItemInMainHand().setAmount(e.getItem().getAmount() - 1);
|
|
||||||
} else {
|
|
||||||
e.getPlayer().getInventory().setItemInMainHand(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
EnderSignal eye = e.getPlayer().getWorld().spawn(e.getPlayer().getLocation().clone().add(0, 0.5F, 0), EnderSignal.class);
|
|
||||||
eye.setTargetLocation(new Location(e.getPlayer().getWorld(), pr.getX(), 40, pr.getZ()));
|
|
||||||
eye.getWorld().playSound(eye, Sound.ENTITY_ENDER_EYE_LAUNCH, 1, 1);
|
|
||||||
Iris.debug("ESignal: " + eye.getTargetLocation().getBlockX() + " " + eye.getTargetLocation().getBlockX());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void on(WorldUnloadEvent e) {
|
public void on(WorldUnloadEvent e) {
|
||||||
if (e.getWorld().equals(getTarget().getWorld().realWorld())) {
|
if (e.getWorld().equals(getTarget().getWorld().realWorld())) {
|
||||||
|
|||||||
@@ -47,9 +47,7 @@ public class EnginePlayer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void tick() {
|
public void tick() {
|
||||||
sample();
|
if (sample() || !IrisSettings.get().getWorld().isEffectSystem())
|
||||||
|
|
||||||
if (!IrisSettings.get().getWorld().isEffectSystem())
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
J.a(() -> {
|
J.a(() -> {
|
||||||
@@ -81,22 +79,22 @@ public class EnginePlayer {
|
|||||||
return M.ms() - lastSample;
|
return M.ms() - lastSample;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sample() {
|
public boolean sample() {
|
||||||
|
Location current = player.getLocation().clone();
|
||||||
|
if (current.getWorld() != engine.getWorld().realWorld())
|
||||||
|
return true;
|
||||||
try {
|
try {
|
||||||
if (ticksSinceLastSample() > 55 && player.getLocation().distanceSquared(lastLocation) > 9 * 9) {
|
if (ticksSinceLastSample() > 55 && current.distanceSquared(lastLocation) > 9 * 9) {
|
||||||
lastLocation = player.getLocation().clone();
|
lastLocation = current;
|
||||||
lastSample = M.ms();
|
lastSample = M.ms();
|
||||||
sampleBiomeRegion();
|
biome = engine.getBiome(current);
|
||||||
|
region = engine.getRegion(current);
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
return true;
|
||||||
|
|
||||||
private void sampleBiomeRegion() {
|
|
||||||
Location l = player.getLocation();
|
|
||||||
biome = engine.getBiome(l);
|
|
||||||
region = engine.getRegion(l);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,8 +22,7 @@ import com.volmit.iris.engine.object.IrisObject;
|
|||||||
import com.volmit.iris.engine.object.IrisObjectPlacement;
|
import com.volmit.iris.engine.object.IrisObjectPlacement;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import com.volmit.iris.util.mantle.Mantle;
|
|||||||
import com.volmit.iris.util.math.Position2;
|
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.container.JigsawPieceContainer;
|
import com.volmit.iris.util.matter.slices.container.JigsawPieceContainer;
|
||||||
|
import com.volmit.iris.util.matter.slices.container.JigsawStructureContainer;
|
||||||
import com.volmit.iris.util.matter.slices.container.JigsawStructuresContainer;
|
import com.volmit.iris.util.matter.slices.container.JigsawStructuresContainer;
|
||||||
import com.volmit.iris.util.scheduling.J;
|
import com.volmit.iris.util.scheduling.J;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -149,11 +150,13 @@ 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 piece = JigsawPieceContainer.toContainer(i.getPiece());
|
||||||
|
JigsawStructureContainer structure = JigsawStructureContainer.toContainer(getStructure());
|
||||||
i.setRealPositions(xx, height, zz, placer);
|
i.setRealPositions(xx, height, zz, placer);
|
||||||
return v.place(xx, height, zz, placer, options, rng, (b, data) -> {
|
return v.place(xx, height, zz, placer, options, rng, (b, data) -> {
|
||||||
e.set(b.getX(), b.getY(), b.getZ(), v.getLoadKey() + "@" + id);
|
e.set(b.getX(), b.getY(), b.getZ(), v.getLoadKey() + "@" + id);
|
||||||
e.set(b.getX(), b.getY(), b.getZ(), container);
|
e.set(b.getX(), b.getY(), b.getZ(), structure);
|
||||||
|
e.set(b.getX(), b.getY(), b.getZ(), piece);
|
||||||
}, null, getData().getEngine() != null ? getData() : eng.getData()) != -1;
|
}, null, getData().getEngine() != null ? getData() : eng.getData()) != -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package com.volmit.iris.engine.mantle;
|
||||||
|
|
||||||
|
import com.volmit.iris.util.mantle.flag.ReservedFlag;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
@Target(ElementType.TYPE)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface ComponentFlag {
|
||||||
|
ReservedFlag value();
|
||||||
|
}
|
||||||
@@ -26,31 +26,33 @@ import com.volmit.iris.engine.framework.Engine;
|
|||||||
import com.volmit.iris.engine.framework.EngineTarget;
|
import com.volmit.iris.engine.framework.EngineTarget;
|
||||||
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.IObjectPlacer;
|
|
||||||
import com.volmit.iris.engine.object.IrisDimension;
|
import com.volmit.iris.engine.object.IrisDimension;
|
||||||
import com.volmit.iris.engine.object.IrisPosition;
|
import com.volmit.iris.engine.object.IrisPosition;
|
||||||
import com.volmit.iris.engine.object.TileData;
|
|
||||||
import com.volmit.iris.util.collection.KList;
|
import com.volmit.iris.util.collection.KList;
|
||||||
import com.volmit.iris.util.context.ChunkContext;
|
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.IrisCustomData;
|
|
||||||
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.hunk.Hunk;
|
import com.volmit.iris.util.hunk.Hunk;
|
||||||
import com.volmit.iris.util.mantle.Mantle;
|
import com.volmit.iris.util.mantle.Mantle;
|
||||||
import com.volmit.iris.util.mantle.MantleChunk;
|
import com.volmit.iris.util.mantle.MantleChunk;
|
||||||
import com.volmit.iris.util.mantle.MantleFlag;
|
import com.volmit.iris.util.mantle.flag.MantleFlag;
|
||||||
|
import com.volmit.iris.util.math.Position2;
|
||||||
import com.volmit.iris.util.matter.*;
|
import com.volmit.iris.util.matter.*;
|
||||||
import com.volmit.iris.util.matter.slices.UpdateMatter;
|
import com.volmit.iris.util.matter.slices.UpdateMatter;
|
||||||
import com.volmit.iris.util.parallel.BurstExecutor;
|
|
||||||
import com.volmit.iris.util.parallel.MultiBurst;
|
import com.volmit.iris.util.parallel.MultiBurst;
|
||||||
import org.bukkit.block.data.BlockData;
|
import org.bukkit.block.data.BlockData;
|
||||||
|
import org.jetbrains.annotations.UnmodifiableView;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
// TODO: MOVE PLACER OUT OF MATTER INTO ITS OWN THING
|
import static com.volmit.iris.util.parallel.StreamUtils.forEach;
|
||||||
public interface EngineMantle extends IObjectPlacer {
|
import static com.volmit.iris.util.parallel.StreamUtils.streamRadius;
|
||||||
|
|
||||||
|
public interface EngineMantle {
|
||||||
BlockData AIR = B.get("AIR");
|
BlockData AIR = B.get("AIR");
|
||||||
|
|
||||||
Mantle getMantle();
|
Mantle getMantle();
|
||||||
@@ -61,9 +63,18 @@ public interface EngineMantle extends IObjectPlacer {
|
|||||||
|
|
||||||
int getRealRadius();
|
int getRealRadius();
|
||||||
|
|
||||||
KList<Pair<KList<MantleComponent>, Integer>> getComponents();
|
@UnmodifiableView
|
||||||
|
List<Pair<List<MantleComponent>, Integer>> getComponents();
|
||||||
|
|
||||||
void registerComponent(MantleComponent c);
|
@UnmodifiableView
|
||||||
|
Map<MantleFlag, MantleComponent> getRegisteredComponents();
|
||||||
|
|
||||||
|
boolean registerComponent(MantleComponent c);
|
||||||
|
|
||||||
|
@UnmodifiableView
|
||||||
|
KList<MantleFlag> getComponentFlags();
|
||||||
|
|
||||||
|
void hotload();
|
||||||
|
|
||||||
default int getHighest(int x, int z) {
|
default int getHighest(int x, int z) {
|
||||||
return getHighest(x, z, getData());
|
return getHighest(x, z, getData());
|
||||||
@@ -85,12 +96,10 @@ public interface EngineMantle extends IObjectPlacer {
|
|||||||
return getHighest(x, z, getData(), ignoreFluid);
|
return getHighest(x, z, getData(), ignoreFluid);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
default int getHighest(int x, int z, IrisData data) {
|
default int getHighest(int x, int z, IrisData data) {
|
||||||
return getHighest(x, z, data, false);
|
return getHighest(x, z, data, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
default int getHighest(int x, int z, IrisData data, boolean ignoreFluid) {
|
default int getHighest(int x, int z, IrisData data, boolean ignoreFluid) {
|
||||||
return ignoreFluid ? trueHeight(x, z) : Math.max(trueHeight(x, z), getEngine().getDimension().getFluidHeight());
|
return ignoreFluid ? trueHeight(x, z) : Math.max(trueHeight(x, z), getEngine().getDimension().getFluidHeight());
|
||||||
}
|
}
|
||||||
@@ -99,24 +108,12 @@ public interface EngineMantle extends IObjectPlacer {
|
|||||||
return getComplex().getRoundedHeighteightStream().get(x, z);
|
return getComplex().getRoundedHeighteightStream().get(x, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated(forRemoval = true)
|
||||||
default boolean isCarved(int x, int h, int z) {
|
default boolean isCarved(int x, int h, int z) {
|
||||||
return getMantle().get(x, h, z, MatterCavern.class) != null;
|
return getMantle().get(x, h, z, MatterCavern.class) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Deprecated(forRemoval = true)
|
||||||
default void set(int x, int y, int z, BlockData d) {
|
|
||||||
if (d instanceof IrisCustomData data) {
|
|
||||||
getMantle().set(x, y, z, data.getBase());
|
|
||||||
getMantle().set(x, y, z, data.getCustom());
|
|
||||||
} else getMantle().set(x, y, z, d == null ? AIR : d);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
default void setTile(int x, int y, int z, TileData d) {
|
|
||||||
getMantle().set(x, y, z, new TileWrapper(d));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
default BlockData get(int x, int y, int z) {
|
default BlockData get(int x, int y, int z) {
|
||||||
BlockData block = getMantle().get(x, y, z, BlockData.class);
|
BlockData block = getMantle().get(x, y, z, BlockData.class);
|
||||||
if (block == null)
|
if (block == null)
|
||||||
@@ -124,27 +121,18 @@ public interface EngineMantle extends IObjectPlacer {
|
|||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
default boolean isPreventingDecay() {
|
default boolean isPreventingDecay() {
|
||||||
return getEngine().getDimension().isPreventLeafDecay();
|
return getEngine().getDimension().isPreventLeafDecay();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
default boolean isSolid(int x, int y, int z) {
|
|
||||||
return B.isSolid(get(x, y, z));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
default boolean isUnderwater(int x, int z) {
|
default boolean isUnderwater(int x, int z) {
|
||||||
return getHighest(x, z, true) <= getFluidHeight();
|
return getHighest(x, z, true) <= getFluidHeight();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
default int getFluidHeight() {
|
default int getFluidHeight() {
|
||||||
return getEngine().getDimension().getFluidHeight();
|
return getEngine().getDimension().getFluidHeight();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
default boolean isDebugSmartBore() {
|
default boolean isDebugSmartBore() {
|
||||||
return getEngine().getDimension().isDebugSmartBore();
|
return getEngine().getDimension().isDebugSmartBore();
|
||||||
}
|
}
|
||||||
@@ -194,7 +182,7 @@ public interface EngineMantle extends IObjectPlacer {
|
|||||||
|
|
||||||
@ChunkCoordinates
|
@ChunkCoordinates
|
||||||
default void generateMatter(int x, int z, boolean multicore, ChunkContext context) {
|
default void generateMatter(int x, int z, boolean multicore, ChunkContext context) {
|
||||||
if (!getEngine().getDimension().isUseMantle()) {
|
if (!getEngine().getDimension().isUseMantle() || getMantle().hasFlag(x, z, MantleFlag.PLANNED)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,30 +192,35 @@ public interface EngineMantle extends IObjectPlacer {
|
|||||||
var pair = iterator.next();
|
var pair = iterator.next();
|
||||||
int radius = pair.getB();
|
int radius = pair.getB();
|
||||||
boolean last = !iterator.hasNext();
|
boolean last = !iterator.hasNext();
|
||||||
BurstExecutor burst = burst().burst(radius * 2 + 1);
|
forEach(streamRadius(x, z, radius),
|
||||||
burst.setMulticore(multicore);
|
pos -> pair.getA()
|
||||||
|
.stream()
|
||||||
|
.filter(MantleComponent::isEnabled)
|
||||||
|
.map(c -> new Pair<>(c, pos)),
|
||||||
|
p -> {
|
||||||
|
MantleComponent c = p.getA();
|
||||||
|
Position2 pos = p.getB();
|
||||||
|
int xx = pos.getX();
|
||||||
|
int zz = pos.getZ();
|
||||||
|
IrisContext.getOr(getEngine()).setChunkContext(context);
|
||||||
|
generateMantleComponent(writer, xx, zz, c, writer.acquireChunk(xx, zz), context);
|
||||||
|
},
|
||||||
|
multicore ? burst() : null
|
||||||
|
);
|
||||||
|
|
||||||
for (int i = -radius; i <= radius; i++) {
|
if (!last) continue;
|
||||||
for (int j = -radius; j <= radius; j++) {
|
forEach(streamRadius(x, z, radius),
|
||||||
int xx = x + i;
|
p -> writer.acquireChunk(x, z).flag(MantleFlag.PLANNED, true),
|
||||||
int zz = z + j;
|
multicore ? burst() : null
|
||||||
MantleChunk mc = getMantle().getChunk(xx, zz);
|
);
|
||||||
|
|
||||||
burst.queue(() -> {
|
|
||||||
IrisContext.touch(getEngine().getContext());
|
|
||||||
pair.getA().forEach(k -> generateMantleComponent(writer, xx, zz, k, mc, context));
|
|
||||||
if (last) mc.flag(MantleFlag.PLANNED, true);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
burst.complete();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
default void generateMantleComponent(MantleWriter writer, int x, int z, MantleComponent c, MantleChunk mc, ChunkContext context) {
|
default void generateMantleComponent(MantleWriter writer, int x, int z, MantleComponent c, MantleChunk mc, ChunkContext context) {
|
||||||
mc.raiseFlag(c.getFlag(), () -> c.generateLayer(writer, x, z, context));
|
mc.raiseFlag(MantleFlag.PLANNED, c.getFlag(), () -> {
|
||||||
|
if (c.isEnabled()) c.generateLayer(writer, x, z, context);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ChunkCoordinates
|
@ChunkCoordinates
|
||||||
@@ -236,7 +229,12 @@ public interface EngineMantle extends IObjectPlacer {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
getMantle().iterateChunk(x, z, t, blocks::set);
|
var chunk = getMantle().getChunk(x, z).use();
|
||||||
|
try {
|
||||||
|
chunk.iterate(t, blocks::set);
|
||||||
|
} finally {
|
||||||
|
chunk.release();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@BlockCoordinates
|
@BlockCoordinates
|
||||||
@@ -289,23 +287,25 @@ public interface EngineMantle extends IObjectPlacer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
default void cleanupChunk(int x, int z) {
|
default void cleanupChunk(int x, int z) {
|
||||||
if (!getMantle().hasFlag(x, z, MantleFlag.CLEANED) && isCovered(x, z)) {
|
if (!isCovered(x, z)) return;
|
||||||
getMantle().raiseFlag(x, z, MantleFlag.CLEANED, () -> {
|
MantleChunk chunk = getMantle().getChunk(x, z).use();
|
||||||
getMantle().deleteChunkSlice(x, z, BlockData.class);
|
try {
|
||||||
getMantle().deleteChunkSlice(x, z, String.class);
|
chunk.raiseFlag(MantleFlag.CLEANED, () -> {
|
||||||
getMantle().deleteChunkSlice(x, z, MatterCavern.class);
|
chunk.deleteSlices(BlockData.class);
|
||||||
getMantle().deleteChunkSlice(x, z, MatterFluidBody.class);
|
chunk.deleteSlices(String.class);
|
||||||
|
chunk.deleteSlices(MatterCavern.class);
|
||||||
|
chunk.deleteSlices(MatterFluidBody.class);
|
||||||
});
|
});
|
||||||
|
} finally {
|
||||||
|
chunk.release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
default long getToUnload(){
|
default long getUnloadRegionCount() {
|
||||||
return getMantle().getToUnload().size();
|
return getMantle().getUnloadRegionCount();
|
||||||
}
|
}
|
||||||
default long getNotQueuedLoadedRegions(){
|
|
||||||
return getMantle().getLoadedRegions().size() - getMantle().getToUnload().size();
|
default double getAdjustedIdleDuration() {
|
||||||
}
|
return getMantle().getAdjustedIdleDuration();
|
||||||
default double getTectonicDuration(){
|
|
||||||
return getMantle().getAdjustedIdleDuration().get();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
package com.volmit.iris.engine.mantle;
|
package com.volmit.iris.engine.mantle;
|
||||||
|
|
||||||
import com.volmit.iris.util.mantle.MantleFlag;
|
import com.volmit.iris.util.mantle.flag.MantleFlag;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
@@ -30,4 +30,32 @@ public abstract class IrisMantleComponent implements MantleComponent {
|
|||||||
private final EngineMantle engineMantle;
|
private final EngineMantle engineMantle;
|
||||||
private final MantleFlag flag;
|
private final MantleFlag flag;
|
||||||
private final int priority;
|
private final int priority;
|
||||||
|
|
||||||
|
private volatile int radius = -1;
|
||||||
|
private final Object lock = new Object();
|
||||||
|
private boolean enabled = true;
|
||||||
|
|
||||||
|
protected abstract int computeRadius();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void hotload() {
|
||||||
|
synchronized (lock) {
|
||||||
|
radius = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final int getRadius() {
|
||||||
|
int r = radius;
|
||||||
|
if(r != -1) return r;
|
||||||
|
|
||||||
|
synchronized (lock) {
|
||||||
|
if((r = radius) != -1) {
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
r = computeRadius();
|
||||||
|
if(r < 0) r = 0;
|
||||||
|
return radius = r;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ import com.volmit.iris.engine.object.IrisDimension;
|
|||||||
import com.volmit.iris.util.context.ChunkContext;
|
import com.volmit.iris.util.context.ChunkContext;
|
||||||
import com.volmit.iris.util.documentation.ChunkCoordinates;
|
import com.volmit.iris.util.documentation.ChunkCoordinates;
|
||||||
import com.volmit.iris.util.mantle.Mantle;
|
import com.volmit.iris.util.mantle.Mantle;
|
||||||
import com.volmit.iris.util.mantle.MantleFlag;
|
import com.volmit.iris.util.mantle.flag.MantleFlag;
|
||||||
import com.volmit.iris.util.parallel.BurstExecutor;
|
import com.volmit.iris.util.parallel.BurstExecutor;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
@@ -61,6 +61,12 @@ public interface MantleComponent extends Comparable<MantleComponent> {
|
|||||||
|
|
||||||
MantleFlag getFlag();
|
MantleFlag getFlag();
|
||||||
|
|
||||||
|
boolean isEnabled();
|
||||||
|
|
||||||
|
void setEnabled(boolean b);
|
||||||
|
|
||||||
|
void hotload();
|
||||||
|
|
||||||
@ChunkCoordinates
|
@ChunkCoordinates
|
||||||
void generateLayer(MantleWriter writer, int x, int z, ChunkContext context);
|
void generateLayer(MantleWriter writer, int x, int z, ChunkContext context);
|
||||||
|
|
||||||
|
|||||||
@@ -29,12 +29,17 @@ import com.volmit.iris.engine.object.IrisPosition;
|
|||||||
import com.volmit.iris.engine.object.TileData;
|
import com.volmit.iris.engine.object.TileData;
|
||||||
import com.volmit.iris.util.collection.KMap;
|
import com.volmit.iris.util.collection.KMap;
|
||||||
import com.volmit.iris.util.collection.KSet;
|
import com.volmit.iris.util.collection.KSet;
|
||||||
|
import com.volmit.iris.util.data.B;
|
||||||
import com.volmit.iris.util.data.IrisCustomData;
|
import com.volmit.iris.util.data.IrisCustomData;
|
||||||
|
import com.volmit.iris.util.documentation.ChunkCoordinates;
|
||||||
import com.volmit.iris.util.function.Function3;
|
import com.volmit.iris.util.function.Function3;
|
||||||
import com.volmit.iris.util.mantle.Mantle;
|
import com.volmit.iris.util.mantle.Mantle;
|
||||||
import com.volmit.iris.util.mantle.MantleChunk;
|
import com.volmit.iris.util.mantle.MantleChunk;
|
||||||
import com.volmit.iris.util.math.RNG;
|
import com.volmit.iris.util.math.RNG;
|
||||||
import com.volmit.iris.util.matter.Matter;
|
import com.volmit.iris.util.matter.Matter;
|
||||||
|
import com.volmit.iris.util.matter.MatterCavern;
|
||||||
|
import com.volmit.iris.util.matter.TileWrapper;
|
||||||
|
import com.volmit.iris.util.noise.CNG;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.bukkit.block.data.BlockData;
|
import org.bukkit.block.data.BlockData;
|
||||||
import org.bukkit.util.Vector;
|
import org.bukkit.util.Vector;
|
||||||
@@ -43,6 +48,8 @@ import java.util.HashSet;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import static com.volmit.iris.engine.mantle.EngineMantle.AIR;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class MantleWriter implements IObjectPlacer, AutoCloseable {
|
public class MantleWriter implements IObjectPlacer, AutoCloseable {
|
||||||
private final EngineMantle engineMantle;
|
private final EngineMantle engineMantle;
|
||||||
@@ -60,8 +67,9 @@ public class MantleWriter implements IObjectPlacer, AutoCloseable {
|
|||||||
this.x = x;
|
this.x = x;
|
||||||
this.z = z;
|
this.z = z;
|
||||||
|
|
||||||
for (int i = -radius; i <= radius; i++) {
|
int r = radius / 4;
|
||||||
for (int j = -radius; j <= radius; j++) {
|
for (int i = -r; i <= r; i++) {
|
||||||
|
for (int j = -r; j <= r; j++) {
|
||||||
cachedChunks.put(Cache.key(i + x, j + z), mantle.getChunk(i + x, j + z).use());
|
cachedChunks.put(Cache.key(i + x, j + z), mantle.getChunk(i + x, j + z).use());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -70,6 +78,7 @@ public class MantleWriter implements IObjectPlacer, AutoCloseable {
|
|||||||
private static Set<IrisPosition> getBallooned(Set<IrisPosition> vset, double radius) {
|
private static Set<IrisPosition> getBallooned(Set<IrisPosition> vset, double radius) {
|
||||||
Set<IrisPosition> returnset = new HashSet<>();
|
Set<IrisPosition> returnset = new HashSet<>();
|
||||||
int ceilrad = (int) Math.ceil(radius);
|
int ceilrad = (int) Math.ceil(radius);
|
||||||
|
double r2 = Math.pow(radius, 2);
|
||||||
|
|
||||||
for (IrisPosition v : vset) {
|
for (IrisPosition v : vset) {
|
||||||
int tipx = v.getX();
|
int tipx = v.getX();
|
||||||
@@ -79,7 +88,7 @@ public class MantleWriter implements IObjectPlacer, AutoCloseable {
|
|||||||
for (int loopx = tipx - ceilrad; loopx <= tipx + ceilrad; loopx++) {
|
for (int loopx = tipx - ceilrad; loopx <= tipx + ceilrad; loopx++) {
|
||||||
for (int loopy = tipy - ceilrad; loopy <= tipy + ceilrad; loopy++) {
|
for (int loopy = tipy - ceilrad; loopy <= tipy + ceilrad; loopy++) {
|
||||||
for (int loopz = tipz - ceilrad; loopz <= tipz + ceilrad; loopz++) {
|
for (int loopz = tipz - ceilrad; loopz <= tipz + ceilrad; loopz++) {
|
||||||
if (hypot(loopx - tipx, loopy - tipy, loopz - tipz) <= radius) {
|
if (hypot(loopx - tipx, loopy - tipy, loopz - tipz) <= r2) {
|
||||||
returnset.add(new IrisPosition(loopx, loopy, loopz));
|
returnset.add(new IrisPosition(loopx, loopy, loopz));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -112,7 +121,7 @@ public class MantleWriter implements IObjectPlacer, AutoCloseable {
|
|||||||
for (double d : pars) {
|
for (double d : pars) {
|
||||||
sum += Math.pow(d, 2);
|
sum += Math.pow(d, 2);
|
||||||
}
|
}
|
||||||
return Math.sqrt(sum);
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static double lengthSq(double x, double y, double z) {
|
private static double lengthSq(double x, double y, double z) {
|
||||||
@@ -141,18 +150,41 @@ public class MantleWriter implements IObjectPlacer, AutoCloseable {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cx >= this.x - radius && cx <= this.x + radius
|
MantleChunk chunk = acquireChunk(cx, cz);
|
||||||
&& cz >= this.z - radius && cz <= this.z + radius) {
|
if (chunk == null) return;
|
||||||
MantleChunk chunk = cachedChunks.get(Cache.key(cx, cz));
|
|
||||||
|
|
||||||
if (chunk == null) {
|
Matter matter = chunk.getOrCreate(y >> 4);
|
||||||
Iris.error("Mantle Writer Accessed " + cx + "," + cz + " and came up null (and yet within bounds!)");
|
matter.slice(matter.getClass(t)).set(x & 15, y & 15, z & 15, t);
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Matter matter = chunk.getOrCreate(y >> 4);
|
public <T> T getData(int x, int y, int z, Class<T> type) {
|
||||||
matter.slice(matter.getClass(t)).set(x & 15, y & 15, z & 15, t);
|
int cx = x >> 4;
|
||||||
|
int cz = z >> 4;
|
||||||
|
|
||||||
|
if (y < 0 || y >= mantle.getWorldHeight()) {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MantleChunk chunk = acquireChunk(cx, cz);
|
||||||
|
if (chunk == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return chunk.getOrCreate(y >> 4)
|
||||||
|
.<T>slice(type)
|
||||||
|
.get(x & 15, y & 15, z & 15);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ChunkCoordinates
|
||||||
|
public MantleChunk acquireChunk(int cx, int cz) {
|
||||||
|
if (cx < this.x - radius || cx > this.x + radius
|
||||||
|
|| cz < this.z - radius || cz > this.z + radius) {
|
||||||
|
Iris.error("Mantle Writer Accessed chunk out of bounds" + cx + "," + cz);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
MantleChunk chunk = cachedChunks.computeIfAbsent(Cache.key(cx, cz), k -> mantle.getChunk(cx, cz).use());
|
||||||
|
if (chunk == null) Iris.error("Mantle Writer Accessed " + cx + "," + cz + " and came up null (and yet within bounds!)");
|
||||||
|
return chunk;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -175,7 +207,10 @@ public class MantleWriter implements IObjectPlacer, AutoCloseable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BlockData get(int x, int y, int z) {
|
public BlockData get(int x, int y, int z) {
|
||||||
return getEngineMantle().get(x, y, z);
|
BlockData block = getData(x, y, z, BlockData.class);
|
||||||
|
if (block == null)
|
||||||
|
return AIR;
|
||||||
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -185,12 +220,12 @@ public class MantleWriter implements IObjectPlacer, AutoCloseable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isCarved(int x, int y, int z) {
|
public boolean isCarved(int x, int y, int z) {
|
||||||
return getEngineMantle().isCarved(x, y, z);
|
return getData(x, y, z, MatterCavern.class) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isSolid(int x, int y, int z) {
|
public boolean isSolid(int x, int y, int z) {
|
||||||
return getEngineMantle().isSolid(x, y, z);
|
return B.isSolid(get(x, y, z));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -210,7 +245,7 @@ public class MantleWriter implements IObjectPlacer, AutoCloseable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setTile(int xx, int yy, int zz, TileData tile) {
|
public void setTile(int xx, int yy, int zz, TileData tile) {
|
||||||
getEngineMantle().setTile(xx, yy, zz, tile);
|
setData(xx, yy, zz, new TileWrapper(tile));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -450,6 +485,62 @@ public class MantleWriter implements IObjectPlacer, AutoCloseable {
|
|||||||
* @param <T> the type of data to apply to the mantle
|
* @param <T> the type of data to apply to the mantle
|
||||||
*/
|
*/
|
||||||
public <T> void setLineConsumer(List<IrisPosition> vectors, double radius, boolean filled, Function3<Integer, Integer, Integer, T> data) {
|
public <T> void setLineConsumer(List<IrisPosition> vectors, double radius, boolean filled, Function3<Integer, Integer, Integer, T> data) {
|
||||||
|
Set<IrisPosition> vset = cleanup(vectors);
|
||||||
|
vset = getBallooned(vset, radius);
|
||||||
|
|
||||||
|
if (!filled) {
|
||||||
|
vset = getHollowed(vset);
|
||||||
|
}
|
||||||
|
|
||||||
|
setConsumer(vset, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set lines for points
|
||||||
|
*
|
||||||
|
* @param vectors the points
|
||||||
|
* @param radius the radius
|
||||||
|
* @param filled hollow or filled?
|
||||||
|
* @param data the data to set
|
||||||
|
* @param <T> the type of data to apply to the mantle
|
||||||
|
*/
|
||||||
|
public <T> void setNoiseMasked(List<IrisPosition> vectors, double radius, double threshold, CNG shape, Set<IrisPosition> masks, boolean filled, Function3<Integer, Integer, Integer, T> data) {
|
||||||
|
Set<IrisPosition> vset = cleanup(vectors);
|
||||||
|
vset = masks == null ? getBallooned(vset, radius) : getMasked(vset, masks, radius);
|
||||||
|
vset.removeIf(p -> shape.noise(p.getX(), p.getY(), p.getZ()) < threshold);
|
||||||
|
|
||||||
|
if (!filled) {
|
||||||
|
vset = getHollowed(vset);
|
||||||
|
}
|
||||||
|
|
||||||
|
setConsumer(vset, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Set<IrisPosition> getMasked(Set<IrisPosition> vectors, Set<IrisPosition> masks, double radius) {
|
||||||
|
Set<IrisPosition> vset = new KSet<>();
|
||||||
|
int ceil = (int) Math.ceil(radius);
|
||||||
|
double r2 = Math.pow(radius, 2);
|
||||||
|
|
||||||
|
for (IrisPosition v : vectors) {
|
||||||
|
int tipX = v.getX();
|
||||||
|
int tipY = v.getY();
|
||||||
|
int tipZ = v.getZ();
|
||||||
|
|
||||||
|
for (int x = -ceil; x <= ceil; x++) {
|
||||||
|
for (int y = -ceil; y <= ceil; y++) {
|
||||||
|
for (int z = -ceil; z <= ceil; z++) {
|
||||||
|
if (hypot(x, y, z) > r2 || !masks.contains(new IrisPosition(x, y, z)))
|
||||||
|
continue;
|
||||||
|
vset.add(new IrisPosition(tipX + x, tipY + y, tipZ + z));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return vset;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Set<IrisPosition> cleanup(List<IrisPosition> vectors) {
|
||||||
Set<IrisPosition> vset = new KSet<>();
|
Set<IrisPosition> vset = new KSet<>();
|
||||||
|
|
||||||
for (int i = 0; vectors.size() != 0 && i < vectors.size() - 1; i++) {
|
for (int i = 0; vectors.size() != 0 && i < vectors.size() - 1; i++) {
|
||||||
@@ -501,13 +592,7 @@ public class MantleWriter implements IObjectPlacer, AutoCloseable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vset = getBallooned(vset, radius);
|
return vset;
|
||||||
|
|
||||||
if (!filled) {
|
|
||||||
vset = getHollowed(vset);
|
|
||||||
}
|
|
||||||
|
|
||||||
setConsumer(vset, data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -639,9 +724,10 @@ public class MantleWriter implements IObjectPlacer, AutoCloseable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {
|
||||||
cachedChunks.values().removeIf(c -> {
|
var iterator = cachedChunks.values().iterator();
|
||||||
c.release();
|
while (iterator.hasNext()) {
|
||||||
return true;
|
iterator.next().release();
|
||||||
});
|
iterator.remove();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
package com.volmit.iris.engine.mantle.components;
|
package com.volmit.iris.engine.mantle.components;
|
||||||
|
|
||||||
import com.volmit.iris.engine.data.cache.Cache;
|
import com.volmit.iris.engine.data.cache.Cache;
|
||||||
|
import com.volmit.iris.engine.mantle.ComponentFlag;
|
||||||
import com.volmit.iris.engine.mantle.EngineMantle;
|
import com.volmit.iris.engine.mantle.EngineMantle;
|
||||||
import com.volmit.iris.engine.mantle.IrisMantleComponent;
|
import com.volmit.iris.engine.mantle.IrisMantleComponent;
|
||||||
import com.volmit.iris.engine.mantle.MantleWriter;
|
import com.volmit.iris.engine.mantle.MantleWriter;
|
||||||
@@ -27,16 +28,13 @@ import com.volmit.iris.engine.object.IrisCarving;
|
|||||||
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.documentation.ChunkCoordinates;
|
import com.volmit.iris.util.documentation.ChunkCoordinates;
|
||||||
import com.volmit.iris.util.mantle.MantleFlag;
|
import com.volmit.iris.util.mantle.flag.ReservedFlag;
|
||||||
import com.volmit.iris.util.math.RNG;
|
import com.volmit.iris.util.math.RNG;
|
||||||
import lombok.Getter;
|
|
||||||
|
|
||||||
@Getter
|
@ComponentFlag(ReservedFlag.CARVED)
|
||||||
public class MantleCarvingComponent extends IrisMantleComponent {
|
public class MantleCarvingComponent extends IrisMantleComponent {
|
||||||
private final int radius = computeRadius();
|
|
||||||
|
|
||||||
public MantleCarvingComponent(EngineMantle engineMantle) {
|
public MantleCarvingComponent(EngineMantle engineMantle) {
|
||||||
super(engineMantle, MantleFlag.CARVED, 0);
|
super(engineMantle, ReservedFlag.CARVED, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -58,21 +56,21 @@ public class MantleCarvingComponent extends IrisMantleComponent {
|
|||||||
|
|
||||||
@ChunkCoordinates
|
@ChunkCoordinates
|
||||||
private void carve(IrisCarving carving, MantleWriter writer, RNG rng, int cx, int cz) {
|
private void carve(IrisCarving carving, MantleWriter writer, RNG rng, int cx, int cz) {
|
||||||
carving.doCarving(writer, rng, getEngineMantle().getEngine(), cx << 4, -1, cz << 4);
|
carving.doCarving(writer, rng, getEngineMantle().getEngine(), cx << 4, -1, cz << 4, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int computeRadius() {
|
protected int computeRadius() {
|
||||||
var dimension = getDimension();
|
var dimension = getDimension();
|
||||||
int max = 0;
|
int max = 0;
|
||||||
|
|
||||||
max = Math.max(max, dimension.getCarving().getMaxRange(getData()));
|
max = Math.max(max, dimension.getCarving().getMaxRange(getData(), 0));
|
||||||
|
|
||||||
for (var i : dimension.getAllRegions(this::getData)) {
|
for (var i : dimension.getAllRegions(this::getData)) {
|
||||||
max = Math.max(max, i.getCarving().getMaxRange(getData()));
|
max = Math.max(max, i.getCarving().getMaxRange(getData(), 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var i : dimension.getAllBiomes(this::getData)) {
|
for (var i : dimension.getAllBiomes(this::getData)) {
|
||||||
max = Math.max(max, i.getCarving().getMaxRange(getData()));
|
max = Math.max(max, i.getCarving().getMaxRange(getData(), 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
return max;
|
return max;
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
package com.volmit.iris.engine.mantle.components;
|
package com.volmit.iris.engine.mantle.components;
|
||||||
|
|
||||||
import com.volmit.iris.engine.data.cache.Cache;
|
import com.volmit.iris.engine.data.cache.Cache;
|
||||||
|
import com.volmit.iris.engine.mantle.ComponentFlag;
|
||||||
import com.volmit.iris.engine.mantle.EngineMantle;
|
import com.volmit.iris.engine.mantle.EngineMantle;
|
||||||
import com.volmit.iris.engine.mantle.IrisMantleComponent;
|
import com.volmit.iris.engine.mantle.IrisMantleComponent;
|
||||||
import com.volmit.iris.engine.mantle.MantleWriter;
|
import com.volmit.iris.engine.mantle.MantleWriter;
|
||||||
@@ -27,16 +28,13 @@ import com.volmit.iris.engine.object.IrisFluidBodies;
|
|||||||
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.documentation.ChunkCoordinates;
|
import com.volmit.iris.util.documentation.ChunkCoordinates;
|
||||||
import com.volmit.iris.util.mantle.MantleFlag;
|
import com.volmit.iris.util.mantle.flag.ReservedFlag;
|
||||||
import com.volmit.iris.util.math.RNG;
|
import com.volmit.iris.util.math.RNG;
|
||||||
import lombok.Getter;
|
|
||||||
|
|
||||||
@Getter
|
@ComponentFlag(ReservedFlag.FLUID_BODIES)
|
||||||
public class MantleFluidBodyComponent extends IrisMantleComponent {
|
public class MantleFluidBodyComponent extends IrisMantleComponent {
|
||||||
private final int radius = computeRadius();
|
|
||||||
|
|
||||||
public MantleFluidBodyComponent(EngineMantle engineMantle) {
|
public MantleFluidBodyComponent(EngineMantle engineMantle) {
|
||||||
super(engineMantle, MantleFlag.FLUID_BODIES, 0);
|
super(engineMantle, ReservedFlag.FLUID_BODIES, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -61,7 +59,7 @@ public class MantleFluidBodyComponent extends IrisMantleComponent {
|
|||||||
bodies.generate(writer, rng, getEngineMantle().getEngine(), cx << 4, -1, cz << 4);
|
bodies.generate(writer, rng, getEngineMantle().getEngine(), cx << 4, -1, cz << 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int computeRadius() {
|
protected int computeRadius() {
|
||||||
int max = 0;
|
int max = 0;
|
||||||
|
|
||||||
max = Math.max(max, getDimension().getFluidBodies().getMaxRange(getData()));
|
max = Math.max(max, getDimension().getFluidBodies().getMaxRange(getData()));
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user