mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2025-12-30 20:39:21 +00:00
Compare commits
216 Commits
3.7.0-1.20
...
dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
97fa0562a4 | ||
|
|
3abe671851 | ||
|
|
e164a3bb5c | ||
|
|
4dfb4441e4 | ||
|
|
e686f67453 | ||
|
|
e2eed4812a | ||
|
|
1737833bfe | ||
|
|
a4c5f46c37 | ||
|
|
025fa833c4 | ||
|
|
98cc82cc3d | ||
|
|
298365f588 | ||
|
|
90e5720e2e | ||
|
|
7cd43791f4 | ||
|
|
a251d192ad | ||
|
|
abfff28f43 | ||
|
|
fbdae4c928 | ||
|
|
93ca26e368 | ||
|
|
8c1db1c223 | ||
|
|
123708601f | ||
|
|
b5ab4968ba | ||
|
|
93ae6037bd | ||
|
|
dd8e487a3b | ||
|
|
d3c8377a12 | ||
|
|
84f3687c0c | ||
|
|
ed1e1f1181 | ||
|
|
528c97f367 | ||
|
|
f7a459f3bc | ||
|
|
cd179b4321 | ||
|
|
6373dbb1b8 | ||
|
|
0b0797f876 | ||
|
|
446acefc91 | ||
|
|
7a44e555b2 | ||
|
|
57d4c2935c | ||
|
|
234fb1b0c4 | ||
|
|
0882b5acc4 | ||
|
|
18da26e1fa | ||
|
|
65aa95f2a5 | ||
|
|
5330ddc4ec | ||
|
|
a7fdd37569 | ||
|
|
a226fea9e2 | ||
|
|
8cea165a29 | ||
|
|
1d7cba184c | ||
|
|
4ca7ea3911 | ||
|
|
ea5919def2 | ||
|
|
be35e49302 | ||
|
|
aadd03990a | ||
|
|
38a579453d | ||
|
|
0bf5da2ca1 | ||
|
|
317848692e | ||
|
|
22118de9e9 | ||
|
|
d7039d120b | ||
|
|
979ee4e7d8 | ||
|
|
f68d45bd30 | ||
|
|
b86d7f303e | ||
|
|
c573843314 | ||
|
|
51a7bef18e | ||
|
|
0e237aa1ad | ||
|
|
b46c413f6b | ||
|
|
f3ef1ca2ae | ||
|
|
703e61dd54 | ||
|
|
e1ec6b7827 | ||
|
|
f94292fdac | ||
|
|
7d153bf985 | ||
|
|
f85f15ed02 | ||
|
|
867686eced | ||
|
|
526efd3ae1 | ||
|
|
9d796bd2a0 | ||
|
|
1a9a5d80ad | ||
|
|
c5c7f9bdc5 | ||
|
|
01a421b732 | ||
|
|
ae92bcf194 | ||
|
|
7e7933858b | ||
|
|
9c073ecbcb | ||
|
|
f4617c1996 | ||
|
|
21a2e4feef | ||
|
|
258d0d3aaa | ||
|
|
27b2fd0823 | ||
|
|
0524adb0df | ||
|
|
3981b0976d | ||
|
|
b5811cae08 | ||
|
|
c998fd1fd9 | ||
|
|
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 | ||
|
|
8f5f44bc96 | ||
|
|
6964b99744 | ||
|
|
11cfd85f6a | ||
|
|
c5416f54fa | ||
|
|
1bc6192c8b | ||
|
|
4b0766c097 | ||
|
|
ec5cb2d646 | ||
|
|
0a30881f87 | ||
|
|
c01a7def5d | ||
|
|
50db1d11a7 | ||
|
|
badf108d56 | ||
|
|
c35c858eee | ||
|
|
cf8243a000 | ||
|
|
cca0bed482 | ||
|
|
a802edc375 | ||
|
|
2929a1f0a7 | ||
|
|
b6f9f68b9f | ||
|
|
73787e21d2 | ||
|
|
5958bcb22e | ||
|
|
8eb35aa8be | ||
|
|
e72abc8c39 | ||
|
|
0a2f35dd8d | ||
|
|
c597c55c2c |
@@ -1,5 +1,3 @@
|
||||
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
|
||||
@@ -24,20 +22,18 @@ import kotlin.system.exitProcess
|
||||
|
||||
buildscript {
|
||||
repositories.maven("https://jitpack.io")
|
||||
dependencies.classpath("com.github.VolmitSoftware:NMSTools:c5cbc46ce6")
|
||||
dependencies.classpath("com.github.VolmitSoftware:NMSTools:c88961416f")
|
||||
}
|
||||
|
||||
plugins {
|
||||
java
|
||||
`java-library`
|
||||
alias(libs.plugins.shadow)
|
||||
alias(libs.plugins.sentry)
|
||||
alias(libs.plugins.download)
|
||||
alias(libs.plugins.runPaper)
|
||||
}
|
||||
|
||||
group = "com.volmit"
|
||||
version = "3.7.0-1.20.1-1.21.7"
|
||||
version = "3.8.0-1.20.1-1.21.10"
|
||||
|
||||
apply<ApiGenerator>()
|
||||
|
||||
@@ -59,14 +55,16 @@ registerCustomOutputTaskUnix("PixelMac", "/Users/test/Desktop/mcserver/plugins")
|
||||
registerCustomOutputTaskUnix("CrazyDev22LT", "/home/julian/Desktop/server/plugins")
|
||||
// ==============================================================
|
||||
|
||||
val serverMinHeap = "2G"
|
||||
val serverMaxHeap = "8G"
|
||||
val serverMinHeap = "10G"
|
||||
val serverMaxHeap = "10G"
|
||||
val additionalFlags = "-XX:+AlwaysPreTouch"
|
||||
//Valid values are: none, truecolor, indexed256, indexed16, indexed8
|
||||
val color = "truecolor"
|
||||
val errorReporting = false
|
||||
val errorReporting = "true" == findProperty("errorReporting")
|
||||
|
||||
val nmsBindings = mapOf(
|
||||
"v1_21_R5" to "1.21.7-R0.1-SNAPSHOT",
|
||||
"v1_21_R6" to "1.21.10-R0.1-SNAPSHOT",
|
||||
"v1_21_R5" to "1.21.8-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",
|
||||
@@ -77,18 +75,14 @@ val nmsBindings = mapOf(
|
||||
"v1_20_R1" to "1.20.1-R0.1-SNAPSHOT",
|
||||
)
|
||||
val jvmVersion = mapOf<String, Int>()
|
||||
nmsBindings.forEach { key, value ->
|
||||
nmsBindings.forEach { (key, value) ->
|
||||
project(":nms:$key") {
|
||||
apply<JavaPlugin>()
|
||||
apply<NMSToolsPlugin>()
|
||||
|
||||
repositories {
|
||||
maven("https://libraries.minecraft.net")
|
||||
}
|
||||
|
||||
extensions.configure(NMSToolsExtension::class) {
|
||||
nmsBinding {
|
||||
jvm = jvmVersion.getOrDefault(key, 21)
|
||||
version = value
|
||||
type = NMSBinding.Type.DIRECT
|
||||
}
|
||||
|
||||
dependencies {
|
||||
@@ -106,22 +100,30 @@ nmsBindings.forEach { key, value ->
|
||||
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", "")
|
||||
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}")
|
||||
jvmArgs(additionalFlags.split(' '))
|
||||
}
|
||||
}
|
||||
|
||||
val included: Configuration by configurations.creating
|
||||
val jarJar: Configuration by configurations.creating
|
||||
dependencies {
|
||||
for (key in nmsBindings.keys) {
|
||||
included(project(":nms:$key", "reobf"))
|
||||
}
|
||||
included(project(":core", "shadow"))
|
||||
jarJar(project(":core:agent"))
|
||||
}
|
||||
|
||||
tasks {
|
||||
jar {
|
||||
inputs.files(included)
|
||||
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 })
|
||||
from(jarJar, provider { included.resolve().map(::zipTree) })
|
||||
archiveFileName.set("Iris-${project.version}.jar")
|
||||
}
|
||||
|
||||
@@ -156,12 +158,13 @@ tasks {
|
||||
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 = "volmit-software"
|
||||
val org = "sentry"
|
||||
val projectName = "iris"
|
||||
exec(cli, "releases", "new", "--auth-token", authToken, "-o", org, "-p", projectName, version)
|
||||
exec(cli, "releases", "set-commits", "--auth-token", authToken, "-o", org, "-p", projectName, version, "--auto", "--ignore-missing")
|
||||
exec(cli, "releases", "finalize", "--auth-token", authToken, "-o", org, "-p", projectName, version)
|
||||
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()
|
||||
}
|
||||
}
|
||||
@@ -277,4 +280,4 @@ fun registerCustomOutputTaskUnix(name: String, path: String) {
|
||||
into(file(path))
|
||||
rename { "Iris.jar" }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
plugins {
|
||||
kotlin("jvm") version "2.0.20"
|
||||
kotlin("jvm") version embeddedKotlinVersion
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
gradlePluginPortal()
|
||||
maven("https://jitpack.io")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation("org.ow2.asm:asm:9.8")
|
||||
implementation("com.github.VolmitSoftware:NMSTools:c88961416f")
|
||||
implementation("io.papermc.paperweight:paperweight-userdev:2.0.0-beta.18")
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.2")
|
||||
}
|
||||
182
buildSrc/src/main/kotlin/NMSBinding.kt
Normal file
182
buildSrc/src/main/kotlin/NMSBinding.kt
Normal file
@@ -0,0 +1,182 @@
|
||||
import NMSBinding.Type
|
||||
import com.volmit.nmstools.NMSToolsExtension
|
||||
import com.volmit.nmstools.NMSToolsPlugin
|
||||
import io.papermc.paperweight.userdev.PaperweightUser
|
||||
import io.papermc.paperweight.userdev.PaperweightUserDependenciesExtension
|
||||
import io.papermc.paperweight.userdev.PaperweightUserExtension
|
||||
import io.papermc.paperweight.userdev.attribute.Obfuscation
|
||||
import io.papermc.paperweight.util.constants.REOBF_CONFIG
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.gradle.api.*
|
||||
import org.gradle.api.attributes.Bundling
|
||||
import org.gradle.api.attributes.Category
|
||||
import org.gradle.api.attributes.LibraryElements
|
||||
import org.gradle.api.attributes.Usage
|
||||
import org.gradle.api.model.ObjectFactory
|
||||
import org.gradle.api.plugins.JavaPluginExtension
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
import org.gradle.internal.extensions.core.extra
|
||||
import org.gradle.jvm.toolchain.JavaLanguageVersion
|
||||
import org.gradle.jvm.toolchain.JavaToolchainService
|
||||
import org.gradle.work.DisableCachingByDefault
|
||||
import java.io.RandomAccessFile
|
||||
import javax.inject.Inject
|
||||
|
||||
class NMSBinding : Plugin<Project> {
|
||||
override fun apply(target: Project): Unit = with(target) {
|
||||
val config = extra["nms"] as? Config ?: throw GradleException("No NMS binding configuration found")
|
||||
val jvm = config.jvm
|
||||
val type = config.type
|
||||
|
||||
if (type == Type.USER_DEV) {
|
||||
plugins.apply(PaperweightUser::class.java)
|
||||
dependencies.extensions.findByType(PaperweightUserDependenciesExtension::class.java)
|
||||
?.paperDevBundle(config.version)
|
||||
|
||||
val java = extensions.findByType(JavaPluginExtension::class.java) ?: throw GradleException("Java plugin not found")
|
||||
java.toolchain.languageVersion.set(JavaLanguageVersion.of(jvm))
|
||||
|
||||
val javaToolchains = project.extensions.getByType(JavaToolchainService::class.java) ?: throw GradleException("Java toolchain service not found")
|
||||
extensions.configure(PaperweightUserExtension::class.java) {
|
||||
it.javaLauncher.set(javaToolchains.launcherFor(java.toolchain))
|
||||
}
|
||||
} else {
|
||||
extra["nmsTools.useBuildTools"] = type == Type.BUILD_TOOLS
|
||||
plugins.apply(NMSToolsPlugin::class.java)
|
||||
extensions.configure(NMSToolsExtension::class.java) {
|
||||
it.jvm.set(jvm)
|
||||
it.version.set(config.version)
|
||||
}
|
||||
|
||||
configurations.register(REOBF_CONFIG) { conf ->
|
||||
conf.isCanBeConsumed = true
|
||||
conf.isCanBeResolved = false
|
||||
conf.attributes {
|
||||
it.attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage.JAVA_RUNTIME))
|
||||
it.attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category.LIBRARY))
|
||||
it.attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, objects.named(LibraryElements.JAR))
|
||||
it.attribute(Bundling.BUNDLING_ATTRIBUTE, objects.named(Bundling.EXTERNAL))
|
||||
it.attribute(Obfuscation.OBFUSCATION_ATTRIBUTE, objects.named(Obfuscation.OBFUSCATED))
|
||||
}
|
||||
conf.outgoing.artifact(tasks.named("remap"))
|
||||
}
|
||||
}
|
||||
|
||||
val (major, minor) = config.version.parseVersion()
|
||||
if (major <= 20 && minor <= 4) return@with
|
||||
tasks.register("convert", ConversionTask::class.java, type)
|
||||
tasks.named("compileJava") { it.dependsOn("convert") }
|
||||
rootProject.tasks.named("prepareKotlinBuildScriptModel") { it.dependsOn("$path:convert") }
|
||||
}
|
||||
|
||||
@DisableCachingByDefault
|
||||
abstract class ConversionTask @Inject constructor(type: Type) : DefaultTask() {
|
||||
private val pattern: Regex
|
||||
private val replacement: String
|
||||
|
||||
init {
|
||||
group = "nms"
|
||||
inputs.property("type", type)
|
||||
val java = project.extensions.findByType(JavaPluginExtension::class.java) ?: throw GradleException("Java plugin not found")
|
||||
val source = java.sourceSets.named("main").map { it.allJava }
|
||||
inputs.files(source)
|
||||
outputs.files(source)
|
||||
|
||||
if (type == Type.USER_DEV) {
|
||||
pattern = "org\\.bukkit\\.craftbukkit\\.${project.name}".toRegex()
|
||||
replacement = "org.bukkit.craftbukkit"
|
||||
} else {
|
||||
pattern = "org\\.bukkit\\.craftbukkit\\.(?!${project.name})".toRegex()
|
||||
replacement = "org.bukkit.craftbukkit.${project.name}."
|
||||
}
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
fun process() {
|
||||
val dispatcher = Dispatchers.IO.limitedParallelism(16)
|
||||
runBlocking {
|
||||
for (file in inputs.files) {
|
||||
if (file.extension !in listOf("java"))
|
||||
continue
|
||||
|
||||
launch(dispatcher) {
|
||||
val output = ArrayList<String>()
|
||||
var changed = false
|
||||
|
||||
file.bufferedReader().use {
|
||||
for (line in it.lines()) {
|
||||
if (line.startsWith("package") || line.isBlank()) {
|
||||
output += line
|
||||
continue
|
||||
}
|
||||
|
||||
if (!line.startsWith("import")) {
|
||||
if (!changed) return@launch
|
||||
else {
|
||||
output += line
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if (!line.contains(pattern)) {
|
||||
output += line
|
||||
continue
|
||||
}
|
||||
|
||||
output += line.replace(pattern, replacement)
|
||||
changed = true
|
||||
}
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
RandomAccessFile(file, "r").use { raf ->
|
||||
val bytes = ByteArray(NEW_LINE_BYTES.size)
|
||||
raf.seek(raf.length() - bytes.size)
|
||||
raf.readFully(bytes)
|
||||
if (bytes.contentEquals(NEW_LINE_BYTES))
|
||||
output += ""
|
||||
}
|
||||
|
||||
file.writer().use {
|
||||
val iterator = output.iterator()
|
||||
while (iterator.hasNext()) {
|
||||
it.append(iterator.next())
|
||||
if (iterator.hasNext())
|
||||
it.append(NEW_LINE)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum class Type {
|
||||
USER_DEV,
|
||||
BUILD_TOOLS,
|
||||
DIRECT,
|
||||
}
|
||||
}
|
||||
|
||||
private val NEW_LINE = System.lineSeparator()
|
||||
private val NEW_LINE_BYTES = NEW_LINE.encodeToByteArray()
|
||||
private fun String.parseVersion() = substringBefore('-').split(".").let {
|
||||
it[1].toInt() to it[2].toInt()
|
||||
}
|
||||
|
||||
class Config(
|
||||
var jvm: Int = 21,
|
||||
var type: Type = Type.DIRECT
|
||||
) {
|
||||
lateinit var version: String
|
||||
}
|
||||
|
||||
fun Project.nmsBinding(action: Config.() -> Unit) {
|
||||
extra["nms"] = Config().apply(action)
|
||||
plugins.apply(NMSBinding::class.java)
|
||||
}
|
||||
|
||||
private inline fun <reified T : Named> ObjectFactory.named(name: String): T = named(T::class.java, name)
|
||||
@@ -1,5 +1,6 @@
|
||||
import io.github.slimjar.func.slimjar
|
||||
import io.github.slimjar.func.slimjarHelper
|
||||
import io.github.slimjar.resolver.data.Mirror
|
||||
import org.ajoberstar.grgit.Grgit
|
||||
import java.net.URI
|
||||
|
||||
/*
|
||||
@@ -26,6 +27,9 @@ plugins {
|
||||
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"
|
||||
@@ -65,7 +69,7 @@ dependencies {
|
||||
compileOnly(libs.multiverseCore)
|
||||
|
||||
// Shaded
|
||||
implementation(slimjar())
|
||||
implementation(slimjarHelper("spigot"))
|
||||
|
||||
// Dynamically Loaded
|
||||
slim(libs.paralithic)
|
||||
@@ -79,6 +83,7 @@ dependencies {
|
||||
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)
|
||||
@@ -86,11 +91,23 @@ dependencies {
|
||||
slim(libs.zip)
|
||||
slim(libs.gson)
|
||||
slim(libs.asm)
|
||||
slim(libs.bsf)
|
||||
slim(libs.rhino)
|
||||
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 {
|
||||
@@ -98,10 +115,11 @@ java {
|
||||
}
|
||||
|
||||
sentry {
|
||||
url = "http://sentry.volmit.com:8080"
|
||||
autoInstallation.enabled = false
|
||||
includeSourceContext = true
|
||||
|
||||
org = "volmit-software"
|
||||
org = "sentry"
|
||||
projectName = "iris"
|
||||
authToken = findProperty("sentry.auth.token") as String? ?: System.getenv("SENTRY_AUTH_TOKEN")
|
||||
}
|
||||
@@ -117,6 +135,14 @@ slimJar {
|
||||
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")
|
||||
relocate("com.github.benmanes.caffeine", "$lib.caffeine")
|
||||
}
|
||||
|
||||
tasks {
|
||||
@@ -147,12 +173,43 @@ tasks {
|
||||
mergeServiceFiles()
|
||||
//minimize()
|
||||
relocate("io.github.slimjar", "$lib.slimjar")
|
||||
exclude("modules/loader-agent.isolated-jar")
|
||||
}
|
||||
|
||||
sentryCollectSourcesJava {
|
||||
dependsOn(generateTemplates)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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()
|
||||
val templateSource = file("src/main/templates")
|
||||
val templateDest = layout.buildDirectory.dir("generated/sources/templates")
|
||||
val generateTemplates = tasks.register<Copy>("generateTemplates") {
|
||||
inputs.properties(
|
||||
"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 } ?: run {
|
||||
this.logger.error("Git commit hash not found", res.exceptionOrNull())
|
||||
"unknown"
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
from(templateSource)
|
||||
into(templateDest)
|
||||
rename { "com/volmit/iris/$it" }
|
||||
expand(inputs.properties)
|
||||
}
|
||||
|
||||
tasks.generateSentryBundleIdJava {
|
||||
dependsOn(generateTemplates)
|
||||
}
|
||||
|
||||
rootProject.tasks.named("prepareKotlinBuildScriptModel") {
|
||||
dependsOn(generateTemplates)
|
||||
}
|
||||
|
||||
sourceSets.main {
|
||||
java.srcDir(generateTemplates.map { it.outputs })
|
||||
}
|
||||
@@ -22,13 +22,12 @@ import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.IrisWorlds;
|
||||
import com.volmit.iris.core.ServerConfigurator;
|
||||
import com.volmit.iris.core.link.IrisPapiExpansion;
|
||||
import com.volmit.iris.core.link.MultiverseCoreLink;
|
||||
import com.volmit.iris.core.link.MythicMobsLink;
|
||||
import com.volmit.iris.core.loader.IrisData;
|
||||
import com.volmit.iris.core.nms.INMS;
|
||||
import com.volmit.iris.core.nms.v1X.NMSBinding1X;
|
||||
import com.volmit.iris.core.pregenerator.LazyPregenerator;
|
||||
import com.volmit.iris.core.service.StudioSVC;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
@@ -43,7 +42,6 @@ import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.exceptions.IrisException;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.function.NastyRunnable;
|
||||
import com.volmit.iris.util.io.FileWatcher;
|
||||
import com.volmit.iris.util.io.IO;
|
||||
@@ -53,11 +51,11 @@ import com.volmit.iris.util.math.M;
|
||||
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.parallel.MultiBurst;
|
||||
import com.volmit.iris.util.plugin.IrisService;
|
||||
import com.volmit.iris.util.plugin.VolmitPlugin;
|
||||
import com.volmit.iris.util.plugin.VolmitSender;
|
||||
import com.volmit.iris.util.plugin.chunk.ChunkTickets;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import com.volmit.iris.util.scheduling.Queue;
|
||||
import com.volmit.iris.util.scheduling.ShurikenQueue;
|
||||
@@ -66,9 +64,6 @@ import org.bukkit.*;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.command.Command;
|
||||
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.event.*;
|
||||
import org.bukkit.generator.BiomeProvider;
|
||||
@@ -82,12 +77,10 @@ import java.io.*;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.net.URL;
|
||||
import java.util.*;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static com.volmit.iris.core.safeguard.IrisSafeguard.*;
|
||||
import static com.volmit.iris.core.safeguard.ServerBootSFG.passedserversoftware;
|
||||
|
||||
@SuppressWarnings("CanBeFinal")
|
||||
public class Iris extends VolmitPlugin implements Listener {
|
||||
private static final Queue<Runnable> syncJobs = new ShurikenQueue<>();
|
||||
@@ -95,10 +88,11 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
public static Iris instance;
|
||||
public static Bindings.Adventure audiences;
|
||||
public static MultiverseCoreLink linkMultiverseCore;
|
||||
public static MythicMobsLink linkMythicMobs;
|
||||
public static IrisCompat compat;
|
||||
public static FileWatcher configWatcher;
|
||||
public static ChunkTickets tickets;
|
||||
private static VolmitSender sender;
|
||||
private static Thread shutdownHook;
|
||||
|
||||
static {
|
||||
try {
|
||||
@@ -308,9 +302,6 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
public static void info(String format, Object... args) {
|
||||
msg(C.WHITE + String.format(format, args));
|
||||
}
|
||||
public static void safeguard(String format, Object... args) {
|
||||
msg(C.RESET + String.format(format, args));
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public static void later(NastyRunnable object) {
|
||||
@@ -420,6 +411,7 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
pw.println();
|
||||
pw.println();
|
||||
}
|
||||
pw.println("[%%__USER__%%,%%__RESOURCE__%%,%%__PRODUCT__%%,%%__BUILTBYBIT__%%]");
|
||||
|
||||
pw.close();
|
||||
Iris.info("DUMPED! See " + fi.getAbsolutePath());
|
||||
@@ -438,8 +430,7 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
|
||||
public Iris() {
|
||||
instance = this;
|
||||
SlimJar.debug(IrisSettings.get().getSentry().isDebug());
|
||||
SlimJar.load(getDataFolder("cache", "libraries"));
|
||||
SlimJar.load();
|
||||
}
|
||||
|
||||
private void enable() {
|
||||
@@ -450,16 +441,16 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
IO.delete(new File("iris"));
|
||||
compat = IrisCompat.configured(getDataFile("compat.json"));
|
||||
ServerConfigurator.configure();
|
||||
IrisSafeguard.IrisSafeguardSystem();
|
||||
IrisSafeguard.execute();
|
||||
getSender().setTag(getTag());
|
||||
IrisSafeguard.splash(true);
|
||||
IrisSafeguard.splash();
|
||||
tickets = new ChunkTickets();
|
||||
linkMultiverseCore = new MultiverseCoreLink();
|
||||
linkMythicMobs = new MythicMobsLink();
|
||||
configWatcher = new FileWatcher(getDataFile("settings.json"));
|
||||
services.values().forEach(IrisService::onEnable);
|
||||
services.values().forEach(this::registerListener);
|
||||
addShutdownHook();
|
||||
J.s(() -> {
|
||||
J.a(IrisSafeguard::suggestPaper);
|
||||
J.a(() -> IO.delete(getTemp()));
|
||||
J.a(LazyPregenerator::loadLazyGenerators, 100);
|
||||
J.a(this::bstats);
|
||||
@@ -467,51 +458,54 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
J.sr(this::tickQueue, 0);
|
||||
J.s(this::setupPapi);
|
||||
J.a(ServerConfigurator::configure, 20);
|
||||
IrisSafeguard.splash(false);
|
||||
|
||||
autoStartStudio();
|
||||
checkForBukkitWorlds();
|
||||
checkForBukkitWorlds(s -> true);
|
||||
IrisToolbelt.retainMantleDataForSlice(String.class.getCanonicalName());
|
||||
IrisToolbelt.retainMantleDataForSlice(BlockData.class.getCanonicalName());
|
||||
});
|
||||
}
|
||||
|
||||
private void checkForBukkitWorlds() {
|
||||
FileConfiguration fc = new YamlConfiguration();
|
||||
public void addShutdownHook() {
|
||||
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 {
|
||||
fc.load(new File("bukkit.yml"));
|
||||
ConfigurationSection section = fc.getConfigurationSection("worlds");
|
||||
if (section == null) {
|
||||
return;
|
||||
}
|
||||
IrisWorlds.readBukkitWorlds().forEach((s, generator) -> {
|
||||
try {
|
||||
if (Bukkit.getWorld(s) != null || !filter.test(s)) return;
|
||||
|
||||
for (String s : section.getKeys(false)) {
|
||||
ConfigurationSection entry = section.getConfigurationSection(s);
|
||||
if (!entry.contains("generator", true)) {
|
||||
continue;
|
||||
Iris.info("Loading World: %s | Generator: %s", s, generator);
|
||||
var gen = getDefaultWorldGenerator(s, generator);
|
||||
var dim = loadDimension(s, generator);
|
||||
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) {
|
||||
e.printStackTrace();
|
||||
reportError(e);
|
||||
@@ -525,9 +519,10 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
Player r = new KList<>(getServer().getOnlinePlayers()).getRandom();
|
||||
Iris.service(StudioSVC.class).open(r != null ? new VolmitSender(r) : getSender(), 1337, IrisSettings.get().getGenerator().getDefaultWorldType(), (w) -> {
|
||||
J.s(() -> {
|
||||
var spawn = w.getSpawnLocation();
|
||||
for (Player i : getServer().getOnlinePlayers()) {
|
||||
i.setGameMode(GameMode.SPECTATOR);
|
||||
i.teleport(new Location(w, 0, 200, 0));
|
||||
i.teleport(spawn);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -556,27 +551,17 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
enable();
|
||||
super.onEnable();
|
||||
Bukkit.getPluginManager().registerEvents(this, this);
|
||||
setupChecks();
|
||||
}
|
||||
|
||||
public void onDisable() {
|
||||
if (IrisSafeguard.isForceShutdown()) return;
|
||||
services.values().forEach(IrisService::onDisable);
|
||||
Bukkit.getScheduler().cancelTasks(this);
|
||||
HandlerList.unregisterAll((Plugin) this);
|
||||
postShutdown.forEach(Runnable::run);
|
||||
super.onDisable();
|
||||
|
||||
J.attempt(new JarScanner(instance.getJarFile(), "", false)::scan);
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
|
||||
Bukkit.getWorlds()
|
||||
.stream()
|
||||
.map(IrisToolbelt::access)
|
||||
.filter(Objects::nonNull)
|
||||
.forEach(PlatformChunkGenerator::close);
|
||||
|
||||
MultiBurst.burst.close();
|
||||
services.clear();
|
||||
}));
|
||||
J.attempt(new JarScanner(instance.getJarFile(), "", false)::scanAll);
|
||||
}
|
||||
|
||||
private void setupPapi() {
|
||||
@@ -597,49 +582,7 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
|
||||
@Override
|
||||
public String getTag(String subTag) {
|
||||
if (unstablemode) {
|
||||
return C.BOLD + "" + C.DARK_GRAY + "[" + C.BOLD + "" + C.RED + "Iris" + C.BOLD + C.DARK_GRAY + "]" + C.RESET + "" + C.GRAY + ": ";
|
||||
}
|
||||
if (warningmode) {
|
||||
return C.BOLD + "" + C.DARK_GRAY + "[" + C.BOLD + "" + C.GOLD + "Iris" + C.BOLD + C.DARK_GRAY + "]" + C.RESET + "" + C.GRAY + ": ";
|
||||
}
|
||||
return C.BOLD + "" + C.DARK_GRAY + "[" + C.BOLD + "" + C.IRIS + "Iris" + C.BOLD + C.DARK_GRAY + "]" + C.RESET + "" + C.GRAY + ": ";
|
||||
|
||||
}
|
||||
|
||||
private boolean setupChecks() {
|
||||
boolean passed = true;
|
||||
Iris.info("Version Information: " + instance.getServer().getVersion() + " | " + instance.getServer().getBukkitVersion());
|
||||
if (INMS.get() instanceof NMSBinding1X) {
|
||||
passed = false;
|
||||
Iris.warn("============================================");
|
||||
Iris.warn("=");
|
||||
Iris.warn("=");
|
||||
Iris.warn("=");
|
||||
Iris.warn("Iris is not compatible with this version of Minecraft.");
|
||||
Iris.warn("=");
|
||||
Iris.warn("=");
|
||||
Iris.warn("=");
|
||||
Iris.warn("============================================");
|
||||
}
|
||||
|
||||
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("Purpur is a fork of Paper that is optimized for performance and stability.");
|
||||
Iris.info("Plugins that work on Spigot / Paper work on Purpur.");
|
||||
Iris.info("You can download it here: https://purpurmc.org");
|
||||
return false;
|
||||
}
|
||||
return passed;
|
||||
return IrisSafeguard.mode().tag(subTag);
|
||||
}
|
||||
|
||||
private void checkConfigHotload() {
|
||||
@@ -716,7 +659,11 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
Iris.debug("Generator Config: " + w.toString());
|
||||
|
||||
File ff = new File(w.worldFolder(), "iris/pack");
|
||||
if (!ff.exists() || ff.listFiles().length == 0) {
|
||||
var files = ff.listFiles();
|
||||
if (files == null || files.length == 0)
|
||||
IO.delete(ff);
|
||||
|
||||
if (!ff.exists()) {
|
||||
ff.mkdirs();
|
||||
service(StudioSVC.class).installIntoWorld(getSender(), dim.getLoadKey(), w.worldFolder());
|
||||
}
|
||||
@@ -726,13 +673,13 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
|
||||
@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);
|
||||
File pack = new File(Bukkit.getWorldContainer(), String.join(File.separator, worldName, "iris", "pack"));
|
||||
var dimension = pack.isDirectory() ? IrisData.get(pack).getDimensionLoader().load(id) : null;
|
||||
if (dimension == null) dimension = IrisData.loadAnyDimension(id, null);
|
||||
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);
|
||||
dimension = IrisData.loadAnyDimension(id, null);
|
||||
|
||||
if (dimension != null) {
|
||||
Iris.info("Resolved missing dimension, proceeding.");
|
||||
@@ -743,88 +690,11 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
}
|
||||
|
||||
public void splash() {
|
||||
if (!IrisSettings.get().getGeneral().isSplashLogoStartup()) {
|
||||
return;
|
||||
}
|
||||
|
||||
String padd = Form.repeat(" ", 8);
|
||||
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()};
|
||||
if (unstablemode) {
|
||||
info = new String[]{"", "", "", "", "", padd2 + C.RED + " Iris", padd2 + C.GRAY + " by " + C.DARK_RED + "Volmit Software", padd2 + C.GRAY + " v" + C.RED + getDescription().getVersion()};
|
||||
}
|
||||
if (warningmode) {
|
||||
info = new String[]{"", "", "", "", "", padd2 + C.GOLD + " Iris", padd2 + C.GRAY + " by " + C.GOLD + "Volmit Software", padd2 + C.GRAY + " v" + C.GOLD + getDescription().getVersion()};
|
||||
}
|
||||
|
||||
String[] splashstable = {
|
||||
padd + C.GRAY + " @@@@@@@@@@@@@@" + C.DARK_GRAY + "@@@",
|
||||
padd + C.GRAY + " @@&&&&&&&&&" + C.DARK_GRAY + "&&&&&&" + C.IRIS + " .(((()))). ",
|
||||
padd + C.GRAY + "@@@&&&&&&&&" + C.DARK_GRAY + "&&&&&" + C.IRIS + " .((((((())))))). ",
|
||||
padd + C.GRAY + "@@@&&&&&" + C.DARK_GRAY + "&&&&&&&" + C.IRIS + " ((((((((())))))))) " + C.GRAY + " @",
|
||||
padd + C.GRAY + "@@@&&&&" + C.DARK_GRAY + "@@@@@&" + C.IRIS + " ((((((((-))))))))) " + C.GRAY + " @@",
|
||||
padd + C.GRAY + "@@@&&" + C.IRIS + " ((((((({ })))))))) " + C.GRAY + " &&@@@",
|
||||
padd + C.GRAY + "@@" + C.IRIS + " ((((((((-))))))))) " + C.DARK_GRAY + "&@@@@@" + C.GRAY + "&&&&@@@",
|
||||
padd + C.GRAY + "@" + C.IRIS + " ((((((((())))))))) " + C.DARK_GRAY + "&&&&&" + C.GRAY + "&&&&&&&@@@",
|
||||
padd + C.GRAY + "" + C.IRIS + " '((((((()))))))' " + C.DARK_GRAY + "&&&&&" + C.GRAY + "&&&&&&&&@@@",
|
||||
padd + C.GRAY + "" + C.IRIS + " '(((())))' " + C.DARK_GRAY + "&&&&&&&&" + C.GRAY + "&&&&&&&@@",
|
||||
padd + C.GRAY + " " + C.DARK_GRAY + "@@@" + C.GRAY + "@@@@@@@@@@@@@@"
|
||||
};
|
||||
|
||||
String[] splashunstable = {
|
||||
padd + C.GRAY + " @@@@@@@@@@@@@@" + C.DARK_GRAY + "@@@",
|
||||
padd + C.GRAY + " @@&&&&&&&&&" + C.DARK_GRAY + "&&&&&&" + C.RED + " .(((()))). ",
|
||||
padd + C.GRAY + "@@@&&&&&&&&" + C.DARK_GRAY + "&&&&&" + C.RED + " .((((((())))))). ",
|
||||
padd + C.GRAY + "@@@&&&&&" + C.DARK_GRAY + "&&&&&&&" + C.RED + " ((((((((())))))))) " + C.GRAY + " @",
|
||||
padd + C.GRAY + "@@@&&&&" + C.DARK_GRAY + "@@@@@&" + C.RED + " ((((((((-))))))))) " + C.GRAY + " @@",
|
||||
padd + C.GRAY + "@@@&&" + C.RED + " ((((((({ })))))))) " + C.GRAY + " &&@@@",
|
||||
padd + C.GRAY + "@@" + C.RED + " ((((((((-))))))))) " + C.DARK_GRAY + "&@@@@@" + C.GRAY + "&&&&@@@",
|
||||
padd + C.GRAY + "@" + C.RED + " ((((((((())))))))) " + C.DARK_GRAY + "&&&&&" + C.GRAY + "&&&&&&&@@@",
|
||||
padd + C.GRAY + "" + C.RED + " '((((((()))))))' " + C.DARK_GRAY + "&&&&&" + C.GRAY + "&&&&&&&&@@@",
|
||||
padd + C.GRAY + "" + C.RED + " '(((())))' " + C.DARK_GRAY + "&&&&&&&&" + C.GRAY + "&&&&&&&@@",
|
||||
padd + C.GRAY + " " + C.DARK_GRAY + "@@@" + C.GRAY + "@@@@@@@@@@@@@@"
|
||||
};
|
||||
String[] splashwarning = {
|
||||
padd + C.GRAY + " @@@@@@@@@@@@@@" + C.DARK_GRAY + "@@@",
|
||||
padd + C.GRAY + " @@&&&&&&&&&" + C.DARK_GRAY + "&&&&&&" + C.GOLD + " .(((()))). ",
|
||||
padd + C.GRAY + "@@@&&&&&&&&" + C.DARK_GRAY + "&&&&&" + C.GOLD + " .((((((())))))). ",
|
||||
padd + C.GRAY + "@@@&&&&&" + C.DARK_GRAY + "&&&&&&&" + C.GOLD + " ((((((((())))))))) " + C.GRAY + " @",
|
||||
padd + C.GRAY + "@@@&&&&" + C.DARK_GRAY + "@@@@@&" + C.GOLD + " ((((((((-))))))))) " + C.GRAY + " @@",
|
||||
padd + C.GRAY + "@@@&&" + C.GOLD + " ((((((({ })))))))) " + C.GRAY + " &&@@@",
|
||||
padd + C.GRAY + "@@" + C.GOLD + " ((((((((-))))))))) " + C.DARK_GRAY + "&@@@@@" + C.GRAY + "&&&&@@@",
|
||||
padd + C.GRAY + "@" + C.GOLD + " ((((((((())))))))) " + C.DARK_GRAY + "&&&&&" + C.GRAY + "&&&&&&&@@@",
|
||||
padd + C.GRAY + "" + C.GOLD + " '((((((()))))))' " + C.DARK_GRAY + "&&&&&" + C.GRAY + "&&&&&&&&@@@",
|
||||
padd + C.GRAY + "" + C.GOLD + " '(((())))' " + C.DARK_GRAY + "&&&&&&&&" + C.GRAY + "&&&&&&&@@",
|
||||
padd + C.GRAY + " " + C.DARK_GRAY + "@@@" + C.GRAY + "@@@@@@@@@@@@@@"
|
||||
};
|
||||
String[] splash;
|
||||
File freeSpace = new File(Bukkit.getWorldContainer() + ".");
|
||||
if (unstablemode) {
|
||||
splash = splashunstable;
|
||||
} else if (warningmode) {
|
||||
splash = splashwarning;
|
||||
} else {
|
||||
splash = splashstable;
|
||||
}
|
||||
|
||||
if (!passedserversoftware) {
|
||||
Iris.info("Server type & version: " + C.RED + Bukkit.getVersion());
|
||||
} else { Iris.info("Server type & version: " + Bukkit.getVersion()); }
|
||||
Iris.info("Java: " + getJava());
|
||||
if (getHardware.getProcessMemory() < 5999) {
|
||||
Iris.warn("6GB+ Ram is recommended");
|
||||
Iris.warn("Process Memory: " + getHardware.getProcessMemory() + " MB");
|
||||
}
|
||||
Iris.info("Bukkit distro: " + Bukkit.getName());
|
||||
Iris.info("Server type & version: " + Bukkit.getName() + " v" + Bukkit.getVersion());
|
||||
Iris.info("Custom Biomes: " + INMS.get().countCustomBiomes());
|
||||
setupChecks();
|
||||
printPacks();
|
||||
|
||||
for (int i = 0; i < info.length; i++) {
|
||||
splash[i] += info[i];
|
||||
}
|
||||
|
||||
Iris.info("\n\n " + new KList<>(splash).toString("\n") + "\n");
|
||||
IrisSafeguard.mode().trySplash();
|
||||
}
|
||||
|
||||
private void printPacks() {
|
||||
|
||||
@@ -23,7 +23,6 @@ import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.util.io.IO;
|
||||
import com.volmit.iris.util.json.JSONException;
|
||||
import com.volmit.iris.util.json.JSONObject;
|
||||
import com.volmit.iris.util.misc.SlimJar;
|
||||
import com.volmit.iris.util.misc.getHardware;
|
||||
import com.volmit.iris.util.plugin.VolmitSender;
|
||||
import lombok.AllArgsConstructor;
|
||||
@@ -50,11 +49,10 @@ public class IrisSettings {
|
||||
private IrisSettingsSentry sentry = new IrisSettingsSentry();
|
||||
|
||||
public static int getThreadCount(int c) {
|
||||
return switch (c) {
|
||||
return Math.max(switch (c) {
|
||||
case -1, -2, -4 -> Runtime.getRuntime().availableProcessors() / -c;
|
||||
case 0, 1, 2 -> 1;
|
||||
default -> Math.max(c, 2);
|
||||
};
|
||||
}, 1);
|
||||
}
|
||||
|
||||
public static IrisSettings get() {
|
||||
@@ -87,7 +85,6 @@ public class IrisSettings {
|
||||
Iris.error("Configuration Error in settings.json! " + ee.getClass().getSimpleName() + ": " + ee.getMessage());
|
||||
}
|
||||
}
|
||||
SlimJar.debug(settings.general.debug);
|
||||
|
||||
return settings;
|
||||
}
|
||||
@@ -140,6 +137,7 @@ public class IrisSettings {
|
||||
@Data
|
||||
public static class IrisSettingsConcurrency {
|
||||
public int parallelism = -1;
|
||||
public int ioParallelism = -2;
|
||||
public int worldGenParallelism = -1;
|
||||
|
||||
public int getWorldGenThreads() {
|
||||
@@ -161,7 +159,7 @@ public class IrisSettings {
|
||||
private IrisSettingsEngineSVC engineSVC = new IrisSettingsEngineSVC();
|
||||
public boolean trimMantleInStudio = false;
|
||||
public int mantleKeepAlive = 30;
|
||||
public int cacheSize = 4_096;
|
||||
public int noiseCacheSize = 1_024;
|
||||
public int resourceLoaderCacheSize = 1_024;
|
||||
public int objectLoaderCacheSize = 4_096;
|
||||
public int scriptLoaderCacheSize = 512;
|
||||
@@ -178,11 +176,18 @@ public class IrisSettings {
|
||||
|
||||
@Data
|
||||
public static class IrisSettingsUpdater {
|
||||
public int maxConcurrency = 256;
|
||||
public boolean nativeThreads = false;
|
||||
public double threadMultiplier = 2;
|
||||
|
||||
public double chunkLoadSensitivity = 0.7;
|
||||
public MsRange emptyMsRange = new MsRange(80, 100);
|
||||
public MsRange defaultMsRange = new MsRange(20, 40);
|
||||
|
||||
public int getMaxConcurrency() {
|
||||
return Math.max(Math.abs(maxConcurrency), 1);
|
||||
}
|
||||
|
||||
public double getThreadMultiplier() {
|
||||
return Math.min(Math.abs(threadMultiplier), 0.1);
|
||||
}
|
||||
@@ -244,6 +249,10 @@ public class IrisSettings {
|
||||
public String defaultWorldType = "overworld";
|
||||
public int maxBiomeChildDepth = 4;
|
||||
public boolean preventLeafDecay = true;
|
||||
public boolean useMulticore = false;
|
||||
public boolean useMulticoreMantle = false;
|
||||
public boolean offsetNoiseTypes = false;
|
||||
public boolean earlyCustomBlocks = false;
|
||||
}
|
||||
|
||||
@Data
|
||||
@@ -257,6 +266,7 @@ public class IrisSettings {
|
||||
@Data
|
||||
public static class IrisSettingsEngineSVC {
|
||||
public boolean useVirtualThreads = true;
|
||||
public boolean forceMulticoreWrite = false;
|
||||
public int priority = Thread.NORM_PRIORITY;
|
||||
|
||||
public int getPriority() {
|
||||
|
||||
@@ -4,10 +4,14 @@ 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;
|
||||
@@ -25,6 +29,7 @@ public class IrisWorlds {
|
||||
|
||||
private IrisWorlds(KMap<String, String> worlds) {
|
||||
this.worlds = worlds;
|
||||
readBukkitWorlds().forEach(this::put0);
|
||||
save();
|
||||
}
|
||||
|
||||
@@ -50,14 +55,33 @@ public class IrisWorlds {
|
||||
}
|
||||
|
||||
public void put(String name, String type) {
|
||||
String old = worlds.put(name, type);
|
||||
if (!type.equals(old))
|
||||
dirty = true;
|
||||
put0(name, type);
|
||||
save();
|
||||
}
|
||||
|
||||
public Stream<File> getFolders() {
|
||||
return worlds.keySet().stream().map(k -> new File(Bukkit.getWorldContainer(), k));
|
||||
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() {
|
||||
@@ -76,4 +100,27 @@ public class IrisWorlds {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,14 +103,14 @@ public class ServerConfigurator {
|
||||
return worlds;
|
||||
}
|
||||
|
||||
public static void installDataPacks(boolean fullInstall) {
|
||||
installDataPacks(DataVersion.getDefault(), fullInstall);
|
||||
public static boolean installDataPacks(boolean 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;
|
||||
return false;
|
||||
}
|
||||
Iris.info("Checking Data Packs...");
|
||||
DimensionHeight height = new DimensionHeight(fixer);
|
||||
@@ -129,11 +129,10 @@ public class ServerConfigurator {
|
||||
IrisDimension.writeShared(folders, height);
|
||||
Iris.info("Data Packs Setup!");
|
||||
|
||||
if (fullInstall)
|
||||
verifyDataPacksPost(IrisSettings.get().getAutoConfiguration().isAutoRestartOnCustomBiomeInstall());
|
||||
return fullInstall && verifyDataPacksPost(IrisSettings.get().getAutoConfiguration().isAutoRestartOnCustomBiomeInstall());
|
||||
}
|
||||
|
||||
private static void verifyDataPacksPost(boolean allowRestarting) {
|
||||
private static boolean verifyDataPacksPost(boolean allowRestarting) {
|
||||
try (Stream<IrisData> stream = allPacks()) {
|
||||
boolean bad = stream
|
||||
.map(data -> {
|
||||
@@ -148,7 +147,7 @@ public class ServerConfigurator {
|
||||
})
|
||||
.toList()
|
||||
.contains(true);
|
||||
if (!bad) return;
|
||||
if (!bad) return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -172,6 +171,7 @@ public class ServerConfigurator {
|
||||
|
||||
J.sleep(3000);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void restart() {
|
||||
@@ -237,14 +237,13 @@ public class ServerConfigurator {
|
||||
}
|
||||
|
||||
public static Stream<IrisData> allPacks() {
|
||||
return Stream.concat(listFiles(Iris.instance.getDataFolder("packs")),
|
||||
IrisWorlds.get().getFolders().map(w -> new File(w, "iris/pack")))
|
||||
return Stream.concat(listFiles(Iris.instance.getDataFolder("packs"))
|
||||
.filter(File::isDirectory)
|
||||
.filter( base -> {
|
||||
var content = new File(base, "dimensions").listFiles();
|
||||
return content != null && content.length > 0;
|
||||
})
|
||||
.map(IrisData::get);
|
||||
.map(IrisData::get), IrisWorlds.get().getPacks());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -18,29 +18,44 @@
|
||||
|
||||
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.core.ServerConfigurator;
|
||||
import com.volmit.iris.core.loader.IrisData;
|
||||
import com.volmit.iris.core.nms.INMS;
|
||||
import com.volmit.iris.core.nms.datapack.DataVersion;
|
||||
import com.volmit.iris.core.service.IrisEngineSVC;
|
||||
import com.volmit.iris.core.tools.IrisPackBenchmarking;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.object.IrisDimension;
|
||||
import com.volmit.iris.engine.object.IrisPosition;
|
||||
import com.volmit.iris.engine.object.annotations.Snippet;
|
||||
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.engine.object.IrisJigsawStructurePlacement;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.decree.DecreeExecutor;
|
||||
import com.volmit.iris.util.decree.DecreeOrigin;
|
||||
import com.volmit.iris.util.decree.annotations.Decree;
|
||||
import com.volmit.iris.util.decree.annotations.Param;
|
||||
import com.volmit.iris.util.decree.specialhandlers.NullableDimensionHandler;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.io.CountingDataInputStream;
|
||||
import com.volmit.iris.util.io.IO;
|
||||
import com.volmit.iris.util.mantle.TectonicPlate;
|
||||
import com.volmit.iris.util.math.M;
|
||||
import com.volmit.iris.util.matter.Matter;
|
||||
import com.volmit.iris.util.nbt.mca.MCAFile;
|
||||
import com.volmit.iris.util.nbt.mca.MCAUtil;
|
||||
import com.volmit.iris.util.parallel.MultiBurst;
|
||||
import com.volmit.iris.util.plugin.VolmitSender;
|
||||
import com.volmit.iris.util.scheduling.jobs.Job;
|
||||
import lombok.SneakyThrows;
|
||||
import net.jpountz.lz4.LZ4BlockInputStream;
|
||||
import net.jpountz.lz4.LZ4BlockOutputStream;
|
||||
import net.jpountz.lz4.LZ4FrameInputStream;
|
||||
@@ -53,10 +68,12 @@ import org.bukkit.World;
|
||||
import java.io.*;
|
||||
import java.net.InetAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.nio.file.Files;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
@@ -64,7 +81,6 @@ import java.util.zip.GZIPOutputStream;
|
||||
public class CommandDeveloper implements DecreeExecutor {
|
||||
private CommandTurboPregen turboPregen;
|
||||
private CommandLazyPregen lazyPregen;
|
||||
private CommandUpdater updater;
|
||||
|
||||
@Decree(description = "Get Loaded TectonicPlates Count", origin = DecreeOrigin.BOTH, sync = true)
|
||||
public void EngineStatus() {
|
||||
@@ -79,6 +95,151 @@ public class CommandDeveloper implements DecreeExecutor {
|
||||
Iris.reportError(new Exception("This is a test"));
|
||||
}
|
||||
|
||||
@Decree(description = "Dev cmd to fix all the broken objects caused by faulty shrinkwarp")
|
||||
public void fixObjects(
|
||||
@Param(aliases = "dimension", description = "The dimension type to create the world with")
|
||||
IrisDimension type
|
||||
) {
|
||||
if (type == null) {
|
||||
sender().sendMessage("Type cant be null?");
|
||||
return;
|
||||
}
|
||||
|
||||
IrisData dm = IrisData.get(Iris.instance.getDataFolder("packs", type.getLoadKey()));
|
||||
var loader = dm.getObjectLoader();
|
||||
var processed = new KMap<String, IrisPosition>();
|
||||
|
||||
var objects = loader.getPossibleKeys();
|
||||
var pieces = dm.getJigsawPieceLoader().getPossibleKeys();
|
||||
var sender = sender();
|
||||
|
||||
sender.sendMessage(C.IRIS + "Found " + objects.length + " objects in " + type.getLoadKey());
|
||||
sender.sendMessage(C.IRIS + "Found " + pieces.length + " jigsaw pieces in " + type.getLoadKey());
|
||||
|
||||
final int total = objects.length;
|
||||
final AtomicInteger completed = new AtomicInteger();
|
||||
final AtomicInteger changed = new AtomicInteger();
|
||||
|
||||
new Job() {
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Fixing Objects";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
Arrays.stream(pieces).parallel()
|
||||
.map(dm.getJigsawPieceLoader()::load)
|
||||
.filter(Objects::nonNull)
|
||||
.forEach(piece -> {
|
||||
var offset = processed.compute(piece.getObject(), (key, o) -> {
|
||||
if (o != null) return o;
|
||||
var obj = loader.load(key);
|
||||
if (obj == null) return new IrisPosition();
|
||||
|
||||
obj.shrinkwrap();
|
||||
try {
|
||||
if (!obj.getShrinkOffset().isZero()) {
|
||||
changed.incrementAndGet();
|
||||
obj.write(obj.getLoadFile());
|
||||
}
|
||||
completeWork();
|
||||
} catch (IOException e) {
|
||||
Iris.error("Failed to write object " + obj.getLoadKey());
|
||||
e.printStackTrace();
|
||||
return new IrisPosition();
|
||||
}
|
||||
|
||||
return new IrisPosition(obj.getShrinkOffset());
|
||||
});
|
||||
if (offset.getX() == 0 && offset.getY() == 0 && offset.getZ() == 0)
|
||||
return;
|
||||
|
||||
piece.getConnectors().forEach(connector -> connector.setPosition(connector.getPosition().add(offset)));
|
||||
|
||||
try {
|
||||
IO.writeAll(piece.getLoadFile(), dm.getGson().toJson(piece));
|
||||
} catch (IOException e) {
|
||||
Iris.error("Failed to write jigsaw piece " + piece.getLoadKey());
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
|
||||
Arrays.stream(loader.getPossibleKeys()).parallel()
|
||||
.filter(key -> !processed.containsKey(key))
|
||||
.map(loader::load)
|
||||
.forEach(obj -> {
|
||||
if (obj == null) {
|
||||
completeWork();
|
||||
return;
|
||||
}
|
||||
|
||||
obj.shrinkwrap();
|
||||
if (obj.getShrinkOffset().isZero()) {
|
||||
completeWork();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
obj.write(obj.getLoadFile());
|
||||
completeWork();
|
||||
changed.incrementAndGet();
|
||||
} catch (IOException e) {
|
||||
Iris.error("Failed to write object " + obj.getLoadKey());
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void completeWork() {
|
||||
completed.incrementAndGet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTotalWork() {
|
||||
return total;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWorkCompleted() {
|
||||
return completed.get();
|
||||
}
|
||||
}.execute(sender, () -> {
|
||||
var failed = total - completed.get();
|
||||
if (failed != 0) sender.sendMessage(C.IRIS + "" + failed + " objects failed!");
|
||||
if (changed.get() != 0) sender.sendMessage(C.IRIS + "" + changed.get() + " objects had their offsets changed!");
|
||||
else sender.sendMessage(C.IRIS + "No objects had their offsets changed!");
|
||||
});
|
||||
}
|
||||
|
||||
@Decree(description = "Test")
|
||||
public void mantle(@Param(defaultValue = "false") boolean plate, @Param(defaultValue = "21474836474") String name) throws Throwable {
|
||||
var base = Iris.instance.getDataFile("dump", "pv." + name + ".ttp.lz4b.bin");
|
||||
var section = Iris.instance.getDataFile("dump", "pv." + name + ".section.bin");
|
||||
|
||||
//extractSection(base, section, 5604930, 4397);
|
||||
|
||||
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 {
|
||||
@@ -115,25 +276,128 @@ public class CommandDeveloper implements DecreeExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(description = "Test")
|
||||
public void benchmarkMantle(
|
||||
@Param(description = "The world to bench", aliases = {"world"})
|
||||
World world
|
||||
) throws IOException, ClassNotFoundException {
|
||||
Engine engine = IrisToolbelt.access(world).getEngine();
|
||||
int maxHeight = engine.getTarget().getHeight();
|
||||
File folder = new File(Bukkit.getWorldContainer(), world.getName());
|
||||
int c = 0;
|
||||
//MCAUtil.read()
|
||||
|
||||
File tectonicplates = new File(folder, "mantle");
|
||||
for (File i : Objects.requireNonNull(tectonicplates.listFiles())) {
|
||||
TectonicPlate.read(maxHeight, i, true);
|
||||
c++;
|
||||
Iris.info("Loaded count: " + c );
|
||||
|
||||
@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 = "null", 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")
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -48,7 +48,7 @@ public class CommandJigsaw implements DecreeExecutor {
|
||||
IrisJigsawPiece piece
|
||||
) {
|
||||
File dest = piece.getLoadFile();
|
||||
new JigsawEditor(player(), piece, IrisData.loadAnyObject(piece.getObject()), dest);
|
||||
new JigsawEditor(player(), piece, IrisData.loadAnyObject(piece.getObject(), data()), dest);
|
||||
}
|
||||
|
||||
@Decree(description = "Place a jigsaw structure")
|
||||
@@ -78,7 +78,7 @@ public class CommandJigsaw implements DecreeExecutor {
|
||||
@Param(description = "The object to use for this piece", customHandler = ObjectHandler.class)
|
||||
String object
|
||||
) {
|
||||
IrisObject o = IrisData.loadAnyObject(object);
|
||||
IrisObject o = IrisData.loadAnyObject(object, data());
|
||||
|
||||
if (object == null) {
|
||||
sender().sendMessage(C.RED + "Failed to find existing object");
|
||||
|
||||
@@ -38,7 +38,6 @@ import com.volmit.iris.util.decree.specialhandlers.ObjectHandler;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.math.Direction;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import com.volmit.iris.util.scheduling.Queue;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
@@ -79,9 +78,9 @@ public class CommandObject implements DecreeExecutor {
|
||||
futureBlockChanges.put(block, block.getBlockData());
|
||||
|
||||
if (d instanceof IrisCustomData data) {
|
||||
block.setBlockData(data.getBase());
|
||||
block.setBlockData(data.getBase(), false);
|
||||
Iris.warn("Tried to place custom block at " + x + ", " + y + ", " + z + " which is not supported!");
|
||||
} else block.setBlockData(d);
|
||||
} else block.setBlockData(d, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -124,6 +123,16 @@ public class CommandObject implements DecreeExecutor {
|
||||
tile.toBukkitTry(world.getBlockAt(xx, yy, zz));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void setData(int xx, int yy, int zz, T data) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T getData(int xx, int yy, int zz, Class<T> t) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Engine getEngine() {
|
||||
return null;
|
||||
@@ -136,11 +145,11 @@ public class CommandObject implements DecreeExecutor {
|
||||
@Param(description = "The object to analyze", customHandler = ObjectHandler.class)
|
||||
String object
|
||||
) {
|
||||
IrisObject o = IrisData.loadAnyObject(object);
|
||||
IrisObject o = IrisData.loadAnyObject(object, data());
|
||||
sender().sendMessage("Object Size: " + o.getW() + " * " + o.getH() + " * " + o.getD() + "");
|
||||
sender().sendMessage("Blocks Used: " + NumberFormat.getIntegerInstance().format(o.getBlocks().size()));
|
||||
|
||||
Queue<BlockData> queue = o.getBlocks().enqueueValues();
|
||||
var queue = o.getBlocks().values();
|
||||
Map<Material, Set<BlockData>> unsorted = new HashMap<>();
|
||||
Map<BlockData, Integer> amounts = new HashMap<>();
|
||||
Map<Material, Integer> materials = new HashMap<>();
|
||||
@@ -201,7 +210,7 @@ public class CommandObject implements DecreeExecutor {
|
||||
|
||||
@Decree(description = "Shrink an object to its minimum size")
|
||||
public void shrink(@Param(description = "The object to shrink", customHandler = ObjectHandler.class) String object) {
|
||||
IrisObject o = IrisData.loadAnyObject(object);
|
||||
IrisObject o = IrisData.loadAnyObject(object, data());
|
||||
sender().sendMessage("Current Object Size: " + o.getW() + " * " + o.getH() + " * " + o.getD());
|
||||
o.shrinkwrap();
|
||||
sender().sendMessage("New Object Size: " + o.getW() + " * " + o.getH() + " * " + o.getD());
|
||||
@@ -325,7 +334,7 @@ public class CommandObject implements DecreeExecutor {
|
||||
// @Param(description = "The scale interpolator to use", defaultValue = "none")
|
||||
// IrisObjectPlacementScaleInterpolator interpolator
|
||||
) {
|
||||
IrisObject o = IrisData.loadAnyObject(object);
|
||||
IrisObject o = IrisData.loadAnyObject(object, data());
|
||||
double maxScale = Double.max(10 - o.getBlocks().size() / 10000d, 1);
|
||||
if (scale > maxScale) {
|
||||
sender().sendMessage(C.YELLOW + "Indicated scale exceeds maximum. Downscaled to maximum: " + maxScale);
|
||||
|
||||
@@ -46,18 +46,19 @@ import com.volmit.iris.util.interpolation.InterpolationMethod;
|
||||
import com.volmit.iris.util.io.IO;
|
||||
import com.volmit.iris.util.json.JSONArray;
|
||||
import com.volmit.iris.util.json.JSONObject;
|
||||
import com.volmit.iris.util.mantle.MantleChunk;
|
||||
import com.volmit.iris.util.math.M;
|
||||
import com.volmit.iris.util.math.Position2;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import com.volmit.iris.util.math.Spiraler;
|
||||
import com.volmit.iris.util.noise.CNG;
|
||||
import com.volmit.iris.util.parallel.BurstExecutor;
|
||||
import com.volmit.iris.util.parallel.MultiBurst;
|
||||
import com.volmit.iris.util.parallel.SyncExecutor;
|
||||
import com.volmit.iris.util.plugin.VolmitSender;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import com.volmit.iris.util.scheduling.O;
|
||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||
import com.volmit.iris.util.scheduling.jobs.QueueJob;
|
||||
import com.volmit.iris.util.scheduling.jobs.ParallelRadiusJob;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.event.inventory.InventoryType;
|
||||
@@ -76,8 +77,8 @@ import java.time.temporal.ChronoUnit;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@@ -91,18 +92,19 @@ public class CommandStudio implements DecreeExecutor {
|
||||
return duration.toString().substring(2).replaceAll("(\\d[HMS])(?!$)", "$1 ").toLowerCase();
|
||||
}
|
||||
|
||||
//TODO fix pack trimming
|
||||
@Decree(description = "Download a project.", aliases = "dl")
|
||||
public void download(
|
||||
@Param(name = "pack", description = "The pack to download", defaultValue = "overworld", aliases = "project")
|
||||
String pack,
|
||||
@Param(name = "branch", description = "The branch to download from", defaultValue = "master")
|
||||
String branch,
|
||||
@Param(name = "trim", description = "Whether or not to download a trimmed version (do not enable when editing)", defaultValue = "false")
|
||||
boolean trim,
|
||||
//@Param(name = "trim", description = "Whether or not to download a trimmed version (do not enable when editing)", defaultValue = "false")
|
||||
//boolean trim,
|
||||
@Param(name = "overwrite", description = "Whether or not to overwrite the pack with the downloaded one", aliases = "force", defaultValue = "false")
|
||||
boolean overwrite
|
||||
) {
|
||||
new CommandIris().download(pack, branch, trim, overwrite);
|
||||
new CommandIris().download(pack, branch, overwrite);
|
||||
}
|
||||
|
||||
@Decree(description = "Open a new studio world", aliases = "o", sync = true)
|
||||
@@ -161,70 +163,74 @@ public class CommandStudio implements DecreeExecutor {
|
||||
@Param(name = "radius", description = "The radius of nearby cunks", defaultValue = "5")
|
||||
int radius
|
||||
) {
|
||||
if (IrisToolbelt.isIrisWorld(player().getWorld())) {
|
||||
VolmitSender sender = sender();
|
||||
J.a(() -> {
|
||||
DecreeContext.touch(sender);
|
||||
PlatformChunkGenerator plat = IrisToolbelt.access(player().getWorld());
|
||||
Engine engine = plat.getEngine();
|
||||
try {
|
||||
Chunk cx = player().getLocation().getChunk();
|
||||
KList<Runnable> js = new KList<>();
|
||||
BurstExecutor b = MultiBurst.burst.burst();
|
||||
b.setMulticore(false);
|
||||
int rad = engine.getMantle().getRadius();
|
||||
for (int i = -(radius + rad); i <= radius + rad; i++) {
|
||||
for (int j = -(radius + rad); j <= radius + rad; j++) {
|
||||
engine.getMantle().getMantle().deleteChunk(i + cx.getX(), j + cx.getZ());
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = -radius; i <= radius; i++) {
|
||||
for (int j = -radius; j <= radius; j++) {
|
||||
int finalJ = j;
|
||||
int finalI = i;
|
||||
b.queue(() -> plat.injectChunkReplacement(player().getWorld(), finalI + cx.getX(), finalJ + cx.getZ(), (f) -> {
|
||||
synchronized (js) {
|
||||
js.add(f);
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
b.complete();
|
||||
sender().sendMessage(C.GREEN + "Regenerating " + Form.f(js.size()) + " Sections");
|
||||
QueueJob<Runnable> r = new QueueJob<>() {
|
||||
final KList<Future<?>> futures = new KList<>();
|
||||
|
||||
@Override
|
||||
public void execute(Runnable runnable) {
|
||||
futures.add(J.sfut(runnable));
|
||||
|
||||
if (futures.size() > 64) {
|
||||
while (futures.isNotEmpty()) {
|
||||
try {
|
||||
futures.remove(0).get();
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Regenerating";
|
||||
}
|
||||
};
|
||||
r.queue(js);
|
||||
r.execute(sender());
|
||||
} catch (Throwable e) {
|
||||
sender().sendMessage("Unable to parse view-distance");
|
||||
}
|
||||
});
|
||||
} else {
|
||||
World world = player().getWorld();
|
||||
if (!IrisToolbelt.isIrisWorld(world)) {
|
||||
sender().sendMessage(C.RED + "You must be in an Iris World to use regen!");
|
||||
}
|
||||
|
||||
VolmitSender sender = sender();
|
||||
var loc = player().getLocation().clone();
|
||||
|
||||
J.a(() -> {
|
||||
PlatformChunkGenerator plat = IrisToolbelt.access(world);
|
||||
Engine engine = plat.getEngine();
|
||||
DecreeContext.touch(sender);
|
||||
try (SyncExecutor executor = new SyncExecutor(20);
|
||||
var service = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors())
|
||||
) {
|
||||
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>();
|
||||
ParallelRadiusJob prep = new ParallelRadiusJob(Integer.MAX_VALUE, service) {
|
||||
@Override
|
||||
protected void execute(int rX, int rZ) {
|
||||
if (Math.abs(rX) <= radius && Math.abs(rZ) <= radius) {
|
||||
mantle.deleteChunk(rX + x, rZ + z);
|
||||
return;
|
||||
}
|
||||
rX += x;
|
||||
rZ += z;
|
||||
chunkMap.put(new Position2(rX, rZ), mantle.getChunk(rX, rZ));
|
||||
mantle.deleteChunk(rX, rZ);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Preparing Mantle";
|
||||
}
|
||||
}.retarget(radius + rad, 0, 0);
|
||||
CountDownLatch pLatch = new CountDownLatch(1);
|
||||
prep.execute(sender(), pLatch::countDown);
|
||||
pLatch.await();
|
||||
|
||||
|
||||
ParallelRadiusJob job = new ParallelRadiusJob(Integer.MAX_VALUE, service) {
|
||||
@Override
|
||||
protected void execute(int x, int z) {
|
||||
plat.injectChunkReplacement(world, x, z, executor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Regenerating";
|
||||
}
|
||||
}.retarget(radius, x, z);
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
job.execute(sender(), latch::countDown);
|
||||
latch.await();
|
||||
|
||||
chunkMap.forEach((pos, chunk) ->
|
||||
mantle.getChunk(pos.getX(), pos.getZ()).copyFrom(chunk));
|
||||
} catch (Throwable e) {
|
||||
sender().sendMessage("Error while regenerating chunks");
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
DecreeContext.remove();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Decree(description = "Convert objects in the \"convert\" folder")
|
||||
@@ -313,11 +319,15 @@ public class CommandStudio implements DecreeExecutor {
|
||||
O<Integer> ta = new O<>();
|
||||
ta.set(-1);
|
||||
|
||||
var sender = sender();
|
||||
var player = player();
|
||||
var engine = engine();
|
||||
|
||||
ta.set(Bukkit.getScheduler().scheduleSyncRepeatingTask(Iris.instance, () ->
|
||||
{
|
||||
if (!player().getOpenInventory().getType().equals(InventoryType.CHEST)) {
|
||||
if (!player.getOpenInventory().getType().equals(InventoryType.CHEST)) {
|
||||
Bukkit.getScheduler().cancelTask(ta.get());
|
||||
sender().sendMessage(C.GREEN + "Opened inventory!");
|
||||
sender.sendMessage(C.GREEN + "Opened inventory!");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -325,13 +335,49 @@ public class CommandStudio implements DecreeExecutor {
|
||||
inv.clear();
|
||||
}
|
||||
|
||||
engine().addItems(true, inv, new RNG(RNG.r.imax()), tables, InventorySlotType.STORAGE, player().getWorld(), player().getLocation().getBlockX(), player().getLocation().getBlockY(), player().getLocation().getBlockZ(), 1);
|
||||
engine.addItems(true, inv, new RNG(RNG.r.imax()), tables, InventorySlotType.STORAGE, player.getWorld(), player.getLocation().getBlockX(), player.getLocation().getBlockY(), player.getLocation().getBlockZ(), 1);
|
||||
}, 0, fast ? 5 : 35));
|
||||
|
||||
sender().sendMessage(C.GREEN + "Opening inventory now!");
|
||||
player().openInventory(inv);
|
||||
}
|
||||
|
||||
@Decree(description = "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)
|
||||
public void distances(@Param(description = "The radius in chunks") int radius) {
|
||||
@@ -343,7 +389,7 @@ public class CommandStudio implements DecreeExecutor {
|
||||
var sender = sender();
|
||||
int d = radius * 2;
|
||||
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);
|
||||
|
||||
sender.sendMessage(C.GRAY + "Generating data...");
|
||||
@@ -642,8 +688,14 @@ public class CommandStudio implements DecreeExecutor {
|
||||
}
|
||||
|
||||
sender().sendMessage(C.GREEN + "Sending you to the studio world!");
|
||||
player().teleport(Iris.service(StudioSVC.class).getActiveProject().getActiveProvider().getTarget().getWorld().spawnLocation());
|
||||
player().setGameMode(GameMode.SPECTATOR);
|
||||
var player = player();
|
||||
PaperLib.teleportAsync(player(), Iris.service(StudioSVC.class)
|
||||
.getActiveProject()
|
||||
.getActiveProvider()
|
||||
.getTarget()
|
||||
.getWorld()
|
||||
.spawnLocation()
|
||||
).thenRun(() -> player.setGameMode(GameMode.SPECTATOR));
|
||||
}
|
||||
|
||||
@Decree(description = "Update your dimension projects VSCode workspace")
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
package com.volmit.iris.core.commands;
|
||||
|
||||
import lombok.Synchronized;
|
||||
import org.bukkit.World;
|
||||
|
||||
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")
|
||||
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")
|
||||
public void start(
|
||||
@@ -43,19 +45,22 @@ public class CommandUpdater implements DecreeExecutor {
|
||||
sender().sendMessage(C.GOLD + "This is not an Iris world");
|
||||
return;
|
||||
}
|
||||
if (chunkUpdater != null) {
|
||||
chunkUpdater.stop();
|
||||
}
|
||||
synchronized (lock) {
|
||||
if (chunkUpdater != null) {
|
||||
chunkUpdater.stop();
|
||||
}
|
||||
|
||||
chunkUpdater = new ChunkUpdater(world);
|
||||
if (sender().isPlayer()) {
|
||||
sender().sendMessage(C.GREEN + "Updating " + world.getName() + C.GRAY + " Total chunks: " + Form.f(chunkUpdater.getChunks()));
|
||||
} else {
|
||||
Iris.info(C.GREEN + "Updating " + world.getName() + C.GRAY + " Total chunks: " + Form.f(chunkUpdater.getChunks()));
|
||||
chunkUpdater = new ChunkUpdater(world);
|
||||
if (sender().isPlayer()) {
|
||||
sender().sendMessage(C.GREEN + "Updating " + world.getName() + C.GRAY + " Total chunks: " + Form.f(chunkUpdater.getChunks()));
|
||||
} else {
|
||||
Iris.info(C.GREEN + "Updating " + world.getName() + C.GRAY + " Total chunks: " + Form.f(chunkUpdater.getChunks()));
|
||||
}
|
||||
chunkUpdater.start();
|
||||
}
|
||||
chunkUpdater.start();
|
||||
}
|
||||
|
||||
@Synchronized("lock")
|
||||
@Decree(description = "Pause the updater")
|
||||
public void pause( ) {
|
||||
if (chunkUpdater == null) {
|
||||
@@ -78,6 +83,7 @@ public class CommandUpdater implements DecreeExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
@Synchronized("lock")
|
||||
@Decree(description = "Stops the updater")
|
||||
public void stop() {
|
||||
if (chunkUpdater == null) {
|
||||
|
||||
@@ -61,14 +61,14 @@ public class JigsawEditor implements Listener {
|
||||
private Location target;
|
||||
|
||||
public JigsawEditor(Player player, IrisJigsawPiece piece, IrisObject object, File saveLocation) {
|
||||
if (editors.containsKey(player)) {
|
||||
editors.get(player).close();
|
||||
}
|
||||
if (object == null) throw new RuntimeException("Object is null! " + piece.getObject());
|
||||
editors.compute(player, ($, current) -> {
|
||||
if (current != null) {
|
||||
current.exit();
|
||||
}
|
||||
return this;
|
||||
});
|
||||
|
||||
editors.put(player, this);
|
||||
if (object == null) {
|
||||
throw new RuntimeException("Object is null! " + piece.getObject());
|
||||
}
|
||||
this.object = object;
|
||||
this.player = player;
|
||||
origin = player.getLocation().clone().add(0, 7, 0);
|
||||
|
||||
@@ -30,7 +30,6 @@ import com.volmit.iris.engine.object.IrisWorld;
|
||||
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.data.registry.Attributes;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.math.BlockPosition;
|
||||
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.PrecisionStopwatch;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.attribute.Attribute;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
@@ -415,8 +413,7 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
||||
}
|
||||
|
||||
private double getWorldX(double screenX) {
|
||||
//return (mscale * screenX) + ((oxp / scale) * mscale);
|
||||
return (mscale * screenX) + ((oxp / scale));
|
||||
return (mscale * screenX) + ((oxp / scale) * mscale);
|
||||
}
|
||||
|
||||
private double getWorldZ(double screenZ) {
|
||||
@@ -486,6 +483,13 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
||||
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()) {
|
||||
J.s(() -> {
|
||||
synchronized (lastEntities) {
|
||||
@@ -510,8 +514,8 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
||||
int iscale = (int) scale;
|
||||
g.setColor(Color.white);
|
||||
g.clearRect(0, 0, w, h);
|
||||
int posX = (int) oxp;
|
||||
int posZ = (int) ozp;
|
||||
double offsetX = oxp / scale;
|
||||
double offsetZ = ozp / scale;
|
||||
m.set(3);
|
||||
|
||||
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 b = j - (h / 2);
|
||||
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) {
|
||||
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) {
|
||||
double cx = getWorldX(getWidth() / 2);
|
||||
double cz = getWorldZ(getHeight() / 2);
|
||||
ox += (wx - cx);
|
||||
oz += (wz - cz);
|
||||
ox += ((wx - cx) / mscale) * scale;
|
||||
oz += ((wz - cz) / mscale) * scale;
|
||||
}
|
||||
|
||||
private void renderPosition(Graphics2D g, double x, double z) {
|
||||
@@ -807,11 +815,28 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
||||
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();
|
||||
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
|
||||
|
||||
@@ -1,24 +1,37 @@
|
||||
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.util.collection.KMap;
|
||||
import com.volmit.iris.util.data.IrisCustomData;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.MissingResourceException;
|
||||
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public abstract class ExternalDataProvider {
|
||||
public abstract class ExternalDataProvider implements Listener {
|
||||
|
||||
@NonNull
|
||||
private final String pluginId;
|
||||
@@ -53,7 +66,21 @@ public abstract class ExternalDataProvider {
|
||||
* @throws MissingResourceException when the blockId is invalid
|
||||
*/
|
||||
@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)
|
||||
@@ -73,7 +100,9 @@ public abstract class ExternalDataProvider {
|
||||
* @throws MissingResourceException when the itemId is invalid
|
||||
*/
|
||||
@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
|
||||
@@ -85,9 +114,57 @@ public abstract class ExternalDataProvider {
|
||||
*/
|
||||
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.ofFloat("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());
|
||||
}
|
||||
}
|
||||
@@ -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.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.reflect.WrappedField;
|
||||
import com.willfp.ecoitems.items.EcoItem;
|
||||
import com.willfp.ecoitems.items.EcoItems;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.MissingResourceException;
|
||||
|
||||
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
|
||||
@Override
|
||||
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();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Identifier[] getBlockTypes() {
|
||||
return new Identifier[0];
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Identifier[] getItemTypes() {
|
||||
KList<Identifier> names = new KList<>();
|
||||
for (EcoItem item : EcoItems.INSTANCE.values()) {
|
||||
try {
|
||||
Identifier key = Identifier.fromNamespacedKey(id.get(item));
|
||||
if (getItemStack(key) != null)
|
||||
names.add(key);
|
||||
} catch (MissingResourceException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
return names.toArray(new Identifier[0]);
|
||||
public @NotNull Collection<@NotNull Identifier> getTypes(@NotNull DataType dataType) {
|
||||
if (dataType != DataType.ITEM) return List.of();
|
||||
return EcoItems.INSTANCE.values()
|
||||
.stream()
|
||||
.map(x -> Identifier.fromNamespacedKey(id.get(x)))
|
||||
.filter(dataType.asPredicate(this))
|
||||
.toList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidProvider(@NotNull Identifier id, boolean isItem) {
|
||||
return id.namespace().equalsIgnoreCase("ecoitems") && isItem;
|
||||
public boolean isValidProvider(@NotNull Identifier id, DataType dataType) {
|
||||
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.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 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.Optional;
|
||||
|
||||
@@ -21,12 +23,6 @@ public class ExecutableItemsDataProvider extends ExternalDataProvider {
|
||||
Iris.info("Setting up ExecutableItems Link...");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public BlockData getBlockData(@NotNull Identifier blockId, @NotNull KMap<String, String> state) throws MissingResourceException {
|
||||
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ItemStack getItemStack(@NotNull Identifier itemId, @NotNull KMap<String, Object> customNbt) throws MissingResourceException {
|
||||
@@ -35,30 +31,19 @@ public class ExecutableItemsDataProvider extends ExternalDataProvider {
|
||||
.orElseThrow(() -> new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key()));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Identifier[] getBlockTypes() {
|
||||
return new Identifier[0];
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Identifier[] getItemTypes() {
|
||||
KList<Identifier> names = new KList<>();
|
||||
for (String name : ExecutableItemsAPI.getExecutableItemsManager().getExecutableItemIdsList()) {
|
||||
try {
|
||||
Identifier key = new Identifier("executable_items", name);
|
||||
if (getItemStack(key) != null)
|
||||
names.add(key);
|
||||
} catch (MissingResourceException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
return names.toArray(new Identifier[0]);
|
||||
public @NotNull Collection<@NotNull Identifier> getTypes(@NotNull DataType dataType) {
|
||||
if (dataType != DataType.ITEM) return List.of();
|
||||
return ExecutableItemsAPI.getExecutableItemsManager()
|
||||
.getExecutableItemIdsList()
|
||||
.stream()
|
||||
.map(name -> new Identifier("executable_items", name))
|
||||
.filter(dataType.asPredicate(this))
|
||||
.toList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidProvider(@NotNull Identifier key, boolean isItem) {
|
||||
return key.namespace().equalsIgnoreCase("executable_items") && isItem;
|
||||
public boolean isValidProvider(@NotNull Identifier key, DataType dataType) {
|
||||
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.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.engine.framework.Engine;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.data.IrisCustomData;
|
||||
import com.volmit.iris.util.reflect.WrappedField;
|
||||
@@ -18,6 +19,8 @@ import org.bukkit.block.data.type.Leaves;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.function.Supplier;
|
||||
@@ -64,7 +67,7 @@ public class HMCLeavesDataProvider extends ExternalDataProvider {
|
||||
BlockData blockData = Bukkit.createBlockData(material);
|
||||
if (IrisSettings.get().getGenerator().preventLeafDecay && blockData instanceof Leaves leaves)
|
||||
leaves.setPersistent(true);
|
||||
return new IrisCustomData(blockData, ExternalDataSVC.buildState(blockId, state));
|
||||
return IrisCustomData.of(blockData, ExternalDataSVC.buildState(blockId, state));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -89,41 +92,20 @@ public class HMCLeavesDataProvider extends ExternalDataProvider {
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Identifier[] getBlockTypes() {
|
||||
KList<Identifier> names = new KList<>();
|
||||
for (String name : blockDataMap.keySet()) {
|
||||
try {
|
||||
Identifier key = new Identifier("hmcleaves", name);
|
||||
if (getBlockData(key) != null)
|
||||
names.add(key);
|
||||
} catch (MissingResourceException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
return names.toArray(new Identifier[0]);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Identifier[] getItemTypes() {
|
||||
KList<Identifier> names = new KList<>();
|
||||
for (String name : itemDataField.keySet()) {
|
||||
try {
|
||||
Identifier key = new Identifier("hmcleaves", name);
|
||||
if (getItemStack(key) != null)
|
||||
names.add(key);
|
||||
} catch (MissingResourceException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
return names.toArray(new Identifier[0]);
|
||||
public @NotNull Collection<@NotNull Identifier> getTypes(@NotNull DataType dataType) {
|
||||
if (dataType == DataType.ENTITY) return List.of();
|
||||
return (dataType == DataType.BLOCK ? blockDataMap.keySet() : itemDataField.keySet())
|
||||
.stream()
|
||||
.map(x -> new Identifier("hmcleaves", x))
|
||||
.filter(dataType.asPredicate(this))
|
||||
.toList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidProvider(@NotNull Identifier id, boolean isItem) {
|
||||
return (isItem ? itemDataField.keySet() : blockDataMap.keySet()).contains(id.key());
|
||||
public boolean isValidProvider(@NotNull Identifier id, DataType dataType) {
|
||||
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) {
|
||||
@@ -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.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.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class ItemAdderDataProvider extends ExternalDataProvider {
|
||||
|
||||
private volatile Set<String> itemNamespaces = Set.of();
|
||||
private volatile Set<String> blockNamespaces = Set.of();
|
||||
|
||||
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 IrisCustomData.of(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());
|
||||
if (dataType == DataType.ITEM) itemNamespaces = namespaces;
|
||||
else blockNamespaces = namespaces;
|
||||
Iris.debug("Updated ItemAdder namespaces: " + dataType + " - " + 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());
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.volmit.iris.core.link;
|
||||
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;
|
||||
@@ -14,6 +16,8 @@ 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 {
|
||||
@@ -29,7 +33,7 @@ public class KGeneratorsDataProvider extends ExternalDataProvider {
|
||||
@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));
|
||||
return IrisCustomData.of(Material.STRUCTURE_VOID.createBlockData(), ExternalDataSVC.buildState(blockId, state));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -54,35 +58,17 @@ public class KGeneratorsDataProvider extends ExternalDataProvider {
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Identifier[] getBlockTypes() {
|
||||
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(i -> {
|
||||
try {
|
||||
return getBlockData(i) != null;
|
||||
} catch (MissingResourceException e) {
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.toArray(Identifier[]::new);
|
||||
.filter(dataType.asPredicate(this))
|
||||
.toList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Identifier[] getItemTypes() {
|
||||
return Main.getGenerators().getAll().stream()
|
||||
.map(gen -> new Identifier("kgenerators", gen.getId()))
|
||||
.filter(i -> {
|
||||
try {
|
||||
return getItemStack(i) != null;
|
||||
} catch (MissingResourceException e) {
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.toArray(Identifier[]::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidProvider(@NotNull Identifier id, boolean isItem) {
|
||||
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.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.scheduling.J;
|
||||
import net.Indyuce.mmoitems.MMOItems;
|
||||
import net.Indyuce.mmoitems.api.ItemTier;
|
||||
import net.Indyuce.mmoitems.api.Type;
|
||||
import net.Indyuce.mmoitems.api.block.CustomBlock;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class MMOItemsDataProvider extends ExternalDataProvider {
|
||||
|
||||
@@ -85,52 +88,35 @@ public class MMOItemsDataProvider extends ExternalDataProvider {
|
||||
return item;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Identifier[] getBlockTypes() {
|
||||
KList<Identifier> names = new KList<>();
|
||||
for (Integer id : api().getCustomBlocks().getBlockIds()) {
|
||||
try {
|
||||
Identifier key = new Identifier("mmoitems", String.valueOf(id));
|
||||
if (getBlockData(key) != null)
|
||||
names.add(key);
|
||||
} catch (MissingResourceException ignored) {
|
||||
}
|
||||
}
|
||||
return names.toArray(new Identifier[0]);
|
||||
}
|
||||
public @NotNull Collection<@NotNull Identifier> getTypes(@NotNull DataType dataType) {
|
||||
return switch (dataType) {
|
||||
case ENTITY -> List.of();
|
||||
case BLOCK -> api().getCustomBlocks().getBlockIds().stream().map(id -> new Identifier("mmoitems", String.valueOf(id)))
|
||||
.filter(dataType.asPredicate(this))
|
||||
.toList();
|
||||
case ITEM -> {
|
||||
Supplier<Collection<Identifier>> supplier = () -> api().getTypes()
|
||||
.getAll()
|
||||
.stream()
|
||||
.flatMap(type -> api()
|
||||
.getTemplates()
|
||||
.getTemplateNames(type)
|
||||
.stream()
|
||||
.map(name -> new Identifier("mmoitems_" + type.getId(), name)))
|
||||
.filter(dataType.asPredicate(this))
|
||||
.toList();
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Identifier[] getItemTypes() {
|
||||
KList<Identifier> names = new KList<>();
|
||||
Runnable run = () -> {
|
||||
for (Type type : api().getTypes().getAll()) {
|
||||
for (String name : api().getTemplates().getTemplateNames(type)) {
|
||||
try {
|
||||
Identifier key = new Identifier("mmoitems_" + type.getId(), name);
|
||||
if (getItemStack(key) != null)
|
||||
names.add(key);
|
||||
} catch (MissingResourceException ignored) {
|
||||
}
|
||||
}
|
||||
if (Bukkit.isPrimaryThread()) yield supplier.get();
|
||||
else yield J.sfut(supplier).join();
|
||||
}
|
||||
};
|
||||
if (Bukkit.isPrimaryThread()) run.run();
|
||||
else {
|
||||
try {
|
||||
J.sfut(run).get();
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
Iris.error("Failed getting MMOItems item types!");
|
||||
Iris.reportError(e);
|
||||
}
|
||||
}
|
||||
return names.toArray(new Identifier[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidProvider(@NotNull Identifier id, boolean isItem) {
|
||||
return isItem ? id.namespace().split("_", 2).length == 2 : id.namespace().equals("mmoitems");
|
||||
public boolean isValidProvider(@NotNull Identifier id, DataType dataType) {
|
||||
if (dataType == DataType.ENTITY) return false;
|
||||
return dataType == DataType.ITEM ? id.namespace().split("_", 2).length == 2 : id.namespace().equals("mmoitems");
|
||||
}
|
||||
|
||||
private MMOItems api() {
|
||||
@@ -16,19 +16,19 @@
|
||||
* 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.core.link.ExternalDataProvider;
|
||||
import com.volmit.iris.core.link.Identifier;
|
||||
import com.volmit.iris.core.nms.INMS;
|
||||
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.engine.data.cache.Cache;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.data.B;
|
||||
import com.volmit.iris.util.data.IrisCustomData;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import io.lumine.mythic.bukkit.BukkitAdapter;
|
||||
import io.lumine.mythic.bukkit.utils.serialize.Chroma;
|
||||
import io.lumine.mythiccrucible.MythicCrucible;
|
||||
@@ -37,11 +37,12 @@ import io.lumine.mythiccrucible.items.ItemManager;
|
||||
import io.lumine.mythiccrucible.items.blocks.CustomBlockItemContext;
|
||||
import io.lumine.mythiccrucible.items.furniture.FurnitureItemContext;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.Optional;
|
||||
|
||||
@@ -71,13 +72,26 @@ public class MythicCrucibleDataProvider extends ExternalDataProvider {
|
||||
CustomBlockItemContext blockItemContext = crucibleItem.getBlockData();
|
||||
FurnitureItemContext furnitureItemContext = crucibleItem.getFurnitureData();
|
||||
if (furnitureItemContext != null) {
|
||||
return new IrisCustomData(B.getAir(), ExternalDataSVC.buildState(blockId, state));
|
||||
return IrisCustomData.of(B.getAir(), ExternalDataSVC.buildState(blockId, state));
|
||||
} else if (blockItemContext != null) {
|
||||
return blockItemContext.getBlockData();
|
||||
}
|
||||
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
|
||||
}
|
||||
|
||||
@Override
|
||||
public @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
|
||||
@Override
|
||||
public ItemStack getItemStack(@NotNull Identifier itemId, @NotNull KMap<String, Object> customNbt) throws MissingResourceException {
|
||||
@@ -88,69 +102,27 @@ public class MythicCrucibleDataProvider extends ExternalDataProvider {
|
||||
.generateItemStack(1));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Identifier[] getBlockTypes() {
|
||||
KList<Identifier> names = new KList<>();
|
||||
for (CrucibleItem item : this.itemManager.getItems()) {
|
||||
if (item.getBlockData() == null) continue;
|
||||
try {
|
||||
Identifier key = new Identifier("crucible", item.getInternalName());
|
||||
if (getBlockData(key) != null) {
|
||||
Iris.info("getBlockTypes: Block loaded '" + item.getInternalName() + "'");
|
||||
names.add(key);
|
||||
}
|
||||
} catch (MissingResourceException ignored) {}
|
||||
}
|
||||
return names.toArray(new Identifier[0]);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Identifier[] getItemTypes() {
|
||||
KList<Identifier> names = new KList<>();
|
||||
for (CrucibleItem item : this.itemManager.getItems()) {
|
||||
try {
|
||||
Identifier key = new Identifier("crucible", item.getInternalName());
|
||||
if (getItemStack(key) != null) {
|
||||
Iris.info("getItemTypes: Item loaded '" + item.getInternalName() + "'");
|
||||
names.add(key);
|
||||
}
|
||||
} catch (MissingResourceException ignored) {}
|
||||
}
|
||||
return names.toArray(new Identifier[0]);
|
||||
public @NotNull Collection<@NotNull Identifier> getTypes(@NotNull DataType dataType) {
|
||||
return itemManager.getItems()
|
||||
.stream()
|
||||
.map(i -> new Identifier("crucible", i.getInternalName()))
|
||||
.filter(dataType.asPredicate(this))
|
||||
.toList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processUpdate(@NotNull Engine engine, @NotNull Block block, @NotNull Identifier blockId) {
|
||||
var pair = ExternalDataSVC.parseState(blockId);
|
||||
var state = pair.getB();
|
||||
blockId = pair.getA();
|
||||
var parsedState = ExternalDataSVC.parseState(blockId);
|
||||
var state = parsedState.getB();
|
||||
blockId = parsedState.getA();
|
||||
|
||||
Optional<CrucibleItem> item = itemManager.getItem(blockId.key());
|
||||
if (item.isEmpty()) return;
|
||||
FurnitureItemContext furniture = item.get().getFurnitureData();
|
||||
if (furniture == null) return;
|
||||
|
||||
float yaw = 0;
|
||||
BlockFace face = BlockFace.NORTH;
|
||||
long seed = engine.getSeedManager().getSeed() + Cache.key(block.getX(), block.getZ()) + block.getY();
|
||||
RNG rng = new RNG(seed);
|
||||
if ("true".equals(state.get("randomYaw"))) {
|
||||
yaw = rng.f(0, 360);
|
||||
} else if (state.containsKey("yaw")) {
|
||||
yaw = Float.parseFloat(state.get("yaw"));
|
||||
}
|
||||
if ("true".equals(state.get("randomFace"))) {
|
||||
BlockFace[] faces = BlockFace.values();
|
||||
face = faces[rng.i(0, faces.length - 1)];
|
||||
} else if (state.containsKey("face")) {
|
||||
face = BlockFace.valueOf(state.get("face").toUpperCase());
|
||||
}
|
||||
if (face == BlockFace.SELF) {
|
||||
face = BlockFace.NORTH;
|
||||
}
|
||||
|
||||
var pair = parseYawAndFace(engine, block, state);
|
||||
BiomeColor type = null;
|
||||
Chroma color = null;
|
||||
try {
|
||||
@@ -161,11 +133,12 @@ public class MythicCrucibleDataProvider extends ExternalDataProvider {
|
||||
if (biomeColor == null) return;
|
||||
color = Chroma.of(biomeColor.getRGB());
|
||||
}
|
||||
furniture.place(block, face, yaw, color);
|
||||
furniture.place(block, pair.getB(), pair.getA(), color);
|
||||
}
|
||||
|
||||
@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");
|
||||
}
|
||||
}
|
||||
@@ -1,89 +1,88 @@
|
||||
/*
|
||||
* 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.data;
|
||||
|
||||
package com.volmit.iris.core.link;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import com.volmit.iris.Iris;
|
||||
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.mobs.entities.SpawnReason;
|
||||
import io.lumine.mythic.api.skills.conditions.ILocationCondition;
|
||||
import io.lumine.mythic.bukkit.BukkitAdapter;
|
||||
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.mobs.ActiveMob;
|
||||
import io.lumine.mythic.core.mobs.MobStack;
|
||||
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.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class MythicMobsLink {
|
||||
|
||||
public MythicMobsLink() {
|
||||
if (getPlugin() == null) return;
|
||||
Iris.instance.registerListener(new ConditionListener());
|
||||
public class MythicMobsDataProvider extends ExternalDataProvider {
|
||||
public MythicMobsDataProvider() {
|
||||
super("MythicMobs");
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return getPlugin() != null;
|
||||
@Override
|
||||
public void init() {
|
||||
}
|
||||
|
||||
public Plugin getPlugin() {
|
||||
return Bukkit.getPluginManager().getPlugin("MythicMobs");
|
||||
@Override
|
||||
public @Nullable Entity spawnMob(@NotNull Location location, @NotNull Identifier entityId) throws MissingResourceException {
|
||||
var mm = spawnMob(BukkitAdapter.adapt(location), entityId);
|
||||
return mm == null ? null : mm.getEntity().getBukkitEntity();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
private ActiveMob spawnMob(AbstractLocation location, Identifier entityId) throws MissingResourceException {
|
||||
var manager = MythicBukkit.inst().getMobManager();
|
||||
var mm = manager.getMythicMob(entityId.key()).orElse(null);
|
||||
if (mm == null) {
|
||||
var stack = manager.getMythicMobStack(entityId.key());
|
||||
if (stack == null) throw new MissingResourceException("Failed to find Mob!", entityId.namespace(), entityId.key());
|
||||
return stack.spawn(location, 1d, SpawnReason.OTHER, null);
|
||||
}
|
||||
return mm.spawn(location, 1d, SpawnReason.OTHER, null, null);
|
||||
}
|
||||
|
||||
public Collection<String> getMythicMobTypes() {
|
||||
return isEnabled() ? MythicBukkit.inst().getMobManager().getMobNames() : List.of();
|
||||
@Override
|
||||
public @NotNull Collection<@NotNull Identifier> getTypes(@NotNull DataType dataType) {
|
||||
if (dataType != DataType.ENTITY) return List.of();
|
||||
var manager = MythicBukkit.inst().getMobManager();
|
||||
return Stream.concat(manager.getMobNames().stream(),
|
||||
manager.getMobStacks()
|
||||
.stream()
|
||||
.map(MobStack::getName)
|
||||
)
|
||||
.distinct()
|
||||
.map(name -> new Identifier("mythicmobs", name))
|
||||
.toList();
|
||||
}
|
||||
|
||||
private static class ConditionListener implements Listener {
|
||||
@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()));
|
||||
}
|
||||
@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 = Sets.newConcurrentHashSet();
|
||||
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;
|
||||
|
||||
@@ -107,10 +106,10 @@ public class MythicMobsLink {
|
||||
}
|
||||
}
|
||||
|
||||
@MythicCondition(author = "CrazyDev22", name = "irisbiome", description = "Tests if the target is within the given list of biomes")
|
||||
@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 = Sets.newConcurrentHashSet();
|
||||
private Set<String> regions = ConcurrentHashMap.newKeySet();
|
||||
|
||||
public IrisRegionCondition(String line, MythicLineConfig mlc) {
|
||||
super(line);
|
||||
@@ -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.NexoFurniture;
|
||||
import com.nexomc.nexo.api.NexoItems;
|
||||
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.container.BiomeColor;
|
||||
import com.volmit.iris.core.nms.container.BlockProperty;
|
||||
import com.volmit.iris.core.service.ExternalDataSVC;
|
||||
import com.volmit.iris.engine.data.cache.Cache;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.data.B;
|
||||
import com.volmit.iris.util.data.IrisCustomData;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import org.bukkit.Color;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.entity.ItemDisplay;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.LeatherArmorMeta;
|
||||
import org.bukkit.inventory.meta.MapMeta;
|
||||
import org.bukkit.inventory.meta.PotionMeta;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public class NexoDataProvider extends ExternalDataProvider {
|
||||
private final AtomicBoolean failed = new AtomicBoolean(false);
|
||||
|
||||
public NexoDataProvider() {
|
||||
super("Nexo");
|
||||
}
|
||||
@@ -49,14 +49,23 @@ public class NexoDataProvider extends ExternalDataProvider {
|
||||
BlockData data = NexoBlocks.blockData(blockId.key());
|
||||
if (data == null)
|
||||
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
|
||||
return new IrisCustomData(data, blockState);
|
||||
return IrisCustomData.of(data, blockState);
|
||||
} else if (NexoFurniture.isFurniture(blockId.key())) {
|
||||
return new IrisCustomData(B.getAir(), blockState);
|
||||
return IrisCustomData.of(B.getAir(), blockState);
|
||||
}
|
||||
|
||||
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
|
||||
@Override
|
||||
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) {
|
||||
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
|
||||
public void processUpdate(@NotNull Engine engine, @NotNull Block block, @NotNull Identifier blockId) {
|
||||
var pair = ExternalDataSVC.parseState(blockId);
|
||||
var state = pair.getB();
|
||||
blockId = pair.getA();
|
||||
var statePair = ExternalDataSVC.parseState(blockId);
|
||||
var state = statePair.getB();
|
||||
blockId = statePair.getA();
|
||||
|
||||
if (NexoBlocks.isCustomBlock(blockId.key())) {
|
||||
NexoBlocks.place(blockId.key(), block.getLocation());
|
||||
@@ -81,26 +95,8 @@ public class NexoDataProvider extends ExternalDataProvider {
|
||||
if (!NexoFurniture.isFurniture(blockId.key()))
|
||||
return;
|
||||
|
||||
float yaw = 0;
|
||||
BlockFace face = BlockFace.NORTH;
|
||||
|
||||
long seed = engine.getSeedManager().getSeed() + Cache.key(block.getX(), block.getZ()) + block.getY();
|
||||
RNG rng = new RNG(seed);
|
||||
if ("true".equals(state.get("randomYaw"))) {
|
||||
yaw = rng.f(0, 360);
|
||||
} else if (state.containsKey("yaw")) {
|
||||
yaw = Float.parseFloat(state.get("yaw"));
|
||||
}
|
||||
if ("true".equals(state.get("randomFace"))) {
|
||||
BlockFace[] faces = BlockFace.values();
|
||||
face = faces[rng.i(0, faces.length - 1)];
|
||||
} else if (state.containsKey("face")) {
|
||||
face = BlockFace.valueOf(state.get("face").toUpperCase());
|
||||
}
|
||||
if (face == BlockFace.SELF) {
|
||||
face = BlockFace.NORTH;
|
||||
}
|
||||
ItemDisplay display = NexoFurniture.place(blockId.key(), block.getLocation(), yaw, face);
|
||||
var pair = parseYawAndFace(engine, block, state);
|
||||
ItemDisplay display = NexoFurniture.place(blockId.key(), block.getLocation(), pair.getA(), pair.getB());
|
||||
if (display == null) return;
|
||||
ItemStack itemStack = display.getItemStack();
|
||||
if (itemStack == null) return;
|
||||
@@ -114,51 +110,31 @@ public class NexoDataProvider extends ExternalDataProvider {
|
||||
var biomeColor = INMS.get().getBiomeColor(block.getLocation(), type);
|
||||
if (biomeColor == null) return;
|
||||
var potionColor = Color.fromARGB(biomeColor.getAlpha(), biomeColor.getRed(), biomeColor.getGreen(), biomeColor.getBlue());
|
||||
if (itemStack.getItemMeta() instanceof PotionMeta meta) {
|
||||
meta.setColor(potionColor);
|
||||
itemStack.setItemMeta(meta);
|
||||
var meta = itemStack.getItemMeta();
|
||||
switch (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);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Identifier[] getBlockTypes() {
|
||||
return NexoItems.itemNames().stream()
|
||||
public @NotNull Collection<@NotNull Identifier> getTypes(@NotNull DataType dataType) {
|
||||
if (dataType == DataType.ENTITY) return List.of();
|
||||
return NexoItems.itemNames()
|
||||
.stream()
|
||||
.map(i -> new Identifier("nexo", i))
|
||||
.filter(i -> {
|
||||
try {
|
||||
return getBlockData(i) != null;
|
||||
} catch (MissingResourceException e) {
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.toArray(Identifier[]::new);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Identifier[] getItemTypes() {
|
||||
return NexoItems.itemNames().stream()
|
||||
.map(i -> new Identifier("nexo", i))
|
||||
.filter(i -> {
|
||||
try {
|
||||
return getItemStack(i) != null;
|
||||
} catch (MissingResourceException e) {
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.toArray(Identifier[]::new);
|
||||
.filter(dataType.asPredicate(this))
|
||||
.toList();
|
||||
}
|
||||
|
||||
@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());
|
||||
}
|
||||
|
||||
@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.JsonWriter;
|
||||
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.framework.Engine;
|
||||
import com.volmit.iris.engine.object.*;
|
||||
@@ -33,21 +34,23 @@ import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.context.IrisContext;
|
||||
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.parallel.BurstExecutor;
|
||||
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.J;
|
||||
import lombok.Data;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
import java.util.*;
|
||||
|
||||
@Data
|
||||
public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
||||
@@ -55,6 +58,7 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
||||
private final File dataFolder;
|
||||
private final int id;
|
||||
private boolean closed = false;
|
||||
private PackEnvironment environment;
|
||||
private ResourceLoader<IrisBiome> biomeLoader;
|
||||
private ResourceLoader<IrisLootTable> lootLoader;
|
||||
private ResourceLoader<IrisRegion> regionLoader;
|
||||
@@ -94,6 +98,10 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
||||
return dataLoaders.computeIfAbsent(dataFolder, IrisData::new);
|
||||
}
|
||||
|
||||
public static Optional<IrisData> getLoaded(File dataFolder) {
|
||||
return Optional.ofNullable(dataLoaders.get(dataFolder));
|
||||
}
|
||||
|
||||
public static void dereference() {
|
||||
dataLoaders.v().forEach(IrisData::cleanupEngine);
|
||||
}
|
||||
@@ -113,92 +121,100 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
||||
Iris.warn(" " + rl.getResourceTypeName() + " @ /" + rl.getFolderName() + ": Cache=" + rl.getLoadCache().getSize() + " Folders=" + rl.getFolders().size());
|
||||
}
|
||||
|
||||
public static IrisObject loadAnyObject(String key) {
|
||||
return loadAny(key, (dm) -> dm.getObjectLoader().load(key, false));
|
||||
public static IrisObject loadAnyObject(String key, @Nullable IrisData nearest) {
|
||||
return loadAny(IrisObject.class, key, nearest);
|
||||
}
|
||||
|
||||
public static IrisMatterObject loadAnyMatter(String key) {
|
||||
return loadAny(key, (dm) -> dm.getMatterLoader().load(key, false));
|
||||
public static IrisMatterObject loadAnyMatter(String key, @Nullable IrisData nearest) {
|
||||
return loadAny(IrisMatterObject.class, key, nearest);
|
||||
}
|
||||
|
||||
public static IrisBiome loadAnyBiome(String key) {
|
||||
return loadAny(key, (dm) -> dm.getBiomeLoader().load(key, false));
|
||||
public static IrisBiome loadAnyBiome(String key, @Nullable IrisData nearest) {
|
||||
return loadAny(IrisBiome.class, key, nearest);
|
||||
}
|
||||
|
||||
public static IrisExpression loadAnyExpression(String key) {
|
||||
return loadAny(key, (dm) -> dm.getExpressionLoader().load(key, false));
|
||||
public static IrisExpression loadAnyExpression(String key, @Nullable IrisData nearest) {
|
||||
return loadAny(IrisExpression.class, key, nearest);
|
||||
}
|
||||
|
||||
public static IrisMod loadAnyMod(String key) {
|
||||
return loadAny(key, (dm) -> dm.getModLoader().load(key, false));
|
||||
public static IrisMod loadAnyMod(String key, @Nullable IrisData nearest) {
|
||||
return loadAny(IrisMod.class, key, nearest);
|
||||
}
|
||||
|
||||
public static IrisJigsawPiece loadAnyJigsawPiece(String key) {
|
||||
return loadAny(key, (dm) -> dm.getJigsawPieceLoader().load(key, false));
|
||||
public static IrisJigsawPiece loadAnyJigsawPiece(String key, @Nullable IrisData nearest) {
|
||||
return loadAny(IrisJigsawPiece.class, key, nearest);
|
||||
}
|
||||
|
||||
public static IrisJigsawPool loadAnyJigsawPool(String key) {
|
||||
return loadAny(key, (dm) -> dm.getJigsawPoolLoader().load(key, false));
|
||||
public static IrisJigsawPool loadAnyJigsawPool(String key, @Nullable IrisData nearest) {
|
||||
return loadAny(IrisJigsawPool.class, key, nearest);
|
||||
}
|
||||
|
||||
public static IrisEntity loadAnyEntity(String key) {
|
||||
return loadAny(key, (dm) -> dm.getEntityLoader().load(key, false));
|
||||
public static IrisEntity loadAnyEntity(String key, @Nullable IrisData nearest) {
|
||||
return loadAny(IrisEntity.class, key, nearest);
|
||||
}
|
||||
|
||||
public static IrisLootTable loadAnyLootTable(String key) {
|
||||
return loadAny(key, (dm) -> dm.getLootLoader().load(key, false));
|
||||
public static IrisLootTable loadAnyLootTable(String key, @Nullable IrisData nearest) {
|
||||
return loadAny(IrisLootTable.class, key, nearest);
|
||||
}
|
||||
|
||||
public static IrisBlockData loadAnyBlock(String key) {
|
||||
return loadAny(key, (dm) -> dm.getBlockLoader().load(key, false));
|
||||
public static IrisBlockData loadAnyBlock(String key, @Nullable IrisData nearest) {
|
||||
return loadAny(IrisBlockData.class, key, nearest);
|
||||
}
|
||||
|
||||
public static IrisSpawner loadAnySpaner(String key) {
|
||||
return loadAny(key, (dm) -> dm.getSpawnerLoader().load(key, false));
|
||||
public static IrisSpawner loadAnySpaner(String key, @Nullable IrisData nearest) {
|
||||
return loadAny(IrisSpawner.class, key, nearest);
|
||||
}
|
||||
|
||||
public static IrisScript loadAnyScript(String key) {
|
||||
return loadAny(key, (dm) -> dm.getScriptLoader().load(key, false));
|
||||
public static IrisScript loadAnyScript(String key, @Nullable IrisData nearest) {
|
||||
return loadAny(IrisScript.class, key, nearest);
|
||||
}
|
||||
|
||||
public static IrisRavine loadAnyRavine(String key) {
|
||||
return loadAny(key, (dm) -> dm.getRavineLoader().load(key, false));
|
||||
public static IrisRavine loadAnyRavine(String key, @Nullable IrisData nearest) {
|
||||
return loadAny(IrisRavine.class, key, nearest);
|
||||
}
|
||||
|
||||
public static IrisRegion loadAnyRegion(String key) {
|
||||
return loadAny(key, (dm) -> dm.getRegionLoader().load(key, false));
|
||||
public static IrisRegion loadAnyRegion(String key, @Nullable IrisData nearest) {
|
||||
return loadAny(IrisRegion.class, key, nearest);
|
||||
}
|
||||
|
||||
public static IrisMarker loadAnyMarker(String key) {
|
||||
return loadAny(key, (dm) -> dm.getMarkerLoader().load(key, false));
|
||||
public static IrisMarker loadAnyMarker(String key, @Nullable IrisData nearest) {
|
||||
return loadAny(IrisMarker.class, key, nearest);
|
||||
}
|
||||
|
||||
public static IrisCave loadAnyCave(String key) {
|
||||
return loadAny(key, (dm) -> dm.getCaveLoader().load(key, false));
|
||||
public static IrisCave loadAnyCave(String key, @Nullable IrisData nearest) {
|
||||
return loadAny(IrisCave.class, key, nearest);
|
||||
}
|
||||
|
||||
public static IrisImage loadAnyImage(String key) {
|
||||
return loadAny(key, (dm) -> dm.getImageLoader().load(key, false));
|
||||
public static IrisImage loadAnyImage(String key, @Nullable IrisData nearest) {
|
||||
return loadAny(IrisImage.class, key, nearest);
|
||||
}
|
||||
|
||||
public static IrisDimension loadAnyDimension(String key) {
|
||||
return loadAny(key, (dm) -> dm.getDimensionLoader().load(key, false));
|
||||
public static IrisDimension loadAnyDimension(String key, @Nullable IrisData nearest) {
|
||||
return loadAny(IrisDimension.class, key, nearest);
|
||||
}
|
||||
|
||||
public static IrisJigsawStructure loadAnyJigsawStructure(String key) {
|
||||
return loadAny(key, (dm) -> dm.getJigsawStructureLoader().load(key, false));
|
||||
public static IrisJigsawStructure loadAnyJigsawStructure(String key, @Nullable IrisData nearest) {
|
||||
return loadAny(IrisJigsawStructure.class, key, nearest);
|
||||
}
|
||||
|
||||
public static IrisGenerator loadAnyGenerator(String key) {
|
||||
return loadAny(key, (dm) -> dm.getGeneratorLoader().load(key, false));
|
||||
public static IrisGenerator loadAnyGenerator(String key, @Nullable IrisData nearest) {
|
||||
return loadAny(IrisGenerator.class, key, nearest);
|
||||
}
|
||||
|
||||
public static <T extends IrisRegistrant> T loadAny(String key, Function<IrisData, T> v) {
|
||||
public static <T extends IrisRegistrant> T loadAny(Class<T> type, String key, @Nullable IrisData nearest) {
|
||||
try {
|
||||
if (nearest != null) {
|
||||
T t = nearest.load(type, key, false);
|
||||
if (t != null) {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
for (File i : Objects.requireNonNull(Iris.instance.getDataFolder("packs").listFiles())) {
|
||||
if (i.isDirectory()) {
|
||||
IrisData dm = get(i);
|
||||
T t = v.apply(dm);
|
||||
if (dm == nearest) continue;
|
||||
T t = dm.load(type, key, false);
|
||||
|
||||
if (t != null) {
|
||||
return t;
|
||||
@@ -213,6 +229,17 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
||||
return null;
|
||||
}
|
||||
|
||||
public <T extends IrisRegistrant> T load(Class<T> type, String key, boolean warn) {
|
||||
var loader = getLoader(type);
|
||||
if (loader == null) return null;
|
||||
return loader.load(key, warn);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends IrisRegistrant> ResourceLoader<T> getLoader(Class<T> type) {
|
||||
return (ResourceLoader<T>) loaders.get(type);
|
||||
}
|
||||
|
||||
public ResourceLoader<?> getTypedLoaderFor(File f) {
|
||||
String[] k = f.getPath().split("\\Q" + File.separator + "\\E");
|
||||
|
||||
@@ -252,12 +279,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) {
|
||||
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()) {
|
||||
engine.getExecution().execute(i);
|
||||
for (String i : local) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -271,6 +306,7 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
||||
public void close() {
|
||||
closed = true;
|
||||
dump();
|
||||
dataLoaders.remove(dataFolder);
|
||||
}
|
||||
|
||||
public IrisData copy() {
|
||||
@@ -311,12 +347,14 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
||||
}
|
||||
|
||||
public synchronized void hotloaded() {
|
||||
closed = false;
|
||||
possibleSnippets = new KMap<>();
|
||||
builder = new GsonBuilder()
|
||||
.addDeserializationExclusionStrategy(this)
|
||||
.addSerializationExclusionStrategy(this)
|
||||
.setLenient()
|
||||
.registerTypeAdapterFactory(this)
|
||||
.registerTypeAdapter(MantleFlag.class, new MantleFlagAdapter())
|
||||
.setPrettyPrinting();
|
||||
loaders.clear();
|
||||
File packs = dataFolder;
|
||||
@@ -341,16 +379,18 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
||||
this.imageLoader = registerLoader(IrisImage.class);
|
||||
this.scriptLoader = registerLoader(IrisScript.class);
|
||||
this.matterObjectLoader = registerLoader(IrisMatterObject.class);
|
||||
if (OldEnum.exists()) {
|
||||
builder.registerTypeAdapterFactory(new TypeAdapterFactory() {
|
||||
@Override
|
||||
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
|
||||
return (TypeAdapter<T>) OldEnum.create(type.getRawType());
|
||||
}
|
||||
});
|
||||
}
|
||||
this.environment = PackEnvironment.create(this);
|
||||
builder.registerTypeAdapterFactory(KeyedType::createTypeAdapter);
|
||||
|
||||
gson = builder.create();
|
||||
dimensionLoader.streamAll()
|
||||
.map(IrisDimension::getDataScripts)
|
||||
.flatMap(KList::stream)
|
||||
.forEach(environment::execute);
|
||||
|
||||
if (engine != null) {
|
||||
engine.hotload();
|
||||
}
|
||||
}
|
||||
|
||||
public void dump() {
|
||||
@@ -366,6 +406,33 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
||||
possibleSnippets.clear();
|
||||
}
|
||||
|
||||
public Set<Class<?>> resolveSnippets() {
|
||||
var result = new HashSet<Class<?>>();
|
||||
var processed = new HashSet<Class<?>>();
|
||||
var excluder = gson.excluder();
|
||||
|
||||
var queue = new LinkedList<Class<?>>(loaders.keySet());
|
||||
while (!queue.isEmpty()) {
|
||||
var type = queue.poll();
|
||||
if (excluder.excludeClass(type, false) || !processed.add(type))
|
||||
continue;
|
||||
if (type.isAnnotationPresent(Snippet.class))
|
||||
result.add(type);
|
||||
|
||||
try {
|
||||
for (var field : type.getDeclaredFields()) {
|
||||
if (excluder.excludeField(field, false))
|
||||
continue;
|
||||
|
||||
queue.add(field.getType());
|
||||
}
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public String toLoadKey(File f) {
|
||||
if (f.getPath().startsWith(getDataFolder().getPath())) {
|
||||
String[] full = f.getPath().split("\\Q" + File.separator + "\\E");
|
||||
@@ -412,6 +479,7 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
||||
}
|
||||
|
||||
String snippetType = typeToken.getRawType().getDeclaredAnnotation(Snippet.class).value();
|
||||
String snippedBase = "snippet/" + snippetType + "/";
|
||||
|
||||
return new TypeAdapter<>() {
|
||||
@Override
|
||||
@@ -425,19 +493,20 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
||||
|
||||
if (reader.peek().equals(JsonToken.STRING)) {
|
||||
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");
|
||||
|
||||
if (f.exists()) {
|
||||
try (JsonReader snippetReader = new JsonReader(new FileReader(f))){
|
||||
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());
|
||||
File f = new File(getDataFolder(), r + ".json");
|
||||
if (f.exists()) {
|
||||
try (JsonReader snippetReader = new JsonReader(new FileReader(f))){
|
||||
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());
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -475,7 +544,7 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
||||
.map(s -> s.substring(absPath.length() + 1))
|
||||
.map(s -> s.replace("\\", "/"))
|
||||
.map(s -> s.split("\\Q.\\E")[0])
|
||||
.forEach(s -> l.add("snippet/" + f + "/" + s));
|
||||
.forEach(s -> l.add("snippet/" + s));
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@@ -489,7 +558,7 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
||||
}
|
||||
|
||||
public void savePrefetch(Engine engine) {
|
||||
BurstExecutor b = MultiBurst.burst.burst(loaders.size());
|
||||
BurstExecutor b = MultiBurst.ioBurst.burst(loaders.size());
|
||||
|
||||
for (ResourceLoader<?> i : loaders.values()) {
|
||||
b.queue(() -> {
|
||||
@@ -506,7 +575,7 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
||||
}
|
||||
|
||||
public void loadPrefetch(Engine engine) {
|
||||
BurstExecutor b = MultiBurst.burst.burst(loaders.size());
|
||||
BurstExecutor b = MultiBurst.ioBurst.burst(loaders.size());
|
||||
|
||||
for (ResourceLoader<?> i : loaders.values()) {
|
||||
b.queue(() -> {
|
||||
|
||||
@@ -28,17 +28,19 @@ import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.json.JSONObject;
|
||||
import com.volmit.iris.util.plugin.VolmitSender;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.File;
|
||||
|
||||
@Data
|
||||
public abstract class IrisRegistrant {
|
||||
@Desc("Preprocess this object in-memory when it's loaded, run scripts using the variable 'Iris.getPreprocessorObject()' and modify properties about this object before it's used.")
|
||||
@Desc("Preprocess this object in-memory when it's loaded, run scripts using the variable 'object' and modify properties about this object before it's used.\nFile extension: .proc.kts")
|
||||
@RegistryListResource(IrisScript.class)
|
||||
@ArrayType(min = 1, type = String.class)
|
||||
private KList<String> preprocessors = new KList<>();
|
||||
|
||||
@EqualsAndHashCode.Exclude
|
||||
private transient IrisData loader;
|
||||
|
||||
private transient String loadKey;
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.project.SchemaBuilder;
|
||||
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.MeteredCache;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
@@ -44,10 +45,10 @@ import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
@@ -60,7 +61,7 @@ import java.util.zip.GZIPOutputStream;
|
||||
public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
||||
public static final AtomicDouble tlt = new AtomicDouble(0);
|
||||
private static final int CACHE_SIZE = 100000;
|
||||
protected final AtomicReference<KList<File>> folderCache;
|
||||
protected final AtomicCache<KList<File>> folderCache;
|
||||
protected KSet<String> firstAccess;
|
||||
protected File root;
|
||||
protected String folderName;
|
||||
@@ -76,7 +77,7 @@ public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
||||
public ResourceLoader(File root, IrisData manager, String folderName, String resourceTypeName, Class<? extends T> objectClass) {
|
||||
this.manager = manager;
|
||||
firstAccess = new KSet<>();
|
||||
folderCache = new AtomicReference<>();
|
||||
folderCache = new AtomicCache<>();
|
||||
sec = new ChronoLatch(5000);
|
||||
loads = new AtomicInteger();
|
||||
this.objectClass = objectClass;
|
||||
@@ -170,7 +171,6 @@ public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
||||
return possibleKeys;
|
||||
}
|
||||
|
||||
KSet<String> m = new KSet<>();
|
||||
KList<File> files = getFolders();
|
||||
|
||||
if (files == null) {
|
||||
@@ -178,6 +178,7 @@ public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
||||
return possibleKeys;
|
||||
}
|
||||
|
||||
HashSet<String> m = new HashSet<>();
|
||||
for (File i : files) {
|
||||
for (File j : matchAllFiles(i, (f) -> f.getName().endsWith(".json"))) {
|
||||
m.add(i.toURI().relativize(j.toURI()).getPath().replaceAll("\\Q.json\\E", ""));
|
||||
@@ -216,6 +217,10 @@ public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
||||
return j;
|
||||
}
|
||||
|
||||
public Stream<T> streamAll() {
|
||||
return streamAll(Arrays.stream(getPossibleKeys()));
|
||||
}
|
||||
|
||||
public Stream<T> streamAll(Stream<String> s) {
|
||||
return s.map(this::load);
|
||||
}
|
||||
@@ -236,7 +241,7 @@ public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
||||
|
||||
public KList<T> loadAllParallel(KList<String> s) {
|
||||
KList<T> m = new KList<>();
|
||||
BurstExecutor burst = MultiBurst.burst.burst(s.size());
|
||||
BurstExecutor burst = MultiBurst.ioBurst.burst(s.size());
|
||||
|
||||
for (String i : s) {
|
||||
burst.queue(() -> {
|
||||
@@ -315,7 +320,8 @@ public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
||||
return null;
|
||||
}
|
||||
|
||||
firstAccess.add(name);
|
||||
var set = firstAccess;
|
||||
if (set != null) firstAccess.add(name);
|
||||
return loadCache.get(name);
|
||||
}
|
||||
|
||||
@@ -338,21 +344,24 @@ public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
||||
}
|
||||
|
||||
din.close();
|
||||
file.deleteOnExit();
|
||||
Iris.info("Loading " + s.size() + " prefetch " + getFolderName());
|
||||
firstAccess = null;
|
||||
loadAllParallel(s);
|
||||
}
|
||||
|
||||
public void saveFirstAccess(Engine engine) throws IOException {
|
||||
if (firstAccess == null) return;
|
||||
String id = "DIM" + Math.abs(engine.getSeedManager().getSeed() + engine.getDimension().getVersion() + engine.getDimension().getLoadKey().hashCode());
|
||||
File file = Iris.instance.getDataFile("prefetch/" + id + "/" + Math.abs(getFolderName().hashCode()) + ".ipfch");
|
||||
file.getParentFile().mkdirs();
|
||||
FileOutputStream fos = new FileOutputStream(file);
|
||||
GZIPOutputStream gzo = new CustomOutputStream(fos, 9);
|
||||
DataOutputStream dos = new DataOutputStream(gzo);
|
||||
dos.writeInt(firstAccess.size());
|
||||
var set = firstAccess;
|
||||
firstAccess = null;
|
||||
dos.writeInt(set.size());
|
||||
|
||||
for (String i : firstAccess) {
|
||||
for (String i : set) {
|
||||
dos.writeUTF(i);
|
||||
}
|
||||
|
||||
@@ -361,29 +370,24 @@ public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
||||
}
|
||||
|
||||
public KList<File> getFolders() {
|
||||
synchronized (folderCache) {
|
||||
if (folderCache.get() == null) {
|
||||
KList<File> fc = new KList<>();
|
||||
return folderCache.aquire(() -> {
|
||||
KList<File> fc = new KList<>();
|
||||
|
||||
File[] files = root.listFiles();
|
||||
if (files == null) {
|
||||
throw new IllegalStateException("Failed to list files in " + root);
|
||||
}
|
||||
File[] files = root.listFiles();
|
||||
if (files == null) {
|
||||
throw new IllegalStateException("Failed to list files in " + root);
|
||||
}
|
||||
|
||||
for (File i : files) {
|
||||
if (i.isDirectory()) {
|
||||
if (i.getName().equals(folderName)) {
|
||||
fc.add(i);
|
||||
break;
|
||||
}
|
||||
for (File i : files) {
|
||||
if (i.isDirectory()) {
|
||||
if (i.getName().equals(folderName)) {
|
||||
fc.add(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
folderCache.set(fc);
|
||||
}
|
||||
}
|
||||
|
||||
return folderCache.get();
|
||||
return fc;
|
||||
});
|
||||
}
|
||||
|
||||
public KList<File> getFolders(String rc) {
|
||||
@@ -403,7 +407,7 @@ public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
||||
public void clearCache() {
|
||||
possibleKeys = null;
|
||||
loadCache.invalidate();
|
||||
folderCache.set(null);
|
||||
folderCache.reset();
|
||||
}
|
||||
|
||||
public File fileFor(T b) {
|
||||
@@ -429,7 +433,7 @@ public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
||||
}
|
||||
|
||||
public void clearList() {
|
||||
folderCache.set(null);
|
||||
folderCache.reset();
|
||||
possibleKeys = null;
|
||||
}
|
||||
|
||||
|
||||
@@ -82,8 +82,8 @@ public class ScriptResourceLoader extends ResourceLoader<IrisScript> {
|
||||
private Set<String> getKeysInDirectory(File directory) {
|
||||
Set<String> keys = new HashSet<>();
|
||||
for (File file : directory.listFiles()) {
|
||||
if (file.isFile() && file.getName().endsWith(".js")) {
|
||||
keys.add(file.getName().replaceAll("\\Q.js\\E", ""));
|
||||
if (file.isFile() && file.getName().endsWith(".kts")) {
|
||||
keys.add(file.getName().replaceAll("\\Q.kts\\E", ""));
|
||||
} else if (file.isDirectory()) {
|
||||
keys.addAll(getKeysInDirectory(file));
|
||||
}
|
||||
@@ -127,12 +127,12 @@ public class ScriptResourceLoader extends ResourceLoader<IrisScript> {
|
||||
public File findFile(String name) {
|
||||
for (File i : getFolders(name)) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
File file = new File(i, name + ".js");
|
||||
File file = new File(i, name + ".kts");
|
||||
|
||||
if (file.exists()) {
|
||||
return file;
|
||||
@@ -147,12 +147,12 @@ public class ScriptResourceLoader extends ResourceLoader<IrisScript> {
|
||||
private IrisScript loadRaw(String name) {
|
||||
for (File i : getFolders(name)) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
File file = new File(i, name + ".js");
|
||||
File file = new File(i, name + ".kts");
|
||||
|
||||
if (file.exists()) {
|
||||
return loadFile(file, name);
|
||||
|
||||
@@ -24,21 +24,22 @@ import com.volmit.iris.core.nms.v1X.NMSBinding1X;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class INMS {
|
||||
private static final Map<String, String> REVISION = Map.of(
|
||||
"1.20.5", "v1_20_R4",
|
||||
"1.20.6", "v1_20_R4",
|
||||
"1.21", "v1_21_R1",
|
||||
"1.21.1", "v1_21_R1",
|
||||
"1.21.2", "v1_21_R2",
|
||||
"1.21.3", "v1_21_R2",
|
||||
"1.21.4", "v1_21_R3",
|
||||
"1.21.5", "v1_21_R4",
|
||||
"1.21.6", "v1_21_R5",
|
||||
"1.21.7", "v1_21_R5"
|
||||
private static final Version CURRENT = Boolean.getBoolean("iris.no-version-limit") ?
|
||||
new Version(Integer.MAX_VALUE, Integer.MAX_VALUE, null) :
|
||||
new Version(21, 10, null);
|
||||
|
||||
private static final List<Version> REVISION = List.of(
|
||||
new Version(21, 9, "v1_21_R6"),
|
||||
new Version(21, 6, "v1_21_R5"),
|
||||
new Version(21, 5, "v1_21_R4"),
|
||||
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(
|
||||
new Version(21, 5, "31100"),
|
||||
new Version(21, 4, "31020"),
|
||||
@@ -48,7 +49,7 @@ public class INMS {
|
||||
|
||||
//@done
|
||||
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() {
|
||||
return binding;
|
||||
@@ -62,7 +63,7 @@ public class INMS {
|
||||
try {
|
||||
String name = Bukkit.getServer().getClass().getCanonicalName();
|
||||
if (name.equals("org.bukkit.craftbukkit.CraftServer")) {
|
||||
return REVISION.getOrDefault(Bukkit.getServer().getBukkitVersion().split("-")[0], "BUKKIT");
|
||||
return getTag(REVISION, "BUKKIT");
|
||||
} else {
|
||||
return name.split("\\Q.\\E")[3];
|
||||
}
|
||||
@@ -100,7 +101,7 @@ public class INMS {
|
||||
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);
|
||||
int major = 0;
|
||||
int minor = 0;
|
||||
@@ -111,13 +112,16 @@ public class INMS {
|
||||
} else if (version.length == 2) {
|
||||
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)
|
||||
continue;
|
||||
return p.tag;
|
||||
}
|
||||
return "3910";
|
||||
return def;
|
||||
}
|
||||
|
||||
private record Version(int major, int minor, String tag) {}
|
||||
|
||||
@@ -18,7 +18,12 @@
|
||||
|
||||
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.BiomeColor;
|
||||
import com.volmit.iris.core.nms.container.BlockProperty;
|
||||
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.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.platform.PlatformChunkGenerator;
|
||||
@@ -36,9 +41,9 @@ import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.util.List;
|
||||
|
||||
public interface INMSBinding {
|
||||
boolean hasTile(Material material);
|
||||
@@ -133,4 +138,10 @@ public interface INMSBinding {
|
||||
default boolean injectBukkit() {
|
||||
return true;
|
||||
}
|
||||
|
||||
KMap<Material, List<BlockProperty>> getBlockProperties();
|
||||
|
||||
void placeStructures(Chunk chunk);
|
||||
|
||||
KMap<Identifier, StructurePlacement> collectStructures();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
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 ofFloat(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 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 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,9 +19,13 @@
|
||||
package com.volmit.iris.core.nms.v1X;
|
||||
|
||||
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.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.StructurePlacement;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
@@ -40,6 +44,7 @@ import org.bukkit.generator.structure.Structure;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.util.List;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
public class NMSBinding1X implements INMSBinding {
|
||||
@@ -124,6 +129,25 @@ public class NMSBinding1X implements INMSBinding {
|
||||
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
|
||||
public CompoundTag serializeEntity(Entity location) {
|
||||
return null;
|
||||
|
||||
@@ -2,16 +2,15 @@ package com.volmit.iris.core.pregenerator;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.nms.container.Pair;
|
||||
import com.volmit.iris.core.service.PreservationSVC;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.engine.data.cache.Cache;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.mantle.MantleFlag;
|
||||
import com.volmit.iris.util.mantle.flag.MantleFlag;
|
||||
import com.volmit.iris.util.math.M;
|
||||
import com.volmit.iris.util.math.Position2;
|
||||
import com.volmit.iris.util.math.RollingSequence;
|
||||
import com.volmit.iris.util.plugin.chunk.TicketHolder;
|
||||
import com.volmit.iris.util.profile.LoadBalancer;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import io.papermc.lib.PaperLib;
|
||||
@@ -21,7 +20,6 @@ import org.bukkit.World;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
@@ -31,7 +29,7 @@ public class ChunkUpdater {
|
||||
private static final String REGION_PATH = "region" + File.separator + "r.";
|
||||
private final AtomicBoolean paused = new AtomicBoolean();
|
||||
private final AtomicBoolean cancelled = new AtomicBoolean();
|
||||
private final KMap<Long, Pair<Long, AtomicInteger>> lastUse = new KMap<>();
|
||||
private final TicketHolder holder;
|
||||
private final RollingSequence chunksPerSecond = new RollingSequence(5);
|
||||
private final AtomicInteger totalMaxChunks = new AtomicInteger();
|
||||
private final AtomicInteger chunksProcessed = new AtomicInteger();
|
||||
@@ -39,14 +37,14 @@ public class ChunkUpdater {
|
||||
private final AtomicInteger chunksUpdated = new AtomicInteger();
|
||||
private final AtomicBoolean serverEmpty = new AtomicBoolean(true);
|
||||
private final AtomicLong lastCpsTime = new AtomicLong(M.ms());
|
||||
private final int maxConcurrency = IrisSettings.get().getUpdater().getMaxConcurrency();
|
||||
private final int coreLimit = (int) Math.max(Runtime.getRuntime().availableProcessors() * IrisSettings.get().getUpdater().getThreadMultiplier(), 1);
|
||||
private final Semaphore semaphore = new Semaphore(256);
|
||||
private final LoadBalancer loadBalancer = new LoadBalancer(semaphore, 256, IrisSettings.get().getUpdater().emptyMsRange);
|
||||
private final Semaphore semaphore = new Semaphore(maxConcurrency);
|
||||
private final LoadBalancer loadBalancer = new LoadBalancer(semaphore, maxConcurrency, IrisSettings.get().getUpdater().emptyMsRange);
|
||||
private final AtomicLong startTime = new AtomicLong();
|
||||
private final Dimensions dimensions;
|
||||
private final PregenTask task;
|
||||
private final ExecutorService executor = Executors.newFixedThreadPool(coreLimit);
|
||||
private final ExecutorService chunkExecutor = Executors.newFixedThreadPool(coreLimit);
|
||||
private final ExecutorService chunkExecutor = IrisSettings.get().getUpdater().isNativeThreads() ? Executors.newFixedThreadPool(coreLimit) : Executors.newVirtualThreadPerTaskExecutor();
|
||||
private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
|
||||
private final CountDownLatch latch;
|
||||
private final Engine engine;
|
||||
@@ -55,6 +53,7 @@ public class ChunkUpdater {
|
||||
public ChunkUpdater(World world) {
|
||||
this.engine = IrisToolbelt.access(world).getEngine();
|
||||
this.world = world;
|
||||
this.holder = Iris.tickets.getHolder(world);
|
||||
this.dimensions = calculateWorldDimensions(new File(world.getWorldFolder(), "region"));
|
||||
this.task = dimensions.task();
|
||||
this.totalMaxChunks.set(dimensions.count * 1024);
|
||||
@@ -113,7 +112,6 @@ public class ChunkUpdater {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}, 0, 3, TimeUnit.SECONDS);
|
||||
scheduler.scheduleAtFixedRate(this::unloadChunks, 0, 1, TimeUnit.SECONDS);
|
||||
scheduler.scheduleAtFixedRate(() -> {
|
||||
boolean empty = Bukkit.getOnlinePlayers().isEmpty();
|
||||
if (serverEmpty.getAndSet(empty) == empty)
|
||||
@@ -128,6 +126,7 @@ public class ChunkUpdater {
|
||||
t.setPriority(Thread.MAX_PRIORITY);
|
||||
t.start();
|
||||
|
||||
Iris.service(PreservationSVC.class).register(t);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@@ -138,8 +137,6 @@ public class ChunkUpdater {
|
||||
loadBalancer.close();
|
||||
semaphore.acquire(256);
|
||||
|
||||
executor.shutdown();
|
||||
executor.awaitTermination(5, TimeUnit.SECONDS);
|
||||
chunkExecutor.shutdown();
|
||||
chunkExecutor.awaitTermination(5, TimeUnit.SECONDS);
|
||||
scheduler.shutdownNow();
|
||||
@@ -200,20 +197,16 @@ public class ChunkUpdater {
|
||||
return;
|
||||
}
|
||||
|
||||
var mc = engine.getMantle().getMantle().getChunk(x, z).use();
|
||||
try {
|
||||
Chunk c = world.getChunkAt(x, z);
|
||||
engine.getMantle().getMantle().getChunk(c);
|
||||
engine.updateChunk(c);
|
||||
|
||||
for (int xx = -1; xx <= 1; xx++) {
|
||||
for (int zz = -1; zz <= 1; zz++) {
|
||||
var counter = lastUse.get(Cache.key(x + xx, z + zz));
|
||||
if (counter != null) counter.getB().decrementAndGet();
|
||||
}
|
||||
}
|
||||
removeTickets(x, z);
|
||||
} finally {
|
||||
chunksUpdated.incrementAndGet();
|
||||
chunksProcessed.getAndIncrement();
|
||||
mc.release();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -235,41 +228,16 @@ public class ChunkUpdater {
|
||||
for (int dz = -1; dz <= 1; dz++) {
|
||||
int xx = x + dx;
|
||||
int zz = z + dz;
|
||||
executor.submit(() -> {
|
||||
try {
|
||||
Chunk c;
|
||||
try {
|
||||
c = PaperLib.getChunkAtAsync(world, xx, zz, false, true)
|
||||
.thenApply(chunk -> {
|
||||
if (chunk != null)
|
||||
chunk.addPluginChunkTicket(Iris.instance);
|
||||
return chunk;
|
||||
}).get();
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
generated.set(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (c == null) {
|
||||
generated.set(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!c.isLoaded()) {
|
||||
var future = J.sfut(() -> c.load(false));
|
||||
if (future != null) future.join();
|
||||
}
|
||||
|
||||
if (!PaperLib.isChunkGenerated(c.getWorld(), xx, zz))
|
||||
generated.set(false);
|
||||
|
||||
var pair = lastUse.computeIfAbsent(Cache.key(c), k -> new Pair<>(0L, new AtomicInteger(-1)));
|
||||
pair.setA(M.ms());
|
||||
pair.getB().updateAndGet(i -> i == -1 ? 1 : ++i);
|
||||
} finally {
|
||||
latch.countDown();
|
||||
}
|
||||
});
|
||||
PaperLib.getChunkAtAsync(world, xx, zz, false, true)
|
||||
.thenAccept(chunk -> {
|
||||
if (chunk == null || !chunk.isGenerated()) {
|
||||
latch.countDown();
|
||||
generated.set(false);
|
||||
return;
|
||||
}
|
||||
holder.addTicket(chunk);
|
||||
latch.countDown();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -278,27 +246,16 @@ public class ChunkUpdater {
|
||||
} catch (InterruptedException e) {
|
||||
Iris.info("Interrupted while waiting for chunks to load");
|
||||
}
|
||||
return generated.get();
|
||||
|
||||
if (generated.get()) return true;
|
||||
removeTickets(x, z);
|
||||
return false;
|
||||
}
|
||||
|
||||
private synchronized void unloadChunks() {
|
||||
for (var key : new ArrayList<>(lastUse.keySet())) {
|
||||
if (key == null) continue;
|
||||
var pair = lastUse.get(key);
|
||||
if (pair == null) continue;
|
||||
var lastUseTime = pair.getA();
|
||||
var counter = pair.getB();
|
||||
if (lastUseTime == null || counter == null)
|
||||
continue;
|
||||
|
||||
if (M.ms() - lastUseTime >= 5000 && counter.get() == 0) {
|
||||
int x = Cache.keyX(key);
|
||||
int z = Cache.keyZ(key);
|
||||
J.s(() -> {
|
||||
world.removePluginChunkTicket(x, z, Iris.instance);
|
||||
world.unloadChunk(x, z);
|
||||
lastUse.remove(key);
|
||||
});
|
||||
private void removeTickets(int x, int z) {
|
||||
for (int xx = -1; xx <= 1; xx++) {
|
||||
for (int zz = -1; zz <= 1; zz++) {
|
||||
holder.removeTicket(x + xx, z + zz);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -311,7 +268,6 @@ public class ChunkUpdater {
|
||||
return;
|
||||
}
|
||||
|
||||
unloadChunks();
|
||||
world.save();
|
||||
}).get();
|
||||
} catch (Throwable e) {
|
||||
|
||||
@@ -24,9 +24,11 @@ public interface PregenCache {
|
||||
|
||||
void write();
|
||||
|
||||
void trim(long unloadDuration);
|
||||
|
||||
static PregenCache create(File directory) {
|
||||
if (directory == null) return EMPTY;
|
||||
return new PregenCacheImpl(directory);
|
||||
return new PregenCacheImpl(directory, 16);
|
||||
}
|
||||
|
||||
default PregenCache sync() {
|
||||
@@ -51,19 +53,16 @@ public interface PregenCache {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cacheChunk(int x, int z) {
|
||||
|
||||
}
|
||||
public void cacheChunk(int x, int z) {}
|
||||
|
||||
@Override
|
||||
public void cacheRegion(int x, int z) {
|
||||
|
||||
}
|
||||
public void cacheRegion(int x, int z) {}
|
||||
|
||||
@Override
|
||||
public void write() {
|
||||
public void write() {}
|
||||
|
||||
}
|
||||
@Override
|
||||
public void trim(long unloadDuration) {}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1,218 +0,0 @@
|
||||
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.volmit.iris.Iris;
|
||||
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 javax.annotation.concurrent.NotThreadSafe;
|
||||
import java.io.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
@NotThreadSafe
|
||||
@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)
|
||||
.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) {}
|
||||
}
|
||||
@@ -1,11 +1,6 @@
|
||||
package com.volmit.iris.core.pregenerator.cache;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
|
||||
@AllArgsConstructor
|
||||
class SynchronizedCache implements PregenCache {
|
||||
private final PregenCache cache;
|
||||
|
||||
record SynchronizedCache(PregenCache cache) implements PregenCache {
|
||||
@Override
|
||||
public boolean isThreadSafe() {
|
||||
return true;
|
||||
@@ -45,4 +40,11 @@ class SynchronizedCache implements PregenCache {
|
||||
cache.write();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void trim(long unloadDuration) {
|
||||
synchronized (cache) {
|
||||
cache.trim(unloadDuration);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -192,7 +192,7 @@ public class AsyncPregenMethod implements PregeneratorMethod {
|
||||
private class ServiceExecutor implements Executor {
|
||||
private final ExecutorService service = IrisSettings.get().getPregen().isUseVirtualThreads() ?
|
||||
Executors.newVirtualThreadPerTaskExecutor() :
|
||||
new MultiBurst("Iris Async Pregen", Thread.MIN_PRIORITY);
|
||||
new MultiBurst("Iris Async Pregen");
|
||||
|
||||
public void generate(int x, int z, PregenListener listener) {
|
||||
service.submit(() -> {
|
||||
|
||||
107
core/src/main/java/com/volmit/iris/core/project/Gradle.java
Normal file
107
core/src/main/java/com/volmit/iris/core/project/Gradle.java
Normal file
@@ -0,0 +1,107 @@
|
||||
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.*;
|
||||
|
||||
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);
|
||||
var lines = Collections.synchronizedList(new ArrayList<String>());
|
||||
attach(process.getInputStream(), lines);
|
||||
attach(process.getErrorStream(), lines);
|
||||
var code = process.waitFor();
|
||||
if (code == 0) {
|
||||
lines.forEach(Iris::debug);
|
||||
return;
|
||||
}
|
||||
lines.forEach(Iris::error);
|
||||
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, List<String> list) {
|
||||
Thread.ofPlatform().start(() -> {
|
||||
try (var in = new Scanner(stream)) {
|
||||
while (in.hasNextLine()) {
|
||||
String line = in.nextLine();
|
||||
list.add(line);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -49,6 +49,8 @@ import lombok.Data;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.World;
|
||||
import org.dom4j.Document;
|
||||
import org.dom4j.Element;
|
||||
import org.zeroturnaround.zip.ZipUtil;
|
||||
|
||||
import java.awt.*;
|
||||
@@ -156,7 +158,7 @@ public class IrisProject {
|
||||
|
||||
public void openVSCode(VolmitSender sender) {
|
||||
|
||||
IrisDimension d = IrisData.loadAnyDimension(getName());
|
||||
IrisDimension d = IrisData.loadAnyDimension(getName(), null);
|
||||
J.attemptAsync(() ->
|
||||
{
|
||||
try {
|
||||
@@ -217,24 +219,15 @@ public class IrisProject {
|
||||
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(() -> {
|
||||
IrisDimension d = IrisData.loadAnyDimension(getName(), null);
|
||||
if (d == null) {
|
||||
sender.sendMessage("Can't find dimension: " + getName());
|
||||
return;
|
||||
} else if (sender.isPlayer()) {
|
||||
J.s(() -> sender.player().setGameMode(GameMode.SPECTATOR));
|
||||
}
|
||||
|
||||
try {
|
||||
activeProvider = (PlatformChunkGenerator) IrisToolbelt.createWorld()
|
||||
.seed(seed)
|
||||
@@ -247,6 +240,8 @@ public class IrisProject {
|
||||
} catch (IrisException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
openVSCode(sender);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -330,7 +325,7 @@ public class IrisProject {
|
||||
}
|
||||
}
|
||||
|
||||
for (Class<?> i : Iris.getClasses("com.volmit.iris.engine.object.", Snippet.class)) {
|
||||
for (Class<?> i : dm.resolveSnippets()) {
|
||||
try {
|
||||
String snipType = i.getDeclaredAnnotation(Snippet.class).value();
|
||||
JSONObject o = new JSONObject();
|
||||
@@ -359,6 +354,74 @@ public class IrisProject {
|
||||
settings.put("json.schemas", schemas);
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,27 +19,30 @@
|
||||
package com.volmit.iris.core.project;
|
||||
|
||||
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.IrisRegistrant;
|
||||
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.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.data.B;
|
||||
import com.volmit.iris.util.json.JSONArray;
|
||||
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.potion.PotionEffectType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.awt.*;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InaccessibleObjectException;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class SchemaBuilder {
|
||||
private static final String SYMBOL_LIMIT__N = "*";
|
||||
@@ -108,47 +111,27 @@ public class SchemaBuilder {
|
||||
private JSONObject buildProperties(Class<?> c) {
|
||||
JSONObject o = 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));
|
||||
JSONArray required = new JSONArray();
|
||||
JSONArray extended = new JSONArray();
|
||||
|
||||
if (c.isAssignableFrom(IrisRegistrant.class) || IrisRegistrant.class.isAssignableFrom(c)) {
|
||||
for (Field k : IrisRegistrant.class.getDeclaredFields()) {
|
||||
k.setAccessible(true);
|
||||
|
||||
if (Modifier.isStatic(k.getModifiers()) || Modifier.isFinal(k.getModifiers()) || Modifier.isTransient(k.getModifiers())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
JSONObject property = buildProperty(k, c);
|
||||
|
||||
if (property.getBoolean("!required")) {
|
||||
required.put(k.getName());
|
||||
}
|
||||
|
||||
property.remove("!required");
|
||||
properties.put(k.getName(), property);
|
||||
}
|
||||
var parent = c.getSuperclass();
|
||||
while (parent != null && IrisRegistrant.class.isAssignableFrom(parent)) {
|
||||
buildProperties(properties, required, extended, parent);
|
||||
parent = parent.getSuperclass();
|
||||
}
|
||||
|
||||
for (Field k : c.getDeclaredFields()) {
|
||||
k.setAccessible(true);
|
||||
|
||||
if (Modifier.isStatic(k.getModifiers()) || Modifier.isFinal(k.getModifiers()) || Modifier.isTransient(k.getModifiers())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
JSONObject property = buildProperty(k, c);
|
||||
|
||||
if (property.getBoolean("!required"))
|
||||
required.put(k.getName());
|
||||
property.remove("!required");
|
||||
properties.put(k.getName(), property);
|
||||
}
|
||||
buildProperties(properties, required, extended, c);
|
||||
|
||||
if (required.length() > 0) {
|
||||
o.put("required", required);
|
||||
}
|
||||
if (extended.length() > 0) {
|
||||
o.put("allOf", extended);
|
||||
}
|
||||
|
||||
o.put("properties", properties);
|
||||
|
||||
@@ -156,6 +139,33 @@ public class SchemaBuilder {
|
||||
return buildSnippet(o, c);
|
||||
}
|
||||
|
||||
private void buildProperties(JSONObject properties, JSONArray required, JSONArray extended, Class<?> c) {
|
||||
for (Field k : c.getDeclaredFields()) {
|
||||
if (Modifier.isStatic(k.getModifiers()) || Modifier.isFinal(k.getModifiers()) || Modifier.isTransient(k.getModifiers())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
k.setAccessible(true);
|
||||
} catch (InaccessibleObjectException e) {
|
||||
continue;
|
||||
}
|
||||
|
||||
JSONObject property = buildProperty(k, c);
|
||||
|
||||
if (Boolean.TRUE == property.remove("!top")) {
|
||||
extended.put(property);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Boolean.TRUE == property.remove("!required")) {
|
||||
required.put(k.getName());
|
||||
}
|
||||
|
||||
properties.put(k.getName(), property);
|
||||
}
|
||||
}
|
||||
|
||||
private JSONObject buildProperty(Field k, Class<?> cl) {
|
||||
JSONObject prop = new JSONObject();
|
||||
String type = getType(k.getType());
|
||||
@@ -266,16 +276,18 @@ public class SchemaBuilder {
|
||||
|
||||
if (!definitions.containsKey(key)) {
|
||||
JSONObject j = new JSONObject();
|
||||
KList<String> list = new KList<>();
|
||||
list.addAll(Iris.linkMythicMobs.getMythicMobTypes().stream().map(s -> "MythicMobs:" + s).collect(Collectors.toList()));
|
||||
//TODO add Citizens stuff here too
|
||||
KList<String> list = Iris.service(ExternalDataSVC.class)
|
||||
.getAllIdentifiers(DataType.ENTITY)
|
||||
.stream()
|
||||
.map(Identifier::toString)
|
||||
.collect(KList.collector());
|
||||
j.put("enum", list.toJSONStringArray());
|
||||
definitions.put(key, j);
|
||||
}
|
||||
|
||||
fancyType = "Mythic Mob Type";
|
||||
fancyType = "Custom Mob Type";
|
||||
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)) {
|
||||
String key = "enum-font";
|
||||
|
||||
@@ -332,20 +344,70 @@ public class SchemaBuilder {
|
||||
prop.put("$ref", "#/definitions/" + key);
|
||||
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()) {
|
||||
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" -> {
|
||||
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()));
|
||||
//TODO add back descriptions
|
||||
if (k.isAnnotationPresent(RegistryMapBlockState.class)) {
|
||||
String blockType = k.getDeclaredAnnotation(RegistryMapBlockState.class).value();
|
||||
fancyType = "Block State";
|
||||
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" -> {
|
||||
fancyType = "List of Something...?";
|
||||
@@ -500,10 +562,10 @@ public class SchemaBuilder {
|
||||
items.put("$ref", "#/definitions/" + key);
|
||||
prop.put("items", items);
|
||||
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()) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -516,11 +578,12 @@ public class SchemaBuilder {
|
||||
}
|
||||
|
||||
KList<String> d = new KList<>();
|
||||
d.add(k.getName());
|
||||
d.add(getFieldDescription(k));
|
||||
d.add(" ");
|
||||
d.add(fancyType);
|
||||
d.add(getDescription(k.getType()));
|
||||
d.add("<h>" + k.getName() + "</h>");
|
||||
d.add(getFieldDescription(k) + "<hr></hr>");
|
||||
d.add("<h>" + fancyType + "</h>");
|
||||
String typeDesc = getDescription(k.getType());
|
||||
boolean present = !typeDesc.isBlank();
|
||||
if (present) d.add(typeDesc);
|
||||
|
||||
Snippet snippet = k.getType().getDeclaredAnnotation(Snippet.class);
|
||||
if (snippet == null) {
|
||||
@@ -532,8 +595,9 @@ public class SchemaBuilder {
|
||||
|
||||
if (snippet != null) {
|
||||
String sm = snippet.value();
|
||||
d.add(" ");
|
||||
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.");
|
||||
present = false;
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -541,15 +605,13 @@ public class SchemaBuilder {
|
||||
Object value = k.get(cl.newInstance());
|
||||
|
||||
if (value != null) {
|
||||
if (present) d.add(" ");
|
||||
if (value instanceof List) {
|
||||
d.add(" ");
|
||||
d.add("* Default Value is an empty list");
|
||||
} else if (!cl.isPrimitive() && !(value instanceof Number) && !(value instanceof String) && !(cl.isEnum()) && !OldEnum.isOldEnum(cl)) {
|
||||
d.add(" ");
|
||||
d.add("* Default Value is a default object (create this object to see default properties)");
|
||||
d.add(SYMBOL_LIMIT__N + " Default Value is an empty list");
|
||||
} else if (!k.getType().isPrimitive() && !(value instanceof Number) && !(value instanceof String) && !(value instanceof Enum<?>) && !KeyedType.isKeyed(k.getType())) {
|
||||
d.add(SYMBOL_LIMIT__N + " Default Value is a default object (create this object to see default properties)");
|
||||
} else {
|
||||
d.add(" ");
|
||||
d.add("* Default Value is " + value);
|
||||
d.add(SYMBOL_LIMIT__N + " Default Value is " + value);
|
||||
}
|
||||
}
|
||||
} catch (Throwable ignored) {
|
||||
@@ -557,8 +619,14 @@ public class SchemaBuilder {
|
||||
}
|
||||
|
||||
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("description", d.toString("\n"));
|
||||
prop.put("description", desc);
|
||||
prop.put("x-intellij-html-description", hDesc);
|
||||
return buildSnippet(prop, k.getType());
|
||||
}
|
||||
|
||||
@@ -584,15 +652,17 @@ public class SchemaBuilder {
|
||||
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
|
||||
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();
|
||||
var s = addEnum(t.type(), items, description, values, function);
|
||||
prop.put("items", items);
|
||||
@@ -601,17 +671,19 @@ public class SchemaBuilder {
|
||||
}
|
||||
|
||||
@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();
|
||||
boolean advanced = type.isAnnotationPresent(Desc.class);
|
||||
for (Object gg : values) {
|
||||
for (T gg : values) {
|
||||
if (advanced) {
|
||||
try {
|
||||
JSONObject j = new JSONObject();
|
||||
String name = function.apply(gg);
|
||||
j.put("const", name);
|
||||
Desc dd = type.getField(name).getAnnotation(Desc.class);
|
||||
j.put("description", dd == null ? ("No Description for " + name) : dd.value());
|
||||
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);
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
@@ -648,7 +720,7 @@ public class SchemaBuilder {
|
||||
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";
|
||||
}
|
||||
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
package com.volmit.iris.core.safeguard;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
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 {
|
||||
private static final AtomicBoolean sfg = new AtomicBoolean(false);
|
||||
public static boolean unstablemode = false;
|
||||
public static boolean warningmode = false;
|
||||
public static boolean stablemode = false;
|
||||
|
||||
public static void IrisSafeguardSystem() {
|
||||
Iris.info("Enabled Iris SafeGuard");
|
||||
ServerBootSFG.BootCheck();
|
||||
}
|
||||
|
||||
public static void splash(boolean early) {
|
||||
if (early && (ServerBootSFG.safeguardPassed || IrisSettings.get().getGeneral().DoomsdayAnnihilationSelfDestructMode))
|
||||
return;
|
||||
|
||||
if (!sfg.getAndSet(true)) {
|
||||
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,80 +0,0 @@
|
||||
package com.volmit.iris.core.safeguard;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.util.format.C;
|
||||
|
||||
public class ModesSFG {
|
||||
public static void selectMode() {
|
||||
if (IrisSafeguard.unstablemode) {
|
||||
Iris.safeguard(C.DARK_RED + "Iris is running in Unstable Mode");
|
||||
unstable();
|
||||
}
|
||||
if (IrisSafeguard.warningmode) {
|
||||
Iris.safeguard(C.GOLD + "Iris is running in Warning Mode");
|
||||
warning();
|
||||
}
|
||||
if (IrisSafeguard.stablemode) {
|
||||
stable();
|
||||
}
|
||||
}
|
||||
|
||||
public static void stable() {
|
||||
Iris.safeguard(C.BLUE + "Iris is running Stable");
|
||||
}
|
||||
|
||||
public static void unstable() {
|
||||
|
||||
UtilsSFG.printIncompatibleWarnings();
|
||||
|
||||
if (IrisSafeguard.unstablemode) {
|
||||
Iris.info("");
|
||||
Iris.info(C.DARK_GRAY + "--==<" + C.RED + " IMPORTANT " + C.DARK_GRAY + ">==--");
|
||||
Iris.info(C.RED + "Iris is running in unstable mode which may cause the following issues:");
|
||||
Iris.info(C.DARK_RED + "Server Issues");
|
||||
Iris.info(C.RED + "- Server won't boot");
|
||||
Iris.info(C.RED + "- Data Loss");
|
||||
Iris.info(C.RED + "- Unexpected behavior.");
|
||||
Iris.info(C.RED + "- And More...");
|
||||
Iris.info(C.DARK_RED + "World Issues");
|
||||
Iris.info(C.RED + "- Worlds can't load due to corruption.");
|
||||
Iris.info(C.RED + "- Worlds may slowly corrupt until they can't load.");
|
||||
Iris.info(C.RED + "- World data loss.");
|
||||
Iris.info(C.RED + "- And More...");
|
||||
Iris.info(C.DARK_RED + "ATTENTION: " + C.RED + "While running Iris in unstable mode, you won't be eligible for support.");
|
||||
Iris.info(C.DARK_RED + "CAUSE: " + C.RED + UtilsSFG.MSGIncompatibleWarnings());
|
||||
|
||||
if (IrisSettings.get().getGeneral().DoomsdayAnnihilationSelfDestructMode) {
|
||||
Iris.info(C.DARK_RED + "Boot Unstable is set to true, continuing with the startup process.");
|
||||
} else {
|
||||
Iris.info(C.DARK_RED + "Go to plugins/iris/settings.json and set DoomsdayAnnihilationSelfDestructMode to true if you wish to proceed.");
|
||||
while (true) {
|
||||
try {
|
||||
Thread.sleep(Long.MAX_VALUE);
|
||||
} catch (InterruptedException e) {
|
||||
// no
|
||||
}
|
||||
}
|
||||
}
|
||||
Iris.info("");
|
||||
}
|
||||
}
|
||||
|
||||
public static void warning() {
|
||||
|
||||
UtilsSFG.printIncompatibleWarnings();
|
||||
|
||||
if (IrisSafeguard.warningmode) {
|
||||
Iris.info("");
|
||||
Iris.info(C.DARK_GRAY + "--==<" + C.GOLD + " IMPORTANT " + C.DARK_GRAY + ">==--");
|
||||
Iris.info(C.GOLD + "Iris is running in warning mode which may cause the following issues:");
|
||||
Iris.info(C.YELLOW + "- Data Loss");
|
||||
Iris.info(C.YELLOW + "- Errors");
|
||||
Iris.info(C.YELLOW + "- Broken worlds");
|
||||
Iris.info(C.YELLOW + "- Unexpected behavior.");
|
||||
Iris.info(C.YELLOW + "- And perhaps further complications.");
|
||||
Iris.info(C.GOLD + "CAUSE: " + C.YELLOW + UtilsSFG.MSGIncompatibleWarnings());
|
||||
Iris.info("");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
package com.volmit.iris.core.safeguard;
|
||||
|
||||
public class PerformanceSFG {
|
||||
public static void calculatePerformance() {
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,213 +0,0 @@
|
||||
package com.volmit.iris.core.safeguard;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.nms.INMS;
|
||||
import com.volmit.iris.core.nms.v1X.NMSBinding1X;
|
||||
import com.volmit.iris.engine.object.IrisDimension;
|
||||
import com.volmit.iris.util.agent.Agent;
|
||||
import com.volmit.iris.util.collection.KSet;
|
||||
import com.volmit.iris.util.misc.ServerProperties;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
import javax.tools.JavaCompiler;
|
||||
import javax.tools.ToolProvider;
|
||||
import java.io.File;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.util.*;
|
||||
|
||||
import static com.volmit.iris.Iris.getJavaVersion;
|
||||
import static com.volmit.iris.core.safeguard.IrisSafeguard.*;
|
||||
|
||||
public class ServerBootSFG {
|
||||
public static final Map<String, Boolean> incompatibilities = new HashMap<>();
|
||||
public static boolean isCorrectJDK = true;
|
||||
public static boolean hasEnoughDiskSpace = true;
|
||||
public static boolean isJRE = false;
|
||||
public static boolean hasPrivileges = true;
|
||||
public static boolean unsuportedversion = false;
|
||||
public static boolean missingDimensionTypes = false;
|
||||
public static boolean missingAgent = false;
|
||||
public static boolean failedInjection = false;
|
||||
protected static boolean safeguardPassed;
|
||||
public static boolean passedserversoftware = true;
|
||||
protected static int count;
|
||||
protected static byte severityLow;
|
||||
protected static byte severityMedium;
|
||||
protected static byte severityHigh;
|
||||
public static String allIncompatibilities;
|
||||
|
||||
public static void BootCheck() {
|
||||
Iris.info("Checking for possible conflicts..");
|
||||
PluginManager pluginManager = Bukkit.getPluginManager();
|
||||
Plugin[] plugins = pluginManager.getPlugins();
|
||||
|
||||
incompatibilities.clear();
|
||||
incompatibilities.put("dynmap", false);
|
||||
incompatibilities.put("Stratos", false);
|
||||
|
||||
String pluginName;
|
||||
for (Plugin plugin : plugins) {
|
||||
pluginName = plugin.getName();
|
||||
Boolean flag = incompatibilities.get(pluginName);
|
||||
if (flag != null && !flag) {
|
||||
severityHigh++;
|
||||
incompatibilities.put(pluginName, true);
|
||||
}
|
||||
}
|
||||
|
||||
StringJoiner joiner = new StringJoiner(", ");
|
||||
for (Map.Entry<String, Boolean> entry : incompatibilities.entrySet()) {
|
||||
if (entry.getValue()) {
|
||||
joiner.add(entry.getKey());
|
||||
}
|
||||
}
|
||||
// Legacy ServerInfo
|
||||
String distro = Bukkit.getName().toLowerCase();
|
||||
if (
|
||||
!distro.contains("purpur") &&
|
||||
!distro.contains("paper") &&
|
||||
!distro.contains("spigot") &&
|
||||
!distro.contains("pufferfish") &&
|
||||
!distro.contains("bukkit")) {
|
||||
|
||||
|
||||
passedserversoftware = false;
|
||||
joiner.add("Server Software");
|
||||
severityMedium++;
|
||||
}
|
||||
|
||||
|
||||
if (INMS.get() instanceof NMSBinding1X) {
|
||||
unsuportedversion = true;
|
||||
joiner.add("Unsupported Minecraft Version");
|
||||
severityHigh++;
|
||||
}
|
||||
|
||||
if (!List.of(21).contains(getJavaVersion())) {
|
||||
isCorrectJDK = false;
|
||||
joiner.add("Unsupported Java version");
|
||||
severityMedium++;
|
||||
}
|
||||
|
||||
if (!isJDK()) {
|
||||
isJRE = true;
|
||||
joiner.add("Unsupported JDK");
|
||||
severityMedium++;
|
||||
}
|
||||
|
||||
// if (!hasPrivileges()){
|
||||
// hasPrivileges = false;
|
||||
// joiner.add("Insufficient Privileges");
|
||||
// severityMedium++;
|
||||
// } Some servers dont like this
|
||||
|
||||
if (!enoughDiskSpace()){
|
||||
hasEnoughDiskSpace = false;
|
||||
joiner.add("Insufficient Disk Space");
|
||||
severityMedium++;
|
||||
}
|
||||
|
||||
if (!Agent.install()) {
|
||||
missingAgent = true;
|
||||
joiner.add("Missing Java Agent");
|
||||
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();
|
||||
|
||||
safeguardPassed = (severityHigh == 0 && severityMedium == 0 && severityLow == 0);
|
||||
count = severityHigh + severityMedium + severityLow;
|
||||
if (safeguardPassed) {
|
||||
stablemode = true;
|
||||
Iris.safeguard("Stable mode has been activated.");
|
||||
}
|
||||
if (!safeguardPassed) {
|
||||
if (severityMedium >= 1 && severityHigh == 0) {
|
||||
warningmode = true;
|
||||
Iris.safeguard("Warning mode has been activated.");
|
||||
}
|
||||
if (severityHigh >= 1) {
|
||||
unstablemode = true;
|
||||
Iris.safeguard("Unstable mode has been activated.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static boolean isJDK() {
|
||||
try {
|
||||
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
|
||||
// If the compiler is null, it means this is a JRE environment, not a JDK.
|
||||
return compiler != null;
|
||||
} catch (Exception ignored) {}
|
||||
return false;
|
||||
}
|
||||
public static boolean hasPrivileges() {
|
||||
Path pv = Paths.get(Bukkit.getWorldContainer() + "iristest.json");
|
||||
try (FileChannel fc = FileChannel.open(pv, StandardOpenOption.CREATE, StandardOpenOption.DELETE_ON_CLOSE, StandardOpenOption.READ, StandardOpenOption.WRITE)) {
|
||||
if (Files.isReadable(pv) && Files.isWritable(pv)) {
|
||||
return true;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean enoughDiskSpace() {
|
||||
File freeSpace = Bukkit.getWorldContainer();
|
||||
double gigabytes = freeSpace.getFreeSpace() / (1024.0 * 1024.0 * 1024.0);
|
||||
return gigabytes > 3;
|
||||
}
|
||||
|
||||
private static boolean checkJavac(String path) {
|
||||
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() {
|
||||
var bukkit = YamlConfiguration.loadConfiguration(ServerProperties.BUKKIT_YML);
|
||||
var worlds = bukkit.getConfigurationSection("worlds");
|
||||
if (worlds == null) return new KSet<>();
|
||||
|
||||
var types = new KSet<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;
|
||||
|
||||
IrisDimension dimension = Iris.loadDimension(world, loadKey);
|
||||
if (dimension == null) continue;
|
||||
types.add(dimension.getDimensionTypeKey());
|
||||
}
|
||||
|
||||
return types;
|
||||
}
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
package com.volmit.iris.core.safeguard;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.util.agent.Agent;
|
||||
import com.volmit.iris.util.format.C;
|
||||
|
||||
public class UtilsSFG {
|
||||
public static void splash() {
|
||||
ModesSFG.selectMode();
|
||||
}
|
||||
|
||||
public static void printIncompatibleWarnings() {
|
||||
String[] parts = Iris.instance.getDescription().getVersion().split("-");
|
||||
String minVersion = parts[1];
|
||||
String maxVersion = parts[2];
|
||||
|
||||
if (ServerBootSFG.safeguardPassed) {
|
||||
Iris.safeguard(C.BLUE + "0 Conflicts found");
|
||||
} else {
|
||||
if (IrisSafeguard.unstablemode) {
|
||||
Iris.safeguard(C.DARK_RED + "" + ServerBootSFG.count + " Conflicts found");
|
||||
}
|
||||
if (IrisSafeguard.warningmode) {
|
||||
Iris.safeguard(C.YELLOW + "" + ServerBootSFG.count + " Conflicts found");
|
||||
}
|
||||
|
||||
if (ServerBootSFG.incompatibilities.get("dynmap")) {
|
||||
Iris.safeguard(C.RED + "Dynmap");
|
||||
Iris.safeguard(C.RED + "- The plugin Dynmap is not compatible with the server.");
|
||||
Iris.safeguard(C.RED + "- If you want to have a map plugin like Dynmap, consider Bluemap.");
|
||||
}
|
||||
if (ServerBootSFG.incompatibilities.get("Stratos")) {
|
||||
Iris.safeguard(C.YELLOW + "Stratos");
|
||||
Iris.safeguard(C.YELLOW + "- Iris is not compatible with other worldgen plugins.");
|
||||
}
|
||||
if (ServerBootSFG.unsuportedversion) {
|
||||
Iris.safeguard(C.RED + "Server Version");
|
||||
Iris.safeguard(C.RED + "- Iris only supports " + minVersion + " > " + maxVersion);
|
||||
}
|
||||
if (ServerBootSFG.missingDimensionTypes) {
|
||||
Iris.safeguard(C.RED + "Dimension Types");
|
||||
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.");
|
||||
}
|
||||
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) {
|
||||
Iris.safeguard(C.YELLOW + "Unsupported Server Software");
|
||||
Iris.safeguard(C.YELLOW + "- Please consider using Paper or Purpur instead.");
|
||||
}
|
||||
if (!ServerBootSFG.hasPrivileges) {
|
||||
Iris.safeguard(C.YELLOW + "Insufficient Privileges");
|
||||
Iris.safeguard(C.YELLOW + "- The server has insufficient Privileges to run iris. Please contact support.");
|
||||
}
|
||||
if (!ServerBootSFG.hasEnoughDiskSpace) {
|
||||
Iris.safeguard(C.YELLOW + "Insufficient Disk Space");
|
||||
Iris.safeguard(C.YELLOW + "- The server has insufficient Free DiskSpace to run iris required 3GB+.");
|
||||
}
|
||||
if (!ServerBootSFG.isCorrectJDK) {
|
||||
Iris.safeguard(C.YELLOW + "Unsupported java version");
|
||||
Iris.safeguard(C.YELLOW + "- Please consider using JDK 21 Instead of JDK " + Iris.getJavaVersion());
|
||||
}
|
||||
if (ServerBootSFG.isJRE) {
|
||||
Iris.safeguard(C.YELLOW + "Unsupported Server JDK");
|
||||
Iris.safeguard(C.YELLOW + "- Please consider using JDK 21 Instead of JRE " + Iris.getJavaVersion());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static String MSGIncompatibleWarnings() {
|
||||
return ServerBootSFG.allIncompatibilities;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.volmit.iris.core.scripting.environment;
|
||||
|
||||
import com.volmit.iris.core.loader.IrisRegistrant;
|
||||
import com.volmit.iris.core.scripting.func.UpdateExecutor;
|
||||
import com.volmit.iris.core.scripting.kotlin.environment.IrisExecutionEnvironment;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.util.mantle.MantleChunk;
|
||||
import lombok.NonNull;
|
||||
import org.bukkit.Chunk;
|
||||
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);
|
||||
|
||||
void updateChunk(@NonNull String script, @NonNull MantleChunk mantleChunk, @NonNull Chunk chunk, @NonNull UpdateExecutor executor);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
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.engine.framework.Engine;
|
||||
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);
|
||||
|
||||
EngineEnvironment with(@NonNull Engine engine);
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.volmit.iris.core.scripting.func;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface UpdateExecutor {
|
||||
|
||||
@NotNull Runnable wrap(int delay, @NotNull Runnable runnable);
|
||||
|
||||
@NotNull
|
||||
default Runnable wrap(@NotNull Runnable runnable) {
|
||||
return wrap(1, runnable);
|
||||
}
|
||||
|
||||
default void execute(@NotNull Runnable runnable) {
|
||||
execute(1, runnable);
|
||||
}
|
||||
|
||||
default void execute(int delay, @NotNull Runnable runnable) {
|
||||
wrap(delay, runnable).run();
|
||||
}
|
||||
}
|
||||
@@ -22,33 +22,39 @@ import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.loader.IrisData;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.util.board.BoardManager;
|
||||
import com.volmit.iris.util.board.BoardProvider;
|
||||
import com.volmit.iris.util.board.BoardSettings;
|
||||
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.format.C;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.plugin.IrisService;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import lombok.Data;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.player.PlayerChangedWorldEvent;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
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 {
|
||||
private final KMap<Player, PlayerBoard> boards = new KMap<>();
|
||||
private com.volmit.iris.util.board.BoardManager manager;
|
||||
private ScheduledExecutorService executor;
|
||||
private BoardManager manager;
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
J.ar(this::tick, 20);
|
||||
executor = Executors.newScheduledThreadPool(0, Thread.ofVirtual().factory());
|
||||
manager = new BoardManager(Iris.instance, BoardSettings.builder()
|
||||
.boardProvider(this)
|
||||
.scoreDirection(ScoreDirection.DOWN)
|
||||
@@ -57,6 +63,7 @@ public class BoardSVC implements IrisService, BoardProvider {
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
executor.shutdownNow();
|
||||
manager.onDisable();
|
||||
boards.clear();
|
||||
}
|
||||
@@ -71,14 +78,22 @@ public class BoardSVC implements IrisService, BoardProvider {
|
||||
J.s(() -> updatePlayer(e.getPlayer()));
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void on(PlayerQuitEvent e) {
|
||||
remove(e.getPlayer());
|
||||
}
|
||||
|
||||
public void updatePlayer(Player p) {
|
||||
if (IrisToolbelt.isIrisStudioWorld(p.getWorld())) {
|
||||
manager.remove(p);
|
||||
manager.setup(p);
|
||||
} else {
|
||||
manager.remove(p);
|
||||
boards.remove(p);
|
||||
}
|
||||
} else remove(p);
|
||||
}
|
||||
|
||||
private void remove(Player player) {
|
||||
manager.remove(player);
|
||||
var board = boards.remove(player);
|
||||
if (board != null) board.task.cancel(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -86,73 +101,63 @@ public class BoardSVC implements IrisService, BoardProvider {
|
||||
return C.GREEN + "Iris";
|
||||
}
|
||||
|
||||
public void tick() {
|
||||
if (!Iris.service(StudioSVC.class).isProjectOpen()) {
|
||||
return;
|
||||
}
|
||||
|
||||
boards.forEach((k, v) -> v.update());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getLines(Player player) {
|
||||
PlayerBoard pb = boards.computeIfAbsent(player, PlayerBoard::new);
|
||||
synchronized (pb.lines) {
|
||||
return pb.lines;
|
||||
}
|
||||
return boards.computeIfAbsent(player, PlayerBoard::new).lines;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class PlayerBoard {
|
||||
public class PlayerBoard {
|
||||
private final Player player;
|
||||
private final CopyOnWriteArrayList<String> lines;
|
||||
private final ScheduledFuture<?> task;
|
||||
private volatile List<String> lines;
|
||||
|
||||
public PlayerBoard(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();
|
||||
}
|
||||
|
||||
public void update() {
|
||||
synchronized (lines) {
|
||||
lines.clear();
|
||||
final World world = player.getWorld();
|
||||
final Location loc = player.getLocation();
|
||||
|
||||
if (!IrisToolbelt.isIrisStudioWorld(player.getWorld())) {
|
||||
return;
|
||||
}
|
||||
final var access = IrisToolbelt.access(world);
|
||||
if (access == null) return;
|
||||
|
||||
Engine engine = IrisToolbelt.access(player.getWorld()).getEngine();
|
||||
int x = player.getLocation().getBlockX();
|
||||
int y = player.getLocation().getBlockY() - player.getWorld().getMinHeight();
|
||||
int z = player.getLocation().getBlockZ();
|
||||
final var engine = access.getEngine();
|
||||
if (engine == null) return;
|
||||
|
||||
if(IrisSettings.get().getGeneral().debug){
|
||||
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(C.LIGHT_PURPLE + "Carving" + C.GRAY + ": " + engine.getMantle().isCarved(x,y,z));
|
||||
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 ");
|
||||
} 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 ");
|
||||
}
|
||||
int x = loc.getBlockX();
|
||||
int y = loc.getBlockY() - world.getMinHeight();
|
||||
int z = loc.getBlockZ();
|
||||
|
||||
List<String> lines = new ArrayList<>(this.lines.size());
|
||||
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());
|
||||
|
||||
if (IrisSettings.get().getGeneral().debug) {
|
||||
lines.add(C.LIGHT_PURPLE + "Carving" + C.GRAY + ": " + engine.getMantle().isCarved(x,y,z));
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.volmit.iris.core.commands.CommandIris;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.engine.data.cache.AtomicCache;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.decree.DecreeContext;
|
||||
import com.volmit.iris.util.decree.DecreeSystem;
|
||||
import com.volmit.iris.util.decree.virtual.VirtualDecreeCommand;
|
||||
import com.volmit.iris.util.format.C;
|
||||
@@ -44,7 +45,14 @@ public class CommandSVC implements IrisService, DecreeSystem {
|
||||
@Override
|
||||
public void onEnable() {
|
||||
Iris.instance.getCommand("iris").setExecutor(this);
|
||||
J.a(() -> getRoot().cacheAll());
|
||||
J.a(() -> {
|
||||
DecreeContext.touch(Iris.getSender());
|
||||
try {
|
||||
getRoot().cacheAll();
|
||||
} finally {
|
||||
DecreeContext.remove();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -20,16 +20,22 @@ package com.volmit.iris.core.service;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
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.engine.framework.Engine;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
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.scheduling.J;
|
||||
import lombok.Data;
|
||||
import lombok.NonNull;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.server.PluginEnableEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
@@ -47,43 +53,12 @@ public class ExternalDataSVC implements IrisService {
|
||||
Iris.info("Loading ExternalDataProvider...");
|
||||
Bukkit.getPluginManager().registerEvents(this, Iris.instance);
|
||||
|
||||
providers.add(new NexoDataProvider());
|
||||
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...");
|
||||
}
|
||||
providers.add(new KGeneratorsDataProvider());
|
||||
if (Bukkit.getPluginManager().getPlugin("KGenerators") != null) {
|
||||
Iris.info("KGenerators found, loading KGeneratorsDataProvider...");
|
||||
}
|
||||
|
||||
providers.addAll(createProviders());
|
||||
for (ExternalDataProvider p : providers) {
|
||||
if (p.isReady()) {
|
||||
activeProviders.add(p);
|
||||
p.init();
|
||||
Iris.instance.registerListener(p);
|
||||
Iris.info("Enabled ExternalDataProvider for %s.", p.getPluginId());
|
||||
}
|
||||
}
|
||||
@@ -95,10 +70,11 @@ public class ExternalDataSVC implements IrisService {
|
||||
|
||||
@EventHandler
|
||||
public void onPluginEnable(PluginEnableEvent e) {
|
||||
if (activeProviders.stream().noneMatch(p -> p.getPlugin().equals(e.getPlugin()))) {
|
||||
providers.stream().filter(p -> p.isReady() && p.getPlugin().equals(e.getPlugin())).findFirst().ifPresent(edp -> {
|
||||
if (activeProviders.stream().noneMatch(p -> e.getPlugin().equals(p.getPlugin()))) {
|
||||
providers.stream().filter(p -> p.isReady() && e.getPlugin().equals(p.getPlugin())).findFirst().ifPresent(edp -> {
|
||||
activeProviders.add(edp);
|
||||
edp.init();
|
||||
Iris.instance.registerListener(edp);
|
||||
Iris.info("Enabled ExternalDataProvider for %s.", edp.getPluginId());
|
||||
});
|
||||
}
|
||||
@@ -113,6 +89,7 @@ public class ExternalDataSVC implements IrisService {
|
||||
if (provider.isReady()) {
|
||||
activeProviders.add(provider);
|
||||
provider.init();
|
||||
Iris.instance.registerListener(provider);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,7 +97,7 @@ public class ExternalDataSVC implements IrisService {
|
||||
var pair = parseState(key);
|
||||
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())
|
||||
return Optional.empty();
|
||||
try {
|
||||
@@ -131,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) {
|
||||
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()) {
|
||||
Iris.warn("No matching Provider found for modded material \"%s\"!", key);
|
||||
return Optional.empty();
|
||||
@@ -146,7 +135,7 @@ public class ExternalDataSVC implements IrisService {
|
||||
}
|
||||
|
||||
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()) {
|
||||
Iris.warn("No matching Provider found for modded material \"%s\"!", blockId);
|
||||
return;
|
||||
@@ -154,16 +143,32 @@ public class ExternalDataSVC implements IrisService {
|
||||
provider.get().processUpdate(engine, block, blockId);
|
||||
}
|
||||
|
||||
public Identifier[] getAllBlockIdentifiers() {
|
||||
KList<Identifier> names = new KList<>();
|
||||
activeProviders.forEach(p -> names.add(p.getBlockTypes()));
|
||||
return names.toArray(new Identifier[0]);
|
||||
public Entity spawnMob(Location location, Identifier mobId) {
|
||||
Optional<ExternalDataProvider> provider = activeProviders.stream().filter(p -> p.isValidProvider(mobId, DataType.ENTITY)).findFirst();
|
||||
if (provider.isEmpty()) {
|
||||
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() {
|
||||
KList<Identifier> names = new KList<>();
|
||||
activeProviders.forEach(p -> names.add(p.getItemTypes()));
|
||||
return names.toArray(new Identifier[0]);
|
||||
public Collection<Identifier> getAllIdentifiers(DataType dataType) {
|
||||
return activeProviders.stream()
|
||||
.flatMap(p -> p.getTypes(dataType).stream())
|
||||
.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) {
|
||||
@@ -188,4 +193,21 @@ public class ExternalDataSVC implements IrisService {
|
||||
.collect(Collectors.joining(",", key.key() + "[", "]"));
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package com.volmit.iris.core.service;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.Cache;
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.pregenerator.cache.PregenCache;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.plugin.IrisService;
|
||||
import com.volmit.iris.util.scheduling.Looper;
|
||||
import lombok.NonNull;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
@@ -17,17 +17,33 @@ import org.bukkit.event.world.WorldUnloadEvent;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class GlobalCacheSVC implements IrisService {
|
||||
private static final Cache<String, PregenCache> REFERENCE_CACHE = Caffeine.newBuilder().weakValues().build();
|
||||
private static final KMap<String, Reference<PregenCache>> REFERENCE_CACHE = new KMap<>();
|
||||
private final KMap<String, PregenCache> globalCache = new KMap<>();
|
||||
private transient boolean lastState;
|
||||
private static boolean disabled = true;
|
||||
private Looper trimmer;
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
disabled = false;
|
||||
trimmer = new Looper() {
|
||||
@Override
|
||||
protected long loop() {
|
||||
var it = REFERENCE_CACHE.values().iterator();
|
||||
while (it.hasNext()) {
|
||||
var cache = it.next().get();
|
||||
if (cache == null) it.remove();
|
||||
else cache.trim(10_000);
|
||||
}
|
||||
return disabled ? -1 : 2_000;
|
||||
}
|
||||
};
|
||||
trimmer.start();
|
||||
lastState = !IrisSettings.get().getWorld().isGlobalPregenCache();
|
||||
if (lastState) return;
|
||||
Bukkit.getWorlds().forEach(this::createCache);
|
||||
@@ -36,6 +52,9 @@ public class GlobalCacheSVC implements IrisService {
|
||||
@Override
|
||||
public void onDisable() {
|
||||
disabled = true;
|
||||
try {
|
||||
trimmer.join();
|
||||
} catch (InterruptedException ignored) {}
|
||||
globalCache.qclear((world, cache) -> cache.write());
|
||||
}
|
||||
|
||||
@@ -70,6 +89,7 @@ public class GlobalCacheSVC implements IrisService {
|
||||
}
|
||||
|
||||
private void createCache(World world) {
|
||||
if (!IrisToolbelt.isIrisWorld(world)) return;
|
||||
globalCache.computeIfAbsent(world.getName(), GlobalCacheSVC::createDefault);
|
||||
}
|
||||
|
||||
@@ -93,7 +113,15 @@ public class GlobalCacheSVC implements IrisService {
|
||||
|
||||
@NonNull
|
||||
public static PregenCache createCache(@NonNull String worldName, @NonNull Function<String, PregenCache> provider) {
|
||||
return REFERENCE_CACHE.get(worldName, provider);
|
||||
PregenCache[] holder = new PregenCache[1];
|
||||
REFERENCE_CACHE.compute(worldName, (name, ref) -> {
|
||||
if (ref != null) {
|
||||
if ((holder[0] = ref.get()) != null)
|
||||
return ref;
|
||||
}
|
||||
return new WeakReference<>(holder[0] = provider.apply(worldName));
|
||||
});
|
||||
return holder[0];
|
||||
}
|
||||
|
||||
@NonNull
|
||||
|
||||
@@ -3,7 +3,7 @@ package com.volmit.iris.core.service;
|
||||
import com.google.common.util.concurrent.AtomicDouble;
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.loader.IrisData;
|
||||
import com.volmit.iris.core.loader.ResourceLoader;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.platform.PlatformChunkGenerator;
|
||||
@@ -14,6 +14,8 @@ import com.volmit.iris.util.math.RNG;
|
||||
import com.volmit.iris.util.plugin.IrisService;
|
||||
import com.volmit.iris.util.plugin.VolmitSender;
|
||||
import com.volmit.iris.util.scheduling.Looper;
|
||||
import com.volmit.iris.util.stream.utility.CachedStream2D;
|
||||
import com.volmit.iris.util.stream.utility.CachedStream3D;
|
||||
import lombok.Synchronized;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
@@ -27,6 +29,7 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
public class IrisEngineSVC implements IrisService {
|
||||
private static final int TRIM_PERIOD = 2_000;
|
||||
private final AtomicInteger tectonicLimit = new AtomicInteger(30);
|
||||
private final AtomicInteger tectonicPlates = new AtomicInteger();
|
||||
private final AtomicInteger queuedTectonicPlates = new AtomicInteger();
|
||||
@@ -64,10 +67,26 @@ public class IrisEngineSVC implements IrisService {
|
||||
}
|
||||
|
||||
public void engineStatus(VolmitSender sender) {
|
||||
long[] sizes = new long[4];
|
||||
long[] count = new long[4];
|
||||
|
||||
for (var cache : Iris.service(PreservationSVC.class).getCaches()) {
|
||||
var type = switch (cache) {
|
||||
case ResourceLoader<?> ignored -> 0;
|
||||
case CachedStream2D<?> ignored -> 1;
|
||||
case CachedStream3D<?> ignored -> 2;
|
||||
default -> 3;
|
||||
};
|
||||
|
||||
sizes[type] += cache.getSize();
|
||||
count[type]++;
|
||||
}
|
||||
|
||||
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 + "- Period: " + C.LIGHT_PURPLE + Form.duration(TRIM_PERIOD));
|
||||
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:");
|
||||
@@ -76,10 +95,14 @@ public class IrisEngineSVC implements IrisService {
|
||||
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 + "Caches:");
|
||||
sender.sendMessage(C.DARK_PURPLE + "- Resource: " + C.LIGHT_PURPLE + sizes[0] + " (" + count[0] + ")");
|
||||
sender.sendMessage(C.DARK_PURPLE + "- 2D Stream: " + C.LIGHT_PURPLE + sizes[1] + " (" + count[1] + ")");
|
||||
sender.sendMessage(C.DARK_PURPLE + "- 3D Stream: " + C.LIGHT_PURPLE + sizes[2] + " (" + count[2] + ")");
|
||||
sender.sendMessage(C.DARK_PURPLE + "- Other: " + C.LIGHT_PURPLE + sizes[3] + " (" + count[3] + ")");
|
||||
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 + "-------------------------");
|
||||
}
|
||||
|
||||
@@ -113,12 +136,12 @@ public class IrisEngineSVC implements IrisService {
|
||||
@Override
|
||||
protected long loop() {
|
||||
try {
|
||||
queuedTectonicPlates.set(0);
|
||||
tectonicPlates.set(0);
|
||||
loadedChunks.set(0);
|
||||
unloaderAlive.set(0);
|
||||
trimmerAlive.set(0);
|
||||
totalWorlds.set(0);
|
||||
int queuedPlates = 0;
|
||||
int totalPlates = 0;
|
||||
long chunks = 0;
|
||||
int unloaders = 0;
|
||||
int trimmers = 0;
|
||||
int iris = 0;
|
||||
|
||||
double maxDuration = Long.MIN_VALUE;
|
||||
double minDuration = Long.MAX_VALUE;
|
||||
@@ -126,23 +149,30 @@ public class IrisEngineSVC implements IrisService {
|
||||
var registered = entry.getValue();
|
||||
if (registered.closed) continue;
|
||||
|
||||
totalWorlds.incrementAndGet();
|
||||
unloaderAlive.addAndGet(registered.unloaderAlive() ? 1 : 0);
|
||||
trimmerAlive.addAndGet(registered.trimmerAlive() ? 1 : 0);
|
||||
iris++;
|
||||
if (registered.unloaderAlive()) unloaders++;
|
||||
if (registered.trimmerAlive()) trimmers++;
|
||||
|
||||
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);
|
||||
queuedPlates += engine.getMantle().getUnloadRegionCount();
|
||||
totalPlates += engine.getMantle().getLoadedRegionCount();
|
||||
chunks += entry.getKey().getLoadedChunks().length;
|
||||
|
||||
double duration = engine.getMantle().getAdjustedIdleDuration();
|
||||
if (duration > maxDuration) maxDuration = duration;
|
||||
if (duration < minDuration) minDuration = duration;
|
||||
}
|
||||
|
||||
trimmerAlive.set(trimmers);
|
||||
unloaderAlive.set(unloaders);
|
||||
tectonicPlates.set(totalPlates);
|
||||
queuedTectonicPlates.set(queuedPlates);
|
||||
maxIdleDuration.set(maxDuration);
|
||||
minIdleDuration.set(minDuration);
|
||||
loadedChunks.set(chunks);
|
||||
totalWorlds.set(iris);
|
||||
|
||||
worlds.values().forEach(Registered::update);
|
||||
} catch (Throwable e) {
|
||||
@@ -157,6 +187,7 @@ public class IrisEngineSVC implements IrisService {
|
||||
private final class Registered {
|
||||
private final String name;
|
||||
private final PlatformChunkGenerator access;
|
||||
private final int offset = RNG.r.nextInt(TRIM_PERIOD);
|
||||
private transient ScheduledFuture<?> trimmer;
|
||||
private transient ScheduledFuture<?> unloader;
|
||||
private transient boolean closed;
|
||||
@@ -193,7 +224,7 @@ public class IrisEngineSVC implements IrisService {
|
||||
Iris.error("EngineSVC: Failed to trim for " + name);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}, RNG.r.nextInt(1000), 1000, TimeUnit.MILLISECONDS);
|
||||
}, offset, TRIM_PERIOD, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
if (unloader == null || unloader.isDone() || unloader.isCancelled()) {
|
||||
@@ -204,7 +235,7 @@ public class IrisEngineSVC implements IrisService {
|
||||
|
||||
try {
|
||||
long unloadStart = System.currentTimeMillis();
|
||||
int count = engine.getMantle().unloadTectonicPlate(tectonicLimit());
|
||||
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));
|
||||
}
|
||||
@@ -213,7 +244,7 @@ public class IrisEngineSVC implements IrisService {
|
||||
Iris.error("EngineSVC: Failed to unload for " + name);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}, RNG.r.nextInt(1000), 1000, TimeUnit.MILLISECONDS);
|
||||
}, offset + TRIM_PERIOD / 2, TRIM_PERIOD, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,50 +24,45 @@ import com.volmit.iris.engine.framework.MeteredCache;
|
||||
import com.volmit.iris.util.context.IrisContext;
|
||||
import com.volmit.iris.util.data.KCache;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.parallel.MultiBurst;
|
||||
import com.volmit.iris.util.plugin.IrisService;
|
||||
import com.volmit.iris.util.scheduling.Looper;
|
||||
import org.jetbrains.annotations.Unmodifiable;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class PreservationSVC implements IrisService {
|
||||
private final List<Thread> threads = new CopyOnWriteArrayList<>();
|
||||
private final List<ExecutorService> services = new CopyOnWriteArrayList<>();
|
||||
private final List<MeteredCache> caches = new CopyOnWriteArrayList<>();
|
||||
private final List<WeakReference<MeteredCache>> caches = new CopyOnWriteArrayList<>();
|
||||
private Looper dereferencer;
|
||||
|
||||
public void register(Thread t) {
|
||||
threads.add(t);
|
||||
}
|
||||
|
||||
public void register(MultiBurst burst) {
|
||||
|
||||
}
|
||||
|
||||
public void register(ExecutorService service) {
|
||||
services.add(service);
|
||||
}
|
||||
|
||||
public void printCaches() {
|
||||
long s = caches.stream().filter(i -> !i.isClosed()).mapToLong(MeteredCache::getSize).sum();
|
||||
long m = caches.stream().filter(i -> !i.isClosed()).mapToLong(MeteredCache::getMaxSize).sum();
|
||||
var c = getCaches();
|
||||
long s = 0;
|
||||
long m = 0;
|
||||
double p = 0;
|
||||
double mf = 0;
|
||||
double mf = Math.max(c.size(), 1);
|
||||
|
||||
for (MeteredCache i : caches) {
|
||||
if (i.isClosed()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
mf++;
|
||||
for (MeteredCache i : c) {
|
||||
s += i.getSize();
|
||||
m += i.getMaxSize();
|
||||
p += i.getUsage();
|
||||
}
|
||||
|
||||
mf = mf == 0 ? 1 : mf;
|
||||
|
||||
Iris.info("Cached " + Form.f(s) + " / " + Form.f(m) + " (" + Form.pc(p / mf) + ") from " + caches.size() + " Caches");
|
||||
}
|
||||
|
||||
@@ -123,14 +118,29 @@ public class PreservationSVC implements IrisService {
|
||||
}
|
||||
|
||||
public void updateCaches() {
|
||||
caches.removeIf(MeteredCache::isClosed);
|
||||
caches.removeIf(ref -> {
|
||||
var c = ref.get();
|
||||
return c == null || c.isClosed();
|
||||
});
|
||||
}
|
||||
|
||||
public void registerCache(MeteredCache cache) {
|
||||
caches.add(cache);
|
||||
caches.add(new WeakReference<>(cache));
|
||||
}
|
||||
|
||||
public List<KCache<?, ?>> caches() {
|
||||
return caches.stream().map(MeteredCache::getRawCache).collect(Collectors.toList());
|
||||
return cacheStream().map(MeteredCache::getRawCache).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Unmodifiable
|
||||
public List<MeteredCache> getCaches() {
|
||||
return cacheStream().toList();
|
||||
}
|
||||
|
||||
private Stream<MeteredCache> cacheStream() {
|
||||
return caches.stream()
|
||||
.map(WeakReference::get)
|
||||
.filter(Objects::nonNull)
|
||||
.filter(cache -> !cache.isClosed());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,16 +88,18 @@ public class StudioSVC implements IrisService {
|
||||
}
|
||||
|
||||
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);
|
||||
File iris = new File(folder, "iris");
|
||||
File irispack = new File(folder, "iris/pack");
|
||||
IrisDimension dim = IrisData.loadAnyDimension(type);
|
||||
IrisDimension dim = IrisData.loadAnyDimension(type, null);
|
||||
|
||||
if (dim == null) {
|
||||
for (File i : getWorkspaceFolder().listFiles()) {
|
||||
if (i.isFile() && i.getName().equals(type + ".iris")) {
|
||||
sender.sendMessage("Found " + type + ".iris in " + WORKSPACE_NAME + " folder");
|
||||
ZipUtil.unpack(i, irispack);
|
||||
ZipUtil.unpack(i, folder);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -106,29 +108,29 @@ public class StudioSVC implements IrisService {
|
||||
File f = new IrisProject(new File(getWorkspaceFolder(), type)).getPath();
|
||||
|
||||
try {
|
||||
FileUtils.copyDirectory(f, irispack);
|
||||
FileUtils.copyDirectory(f, folder);
|
||||
} catch (IOException 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);
|
||||
File downloaded = getWorkspaceFolder(type);
|
||||
|
||||
for (File i : downloaded.listFiles()) {
|
||||
if (i.isFile()) {
|
||||
try {
|
||||
FileUtils.copyFile(i, new File(irispack, i.getName()));
|
||||
FileUtils.copyFile(i, new File(folder, i.getName()));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
Iris.reportError(e);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
FileUtils.copyDirectory(i, new File(irispack, i.getName()));
|
||||
FileUtils.copyDirectory(i, new File(folder, i.getName()));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
Iris.reportError(e);
|
||||
@@ -139,12 +141,13 @@ public class StudioSVC implements IrisService {
|
||||
IO.delete(downloaded);
|
||||
}
|
||||
|
||||
if (!dimf.exists() || !dimf.isFile()) {
|
||||
sender.sendMessage("Can't find the " + dimf.getName() + " in the dimensions folder of this pack! Failed!");
|
||||
if (!dimensionFile.exists() || !dimensionFile.isFile()) {
|
||||
sender.sendMessage("Can't find the " + dimensionFile.getName() + " in the dimensions folder of this pack! Failed!");
|
||||
return null;
|
||||
}
|
||||
|
||||
IrisData dm = IrisData.get(irispack);
|
||||
IrisData dm = IrisData.get(folder);
|
||||
dm.hotloaded();
|
||||
dim = dm.getDimensionLoader().load(type);
|
||||
|
||||
if (dim == null) {
|
||||
@@ -261,6 +264,7 @@ public class StudioSVC implements IrisService {
|
||||
}
|
||||
|
||||
IrisDimension d = data.getDimensionLoader().load(dimensions[0]);
|
||||
data.close();
|
||||
|
||||
if (d == null) {
|
||||
sender.sendMessage("Invalid dimension (folder) in dimensions folder");
|
||||
@@ -275,7 +279,7 @@ public class StudioSVC implements IrisService {
|
||||
IO.delete(packEntry);
|
||||
}
|
||||
|
||||
if (IrisData.loadAnyDimension(key) != null) {
|
||||
if (IrisData.loadAnyDimension(key, null) != null) {
|
||||
sender.sendMessage("Another dimension in the packs folder is already using the key " + key + " IMPORT FAILED!");
|
||||
return;
|
||||
}
|
||||
@@ -294,6 +298,8 @@ public class StudioSVC implements IrisService {
|
||||
packEntry.mkdirs();
|
||||
ZipUtil.unpack(cp, packEntry);
|
||||
}
|
||||
IrisData.getLoaded(packEntry)
|
||||
.ifPresent(IrisData::hotloaded);
|
||||
|
||||
sender.sendMessage("Successfully Aquired " + d.getName());
|
||||
ServerConfigurator.installDataPacks(true);
|
||||
|
||||
@@ -189,6 +189,16 @@ public class TreeSVC implements IrisService {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void setData(int xx, int yy, int zz, T data) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T getData(int xx, int yy, int zz, Class<T> t) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Engine getEngine() {
|
||||
return engine;
|
||||
@@ -225,7 +235,7 @@ public class TreeSVC implements IrisService {
|
||||
if (d instanceof IrisCustomData data) {
|
||||
block.setBlockData(data.getBase(), false);
|
||||
Iris.service(ExternalDataSVC.class).processUpdate(engine, block, data.getCustom());
|
||||
} else block.setBlockData(d);
|
||||
} else block.setBlockData(d, false);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -90,6 +90,7 @@ public class WandSVC implements IrisService {
|
||||
|
||||
int total = c.getSizeX() * c.getSizeY() * c.getSizeZ();
|
||||
var latch = new CountDownLatch(1);
|
||||
var holder = Iris.tickets.getHolder(p.getWorld());
|
||||
new Job() {
|
||||
private int i;
|
||||
private Chunk chunk;
|
||||
@@ -108,7 +109,7 @@ public class WandSVC implements IrisService {
|
||||
while (time > M.ms()) {
|
||||
if (!it.hasNext()) {
|
||||
if (chunk != null) {
|
||||
chunk.removePluginChunkTicket(Iris.instance);
|
||||
holder.removeTicket(chunk);
|
||||
chunk = null;
|
||||
}
|
||||
|
||||
@@ -122,9 +123,10 @@ public class WandSVC implements IrisService {
|
||||
var bChunk = b.getChunk();
|
||||
if (chunk == null) {
|
||||
chunk = bChunk;
|
||||
chunk.addPluginChunkTicket(Iris.instance);
|
||||
holder.addTicket(chunk);
|
||||
} else if (chunk != bChunk) {
|
||||
chunk.removePluginChunkTicket(Iris.instance);
|
||||
holder.removeTicket(chunk);
|
||||
holder.addTicket(bChunk);
|
||||
chunk = bChunk;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,29 +2,21 @@ package com.volmit.iris.core.tools;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.engine.object.*;
|
||||
import com.volmit.iris.util.data.Varint;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.nbt.io.NBTUtil;
|
||||
import com.volmit.iris.util.nbt.io.NamedTag;
|
||||
import com.volmit.iris.util.nbt.tag.*;
|
||||
import com.volmit.iris.util.plugin.VolmitSender;
|
||||
import com.volmit.iris.util.reflect.V;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.util.FileUtil;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
@@ -39,13 +31,17 @@ public class IrisConverter {
|
||||
sender.sendMessage("No schematic files to convert found in " + folder.getAbsolutePath());
|
||||
return;
|
||||
}
|
||||
|
||||
AtomicInteger counter = new AtomicInteger(0);
|
||||
var stopwatch = PrecisionStopwatch.start();
|
||||
ExecutorService executorService = Executors.newFixedThreadPool(1);
|
||||
executorService.submit(() -> {
|
||||
for (File schem : fileList) {
|
||||
try {
|
||||
for (File schem : fileList) {
|
||||
try {
|
||||
PrecisionStopwatch p = PrecisionStopwatch.start();
|
||||
IrisObject object;
|
||||
boolean largeObject = false;
|
||||
NamedTag tag = null;
|
||||
NamedTag tag;
|
||||
try {
|
||||
tag = NBTUtil.read(schem);
|
||||
} catch (IOException e) {
|
||||
@@ -53,17 +49,20 @@ public class IrisConverter {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
CompoundTag compound = (CompoundTag) tag.getTag();
|
||||
int version = resolveVersion(compound);
|
||||
if (!(version == 2 || version == 3))
|
||||
throw new RuntimeException(C.RED + "Unsupported schematic version: " + version);
|
||||
|
||||
if (compound.containsKey("Palette") && compound.containsKey("Width") && compound.containsKey("Height") && compound.containsKey("Length")) {
|
||||
compound = version == 3 ? (CompoundTag) compound.get("Schematic") : compound;
|
||||
int objW = ((ShortTag) compound.get("Width")).getValue();
|
||||
int objH = ((ShortTag) compound.get("Height")).getValue();
|
||||
int objD = ((ShortTag) compound.get("Length")).getValue();
|
||||
int i = -1;
|
||||
int mv = objW * objH * objD;
|
||||
AtomicInteger v = new AtomicInteger(0);
|
||||
if (mv > 500_000) {
|
||||
if (mv > 2_000_000) {
|
||||
largeObject = true;
|
||||
Iris.info(C.GRAY + "Converting.. "+ schem.getName() + " -> " + schem.getName().replace(".schem", ".iob"));
|
||||
Iris.info(C.GRAY + "Converting.. " + schem.getName() + " -> " + schem.getName().replace(".schem", ".iob"));
|
||||
Iris.info(C.GRAY + "- It may take a while");
|
||||
if (sender.isPlayer()) {
|
||||
i = J.ar(() -> {
|
||||
@@ -72,6 +71,7 @@ public class IrisConverter {
|
||||
}
|
||||
}
|
||||
|
||||
compound = version == 3 ? (CompoundTag) compound.get("Blocks") : compound;
|
||||
CompoundTag paletteTag = (CompoundTag) compound.get("Palette");
|
||||
Map<Integer, BlockData> blockmap = new HashMap<>(paletteTag.size(), 0.9f);
|
||||
for (Map.Entry<String, Tag<?>> entry : paletteTag.getValue().entrySet()) {
|
||||
@@ -82,14 +82,16 @@ public class IrisConverter {
|
||||
blockmap.put(blockId, bd);
|
||||
}
|
||||
|
||||
ByteArrayTag byteArray = (ByteArrayTag) compound.get("BlockData");
|
||||
boolean isBytes = version == 3 ? compound.getByteArrayTag("Data").length() < 128 : ((IntTag) compound.get("PaletteMax")).getValue() < 128;
|
||||
ByteArrayTag byteArray = version == 3 ? (ByteArrayTag) compound.get("Data") : (ByteArrayTag) compound.get("BlockData");
|
||||
byte[] originalBlockArray = byteArray.getValue();
|
||||
|
||||
IrisObject object = new IrisObject(objW, objH, objD);
|
||||
var din = new DataInputStream(new ByteArrayInputStream(originalBlockArray));
|
||||
object = new IrisObject(objW, objH, objD);
|
||||
for (int h = 0; h < objH; h++) {
|
||||
for (int d = 0; d < objD; d++) {
|
||||
for (int w = 0; w < objW; w++) {
|
||||
BlockData bd = blockmap.get((int) originalBlockArray[v.get()]);
|
||||
int blockIndex = isBytes ? din.read() & 0xFF : Varint.readUnsignedVarInt(din);
|
||||
BlockData bd = blockmap.get(blockIndex);
|
||||
if (!bd.getMaterial().isAir()) {
|
||||
object.setUnsigned(w, h, d, bd);
|
||||
}
|
||||
@@ -97,42 +99,59 @@ public class IrisConverter {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (i != -1) J.car(i);
|
||||
try {
|
||||
object.shrinkwrap();
|
||||
object.write(new File(folder, schem.getName().replace(".schem", ".iob")));
|
||||
} catch (IOException e) {
|
||||
Iris.info(C.RED + "Failed to save: " + schem.getName());
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
if (sender.isPlayer()) {
|
||||
if (largeObject) {
|
||||
sender.sendMessage(C.IRIS + "Converted "+ schem.getName() + " -> " + schem.getName().replace(".schem", ".iob") + " in " + Form.duration(p.getMillis()));
|
||||
} else {
|
||||
sender.sendMessage(C.IRIS + "Converted " + schem.getName() + " -> " + schem.getName().replace(".schem", ".iob"));
|
||||
counter.incrementAndGet();
|
||||
if (sender.isPlayer()) {
|
||||
if (largeObject) {
|
||||
sender.sendMessage(C.IRIS + "Converted " + schem.getName() + " -> " + schem.getName().replace(".schem", ".iob") + " in " + Form.duration(p.getMillis()));
|
||||
} else {
|
||||
sender.sendMessage(C.IRIS + "Converted " + schem.getName() + " -> " + schem.getName().replace(".schem", ".iob"));
|
||||
}
|
||||
}
|
||||
if (largeObject) {
|
||||
Iris.info(C.GRAY + "Converted " + schem.getName() + " -> " + schem.getName().replace(".schem", ".iob") + " in " + Form.duration(p.getMillis()));
|
||||
} else {
|
||||
Iris.info(C.GRAY + "Converted " + schem.getName() + " -> " + schem.getName().replace(".schem", ".iob"));
|
||||
}
|
||||
FileUtils.delete(schem);
|
||||
} catch (IOException e) {
|
||||
sender.sendMessage(C.RED + "Failed to save: " + schem.getName());
|
||||
throw new IOException(e);
|
||||
}
|
||||
if (largeObject) {
|
||||
Iris.info(C.GRAY + "Converted "+ schem.getName() + " -> " + schem.getName().replace(".schem", ".iob") + " in " + Form.duration(p.getMillis()));
|
||||
} else {
|
||||
Iris.info(C.GRAY + "Converted " + schem.getName() + " -> " + schem.getName().replace(".schem", ".iob"));
|
||||
}
|
||||
FileUtils.delete(schem);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Iris.info(C.RED + "Failed to convert: " + schem.getName());
|
||||
if (sender.isPlayer()) {
|
||||
|
||||
|
||||
} catch (Exception e) {
|
||||
sender.sendMessage(C.RED + "Failed to convert: " + schem.getName());
|
||||
e.printStackTrace();
|
||||
}
|
||||
e.printStackTrace();
|
||||
Iris.reportError(e);
|
||||
}
|
||||
}
|
||||
sender.sendMessage(C.GRAY + "converted: " + fileList.length);
|
||||
stopwatch.end();
|
||||
if (counter.get() != 0) {
|
||||
sender.sendMessage(C.GRAY + "Converted: " + counter.get() + " in " + Form.duration(stopwatch.getMillis()));
|
||||
}
|
||||
if (counter.get() < fileList.length) {
|
||||
sender.sendMessage(C.RED + "Some schematics failed to convert. Check the console for details.");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static int resolveVersion(CompoundTag compound) throws Exception {
|
||||
try {
|
||||
|
||||
IntTag root = compound.getIntTag("Version");
|
||||
if (root != null) {
|
||||
return root.getValue();
|
||||
}
|
||||
CompoundTag schematic = (CompoundTag) compound.get("Schematic");
|
||||
return schematic.getIntTag("Version").getValue();
|
||||
} catch (NullPointerException e) {
|
||||
throw new Exception("Cannot resolve schematic version", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -43,8 +43,9 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.function.IntSupplier;
|
||||
|
||||
import static com.volmit.iris.util.misc.ServerProperties.BUKKIT_YML;
|
||||
|
||||
/**
|
||||
* Makes it a lot easier to setup an engine, world, studio or whatever
|
||||
@@ -52,7 +53,6 @@ import java.util.function.Supplier;
|
||||
@Data
|
||||
@Accessors(fluent = true, chain = true)
|
||||
public class IrisCreator {
|
||||
private static final File BUKKIT_YML = new File("bukkit.yml");
|
||||
/**
|
||||
* 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()));
|
||||
}
|
||||
|
||||
PlatformChunkGenerator access;
|
||||
AtomicReference<World> world = new AtomicReference<>();
|
||||
AtomicDouble pp = new AtomicDouble(0);
|
||||
O<Boolean> done = new O<>();
|
||||
done.set(false);
|
||||
@@ -138,30 +136,29 @@ public class IrisCreator {
|
||||
.seed(seed)
|
||||
.studio(studio)
|
||||
.create();
|
||||
ServerConfigurator.installDataPacks(false);
|
||||
if (ServerConfigurator.installDataPacks(true)) {
|
||||
throw new IrisException("Datapacks were missing!");
|
||||
}
|
||||
|
||||
access = (PlatformChunkGenerator) wc.generator();
|
||||
PlatformChunkGenerator finalAccess1 = access;
|
||||
PlatformChunkGenerator access = (PlatformChunkGenerator) wc.generator();
|
||||
if (access == null) throw new IrisException("Access is null. Something bad happened.");
|
||||
|
||||
J.a(() ->
|
||||
{
|
||||
Supplier<Integer> g = () -> {
|
||||
if (finalAccess1 == null || finalAccess1.getEngine() == null) {
|
||||
J.a(() -> {
|
||||
IntSupplier g = () -> {
|
||||
if (access.getEngine() == null) {
|
||||
return 0;
|
||||
}
|
||||
return finalAccess1.getEngine().getGenerated();
|
||||
return access.getEngine().getGenerated();
|
||||
};
|
||||
if(!benchmark) {
|
||||
if (finalAccess1 == null) return;
|
||||
int req = finalAccess1.getSpawnChunks().join();
|
||||
|
||||
while (g.get() < req) {
|
||||
double v = (double) g.get() / (double) req;
|
||||
int req = access.getSpawnChunks().join();
|
||||
for (int c = 0; c < req && !done.get(); c = g.getAsInt()) {
|
||||
double v = (double) c / req;
|
||||
if (sender.isPlayer()) {
|
||||
sender.sendProgress(v, "Generating");
|
||||
J.sleep(16);
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
@@ -169,39 +166,33 @@ public class IrisCreator {
|
||||
});
|
||||
|
||||
|
||||
World world;
|
||||
try {
|
||||
J.sfut(() -> {
|
||||
world.set(INMS.get().createWorld(wc));
|
||||
}).get();
|
||||
world = J.sfut(() -> INMS.get().createWorld(wc)).get();
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
if (access == null) {
|
||||
throw new IrisException("Access is null. Something bad happened.");
|
||||
done.set(true);
|
||||
throw new IrisException("Failed to create world!", e);
|
||||
}
|
||||
|
||||
done.set(true);
|
||||
|
||||
if (sender.isPlayer() && !benchmark) {
|
||||
J.s(() -> {
|
||||
sender.player().teleport(new Location(world.get(), 0, world.get().getHighestBlockYAt(0, 0), 0));
|
||||
});
|
||||
J.s(() -> sender.player().teleport(new Location(world, 0, world.getHighestBlockYAt(0, 0) + 1, 0)));
|
||||
}
|
||||
|
||||
if (studio || benchmark) {
|
||||
J.s(() -> {
|
||||
Iris.linkMultiverseCore.removeFromConfig(world.get());
|
||||
Iris.linkMultiverseCore.removeFromConfig(world);
|
||||
|
||||
if (IrisSettings.get().getStudio().isDisableTimeAndWeather()) {
|
||||
world.get().setGameRule(GameRule.DO_WEATHER_CYCLE, false);
|
||||
world.get().setGameRule(GameRule.DO_DAYLIGHT_CYCLE, false);
|
||||
world.get().setTime(6000);
|
||||
world.setGameRule(GameRule.DO_WEATHER_CYCLE, false);
|
||||
world.setGameRule(GameRule.DO_DAYLIGHT_CYCLE, false);
|
||||
world.setTime(6000);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
addToBukkitYml();
|
||||
J.s(() -> Iris.linkMultiverseCore.updateWorld(world.get(), dimension));
|
||||
J.s(() -> Iris.linkMultiverseCore.updateWorld(world, dimension));
|
||||
}
|
||||
|
||||
if (pregen != null) {
|
||||
@@ -232,7 +223,7 @@ public class IrisCreator {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return world.get();
|
||||
return world;
|
||||
}
|
||||
|
||||
private void addToBukkitYml() {
|
||||
|
||||
@@ -34,6 +34,7 @@ import com.volmit.iris.util.plugin.VolmitSender;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@@ -45,6 +46,7 @@ import java.util.Map;
|
||||
* Hope you packed snacks & road sodas.
|
||||
*/
|
||||
public class IrisToolbelt {
|
||||
@ApiStatus.Internal
|
||||
public static Map<String, Boolean> toolbeltConfiguration = new HashMap<>();
|
||||
|
||||
/**
|
||||
@@ -232,7 +234,11 @@ public class IrisToolbelt {
|
||||
}
|
||||
|
||||
public static void retainMantleDataForSlice(String className) {
|
||||
toolbeltConfiguration.put("retain.mantle." + className, true);
|
||||
toolbeltConfiguration.put("retain.mantle." + className, Boolean.TRUE);
|
||||
}
|
||||
|
||||
public static boolean isRetainingMantleDataForSlice(String className) {
|
||||
return !toolbeltConfiguration.isEmpty() && toolbeltConfiguration.get("retain.mantle." + className) == Boolean.TRUE;
|
||||
}
|
||||
|
||||
public static <T> T getMantleData(World world, int x, int y, int z, Class<T> of) {
|
||||
|
||||
@@ -21,13 +21,10 @@ package com.volmit.iris.core.tools;
|
||||
import com.volmit.iris.core.loader.IrisData;
|
||||
import com.volmit.iris.engine.object.*;
|
||||
import com.volmit.iris.engine.platform.BukkitChunkGenerator;
|
||||
import com.volmit.iris.util.reflect.WrappedField;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.WorldCreator;
|
||||
import org.bukkit.WorldType;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
import sun.misc.Unsafe;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
@@ -67,7 +64,7 @@ public class IrisWorldCreator {
|
||||
}
|
||||
|
||||
public WorldCreator create() {
|
||||
IrisDimension dim = IrisData.loadAnyDimension(dimensionName);
|
||||
IrisDimension dim = IrisData.loadAnyDimension(dimensionName, null);
|
||||
|
||||
IrisWorld w = IrisWorld.builder()
|
||||
.name(name)
|
||||
@@ -83,13 +80,13 @@ public class IrisWorldCreator {
|
||||
|
||||
|
||||
return new WorldCreator(name)
|
||||
.environment(findEnvironment())
|
||||
.environment(w.environment())
|
||||
.generateStructures(true)
|
||||
.generator(g).seed(seed);
|
||||
}
|
||||
|
||||
private World.Environment findEnvironment() {
|
||||
IrisDimension dim = IrisData.loadAnyDimension(dimensionName);
|
||||
IrisDimension dim = IrisData.loadAnyDimension(dimensionName, null);
|
||||
if (dim == null || dim.getEnvironment() == null) {
|
||||
return World.Environment.NORMAL;
|
||||
} else {
|
||||
|
||||
@@ -25,8 +25,6 @@ import com.volmit.iris.engine.data.cache.Cache;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.object.*;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.collection.KSet;
|
||||
import com.volmit.iris.util.context.IrisContext;
|
||||
import com.volmit.iris.util.data.DataProvider;
|
||||
import com.volmit.iris.util.interpolation.IrisInterpolation.NoiseKey;
|
||||
@@ -43,7 +41,7 @@ import org.bukkit.block.Biome;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.UUID;
|
||||
import java.util.*;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(exclude = "data")
|
||||
@@ -53,7 +51,7 @@ public class IrisComplex implements DataProvider {
|
||||
private RNG rng;
|
||||
private double fluidHeight;
|
||||
private IrisData data;
|
||||
private KMap<IrisInterpolator, KSet<IrisGenerator>> generators;
|
||||
private Map<IrisInterpolator, Set<IrisGenerator>> generators;
|
||||
private ProceduralStream<IrisRegion> regionStream;
|
||||
private ProceduralStream<Double> regionStyleStream;
|
||||
private ProceduralStream<Double> regionIdentityStream;
|
||||
@@ -91,17 +89,17 @@ public class IrisComplex implements DataProvider {
|
||||
}
|
||||
|
||||
public IrisComplex(Engine engine, boolean simple) {
|
||||
int cacheSize = IrisSettings.get().getPerformance().getCacheSize();
|
||||
int cacheSize = IrisSettings.get().getPerformance().getNoiseCacheSize();
|
||||
IrisBiome emptyBiome = new IrisBiome();
|
||||
UUID focusUUID = UUID.nameUUIDFromBytes("focus".getBytes());
|
||||
this.rng = new RNG(engine.getSeedManager().getComplex());
|
||||
this.data = engine.getData();
|
||||
double height = engine.getMaxHeight();
|
||||
fluidHeight = engine.getDimension().getFluidHeight();
|
||||
generators = new KMap<>();
|
||||
generators = new HashMap<>();
|
||||
focusBiome = engine.getFocus();
|
||||
focusRegion = engine.getFocusRegion();
|
||||
KMap<InferredType, ProceduralStream<IrisBiome>> inferredStreams = new KMap<>();
|
||||
Map<InferredType, ProceduralStream<IrisBiome>> inferredStreams = new HashMap<>();
|
||||
|
||||
if (focusBiome != null) {
|
||||
focusBiome.setInferredType(InferredType.LAND);
|
||||
@@ -118,6 +116,7 @@ public class IrisComplex implements DataProvider {
|
||||
.getAllBiomes(this)
|
||||
.forEach(this::registerGenerators));
|
||||
}
|
||||
boolean legacy = engine.getDimension().isLegacyRarity();
|
||||
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)));
|
||||
rockStream = engine.getDimension().getRockPalette().getLayerGenerator(rng.nextParallelRNG(45), data).stream()
|
||||
@@ -131,7 +130,7 @@ public class IrisComplex implements DataProvider {
|
||||
ProceduralStream.of((x, z) -> focusRegion,
|
||||
Interpolated.of(a -> 0D, a -> focusRegion))
|
||||
: regionStyleStream
|
||||
.selectRarity(data.getRegionLoader().loadAll(engine.getDimension().getRegions()))
|
||||
.selectRarity(data.getRegionLoader().loadAll(engine.getDimension().getRegions()), legacy)
|
||||
.cache2D("regionStream", engine, cacheSize).waste("Region Stream");
|
||||
regionIDStream = regionIdentityStream.convertCached((i) -> new UUID(Double.doubleToLongBits(i),
|
||||
String.valueOf(i * 38445).hashCode() * 3245556666L)).waste("Region ID Stream");
|
||||
@@ -140,7 +139,7 @@ public class IrisComplex implements DataProvider {
|
||||
-> engine.getDimension().getCaveBiomeStyle().create(rng.nextParallelRNG(InferredType.CAVE.ordinal()), getData()).stream()
|
||||
.zoom(engine.getDimension().getBiomeZoom())
|
||||
.zoom(r.getCaveBiomeZoom())
|
||||
.selectRarity(data.getBiomeLoader().loadAll(r.getCaveBiomes()))
|
||||
.selectRarity(data.getBiomeLoader().loadAll(r.getCaveBiomes()), legacy)
|
||||
.onNull(emptyBiome)
|
||||
).convertAware2D(ProceduralStream::get).cache2D("caveBiomeStream", engine, cacheSize).waste("Cave Biome Stream");
|
||||
inferredStreams.put(InferredType.CAVE, caveBiomeStream);
|
||||
@@ -150,7 +149,7 @@ public class IrisComplex implements DataProvider {
|
||||
.zoom(engine.getDimension().getBiomeZoom())
|
||||
.zoom(engine.getDimension().getLandZoom())
|
||||
.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)
|
||||
.cache2D("landBiomeStream", engine, cacheSize).waste("Land Biome Stream");
|
||||
inferredStreams.put(InferredType.LAND, landBiomeStream);
|
||||
@@ -160,7 +159,7 @@ public class IrisComplex implements DataProvider {
|
||||
.zoom(engine.getDimension().getBiomeZoom())
|
||||
.zoom(engine.getDimension().getSeaZoom())
|
||||
.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)
|
||||
.cache2D("seaBiomeStream", engine, cacheSize).waste("Sea Biome Stream");
|
||||
inferredStreams.put(InferredType.SEA, seaBiomeStream);
|
||||
@@ -169,7 +168,7 @@ public class IrisComplex implements DataProvider {
|
||||
-> engine.getDimension().getShoreBiomeStyle().create(rng.nextParallelRNG(InferredType.SHORE.ordinal()), getData()).stream()
|
||||
.zoom(engine.getDimension().getBiomeZoom())
|
||||
.zoom(r.getShoreBiomeZoom())
|
||||
.selectRarity(data.getBiomeLoader().loadAll(r.getShoreBiomes(), (t) -> t.setInferredType(InferredType.SHORE)))
|
||||
.selectRarity(data.getBiomeLoader().loadAll(r.getShoreBiomes(), (t) -> t.setInferredType(InferredType.SHORE)), legacy)
|
||||
).convertAware2D(ProceduralStream::get).cache2D("shoreBiomeStream", engine, cacheSize).waste("Shore Biome Stream");
|
||||
inferredStreams.put(InferredType.SHORE, shoreBiomeStream);
|
||||
bridgeStream = focusBiome != null ? ProceduralStream.of((x, z) -> focusBiome.getInferredType(),
|
||||
@@ -302,12 +301,12 @@ public class IrisComplex implements DataProvider {
|
||||
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()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
KMap<NoiseKey, IrisBiome> cache = new KMap<>();
|
||||
HashMap<NoiseKey, IrisBiome> cache = new HashMap<>(64);
|
||||
double hi = interpolator.interpolate(x, z, (xx, zz) -> {
|
||||
try {
|
||||
IrisBiome bx = baseBiomeStream.get(xx, zz);
|
||||
@@ -379,7 +378,7 @@ public class IrisComplex implements DataProvider {
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -29,13 +29,15 @@ import com.volmit.iris.engine.mantle.components.MantleJigsawComponent;
|
||||
import com.volmit.iris.engine.mantle.components.MantleObjectComponent;
|
||||
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.mantle.Mantle;
|
||||
import com.volmit.iris.util.mantle.MantleFlag;
|
||||
import com.volmit.iris.util.mantle.flag.MantleFlag;
|
||||
import lombok.*;
|
||||
|
||||
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
|
||||
@EqualsAndHashCode(exclude = "engine")
|
||||
@@ -45,8 +47,9 @@ public class IrisEngineMantle implements EngineMantle {
|
||||
private final Mantle mantle;
|
||||
@Getter(AccessLevel.NONE)
|
||||
private final KMap<Integer, KList<MantleComponent>> components;
|
||||
private final AtomicCache<KList<Pair<KList<MantleComponent>, Integer>>> componentsCache = new AtomicCache<>();
|
||||
private final AtomicCache<KSet<MantleFlag>> disabledFlags = new AtomicCache<>();
|
||||
private final KMap<MantleFlag, MantleComponent> registeredComponents = new KMap<>();
|
||||
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 MantleJigsawComponent jigsaw;
|
||||
|
||||
@@ -75,7 +78,7 @@ public class IrisEngineMantle implements EngineMantle {
|
||||
}
|
||||
|
||||
@Override
|
||||
public KList<Pair<KList<MantleComponent>, Integer>> getComponents() {
|
||||
public List<Pair<List<MantleComponent>, Integer>> getComponents() {
|
||||
return componentsCache.aquire(() -> {
|
||||
var list = components.keySet()
|
||||
.stream()
|
||||
@@ -83,13 +86,14 @@ public class IrisEngineMantle implements EngineMantle {
|
||||
.map(components::get)
|
||||
.map(components -> {
|
||||
int radius = components.stream()
|
||||
.filter(MantleComponent::isEnabled)
|
||||
.mapToInt(MantleComponent::getRadius)
|
||||
.max()
|
||||
.orElse(0);
|
||||
return new Pair<>(components, radius);
|
||||
return new Pair<>(List.copyOf(components), radius);
|
||||
})
|
||||
.collect(Collectors.toCollection(KList::new));
|
||||
|
||||
.filter(pair -> !pair.getA().isEmpty())
|
||||
.toList();
|
||||
|
||||
int radius = 0;
|
||||
for (var pair : list.reversed()) {
|
||||
@@ -102,19 +106,36 @@ public class IrisEngineMantle implements EngineMantle {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerComponent(MantleComponent c) {
|
||||
c.setEnabled(!getDimension().getDisabledComponents().contains(c.getFlag()));
|
||||
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);
|
||||
componentsCache.reset();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KList<MantleFlag> getComponentFlags() {
|
||||
return components.values()
|
||||
.stream()
|
||||
.flatMap(KList::stream)
|
||||
.map(MantleComponent::getFlag)
|
||||
.collect(KList.collector());
|
||||
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
|
||||
|
||||
@@ -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.core.IrisSettings;
|
||||
import com.volmit.iris.core.link.Identifier;
|
||||
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.EngineAssignedWorldManager;
|
||||
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.format.Form;
|
||||
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.Position2;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
@@ -424,18 +426,35 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
|
||||
}
|
||||
|
||||
var ref = new WeakReference<>(e.getWorld());
|
||||
int x = e.getX(), z = e.getZ();
|
||||
int cX = e.getX(), cZ = e.getZ();
|
||||
J.s(() -> {
|
||||
World world = ref.get();
|
||||
if (world == null || !world.isChunkLoaded(x, z))
|
||||
if (world == null || !world.isChunkLoaded(cX, cZ))
|
||||
return;
|
||||
energy += 0.3;
|
||||
fixEnergy();
|
||||
getEngine().cleanupMantleChunk(x, z);
|
||||
getEngine().cleanupMantleChunk(cX, cZ);
|
||||
}, IrisSettings.get().getPerformance().mantleCleanupDelay);
|
||||
|
||||
if (generated) {
|
||||
//INMS.get().injectBiomesFromMantle(e, getMantle());
|
||||
|
||||
if (!IrisSettings.get().getGenerator().earlyCustomBlocks) return;
|
||||
Iris.tickets.addTicket(e);
|
||||
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();
|
||||
Iris.tickets.removeTicket(e);
|
||||
}
|
||||
}, RNG.r.i(20, 60));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
package com.volmit.iris.engine.framework;
|
||||
|
||||
import com.volmit.iris.util.mantle.MantleChunk;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
@@ -28,5 +29,5 @@ public interface BlockUpdater {
|
||||
|
||||
void updateChunk(Chunk c);
|
||||
|
||||
void update(int x, int y, int z, Chunk c, RNG rf);
|
||||
void update(int x, int y, int z, Chunk c, MantleChunk mc, RNG rf);
|
||||
}
|
||||
|
||||
@@ -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.Pair;
|
||||
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.engine.IrisComplex;
|
||||
import com.volmit.iris.engine.data.cache.Cache;
|
||||
import com.volmit.iris.engine.data.chunk.TerrainChunk;
|
||||
import com.volmit.iris.engine.mantle.EngineMantle;
|
||||
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.KMap;
|
||||
import com.volmit.iris.util.context.ChunkContext;
|
||||
@@ -48,7 +48,8 @@ import com.volmit.iris.util.documentation.ChunkCoordinates;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.function.Function2;
|
||||
import com.volmit.iris.util.hunk.Hunk;
|
||||
import com.volmit.iris.util.mantle.MantleFlag;
|
||||
import com.volmit.iris.util.mantle.MantleChunk;
|
||||
import com.volmit.iris.util.mantle.flag.MantleFlag;
|
||||
import com.volmit.iris.util.math.BlockPosition;
|
||||
import com.volmit.iris.util.math.M;
|
||||
import com.volmit.iris.util.math.Position2;
|
||||
@@ -110,7 +111,7 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
|
||||
|
||||
IrisContext getContext();
|
||||
|
||||
EngineExecutionEnvironment getExecution();
|
||||
EngineEnvironment getExecution();
|
||||
|
||||
double getMaxBiomeObjectDensity();
|
||||
|
||||
@@ -231,6 +232,9 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
|
||||
@ChunkCoordinates
|
||||
IrisJigsawStructure getStructureAt(int x, int z);
|
||||
|
||||
@BlockCoordinates
|
||||
IrisJigsawStructure getStructureAt(int x, int y, int z);
|
||||
|
||||
@BlockCoordinates
|
||||
default IrisBiome getCaveBiome(int x, int z) {
|
||||
return getComplex().getCaveBiomeStream().get(x, z);
|
||||
@@ -262,7 +266,7 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
|
||||
getMantle().updateBlock(x, y, z);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -291,110 +295,107 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
|
||||
|
||||
var chunk = mantle.getChunk(c).use();
|
||||
try {
|
||||
Semaphore semaphore = new Semaphore(3);
|
||||
chunk.raiseFlag(MantleFlag.ETCHED, () -> {
|
||||
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());
|
||||
Semaphore semaphore = new Semaphore(1024);
|
||||
chunk.raiseFlagUnchecked(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());
|
||||
});
|
||||
})));
|
||||
chunk.raiseFlag(MantleFlag.CUSTOM, run(semaphore, () -> J.s(() -> {
|
||||
mantle.iterateChunk(c.getX(), c.getZ(), Identifier.class, (x, y, z, v) -> {
|
||||
}, 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.raiseFlag(MantleFlag.UPDATE, run(semaphore, () -> J.s(() -> {
|
||||
chunk.raiseFlagUnchecked(MantleFlag.UPDATE, run(semaphore, () -> {
|
||||
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[][] 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();
|
||||
if (!B.isFluid(c.getBlock(x & 15, y, z & 15).getBlockData())) {
|
||||
x &= 15;
|
||||
z &= 15;
|
||||
Block block = c.getBlock(x, y, z);
|
||||
if (!B.isFluid(block.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;
|
||||
}
|
||||
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) {
|
||||
updates.compute(Cache.key(x & 15, z & 15), (k, vv) -> {
|
||||
if (vv != null) {
|
||||
return Math.max(vv, y);
|
||||
}
|
||||
|
||||
return y;
|
||||
});
|
||||
}
|
||||
if (u) grid[x][z] = Math.max(grid[x][z], 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) -> {
|
||||
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, chunk, rng);
|
||||
}
|
||||
}
|
||||
|
||||
chunk.iterate(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);
|
||||
}
|
||||
update(x, y, z, c, chunk, rng);
|
||||
}
|
||||
});
|
||||
mantle.deleteChunkSlice(c.getX(), c.getZ(), MatterUpdate.class);
|
||||
chunk.deleteSlices(MatterUpdate.class);
|
||||
getMetrics().getUpdates().put(p.getMilliseconds());
|
||||
}, RNG.r.i(0, 20))));
|
||||
}, RNG.r.i(1, 20))); //Why is there a random delay here?
|
||||
});
|
||||
|
||||
chunk.raiseFlagUnchecked(MantleFlag.SCRIPT, () -> {
|
||||
var scripts = getDimension().getChunkUpdateScripts();
|
||||
if (scripts == null || scripts.isEmpty())
|
||||
return;
|
||||
|
||||
for (var script : scripts) {
|
||||
getExecution().updateChunk(script, chunk, c, (delay, task) -> run(semaphore, task, delay));
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
semaphore.acquire(3);
|
||||
semaphore.acquire(1024);
|
||||
} 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 () -> {
|
||||
if (!semaphore.tryAcquire())
|
||||
return;
|
||||
try {
|
||||
runnable.run();
|
||||
} finally {
|
||||
semaphore.release();
|
||||
semaphore.acquire();
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
J.s(() -> {
|
||||
try {
|
||||
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
|
||||
@Override
|
||||
|
||||
default void update(int x, int y, int z, Chunk c, RNG rf) {
|
||||
default void update(int x, int y, int z, Chunk c, MantleChunk mc, RNG rf) {
|
||||
Block block = c.getBlock(x, y, z);
|
||||
BlockData data = block.getBlockData();
|
||||
blockUpdatedMetric();
|
||||
@@ -407,17 +408,11 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
|
||||
}
|
||||
|
||||
if (slot != null) {
|
||||
KList<IrisLootTable> tables = getLootTables(rx, block);
|
||||
KList<IrisLootTable> tables = getLootTables(rx, block, mc);
|
||||
|
||||
try {
|
||||
Bukkit.getPluginManager().callEvent(new IrisLootEvent(this, block, slot, tables));
|
||||
|
||||
if (!tables.isEmpty()){
|
||||
Iris.debug("IrisLootEvent has been accessed");
|
||||
}
|
||||
|
||||
if (tables.isEmpty())
|
||||
return;
|
||||
if (tables.isEmpty()) return;
|
||||
InventoryHolder m = (InventoryHolder) block.getState();
|
||||
addItems(false, m.getInventory(), rx, tables, slot, c.getWorld(), x, y, z, 15);
|
||||
|
||||
@@ -483,13 +478,23 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
|
||||
@BlockCoordinates
|
||||
@Override
|
||||
default KList<IrisLootTable> getLootTables(RNG rng, Block b) {
|
||||
MantleChunk mc = getMantle().getMantle().getChunk(b.getChunk()).use();
|
||||
try {
|
||||
return getLootTables(rng, b, mc);
|
||||
} finally {
|
||||
mc.release();
|
||||
}
|
||||
}
|
||||
|
||||
@BlockCoordinates
|
||||
default KList<IrisLootTable> getLootTables(RNG rng, Block b, MantleChunk mc) {
|
||||
int rx = b.getX();
|
||||
int rz = b.getZ();
|
||||
int ry = b.getY() - getWorld().minHeight();
|
||||
double he = getComplex().getHeightStream().get(rx, rz);
|
||||
KList<IrisLootTable> tables = new KList<>();
|
||||
|
||||
PlacedObject po = getObjectPlacement(rx, ry, rz);
|
||||
PlacedObject po = getObjectPlacement(rx, ry, rz, mc);
|
||||
if (po != null && po.getPlacement() != null) {
|
||||
if (B.isStorageChest(b.getBlockData())) {
|
||||
IrisLootTable table = po.getPlacement().getTable(b.getBlockData(), getData());
|
||||
@@ -812,7 +817,16 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
|
||||
}
|
||||
|
||||
default PlacedObject getObjectPlacement(int x, int y, int z) {
|
||||
String objectAt = getMantle().getMantle().get(x, y, z, String.class);
|
||||
MantleChunk chunk = getMantle().getMantle().getChunk(x >> 4, z >> 4).use();
|
||||
try {
|
||||
return getObjectPlacement(x, y, z, chunk);
|
||||
} finally {
|
||||
chunk.release();
|
||||
}
|
||||
}
|
||||
|
||||
default PlacedObject getObjectPlacement(int x, int y, int z, MantleChunk chunk) {
|
||||
String objectAt = chunk.get(x & 15, y, z & 15, String.class);
|
||||
if (objectAt == null || objectAt.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
@@ -822,7 +836,7 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
|
||||
int id = Integer.parseInt(v[1]);
|
||||
|
||||
|
||||
JigsawPieceContainer container = getMantle().getMantle().get(x, y, z, JigsawPieceContainer.class);
|
||||
JigsawPieceContainer container = chunk.get(x & 15, y, z & 15, JigsawPieceContainer.class);
|
||||
if (container != null) {
|
||||
IrisJigsawPiece piece = container.load(getData());
|
||||
if (piece.getObject().equals(object))
|
||||
@@ -837,7 +851,7 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
|
||||
}
|
||||
}
|
||||
|
||||
IrisBiome biome = getBiome(x, y, z);
|
||||
IrisBiome biome = getSurfaceBiome(x, z);
|
||||
|
||||
for (IrisObjectPlacement i : biome.getObjects()) {
|
||||
if (i.getPlace().contains(object)) {
|
||||
@@ -876,7 +890,7 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
|
||||
default void gotoBiome(IrisBiome biome, Player player, boolean teleport) {
|
||||
Set<String> regionKeys = getDimension()
|
||||
.getAllRegions(this).stream()
|
||||
.filter((i) -> i.getAllBiomes(this).contains(biome))
|
||||
.filter((i) -> i.getAllBiomeIds().contains(biome.getLoadKey()))
|
||||
.map(IrisRegistrant::getLoadKey)
|
||||
.collect(Collectors.toSet());
|
||||
Locator<IrisBiome> lb = Locator.surfaceBiome(biome.getLoadKey());
|
||||
@@ -972,7 +986,7 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
|
||||
}
|
||||
|
||||
default void gotoRegion(IrisRegion r, Player player, boolean teleport) {
|
||||
if (!getDimension().getAllRegions(this).contains(r)) {
|
||||
if (!getDimension().getRegions().contains(r.getLoadKey())) {
|
||||
player.sendMessage(C.RED + r.getName() + " is not defined in the dimension!");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -22,8 +22,7 @@ import com.volmit.iris.engine.object.IrisObject;
|
||||
import com.volmit.iris.engine.object.IrisObjectPlacement;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
|
||||
@@ -24,7 +24,6 @@ import com.volmit.iris.engine.object.IObjectPlacer;
|
||||
import com.volmit.iris.engine.object.IrisObjectPlacement;
|
||||
import com.volmit.iris.engine.object.TileData;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import org.bukkit.block.TileState;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
|
||||
public class HeightmapObjectPlacer implements IObjectPlacer {
|
||||
@@ -83,6 +82,16 @@ public class HeightmapObjectPlacer implements IObjectPlacer {
|
||||
oplacer.setTile(param1Int1, param1Int2, param1Int3, param1TileData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void setData(int xx, int yy, int zz, T data) {
|
||||
oplacer.setData(xx, yy, zz, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T getData(int xx, int yy, int zz, Class<T> t) {
|
||||
return oplacer.getData(xx, yy, zz, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Engine getEngine() {
|
||||
return null;
|
||||
|
||||
@@ -59,6 +59,11 @@ public class WorldObjectPlacer implements IObjectPlacer {
|
||||
slot = InventorySlotType.STORAGE;
|
||||
}
|
||||
|
||||
if (d instanceof IrisCustomData data) {
|
||||
block.setBlockData(data.getBase(), false);
|
||||
Iris.warn("Tried to place custom block at " + x + ", " + y + ", " + z + " which is not supported!");
|
||||
} else block.setBlockData(d, false);
|
||||
|
||||
if (slot != null) {
|
||||
RNG rx = new RNG(Cache.key(x, z));
|
||||
KList<IrisLootTable> tables = engine.getLootTables(rx, block);
|
||||
@@ -78,12 +83,6 @@ public class WorldObjectPlacer implements IObjectPlacer {
|
||||
Iris.reportError(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (d instanceof IrisCustomData data) {
|
||||
block.setBlockData(data.getBase());
|
||||
Iris.warn("Tried to place custom block at " + x + ", " + y + ", " + z + " which is not supported!");
|
||||
} else block.setBlockData(d);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -125,4 +124,13 @@ public class WorldObjectPlacer implements IObjectPlacer {
|
||||
public void setTile(int xx, int yy, int zz, TileData tile) {
|
||||
tile.toBukkitTry(world.getBlockAt(xx, yy + world.getMinHeight(), zz));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void setData(int xx, int yy, int zz, T data) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T getData(int xx, int yy, int zz, Class<T> t) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ public class PlannedPiece {
|
||||
this.setRotation(rot);
|
||||
this.ogObject = data.getObjectLoader().load(piece.getObject());
|
||||
this.object = structure.rotated(piece, rotation);
|
||||
this.piece = rotation.rotateCopy(piece);
|
||||
this.piece = rotation.rotateCopy(piece, new IrisPosition(object.getShrinkOffset()));
|
||||
this.piece.setLoadKey(piece.getLoadKey());
|
||||
this.object.setLoadKey(piece.getObject());
|
||||
this.ogObject.setLoadKey(piece.getObject());
|
||||
|
||||
@@ -29,6 +29,7 @@ import com.volmit.iris.util.mantle.Mantle;
|
||||
import com.volmit.iris.util.math.Position2;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import com.volmit.iris.util.matter.slices.container.JigsawPieceContainer;
|
||||
import com.volmit.iris.util.matter.slices.container.JigsawStructureContainer;
|
||||
import com.volmit.iris.util.matter.slices.container.JigsawStructuresContainer;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import lombok.Data;
|
||||
@@ -149,11 +150,13 @@ public class PlannedStructure {
|
||||
}
|
||||
|
||||
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);
|
||||
return v.place(xx, height, zz, placer, options, rng, (b, data) -> {
|
||||
e.set(b.getX(), b.getY(), b.getZ(), v.getLoadKey() + "@" + id);
|
||||
e.set(b.getX(), b.getY(), b.getZ(), container);
|
||||
placer.setData(b.getX(), b.getY(), b.getZ(), v.getLoadKey() + "@" + id);
|
||||
placer.setData(b.getX(), b.getY(), b.getZ(), structure);
|
||||
placer.setData(b.getX(), b.getY(), b.getZ(), piece);
|
||||
}, null, getData().getEngine() != null ? getData() : eng.getData()) != -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.volmit.iris.engine.mantle;
|
||||
|
||||
import com.volmit.iris.util.mantle.MantleFlag;
|
||||
import com.volmit.iris.util.mantle.flag.ReservedFlag;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
@@ -10,5 +10,5 @@ import java.lang.annotation.Target;
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface ComponentFlag {
|
||||
MantleFlag value();
|
||||
ReservedFlag value();
|
||||
}
|
||||
|
||||
@@ -26,31 +26,27 @@ import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.framework.EngineTarget;
|
||||
import com.volmit.iris.engine.mantle.components.MantleJigsawComponent;
|
||||
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.IrisPosition;
|
||||
import com.volmit.iris.engine.object.TileData;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.context.ChunkContext;
|
||||
import com.volmit.iris.util.context.IrisContext;
|
||||
import com.volmit.iris.util.data.B;
|
||||
import com.volmit.iris.util.data.IrisCustomData;
|
||||
import com.volmit.iris.util.documentation.BlockCoordinates;
|
||||
import com.volmit.iris.util.documentation.ChunkCoordinates;
|
||||
import com.volmit.iris.util.hunk.Hunk;
|
||||
import com.volmit.iris.util.mantle.Mantle;
|
||||
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.matter.*;
|
||||
import com.volmit.iris.util.matter.slices.UpdateMatter;
|
||||
import com.volmit.iris.util.parallel.BurstExecutor;
|
||||
import com.volmit.iris.util.parallel.MultiBurst;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.jetbrains.annotations.UnmodifiableView;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
// TODO: MOVE PLACER OUT OF MATTER INTO ITS OWN THING
|
||||
public interface EngineMantle extends IObjectPlacer {
|
||||
public interface EngineMantle extends MatterGenerator {
|
||||
BlockData AIR = B.get("AIR");
|
||||
|
||||
Mantle getMantle();
|
||||
@@ -61,12 +57,19 @@ public interface EngineMantle extends IObjectPlacer {
|
||||
|
||||
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) {
|
||||
return getHighest(x, z, getData());
|
||||
}
|
||||
@@ -87,12 +90,10 @@ public interface EngineMantle extends IObjectPlacer {
|
||||
return getHighest(x, z, getData(), ignoreFluid);
|
||||
}
|
||||
|
||||
@Override
|
||||
default int getHighest(int x, int z, IrisData data) {
|
||||
return getHighest(x, z, data, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
default int getHighest(int x, int z, IrisData data, boolean ignoreFluid) {
|
||||
return ignoreFluid ? trueHeight(x, z) : Math.max(trueHeight(x, z), getEngine().getDimension().getFluidHeight());
|
||||
}
|
||||
@@ -101,24 +102,12 @@ public interface EngineMantle extends IObjectPlacer {
|
||||
return getComplex().getRoundedHeighteightStream().get(x, z);
|
||||
}
|
||||
|
||||
@Deprecated(forRemoval = true)
|
||||
default boolean isCarved(int x, int h, int z) {
|
||||
return getMantle().get(x, h, z, MatterCavern.class) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
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
|
||||
@Deprecated(forRemoval = true)
|
||||
default BlockData get(int x, int y, int z) {
|
||||
BlockData block = getMantle().get(x, y, z, BlockData.class);
|
||||
if (block == null)
|
||||
@@ -126,27 +115,18 @@ public interface EngineMantle extends IObjectPlacer {
|
||||
return block;
|
||||
}
|
||||
|
||||
@Override
|
||||
default boolean isPreventingDecay() {
|
||||
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) {
|
||||
return getHighest(x, z, true) <= getFluidHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
default int getFluidHeight() {
|
||||
return getEngine().getDimension().getFluidHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
default boolean isDebugSmartBore() {
|
||||
return getEngine().getDimension().isDebugSmartBore();
|
||||
}
|
||||
@@ -194,53 +174,18 @@ public interface EngineMantle extends IObjectPlacer {
|
||||
return getEngine().burst();
|
||||
}
|
||||
|
||||
@ChunkCoordinates
|
||||
default void generateMatter(int x, int z, boolean multicore, ChunkContext context) {
|
||||
if (!getEngine().getDimension().isUseMantle()) {
|
||||
return;
|
||||
}
|
||||
|
||||
try (MantleWriter writer = getMantle().write(this, x, z, getRadius() * 2)) {
|
||||
var iterator = getComponents().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
var pair = iterator.next();
|
||||
int radius = pair.getB();
|
||||
boolean last = !iterator.hasNext();
|
||||
BurstExecutor burst = burst().burst(radius * 2 + 1);
|
||||
burst.setMulticore(multicore);
|
||||
|
||||
for (int i = -radius; i <= radius; i++) {
|
||||
for (int j = -radius; j <= radius; j++) {
|
||||
int xx = x + i;
|
||||
int zz = z + j;
|
||||
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) {
|
||||
mc.raiseFlag(c.getFlag(), () -> {
|
||||
if (c.isEnabled()) c.generateLayer(writer, x, z, context);
|
||||
});
|
||||
}
|
||||
|
||||
@ChunkCoordinates
|
||||
default <T> void insertMatter(int x, int z, Class<T> t, Hunk<T> blocks, boolean multicore) {
|
||||
if (!getEngine().getDimension().isUseMantle()) {
|
||||
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
|
||||
@@ -268,9 +213,6 @@ public interface EngineMantle extends IObjectPlacer {
|
||||
default int getLoadedRegionCount() {
|
||||
return getMantle().getLoadedRegionCount();
|
||||
}
|
||||
default long getLastUseMapMemoryUsage(){
|
||||
return getMantle().LastUseMapMemoryUsage();
|
||||
}
|
||||
|
||||
MantleJigsawComponent getJigsawComponent();
|
||||
|
||||
@@ -296,7 +238,7 @@ public interface EngineMantle extends IObjectPlacer {
|
||||
if (!isCovered(x, z)) return;
|
||||
MantleChunk chunk = getMantle().getChunk(x, z).use();
|
||||
try {
|
||||
chunk.raiseFlag(MantleFlag.CLEANED, () -> {
|
||||
chunk.raiseFlagUnchecked(MantleFlag.CLEANED, () -> {
|
||||
chunk.deleteSlices(BlockData.class);
|
||||
chunk.deleteSlices(String.class);
|
||||
chunk.deleteSlices(MatterCavern.class);
|
||||
@@ -307,7 +249,7 @@ public interface EngineMantle extends IObjectPlacer {
|
||||
}
|
||||
}
|
||||
|
||||
default long getUnloadRegionCount() {
|
||||
default int getUnloadRegionCount() {
|
||||
return getMantle().getUnloadRegionCount();
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
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.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
@@ -30,5 +30,32 @@ public abstract class IrisMantleComponent implements MantleComponent {
|
||||
private final EngineMantle engineMantle;
|
||||
private final MantleFlag flag;
|
||||
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.documentation.ChunkCoordinates;
|
||||
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 org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -65,6 +65,8 @@ public interface MantleComponent extends Comparable<MantleComponent> {
|
||||
|
||||
void setEnabled(boolean b);
|
||||
|
||||
void hotload();
|
||||
|
||||
@ChunkCoordinates
|
||||
void generateLayer(MantleWriter writer, int x, int z, ChunkContext context);
|
||||
|
||||
|
||||
@@ -29,38 +29,44 @@ import com.volmit.iris.engine.object.IrisPosition;
|
||||
import com.volmit.iris.engine.object.TileData;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
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.documentation.ChunkCoordinates;
|
||||
import com.volmit.iris.util.function.Function3;
|
||||
import com.volmit.iris.util.mantle.Mantle;
|
||||
import com.volmit.iris.util.mantle.MantleChunk;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
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 org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
import static com.volmit.iris.engine.mantle.EngineMantle.AIR;
|
||||
|
||||
@Data
|
||||
public class MantleWriter implements IObjectPlacer, AutoCloseable {
|
||||
private final EngineMantle engineMantle;
|
||||
private final Mantle mantle;
|
||||
private final KMap<Long, MantleChunk> cachedChunks;
|
||||
private final Map<Long, MantleChunk> cachedChunks;
|
||||
private final int radius;
|
||||
private final int x;
|
||||
private final int z;
|
||||
|
||||
public MantleWriter(EngineMantle engineMantle, Mantle mantle, int x, int z, int radius) {
|
||||
public MantleWriter(EngineMantle engineMantle, Mantle mantle, int x, int z, int radius, boolean multicore) {
|
||||
this.engineMantle = engineMantle;
|
||||
this.mantle = mantle;
|
||||
this.cachedChunks = new KMap<>();
|
||||
this.radius = radius;
|
||||
this.radius = radius * 2;
|
||||
int d = this.radius + 1;
|
||||
this.cachedChunks = multicore ? new KMap<>(d * d, 0.75f, Math.max(32, Runtime.getRuntime().availableProcessors() * 4)) : new HashMap<>(d * d);
|
||||
this.x = x;
|
||||
this.z = z;
|
||||
|
||||
int r = radius / 4;
|
||||
int r = radius / 2;
|
||||
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());
|
||||
@@ -71,6 +77,7 @@ public class MantleWriter implements IObjectPlacer, AutoCloseable {
|
||||
private static Set<IrisPosition> getBallooned(Set<IrisPosition> vset, double radius) {
|
||||
Set<IrisPosition> returnset = new HashSet<>();
|
||||
int ceilrad = (int) Math.ceil(radius);
|
||||
double r2 = Math.pow(radius, 2);
|
||||
|
||||
for (IrisPosition v : vset) {
|
||||
int tipx = v.getX();
|
||||
@@ -80,7 +87,7 @@ public class MantleWriter implements IObjectPlacer, AutoCloseable {
|
||||
for (int loopx = tipx - ceilrad; loopx <= tipx + ceilrad; loopx++) {
|
||||
for (int loopy = tipy - ceilrad; loopy <= tipy + ceilrad; loopy++) {
|
||||
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));
|
||||
}
|
||||
}
|
||||
@@ -113,7 +120,7 @@ public class MantleWriter implements IObjectPlacer, AutoCloseable {
|
||||
for (double d : pars) {
|
||||
sum += Math.pow(d, 2);
|
||||
}
|
||||
return Math.sqrt(sum);
|
||||
return sum;
|
||||
}
|
||||
|
||||
private static double lengthSq(double x, double y, double z) {
|
||||
@@ -142,20 +149,46 @@ public class MantleWriter implements IObjectPlacer, AutoCloseable {
|
||||
return;
|
||||
}
|
||||
|
||||
if (cx >= this.x - radius && cx <= this.x + radius
|
||||
&& cz >= this.z - radius && cz <= this.z + radius) {
|
||||
MantleChunk chunk = cachedChunks.computeIfAbsent(Cache.key(cx, cz), k -> mantle.getChunk(cx, cz).use());
|
||||
MantleChunk chunk = acquireChunk(cx, cz);
|
||||
if (chunk == null) return;
|
||||
|
||||
if (chunk == null) {
|
||||
Iris.error("Mantle Writer Accessed " + cx + "," + cz + " and came up null (and yet within bounds!)");
|
||||
return;
|
||||
}
|
||||
Matter matter = chunk.getOrCreate(y >> 4);
|
||||
matter.slice(matter.getClass(t)).set(x & 15, y & 15, z & 15, t);
|
||||
}
|
||||
|
||||
Matter matter = chunk.getOrCreate(y >> 4);
|
||||
matter.slice(matter.getClass(t)).set(x & 15, y & 15, z & 15, t);
|
||||
} else {
|
||||
Iris.error("Mantle Writer Accessed chunk out of bounds" + cx + "," + cz);
|
||||
public <T> T getData(int x, int y, int z, Class<T> type) {
|
||||
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;
|
||||
}
|
||||
final Long key = Cache.key(cx, cz);
|
||||
MantleChunk chunk = cachedChunks.get(key);
|
||||
if (chunk == null) {
|
||||
chunk = mantle.getChunk(cx, cz).use();
|
||||
var old = cachedChunks.put(key, chunk);
|
||||
if (old != null) old.release();
|
||||
}
|
||||
return chunk;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -178,7 +211,10 @@ public class MantleWriter implements IObjectPlacer, AutoCloseable {
|
||||
|
||||
@Override
|
||||
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
|
||||
@@ -188,12 +224,12 @@ public class MantleWriter implements IObjectPlacer, AutoCloseable {
|
||||
|
||||
@Override
|
||||
public boolean isCarved(int x, int y, int z) {
|
||||
return getEngineMantle().isCarved(x, y, z);
|
||||
return getData(x, y, z, MatterCavern.class) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSolid(int x, int y, int z) {
|
||||
return getEngineMantle().isSolid(x, y, z);
|
||||
return B.isSolid(get(x, y, z));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -213,7 +249,7 @@ public class MantleWriter implements IObjectPlacer, AutoCloseable {
|
||||
|
||||
@Override
|
||||
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
|
||||
@@ -453,6 +489,62 @@ public class MantleWriter implements IObjectPlacer, AutoCloseable {
|
||||
* @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) {
|
||||
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<>();
|
||||
|
||||
for (int i = 0; vectors.size() != 0 && i < vectors.size() - 1; i++) {
|
||||
@@ -504,13 +596,7 @@ public class MantleWriter implements IObjectPlacer, AutoCloseable {
|
||||
}
|
||||
}
|
||||
|
||||
vset = getBallooned(vset, radius);
|
||||
|
||||
if (!filled) {
|
||||
vset = getHollowed(vset);
|
||||
}
|
||||
|
||||
setConsumer(vset, data);
|
||||
return vset;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -28,17 +28,13 @@ import com.volmit.iris.engine.object.IrisCarving;
|
||||
import com.volmit.iris.engine.object.IrisRegion;
|
||||
import com.volmit.iris.util.context.ChunkContext;
|
||||
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 lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@ComponentFlag(MantleFlag.CARVED)
|
||||
@ComponentFlag(ReservedFlag.CARVED)
|
||||
public class MantleCarvingComponent extends IrisMantleComponent {
|
||||
private final int radius = computeRadius();
|
||||
|
||||
public MantleCarvingComponent(EngineMantle engineMantle) {
|
||||
super(engineMantle, MantleFlag.CARVED, 0);
|
||||
super(engineMantle, ReservedFlag.CARVED, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -63,7 +59,7 @@ public class MantleCarvingComponent extends IrisMantleComponent {
|
||||
carving.doCarving(writer, rng, getEngineMantle().getEngine(), cx << 4, -1, cz << 4, 0);
|
||||
}
|
||||
|
||||
private int computeRadius() {
|
||||
protected int computeRadius() {
|
||||
var dimension = getDimension();
|
||||
int max = 0;
|
||||
|
||||
|
||||
@@ -28,17 +28,13 @@ import com.volmit.iris.engine.object.IrisFluidBodies;
|
||||
import com.volmit.iris.engine.object.IrisRegion;
|
||||
import com.volmit.iris.util.context.ChunkContext;
|
||||
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 lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@ComponentFlag(MantleFlag.FLUID_BODIES)
|
||||
@ComponentFlag(ReservedFlag.FLUID_BODIES)
|
||||
public class MantleFluidBodyComponent extends IrisMantleComponent {
|
||||
private final int radius = computeRadius();
|
||||
|
||||
public MantleFluidBodyComponent(EngineMantle engineMantle) {
|
||||
super(engineMantle, MantleFlag.FLUID_BODIES, 0);
|
||||
super(engineMantle, ReservedFlag.FLUID_BODIES, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -63,7 +59,7 @@ public class MantleFluidBodyComponent extends IrisMantleComponent {
|
||||
bodies.generate(writer, rng, getEngineMantle().getEngine(), cx << 4, -1, cz << 4);
|
||||
}
|
||||
|
||||
private int computeRadius() {
|
||||
protected int computeRadius() {
|
||||
int max = 0;
|
||||
|
||||
max = Math.max(max, getDimension().getFluidBodies().getMaxRange(getData()));
|
||||
|
||||
@@ -30,24 +30,21 @@ import com.volmit.iris.util.collection.KSet;
|
||||
import com.volmit.iris.util.context.ChunkContext;
|
||||
import com.volmit.iris.util.documentation.BlockCoordinates;
|
||||
import com.volmit.iris.util.documentation.ChunkCoordinates;
|
||||
import com.volmit.iris.util.mantle.MantleFlag;
|
||||
import com.volmit.iris.util.mantle.flag.ReservedFlag;
|
||||
import com.volmit.iris.util.math.Position2;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import com.volmit.iris.util.matter.slices.container.JigsawStructuresContainer;
|
||||
import com.volmit.iris.util.noise.CNG;
|
||||
import lombok.Getter;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ComponentFlag(MantleFlag.JIGSAW)
|
||||
@ComponentFlag(ReservedFlag.JIGSAW)
|
||||
public class MantleJigsawComponent extends IrisMantleComponent {
|
||||
@Getter
|
||||
private final int radius = computeRadius();
|
||||
private final CNG cng;
|
||||
|
||||
public MantleJigsawComponent(EngineMantle engineMantle) {
|
||||
super(engineMantle, MantleFlag.JIGSAW, 1);
|
||||
super(engineMantle, ReservedFlag.JIGSAW, 1);
|
||||
cng = NoiseStyle.STATIC.create(new RNG(jigsaw()));
|
||||
}
|
||||
|
||||
@@ -169,6 +166,7 @@ public class MantleJigsawComponent extends IrisMantleComponent {
|
||||
|
||||
@BlockCoordinates
|
||||
private boolean place(MantleWriter writer, IrisPosition position, IrisJigsawStructure structure, RNG rng, boolean forcePlace) {
|
||||
if (structure == null || structure.getDatapackStructures().isNotEmpty()) return false;
|
||||
return new PlannedStructure(structure, position, rng, forcePlace).place(writer, getMantle(), writer.getEngine());
|
||||
}
|
||||
|
||||
@@ -176,10 +174,14 @@ public class MantleJigsawComponent extends IrisMantleComponent {
|
||||
return getEngineMantle().getEngine().getSeedManager().getJigsaw();
|
||||
}
|
||||
|
||||
private int computeRadius() {
|
||||
protected int computeRadius() {
|
||||
var dimension = getDimension();
|
||||
|
||||
KSet<String> structures = new KSet<>();
|
||||
if (dimension.getStronghold() != null) {
|
||||
structures.add(dimension.getStronghold());
|
||||
}
|
||||
|
||||
for (var placement : dimension.getJigsawStructures()) {
|
||||
structures.add(placement.getStructure());
|
||||
}
|
||||
|
||||
@@ -33,13 +33,12 @@ import com.volmit.iris.util.data.B;
|
||||
import com.volmit.iris.util.documentation.BlockCoordinates;
|
||||
import com.volmit.iris.util.documentation.ChunkCoordinates;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
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.matter.MatterStructurePOI;
|
||||
import com.volmit.iris.util.noise.CNG;
|
||||
import com.volmit.iris.util.noise.NoiseType;
|
||||
import com.volmit.iris.util.parallel.BurstExecutor;
|
||||
import lombok.Getter;
|
||||
import org.bukkit.util.BlockVector;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -47,13 +46,11 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
@Getter
|
||||
@ComponentFlag(MantleFlag.OBJECT)
|
||||
@ComponentFlag(ReservedFlag.OBJECT)
|
||||
public class MantleObjectComponent extends IrisMantleComponent {
|
||||
private final int radius = computeRadius();
|
||||
|
||||
public MantleObjectComponent(EngineMantle engineMantle) {
|
||||
super(engineMantle, MantleFlag.OBJECT, 1);
|
||||
super(engineMantle, ReservedFlag.OBJECT, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -157,7 +154,7 @@ public class MantleObjectComponent extends IrisMantleComponent {
|
||||
return v;
|
||||
}
|
||||
|
||||
private int computeRadius() {
|
||||
protected int computeRadius() {
|
||||
var dimension = getDimension();
|
||||
|
||||
AtomicInteger xg = new AtomicInteger();
|
||||
|
||||
@@ -27,6 +27,7 @@ import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.context.ChunkContext;
|
||||
import com.volmit.iris.util.data.B;
|
||||
import com.volmit.iris.util.documentation.ChunkCoordinates;
|
||||
import com.volmit.iris.util.function.Consumer4;
|
||||
import com.volmit.iris.util.hunk.Hunk;
|
||||
import com.volmit.iris.util.mantle.Mantle;
|
||||
@@ -53,10 +54,11 @@ public class IrisCarveModifier extends EngineAssignedModifier<BlockData> {
|
||||
}
|
||||
|
||||
@Override
|
||||
@ChunkCoordinates
|
||||
public void onModify(int x, int z, Hunk<BlockData> output, boolean multicore, ChunkContext context) {
|
||||
PrecisionStopwatch p = PrecisionStopwatch.start();
|
||||
Mantle mantle = getEngine().getMantle().getMantle();
|
||||
MantleChunk mc = getEngine().getMantle().getMantle().getChunk(x, z).use();
|
||||
MantleChunk mc = mantle.getChunk(x, z).use();
|
||||
KMap<Long, KList<Integer>> positions = new KMap<>();
|
||||
KMap<IrisPosition, MatterCavern> walls = new KMap<>();
|
||||
Consumer4<Integer, Integer, Integer, MatterCavern> iterator = (xx, yy, zz, c) -> {
|
||||
@@ -81,19 +83,19 @@ public class IrisCarveModifier extends EngineAssignedModifier<BlockData> {
|
||||
|
||||
//todo: Fix chunk decoration not working on chunk's border
|
||||
|
||||
if (rz < 15 && mantle.get(xx, yy, zz + 1, MatterCavern.class) == null) {
|
||||
if (rz < 15 && mc.get(xx, yy, zz + 1, MatterCavern.class) == null) {
|
||||
walls.put(new IrisPosition(rx, yy, rz + 1), c);
|
||||
}
|
||||
|
||||
if (rx < 15 && mantle.get(xx + 1, yy, zz, MatterCavern.class) == null) {
|
||||
if (rx < 15 && mc.get(xx + 1, yy, zz, MatterCavern.class) == null) {
|
||||
walls.put(new IrisPosition(rx + 1, yy, rz), c);
|
||||
}
|
||||
|
||||
if (rz > 0 && mantle.get(xx, yy, zz - 1, MatterCavern.class) == null) {
|
||||
if (rz > 0 && mc.get(xx, yy, zz - 1, MatterCavern.class) == null) {
|
||||
walls.put(new IrisPosition(rx, yy, rz - 1), c);
|
||||
}
|
||||
|
||||
if (rx > 0 && mantle.get(xx - 1, yy, zz, MatterCavern.class) == null) {
|
||||
if (rx > 0 && mc.get(xx - 1, yy, zz, MatterCavern.class) == null) {
|
||||
walls.put(new IrisPosition(rx - 1, yy, rz), c);
|
||||
}
|
||||
|
||||
@@ -217,16 +219,21 @@ public class IrisCarveModifier extends EngineAssignedModifier<BlockData> {
|
||||
if (!blocks.hasIndex(i)) {
|
||||
break;
|
||||
}
|
||||
int y = zone.floor - i - 1;
|
||||
|
||||
if (!B.isSolid(output.get(rx, zone.floor - i - 1, rz))) {
|
||||
BlockData b = blocks.get(i);
|
||||
BlockData down = output.get(rx, y, rz);
|
||||
|
||||
if (!B.isSolid(down)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (B.isOre(output.get(rx, zone.floor - i - 1, rz))) {
|
||||
if (B.isOre(down)) {
|
||||
output.set(rx, y, rz, B.toDeepSlateOre(down, b));
|
||||
continue;
|
||||
}
|
||||
|
||||
output.set(rx, zone.floor - i - 1, rz, blocks.get(i));
|
||||
output.set(rx, y, rz, blocks.get(i));
|
||||
}
|
||||
|
||||
blocks = biome.generateCeilingLayers(getDimension(), xx, zz, rng, 3, zone.ceiling, getData(), getComplex());
|
||||
|
||||
@@ -5,7 +5,7 @@ import com.volmit.iris.engine.framework.EngineAssignedModifier;
|
||||
import com.volmit.iris.util.context.ChunkContext;
|
||||
import com.volmit.iris.util.data.IrisCustomData;
|
||||
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.parallel.BurstExecutor;
|
||||
import com.volmit.iris.util.parallel.MultiBurst;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
|
||||
@@ -25,9 +25,12 @@ import com.volmit.iris.util.context.ChunkContext;
|
||||
import com.volmit.iris.util.data.B;
|
||||
import com.volmit.iris.util.data.HeightMap;
|
||||
import com.volmit.iris.util.hunk.Hunk;
|
||||
import com.volmit.iris.util.mantle.MantleChunk;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import com.volmit.iris.util.matter.MatterCavern;
|
||||
import com.volmit.iris.util.parallel.BurstExecutor;
|
||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.util.BlockVector;
|
||||
|
||||
@@ -53,28 +56,30 @@ public class IrisDepositModifier extends EngineAssignedModifier<BlockData> {
|
||||
|
||||
long seed = x * 341873128712L + z * 132897987541L;
|
||||
long mask = 0;
|
||||
MantleChunk chunk = getEngine().getMantle().getMantle().getChunk(x, z).use();
|
||||
for (IrisDepositGenerator k : getDimension().getDeposits()) {
|
||||
long finalSeed = seed * ++mask;
|
||||
burst.queue(() -> generate(k, terrain, rng.nextParallelRNG(finalSeed), x, z, false, context));
|
||||
burst.queue(() -> generate(k, chunk, terrain, rng.nextParallelRNG(finalSeed), x, z, false, context));
|
||||
}
|
||||
|
||||
for (IrisDepositGenerator k : region.getDeposits()) {
|
||||
long finalSeed = seed * ++mask;
|
||||
burst.queue(() -> generate(k, terrain, rng.nextParallelRNG(finalSeed), x, z, false, context));
|
||||
burst.queue(() -> generate(k, chunk, terrain, rng.nextParallelRNG(finalSeed), x, z, false, context));
|
||||
}
|
||||
|
||||
for (IrisDepositGenerator k : biome.getDeposits()) {
|
||||
long finalSeed = seed * ++mask;
|
||||
burst.queue(() -> generate(k, terrain, rng.nextParallelRNG(finalSeed), x, z, false, context));
|
||||
burst.queue(() -> generate(k, chunk, terrain, rng.nextParallelRNG(finalSeed), x, z, false, context));
|
||||
}
|
||||
burst.complete();
|
||||
chunk.release();
|
||||
}
|
||||
|
||||
public void generate(IrisDepositGenerator k, Hunk<BlockData> data, RNG rng, int cx, int cz, boolean safe, ChunkContext context) {
|
||||
generate(k, data, rng, cx, cz, safe, null, context);
|
||||
public void generate(IrisDepositGenerator k, MantleChunk chunk, Hunk<BlockData> data, RNG rng, int cx, int cz, boolean safe, ChunkContext context) {
|
||||
generate(k, chunk, data, rng, cx, cz, safe, null, context);
|
||||
}
|
||||
|
||||
public void generate(IrisDepositGenerator k, Hunk<BlockData> data, RNG rng, int cx, int cz, boolean safe, HeightMap he, ChunkContext context) {
|
||||
public void generate(IrisDepositGenerator k, MantleChunk chunk, Hunk<BlockData> data, RNG rng, int cx, int cz, boolean safe, HeightMap he, ChunkContext context) {
|
||||
if (k.getSpawnChance() < rng.d())
|
||||
return;
|
||||
|
||||
@@ -114,7 +119,7 @@ public class IrisDepositModifier extends EngineAssignedModifier<BlockData> {
|
||||
if (y > k.getMaxHeight() || y < k.getMinHeight() || y > height - 2)
|
||||
continue;
|
||||
|
||||
for (BlockVector j : clump.getBlocks().keySet()) {
|
||||
for (BlockVector j : clump.getBlocks().keys()) {
|
||||
int nx = j.getBlockX() + x;
|
||||
int ny = j.getBlockY() + y;
|
||||
int nz = j.getBlockZ() + z;
|
||||
@@ -122,8 +127,11 @@ public class IrisDepositModifier extends EngineAssignedModifier<BlockData> {
|
||||
if (ny > height || nx > 15 || nx < 0 || ny > getEngine().getHeight() || ny < 0 || nz < 0 || nz > 15) {
|
||||
continue;
|
||||
}
|
||||
if (!k.isReplaceBedrock() && data.get(nx, ny, nz).getMaterial() == Material.BEDROCK) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!getEngine().getMantle().isCarved((cx << 4) + nx, ny, (cz << 4) + nz)) {
|
||||
if (chunk.get(nx, ny, nz, MatterCavern.class) == null) {
|
||||
data.set(nx, ny, nz, B.toDeepSlateOre(data.get(nx, ny, nz), clump.getBlocks().get(j)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ package com.volmit.iris.engine.modifier;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.framework.EngineAssignedModifier;
|
||||
import com.volmit.iris.engine.object.IrisBiome;
|
||||
import com.volmit.iris.engine.object.IrisSlopeClip;
|
||||
import com.volmit.iris.util.context.ChunkContext;
|
||||
import com.volmit.iris.util.data.B;
|
||||
import com.volmit.iris.util.hunk.Hunk;
|
||||
@@ -174,7 +175,8 @@ public class IrisPostModifier extends EngineAssignedModifier<BlockData> {
|
||||
|| (hd == h + 1 && isSolidNonSlab(x, hd, z - 1, currentPostX, currentPostZ, currentData)))
|
||||
//@done
|
||||
{
|
||||
BlockData d = biome.getSlab().get(rng, x, h, z, getData());
|
||||
IrisSlopeClip sc = biome.getSlab().getSlopeCondition();
|
||||
BlockData d = sc.isValid(getComplex().getSlopeStream().get(x, z)) ? biome.getSlab().get(rng, x, h, z, getData()) : null;
|
||||
|
||||
if (d != null) {
|
||||
boolean cancel = B.isAir(d);
|
||||
|
||||
@@ -20,8 +20,8 @@ package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.core.loader.IrisData;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import org.bukkit.block.TileState;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface IObjectPlacer {
|
||||
int getHighest(int x, int z, IrisData data);
|
||||
@@ -46,5 +46,9 @@ public interface IObjectPlacer {
|
||||
|
||||
void setTile(int xx, int yy, int zz, TileData tile);
|
||||
|
||||
<T> void setData(int xx, int yy, int zz, T data);
|
||||
|
||||
<T> @Nullable T getData(int xx, int yy, int zz, Class<T> t);
|
||||
|
||||
Engine getEngine();
|
||||
}
|
||||
|
||||
@@ -25,9 +25,9 @@ import com.volmit.iris.util.stream.interpolation.Interpolated;
|
||||
import java.util.List;
|
||||
|
||||
public interface IRare {
|
||||
static <T extends IRare> ProceduralStream<T> stream(ProceduralStream<Double> noise, List<T> possibilities) {
|
||||
return ProceduralStream.of((x, z) -> pick(possibilities, noise.get(x, z)),
|
||||
(x, y, z) -> pick(possibilities, noise.get(x, y, z)),
|
||||
static <T extends IRare> ProceduralStream<T> stream(ProceduralStream<Double> noise, List<T> possibilities, boolean legacyRarity) {
|
||||
return ProceduralStream.of(legacyRarity ? (x, z) -> pickLegacy(possibilities, noise.get(x, z)) : (x, z) -> pick(possibilities, noise.get(x, z)),
|
||||
legacyRarity ? (x, y, z) -> pickLegacy(possibilities, noise.get(x, y, z)) : (x, y, z) -> pick(possibilities, noise.get(x, y, z)),
|
||||
new Interpolated<T>() {
|
||||
@Override
|
||||
public double toDouble(T t) {
|
||||
@@ -69,6 +69,32 @@ public interface IRare {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (possibilities.size() == 1) {
|
||||
return possibilities.getFirst();
|
||||
}
|
||||
|
||||
double total = 0;
|
||||
for (T i : possibilities) {
|
||||
total += 1d / i.getRarity();
|
||||
}
|
||||
|
||||
double threshold = total * noiseValue;
|
||||
double buffer = 0;
|
||||
for (T i : possibilities) {
|
||||
buffer += 1d / i.getRarity();
|
||||
if (buffer >= threshold) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return possibilities.getLast();
|
||||
}
|
||||
|
||||
static <T extends IRare> T pickLegacy(List<T> possibilities, double noiseValue) {
|
||||
if (possibilities.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (possibilities.size() == 1) {
|
||||
return possibilities.get(0);
|
||||
}
|
||||
|
||||
@@ -143,14 +143,14 @@ public class IrisBiome extends IrisRegistrant implements IRare {
|
||||
@Desc("The default wall if iris decides to place a wall higher than 2 blocks (steep hills or possibly cliffs)")
|
||||
private IrisBiomePaletteLayer wall = new IrisBiomePaletteLayer().zero();
|
||||
@Required
|
||||
@ArrayType(min = 1, type = IrisBiomePaletteLayer.class)
|
||||
@ArrayType(type = IrisBiomePaletteLayer.class)
|
||||
@Desc("This defines the layers of materials in this biome. Each layer has a palette and min/max height and some other properties. Usually a grassy/sandy layer then a dirt layer then a stone layer. Iris will fill in the remaining blocks below your layers with stone.")
|
||||
private KList<IrisBiomePaletteLayer> layers = new KList<IrisBiomePaletteLayer>().qadd(new IrisBiomePaletteLayer());
|
||||
@Required
|
||||
@ArrayType(min = 1, type = IrisBiomePaletteLayer.class)
|
||||
@ArrayType(type = IrisBiomePaletteLayer.class)
|
||||
@Desc("This defines the layers of materials in this biome. Each layer has a palette and min/max height and some other properties. Usually a grassy/sandy layer then a dirt layer then a stone layer. Iris will fill in the remaining blocks below your layers with stone.")
|
||||
private KList<IrisBiomePaletteLayer> caveCeilingLayers = new KList<IrisBiomePaletteLayer>().qadd(new IrisBiomePaletteLayer());
|
||||
@ArrayType(min = 1, type = IrisBiomePaletteLayer.class)
|
||||
@ArrayType(type = IrisBiomePaletteLayer.class)
|
||||
@Desc("This defines the layers of materials in this biome. Each layer has a palette and min/max height and some other properties. Usually a grassy/sandy layer then a dirt layer then a stone layer. Iris will fill in the remaining blocks below your layers with stone.")
|
||||
private KList<IrisBiomePaletteLayer> seaLayers = new KList<>();
|
||||
@ArrayType(min = 1, type = IrisDecorator.class)
|
||||
|
||||
@@ -61,6 +61,7 @@ public class IrisBlockData extends IrisRegistrant {
|
||||
private int weight = 1;
|
||||
@Desc("If the block cannot be created on this version, Iris will attempt to use this backup block data instead.")
|
||||
private IrisBlockData backup = null;
|
||||
@RegistryMapBlockState("block")
|
||||
@Desc("Optional properties for this block data such as 'waterlogged': true")
|
||||
private KMap<String, Object> data = new KMap<>();
|
||||
@Desc("Optional tile data for this block data")
|
||||
|
||||
@@ -62,31 +62,31 @@ public class IrisCarving {
|
||||
|
||||
@BlockCoordinates
|
||||
public void doCarving(MantleWriter writer, RNG rng, Engine engine, int x, int y, int z, int depth) {
|
||||
doCarving(writer, rng, engine, x, y, z, depth, -1);
|
||||
doCarving(writer, rng, new RNG(engine.getSeedManager().getCarve()), engine, x, y, z, depth, -1);
|
||||
}
|
||||
|
||||
@BlockCoordinates
|
||||
public void doCarving(MantleWriter writer, RNG rng, Engine engine, int x, int y, int z, int recursion, int waterHint) {
|
||||
public void doCarving(MantleWriter writer, RNG rng, RNG base, Engine engine, int x, int y, int z, int recursion, int waterHint) {
|
||||
int nextRecursion = recursion + 1;
|
||||
|
||||
if (caves.isNotEmpty()) {
|
||||
for (IrisCavePlacer i : caves) {
|
||||
if (recursion > i.getMaxRecursion()) continue;
|
||||
i.generateCave(writer, rng, engine, x, y, z, nextRecursion, waterHint);
|
||||
i.generateCave(writer, rng, base, engine, x, y, z, nextRecursion, waterHint);
|
||||
}
|
||||
}
|
||||
|
||||
if (ravines.isNotEmpty()) {
|
||||
for (IrisRavinePlacer i : ravines) {
|
||||
if (recursion > i.getMaxRecursion()) continue;
|
||||
i.generateRavine(writer, rng, engine, x, y, z, nextRecursion, waterHint);
|
||||
i.generateRavine(writer, rng, base, engine, x, y, z, nextRecursion, waterHint);
|
||||
}
|
||||
}
|
||||
|
||||
if (spheres.isNotEmpty()) {
|
||||
for (IrisSphere i : spheres) {
|
||||
if (rng.nextInt(i.getRarity()) == 0) {
|
||||
i.generate(rng, engine, writer, x, y, z);
|
||||
i.generate(base, engine, writer, x, y, z);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -94,7 +94,7 @@ public class IrisCarving {
|
||||
if (elipsoids.isNotEmpty()) {
|
||||
for (IrisElipsoid i : elipsoids) {
|
||||
if (rng.nextInt(i.getRarity()) == 0) {
|
||||
i.generate(rng, engine, writer, x, y, z);
|
||||
i.generate(base, engine, writer, x, y, z);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -102,7 +102,7 @@ public class IrisCarving {
|
||||
if (pyramids.isNotEmpty()) {
|
||||
for (IrisPyramid i : pyramids) {
|
||||
if (rng.nextInt(i.getRarity()) == 0) {
|
||||
i.generate(rng, engine, writer, x, y, z);
|
||||
i.generate(base, engine, writer, x, y, z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,9 +25,11 @@ import com.volmit.iris.engine.mantle.MantleWriter;
|
||||
import com.volmit.iris.engine.object.annotations.Desc;
|
||||
import com.volmit.iris.engine.object.annotations.RegistryListResource;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KSet;
|
||||
import com.volmit.iris.util.json.JSONObject;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import com.volmit.iris.util.matter.MatterCavern;
|
||||
import com.volmit.iris.util.noise.CNG;
|
||||
import com.volmit.iris.util.plugin.VolmitSender;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
@@ -55,6 +57,9 @@ public class IrisCave extends IrisRegistrant {
|
||||
@Desc("Limit the worm from ever getting higher or lower than this range")
|
||||
private IrisRange verticalRange = new IrisRange(3, 255);
|
||||
|
||||
@Desc("Shape of the caves")
|
||||
private IrisCaveShape shape = new IrisCaveShape();
|
||||
|
||||
@Override
|
||||
public String getFolderName() {
|
||||
return "caves";
|
||||
@@ -66,12 +71,12 @@ public class IrisCave extends IrisRegistrant {
|
||||
}
|
||||
|
||||
public void generate(MantleWriter writer, RNG rng, Engine engine, int x, int y, int z) {
|
||||
generate(writer, rng, engine, x, y, z, 0, -1, true);
|
||||
generate(writer, rng, new RNG(engine.getSeedManager().getCarve()), engine, x, y, z, 0, -1, true);
|
||||
}
|
||||
|
||||
public void generate(MantleWriter writer, RNG rng, Engine engine, int x, int y, int z, int recursion, int waterHint, boolean breakSurface) {
|
||||
double girth = getWorm().getGirth().get(rng, x, z, engine.getData());
|
||||
KList<IrisPosition> points = getWorm().generate(rng, engine.getData(), writer, verticalRange, x, y, z, breakSurface, girth + 9);
|
||||
public void generate(MantleWriter writer, RNG rng, RNG base, Engine engine, int x, int y, int z, int recursion, int waterHint, boolean breakSurface) {
|
||||
double girth = getWorm().getGirth().get(base.nextParallelRNG(465156), x, z, engine.getData());
|
||||
KList<IrisPosition> points = getWorm().generate(base.nextParallelRNG(784684), engine.getData(), writer, verticalRange, x, y, z, breakSurface, girth + 9);
|
||||
int highestWater = Math.max(waterHint, -1);
|
||||
|
||||
if (highestWater == -1) {
|
||||
@@ -87,17 +92,19 @@ public class IrisCave extends IrisRegistrant {
|
||||
}
|
||||
|
||||
|
||||
int h = Math.min(Math.max(highestWater, waterHint), engine.getDimension().getFluidHeight());
|
||||
int h = Math.min(highestWater, engine.getDimension().getFluidHeight());
|
||||
|
||||
for (IrisPosition i : points) {
|
||||
fork.doCarving(writer, rng, engine, i.getX(), i.getY(), i.getZ(), recursion, h);
|
||||
fork.doCarving(writer, rng, base, engine, i.getX(), i.getY(), i.getZ(), recursion, h);
|
||||
}
|
||||
|
||||
MatterCavern c = new MatterCavern(true, customBiome, (byte) 0);
|
||||
MatterCavern w = new MatterCavern(true, customBiome, (byte) 1);
|
||||
|
||||
writer.setLineConsumer(points,
|
||||
girth, true,
|
||||
CNG cng = shape.getNoise(base.nextParallelRNG(8131545), engine);
|
||||
KSet<IrisPosition> mask = shape.getMasked(rng, engine);
|
||||
writer.setNoiseMasked(points,
|
||||
girth, shape.getNoiseThreshold() < 0 ? cng.noise(x, y, z) : shape.getNoiseThreshold(), cng, mask, true,
|
||||
(xf, yf, zf) -> yf <= h ? w : c);
|
||||
}
|
||||
|
||||
@@ -107,6 +114,6 @@ public class IrisCave extends IrisRegistrant {
|
||||
}
|
||||
|
||||
public int getMaxSize(IrisData data, int depth) {
|
||||
return getWorm().getMaxDistance() + fork.getMaxRange(data, depth);
|
||||
return (int) (Math.ceil(getWorm().getGirth().getMax() * 2) + getWorm().getMaxDistance() + fork.getMaxRange(data, depth));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,10 +64,10 @@ public class IrisCavePlacer implements IRare {
|
||||
}
|
||||
|
||||
public void generateCave(MantleWriter mantle, RNG rng, Engine engine, int x, int y, int z) {
|
||||
generateCave(mantle, rng, engine, x, y, z, 0, -1);
|
||||
generateCave(mantle, rng, new RNG(engine.getSeedManager().getCarve()), engine, x, y, z, 0, -1);
|
||||
}
|
||||
|
||||
public void generateCave(MantleWriter mantle, RNG rng, Engine engine, int x, int y, int z, int recursion, int waterHint) {
|
||||
public void generateCave(MantleWriter mantle, RNG rng, RNG base, Engine engine, int x, int y, int z, int recursion, int waterHint) {
|
||||
if (fail.get()) {
|
||||
return;
|
||||
}
|
||||
@@ -86,13 +86,13 @@ public class IrisCavePlacer implements IRare {
|
||||
}
|
||||
|
||||
if (y == -1) {
|
||||
int h = (int) caveStartHeight.get(rng, x, z, data);
|
||||
int h = (int) caveStartHeight.get(base, x, z, data);
|
||||
int ma = breakSurface ? h : (int) (engine.getComplex().getHeightStream().get(x, z) - 9);
|
||||
y = Math.min(h, ma);
|
||||
}
|
||||
|
||||
try {
|
||||
cave.generate(mantle, rng, engine, x + rng.nextInt(15), y, z + rng.nextInt(15), recursion, waterHint, breakSurface);
|
||||
cave.generate(mantle, rng, base, engine, x + rng.nextInt(15), y, z + rng.nextInt(15), recursion, waterHint, breakSurface);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
fail.set(true);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user