mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-02-16 18:40:41 +00:00
Compare commits
1 Commits
unificatio
...
feat/craft
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a7eb3bed13 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -10,4 +10,4 @@ libs/
|
||||
|
||||
collection/
|
||||
|
||||
/core/src/main/java/art/arcane/iris/util/uniques/
|
||||
/core/src/main/java/com/volmit/iris/util/uniques/
|
||||
|
||||
@@ -45,7 +45,7 @@ Consider supporting our development by buying Iris on spigot! We work hard to ma
|
||||
Everyone needs a tool-belt.
|
||||
|
||||
```java
|
||||
package art.arcane.iris.core.tools;
|
||||
package com.volmit.iris.core.tools;
|
||||
|
||||
// Get IrisDataManager from a world
|
||||
IrisToolbelt.access(anyWorld).getCompound().getData();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import com.volmit.nmstools.NMSToolsExtension
|
||||
import com.volmit.nmstools.NMSToolsPlugin
|
||||
import de.undercouch.gradle.tasks.download.Download
|
||||
import org.gradle.jvm.toolchain.JavaLanguageVersion
|
||||
import xyz.jpenilla.runpaper.task.RunServer
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
@@ -23,18 +24,19 @@ import kotlin.system.exitProcess
|
||||
|
||||
buildscript {
|
||||
repositories.maven("https://jitpack.io")
|
||||
dependencies.classpath("com.github.VolmitSoftware:NMSTools:c88961416f")
|
||||
dependencies.classpath("com.github.VolmitSoftware:NMSTools:c5cbc46ce6")
|
||||
}
|
||||
|
||||
plugins {
|
||||
java
|
||||
`java-library`
|
||||
alias(libs.plugins.shadow)
|
||||
alias(libs.plugins.download)
|
||||
alias(libs.plugins.runPaper)
|
||||
}
|
||||
|
||||
group = "art.arcane"
|
||||
version = "4.0.0-1.20.1-1.21.11-Dev1"
|
||||
group = "com.volmit"
|
||||
version = "3.7.2-1.20.1-1.21.8"
|
||||
|
||||
apply<ApiGenerator>()
|
||||
|
||||
@@ -51,40 +53,41 @@ registerCustomOutputTask("PixelFury", "C://Users/repix/workplace/Iris/1.21.3 - D
|
||||
registerCustomOutputTask("PixelFuryDev", "C://Users/repix/workplace/Iris/1.21 - Development-v3/plugins")
|
||||
// ========================== UNIX ==============================
|
||||
registerCustomOutputTaskUnix("CyberpwnLT", "/Users/danielmills/development/server/plugins")
|
||||
registerCustomOutputTaskUnix("PsychoLT", "/Users/brianfopiano/Developer/RemoteGit/[Minecraft Server]/plugin-jars")
|
||||
registerCustomOutputTaskUnix("PsychoLT", "/Users/brianfopiano/Developer/RemoteGit/Server/plugins")
|
||||
registerCustomOutputTaskUnix("PixelMac", "/Users/test/Desktop/mcserver/plugins")
|
||||
registerCustomOutputTaskUnix("CrazyDev22LT", "/home/julian/Desktop/server/plugins")
|
||||
// ==============================================================
|
||||
|
||||
val serverMinHeap = "10G"
|
||||
val serverMaxHeap = "10G"
|
||||
val additionalFlags = "-XX:+AlwaysPreTouch"
|
||||
val serverMinHeap = "2G"
|
||||
val serverMaxHeap = "8G"
|
||||
//Valid values are: none, truecolor, indexed256, indexed16, indexed8
|
||||
val color = "truecolor"
|
||||
val errorReporting = "true" == findProperty("errorReporting")
|
||||
val errorReporting = findProperty("errorReporting") as Boolean? ?: false
|
||||
|
||||
val nmsBindings = mapOf(
|
||||
"v1_21_R7" to "1.21.11-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",
|
||||
"v1_21_R1" to "1.21.1-R0.1-SNAPSHOT",
|
||||
"v1_20_R4" to "1.20.6-R0.1-SNAPSHOT",
|
||||
"v1_20_R3" to "1.20.4-R0.1-SNAPSHOT",
|
||||
"v1_20_R2" to "1.20.2-R0.1-SNAPSHOT",
|
||||
"v1_20_R1" to "1.20.1-R0.1-SNAPSHOT",
|
||||
"v1_21_R5" to "1.21.7-R0.1-SNAPSHOT",
|
||||
"v1_21_R4" to "1.21.5-R0.1-SNAPSHOT",
|
||||
"v1_21_R3" to "1.21.4-R0.1-SNAPSHOT",
|
||||
"v1_21_R2" to "1.21.3-R0.1-SNAPSHOT",
|
||||
"v1_21_R1" to "1.21.1-R0.1-SNAPSHOT",
|
||||
"v1_20_R4" to "1.20.6-R0.1-SNAPSHOT",
|
||||
"v1_20_R3" to "1.20.4-R0.1-SNAPSHOT",
|
||||
"v1_20_R2" to "1.20.2-R0.1-SNAPSHOT",
|
||||
"v1_20_R1" to "1.20.1-R0.1-SNAPSHOT",
|
||||
)
|
||||
val jvmVersion = mapOf<String, Int>()
|
||||
nmsBindings.forEach { (key, value) ->
|
||||
nmsBindings.forEach { key, value ->
|
||||
project(":nms:$key") {
|
||||
apply<JavaPlugin>()
|
||||
apply<NMSToolsPlugin>()
|
||||
|
||||
nmsBinding {
|
||||
repositories {
|
||||
maven("https://libraries.minecraft.net")
|
||||
}
|
||||
|
||||
extensions.configure(NMSToolsExtension::class) {
|
||||
jvm = jvmVersion.getOrDefault(key, 21)
|
||||
version = value
|
||||
type = NMSBinding.Type.DIRECT
|
||||
}
|
||||
|
||||
dependencies {
|
||||
@@ -107,25 +110,17 @@ nmsBindings.forEach { (key, value) ->
|
||||
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
|
||||
from(jarJar, provider { included.resolve().map(::zipTree) })
|
||||
nmsBindings.forEach { key, _ ->
|
||||
from(project(":nms:$key").tasks.named("remap").map { zipTree(it.outputs.files.singleFile) })
|
||||
}
|
||||
from(project(":core").tasks.shadowJar.flatMap { it.archiveFile }.map { zipTree(it) })
|
||||
from(project(":core:agent").tasks.jar.flatMap { it.archiveFile })
|
||||
archiveFileName.set("Iris-${project.version}.jar")
|
||||
}
|
||||
|
||||
@@ -188,12 +183,6 @@ configurations.configureEach {
|
||||
allprojects {
|
||||
apply<JavaPlugin>()
|
||||
|
||||
java {
|
||||
toolchain {
|
||||
languageVersion.set(JavaLanguageVersion.of(21))
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven("https://repo.papermc.io/repository/maven-public/")
|
||||
@@ -206,6 +195,7 @@ allprojects {
|
||||
maven("https://mvn.lumine.io/repository/maven-public/") // mythic
|
||||
maven("https://nexus.phoenixdevt.fr/repository/maven-public/") //MMOItems
|
||||
maven("https://repo.onarandombox.com/content/groups/public/") //Multiverse Core
|
||||
maven("https://repo.momirealms.net/releases/") //CraftEngine
|
||||
}
|
||||
|
||||
dependencies {
|
||||
@@ -241,14 +231,14 @@ allprojects {
|
||||
}
|
||||
}
|
||||
|
||||
if (!JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_21)) {
|
||||
if (JavaVersion.current().toString() != "21") {
|
||||
System.err.println()
|
||||
System.err.println("=========================================================================================================")
|
||||
System.err.println("You must run gradle on Java 21 or newer. You are using " + JavaVersion.current())
|
||||
System.err.println("You must run gradle on Java 21. You are using " + JavaVersion.current())
|
||||
System.err.println()
|
||||
System.err.println("=== For IDEs ===")
|
||||
System.err.println("1. Configure the project for Java 21 toolchain")
|
||||
System.err.println("2. Configure the bundled gradle to use Java 21+ in settings")
|
||||
System.err.println("1. Configure the project for Java 21")
|
||||
System.err.println("2. Configure the bundled gradle to use Java 21 in settings")
|
||||
System.err.println()
|
||||
System.err.println("=== For Command Line (gradlew) ===")
|
||||
System.err.println("1. Install JDK 21 from https://www.oracle.com/java/technologies/javase/jdk21-archive-downloads.html")
|
||||
|
||||
@@ -1,32 +1,11 @@
|
||||
import org.gradle.jvm.toolchain.JavaLanguageVersion
|
||||
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
||||
|
||||
plugins {
|
||||
kotlin("jvm") version embeddedKotlinVersion
|
||||
}
|
||||
|
||||
java {
|
||||
toolchain {
|
||||
languageVersion.set(JavaLanguageVersion.of(21))
|
||||
}
|
||||
}
|
||||
|
||||
kotlin {
|
||||
jvmToolchain(21)
|
||||
compilerOptions {
|
||||
jvmTarget.set(JvmTarget.JVM_21)
|
||||
}
|
||||
kotlin("jvm") version "2.0.20"
|
||||
}
|
||||
|
||||
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")
|
||||
}
|
||||
}
|
||||
@@ -1,182 +0,0 @@
|
||||
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)
|
||||
@@ -4,8 +4,8 @@ plugins {
|
||||
|
||||
tasks.jar {
|
||||
manifest.attributes(
|
||||
"Agent-Class" to "art.arcane.iris.util.agent.Installer",
|
||||
"Premain-Class" to "art.arcane.iris.util.agent.Installer",
|
||||
"Agent-Class" to "com.volmit.iris.util.agent.Installer",
|
||||
"Premain-Class" to "com.volmit.iris.util.agent.Installer",
|
||||
"Can-Redefine-Classes" to true,
|
||||
"Can-Retransform-Classes" to true
|
||||
)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package art.arcane.iris.util.agent;
|
||||
package com.volmit.iris.util.agent;
|
||||
|
||||
import java.lang.instrument.Instrumentation;
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
import io.github.slimjar.func.slimjarHelper
|
||||
import io.github.slimjar.resolver.data.Mirror
|
||||
import org.ajoberstar.grgit.Grgit
|
||||
import org.gradle.jvm.toolchain.JavaLanguageVersion
|
||||
import org.gradle.jvm.tasks.Jar
|
||||
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
||||
import java.net.URI
|
||||
|
||||
/*
|
||||
@@ -36,8 +33,8 @@ plugins {
|
||||
}
|
||||
|
||||
val apiVersion = "1.19"
|
||||
val main = "art.arcane.iris.Iris"
|
||||
val lib = "art.arcane.iris.util"
|
||||
val main = "com.volmit.iris.Iris"
|
||||
val lib = "com.volmit.iris.util"
|
||||
|
||||
/**
|
||||
* Dependencies.
|
||||
@@ -70,6 +67,9 @@ dependencies {
|
||||
isTransitive = false
|
||||
}
|
||||
compileOnly(libs.multiverseCore)
|
||||
compileOnly(libs.craftengine.core)
|
||||
compileOnly(libs.craftengine.bukkit)
|
||||
//compileOnly(libs.sparrowNbt)
|
||||
|
||||
// Shaded
|
||||
implementation(slimjarHelper("spigot"))
|
||||
@@ -115,20 +115,10 @@ dependencies {
|
||||
|
||||
java {
|
||||
disableAutoTargetJvm()
|
||||
toolchain {
|
||||
languageVersion.set(JavaLanguageVersion.of(21))
|
||||
}
|
||||
}
|
||||
|
||||
kotlin {
|
||||
jvmToolchain(21)
|
||||
compilerOptions {
|
||||
jvmTarget.set(JvmTarget.JVM_21)
|
||||
}
|
||||
}
|
||||
|
||||
sentry {
|
||||
url = "http://sentry.volmit.com:8080"
|
||||
url = "http://sentry.volmit.com:8080/"
|
||||
autoInstallation.enabled = false
|
||||
includeSourceContext = true
|
||||
|
||||
@@ -155,11 +145,8 @@ slimJar {
|
||||
relocate("com.google.inject", "$lib.guice")
|
||||
relocate("org.dom4j", "$lib.dom4j")
|
||||
relocate("org.jaxen", "$lib.jaxen")
|
||||
relocate("com.github.benmanes.caffeine", "$lib.caffeine")
|
||||
}
|
||||
|
||||
val embeddedAgentJar = project(":core:agent").tasks.named<Jar>("jar")
|
||||
|
||||
tasks {
|
||||
/**
|
||||
* We need parameter meta for the decree command system
|
||||
@@ -178,6 +165,15 @@ tasks {
|
||||
"version" to rootProject.version,
|
||||
"apiVersion" to apiVersion,
|
||||
"main" to main,
|
||||
"environment" to if (project.hasProperty("release")) "production" else "development",
|
||||
"commit" to provider {
|
||||
val res = runCatching { project.extensions.getByType<Grgit>().head().id }
|
||||
res.getOrDefault("")
|
||||
.takeIf { it.length == 40 } ?: {
|
||||
logger.error("Git commit hash not found", res.exceptionOrNull())
|
||||
"unknown"
|
||||
}()
|
||||
},
|
||||
)
|
||||
filesMatching("**/plugin.yml") {
|
||||
expand(inputs.properties)
|
||||
@@ -185,59 +181,16 @@ tasks {
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
dependsOn(embeddedAgentJar)
|
||||
mergeServiceFiles()
|
||||
//minimize()
|
||||
relocate("io.github.slimjar", "$lib.slimjar")
|
||||
exclude("modules/loader-agent.isolated-jar")
|
||||
from(embeddedAgentJar.map { it.archiveFile }) {
|
||||
rename { "agent.jar" }
|
||||
}
|
||||
}
|
||||
|
||||
sentryCollectSourcesJava {
|
||||
dependsOn(generateTemplates)
|
||||
}
|
||||
}
|
||||
|
||||
val templateSource = file("src/main/templates")
|
||||
val templateDest = layout.buildDirectory.dir("generated/sources/templates")!!
|
||||
val generateTemplates = tasks.register<Copy>("generateTemplates") {
|
||||
inputs.properties(
|
||||
"environment" to when {
|
||||
project.hasProperty("release") -> "production"
|
||||
project.hasProperty("argghh") -> "Argghh!"
|
||||
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 { "art/arcane/iris/$it" }
|
||||
expand(inputs.properties)
|
||||
}
|
||||
|
||||
tasks.generateSentryBundleIdJava {
|
||||
dependsOn(generateTemplates)
|
||||
}
|
||||
|
||||
rootProject.tasks.named("prepareKotlinBuildScriptModel") {
|
||||
dependsOn(generateTemplates)
|
||||
}
|
||||
|
||||
sourceSets.main {
|
||||
java.srcDir("../../VolmLib/shared/src/main/java")
|
||||
java.srcDir(generateTemplates.map { it.outputs })
|
||||
}
|
||||
|
||||
kotlin.sourceSets.named("main") {
|
||||
kotlin.srcDir("../../VolmLib/shared/src/main/kotlin")
|
||||
}
|
||||
/**
|
||||
* 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()
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
package art.arcane.iris.core.nms.datapack;
|
||||
|
||||
import art.arcane.iris.Iris;
|
||||
import art.arcane.iris.core.nms.INMS;
|
||||
import art.arcane.iris.core.nms.datapack.v1192.DataFixerV1192;
|
||||
import art.arcane.iris.core.nms.datapack.v1206.DataFixerV1206;
|
||||
import art.arcane.iris.core.nms.datapack.v1213.DataFixerV1213;
|
||||
import art.arcane.iris.core.nms.datapack.v1217.DataFixerV1217;
|
||||
import art.arcane.volmlib.util.collection.KMap;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
//https://minecraft.wiki/w/Pack_format
|
||||
@Getter
|
||||
public enum DataVersion {
|
||||
UNSUPPORTED("0.0.0", 0, () -> null),
|
||||
V1_19_2("1.19.2", 10, DataFixerV1192::new),
|
||||
V1_20_5("1.20.6", 41, DataFixerV1206::new),
|
||||
V1_21_3("1.21.3", 57, DataFixerV1213::new),
|
||||
V1_21_11("1.21.11", 75, DataFixerV1217::new);
|
||||
private static final KMap<DataVersion, IDataFixer> cache = new KMap<>();
|
||||
@Getter(AccessLevel.NONE)
|
||||
private final Supplier<IDataFixer> constructor;
|
||||
private final String version;
|
||||
private final int packFormat;
|
||||
|
||||
DataVersion(String version, int packFormat, Supplier<IDataFixer> constructor) {
|
||||
this.constructor = constructor;
|
||||
this.packFormat = packFormat;
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public IDataFixer get() {
|
||||
return cache.computeIfAbsent(this, k -> constructor.get());
|
||||
}
|
||||
|
||||
public static IDataFixer getDefault() {
|
||||
DataVersion version = INMS.get().getDataVersion();
|
||||
if (version == null || version == UNSUPPORTED) {
|
||||
DataVersion fallback = getLatest();
|
||||
Iris.warn("Unsupported datapack version mapping detected, falling back to latest fixer: " + fallback.getVersion());
|
||||
return fallback.get();
|
||||
}
|
||||
|
||||
IDataFixer fixer = version.get();
|
||||
if (fixer == null) {
|
||||
DataVersion fallback = getLatest();
|
||||
Iris.warn("Null datapack fixer for " + version.getVersion() + ", falling back to latest fixer: " + fallback.getVersion());
|
||||
return fallback.get();
|
||||
}
|
||||
|
||||
return fixer;
|
||||
}
|
||||
|
||||
public static DataVersion getLatest() {
|
||||
return values()[values().length - 1];
|
||||
}
|
||||
}
|
||||
@@ -1,170 +0,0 @@
|
||||
package art.arcane.iris.core.nms.datapack.v1217;
|
||||
|
||||
import art.arcane.iris.core.nms.datapack.v1213.DataFixerV1213;
|
||||
import art.arcane.iris.engine.object.IrisBiomeCustom;
|
||||
import art.arcane.volmlib.util.json.JSONArray;
|
||||
import art.arcane.volmlib.util.json.JSONObject;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class DataFixerV1217 extends DataFixerV1213 {
|
||||
private static final Map<Dimension, String> DIMENSIONS = Map.of(
|
||||
Dimension.OVERWORLD, """
|
||||
{
|
||||
"ambient_light": 0.0,
|
||||
"attributes": {
|
||||
"minecraft:audio/ambient_sounds": {
|
||||
"mood": {
|
||||
"block_search_extent": 8,
|
||||
"offset": 2.0,
|
||||
"sound": "minecraft:ambient.cave",
|
||||
"tick_delay": 6000
|
||||
}
|
||||
},
|
||||
"minecraft:audio/background_music": {
|
||||
"creative": {
|
||||
"max_delay": 24000,
|
||||
"min_delay": 12000,
|
||||
"sound": "minecraft:music.creative"
|
||||
},
|
||||
"default": {
|
||||
"max_delay": 24000,
|
||||
"min_delay": 12000,
|
||||
"sound": "minecraft:music.game"
|
||||
}
|
||||
},
|
||||
"minecraft:visual/cloud_color": "#ccffffff",
|
||||
"minecraft:visual/fog_color": "#c0d8ff",
|
||||
"minecraft:visual/sky_color": "#78a7ff"
|
||||
},
|
||||
"timelines": "#minecraft:in_overworld"
|
||||
}""",
|
||||
Dimension.NETHER, """
|
||||
{
|
||||
"ambient_light": 0.1,
|
||||
"attributes": {
|
||||
"minecraft:gameplay/sky_light_level": 4.0,
|
||||
"minecraft:gameplay/snow_golem_melts": true,
|
||||
"minecraft:visual/fog_end_distance": 96.0,
|
||||
"minecraft:visual/fog_start_distance": 10.0,
|
||||
"minecraft:visual/sky_light_color": "#7a7aff",
|
||||
"minecraft:visual/sky_light_factor": 0.0
|
||||
},
|
||||
"cardinal_light": "nether",
|
||||
"skybox": "none",
|
||||
"timelines": "#minecraft:in_nether"
|
||||
}""",
|
||||
Dimension.END, """
|
||||
{
|
||||
"ambient_light": 0.25,
|
||||
"attributes": {
|
||||
"minecraft:audio/ambient_sounds": {
|
||||
"mood": {
|
||||
"block_search_extent": 8,
|
||||
"offset": 2.0,
|
||||
"sound": "minecraft:ambient.cave",
|
||||
"tick_delay": 6000
|
||||
}
|
||||
},
|
||||
"minecraft:audio/background_music": {
|
||||
"default": {
|
||||
"max_delay": 24000,
|
||||
"min_delay": 6000,
|
||||
"replace_current_music": true,
|
||||
"sound": "minecraft:music.end"
|
||||
}
|
||||
},
|
||||
"minecraft:visual/fog_color": "#181318",
|
||||
"minecraft:visual/sky_color": "#000000",
|
||||
"minecraft:visual/sky_light_color": "#e580ff",
|
||||
"minecraft:visual/sky_light_factor": 0.0
|
||||
},
|
||||
"skybox": "end",
|
||||
"timelines": "#minecraft:in_end"
|
||||
}"""
|
||||
);
|
||||
|
||||
@Override
|
||||
public JSONObject fixCustomBiome(IrisBiomeCustom biome, JSONObject json) {
|
||||
json = super.fixCustomBiome(biome, json);
|
||||
var effects = json.getJSONObject("effects");
|
||||
var attributes = new JSONObject();
|
||||
|
||||
attributes.put("minecraft:visual/fog_color", effects.remove("fog_color"));
|
||||
attributes.put("minecraft:visual/sky_color", effects.remove("sky_color"));
|
||||
attributes.put("minecraft:visual/water_fog_color", effects.remove("water_fog_color"));
|
||||
|
||||
JSONObject particle = (JSONObject) effects.remove("particle");
|
||||
if (particle != null) {
|
||||
attributes.put("minecraft:visual/ambient_particles", new JSONArray()
|
||||
.put(particle.getJSONObject("options")
|
||||
.put("probability", particle.get("probability"))));
|
||||
}
|
||||
json.put("attributes", attributes);
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fixDimension(Dimension dimension, JSONObject json) {
|
||||
super.fixDimension(dimension, json);
|
||||
|
||||
var attributes = new JSONObject();
|
||||
if ((Boolean) json.remove("ultrawarm")) {
|
||||
attributes.put("minecraft:gameplay/water_evaporates", true);
|
||||
attributes.put("minecraft:gameplay/fast_lava", true);
|
||||
attributes.put("minecraft:gameplay/snow_golem_melts", true);
|
||||
attributes.put("minecraft:visual/default_dripstone_particle", new JSONObject()
|
||||
.put("value", "minecraft:dripstone_drip_water_lava"));
|
||||
}
|
||||
|
||||
if ((Boolean) json.remove("bed_works")) {
|
||||
attributes.put("minecraft:gameplay/bed_rule", new JSONObject()
|
||||
.put("can_set_spawn", "always")
|
||||
.put("can_sleep", "when_dark")
|
||||
.put("error_message", new JSONObject()
|
||||
.put("translate", "block.minecraft.bed.no_sleep")));
|
||||
} else {
|
||||
attributes.put("minecraft:gameplay/bed_rule", new JSONObject()
|
||||
.put("can_set_spawn", "never")
|
||||
.put("can_sleep", "never")
|
||||
.put("explodes", true));
|
||||
}
|
||||
|
||||
attributes.put("minecraft:gameplay/respawn_anchor_works", json.remove("respawn_anchor_works"));
|
||||
attributes.put("minecraft:gameplay/piglins_zombify", json.remove("piglin_safe"));
|
||||
attributes.put("minecraft:gameplay/can_start_raid", json.remove("has_raids"));
|
||||
|
||||
var cloud_height = json.remove("cloud_height");
|
||||
if (cloud_height != null) attributes.put("minecraft:visual/cloud_height", cloud_height);
|
||||
|
||||
boolean natural = (Boolean) json.remove("natural");
|
||||
attributes.put("minecraft:gameplay/nether_portal_spawns_piglin", natural);
|
||||
if (natural != (dimension == Dimension.OVERWORLD)) {
|
||||
attributes.put("minecraft:gameplay/eyeblossom_open", natural);
|
||||
attributes.put("minecraft:gameplay/creaking_active", natural);
|
||||
}
|
||||
|
||||
//json.put("has_fixed_time", json.remove("fixed_time") != null); //TODO investigate
|
||||
json.put("attributes", attributes);
|
||||
|
||||
json.remove("effects");
|
||||
var defaults = new JSONObject(DIMENSIONS.get(dimension));
|
||||
merge(json, defaults);
|
||||
}
|
||||
|
||||
private void merge(JSONObject base, JSONObject override) {
|
||||
for (String key : override.keySet()) {
|
||||
switch (base.opt(key)) {
|
||||
case null -> base.put(key, override.opt(key));
|
||||
case JSONObject base1 when override.opt(key) instanceof JSONObject override1 -> merge(base1, override1);
|
||||
case JSONArray base1 when override.opt(key) instanceof JSONArray override1 -> {
|
||||
for (Object o : override1) {
|
||||
base1.put(o);
|
||||
}
|
||||
}
|
||||
default -> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
package art.arcane.iris.core.scripting.func;
|
||||
|
||||
import art.arcane.iris.engine.object.IrisBiome;
|
||||
import art.arcane.volmlib.util.documentation.BlockCoordinates;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface BiomeLookup {
|
||||
@BlockCoordinates
|
||||
IrisBiome at(int x, int z);
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
package art.arcane.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();
|
||||
}
|
||||
}
|
||||
@@ -1,270 +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 art.arcane.iris.core.service;
|
||||
|
||||
import art.arcane.iris.Iris;
|
||||
import art.arcane.iris.core.IrisSettings;
|
||||
import art.arcane.iris.core.commands.CommandIris;
|
||||
import art.arcane.iris.core.tools.IrisToolbelt;
|
||||
import art.arcane.iris.engine.data.cache.AtomicCache;
|
||||
import art.arcane.iris.util.decree.DecreeContext;
|
||||
import art.arcane.iris.util.decree.DecreeContextHandler;
|
||||
import art.arcane.iris.util.decree.DecreeSystem;
|
||||
import art.arcane.iris.util.format.C;
|
||||
import art.arcane.iris.util.plugin.IrisService;
|
||||
import art.arcane.iris.util.plugin.VolmitSender;
|
||||
import art.arcane.iris.util.scheduling.J;
|
||||
import art.arcane.volmlib.util.director.compat.DirectorDecreeEngineFactory;
|
||||
import art.arcane.volmlib.util.director.context.DirectorContextRegistry;
|
||||
import art.arcane.volmlib.util.director.runtime.DirectorExecutionMode;
|
||||
import art.arcane.volmlib.util.director.runtime.DirectorExecutionResult;
|
||||
import art.arcane.volmlib.util.director.runtime.DirectorInvocation;
|
||||
import art.arcane.volmlib.util.director.runtime.DirectorInvocationHook;
|
||||
import art.arcane.volmlib.util.director.runtime.DirectorRuntimeEngine;
|
||||
import art.arcane.volmlib.util.director.runtime.DirectorRuntimeNode;
|
||||
import art.arcane.volmlib.util.director.runtime.DirectorSender;
|
||||
import art.arcane.volmlib.util.director.visual.DirectorVisualCommand;
|
||||
import art.arcane.volmlib.util.math.RNG;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.PluginCommand;
|
||||
import org.bukkit.command.TabCompleter;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public class CommandSVC implements IrisService, CommandExecutor, TabCompleter, DirectorInvocationHook {
|
||||
private static final String ROOT_COMMAND = "iris";
|
||||
private static final String ROOT_PERMISSION = "iris.all";
|
||||
|
||||
private final transient AtomicCache<DirectorRuntimeEngine> directorCache = new AtomicCache<>();
|
||||
private final transient AtomicCache<DirectorVisualCommand> helpCache = new AtomicCache<>();
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
PluginCommand command = Iris.instance.getCommand(ROOT_COMMAND);
|
||||
if (command == null) {
|
||||
Iris.warn("Failed to find command '" + ROOT_COMMAND + "'");
|
||||
return;
|
||||
}
|
||||
|
||||
command.setExecutor(this);
|
||||
command.setTabCompleter(this);
|
||||
J.a(this::getDirector);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void on(PlayerCommandPreprocessEvent e) {
|
||||
String msg = e.getMessage().startsWith("/") ? e.getMessage().substring(1) : e.getMessage();
|
||||
|
||||
if ((msg.startsWith("locate ") || msg.startsWith("locatebiome ")) && IrisToolbelt.isIrisWorld(e.getPlayer().getWorld())) {
|
||||
new VolmitSender(e.getPlayer()).sendMessage(C.RED + "Locating biomes & objects is disabled in Iris Worlds. Use /iris studio goto <biome>");
|
||||
e.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
public DirectorRuntimeEngine getDirector() {
|
||||
return directorCache.aquireNastyPrint(() -> DirectorDecreeEngineFactory.create(
|
||||
new CommandIris(),
|
||||
null,
|
||||
buildDirectorContexts(),
|
||||
this::dispatchDirector,
|
||||
this,
|
||||
DecreeSystem.handlers
|
||||
));
|
||||
}
|
||||
|
||||
private DirectorContextRegistry buildDirectorContexts() {
|
||||
DirectorContextRegistry contexts = new DirectorContextRegistry();
|
||||
|
||||
for (Map.Entry<Class<?>, DecreeContextHandler<?>> entry : DecreeContextHandler.contextHandlers.entrySet()) {
|
||||
registerContextHandler(contexts, entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
return contexts;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
private void registerContextHandler(DirectorContextRegistry contexts, Class<?> type, DecreeContextHandler<?> handler) {
|
||||
contexts.register((Class) type, (invocation, map) -> {
|
||||
if (invocation.getSender() instanceof BukkitDirectorSender sender) {
|
||||
return ((DecreeContextHandler) handler).handle(new VolmitSender(sender.sender()));
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
private void dispatchDirector(DirectorExecutionMode mode, Runnable runnable) {
|
||||
if (mode == DirectorExecutionMode.SYNC) {
|
||||
J.s(runnable);
|
||||
} else {
|
||||
runnable.run();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeInvoke(DirectorInvocation invocation, DirectorRuntimeNode node) {
|
||||
if (invocation.getSender() instanceof BukkitDirectorSender sender) {
|
||||
DecreeContext.touch(new VolmitSender(sender.sender()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterInvoke(DirectorInvocation invocation, DirectorRuntimeNode node) {
|
||||
DecreeContext.remove();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] args) {
|
||||
if (!command.getName().equalsIgnoreCase(ROOT_COMMAND)) {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
List<String> v = runDirectorTab(sender, alias, args);
|
||||
if (sender instanceof Player player && IrisSettings.get().getGeneral().isCommandSounds()) {
|
||||
player.playSound(player.getLocation(), Sound.BLOCK_AMETHYST_BLOCK_CHIME, 0.25f, RNG.r.f(0.125f, 1.95f));
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
|
||||
if (!command.getName().equalsIgnoreCase(ROOT_COMMAND)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!sender.hasPermission(ROOT_PERMISSION)) {
|
||||
sender.sendMessage("You lack the Permission '" + ROOT_PERMISSION + "'");
|
||||
return true;
|
||||
}
|
||||
|
||||
J.aBukkit(() -> executeCommand(sender, label, args));
|
||||
return true;
|
||||
}
|
||||
|
||||
private void executeCommand(CommandSender sender, String label, String[] args) {
|
||||
if (sendHelpIfRequested(sender, args)) {
|
||||
playSuccessSound(sender);
|
||||
return;
|
||||
}
|
||||
|
||||
DirectorExecutionResult result = runDirector(sender, label, args);
|
||||
|
||||
if (result.isSuccess()) {
|
||||
playSuccessSound(sender);
|
||||
return;
|
||||
}
|
||||
|
||||
playFailureSound(sender);
|
||||
if (result.getMessage() == null || result.getMessage().trim().isEmpty()) {
|
||||
new VolmitSender(sender).sendMessage(C.RED + "Unknown Iris Command");
|
||||
}
|
||||
}
|
||||
|
||||
private boolean sendHelpIfRequested(CommandSender sender, String[] args) {
|
||||
Optional<DirectorVisualCommand.HelpRequest> request = DirectorVisualCommand.resolveHelp(getHelpRoot(), Arrays.asList(args));
|
||||
if (request.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
VolmitSender volmitSender = new VolmitSender(sender);
|
||||
volmitSender.sendDecreeHelp(request.get().command(), request.get().page());
|
||||
return true;
|
||||
}
|
||||
|
||||
private DirectorVisualCommand getHelpRoot() {
|
||||
return helpCache.aquireNastyPrint(() -> DirectorVisualCommand.createRoot(getDirector()));
|
||||
}
|
||||
|
||||
private DirectorExecutionResult runDirector(CommandSender sender, String label, String[] args) {
|
||||
try {
|
||||
return getDirector().execute(new DirectorInvocation(new BukkitDirectorSender(sender), label, Arrays.asList(args)));
|
||||
} catch (Throwable e) {
|
||||
Iris.warn("Director command execution failed: " + e.getClass().getSimpleName() + " " + e.getMessage());
|
||||
return DirectorExecutionResult.notHandled();
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> runDirectorTab(CommandSender sender, String alias, String[] args) {
|
||||
try {
|
||||
return getDirector().tabComplete(new DirectorInvocation(new BukkitDirectorSender(sender), alias, Arrays.asList(args)));
|
||||
} catch (Throwable e) {
|
||||
Iris.warn("Director tab completion failed: " + e.getClass().getSimpleName() + " " + e.getMessage());
|
||||
return List.of();
|
||||
}
|
||||
}
|
||||
|
||||
private void playFailureSound(CommandSender sender) {
|
||||
if (!IrisSettings.get().getGeneral().isCommandSounds()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (sender instanceof Player player) {
|
||||
player.playSound(player.getLocation(), Sound.BLOCK_AMETHYST_CLUSTER_BREAK, 0.77f, 0.25f);
|
||||
player.playSound(player.getLocation(), Sound.BLOCK_BEACON_DEACTIVATE, 0.2f, 0.45f);
|
||||
}
|
||||
}
|
||||
|
||||
private void playSuccessSound(CommandSender sender) {
|
||||
if (!IrisSettings.get().getGeneral().isCommandSounds()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (sender instanceof Player player) {
|
||||
player.playSound(player.getLocation(), Sound.BLOCK_AMETHYST_CLUSTER_BREAK, 0.77f, 1.65f);
|
||||
player.playSound(player.getLocation(), Sound.BLOCK_RESPAWN_ANCHOR_CHARGE, 0.125f, 2.99f);
|
||||
}
|
||||
}
|
||||
|
||||
private record BukkitDirectorSender(CommandSender sender) implements DirectorSender {
|
||||
@Override
|
||||
public String getName() {
|
||||
return sender.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPlayer() {
|
||||
return sender instanceof Player;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(String message) {
|
||||
if (message != null && !message.trim().isEmpty()) {
|
||||
sender.sendMessage(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,230 +0,0 @@
|
||||
package art.arcane.iris.core.service;
|
||||
|
||||
import art.arcane.iris.Iris;
|
||||
import art.arcane.iris.core.gui.PregeneratorJob;
|
||||
import art.arcane.iris.core.pregenerator.LazyPregenerator;
|
||||
import art.arcane.iris.core.pregenerator.TurboPregenerator;
|
||||
import art.arcane.iris.util.plugin.IrisService;
|
||||
import art.arcane.volmlib.integration.IntegrationHandshakeRequest;
|
||||
import art.arcane.volmlib.integration.IntegrationHandshakeResponse;
|
||||
import art.arcane.volmlib.integration.IntegrationHeartbeat;
|
||||
import art.arcane.volmlib.integration.IntegrationMetricDescriptor;
|
||||
import art.arcane.volmlib.integration.IntegrationMetricSample;
|
||||
import art.arcane.volmlib.integration.IntegrationMetricSchema;
|
||||
import art.arcane.volmlib.integration.IntegrationProtocolNegotiator;
|
||||
import art.arcane.volmlib.integration.IntegrationProtocolVersion;
|
||||
import art.arcane.volmlib.integration.IntegrationServiceContract;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.ServicePriority;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
public class IrisIntegrationService implements IrisService, IntegrationServiceContract {
|
||||
private static final Set<IntegrationProtocolVersion> SUPPORTED_PROTOCOLS = Set.of(
|
||||
new IntegrationProtocolVersion(1, 0),
|
||||
new IntegrationProtocolVersion(1, 1)
|
||||
);
|
||||
|
||||
private static final Set<String> CAPABILITIES = Set.of(
|
||||
"handshake",
|
||||
"heartbeat",
|
||||
"metrics",
|
||||
"iris-engine-metrics"
|
||||
);
|
||||
|
||||
private volatile IntegrationProtocolVersion negotiatedProtocol = new IntegrationProtocolVersion(1, 1);
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
Bukkit.getServicesManager().register(IntegrationServiceContract.class, this, Iris.instance, ServicePriority.Normal);
|
||||
Iris.verbose("Integration provider registered for Iris");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
Bukkit.getServicesManager().unregister(IntegrationServiceContract.class, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String pluginId() {
|
||||
return "iris";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String pluginVersion() {
|
||||
return Iris.instance.getDescription().getVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<IntegrationProtocolVersion> supportedProtocols() {
|
||||
return SUPPORTED_PROTOCOLS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> capabilities() {
|
||||
return CAPABILITIES;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<IntegrationMetricDescriptor> metricDescriptors() {
|
||||
return IntegrationMetricSchema.descriptors().stream()
|
||||
.filter(descriptor -> descriptor.key().startsWith("iris."))
|
||||
.collect(java.util.stream.Collectors.toSet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public IntegrationHandshakeResponse handshake(IntegrationHandshakeRequest request) {
|
||||
long now = System.currentTimeMillis();
|
||||
if (request == null) {
|
||||
return new IntegrationHandshakeResponse(
|
||||
pluginId(),
|
||||
pluginVersion(),
|
||||
false,
|
||||
null,
|
||||
SUPPORTED_PROTOCOLS,
|
||||
CAPABILITIES,
|
||||
"missing request",
|
||||
now
|
||||
);
|
||||
}
|
||||
|
||||
Optional<IntegrationProtocolVersion> negotiated = IntegrationProtocolNegotiator.negotiate(
|
||||
SUPPORTED_PROTOCOLS,
|
||||
request.supportedProtocols()
|
||||
);
|
||||
if (negotiated.isEmpty()) {
|
||||
return new IntegrationHandshakeResponse(
|
||||
pluginId(),
|
||||
pluginVersion(),
|
||||
false,
|
||||
null,
|
||||
SUPPORTED_PROTOCOLS,
|
||||
CAPABILITIES,
|
||||
"no-common-protocol",
|
||||
now
|
||||
);
|
||||
}
|
||||
|
||||
negotiatedProtocol = negotiated.get();
|
||||
return new IntegrationHandshakeResponse(
|
||||
pluginId(),
|
||||
pluginVersion(),
|
||||
true,
|
||||
negotiatedProtocol,
|
||||
SUPPORTED_PROTOCOLS,
|
||||
CAPABILITIES,
|
||||
"ok",
|
||||
now
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IntegrationHeartbeat heartbeat() {
|
||||
long now = System.currentTimeMillis();
|
||||
return new IntegrationHeartbeat(negotiatedProtocol, true, now, "ok");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, IntegrationMetricSample> sampleMetrics(Set<String> metricKeys) {
|
||||
Set<String> requested = metricKeys == null || metricKeys.isEmpty()
|
||||
? IntegrationMetricSchema.irisKeys()
|
||||
: metricKeys;
|
||||
long now = System.currentTimeMillis();
|
||||
Map<String, IntegrationMetricSample> out = new HashMap<>();
|
||||
|
||||
for (String key : requested) {
|
||||
switch (key) {
|
||||
case IntegrationMetricSchema.IRIS_CHUNK_STREAM_MS -> out.put(key, sampleChunkStreamMetric(now));
|
||||
case IntegrationMetricSchema.IRIS_PREGEN_QUEUE -> out.put(key, samplePregenQueueMetric(now));
|
||||
case IntegrationMetricSchema.IRIS_BIOME_CACHE_HIT_RATE -> out.put(key, sampleBiomeCacheHitRateMetric(now));
|
||||
default -> out.put(key, IntegrationMetricSample.unavailable(
|
||||
IntegrationMetricSchema.descriptor(key),
|
||||
"unsupported-key",
|
||||
now
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
private IntegrationMetricSample sampleChunkStreamMetric(long now) {
|
||||
IntegrationMetricDescriptor descriptor = IntegrationMetricSchema.descriptor(IntegrationMetricSchema.IRIS_CHUNK_STREAM_MS);
|
||||
|
||||
double chunksPerSecond = PregeneratorJob.chunksPerSecond();
|
||||
if (chunksPerSecond <= 0D) {
|
||||
chunksPerSecond = TurboPregenerator.chunksPerSecond();
|
||||
}
|
||||
if (chunksPerSecond <= 0D) {
|
||||
chunksPerSecond = LazyPregenerator.chunksPerSecond();
|
||||
}
|
||||
|
||||
if (chunksPerSecond > 0D) {
|
||||
return IntegrationMetricSample.available(descriptor, 1000D / chunksPerSecond, now);
|
||||
}
|
||||
|
||||
IrisEngineSVC engineService = Iris.service(IrisEngineSVC.class);
|
||||
if (engineService != null) {
|
||||
double idle = engineService.getAverageIdleDuration();
|
||||
if (idle > 0D && Double.isFinite(idle)) {
|
||||
return IntegrationMetricSample.available(descriptor, idle, now);
|
||||
}
|
||||
}
|
||||
|
||||
return IntegrationMetricSample.available(descriptor, 0D, now);
|
||||
}
|
||||
|
||||
private IntegrationMetricSample samplePregenQueueMetric(long now) {
|
||||
IntegrationMetricDescriptor descriptor = IntegrationMetricSchema.descriptor(IntegrationMetricSchema.IRIS_PREGEN_QUEUE);
|
||||
long totalQueue = 0L;
|
||||
boolean hasAnySource = false;
|
||||
|
||||
long pregenRemaining = PregeneratorJob.chunksRemaining();
|
||||
if (pregenRemaining >= 0L) {
|
||||
totalQueue += pregenRemaining;
|
||||
hasAnySource = true;
|
||||
}
|
||||
|
||||
long turboRemaining = TurboPregenerator.remainingChunks();
|
||||
if (turboRemaining >= 0L) {
|
||||
totalQueue += turboRemaining;
|
||||
hasAnySource = true;
|
||||
}
|
||||
|
||||
long lazyRemaining = LazyPregenerator.remainingChunks();
|
||||
if (lazyRemaining >= 0L) {
|
||||
totalQueue += lazyRemaining;
|
||||
hasAnySource = true;
|
||||
}
|
||||
|
||||
IrisEngineSVC engineService = Iris.service(IrisEngineSVC.class);
|
||||
if (engineService != null) {
|
||||
totalQueue += Math.max(0, engineService.getQueuedTectonicPlateCount());
|
||||
hasAnySource = true;
|
||||
}
|
||||
|
||||
if (!hasAnySource) {
|
||||
return IntegrationMetricSample.unavailable(descriptor, "queue-not-available", now);
|
||||
}
|
||||
|
||||
return IntegrationMetricSample.available(descriptor, totalQueue, now);
|
||||
}
|
||||
|
||||
private IntegrationMetricSample sampleBiomeCacheHitRateMetric(long now) {
|
||||
IntegrationMetricDescriptor descriptor = IntegrationMetricSchema.descriptor(IntegrationMetricSchema.IRIS_BIOME_CACHE_HIT_RATE);
|
||||
IrisEngineSVC engineService = Iris.service(IrisEngineSVC.class);
|
||||
if (engineService == null) {
|
||||
return IntegrationMetricSample.unavailable(descriptor, "engine-service-unavailable", now);
|
||||
}
|
||||
|
||||
double ratio = engineService.getBiomeCacheUsageRatio();
|
||||
if (!Double.isFinite(ratio)) {
|
||||
return IntegrationMetricSample.unavailable(descriptor, "biome-cache-ratio-invalid", now);
|
||||
}
|
||||
|
||||
return IntegrationMetricSample.available(descriptor, Math.max(0D, Math.min(1D, ratio)), now);
|
||||
}
|
||||
}
|
||||
@@ -1,157 +0,0 @@
|
||||
package art.arcane.iris.core.tools;
|
||||
|
||||
import art.arcane.iris.Iris;
|
||||
import art.arcane.iris.engine.object.*;
|
||||
import art.arcane.volmlib.util.data.Varint;
|
||||
import art.arcane.iris.util.format.C;
|
||||
import art.arcane.volmlib.util.format.Form;
|
||||
import art.arcane.volmlib.util.nbt.io.NBTUtil;
|
||||
import art.arcane.volmlib.util.nbt.io.NamedTag;
|
||||
import art.arcane.volmlib.util.nbt.tag.*;
|
||||
import art.arcane.iris.util.plugin.VolmitSender;
|
||||
import art.arcane.iris.util.scheduling.J;
|
||||
import art.arcane.volmlib.util.scheduling.PrecisionStopwatch;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class IrisConverter {
|
||||
public static void convertSchematics(VolmitSender sender) {
|
||||
File folder = Iris.instance.getDataFolder("convert");
|
||||
|
||||
FilenameFilter filter = (dir, name) -> name.endsWith(".schem");
|
||||
File[] fileList = folder.listFiles(filter);
|
||||
if (fileList == null) {
|
||||
sender.sendMessage("No schematic files to convert found in " + folder.getAbsolutePath());
|
||||
return;
|
||||
}
|
||||
|
||||
AtomicInteger counter = new AtomicInteger(0);
|
||||
var stopwatch = PrecisionStopwatch.start();
|
||||
ExecutorService executorService = Executors.newFixedThreadPool(1);
|
||||
executorService.submit(() -> {
|
||||
for (File schem : fileList) {
|
||||
try {
|
||||
PrecisionStopwatch p = PrecisionStopwatch.start();
|
||||
IrisObject object;
|
||||
boolean largeObject = false;
|
||||
NamedTag tag;
|
||||
try {
|
||||
tag = NBTUtil.read(schem);
|
||||
} catch (IOException e) {
|
||||
Iris.info(C.RED + "Failed to read: " + schem.getName());
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
CompoundTag compound = (CompoundTag) tag.getTag();
|
||||
int version = resolveVersion(compound);
|
||||
if (!(version == 2 || version == 3))
|
||||
throw new RuntimeException(C.RED + "Unsupported schematic version: " + version);
|
||||
|
||||
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 > 2_000_000) {
|
||||
largeObject = true;
|
||||
Iris.info(C.GRAY + "Converting.. " + schem.getName() + " -> " + schem.getName().replace(".schem", ".iob"));
|
||||
Iris.info(C.GRAY + "- It may take a while");
|
||||
if (sender.isPlayer()) {
|
||||
i = J.ar(() -> {
|
||||
sender.sendProgress((double) v.get() / mv, "Converting");
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
|
||||
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()) {
|
||||
String blockName = entry.getKey();
|
||||
BlockData bd = Bukkit.createBlockData(blockName);
|
||||
Tag<?> blockTag = entry.getValue();
|
||||
int blockId = ((IntTag) blockTag).getValue();
|
||||
blockmap.put(blockId, bd);
|
||||
}
|
||||
|
||||
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();
|
||||
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++) {
|
||||
int blockIndex = isBytes ? din.read() & 0xFF : Varint.readUnsignedVarInt(din);
|
||||
BlockData bd = blockmap.get(blockIndex);
|
||||
if (!bd.getMaterial().isAir()) {
|
||||
object.setUnsigned(w, h, d, bd);
|
||||
}
|
||||
v.getAndAdd(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (i != -1) J.car(i);
|
||||
try {
|
||||
object.shrinkwrap();
|
||||
object.write(new File(folder, schem.getName().replace(".schem", ".iob")));
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
} catch (Exception e) {
|
||||
sender.sendMessage(C.RED + "Failed to convert: " + schem.getName());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
package art.arcane.iris.util.board;
|
||||
|
||||
public class BoardEntry {
|
||||
private final art.arcane.volmlib.util.board.BoardEntry delegate;
|
||||
|
||||
private BoardEntry(art.arcane.volmlib.util.board.BoardEntry delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
public String getPrefix() {
|
||||
return delegate.getPrefix();
|
||||
}
|
||||
|
||||
public String getSuffix() {
|
||||
return delegate.getSuffix();
|
||||
}
|
||||
|
||||
public static BoardEntry translateToEntry(String input) {
|
||||
return new BoardEntry(art.arcane.volmlib.util.board.BoardEntry.translateToEntry(input));
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
package art.arcane.iris.util.board;
|
||||
|
||||
import art.arcane.volmlib.util.board.BoardProvider;
|
||||
|
||||
public class BoardSettings {
|
||||
private final BoardProvider boardProvider;
|
||||
private final ScoreDirection scoreDirection;
|
||||
|
||||
private BoardSettings(BoardProvider boardProvider, ScoreDirection scoreDirection) {
|
||||
this.boardProvider = boardProvider;
|
||||
this.scoreDirection = scoreDirection;
|
||||
}
|
||||
|
||||
public BoardProvider getBoardProvider() {
|
||||
return boardProvider;
|
||||
}
|
||||
|
||||
public ScoreDirection getScoreDirection() {
|
||||
return scoreDirection;
|
||||
}
|
||||
|
||||
public art.arcane.volmlib.util.board.BoardSettings toShared() {
|
||||
return art.arcane.volmlib.util.board.BoardSettings.builder()
|
||||
.boardProvider(boardProvider)
|
||||
.scoreDirection(scoreDirection.toShared())
|
||||
.build();
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private BoardProvider boardProvider;
|
||||
private ScoreDirection scoreDirection;
|
||||
|
||||
public Builder boardProvider(BoardProvider boardProvider) {
|
||||
this.boardProvider = boardProvider;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder scoreDirection(ScoreDirection scoreDirection) {
|
||||
this.scoreDirection = scoreDirection;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BoardSettings build() {
|
||||
return new BoardSettings(boardProvider, scoreDirection);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
package art.arcane.iris.util.board;
|
||||
|
||||
public enum ScoreDirection {
|
||||
UP,
|
||||
DOWN;
|
||||
|
||||
public art.arcane.volmlib.util.board.ScoreDirection toShared() {
|
||||
return this == UP
|
||||
? art.arcane.volmlib.util.board.ScoreDirection.UP
|
||||
: art.arcane.volmlib.util.board.ScoreDirection.DOWN;
|
||||
}
|
||||
|
||||
public static ScoreDirection fromShared(art.arcane.volmlib.util.board.ScoreDirection direction) {
|
||||
return direction == art.arcane.volmlib.util.board.ScoreDirection.UP ? UP : DOWN;
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
package art.arcane.iris.util.cache;
|
||||
|
||||
import art.arcane.volmlib.util.cache.ChunkCache2D;
|
||||
|
||||
import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap;
|
||||
import art.arcane.iris.engine.data.cache.Cache;
|
||||
import art.arcane.volmlib.util.function.Function2;
|
||||
|
||||
public class WorldCache2D<T> {
|
||||
private final ConcurrentLinkedHashMap<Long, ChunkCache2D<T>> chunks;
|
||||
private final Function2<Integer, Integer, T> resolver;
|
||||
|
||||
public WorldCache2D(Function2<Integer, Integer, T> resolver, int size) {
|
||||
this.resolver = resolver;
|
||||
chunks = new ConcurrentLinkedHashMap.Builder<Long, ChunkCache2D<T>>()
|
||||
.initialCapacity(size)
|
||||
.maximumWeightedCapacity(size)
|
||||
.concurrencyLevel(Math.max(32, Runtime.getRuntime().availableProcessors() * 4))
|
||||
.build();
|
||||
}
|
||||
|
||||
public T get(int x, int z) {
|
||||
ChunkCache2D<T> chunk = chunks.computeIfAbsent(Cache.key(x >> 4, z >> 4), $ -> new ChunkCache2D<>("iris"));
|
||||
return chunk.get(x, z, resolver);
|
||||
}
|
||||
|
||||
public long getSize() {
|
||||
return chunks.size() * 256L;
|
||||
}
|
||||
|
||||
public long getMaxSize() {
|
||||
return chunks.capacity() * 256L;
|
||||
}
|
||||
}
|
||||
@@ -1,257 +0,0 @@
|
||||
package art.arcane.iris.util.data;
|
||||
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
import art.arcane.volmlib.util.collection.KMap;
|
||||
import art.arcane.volmlib.util.data.BSupport;
|
||||
import art.arcane.iris.Iris;
|
||||
import art.arcane.iris.core.IrisSettings;
|
||||
import art.arcane.iris.core.link.Identifier;
|
||||
import art.arcane.iris.core.link.data.DataType;
|
||||
import art.arcane.iris.core.nms.INMS;
|
||||
import art.arcane.iris.core.nms.container.BlockProperty;
|
||||
import art.arcane.iris.core.service.ExternalDataSVC;
|
||||
import art.arcane.iris.util.data.registry.Materials;
|
||||
import it.unimi.dsi.fastutil.ints.IntSet;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public class B {
|
||||
private static final BSupportImpl BASE = new BSupportImpl();
|
||||
|
||||
private static final class BSupportImpl extends BSupport<BlockProperty> {
|
||||
@Override
|
||||
protected void warn(String message) {
|
||||
Iris.warn(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void debug(String message) {
|
||||
Iris.debug(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void reportError(Throwable throwable) {
|
||||
Iris.reportError(throwable);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void error(String message) {
|
||||
Iris.error(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Material shortGrassMaterial() {
|
||||
return Materials.GRASS;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void appendExtraFoliageMaterials(IntSet foliage) {
|
||||
// Iris has no extra foliage materials beyond Bukkit Material.
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean includeLitInUpdatable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BlockData resolveCompatBlock(String bdxf) {
|
||||
if (bdxf.contains(":")) {
|
||||
if (bdxf.startsWith("minecraft:")) {
|
||||
return Iris.compat.getBlock(bdxf);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return Iris.compat.getBlock(bdxf);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BlockData resolveExternalBlockData(String ix) {
|
||||
if (ix.startsWith("minecraft:") || !ix.contains(":")) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Identifier key = Identifier.fromString(ix);
|
||||
Optional<BlockData> bd = Iris.service(ExternalDataSVC.class).getBlockData(key);
|
||||
debug("Loading block data " + key);
|
||||
return bd.orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldPreventLeafDecay() {
|
||||
return IrisSettings.get().getGenerator().isPreventLeafDecay();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void appendExternalBlockTypes(KList<String> blockTypes) {
|
||||
for (Identifier id : Iris.service(ExternalDataSVC.class).getAllIdentifiers(DataType.BLOCK)) {
|
||||
blockTypes.add(id.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void appendExternalItemTypes(KList<String> itemTypes) {
|
||||
for (Identifier id : Iris.service(ExternalDataSVC.class).getAllIdentifiers(DataType.ITEM)) {
|
||||
itemTypes.add(id.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected KMap<List<String>, List<BlockProperty>> loadExternalBlockStates() {
|
||||
KMap<List<BlockProperty>, List<String>> flipped = new KMap<>();
|
||||
INMS.get().getBlockProperties().forEach((k, v) -> {
|
||||
flipped.computeIfAbsent(v, $ -> new KList<>()).add(k.getKey().toString());
|
||||
});
|
||||
|
||||
var emptyStates = flipped.computeIfAbsent(new KList<>(0), $ -> new KList<>());
|
||||
for (var pair : Iris.service(ExternalDataSVC.class).getAllBlockProperties()) {
|
||||
if (pair.getB().isEmpty()) {
|
||||
emptyStates.add(pair.getA().toString());
|
||||
} else {
|
||||
flipped.computeIfAbsent(pair.getB(), $ -> new KList<>()).add(pair.getA().toString());
|
||||
}
|
||||
}
|
||||
|
||||
KMap<List<String>, List<BlockProperty>> states = new KMap<>();
|
||||
flipped.forEach((k, v) -> {
|
||||
var old = states.put(v, k);
|
||||
if (old != null) {
|
||||
error("Duplicate block state: " + v + " (" + old + " and " + k + ")");
|
||||
}
|
||||
});
|
||||
|
||||
return states;
|
||||
}
|
||||
}
|
||||
|
||||
public static BlockData toDeepSlateOre(BlockData block, BlockData ore) {
|
||||
return BASE.toDeepSlateOre(block, ore);
|
||||
}
|
||||
|
||||
public static boolean isDeepSlate(BlockData blockData) {
|
||||
return BASE.isDeepSlate(blockData);
|
||||
}
|
||||
|
||||
public static boolean isOre(BlockData blockData) {
|
||||
return BASE.isOre(blockData);
|
||||
}
|
||||
|
||||
public static boolean canPlaceOnto(Material mat, Material onto) {
|
||||
return BASE.canPlaceOnto(mat, onto);
|
||||
}
|
||||
|
||||
public static boolean isFoliagePlantable(BlockData d) {
|
||||
return BASE.isFoliagePlantable(d);
|
||||
}
|
||||
|
||||
public static boolean isFoliagePlantable(Material d) {
|
||||
return BASE.isFoliagePlantable(d);
|
||||
}
|
||||
|
||||
public static boolean isWater(BlockData b) {
|
||||
return BASE.isWater(b);
|
||||
}
|
||||
|
||||
public static BlockData getAir() {
|
||||
return BASE.getAir();
|
||||
}
|
||||
|
||||
public static Material getMaterialOrNull(String bdx) {
|
||||
return BASE.getMaterialOrNull(bdx);
|
||||
}
|
||||
|
||||
public static Material getMaterial(String bdx) {
|
||||
return BASE.getMaterial(bdx);
|
||||
}
|
||||
|
||||
public static boolean isSolid(BlockData mat) {
|
||||
return BASE.isSolid(mat);
|
||||
}
|
||||
|
||||
public static BlockData getOrNull(String bdxf) {
|
||||
return BASE.getOrNull(bdxf);
|
||||
}
|
||||
|
||||
public static BlockData getOrNull(String bdxf, boolean warn) {
|
||||
return BASE.getOrNull(bdxf, warn);
|
||||
}
|
||||
|
||||
public static BlockData getNoCompat(String bdxf) {
|
||||
return BASE.getNoCompat(bdxf);
|
||||
}
|
||||
|
||||
public static BlockData get(String bdxf) {
|
||||
return BASE.get(bdxf);
|
||||
}
|
||||
|
||||
public static boolean isStorage(BlockData mat) {
|
||||
return BASE.isStorage(mat);
|
||||
}
|
||||
|
||||
public static boolean isStorageChest(BlockData mat) {
|
||||
return BASE.isStorageChest(mat);
|
||||
}
|
||||
|
||||
public static boolean isLit(BlockData mat) {
|
||||
return BASE.isLit(mat);
|
||||
}
|
||||
|
||||
public static boolean isUpdatable(BlockData mat) {
|
||||
return BASE.isUpdatable(mat);
|
||||
}
|
||||
|
||||
public static boolean isFoliage(Material d) {
|
||||
return BASE.isFoliage(d);
|
||||
}
|
||||
|
||||
public static boolean isFoliage(BlockData d) {
|
||||
return BASE.isFoliage(d);
|
||||
}
|
||||
|
||||
public static boolean isDecorant(BlockData m) {
|
||||
return BASE.isDecorant(m);
|
||||
}
|
||||
|
||||
public static KList<BlockData> get(KList<String> find) {
|
||||
return BASE.get(find);
|
||||
}
|
||||
|
||||
public static boolean isFluid(BlockData d) {
|
||||
return BASE.isFluid(d);
|
||||
}
|
||||
|
||||
public static boolean isAirOrFluid(BlockData d) {
|
||||
return BASE.isAirOrFluid(d);
|
||||
}
|
||||
|
||||
public static boolean isAir(BlockData d) {
|
||||
return BASE.isAir(d);
|
||||
}
|
||||
|
||||
public synchronized static String[] getBlockTypes() {
|
||||
return BASE.getBlockTypes();
|
||||
}
|
||||
|
||||
public synchronized static KMap<List<String>, List<BlockProperty>> getBlockStates() {
|
||||
return BASE.getBlockStates();
|
||||
}
|
||||
|
||||
public static String[] getItemTypes() {
|
||||
return BASE.getItemTypes();
|
||||
}
|
||||
|
||||
public static boolean isWaterLogged(BlockData b) {
|
||||
return BASE.isWaterLogged(b);
|
||||
}
|
||||
|
||||
public static void registerCustomBlockData(String namespace, String key, BlockData blockData) {
|
||||
BASE.registerCustomBlockData(namespace, key, blockData);
|
||||
}
|
||||
|
||||
public static boolean isVineBlock(BlockData data) {
|
||||
return BASE.isVineBlock(data);
|
||||
}
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
package art.arcane.iris.util.data;
|
||||
|
||||
import art.arcane.iris.core.link.Identifier;
|
||||
import art.arcane.volmlib.util.collection.KMap;
|
||||
import lombok.NonNull;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.*;
|
||||
|
||||
public interface IrisCustomData extends BlockData {
|
||||
@NonNull BlockData getBase();
|
||||
@NonNull Identifier getCustom();
|
||||
|
||||
static IrisCustomData of(@NotNull BlockData base, @NotNull Identifier custom) {
|
||||
var clazz = base.getClass();
|
||||
var loader = IrisCustomData.class.getClassLoader();
|
||||
return (IrisCustomData) Proxy.newProxyInstance(loader, Internal.getInterfaces(loader, clazz), (proxy, method, args) ->
|
||||
switch (method.getName()) {
|
||||
case "getBase" -> base;
|
||||
case "getCustom" -> custom;
|
||||
case "merge" -> of(base.merge((BlockData) args[0]), custom);
|
||||
case "clone" -> of(base.clone(), custom);
|
||||
case "hashCode" -> Objects.hash(base, custom);
|
||||
case "matches" -> {
|
||||
if (!(args[0] instanceof IrisCustomData store))
|
||||
yield false;
|
||||
yield base.matches(store.getBase()) && custom.equals(store.getCustom());
|
||||
}
|
||||
case "equals" -> {
|
||||
if (!(args[0] instanceof IrisCustomData store))
|
||||
yield false;
|
||||
yield store.getBase().equals(base) && store.getCustom().equals(custom);
|
||||
}
|
||||
default -> method.invoke(base, args);
|
||||
});
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
abstract class Internal {
|
||||
private static final KMap<Class<?>, Class<?>[]> cache = new KMap<>();
|
||||
|
||||
private static Class<?>[] getInterfaces(ClassLoader loader, Class<?> base) {
|
||||
return cache.computeIfAbsent(base, k -> {
|
||||
Set<Class<?>> set = new HashSet<>();
|
||||
|
||||
Class<?> i = base;
|
||||
while (i != null) {
|
||||
if (!BlockData.class.isAssignableFrom(i))
|
||||
break;
|
||||
|
||||
for (Class<?> j : i.getInterfaces()) {
|
||||
if (j.isSealed() || j.isHidden())
|
||||
continue;
|
||||
|
||||
try {
|
||||
Class.forName(j.getName(), false, loader);
|
||||
set.add(j);
|
||||
} catch (ClassNotFoundException ignored) {}
|
||||
}
|
||||
|
||||
i = i.getSuperclass();
|
||||
}
|
||||
|
||||
set.add(IrisCustomData.class);
|
||||
return set.toArray(Class<?>[]::new);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,220 +0,0 @@
|
||||
package art.arcane.iris.util.data;
|
||||
|
||||
import art.arcane.volmlib.util.collection.KMap;
|
||||
import lombok.NonNull;
|
||||
import org.bukkit.util.BlockVector;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class VectorMap<T> implements Iterable<Map.Entry<BlockVector, T>> {
|
||||
private final Map<Key, Map<Key, T>> map = new KMap<>();
|
||||
|
||||
public int size() {
|
||||
return map.values().stream().mapToInt(Map::size).sum();
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return map.values().stream().allMatch(Map::isEmpty);
|
||||
}
|
||||
|
||||
public boolean containsKey(@NonNull BlockVector vector) {
|
||||
var chunk = map.get(chunk(vector));
|
||||
return chunk != null && chunk.containsKey(relative(vector));
|
||||
}
|
||||
|
||||
public boolean containsValue(@NonNull T value) {
|
||||
return map.values().stream().anyMatch(m -> m.containsValue(value));
|
||||
}
|
||||
|
||||
public @Nullable T get(@NonNull BlockVector vector) {
|
||||
var chunk = map.get(chunk(vector));
|
||||
return chunk == null ? null : chunk.get(relative(vector));
|
||||
}
|
||||
|
||||
public @Nullable T put(@NonNull BlockVector vector, @NonNull T value) {
|
||||
return map.computeIfAbsent(chunk(vector), k -> new KMap<>())
|
||||
.put(relative(vector), value);
|
||||
}
|
||||
|
||||
public @Nullable T computeIfAbsent(@NonNull BlockVector vector, @NonNull Function<@NonNull BlockVector, @NonNull T> mappingFunction) {
|
||||
return map.computeIfAbsent(chunk(vector), k -> new KMap<>())
|
||||
.computeIfAbsent(relative(vector), $ -> mappingFunction.apply(vector));
|
||||
}
|
||||
|
||||
public @Nullable T remove(@NonNull BlockVector vector) {
|
||||
var chunk = map.get(chunk(vector));
|
||||
return chunk == null ? null : chunk.remove(relative(vector));
|
||||
}
|
||||
|
||||
public void putAll(@NonNull VectorMap<T> map) {
|
||||
map.forEach(this::put);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
map.clear();
|
||||
}
|
||||
|
||||
public void forEach(@NonNull BiConsumer<@NonNull BlockVector, @NonNull T> consumer) {
|
||||
map.forEach((chunk, values) -> {
|
||||
int rX = chunk.x << 10;
|
||||
int rY = chunk.y << 10;
|
||||
int rZ = chunk.z << 10;
|
||||
|
||||
values.forEach((relative, value) -> consumer.accept(
|
||||
relative.resolve(rX, rY, rZ),
|
||||
value
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
private static Key chunk(BlockVector vector) {
|
||||
return new Key(vector.getBlockX() >> 10, vector.getBlockY() >> 10, vector.getBlockZ() >> 10);
|
||||
}
|
||||
|
||||
private static Key relative(BlockVector vector) {
|
||||
return new Key(vector.getBlockX() & 0x3FF, vector.getBlockY() & 0x3FF, vector.getBlockZ() & 0x3FF);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull EntryIterator iterator() {
|
||||
return new EntryIterator();
|
||||
}
|
||||
|
||||
public @NotNull KeyIterator keys() {
|
||||
return new KeyIterator();
|
||||
}
|
||||
|
||||
public @NotNull ValueIterator values() {
|
||||
return new ValueIterator();
|
||||
}
|
||||
|
||||
public class EntryIterator implements Iterator<Map.Entry<BlockVector, T>> {
|
||||
private final Iterator<Map.Entry<Key, Map<Key, T>>> chunkIterator = map.entrySet().iterator();
|
||||
private Iterator<Map.Entry<Key, T>> relativeIterator;
|
||||
private int rX, rY, rZ;
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return relativeIterator != null && relativeIterator.hasNext() || chunkIterator.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map.Entry<BlockVector, T> next() {
|
||||
if (relativeIterator == null || !relativeIterator.hasNext()) {
|
||||
if (!chunkIterator.hasNext()) throw new IllegalStateException("No more elements");
|
||||
var chunk = chunkIterator.next();
|
||||
rX = chunk.getKey().x << 10;
|
||||
rY = chunk.getKey().y << 10;
|
||||
rZ = chunk.getKey().z << 10;
|
||||
relativeIterator = chunk.getValue().entrySet().iterator();
|
||||
}
|
||||
|
||||
var entry = relativeIterator.next();
|
||||
return Map.entry(entry.getKey().resolve(rX, rY, rZ), entry.getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
if (relativeIterator == null) throw new IllegalStateException("No element to remove");
|
||||
relativeIterator.remove();
|
||||
}
|
||||
}
|
||||
|
||||
public class KeyIterator implements Iterator<BlockVector>, Iterable<BlockVector> {
|
||||
private final Iterator<Map.Entry<Key, Map<Key, T>>> chunkIterator = map.entrySet().iterator();
|
||||
private Iterator<Key> relativeIterator;
|
||||
private int rX, rY, rZ;
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return relativeIterator != null && relativeIterator.hasNext() || chunkIterator.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockVector next() {
|
||||
if (relativeIterator == null || !relativeIterator.hasNext()) {
|
||||
var chunk = chunkIterator.next();
|
||||
rX = chunk.getKey().x << 10;
|
||||
rY = chunk.getKey().y << 10;
|
||||
rZ = chunk.getKey().z << 10;
|
||||
relativeIterator = chunk.getValue().keySet().iterator();
|
||||
}
|
||||
|
||||
return relativeIterator.next().resolve(rX, rY, rZ);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
if (relativeIterator == null) throw new IllegalStateException("No element to remove");
|
||||
relativeIterator.remove();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Iterator<BlockVector> iterator() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public class ValueIterator implements Iterator<T>, Iterable<T> {
|
||||
private final Iterator<Map<Key, T>> chunkIterator = map.values().iterator();
|
||||
private Iterator<T> relativeIterator;
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return relativeIterator != null && relativeIterator.hasNext() || chunkIterator.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public T next() {
|
||||
if (relativeIterator == null || !relativeIterator.hasNext()) {
|
||||
relativeIterator = chunkIterator.next().values().iterator();
|
||||
}
|
||||
return relativeIterator.next();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
if (relativeIterator == null) throw new IllegalStateException("No element to remove");
|
||||
relativeIterator.remove();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Iterator<T> iterator() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
private static final class Key {
|
||||
private final int x;
|
||||
private final int y;
|
||||
private final int z;
|
||||
private final int hashCode;
|
||||
|
||||
private Key(int x, int y, int z) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.hashCode = (x << 20) | (y << 10) | z;
|
||||
}
|
||||
|
||||
private BlockVector resolve(int rX, int rY, int rZ) {
|
||||
return new BlockVector(rX + x, rY + y, rZ + z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof Key key)) return false;
|
||||
return x == key.x && y == key.y && z == key.z;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package art.arcane.iris.util.decree;
|
||||
|
||||
import art.arcane.volmlib.util.decree.context.DecreeContextBase;
|
||||
import art.arcane.iris.util.plugin.VolmitSender;
|
||||
|
||||
public class DecreeContext {
|
||||
private static final DecreeContextBase<VolmitSender> context = new DecreeContextBase<>();
|
||||
|
||||
public static VolmitSender get() {
|
||||
return context.get();
|
||||
}
|
||||
|
||||
public static void touch(VolmitSender c) {
|
||||
context.touch(c);
|
||||
}
|
||||
|
||||
public static void remove() {
|
||||
context.remove();
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
package art.arcane.iris.util.decree;
|
||||
|
||||
import art.arcane.volmlib.util.decree.context.DecreeContextHandlers;
|
||||
import art.arcane.volmlib.util.decree.context.DecreeContextHandlerType;
|
||||
import art.arcane.iris.Iris;
|
||||
import art.arcane.iris.util.plugin.VolmitSender;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public interface DecreeContextHandler<T> extends DecreeContextHandlerType<T, VolmitSender> {
|
||||
Map<Class<?>, DecreeContextHandler<?>> contextHandlers = buildContextHandlers();
|
||||
|
||||
static Map<Class<?>, DecreeContextHandler<?>> buildContextHandlers() {
|
||||
return DecreeContextHandlers.buildOrEmpty(
|
||||
Iris.initialize("art.arcane.iris.util.decree.context"),
|
||||
DecreeContextHandler.class,
|
||||
h -> ((DecreeContextHandler<?>) h).getType(),
|
||||
e -> {
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
package art.arcane.iris.util.decree;
|
||||
|
||||
public interface DecreeParameterHandler<T>
|
||||
extends DecreeExecutor, art.arcane.volmlib.util.decree.DecreeParameterHandler<T> {
|
||||
}
|
||||
@@ -1,45 +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 art.arcane.iris.util.decree;
|
||||
|
||||
import art.arcane.volmlib.util.decree.DecreeSystemSupport;
|
||||
import art.arcane.iris.Iris;
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
public final class DecreeSystem {
|
||||
public static final KList<DecreeParameterHandler<?>> handlers = Iris.initialize("art.arcane.iris.util.decree.handlers", null).convert((i) -> (DecreeParameterHandler<?>) i);
|
||||
|
||||
private DecreeSystem() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the handler for the specified type
|
||||
*
|
||||
* @param type The type to handle
|
||||
* @return The corresponding {@link DecreeParameterHandler}, or null
|
||||
*/
|
||||
public static DecreeParameterHandler<?> getHandler(Class<?> type) {
|
||||
DecreeParameterHandler<?> handler = DecreeSystemSupport.getHandler(handlers, type, (h, t) -> h.supports(t));
|
||||
if (handler != null) {
|
||||
return handler;
|
||||
}
|
||||
|
||||
Iris.error("Unhandled type in Decree Parameter: " + type.getName() + ". This is bad!");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package art.arcane.iris.util.decree.context;
|
||||
|
||||
import art.arcane.volmlib.util.decree.context.WorldContextHandlerBase;
|
||||
import art.arcane.iris.util.decree.DecreeContextHandler;
|
||||
import art.arcane.iris.util.plugin.VolmitSender;
|
||||
import org.bukkit.World;
|
||||
|
||||
public class WorldContextHandler extends WorldContextHandlerBase<VolmitSender> implements DecreeContextHandler<World> {
|
||||
@Override
|
||||
protected boolean isPlayer(VolmitSender sender) {
|
||||
return sender.isPlayer();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected World getWorld(VolmitSender sender) {
|
||||
return sender.player().getWorld();
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
package art.arcane.iris.util.decree.handlers;
|
||||
|
||||
import art.arcane.iris.util.decree.DecreeContext;
|
||||
import art.arcane.iris.util.decree.DecreeParameterHandler;
|
||||
import art.arcane.iris.util.decree.DecreeSystem;
|
||||
import art.arcane.volmlib.util.decree.handlers.base.BlockVectorHandlerBase;
|
||||
import art.arcane.volmlib.util.format.Form;
|
||||
import org.bukkit.FluidCollisionMode;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.util.BlockVector;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class BlockVectorHandler extends BlockVectorHandlerBase implements DecreeParameterHandler<BlockVector> {
|
||||
@Override
|
||||
protected boolean isSenderPlayer() {
|
||||
return DecreeContext.get().isPlayer();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BlockVector getSenderBlockVector() {
|
||||
return DecreeContext.get().player().getLocation().toVector().toBlockVector();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BlockVector getLookBlockVector() {
|
||||
return DecreeContext.get().player().getTargetBlockExact(256, FluidCollisionMode.NEVER).getLocation().toVector().toBlockVector();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<?> playerPossibilities(String query) {
|
||||
return DecreeSystem.getHandler(Player.class).getPossibilities(query);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String format(double value) {
|
||||
return Form.f(value, 2);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
package art.arcane.iris.util.decree.handlers;
|
||||
|
||||
import art.arcane.volmlib.util.decree.handlers.base.BooleanHandlerBase;
|
||||
import art.arcane.iris.util.decree.DecreeParameterHandler;
|
||||
|
||||
public class BooleanHandler extends BooleanHandlerBase implements DecreeParameterHandler<Boolean> {
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
package art.arcane.iris.util.decree.handlers;
|
||||
|
||||
import art.arcane.volmlib.util.decree.handlers.base.ByteHandlerBase;
|
||||
import art.arcane.iris.util.decree.DecreeParameterHandler;
|
||||
|
||||
public class ByteHandler extends ByteHandlerBase implements DecreeParameterHandler<Byte> {
|
||||
}
|
||||
@@ -1,87 +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 art.arcane.iris.util.decree.handlers;
|
||||
|
||||
import art.arcane.iris.core.IrisSettings;
|
||||
import art.arcane.iris.core.tools.IrisToolbelt;
|
||||
import art.arcane.iris.engine.object.IrisDimension;
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
import art.arcane.volmlib.util.decree.exceptions.DecreeParsingException;
|
||||
import art.arcane.iris.util.decree.specialhandlers.RegistrantHandler;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
public class DimensionHandler extends RegistrantHandler<IrisDimension> {
|
||||
public DimensionHandler() {
|
||||
super(IrisDimension.class, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IrisDimension parse(String in, boolean force) throws DecreeParsingException {
|
||||
String key = in.trim();
|
||||
if (key.equalsIgnoreCase("default")) {
|
||||
key = IrisSettings.get().getGenerator().getDefaultWorldType();
|
||||
}
|
||||
|
||||
try {
|
||||
return super.parse(key, force);
|
||||
} catch (DecreeParsingException ignored) {
|
||||
String normalized = key.toLowerCase(Locale.ROOT);
|
||||
IrisDimension resolved = IrisToolbelt.getDimension(normalized);
|
||||
if (resolved != null) {
|
||||
return resolved;
|
||||
}
|
||||
|
||||
if (!normalized.equals(key)) {
|
||||
resolved = IrisToolbelt.getDimension(key);
|
||||
if (resolved != null) {
|
||||
return resolved;
|
||||
}
|
||||
}
|
||||
|
||||
throw ignored;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public KList<IrisDimension> getPossibilities(String input) {
|
||||
KList<IrisDimension> possibilities = super.getPossibilities();
|
||||
String normalizedInput = input == null ? "" : input.trim().toLowerCase(Locale.ROOT);
|
||||
if (normalizedInput.isEmpty()) {
|
||||
return possibilities;
|
||||
}
|
||||
|
||||
KList<IrisDimension> filtered = new KList<>();
|
||||
for (IrisDimension dimension : possibilities) {
|
||||
if (dimension != null && dimension.getLoadKey() != null) {
|
||||
String key = dimension.getLoadKey().toLowerCase(Locale.ROOT);
|
||||
if (key.startsWith(normalizedInput)) {
|
||||
filtered.add(dimension);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return filtered;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRandomDefault() {
|
||||
return "dimension";
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
package art.arcane.iris.util.decree.handlers;
|
||||
|
||||
import art.arcane.volmlib.util.decree.handlers.base.DoubleHandlerBase;
|
||||
import art.arcane.iris.util.decree.DecreeParameterHandler;
|
||||
|
||||
public class DoubleHandler extends DoubleHandlerBase implements DecreeParameterHandler<Double> {
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
package art.arcane.iris.util.decree.handlers;
|
||||
|
||||
import art.arcane.volmlib.util.decree.handlers.base.FloatHandlerBase;
|
||||
import art.arcane.iris.util.decree.DecreeParameterHandler;
|
||||
|
||||
public class FloatHandler extends FloatHandlerBase implements DecreeParameterHandler<Float> {
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
package art.arcane.iris.util.decree.handlers;
|
||||
|
||||
import art.arcane.volmlib.util.decree.handlers.base.IntegerHandlerBase;
|
||||
import art.arcane.iris.util.decree.DecreeParameterHandler;
|
||||
|
||||
public class IntegerHandler extends IntegerHandlerBase implements DecreeParameterHandler<Integer> {
|
||||
}
|
||||
@@ -1,33 +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 art.arcane.iris.util.decree.handlers;
|
||||
|
||||
import art.arcane.iris.engine.object.IrisJigsawPiece;
|
||||
import art.arcane.iris.util.decree.specialhandlers.RegistrantHandler;
|
||||
|
||||
public class JigsawPieceHandler extends RegistrantHandler<IrisJigsawPiece> {
|
||||
public JigsawPieceHandler() {
|
||||
super(IrisJigsawPiece.class, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRandomDefault() {
|
||||
return "jigsaw-piece";
|
||||
}
|
||||
}
|
||||
@@ -1,33 +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 art.arcane.iris.util.decree.handlers;
|
||||
|
||||
import art.arcane.iris.engine.object.IrisJigsawPool;
|
||||
import art.arcane.iris.util.decree.specialhandlers.RegistrantHandler;
|
||||
|
||||
public class JigsawPoolHandler extends RegistrantHandler<IrisJigsawPool> {
|
||||
public JigsawPoolHandler() {
|
||||
super(IrisJigsawPool.class, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRandomDefault() {
|
||||
return "jigsaw-pool";
|
||||
}
|
||||
}
|
||||
@@ -1,33 +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 art.arcane.iris.util.decree.handlers;
|
||||
|
||||
import art.arcane.iris.engine.object.IrisJigsawStructure;
|
||||
import art.arcane.iris.util.decree.specialhandlers.RegistrantHandler;
|
||||
|
||||
public class JigsawStructureHandler extends RegistrantHandler<IrisJigsawStructure> {
|
||||
public JigsawStructureHandler() {
|
||||
super(IrisJigsawStructure.class, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRandomDefault() {
|
||||
return "jigsaw-structure";
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
package art.arcane.iris.util.decree.handlers;
|
||||
|
||||
import art.arcane.volmlib.util.decree.handlers.base.LongHandlerBase;
|
||||
import art.arcane.iris.util.decree.DecreeParameterHandler;
|
||||
|
||||
public class LongHandler extends LongHandlerBase implements DecreeParameterHandler<Long> {
|
||||
}
|
||||
@@ -1,33 +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 art.arcane.iris.util.decree.handlers;
|
||||
|
||||
import art.arcane.iris.engine.object.IrisScript;
|
||||
import art.arcane.iris.util.decree.specialhandlers.RegistrantHandler;
|
||||
|
||||
public class ScriptHandler extends RegistrantHandler<IrisScript> {
|
||||
public ScriptHandler() {
|
||||
super(IrisScript.class, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRandomDefault() {
|
||||
return "script";
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
package art.arcane.iris.util.decree.handlers;
|
||||
|
||||
import art.arcane.volmlib.util.decree.handlers.base.ShortHandlerBase;
|
||||
import art.arcane.iris.util.decree.DecreeParameterHandler;
|
||||
|
||||
public class ShortHandler extends ShortHandlerBase implements DecreeParameterHandler<Short> {
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
package art.arcane.iris.util.decree.handlers;
|
||||
|
||||
import art.arcane.volmlib.util.decree.handlers.StringHandlerBase;
|
||||
import art.arcane.iris.util.decree.DecreeParameterHandler;
|
||||
|
||||
public class StringHandler extends StringHandlerBase implements DecreeParameterHandler<String> {
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
package art.arcane.iris.util.decree.handlers;
|
||||
|
||||
import art.arcane.iris.util.decree.DecreeContext;
|
||||
import art.arcane.iris.util.decree.DecreeParameterHandler;
|
||||
import art.arcane.iris.util.decree.DecreeSystem;
|
||||
import art.arcane.volmlib.util.decree.handlers.base.VectorHandlerBase;
|
||||
import art.arcane.volmlib.util.format.Form;
|
||||
import org.bukkit.FluidCollisionMode;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class VectorHandler extends VectorHandlerBase implements DecreeParameterHandler<Vector> {
|
||||
@Override
|
||||
protected boolean isSenderPlayer() {
|
||||
return DecreeContext.get().isPlayer();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Vector getSenderVector() {
|
||||
return DecreeContext.get().player().getLocation().toVector();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Vector getLookVector() {
|
||||
return DecreeContext.get().player().getTargetBlockExact(256, FluidCollisionMode.NEVER).getLocation().toVector();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<?> playerPossibilities(String query) {
|
||||
return DecreeSystem.getHandler(Player.class).getPossibilities(query);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String format(double value) {
|
||||
return Form.f(value, 2);
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package art.arcane.iris.util.decree.handlers;
|
||||
|
||||
import art.arcane.volmlib.util.decree.handlers.base.WorldHandlerBase;
|
||||
import art.arcane.iris.util.decree.DecreeParameterHandler;
|
||||
import org.bukkit.World;
|
||||
|
||||
public class WorldHandler extends WorldHandlerBase implements DecreeParameterHandler<World> {
|
||||
@Override
|
||||
protected String excludedPrefix() {
|
||||
return "iris/";
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
package art.arcane.iris.util.decree.specialhandlers;
|
||||
|
||||
import art.arcane.volmlib.util.decree.handlers.base.DummyHandlerBase;
|
||||
import art.arcane.iris.util.decree.DecreeParameterHandler;
|
||||
|
||||
public class DummyHandler extends DummyHandlerBase implements DecreeParameterHandler<Object> {
|
||||
}
|
||||
@@ -1,86 +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 art.arcane.iris.util.decree.specialhandlers;
|
||||
|
||||
import art.arcane.iris.core.IrisSettings;
|
||||
import art.arcane.iris.core.tools.IrisToolbelt;
|
||||
import art.arcane.iris.engine.object.IrisDimension;
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
import art.arcane.volmlib.util.decree.exceptions.DecreeParsingException;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
public class NullableDimensionHandler extends RegistrantHandler<IrisDimension> {
|
||||
public NullableDimensionHandler() {
|
||||
super(IrisDimension.class, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IrisDimension parse(String in, boolean force) throws DecreeParsingException {
|
||||
String key = in.trim();
|
||||
if (key.equalsIgnoreCase("default")) {
|
||||
key = IrisSettings.get().getGenerator().getDefaultWorldType();
|
||||
}
|
||||
|
||||
try {
|
||||
return super.parse(key, force);
|
||||
} catch (DecreeParsingException ignored) {
|
||||
String normalized = key.toLowerCase(Locale.ROOT);
|
||||
IrisDimension resolved = IrisToolbelt.getDimension(normalized);
|
||||
if (resolved != null) {
|
||||
return resolved;
|
||||
}
|
||||
|
||||
if (!normalized.equals(key)) {
|
||||
resolved = IrisToolbelt.getDimension(key);
|
||||
if (resolved != null) {
|
||||
return resolved;
|
||||
}
|
||||
}
|
||||
|
||||
throw ignored;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public KList<IrisDimension> getPossibilities(String input) {
|
||||
KList<IrisDimension> possibilities = super.getPossibilities();
|
||||
String normalizedInput = input == null ? "" : input.trim().toLowerCase(Locale.ROOT);
|
||||
if (normalizedInput.isEmpty()) {
|
||||
return possibilities;
|
||||
}
|
||||
|
||||
KList<IrisDimension> filtered = new KList<>();
|
||||
for (IrisDimension dimension : possibilities) {
|
||||
if (dimension != null && dimension.getLoadKey() != null) {
|
||||
String key = dimension.getLoadKey().toLowerCase(Locale.ROOT);
|
||||
if (key.startsWith(normalizedInput)) {
|
||||
filtered.add(dimension);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return filtered;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRandomDefault() {
|
||||
return "dimension";
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package art.arcane.iris.util.decree.specialhandlers;
|
||||
|
||||
import art.arcane.volmlib.util.decree.handlers.base.NullablePlayerHandlerBase;
|
||||
import art.arcane.volmlib.util.decree.exceptions.DecreeParsingException;
|
||||
import art.arcane.iris.util.decree.DecreeParameterHandler;
|
||||
import art.arcane.iris.util.decree.handlers.PlayerHandler;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class NullablePlayerHandler extends PlayerHandler implements DecreeParameterHandler<Player> {
|
||||
@Override
|
||||
public Player parse(String in, boolean force) throws DecreeParsingException {
|
||||
return NullablePlayerHandlerBase.parseNullable(this, in);
|
||||
}
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
package art.arcane.iris.util.decree.specialhandlers;
|
||||
|
||||
import art.arcane.iris.Iris;
|
||||
import art.arcane.iris.core.loader.IrisData;
|
||||
import art.arcane.iris.core.loader.IrisRegistrant;
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
import art.arcane.iris.util.decree.DecreeParameterHandler;
|
||||
import art.arcane.volmlib.util.decree.exceptions.DecreeParsingException;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public abstract class RegistrantHandler<T extends IrisRegistrant> implements DecreeParameterHandler<T> {
|
||||
private final Class<T> type;
|
||||
private final String name;
|
||||
private final boolean nullable;
|
||||
|
||||
public RegistrantHandler(Class<T> type, boolean nullable) {
|
||||
this.type = type;
|
||||
this.name = type.getSimpleName().replaceFirst("Iris", "");
|
||||
this.nullable = nullable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KList<T> getPossibilities() {
|
||||
KList<T> p = new KList<>();
|
||||
Set<String> known = new HashSet<>();
|
||||
IrisData data = data();
|
||||
if (data != null) {
|
||||
for (T j : data.getLoader(type).loadAll(data.getLoader(type).getPossibleKeys())) {
|
||||
known.add(j.getLoadKey());
|
||||
p.add(j);
|
||||
}
|
||||
}
|
||||
|
||||
//noinspection ConstantConditions
|
||||
for (File i : Iris.instance.getDataFolder("packs").listFiles()) {
|
||||
if (i.isDirectory()) {
|
||||
data = IrisData.get(i);
|
||||
for (T j : data.getLoader(type).loadAll(data.getLoader(type).getPossibleKeys())) {
|
||||
if (known.add(j.getLoadKey()))
|
||||
p.add(j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(T t) {
|
||||
return t != null ? t.getLoadKey() : "null";
|
||||
}
|
||||
|
||||
@Override
|
||||
public T parse(String in, boolean force) throws DecreeParsingException {
|
||||
if (in.equals("null") && nullable) {
|
||||
return null;
|
||||
}
|
||||
KList<T> options = getPossibilities(in);
|
||||
if (options.isEmpty()) {
|
||||
throw new DecreeParsingException("Unable to find " + name + " \"" + in + "\"");
|
||||
}
|
||||
|
||||
return options.stream()
|
||||
.filter((i) -> toString(i).equalsIgnoreCase(in))
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new DecreeParsingException("Unable to filter which " + name + " \"" + in + "\""));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(Class<?> type) {
|
||||
return type.equals(this.type);
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package art.arcane.iris.util.inventorygui;
|
||||
|
||||
public enum ElementEvent {
|
||||
LEFT,
|
||||
RIGHT,
|
||||
SHIFT_LEFT,
|
||||
SHIFT_RIGHT,
|
||||
DRAG_INTO,
|
||||
OTHER_DRAG_INTO;
|
||||
|
||||
public art.arcane.volmlib.util.inventorygui.ElementEvent toShared() {
|
||||
return art.arcane.volmlib.util.inventorygui.ElementEvent.valueOf(name());
|
||||
}
|
||||
|
||||
public static ElementEvent fromShared(art.arcane.volmlib.util.inventorygui.ElementEvent event) {
|
||||
return valueOf(event.name());
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
package art.arcane.iris.util.inventorygui;
|
||||
|
||||
import org.bukkit.event.inventory.InventoryType;
|
||||
|
||||
public enum WindowResolution {
|
||||
W9_H6(9, 6, InventoryType.CHEST),
|
||||
W5_H1(5, 1, InventoryType.HOPPER),
|
||||
W3_H3(3, 3, InventoryType.DROPPER);
|
||||
|
||||
private final int width;
|
||||
private final int maxHeight;
|
||||
private final InventoryType type;
|
||||
|
||||
WindowResolution(int w, int h, InventoryType type) {
|
||||
this.width = w;
|
||||
this.maxHeight = h;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public int getMaxWidthOffset() {
|
||||
return (getWidth() - 1) / 2;
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
public int getMaxHeight() {
|
||||
return maxHeight;
|
||||
}
|
||||
|
||||
public InventoryType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public art.arcane.volmlib.util.inventorygui.WindowResolution toShared() {
|
||||
return art.arcane.volmlib.util.inventorygui.WindowResolution.valueOf(name());
|
||||
}
|
||||
|
||||
public static WindowResolution fromShared(art.arcane.volmlib.util.inventorygui.WindowResolution resolution) {
|
||||
return valueOf(resolution.name());
|
||||
}
|
||||
}
|
||||
@@ -1,162 +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 art.arcane.iris.util.mantle;
|
||||
|
||||
import art.arcane.volmlib.util.documentation.BlockCoordinates;
|
||||
import art.arcane.volmlib.util.documentation.ChunkCoordinates;
|
||||
import art.arcane.volmlib.util.function.Consumer4;
|
||||
import art.arcane.iris.Iris;
|
||||
import art.arcane.iris.core.IrisSettings;
|
||||
import art.arcane.iris.core.tools.IrisToolbelt;
|
||||
import art.arcane.iris.engine.framework.Engine;
|
||||
import art.arcane.iris.engine.mantle.EngineMantle;
|
||||
import art.arcane.iris.engine.mantle.MantleWriter;
|
||||
import art.arcane.volmlib.util.format.Form;
|
||||
import art.arcane.volmlib.util.io.IO;
|
||||
import art.arcane.iris.util.mantle.io.IOWorker;
|
||||
import art.arcane.iris.util.matter.Matter;
|
||||
import art.arcane.iris.util.matter.MatterSlice;
|
||||
import art.arcane.iris.util.parallel.HyperLock;
|
||||
import art.arcane.iris.util.parallel.MultiBurst;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Iris adapter over shared mantle runtime.
|
||||
*/
|
||||
public class Mantle extends art.arcane.volmlib.util.mantle.Mantle<TectonicPlate, MantleChunk> {
|
||||
private static final int LOCK_SIZE = Short.MAX_VALUE;
|
||||
|
||||
@BlockCoordinates
|
||||
public Mantle(File dataFolder, int worldHeight) {
|
||||
super(dataFolder, worldHeight, LOCK_SIZE, new HyperLock(), MultiBurst.ioBurst, new IOWorkerRegionIO(dataFolder, worldHeight));
|
||||
}
|
||||
|
||||
@ChunkCoordinates
|
||||
public MantleWriter write(EngineMantle engineMantle, int x, int z, int radius, boolean multicore) {
|
||||
return new MantleWriter(engineMantle, this, x, z, radius, multicore);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TectonicPlate createRegion(int x, int z) {
|
||||
return new TectonicPlate(getWorldHeight(), x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T> void setChunkValue(MantleChunk chunk, int x, int y, int z, T value) {
|
||||
Matter matter = chunk.getOrCreate(y >> 4);
|
||||
matter.slice(matter.getClass(value)).set(x & 15, y & 15, z & 15, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T> void removeChunkValue(MantleChunk chunk, int x, int y, int z, Class<T> type) {
|
||||
Matter matter = chunk.getOrCreate(y >> 4);
|
||||
matter.slice(type).set(x & 15, y & 15, z & 15, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected <T> T getChunkValue(MantleChunk chunk, int x, int y, int z, Class<T> type) {
|
||||
return (T) chunk.getOrCreate(y >> 4)
|
||||
.slice(type)
|
||||
.get(x & 15, y & 15, z & 15);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T> void iterateChunkValues(MantleChunk chunk, Class<T> type, Consumer4<Integer, Integer, Integer, T> iterator) {
|
||||
chunk.iterate(type, iterator);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void deleteChunkSlice(MantleChunk chunk, Class<?> type) {
|
||||
chunk.deleteSlices(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldRetainSlice(Class<?> sliceType) {
|
||||
return IrisToolbelt.isRetainingMantleDataForSlice(sliceType.getCanonicalName());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String formatDuration(double millis) {
|
||||
return Form.duration(millis, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDebug(String message) {
|
||||
Iris.debug(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onWarn(String message) {
|
||||
Iris.warn(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onError(Throwable throwable) {
|
||||
Iris.reportError(throwable);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void deleteTemporaryFiles() {
|
||||
IO.delete(new File(getDataFolder(), ".tmp"));
|
||||
}
|
||||
|
||||
public void set(int x, int y, int z, Matter matter) {
|
||||
for (MatterSlice<?> slice : matter.getSliceMap().values()) {
|
||||
slice.iterate((mx, my, mz, v) -> set(mx + x, my + y, mz + z, v));
|
||||
}
|
||||
}
|
||||
|
||||
public <T> void set(int x, int y, int z, MatterSlice<T> slice) {
|
||||
if (slice.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
slice.iterateSync((xx, yy, zz, t) -> set(x + xx, y + yy, z + zz, t));
|
||||
}
|
||||
|
||||
public boolean shouldReduce(Engine engine) {
|
||||
return !engine.isStudio() || IrisSettings.get().getPerformance().isTrimMantleInStudio();
|
||||
}
|
||||
|
||||
private static final class IOWorkerRegionIO implements RegionIO<TectonicPlate> {
|
||||
private final IOWorker worker;
|
||||
|
||||
private IOWorkerRegionIO(File root, int worldHeight) {
|
||||
this.worker = new IOWorker(root, worldHeight);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TectonicPlate read(String name) throws IOException {
|
||||
return worker.read(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(String name, TectonicPlate region) throws IOException {
|
||||
worker.write(name, region);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
worker.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,140 +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 art.arcane.iris.util.mantle;
|
||||
|
||||
import art.arcane.volmlib.util.documentation.ChunkCoordinates;
|
||||
import art.arcane.volmlib.util.documentation.ChunkRelativeBlockCoordinates;
|
||||
import art.arcane.volmlib.util.function.Consumer4;
|
||||
import art.arcane.volmlib.util.io.CountingDataInputStream;
|
||||
import art.arcane.iris.Iris;
|
||||
import art.arcane.iris.core.tools.IrisToolbelt;
|
||||
import art.arcane.iris.util.matter.IrisMatter;
|
||||
import art.arcane.iris.util.matter.Matter;
|
||||
import art.arcane.iris.util.matter.MatterSlice;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Represents a mantle chunk. Mantle chunks contain sections of matter (see matter api)
|
||||
* Mantle Chunks are fully atomic & thread safe
|
||||
*/
|
||||
public class MantleChunk extends art.arcane.volmlib.util.mantle.MantleChunk<Matter> {
|
||||
@ChunkCoordinates
|
||||
public MantleChunk(int sectionHeight, int x, int z) {
|
||||
super(sectionHeight, x, z);
|
||||
}
|
||||
|
||||
public MantleChunk(int version, int sectionHeight, CountingDataInputStream din) throws IOException {
|
||||
super(version, sectionHeight, din);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBeforeReadSection(int index) {
|
||||
Iris.addPanic("read.section", "Section[" + index + "]");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onReadSectionFailure(int index, long start, long end, CountingDataInputStream din, IOException e) {
|
||||
Iris.error("Failed to read chunk section, skipping it.");
|
||||
Iris.addPanic("read.byte.range", start + " " + end);
|
||||
Iris.addPanic("read.byte.current", din.count() + "");
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
Iris.panic();
|
||||
TectonicPlate.addError();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Matter createSection() {
|
||||
return new IrisMatter(16, 16, 16);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Matter readSection(CountingDataInputStream din) throws IOException {
|
||||
return Matter.readDin(din);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeSection(Matter section, DataOutputStream dos) throws IOException {
|
||||
section.writeDos(dos);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void trimSection(Matter section) {
|
||||
section.trimSlices();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isSectionEmpty(Matter section) {
|
||||
return section.getSliceMap().isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MantleChunk use() {
|
||||
super.use();
|
||||
return this;
|
||||
}
|
||||
|
||||
public void copyFrom(MantleChunk chunk) {
|
||||
super.copyFrom(chunk);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@ChunkRelativeBlockCoordinates
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T get(int x, int y, int z, Class<T> type) {
|
||||
return (T) getOrCreate(y >> 4)
|
||||
.slice(type)
|
||||
.get(x & 15, y & 15, z & 15);
|
||||
}
|
||||
|
||||
public <T> void iterate(Class<T> type, Consumer4<Integer, Integer, Integer, T> iterator) {
|
||||
for (int i = 0; i < sectionCount(); i++) {
|
||||
int bs = (i << 4);
|
||||
Matter matter = get(i);
|
||||
|
||||
if (matter != null) {
|
||||
MatterSlice<T> t = matter.getSlice(type);
|
||||
|
||||
if (t != null) {
|
||||
t.iterateSync((a, b, c, f) -> iterator.accept(a, b + bs, c, f));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteSlices(Class<?> c) {
|
||||
if (IrisToolbelt.isRetainingMantleDataForSlice(c.getCanonicalName())) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < sectionCount(); i++) {
|
||||
Matter m = get(i);
|
||||
if (m != null && m.hasSlice(c)) {
|
||||
m.deleteSlice(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void trimSlices() {
|
||||
trimSections();
|
||||
}
|
||||
}
|
||||
@@ -1,96 +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 art.arcane.iris.util.mantle;
|
||||
|
||||
import art.arcane.volmlib.util.io.CountingDataInputStream;
|
||||
import art.arcane.iris.Iris;
|
||||
import art.arcane.iris.engine.EnginePanic;
|
||||
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Tectonic Plates are essentially representations of regions in minecraft.
|
||||
* Tectonic Plates are fully atomic & thread safe
|
||||
*/
|
||||
public class TectonicPlate extends art.arcane.volmlib.util.mantle.TectonicPlate<MantleChunk> {
|
||||
public static final int MISSING = art.arcane.volmlib.util.mantle.TectonicPlate.MISSING;
|
||||
public static final int CURRENT = art.arcane.volmlib.util.mantle.TectonicPlate.CURRENT;
|
||||
|
||||
public TectonicPlate(int worldHeight, int x, int z) {
|
||||
super(worldHeight, x, z);
|
||||
}
|
||||
|
||||
public TectonicPlate(int worldHeight, CountingDataInputStream din, boolean versioned) throws IOException {
|
||||
super(worldHeight, din, versioned);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void beforeReadChunk(int index) {
|
||||
Iris.addPanic("read-chunk", "Chunk[" + index + "]");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void afterReadChunk(int index) {
|
||||
EnginePanic.saveLast();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onReadChunkFailure(int index, long start, long end, CountingDataInputStream din, Throwable e) {
|
||||
Iris.error("Failed to read chunk, creating a new chunk instead.");
|
||||
Iris.addPanic("read.byte.range", start + " " + end);
|
||||
Iris.addPanic("read.byte.current", din.count() + "");
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
Iris.panic();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MantleChunk readChunk(int version, int sectionHeight, CountingDataInputStream din) throws IOException {
|
||||
return new MantleChunk(version, sectionHeight, din);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MantleChunk createChunk(int sectionHeight, int x, int z) {
|
||||
return new MantleChunk(sectionHeight, x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isChunkInUse(MantleChunk chunk) {
|
||||
return chunk.inUse();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void closeChunk(MantleChunk chunk) {
|
||||
chunk.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeChunk(MantleChunk chunk, DataOutputStream dos) throws IOException {
|
||||
chunk.write(dos);
|
||||
}
|
||||
|
||||
public static void addError() {
|
||||
art.arcane.volmlib.util.mantle.TectonicPlate.addError();
|
||||
}
|
||||
|
||||
public static boolean hasError() {
|
||||
return art.arcane.volmlib.util.mantle.TectonicPlate.hasError();
|
||||
}
|
||||
}
|
||||
@@ -1,87 +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 art.arcane.iris.util.mantle.io;
|
||||
|
||||
import art.arcane.volmlib.util.mantle.io.IOWorkerCodecSupport;
|
||||
import art.arcane.volmlib.util.mantle.io.IOWorkerRuntimeSupport;
|
||||
import art.arcane.volmlib.util.mantle.io.IOWorkerSupport;
|
||||
import art.arcane.iris.Iris;
|
||||
import art.arcane.iris.core.IrisSettings;
|
||||
import art.arcane.iris.util.format.C;
|
||||
import art.arcane.volmlib.util.format.Form;
|
||||
import art.arcane.iris.util.mantle.TectonicPlate;
|
||||
import art.arcane.volmlib.util.scheduling.PrecisionStopwatch;
|
||||
import net.jpountz.lz4.LZ4BlockInputStream;
|
||||
import net.jpountz.lz4.LZ4BlockOutputStream;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public class IOWorker {
|
||||
private static final IOWorkerCodecSupport LZ4_CODEC = new IOWorkerCodecSupport() {
|
||||
@Override
|
||||
public InputStream decode(InputStream input) throws IOException {
|
||||
return new LZ4BlockInputStream(input);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OutputStream encode(OutputStream output) throws IOException {
|
||||
return new LZ4BlockOutputStream(output);
|
||||
}
|
||||
};
|
||||
|
||||
private final int worldHeight;
|
||||
private final IOWorkerSupport support;
|
||||
private final IOWorkerRuntimeSupport runtime;
|
||||
|
||||
public IOWorker(File root, int worldHeight) {
|
||||
this.worldHeight = worldHeight;
|
||||
this.support = new IOWorkerSupport(root, 128, (name, millis) ->
|
||||
Iris.debug("Acquired Channel for " + C.DARK_GREEN + name + C.RED + " in " + Form.duration(millis, 2))
|
||||
);
|
||||
this.runtime = new IOWorkerRuntimeSupport(support, LZ4_CODEC);
|
||||
}
|
||||
|
||||
public TectonicPlate read(final String name) throws IOException {
|
||||
PrecisionStopwatch p = PrecisionStopwatch.start();
|
||||
try {
|
||||
return runtime.read(name, (regionName, in) -> new TectonicPlate(worldHeight, in, regionName.startsWith("pv.")));
|
||||
} finally {
|
||||
if (TectonicPlate.hasError() && IrisSettings.get().getGeneral().isDumpMantleOnError()) {
|
||||
File dump = Iris.instance.getDataFolder("dump", name + ".bin");
|
||||
runtime.dumpDecoded(name, dump.toPath());
|
||||
} else {
|
||||
Iris.debug("Read Tectonic Plate " + C.DARK_GREEN + name + C.RED + " in " + Form.duration(p.getMilliseconds(), 2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void write(final String name, final TectonicPlate plate) throws IOException {
|
||||
PrecisionStopwatch p = PrecisionStopwatch.start();
|
||||
runtime.writeAtomically(name, "iris", ".bin", plate, TectonicPlate::write);
|
||||
|
||||
Iris.debug("Saved Tectonic Plate " + C.DARK_GREEN + name + C.RED + " in " + Form.duration(p.getMilliseconds(), 2));
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
support.close();
|
||||
}
|
||||
}
|
||||
@@ -1,158 +0,0 @@
|
||||
package art.arcane.iris.util.math;
|
||||
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
import art.arcane.volmlib.util.data.Cuboid.CuboidDirection;
|
||||
import org.bukkit.Axis;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
public enum Direction {
|
||||
U(art.arcane.volmlib.util.math.DirectionBasis.U, CuboidDirection.Up),
|
||||
D(art.arcane.volmlib.util.math.DirectionBasis.D, CuboidDirection.Down),
|
||||
N(art.arcane.volmlib.util.math.DirectionBasis.N, CuboidDirection.North),
|
||||
S(art.arcane.volmlib.util.math.DirectionBasis.S, CuboidDirection.South),
|
||||
E(art.arcane.volmlib.util.math.DirectionBasis.E, CuboidDirection.East),
|
||||
W(art.arcane.volmlib.util.math.DirectionBasis.W, CuboidDirection.West);
|
||||
|
||||
private final art.arcane.volmlib.util.math.DirectionBasis basis;
|
||||
private final CuboidDirection f;
|
||||
|
||||
Direction(art.arcane.volmlib.util.math.DirectionBasis basis, CuboidDirection f) {
|
||||
this.basis = basis;
|
||||
this.f = f;
|
||||
}
|
||||
|
||||
private static Direction fromBasis(art.arcane.volmlib.util.math.DirectionBasis b) {
|
||||
if (b == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return switch (b) {
|
||||
case U -> U;
|
||||
case D -> D;
|
||||
case N -> N;
|
||||
case S -> S;
|
||||
case E -> E;
|
||||
case W -> W;
|
||||
};
|
||||
}
|
||||
|
||||
public static Direction getDirection(BlockFace f) {
|
||||
return fromBasis(art.arcane.volmlib.util.math.DirectionBasis.getDirection(f));
|
||||
}
|
||||
|
||||
public static Direction closest(Vector v) {
|
||||
return fromBasis(art.arcane.volmlib.util.math.DirectionBasis.closest(v));
|
||||
}
|
||||
|
||||
public static Direction closest(Vector v, Direction... d) {
|
||||
double m = Double.MAX_VALUE;
|
||||
Direction s = null;
|
||||
|
||||
for (Direction i : d) {
|
||||
Vector x = i.toVector();
|
||||
double g = x.distance(v);
|
||||
|
||||
if (g < m) {
|
||||
m = g;
|
||||
s = i;
|
||||
}
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
public static Direction closest(Vector v, KList<Direction> d) {
|
||||
double m = Double.MAX_VALUE;
|
||||
Direction s = null;
|
||||
|
||||
for (Direction i : d) {
|
||||
Vector x = i.toVector();
|
||||
double g = x.distance(v);
|
||||
|
||||
if (g < m) {
|
||||
m = g;
|
||||
s = i;
|
||||
}
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
public static KList<Direction> news() {
|
||||
return new KList<Direction>().add(N, E, W, S);
|
||||
}
|
||||
|
||||
public static Direction getDirection(Vector v) {
|
||||
return fromBasis(art.arcane.volmlib.util.math.DirectionBasis.getDirection(v));
|
||||
}
|
||||
|
||||
public static KList<Direction> udnews() {
|
||||
return new KList<Direction>().add(U, D, N, E, W, S);
|
||||
}
|
||||
|
||||
public static Direction fromByte(byte b) {
|
||||
return fromBasis(art.arcane.volmlib.util.math.DirectionBasis.fromByte(b));
|
||||
}
|
||||
|
||||
public static void calculatePermutations() {
|
||||
art.arcane.volmlib.util.math.DirectionBasis.calculatePermutations();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return basis.toString();
|
||||
}
|
||||
|
||||
public boolean isVertical() {
|
||||
return basis.isVertical();
|
||||
}
|
||||
|
||||
public Vector toVector() {
|
||||
return basis.toVector();
|
||||
}
|
||||
|
||||
public boolean isCrooked(Direction to) {
|
||||
if (equals(to.reverse())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !equals(to);
|
||||
}
|
||||
|
||||
public Vector angle(Vector initial, Direction d) {
|
||||
return basis.angle(initial, d.basis);
|
||||
}
|
||||
|
||||
public Direction reverse() {
|
||||
return fromBasis(basis.reverse());
|
||||
}
|
||||
|
||||
public int x() {
|
||||
return basis.x();
|
||||
}
|
||||
|
||||
public int y() {
|
||||
return basis.y();
|
||||
}
|
||||
|
||||
public int z() {
|
||||
return basis.z();
|
||||
}
|
||||
|
||||
public CuboidDirection f() {
|
||||
return f;
|
||||
}
|
||||
|
||||
public byte byteValue() {
|
||||
return basis.byteValue();
|
||||
}
|
||||
|
||||
public BlockFace getFace() {
|
||||
return basis.getFace();
|
||||
}
|
||||
|
||||
public Axis getAxis() {
|
||||
return basis.getAxis();
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
package art.arcane.iris.util.math;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
public class Spiral implements Iterable<Position2> {
|
||||
private final Position2 start;
|
||||
private final long max;
|
||||
private final art.arcane.volmlib.util.math.Spiral delegate;
|
||||
|
||||
public Spiral(Position2 start, long max) {
|
||||
this.start = start;
|
||||
this.max = max;
|
||||
this.delegate = new art.arcane.volmlib.util.math.Spiral(start, max);
|
||||
}
|
||||
|
||||
public static Position2 next(Position2 p) {
|
||||
art.arcane.volmlib.util.math.Position2 n = art.arcane.volmlib.util.math.Spiral.next(p);
|
||||
return new Position2(n.getX(), n.getZ());
|
||||
}
|
||||
|
||||
public static Spiral from(Position2 p, long iterations) {
|
||||
return new Spiral(p, iterations);
|
||||
}
|
||||
|
||||
public Position2 getStart() {
|
||||
return start;
|
||||
}
|
||||
|
||||
public long getMax() {
|
||||
return max;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Iterator<Position2> iterator() {
|
||||
Iterator<art.arcane.volmlib.util.math.Position2> it = delegate.iterator();
|
||||
return new Iterator<>() {
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return it.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position2 next() {
|
||||
art.arcane.volmlib.util.math.Position2 p = it.next();
|
||||
return new Position2(p.getX(), p.getZ());
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package art.arcane.iris.util.math;
|
||||
|
||||
import org.bukkit.util.BlockVector;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class Vector3i extends BlockVector {
|
||||
public Vector3i(int x, int y, int z) {
|
||||
super(x, y, z);
|
||||
}
|
||||
|
||||
public Vector3i(Vector vec) {
|
||||
super(vec);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Vector3i clone() {
|
||||
return (Vector3i) super.clone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return (int) x ^ ((int) z << 12) ^ ((int) y << 24);
|
||||
}
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
package art.arcane.iris.util.math;
|
||||
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
public class VectorMath extends art.arcane.volmlib.util.math.VectorMath {
|
||||
public static Vector rotate(Direction current, Direction to, Vector v) {
|
||||
if (current.equals(to)) {
|
||||
return v;
|
||||
} else if (current.equals(to.reverse())) {
|
||||
if (current.isVertical()) {
|
||||
return new Vector(v.getX(), -v.getY(), v.getZ());
|
||||
} else {
|
||||
return new Vector(-v.getX(), v.getY(), -v.getZ());
|
||||
}
|
||||
} else {
|
||||
Vector c = current.toVector().clone().add(to.toVector());
|
||||
|
||||
if (c.getX() == 0) {
|
||||
if (c.getY() != c.getZ()) {
|
||||
return rotate90CX(v);
|
||||
}
|
||||
|
||||
return rotate90CCX(v);
|
||||
} else if (c.getY() == 0) {
|
||||
if (c.getX() != c.getZ()) {
|
||||
return rotate90CY(v);
|
||||
}
|
||||
|
||||
return rotate90CCY(v);
|
||||
} else if (c.getZ() == 0) {
|
||||
if (c.getX() != c.getY()) {
|
||||
return rotate90CZ(v);
|
||||
}
|
||||
|
||||
return rotate90CCZ(v);
|
||||
}
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
public static Vector rotate(Direction current, Direction to, Vector v, int w, int h, int d) {
|
||||
if (current.equals(to)) {
|
||||
return v;
|
||||
} else if (current.equals(to.reverse())) {
|
||||
if (current.isVertical()) {
|
||||
return new Vector(v.getX(), -v.getY() + h, v.getZ());
|
||||
} else {
|
||||
return new Vector(-v.getX() + w, v.getY(), -v.getZ() + d);
|
||||
}
|
||||
} else {
|
||||
Vector c = current.toVector().clone().add(to.toVector());
|
||||
|
||||
if (c.getX() == 0) {
|
||||
if (c.getY() != c.getZ()) {
|
||||
return rotate90CX(v, d);
|
||||
}
|
||||
|
||||
return rotate90CCX(v, h);
|
||||
} else if (c.getY() == 0) {
|
||||
if (c.getX() != c.getZ()) {
|
||||
return rotate90CY(v, d);
|
||||
}
|
||||
|
||||
return rotate90CCY(v, w);
|
||||
} else if (c.getZ() == 0) {
|
||||
if (c.getX() != c.getY()) {
|
||||
return rotate90CZ(v, w);
|
||||
}
|
||||
|
||||
return rotate90CCZ(v, h);
|
||||
}
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
public static Vector getAxis(Direction current, Direction to) {
|
||||
if (current.equals(Direction.U) || current.equals(Direction.D)) {
|
||||
if (to.equals(Direction.U) || to.equals(Direction.D)) {
|
||||
return new Vector(1, 0, 0);
|
||||
} else {
|
||||
if (current.equals(Direction.N) || current.equals(Direction.S)) {
|
||||
return Direction.E.toVector();
|
||||
} else {
|
||||
return Direction.S.toVector();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new Vector(0, 1, 0);
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package art.arcane.iris.util.nbt.mca;
|
||||
|
||||
import art.arcane.volmlib.util.nbt.mca.MCAChunkSupport;
|
||||
import art.arcane.volmlib.util.nbt.tag.CompoundTag;
|
||||
import art.arcane.iris.Iris;
|
||||
import art.arcane.iris.core.nms.INMS;
|
||||
|
||||
import static org.bukkit.Bukkit.getServer;
|
||||
|
||||
public class Chunk extends MCAChunkSupport<Section> {
|
||||
public static final int DEFAULT_DATA_VERSION = 2730;
|
||||
|
||||
private static final Config<Section> CONFIG = new Config<>(
|
||||
DEFAULT_DATA_VERSION,
|
||||
() -> getServer().getWorlds().get(0).getMinHeight(),
|
||||
() -> getServer().getWorlds().get(0).getMaxHeight(),
|
||||
(min, max) -> INMS.get().newBiomeContainer(min, max),
|
||||
(min, max, data) -> INMS.get().newBiomeContainer(min, max, data),
|
||||
(sectionRoot, dataVersion, loadFlags) -> new Section(sectionRoot, dataVersion, loadFlags),
|
||||
Section::newSection,
|
||||
() -> "Iris Headless " + Iris.instance.getDescription().getVersion(),
|
||||
() -> "Iris " + Iris.instance.getDescription().getVersion()
|
||||
);
|
||||
|
||||
Chunk(int lastMCAUpdate) {
|
||||
super(lastMCAUpdate, CONFIG);
|
||||
}
|
||||
|
||||
public Chunk(CompoundTag data) {
|
||||
super(data, CONFIG);
|
||||
}
|
||||
|
||||
public static Chunk newChunk() {
|
||||
Chunk c = new Chunk(0);
|
||||
c.initializeNewChunk();
|
||||
return c;
|
||||
}
|
||||
|
||||
public static void injectIrisData(Chunk c) {
|
||||
c.injectNativeData("Iris");
|
||||
}
|
||||
}
|
||||
@@ -1,89 +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 art.arcane.iris.util.nbt.mca;
|
||||
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
import art.arcane.volmlib.util.nbt.mca.MCAFileSupport;
|
||||
import art.arcane.volmlib.util.nbt.mca.LoadFlags;
|
||||
import art.arcane.iris.util.math.Position2;
|
||||
import art.arcane.iris.util.scheduling.J;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
|
||||
@SuppressWarnings("ALL")
|
||||
public class MCAFile extends MCAFileSupport<Chunk> {
|
||||
|
||||
/**
|
||||
* The default chunk data version used when no custom version is supplied.
|
||||
*/
|
||||
public static final int DEFAULT_DATA_VERSION = 1628;
|
||||
|
||||
/**
|
||||
* MCAFile represents a world save file used by Minecraft to store world
|
||||
* data on the hard drive.
|
||||
* This constructor needs the x- and z-coordinates of the stored region,
|
||||
* which can usually be taken from the file name {@code r.x.z.mca}
|
||||
*
|
||||
* @param regionX The x-coordinate of this region.
|
||||
* @param regionZ The z-coordinate of this region.
|
||||
*/
|
||||
public MCAFile(int regionX, int regionZ) {
|
||||
super(regionX, regionZ, Chunk::newChunk, task -> J.a(task, 20));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the index of a chunk from its x- and z-coordinates in this region.
|
||||
* This works with absolute and relative coordinates.
|
||||
*
|
||||
* @param chunkX The x-coordinate of the chunk.
|
||||
* @param chunkZ The z-coordinate of the chunk.
|
||||
* @return The index of this chunk.
|
||||
*/
|
||||
public static int getChunkIndex(int chunkX, int chunkZ) {
|
||||
return MCAFileSupport.getChunkIndex(chunkX, chunkZ);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads an .mca file from a {@code RandomAccessFile} into this object.
|
||||
* This method does not perform any cleanups on the data.
|
||||
*
|
||||
* @param raf The {@code RandomAccessFile} to read from.
|
||||
* @throws IOException If something went wrong during deserialization.
|
||||
*/
|
||||
public void deserialize(RandomAccessFile raf) throws IOException {
|
||||
deserialize(raf, LoadFlags.ALL_DATA);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads an .mca file from a {@code RandomAccessFile} into this object.
|
||||
* This method does not perform any cleanups on the data.
|
||||
*
|
||||
* @param raf The {@code RandomAccessFile} to read from.
|
||||
* @param loadFlags A logical or of {@link LoadFlags} constants indicating what data should be loaded
|
||||
* @throws IOException If something went wrong during deserialization.
|
||||
*/
|
||||
public void deserialize(RandomAccessFile raf, long loadFlags) throws IOException {
|
||||
super.deserialize(raf, loadFlags, Chunk::new);
|
||||
}
|
||||
|
||||
public KList<Position2> samplePositions(RandomAccessFile raf) throws IOException {
|
||||
return super.samplePositions(raf, Position2::new);
|
||||
}
|
||||
}
|
||||
@@ -1,246 +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 art.arcane.iris.util.nbt.mca;
|
||||
|
||||
import art.arcane.iris.Iris;
|
||||
import art.arcane.iris.core.nms.INMS;
|
||||
import art.arcane.iris.engine.data.cache.Cache;
|
||||
import art.arcane.volmlib.util.collection.KMap;
|
||||
import art.arcane.volmlib.util.nbt.mca.MCAWorldStoreSupport;
|
||||
import art.arcane.volmlib.util.nbt.mca.MCAWorldRuntimeSupport;
|
||||
import art.arcane.volmlib.util.nbt.mca.NBTWorldSupport;
|
||||
import art.arcane.iris.util.data.B;
|
||||
import art.arcane.volmlib.util.math.M;
|
||||
import art.arcane.volmlib.util.nbt.tag.CompoundTag;
|
||||
import art.arcane.iris.util.parallel.HyperLock;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Map;
|
||||
|
||||
public class NBTWorld {
|
||||
private static final BlockData AIR = B.get("AIR");
|
||||
private static final NBTWorldSupport.BlockStateCodec<BlockData> BLOCK_STATE_CODEC = NBTWorldSupport.blockStateCodec(
|
||||
blockStateString -> B.getOrNull(blockStateString, true),
|
||||
B::getAir,
|
||||
blockData -> blockData.getAsString(true),
|
||||
blockData -> {
|
||||
NamespacedKey key = blockData.getMaterial().getKey();
|
||||
return key.getNamespace() + ":" + key.getKey();
|
||||
}
|
||||
);
|
||||
private static final Map<Biome, Integer> biomeIds = computeBiomeIDs();
|
||||
private final HyperLock hyperLock = new HyperLock();
|
||||
private final MCAWorldStoreSupport<MCAFile> regionStore;
|
||||
private final MCAWorldRuntimeSupport<MCAFile, Chunk, Section> worldRuntime;
|
||||
|
||||
public NBTWorld(File worldFolder) {
|
||||
this.regionStore = new MCAWorldStoreSupport<>(new MCAWorldStoreSupport.Config<>(
|
||||
NBTWorldSupport.keyCodec(Cache::key, Cache::keyX, Cache::keyZ),
|
||||
new MCAWorldStoreSupport.GridLock() {
|
||||
@Override
|
||||
public <T> T withResult(int x, int z, java.util.function.Supplier<T> supplier) {
|
||||
return hyperLock.withResult(x, z, supplier::get);
|
||||
}
|
||||
},
|
||||
MCAFile::new,
|
||||
NBTWorldSupport.regionFileResolver(worldFolder, "region"),
|
||||
MCAUtil::write,
|
||||
NBTWorldSupport.logger(
|
||||
Iris::info,
|
||||
Iris::debug,
|
||||
(message, error) -> {
|
||||
Iris.error(message);
|
||||
if (error != null) {
|
||||
error.printStackTrace();
|
||||
}
|
||||
}
|
||||
),
|
||||
M::ms,
|
||||
60000L,
|
||||
"Iris MCA Writer"
|
||||
));
|
||||
|
||||
this.worldRuntime = new MCAWorldRuntimeSupport<>(
|
||||
this::getMCA,
|
||||
new MCAWorldRuntimeSupport.ChunkAccess<>() {
|
||||
@Override
|
||||
public Chunk getChunk(MCAFile mca, int chunkX, int chunkZ) {
|
||||
return mca.getChunk(chunkX, chunkZ);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setChunk(MCAFile mca, int chunkX, int chunkZ, Chunk chunk) {
|
||||
mca.setChunk(chunkX, chunkZ, chunk);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Chunk createChunk() {
|
||||
return Chunk.newChunk();
|
||||
}
|
||||
},
|
||||
new MCAWorldRuntimeSupport.SectionAccess<>() {
|
||||
@Override
|
||||
public Section getSection(Chunk chunk, int sectionY) {
|
||||
return chunk.getSection(sectionY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSection(Chunk chunk, int sectionY, Section section) {
|
||||
chunk.setSection(sectionY, section);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Section createSection() {
|
||||
return Section.newSection();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public static BlockData getBlockData(CompoundTag tag) {
|
||||
return BLOCK_STATE_CODEC.decode(tag);
|
||||
}
|
||||
|
||||
public static CompoundTag getCompound(BlockData bd) {
|
||||
return BLOCK_STATE_CODEC.encode(bd);
|
||||
}
|
||||
|
||||
private static Map<Biome, Integer> computeBiomeIDs() {
|
||||
Map<Biome, Integer> biomeIds = new KMap<>();
|
||||
|
||||
for (Biome biome : Biome.values()) {
|
||||
if (!biome.name().equals("CUSTOM")) {
|
||||
biomeIds.put(biome, INMS.get().getBiomeId(biome));
|
||||
}
|
||||
}
|
||||
|
||||
return biomeIds;
|
||||
}
|
||||
|
||||
public void close() {
|
||||
regionStore.close();
|
||||
}
|
||||
|
||||
public void flushNow() {
|
||||
regionStore.flushNow();
|
||||
}
|
||||
|
||||
public void queueSaveUnload(int x, int z) {
|
||||
regionStore.queueSaveUnload(x, z);
|
||||
}
|
||||
|
||||
public void doSaveUnload(int x, int z) {
|
||||
regionStore.doSaveUnload(x, z);
|
||||
}
|
||||
|
||||
public void save() {
|
||||
regionStore.save();
|
||||
}
|
||||
|
||||
public void queueSave() {
|
||||
|
||||
}
|
||||
|
||||
public synchronized void unloadRegion(int x, int z) {
|
||||
regionStore.unloadRegion(x, z);
|
||||
}
|
||||
|
||||
public void saveRegion(int x, int z) {
|
||||
regionStore.saveRegion(x, z);
|
||||
}
|
||||
|
||||
public void saveRegion(int x, int z, MCAFile mca) {
|
||||
regionStore.saveRegion(x, z, mca);
|
||||
}
|
||||
|
||||
public boolean shouldUnload(int x, int z) {
|
||||
return regionStore.shouldUnload(x, z);
|
||||
}
|
||||
|
||||
public File getRegionFile(int x, int z) {
|
||||
return regionStore.getRegionFile(x, z);
|
||||
}
|
||||
|
||||
public BlockData getBlockData(int x, int y, int z) {
|
||||
try {
|
||||
CompoundTag tag = worldRuntime.getBlockStateTag(x, y, z);
|
||||
|
||||
if (tag == null) {
|
||||
return AIR;
|
||||
}
|
||||
|
||||
return getBlockData(tag);
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
|
||||
}
|
||||
return AIR;
|
||||
}
|
||||
|
||||
public void setBlockData(int x, int y, int z, BlockData data) {
|
||||
worldRuntime.setBlockStateTag(x, y, z, getCompound(data), false);
|
||||
}
|
||||
|
||||
public int getBiomeId(Biome b) {
|
||||
return biomeIds.get(b);
|
||||
}
|
||||
|
||||
public void setBiome(int x, int y, int z, Biome biome) {
|
||||
worldRuntime.setBiomeId(x, y, z, biomeIds.get(biome));
|
||||
}
|
||||
|
||||
public Section getChunkSection(int x, int y, int z) {
|
||||
return worldRuntime.getChunkSection(x, y, z);
|
||||
}
|
||||
|
||||
public Chunk getChunk(int x, int z) {
|
||||
return worldRuntime.getChunk(x, z);
|
||||
}
|
||||
|
||||
public Chunk getChunk(MCAFile mca, int x, int z) {
|
||||
return worldRuntime.getChunk(mca, x, z);
|
||||
}
|
||||
|
||||
public Chunk getNewChunk(MCAFile mca, int x, int z) {
|
||||
return worldRuntime.getNewChunk(mca, x, z);
|
||||
}
|
||||
|
||||
public long getIdleDuration(int x, int z) {
|
||||
return regionStore.getIdleDuration(x, z);
|
||||
}
|
||||
|
||||
public MCAFile getMCA(int x, int z) {
|
||||
return regionStore.getMCA(x, z);
|
||||
}
|
||||
|
||||
public MCAFile getMCAOrNull(int x, int z) {
|
||||
return regionStore.getMCAOrNull(x, z);
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return regionStore.size();
|
||||
}
|
||||
|
||||
public boolean isLoaded(int x, int z) {
|
||||
return regionStore.isLoaded(x, z);
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
package art.arcane.iris.util.parallel;
|
||||
|
||||
import art.arcane.iris.Iris;
|
||||
import art.arcane.volmlib.util.parallel.BurstExecutorSupport;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
public class BurstExecutor extends BurstExecutorSupport {
|
||||
public BurstExecutor(ExecutorService executor, int burstSizeEstimate) {
|
||||
super(executor, burstSizeEstimate, Iris::reportError);
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
package art.arcane.iris.util.parallel;
|
||||
|
||||
import art.arcane.iris.Iris;
|
||||
import art.arcane.volmlib.util.parallel.GridLockSupport;
|
||||
|
||||
public class GridLock extends GridLockSupport {
|
||||
public GridLock(int x, int z) {
|
||||
super(x, z, Iris::reportError);
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package art.arcane.iris.util.parallel;
|
||||
|
||||
import art.arcane.iris.Iris;
|
||||
import art.arcane.volmlib.util.parallel.HyperLockSupport;
|
||||
|
||||
public class HyperLock extends HyperLockSupport {
|
||||
public HyperLock() {
|
||||
this(1024, false);
|
||||
}
|
||||
|
||||
public HyperLock(int capacity) {
|
||||
this(capacity, false);
|
||||
}
|
||||
|
||||
public HyperLock(int capacity, boolean fair) {
|
||||
super(capacity, fair, Iris::warn, Iris::reportError);
|
||||
}
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
package art.arcane.iris.util.parallel;
|
||||
|
||||
import art.arcane.iris.Iris;
|
||||
import art.arcane.iris.core.IrisSettings;
|
||||
import art.arcane.volmlib.util.parallel.MultiBurstSupport;
|
||||
import art.arcane.volmlib.util.math.M;
|
||||
import kotlinx.coroutines.CoroutineDispatcher;
|
||||
import kotlinx.coroutines.ExecutorsKt;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.function.IntSupplier;
|
||||
|
||||
public class MultiBurst extends MultiBurstSupport {
|
||||
private static final long TIMEOUT = Long.getLong("iris.burst.timeout", 15000);
|
||||
public static final MultiBurst burst = new MultiBurst();
|
||||
public static final MultiBurst ioBurst = new MultiBurst("Iris IO", () -> IrisSettings.get().getConcurrency().getIoParallelism());
|
||||
private volatile CoroutineDispatcher dispatcher;
|
||||
private volatile ExecutorService dispatcherService;
|
||||
|
||||
public MultiBurst() {
|
||||
this("Iris");
|
||||
}
|
||||
|
||||
public MultiBurst(String name) {
|
||||
this(name, Thread.MIN_PRIORITY, () -> IrisSettings.get().getConcurrency().getParallelism());
|
||||
}
|
||||
|
||||
public MultiBurst(String name, IntSupplier parallelism) {
|
||||
this(name, Thread.MIN_PRIORITY, parallelism);
|
||||
}
|
||||
|
||||
public MultiBurst(String name, int priority, IntSupplier parallelism) {
|
||||
super(name, priority, parallelism, IrisSettings::getThreadCount, M::ms, Iris::reportError, Iris::info, Iris::warn, TIMEOUT);
|
||||
}
|
||||
|
||||
public CoroutineDispatcher getDispatcher() {
|
||||
ExecutorService service = service();
|
||||
if (dispatcherService != service || dispatcher == null) {
|
||||
synchronized (this) {
|
||||
if (dispatcherService != service || dispatcher == null) {
|
||||
dispatcher = ExecutorsKt.from(service);
|
||||
dispatcherService = service;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dispatcher;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BurstExecutor burst(int estimate) {
|
||||
return new BurstExecutor(service(), estimate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BurstExecutor burst() {
|
||||
return burst(16);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BurstExecutor burst(boolean multicore) {
|
||||
BurstExecutor b = burst();
|
||||
b.setMulticore(multicore);
|
||||
return b;
|
||||
}
|
||||
|
||||
public static void close(ExecutorService service) {
|
||||
MultiBurstSupport.close(service, M::ms, Iris::info, Iris::warn, Iris::reportError, TIMEOUT);
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package art.arcane.iris.util.parallel;
|
||||
|
||||
import art.arcane.volmlib.util.parallel.NoopGridLockSupport;
|
||||
|
||||
public class NOOPGridLock extends NoopGridLockSupport {
|
||||
public NOOPGridLock(int x, int z) {
|
||||
super(x, z);
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
package art.arcane.iris.util.parallel;
|
||||
|
||||
import art.arcane.volmlib.util.parallel.StreamUtilsSupport;
|
||||
import art.arcane.iris.util.math.Position2;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class StreamUtils {
|
||||
|
||||
public static Stream<Position2> streamRadius(int x, int z, int radius) {
|
||||
return streamRadius(x, z, radius, radius);
|
||||
}
|
||||
|
||||
public static Stream<Position2> streamRadius(int x, int z, int radiusX, int radiusZ) {
|
||||
return StreamUtilsSupport.streamRadius(x, z, radiusX, radiusZ)
|
||||
.map(p -> new Position2(p.getX(), p.getZ()));
|
||||
}
|
||||
|
||||
public static <T, M> void forEach(Stream<T> stream, Function<T, Stream<M>> mapper, Consumer<M> consumer, @Nullable MultiBurst burst) {
|
||||
StreamUtilsSupport.forEach(stream, mapper, consumer, burst == null ? null : burst::burst);
|
||||
}
|
||||
|
||||
public static <T> void forEach(Stream<T> stream, Consumer<T> task, @Nullable MultiBurst burst) {
|
||||
StreamUtilsSupport.forEach(stream, task, burst == null ? null : burst::burst);
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package art.arcane.iris.util.parallel;
|
||||
|
||||
import art.arcane.volmlib.util.parallel.SyncExecutorSupport;
|
||||
import art.arcane.volmlib.util.math.M;
|
||||
import art.arcane.volmlib.util.scheduling.SR;
|
||||
|
||||
public class SyncExecutor extends SyncExecutorSupport {
|
||||
public SyncExecutor(int msPerTick) {
|
||||
super(msPerTick, M::ms, task -> {
|
||||
SR sr = new SR() {
|
||||
@Override
|
||||
public void run() {
|
||||
task.run();
|
||||
}
|
||||
};
|
||||
|
||||
return sr::cancel;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
package art.arcane.iris.util.plugin.chunk;
|
||||
|
||||
import art.arcane.iris.Iris;
|
||||
import lombok.NonNull;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.world.WorldLoadEvent;
|
||||
import org.bukkit.event.world.WorldUnloadEvent;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class ChunkTickets implements Listener {
|
||||
private final Map<World, TicketHolder> holders = new HashMap<>();
|
||||
|
||||
public ChunkTickets() {
|
||||
Iris.instance.registerListener(this);
|
||||
Bukkit.getWorlds().forEach(w -> holders.put(w, new TicketHolder(w)));
|
||||
}
|
||||
|
||||
public TicketHolder getHolder(@NonNull World world) {
|
||||
return holders.get(world);
|
||||
}
|
||||
|
||||
public void addTicket(@NonNull Chunk chunk) {
|
||||
addTicket(chunk.getWorld(), chunk.getX(), chunk.getZ());
|
||||
}
|
||||
|
||||
public void addTicket(@NonNull World world, int x, int z) {
|
||||
var holder = getHolder(world);
|
||||
if (holder != null) holder.addTicket(x, z);
|
||||
}
|
||||
|
||||
public boolean removeTicket(@NonNull Chunk chunk) {
|
||||
return removeTicket(chunk.getWorld(), chunk.getX(), chunk.getZ());
|
||||
}
|
||||
|
||||
public boolean removeTicket(@NonNull World world, int x, int z) {
|
||||
var holder = getHolder(world);
|
||||
if (holder != null) return holder.removeTicket(x, z);
|
||||
return false;
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void on(@NonNull WorldLoadEvent event) {
|
||||
holders.put(event.getWorld(), new TicketHolder(event.getWorld()));
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void on(@NonNull WorldUnloadEvent event) {
|
||||
holders.remove(event.getWorld());
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
package art.arcane.iris.util.plugin.chunk;
|
||||
|
||||
import art.arcane.iris.Iris;
|
||||
import art.arcane.iris.engine.data.cache.Cache;
|
||||
import art.arcane.volmlib.util.collection.KMap;
|
||||
import lombok.NonNull;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.World;
|
||||
|
||||
public class TicketHolder {
|
||||
private final World world;
|
||||
private final KMap<Long, Long> tickets = new KMap<>();
|
||||
|
||||
public TicketHolder(@NonNull World world) {
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
public void addTicket(@NonNull Chunk chunk) {
|
||||
if (chunk.getWorld() != world) return;
|
||||
addTicket(chunk.getX(), chunk.getZ());
|
||||
}
|
||||
|
||||
public void addTicket(int x, int z) {
|
||||
tickets.compute(Cache.key(x, z), ($, ref) -> {
|
||||
if (ref == null) {
|
||||
world.addPluginChunkTicket(x, z, Iris.instance);
|
||||
return 1L;
|
||||
}
|
||||
return ++ref;
|
||||
});
|
||||
}
|
||||
|
||||
public boolean removeTicket(@NonNull Chunk chunk) {
|
||||
if (chunk.getWorld() != world) return false;
|
||||
return removeTicket(chunk.getX(), chunk.getZ());
|
||||
}
|
||||
|
||||
public boolean removeTicket(int x, int z) {
|
||||
return tickets.compute(Cache.key(x, z), ($, ref) -> {
|
||||
if (ref == null) return null;
|
||||
if (--ref <= 0) {
|
||||
world.removePluginChunkTicket(x, z, Iris.instance);
|
||||
return null;
|
||||
}
|
||||
return ref;
|
||||
}) == null;
|
||||
}
|
||||
}
|
||||
@@ -1,568 +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 art.arcane.iris.util.scheduling;
|
||||
|
||||
import art.arcane.iris.Iris;
|
||||
import art.arcane.iris.core.service.PreservationSVC;
|
||||
import art.arcane.iris.util.parallel.MultiBurst;
|
||||
import art.arcane.volmlib.util.function.NastyFunction;
|
||||
import art.arcane.volmlib.util.function.NastyFuture;
|
||||
import art.arcane.volmlib.util.function.NastyRunnable;
|
||||
import art.arcane.volmlib.util.function.NastySupplier;
|
||||
import art.arcane.volmlib.util.math.FinalInteger;
|
||||
import art.arcane.volmlib.util.scheduling.AR;
|
||||
import art.arcane.volmlib.util.scheduling.FoliaScheduler;
|
||||
import art.arcane.volmlib.util.scheduling.JSupport;
|
||||
import art.arcane.volmlib.util.scheduling.SR;
|
||||
import art.arcane.volmlib.util.scheduling.SchedulerBridge;
|
||||
import art.arcane.volmlib.util.scheduling.StartupQueueSupport;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@SuppressWarnings("ALL")
|
||||
public class J {
|
||||
private static final long TICK_MS = 50L;
|
||||
private static final AtomicInteger TASK_IDS = new AtomicInteger(1);
|
||||
private static final Map<Integer, Runnable> REPEATING_CANCELLERS = new ConcurrentHashMap<>();
|
||||
private static final StartupQueueSupport STARTUP_QUEUE = new StartupQueueSupport();
|
||||
|
||||
static {
|
||||
SchedulerBridge.setSyncScheduler(J::s);
|
||||
SchedulerBridge.setDelayedSyncScheduler(J::s);
|
||||
SchedulerBridge.setAsyncScheduler(J::a);
|
||||
SchedulerBridge.setDelayedAsyncScheduler(J::a);
|
||||
SchedulerBridge.setSyncRepeatingScheduler(J::sr);
|
||||
SchedulerBridge.setAsyncRepeatingScheduler(J::ar);
|
||||
SchedulerBridge.setCancelScheduler(J::car);
|
||||
SchedulerBridge.setErrorHandler(e -> {
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
});
|
||||
SchedulerBridge.setInfoLogger(Iris::debug);
|
||||
SchedulerBridge.setThreadRegistrar(thread -> {
|
||||
try {
|
||||
Iris.service(PreservationSVC.class).register(thread);
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void dofor(int a, Function<Integer, Boolean> c, int ch, Consumer<Integer> d) {
|
||||
JSupport.dofor(a, c, ch, d);
|
||||
}
|
||||
|
||||
public static boolean doif(Supplier<Boolean> c, Runnable g) {
|
||||
return JSupport.doif(c, g, Iris::reportError);
|
||||
}
|
||||
|
||||
public static void arun(Runnable a) {
|
||||
MultiBurst.burst.lazy(() -> {
|
||||
try {
|
||||
a.run();
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
Iris.error("Failed to run async task");
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void a(Runnable a) {
|
||||
MultiBurst.burst.lazy(() -> {
|
||||
try {
|
||||
a.run();
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
Iris.error("Failed to run async task");
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void aBukkit(Runnable a) {
|
||||
if (!isPluginEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!runAsyncImmediate(a)) {
|
||||
a(a, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> Future<T> a(Callable<T> a) {
|
||||
return MultiBurst.burst.lazySubmit(a);
|
||||
}
|
||||
|
||||
public static void attemptAsync(NastyRunnable r) {
|
||||
JSupport.attemptAsync(r::run, J::a);
|
||||
}
|
||||
|
||||
public static <R> R attemptResult(NastyFuture<R> r, R onError) {
|
||||
return JSupport.attemptResult(r::run, onError, Iris::reportError);
|
||||
}
|
||||
|
||||
public static <T, R> R attemptFunction(NastyFunction<T, R> r, T param, R onError) {
|
||||
return JSupport.attemptFunction(r::run, param, onError, Iris::reportError);
|
||||
}
|
||||
|
||||
public static boolean sleep(long ms) {
|
||||
return JSupport.sleep(ms);
|
||||
}
|
||||
|
||||
public static boolean attempt(NastyRunnable r) {
|
||||
return JSupport.attempt(r::run);
|
||||
}
|
||||
|
||||
public static <T> T attemptResult(NastySupplier<T> r) {
|
||||
return JSupport.attemptNullable(r::get);
|
||||
}
|
||||
|
||||
public static Throwable attemptCatch(NastyRunnable r) {
|
||||
return JSupport.attemptCatch(r::run);
|
||||
}
|
||||
|
||||
public static <T> T attempt(Supplier<T> t, T i) {
|
||||
return JSupport.attempt(t::get, i, Iris::reportError);
|
||||
}
|
||||
|
||||
public static void executeAfterStartupQueue() {
|
||||
JSupport.executeAfterStartupQueue(STARTUP_QUEUE, J::s, J::a);
|
||||
}
|
||||
|
||||
public static void ass(Runnable r) {
|
||||
JSupport.enqueueAfterStartupSync(STARTUP_QUEUE, r, J::s);
|
||||
}
|
||||
|
||||
public static void asa(Runnable r) {
|
||||
JSupport.enqueueAfterStartupAsync(STARTUP_QUEUE, r, J::a);
|
||||
}
|
||||
|
||||
public static boolean isFolia() {
|
||||
return FoliaScheduler.isFolia(Iris.instance);
|
||||
}
|
||||
|
||||
public static boolean isPrimaryThread() {
|
||||
return FoliaScheduler.isPrimaryThread();
|
||||
}
|
||||
|
||||
public static boolean isOwnedByCurrentRegion(Entity entity) {
|
||||
return FoliaScheduler.isOwnedByCurrentRegion(entity);
|
||||
}
|
||||
|
||||
public static boolean isOwnedByCurrentRegion(World world, int chunkX, int chunkZ) {
|
||||
return FoliaScheduler.isOwnedByCurrentRegion(world, chunkX, chunkZ);
|
||||
}
|
||||
|
||||
public static boolean runEntity(Entity entity, Runnable runnable) {
|
||||
if (entity == null || runnable == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isFolia()) {
|
||||
if (isOwnedByCurrentRegion(entity)) {
|
||||
runnable.run();
|
||||
return true;
|
||||
}
|
||||
|
||||
return runEntityImmediate(entity, runnable);
|
||||
}
|
||||
|
||||
if (isPrimaryThread()) {
|
||||
runnable.run();
|
||||
return true;
|
||||
}
|
||||
|
||||
s(runnable);
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean runEntity(Entity entity, Runnable runnable, int delayTicks) {
|
||||
if (entity == null || runnable == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (delayTicks <= 0) {
|
||||
return runEntity(entity, runnable);
|
||||
}
|
||||
|
||||
if (isFolia() && runEntityDelayed(entity, runnable, delayTicks)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
s(() -> runEntity(entity, runnable), delayTicks);
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean runRegion(World world, int chunkX, int chunkZ, Runnable runnable) {
|
||||
if (world == null || runnable == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isFolia() && isOwnedByCurrentRegion(world, chunkX, chunkZ)) {
|
||||
runnable.run();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (runRegionImmediate(world, chunkX, chunkZ, runnable)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isFolia()) {
|
||||
Iris.verbose("Failed to schedule immediate region task for " + world.getName() + "@" + chunkX + "," + chunkZ + " on Folia.");
|
||||
return false;
|
||||
}
|
||||
|
||||
s(runnable);
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean runRegion(World world, int chunkX, int chunkZ, Runnable runnable, int delayTicks) {
|
||||
if (world == null || runnable == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (delayTicks <= 0) {
|
||||
return runRegion(world, chunkX, chunkZ, runnable);
|
||||
}
|
||||
|
||||
if (runRegionDelayed(world, chunkX, chunkZ, runnable, delayTicks)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isFolia()) {
|
||||
Iris.verbose("Failed to schedule delayed region task for " + world.getName() + "@" + chunkX + "," + chunkZ
|
||||
+ " (" + delayTicks + "t) on Folia.");
|
||||
return false;
|
||||
}
|
||||
|
||||
s(runnable, delayTicks);
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean runAt(Location location, Runnable runnable) {
|
||||
if (location == null || runnable == null || location.getWorld() == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return runRegion(location.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4, runnable);
|
||||
}
|
||||
|
||||
public static boolean runAt(Location location, Runnable runnable, int delayTicks) {
|
||||
if (location == null || runnable == null || location.getWorld() == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return runRegion(location.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4, runnable, delayTicks);
|
||||
}
|
||||
|
||||
public static void cancelPluginTasks() {
|
||||
if (Iris.instance == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
FoliaScheduler.cancelTasks(Iris.instance);
|
||||
|
||||
try {
|
||||
Bukkit.getScheduler().cancelTasks(Iris.instance);
|
||||
} catch (UnsupportedOperationException ex) {
|
||||
// Folia blocks BukkitScheduler usage.
|
||||
Iris.verbose("Skipping BukkitScheduler#cancelTasks for Iris on this server.");
|
||||
}
|
||||
}
|
||||
|
||||
public static void s(Runnable r) {
|
||||
if (!isPluginEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!runGlobalImmediate(r)) {
|
||||
try {
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(Iris.instance, r);
|
||||
} catch (UnsupportedOperationException e) {
|
||||
throw new IllegalStateException("Failed to schedule sync task (Folia scheduler unavailable, BukkitScheduler unsupported).", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static CompletableFuture sfut(Runnable r) {
|
||||
CompletableFuture f = new CompletableFuture();
|
||||
|
||||
if (!isPluginEnabled()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
s(() -> {
|
||||
r.run();
|
||||
f.complete(null);
|
||||
});
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
public static <T> CompletableFuture<T> sfut(Supplier<T> r) {
|
||||
CompletableFuture<T> f = new CompletableFuture<>();
|
||||
|
||||
if (!isPluginEnabled()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
s(() -> {
|
||||
try {
|
||||
f.complete(r.get());
|
||||
} catch (Throwable e) {
|
||||
f.completeExceptionally(e);
|
||||
}
|
||||
});
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
public static CompletableFuture sfut(Runnable r, int delay) {
|
||||
CompletableFuture f = new CompletableFuture();
|
||||
|
||||
if (!isPluginEnabled()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
s(() -> {
|
||||
r.run();
|
||||
f.complete(null);
|
||||
}, delay);
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
public static CompletableFuture afut(Runnable r) {
|
||||
CompletableFuture f = new CompletableFuture();
|
||||
J.a(() -> {
|
||||
r.run();
|
||||
f.complete(null);
|
||||
});
|
||||
return f;
|
||||
}
|
||||
|
||||
public static void s(Runnable r, int delay) {
|
||||
if (!isPluginEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (delay <= 0) {
|
||||
s(r);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (!runGlobalDelayed(r, delay)) {
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(Iris.instance, r, delay);
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void csr(int id) {
|
||||
cancelRepeatingTask(id);
|
||||
}
|
||||
|
||||
public static int sr(Runnable r, int interval) {
|
||||
if (!isPluginEnabled()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int safeInterval = Math.max(1, interval);
|
||||
RepeatingState state = new RepeatingState();
|
||||
int taskId = trackRepeatingTask(() -> state.cancelled = true);
|
||||
|
||||
Runnable[] loop = new Runnable[1];
|
||||
loop[0] = () -> {
|
||||
if (state.cancelled || !isPluginEnabled()) {
|
||||
REPEATING_CANCELLERS.remove(taskId);
|
||||
return;
|
||||
}
|
||||
|
||||
r.run();
|
||||
if (state.cancelled || !isPluginEnabled()) {
|
||||
REPEATING_CANCELLERS.remove(taskId);
|
||||
return;
|
||||
}
|
||||
|
||||
s(loop[0], safeInterval);
|
||||
};
|
||||
|
||||
s(loop[0]);
|
||||
return taskId;
|
||||
}
|
||||
|
||||
public static void sr(Runnable r, int interval, int intervals) {
|
||||
FinalInteger fi = new FinalInteger(0);
|
||||
|
||||
new SR(interval) {
|
||||
@Override
|
||||
public void run() {
|
||||
fi.add(1);
|
||||
r.run();
|
||||
|
||||
if (fi.get() >= intervals) {
|
||||
cancel();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static void a(Runnable r, int delay) {
|
||||
if (!isPluginEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (delay <= 0) {
|
||||
if (!runAsyncImmediate(r)) {
|
||||
a(r);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!runAsyncDelayed(r, delay)) {
|
||||
a(() -> {
|
||||
if (sleep(ticksToMilliseconds(delay))) {
|
||||
r.run();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public static void car(int id) {
|
||||
cancelRepeatingTask(id);
|
||||
}
|
||||
|
||||
public static int ar(Runnable r, int interval) {
|
||||
if (!isPluginEnabled()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int safeInterval = Math.max(1, interval);
|
||||
RepeatingState state = new RepeatingState();
|
||||
int taskId = trackRepeatingTask(() -> state.cancelled = true);
|
||||
|
||||
Runnable[] loop = new Runnable[1];
|
||||
loop[0] = () -> {
|
||||
if (state.cancelled || !isPluginEnabled()) {
|
||||
REPEATING_CANCELLERS.remove(taskId);
|
||||
return;
|
||||
}
|
||||
|
||||
r.run();
|
||||
if (state.cancelled || !isPluginEnabled()) {
|
||||
REPEATING_CANCELLERS.remove(taskId);
|
||||
return;
|
||||
}
|
||||
|
||||
a(loop[0], safeInterval);
|
||||
};
|
||||
|
||||
a(loop[0], 0);
|
||||
return taskId;
|
||||
}
|
||||
|
||||
public static void ar(Runnable r, int interval, int intervals) {
|
||||
FinalInteger fi = new FinalInteger(0);
|
||||
|
||||
new AR(interval) {
|
||||
@Override
|
||||
public void run() {
|
||||
fi.add(1);
|
||||
r.run();
|
||||
|
||||
if (fi.get() >= intervals) {
|
||||
cancel();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static int trackRepeatingTask(Runnable cancelAction) {
|
||||
int id = TASK_IDS.getAndIncrement();
|
||||
REPEATING_CANCELLERS.put(id, cancelAction);
|
||||
return id;
|
||||
}
|
||||
|
||||
private static void cancelRepeatingTask(int id) {
|
||||
Runnable cancelAction = REPEATING_CANCELLERS.remove(id);
|
||||
if (cancelAction != null) {
|
||||
cancelAction.run();
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isPluginEnabled() {
|
||||
return Iris.instance != null && Bukkit.getPluginManager().isPluginEnabled(Iris.instance);
|
||||
}
|
||||
|
||||
private static long ticksToMilliseconds(int ticks) {
|
||||
return Math.max(0L, ticks) * TICK_MS;
|
||||
}
|
||||
|
||||
private static boolean runGlobalImmediate(Runnable runnable) {
|
||||
return FoliaScheduler.runGlobal(Iris.instance, runnable);
|
||||
}
|
||||
|
||||
private static boolean runGlobalDelayed(Runnable runnable, int delayTicks) {
|
||||
return FoliaScheduler.runGlobal(Iris.instance, runnable, Math.max(0, delayTicks));
|
||||
}
|
||||
|
||||
private static boolean runRegionImmediate(World world, int chunkX, int chunkZ, Runnable runnable) {
|
||||
return FoliaScheduler.runRegion(Iris.instance, world, chunkX, chunkZ, runnable);
|
||||
}
|
||||
|
||||
private static boolean runRegionDelayed(World world, int chunkX, int chunkZ, Runnable runnable, int delayTicks) {
|
||||
return FoliaScheduler.runRegion(Iris.instance, world, chunkX, chunkZ, runnable, Math.max(0, delayTicks));
|
||||
}
|
||||
|
||||
private static boolean runAsyncImmediate(Runnable runnable) {
|
||||
return FoliaScheduler.runAsync(Iris.instance, runnable);
|
||||
}
|
||||
|
||||
private static boolean runAsyncDelayed(Runnable runnable, int delayTicks) {
|
||||
return FoliaScheduler.runAsync(Iris.instance, runnable, Math.max(0, delayTicks));
|
||||
}
|
||||
|
||||
private static boolean runEntityImmediate(Entity entity, Runnable runnable) {
|
||||
return FoliaScheduler.runEntity(Iris.instance, entity, runnable);
|
||||
}
|
||||
|
||||
private static boolean runEntityDelayed(Entity entity, Runnable runnable, int delayTicks) {
|
||||
return FoliaScheduler.runEntity(Iris.instance, entity, runnable, Math.max(0, delayTicks));
|
||||
}
|
||||
|
||||
private static final class RepeatingState {
|
||||
private volatile boolean cancelled;
|
||||
}
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
package art.arcane.iris.util.scheduling.jobs;
|
||||
|
||||
import art.arcane.volmlib.util.math.Spiraler;
|
||||
import art.arcane.iris.util.parallel.MultiBurst;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.Synchronized;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Semaphore;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public abstract class ParallelRadiusJob implements Job {
|
||||
private final ExecutorService service;
|
||||
private final AtomicInteger completed;
|
||||
private volatile int radiusX, radiusZ;
|
||||
private volatile int offsetX, offsetZ;
|
||||
private volatile int total;
|
||||
private final Semaphore lock;
|
||||
private final int lockSize;
|
||||
|
||||
public ParallelRadiusJob(int concurrent) {
|
||||
this(concurrent, MultiBurst.burst);
|
||||
}
|
||||
|
||||
public ParallelRadiusJob(int concurrent, ExecutorService service) {
|
||||
this.service = service;
|
||||
completed = new AtomicInteger(0);
|
||||
lock = new Semaphore(concurrent);
|
||||
lockSize = concurrent;
|
||||
}
|
||||
|
||||
public ParallelRadiusJob retarget(int radius, int offsetX, int offsetZ) {
|
||||
return retarget(radius, radius, offsetX, offsetZ);
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
public ParallelRadiusJob retarget(int radiusX, int radiusZ, int offsetX, int offsetZ) {
|
||||
completed.set(0);
|
||||
this.radiusX = radiusX;
|
||||
this.radiusZ = radiusZ;
|
||||
this.offsetX = offsetX;
|
||||
this.offsetZ = offsetZ;
|
||||
total = (radiusX * 2 + 1) * (radiusZ * 2 + 1);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
@Synchronized
|
||||
public void execute() {
|
||||
new Spiraler(radiusX * 2 + 3, radiusZ * 2 + 3, this::submit).drain();
|
||||
lock.acquire(lockSize);
|
||||
lock.release(lockSize);
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
private void submit(int x, int z) {
|
||||
if (Math.abs(x) > radiusX || Math.abs(z) > radiusZ) return;
|
||||
lock.acquire();
|
||||
service.submit(() -> {
|
||||
try {
|
||||
execute(x + offsetX, z + offsetZ);
|
||||
} finally {
|
||||
completeWork();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected abstract void execute(int x, int z);
|
||||
|
||||
@Override
|
||||
public void completeWork() {
|
||||
completed.incrementAndGet();
|
||||
lock.release();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTotalWork() {
|
||||
return total;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWorkCompleted() {
|
||||
return completed.get();
|
||||
}
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
package art.arcane.iris.util.agent;
|
||||
|
||||
import art.arcane.iris.Iris;
|
||||
import net.bytebuddy.agent.ByteBuddyAgent;
|
||||
import net.bytebuddy.dynamic.loading.ClassReloadingStrategy;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.lang.instrument.Instrumentation;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
|
||||
public class Agent {
|
||||
private static final String NAME = "art.arcane.iris.util.agent.Installer";
|
||||
public static final File AGENT_JAR = new File(Iris.instance.getDataFolder(), "agent.jar");
|
||||
|
||||
public static ClassReloadingStrategy installed() {
|
||||
return ClassReloadingStrategy.of(getInstrumentation());
|
||||
}
|
||||
|
||||
public static boolean isInstalled() {
|
||||
return doGetInstrumentation() != null;
|
||||
}
|
||||
|
||||
public static Instrumentation getInstrumentation() {
|
||||
Instrumentation instrumentation = doGetInstrumentation();
|
||||
if (instrumentation == null) throw new IllegalStateException("The agent is not initialized or unavailable");
|
||||
return instrumentation;
|
||||
}
|
||||
|
||||
public static boolean install() {
|
||||
if (isInstalled())
|
||||
return true;
|
||||
|
||||
if (!ensureAgentJar())
|
||||
return false;
|
||||
|
||||
try {
|
||||
Iris.info("Installing Java Agent...");
|
||||
Iris.info("Note: JVM [Attach Listener/ERROR] [STDERR] warning lines during this step are expected and not Iris errors.");
|
||||
ByteBuddyAgent.attach(AGENT_JAR, ByteBuddyAgent.ProcessProvider.ForCurrentVm.INSTANCE);
|
||||
} catch (Throwable e) {
|
||||
Iris.error("Failed to install Java Agent: " + e.getMessage());
|
||||
Iris.reportError(e);
|
||||
}
|
||||
return doGetInstrumentation() != null;
|
||||
}
|
||||
|
||||
private static boolean ensureAgentJar() {
|
||||
File parent = AGENT_JAR.getParentFile();
|
||||
if (parent != null && !parent.exists() && !parent.mkdirs() && !parent.exists()) {
|
||||
Iris.error("Failed to create Iris plugin data folder for Java agent: " + parent.getAbsolutePath());
|
||||
return false;
|
||||
}
|
||||
|
||||
try (InputStream in = openBundledAgentJar()) {
|
||||
if (in == null) {
|
||||
if (AGENT_JAR.isFile() && AGENT_JAR.length() > 0) {
|
||||
Iris.warn("Bundled agent.jar not found in Iris plugin jar. Reusing existing " + AGENT_JAR.getAbsolutePath());
|
||||
return true;
|
||||
}
|
||||
|
||||
Iris.error("Bundled agent.jar was not found in Iris plugin jar. Rebuild/deploy Iris with embedded agent.jar.");
|
||||
return false;
|
||||
}
|
||||
|
||||
Files.copy(in, AGENT_JAR.toPath(), StandardCopyOption.REPLACE_EXISTING);
|
||||
return true;
|
||||
} catch (Throwable e) {
|
||||
Iris.error("Failed to prepare Java agent jar: " + e.getMessage());
|
||||
Iris.reportError(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static InputStream openBundledAgentJar() {
|
||||
InputStream stream = Iris.instance.getResource("agent.jar");
|
||||
if (stream != null) {
|
||||
return stream;
|
||||
}
|
||||
|
||||
return Agent.class.getClassLoader().getResourceAsStream("agent.jar");
|
||||
}
|
||||
|
||||
private static Instrumentation doGetInstrumentation() {
|
||||
try {
|
||||
return (Instrumentation) Class.forName(NAME, true, ClassLoader.getSystemClassLoader()).getMethod("getInstrumentation").invoke(null);
|
||||
} catch (Exception ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
package art.arcane.iris.util.hunk;
|
||||
|
||||
import art.arcane.volmlib.util.hunk.HunkLike;
|
||||
|
||||
final class SharedHunkAdapter<T> implements Hunk<T> {
|
||||
private final HunkLike<T> delegate;
|
||||
|
||||
SharedHunkAdapter(HunkLike<T> delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
HunkLike<T> delegate() {
|
||||
return delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWidth() {
|
||||
return delegate.getWidth();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDepth() {
|
||||
return delegate.getDepth();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHeight() {
|
||||
return delegate.getHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRaw(int x, int y, int z, T t) {
|
||||
delegate.setRaw(x, y, z, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T getRaw(int x, int y, int z) {
|
||||
return delegate.getRaw(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMapped() {
|
||||
return delegate instanceof art.arcane.volmlib.util.hunk.storage.MappedHunk<?>
|
||||
|| delegate instanceof art.arcane.volmlib.util.hunk.storage.MappedSyncHunk<?>;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEntryCount() {
|
||||
if (delegate instanceof art.arcane.volmlib.util.hunk.storage.MappedHunk<?> mapped) {
|
||||
return mapped.getEntryCount();
|
||||
}
|
||||
|
||||
if (delegate instanceof art.arcane.volmlib.util.hunk.storage.MappedSyncHunk<?> mapped) {
|
||||
return mapped.getEntryCount();
|
||||
}
|
||||
|
||||
return Hunk.super.getEntryCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAtomic() {
|
||||
return delegate instanceof art.arcane.volmlib.util.hunk.storage.AtomicHunk<?>;
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
package art.arcane.iris.util.hunk.storage;
|
||||
|
||||
import art.arcane.volmlib.util.function.Consumer4;
|
||||
import art.arcane.volmlib.util.function.Consumer4IO;
|
||||
import art.arcane.iris.util.hunk.Hunk;
|
||||
import art.arcane.volmlib.util.hunk.bits.DataContainer;
|
||||
import art.arcane.volmlib.util.hunk.bits.Writable;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public abstract class PaletteOrHunk<T> extends art.arcane.volmlib.util.hunk.storage.PaletteOrHunk<T> implements Hunk<T>, Writable<T> {
|
||||
public PaletteOrHunk(int width, int height, int depth, boolean allow, Supplier<Hunk<T>> factory) {
|
||||
super(width, height, depth, allow, factory::get);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public DataContainer<T> palette() {
|
||||
return (DataContainer<T>) super.palette();
|
||||
}
|
||||
|
||||
public void setPalette(DataContainer<T> c) {
|
||||
super.setPalette(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PaletteOrHunk<T> iterateSync(Consumer4<Integer, Integer, Integer, T> c) {
|
||||
super.iterateSync(c);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PaletteOrHunk<T> iterateSyncIO(Consumer4IO<Integer, Integer, Integer, T> c) throws IOException {
|
||||
super.iterateSyncIO(c);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -1,45 +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 art.arcane.iris.util.hunk.view;
|
||||
|
||||
import art.arcane.iris.core.nms.INMS;
|
||||
import art.arcane.iris.engine.data.chunk.LinkedTerrainChunk;
|
||||
import art.arcane.iris.util.hunk.Hunk;
|
||||
import art.arcane.volmlib.util.hunk.view.BiomeGridForceSupport;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.generator.ChunkGenerator.BiomeGrid;
|
||||
|
||||
@SuppressWarnings("ClassCanBeRecord")
|
||||
public class BiomeGridHunkHolder extends art.arcane.volmlib.util.hunk.view.BiomeGridHunkHolder implements Hunk<Biome> {
|
||||
public BiomeGridHunkHolder(BiomeGrid chunk, int minHeight, int maxHeight) {
|
||||
super(chunk, minHeight, maxHeight);
|
||||
}
|
||||
|
||||
public void forceBiomeBaseInto(int x, int y, int z, Object somethingVeryDirty) {
|
||||
BiomeGridForceSupport.forceBiomeBaseInto(
|
||||
getChunk(),
|
||||
getMinHeight(),
|
||||
x,
|
||||
y,
|
||||
z,
|
||||
somethingVeryDirty,
|
||||
chunk -> chunk instanceof LinkedTerrainChunk ? ((LinkedTerrainChunk) chunk).getRawBiome() : chunk,
|
||||
(wx, wy, wz, dirty, target) -> INMS.get().forceBiomeInto(wx, wy, wz, dirty, target));
|
||||
}
|
||||
}
|
||||
@@ -1,45 +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 art.arcane.iris.util.hunk.view;
|
||||
|
||||
import art.arcane.iris.core.nms.INMS;
|
||||
import art.arcane.iris.engine.data.chunk.LinkedTerrainChunk;
|
||||
import art.arcane.iris.util.hunk.Hunk;
|
||||
import art.arcane.volmlib.util.hunk.view.BiomeGridForceSupport;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.generator.ChunkGenerator.BiomeGrid;
|
||||
|
||||
@SuppressWarnings("ClassCanBeRecord")
|
||||
public class BiomeGridHunkView extends art.arcane.volmlib.util.hunk.view.BiomeGridHunkView implements Hunk<Biome> {
|
||||
public BiomeGridHunkView(BiomeGrid chunk, int minHeight, int maxHeight) {
|
||||
super(chunk, minHeight, maxHeight);
|
||||
}
|
||||
|
||||
public void forceBiomeBaseInto(int x, int y, int z, Object somethingVeryDirty) {
|
||||
BiomeGridForceSupport.forceBiomeBaseInto(
|
||||
getChunk(),
|
||||
getMinHeight(),
|
||||
x,
|
||||
y,
|
||||
z,
|
||||
somethingVeryDirty,
|
||||
chunk -> chunk instanceof LinkedTerrainChunk ? ((LinkedTerrainChunk) chunk).getRawBiome() : chunk,
|
||||
(wx, wy, wz, dirty, target) -> INMS.get().forceBiomeInto(wx, wy, wz, dirty, target));
|
||||
}
|
||||
}
|
||||
@@ -1,47 +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 art.arcane.iris.util.hunk.view;
|
||||
|
||||
import art.arcane.iris.util.data.B;
|
||||
import art.arcane.iris.util.data.IrisCustomData;
|
||||
import art.arcane.iris.util.hunk.Hunk;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.generator.ChunkGenerator.ChunkData;
|
||||
|
||||
@SuppressWarnings("ClassCanBeRecord")
|
||||
public class ChunkDataHunkView extends art.arcane.volmlib.util.hunk.view.ChunkDataHunkView implements Hunk<BlockData> {
|
||||
private static final BlockData AIR = B.getAir();
|
||||
|
||||
public ChunkDataHunkView(ChunkData chunk) {
|
||||
super(chunk, AIR, (data) -> data instanceof IrisCustomData d ? d.getBase() : data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(int x1, int y1, int z1, int x2, int y2, int z2, BlockData t) {
|
||||
setRegion(x1, y1, z1, x2, y2, z2, t);
|
||||
}
|
||||
|
||||
public BlockData get(int x, int y, int z) {
|
||||
return super.get(x, y, z);
|
||||
}
|
||||
|
||||
public void set(int x, int y, int z, BlockData t) {
|
||||
super.set(x, y, z, t);
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package art.arcane.iris.util.uniques.features;
|
||||
|
||||
import art.arcane.volmlib.util.math.RNG;
|
||||
import art.arcane.iris.util.uniques.UFeature;
|
||||
import art.arcane.iris.util.uniques.UFeatureMeta;
|
||||
import art.arcane.iris.util.uniques.UImage;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class UFNOOP implements UFeature {
|
||||
@Override
|
||||
public void render(UImage image, RNG rng, double t, Consumer<Double> progressor, UFeatureMeta meta) {
|
||||
}
|
||||
}
|
||||
@@ -16,49 +16,51 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package art.arcane.iris;
|
||||
package com.volmit.iris;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.google.gson.JsonParser;
|
||||
import art.arcane.iris.core.IrisSettings;
|
||||
import art.arcane.iris.core.IrisWorlds;
|
||||
import art.arcane.iris.core.ServerConfigurator;
|
||||
import art.arcane.iris.core.link.IrisPapiExpansion;
|
||||
import art.arcane.iris.core.link.MultiverseCoreLink;
|
||||
import art.arcane.iris.core.loader.IrisData;
|
||||
import art.arcane.iris.core.nms.INMS;
|
||||
import art.arcane.iris.core.pregenerator.LazyPregenerator;
|
||||
import art.arcane.iris.core.service.StudioSVC;
|
||||
import art.arcane.iris.core.tools.IrisToolbelt;
|
||||
import art.arcane.iris.engine.EnginePanic;
|
||||
import art.arcane.iris.engine.object.IrisCompat;
|
||||
import art.arcane.iris.engine.object.IrisDimension;
|
||||
import art.arcane.iris.engine.object.IrisWorld;
|
||||
import art.arcane.iris.engine.platform.BukkitChunkGenerator;
|
||||
import art.arcane.iris.core.safeguard.IrisSafeguard;
|
||||
import art.arcane.iris.engine.platform.PlatformChunkGenerator;
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
import art.arcane.volmlib.util.collection.KMap;
|
||||
import art.arcane.volmlib.util.exceptions.IrisException;
|
||||
import art.arcane.iris.util.format.C;
|
||||
import art.arcane.volmlib.util.function.NastyRunnable;
|
||||
import art.arcane.volmlib.util.hotload.ConfigHotloadEngine;
|
||||
import art.arcane.volmlib.util.io.IO;
|
||||
import art.arcane.volmlib.util.io.InstanceState;
|
||||
import art.arcane.volmlib.util.io.JarScanner;
|
||||
import art.arcane.volmlib.util.math.M;
|
||||
import art.arcane.volmlib.util.math.RNG;
|
||||
import art.arcane.iris.util.misc.Bindings;
|
||||
import art.arcane.iris.util.misc.SlimJar;
|
||||
import art.arcane.iris.util.parallel.MultiBurst;
|
||||
import art.arcane.iris.util.plugin.IrisService;
|
||||
import art.arcane.iris.util.plugin.VolmitPlugin;
|
||||
import art.arcane.iris.util.plugin.VolmitSender;
|
||||
import art.arcane.iris.util.plugin.chunk.ChunkTickets;
|
||||
import art.arcane.iris.util.scheduling.J;
|
||||
import art.arcane.volmlib.util.scheduling.Queue;
|
||||
import art.arcane.volmlib.util.scheduling.ShurikenQueue;
|
||||
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.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;
|
||||
import com.volmit.iris.engine.EnginePanic;
|
||||
import com.volmit.iris.engine.object.IrisCompat;
|
||||
import com.volmit.iris.engine.object.IrisDimension;
|
||||
import com.volmit.iris.engine.object.IrisWorld;
|
||||
import com.volmit.iris.engine.platform.BukkitChunkGenerator;
|
||||
import com.volmit.iris.core.safeguard.IrisSafeguard;
|
||||
import com.volmit.iris.engine.platform.PlatformChunkGenerator;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.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;
|
||||
import com.volmit.iris.util.io.InstanceState;
|
||||
import com.volmit.iris.util.io.JarScanner;
|
||||
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.scheduling.J;
|
||||
import com.volmit.iris.util.scheduling.Queue;
|
||||
import com.volmit.iris.util.scheduling.ShurikenQueue;
|
||||
import lombok.NonNull;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
@@ -81,6 +83,9 @@ 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<>();
|
||||
@@ -89,19 +94,15 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
public static Bindings.Adventure audiences;
|
||||
public static MultiverseCoreLink linkMultiverseCore;
|
||||
public static IrisCompat compat;
|
||||
public static ConfigHotloadEngine configHotloadEngine;
|
||||
public static ChunkTickets tickets;
|
||||
public static FileWatcher configWatcher;
|
||||
private static VolmitSender sender;
|
||||
private static Thread shutdownHook;
|
||||
private static File settingsFile;
|
||||
|
||||
static {
|
||||
try {
|
||||
InstanceState.updateInstanceId();
|
||||
} catch (Throwable ex) {
|
||||
System.err.println("[Iris] Failed to update instance id: " + ex.getClass().getSimpleName()
|
||||
+ (ex.getMessage() == null ? "" : " - " + ex.getMessage()));
|
||||
ex.printStackTrace();
|
||||
} catch (Throwable ignored) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,12 +138,8 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
if (slicedClass == null || i.isAnnotationPresent(slicedClass)) {
|
||||
try {
|
||||
v.add(i.getDeclaredConstructor().newInstance());
|
||||
} catch (Throwable ex) {
|
||||
Iris.warn("Skipped class initialization for %s: %s%s",
|
||||
i.getName(),
|
||||
ex.getClass().getSimpleName(),
|
||||
ex.getMessage() == null ? "" : " - " + ex.getMessage());
|
||||
Iris.reportError(ex);
|
||||
} catch (Throwable ignored) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -158,12 +155,8 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
if (slicedClass == null || i.isAnnotationPresent(slicedClass)) {
|
||||
try {
|
||||
v.add(i);
|
||||
} catch (Throwable ex) {
|
||||
Iris.warn("Skipped class discovery entry for %s: %s%s",
|
||||
i.getName(),
|
||||
ex.getClass().getSimpleName(),
|
||||
ex.getMessage() == null ? "" : " - " + ex.getMessage());
|
||||
Iris.reportError(ex);
|
||||
} catch (Throwable ignored) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -191,9 +184,8 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
} catch (Throwable e) {
|
||||
try {
|
||||
instance.getLogger().info(instance.getTag() + string.replaceAll("(<([^>]+)>)", ""));
|
||||
} catch (Throwable inner) {
|
||||
System.err.println("[Iris] Failed to emit log message: " + inner.getMessage());
|
||||
inner.printStackTrace(System.err);
|
||||
} catch (Throwable ignored1) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -314,11 +306,15 @@ 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) {
|
||||
try {
|
||||
J.a(() -> {
|
||||
Bukkit.getScheduler().scheduleAsyncDelayedTask(instance, () ->
|
||||
{
|
||||
try {
|
||||
object.run();
|
||||
} catch (Throwable e) {
|
||||
@@ -326,10 +322,8 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
Iris.reportError(e);
|
||||
}
|
||||
}, RNG.r.i(100, 1200));
|
||||
} catch (IllegalPluginAccessException ex) {
|
||||
Iris.verbose("Skipping deferred task registration because plugin access is unavailable: "
|
||||
+ ex.getClass().getSimpleName()
|
||||
+ (ex.getMessage() == null ? "" : " - " + ex.getMessage()));
|
||||
} catch (IllegalPluginAccessException ignored) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -424,7 +418,6 @@ 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());
|
||||
@@ -450,27 +443,20 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
services = new KMap<>();
|
||||
setupAudience();
|
||||
Bindings.setupSentry();
|
||||
initialize("art.arcane.iris.core.service").forEach((i) -> services.put((Class<? extends IrisService>) i.getClass(), (IrisService) i));
|
||||
initialize("com.volmit.iris.core.service").forEach((i) -> services.put((Class<? extends IrisService>) i.getClass(), (IrisService) i));
|
||||
IO.delete(new File("iris"));
|
||||
compat = IrisCompat.configured(getDataFile("compat.json"));
|
||||
ServerConfigurator.configure();
|
||||
IrisSafeguard.execute();
|
||||
IrisSafeguard.IrisSafeguardSystem();
|
||||
getSender().setTag(getTag());
|
||||
IrisSafeguard.splash();
|
||||
tickets = new ChunkTickets();
|
||||
IrisSafeguard.splash(true);
|
||||
linkMultiverseCore = new MultiverseCoreLink();
|
||||
settingsFile = getDataFile("settings.json");
|
||||
configHotloadEngine = new ConfigHotloadEngine(
|
||||
Iris::isSettingsFile,
|
||||
Iris::knownSettingsFiles,
|
||||
Iris::readSettingsContent,
|
||||
Iris::normalizeSettingsContent
|
||||
);
|
||||
configHotloadEngine.configure(3_000L, List.of(settingsFile), List.of());
|
||||
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);
|
||||
@@ -478,6 +464,7 @@ 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(s -> true);
|
||||
@@ -488,12 +475,7 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
|
||||
public void addShutdownHook() {
|
||||
if (shutdownHook != null) {
|
||||
try {
|
||||
Runtime.getRuntime().removeShutdownHook(shutdownHook);
|
||||
} catch (IllegalStateException ex) {
|
||||
Iris.debug("Skipping shutdown hook replacement because JVM shutdown is already in progress.");
|
||||
return;
|
||||
}
|
||||
Runtime.getRuntime().removeShutdownHook(shutdownHook);
|
||||
}
|
||||
shutdownHook = new Thread(() -> {
|
||||
Bukkit.getWorlds()
|
||||
@@ -504,15 +486,9 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
|
||||
MultiBurst.burst.close();
|
||||
MultiBurst.ioBurst.close();
|
||||
if (services != null) {
|
||||
services.clear();
|
||||
}
|
||||
}, "Iris-ShutdownHook");
|
||||
try {
|
||||
Runtime.getRuntime().addShutdownHook(shutdownHook);
|
||||
} catch (IllegalStateException ex) {
|
||||
Iris.debug("Skipping shutdown hook registration because JVM shutdown is already in progress.");
|
||||
}
|
||||
services.clear();
|
||||
});
|
||||
Runtime.getRuntime().addShutdownHook(shutdownHook);
|
||||
}
|
||||
|
||||
public void checkForBukkitWorlds(Predicate<String> filter) {
|
||||
@@ -550,10 +526,9 @@ 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(spawn);
|
||||
i.teleport(new Location(w, 0, 200, 0));
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -582,18 +557,12 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
enable();
|
||||
super.onEnable();
|
||||
Bukkit.getPluginManager().registerEvents(this, this);
|
||||
setupChecks();
|
||||
}
|
||||
|
||||
public void onDisable() {
|
||||
if (IrisSafeguard.isForceShutdown()) return;
|
||||
if (services != null) {
|
||||
services.values().forEach(IrisService::onDisable);
|
||||
}
|
||||
if (configHotloadEngine != null) {
|
||||
configHotloadEngine.clear();
|
||||
configHotloadEngine = null;
|
||||
}
|
||||
J.cancelPluginTasks();
|
||||
services.values().forEach(IrisService::onDisable);
|
||||
Bukkit.getScheduler().cancelTasks(this);
|
||||
HandlerList.unregisterAll((Plugin) this);
|
||||
postShutdown.forEach(Runnable::run);
|
||||
super.onDisable();
|
||||
@@ -619,60 +588,58 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
|
||||
@Override
|
||||
public String getTag(String subTag) {
|
||||
return IrisSafeguard.mode().tag(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 void checkConfigHotload() {
|
||||
if (configHotloadEngine == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (File file : configHotloadEngine.pollTouchedFiles()) {
|
||||
configHotloadEngine.processFileChange(file, ignored -> {
|
||||
IrisSettings.invalidate();
|
||||
IrisSettings.get();
|
||||
return true;
|
||||
}, ignored -> Iris.info("Hotloaded settings.json "));
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isSettingsFile(File file) {
|
||||
if (file == null || settingsFile == null) {
|
||||
return false;
|
||||
}
|
||||
return settingsFile.getAbsoluteFile().equals(file.getAbsoluteFile());
|
||||
}
|
||||
|
||||
private static List<File> knownSettingsFiles() {
|
||||
if (settingsFile == null) {
|
||||
return List.of();
|
||||
}
|
||||
return List.of(settingsFile);
|
||||
}
|
||||
|
||||
private static String readSettingsContent(File file) {
|
||||
if (file == null || !file.exists() || !file.isFile()) {
|
||||
return null;
|
||||
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 {
|
||||
return IO.readAll(file);
|
||||
} catch (Throwable ex) {
|
||||
Iris.warn("Failed to read settings file %s: %s%s",
|
||||
file.getAbsolutePath(),
|
||||
ex.getClass().getSimpleName(),
|
||||
ex.getMessage() == null ? "" : " - " + ex.getMessage());
|
||||
Iris.reportError(ex);
|
||||
return null;
|
||||
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;
|
||||
}
|
||||
|
||||
private static String normalizeSettingsContent(String text) {
|
||||
if (text == null) {
|
||||
return null;
|
||||
private void checkConfigHotload() {
|
||||
if (configWatcher.checkModified()) {
|
||||
IrisSettings.invalidate();
|
||||
IrisSettings.get();
|
||||
configWatcher.checkModified();
|
||||
Iris.info("Hotloaded settings.json ");
|
||||
}
|
||||
|
||||
return text.replace("\r\n", "\n").trim();
|
||||
}
|
||||
|
||||
private void tickQueue() {
|
||||
@@ -740,11 +707,7 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
Iris.debug("Generator Config: " + w.toString());
|
||||
|
||||
File ff = new File(w.worldFolder(), "iris/pack");
|
||||
var files = ff.listFiles();
|
||||
if (files == null || files.length == 0)
|
||||
IO.delete(ff);
|
||||
|
||||
if (!ff.exists()) {
|
||||
if (!ff.exists() || ff.listFiles().length == 0) {
|
||||
ff.mkdirs();
|
||||
service(StudioSVC.class).installIntoWorld(getSender(), dim.getLoadKey(), w.worldFolder());
|
||||
}
|
||||
@@ -754,13 +717,13 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
|
||||
@Nullable
|
||||
public static IrisDimension loadDimension(@NonNull String worldName, @NonNull String 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);
|
||||
var data = IrisData.get(new File(Bukkit.getWorldContainer(), String.join(File.separator, worldName, "iris", "pack")));
|
||||
var dimension = data.getDimensionLoader().load(id);
|
||||
if (dimension == null) dimension = IrisData.loadAnyDimension(id);
|
||||
if (dimension == null) {
|
||||
Iris.warn("Unable to find dimension type " + id + " Looking for online packs...");
|
||||
Iris.service(StudioSVC.class).downloadSearch(new VolmitSender(Bukkit.getConsoleSender()), id, false);
|
||||
dimension = IrisData.loadAnyDimension(id, null);
|
||||
dimension = IrisData.loadAnyDimension(id);
|
||||
|
||||
if (dimension != null) {
|
||||
Iris.info("Resolved missing dimension, proceeding.");
|
||||
@@ -771,11 +734,88 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
}
|
||||
|
||||
public void splash() {
|
||||
Iris.info("Server type & version: " + Bukkit.getName() + " v" + Bukkit.getVersion());
|
||||
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("Custom Biomes: " + INMS.get().countCustomBiomes());
|
||||
setupChecks();
|
||||
printPacks();
|
||||
|
||||
IrisSafeguard.mode().trySplash();
|
||||
for (int i = 0; i < info.length; i++) {
|
||||
splash[i] += info[i];
|
||||
}
|
||||
|
||||
Iris.info("\n\n " + new KList<>(splash).toString("\n") + "\n");
|
||||
}
|
||||
|
||||
private void printPacks() {
|
||||
@@ -795,10 +835,7 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
JsonObject json = JsonParser.parseReader(r).getAsJsonObject();
|
||||
if (json.has("version"))
|
||||
version = json.get("version").getAsString();
|
||||
} catch (IOException | JsonParseException ex) {
|
||||
Iris.verbose("Failed to read dimension version metadata for " + dimName + ": "
|
||||
+ ex.getClass().getSimpleName()
|
||||
+ (ex.getMessage() == null ? "" : " - " + ex.getMessage()));
|
||||
} catch (IOException | JsonParseException ignored) {
|
||||
}
|
||||
Iris.info(" " + dimName + " v" + version);
|
||||
}
|
||||
@@ -16,15 +16,15 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package art.arcane.iris.core;
|
||||
package com.volmit.iris.core;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import art.arcane.iris.Iris;
|
||||
import art.arcane.volmlib.util.io.IO;
|
||||
import art.arcane.volmlib.util.json.JSONException;
|
||||
import art.arcane.volmlib.util.json.JSONObject;
|
||||
import art.arcane.iris.util.misc.getHardware;
|
||||
import art.arcane.iris.util.plugin.VolmitSender;
|
||||
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.getHardware;
|
||||
import com.volmit.iris.util.plugin.VolmitSender;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
@@ -159,7 +159,7 @@ public class IrisSettings {
|
||||
private IrisSettingsEngineSVC engineSVC = new IrisSettingsEngineSVC();
|
||||
public boolean trimMantleInStudio = false;
|
||||
public int mantleKeepAlive = 30;
|
||||
public int noiseCacheSize = 1_024;
|
||||
public int cacheSize = 4_096;
|
||||
public int resourceLoaderCacheSize = 1_024;
|
||||
public int objectLoaderCacheSize = 4_096;
|
||||
public int scriptLoaderCacheSize = 512;
|
||||
@@ -170,16 +170,13 @@ public class IrisSettings {
|
||||
if (tectonicPlateSize > 0)
|
||||
return tectonicPlateSize;
|
||||
|
||||
return (int) (getHardware.getProcessMemory() / 512L);
|
||||
return (int) (getHardware.getProcessMemory() / 200L);
|
||||
}
|
||||
}
|
||||
|
||||
@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);
|
||||
@@ -188,10 +185,6 @@ public class IrisSettings {
|
||||
return Math.max(Math.abs(maxConcurrency), 1);
|
||||
}
|
||||
|
||||
public double getThreadMultiplier() {
|
||||
return Math.min(Math.abs(threadMultiplier), 0.1);
|
||||
}
|
||||
|
||||
public double getChunkLoadSensitivity() {
|
||||
return Math.min(chunkLoadSensitivity, 0.9);
|
||||
}
|
||||
@@ -207,6 +200,7 @@ public class IrisSettings {
|
||||
|
||||
@Data
|
||||
public static class IrisSettingsGeneral {
|
||||
public boolean DoomsdayAnnihilationSelfDestructMode = false;
|
||||
public boolean commandSounds = true;
|
||||
public boolean debug = false;
|
||||
public boolean dumpMantleOnError = false;
|
||||
@@ -249,7 +243,6 @@ public class IrisSettings {
|
||||
public int maxBiomeChildDepth = 4;
|
||||
public boolean preventLeafDecay = true;
|
||||
public boolean useMulticore = false;
|
||||
public boolean useMulticoreMantle = false;
|
||||
public boolean offsetNoiseTypes = false;
|
||||
public boolean earlyCustomBlocks = false;
|
||||
}
|
||||
@@ -1,15 +1,15 @@
|
||||
package art.arcane.iris.core;
|
||||
package com.volmit.iris.core;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import art.arcane.iris.Iris;
|
||||
import art.arcane.iris.core.loader.IrisData;
|
||||
import art.arcane.iris.engine.data.cache.AtomicCache;
|
||||
import art.arcane.iris.engine.object.IrisDimension;
|
||||
import art.arcane.volmlib.util.collection.KMap;
|
||||
import art.arcane.volmlib.util.io.IO;
|
||||
import art.arcane.iris.util.misc.ServerProperties;
|
||||
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;
|
||||
|
||||
@@ -16,21 +16,21 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package art.arcane.iris.core;
|
||||
package com.volmit.iris.core;
|
||||
|
||||
import art.arcane.iris.Iris;
|
||||
import art.arcane.iris.core.loader.IrisData;
|
||||
import art.arcane.iris.core.nms.INMS;
|
||||
import art.arcane.iris.core.nms.datapack.DataVersion;
|
||||
import art.arcane.iris.core.nms.datapack.IDataFixer;
|
||||
import art.arcane.iris.engine.object.*;
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
import art.arcane.volmlib.util.collection.KMap;
|
||||
import art.arcane.volmlib.util.collection.KSet;
|
||||
import art.arcane.iris.util.format.C;
|
||||
import art.arcane.iris.util.misc.ServerProperties;
|
||||
import art.arcane.iris.util.plugin.VolmitSender;
|
||||
import art.arcane.iris.util.scheduling.J;
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.loader.IrisData;
|
||||
import com.volmit.iris.core.nms.INMS;
|
||||
import com.volmit.iris.core.nms.datapack.DataVersion;
|
||||
import com.volmit.iris.core.nms.datapack.IDataFixer;
|
||||
import com.volmit.iris.engine.object.*;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.collection.KSet;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.misc.ServerProperties;
|
||||
import com.volmit.iris.util.plugin.VolmitSender;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import lombok.NonNull;
|
||||
import lombok.SneakyThrows;
|
||||
import org.bukkit.Bukkit;
|
||||
@@ -104,13 +104,7 @@ public class ServerConfigurator {
|
||||
}
|
||||
|
||||
public static boolean installDataPacks(boolean fullInstall) {
|
||||
IDataFixer fixer = DataVersion.getDefault();
|
||||
if (fixer == null) {
|
||||
DataVersion fallback = DataVersion.getLatest();
|
||||
Iris.warn("Primary datapack fixer was null, forcing latest fixer: " + fallback.getVersion());
|
||||
fixer = fallback.get();
|
||||
}
|
||||
return installDataPacks(fixer, fullInstall);
|
||||
return installDataPacks(DataVersion.getDefault(), fullInstall);
|
||||
}
|
||||
|
||||
public static boolean installDataPacks(IDataFixer fixer, boolean fullInstall) {
|
||||
@@ -16,47 +16,42 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package art.arcane.iris.core.commands;
|
||||
package com.volmit.iris.core.commands;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import art.arcane.iris.Iris;
|
||||
import art.arcane.iris.core.IrisSettings;
|
||||
import art.arcane.iris.core.ServerConfigurator;
|
||||
import art.arcane.iris.core.loader.IrisData;
|
||||
import art.arcane.iris.core.nms.INMS;
|
||||
import art.arcane.iris.core.nms.datapack.DataVersion;
|
||||
import art.arcane.iris.core.service.IrisEngineSVC;
|
||||
import art.arcane.iris.core.service.StudioSVC;
|
||||
import art.arcane.iris.core.tools.IrisPackBenchmarking;
|
||||
import art.arcane.iris.core.tools.IrisToolbelt;
|
||||
import art.arcane.iris.engine.framework.Engine;
|
||||
import art.arcane.iris.engine.object.IrisDimension;
|
||||
import art.arcane.iris.engine.object.IrisPosition;
|
||||
import art.arcane.iris.engine.object.annotations.Snippet;
|
||||
import art.arcane.volmlib.util.collection.KMap;
|
||||
import art.arcane.volmlib.util.collection.KSet;
|
||||
import art.arcane.iris.util.context.IrisContext;
|
||||
import art.arcane.iris.engine.object.IrisJigsawStructurePlacement;
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
import art.arcane.iris.util.decree.DecreeExecutor;
|
||||
import art.arcane.volmlib.util.decree.DecreeOrigin;
|
||||
import art.arcane.volmlib.util.decree.annotations.Decree;
|
||||
import art.arcane.volmlib.util.decree.annotations.Param;
|
||||
import art.arcane.iris.util.decree.specialhandlers.NullableDimensionHandler;
|
||||
import art.arcane.iris.util.format.C;
|
||||
import art.arcane.volmlib.util.format.Form;
|
||||
import art.arcane.volmlib.util.io.CountingDataInputStream;
|
||||
import art.arcane.volmlib.util.io.IO;
|
||||
import art.arcane.iris.util.mantle.TectonicPlate;
|
||||
import art.arcane.volmlib.util.math.M;
|
||||
import art.arcane.iris.util.matter.Matter;
|
||||
import art.arcane.iris.util.nbt.mca.MCAFile;
|
||||
import art.arcane.iris.util.nbt.mca.MCAUtil;
|
||||
import art.arcane.iris.util.parallel.MultiBurst;
|
||||
import art.arcane.iris.util.plugin.VolmitSender;
|
||||
import art.arcane.iris.util.scheduling.jobs.Job;
|
||||
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.annotations.Snippet;
|
||||
import com.volmit.iris.util.collection.KSet;
|
||||
import com.volmit.iris.util.context.IrisContext;
|
||||
import com.volmit.iris.engine.object.IrisJigsawStructurePlacement;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.decree.DecreeExecutor;
|
||||
import com.volmit.iris.util.decree.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 lombok.SneakyThrows;
|
||||
import net.jpountz.lz4.LZ4BlockInputStream;
|
||||
import net.jpountz.lz4.LZ4BlockOutputStream;
|
||||
@@ -76,6 +71,7 @@ import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
@@ -97,207 +93,6 @@ public class CommandDeveloper implements DecreeExecutor {
|
||||
Iris.reportError(new Exception("This is a test"));
|
||||
}
|
||||
|
||||
@Decree(description = "QOL command to open an overworld studio world", sync = true)
|
||||
public void so() {
|
||||
sender().sendMessage(C.GREEN + "Opening studio for the \"Overworld\" pack (seed: 1337)");
|
||||
Iris.service(StudioSVC.class).open(sender(), 1337, "overworld");
|
||||
}
|
||||
|
||||
@Decree(description = "Set aura spins")
|
||||
public void aura(
|
||||
@Param(description = "The h color value", defaultValue = "-20")
|
||||
int h,
|
||||
@Param(description = "The s color value", defaultValue = "7")
|
||||
int s,
|
||||
@Param(description = "The b color value", defaultValue = "8")
|
||||
int b
|
||||
) {
|
||||
IrisSettings.get().getGeneral().setSpinh(h);
|
||||
IrisSettings.get().getGeneral().setSpins(s);
|
||||
IrisSettings.get().getGeneral().setSpinb(b);
|
||||
IrisSettings.get().forceSave();
|
||||
sender().sendMessage("<rainbow>Aura Spins updated to " + h + " " + s + " " + b);
|
||||
}
|
||||
|
||||
@Decree(description = "Bitwise calculations")
|
||||
public void bitwise(
|
||||
@Param(description = "The first value to run calculations on")
|
||||
int value1,
|
||||
@Param(description = "The operator: | & ^ << >> %")
|
||||
String operator,
|
||||
@Param(description = "The second value to run calculations on")
|
||||
int value2
|
||||
) {
|
||||
Integer v = null;
|
||||
switch (operator) {
|
||||
case "|" -> v = value1 | value2;
|
||||
case "&" -> v = value1 & value2;
|
||||
case "^" -> v = value1 ^ value2;
|
||||
case "%" -> v = value1 % value2;
|
||||
case ">>" -> v = value1 >> value2;
|
||||
case "<<" -> v = value1 << value2;
|
||||
}
|
||||
if (v == null) {
|
||||
sender().sendMessage(C.RED + "The operator you entered: (" + operator + ") is invalid!");
|
||||
return;
|
||||
}
|
||||
sender().sendMessage(C.GREEN + "" + value1 + " " + C.GREEN + operator.replaceAll("<", "≺").replaceAll(">", "≻").replaceAll("%", "%") + " " + C.GREEN + value2 + C.GREEN + " returns " + C.GREEN + v);
|
||||
}
|
||||
|
||||
@Decree(description = "Update the pack of a world (UNSAFE!)", name = "update-world", aliases = "^world")
|
||||
public void updateWorld(
|
||||
@Param(description = "The world to update", contextual = true)
|
||||
World world,
|
||||
@Param(description = "The pack to install into the world", contextual = true, aliases = "dimension")
|
||||
IrisDimension pack,
|
||||
@Param(description = "Make sure to make a backup & read the warnings first!", defaultValue = "false", aliases = "c")
|
||||
boolean confirm,
|
||||
@Param(description = "Should Iris download the pack again for you", defaultValue = "false", name = "fresh-download", aliases = {"fresh", "new"})
|
||||
boolean freshDownload
|
||||
) {
|
||||
if (!confirm) {
|
||||
sender().sendMessage(new String[]{
|
||||
C.RED + "You should always make a backup before using this",
|
||||
C.YELLOW + "Issues caused by this can be, but are not limited to:",
|
||||
C.YELLOW + " - Broken chunks (cut-offs) between old and new chunks (before & after the update)",
|
||||
C.YELLOW + " - Regenerated chunks that do not fit in with the old chunks",
|
||||
C.YELLOW + " - Structures not spawning again when regenerating",
|
||||
C.YELLOW + " - Caves not lining up",
|
||||
C.YELLOW + " - Terrain layers not lining up",
|
||||
C.RED + "Now that you are aware of the risks, and have made a back-up:",
|
||||
C.RED + "/iris developer update-world " + world.getName() + " " + pack.getLoadKey() + " confirm=true"
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
File folder = world.getWorldFolder();
|
||||
folder.mkdirs();
|
||||
|
||||
if (freshDownload) {
|
||||
Iris.service(StudioSVC.class).downloadSearch(sender(), pack.getLoadKey(), false, true);
|
||||
}
|
||||
|
||||
Iris.service(StudioSVC.class).installIntoWorld(sender(), pack.getLoadKey(), folder);
|
||||
}
|
||||
|
||||
@Decree(description = "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");
|
||||
@@ -364,7 +159,7 @@ public class CommandDeveloper implements DecreeExecutor {
|
||||
@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)
|
||||
@Param(description = "The pack to add the generated structures to", aliases = "pack", defaultValue = "---", customHandler = NullableDimensionHandler.class)
|
||||
IrisDimension dimension,
|
||||
@Param(description = "Ignore existing structures", defaultValue = "false")
|
||||
boolean force
|
||||
@@ -662,3 +457,4 @@ public class CommandDeveloper implements DecreeExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,16 +16,16 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package art.arcane.iris.core.commands;
|
||||
package com.volmit.iris.core.commands;
|
||||
|
||||
import art.arcane.iris.Iris;
|
||||
import art.arcane.iris.core.service.StudioSVC;
|
||||
import art.arcane.iris.engine.object.*;
|
||||
import art.arcane.iris.util.decree.DecreeExecutor;
|
||||
import art.arcane.volmlib.util.decree.DecreeOrigin;
|
||||
import art.arcane.volmlib.util.decree.annotations.Decree;
|
||||
import art.arcane.volmlib.util.decree.annotations.Param;
|
||||
import art.arcane.iris.util.format.C;
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.service.StudioSVC;
|
||||
import com.volmit.iris.engine.object.*;
|
||||
import com.volmit.iris.util.decree.DecreeExecutor;
|
||||
import com.volmit.iris.util.decree.DecreeOrigin;
|
||||
import com.volmit.iris.util.decree.annotations.Decree;
|
||||
import com.volmit.iris.util.decree.annotations.Param;
|
||||
import com.volmit.iris.util.format.C;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
@@ -46,16 +46,6 @@ public class CommandEdit implements DecreeExecutor {
|
||||
sender().sendMessage(C.RED + "You must be in a studio world!");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (GraphicsEnvironment.isHeadless()) {
|
||||
sender().sendMessage(C.RED + "Cannot open files in headless environments!");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!Desktop.isDesktopSupported()) {
|
||||
sender().sendMessage(C.RED + "Desktop is not supported by this environment!");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -16,18 +16,18 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package art.arcane.iris.core.commands;
|
||||
package com.volmit.iris.core.commands;
|
||||
|
||||
import art.arcane.iris.engine.framework.Engine;
|
||||
import art.arcane.iris.engine.object.IrisBiome;
|
||||
import art.arcane.iris.engine.object.IrisJigsawStructure;
|
||||
import art.arcane.iris.engine.object.IrisRegion;
|
||||
import art.arcane.iris.util.decree.DecreeExecutor;
|
||||
import art.arcane.volmlib.util.decree.DecreeOrigin;
|
||||
import art.arcane.volmlib.util.decree.annotations.Decree;
|
||||
import art.arcane.volmlib.util.decree.annotations.Param;
|
||||
import art.arcane.iris.util.decree.specialhandlers.ObjectHandler;
|
||||
import art.arcane.iris.util.format.C;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.object.IrisBiome;
|
||||
import com.volmit.iris.engine.object.IrisJigsawStructure;
|
||||
import com.volmit.iris.engine.object.IrisRegion;
|
||||
import com.volmit.iris.util.decree.DecreeExecutor;
|
||||
import com.volmit.iris.util.decree.DecreeOrigin;
|
||||
import com.volmit.iris.util.decree.annotations.Decree;
|
||||
import com.volmit.iris.util.decree.annotations.Param;
|
||||
import com.volmit.iris.util.decree.specialhandlers.ObjectHandler;
|
||||
import com.volmit.iris.util.format.C;
|
||||
|
||||
@Decree(name = "find", origin = DecreeOrigin.PLAYER, description = "Iris Find commands", aliases = "goto")
|
||||
public class CommandFind implements DecreeExecutor {
|
||||
@@ -16,29 +16,27 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package art.arcane.iris.core.commands;
|
||||
package com.volmit.iris.core.commands;
|
||||
|
||||
import art.arcane.iris.Iris;
|
||||
import art.arcane.iris.core.IrisSettings;
|
||||
import art.arcane.iris.core.loader.IrisData;
|
||||
import art.arcane.iris.core.nms.INMS;
|
||||
import art.arcane.iris.core.service.StudioSVC;
|
||||
import art.arcane.iris.core.tools.IrisToolbelt;
|
||||
import art.arcane.iris.engine.framework.Engine;
|
||||
import art.arcane.iris.engine.object.IrisDimension;
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
import art.arcane.volmlib.util.decree.DecreeParameterHandler;
|
||||
import art.arcane.iris.util.decree.DecreeExecutor;
|
||||
import art.arcane.volmlib.util.decree.DecreeOrigin;
|
||||
import art.arcane.volmlib.util.decree.annotations.Decree;
|
||||
import art.arcane.volmlib.util.decree.annotations.Param;
|
||||
import art.arcane.volmlib.util.decree.exceptions.DecreeParsingException;
|
||||
import art.arcane.iris.util.decree.specialhandlers.NullablePlayerHandler;
|
||||
import art.arcane.iris.util.format.C;
|
||||
import art.arcane.volmlib.util.io.IO;
|
||||
import art.arcane.iris.util.misc.ServerProperties;
|
||||
import art.arcane.iris.util.plugin.VolmitSender;
|
||||
import art.arcane.iris.util.scheduling.J;
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.nms.INMS;
|
||||
import com.volmit.iris.core.service.StudioSVC;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.object.IrisDimension;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.decree.DecreeExecutor;
|
||||
import com.volmit.iris.util.decree.DecreeOrigin;
|
||||
import com.volmit.iris.util.decree.annotations.Decree;
|
||||
import com.volmit.iris.util.decree.annotations.Param;
|
||||
import com.volmit.iris.util.decree.specialhandlers.NullablePlayerHandler;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.io.IO;
|
||||
import com.volmit.iris.util.misc.ServerProperties;
|
||||
import com.volmit.iris.util.plugin.VolmitSender;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import lombok.SneakyThrows;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
@@ -47,13 +45,11 @@ import org.bukkit.entity.Player;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import static art.arcane.iris.core.service.EditSVC.deletingWorld;
|
||||
import static art.arcane.iris.util.misc.ServerProperties.BUKKIT_YML;
|
||||
import static com.volmit.iris.core.service.EditSVC.deletingWorld;
|
||||
import static com.volmit.iris.util.misc.ServerProperties.BUKKIT_YML;
|
||||
import static org.bukkit.Bukkit.getServer;
|
||||
|
||||
@Decree(name = "iris", aliases = {"ir", "irs"}, description = "Basic Command")
|
||||
@@ -78,13 +74,8 @@ public class CommandIris implements DecreeExecutor {
|
||||
public void create(
|
||||
@Param(aliases = "world-name", description = "The name of the world to create")
|
||||
String name,
|
||||
@Param(
|
||||
aliases = {"dimension", "pack"},
|
||||
description = "The dimension/pack to create the world with",
|
||||
defaultValue = "default",
|
||||
customHandler = PackDimensionTypeHandler.class
|
||||
)
|
||||
String type,
|
||||
@Param(aliases = "dimension", description = "The dimension type to create the world with", defaultValue = "default")
|
||||
IrisDimension type,
|
||||
@Param(description = "The seed to generate the world with", defaultValue = "1337")
|
||||
long seed,
|
||||
@Param(aliases = "main-world", description = "Whether or not to automatically use this world as the main world", defaultValue = "false")
|
||||
@@ -107,29 +98,10 @@ public class CommandIris implements DecreeExecutor {
|
||||
return;
|
||||
}
|
||||
|
||||
String resolvedType = type.equalsIgnoreCase("default")
|
||||
? IrisSettings.get().getGenerator().getDefaultWorldType()
|
||||
: type;
|
||||
|
||||
IrisDimension dimension = IrisToolbelt.getDimension(resolvedType);
|
||||
if (dimension == null) {
|
||||
sender().sendMessage(C.RED + "Could not find or download dimension \"" + resolvedType + "\".");
|
||||
sender().sendMessage(C.YELLOW + "Try one of: overworld, vanilla, flat, theend");
|
||||
sender().sendMessage(C.YELLOW + "Or download manually: /iris download IrisDimensions/" + resolvedType);
|
||||
return;
|
||||
}
|
||||
|
||||
if (J.isFolia()) {
|
||||
if (stageFoliaWorldCreation(name, dimension, seed, main)) {
|
||||
sender().sendMessage(C.GREEN + "World staging completed. Restart the server to generate/load \"" + name + "\".");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
worldCreation = true;
|
||||
IrisToolbelt.createWorld()
|
||||
.dimension(dimension.getLoadKey())
|
||||
.dimension(type.getLoadKey())
|
||||
.name(name)
|
||||
.seed(seed)
|
||||
.sender(sender())
|
||||
@@ -153,98 +125,20 @@ public class CommandIris implements DecreeExecutor {
|
||||
if (main) sender().sendMessage(C.GREEN + "Your world will automatically be set as the main world when the server restarts.");
|
||||
}
|
||||
|
||||
private boolean updateMainWorld(String newName) {
|
||||
try {
|
||||
File worlds = Bukkit.getWorldContainer();
|
||||
var data = ServerProperties.DATA;
|
||||
try (var in = new FileInputStream(ServerProperties.SERVER_PROPERTIES)) {
|
||||
data.load(in);
|
||||
}
|
||||
|
||||
File oldWorldFolder = new File(worlds, ServerProperties.LEVEL_NAME);
|
||||
File newWorldFolder = new File(worlds, newName);
|
||||
if (!newWorldFolder.exists() && !newWorldFolder.mkdirs()) {
|
||||
Iris.warn("Could not create target main world folder: " + newWorldFolder.getAbsolutePath());
|
||||
}
|
||||
|
||||
for (String sub : List.of("datapacks", "playerdata", "advancements", "stats")) {
|
||||
File source = new File(oldWorldFolder, sub);
|
||||
if (!source.exists()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
IO.copyDirectory(source.toPath(), new File(newWorldFolder, sub).toPath());
|
||||
}
|
||||
|
||||
data.setProperty("level-name", newName);
|
||||
try (var out = new FileOutputStream(ServerProperties.SERVER_PROPERTIES)) {
|
||||
data.store(out, null);
|
||||
}
|
||||
return true;
|
||||
} catch (Throwable e) {
|
||||
Iris.error("Failed to update server.properties main world to \"" + newName + "\"");
|
||||
Iris.reportError(e);
|
||||
return false;
|
||||
@SneakyThrows
|
||||
private void updateMainWorld(String newName) {
|
||||
File worlds = Bukkit.getWorldContainer();
|
||||
var data = ServerProperties.DATA;
|
||||
try (var in = new FileInputStream(ServerProperties.SERVER_PROPERTIES)) {
|
||||
data.load(in);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean stageFoliaWorldCreation(String name, IrisDimension dimension, long seed, boolean main) {
|
||||
sender().sendMessage(C.YELLOW + "Runtime world creation is disabled on Folia.");
|
||||
sender().sendMessage(C.YELLOW + "Preparing world files and bukkit.yml for next startup...");
|
||||
|
||||
File worldFolder = new File(Bukkit.getWorldContainer(), name);
|
||||
IrisDimension installed = Iris.service(StudioSVC.class).installIntoWorld(sender(), dimension.getLoadKey(), worldFolder);
|
||||
if (installed == null) {
|
||||
sender().sendMessage(C.RED + "Failed to stage world files for dimension \"" + dimension.getLoadKey() + "\".");
|
||||
return false;
|
||||
for (String sub : List.of("datapacks", "playerdata", "advancements", "stats")) {
|
||||
IO.copyDirectory(new File(worlds, ServerProperties.LEVEL_NAME + "/" + sub).toPath(), new File(worlds, newName + "/" + sub).toPath());
|
||||
}
|
||||
|
||||
if (!registerWorldInBukkitYml(name, dimension.getLoadKey(), seed)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (main) {
|
||||
if (updateMainWorld(name)) {
|
||||
sender().sendMessage(C.GREEN + "Updated server.properties level-name to \"" + name + "\".");
|
||||
} else {
|
||||
sender().sendMessage(C.RED + "World was staged, but failed to update server.properties main world.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
sender().sendMessage(C.GREEN + "Staged Iris world \"" + name + "\" with generator Iris:" + dimension.getLoadKey() + " and seed " + seed + ".");
|
||||
if (main) {
|
||||
sender().sendMessage(C.GREEN + "This world is now configured as main for next restart.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean registerWorldInBukkitYml(String worldName, String dimension, Long seed) {
|
||||
YamlConfiguration yml = YamlConfiguration.loadConfiguration(BUKKIT_YML);
|
||||
ConfigurationSection worlds = yml.getConfigurationSection("worlds");
|
||||
if (worlds == null) {
|
||||
worlds = yml.createSection("worlds");
|
||||
}
|
||||
ConfigurationSection worldSection = worlds.getConfigurationSection(worldName);
|
||||
if (worldSection == null) {
|
||||
worldSection = worlds.createSection(worldName);
|
||||
}
|
||||
|
||||
String generator = "Iris:" + dimension;
|
||||
worldSection.set("generator", generator);
|
||||
if (seed != null) {
|
||||
worldSection.set("seed", seed);
|
||||
}
|
||||
|
||||
try {
|
||||
yml.save(BUKKIT_YML);
|
||||
Iris.info("Registered \"" + worldName + "\" in bukkit.yml");
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
sender().sendMessage(C.RED + "Failed to update bukkit.yml: " + e.getMessage());
|
||||
Iris.error("Failed to update bukkit.yml!");
|
||||
Iris.reportError(e);
|
||||
return false;
|
||||
data.setProperty("level-name", newName);
|
||||
try (var out = new FileOutputStream(ServerProperties.SERVER_PROPERTIES)) {
|
||||
data.store(out, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -303,6 +197,12 @@ public class CommandIris implements DecreeExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(description = "QOL command to open a overworld studio world.", sync = true)
|
||||
public void so() {
|
||||
sender().sendMessage(C.GREEN + "Opening studio for the \"Overworld\" pack (seed: 1337)");
|
||||
Iris.service(StudioSVC.class).open(sender(), 1337, "overworld");
|
||||
}
|
||||
|
||||
@Decree(description = "Check access of all worlds.", aliases = {"accesslist"})
|
||||
public void worlds() {
|
||||
KList<World> IrisWorlds = new KList<>();
|
||||
@@ -417,6 +317,47 @@ public class CommandIris implements DecreeExecutor {
|
||||
return dir.delete();
|
||||
}
|
||||
|
||||
@Decree(description = "Set aura spins")
|
||||
public void aura(
|
||||
@Param(description = "The h color value", defaultValue = "-20")
|
||||
int h,
|
||||
@Param(description = "The s color value", defaultValue = "7")
|
||||
int s,
|
||||
@Param(description = "The b color value", defaultValue = "8")
|
||||
int b
|
||||
) {
|
||||
IrisSettings.get().getGeneral().setSpinh(h);
|
||||
IrisSettings.get().getGeneral().setSpins(s);
|
||||
IrisSettings.get().getGeneral().setSpinb(b);
|
||||
IrisSettings.get().forceSave();
|
||||
sender().sendMessage("<rainbow>Aura Spins updated to " + h + " " + s + " " + b);
|
||||
}
|
||||
|
||||
@Decree(description = "Bitwise calculations")
|
||||
public void bitwise(
|
||||
@Param(description = "The first value to run calculations on")
|
||||
int value1,
|
||||
@Param(description = "The operator: | & ^ ≺≺ ≻≻ %")
|
||||
String operator,
|
||||
@Param(description = "The second value to run calculations on")
|
||||
int value2
|
||||
) {
|
||||
Integer v = null;
|
||||
switch (operator) {
|
||||
case "|" -> v = value1 | value2;
|
||||
case "&" -> v = value1 & value2;
|
||||
case "^" -> v = value1 ^ value2;
|
||||
case "%" -> v = value1 % value2;
|
||||
case ">>" -> v = value1 >> value2;
|
||||
case "<<" -> v = value1 << value2;
|
||||
}
|
||||
if (v == null) {
|
||||
sender().sendMessage(C.RED + "The operator you entered: (" + operator + ") is invalid!");
|
||||
return;
|
||||
}
|
||||
sender().sendMessage(C.GREEN + "" + value1 + " " + C.GREEN + operator.replaceAll("<", "≺").replaceAll(">", "≻").replaceAll("%", "%") + " " + C.GREEN + value2 + C.GREEN + " returns " + C.GREEN + v);
|
||||
}
|
||||
|
||||
@Decree(description = "Toggle debug")
|
||||
public void debug(
|
||||
@Param(name = "on", description = "Whether or not debug should be on", defaultValue = "other")
|
||||
@@ -467,6 +408,42 @@ public class CommandIris implements DecreeExecutor {
|
||||
sender().sendMessage(C.GREEN + "Hotloaded settings");
|
||||
}
|
||||
|
||||
@Decree(description = "Update the pack of a world (UNSAFE!)", name = "^world", aliases = "update-world")
|
||||
public void updateWorld(
|
||||
@Param(description = "The world to update", contextual = true)
|
||||
World world,
|
||||
@Param(description = "The pack to install into the world", contextual = true, aliases = "dimension")
|
||||
IrisDimension pack,
|
||||
@Param(description = "Make sure to make a backup & read the warnings first!", defaultValue = "false", aliases = "c")
|
||||
boolean confirm,
|
||||
@Param(description = "Should Iris download the pack again for you", defaultValue = "false", name = "fresh-download", aliases = {"fresh", "new"})
|
||||
boolean freshDownload
|
||||
) {
|
||||
if (!confirm) {
|
||||
sender().sendMessage(new String[]{
|
||||
C.RED + "You should always make a backup before using this",
|
||||
C.YELLOW + "Issues caused by this can be, but are not limited to:",
|
||||
C.YELLOW + " - Broken chunks (cut-offs) between old and new chunks (before & after the update)",
|
||||
C.YELLOW + " - Regenerated chunks that do not fit in with the old chunks",
|
||||
C.YELLOW + " - Structures not spawning again when regenerating",
|
||||
C.YELLOW + " - Caves not lining up",
|
||||
C.YELLOW + " - Terrain layers not lining up",
|
||||
C.RED + "Now that you are aware of the risks, and have made a back-up:",
|
||||
C.RED + "/iris ^world " + world.getName() + " " + pack.getLoadKey() + " confirm=true"
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
File folder = world.getWorldFolder();
|
||||
folder.mkdirs();
|
||||
|
||||
if (freshDownload) {
|
||||
Iris.service(StudioSVC.class).downloadSearch(sender(), pack.getLoadKey(), false, true);
|
||||
}
|
||||
|
||||
Iris.service(StudioSVC.class).installIntoWorld(sender(), pack.getLoadKey(), folder);
|
||||
}
|
||||
|
||||
@Decree(description = "Unload an Iris World", origin = DecreeOrigin.PLAYER, sync = true)
|
||||
public void unloadWorld(
|
||||
@Param(description = "The world to unload")
|
||||
@@ -523,23 +500,22 @@ public class CommandIris implements DecreeExecutor {
|
||||
sender().sendMessage(C.GOLD + world + " is not an iris world.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (dimension == null) {
|
||||
sender().sendMessage(C.RED + "Could not determine Iris dimension for " + world + ".");
|
||||
return;
|
||||
}
|
||||
|
||||
sender().sendMessage(C.GREEN + "Loading world: " + world);
|
||||
|
||||
if (!registerWorldInBukkitYml(world, dimension, null)) {
|
||||
return;
|
||||
YamlConfiguration yml = YamlConfiguration.loadConfiguration(BUKKIT_YML);
|
||||
String gen = "Iris:" + dimension;
|
||||
ConfigurationSection section = yml.contains("worlds") ? yml.getConfigurationSection("worlds") : yml.createSection("worlds");
|
||||
if (!section.contains(world)) {
|
||||
section.createSection(world).set("generator", gen);
|
||||
try {
|
||||
yml.save(BUKKIT_YML);
|
||||
Iris.info("Registered \"" + world + "\" in bukkit.yml");
|
||||
} catch (IOException e) {
|
||||
Iris.error("Failed to update bukkit.yml!");
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (J.isFolia()) {
|
||||
sender().sendMessage(C.YELLOW + "Folia cannot load new worlds at runtime. Restart the server to load \"" + world + "\".");
|
||||
return;
|
||||
}
|
||||
|
||||
Iris.instance.checkForBukkitWorlds(world::equals);
|
||||
sender().sendMessage(C.GREEN + world + " loaded successfully.");
|
||||
}
|
||||
@@ -561,58 +537,4 @@ public class CommandIris implements DecreeExecutor {
|
||||
File worldDirectory = new File(worldContainer, worldName);
|
||||
return worldDirectory.exists() && worldDirectory.isDirectory();
|
||||
}
|
||||
|
||||
public static class PackDimensionTypeHandler implements DecreeParameterHandler<String> {
|
||||
@Override
|
||||
public KList<String> getPossibilities() {
|
||||
Set<String> options = new LinkedHashSet<>();
|
||||
options.add("default");
|
||||
|
||||
File packsFolder = Iris.instance.getDataFolder("packs");
|
||||
File[] packs = packsFolder.listFiles();
|
||||
if (packs != null) {
|
||||
for (File pack : packs) {
|
||||
if (pack == null || !pack.isDirectory()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
options.add(pack.getName());
|
||||
|
||||
try {
|
||||
IrisData data = IrisData.get(pack);
|
||||
for (String key : data.getDimensionLoader().getPossibleKeys()) {
|
||||
options.add(key);
|
||||
}
|
||||
} catch (Throwable ex) {
|
||||
Iris.warn("Failed to read dimension keys from pack %s: %s%s",
|
||||
pack.getName(),
|
||||
ex.getClass().getSimpleName(),
|
||||
ex.getMessage() == null ? "" : " - " + ex.getMessage());
|
||||
Iris.reportError(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new KList<>(options);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(String value) {
|
||||
return value == null ? "" : value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String parse(String in, boolean force) throws DecreeParsingException {
|
||||
if (in == null || in.trim().isEmpty()) {
|
||||
throw new DecreeParsingException("World type cannot be empty");
|
||||
}
|
||||
|
||||
return in.trim();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(Class<?> type) {
|
||||
return type == String.class;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,27 +16,27 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package art.arcane.iris.core.commands;
|
||||
package com.volmit.iris.core.commands;
|
||||
|
||||
import art.arcane.iris.Iris;
|
||||
import art.arcane.iris.core.edit.JigsawEditor;
|
||||
import art.arcane.iris.core.loader.IrisData;
|
||||
import art.arcane.iris.engine.framework.placer.WorldObjectPlacer;
|
||||
import art.arcane.iris.engine.jigsaw.PlannedStructure;
|
||||
import art.arcane.iris.engine.object.IrisJigsawPiece;
|
||||
import art.arcane.iris.engine.object.IrisJigsawStructure;
|
||||
import art.arcane.iris.engine.object.IrisObject;
|
||||
import art.arcane.iris.engine.object.IrisPosition;
|
||||
import art.arcane.iris.util.decree.DecreeExecutor;
|
||||
import art.arcane.volmlib.util.decree.DecreeOrigin;
|
||||
import art.arcane.volmlib.util.decree.annotations.Decree;
|
||||
import art.arcane.volmlib.util.decree.annotations.Param;
|
||||
import art.arcane.iris.util.decree.specialhandlers.ObjectHandler;
|
||||
import art.arcane.iris.util.format.C;
|
||||
import art.arcane.volmlib.util.format.Form;
|
||||
import art.arcane.volmlib.util.math.RNG;
|
||||
import art.arcane.iris.util.plugin.VolmitSender;
|
||||
import art.arcane.volmlib.util.scheduling.PrecisionStopwatch;
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.edit.JigsawEditor;
|
||||
import com.volmit.iris.core.loader.IrisData;
|
||||
import com.volmit.iris.engine.framework.placer.WorldObjectPlacer;
|
||||
import com.volmit.iris.engine.jigsaw.PlannedStructure;
|
||||
import com.volmit.iris.engine.object.IrisJigsawPiece;
|
||||
import com.volmit.iris.engine.object.IrisJigsawStructure;
|
||||
import com.volmit.iris.engine.object.IrisObject;
|
||||
import com.volmit.iris.engine.object.IrisPosition;
|
||||
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.ObjectHandler;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import com.volmit.iris.util.plugin.VolmitSender;
|
||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
@@ -48,7 +48,7 @@ public class CommandJigsaw implements DecreeExecutor {
|
||||
IrisJigsawPiece piece
|
||||
) {
|
||||
File dest = piece.getLoadFile();
|
||||
new JigsawEditor(player(), piece, IrisData.loadAnyObject(piece.getObject(), data()), dest);
|
||||
new JigsawEditor(player(), piece, IrisData.loadAnyObject(piece.getObject()), 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, data());
|
||||
IrisObject o = IrisData.loadAnyObject(object);
|
||||
|
||||
if (object == null) {
|
||||
sender().sendMessage(C.RED + "Failed to find existing object");
|
||||
@@ -16,19 +16,19 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package art.arcane.iris.core.commands;
|
||||
package com.volmit.iris.core.commands;
|
||||
|
||||
import art.arcane.iris.Iris;
|
||||
import art.arcane.iris.core.IrisSettings;
|
||||
import art.arcane.iris.core.gui.PregeneratorJob;
|
||||
import art.arcane.iris.core.pregenerator.LazyPregenerator;
|
||||
import art.arcane.iris.core.pregenerator.PregenTask;
|
||||
import art.arcane.iris.core.tools.IrisToolbelt;
|
||||
import art.arcane.iris.util.decree.DecreeExecutor;
|
||||
import art.arcane.volmlib.util.decree.annotations.Decree;
|
||||
import art.arcane.volmlib.util.decree.annotations.Param;
|
||||
import art.arcane.iris.util.format.C;
|
||||
import art.arcane.iris.util.math.Position2;
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.gui.PregeneratorJob;
|
||||
import com.volmit.iris.core.pregenerator.LazyPregenerator;
|
||||
import com.volmit.iris.core.pregenerator.PregenTask;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.util.decree.DecreeExecutor;
|
||||
import com.volmit.iris.util.decree.annotations.Decree;
|
||||
import com.volmit.iris.util.decree.annotations.Param;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.math.Position2;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.util.Vector;
|
||||
@@ -16,28 +16,29 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package art.arcane.iris.core.commands;
|
||||
package com.volmit.iris.core.commands;
|
||||
|
||||
import art.arcane.iris.Iris;
|
||||
import art.arcane.iris.core.link.WorldEditLink;
|
||||
import art.arcane.iris.core.loader.IrisData;
|
||||
import art.arcane.iris.core.service.ObjectSVC;
|
||||
import art.arcane.iris.core.service.StudioSVC;
|
||||
import art.arcane.iris.core.service.WandSVC;
|
||||
import art.arcane.iris.core.tools.IrisConverter;
|
||||
import art.arcane.iris.engine.framework.Engine;
|
||||
import art.arcane.iris.engine.object.*;
|
||||
import art.arcane.volmlib.util.data.Cuboid;
|
||||
import art.arcane.iris.util.data.IrisCustomData;
|
||||
import art.arcane.iris.util.data.registry.Materials;
|
||||
import art.arcane.iris.util.decree.DecreeExecutor;
|
||||
import art.arcane.volmlib.util.decree.DecreeOrigin;
|
||||
import art.arcane.volmlib.util.decree.annotations.Decree;
|
||||
import art.arcane.volmlib.util.decree.annotations.Param;
|
||||
import art.arcane.iris.util.decree.specialhandlers.ObjectHandler;
|
||||
import art.arcane.iris.util.format.C;
|
||||
import art.arcane.iris.util.math.Direction;
|
||||
import art.arcane.volmlib.util.math.RNG;
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.link.WorldEditLink;
|
||||
import com.volmit.iris.core.loader.IrisData;
|
||||
import com.volmit.iris.core.service.ObjectSVC;
|
||||
import com.volmit.iris.core.service.StudioSVC;
|
||||
import com.volmit.iris.core.service.WandSVC;
|
||||
import com.volmit.iris.core.tools.IrisConverter;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.object.*;
|
||||
import com.volmit.iris.util.data.Cuboid;
|
||||
import com.volmit.iris.util.data.IrisCustomData;
|
||||
import com.volmit.iris.util.data.registry.Materials;
|
||||
import com.volmit.iris.util.decree.DecreeExecutor;
|
||||
import com.volmit.iris.util.decree.DecreeOrigin;
|
||||
import com.volmit.iris.util.decree.annotations.Decree;
|
||||
import com.volmit.iris.util.decree.annotations.Param;
|
||||
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;
|
||||
@@ -78,9 +79,9 @@ public class CommandObject implements DecreeExecutor {
|
||||
futureBlockChanges.put(block, block.getBlockData());
|
||||
|
||||
if (d instanceof IrisCustomData data) {
|
||||
block.setBlockData(data.getBase(), false);
|
||||
block.setBlockData(data.getBase());
|
||||
Iris.warn("Tried to place custom block at " + x + ", " + y + ", " + z + " which is not supported!");
|
||||
} else block.setBlockData(d, false);
|
||||
} else block.setBlockData(d);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -123,16 +124,6 @@ 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;
|
||||
@@ -145,11 +136,11 @@ public class CommandObject implements DecreeExecutor {
|
||||
@Param(description = "The object to analyze", customHandler = ObjectHandler.class)
|
||||
String object
|
||||
) {
|
||||
IrisObject o = IrisData.loadAnyObject(object, data());
|
||||
IrisObject o = IrisData.loadAnyObject(object);
|
||||
sender().sendMessage("Object Size: " + o.getW() + " * " + o.getH() + " * " + o.getD() + "");
|
||||
sender().sendMessage("Blocks Used: " + NumberFormat.getIntegerInstance().format(o.getBlocks().size()));
|
||||
|
||||
var queue = o.getBlocks().values();
|
||||
Queue<BlockData> queue = o.getBlocks().enqueueValues();
|
||||
Map<Material, Set<BlockData>> unsorted = new HashMap<>();
|
||||
Map<BlockData, Integer> amounts = new HashMap<>();
|
||||
Map<Material, Integer> materials = new HashMap<>();
|
||||
@@ -210,7 +201,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, data());
|
||||
IrisObject o = IrisData.loadAnyObject(object);
|
||||
sender().sendMessage("Current Object Size: " + o.getW() + " * " + o.getH() + " * " + o.getD());
|
||||
o.shrinkwrap();
|
||||
sender().sendMessage("New Object Size: " + o.getW() + " * " + o.getH() + " * " + o.getD());
|
||||
@@ -259,7 +250,7 @@ public class CommandObject implements DecreeExecutor {
|
||||
Cuboid cursor = new Cuboid(a1, a2);
|
||||
Direction d = Direction.closest(player().getLocation().getDirection()).reverse();
|
||||
assert d != null;
|
||||
cursor = cursor.expand(d.f(), -amount);
|
||||
cursor = cursor.expand(d, -amount);
|
||||
b[0] = cursor.getLowerNE();
|
||||
b[1] = cursor.getUpperSW();
|
||||
player().getInventory().setItemInMainHand(WandSVC.createWand(b[0], b[1]));
|
||||
@@ -334,7 +325,7 @@ public class CommandObject implements DecreeExecutor {
|
||||
// @Param(description = "The scale interpolator to use", defaultValue = "none")
|
||||
// IrisObjectPlacementScaleInterpolator interpolator
|
||||
) {
|
||||
IrisObject o = IrisData.loadAnyObject(object, data());
|
||||
IrisObject o = IrisData.loadAnyObject(object);
|
||||
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);
|
||||
@@ -16,17 +16,17 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package art.arcane.iris.core.commands;
|
||||
package com.volmit.iris.core.commands;
|
||||
|
||||
import art.arcane.iris.Iris;
|
||||
import art.arcane.iris.core.gui.PregeneratorJob;
|
||||
import art.arcane.iris.core.pregenerator.PregenTask;
|
||||
import art.arcane.iris.core.tools.IrisToolbelt;
|
||||
import art.arcane.iris.util.decree.DecreeExecutor;
|
||||
import art.arcane.volmlib.util.decree.annotations.Decree;
|
||||
import art.arcane.volmlib.util.decree.annotations.Param;
|
||||
import art.arcane.iris.util.format.C;
|
||||
import art.arcane.iris.util.math.Position2;
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.gui.PregeneratorJob;
|
||||
import com.volmit.iris.core.pregenerator.PregenTask;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.util.decree.DecreeExecutor;
|
||||
import com.volmit.iris.util.decree.annotations.Decree;
|
||||
import com.volmit.iris.util.decree.annotations.Param;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.math.Position2;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
@@ -16,9 +16,9 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package art.arcane.iris.core.commands;
|
||||
package com.volmit.iris.core.commands;
|
||||
|
||||
import art.arcane.iris.util.decree.DecreeExecutor;
|
||||
import com.volmit.iris.util.decree.DecreeExecutor;
|
||||
|
||||
public class CommandSettings implements DecreeExecutor {
|
||||
|
||||
@@ -16,51 +16,49 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package art.arcane.iris.core.commands;
|
||||
package com.volmit.iris.core.commands;
|
||||
|
||||
import art.arcane.iris.Iris;
|
||||
import art.arcane.iris.core.IrisSettings;
|
||||
import art.arcane.iris.core.gui.NoiseExplorerGUI;
|
||||
import art.arcane.iris.core.gui.VisionGUI;
|
||||
import art.arcane.iris.core.loader.IrisData;
|
||||
import art.arcane.iris.core.project.IrisProject;
|
||||
import art.arcane.iris.core.service.ConversionSVC;
|
||||
import art.arcane.iris.core.service.StudioSVC;
|
||||
import art.arcane.iris.core.tools.IrisToolbelt;
|
||||
import art.arcane.iris.engine.framework.Engine;
|
||||
import art.arcane.iris.engine.object.*;
|
||||
import art.arcane.iris.engine.platform.PlatformChunkGenerator;
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
import art.arcane.volmlib.util.collection.KMap;
|
||||
import art.arcane.volmlib.util.collection.KSet;
|
||||
import art.arcane.iris.util.decree.DecreeContext;
|
||||
import art.arcane.iris.util.decree.DecreeExecutor;
|
||||
import art.arcane.iris.util.decree.handlers.DimensionHandler;
|
||||
import art.arcane.iris.util.decree.specialhandlers.NullableDimensionHandler;
|
||||
import art.arcane.volmlib.util.decree.DecreeOrigin;
|
||||
import art.arcane.volmlib.util.decree.annotations.Decree;
|
||||
import art.arcane.volmlib.util.decree.annotations.Param;
|
||||
import art.arcane.iris.util.format.C;
|
||||
import art.arcane.volmlib.util.format.Form;
|
||||
import art.arcane.volmlib.util.function.Function2;
|
||||
import art.arcane.volmlib.util.function.NoiseProvider;
|
||||
import art.arcane.iris.util.interpolation.InterpolationMethod;
|
||||
import art.arcane.volmlib.util.io.IO;
|
||||
import art.arcane.volmlib.util.json.JSONArray;
|
||||
import art.arcane.volmlib.util.json.JSONObject;
|
||||
import art.arcane.iris.util.mantle.MantleChunk;
|
||||
import art.arcane.volmlib.util.math.M;
|
||||
import art.arcane.iris.util.math.Position2;
|
||||
import art.arcane.volmlib.util.math.RNG;
|
||||
import art.arcane.volmlib.util.math.Spiraler;
|
||||
import art.arcane.iris.util.noise.CNG;
|
||||
import art.arcane.iris.util.parallel.MultiBurst;
|
||||
import art.arcane.iris.util.parallel.SyncExecutor;
|
||||
import art.arcane.iris.util.plugin.VolmitSender;
|
||||
import art.arcane.iris.util.scheduling.J;
|
||||
import art.arcane.volmlib.util.scheduling.O;
|
||||
import art.arcane.volmlib.util.scheduling.PrecisionStopwatch;
|
||||
import art.arcane.iris.util.scheduling.jobs.ParallelRadiusJob;
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.gui.NoiseExplorerGUI;
|
||||
import com.volmit.iris.core.gui.VisionGUI;
|
||||
import com.volmit.iris.core.loader.IrisData;
|
||||
import com.volmit.iris.core.project.IrisProject;
|
||||
import com.volmit.iris.core.service.ConversionSVC;
|
||||
import com.volmit.iris.core.service.StudioSVC;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.object.*;
|
||||
import com.volmit.iris.engine.platform.PlatformChunkGenerator;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.collection.KSet;
|
||||
import com.volmit.iris.util.decree.DecreeContext;
|
||||
import com.volmit.iris.util.decree.DecreeExecutor;
|
||||
import com.volmit.iris.util.decree.DecreeOrigin;
|
||||
import com.volmit.iris.util.decree.annotations.Decree;
|
||||
import com.volmit.iris.util.decree.annotations.Param;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.function.Function2;
|
||||
import com.volmit.iris.util.function.NoiseProvider;
|
||||
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.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.ParallelQueueJob;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.event.inventory.InventoryType;
|
||||
@@ -80,7 +78,6 @@ import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@@ -111,24 +108,17 @@ public class CommandStudio implements DecreeExecutor {
|
||||
|
||||
@Decree(description = "Open a new studio world", aliases = "o", sync = true)
|
||||
public void open(
|
||||
@Param(defaultValue = "default", description = "The dimension to open a studio for", aliases = "dim", customHandler = DimensionHandler.class)
|
||||
@Param(defaultValue = "default", description = "The dimension to open a studio for", aliases = "dim")
|
||||
IrisDimension dimension,
|
||||
@Param(defaultValue = "1337", description = "The seed to generate the studio with", aliases = "s")
|
||||
long seed) {
|
||||
if (J.isFolia()) {
|
||||
sender().sendMessage(C.RED + "Studio world opening is disabled on Folia.");
|
||||
sender().sendMessage(C.YELLOW + "Folia does not currently support runtime world creation via Bukkit.createWorld().");
|
||||
sender().sendMessage(C.YELLOW + "Use Paper/Purpur for Studio mode, or preconfigure worlds and restart.");
|
||||
return;
|
||||
}
|
||||
|
||||
sender().sendMessage(C.GREEN + "Opening studio for the \"" + dimension.getName() + "\" pack (seed: " + seed + ")");
|
||||
Iris.service(StudioSVC.class).open(sender(), seed, dimension.getLoadKey());
|
||||
}
|
||||
|
||||
@Decree(description = "Open VSCode for a dimension", aliases = {"vsc", "edit"})
|
||||
public void vscode(
|
||||
@Param(defaultValue = "default", description = "The dimension to open VSCode for", aliases = "dim", customHandler = DimensionHandler.class)
|
||||
@Param(defaultValue = "default", description = "The dimension to open VSCode for", aliases = "dim")
|
||||
IrisDimension dimension
|
||||
) {
|
||||
sender().sendMessage(C.GREEN + "Opening VSCode for the \"" + dimension.getName() + "\" pack");
|
||||
@@ -150,11 +140,7 @@ public class CommandStudio implements DecreeExecutor {
|
||||
public void create(
|
||||
@Param(description = "The name of this new Iris Project.")
|
||||
String name,
|
||||
@Param(
|
||||
description = "Copy the contents of an existing project in your packs folder and use it as a template in this new project.",
|
||||
contextual = true,
|
||||
customHandler = NullableDimensionHandler.class
|
||||
)
|
||||
@Param(description = "Copy the contents of an existing project in your packs folder and use it as a template in this new project.", contextual = true)
|
||||
IrisDimension template) {
|
||||
if (template != null) {
|
||||
Iris.service(StudioSVC.class).create(sender(), name, template.getLoadKey());
|
||||
@@ -165,7 +151,7 @@ public class CommandStudio implements DecreeExecutor {
|
||||
|
||||
@Decree(description = "Get the version of a pack")
|
||||
public void version(
|
||||
@Param(defaultValue = "default", description = "The dimension get the version of", aliases = "dim", contextual = true, customHandler = DimensionHandler.class)
|
||||
@Param(defaultValue = "default", description = "The dimension get the version of", aliases = "dim", contextual = true)
|
||||
IrisDimension dimension
|
||||
) {
|
||||
sender().sendMessage(C.GREEN + "The \"" + dimension.getName() + "\" pack has version: " + dimension.getVersion());
|
||||
@@ -185,63 +171,82 @@ public class CommandStudio implements DecreeExecutor {
|
||||
var loc = player().getLocation().clone();
|
||||
|
||||
J.a(() -> {
|
||||
DecreeContext.touch(sender);
|
||||
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())
|
||||
) {
|
||||
try (SyncExecutor executor = new SyncExecutor(20)) {
|
||||
int x = loc.getBlockX() >> 4;
|
||||
int z = loc.getBlockZ() >> 4;
|
||||
|
||||
int rad = engine.getMantle().getRadius();
|
||||
var mantle = engine.getMantle().getMantle();
|
||||
var chunkMap = new KMap<Position2, MantleChunk>();
|
||||
ParallelRadiusJob prep = new ParallelRadiusJob(Integer.MAX_VALUE, service) {
|
||||
ParallelQueueJob<Position2> prep = new ParallelQueueJob<>() {
|
||||
@Override
|
||||
protected void execute(int rX, int rZ) {
|
||||
if (Math.abs(rX) <= radius && Math.abs(rZ) <= radius) {
|
||||
mantle.deleteChunk(rX + x, rZ + z);
|
||||
public void execute(Position2 pos) {
|
||||
var cpos = pos.add(x, z);
|
||||
if (Math.abs(pos.getX()) <= radius && Math.abs(pos.getZ()) <= radius) {
|
||||
mantle.deleteChunk(cpos.getX(), cpos.getZ());
|
||||
return;
|
||||
}
|
||||
rX += x;
|
||||
rZ += z;
|
||||
chunkMap.put(new Position2(rX, rZ), mantle.getChunk(rX, rZ));
|
||||
mantle.deleteChunk(rX, rZ);
|
||||
chunkMap.put(cpos, mantle.getChunk(cpos.getX(), cpos.getZ()));
|
||||
mantle.deleteChunk(cpos.getX(), cpos.getZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Preparing Mantle";
|
||||
}
|
||||
}.retarget(radius + rad, 0, 0);
|
||||
};
|
||||
for (int xx = -(radius + rad); xx <= radius + rad; xx++) {
|
||||
for (int zz = -(radius + rad); zz <= radius + rad; zz++) {
|
||||
prep.queue(new Position2(xx, zz));
|
||||
}
|
||||
}
|
||||
CountDownLatch pLatch = new CountDownLatch(1);
|
||||
prep.execute(sender(), pLatch::countDown);
|
||||
pLatch.await();
|
||||
|
||||
|
||||
ParallelRadiusJob job = new ParallelRadiusJob(Integer.MAX_VALUE, service) {
|
||||
ParallelQueueJob<Position2> job = new ParallelQueueJob<>() {
|
||||
@Override
|
||||
protected void execute(int x, int z) {
|
||||
plat.injectChunkReplacement(world, x, z, executor);
|
||||
public void execute(Position2 p) {
|
||||
plat.injectChunkReplacement(world, p.getX(), p.getZ(), executor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Regenerating";
|
||||
}
|
||||
}.retarget(radius, x, z);
|
||||
};
|
||||
for (int i = -radius; i <= radius; i++) {
|
||||
for (int j = -radius; j <= radius; j++) {
|
||||
job.queue(new Position2(i + x, j + z));
|
||||
}
|
||||
}
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
job.execute(sender(), latch::countDown);
|
||||
latch.await();
|
||||
|
||||
chunkMap.forEach((pos, chunk) ->
|
||||
mantle.getChunk(pos.getX(), pos.getZ()).copyFrom(chunk));
|
||||
int sections = mantle.getWorldHeight() >> 4;
|
||||
chunkMap.forEach((pos, chunk) -> {
|
||||
var c = mantle.getChunk(pos.getX(), pos.getZ()).use();
|
||||
try {
|
||||
c.copyFlags(chunk);
|
||||
c.clear();
|
||||
for (int y = 0; y < sections; y++) {
|
||||
var slice = chunk.get(y);
|
||||
if (slice == null) continue;
|
||||
var s = c.getOrCreate(y);
|
||||
slice.getSliceMap().forEach(s::putSlice);
|
||||
}
|
||||
} finally {
|
||||
c.release();
|
||||
}
|
||||
});
|
||||
} catch (Throwable e) {
|
||||
sender().sendMessage("Error while regenerating chunks");
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
DecreeContext.remove();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -332,15 +337,11 @@ public class CommandStudio implements DecreeExecutor {
|
||||
O<Integer> ta = new O<>();
|
||||
ta.set(-1);
|
||||
|
||||
var sender = sender();
|
||||
var player = player();
|
||||
var engine = engine();
|
||||
|
||||
ta.set(J.sr(() ->
|
||||
ta.set(Bukkit.getScheduler().scheduleSyncRepeatingTask(Iris.instance, () ->
|
||||
{
|
||||
if (!player.getOpenInventory().getType().equals(InventoryType.CHEST)) {
|
||||
J.csr(ta.get());
|
||||
sender.sendMessage(C.GREEN + "Opened inventory!");
|
||||
if (!player().getOpenInventory().getType().equals(InventoryType.CHEST)) {
|
||||
Bukkit.getScheduler().cancelTask(ta.get());
|
||||
sender().sendMessage(C.GREEN + "Opened inventory!");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -348,8 +349,8 @@ 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);
|
||||
}, fast ? 5 : 35));
|
||||
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);
|
||||
@@ -476,7 +477,7 @@ public class CommandStudio implements DecreeExecutor {
|
||||
|
||||
@Decree(description = "Package a dimension into a compressed format", aliases = "package")
|
||||
public void pkg(
|
||||
@Param(name = "dimension", description = "The dimension pack to compress", contextual = true, defaultValue = "default", customHandler = DimensionHandler.class)
|
||||
@Param(name = "dimension", description = "The dimension pack to compress", contextual = true, defaultValue = "default")
|
||||
IrisDimension dimension,
|
||||
@Param(name = "obfuscate", description = "Whether or not to obfuscate the pack", defaultValue = "false")
|
||||
boolean obfuscate,
|
||||
@@ -488,7 +489,7 @@ public class CommandStudio implements DecreeExecutor {
|
||||
|
||||
@Decree(description = "Profiles the performance of a dimension", origin = DecreeOrigin.PLAYER)
|
||||
public void profile(
|
||||
@Param(description = "The dimension to profile", contextual = true, defaultValue = "default", customHandler = DimensionHandler.class)
|
||||
@Param(description = "The dimension to profile", contextual = true, defaultValue = "default")
|
||||
IrisDimension dimension
|
||||
) {
|
||||
// Todo: Make this more accurate
|
||||
@@ -701,19 +702,13 @@ public class CommandStudio implements DecreeExecutor {
|
||||
}
|
||||
|
||||
sender().sendMessage(C.GREEN + "Sending you to the studio world!");
|
||||
var player = player();
|
||||
PaperLib.teleportAsync(player(), Iris.service(StudioSVC.class)
|
||||
.getActiveProject()
|
||||
.getActiveProvider()
|
||||
.getTarget()
|
||||
.getWorld()
|
||||
.spawnLocation()
|
||||
).thenRun(() -> player.setGameMode(GameMode.SPECTATOR));
|
||||
player().teleport(Iris.service(StudioSVC.class).getActiveProject().getActiveProvider().getTarget().getWorld().spawnLocation());
|
||||
player().setGameMode(GameMode.SPECTATOR);
|
||||
}
|
||||
|
||||
@Decree(description = "Update your dimension projects VSCode workspace")
|
||||
public void update(
|
||||
@Param(description = "The dimension to update the workspace of", contextual = true, defaultValue = "default", customHandler = DimensionHandler.class)
|
||||
@Param(description = "The dimension to update the workspace of", contextual = true, defaultValue = "default")
|
||||
IrisDimension dimension
|
||||
) {
|
||||
sender().sendMessage(C.GOLD + "Updating Code Workspace for " + dimension.getName() + "...");
|
||||
@@ -16,16 +16,16 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package art.arcane.iris.core.commands;
|
||||
package com.volmit.iris.core.commands;
|
||||
|
||||
import art.arcane.iris.Iris;
|
||||
import art.arcane.iris.core.pregenerator.LazyPregenerator;
|
||||
import art.arcane.iris.core.pregenerator.TurboPregenerator;
|
||||
import art.arcane.iris.core.pregenerator.TurboPregenerator;
|
||||
import art.arcane.iris.util.decree.DecreeExecutor;
|
||||
import art.arcane.volmlib.util.decree.annotations.Decree;
|
||||
import art.arcane.volmlib.util.decree.annotations.Param;
|
||||
import art.arcane.iris.util.format.C;
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.pregenerator.LazyPregenerator;
|
||||
import com.volmit.iris.core.pregenerator.TurboPregenerator;
|
||||
import com.volmit.iris.core.pregenerator.TurboPregenerator;
|
||||
import com.volmit.iris.util.decree.DecreeExecutor;
|
||||
import com.volmit.iris.util.decree.annotations.Decree;
|
||||
import com.volmit.iris.util.decree.annotations.Param;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.util.Vector;
|
||||
@@ -16,20 +16,20 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package art.arcane.iris.core.commands;
|
||||
package com.volmit.iris.core.commands;
|
||||
|
||||
import lombok.Synchronized;
|
||||
import org.bukkit.World;
|
||||
|
||||
import art.arcane.iris.Iris;
|
||||
import art.arcane.iris.core.pregenerator.ChunkUpdater;
|
||||
import art.arcane.iris.core.tools.IrisToolbelt;
|
||||
import art.arcane.iris.util.decree.DecreeExecutor;
|
||||
import art.arcane.volmlib.util.decree.DecreeOrigin;
|
||||
import art.arcane.volmlib.util.decree.annotations.Decree;
|
||||
import art.arcane.volmlib.util.decree.annotations.Param;
|
||||
import art.arcane.iris.util.format.C;
|
||||
import art.arcane.volmlib.util.format.Form;
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.pregenerator.ChunkUpdater;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.util.decree.DecreeExecutor;
|
||||
import com.volmit.iris.util.decree.DecreeOrigin;
|
||||
import com.volmit.iris.util.decree.annotations.Decree;
|
||||
import com.volmit.iris.util.decree.annotations.Param;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
|
||||
@Decree(name = "updater", origin = DecreeOrigin.BOTH, description = "Iris World Updater")
|
||||
public class CommandUpdater implements DecreeExecutor {
|
||||
@@ -16,23 +16,23 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package art.arcane.iris.core.commands;
|
||||
package com.volmit.iris.core.commands;
|
||||
|
||||
import art.arcane.iris.Iris;
|
||||
import art.arcane.iris.core.edit.BlockSignal;
|
||||
import art.arcane.iris.core.nms.INMS;
|
||||
import art.arcane.iris.core.tools.IrisToolbelt;
|
||||
import art.arcane.iris.engine.framework.Engine;
|
||||
import art.arcane.iris.engine.object.IrisBiome;
|
||||
import art.arcane.iris.engine.object.IrisRegion;
|
||||
import art.arcane.iris.util.data.B;
|
||||
import art.arcane.iris.util.decree.DecreeExecutor;
|
||||
import art.arcane.volmlib.util.decree.DecreeOrigin;
|
||||
import art.arcane.volmlib.util.decree.annotations.Decree;
|
||||
import art.arcane.volmlib.util.decree.annotations.Param;
|
||||
import art.arcane.iris.util.format.C;
|
||||
import art.arcane.volmlib.util.matter.MatterMarker;
|
||||
import art.arcane.iris.util.scheduling.J;
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.edit.BlockSignal;
|
||||
import com.volmit.iris.core.nms.INMS;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.object.IrisBiome;
|
||||
import com.volmit.iris.engine.object.IrisRegion;
|
||||
import com.volmit.iris.util.data.B;
|
||||
import com.volmit.iris.util.decree.DecreeExecutor;
|
||||
import com.volmit.iris.util.decree.DecreeOrigin;
|
||||
import com.volmit.iris.util.decree.annotations.Decree;
|
||||
import com.volmit.iris.util.decree.annotations.Param;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.matter.MatterMarker;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.FluidCollisionMode;
|
||||
import org.bukkit.Material;
|
||||
@@ -16,7 +16,7 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package art.arcane.iris.core.edit;
|
||||
package com.volmit.iris.core.edit;
|
||||
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
@@ -16,11 +16,11 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package art.arcane.iris.core.edit;
|
||||
package com.volmit.iris.core.edit;
|
||||
|
||||
import art.arcane.iris.util.parallel.MultiBurst;
|
||||
import art.arcane.iris.util.scheduling.J;
|
||||
import art.arcane.volmlib.util.scheduling.SR;
|
||||
import com.volmit.iris.util.parallel.MultiBurst;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import com.volmit.iris.util.scheduling.SR;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
@@ -16,9 +16,9 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package art.arcane.iris.core.edit;
|
||||
package com.volmit.iris.core.edit;
|
||||
|
||||
import art.arcane.volmlib.util.math.M;
|
||||
import com.volmit.iris.util.math.M;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
@@ -16,17 +16,17 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package art.arcane.iris.core.edit;
|
||||
package com.volmit.iris.core.edit;
|
||||
|
||||
import art.arcane.iris.Iris;
|
||||
import art.arcane.iris.core.tools.IrisToolbelt;
|
||||
import art.arcane.iris.engine.framework.Engine;
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
import art.arcane.volmlib.util.math.BlockPosition;
|
||||
import art.arcane.volmlib.util.math.M;
|
||||
import art.arcane.volmlib.util.math.RNG;
|
||||
import art.arcane.iris.util.plugin.VolmitSender;
|
||||
import art.arcane.iris.util.scheduling.J;
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.math.BlockPosition;
|
||||
import com.volmit.iris.util.math.M;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import com.volmit.iris.util.plugin.VolmitSender;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import lombok.Data;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.World;
|
||||
@@ -16,20 +16,20 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package art.arcane.iris.core.edit;
|
||||
package com.volmit.iris.core.edit;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import art.arcane.iris.Iris;
|
||||
import art.arcane.iris.core.service.WandSVC;
|
||||
import art.arcane.iris.engine.object.*;
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
import art.arcane.volmlib.util.collection.KMap;
|
||||
import art.arcane.volmlib.util.data.Cuboid;
|
||||
import art.arcane.volmlib.util.io.IO;
|
||||
import art.arcane.volmlib.util.json.JSONObject;
|
||||
import art.arcane.volmlib.util.math.RNG;
|
||||
import art.arcane.volmlib.util.scheduling.ChronoLatch;
|
||||
import art.arcane.iris.util.scheduling.J;
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.service.WandSVC;
|
||||
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.data.Cuboid;
|
||||
import com.volmit.iris.util.io.IO;
|
||||
import com.volmit.iris.util.json.JSONObject;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import com.volmit.iris.util.scheduling.ChronoLatch;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Particle;
|
||||
@@ -61,14 +61,14 @@ public class JigsawEditor implements Listener {
|
||||
private Location target;
|
||||
|
||||
public JigsawEditor(Player player, IrisJigsawPiece piece, IrisObject object, File saveLocation) {
|
||||
if (object == null) throw new RuntimeException("Object is null! " + piece.getObject());
|
||||
editors.compute(player, ($, current) -> {
|
||||
if (current != null) {
|
||||
current.exit();
|
||||
}
|
||||
return this;
|
||||
});
|
||||
if (editors.containsKey(player)) {
|
||||
editors.get(player).close();
|
||||
}
|
||||
|
||||
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);
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user