mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2026-10-25 13:30:10 +00:00
Merge pull request #43 from PolyhedralDev/agnostic
Platform-agnostic engine & TerraScript structures
This commit is contained in:
568 files changed
+21651
-4872
No files matched your search
@@ -137,3 +137,9 @@ build
|
|||||||
|
|
||||||
!lib/*.jar
|
!lib/*.jar
|
||||||
.idea/Terra.iml
|
.idea/Terra.iml
|
||||||
|
/run/
|
||||||
|
.idea/**.iml
|
||||||
|
/lang/
|
||||||
|
/packs/
|
||||||
|
/config.yml
|
||||||
|
/region/
|
||||||
+6
-211
@@ -1,192 +1,11 @@
|
|||||||
//import java.util.zip.ZipFile
|
import com.dfsek.terra.getGitHash
|
||||||
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
|
|
||||||
import java.io.ByteArrayOutputStream
|
|
||||||
import java.net.URL
|
|
||||||
import java.nio.channels.Channels
|
|
||||||
import java.nio.file.Files
|
|
||||||
import java.nio.file.Paths
|
|
||||||
import java.nio.file.StandardCopyOption
|
|
||||||
|
|
||||||
plugins {
|
val versionObj = Version("3", "0", "0", true)
|
||||||
java
|
|
||||||
maven
|
allprojects {
|
||||||
id("com.github.johnrengelman.shadow").version("6.1.0")
|
version = versionObj
|
||||||
|
group = "com.dfsek.terra"
|
||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
|
||||||
maven { url = uri("https://hub.spigotmc.org/nexus/content/repositories/snapshots/") }
|
|
||||||
maven { url = uri("http://maven.enginehub.org/repo/") }
|
|
||||||
maven { url = uri("https://repo.codemc.org/repository/maven-public") }
|
|
||||||
maven { url = uri("https://papermc.io/repo/repository/maven-public/") }
|
|
||||||
}
|
|
||||||
|
|
||||||
java {
|
|
||||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
|
||||||
targetCompatibility = JavaVersion.VERSION_1_8
|
|
||||||
}
|
|
||||||
|
|
||||||
val versionObj = Version("2", "1", "1", true)
|
|
||||||
|
|
||||||
version = versionObj
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
val gaeaVersion = "1.15.0"
|
|
||||||
compileOnly("org.polydev.gaea:Gaea:${gaeaVersion}")
|
|
||||||
testImplementation("org.polydev.gaea:Gaea:${gaeaVersion}")
|
|
||||||
|
|
||||||
compileOnly("org.jetbrains:annotations:20.1.0")
|
|
||||||
|
|
||||||
implementation("commons-io:commons-io:2.4")
|
|
||||||
implementation("org.apache.commons:commons-imaging:1.0-alpha2")
|
|
||||||
|
|
||||||
compileOnly("com.sk89q.worldedit:worldedit-bukkit:7.2.0-SNAPSHOT")
|
|
||||||
implementation("org.bstats:bstats-bukkit:1.7")
|
|
||||||
|
|
||||||
compileOnly("com.googlecode.json-simple:json-simple:1.1")
|
|
||||||
|
|
||||||
implementation("com.scireum:parsii:1.2.1")
|
|
||||||
|
|
||||||
compileOnly("org.spigotmc:spigot-api:1.16.2-R0.1-SNAPSHOT")
|
|
||||||
implementation("io.papermc:paperlib:1.0.5")
|
|
||||||
|
|
||||||
implementation("net.jafama:jafama:2.3.2")
|
|
||||||
|
|
||||||
implementation("com.dfsek:Tectonic:1.0.3")
|
|
||||||
|
|
||||||
|
|
||||||
// JUnit.
|
|
||||||
testImplementation("org.junit.jupiter:junit-jupiter-api:5.7.0")
|
|
||||||
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.7.0")
|
|
||||||
}
|
|
||||||
|
|
||||||
val compileJava: JavaCompile by tasks
|
|
||||||
val mainSourceSet: SourceSet = sourceSets["main"]
|
|
||||||
|
|
||||||
tasks.withType<ProcessResources> {
|
|
||||||
include("**/*.yml")
|
|
||||||
filter<org.apache.tools.ant.filters.ReplaceTokens>(
|
|
||||||
"tokens" to mapOf(
|
|
||||||
"VERSION" to project.version.toString()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
compileJava.apply {
|
|
||||||
options.encoding = "UTF-8"
|
|
||||||
doFirst {
|
|
||||||
options.compilerArgs = mutableListOf("-Xlint:all")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.test {
|
|
||||||
useJUnitPlatform()
|
|
||||||
|
|
||||||
maxHeapSize = "4G"
|
|
||||||
ignoreFailures = false
|
|
||||||
failFast = true
|
|
||||||
maxParallelForks = 12
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.named<ShadowJar>("shadowJar") {
|
|
||||||
// Tell shadow to download the packs
|
|
||||||
dependsOn(downloadDefaultPacks)
|
|
||||||
|
|
||||||
archiveClassifier.set("")
|
|
||||||
archiveBaseName.set("Terra")
|
|
||||||
setVersion(project.version)
|
|
||||||
relocate("org.apache.commons", "com.dfsek.terra.lib.commons")
|
|
||||||
relocate("org.bstats.bukkit", "com.dfsek.terra.lib.bstats")
|
|
||||||
relocate("parsii", "com.dfsek.terra.lib.parsii")
|
|
||||||
relocate("io.papermc.lib", "com.dfsek.terra.lib.paperlib")
|
|
||||||
relocate("net.jafama", "com.dfsek.terra.lib.jafama")
|
|
||||||
relocate("com.dfsek.tectonic", "com.dfsek.terra.lib.tectonic")
|
|
||||||
minimize()
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.build {
|
|
||||||
dependsOn(tasks.shadowJar)
|
|
||||||
// dependsOn(testWithPaper)
|
|
||||||
// testWithPaper.mustRunAfter(tasks.shadowJar)
|
|
||||||
}
|
|
||||||
|
|
||||||
val testDir = "target/server/"
|
|
||||||
|
|
||||||
val setupServer = tasks.create("setupServer") {
|
|
||||||
dependsOn(tasks.shadowJar)
|
|
||||||
doFirst {
|
|
||||||
// clean
|
|
||||||
file("${testDir}/").deleteRecursively()
|
|
||||||
file("${testDir}/plugins").mkdirs()
|
|
||||||
|
|
||||||
// Downloading latest paper jar.
|
|
||||||
val paperUrl = URL("https://papermc.io/api/v1/paper/1.16.4/latest/download")
|
|
||||||
val paperReadableByteChannel = Channels.newChannel(paperUrl.openStream())
|
|
||||||
val paperFile = file("${testDir}/paper.jar")
|
|
||||||
val paperFileOutputStream = paperFile.outputStream()
|
|
||||||
val paperFileChannel = paperFileOutputStream.channel
|
|
||||||
paperFileChannel.transferFrom(paperReadableByteChannel, 0, Long.MAX_VALUE)
|
|
||||||
|
|
||||||
// Cloning test setup.
|
|
||||||
gitClone("https://github.com/PolyhedralDev/WorldGenTestServer")
|
|
||||||
// Copying plugins
|
|
||||||
Files.move(Paths.get("WorldGenTestServer/plugins"),
|
|
||||||
Paths.get("$testDir/plugins"),
|
|
||||||
StandardCopyOption.REPLACE_EXISTING)
|
|
||||||
// Copying config
|
|
||||||
val serverText = URL("https://raw.githubusercontent.com/PolyhedralDev/WorldGenTestServer/master/server.properties").readText()
|
|
||||||
file("${testDir}/server.properties").writeText(serverText)
|
|
||||||
val bukkitText = URL("https://raw.githubusercontent.com/PolyhedralDev/WorldGenTestServer/master/bukkit.yml").readText()
|
|
||||||
file("${testDir}/bukkit.yml").writeText(bukkitText.replace("\${world}", "world").replace("\${gen}", "Terra:DEFAULT"))
|
|
||||||
|
|
||||||
File("${testDir}/eula.txt").writeText("eula=true")
|
|
||||||
|
|
||||||
// clean up
|
|
||||||
file("WorldGenTestServer").deleteRecursively()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val downloadDefaultPacks = tasks.create("downloadDefaultPacks") {
|
|
||||||
doFirst {
|
|
||||||
// Downloading latest paper jar.
|
|
||||||
// if (file("${buildDir}/resources/main/packs/default").exists() && file("${buildDir}/resources/main/packs/nether").exists())
|
|
||||||
// return@doFirst
|
|
||||||
// else
|
|
||||||
file("${buildDir}/resources/main/packs/").deleteRecursively()
|
|
||||||
|
|
||||||
val defaultPackUrl = URL("https://github.com/PolyhedralDev/TerraDefaultConfig/releases/download/latest/default.zip")
|
|
||||||
downloadPack(defaultPackUrl)
|
|
||||||
val netherPackUrl = URL("https://github.com/PolyhedralDev/TerraDefaultConfig/releases/download/latest/nether.zip")
|
|
||||||
downloadPack(netherPackUrl)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val testWithPaper = task<JavaExec>(name = "testWithPaper") {
|
|
||||||
standardInput = System.`in`
|
|
||||||
dependsOn(tasks.shadowJar)
|
|
||||||
// Copy Terra into dir
|
|
||||||
doFirst {
|
|
||||||
copy {
|
|
||||||
from("${buildDir}/libs/Terra-${versionObj}.jar")
|
|
||||||
into("${testDir}/plugins/")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
main = "io.papermc.paperclip.Paperclip"
|
|
||||||
jvmArgs = listOf("-XX:+UseG1GC", "-XX:+ParallelRefProcEnabled", "-XX:MaxGCPauseMillis=200",
|
|
||||||
"-XX:+UnlockExperimentalVMOptions", "-XX:+DisableExplicitGC", "-XX:+AlwaysPreTouch",
|
|
||||||
"-XX:G1NewSizePercent=30", "-XX:G1MaxNewSizePercent=40", "-XX:G1HeapRegionSize=8M",
|
|
||||||
"-XX:G1ReservePercent=20", "-XX:G1HeapWastePercent=5", "-XX:G1MixedGCCountTarget=4",
|
|
||||||
"-XX:InitiatingHeapOccupancyPercent=15", "-XX:G1MixedGCLiveThresholdPercent=90",
|
|
||||||
"-XX:G1RSetUpdatingPauseTimePercent=5", "-XX:SurvivorRatio=32", "-XX:+PerfDisableSharedMem",
|
|
||||||
"-XX:MaxTenuringThreshold=1", "-Dusing.aikars.flags=https://mcflags.emc.gs",
|
|
||||||
"-Daikars.new.flags=true", "-DIReallyKnowWhatIAmDoingISwear")
|
|
||||||
maxHeapSize = "2G"
|
|
||||||
args = listOf("nogui")
|
|
||||||
workingDir = file("${testDir}/")
|
|
||||||
classpath = files("${testDir}/paper.jar")
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Version class that does version stuff.
|
* Version class that does version stuff.
|
||||||
*/
|
*/
|
||||||
@@ -199,28 +18,4 @@ class Version(val major: String, val minor: String, val revision: String, val pr
|
|||||||
else //Only use git hash if it's a prerelease.
|
else //Only use git hash if it's a prerelease.
|
||||||
"$major.$minor.$revision-BETA+${getGitHash()}"
|
"$major.$minor.$revision-BETA+${getGitHash()}"
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fun getGitHash(): String {
|
|
||||||
val stdout = ByteArrayOutputStream()
|
|
||||||
exec {
|
|
||||||
commandLine = mutableListOf("git", "rev-parse", "--short", "HEAD")
|
|
||||||
standardOutput = stdout
|
|
||||||
}
|
|
||||||
return stdout.toString().trim()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun gitClone(name: String) {
|
|
||||||
val stdout = ByteArrayOutputStream()
|
|
||||||
exec {
|
|
||||||
commandLine = mutableListOf("git", "clone", name)
|
|
||||||
standardOutput = stdout
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun downloadPack(packUrl: URL) {
|
|
||||||
val fileName = packUrl.file.substring(packUrl.file.lastIndexOf("/"))
|
|
||||||
val file = file("${buildDir}/resources/main/packs/${fileName}")
|
|
||||||
file.parentFile.mkdirs()
|
|
||||||
file.outputStream().write(packUrl.readBytes())
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
plugins {
|
||||||
|
`kotlin-dsl`
|
||||||
|
kotlin("jvm") version embeddedKotlinVersion
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
gradlePluginPortal()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
"implementation"("com.github.jengelman.gradle.plugins:shadow:+")
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
package com.dfsek.terra
|
||||||
|
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.api.tasks.testing.Test
|
||||||
|
import org.gradle.kotlin.dsl.apply
|
||||||
|
import org.gradle.kotlin.dsl.withType
|
||||||
|
import java.io.ByteArrayOutputStream
|
||||||
|
|
||||||
|
fun Project.configureCommon() {
|
||||||
|
apply(plugin = "java-library")
|
||||||
|
apply(plugin = "maven-publish")
|
||||||
|
apply(plugin = "idea")
|
||||||
|
|
||||||
|
configureDependencies()
|
||||||
|
configureCompilation()
|
||||||
|
configureDistribution()
|
||||||
|
|
||||||
|
version = rootProject.version
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
tasks.withType<Test>().configureEach {
|
||||||
|
useJUnitPlatform()
|
||||||
|
|
||||||
|
maxHeapSize = "2G"
|
||||||
|
ignoreFailures = false
|
||||||
|
failFast = true
|
||||||
|
maxParallelForks = 12
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Project.getGitHash(): String {
|
||||||
|
val stdout = java.io.ByteArrayOutputStream()
|
||||||
|
exec {
|
||||||
|
commandLine = mutableListOf("git", "rev-parse", "--short", "HEAD")
|
||||||
|
standardOutput = stdout
|
||||||
|
}
|
||||||
|
return stdout.toString().trim()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Project.gitClone(name: String) {
|
||||||
|
val stdout = ByteArrayOutputStream()
|
||||||
|
exec {
|
||||||
|
commandLine = mutableListOf("git", "clone", name)
|
||||||
|
standardOutput = stdout
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package com.dfsek.terra
|
||||||
|
|
||||||
|
import org.gradle.api.JavaVersion
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.api.plugins.JavaPluginConvention
|
||||||
|
import org.gradle.api.tasks.compile.JavaCompile
|
||||||
|
import org.gradle.api.tasks.javadoc.Javadoc
|
||||||
|
import org.gradle.kotlin.dsl.configure
|
||||||
|
import org.gradle.kotlin.dsl.withType
|
||||||
|
|
||||||
|
fun Project.configureCompilation() {
|
||||||
|
configure<JavaPluginConvention> {
|
||||||
|
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||||
|
targetCompatibility = JavaVersion.VERSION_1_8
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.withType<JavaCompile> {
|
||||||
|
options.encoding = "UTF-8"
|
||||||
|
doFirst {
|
||||||
|
options.compilerArgs = mutableListOf("-Xlint:all")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.withType<Javadoc> {
|
||||||
|
options.encoding = "UTF-8"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package com.dfsek.terra
|
||||||
|
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.kotlin.dsl.dependencies
|
||||||
|
import org.gradle.kotlin.dsl.repositories
|
||||||
|
|
||||||
|
fun Project.configureDependencies() {
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
maven { url = uri("https://hub.spigotmc.org/nexus/content/repositories/snapshots/") }
|
||||||
|
maven { url = uri("http://maven.enginehub.org/repo/") }
|
||||||
|
maven { url = uri("https://repo.codemc.org/repository/maven-public") }
|
||||||
|
maven { url = uri("https://papermc.io/repo/repository/maven-public/") }
|
||||||
|
maven { url = uri("https://maven.fabricmc.net/") }
|
||||||
|
gradlePluginPortal()
|
||||||
|
jcenter()
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
"testImplementation"("org.junit.jupiter:junit-jupiter-api:5.7.0")
|
||||||
|
"testRuntimeOnly"("org.junit.jupiter:junit-jupiter-engine:5.7.0")
|
||||||
|
"compileOnly"("org.jetbrains:annotations:20.1.0")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
package com.dfsek.terra
|
||||||
|
|
||||||
|
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
|
||||||
|
import org.gradle.api.DefaultTask
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.api.plugins.BasePluginConvention
|
||||||
|
import org.gradle.api.tasks.bundling.Jar
|
||||||
|
import org.gradle.api.tasks.javadoc.Javadoc
|
||||||
|
import org.gradle.kotlin.dsl.*
|
||||||
|
import java.io.File
|
||||||
|
import java.net.URL
|
||||||
|
|
||||||
|
fun Project.configureDistribution() {
|
||||||
|
apply(plugin = "java-library")
|
||||||
|
apply(plugin = "com.github.johnrengelman.shadow")
|
||||||
|
|
||||||
|
|
||||||
|
// configurations.create("shaded")
|
||||||
|
|
||||||
|
configurations {
|
||||||
|
val shaded = create("shaded")
|
||||||
|
getByName("compile").extendsFrom(shaded)
|
||||||
|
// shaded.extendsFrom(getByName("compile"))
|
||||||
|
val shadedApi = create("shadedApi")
|
||||||
|
shaded.extendsFrom(shadedApi)
|
||||||
|
getByName("api").extendsFrom(shadedApi)
|
||||||
|
val shadedImplementation = create("shadedImplementation")
|
||||||
|
shaded.extendsFrom(shadedImplementation)
|
||||||
|
getByName("implementation").extendsFrom(shadedImplementation)
|
||||||
|
}
|
||||||
|
|
||||||
|
// tasks.withType<JavaCompile> {
|
||||||
|
// classpath +=
|
||||||
|
// }
|
||||||
|
|
||||||
|
val downloadDefaultPacks = tasks.create("downloadDefaultPacks") {
|
||||||
|
doFirst {
|
||||||
|
file("${buildDir}/resources/main/packs/").deleteRecursively()
|
||||||
|
|
||||||
|
val defaultPackUrl = URL("https://github.com/PolyhedralDev/TerraDefaultConfig/releases/download/latest/default.zip")
|
||||||
|
downloadPack(defaultPackUrl, project)
|
||||||
|
val netherPackUrl = URL("https://github.com/PolyhedralDev/TerraDefaultConfig/releases/download/latest/nether.zip")
|
||||||
|
downloadPack(netherPackUrl, project)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tasks["processResources"].dependsOn(downloadDefaultPacks)
|
||||||
|
|
||||||
|
tasks.register<Jar>("sourcesJar") {
|
||||||
|
archiveClassifier.set("sources")
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.withType<Jar> {
|
||||||
|
from("../LICENSE", "../../LICENSE")
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.register<Jar>("javadocJar") {
|
||||||
|
dependsOn("javadoc")
|
||||||
|
archiveClassifier.set("javadoc")
|
||||||
|
from(tasks.getByName<Javadoc>("javadoc").destinationDir)
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.named<ShadowJar>("shadowJar") {
|
||||||
|
// Tell shadow to download the packs
|
||||||
|
dependsOn(downloadDefaultPacks)
|
||||||
|
|
||||||
|
configurations = listOf(project.configurations["shaded"])
|
||||||
|
|
||||||
|
archiveClassifier.set("shaded")
|
||||||
|
setVersion(project.version)
|
||||||
|
relocate("org.apache.commons", "com.dfsek.terra.lib.commons")
|
||||||
|
relocate("parsii", "com.dfsek.terra.lib.parsii")
|
||||||
|
relocate("net.jafama", "com.dfsek.terra.lib.jafama")
|
||||||
|
minimize()
|
||||||
|
}
|
||||||
|
convention.getPlugin<BasePluginConvention>().archivesBaseName = project.name
|
||||||
|
|
||||||
|
tasks.named<DefaultTask>("build") {
|
||||||
|
dependsOn(tasks["shadowJar"])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun downloadPack(packUrl: URL, project: Project) {
|
||||||
|
val fileName = packUrl.file.substring(packUrl.file.lastIndexOf("/"))
|
||||||
|
val file = File("${project.buildDir}/resources/main/packs/${fileName}")
|
||||||
|
file.parentFile.mkdirs()
|
||||||
|
file.outputStream().write(packUrl.readBytes())
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import com.dfsek.terra.configureCommon
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
`java-library`
|
||||||
|
}
|
||||||
|
|
||||||
|
configureCommon()
|
||||||
|
|
||||||
|
group = "com.dfsek.terra.common"
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
"shadedApi"("org.apache.commons:commons-rng-core:1.3")
|
||||||
|
"shadedApi"("commons-io:commons-io:2.4")
|
||||||
|
|
||||||
|
"shadedApi"("com.scireum:parsii:1.2.1")
|
||||||
|
"shadedApi"("com.dfsek:Tectonic:1.1.0")
|
||||||
|
"shadedApi"("net.jafama:jafama:2.3.2")
|
||||||
|
"shadedApi"("org.yaml:snakeyaml:1.27")
|
||||||
|
|
||||||
|
"compileOnly"("com.googlecode.json-simple:json-simple:1.1")
|
||||||
|
|
||||||
|
"shadedApi"("com.google.guava:guava:30.0-jre")
|
||||||
|
}
|
||||||
+5
-6
@@ -1,9 +1,9 @@
|
|||||||
package com.dfsek.terra;
|
package com.dfsek.terra;
|
||||||
|
|
||||||
import org.bukkit.World;
|
import com.dfsek.terra.api.platform.world.World;
|
||||||
import org.polydev.gaea.profiler.DataType;
|
import com.dfsek.terra.api.profiler.DataType;
|
||||||
import org.polydev.gaea.profiler.Measurement;
|
import com.dfsek.terra.api.profiler.Measurement;
|
||||||
import org.polydev.gaea.profiler.WorldProfiler;
|
import com.dfsek.terra.api.profiler.WorldProfiler;
|
||||||
|
|
||||||
public class TerraProfiler extends WorldProfiler {
|
public class TerraProfiler extends WorldProfiler {
|
||||||
public TerraProfiler(World w) {
|
public TerraProfiler(World w) {
|
||||||
@@ -13,7 +13,6 @@ public class TerraProfiler extends WorldProfiler {
|
|||||||
.addMeasurement(new Measurement(10000000, DataType.PERIOD_MILLISECONDS), "TreeTime")
|
.addMeasurement(new Measurement(10000000, DataType.PERIOD_MILLISECONDS), "TreeTime")
|
||||||
.addMeasurement(new Measurement(1500000, DataType.PERIOD_MILLISECONDS), "OreTime")
|
.addMeasurement(new Measurement(1500000, DataType.PERIOD_MILLISECONDS), "OreTime")
|
||||||
.addMeasurement(new Measurement(5000000, DataType.PERIOD_MILLISECONDS), "CaveTime")
|
.addMeasurement(new Measurement(5000000, DataType.PERIOD_MILLISECONDS), "CaveTime")
|
||||||
.addMeasurement(new Measurement(1500000, DataType.PERIOD_MILLISECONDS), "StructureTime")
|
.addMeasurement(new Measurement(1500000, DataType.PERIOD_MILLISECONDS), "StructureTime");
|
||||||
.addMeasurement(new Measurement(1500000, DataType.PERIOD_MILLISECONDS), "ElevationTime");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
package com.dfsek.terra;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.platform.TerraPlugin;
|
||||||
|
import com.dfsek.terra.api.platform.generator.GeneratorWrapper;
|
||||||
|
import com.dfsek.terra.api.platform.world.World;
|
||||||
|
import com.dfsek.terra.biome.BiomeZone;
|
||||||
|
import com.dfsek.terra.biome.grid.master.TerraBiomeGrid;
|
||||||
|
import com.dfsek.terra.config.base.ConfigPack;
|
||||||
|
|
||||||
|
public class TerraWorld {
|
||||||
|
private final TerraBiomeGrid grid;
|
||||||
|
private final BiomeZone zone;
|
||||||
|
private final ConfigPack config;
|
||||||
|
private final boolean safe;
|
||||||
|
private final TerraProfiler profiler;
|
||||||
|
private final World world;
|
||||||
|
|
||||||
|
|
||||||
|
public TerraWorld(World w, ConfigPack c, TerraPlugin main) {
|
||||||
|
config = c;
|
||||||
|
profiler = new TerraProfiler(w);
|
||||||
|
this.grid = new TerraBiomeGrid.TerraBiomeGridBuilder(w.getSeed(), c, main).build();
|
||||||
|
this.zone = grid.getZone();
|
||||||
|
this.world = w;
|
||||||
|
safe = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public World getWorld() {
|
||||||
|
return world;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isTerraWorld(World w) {
|
||||||
|
return w.getGenerator().getHandle() instanceof GeneratorWrapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TerraBiomeGrid getGrid() {
|
||||||
|
return grid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConfigPack getConfig() {
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BiomeZone getZone() {
|
||||||
|
return zone;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSafe() {
|
||||||
|
return safe;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TerraProfiler getProfiler() {
|
||||||
|
return profiler;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package com.dfsek.terra.api;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.math.vector.Location;
|
||||||
|
import com.dfsek.terra.api.platform.Handle;
|
||||||
|
|
||||||
|
public interface Entity extends Handle {
|
||||||
|
Location getLocation();
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package com.dfsek.terra.api;
|
||||||
|
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.platform.world.World;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
public class Gaea {
|
||||||
|
private static boolean debug;
|
||||||
|
|
||||||
|
public static File getGaeaFolder(World w) {
|
||||||
|
File f = new File(w.getWorldFolder(), "gaea");
|
||||||
|
f.mkdirs();
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isDebug() {
|
||||||
|
return debug;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
package com.dfsek.terra.api;
|
||||||
|
|
||||||
|
import com.dfsek.tectonic.loading.TypeRegistry;
|
||||||
|
import com.dfsek.terra.api.math.GridSpawn;
|
||||||
|
import com.dfsek.terra.api.math.ProbabilityCollection;
|
||||||
|
import com.dfsek.terra.api.math.Range;
|
||||||
|
import com.dfsek.terra.api.platform.TerraPlugin;
|
||||||
|
import com.dfsek.terra.biome.grid.master.TerraBiomeGrid;
|
||||||
|
import com.dfsek.terra.biome.palette.PaletteHolder;
|
||||||
|
import com.dfsek.terra.biome.palette.PaletteLayer;
|
||||||
|
import com.dfsek.terra.carving.CarverPalette;
|
||||||
|
import com.dfsek.terra.config.loaders.ImageLoaderLoader;
|
||||||
|
import com.dfsek.terra.config.loaders.MaterialSetLoader;
|
||||||
|
import com.dfsek.terra.config.loaders.ProbabilityCollectionLoader;
|
||||||
|
import com.dfsek.terra.config.loaders.RangeLoader;
|
||||||
|
import com.dfsek.terra.config.loaders.config.FloraLayerLoader;
|
||||||
|
import com.dfsek.terra.config.loaders.config.GridSpawnLoader;
|
||||||
|
import com.dfsek.terra.config.loaders.config.NoiseBuilderLoader;
|
||||||
|
import com.dfsek.terra.config.loaders.config.OreConfigLoader;
|
||||||
|
import com.dfsek.terra.config.loaders.config.OreHolderLoader;
|
||||||
|
import com.dfsek.terra.config.loaders.config.TreeLayerLoader;
|
||||||
|
import com.dfsek.terra.config.loaders.palette.CarverPaletteLoader;
|
||||||
|
import com.dfsek.terra.config.loaders.palette.PaletteHolderLoader;
|
||||||
|
import com.dfsek.terra.config.loaders.palette.PaletteLayerLoader;
|
||||||
|
import com.dfsek.terra.generation.config.NoiseBuilder;
|
||||||
|
import com.dfsek.terra.image.ImageLoader;
|
||||||
|
import com.dfsek.terra.population.items.flora.FloraLayer;
|
||||||
|
import com.dfsek.terra.population.items.flora.TerraFlora;
|
||||||
|
import com.dfsek.terra.population.items.ores.Ore;
|
||||||
|
import com.dfsek.terra.population.items.ores.OreConfig;
|
||||||
|
import com.dfsek.terra.population.items.ores.OreHolder;
|
||||||
|
import com.dfsek.terra.population.items.tree.TreeLayer;
|
||||||
|
import com.dfsek.terra.util.MaterialSet;
|
||||||
|
|
||||||
|
public class GenericLoaders implements LoaderRegistrar {
|
||||||
|
private final TerraPlugin main;
|
||||||
|
|
||||||
|
public GenericLoaders(TerraPlugin main) {
|
||||||
|
this.main = main;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void register(TypeRegistry registry) {
|
||||||
|
registry.registerLoader(ProbabilityCollection.class, new ProbabilityCollectionLoader())
|
||||||
|
.registerLoader(Range.class, new RangeLoader())
|
||||||
|
.registerLoader(CarverPalette.class, new CarverPaletteLoader())
|
||||||
|
.registerLoader(GridSpawn.class, new GridSpawnLoader())
|
||||||
|
.registerLoader(PaletteHolder.class, new PaletteHolderLoader())
|
||||||
|
.registerLoader(PaletteLayer.class, new PaletteLayerLoader())
|
||||||
|
.registerLoader(FloraLayer.class, new FloraLayerLoader())
|
||||||
|
.registerLoader(Ore.Type.class, (t, o, l) -> Ore.Type.valueOf((String) o))
|
||||||
|
.registerLoader(OreConfig.class, new OreConfigLoader())
|
||||||
|
.registerLoader(NoiseBuilder.class, new NoiseBuilderLoader())
|
||||||
|
.registerLoader(TreeLayer.class, new TreeLayerLoader())
|
||||||
|
.registerLoader(MaterialSet.class, new MaterialSetLoader())
|
||||||
|
.registerLoader(OreHolder.class, new OreHolderLoader())
|
||||||
|
.registerLoader(ImageLoader.class, new ImageLoaderLoader())
|
||||||
|
.registerLoader(TerraBiomeGrid.Type.class, (t, o, l) -> TerraBiomeGrid.Type.valueOf((String) o))
|
||||||
|
.registerLoader(ImageLoader.Channel.class, (t, o, l) -> ImageLoader.Channel.valueOf((String) o))
|
||||||
|
.registerLoader(ImageLoader.Align.class, (t, o, l) -> ImageLoader.Align.valueOf((String) o))
|
||||||
|
.registerLoader(TerraFlora.Search.class, (t, o, l) -> TerraFlora.Search.valueOf((String) o));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package com.dfsek.terra.api;
|
||||||
|
|
||||||
|
import com.dfsek.tectonic.loading.TypeRegistry;
|
||||||
|
|
||||||
|
public interface LoaderRegistrar {
|
||||||
|
void register(TypeRegistry registry);
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
package com.dfsek.terra.api;
|
||||||
|
|
||||||
|
public interface Player extends Entity {
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package com.dfsek.terra.api.language;
|
||||||
|
|
||||||
|
|
||||||
|
import com.dfsek.tectonic.config.Configuration;
|
||||||
|
import com.dfsek.terra.api.platform.CommandSender;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
public class Language {
|
||||||
|
private final Configuration configuration;
|
||||||
|
public Language(File file) throws IOException {
|
||||||
|
configuration = new Configuration(new FileInputStream(file));
|
||||||
|
}
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public Message getMessage(String id) {
|
||||||
|
Message temp = null;
|
||||||
|
if(configuration.contains(id)) {
|
||||||
|
Object m = configuration.get(id);
|
||||||
|
|
||||||
|
if(m instanceof List) {
|
||||||
|
temp = new MultiLineMessage((List<String>) m);
|
||||||
|
} else if(m instanceof String) {
|
||||||
|
temp = new SingleLineMessage((String) m);
|
||||||
|
} else return new SingleLineMessage("message:" + id + ":translation_undefined");
|
||||||
|
}
|
||||||
|
if(temp == null || temp.isEmpty()) return new SingleLineMessage("message:" + id + ":translation_undefined");
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
public void log(String messageID, Level level, Logger logger, String... args) {
|
||||||
|
getMessage(messageID).log(logger, level, args);
|
||||||
|
}
|
||||||
|
public void send(String messageID, CommandSender sender, String... args) {
|
||||||
|
getMessage(messageID).send(sender, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package com.dfsek.terra.api.language;
|
||||||
|
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.platform.CommandSender;
|
||||||
|
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
public interface Message {
|
||||||
|
void log(Logger logger, Level level, String... args);
|
||||||
|
void send(CommandSender sender, String... args);
|
||||||
|
boolean isEmpty();
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package com.dfsek.terra.api.language;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.platform.CommandSender;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
public class MultiLineMessage implements Message {
|
||||||
|
private final List<String> message;
|
||||||
|
public MultiLineMessage(List<String> message) {
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void log(Logger logger, Level level, String... args) {
|
||||||
|
for(String line: message) {
|
||||||
|
logger.log(level, String.format(line, Arrays.asList(args).toArray()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void send(CommandSender sender, String... args) {
|
||||||
|
for(String line: message) {
|
||||||
|
sender.sendMessage(String.format(line, Arrays.asList(args).toArray()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return message == null || message.isEmpty();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package com.dfsek.terra.api.language;
|
||||||
|
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.platform.CommandSender;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
public class SingleLineMessage implements Message {
|
||||||
|
private final String message;
|
||||||
|
public SingleLineMessage(String message) {
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void log(Logger logger, Level level, String... args) {
|
||||||
|
logger.log(level, String.format(message, Arrays.asList(args).toArray()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void send(CommandSender sender, String... args) {
|
||||||
|
sender.sendMessage(String.format(message, Arrays.asList(args).toArray()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return message == null || message.equals("");
|
||||||
|
}
|
||||||
|
}
|
||||||
+16
-17
@@ -1,9 +1,8 @@
|
|||||||
package com.dfsek.terra.procgen;
|
package com.dfsek.terra.api.math;
|
||||||
|
|
||||||
import org.bukkit.util.Vector;
|
import com.dfsek.terra.api.math.vector.Vector3;
|
||||||
import org.polydev.gaea.math.MathUtil;
|
import com.dfsek.terra.api.util.FastRandom;
|
||||||
import org.polydev.gaea.util.FastRandom;
|
import com.dfsek.terra.api.util.GlueList;
|
||||||
import org.polydev.gaea.util.GlueList;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
@@ -14,12 +13,12 @@ import java.util.Random;
|
|||||||
public class GridSpawn {
|
public class GridSpawn {
|
||||||
private final int separation;
|
private final int separation;
|
||||||
private final int width;
|
private final int width;
|
||||||
private final int seedOffset;
|
private final int salt;
|
||||||
|
|
||||||
public GridSpawn(int width, int separation, int seedOffset) {
|
public GridSpawn(int width, int separation, int salt) {
|
||||||
this.separation = separation;
|
this.separation = separation;
|
||||||
this.width = width;
|
this.width = width;
|
||||||
this.seedOffset = seedOffset;
|
this.salt = salt;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -30,18 +29,18 @@ public class GridSpawn {
|
|||||||
* @param seed Seed for RNG
|
* @param seed Seed for RNG
|
||||||
* @return Vector representing nearest spawnpoint
|
* @return Vector representing nearest spawnpoint
|
||||||
*/
|
*/
|
||||||
public Vector getNearestSpawn(int x, int z, long seed) {
|
public Vector3 getNearestSpawn(int x, int z, long seed) {
|
||||||
int structureChunkX = x / (width + 2 * separation);
|
int structureChunkX = x / (width + 2 * separation);
|
||||||
int structureChunkZ = z / (width + 2 * separation);
|
int structureChunkZ = z / (width + 2 * separation);
|
||||||
List<Vector> zones = new GlueList<>();
|
List<Vector3> zones = new GlueList<>();
|
||||||
for(int xi = structureChunkX - 1; xi <= structureChunkX + 1; xi++) {
|
for(int xi = structureChunkX - 1; xi <= structureChunkX + 1; xi++) {
|
||||||
for(int zi = structureChunkZ - 1; zi <= structureChunkZ + 1; zi++) {
|
for(int zi = structureChunkZ - 1; zi <= structureChunkZ + 1; zi++) {
|
||||||
zones.add(getChunkSpawn(xi, zi, seed + seedOffset));
|
zones.add(getChunkSpawn(xi, zi, seed));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Vector shortest = zones.get(0);
|
Vector3 shortest = zones.get(0);
|
||||||
Vector compare = new Vector(x, 0, z);
|
Vector3 compare = new Vector3(x, 0, z);
|
||||||
for(Vector v : zones) {
|
for(Vector3 v : zones) {
|
||||||
if(compare.distanceSquared(shortest) > compare.distanceSquared(v)) shortest = v.clone();
|
if(compare.distanceSquared(shortest) > compare.distanceSquared(v)) shortest = v.clone();
|
||||||
}
|
}
|
||||||
return shortest;
|
return shortest;
|
||||||
@@ -55,13 +54,13 @@ public class GridSpawn {
|
|||||||
* @param seed Seed for RNG
|
* @param seed Seed for RNG
|
||||||
* @return Vector representing spawnpoint
|
* @return Vector representing spawnpoint
|
||||||
*/
|
*/
|
||||||
public Vector getChunkSpawn(int structureChunkX, int structureChunkZ, long seed) {
|
public Vector3 getChunkSpawn(int structureChunkX, int structureChunkZ, long seed) {
|
||||||
Random r = new FastRandom(MathUtil.getCarverChunkSeed(structureChunkX, structureChunkZ, seed + seedOffset));
|
Random r = new FastRandom(MathUtil.getCarverChunkSeed(structureChunkX, structureChunkZ, seed + salt));
|
||||||
int offsetX = r.nextInt(width);
|
int offsetX = r.nextInt(width);
|
||||||
int offsetZ = r.nextInt(width);
|
int offsetZ = r.nextInt(width);
|
||||||
int sx = structureChunkX * (width + 2 * separation) + offsetX;
|
int sx = structureChunkX * (width + 2 * separation) + offsetX;
|
||||||
int sz = structureChunkZ * (width + 2 * separation) + offsetZ;
|
int sz = structureChunkZ * (width + 2 * separation) + offsetZ;
|
||||||
return new Vector(sx, 0, sz);
|
return new Vector3(sx, 0, sz);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getWidth() {
|
public int getWidth() {
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
package com.dfsek.terra.api.math;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.util.FastRandom;
|
||||||
|
import com.dfsek.terra.generation.math.Sampler;
|
||||||
|
import net.jafama.FastMath;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility class for mathematical functions.
|
||||||
|
*/
|
||||||
|
public final class MathUtil {
|
||||||
|
/**
|
||||||
|
* Epsilon for fuzzy floating point comparisons.
|
||||||
|
*/
|
||||||
|
public static final double EPSILON = 1.0E-5;
|
||||||
|
/**
|
||||||
|
* Derivative constant.
|
||||||
|
*/
|
||||||
|
private static final double DERIVATIVE_DIST = 0.55;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the standard deviation of an array of doubles.
|
||||||
|
*
|
||||||
|
* @param numArray The array of numbers to calculate the standard deviation of.
|
||||||
|
* @return double - The standard deviation.
|
||||||
|
*/
|
||||||
|
public static double standardDeviation(List<Number> numArray) {
|
||||||
|
double sum = 0.0, standardDeviation = 0.0;
|
||||||
|
int length = numArray.size();
|
||||||
|
|
||||||
|
for(Number num : numArray) {
|
||||||
|
sum += num.doubleValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
double mean = sum / length;
|
||||||
|
|
||||||
|
for(Number num : numArray) {
|
||||||
|
standardDeviation += FastMath.pow2(num.doubleValue() - mean);
|
||||||
|
}
|
||||||
|
|
||||||
|
return FastMath.sqrt(standardDeviation / length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the carver seed for a chunk.
|
||||||
|
*
|
||||||
|
* @param chunkX Chunk's X coordinate
|
||||||
|
* @param chunkZ Chunk's Z coordinate
|
||||||
|
* @param seed World seed
|
||||||
|
* @return long - The carver seed.
|
||||||
|
*/
|
||||||
|
public static long getCarverChunkSeed(int chunkX, int chunkZ, long seed) {
|
||||||
|
Random r = new FastRandom(seed);
|
||||||
|
return chunkX * r.nextLong() ^ chunkZ * r.nextLong() ^ seed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static long hashToLong(String s) {
|
||||||
|
if(s == null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
long hash = 0;
|
||||||
|
for(char c : s.toCharArray()) {
|
||||||
|
hash = 31L * hash + c;
|
||||||
|
}
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compare 2 floating-point values with epsilon to account for rounding errors
|
||||||
|
*
|
||||||
|
* @param a Value 1
|
||||||
|
* @param b Value 2
|
||||||
|
* @return Whether these values are equal
|
||||||
|
*/
|
||||||
|
public static boolean equals(double a, double b) {
|
||||||
|
return a == b || FastMath.abs(a - b) < EPSILON;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double derivative(Sampler sampler, double x, double y, double z) {
|
||||||
|
double baseSample = sampler.sample(x, y, z);
|
||||||
|
|
||||||
|
double xVal1 = (sampler.sample(x + DERIVATIVE_DIST, y, z) - baseSample) / DERIVATIVE_DIST;
|
||||||
|
double xVal2 = (sampler.sample(x - DERIVATIVE_DIST, y, z) - baseSample) / DERIVATIVE_DIST;
|
||||||
|
double zVal1 = (sampler.sample(x, y, z + DERIVATIVE_DIST) - baseSample) / DERIVATIVE_DIST;
|
||||||
|
double zVal2 = (sampler.sample(x, y, z - DERIVATIVE_DIST) - baseSample) / DERIVATIVE_DIST;
|
||||||
|
double yVal1 = (sampler.sample(x, y + DERIVATIVE_DIST, z) - baseSample) / DERIVATIVE_DIST;
|
||||||
|
double yVal2 = (sampler.sample(x, y - DERIVATIVE_DIST, z) - baseSample) / DERIVATIVE_DIST;
|
||||||
|
|
||||||
|
return Math.sqrt(((xVal2 - xVal1) * (xVal2 - xVal1)) + ((zVal2 - zVal1) * (zVal2 - zVal1)) + ((yVal2 - yVal1) * (yVal2 - yVal1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static long squash(int first, int last) {
|
||||||
|
return (((long) first) << 32) | (last & 0xffffffffL);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package com.dfsek.terra.api.math;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.math.noise.samplers.NoiseSampler;
|
||||||
|
import com.dfsek.terra.api.world.biome.NormalizationUtil;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Random;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public class ProbabilityCollection<E> {
|
||||||
|
private final Set<Object> cont = new HashSet<>();
|
||||||
|
private Object[] array = new Object[0];
|
||||||
|
private int size;
|
||||||
|
|
||||||
|
public com.dfsek.terra.api.math.ProbabilityCollection<E> add(E item, int probability) {
|
||||||
|
if(!cont.contains(item)) size++;
|
||||||
|
cont.add(item);
|
||||||
|
int oldLength = array.length;
|
||||||
|
Object[] newArray = new Object[array.length + probability];
|
||||||
|
System.arraycopy(array, 0, newArray, 0, array.length); // Expand array.
|
||||||
|
array = newArray;
|
||||||
|
for(int i = oldLength; i < array.length; i++) array[i] = item;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public E get() {
|
||||||
|
if(array.length == 0) return null;
|
||||||
|
return (E) array[ThreadLocalRandom.current().nextInt(array.length)];
|
||||||
|
}
|
||||||
|
|
||||||
|
public E get(Random r) {
|
||||||
|
if(array.length == 0) return null;
|
||||||
|
return (E) array[r.nextInt(array.length)];
|
||||||
|
}
|
||||||
|
|
||||||
|
public E get(NoiseSampler n, double x, double z) {
|
||||||
|
if(array.length == 0) return null;
|
||||||
|
return (E) array[NormalizationUtil.normalize(n.getNoise(x, z), array.length, 1)];
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getTotalProbability() {
|
||||||
|
return array.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int size() {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,123 @@
|
|||||||
|
package com.dfsek.terra.api.math;
|
||||||
|
|
||||||
|
import net.jafama.FastMath;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class Range implements Iterable<Integer> {
|
||||||
|
private int min;
|
||||||
|
private int max;
|
||||||
|
|
||||||
|
public Range(int min, int max) {
|
||||||
|
if(min > max) throw new IllegalArgumentException("Minimum must not be grater than maximum!");
|
||||||
|
this.max = max;
|
||||||
|
this.min = min;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isInRange(int test) {
|
||||||
|
return test >= min && test < max;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMax() {
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
|
||||||
|
public com.dfsek.terra.api.math.Range setMax(int max) {
|
||||||
|
this.max = max;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMin() {
|
||||||
|
return min;
|
||||||
|
}
|
||||||
|
|
||||||
|
public com.dfsek.terra.api.math.Range setMin(int min) {
|
||||||
|
this.min = min;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRange() {
|
||||||
|
return max - min;
|
||||||
|
}
|
||||||
|
|
||||||
|
public com.dfsek.terra.api.math.Range multiply(int mult) {
|
||||||
|
min *= mult;
|
||||||
|
max *= mult;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public com.dfsek.terra.api.math.Range reflect(int pt) {
|
||||||
|
return new com.dfsek.terra.api.math.Range(2 * pt - this.getMax(), 2 * pt - this.getMin());
|
||||||
|
}
|
||||||
|
|
||||||
|
public int get(Random r) {
|
||||||
|
return r.nextInt((max - min) + 1) + min;
|
||||||
|
}
|
||||||
|
|
||||||
|
public com.dfsek.terra.api.math.Range intersects(com.dfsek.terra.api.math.Range other) {
|
||||||
|
try {
|
||||||
|
return new com.dfsek.terra.api.math.Range(FastMath.max(this.getMin(), other.getMin()), FastMath.min(this.getMax(), other.getMax()));
|
||||||
|
} catch(IllegalArgumentException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public com.dfsek.terra.api.math.Range add(int add) {
|
||||||
|
this.min += add;
|
||||||
|
this.max += add;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public com.dfsek.terra.api.math.Range sub(int sub) {
|
||||||
|
this.min -= sub;
|
||||||
|
this.max -= sub;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Min: " + getMin() + ", Max:" + getMax();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return min * 31 + max;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if(!(obj instanceof com.dfsek.terra.api.math.Range)) return false;
|
||||||
|
com.dfsek.terra.api.math.Range other = (com.dfsek.terra.api.math.Range) obj;
|
||||||
|
return other.getMin() == this.getMin() && other.getMax() == this.getMax();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Iterator<Integer> iterator() {
|
||||||
|
return new RangeIterator(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class RangeIterator implements Iterator<Integer> {
|
||||||
|
private final com.dfsek.terra.api.math.Range m;
|
||||||
|
private Integer current;
|
||||||
|
|
||||||
|
public RangeIterator(com.dfsek.terra.api.math.Range m) {
|
||||||
|
this.m = m;
|
||||||
|
current = m.getMin();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasNext() {
|
||||||
|
return current < m.getMax();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer next() {
|
||||||
|
current++;
|
||||||
|
return current - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.dfsek.terra.math;
|
package com.dfsek.terra.api.math.noise;
|
||||||
|
|
||||||
import parsii.eval.Function;
|
import parsii.eval.Function;
|
||||||
|
|
||||||
+4
-4
@@ -1,14 +1,14 @@
|
|||||||
package com.dfsek.terra.math;
|
package com.dfsek.terra.api.math.noise;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.math.noise.samplers.NoiseSampler;
|
||||||
import com.dfsek.terra.generation.config.NoiseBuilder;
|
import com.dfsek.terra.generation.config.NoiseBuilder;
|
||||||
import com.dfsek.terra.util.hash.HashMapDoubleDouble;
|
import com.dfsek.terra.util.hash.HashMapDoubleDouble;
|
||||||
import org.polydev.gaea.math.FastNoiseLite;
|
|
||||||
import parsii.eval.Expression;
|
import parsii.eval.Expression;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class NoiseFunction2 implements NoiseFunction {
|
public class NoiseFunction2 implements NoiseFunction {
|
||||||
private final FastNoiseLite gen;
|
private final NoiseSampler gen;
|
||||||
private final Cache cache = new Cache();
|
private final Cache cache = new Cache();
|
||||||
|
|
||||||
public NoiseFunction2(long seed, NoiseBuilder builder) {
|
public NoiseFunction2(long seed, NoiseBuilder builder) {
|
||||||
@@ -44,7 +44,7 @@ public class NoiseFunction2 implements NoiseFunction {
|
|||||||
private static final long serialVersionUID = 8915092734723467010L;
|
private static final long serialVersionUID = 8915092734723467010L;
|
||||||
private static final int cacheSize = 384;
|
private static final int cacheSize = 384;
|
||||||
|
|
||||||
public double get(FastNoiseLite noise, double x, double z) {
|
public double get(NoiseSampler noise, double x, double z) {
|
||||||
double xx = x >= 0 ? x * 2 : x * -2 - 1;
|
double xx = x >= 0 ? x * 2 : x * -2 - 1;
|
||||||
double zz = z >= 0 ? z * 2 : z * -2 - 1;
|
double zz = z >= 0 ? z * 2 : z * -2 - 1;
|
||||||
double key = (xx >= zz) ? (xx * xx + xx + zz) : (zz * zz + xx);
|
double key = (xx >= zz) ? (xx * xx + xx + zz) : (zz * zz + xx);
|
||||||
+3
-3
@@ -1,13 +1,13 @@
|
|||||||
package com.dfsek.terra.math;
|
package com.dfsek.terra.api.math.noise;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.math.noise.samplers.NoiseSampler;
|
||||||
import com.dfsek.terra.generation.config.NoiseBuilder;
|
import com.dfsek.terra.generation.config.NoiseBuilder;
|
||||||
import org.polydev.gaea.math.FastNoiseLite;
|
|
||||||
import parsii.eval.Expression;
|
import parsii.eval.Expression;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class NoiseFunction3 implements NoiseFunction {
|
public class NoiseFunction3 implements NoiseFunction {
|
||||||
private final FastNoiseLite gen;
|
private final NoiseSampler gen;
|
||||||
|
|
||||||
public NoiseFunction3(long seed, NoiseBuilder builder) {
|
public NoiseFunction3(long seed, NoiseBuilder builder) {
|
||||||
this.gen = builder.build((int) seed);
|
this.gen = builder.build((int) seed);
|
||||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,28 @@
|
|||||||
|
package com.dfsek.terra.api.math.noise.samplers;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.math.vector.Vector2;
|
||||||
|
import com.dfsek.terra.api.math.vector.Vector3;
|
||||||
|
|
||||||
|
public interface NoiseSampler {
|
||||||
|
/**
|
||||||
|
* 2D noise at given position using current settings
|
||||||
|
* <p>
|
||||||
|
* Noise output bounded between -1...1
|
||||||
|
*/
|
||||||
|
double getNoise(/*FNLdouble*/ double x, /*FNLdouble*/ double y);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 3D noise at given position using current settings
|
||||||
|
* <p>
|
||||||
|
* Noise output bounded between -1...1
|
||||||
|
*/
|
||||||
|
double getNoise(/*FNLdouble*/ double x, /*FNLdouble*/ double y, /*FNLdouble*/ double z);
|
||||||
|
|
||||||
|
default double getNoise(Vector3 vector3) {
|
||||||
|
return getNoise(vector3.getX(), vector3.getY(), vector3.getZ());
|
||||||
|
}
|
||||||
|
|
||||||
|
default double getNoise(Vector2 vector2) {
|
||||||
|
return getNoise(vector2.getX(), vector2.getZ());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package com.dfsek.terra.api.math.noise.samplers;
|
||||||
|
|
||||||
|
public abstract class Normalizer implements NoiseSampler {
|
||||||
|
private final NoiseSampler sampler;
|
||||||
|
|
||||||
|
protected Normalizer(NoiseSampler sampler) {
|
||||||
|
this.sampler = sampler;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract double normalize(double in);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getNoise(double x, double y) {
|
||||||
|
return normalize(sampler.getNoise(x, y));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getNoise(double x, double y, double z) {
|
||||||
|
return normalize(sampler.getNoise(x, y, z));
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.dfsek.terra.math;
|
package com.dfsek.terra.api.math.parsii;
|
||||||
|
|
||||||
import parsii.eval.Expression;
|
import parsii.eval.Expression;
|
||||||
import parsii.eval.Function;
|
import parsii.eval.Function;
|
||||||
+3
-3
@@ -1,13 +1,13 @@
|
|||||||
package com.dfsek.terra.math;
|
package com.dfsek.terra.api.math.parsii;
|
||||||
|
|
||||||
import org.polydev.gaea.util.FastRandom;
|
import com.dfsek.terra.api.util.FastRandom;
|
||||||
import parsii.eval.Expression;
|
import parsii.eval.Expression;
|
||||||
import parsii.eval.Function;
|
import parsii.eval.Function;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides access to a PRNG ({@link org.polydev.gaea.util.FastRandom})
|
* Provides access to a PRNG ({@link com.dfsek.terra.api.util.FastRandom})
|
||||||
* <p>
|
* <p>
|
||||||
* Takes 1 argument, which sets the seed
|
* Takes 1 argument, which sets the seed
|
||||||
*/
|
*/
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.dfsek.terra.procgen.pixel;
|
package com.dfsek.terra.api.math.pixel;
|
||||||
|
|
||||||
public class Distribution {
|
public class Distribution {
|
||||||
public Distribution(Rectangle bound, int numPoints, double minRad) {
|
public Distribution(Rectangle bound, int numPoints, double minRad) {
|
||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
package com.dfsek.terra.procgen.pixel;
|
package com.dfsek.terra.api.math.pixel;
|
||||||
|
|
||||||
import com.dfsek.terra.procgen.math.Vector2;
|
import com.dfsek.terra.api.math.vector.Vector2;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
package com.dfsek.terra.procgen.pixel;
|
package com.dfsek.terra.api.math.pixel;
|
||||||
|
|
||||||
import com.dfsek.terra.procgen.math.Vector2;
|
import com.dfsek.terra.api.math.vector.Vector2;
|
||||||
import net.jafama.FastMath;
|
import net.jafama.FastMath;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@@ -0,0 +1,173 @@
|
|||||||
|
package com.dfsek.terra.api.math.vector;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.platform.block.Block;
|
||||||
|
import com.dfsek.terra.api.platform.world.World;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public class Location implements Cloneable {
|
||||||
|
private World world;
|
||||||
|
private Vector3 vector;
|
||||||
|
private double pitch;
|
||||||
|
private double yaw;
|
||||||
|
|
||||||
|
public Location(World w, double x, double y, double z) {
|
||||||
|
this.world = w;
|
||||||
|
this.vector = new Vector3(x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Location(World w, Vector3 vector) {
|
||||||
|
this.world = w;
|
||||||
|
this.vector = vector;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWorld(World world) {
|
||||||
|
this.world = world;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector3 getVector() {
|
||||||
|
return vector;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVector(Vector3 vector) {
|
||||||
|
this.vector = vector;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Location clone() {
|
||||||
|
try {
|
||||||
|
Location other = (Location) super.clone();
|
||||||
|
other.setVector(other.getVector().clone());
|
||||||
|
return other;
|
||||||
|
} catch(CloneNotSupportedException e) {
|
||||||
|
throw new Error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBlockX() {
|
||||||
|
return vector.getBlockX();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBlockY() {
|
||||||
|
return vector.getBlockY();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBlockZ() {
|
||||||
|
return vector.getBlockZ();
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getY() {
|
||||||
|
return vector.getY();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Location setY(double y) {
|
||||||
|
vector.setY(y);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getX() {
|
||||||
|
return vector.getX();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Location setX(double x) {
|
||||||
|
vector.setX(x);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getZ() {
|
||||||
|
return vector.getZ();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Location setZ(double z) {
|
||||||
|
vector.setZ(z);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public World getWorld() {
|
||||||
|
return world;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Location add(double x, double y, double z) {
|
||||||
|
vector.add(x, y, z);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Block getBlock() {
|
||||||
|
return world.getBlockAt(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Location subtract(int x, int y, int z) {
|
||||||
|
vector.subtract(x, y, z);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Location add(Vector3 add) {
|
||||||
|
vector.add(add);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Location add(Location add) {
|
||||||
|
vector.add(add.toVector());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if(!(obj instanceof Location)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
final Location other = (Location) obj;
|
||||||
|
|
||||||
|
World world = this.world;
|
||||||
|
World otherWorld = other.world;
|
||||||
|
if(!Objects.equals(world, otherWorld)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(Double.doubleToLongBits(this.vector.getX()) != Double.doubleToLongBits(other.vector.getX())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(Double.doubleToLongBits(this.vector.getY()) != Double.doubleToLongBits(other.vector.getY())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return Double.doubleToLongBits(this.vector.getZ()) == Double.doubleToLongBits(other.vector.getZ());
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getPitch() {
|
||||||
|
return pitch;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPitch(double pitch) {
|
||||||
|
this.pitch = pitch;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getYaw() {
|
||||||
|
return yaw;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setYaw(double yaw) {
|
||||||
|
this.yaw = yaw;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int hash = 3;
|
||||||
|
|
||||||
|
World world = (this.world == null) ? null : this.world;
|
||||||
|
hash = 19 * hash + (world != null ? world.hashCode() : 0);
|
||||||
|
hash = 19 * hash + (int) (Double.doubleToLongBits(this.vector.getX()) ^ (Double.doubleToLongBits(this.vector.getX()) >>> 32));
|
||||||
|
hash = 19 * hash + (int) (Double.doubleToLongBits(this.vector.getY()) ^ (Double.doubleToLongBits(this.vector.getY()) >>> 32));
|
||||||
|
hash = 19 * hash + (int) (Double.doubleToLongBits(this.vector.getZ()) ^ (Double.doubleToLongBits(this.vector.getZ()) >>> 32));
|
||||||
|
hash = 19 * hash + (int) (Double.doubleToLongBits(this.pitch) ^ Double.doubleToLongBits(this.pitch) >>> 32);
|
||||||
|
hash = 19 * hash + (int) (Double.doubleToLongBits(this.yaw) ^ Double.doubleToLongBits(this.yaw) >>> 32);
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector3 toVector() {
|
||||||
|
return vector.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "[" + world + ": (" + getX() + ", " + getY() + ", " + getZ() + ")]";
|
||||||
|
}
|
||||||
|
}
|
||||||
+10
-5
@@ -1,5 +1,6 @@
|
|||||||
package com.dfsek.terra.procgen.math;
|
package com.dfsek.terra.api.math.vector;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.math.MathUtil;
|
||||||
import net.jafama.FastMath;
|
import net.jafama.FastMath;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -157,11 +158,9 @@ public class Vector2 implements Cloneable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
if(!(obj instanceof Vector2)) {
|
if(!(obj instanceof Vector2)) return false;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Vector2 other = (Vector2) obj;
|
Vector2 other = (Vector2) obj;
|
||||||
return other.x == this.x && other.z == this.z;
|
return MathUtil.equals(this.x, other.x) && MathUtil.equals(this.z, other.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -173,6 +172,12 @@ public class Vector2 implements Cloneable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Vector2 add(double x, double z) {
|
||||||
|
this.x += x;
|
||||||
|
this.z += z;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "(" + x + ", " + z + ")";
|
return "(" + x + ", " + z + ")";
|
||||||
@@ -0,0 +1,338 @@
|
|||||||
|
package com.dfsek.terra.api.math.vector;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.math.MathUtil;
|
||||||
|
import com.dfsek.terra.api.platform.world.World;
|
||||||
|
import net.jafama.FastMath;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public class Vector3 implements Cloneable {
|
||||||
|
|
||||||
|
|
||||||
|
private double x;
|
||||||
|
private double y;
|
||||||
|
private double z;
|
||||||
|
|
||||||
|
public Vector3(double x, double y, double z) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
this.z = z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getZ() {
|
||||||
|
return z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector3 setZ(double z) {
|
||||||
|
this.z = z;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getX() {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector3 setX(double x) {
|
||||||
|
this.x = x;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getY() {
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector3 setY(double y) {
|
||||||
|
this.y = y;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBlockX() {
|
||||||
|
return FastMath.floorToInt(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBlockY() {
|
||||||
|
return FastMath.floorToInt(y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBlockZ() {
|
||||||
|
return FastMath.floorToInt(z);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector3 multiply(double m) {
|
||||||
|
x *= m;
|
||||||
|
y *= m;
|
||||||
|
z *= m;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector3 add(double x, double y, double z) {
|
||||||
|
this.x += x;
|
||||||
|
this.y += y;
|
||||||
|
this.z += z;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector3 add(Vector3 other) {
|
||||||
|
this.x += other.getX();
|
||||||
|
this.y += other.getY();
|
||||||
|
this.z += other.getZ();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector3 add(Vector2 other) {
|
||||||
|
this.x += other.getX();
|
||||||
|
this.z += other.getZ();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double lengthSquared() {
|
||||||
|
return x * x + y * y + z * z;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Vector3 clone() {
|
||||||
|
try {
|
||||||
|
return (Vector3) super.clone();
|
||||||
|
} catch(CloneNotSupportedException e) {
|
||||||
|
throw new Error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public double length() {
|
||||||
|
return FastMath.sqrt(lengthSquared());
|
||||||
|
}
|
||||||
|
|
||||||
|
public double inverseLength() {
|
||||||
|
return FastMath.invSqrtQuick(lengthSquared());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns if a vector is normalized
|
||||||
|
*
|
||||||
|
* @return whether the vector is normalised
|
||||||
|
*/
|
||||||
|
public boolean isNormalized() {
|
||||||
|
return MathUtil.equals(this.lengthSquared(), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rotates the vector around the x axis.
|
||||||
|
* <p>
|
||||||
|
* This piece of math is based on the standard rotation matrix for vectors
|
||||||
|
* in three dimensional space. This matrix can be found here:
|
||||||
|
* <a href="https://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations">Rotation
|
||||||
|
* Matrix</a>.
|
||||||
|
*
|
||||||
|
* @param angle the angle to rotate the vector about. This angle is passed
|
||||||
|
* in radians
|
||||||
|
* @return the same vector
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
public Vector3 rotateAroundX(double angle) {
|
||||||
|
double angleCos = Math.cos(angle);
|
||||||
|
double angleSin = Math.sin(angle);
|
||||||
|
|
||||||
|
double y = angleCos * getY() - angleSin * getZ();
|
||||||
|
double z = angleSin * getY() + angleCos * getZ();
|
||||||
|
return setY(y).setZ(z);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rotates the vector around the y axis.
|
||||||
|
* <p>
|
||||||
|
* This piece of math is based on the standard rotation matrix for vectors
|
||||||
|
* in three dimensional space. This matrix can be found here:
|
||||||
|
* <a href="https://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations">Rotation
|
||||||
|
* Matrix</a>.
|
||||||
|
*
|
||||||
|
* @param angle the angle to rotate the vector about. This angle is passed
|
||||||
|
* in radians
|
||||||
|
* @return the same vector
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
public Vector3 rotateAroundY(double angle) {
|
||||||
|
double angleCos = Math.cos(angle);
|
||||||
|
double angleSin = Math.sin(angle);
|
||||||
|
|
||||||
|
double x = angleCos * getX() + angleSin * getZ();
|
||||||
|
double z = -angleSin * getX() + angleCos * getZ();
|
||||||
|
return setX(x).setZ(z);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rotates the vector around the z axis
|
||||||
|
* <p>
|
||||||
|
* This piece of math is based on the standard rotation matrix for vectors
|
||||||
|
* in three dimensional space. This matrix can be found here:
|
||||||
|
* <a href="https://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations">Rotation
|
||||||
|
* Matrix</a>.
|
||||||
|
*
|
||||||
|
* @param angle the angle to rotate the vector about. This angle is passed
|
||||||
|
* in radians
|
||||||
|
* @return the same vector
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
public Vector3 rotateAroundZ(double angle) {
|
||||||
|
double angleCos = Math.cos(angle);
|
||||||
|
double angleSin = Math.sin(angle);
|
||||||
|
|
||||||
|
double x = angleCos * getX() - angleSin * getY();
|
||||||
|
double y = angleSin * getX() + angleCos * getY();
|
||||||
|
return setX(x).setY(y);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the distance between this vector and another. The value of this
|
||||||
|
* method is not cached and uses a costly square-root function, so do not
|
||||||
|
* repeatedly call this method to get the vector's magnitude. NaN will be
|
||||||
|
* returned if the inner result of the sqrt() function overflows, which
|
||||||
|
* will be caused if the distance is too long.
|
||||||
|
*
|
||||||
|
* @param o The other vector
|
||||||
|
* @return the distance
|
||||||
|
*/
|
||||||
|
public double distance(@NotNull Vector3 o) {
|
||||||
|
return FastMath.sqrt(FastMath.pow2(x - o.x) + FastMath.pow2(y - o.y) + FastMath.pow2(z - o.z));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the squared distance between this vector and another.
|
||||||
|
*
|
||||||
|
* @param o The other vector
|
||||||
|
* @return the distance
|
||||||
|
*/
|
||||||
|
public double distanceSquared(@NotNull Vector3 o) {
|
||||||
|
return FastMath.pow2(x - o.x) + FastMath.pow2(y - o.y) + FastMath.pow2(z - o.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rotates the vector around a given arbitrary axis in 3 dimensional space.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Rotation will follow the general Right-Hand-Rule, which means rotation
|
||||||
|
* will be counterclockwise when the axis is pointing towards the observer.
|
||||||
|
* <p>
|
||||||
|
* This method will always make sure the provided axis is a unit vector, to
|
||||||
|
* not modify the length of the vector when rotating.
|
||||||
|
*
|
||||||
|
* @param axis the axis to rotate the vector around. If the passed vector is
|
||||||
|
* not of length 1, it gets copied and normalized before using it for the
|
||||||
|
* rotation. Please use {@link Vector3#normalize()} on the instance before
|
||||||
|
* passing it to this method
|
||||||
|
* @param angle the angle to rotate the vector around the axis
|
||||||
|
* @return the same vector
|
||||||
|
* @throws IllegalArgumentException if the provided axis vector instance is
|
||||||
|
* null
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
public Vector3 rotateAroundAxis(@NotNull Vector3 axis, double angle) throws IllegalArgumentException {
|
||||||
|
return rotateAroundNonUnitAxis(axis.isNormalized() ? axis : axis.clone().normalize(), angle);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rotates the vector around a given arbitrary axis in 3 dimensional space.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Rotation will follow the general Right-Hand-Rule, which means rotation
|
||||||
|
* will be counterclockwise when the axis is pointing towards the observer.
|
||||||
|
* <p>
|
||||||
|
* Note that the vector length will change accordingly to the axis vector
|
||||||
|
* length. If the provided axis is not a unit vector, the rotated vector
|
||||||
|
* will not have its previous length. The scaled length of the resulting
|
||||||
|
* vector will be related to the axis vector.
|
||||||
|
*
|
||||||
|
* @param axis the axis to rotate the vector around.
|
||||||
|
* @param angle the angle to rotate the vector around the axis
|
||||||
|
* @return the same vector
|
||||||
|
* @throws IllegalArgumentException if the provided axis vector instance is
|
||||||
|
* null
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
public Vector3 rotateAroundNonUnitAxis(@NotNull Vector3 axis, double angle) throws IllegalArgumentException {
|
||||||
|
double x = getX(), y = getY(), z = getZ();
|
||||||
|
double x2 = axis.getX(), y2 = axis.getY(), z2 = axis.getZ();
|
||||||
|
|
||||||
|
double cosTheta = Math.cos(angle);
|
||||||
|
double sinTheta = Math.sin(angle);
|
||||||
|
double dotProduct = this.dot(axis);
|
||||||
|
|
||||||
|
double xPrime = x2 * dotProduct * (1d - cosTheta)
|
||||||
|
+ x * cosTheta
|
||||||
|
+ (-z2 * y + y2 * z) * sinTheta;
|
||||||
|
double yPrime = y2 * dotProduct * (1d - cosTheta)
|
||||||
|
+ y * cosTheta
|
||||||
|
+ (z2 * x - x2 * z) * sinTheta;
|
||||||
|
double zPrime = z2 * dotProduct * (1d - cosTheta)
|
||||||
|
+ z * cosTheta
|
||||||
|
+ (-y2 * x + x2 * y) * sinTheta;
|
||||||
|
|
||||||
|
return setX(xPrime).setY(yPrime).setZ(zPrime);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the dot product of this vector with another. The dot product
|
||||||
|
* is defined as x1*x2+y1*y2+z1*z2. The returned value is a scalar.
|
||||||
|
*
|
||||||
|
* @param other The other vector
|
||||||
|
* @return dot product
|
||||||
|
*/
|
||||||
|
public double dot(@NotNull Vector3 other) {
|
||||||
|
return x * other.x + y * other.y + z * other.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Location toLocation(World world) {
|
||||||
|
return new Location(world, this.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector3 normalize() {
|
||||||
|
return this.multiply(this.inverseLength());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector3 subtract(int x, int y, int z) {
|
||||||
|
this.x -= x;
|
||||||
|
this.y -= y;
|
||||||
|
this.z -= z;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector3 subtract(Vector3 end) {
|
||||||
|
x -= end.x;
|
||||||
|
y -= end.y;
|
||||||
|
z -= end.z;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a hash code for this vector
|
||||||
|
*
|
||||||
|
* @return hash code
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int hash = 7;
|
||||||
|
|
||||||
|
hash = 79 * hash + (int) (Double.doubleToLongBits(this.x) ^ (Double.doubleToLongBits(this.x) >>> 32));
|
||||||
|
hash = 79 * hash + (int) (Double.doubleToLongBits(this.y) ^ (Double.doubleToLongBits(this.y) >>> 32));
|
||||||
|
hash = 79 * hash + (int) (Double.doubleToLongBits(this.z) ^ (Double.doubleToLongBits(this.z) >>> 32));
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks to see if two objects are equal.
|
||||||
|
* <p>
|
||||||
|
* Only two Vectors can ever return true. This method uses a fuzzy match
|
||||||
|
* to account for floating point errors. The epsilon can be retrieved
|
||||||
|
* with epsilon.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if(!(obj instanceof Vector3)) return false;
|
||||||
|
Vector3 other = (Vector3) obj;
|
||||||
|
return MathUtil.equals(x, other.x) && MathUtil.equals(y, other.y) && MathUtil.equals(x, other.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "(" + getX() + ", " + getY() + ", " + getZ() + ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package com.dfsek.terra.api.math.voxel;
|
||||||
|
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.math.vector.Vector3;
|
||||||
|
|
||||||
|
public class Cylinder extends VoxelGeometry {
|
||||||
|
public Cylinder(Vector3 start, int rad, int height) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
+5
-5
@@ -1,14 +1,14 @@
|
|||||||
package com.dfsek.terra.procgen.voxel;
|
package com.dfsek.terra.api.math.voxel;
|
||||||
|
|
||||||
import org.bukkit.util.Vector;
|
import com.dfsek.terra.api.math.noise.samplers.NoiseSampler;
|
||||||
import org.polydev.gaea.math.FastNoiseLite;
|
import com.dfsek.terra.api.math.vector.Vector3;
|
||||||
|
|
||||||
public class DeformedSphere extends VoxelGeometry {
|
public class DeformedSphere extends VoxelGeometry {
|
||||||
public DeformedSphere(Vector start, int rad, double deform, FastNoiseLite noise) {
|
public DeformedSphere(Vector3 start, int rad, double deform, NoiseSampler noise) {
|
||||||
for(int x = -rad; x <= rad; x++) {
|
for(int x = -rad; x <= rad; x++) {
|
||||||
for(int y = -rad; y <= rad; y++) {
|
for(int y = -rad; y <= rad; y++) {
|
||||||
for(int z = -rad; z <= rad; z++) {
|
for(int z = -rad; z <= rad; z++) {
|
||||||
Vector c = new Vector(x, y, z);
|
Vector3 c = new Vector3(x, y, z);
|
||||||
if(c.length() < (rad + 0.5) * ((noise.getNoise(x, y, z) + 1) * deform)) {
|
if(c.length() < (rad + 0.5) * ((noise.getNoise(x, y, z) + 1) * deform)) {
|
||||||
addVector(c.add(start));
|
addVector(c.add(start));
|
||||||
}
|
}
|
||||||
+4
-4
@@ -1,13 +1,13 @@
|
|||||||
package com.dfsek.terra.procgen.voxel;
|
package com.dfsek.terra.api.math.voxel;
|
||||||
|
|
||||||
import org.bukkit.util.Vector;
|
import com.dfsek.terra.api.math.vector.Vector3;
|
||||||
|
|
||||||
public class Sphere extends VoxelGeometry {
|
public class Sphere extends VoxelGeometry {
|
||||||
public Sphere(Vector start, int rad) {
|
public Sphere(Vector3 start, int rad) {
|
||||||
for(int x = -rad; x <= rad; x++) {
|
for(int x = -rad; x <= rad; x++) {
|
||||||
for(int y = -rad; y <= rad; y++) {
|
for(int y = -rad; y <= rad; y++) {
|
||||||
for(int z = -rad; z <= rad; z++) {
|
for(int z = -rad; z <= rad; z++) {
|
||||||
Vector c = new Vector(x, y, z);
|
Vector3 c = new Vector3(x, y, z);
|
||||||
if(c.length() < rad + 0.5) {
|
if(c.length() < rad + 0.5) {
|
||||||
addVector(c.add(start));
|
addVector(c.add(start));
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package com.dfsek.terra.api.math.voxel;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.math.vector.Vector3;
|
||||||
|
|
||||||
|
public class Tube extends VoxelGeometry {
|
||||||
|
public Tube(Vector3 start, Vector3 end, int radius) {
|
||||||
|
Vector3 step = start.clone().subtract(end).normalize();
|
||||||
|
Vector3 run = start.clone();
|
||||||
|
int steps = (int) start.distance(end);
|
||||||
|
for(int i = 0; i < steps; i++) {
|
||||||
|
merge(new Sphere(run, radius));
|
||||||
|
run.add(step);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+6
-6
@@ -1,23 +1,23 @@
|
|||||||
package com.dfsek.terra.procgen.voxel;
|
package com.dfsek.terra.api.math.voxel;
|
||||||
|
|
||||||
import org.bukkit.util.Vector;
|
import com.dfsek.terra.api.math.vector.Vector3;
|
||||||
import org.polydev.gaea.util.GlueList;
|
import com.dfsek.terra.api.util.GlueList;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public abstract class VoxelGeometry {
|
public abstract class VoxelGeometry {
|
||||||
private final List<Vector> geometry = new GlueList<>();
|
private final List<Vector3> geometry = new GlueList<>();
|
||||||
|
|
||||||
public static VoxelGeometry getBlank() {
|
public static VoxelGeometry getBlank() {
|
||||||
return new VoxelGeometry() {
|
return new VoxelGeometry() {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Vector> getGeometry() {
|
public List<Vector3> getGeometry() {
|
||||||
return geometry;
|
return geometry;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void addVector(Vector v) {
|
protected void addVector(Vector3 v) {
|
||||||
geometry.add(v);
|
geometry.add(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package com.dfsek.terra.api.platform;
|
||||||
|
|
||||||
|
public interface CommandSender extends Handle {
|
||||||
|
void sendMessage(String message);
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package com.dfsek.terra.api.platform;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An interface that contains a platform delegate.
|
||||||
|
*/
|
||||||
|
public interface Handle {
|
||||||
|
Object getHandle();
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
package com.dfsek.terra.api.platform;
|
||||||
|
|
||||||
|
import com.dfsek.terra.TerraWorld;
|
||||||
|
import com.dfsek.terra.api.LoaderRegistrar;
|
||||||
|
import com.dfsek.terra.api.language.Language;
|
||||||
|
import com.dfsek.terra.api.platform.handle.ItemHandle;
|
||||||
|
import com.dfsek.terra.api.platform.handle.WorldHandle;
|
||||||
|
import com.dfsek.terra.api.platform.world.World;
|
||||||
|
import com.dfsek.terra.config.base.PluginConfig;
|
||||||
|
import com.dfsek.terra.registry.ConfigRegistry;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
public interface TerraPlugin extends LoaderRegistrar {
|
||||||
|
WorldHandle getWorldHandle();
|
||||||
|
|
||||||
|
boolean isEnabled();
|
||||||
|
|
||||||
|
TerraWorld getWorld(World world);
|
||||||
|
|
||||||
|
Logger getLogger();
|
||||||
|
|
||||||
|
PluginConfig getTerraConfig();
|
||||||
|
|
||||||
|
File getDataFolder();
|
||||||
|
|
||||||
|
boolean isDebug();
|
||||||
|
|
||||||
|
Language getLanguage();
|
||||||
|
|
||||||
|
ConfigRegistry getRegistry();
|
||||||
|
|
||||||
|
void reload();
|
||||||
|
|
||||||
|
ItemHandle getItemHandle();
|
||||||
|
|
||||||
|
void saveDefaultConfig();
|
||||||
|
|
||||||
|
String platformName();
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package com.dfsek.terra.api.platform.block;
|
||||||
|
|
||||||
|
public enum Axis {
|
||||||
|
X, Y, Z
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package com.dfsek.terra.api.platform.block;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.math.vector.Location;
|
||||||
|
import com.dfsek.terra.api.platform.Handle;
|
||||||
|
import com.dfsek.terra.api.platform.block.state.BlockState;
|
||||||
|
|
||||||
|
public interface Block extends Handle {
|
||||||
|
void setBlockData(BlockData data, boolean physics);
|
||||||
|
|
||||||
|
BlockData getBlockData();
|
||||||
|
|
||||||
|
BlockState getState();
|
||||||
|
|
||||||
|
Block getRelative(BlockFace face);
|
||||||
|
|
||||||
|
Block getRelative(BlockFace face, int len);
|
||||||
|
|
||||||
|
boolean isEmpty();
|
||||||
|
|
||||||
|
Location getLocation();
|
||||||
|
|
||||||
|
MaterialData getType();
|
||||||
|
|
||||||
|
int getX();
|
||||||
|
|
||||||
|
int getZ();
|
||||||
|
|
||||||
|
int getY();
|
||||||
|
|
||||||
|
boolean isPassable();
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package com.dfsek.terra.api.platform.block;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.platform.Handle;
|
||||||
|
|
||||||
|
public interface BlockData extends Cloneable, Handle {
|
||||||
|
MaterialData getMaterial();
|
||||||
|
|
||||||
|
boolean matches(MaterialData materialData);
|
||||||
|
|
||||||
|
BlockData clone();
|
||||||
|
|
||||||
|
String getAsString();
|
||||||
|
}
|
||||||
@@ -0,0 +1,148 @@
|
|||||||
|
package com.dfsek.terra.api.platform.block;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.math.vector.Vector3;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public enum BlockFace {
|
||||||
|
NORTH(0, 0, -1),
|
||||||
|
EAST(1, 0, 0),
|
||||||
|
SOUTH(0, 0, 1),
|
||||||
|
WEST(-1, 0, 0),
|
||||||
|
UP(0, 1, 0),
|
||||||
|
DOWN(0, -1, 0),
|
||||||
|
NORTH_EAST(NORTH, EAST),
|
||||||
|
NORTH_WEST(NORTH, WEST),
|
||||||
|
SOUTH_EAST(SOUTH, EAST),
|
||||||
|
SOUTH_WEST(SOUTH, WEST),
|
||||||
|
WEST_NORTH_WEST(WEST, NORTH_WEST),
|
||||||
|
NORTH_NORTH_WEST(NORTH, NORTH_WEST),
|
||||||
|
NORTH_NORTH_EAST(NORTH, NORTH_EAST),
|
||||||
|
EAST_NORTH_EAST(EAST, NORTH_EAST),
|
||||||
|
EAST_SOUTH_EAST(EAST, SOUTH_EAST),
|
||||||
|
SOUTH_SOUTH_EAST(SOUTH, SOUTH_EAST),
|
||||||
|
SOUTH_SOUTH_WEST(SOUTH, SOUTH_WEST),
|
||||||
|
WEST_SOUTH_WEST(WEST, SOUTH_WEST),
|
||||||
|
SELF(0, 0, 0);
|
||||||
|
|
||||||
|
private final int modX;
|
||||||
|
private final int modY;
|
||||||
|
private final int modZ;
|
||||||
|
|
||||||
|
BlockFace(final int modX, final int modY, final int modZ) {
|
||||||
|
this.modX = modX;
|
||||||
|
this.modY = modY;
|
||||||
|
this.modZ = modZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockFace(final BlockFace face1, final BlockFace face2) {
|
||||||
|
this.modX = face1.getModX() + face2.getModX();
|
||||||
|
this.modY = face1.getModY() + face2.getModY();
|
||||||
|
this.modZ = face1.getModZ() + face2.getModZ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the amount of X-coordinates to modify to get the represented block
|
||||||
|
*
|
||||||
|
* @return Amount of X-coordinates to modify
|
||||||
|
*/
|
||||||
|
public int getModX() {
|
||||||
|
return modX;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the amount of Y-coordinates to modify to get the represented block
|
||||||
|
*
|
||||||
|
* @return Amount of Y-coordinates to modify
|
||||||
|
*/
|
||||||
|
public int getModY() {
|
||||||
|
return modY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the amount of Z-coordinates to modify to get the represented block
|
||||||
|
*
|
||||||
|
* @return Amount of Z-coordinates to modify
|
||||||
|
*/
|
||||||
|
public int getModZ() {
|
||||||
|
return modZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the normal vector corresponding to this block face.
|
||||||
|
*
|
||||||
|
* @return the normal vector
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
public Vector3 getDirection() {
|
||||||
|
Vector3 direction = new Vector3(modX, modY, modZ);
|
||||||
|
if(modX != 0 || modY != 0 || modZ != 0) {
|
||||||
|
direction.normalize();
|
||||||
|
}
|
||||||
|
return direction;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public BlockFace getOppositeFace() {
|
||||||
|
switch(this) {
|
||||||
|
case NORTH:
|
||||||
|
return BlockFace.SOUTH;
|
||||||
|
|
||||||
|
case SOUTH:
|
||||||
|
return BlockFace.NORTH;
|
||||||
|
|
||||||
|
case EAST:
|
||||||
|
return BlockFace.WEST;
|
||||||
|
|
||||||
|
case WEST:
|
||||||
|
return BlockFace.EAST;
|
||||||
|
|
||||||
|
case UP:
|
||||||
|
return BlockFace.DOWN;
|
||||||
|
|
||||||
|
case DOWN:
|
||||||
|
return BlockFace.UP;
|
||||||
|
|
||||||
|
case NORTH_EAST:
|
||||||
|
return BlockFace.SOUTH_WEST;
|
||||||
|
|
||||||
|
case NORTH_WEST:
|
||||||
|
return BlockFace.SOUTH_EAST;
|
||||||
|
|
||||||
|
case SOUTH_EAST:
|
||||||
|
return BlockFace.NORTH_WEST;
|
||||||
|
|
||||||
|
case SOUTH_WEST:
|
||||||
|
return BlockFace.NORTH_EAST;
|
||||||
|
|
||||||
|
case WEST_NORTH_WEST:
|
||||||
|
return BlockFace.EAST_SOUTH_EAST;
|
||||||
|
|
||||||
|
case NORTH_NORTH_WEST:
|
||||||
|
return BlockFace.SOUTH_SOUTH_EAST;
|
||||||
|
|
||||||
|
case NORTH_NORTH_EAST:
|
||||||
|
return BlockFace.SOUTH_SOUTH_WEST;
|
||||||
|
|
||||||
|
case EAST_NORTH_EAST:
|
||||||
|
return BlockFace.WEST_SOUTH_WEST;
|
||||||
|
|
||||||
|
case EAST_SOUTH_EAST:
|
||||||
|
return BlockFace.WEST_NORTH_WEST;
|
||||||
|
|
||||||
|
case SOUTH_SOUTH_EAST:
|
||||||
|
return BlockFace.NORTH_NORTH_WEST;
|
||||||
|
|
||||||
|
case SOUTH_SOUTH_WEST:
|
||||||
|
return BlockFace.NORTH_NORTH_EAST;
|
||||||
|
|
||||||
|
case WEST_SOUTH_WEST:
|
||||||
|
return BlockFace.EAST_NORTH_EAST;
|
||||||
|
|
||||||
|
case SELF:
|
||||||
|
return BlockFace.SELF;
|
||||||
|
}
|
||||||
|
|
||||||
|
return BlockFace.SELF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package com.dfsek.terra.api.platform.block;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.platform.Handle;
|
||||||
|
|
||||||
|
public interface MaterialData extends Handle {
|
||||||
|
boolean matches(MaterialData other);
|
||||||
|
|
||||||
|
boolean matches(BlockData other);
|
||||||
|
|
||||||
|
boolean isSolid();
|
||||||
|
|
||||||
|
boolean isAir();
|
||||||
|
|
||||||
|
double getMaxDurability();
|
||||||
|
|
||||||
|
BlockData createBlockData();
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package com.dfsek.terra.api.platform.block.data;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.platform.block.BlockData;
|
||||||
|
|
||||||
|
public interface AnaloguePowerable extends BlockData {
|
||||||
|
int getMaximumPower();
|
||||||
|
int getPower();
|
||||||
|
void setPower(int power);
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package com.dfsek.terra.api.platform.block.data;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.platform.block.BlockData;
|
||||||
|
|
||||||
|
public interface Bisected extends BlockData {
|
||||||
|
Half getHalf();
|
||||||
|
|
||||||
|
void setHalf(Half half);
|
||||||
|
|
||||||
|
enum Half {
|
||||||
|
/**
|
||||||
|
* The top half of the block, normally with the higher y coordinate.
|
||||||
|
*/
|
||||||
|
TOP,
|
||||||
|
/**
|
||||||
|
* The bottom half of the block, normally with the lower y coordinate.
|
||||||
|
*/
|
||||||
|
BOTTOM
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package com.dfsek.terra.api.platform.block.data;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.platform.block.BlockData;
|
||||||
|
import com.dfsek.terra.api.platform.block.BlockFace;
|
||||||
|
|
||||||
|
public interface Directional extends BlockData {
|
||||||
|
BlockFace getFacing();
|
||||||
|
|
||||||
|
void setFacing(BlockFace facing);
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package com.dfsek.terra.api.platform.block.data;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.platform.block.BlockData;
|
||||||
|
import com.dfsek.terra.api.platform.block.BlockFace;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public interface MultipleFacing extends BlockData {
|
||||||
|
Set<BlockFace> getFaces();
|
||||||
|
|
||||||
|
void setFace(BlockFace face, boolean facing);
|
||||||
|
|
||||||
|
Set<BlockFace> getAllowedFaces();
|
||||||
|
|
||||||
|
boolean hasFace(BlockFace f);
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package com.dfsek.terra.api.platform.block.data;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.platform.block.Axis;
|
||||||
|
import com.dfsek.terra.api.platform.block.BlockData;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public interface Orientable extends BlockData {
|
||||||
|
Set<Axis> getAxes();
|
||||||
|
|
||||||
|
Axis getAxis();
|
||||||
|
|
||||||
|
void setAxis(Axis axis);
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package com.dfsek.terra.api.platform.block.data;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.platform.block.BlockData;
|
||||||
|
|
||||||
|
public interface Rail extends BlockData {
|
||||||
|
Shape getShape();
|
||||||
|
|
||||||
|
void setShape(Shape newShape);
|
||||||
|
|
||||||
|
enum Shape {
|
||||||
|
ASCENDING_EAST,
|
||||||
|
ASCENDING_NORTH,
|
||||||
|
ASCENDING_SOUTH,
|
||||||
|
ASCENDING_WEST,
|
||||||
|
EAST_WEST,
|
||||||
|
NORTH_EAST,
|
||||||
|
NORTH_SOUTH,
|
||||||
|
NORTH_WEST,
|
||||||
|
SOUTH_EAST,
|
||||||
|
SOUTH_WEST
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package com.dfsek.terra.api.platform.block.data;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.platform.block.BlockData;
|
||||||
|
import com.dfsek.terra.api.platform.block.BlockFace;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public interface RedstoneWire extends BlockData, AnaloguePowerable {
|
||||||
|
Set<BlockFace> getAllowedFaces();
|
||||||
|
Connection getFace(BlockFace face);
|
||||||
|
void setFace(BlockFace face, Connection connection);
|
||||||
|
enum Connection {
|
||||||
|
NONE, SIDE, UP
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package com.dfsek.terra.api.platform.block.data;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.platform.block.BlockData;
|
||||||
|
import com.dfsek.terra.api.platform.block.BlockFace;
|
||||||
|
|
||||||
|
public interface Rotatable extends BlockData {
|
||||||
|
BlockFace getRotation();
|
||||||
|
|
||||||
|
void setRotation(BlockFace face);
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package com.dfsek.terra.api.platform.block.data;
|
||||||
|
|
||||||
|
public interface Slab extends Waterlogged {
|
||||||
|
Type getType();
|
||||||
|
|
||||||
|
void setType(Type type);
|
||||||
|
|
||||||
|
enum Type {
|
||||||
|
TOP, BOTTOM, DOUBLE
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package com.dfsek.terra.api.platform.block.data;
|
||||||
|
|
||||||
|
public interface Stairs extends Waterlogged, Directional, Bisected {
|
||||||
|
Shape getShape();
|
||||||
|
|
||||||
|
void setShape(Shape shape);
|
||||||
|
|
||||||
|
enum Shape {
|
||||||
|
/**
|
||||||
|
* Regular stair block.
|
||||||
|
*/
|
||||||
|
STRAIGHT,
|
||||||
|
/**
|
||||||
|
* Inner corner stair block with higher left side.
|
||||||
|
*/
|
||||||
|
INNER_LEFT,
|
||||||
|
/**
|
||||||
|
* Inner corner stair block with higher right side.
|
||||||
|
*/
|
||||||
|
INNER_RIGHT,
|
||||||
|
/**
|
||||||
|
* Outer corner stair block with higher left side.
|
||||||
|
*/
|
||||||
|
OUTER_LEFT,
|
||||||
|
/**
|
||||||
|
* Outer corner stair block with higher right side.
|
||||||
|
*/
|
||||||
|
OUTER_RIGHT
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package com.dfsek.terra.api.platform.block.data;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.platform.block.BlockData;
|
||||||
|
import com.dfsek.terra.api.platform.block.BlockFace;
|
||||||
|
|
||||||
|
public interface Wall extends BlockData, Waterlogged {
|
||||||
|
boolean isUp();
|
||||||
|
void setHeight(BlockFace face, Height height);
|
||||||
|
Height getHeight(BlockFace face);
|
||||||
|
void setUp(boolean up);
|
||||||
|
|
||||||
|
enum Height {
|
||||||
|
LOW, NONE, TALL
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package com.dfsek.terra.api.platform.block.data;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.platform.block.BlockData;
|
||||||
|
|
||||||
|
public interface Waterlogged extends BlockData {
|
||||||
|
boolean isWaterlogged();
|
||||||
|
|
||||||
|
void setWaterlogged(boolean waterlogged);
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package com.dfsek.terra.api.platform.block.state;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.platform.Handle;
|
||||||
|
import com.dfsek.terra.api.platform.block.Block;
|
||||||
|
import com.dfsek.terra.api.platform.block.BlockData;
|
||||||
|
|
||||||
|
public interface BlockState extends Handle {
|
||||||
|
Block getBlock();
|
||||||
|
|
||||||
|
int getX();
|
||||||
|
|
||||||
|
int getY();
|
||||||
|
|
||||||
|
int getZ();
|
||||||
|
|
||||||
|
BlockData getBlockData();
|
||||||
|
|
||||||
|
boolean update(boolean applyPhysics);
|
||||||
|
|
||||||
|
default void applyState(String state) {
|
||||||
|
// Do nothing by default.
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package com.dfsek.terra.api.platform.block.state;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.platform.inventory.BlockInventoryHolder;
|
||||||
|
|
||||||
|
public interface Container extends BlockState, BlockInventoryHolder {
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package com.dfsek.terra.api.platform.block.state;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.platform.world.entity.EntityType;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public interface MobSpawner extends BlockState {
|
||||||
|
EntityType getSpawnedType();
|
||||||
|
|
||||||
|
void setSpawnedType(@NotNull EntityType creatureType);
|
||||||
|
|
||||||
|
int getDelay();
|
||||||
|
|
||||||
|
void setDelay(int delay);
|
||||||
|
|
||||||
|
int getMinSpawnDelay();
|
||||||
|
|
||||||
|
void setMinSpawnDelay(int delay);
|
||||||
|
|
||||||
|
int getMaxSpawnDelay();
|
||||||
|
|
||||||
|
void setMaxSpawnDelay(int delay);
|
||||||
|
|
||||||
|
int getSpawnCount();
|
||||||
|
|
||||||
|
void setSpawnCount(int spawnCount);
|
||||||
|
|
||||||
|
int getMaxNearbyEntities();
|
||||||
|
|
||||||
|
void setMaxNearbyEntities(int maxNearbyEntities);
|
||||||
|
|
||||||
|
int getRequiredPlayerRange();
|
||||||
|
|
||||||
|
void setRequiredPlayerRange(int requiredPlayerRange);
|
||||||
|
|
||||||
|
int getSpawnRange();
|
||||||
|
|
||||||
|
void setSpawnRange(int spawnRange);
|
||||||
|
}
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
package com.dfsek.terra.api.platform.block.state;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class SerialState {
|
||||||
|
protected final Map<String, Property<?>> properties = new HashMap<>();
|
||||||
|
|
||||||
|
public SerialState() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Map<String, String> parse(String props) {
|
||||||
|
String[] sep = props.split(",");
|
||||||
|
Map<String, String> map = new HashMap<>();
|
||||||
|
for(String item : sep) {
|
||||||
|
map.put(item.substring(0, item.indexOf('=')), item.substring(item.indexOf('=') + 1));
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkExists(String prop) {
|
||||||
|
if(!properties.containsKey(prop)) throw new IllegalArgumentException("No such property \"" + prop + "\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkType(Class<?> clazz, Object o, String id) {
|
||||||
|
if(!clazz.isInstance(o))
|
||||||
|
throw new IllegalArgumentException("Invalid data for property " + id + ": " + o);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProperty(String id, Object value) {
|
||||||
|
checkExists(id);
|
||||||
|
Property<?> prop = properties.get(id);
|
||||||
|
checkType(prop.getValueClass(), value, id);
|
||||||
|
prop.setValue(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getInteger(String id) {
|
||||||
|
checkExists(id);
|
||||||
|
Property<?> prop = properties.get(id);
|
||||||
|
checkType(Integer.class, prop.getValue(), id);
|
||||||
|
return (Integer) prop.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getString(String id) {
|
||||||
|
checkExists(id);
|
||||||
|
Property<?> prop = properties.get(id);
|
||||||
|
checkType(String.class, prop.getValue(), id);
|
||||||
|
return (String) prop.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getLong(String id) {
|
||||||
|
checkExists(id);
|
||||||
|
Property<?> prop = properties.get(id);
|
||||||
|
checkType(Long.class, prop.getValue(), id);
|
||||||
|
return (Long) prop.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getBoolean(String id) {
|
||||||
|
checkExists(id);
|
||||||
|
Property<?> prop = properties.get(id);
|
||||||
|
checkType(Boolean.class, prop.getValue(), id);
|
||||||
|
return (Boolean) prop.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <T> T get(String id, Class<T> clazz) {
|
||||||
|
checkExists(id);
|
||||||
|
Property<?> prop = properties.get(id);
|
||||||
|
checkType(clazz, prop.getValue(), id);
|
||||||
|
return (T) prop.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static class Property<T> {
|
||||||
|
private final Class<T> clazz;
|
||||||
|
private Object value;
|
||||||
|
|
||||||
|
public Property(Class<T> clazz) {
|
||||||
|
this.clazz = clazz;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class<T> getValueClass() {
|
||||||
|
return clazz;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public T getValue() {
|
||||||
|
return (T) value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(Object value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package com.dfsek.terra.api.platform.block.state;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public interface Sign extends BlockState {
|
||||||
|
@NotNull String[] getLines();
|
||||||
|
|
||||||
|
@NotNull String getLine(int index) throws IndexOutOfBoundsException;
|
||||||
|
|
||||||
|
void setLine(int index, @NotNull String line) throws IndexOutOfBoundsException;
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package com.dfsek.terra.api.platform.generator;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.platform.Handle;
|
||||||
|
import com.dfsek.terra.api.platform.world.Chunk;
|
||||||
|
import com.dfsek.terra.api.platform.world.World;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public interface BlockPopulator extends Handle {
|
||||||
|
void populate(World world, Random random, Chunk chunk);
|
||||||
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
package com.dfsek.terra.api.platform.generator;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.platform.Handle;
|
||||||
|
import com.dfsek.terra.api.platform.block.BlockData;
|
||||||
|
import com.dfsek.terra.api.platform.world.BiomeGrid;
|
||||||
|
import com.dfsek.terra.api.platform.world.World;
|
||||||
|
import com.dfsek.terra.api.world.generation.TerraChunkGenerator;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public interface ChunkGenerator extends Handle {
|
||||||
|
boolean isParallelCapable();
|
||||||
|
|
||||||
|
boolean shouldGenerateCaves();
|
||||||
|
|
||||||
|
boolean shouldGenerateDecorations();
|
||||||
|
|
||||||
|
boolean shouldGenerateMobs();
|
||||||
|
|
||||||
|
boolean shouldGenerateStructures();
|
||||||
|
|
||||||
|
ChunkData generateChunkData(@NotNull World world, @NotNull Random random, int x, int z, @NotNull BiomeGrid biome);
|
||||||
|
|
||||||
|
|
||||||
|
List<BlockPopulator> getDefaultPopulators(World world);
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
TerraChunkGenerator getTerraGenerator();
|
||||||
|
|
||||||
|
interface ChunkData extends Handle {
|
||||||
|
/**
|
||||||
|
* Get the maximum height for the chunk.
|
||||||
|
* <p>
|
||||||
|
* Setting blocks at or above this height will do nothing.
|
||||||
|
*
|
||||||
|
* @return the maximum height
|
||||||
|
*/
|
||||||
|
int getMaxHeight();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the block at x,y,z in the chunk data to material.
|
||||||
|
* <p>
|
||||||
|
* Setting blocks outside the chunk's bounds does nothing.
|
||||||
|
*
|
||||||
|
* @param x the x location in the chunk from 0-15 inclusive
|
||||||
|
* @param y the y location in the chunk from 0 (inclusive) - maxHeight (exclusive)
|
||||||
|
* @param z the z location in the chunk from 0-15 inclusive
|
||||||
|
* @param blockData the type to set the block to
|
||||||
|
*/
|
||||||
|
void setBlock(int x, int y, int z, @NotNull BlockData blockData);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the type and data of the block at x, y, z.
|
||||||
|
* <p>
|
||||||
|
* Getting blocks outside the chunk's bounds returns air.
|
||||||
|
*
|
||||||
|
* @param x the x location in the chunk from 0-15 inclusive
|
||||||
|
* @param y the y location in the chunk from 0 (inclusive) - maxHeight (exclusive)
|
||||||
|
* @param z the z location in the chunk from 0-15 inclusive
|
||||||
|
* @return the data of the block or the BlockData for air if x, y or z are outside the chunk's bounds
|
||||||
|
*/
|
||||||
|
@NotNull BlockData getBlockData(int x, int y, int z);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package com.dfsek.terra.api.platform.generator;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.platform.Handle;
|
||||||
|
|
||||||
|
public interface GeneratorWrapper extends Handle {
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package com.dfsek.terra.api.platform.handle;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.platform.block.MaterialData;
|
||||||
|
import com.dfsek.terra.api.platform.inventory.ItemStack;
|
||||||
|
import com.dfsek.terra.api.platform.inventory.item.Enchantment;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public interface ItemHandle {
|
||||||
|
ItemStack newItemStack(MaterialData material, int amount);
|
||||||
|
|
||||||
|
Enchantment getEnchantment(String id);
|
||||||
|
|
||||||
|
Set<Enchantment> getEnchantments();
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package com.dfsek.terra.api.platform.handle;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.platform.block.Block;
|
||||||
|
import com.dfsek.terra.api.platform.block.BlockData;
|
||||||
|
import com.dfsek.terra.api.platform.block.MaterialData;
|
||||||
|
import com.dfsek.terra.api.platform.world.Tree;
|
||||||
|
import com.dfsek.terra.api.platform.world.entity.EntityType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface to be implemented for world manipulation.
|
||||||
|
*/
|
||||||
|
public interface WorldHandle {
|
||||||
|
void setBlockData(Block block, BlockData data, boolean physics);
|
||||||
|
|
||||||
|
BlockData getBlockData(Block block);
|
||||||
|
|
||||||
|
MaterialData getType(Block block);
|
||||||
|
|
||||||
|
BlockData createBlockData(String data);
|
||||||
|
|
||||||
|
MaterialData createMaterialData(String data);
|
||||||
|
|
||||||
|
Tree getTree(String id);
|
||||||
|
|
||||||
|
EntityType getEntity(String id);
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package com.dfsek.terra.api.platform.inventory;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.platform.block.Block;
|
||||||
|
|
||||||
|
public interface BlockInventoryHolder extends InventoryHolder {
|
||||||
|
Block getBlock();
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package com.dfsek.terra.api.platform.inventory;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.platform.Handle;
|
||||||
|
|
||||||
|
public interface Inventory extends Handle {
|
||||||
|
int getSize();
|
||||||
|
|
||||||
|
ItemStack getItem(int slot);
|
||||||
|
|
||||||
|
void setItem(int slot, ItemStack newStack);
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package com.dfsek.terra.api.platform.inventory;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.platform.Handle;
|
||||||
|
|
||||||
|
public interface InventoryHolder extends Handle {
|
||||||
|
Inventory getInventory();
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package com.dfsek.terra.api.platform.inventory;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.platform.Handle;
|
||||||
|
import com.dfsek.terra.api.platform.block.MaterialData;
|
||||||
|
import com.dfsek.terra.api.platform.inventory.item.ItemMeta;
|
||||||
|
|
||||||
|
public interface ItemStack extends Handle, Cloneable {
|
||||||
|
int getAmount();
|
||||||
|
|
||||||
|
void setAmount(int i);
|
||||||
|
|
||||||
|
MaterialData getType();
|
||||||
|
|
||||||
|
ItemStack clone();
|
||||||
|
|
||||||
|
ItemMeta getItemMeta();
|
||||||
|
|
||||||
|
void setItemMeta(ItemMeta meta);
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package com.dfsek.terra.api.platform.inventory.item;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.platform.Handle;
|
||||||
|
|
||||||
|
public interface Damageable extends Handle {
|
||||||
|
int getDamage();
|
||||||
|
|
||||||
|
void setDamage(int damage);
|
||||||
|
|
||||||
|
boolean hasDamage();
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package com.dfsek.terra.api.platform.inventory.item;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.platform.Handle;
|
||||||
|
import com.dfsek.terra.api.platform.inventory.ItemStack;
|
||||||
|
|
||||||
|
public interface Enchantment extends Handle {
|
||||||
|
boolean canEnchantItem(ItemStack itemStack);
|
||||||
|
|
||||||
|
String getID();
|
||||||
|
|
||||||
|
boolean conflictsWith(Enchantment other);
|
||||||
|
|
||||||
|
int getMaxLevel();
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package com.dfsek.terra.api.platform.inventory.item;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.platform.Handle;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public interface ItemMeta extends Handle {
|
||||||
|
Map<Enchantment, Integer> getEnchantments();
|
||||||
|
|
||||||
|
void addEnchantment(Enchantment enchantment, int level);
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
/**
|
||||||
|
* API for platform implementations. Mostly interfaces to be implemented by platform delegates.
|
||||||
|
*/
|
||||||
|
package com.dfsek.terra.api.platform;
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package com.dfsek.terra.api.platform.world;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.platform.Handle;
|
||||||
|
|
||||||
|
public interface Biome extends Handle {
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package com.dfsek.terra.api.platform.world;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.platform.Handle;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public interface BiomeGrid extends Handle {
|
||||||
|
/**
|
||||||
|
* Get biome at x, z within chunk being generated
|
||||||
|
*
|
||||||
|
* @param x - 0-15
|
||||||
|
* @param z - 0-15
|
||||||
|
* @return Biome value
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
Biome getBiome(int x, int z);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get biome at x, z within chunk being generated
|
||||||
|
*
|
||||||
|
* @param x - 0-15
|
||||||
|
* @param y - 0-255
|
||||||
|
* @param z - 0-15
|
||||||
|
* @return Biome value
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
Biome getBiome(int x, int y, int z);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set biome at x, z within chunk being generated
|
||||||
|
*
|
||||||
|
* @param x - 0-15
|
||||||
|
* @param z - 0-15
|
||||||
|
* @param bio - Biome value
|
||||||
|
*/
|
||||||
|
void setBiome(int x, int z, @NotNull Biome bio);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set biome at x, z within chunk being generated
|
||||||
|
*
|
||||||
|
* @param x - 0-15
|
||||||
|
* @param y - 0-255
|
||||||
|
* @param z - 0-15
|
||||||
|
* @param bio - Biome value
|
||||||
|
*/
|
||||||
|
void setBiome(int x, int y, int z, @NotNull Biome bio);
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package com.dfsek.terra.api.platform.world;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.platform.Handle;
|
||||||
|
import com.dfsek.terra.api.platform.block.Block;
|
||||||
|
|
||||||
|
public interface Chunk extends Handle {
|
||||||
|
int getX();
|
||||||
|
|
||||||
|
int getZ();
|
||||||
|
|
||||||
|
World getWorld();
|
||||||
|
|
||||||
|
Block getBlock(int x, int y, int z);
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package com.dfsek.terra.api.platform.world;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.platform.Handle;
|
||||||
|
|
||||||
|
public interface Tree extends Handle, com.dfsek.terra.api.world.tree.Tree {
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package com.dfsek.terra.api.platform.world;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.math.vector.Location;
|
||||||
|
import com.dfsek.terra.api.platform.Handle;
|
||||||
|
import com.dfsek.terra.api.platform.block.Block;
|
||||||
|
import com.dfsek.terra.api.platform.generator.ChunkGenerator;
|
||||||
|
import com.dfsek.terra.api.platform.world.entity.Entity;
|
||||||
|
import com.dfsek.terra.api.platform.world.entity.EntityType;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public interface World extends Handle {
|
||||||
|
long getSeed();
|
||||||
|
|
||||||
|
int getMaxHeight();
|
||||||
|
|
||||||
|
ChunkGenerator getGenerator();
|
||||||
|
|
||||||
|
String getName();
|
||||||
|
|
||||||
|
UUID getUID();
|
||||||
|
|
||||||
|
boolean isChunkGenerated(int x, int z);
|
||||||
|
|
||||||
|
Chunk getChunkAt(int x, int z);
|
||||||
|
|
||||||
|
File getWorldFolder();
|
||||||
|
|
||||||
|
Block getBlockAt(int x, int y, int z);
|
||||||
|
|
||||||
|
Block getBlockAt(Location l);
|
||||||
|
|
||||||
|
boolean generateTree(Location l, Tree vanillaTreeType);
|
||||||
|
|
||||||
|
Entity spawnEntity(Location location, EntityType entityType);
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package com.dfsek.terra.api.platform.world.entity;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.platform.Handle;
|
||||||
|
|
||||||
|
public interface Entity extends Handle {
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package com.dfsek.terra.api.platform.world.entity;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.platform.Handle;
|
||||||
|
|
||||||
|
public interface EntityType extends Handle {
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package com.dfsek.terra.api.profiler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class to hold a profiler data value. Contains formatting method to highlight value based on desired range.
|
||||||
|
*/
|
||||||
|
public class DataHolder {
|
||||||
|
private final long desired;
|
||||||
|
private final DataType type;
|
||||||
|
private final double desiredRangePercent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a DataHolder with a DataType and a desired value, including a percentage around the desired value considered acceptable
|
||||||
|
*
|
||||||
|
* @param type The type of data held in this instance.
|
||||||
|
* @param desired The desired value. This should be the average value of whatever is being measured.
|
||||||
|
* @param desiredRangePercent The percentage around the desired value to be considered acceptable.
|
||||||
|
*/
|
||||||
|
public DataHolder(DataType type, long desired, double desiredRangePercent) {
|
||||||
|
this.desired = desired;
|
||||||
|
this.type = type;
|
||||||
|
this.desiredRangePercent = desiredRangePercent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a String, formatted with Bungee ChatColors.<br>
|
||||||
|
* GREEN if the value is better than desired and outside of acceptable range.<br>
|
||||||
|
* YELLOW if the value is better or worse than desired, and within acceptable range.<br>
|
||||||
|
* RED if the value is worse than desired and outside of acceptable range.<br>
|
||||||
|
*
|
||||||
|
* @param data The data to format.
|
||||||
|
* @return String - The formatted data.
|
||||||
|
*/
|
||||||
|
public String getFormattedData(long data) {
|
||||||
|
return type.getFormatted(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package com.dfsek.terra.api.profiler;
|
||||||
|
|
||||||
|
import net.jafama.FastMath;
|
||||||
|
|
||||||
|
public enum DataType {
|
||||||
|
PERIOD_MILLISECONDS(Desire.LOW, 1000000, "ms"), PERIOD_NANOSECONDS(Desire.LOW, 1, "ns");
|
||||||
|
private final Desire desire;
|
||||||
|
private final long divisor;
|
||||||
|
private final String unit;
|
||||||
|
|
||||||
|
DataType(Desire d, long divisor, String unit) {
|
||||||
|
this.desire = d;
|
||||||
|
this.divisor = divisor;
|
||||||
|
this.unit = unit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFormatted(long value) {
|
||||||
|
return (double) FastMath.round(((double) value / divisor) * 100D) / 100D + unit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Desire getDesire() {
|
||||||
|
return desire;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package com.dfsek.terra.api.profiler;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enum to represent the "goal" of a value, whether it is desirable for the value to be high (e.g. Frequency), or low (e.g. Period)
|
||||||
|
*/
|
||||||
|
public enum Desire {
|
||||||
|
LOW, HIGH
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
package com.dfsek.terra.api.profiler;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.math.MathUtil;
|
||||||
|
import com.dfsek.terra.api.util.GlueList;
|
||||||
|
import net.jafama.FastMath;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class to record and hold all data for a single type of measurement performed by the profiler.
|
||||||
|
*/
|
||||||
|
public class Measurement {
|
||||||
|
private final List<Long> measurements = new LinkedList<>();
|
||||||
|
private final long desirable;
|
||||||
|
private final DataType type;
|
||||||
|
private long min = Long.MAX_VALUE;
|
||||||
|
private long max = Long.MIN_VALUE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new Measurement with a desired value and DataType.
|
||||||
|
*
|
||||||
|
* @param desirable The desired value of the measurement.
|
||||||
|
* @param type The type of data the measurement is holding.
|
||||||
|
*/
|
||||||
|
public Measurement(long desirable, DataType type) {
|
||||||
|
this.desirable = desirable;
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void record(long value) {
|
||||||
|
max = FastMath.max(value, max);
|
||||||
|
min = FastMath.min(value, min);
|
||||||
|
measurements.add(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int size() {
|
||||||
|
return measurements.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProfileFuture beginMeasurement() {
|
||||||
|
ProfileFuture future = new ProfileFuture();
|
||||||
|
long current = System.nanoTime();
|
||||||
|
future.thenRun(() -> record(System.nanoTime() - current));
|
||||||
|
return future;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reset() {
|
||||||
|
min = Long.MAX_VALUE;
|
||||||
|
max = Long.MIN_VALUE;
|
||||||
|
measurements.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public DataHolder getDataHolder() {
|
||||||
|
return new DataHolder(type, desirable, 0.25);
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getMin() {
|
||||||
|
if(min == Long.MAX_VALUE) return 0;
|
||||||
|
return min;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getMax() {
|
||||||
|
if(max == Long.MIN_VALUE) return 0;
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long average() {
|
||||||
|
BigInteger running = BigInteger.valueOf(0);
|
||||||
|
List<Long> mTemp = new GlueList<>(measurements);
|
||||||
|
for(Long l : mTemp) {
|
||||||
|
running = running.add(BigInteger.valueOf(l));
|
||||||
|
}
|
||||||
|
if(measurements.size() == 0) return 0;
|
||||||
|
return running.divide(BigInteger.valueOf(measurements.size())).longValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getStdDev() {
|
||||||
|
return MathUtil.standardDeviation(new GlueList<>(measurements));
|
||||||
|
}
|
||||||
|
|
||||||
|
public int entries() {
|
||||||
|
return measurements.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package com.dfsek.terra.api.profiler;
|
||||||
|
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
public class ProfileFuture extends CompletableFuture<Boolean> implements AutoCloseable {
|
||||||
|
public ProfileFuture() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean complete() {
|
||||||
|
return super.complete(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
this.complete();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
package com.dfsek.terra.api.profiler;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.platform.world.World;
|
||||||
|
import com.google.common.collect.BiMap;
|
||||||
|
import com.google.common.collect.HashBiMap;
|
||||||
|
import net.jafama.FastMath;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class WorldProfiler {
|
||||||
|
private final BiMap<String, Measurement> measures = HashBiMap.create();
|
||||||
|
private final World world;
|
||||||
|
private boolean isProfiling;
|
||||||
|
|
||||||
|
public WorldProfiler(World w) {
|
||||||
|
if(w.getGenerator().getTerraGenerator() == null)
|
||||||
|
throw new IllegalArgumentException("Attempted to instantiate profiler on non-Gaea managed world!");
|
||||||
|
this.addMeasurement(new Measurement(2500000, DataType.PERIOD_MILLISECONDS), "TotalChunkGenTime");
|
||||||
|
isProfiling = false;
|
||||||
|
this.world = w;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getResultsFormatted() {
|
||||||
|
if(! isProfiling) return "Profiler is not currently running.";
|
||||||
|
StringBuilder result = new StringBuilder("Gaea World Profiler Results (Min / Avg / Max / Std Dev): \n");
|
||||||
|
for(Map.Entry<String, Measurement> e : measures.entrySet()) {
|
||||||
|
result
|
||||||
|
.append(e.getKey())
|
||||||
|
.append(": ")
|
||||||
|
.append(e.getValue().getDataHolder().getFormattedData(e.getValue().getMin()))
|
||||||
|
.append(" / ")
|
||||||
|
.append(e.getValue().getDataHolder().getFormattedData(e.getValue().average()))
|
||||||
|
.append(" / ")
|
||||||
|
.append(e.getValue().getDataHolder().getFormattedData(e.getValue().getMax()))
|
||||||
|
.append(" / ")
|
||||||
|
.append((double) FastMath.round((e.getValue().getStdDev() / 1000000) * 100D) / 100D)
|
||||||
|
.append("ms")
|
||||||
|
.append(" (x").append(e.getValue().size()).append(")\n");
|
||||||
|
}
|
||||||
|
return result.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reset() {
|
||||||
|
for(Map.Entry<String, Measurement> e : measures.entrySet()) {
|
||||||
|
e.getValue().reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public com.dfsek.terra.api.profiler.WorldProfiler addMeasurement(Measurement m, String name) {
|
||||||
|
measures.put(name, m);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMeasurement(String id, long value) {
|
||||||
|
if(isProfiling) measures.get(id).record(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProfileFuture measure(String id) {
|
||||||
|
if(isProfiling) return measures.get(id).beginMeasurement();
|
||||||
|
else return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getID(Measurement m) {
|
||||||
|
return measures.inverse().get(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isProfiling() {
|
||||||
|
return isProfiling;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProfiling(boolean enabled) {
|
||||||
|
this.isProfiling = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public World getWorld() {
|
||||||
|
return world;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,103 @@
|
|||||||
|
package com.dfsek.terra.api.structures.loot;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.platform.TerraPlugin;
|
||||||
|
import com.dfsek.terra.api.platform.block.MaterialData;
|
||||||
|
import com.dfsek.terra.api.platform.inventory.ItemStack;
|
||||||
|
import com.dfsek.terra.api.structures.loot.functions.AmountFunction;
|
||||||
|
import com.dfsek.terra.api.structures.loot.functions.DamageFunction;
|
||||||
|
import com.dfsek.terra.api.structures.loot.functions.EnchantFunction;
|
||||||
|
import com.dfsek.terra.api.structures.loot.functions.LootFunction;
|
||||||
|
import com.dfsek.terra.api.util.GlueList;
|
||||||
|
import net.jafama.FastMath;
|
||||||
|
import org.json.simple.JSONArray;
|
||||||
|
import org.json.simple.JSONObject;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Representation of a single item entry within a Loot Table pool.
|
||||||
|
*/
|
||||||
|
public class Entry {
|
||||||
|
private final MaterialData item;
|
||||||
|
private final long weight;
|
||||||
|
private final List<LootFunction> functions = new GlueList<>();
|
||||||
|
private final TerraPlugin main;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates an Entry from a JSON representation.
|
||||||
|
*
|
||||||
|
* @param entry The JSON Object to instantiate from.
|
||||||
|
*/
|
||||||
|
public Entry(JSONObject entry, TerraPlugin main) {
|
||||||
|
this.main = main;
|
||||||
|
String id = entry.get("name").toString();
|
||||||
|
this.item = main.getWorldHandle().createMaterialData(id);
|
||||||
|
|
||||||
|
long weight1;
|
||||||
|
try {
|
||||||
|
weight1 = (long) entry.get("weight");
|
||||||
|
} catch(NullPointerException e) {
|
||||||
|
weight1 = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.weight = weight1;
|
||||||
|
if(entry.containsKey("functions")) {
|
||||||
|
for(Object function : (JSONArray) entry.get("functions")) {
|
||||||
|
switch(((String) ((JSONObject) function).get("function"))) {
|
||||||
|
case "minecraft:set_count":
|
||||||
|
case "set_count":
|
||||||
|
Object loot = ((JSONObject) function).get("count");
|
||||||
|
long max, min;
|
||||||
|
if(loot instanceof Long) {
|
||||||
|
max = (Long) loot;
|
||||||
|
min = (Long) loot;
|
||||||
|
} else {
|
||||||
|
max = (long) ((JSONObject) loot).get("max");
|
||||||
|
min = (long) ((JSONObject) loot).get("min");
|
||||||
|
}
|
||||||
|
functions.add(new AmountFunction(FastMath.toIntExact(min), FastMath.toIntExact(max)));
|
||||||
|
break;
|
||||||
|
case "minecraft:set_damage":
|
||||||
|
case "set_damage":
|
||||||
|
long maxDamage = (long) ((JSONObject) ((JSONObject) function).get("damage")).get("max");
|
||||||
|
long minDamage = (long) ((JSONObject) ((JSONObject) function).get("damage")).get("min");
|
||||||
|
functions.add(new DamageFunction(FastMath.toIntExact(minDamage), FastMath.toIntExact(maxDamage)));
|
||||||
|
break;
|
||||||
|
case "minecraft:enchant_with_levels":
|
||||||
|
case "enchant_with_levels":
|
||||||
|
long maxEnchant = (long) ((JSONObject) ((JSONObject) function).get("levels")).get("max");
|
||||||
|
long minEnchant = (long) ((JSONObject) ((JSONObject) function).get("levels")).get("min");
|
||||||
|
JSONArray disabled = null;
|
||||||
|
if(((JSONObject) function).containsKey("disabled_enchants"))
|
||||||
|
disabled = (JSONArray) ((JSONObject) function).get("disabled_enchants");
|
||||||
|
functions.add(new EnchantFunction(FastMath.toIntExact(minEnchant), FastMath.toIntExact(maxEnchant), disabled, main));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches a single ItemStack from the Entry, applying all functions to it.
|
||||||
|
*
|
||||||
|
* @param r The Random instance to apply functions with
|
||||||
|
* @return ItemStack - The ItemStack with all functions applied.
|
||||||
|
*/
|
||||||
|
public ItemStack getItem(Random r) {
|
||||||
|
ItemStack item = main.getItemHandle().newItemStack(this.item, 1);
|
||||||
|
for(LootFunction f : functions) {
|
||||||
|
item = f.apply(item, r);
|
||||||
|
}
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the weight attribute of the Entry.
|
||||||
|
*
|
||||||
|
* @return long - The weight of the Entry.
|
||||||
|
*/
|
||||||
|
public long getWeight() {
|
||||||
|
return this.weight;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
package com.dfsek.terra.api.structures.loot;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.platform.TerraPlugin;
|
||||||
|
import com.dfsek.terra.api.platform.inventory.Inventory;
|
||||||
|
import com.dfsek.terra.api.platform.inventory.ItemStack;
|
||||||
|
import com.dfsek.terra.api.util.GlueList;
|
||||||
|
import org.json.simple.JSONArray;
|
||||||
|
import org.json.simple.JSONObject;
|
||||||
|
import org.json.simple.parser.JSONParser;
|
||||||
|
import org.json.simple.parser.ParseException;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class representation of a Loot Table to populate chest loot.
|
||||||
|
*/
|
||||||
|
public class LootTable {
|
||||||
|
private final List<Pool> pools = new GlueList<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a LootTable from a JSON String.
|
||||||
|
*
|
||||||
|
* @param json The JSON String representing the loot table.
|
||||||
|
* @throws ParseException if malformed JSON is passed.
|
||||||
|
*/
|
||||||
|
public LootTable(String json, TerraPlugin main) throws ParseException {
|
||||||
|
JSONParser jsonParser = new JSONParser();
|
||||||
|
Object tableJSON = jsonParser.parse(json);
|
||||||
|
JSONArray poolArray = (JSONArray) ((JSONObject) tableJSON).get("pools");
|
||||||
|
for(Object pool : poolArray) {
|
||||||
|
pools.add(new Pool((JSONObject) pool, main));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches a list of ItemStacks from the loot table using the given Random instance.
|
||||||
|
*
|
||||||
|
* @param r The Random instance to use.
|
||||||
|
* @return List<ItemStack> - The list of loot fetched.
|
||||||
|
*/
|
||||||
|
public List<ItemStack> getLoot(Random r) {
|
||||||
|
List<ItemStack> itemList = new GlueList<>();
|
||||||
|
for(Pool pool : pools) {
|
||||||
|
itemList.addAll(pool.getItems(r));
|
||||||
|
}
|
||||||
|
return itemList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fills an Inventory with loot.
|
||||||
|
*
|
||||||
|
* @param i The Inventory to fill.
|
||||||
|
* @param r The The Random instance to use.
|
||||||
|
*/
|
||||||
|
public void fillInventory(Inventory i, Random r) {
|
||||||
|
List<ItemStack> loot = getLoot(r);
|
||||||
|
for(ItemStack stack : loot) {
|
||||||
|
int attempts = 0;
|
||||||
|
while(stack.getAmount() != 0 && attempts < 10) {
|
||||||
|
ItemStack newStack = stack.clone();
|
||||||
|
newStack.setAmount(1);
|
||||||
|
int slot = r.nextInt(i.getSize());
|
||||||
|
ItemStack slotItem = i.getItem(slot);
|
||||||
|
if(slotItem == null) {
|
||||||
|
i.setItem(slot, newStack);
|
||||||
|
stack.setAmount(stack.getAmount() - 1);
|
||||||
|
} else if(slotItem.getType().equals(newStack.getType())) {
|
||||||
|
ItemStack dep = newStack.clone();
|
||||||
|
dep.setAmount(newStack.getAmount() + slotItem.getAmount());
|
||||||
|
i.setItem(slot, dep);
|
||||||
|
stack.setAmount(stack.getAmount() - 1);
|
||||||
|
}
|
||||||
|
attempts++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
package com.dfsek.terra.api.structures.loot;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.math.ProbabilityCollection;
|
||||||
|
import com.dfsek.terra.api.platform.TerraPlugin;
|
||||||
|
import com.dfsek.terra.api.platform.inventory.ItemStack;
|
||||||
|
import com.dfsek.terra.api.util.GlueList;
|
||||||
|
import net.jafama.FastMath;
|
||||||
|
import org.json.simple.JSONArray;
|
||||||
|
import org.json.simple.JSONObject;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Representation of a Loot Table pool, or a set of items to be fetched independently.
|
||||||
|
*/
|
||||||
|
public class Pool {
|
||||||
|
private final int max;
|
||||||
|
private final int min;
|
||||||
|
private final ProbabilityCollection<Entry> entries;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a Pool from a JSON representation.
|
||||||
|
*
|
||||||
|
* @param pool The JSON Object to instantiate from.
|
||||||
|
*/
|
||||||
|
public Pool(JSONObject pool, TerraPlugin main) {
|
||||||
|
entries = new ProbabilityCollection<>();
|
||||||
|
Object amount = pool.get("rolls");
|
||||||
|
if(amount instanceof Long) {
|
||||||
|
max = FastMath.toIntExact((Long) amount);
|
||||||
|
min = FastMath.toIntExact((Long) amount);
|
||||||
|
} else {
|
||||||
|
max = FastMath.toIntExact((Long) ((JSONObject) amount).get("max"));
|
||||||
|
min = FastMath.toIntExact((Long) ((JSONObject) amount).get("min"));
|
||||||
|
}
|
||||||
|
|
||||||
|
for(Object entryJSON : (JSONArray) pool.get("entries")) {
|
||||||
|
Entry entry = new Entry((JSONObject) entryJSON, main);
|
||||||
|
entries.add(entry, FastMath.toIntExact(entry.getWeight()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches a list of items from the pool using the provided Random instance.
|
||||||
|
*
|
||||||
|
* @param r The Random instance to use.
|
||||||
|
* @return List<ItemStack> - The list of items fetched.
|
||||||
|
*/
|
||||||
|
public List<ItemStack> getItems(Random r) {
|
||||||
|
|
||||||
|
int rolls = r.nextInt(max - min + 1) + min;
|
||||||
|
List<ItemStack> items = new GlueList<>();
|
||||||
|
for(int i = 0; i < rolls; i++) {
|
||||||
|
items.add(entries.get(r).getItem(r));
|
||||||
|
}
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
}
|
||||||
+38
@@ -0,0 +1,38 @@
|
|||||||
|
package com.dfsek.terra.api.structures.loot.functions;
|
||||||
|
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.platform.inventory.ItemStack;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loot LootFunction fot setting the amount of an item.
|
||||||
|
*/
|
||||||
|
public class AmountFunction implements LootFunction {
|
||||||
|
private final int max;
|
||||||
|
private final int min;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates an AmountFunction.
|
||||||
|
*
|
||||||
|
* @param min Minimum amount.
|
||||||
|
* @param max Maximum amount.
|
||||||
|
*/
|
||||||
|
public AmountFunction(int min, int max) {
|
||||||
|
this.min = min;
|
||||||
|
this.max = max;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies the function to an ItemStack.
|
||||||
|
*
|
||||||
|
* @param original The ItemStack on which to apply the function.
|
||||||
|
* @param r The Random instance to use.
|
||||||
|
* @return - ItemStack - The mutated ItemStack.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public ItemStack apply(ItemStack original, Random r) {
|
||||||
|
original.setAmount(r.nextInt(max - min + 1) + min);
|
||||||
|
return original;
|
||||||
|
}
|
||||||
|
}
|
||||||
+42
@@ -0,0 +1,42 @@
|
|||||||
|
package com.dfsek.terra.api.structures.loot.functions;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.platform.inventory.ItemStack;
|
||||||
|
import com.dfsek.terra.api.platform.inventory.item.Damageable;
|
||||||
|
import com.dfsek.terra.api.platform.inventory.item.ItemMeta;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loot LootFunction for setting the damage on items in Loot Tables
|
||||||
|
*/
|
||||||
|
public class DamageFunction implements LootFunction {
|
||||||
|
private final int max;
|
||||||
|
private final int min;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a DamageFunction.
|
||||||
|
*
|
||||||
|
* @param min Minimum amount of damage (percentage, out of 100)
|
||||||
|
* @param max Maximum amount of damage (percentage, out of 100)
|
||||||
|
*/
|
||||||
|
public DamageFunction(int min, int max) {
|
||||||
|
this.min = min;
|
||||||
|
this.max = max;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies the function to an ItemStack.
|
||||||
|
*
|
||||||
|
* @param original The ItemStack on which to apply the function.
|
||||||
|
* @param r The Random instance to use.
|
||||||
|
* @return - ItemStack - The mutated ItemStack.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public ItemStack apply(ItemStack original, Random r) {
|
||||||
|
double itemDurability = (r.nextDouble() * (max - min)) + min;
|
||||||
|
Damageable damage = (Damageable) original.getItemMeta();
|
||||||
|
damage.setDamage((int) (original.getType().getMaxDurability() - (itemDurability / 100) * original.getType().getMaxDurability()));
|
||||||
|
original.setItemMeta((ItemMeta) damage);
|
||||||
|
return original;
|
||||||
|
}
|
||||||
|
}
|
||||||
+64
@@ -0,0 +1,64 @@
|
|||||||
|
package com.dfsek.terra.api.structures.loot.functions;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.platform.TerraPlugin;
|
||||||
|
import com.dfsek.terra.api.platform.inventory.ItemStack;
|
||||||
|
import com.dfsek.terra.api.platform.inventory.item.Enchantment;
|
||||||
|
import com.dfsek.terra.api.platform.inventory.item.ItemMeta;
|
||||||
|
import com.dfsek.terra.api.util.GlueList;
|
||||||
|
import net.jafama.FastMath;
|
||||||
|
import org.json.simple.JSONArray;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class EnchantFunction implements LootFunction {
|
||||||
|
private final int min;
|
||||||
|
private final int max;
|
||||||
|
private final JSONArray disabled;
|
||||||
|
private final TerraPlugin main;
|
||||||
|
|
||||||
|
|
||||||
|
public EnchantFunction(int min, int max, JSONArray disabled, TerraPlugin main) {
|
||||||
|
this.max = max;
|
||||||
|
this.min = min;
|
||||||
|
this.disabled = disabled;
|
||||||
|
this.main = main;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies the function to an ItemStack.
|
||||||
|
*
|
||||||
|
* @param original The ItemStack on which to apply the function.
|
||||||
|
* @param r The Random instance to use.
|
||||||
|
* @return - ItemStack - The mutated ItemStack.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public ItemStack apply(ItemStack original, Random r) {
|
||||||
|
double enchant = (r.nextDouble() * (max - min)) + min;
|
||||||
|
List<Enchantment> possible = new GlueList<>();
|
||||||
|
for(Enchantment ench : main.getItemHandle().getEnchantments()) {
|
||||||
|
if(ench.canEnchantItem(original) && (disabled == null || !this.disabled.contains(ench.getID()))) {
|
||||||
|
possible.add(ench);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int numEnchant = (r.nextInt((int) FastMath.abs(enchant)) / 10 + 1);
|
||||||
|
Collections.shuffle(possible);
|
||||||
|
ItemMeta meta = original.getItemMeta();
|
||||||
|
iter:
|
||||||
|
for(int i = 0; i < numEnchant && i < possible.size(); i++) {
|
||||||
|
Enchantment chosen = possible.get(i);
|
||||||
|
for(Enchantment ench : meta.getEnchantments().keySet()) {
|
||||||
|
if(chosen.conflictsWith(ench)) continue iter;
|
||||||
|
}
|
||||||
|
int lvl = r.nextInt(1 + (int) (((enchant / 40 > 1) ? 1 : enchant / 40) * (chosen.getMaxLevel())));
|
||||||
|
try {
|
||||||
|
meta.addEnchantment(chosen, FastMath.max(lvl, 1));
|
||||||
|
} catch(IllegalArgumentException e) {
|
||||||
|
main.getLogger().warning("Attempted to enchant " + original.getType() + " with " + chosen + " at level " + FastMath.max(lvl, 1) + ", but an unexpected exception occurred! Usually this is caused by a misbehaving enchantment plugin.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
original.setItemMeta(meta);
|
||||||
|
return original;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package com.dfsek.terra.api.structures.loot.functions;
|
||||||
|
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.platform.inventory.ItemStack;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for mutating items in Loot Tables.
|
||||||
|
*/
|
||||||
|
public interface LootFunction {
|
||||||
|
/**
|
||||||
|
* Applies the function to an ItemStack.
|
||||||
|
*
|
||||||
|
* @param original The ItemStack on which to apply the function.
|
||||||
|
* @param r The Random instance to use.
|
||||||
|
* @return - ItemStack - The mutated ItemStack.
|
||||||
|
*/
|
||||||
|
ItemStack apply(ItemStack original, Random r);
|
||||||
|
}
|
||||||
Loaded 100 of 568 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user