diff --git a/.gitignore b/.gitignore index 6d85c9383..ab2a28212 100644 --- a/.gitignore +++ b/.gitignore @@ -137,3 +137,9 @@ build !lib/*.jar .idea/Terra.iml +/run/ +.idea/**.iml +/lang/ +/packs/ +/config.yml +/region/ diff --git a/build.gradle.kts b/build.gradle.kts index 8bfb37382..b90837c17 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,192 +1,11 @@ -//import java.util.zip.ZipFile -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 +import com.dfsek.terra.getGitHash -plugins { - java - maven - id("com.github.johnrengelman.shadow").version("6.1.0") +val versionObj = Version("3", "0", "0", true) + +allprojects { + 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 { - include("**/*.yml") - filter( - "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") { - // 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(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. */ @@ -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. "$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()) } \ No newline at end of file diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts new file mode 100644 index 000000000..ecf0454d8 --- /dev/null +++ b/buildSrc/build.gradle.kts @@ -0,0 +1,13 @@ +plugins { + `kotlin-dsl` + kotlin("jvm") version embeddedKotlinVersion +} + +repositories { + mavenCentral() + gradlePluginPortal() +} + +dependencies { + "implementation"("com.github.jengelman.gradle.plugins:shadow:+") +} \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/com/dfsek/terra/CommonConfig.kt b/buildSrc/src/main/kotlin/com/dfsek/terra/CommonConfig.kt new file mode 100644 index 000000000..2405568cd --- /dev/null +++ b/buildSrc/src/main/kotlin/com/dfsek/terra/CommonConfig.kt @@ -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().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 + } +} diff --git a/buildSrc/src/main/kotlin/com/dfsek/terra/CompilationConfig.kt b/buildSrc/src/main/kotlin/com/dfsek/terra/CompilationConfig.kt new file mode 100644 index 000000000..ae2f81b9c --- /dev/null +++ b/buildSrc/src/main/kotlin/com/dfsek/terra/CompilationConfig.kt @@ -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 { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } + + tasks.withType { + options.encoding = "UTF-8" + doFirst { + options.compilerArgs = mutableListOf("-Xlint:all") + } + } + + tasks.withType { + options.encoding = "UTF-8" + } +} \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/com/dfsek/terra/DependencyConfig.kt b/buildSrc/src/main/kotlin/com/dfsek/terra/DependencyConfig.kt new file mode 100644 index 000000000..28a6f8e00 --- /dev/null +++ b/buildSrc/src/main/kotlin/com/dfsek/terra/DependencyConfig.kt @@ -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") + } +} \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/com/dfsek/terra/DistributionConfig.kt b/buildSrc/src/main/kotlin/com/dfsek/terra/DistributionConfig.kt new file mode 100644 index 000000000..4f5392ca6 --- /dev/null +++ b/buildSrc/src/main/kotlin/com/dfsek/terra/DistributionConfig.kt @@ -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 { +// 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("sourcesJar") { + archiveClassifier.set("sources") + } + + tasks.withType { + from("../LICENSE", "../../LICENSE") + } + + tasks.register("javadocJar") { + dependsOn("javadoc") + archiveClassifier.set("javadoc") + from(tasks.getByName("javadoc").destinationDir) + } + + tasks.named("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().archivesBaseName = project.name + + tasks.named("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()) +} \ No newline at end of file diff --git a/common/build.gradle.kts b/common/build.gradle.kts new file mode 100644 index 000000000..7134054f9 --- /dev/null +++ b/common/build.gradle.kts @@ -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") +} \ No newline at end of file diff --git a/src/main/java/com/dfsek/terra/TerraProfiler.java b/common/src/main/java/com/dfsek/terra/TerraProfiler.java similarity index 66% rename from src/main/java/com/dfsek/terra/TerraProfiler.java rename to common/src/main/java/com/dfsek/terra/TerraProfiler.java index a0b03a9e0..7633fdf0c 100644 --- a/src/main/java/com/dfsek/terra/TerraProfiler.java +++ b/common/src/main/java/com/dfsek/terra/TerraProfiler.java @@ -1,9 +1,9 @@ package com.dfsek.terra; -import org.bukkit.World; -import org.polydev.gaea.profiler.DataType; -import org.polydev.gaea.profiler.Measurement; -import org.polydev.gaea.profiler.WorldProfiler; +import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.api.profiler.DataType; +import com.dfsek.terra.api.profiler.Measurement; +import com.dfsek.terra.api.profiler.WorldProfiler; public class TerraProfiler extends WorldProfiler { public TerraProfiler(World w) { @@ -13,7 +13,6 @@ public class TerraProfiler extends WorldProfiler { .addMeasurement(new Measurement(10000000, DataType.PERIOD_MILLISECONDS), "TreeTime") .addMeasurement(new Measurement(1500000, DataType.PERIOD_MILLISECONDS), "OreTime") .addMeasurement(new Measurement(5000000, DataType.PERIOD_MILLISECONDS), "CaveTime") - .addMeasurement(new Measurement(1500000, DataType.PERIOD_MILLISECONDS), "StructureTime") - .addMeasurement(new Measurement(1500000, DataType.PERIOD_MILLISECONDS), "ElevationTime"); + .addMeasurement(new Measurement(1500000, DataType.PERIOD_MILLISECONDS), "StructureTime"); } } diff --git a/common/src/main/java/com/dfsek/terra/TerraWorld.java b/common/src/main/java/com/dfsek/terra/TerraWorld.java new file mode 100644 index 000000000..350b6b67f --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/TerraWorld.java @@ -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; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/Entity.java b/common/src/main/java/com/dfsek/terra/api/Entity.java new file mode 100644 index 000000000..7f3ea7514 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/Entity.java @@ -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(); +} diff --git a/common/src/main/java/com/dfsek/terra/api/Gaea.java b/common/src/main/java/com/dfsek/terra/api/Gaea.java new file mode 100644 index 000000000..4c0890fca --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/Gaea.java @@ -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; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/GenericLoaders.java b/common/src/main/java/com/dfsek/terra/api/GenericLoaders.java new file mode 100644 index 000000000..a3ec9ab35 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/GenericLoaders.java @@ -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)); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/LoaderRegistrar.java b/common/src/main/java/com/dfsek/terra/api/LoaderRegistrar.java new file mode 100644 index 000000000..96308deb0 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/LoaderRegistrar.java @@ -0,0 +1,7 @@ +package com.dfsek.terra.api; + +import com.dfsek.tectonic.loading.TypeRegistry; + +public interface LoaderRegistrar { + void register(TypeRegistry registry); +} diff --git a/common/src/main/java/com/dfsek/terra/api/Player.java b/common/src/main/java/com/dfsek/terra/api/Player.java new file mode 100644 index 000000000..3d4a1b4a0 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/Player.java @@ -0,0 +1,4 @@ +package com.dfsek.terra.api; + +public interface Player extends Entity { +} diff --git a/common/src/main/java/com/dfsek/terra/api/language/Language.java b/common/src/main/java/com/dfsek/terra/api/language/Language.java new file mode 100644 index 000000000..d00066da7 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/language/Language.java @@ -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) 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); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/language/Message.java b/common/src/main/java/com/dfsek/terra/api/language/Message.java new file mode 100644 index 000000000..8a064132b --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/language/Message.java @@ -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(); +} diff --git a/common/src/main/java/com/dfsek/terra/api/language/MultiLineMessage.java b/common/src/main/java/com/dfsek/terra/api/language/MultiLineMessage.java new file mode 100644 index 000000000..397ff629e --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/language/MultiLineMessage.java @@ -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 message; + public MultiLineMessage(List 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(); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/language/SingleLineMessage.java b/common/src/main/java/com/dfsek/terra/api/language/SingleLineMessage.java new file mode 100644 index 000000000..e3f65411b --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/language/SingleLineMessage.java @@ -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(""); + } +} diff --git a/src/main/java/com/dfsek/terra/procgen/GridSpawn.java b/common/src/main/java/com/dfsek/terra/api/math/GridSpawn.java similarity index 68% rename from src/main/java/com/dfsek/terra/procgen/GridSpawn.java rename to common/src/main/java/com/dfsek/terra/api/math/GridSpawn.java index 371625192..f25832de1 100644 --- a/src/main/java/com/dfsek/terra/procgen/GridSpawn.java +++ b/common/src/main/java/com/dfsek/terra/api/math/GridSpawn.java @@ -1,9 +1,8 @@ -package com.dfsek.terra.procgen; +package com.dfsek.terra.api.math; -import org.bukkit.util.Vector; -import org.polydev.gaea.math.MathUtil; -import org.polydev.gaea.util.FastRandom; -import org.polydev.gaea.util.GlueList; +import com.dfsek.terra.api.math.vector.Vector3; +import com.dfsek.terra.api.util.FastRandom; +import com.dfsek.terra.api.util.GlueList; import java.util.List; import java.util.Random; @@ -14,12 +13,12 @@ import java.util.Random; public class GridSpawn { private final int separation; 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.width = width; - this.seedOffset = seedOffset; + this.salt = salt; } /** @@ -30,18 +29,18 @@ public class GridSpawn { * @param seed Seed for RNG * @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 structureChunkZ = z / (width + 2 * separation); - List zones = new GlueList<>(); + List zones = new GlueList<>(); for(int xi = structureChunkX - 1; xi <= structureChunkX + 1; xi++) { 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); - Vector compare = new Vector(x, 0, z); - for(Vector v : zones) { + Vector3 shortest = zones.get(0); + Vector3 compare = new Vector3(x, 0, z); + for(Vector3 v : zones) { if(compare.distanceSquared(shortest) > compare.distanceSquared(v)) shortest = v.clone(); } return shortest; @@ -55,13 +54,13 @@ public class GridSpawn { * @param seed Seed for RNG * @return Vector representing spawnpoint */ - public Vector getChunkSpawn(int structureChunkX, int structureChunkZ, long seed) { - Random r = new FastRandom(MathUtil.getCarverChunkSeed(structureChunkX, structureChunkZ, seed + seedOffset)); + public Vector3 getChunkSpawn(int structureChunkX, int structureChunkZ, long seed) { + Random r = new FastRandom(MathUtil.getCarverChunkSeed(structureChunkX, structureChunkZ, seed + salt)); int offsetX = r.nextInt(width); int offsetZ = r.nextInt(width); int sx = structureChunkX * (width + 2 * separation) + offsetX; int sz = structureChunkZ * (width + 2 * separation) + offsetZ; - return new Vector(sx, 0, sz); + return new Vector3(sx, 0, sz); } public int getWidth() { diff --git a/common/src/main/java/com/dfsek/terra/api/math/MathUtil.java b/common/src/main/java/com/dfsek/terra/api/math/MathUtil.java new file mode 100644 index 000000000..a16981af3 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/math/MathUtil.java @@ -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 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); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/math/ProbabilityCollection.java b/common/src/main/java/com/dfsek/terra/api/math/ProbabilityCollection.java new file mode 100644 index 000000000..829acf7d6 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/math/ProbabilityCollection.java @@ -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 { + private final Set cont = new HashSet<>(); + private Object[] array = new Object[0]; + private int size; + + public com.dfsek.terra.api.math.ProbabilityCollection 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; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/math/Range.java b/common/src/main/java/com/dfsek/terra/api/math/Range.java new file mode 100644 index 000000000..6c5d3174a --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/math/Range.java @@ -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 { + 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 iterator() { + return new RangeIterator(this); + } + + private static class RangeIterator implements Iterator { + 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; + } + } +} + diff --git a/src/main/java/com/dfsek/terra/math/NoiseFunction.java b/common/src/main/java/com/dfsek/terra/api/math/noise/NoiseFunction.java similarity index 67% rename from src/main/java/com/dfsek/terra/math/NoiseFunction.java rename to common/src/main/java/com/dfsek/terra/api/math/noise/NoiseFunction.java index ccc604c9e..fee570689 100644 --- a/src/main/java/com/dfsek/terra/math/NoiseFunction.java +++ b/common/src/main/java/com/dfsek/terra/api/math/noise/NoiseFunction.java @@ -1,4 +1,4 @@ -package com.dfsek.terra.math; +package com.dfsek.terra.api.math.noise; import parsii.eval.Function; diff --git a/src/main/java/com/dfsek/terra/math/NoiseFunction2.java b/common/src/main/java/com/dfsek/terra/api/math/noise/NoiseFunction2.java similarity index 89% rename from src/main/java/com/dfsek/terra/math/NoiseFunction2.java rename to common/src/main/java/com/dfsek/terra/api/math/noise/NoiseFunction2.java index fac412c93..a1f490c3d 100644 --- a/src/main/java/com/dfsek/terra/math/NoiseFunction2.java +++ b/common/src/main/java/com/dfsek/terra/api/math/noise/NoiseFunction2.java @@ -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.util.hash.HashMapDoubleDouble; -import org.polydev.gaea.math.FastNoiseLite; import parsii.eval.Expression; import java.util.List; public class NoiseFunction2 implements NoiseFunction { - private final FastNoiseLite gen; + private final NoiseSampler gen; private final Cache cache = new Cache(); public NoiseFunction2(long seed, NoiseBuilder builder) { @@ -44,7 +44,7 @@ public class NoiseFunction2 implements NoiseFunction { private static final long serialVersionUID = 8915092734723467010L; 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 zz = z >= 0 ? z * 2 : z * -2 - 1; double key = (xx >= zz) ? (xx * xx + xx + zz) : (zz * zz + xx); diff --git a/src/main/java/com/dfsek/terra/math/NoiseFunction3.java b/common/src/main/java/com/dfsek/terra/api/math/noise/NoiseFunction3.java similarity index 81% rename from src/main/java/com/dfsek/terra/math/NoiseFunction3.java rename to common/src/main/java/com/dfsek/terra/api/math/noise/NoiseFunction3.java index f257afff5..4915e1c68 100644 --- a/src/main/java/com/dfsek/terra/math/NoiseFunction3.java +++ b/common/src/main/java/com/dfsek/terra/api/math/noise/NoiseFunction3.java @@ -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 org.polydev.gaea.math.FastNoiseLite; import parsii.eval.Expression; import java.util.List; public class NoiseFunction3 implements NoiseFunction { - private final FastNoiseLite gen; + private final NoiseSampler gen; public NoiseFunction3(long seed, NoiseBuilder builder) { this.gen = builder.build((int) seed); diff --git a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/FastNoiseLite.java b/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/FastNoiseLite.java new file mode 100644 index 000000000..3b125cf05 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/FastNoiseLite.java @@ -0,0 +1,2567 @@ +package com.dfsek.terra.api.math.noise.samplers;// MIT License + +import com.dfsek.terra.api.math.vector.Vector2; +import com.dfsek.terra.api.math.vector.Vector3; +import net.jafama.FastMath; + +/* + +Copyright(c) 2020 Jordan Peck (jordan.me2@gmail.com) +Copyright(c) 2020 Contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +VERSION: 1.0.1 +https://github.com/Auburn/FastNoise + */ +@SuppressWarnings({"ManualMinMaxCalculation", "unused"}) +public class FastNoiseLite implements NoiseSampler { + private static final double[] GRADIENTS_2_D = { + 0.130526192220052f, 0.99144486137381f, 0.38268343236509f, 0.923879532511287f, 0.608761429008721f, 0.793353340291235f, + 0.793353340291235f, 0.608761429008721f, 0.923879532511287f, 0.38268343236509f, 0.99144486137381f, 0.130526192220051f, + 0.99144486137381f, -0.130526192220051f, 0.923879532511287f, -0.38268343236509f, 0.793353340291235f, -0.60876142900872f, + 0.608761429008721f, -0.793353340291235f, 0.38268343236509f, -0.923879532511287f, 0.130526192220052f, -0.99144486137381f, + -0.130526192220052f, -0.99144486137381f, -0.38268343236509f, -0.923879532511287f, -0.608761429008721f, -0.793353340291235f, + -0.793353340291235f, -0.608761429008721f, -0.923879532511287f, -0.38268343236509f, -0.99144486137381f, -0.130526192220052f, + -0.99144486137381f, 0.130526192220051f, -0.923879532511287f, 0.38268343236509f, -0.793353340291235f, 0.608761429008721f, + -0.608761429008721f, 0.793353340291235f, -0.38268343236509f, 0.923879532511287f, -0.130526192220052f, 0.99144486137381f, + 0.130526192220052f, 0.99144486137381f, 0.38268343236509f, 0.923879532511287f, 0.608761429008721f, 0.793353340291235f, + 0.793353340291235f, 0.608761429008721f, 0.923879532511287f, 0.38268343236509f, 0.99144486137381f, 0.130526192220051f, + 0.99144486137381f, -0.130526192220051f, 0.923879532511287f, -0.38268343236509f, 0.793353340291235f, -0.60876142900872f, + 0.608761429008721f, -0.793353340291235f, 0.38268343236509f, -0.923879532511287f, 0.130526192220052f, -0.99144486137381f, + -0.130526192220052f, -0.99144486137381f, -0.38268343236509f, -0.923879532511287f, -0.608761429008721f, -0.793353340291235f, + -0.793353340291235f, -0.608761429008721f, -0.923879532511287f, -0.38268343236509f, -0.99144486137381f, -0.130526192220052f, + -0.99144486137381f, 0.130526192220051f, -0.923879532511287f, 0.38268343236509f, -0.793353340291235f, 0.608761429008721f, + -0.608761429008721f, 0.793353340291235f, -0.38268343236509f, 0.923879532511287f, -0.130526192220052f, 0.99144486137381f, + 0.130526192220052f, 0.99144486137381f, 0.38268343236509f, 0.923879532511287f, 0.608761429008721f, 0.793353340291235f, + 0.793353340291235f, 0.608761429008721f, 0.923879532511287f, 0.38268343236509f, 0.99144486137381f, 0.130526192220051f, + 0.99144486137381f, -0.130526192220051f, 0.923879532511287f, -0.38268343236509f, 0.793353340291235f, -0.60876142900872f, + 0.608761429008721f, -0.793353340291235f, 0.38268343236509f, -0.923879532511287f, 0.130526192220052f, -0.99144486137381f, + -0.130526192220052f, -0.99144486137381f, -0.38268343236509f, -0.923879532511287f, -0.608761429008721f, -0.793353340291235f, + -0.793353340291235f, -0.608761429008721f, -0.923879532511287f, -0.38268343236509f, -0.99144486137381f, -0.130526192220052f, + -0.99144486137381f, 0.130526192220051f, -0.923879532511287f, 0.38268343236509f, -0.793353340291235f, 0.608761429008721f, + -0.608761429008721f, 0.793353340291235f, -0.38268343236509f, 0.923879532511287f, -0.130526192220052f, 0.99144486137381f, + 0.130526192220052f, 0.99144486137381f, 0.38268343236509f, 0.923879532511287f, 0.608761429008721f, 0.793353340291235f, + 0.793353340291235f, 0.608761429008721f, 0.923879532511287f, 0.38268343236509f, 0.99144486137381f, 0.130526192220051f, + 0.99144486137381f, -0.130526192220051f, 0.923879532511287f, -0.38268343236509f, 0.793353340291235f, -0.60876142900872f, + 0.608761429008721f, -0.793353340291235f, 0.38268343236509f, -0.923879532511287f, 0.130526192220052f, -0.99144486137381f, + -0.130526192220052f, -0.99144486137381f, -0.38268343236509f, -0.923879532511287f, -0.608761429008721f, -0.793353340291235f, + -0.793353340291235f, -0.608761429008721f, -0.923879532511287f, -0.38268343236509f, -0.99144486137381f, -0.130526192220052f, + -0.99144486137381f, 0.130526192220051f, -0.923879532511287f, 0.38268343236509f, -0.793353340291235f, 0.608761429008721f, + -0.608761429008721f, 0.793353340291235f, -0.38268343236509f, 0.923879532511287f, -0.130526192220052f, 0.99144486137381f, + 0.130526192220052f, 0.99144486137381f, 0.38268343236509f, 0.923879532511287f, 0.608761429008721f, 0.793353340291235f, + 0.793353340291235f, 0.608761429008721f, 0.923879532511287f, 0.38268343236509f, 0.99144486137381f, 0.130526192220051f, + 0.99144486137381f, -0.130526192220051f, 0.923879532511287f, -0.38268343236509f, 0.793353340291235f, -0.60876142900872f, + 0.608761429008721f, -0.793353340291235f, 0.38268343236509f, -0.923879532511287f, 0.130526192220052f, -0.99144486137381f, + -0.130526192220052f, -0.99144486137381f, -0.38268343236509f, -0.923879532511287f, -0.608761429008721f, -0.793353340291235f, + -0.793353340291235f, -0.608761429008721f, -0.923879532511287f, -0.38268343236509f, -0.99144486137381f, -0.130526192220052f, + -0.99144486137381f, 0.130526192220051f, -0.923879532511287f, 0.38268343236509f, -0.793353340291235f, 0.608761429008721f, + -0.608761429008721f, 0.793353340291235f, -0.38268343236509f, 0.923879532511287f, -0.130526192220052f, 0.99144486137381f, + 0.38268343236509f, 0.923879532511287f, 0.923879532511287f, 0.38268343236509f, 0.923879532511287f, -0.38268343236509f, + 0.38268343236509f, -0.923879532511287f, -0.38268343236509f, -0.923879532511287f, -0.923879532511287f, -0.38268343236509f, + -0.923879532511287f, 0.38268343236509f, -0.38268343236509f, 0.923879532511287f, + }; + + private static final double[] RAND_VECS_2D = { + -0.2700222198f, -0.9628540911f, 0.3863092627f, -0.9223693152f, 0.04444859006f, -0.999011673f, -0.5992523158f, -0.8005602176f, + -0.7819280288f, 0.6233687174f, 0.9464672271f, 0.3227999196f, -0.6514146797f, -0.7587218957f, 0.9378472289f, 0.347048376f, + -0.8497875957f, -0.5271252623f, -0.879042592f, 0.4767432447f, -0.892300288f, -0.4514423508f, -0.379844434f, -0.9250503802f, + -0.9951650832f, 0.0982163789f, 0.7724397808f, -0.6350880136f, 0.7573283322f, -0.6530343002f, -0.9928004525f, -0.119780055f, + -0.0532665713f, 0.9985803285f, 0.9754253726f, -0.2203300762f, -0.7665018163f, 0.6422421394f, 0.991636706f, 0.1290606184f, + -0.994696838f, 0.1028503788f, -0.5379205513f, -0.84299554f, 0.5022815471f, -0.8647041387f, 0.4559821461f, -0.8899889226f, + -0.8659131224f, -0.5001944266f, 0.0879458407f, -0.9961252577f, -0.5051684983f, 0.8630207346f, 0.7753185226f, -0.6315704146f, + -0.6921944612f, 0.7217110418f, -0.5191659449f, -0.8546734591f, 0.8978622882f, -0.4402764035f, -0.1706774107f, 0.9853269617f, + -0.9353430106f, -0.3537420705f, -0.9992404798f, 0.03896746794f, -0.2882064021f, -0.9575683108f, -0.9663811329f, 0.2571137995f, + -0.8759714238f, -0.4823630009f, -0.8303123018f, -0.5572983775f, 0.05110133755f, -0.9986934731f, -0.8558373281f, -0.5172450752f, + 0.09887025282f, 0.9951003332f, 0.9189016087f, 0.3944867976f, -0.2439375892f, -0.9697909324f, -0.8121409387f, -0.5834613061f, + -0.9910431363f, 0.1335421355f, 0.8492423985f, -0.5280031709f, -0.9717838994f, -0.2358729591f, 0.9949457207f, 0.1004142068f, + 0.6241065508f, -0.7813392434f, 0.662910307f, 0.7486988212f, -0.7197418176f, 0.6942418282f, -0.8143370775f, -0.5803922158f, + 0.104521054f, -0.9945226741f, -0.1065926113f, -0.9943027784f, 0.445799684f, -0.8951327509f, 0.105547406f, 0.9944142724f, + -0.992790267f, 0.1198644477f, -0.8334366408f, 0.552615025f, 0.9115561563f, -0.4111755999f, 0.8285544909f, -0.5599084351f, + 0.7217097654f, -0.6921957921f, 0.4940492677f, -0.8694339084f, -0.3652321272f, -0.9309164803f, -0.9696606758f, 0.2444548501f, + 0.08925509731f, -0.996008799f, 0.5354071276f, -0.8445941083f, -0.1053576186f, 0.9944343981f, -0.9890284586f, 0.1477251101f, + 0.004856104961f, 0.9999882091f, 0.9885598478f, 0.1508291331f, 0.9286129562f, -0.3710498316f, -0.5832393863f, -0.8123003252f, + 0.3015207509f, 0.9534596146f, -0.9575110528f, 0.2883965738f, 0.9715802154f, -0.2367105511f, 0.229981792f, 0.9731949318f, + 0.955763816f, -0.2941352207f, 0.740956116f, 0.6715534485f, -0.9971513787f, -0.07542630764f, 0.6905710663f, -0.7232645452f, + -0.290713703f, -0.9568100872f, 0.5912777791f, -0.8064679708f, -0.9454592212f, -0.325740481f, 0.6664455681f, 0.74555369f, + 0.6236134912f, 0.7817328275f, 0.9126993851f, -0.4086316587f, -0.8191762011f, 0.5735419353f, -0.8812745759f, -0.4726046147f, + 0.9953313627f, 0.09651672651f, 0.9855650846f, -0.1692969699f, -0.8495980887f, 0.5274306472f, 0.6174853946f, -0.7865823463f, + 0.8508156371f, 0.52546432f, 0.9985032451f, -0.05469249926f, 0.1971371563f, -0.9803759185f, 0.6607855748f, -0.7505747292f, + -0.03097494063f, 0.9995201614f, -0.6731660801f, 0.739491331f, -0.7195018362f, -0.6944905383f, 0.9727511689f, 0.2318515979f, + 0.9997059088f, -0.0242506907f, 0.4421787429f, -0.8969269532f, 0.9981350961f, -0.061043673f, -0.9173660799f, -0.3980445648f, + -0.8150056635f, -0.5794529907f, -0.8789331304f, 0.4769450202f, 0.0158605829f, 0.999874213f, -0.8095464474f, 0.5870558317f, + -0.9165898907f, -0.3998286786f, -0.8023542565f, 0.5968480938f, -0.5176737917f, 0.8555780767f, -0.8154407307f, -0.5788405779f, + 0.4022010347f, -0.9155513791f, -0.9052556868f, -0.4248672045f, 0.7317445619f, 0.6815789728f, -0.5647632201f, -0.8252529947f, + -0.8403276335f, -0.5420788397f, -0.9314281527f, 0.363925262f, 0.5238198472f, 0.8518290719f, 0.7432803869f, -0.6689800195f, + -0.985371561f, -0.1704197369f, 0.4601468731f, 0.88784281f, 0.825855404f, 0.5638819483f, 0.6182366099f, 0.7859920446f, + 0.8331502863f, -0.553046653f, 0.1500307506f, 0.9886813308f, -0.662330369f, -0.7492119075f, -0.668598664f, 0.743623444f, + 0.7025606278f, 0.7116238924f, -0.5419389763f, -0.8404178401f, -0.3388616456f, 0.9408362159f, 0.8331530315f, 0.5530425174f, + -0.2989720662f, -0.9542618632f, 0.2638522993f, 0.9645630949f, 0.124108739f, -0.9922686234f, -0.7282649308f, -0.6852956957f, + 0.6962500149f, 0.7177993569f, -0.9183535368f, 0.3957610156f, -0.6326102274f, -0.7744703352f, -0.9331891859f, -0.359385508f, + -0.1153779357f, -0.9933216659f, 0.9514974788f, -0.3076565421f, -0.08987977445f, -0.9959526224f, 0.6678496916f, 0.7442961705f, + 0.7952400393f, -0.6062947138f, -0.6462007402f, -0.7631674805f, -0.2733598753f, 0.9619118351f, 0.9669590226f, -0.254931851f, + -0.9792894595f, 0.2024651934f, -0.5369502995f, -0.8436138784f, -0.270036471f, -0.9628500944f, -0.6400277131f, 0.7683518247f, + -0.7854537493f, -0.6189203566f, 0.06005905383f, -0.9981948257f, -0.02455770378f, 0.9996984141f, -0.65983623f, 0.751409442f, + -0.6253894466f, -0.7803127835f, -0.6210408851f, -0.7837781695f, 0.8348888491f, 0.5504185768f, -0.1592275245f, 0.9872419133f, + 0.8367622488f, 0.5475663786f, -0.8675753916f, -0.4973056806f, -0.2022662628f, -0.9793305667f, 0.9399189937f, 0.3413975472f, + 0.9877404807f, -0.1561049093f, -0.9034455656f, 0.4287028224f, 0.1269804218f, -0.9919052235f, -0.3819600854f, 0.924178821f, + 0.9754625894f, 0.2201652486f, -0.3204015856f, -0.9472818081f, -0.9874760884f, 0.1577687387f, 0.02535348474f, -0.9996785487f, + 0.4835130794f, -0.8753371362f, -0.2850799925f, -0.9585037287f, -0.06805516006f, -0.99768156f, -0.7885244045f, -0.6150034663f, + 0.3185392127f, -0.9479096845f, 0.8880043089f, 0.4598351306f, 0.6476921488f, -0.7619021462f, 0.9820241299f, 0.1887554194f, + 0.9357275128f, -0.3527237187f, -0.8894895414f, 0.4569555293f, 0.7922791302f, 0.6101588153f, 0.7483818261f, 0.6632681526f, + -0.7288929755f, -0.6846276581f, 0.8729032783f, -0.4878932944f, 0.8288345784f, 0.5594937369f, 0.08074567077f, 0.9967347374f, + 0.9799148216f, -0.1994165048f, -0.580730673f, -0.8140957471f, -0.4700049791f, -0.8826637636f, 0.2409492979f, 0.9705377045f, + 0.9437816757f, -0.3305694308f, -0.8927998638f, -0.4504535528f, -0.8069622304f, 0.5906030467f, 0.06258973166f, 0.9980393407f, + -0.9312597469f, 0.3643559849f, 0.5777449785f, 0.8162173362f, -0.3360095855f, -0.941858566f, 0.697932075f, -0.7161639607f, + -0.002008157227f, -0.9999979837f, -0.1827294312f, -0.9831632392f, -0.6523911722f, 0.7578824173f, -0.4302626911f, -0.9027037258f, + -0.9985126289f, -0.05452091251f, -0.01028102172f, -0.9999471489f, -0.4946071129f, 0.8691166802f, -0.2999350194f, 0.9539596344f, + 0.8165471961f, 0.5772786819f, 0.2697460475f, 0.962931498f, -0.7306287391f, -0.6827749597f, -0.7590952064f, -0.6509796216f, + -0.907053853f, 0.4210146171f, -0.5104861064f, -0.8598860013f, 0.8613350597f, 0.5080373165f, 0.5007881595f, -0.8655698812f, + -0.654158152f, 0.7563577938f, -0.8382755311f, -0.545246856f, 0.6940070834f, 0.7199681717f, 0.06950936031f, 0.9975812994f, + 0.1702942185f, -0.9853932612f, 0.2695973274f, 0.9629731466f, 0.5519612192f, -0.8338697815f, 0.225657487f, -0.9742067022f, + 0.4215262855f, -0.9068161835f, 0.4881873305f, -0.8727388672f, -0.3683854996f, -0.9296731273f, -0.9825390578f, 0.1860564427f, + 0.81256471f, 0.5828709909f, 0.3196460933f, -0.9475370046f, 0.9570913859f, 0.2897862643f, -0.6876655497f, -0.7260276109f, + -0.9988770922f, -0.047376731f, -0.1250179027f, 0.992154486f, -0.8280133617f, 0.560708367f, 0.9324863769f, -0.3612051451f, + 0.6394653183f, 0.7688199442f, -0.01623847064f, -0.9998681473f, -0.9955014666f, -0.09474613458f, -0.81453315f, 0.580117012f, + 0.4037327978f, -0.9148769469f, 0.9944263371f, 0.1054336766f, -0.1624711654f, 0.9867132919f, -0.9949487814f, -0.100383875f, + -0.6995302564f, 0.7146029809f, 0.5263414922f, -0.85027327f, -0.5395221479f, 0.841971408f, 0.6579370318f, 0.7530729462f, + 0.01426758847f, -0.9998982128f, -0.6734383991f, 0.7392433447f, 0.639412098f, -0.7688642071f, 0.9211571421f, 0.3891908523f, + -0.146637214f, -0.9891903394f, -0.782318098f, 0.6228791163f, -0.5039610839f, -0.8637263605f, -0.7743120191f, -0.6328039957f, + }; + + private static final double[] GRADIENTS_3D = { + 0, 1, 1, 0, 0, -1, 1, 0, 0, 1, -1, 0, 0, -1, -1, 0, + 1, 0, 1, 0, -1, 0, 1, 0, 1, 0, -1, 0, -1, 0, -1, 0, + 1, 1, 0, 0, -1, 1, 0, 0, 1, -1, 0, 0, -1, -1, 0, 0, + 0, 1, 1, 0, 0, -1, 1, 0, 0, 1, -1, 0, 0, -1, -1, 0, + 1, 0, 1, 0, -1, 0, 1, 0, 1, 0, -1, 0, -1, 0, -1, 0, + 1, 1, 0, 0, -1, 1, 0, 0, 1, -1, 0, 0, -1, -1, 0, 0, + 0, 1, 1, 0, 0, -1, 1, 0, 0, 1, -1, 0, 0, -1, -1, 0, + 1, 0, 1, 0, -1, 0, 1, 0, 1, 0, -1, 0, -1, 0, -1, 0, + 1, 1, 0, 0, -1, 1, 0, 0, 1, -1, 0, 0, -1, -1, 0, 0, + 0, 1, 1, 0, 0, -1, 1, 0, 0, 1, -1, 0, 0, -1, -1, 0, + 1, 0, 1, 0, -1, 0, 1, 0, 1, 0, -1, 0, -1, 0, -1, 0, + 1, 1, 0, 0, -1, 1, 0, 0, 1, -1, 0, 0, -1, -1, 0, 0, + 0, 1, 1, 0, 0, -1, 1, 0, 0, 1, -1, 0, 0, -1, -1, 0, + 1, 0, 1, 0, -1, 0, 1, 0, 1, 0, -1, 0, -1, 0, -1, 0, + 1, 1, 0, 0, -1, 1, 0, 0, 1, -1, 0, 0, -1, -1, 0, 0, + 1, 1, 0, 0, 0, -1, 1, 0, -1, 1, 0, 0, 0, -1, -1, 0 + }; + + private static final double[] RAND_VECS_3D = { + -0.7292736885f, -0.6618439697f, 0.1735581948f, 0, 0.790292081f, -0.5480887466f, -0.2739291014f, 0, 0.7217578935f, 0.6226212466f, + -0.3023380997f, 0, 0.565683137f, -0.8208298145f, -0.0790000257f, 0, 0.760049034f, -0.5555979497f, -0.3370999617f, 0, + 0.3713945616f, 0.5011264475f, 0.7816254623f, 0, -0.1277062463f, -0.4254438999f, -0.8959289049f, 0, -0.2881560924f, + -0.5815838982f, 0.7607405838f, 0, 0.5849561111f, -0.662820239f, -0.4674352136f, 0, 0.3307171178f, 0.0391653737f, 0.94291689f, 0, + 0.8712121778f, -0.4113374369f, -0.2679381538f, 0, 0.580981015f, 0.7021915846f, 0.4115677815f, 0, 0.503756873f, 0.6330056931f, + -0.5878203852f, 0, 0.4493712205f, 0.601390195f, 0.6606022552f, 0, -0.6878403724f, 0.09018890807f, -0.7202371714f, 0, + -0.5958956522f, -0.6469350577f, 0.475797649f, 0, -0.5127052122f, 0.1946921978f, -0.8361987284f, 0, -0.9911507142f, + -0.05410276466f, -0.1212153153f, 0, -0.2149721042f, 0.9720882117f, -0.09397607749f, 0, -0.7518650936f, -0.5428057603f, + 0.3742469607f, 0, 0.5237068895f, 0.8516377189f, -0.02107817834f, 0, 0.6333504779f, 0.1926167129f, -0.7495104896f, 0, + -0.06788241606f, 0.3998305789f, 0.9140719259f, 0, -0.5538628599f, -0.4729896695f, -0.6852128902f, 0, -0.7261455366f, + -0.5911990757f, 0.3509933228f, 0, -0.9229274737f, -0.1782808786f, 0.3412049336f, 0, -0.6968815002f, 0.6511274338f, + 0.3006480328f, 0, 0.9608044783f, -0.2098363234f, -0.1811724921f, 0, 0.06817146062f, -0.9743405129f, 0.2145069156f, 0, + -0.3577285196f, -0.6697087264f, -0.6507845481f, 0, -0.1868621131f, 0.7648617052f, -0.6164974636f, 0, -0.6541697588f, + 0.3967914832f, 0.6439087246f, 0, 0.6993340405f, -0.6164538506f, 0.3618239211f, 0, -0.1546665739f, 0.6291283928f, 0.7617583057f, + 0, -0.6841612949f, -0.2580482182f, -0.6821542638f, 0, 0.5383980957f, 0.4258654885f, 0.7271630328f, 0, -0.5026987823f, + -0.7939832935f, -0.3418836993f, 0, 0.3202971715f, 0.2834415347f, 0.9039195862f, 0, 0.8683227101f, -0.0003762656404f, + -0.4959995258f, 0, 0.791120031f, -0.08511045745f, 0.6057105799f, 0, -0.04011016052f, -0.4397248749f, 0.8972364289f, 0, + 0.9145119872f, 0.3579346169f, -0.1885487608f, 0, -0.9612039066f, -0.2756484276f, 0.01024666929f, 0, 0.6510361721f, + -0.2877799159f, -0.7023778346f, 0, -0.2041786351f, 0.7365237271f, 0.644859585f, 0, -0.7718263711f, 0.3790626912f, 0.5104855816f, + 0, -0.3060082741f, -0.7692987727f, 0.5608371729f, 0, 0.454007341f, -0.5024843065f, 0.7357899537f, 0, 0.4816795475f, + 0.6021208291f, -0.6367380315f, 0, 0.6961980369f, -0.3222197429f, 0.641469197f, 0, -0.6532160499f, -0.6781148932f, 0.3368515753f, + 0, 0.5089301236f, -0.6154662304f, -0.6018234363f, 0, -0.1635919754f, -0.9133604627f, -0.372840892f, 0, 0.52408019f, + -0.8437664109f, 0.1157505864f, 0, 0.5902587356f, 0.4983817807f, -0.6349883666f, 0, 0.5863227872f, 0.494764745f, 0.6414307729f, + 0, 0.6779335087f, 0.2341345225f, 0.6968408593f, 0, 0.7177054546f, -0.6858979348f, 0.120178631f, 0, -0.5328819713f, + -0.5205125012f, 0.6671608058f, 0, -0.8654874251f, -0.0700727088f, -0.4960053754f, 0, -0.2861810166f, 0.7952089234f, + 0.5345495242f, 0, -0.04849529634f, 0.9810836427f, -0.1874115585f, 0, -0.6358521667f, 0.6058348682f, 0.4781800233f, 0, + 0.6254794696f, -0.2861619734f, 0.7258696564f, 0, -0.2585259868f, 0.5061949264f, -0.8227581726f, 0, 0.02136306781f, + 0.5064016808f, -0.8620330371f, 0, 0.200111773f, 0.8599263484f, 0.4695550591f, 0, 0.4743561372f, 0.6014985084f, -0.6427953014f, + 0, 0.6622993731f, -0.5202474575f, -0.5391679918f, 0, 0.08084972818f, -0.6532720452f, 0.7527940996f, 0, -0.6893687501f, + 0.0592860349f, 0.7219805347f, 0, -0.1121887082f, -0.9673185067f, 0.2273952515f, 0, 0.7344116094f, 0.5979668656f, -0.3210532909f, + 0, 0.5789393465f, -0.2488849713f, 0.7764570201f, 0, 0.6988182827f, 0.3557169806f, -0.6205791146f, 0, -0.8636845529f, + -0.2748771249f, -0.4224826141f, 0, -0.4247027957f, -0.4640880967f, 0.777335046f, 0, 0.5257722489f, -0.8427017621f, + 0.1158329937f, 0, 0.9343830603f, 0.316302472f, -0.1639543925f, 0, -0.1016836419f, -0.8057303073f, -0.5834887393f, 0, + -0.6529238969f, 0.50602126f, -0.5635892736f, 0, -0.2465286165f, -0.9668205684f, -0.06694497494f, 0, -0.9776897119f, + -0.2099250524f, -0.007368825344f, 0, 0.7736893337f, 0.5734244712f, 0.2694238123f, 0, -0.6095087895f, 0.4995678998f, + 0.6155736747f, 0, 0.5794535482f, 0.7434546771f, 0.3339292269f, 0, -0.8226211154f, 0.08142581855f, 0.5627293636f, 0, + -0.510385483f, 0.4703667658f, 0.7199039967f, 0, -0.5764971849f, -0.07231656274f, -0.8138926898f, 0, 0.7250628871f, + 0.3949971505f, -0.5641463116f, 0, -0.1525424005f, 0.4860840828f, -0.8604958341f, 0, -0.5550976208f, -0.4957820792f, + 0.667882296f, 0, -0.1883614327f, 0.9145869398f, 0.357841725f, 0, 0.7625556724f, -0.5414408243f, -0.3540489801f, 0, + -0.5870231946f, -0.3226498013f, -0.7424963803f, 0, 0.3051124198f, 0.2262544068f, -0.9250488391f, 0, 0.6379576059f, 0.577242424f, + -0.5097070502f, 0, -0.5966775796f, 0.1454852398f, -0.7891830656f, 0, -0.658330573f, 0.6555487542f, -0.3699414651f, 0, + 0.7434892426f, 0.2351084581f, 0.6260573129f, 0, 0.5562114096f, 0.8264360377f, -0.0873632843f, 0, -0.3028940016f, -0.8251527185f, + 0.4768419182f, 0, 0.1129343818f, -0.985888439f, -0.1235710781f, 0, 0.5937652891f, -0.5896813806f, 0.5474656618f, 0, + 0.6757964092f, -0.5835758614f, -0.4502648413f, 0, 0.7242302609f, -0.1152719764f, 0.6798550586f, 0, -0.9511914166f, + 0.0753623979f, -0.2992580792f, 0, 0.2539470961f, -0.1886339355f, 0.9486454084f, 0, 0.571433621f, -0.1679450851f, -0.8032795685f, + 0, -0.06778234979f, 0.3978269256f, 0.9149531629f, 0, 0.6074972649f, 0.733060024f, -0.3058922593f, 0, -0.5435478392f, + 0.1675822484f, 0.8224791405f, 0, -0.5876678086f, -0.3380045064f, -0.7351186982f, 0, -0.7967562402f, 0.04097822706f, + -0.6029098428f, 0, -0.1996350917f, 0.8706294745f, 0.4496111079f, 0, -0.02787660336f, -0.9106232682f, -0.4122962022f, 0, + -0.7797625996f, -0.6257634692f, 0.01975775581f, 0, -0.5211232846f, 0.7401644346f, -0.4249554471f, 0, 0.8575424857f, + 0.4053272873f, -0.3167501783f, 0, 0.1045223322f, 0.8390195772f, -0.5339674439f, 0, 0.3501822831f, 0.9242524096f, -0.1520850155f, + 0, 0.1987849858f, 0.07647613266f, 0.9770547224f, 0, 0.7845996363f, 0.6066256811f, -0.1280964233f, 0, 0.09006737436f, + -0.9750989929f, -0.2026569073f, 0, -0.8274343547f, -0.542299559f, 0.1458203587f, 0, -0.3485797732f, -0.415802277f, 0.840000362f, + 0, -0.2471778936f, -0.7304819962f, -0.6366310879f, 0, -0.3700154943f, 0.8577948156f, 0.3567584454f, 0, 0.5913394901f, + -0.548311967f, -0.5913303597f, 0, 0.1204873514f, -0.7626472379f, -0.6354935001f, 0, 0.616959265f, 0.03079647928f, 0.7863922953f, + 0, 0.1258156836f, -0.6640829889f, -0.7369967419f, 0, -0.6477565124f, -0.1740147258f, -0.7417077429f, 0, 0.6217889313f, + -0.7804430448f, -0.06547655076f, 0, 0.6589943422f, -0.6096987708f, 0.4404473475f, 0, -0.2689837504f, -0.6732403169f, + -0.6887635427f, 0, -0.3849775103f, 0.5676542638f, 0.7277093879f, 0, 0.5754444408f, 0.8110471154f, -0.1051963504f, 0, + 0.9141593684f, 0.3832947817f, 0.131900567f, 0, -0.107925319f, 0.9245493968f, 0.3654593525f, 0, 0.377977089f, 0.3043148782f, + 0.8743716458f, 0, -0.2142885215f, -0.8259286236f, 0.5214617324f, 0, 0.5802544474f, 0.4148098596f, -0.7008834116f, 0, + -0.1982660881f, 0.8567161266f, -0.4761596756f, 0, -0.03381553704f, 0.3773180787f, -0.9254661404f, 0, -0.6867922841f, + -0.6656597827f, 0.2919133642f, 0, 0.7731742607f, -0.2875793547f, -0.5652430251f, 0, -0.09655941928f, 0.9193708367f, + -0.3813575004f, 0, 0.2715702457f, -0.9577909544f, -0.09426605581f, 0, 0.2451015704f, -0.6917998565f, -0.6792188003f, 0, + 0.977700782f, -0.1753855374f, 0.1155036542f, 0, -0.5224739938f, 0.8521606816f, 0.02903615945f, 0, -0.7734880599f, + -0.5261292347f, 0.3534179531f, 0, -0.7134492443f, -0.269547243f, 0.6467878011f, 0, 0.1644037271f, 0.5105846203f, -0.8439637196f, + 0, 0.6494635788f, 0.05585611296f, 0.7583384168f, 0, -0.4711970882f, 0.5017280509f, -0.7254255765f, 0, -0.6335764307f, + -0.2381686273f, -0.7361091029f, 0, -0.9021533097f, -0.270947803f, -0.3357181763f, 0, -0.3793711033f, 0.872258117f, + 0.3086152025f, 0, -0.6855598966f, -0.3250143309f, 0.6514394162f, 0, 0.2900942212f, -0.7799057743f, -0.5546100667f, 0, + -0.2098319339f, 0.85037073f, 0.4825351604f, 0, -0.4592603758f, 0.6598504336f, -0.5947077538f, 0, 0.8715945488f, 0.09616365406f, + -0.4807031248f, 0, -0.6776666319f, 0.7118504878f, -0.1844907016f, 0, 0.7044377633f, 0.312427597f, 0.637304036f, 0, + -0.7052318886f, -0.2401093292f, -0.6670798253f, 0, 0.081921007f, -0.7207336136f, -0.6883545647f, 0, -0.6993680906f, + -0.5875763221f, -0.4069869034f, 0, -0.1281454481f, 0.6419895885f, 0.7559286424f, 0, -0.6337388239f, -0.6785471501f, + -0.3714146849f, 0, 0.5565051903f, -0.2168887573f, -0.8020356851f, 0, -0.5791554484f, 0.7244372011f, -0.3738578718f, 0, + 0.1175779076f, -0.7096451073f, 0.6946792478f, 0, -0.6134619607f, 0.1323631078f, 0.7785527795f, 0, 0.6984635305f, + -0.02980516237f, -0.715024719f, 0, 0.8318082963f, -0.3930171956f, 0.3919597455f, 0, 0.1469576422f, 0.05541651717f, + -0.9875892167f, 0, 0.708868575f, -0.2690503865f, 0.6520101478f, 0, 0.2726053183f, 0.67369766f, -0.68688995f, 0, -0.6591295371f, + 0.3035458599f, -0.6880466294f, 0, 0.4815131379f, -0.7528270071f, 0.4487723203f, 0, 0.9430009463f, 0.1675647412f, -0.2875261255f, + 0, 0.434802957f, 0.7695304522f, -0.4677277752f, 0, 0.3931996188f, 0.594473625f, 0.7014236729f, 0, 0.7254336655f, -0.603925654f, + 0.3301814672f, 0, 0.7590235227f, -0.6506083235f, 0.02433313207f, 0, -0.8552768592f, -0.3430042733f, 0.3883935666f, 0, + -0.6139746835f, 0.6981725247f, 0.3682257648f, 0, -0.7465905486f, -0.5752009504f, 0.3342849376f, 0, 0.5730065677f, 0.810555537f, + -0.1210916791f, 0, -0.9225877367f, -0.3475211012f, -0.167514036f, 0, -0.7105816789f, -0.4719692027f, -0.5218416899f, 0, + -0.08564609717f, 0.3583001386f, 0.929669703f, 0, -0.8279697606f, -0.2043157126f, 0.5222271202f, 0, 0.427944023f, 0.278165994f, + 0.8599346446f, 0, 0.5399079671f, -0.7857120652f, -0.3019204161f, 0, 0.5678404253f, -0.5495413974f, -0.6128307303f, 0, + -0.9896071041f, 0.1365639107f, -0.04503418428f, 0, -0.6154342638f, -0.6440875597f, 0.4543037336f, 0, 0.1074204368f, + -0.7946340692f, 0.5975094525f, 0, -0.3595449969f, -0.8885529948f, 0.28495784f, 0, -0.2180405296f, 0.1529888965f, 0.9638738118f, + 0, -0.7277432317f, -0.6164050508f, -0.3007234646f, 0, 0.7249729114f, -0.00669719484f, 0.6887448187f, 0, -0.5553659455f, + -0.5336586252f, 0.6377908264f, 0, 0.5137558015f, 0.7976208196f, -0.3160000073f, 0, -0.3794024848f, 0.9245608561f, + -0.03522751494f, 0, 0.8229248658f, 0.2745365933f, -0.4974176556f, 0, -0.5404114394f, 0.6091141441f, 0.5804613989f, 0, + 0.8036581901f, -0.2703029469f, 0.5301601931f, 0, 0.6044318879f, 0.6832968393f, 0.4095943388f, 0, 0.06389988817f, 0.9658208605f, + -0.2512108074f, 0, 0.1087113286f, 0.7402471173f, -0.6634877936f, 0, -0.713427712f, -0.6926784018f, 0.1059128479f, 0, + 0.6458897819f, -0.5724548511f, -0.5050958653f, 0, -0.6553931414f, 0.7381471625f, 0.159995615f, 0, 0.3910961323f, 0.9188871375f, + -0.05186755998f, 0, -0.4879022471f, -0.5904376907f, 0.6429111375f, 0, 0.6014790094f, 0.7707441366f, -0.2101820095f, 0, + -0.5677173047f, 0.7511360995f, 0.3368851762f, 0, 0.7858573506f, 0.226674665f, 0.5753666838f, 0, -0.4520345543f, -0.604222686f, + -0.6561857263f, 0, 0.002272116345f, 0.4132844051f, -0.9105991643f, 0, -0.5815751419f, -0.5162925989f, 0.6286591339f, 0, + -0.03703704785f, 0.8273785755f, 0.5604221175f, 0, -0.5119692504f, 0.7953543429f, -0.3244980058f, 0, -0.2682417366f, + -0.9572290247f, -0.1084387619f, 0, -0.2322482736f, -0.9679131102f, -0.09594243324f, 0, 0.3554328906f, -0.8881505545f, + 0.2913006227f, 0, 0.7346520519f, -0.4371373164f, 0.5188422971f, 0, 0.9985120116f, 0.04659011161f, -0.02833944577f, 0, + -0.3727687496f, -0.9082481361f, 0.1900757285f, 0, 0.91737377f, -0.3483642108f, 0.1925298489f, 0, 0.2714911074f, 0.4147529736f, + -0.8684886582f, 0, 0.5131763485f, -0.7116334161f, 0.4798207128f, 0, -0.8737353606f, 0.18886992f, -0.4482350644f, 0, + 0.8460043821f, -0.3725217914f, 0.3814499973f, 0, 0.8978727456f, -0.1780209141f, -0.4026575304f, 0, 0.2178065647f, + -0.9698322841f, -0.1094789531f, 0, -0.1518031304f, -0.7788918132f, -0.6085091231f, 0, -0.2600384876f, -0.4755398075f, + -0.8403819825f, 0, 0.572313509f, -0.7474340931f, -0.3373418503f, 0, -0.7174141009f, 0.1699017182f, -0.6756111411f, 0, + -0.684180784f, 0.02145707593f, -0.7289967412f, 0, -0.2007447902f, 0.06555605789f, -0.9774476623f, 0, -0.1148803697f, + -0.8044887315f, 0.5827524187f, 0, -0.7870349638f, 0.03447489231f, 0.6159443543f, 0, -0.2015596421f, 0.6859872284f, + 0.6991389226f, 0, -0.08581082512f, -0.10920836f, -0.9903080513f, 0, 0.5532693395f, 0.7325250401f, -0.396610771f, 0, + -0.1842489331f, -0.9777375055f, -0.1004076743f, 0, 0.0775473789f, -0.9111505856f, 0.4047110257f, 0, 0.1399838409f, + 0.7601631212f, -0.6344734459f, 0, 0.4484419361f, -0.845289248f, 0.2904925424f, 0 + }; + + // Hashing + private static final int PRIME_X = 501125321; + private static final int PRIME_Y = 1136930381; + private static final int PRIME_Z = 1720413743; + private static final NoiseSampler CELLULAR_LOOKUP_DEFAULT = new FastNoiseLite(); + private int mSeed = 1337; + private double mFrequency = 0.01f; + private NoiseType mNoiseType = NoiseType.OpenSimplex2; + private RotationType3D mRotationType3D = RotationType3D.None; + private TransformType3D mTransformType3D = TransformType3D.DefaultOpenSimplex2; + private FractalType mFractalType = FractalType.None; + private int mOctaves = 3; + private double mLacunarity = 2.0f; + private double mGain = 0.5f; + private double mWeightedStrength = 0.0f; + private double mPingPongStength = 2.0f; + private double mFractalBounding = 1 / 1.75f; + private CellularDistanceFunction mCellularDistanceFunction = CellularDistanceFunction.EuclideanSq; + private CellularReturnType mCellularReturnType = CellularReturnType.Distance; + private double mCellularJitterModifier = 1.0f; + private DomainWarpType mDomainWarpType = DomainWarpType.OpenSimplex2; + private TransformType3D mWarpTransformType3D = TransformType3D.DefaultOpenSimplex2; + private double mDomainWarpAmp = 1.0f; + private NoiseSampler cellularNoiseLookup = CELLULAR_LOOKUP_DEFAULT; + + /** + * Create new FastNoise object with default seed + */ + public FastNoiseLite() { + + } + + /** + * Create new FastNoise object with specified seed + */ + public FastNoiseLite(int seed) { + setSeed(seed); + } + + private static double fastMin(double a, double b) { + return a < b ? a : b; + } + + private static double fastMax(double a, double b) { + return a > b ? a : b; + } + + private static double fastSqrt(double f) { + return FastMath.sqrt(f); + } + + private static int fastFloor(double f) { + return f >= 0 ? (int) f : (int) f - 1; + } + + private static int fastRound(double f) { + return f >= 0 ? (int) (f + 0.5f) : (int) (f - 0.5f); + } + + private static double lerp(double a, double b, double t) { + return a + t * (b - a); + } + + private static double interpHermite(double t) { + return t * t * (3 - 2 * t); + } + + private static double interpQuintic(double t) { + return t * t * t * (t * (t * 6 - 15) + 10); + } + + private static double cubicLerp(double a, double b, double c, double d, double t) { + double p = (d - c) - (a - b); + return t * t * t * p + t * t * ((a - b) - p) + t * (c - a) + b; + } + + private static double pingPong(double t) { + t -= (int) (t * 0.5f) << 1; + return t < 1 ? t : 2 - t; + } + + private static int hash(int seed, int xPrimed, int yPrimed) { + int hash = seed ^ xPrimed ^ yPrimed; + + hash *= 0x27d4eb2d; + return hash; + } + + private static int hash(int seed, int xPrimed, int yPrimed, int zPrimed) { + int hash = seed ^ xPrimed ^ yPrimed ^ zPrimed; + + hash *= 0x27d4eb2d; + return hash; + } + + private static double valCoord(int seed, int xPrimed, int yPrimed) { + int hash = hash(seed, xPrimed, yPrimed); + + hash *= hash; + hash ^= hash << 19; + return hash * (1 / 2147483648.0f); + } + + private static double valCoord(int seed, int xPrimed, int yPrimed, int zPrimed) { + int hash = hash(seed, xPrimed, yPrimed, zPrimed); + + hash *= hash; + hash ^= hash << 19; + return hash * (1 / 2147483648.0f); + } + + private static double gradCoord(int seed, int xPrimed, int yPrimed, double xd, double yd) { + int hash = hash(seed, xPrimed, yPrimed); + hash ^= hash >> 15; + hash &= 127 << 1; + + double xg = GRADIENTS_2_D[hash]; + double yg = GRADIENTS_2_D[hash | 1]; + + return xd * xg + yd * yg; + } + + private static double gradCoord(int seed, int xPrimed, int yPrimed, int zPrimed, double xd, double yd, double zd) { + int hash = hash(seed, xPrimed, yPrimed, zPrimed); + hash ^= hash >> 15; + hash &= 63 << 2; + + double xg = GRADIENTS_3D[hash]; + double yg = GRADIENTS_3D[hash | 1]; + double zg = GRADIENTS_3D[hash | 2]; + + return xd * xg + yd * yg + zd * zg; + } + + private static double fastAbs(double f) { + return f < 0 ? -f : f; + } + + public NoiseSampler getCellularNoiseLookup() { + return cellularNoiseLookup; + } + + public void setCellularNoiseLookup(NoiseSampler cellularNoiseLookup) { + this.cellularNoiseLookup = cellularNoiseLookup; + } + + /** + * Sets seed used for all noise types + *

+ * Default: 1337 + */ + public void setSeed(int seed) { + mSeed = seed; + } + + /** + * Sets frequency for all noise types + *

+ * Default: 0.01 + */ + public void setFrequency(double frequency) { + mFrequency = frequency; + } + + /** + * Sets noise algorithm used for GetNoise(...) + *

+ * Default: OpenSimplex2 + */ + public void setNoiseType(NoiseType noiseType) { + mNoiseType = noiseType; + UpdateTransformType3D(); + } + + private void UpdateTransformType3D() { + switch(mRotationType3D) { + case ImproveXYPlanes: + mTransformType3D = TransformType3D.ImproveXYPlanes; + break; + case ImproveXZPlanes: + mTransformType3D = TransformType3D.ImproveXZPlanes; + break; + default: + switch(mNoiseType) { + case OpenSimplex2: + case OpenSimplex2S: + mTransformType3D = TransformType3D.DefaultOpenSimplex2; + break; + default: + mTransformType3D = TransformType3D.None; + break; + } + break; + } + } + + /** + * Sets domain rotation type for 3D Noise and 3D DomainWarp. + * Can aid in reducing directional artifacts when sampling a 2D plane in 3D + *

+ * Default: None + */ + public void setRotationType3D(RotationType3D rotationType3D) { + mRotationType3D = rotationType3D; + UpdateTransformType3D(); + updateWarpTransformType3D(); + } + + private void updateWarpTransformType3D() { + switch(mRotationType3D) { + case ImproveXYPlanes: + mWarpTransformType3D = TransformType3D.ImproveXYPlanes; + break; + case ImproveXZPlanes: + mWarpTransformType3D = TransformType3D.ImproveXZPlanes; + break; + default: + switch(mDomainWarpType) { + case OpenSimplex2: + case OpenSimplex2Reduced: + mWarpTransformType3D = TransformType3D.DefaultOpenSimplex2; + break; + default: + mWarpTransformType3D = TransformType3D.None; + break; + } + break; + } + } + + /** + * Sets method for combining octaves in all fractal noise types + *

+ * Default: None + * Note: FractalType.DomainWarp... only affects DomainWarp(...) + */ + public void setFractalType(FractalType fractalType) { + mFractalType = fractalType; + } + + /** + * Sets octave count for all fractal noise types + *

+ * Default: 3 + */ + public void setFractalOctaves(int octaves) { + mOctaves = octaves; + calculateFractalBounding(); + } + + private void calculateFractalBounding() { + double gain = fastAbs(mGain); + double amp = gain; + double ampFractal = 1.0f; + for(int i = 1; i < mOctaves; i++) { + ampFractal += amp; + amp *= gain; + } + mFractalBounding = 1 / ampFractal; + } + + /** + * Sets octave lacunarity for all fractal noise types + *

+ * Default: 2.0 + */ + public void setFractalLacunarity(double lacunarity) { + mLacunarity = lacunarity; + } + + /** + * Sets octave gain for all fractal noise types + *

+ * Default: 0.5 + */ + public void setFractalGain(double gain) { + mGain = gain; + calculateFractalBounding(); + } + + /** + * Sets octave weighting for all none DomainWarp fratal types + *

+ * Default: 0.0 + * Note: Keep between 0...1 to maintain -1...1 output bounding + */ + public void setFractalWeightedStrength(double weightedStrength) { + mWeightedStrength = weightedStrength; + } + + /** + * Sets strength of the fractal ping pong effect + *

+ * Default: 2.0 + */ + public void setFractalPingPongStrength(double pingPongStrength) { + mPingPongStength = pingPongStrength; + } + + /** + * Sets distance function used in cellular noise calculations + *

+ * Default: Distance + */ + public void setCellularDistanceFunction(CellularDistanceFunction cellularDistanceFunction) { + mCellularDistanceFunction = cellularDistanceFunction; + } + + /** + * Sets return type from cellular noise calculations + *

+ * Default: EuclideanSq + */ + public void setCellularReturnType(CellularReturnType cellularReturnType) { + mCellularReturnType = cellularReturnType; + } + + /** + * Sets the maximum distance a cellular point can move from it's grid position + *

+ * Default: 1.0 + * Note: Setting this higher than 1 will cause artifacts + */ + public void setCellularJitter(double cellularJitter) { + mCellularJitterModifier = cellularJitter; + } + + /** + * Sets the warp algorithm when using DomainWarp(...) + *

+ * Default: OpenSimplex2 + */ + public void setDomainWarpType(DomainWarpType domainWarpType) { + mDomainWarpType = domainWarpType; + updateWarpTransformType3D(); + } + + /** + * Sets the maximum warp distance from original position when using DomainWarp(...) + *

+ * Default: 1.0 + */ + public void setDomainWarpAmp(double domainWarpAmp) { + mDomainWarpAmp = domainWarpAmp; + } + + /** + * 2D noise at given position using current settings + *

+ * Noise output bounded between -1...1 + */ + @Override + public double getNoise(double x, double y) { + x *= mFrequency; + y *= mFrequency; + + switch(mNoiseType) { + case OpenSimplex2: + case OpenSimplex2S: { + + final double SQRT3 = 1.7320508075688772935274463415059; + final double F2 = 0.5f * (SQRT3 - 1); + + double t = (x + y) * F2; + x += t; + y += t; + } + break; + default: + break; + } + + switch(mFractalType) { + default: + return genNoiseSingle(mSeed, x, y); + case FBm: + return genFractalFBm(x, y); + case Ridged: + return genFractalRidged(x, y); + case PingPong: + return genFractalPingPong(x, y); + } + } + + /** + * 3D noise at given position using current settings + *

+ * Noise output bounded between -1...1 + */ + @Override + public double getNoise(double x, double y, double z) { + x *= mFrequency; + y *= mFrequency; + z *= mFrequency; + + switch(mTransformType3D) { + case ImproveXYPlanes: { + + double xy = x + y; + + double s2 = xy * -0.211324865405187D; + + z *= 0.577350269189626; + x += s2 - z; + y = y + s2 - z; + + z += xy * 0.577350269189626; + } + break; + case ImproveXZPlanes: { + + double xz = x + z; + + double s2 = xz * -0.211324865405187D; + + y *= 0.577350269189626; + x += s2 - y; + z += s2 - y; + + y += xz * 0.577350269189626; + } + break; + case DefaultOpenSimplex2: { + + final double R3 = 2.0 / 3.0; + + double r = (x + y + z) * R3; // Rotation, not skew + x = r - x; + y = r - y; + z = r - z; + } + break; + default: + break; + } + + switch(mFractalType) { + default: + return genNoiseSingle(mSeed, x, y, z); + case FBm: + return genFractalFBm(x, y, z); + case Ridged: + return genFractalRidged(x, y, z); + case PingPong: + return genFractalPingPong(x, y, z); + } + } + + /** + * 2D warps the input position using current domain warp settings + *

+ * Example usage with GetNoise + * DomainWarp(coord) + * noise = GetNoise(x, y) + */ + public void domainWarp(Vector2 coord) { + switch(mFractalType) { + default: + domainWarpSingle(coord); + break; + case DomainWarpProgressive: + domainWarpFractalProgressive(coord); + break; + case DomainWarpIndependent: + domainWarpFractalIndependent(coord); + break; + } + } + + /** + * 3D warps the input position using current domain warp settings + *

+ * Example usage with GetNoise + * DomainWarp(coord) + * noise = GetNoise(x, y, z) + */ + public void domainWarp(Vector3 coord) { + switch(mFractalType) { + default: + domainWarpSingle(coord); + break; + case DomainWarpProgressive: + domainWarpFractalProgressive(coord); + break; + case DomainWarpIndependent: + domainWarpFractalIndependent(coord); + break; + } + } + + private double genNoiseSingle(int seed, double x, double y) { + switch(mNoiseType) { + case OpenSimplex2: + return singleSimplex(seed, x, y); + case OpenSimplex2S: + return singleOpenSimplex2S(seed, x, y); + case Cellular: + return singleCellular(seed, x, y); + case Perlin: + return singlePerlin(seed, x, y); + case ValueCubic: + return singleValueCubic(seed, x, y); + case Value: + return singleValue(seed, x, y); + case WhiteNoise: + return singleWhiteNoise(seed, x, y); + default: + return 0; + } + } + + private double genNoiseSingle(int seed, double x, double y, double z) { + switch(mNoiseType) { + case OpenSimplex2: + return singleOpenSimplex2(seed, x, y, z); + case OpenSimplex2S: + return singleOpenSimplex2S(seed, x, y, z); + case Cellular: + return singleCellular(seed, x, y, z); + case Perlin: + return singlePerlin(seed, x, y, z); + case ValueCubic: + return singleValueCubic(seed, x, y, z); + case Value: + return singleValue(seed, x, y, z); + case WhiteNoise: + return singleWhiteNoise(seed, x, y, z); + default: + return 0; + } + } + + private double genFractalFBm(double x, double y) { + int seed = mSeed; + double sum = 0; + double amp = mFractalBounding; + + for(int i = 0; i < mOctaves; i++) { + double noise = genNoiseSingle(seed++, x, y); + sum += noise * amp; + amp *= lerp(1.0f, fastMin(noise + 1, 2) * 0.5f, mWeightedStrength); + + x *= mLacunarity; + y *= mLacunarity; + amp *= mGain; + } + + return sum; + } + + private double genFractalFBm(double x, double y, double z) { + int seed = mSeed; + double sum = 0; + double amp = mFractalBounding; + + for(int i = 0; i < mOctaves; i++) { + double noise = genNoiseSingle(seed++, x, y, z); + sum += noise * amp; + amp *= lerp(1.0f, (noise + 1) * 0.5f, mWeightedStrength); + + x *= mLacunarity; + y *= mLacunarity; + z *= mLacunarity; + amp *= mGain; + } + + return sum; + } + + private double genFractalRidged(double x, double y) { + int seed = mSeed; + double sum = 0; + double amp = mFractalBounding; + + for(int i = 0; i < mOctaves; i++) { + double noise = fastAbs(genNoiseSingle(seed++, x, y)); + sum += (noise * -2 + 1) * amp; + amp *= lerp(1.0f, 1 - noise, mWeightedStrength); + + x *= mLacunarity; + y *= mLacunarity; + amp *= mGain; + } + + return sum; + } + + // Generic noise gen + private double genFractalRidged(double x, double y, double z) { + int seed = mSeed; + double sum = 0; + double amp = mFractalBounding; + + for(int i = 0; i < mOctaves; i++) { + double noise = fastAbs(genNoiseSingle(seed++, x, y, z)); + sum += (noise * -2 + 1) * amp; + amp *= lerp(1.0f, 1 - noise, mWeightedStrength); + + x *= mLacunarity; + y *= mLacunarity; + z *= mLacunarity; + amp *= mGain; + } + + return sum; + } + + private double genFractalPingPong(double x, double y) { + int seed = mSeed; + double sum = 0; + double amp = mFractalBounding; + + for(int i = 0; i < mOctaves; i++) { + double noise = pingPong((genNoiseSingle(seed++, x, y) + 1) * mPingPongStength); + sum += (noise - 0.5f) * 2 * amp; + amp *= lerp(1.0f, noise, mWeightedStrength); + + x *= mLacunarity; + y *= mLacunarity; + amp *= mGain; + } + + return sum; + } + + // Noise Coordinate Transforms (frequency, and possible skew or rotation) + private double genFractalPingPong(double x, double y, double z) { + int seed = mSeed; + double sum = 0; + double amp = mFractalBounding; + + for(int i = 0; i < mOctaves; i++) { + double noise = pingPong((genNoiseSingle(seed++, x, y, z) + 1) * mPingPongStength); + sum += (noise - 0.5f) * 2 * amp; + amp *= lerp(1.0f, noise, mWeightedStrength); + + x *= mLacunarity; + y *= mLacunarity; + z *= mLacunarity; + amp *= mGain; + } + + return sum; + } + + private double singleSimplex(int seed, double x, double y) { + // 2D OpenSimplex2 case uses the same algorithm as ordinary Simplex. + final double SQRT3 = 1.7320508075688772935274463415059f; + final double G2 = (3 - SQRT3) / 6; + + /* + * --- Skew moved to switch statements before fractal evaluation --- + * final FNLdouble F2 = 0.5f * (SQRT3 - 1); + * FNLdouble s = (x + y) * F2; + * x += s; y += s; + */ + + int i = fastFloor(x); + int j = fastFloor(y); + double xi = x - i; + double yi = y - j; + + double t = (xi + yi) * G2; + double x0 = xi - t; + double y0 = yi - t; + + i *= PRIME_X; + j *= PRIME_Y; + + double n0, n1, n2; + + double a = 0.5f - x0 * x0 - y0 * y0; + if(a <= 0) n0 = 0; + else { + n0 = (a * a) * (a * a) * gradCoord(seed, i, j, x0, y0); + } + + double c = 2 * (1 - 2 * G2) * (1 / G2 - 2) * t + ((-2 * (1 - 2 * G2) * (1 - 2 * G2)) + a); + if(c <= 0) n2 = 0; + else { + double x2 = x0 + (2 * G2 - 1); + double y2 = y0 + (2 * G2 - 1); + n2 = (c * c) * (c * c) * gradCoord(seed, i + PRIME_X, j + PRIME_Y, x2, y2); + } + + if(y0 > x0) { + double x1 = x0 + G2; + double y1 = y0 + (G2 - 1); + double b = 0.5f - x1 * x1 - y1 * y1; + if(b <= 0) n1 = 0; + else { + n1 = (b * b) * (b * b) * gradCoord(seed, i, j + PRIME_Y, x1, y1); + } + } else { + double x1 = x0 + (G2 - 1); + double y1 = y0 + G2; + double b = 0.5f - x1 * x1 - y1 * y1; + if(b <= 0) n1 = 0; + else { + n1 = (b * b) * (b * b) * gradCoord(seed, i + PRIME_X, j, x1, y1); + } + } + + return (n0 + n1 + n2) * 99.83685446303647f; + } + + // Fractal FBm + private double singleOpenSimplex2(int seed, double x, double y, double z) { + // 3D OpenSimplex2 case uses two offset rotated cube grids. + /* + * --- Rotation moved to switch statements before fractal evaluation --- + * final FNLdouble R3 = (FNLdouble)(2.0 / 3.0); + * FNLdouble r = (x + y + z) * R3; // Rotation, not skew + * x = r - x; y = r - y; z = r - z; + */ + + int i = fastRound(x); + int j = fastRound(y); + int k = fastRound(z); + double x0 = x - i; + double y0 = y - j; + double z0 = z - k; + + int xNSign = (int) (-1.0f - x0) | 1; + int yNSign = (int) (-1.0f - y0) | 1; + int zNSign = (int) (-1.0f - z0) | 1; + + double ax0 = xNSign * -x0; + double ay0 = yNSign * -y0; + double az0 = zNSign * -z0; + + i *= PRIME_X; + j *= PRIME_Y; + k *= PRIME_Z; + + double value = 0; + double a = (0.6f - x0 * x0) - (y0 * y0 + z0 * z0); + + for(int l = 0; ; l++) { + if(a > 0) { + value += (a * a) * (a * a) * gradCoord(seed, i, j, k, x0, y0, z0); + } + + if(ax0 >= ay0 && ax0 >= az0) { + double b = a + ax0 + ax0; + if(b > 1) { + b -= 1; + value += (b * b) * (b * b) * gradCoord(seed, i - xNSign * PRIME_X, j, k, x0 + xNSign, y0, z0); + } + } else if(ay0 > ax0 && ay0 >= az0) { + double b = a + ay0 + ay0; + if(b > 1) { + b -= 1; + value += (b * b) * (b * b) * gradCoord(seed, i, j - yNSign * PRIME_Y, k, x0, y0 + yNSign, z0); + } + } else { + double b = a + az0 + az0; + if(b > 1) { + b -= 1; + value += (b * b) * (b * b) * gradCoord(seed, i, j, k - zNSign * PRIME_Z, x0, y0, z0 + zNSign); + } + } + + if(l == 1) break; + + ax0 = 0.5f - ax0; + ay0 = 0.5f - ay0; + az0 = 0.5f - az0; + + x0 = xNSign * ax0; + y0 = yNSign * ay0; + z0 = zNSign * az0; + + a += (0.75f - ax0) - (ay0 + az0); + + i += (xNSign >> 1) & PRIME_X; + j += (yNSign >> 1) & PRIME_Y; + k += (zNSign >> 1) & PRIME_Z; + + xNSign = -xNSign; + yNSign = -yNSign; + zNSign = -zNSign; + + seed = ~seed; + } + + return value * 32.69428253173828125f; + } + + @SuppressWarnings("NumericOverflow") + private double singleOpenSimplex2S(int seed, double x, double y) { + // 2D OpenSimplex2S case is a modified 2D simplex noise. + + final double SQRT3 = 1.7320508075688772935274463415059; + final double G2 = (3 - SQRT3) / 6; + + /* + * --- Skew moved to TransformNoiseCoordinate method --- + * final FNLdouble F2 = 0.5f * (SQRT3 - 1); + * FNLdouble s = (x + y) * F2; + * x += s; y += s; + */ + + int i = fastFloor(x); + int j = fastFloor(y); + double xi = x - i; + double yi = y - j; + + i *= PRIME_X; + j *= PRIME_Y; + int i1 = i + PRIME_X; + int j1 = j + PRIME_Y; + + double t = (xi + yi) * G2; + double x0 = xi - t; + double y0 = yi - t; + + double a0 = (2.0f / 3.0f) - x0 * x0 - y0 * y0; + double value = (a0 * a0) * (a0 * a0) * gradCoord(seed, i, j, x0, y0); + + double a1 = 2 * (1 - 2 * G2) * (1 / G2 - 2) * t + ((-2 * (1 - 2 * G2) * (1 - 2 * G2)) + a0); + double x1 = x0 - (1 - 2 * G2); + double y1 = y0 - (1 - 2 * G2); + value += (a1 * a1) * (a1 * a1) * gradCoord(seed, i1, j1, x1, y1); + + // Nested conditionals were faster than compact bit logic/arithmetic. + double xmyi = xi - yi; + if(t > G2) { + if(xi + xmyi > 1) { + double x2 = x0 + (3 * G2 - 2); + double y2 = y0 + (3 * G2 - 1); + double a2 = (2.0f / 3.0f) - x2 * x2 - y2 * y2; + if(a2 > 0) { + value += (a2 * a2) * (a2 * a2) * gradCoord(seed, i + (PRIME_X << 1), j + PRIME_Y, x2, y2); + } + } else { + double x2 = x0 + G2; + double y2 = y0 + (G2 - 1); + double a2 = (2.0f / 3.0f) - x2 * x2 - y2 * y2; + if(a2 > 0) { + value += (a2 * a2) * (a2 * a2) * gradCoord(seed, i, j + PRIME_Y, x2, y2); + } + } + + if(yi - xmyi > 1) { + double x3 = x0 + (3 * G2 - 1); + double y3 = y0 + (3 * G2 - 2); + double a3 = (2.0f / 3.0f) - x3 * x3 - y3 * y3; + if(a3 > 0) { + value += (a3 * a3) * (a3 * a3) * gradCoord(seed, i + PRIME_X, j + (PRIME_Y << 1), x3, y3); + } + } else { + double x3 = x0 + (G2 - 1); + double y3 = y0 + G2; + double a3 = (2.0f / 3.0f) - x3 * x3 - y3 * y3; + if(a3 > 0) { + value += (a3 * a3) * (a3 * a3) * gradCoord(seed, i + PRIME_X, j, x3, y3); + } + } + } else { + if(xi + xmyi < 0) { + double x2 = x0 + (1 - G2); + double y2 = y0 - G2; + double a2 = (2.0f / 3.0f) - x2 * x2 - y2 * y2; + if(a2 > 0) { + value += (a2 * a2) * (a2 * a2) * gradCoord(seed, i - PRIME_X, j, x2, y2); + } + } else { + double x2 = x0 + (G2 - 1); + double y2 = y0 + G2; + double a2 = (2.0f / 3.0f) - x2 * x2 - y2 * y2; + if(a2 > 0) { + value += (a2 * a2) * (a2 * a2) * gradCoord(seed, i + PRIME_X, j, x2, y2); + } + } + + if(yi < xmyi) { + double x2 = x0 - G2; + double y2 = y0 - (G2 - 1); + double a2 = (2.0f / 3.0f) - x2 * x2 - y2 * y2; + if(a2 > 0) { + value += (a2 * a2) * (a2 * a2) * gradCoord(seed, i, j - PRIME_Y, x2, y2); + } + } else { + double x2 = x0 + G2; + double y2 = y0 + (G2 - 1); + double a2 = (2.0f / 3.0f) - x2 * x2 - y2 * y2; + if(a2 > 0) { + value += (a2 * a2) * (a2 * a2) * gradCoord(seed, i, j + PRIME_Y, x2, y2); + } + } + } + + return value * 18.24196194486065f; + } + + // Fractal Ridged + @SuppressWarnings("NumericOverflow") + private double singleOpenSimplex2S(int seed, double x, double y, double z) { + // 3D OpenSimplex2S case uses two offset rotated cube grids. + /* + * --- Rotation moved to TransformNoiseCoordinate method --- + * final FNLdouble R3 = (FNLdouble)(2.0 / 3.0); + * FNLdouble r = (x + y + z) * R3; // Rotation, not skew + * x = r - x; y = r - y; z = r - z; + */ + + int i = fastFloor(x); + int j = fastFloor(y); + int k = fastFloor(z); + double xi = x - i; + double yi = y - j; + double zi = z - k; + + i *= PRIME_X; + j *= PRIME_Y; + k *= PRIME_Z; + int seed2 = seed + 1293373; + + int xNMask = (int) (-0.5f - xi); + int yNMask = (int) (-0.5f - yi); + int zNMask = (int) (-0.5f - zi); + + double x0 = xi + xNMask; + double y0 = yi + yNMask; + double z0 = zi + zNMask; + double a0 = 0.75f - x0 * x0 - y0 * y0 - z0 * z0; + double value = (a0 * a0) * (a0 * a0) * gradCoord(seed, i + (xNMask & PRIME_X), j + (yNMask & PRIME_Y), k + (zNMask & PRIME_Z), x0, y0, + z0); + + double x1 = xi - 0.5f; + double y1 = yi - 0.5f; + double z1 = zi - 0.5f; + double a1 = 0.75f - x1 * x1 - y1 * y1 - z1 * z1; + value += (a1 * a1) * (a1 * a1) * gradCoord(seed2, i + PRIME_X, j + PRIME_Y, k + PRIME_Z, x1, y1, z1); + + double xAFlipMask0 = ((xNMask | 1) << 1) * x1; + double yAFlipMask0 = ((yNMask | 1) << 1) * y1; + double zAFlipMask0 = ((zNMask | 1) << 1) * z1; + double xAFlipMask1 = (-2 - (xNMask << 2)) * x1 - 1.0f; + double yAFlipMask1 = (-2 - (yNMask << 2)) * y1 - 1.0f; + double zAFlipMask1 = (-2 - (zNMask << 2)) * z1 - 1.0f; + + boolean skip5 = false; + double a2 = xAFlipMask0 + a0; + if(a2 > 0) { + double x2 = x0 - (xNMask | 1); + value += (a2 * a2) * (a2 * a2) * gradCoord(seed, i + (~xNMask & PRIME_X), j + (yNMask & PRIME_Y), k + (zNMask & PRIME_Z), x2, y0, + z0); + } else { + double a3 = yAFlipMask0 + zAFlipMask0 + a0; + if(a3 > 0) { + double y3 = y0 - (yNMask | 1); + double z3 = z0 - (zNMask | 1); + value += (a3 * a3) * (a3 * a3) * gradCoord(seed, i + (xNMask & PRIME_X), j + (~yNMask & PRIME_Y), k + (~zNMask & PRIME_Z), x0, + y3, z3); + } + + double a4 = xAFlipMask1 + a1; + if(a4 > 0) { + double x4 = (xNMask | 1) + x1; + value += (a4 * a4) * (a4 * a4) * gradCoord(seed2, i + (xNMask & (PRIME_X << 1)), j + PRIME_Y, k + PRIME_Z, x4, y1, z1); + skip5 = true; + } + } + + boolean skip9 = false; + double a6 = yAFlipMask0 + a0; + if(a6 > 0) { + double y6 = y0 - (yNMask | 1); + value += (a6 * a6) * (a6 * a6) * gradCoord(seed, i + (xNMask & PRIME_X), j + (~yNMask & PRIME_Y), k + (zNMask & PRIME_Z), x0, y6, + z0); + } else { + double a7 = xAFlipMask0 + zAFlipMask0 + a0; + if(a7 > 0) { + double x7 = x0 - (xNMask | 1); + double z7 = z0 - (zNMask | 1); + value += (a7 * a7) * (a7 * a7) * gradCoord(seed, i + (~xNMask & PRIME_X), j + (yNMask & PRIME_Y), k + (~zNMask & PRIME_Z), x7, + y0, z7); + } + + double a8 = yAFlipMask1 + a1; + if(a8 > 0) { + double y8 = (yNMask | 1) + y1; + value += (a8 * a8) * (a8 * a8) * gradCoord(seed2, i + PRIME_X, j + (yNMask & (PRIME_Y << 1)), k + PRIME_Z, x1, y8, z1); + skip9 = true; + } + } + + boolean skipD = false; + double aA = zAFlipMask0 + a0; + if(aA > 0) { + double zA = z0 - (zNMask | 1); + value += (aA * aA) * (aA * aA) * gradCoord(seed, i + (xNMask & PRIME_X), j + (yNMask & PRIME_Y), k + (~zNMask & PRIME_Z), x0, y0, + zA); + } else { + double aB = xAFlipMask0 + yAFlipMask0 + a0; + if(aB > 0) { + double xB = x0 - (xNMask | 1); + double yB = y0 - (yNMask | 1); + value += (aB * aB) * (aB * aB) * gradCoord(seed, i + (~xNMask & PRIME_X), j + (~yNMask & PRIME_Y), k + (zNMask & PRIME_Z), xB, + yB, z0); + } + + double aC = zAFlipMask1 + a1; + if(aC > 0) { + double zC = (zNMask | 1) + z1; + value += (aC * aC) * (aC * aC) * gradCoord(seed2, i + PRIME_X, j + PRIME_Y, k + (zNMask & (PRIME_Z << 1)), x1, y1, zC); + skipD = true; + } + } + + if(!skip5) { + double a5 = yAFlipMask1 + zAFlipMask1 + a1; + if(a5 > 0) { + double y5 = (yNMask | 1) + y1; + double z5 = (zNMask | 1) + z1; + value += (a5 * a5) * (a5 * a5) * gradCoord(seed2, i + PRIME_X, j + (yNMask & (PRIME_Y << 1)), k + (zNMask & (PRIME_Z << 1)), + x1, y5, z5); + } + } + + if(!skip9) { + double a9 = xAFlipMask1 + zAFlipMask1 + a1; + if(a9 > 0) { + double x9 = (xNMask | 1) + x1; + double z9 = (zNMask | 1) + z1; + value += (a9 * a9) * (a9 * a9) * gradCoord(seed2, i + (xNMask & (PRIME_X << 1)), j + PRIME_Y, k + (zNMask & (PRIME_Z << 1)), x9, + y1, z9); + } + } + + if(!skipD) { + double aD = xAFlipMask1 + yAFlipMask1 + a1; + if(aD > 0) { + double xD = (xNMask | 1) + x1; + double yD = (yNMask | 1) + y1; + value += (aD * aD) * (aD * aD) * gradCoord(seed2, i + (xNMask & (PRIME_X << 1)), j + (yNMask & (PRIME_Y << 1)), k + PRIME_Z, + xD, yD, z1); + } + } + + return value * 9.046026385208288f; + } + + private double singleCellular(int seed, double x, double y) { + int xr = fastRound(x); + int yr = fastRound(y); + + double distance0 = Double.MAX_VALUE; + double distance1 = Double.MAX_VALUE; + int closestHash = 0; + + double cellularJitter = 0.43701595f * mCellularJitterModifier; + + int xPrimed = (xr - 1) * PRIME_X; + int yPrimedBase = (yr - 1) * PRIME_Y; + + Vector2 center = new Vector2(x, y); + + switch(mCellularDistanceFunction) { + default: + case Euclidean: + case EuclideanSq: + for(int xi = xr - 1; xi <= xr + 1; xi++) { + int yPrimed = yPrimedBase; + + for(int yi = yr - 1; yi <= yr + 1; yi++) { + int hash = hash(seed, xPrimed, yPrimed); + int idx = hash & (255 << 1); + + double vecX = (xi - x) + RAND_VECS_2D[idx] * cellularJitter; + double vecY = (yi - y) + RAND_VECS_2D[idx | 1] * cellularJitter; + + double newDistance = vecX * vecX + vecY * vecY; + + distance1 = fastMax(fastMin(distance1, newDistance), distance0); + if(newDistance < distance0) { + distance0 = newDistance; + closestHash = hash; + center.setX((xi + RAND_VECS_2D[idx] * cellularJitter) / mFrequency); + center.setZ((yi + RAND_VECS_2D[idx | 1] * cellularJitter) / mFrequency); + } + yPrimed += PRIME_Y; + } + xPrimed += PRIME_X; + } + break; + case Manhattan: + for(int xi = xr - 1; xi <= xr + 1; xi++) { + int yPrimed = yPrimedBase; + + for(int yi = yr - 1; yi <= yr + 1; yi++) { + int hash = hash(seed, xPrimed, yPrimed); + int idx = hash & (255 << 1); + + double vecX = (xi - x) + RAND_VECS_2D[idx] * cellularJitter; + double vecY = (yi - y) + RAND_VECS_2D[idx | 1] * cellularJitter; + + double newDistance = fastAbs(vecX) + fastAbs(vecY); + + distance1 = fastMax(fastMin(distance1, newDistance), distance0); + if(newDistance < distance0) { + distance0 = newDistance; + closestHash = hash; + center.setX((xi + RAND_VECS_2D[idx] * cellularJitter) / mFrequency); + center.setZ((yi + RAND_VECS_2D[idx | 1] * cellularJitter) / mFrequency); + } + yPrimed += PRIME_Y; + } + xPrimed += PRIME_X; + } + break; + case Hybrid: + for(int xi = xr - 1; xi <= xr + 1; xi++) { + int yPrimed = yPrimedBase; + + for(int yi = yr - 1; yi <= yr + 1; yi++) { + int hash = hash(seed, xPrimed, yPrimed); + int idx = hash & (255 << 1); + + double vecX = (xi - x) + RAND_VECS_2D[idx] * cellularJitter; + double vecY = (yi - y) + RAND_VECS_2D[idx | 1] * cellularJitter; + + double newDistance = (fastAbs(vecX) + fastAbs(vecY)) + (vecX * vecX + vecY * vecY); + + distance1 = fastMax(fastMin(distance1, newDistance), distance0); + if(newDistance < distance0) { + distance0 = newDistance; + closestHash = hash; + center.setX((xi + RAND_VECS_2D[idx] * cellularJitter) / mFrequency); + center.setZ((yi + RAND_VECS_2D[idx | 1] * cellularJitter) / mFrequency); + } + yPrimed += PRIME_Y; + } + xPrimed += PRIME_X; + } + break; + } + + if(mCellularDistanceFunction == CellularDistanceFunction.Euclidean && mCellularReturnType != CellularReturnType.CellValue) { + distance0 = fastSqrt(distance0); + if(mCellularReturnType != CellularReturnType.CellValue) { + distance1 = fastSqrt(distance1); + } + } + + switch(mCellularReturnType) { + case CellValue: + return closestHash * (1 / 2147483648.0f); + case Distance: + return distance0 - 1; + case Distance2: + return distance1 - 1; + case Distance2Add: + return (distance1 + distance0) * 0.5f - 1; + case Distance2Sub: + return distance1 - distance0 - 1; + case Distance2Mul: + return distance1 * distance0 * 0.5f - 1; + case Distance2Div: + return distance0 / distance1 - 1; + case NoiseLookup: + return cellularNoiseLookup.getNoise(center.getX(), center.getZ()); + default: + return 0; + } + } + + // Fractal pingPong + private double singleCellular(int seed, double x, double y, double z) { + int xr = fastRound(x); + int yr = fastRound(y); + int zr = fastRound(z); + + double distance0 = Double.MAX_VALUE; + double distance1 = Double.MAX_VALUE; + int closestHash = 0; + + double cellularJitter = 0.39614353f * mCellularJitterModifier; + + int xPrimed = (xr - 1) * PRIME_X; + int yPrimedBase = (yr - 1) * PRIME_Y; + int zPrimedBase = (zr - 1) * PRIME_Z; + + Vector3 center = new Vector3(x, y, z); + + switch(mCellularDistanceFunction) { + case Euclidean: + case EuclideanSq: + for(int xi = xr - 1; xi <= xr + 1; xi++) { + int yPrimed = yPrimedBase; + + for(int yi = yr - 1; yi <= yr + 1; yi++) { + int zPrimed = zPrimedBase; + + for(int zi = zr - 1; zi <= zr + 1; zi++) { + int hash = hash(seed, xPrimed, yPrimed, zPrimed); + int idx = hash & (255 << 2); + + double vecX = (xi - x) + RAND_VECS_3D[idx] * cellularJitter; + double vecY = (yi - y) + RAND_VECS_3D[idx | 1] * cellularJitter; + double vecZ = (zi - z) + RAND_VECS_3D[idx | 2] * cellularJitter; + + double newDistance = vecX * vecX + vecY * vecY + vecZ * vecZ; + + distance1 = fastMax(fastMin(distance1, newDistance), distance0); + if(newDistance < distance0) { + distance0 = newDistance; + closestHash = hash; + center.setX((xi + RAND_VECS_3D[idx] * cellularJitter) / mFrequency); + center.setY((yi + RAND_VECS_3D[idx | 1] * cellularJitter) / mFrequency); + center.setZ((zi + RAND_VECS_3D[idx | 2] * cellularJitter) / mFrequency); + } + zPrimed += PRIME_Z; + } + yPrimed += PRIME_Y; + } + xPrimed += PRIME_X; + } + break; + case Manhattan: + for(int xi = xr - 1; xi <= xr + 1; xi++) { + int yPrimed = yPrimedBase; + + for(int yi = yr - 1; yi <= yr + 1; yi++) { + int zPrimed = zPrimedBase; + + for(int zi = zr - 1; zi <= zr + 1; zi++) { + int hash = hash(seed, xPrimed, yPrimed, zPrimed); + int idx = hash & (255 << 2); + + double vecX = (xi - x) + RAND_VECS_3D[idx] * cellularJitter; + double vecY = (yi - y) + RAND_VECS_3D[idx | 1] * cellularJitter; + double vecZ = (zi - z) + RAND_VECS_3D[idx | 2] * cellularJitter; + + double newDistance = fastAbs(vecX) + fastAbs(vecY) + fastAbs(vecZ); + + distance1 = fastMax(fastMin(distance1, newDistance), distance0); + if(newDistance < distance0) { + distance0 = newDistance; + closestHash = hash; + center.setX((xi + RAND_VECS_3D[idx] * cellularJitter) / mFrequency); + center.setY((yi + RAND_VECS_3D[idx | 1] * cellularJitter) / mFrequency); + center.setZ((zi + RAND_VECS_3D[idx | 2] * cellularJitter) / mFrequency); + } + zPrimed += PRIME_Z; + } + yPrimed += PRIME_Y; + } + xPrimed += PRIME_X; + } + break; + case Hybrid: + for(int xi = xr - 1; xi <= xr + 1; xi++) { + int yPrimed = yPrimedBase; + + for(int yi = yr - 1; yi <= yr + 1; yi++) { + int zPrimed = zPrimedBase; + + for(int zi = zr - 1; zi <= zr + 1; zi++) { + int hash = hash(seed, xPrimed, yPrimed, zPrimed); + int idx = hash & (255 << 2); + + double vecX = (xi - x) + RAND_VECS_3D[idx] * cellularJitter; + double vecY = (yi - y) + RAND_VECS_3D[idx | 1] * cellularJitter; + double vecZ = (zi - z) + RAND_VECS_3D[idx | 2] * cellularJitter; + + double newDistance = (fastAbs(vecX) + fastAbs(vecY) + fastAbs(vecZ)) + + (vecX * vecX + vecY * vecY + vecZ * vecZ); + + distance1 = fastMax(fastMin(distance1, newDistance), distance0); + if(newDistance < distance0) { + distance0 = newDistance; + closestHash = hash; + center.setX((xi + RAND_VECS_3D[idx] * cellularJitter) / mFrequency); + center.setY((yi + RAND_VECS_3D[idx | 1] * cellularJitter) / mFrequency); + center.setZ((zi + RAND_VECS_3D[idx | 2] * cellularJitter) / mFrequency); + } + zPrimed += PRIME_Z; + } + yPrimed += PRIME_Y; + } + xPrimed += PRIME_X; + } + break; + default: + break; + } + + if(mCellularDistanceFunction == CellularDistanceFunction.Euclidean && mCellularReturnType != CellularReturnType.CellValue) { + distance0 = fastSqrt(distance0); + if(mCellularReturnType != CellularReturnType.CellValue) { + distance1 = fastSqrt(distance1); + } + } + + switch(mCellularReturnType) { + case CellValue: + return closestHash * (1 / 2147483648.0f); + case Distance: + return distance0 - 1; + case Distance2: + return distance1 - 1; + case Distance2Add: + return (distance1 + distance0) * 0.5f - 1; + case Distance2Sub: + return distance1 - distance0 - 1; + case Distance2Mul: + return distance1 * distance0 * 0.5f - 1; + case Distance2Div: + return distance0 / distance1 - 1; + case NoiseLookup: + return cellularNoiseLookup.getNoise(center.getX(), center.getY(), center.getZ()); + default: + return 0; + } + } + + private double singlePerlin(int seed, double x, double y) { + int x0 = fastFloor(x); + int y0 = fastFloor(y); + + double xd0 = x - x0; + double yd0 = y - y0; + double xd1 = xd0 - 1; + double yd1 = yd0 - 1; + + double xs = interpQuintic(xd0); + double ys = interpQuintic(yd0); + + x0 *= PRIME_X; + y0 *= PRIME_Y; + int x1 = x0 + PRIME_X; + int y1 = y0 + PRIME_Y; + + double xf0 = lerp(gradCoord(seed, x0, y0, xd0, yd0), gradCoord(seed, x1, y0, xd1, yd0), xs); + double xf1 = lerp(gradCoord(seed, x0, y1, xd0, yd1), gradCoord(seed, x1, y1, xd1, yd1), xs); + + return lerp(xf0, xf1, ys) * 1.4247691104677813f; + } + + private int doubleCast2Int(double f) { + int i = Float.floatToRawIntBits((float) f); + + return i ^ (i >> 16); + } + + private double singleWhiteNoise(int seed, double x, double y, double z) { + int xi = doubleCast2Int(x); + int yi = doubleCast2Int(y); + int zi = doubleCast2Int(z); + + return valCoord(seed, xi, yi, zi); + } + + private double singleWhiteNoise(int seed, double x, double y) { + int xi = doubleCast2Int(x); + int yi = doubleCast2Int(y); + + return valCoord(seed, xi, yi); + } + + // Simplex/OpenSimplex2 Noise + private double singlePerlin(int seed, double x, double y, double z) { + int x0 = fastFloor(x); + int y0 = fastFloor(y); + int z0 = fastFloor(z); + + double xd0 = x - x0; + double yd0 = y - y0; + double zd0 = z - z0; + double xd1 = xd0 - 1; + double yd1 = yd0 - 1; + double zd1 = zd0 - 1; + + double xs = interpQuintic(xd0); + double ys = interpQuintic(yd0); + double zs = interpQuintic(zd0); + + x0 *= PRIME_X; + y0 *= PRIME_Y; + z0 *= PRIME_Z; + int x1 = x0 + PRIME_X; + int y1 = y0 + PRIME_Y; + int z1 = z0 + PRIME_Z; + + double xf00 = lerp(gradCoord(seed, x0, y0, z0, xd0, yd0, zd0), gradCoord(seed, x1, y0, z0, xd1, yd0, zd0), xs); + double xf10 = lerp(gradCoord(seed, x0, y1, z0, xd0, yd1, zd0), gradCoord(seed, x1, y1, z0, xd1, yd1, zd0), xs); + double xf01 = lerp(gradCoord(seed, x0, y0, z1, xd0, yd0, zd1), gradCoord(seed, x1, y0, z1, xd1, yd0, zd1), xs); + double xf11 = lerp(gradCoord(seed, x0, y1, z1, xd0, yd1, zd1), gradCoord(seed, x1, y1, z1, xd1, yd1, zd1), xs); + + double yf0 = lerp(xf00, xf10, ys); + double yf1 = lerp(xf01, xf11, ys); + + return lerp(yf0, yf1, zs) * 0.964921414852142333984375f; + } + + private double singleValueCubic(int seed, double x, double y) { + int x1 = fastFloor(x); + int y1 = fastFloor(y); + + double xs = x - x1; + double ys = y - y1; + + x1 *= PRIME_X; + y1 *= PRIME_Y; + int x0 = x1 - PRIME_X; + int y0 = y1 - PRIME_Y; + int x2 = x1 + PRIME_X; + int y2 = y1 + PRIME_Y; + int x3 = x1 + (PRIME_X << 1); + int y3 = y1 + (PRIME_Y << 1); + + return cubicLerp( + cubicLerp(valCoord(seed, x0, y0), valCoord(seed, x1, y0), valCoord(seed, x2, y0), valCoord(seed, x3, y0), + xs), + cubicLerp(valCoord(seed, x0, y1), valCoord(seed, x1, y1), valCoord(seed, x2, y1), valCoord(seed, x3, y1), + xs), + cubicLerp(valCoord(seed, x0, y2), valCoord(seed, x1, y2), valCoord(seed, x2, y2), valCoord(seed, x3, y2), + xs), + cubicLerp(valCoord(seed, x0, y3), valCoord(seed, x1, y3), valCoord(seed, x2, y3), valCoord(seed, x3, y3), + xs), + ys) * (1 / (1.5f * 1.5f)); + } + + // OpenSimplex2S Noise + private double singleValueCubic(int seed, double x, double y, double z) { + int x1 = fastFloor(x); + int y1 = fastFloor(y); + int z1 = fastFloor(z); + + double xs = x - x1; + double ys = y - y1; + double zs = z - z1; + + x1 *= PRIME_X; + y1 *= PRIME_Y; + z1 *= PRIME_Z; + + int x0 = x1 - PRIME_X; + int y0 = y1 - PRIME_Y; + int z0 = z1 - PRIME_Z; + int x2 = x1 + PRIME_X; + int y2 = y1 + PRIME_Y; + int z2 = z1 + PRIME_Z; + int x3 = x1 + (PRIME_X << 1); + int y3 = y1 + (PRIME_Y << 1); + int z3 = z1 + (PRIME_Z << 1); + + return cubicLerp( + cubicLerp( + cubicLerp(valCoord(seed, x0, y0, z0), valCoord(seed, x1, y0, z0), valCoord(seed, x2, y0, z0), + valCoord(seed, x3, y0, z0), xs), + cubicLerp(valCoord(seed, x0, y1, z0), valCoord(seed, x1, y1, z0), valCoord(seed, x2, y1, z0), + valCoord(seed, x3, y1, z0), xs), + cubicLerp(valCoord(seed, x0, y2, z0), valCoord(seed, x1, y2, z0), valCoord(seed, x2, y2, z0), + valCoord(seed, x3, y2, z0), xs), + cubicLerp(valCoord(seed, x0, y3, z0), valCoord(seed, x1, y3, z0), valCoord(seed, x2, y3, z0), + valCoord(seed, x3, y3, z0), xs), + ys), + cubicLerp( + cubicLerp(valCoord(seed, x0, y0, z1), valCoord(seed, x1, y0, z1), valCoord(seed, x2, y0, z1), + valCoord(seed, x3, y0, z1), xs), + cubicLerp(valCoord(seed, x0, y1, z1), valCoord(seed, x1, y1, z1), valCoord(seed, x2, y1, z1), + valCoord(seed, x3, y1, z1), xs), + cubicLerp(valCoord(seed, x0, y2, z1), valCoord(seed, x1, y2, z1), valCoord(seed, x2, y2, z1), + valCoord(seed, x3, y2, z1), xs), + cubicLerp(valCoord(seed, x0, y3, z1), valCoord(seed, x1, y3, z1), valCoord(seed, x2, y3, z1), + valCoord(seed, x3, y3, z1), xs), + ys), + cubicLerp( + cubicLerp(valCoord(seed, x0, y0, z2), valCoord(seed, x1, y0, z2), valCoord(seed, x2, y0, z2), + valCoord(seed, x3, y0, z2), xs), + cubicLerp(valCoord(seed, x0, y1, z2), valCoord(seed, x1, y1, z2), valCoord(seed, x2, y1, z2), + valCoord(seed, x3, y1, z2), xs), + cubicLerp(valCoord(seed, x0, y2, z2), valCoord(seed, x1, y2, z2), valCoord(seed, x2, y2, z2), + valCoord(seed, x3, y2, z2), xs), + cubicLerp(valCoord(seed, x0, y3, z2), valCoord(seed, x1, y3, z2), valCoord(seed, x2, y3, z2), + valCoord(seed, x3, y3, z2), xs), + ys), + cubicLerp( + cubicLerp(valCoord(seed, x0, y0, z3), valCoord(seed, x1, y0, z3), valCoord(seed, x2, y0, z3), + valCoord(seed, x3, y0, z3), xs), + cubicLerp(valCoord(seed, x0, y1, z3), valCoord(seed, x1, y1, z3), valCoord(seed, x2, y1, z3), + valCoord(seed, x3, y1, z3), xs), + cubicLerp(valCoord(seed, x0, y2, z3), valCoord(seed, x1, y2, z3), valCoord(seed, x2, y2, z3), + valCoord(seed, x3, y2, z3), xs), + cubicLerp(valCoord(seed, x0, y3, z3), valCoord(seed, x1, y3, z3), valCoord(seed, x2, y3, z3), + valCoord(seed, x3, y3, z3), xs), + ys), + zs) * (1 / (1.5f * 1.5f * 1.5f)); + } + + private double singleValue(int seed, double x, double y) { + int x0 = fastFloor(x); + int y0 = fastFloor(y); + + double xs = interpHermite(x - x0); + double ys = interpHermite(y - y0); + + x0 *= PRIME_X; + y0 *= PRIME_Y; + int x1 = x0 + PRIME_X; + int y1 = y0 + PRIME_Y; + + double xf0 = lerp(valCoord(seed, x0, y0), valCoord(seed, x1, y0), xs); + double xf1 = lerp(valCoord(seed, x0, y1), valCoord(seed, x1, y1), xs); + + return lerp(xf0, xf1, ys); + } + + // Cellular Noise + private double singleValue(int seed, double x, double y, double z) { + int x0 = fastFloor(x); + int y0 = fastFloor(y); + int z0 = fastFloor(z); + + double xs = interpHermite(x - x0); + double ys = interpHermite(y - y0); + double zs = interpHermite(z - z0); + + x0 *= PRIME_X; + y0 *= PRIME_Y; + z0 *= PRIME_Z; + int x1 = x0 + PRIME_X; + int y1 = y0 + PRIME_Y; + int z1 = z0 + PRIME_Z; + + double xf00 = lerp(valCoord(seed, x0, y0, z0), valCoord(seed, x1, y0, z0), xs); + double xf10 = lerp(valCoord(seed, x0, y1, z0), valCoord(seed, x1, y1, z0), xs); + double xf01 = lerp(valCoord(seed, x0, y0, z1), valCoord(seed, x1, y0, z1), xs); + double xf11 = lerp(valCoord(seed, x0, y1, z1), valCoord(seed, x1, y1, z1), xs); + + double yf0 = lerp(xf00, xf10, ys); + double yf1 = lerp(xf01, xf11, ys); + + return lerp(yf0, yf1, zs); + } + + private void doSingleDomainWarp(int seed, double amp, double freq, double x, double y, Vector2 coord) { + switch(mDomainWarpType) { + case OpenSimplex2: + singleDomainWarpSimplexGradient(seed, amp * 38.283687591552734375f, freq, x, y, coord, false); + break; + case OpenSimplex2Reduced: + singleDomainWarpSimplexGradient(seed, amp * 16.0f, freq, x, y, coord, true); + break; + case BasicGrid: + singleDomainWarpBasicGrid(seed, amp, freq, x, y, coord); + break; + } + } + + // Perlin Noise + private void doSingleDomainWarp(int seed, double amp, double freq, double x, double y, + double z, + Vector3 coord) { + switch(mDomainWarpType) { + case OpenSimplex2: + singleDomainWarpOpenSimplex2Gradient(seed, amp * 32.69428253173828125f, freq, x, y, z, coord, false); + break; + case OpenSimplex2Reduced: + singleDomainWarpOpenSimplex2Gradient(seed, amp * 7.71604938271605f, freq, x, y, z, coord, true); + break; + case BasicGrid: + singleDomainWarpBasicGrid(seed, amp, freq, x, y, z, coord); + break; + } + } + + private void domainWarpSingle(Vector2 coord) { + int seed = mSeed; + double amp = mDomainWarpAmp * mFractalBounding; + double freq = mFrequency; + + + double xs = coord.getX(); + + double ys = coord.getZ(); + switch(mDomainWarpType) { + case OpenSimplex2: + case OpenSimplex2Reduced: { + + final double SQRT3 = 1.7320508075688772935274463415059; + final double F2 = 0.5f * (SQRT3 - 1); + + double t = (xs + ys) * F2; + xs += t; + ys += t; + } + break; + default: + break; + } + + doSingleDomainWarp(seed, amp, freq, xs, ys, coord); + } + + // Value Cubic Noise + private void domainWarpSingle(Vector3 coord) { + int seed = mSeed; + double amp = mDomainWarpAmp * mFractalBounding; + double freq = mFrequency; + + + double xs = coord.getX(); + + double ys = coord.getY(); + + double zs = coord.getZ(); + switch(mWarpTransformType3D) { + case ImproveXYPlanes: { + + double xy = xs + ys; + + double s2 = xy * -0.211324865405187D; + + zs *= 0.577350269189626; + xs += s2 - zs; + ys = ys + s2 - zs; + + zs += xy * 0.577350269189626; + } + break; + case ImproveXZPlanes: { + + double xz = xs + zs; + + double s2 = xz * -0.211324865405187D; + + ys *= 0.577350269189626; + xs += s2 - ys; + zs += s2 - ys; + + ys += xz * 0.577350269189626; + } + break; + case DefaultOpenSimplex2: { + + final double R3 = 2.0 / 3.0; + + double r = (xs + ys + zs) * R3; // Rotation, not skew + xs = r - xs; + ys = r - ys; + zs = r - zs; + } + break; + default: + break; + } + + doSingleDomainWarp(seed, amp, freq, xs, ys, zs, coord); + } + + private void domainWarpFractalProgressive(Vector2 coord) { + int seed = mSeed; + double amp = mDomainWarpAmp * mFractalBounding; + double freq = mFrequency; + + for(int i = 0; i < mOctaves; i++) { + + double xs = coord.getX(); + + double ys = coord.getZ(); + switch(mDomainWarpType) { + case OpenSimplex2: + case OpenSimplex2Reduced: { + + final double SQRT3 = 1.7320508075688772935274463415059; + final double F2 = 0.5f * (SQRT3 - 1); + + double t = (xs + ys) * F2; + xs += t; + ys += t; + } + break; + default: + break; + } + + doSingleDomainWarp(seed, amp, freq, xs, ys, coord); + + seed++; + amp *= mGain; + freq *= mLacunarity; + } + } + + // Value Noise + private void domainWarpFractalProgressive(Vector3 coord) { + int seed = mSeed; + double amp = mDomainWarpAmp * mFractalBounding; + double freq = mFrequency; + + for(int i = 0; i < mOctaves; i++) { + + double xs = coord.getX(); + + double ys = coord.getY(); + + double zs = coord.getZ(); + switch(mWarpTransformType3D) { + case ImproveXYPlanes: { + + double xy = xs + ys; + + double s2 = xy * -0.211324865405187D; + + zs *= 0.577350269189626; + xs += s2 - zs; + ys = ys + s2 - zs; + + zs += xy * 0.577350269189626; + } + break; + case ImproveXZPlanes: { + + double xz = xs + zs; + + double s2 = xz * -0.211324865405187D; + + ys *= 0.577350269189626; + xs += s2 - ys; + zs += s2 - ys; + + ys += xz * 0.577350269189626; + } + break; + case DefaultOpenSimplex2: { + + final double R3 = 2.0 / 3.0; + + double r = (xs + ys + zs) * R3; // Rotation, not skew + xs = r - xs; + ys = r - ys; + zs = r - zs; + } + break; + default: + break; + } + + doSingleDomainWarp(seed, amp, freq, xs, ys, zs, coord); + + seed++; + amp *= mGain; + freq *= mLacunarity; + } + } + + // Domain Warp Fractal Independant + private void domainWarpFractalIndependent(Vector2 coord) { + + double xs = coord.getX(); + + double ys = coord.getZ(); + switch(mDomainWarpType) { + case OpenSimplex2: + case OpenSimplex2Reduced: { + + final double SQRT3 = 1.7320508075688772935274463415059; + final double F2 = 0.5f * (SQRT3 - 1); + + double t = (xs + ys) * F2; + xs += t; + ys += t; + } + break; + default: + break; + } + + int seed = mSeed; + double amp = mDomainWarpAmp * mFractalBounding; + double freq = mFrequency; + + for(int i = 0; i < mOctaves; i++) { + doSingleDomainWarp(seed, amp, freq, xs, ys, coord); + + seed++; + amp *= mGain; + freq *= mLacunarity; + } + } + + // Domain Warp + private void domainWarpFractalIndependent(Vector3 coord) { + + double xs = coord.getX(); + + double ys = coord.getY(); + + double zs = coord.getZ(); + switch(mWarpTransformType3D) { + case ImproveXYPlanes: { + + double xy = xs + ys; + + double s2 = xy * -0.211324865405187D; + + zs *= 0.577350269189626; + xs += s2 - zs; + ys = ys + s2 - zs; + + zs += xy * 0.577350269189626; + } + break; + case ImproveXZPlanes: { + + double xz = xs + zs; + + double s2 = xz * -0.211324865405187D; + + ys *= 0.577350269189626; + xs += s2 - ys; + zs += s2 - ys; + + ys += xz * 0.577350269189626; + } + break; + case DefaultOpenSimplex2: { + + final double R3 = 2.0 / 3.0; + + double r = (xs + ys + zs) * R3; // Rotation, not skew + xs = r - xs; + ys = r - ys; + zs = r - zs; + } + break; + default: + break; + } + + int seed = mSeed; + double amp = mDomainWarpAmp * mFractalBounding; + double freq = mFrequency; + + for(int i = 0; i < mOctaves; i++) { + doSingleDomainWarp(seed, amp, freq, xs, ys, zs, coord); + + seed++; + amp *= mGain; + freq *= mLacunarity; + } + } + + private void singleDomainWarpBasicGrid(int seed, double warpAmp, double frequency, double x, double y, + Vector2 coord) { + + double xf = x * frequency; + + double yf = y * frequency; + + int x0 = fastFloor(xf); + int y0 = fastFloor(yf); + + double xs = interpHermite(xf - x0); + double ys = interpHermite(yf - y0); + + x0 *= PRIME_X; + y0 *= PRIME_Y; + int x1 = x0 + PRIME_X; + int y1 = y0 + PRIME_Y; + + int hash0 = hash(seed, x0, y0) & (255 << 1); + int hash1 = hash(seed, x1, y0) & (255 << 1); + + double lx0x = lerp(RAND_VECS_2D[hash0], RAND_VECS_2D[hash1], xs); + double ly0x = lerp(RAND_VECS_2D[hash0 | 1], RAND_VECS_2D[hash1 | 1], xs); + + hash0 = hash(seed, x0, y1) & (255 << 1); + hash1 = hash(seed, x1, y1) & (255 << 1); + + double lx1x = lerp(RAND_VECS_2D[hash0], RAND_VECS_2D[hash1], xs); + double ly1x = lerp(RAND_VECS_2D[hash0 | 1], RAND_VECS_2D[hash1 | 1], xs); + + coord.add(lerp(lx0x, lx1x, ys) * warpAmp, + lerp(ly0x, ly1x, ys) * warpAmp); + } + + // Domain Warp Single Wrapper + private void singleDomainWarpBasicGrid(int seed, double warpAmp, double frequency, double x, + double y, double z, Vector3 coord) { + + double xf = x * frequency; + + double yf = y * frequency; + + double zf = z * frequency; + + int x0 = fastFloor(xf); + int y0 = fastFloor(yf); + int z0 = fastFloor(zf); + + double xs = interpHermite(xf - x0); + double ys = interpHermite(yf - y0); + double zs = interpHermite(zf - z0); + + x0 *= PRIME_X; + y0 *= PRIME_Y; + z0 *= PRIME_Z; + int x1 = x0 + PRIME_X; + int y1 = y0 + PRIME_Y; + int z1 = z0 + PRIME_Z; + + int hash0 = hash(seed, x0, y0, z0) & (255 << 2); + int hash1 = hash(seed, x1, y0, z0) & (255 << 2); + + double lx0x = lerp(RAND_VECS_3D[hash0], RAND_VECS_3D[hash1], xs); + double ly0x = lerp(RAND_VECS_3D[hash0 | 1], RAND_VECS_3D[hash1 | 1], xs); + double lz0x = lerp(RAND_VECS_3D[hash0 | 2], RAND_VECS_3D[hash1 | 2], xs); + + hash0 = hash(seed, x0, y1, z0) & (255 << 2); + hash1 = hash(seed, x1, y1, z0) & (255 << 2); + + double lx1x = lerp(RAND_VECS_3D[hash0], RAND_VECS_3D[hash1], xs); + double ly1x = lerp(RAND_VECS_3D[hash0 | 1], RAND_VECS_3D[hash1 | 1], xs); + double lz1x = lerp(RAND_VECS_3D[hash0 | 2], RAND_VECS_3D[hash1 | 2], xs); + + double lx0y = lerp(lx0x, lx1x, ys); + double ly0y = lerp(ly0x, ly1x, ys); + double lz0y = lerp(lz0x, lz1x, ys); + + hash0 = hash(seed, x0, y0, z1) & (255 << 2); + hash1 = hash(seed, x1, y0, z1) & (255 << 2); + + lx0x = lerp(RAND_VECS_3D[hash0], RAND_VECS_3D[hash1], xs); + ly0x = lerp(RAND_VECS_3D[hash0 | 1], RAND_VECS_3D[hash1 | 1], xs); + lz0x = lerp(RAND_VECS_3D[hash0 | 2], RAND_VECS_3D[hash1 | 2], xs); + + hash0 = hash(seed, x0, y1, z1) & (255 << 2); + hash1 = hash(seed, x1, y1, z1) & (255 << 2); + + lx1x = lerp(RAND_VECS_3D[hash0], RAND_VECS_3D[hash1], xs); + ly1x = lerp(RAND_VECS_3D[hash0 | 1], RAND_VECS_3D[hash1 | 1], xs); + lz1x = lerp(RAND_VECS_3D[hash0 | 2], RAND_VECS_3D[hash1 | 2], xs); + + coord.add(lerp(lx0y, lerp(lx0x, lx1x, ys), zs) * warpAmp, + lerp(ly0y, lerp(ly0x, ly1x, ys), zs) * warpAmp, + lerp(lz0y, lerp(lz0x, lz1x, ys), zs) * warpAmp); + } + + // Domain Warp Simplex/OpenSimplex2 + private void singleDomainWarpSimplexGradient(int seed, double warpAmp, double frequency, double x, double y, + Vector2 coord, boolean outGradOnly) { + final double SQRT3 = 1.7320508075688772935274463415059f; + final double G2 = (3 - SQRT3) / 6; + + x *= frequency; + y *= frequency; + + /* + * --- Skew moved to switch statements before fractal evaluation --- + * final FNLdouble F2 = 0.5f * (SQRT3 - 1); + * FNLdouble s = (x + y) * F2; + * x += s; y += s; + */ + + int i = fastFloor(x); + int j = fastFloor(y); + double xi = x - i; + double yi = y - j; + + double t = (xi + yi) * G2; + double x0 = xi - t; + double y0 = yi - t; + + i *= PRIME_X; + j *= PRIME_Y; + + double vx, vy; + vx = vy = 0; + + double a = 0.5f - x0 * x0 - y0 * y0; + if(a > 0) { + double aaaa = (a * a) * (a * a); + double xo, yo; + if(outGradOnly) { + int hash = hash(seed, i, j) & (255 << 1); + xo = RAND_VECS_2D[hash]; + yo = RAND_VECS_2D[hash | 1]; + } else { + int hash = hash(seed, i, j); + int index1 = hash & (127 << 1); + int index2 = (hash >> 7) & (255 << 1); + double xg = GRADIENTS_2_D[index1]; + double yg = GRADIENTS_2_D[index1 | 1]; + double value = x0 * xg + y0 * yg; + double xgo = RAND_VECS_2D[index2]; + double ygo = RAND_VECS_2D[index2 | 1]; + xo = value * xgo; + yo = value * ygo; + } + vx += aaaa * xo; + vy += aaaa * yo; + } + + double c = 2 * (1 - 2 * G2) * (1 / G2 - 2) * t + ((-2 * (1 - 2 * G2) * (1 - 2 * G2)) + a); + if(c > 0) { + double x2 = x0 + (2 * G2 - 1); + double y2 = y0 + (2 * G2 - 1); + double cccc = (c * c) * (c * c); + double xo, yo; + if(outGradOnly) { + int hash = hash(seed, i + PRIME_X, j + PRIME_Y) & (255 << 1); + xo = RAND_VECS_2D[hash]; + yo = RAND_VECS_2D[hash | 1]; + } else { + int hash = hash(seed, i + PRIME_X, j + PRIME_Y); + int index1 = hash & (127 << 1); + int index2 = (hash >> 7) & (255 << 1); + double xg = GRADIENTS_2_D[index1]; + double yg = GRADIENTS_2_D[index1 | 1]; + double value = x2 * xg + y2 * yg; + double xgo = RAND_VECS_2D[index2]; + double ygo = RAND_VECS_2D[index2 | 1]; + xo = value * xgo; + yo = value * ygo; + } + vx += cccc * xo; + vy += cccc * yo; + } + + if(y0 > x0) { + double x1 = x0 + G2; + double y1 = y0 + (G2 - 1); + double b = 0.5f - x1 * x1 - y1 * y1; + if(b > 0) { + double bbbb = (b * b) * (b * b); + double xo, yo; + if(outGradOnly) { + int hash = hash(seed, i, j + PRIME_Y) & (255 << 1); + xo = RAND_VECS_2D[hash]; + yo = RAND_VECS_2D[hash | 1]; + } else { + int hash = hash(seed, i, j + PRIME_Y); + int index1 = hash & (127 << 1); + int index2 = (hash >> 7) & (255 << 1); + double xg = GRADIENTS_2_D[index1]; + double yg = GRADIENTS_2_D[index1 | 1]; + double value = x1 * xg + y1 * yg; + double xgo = RAND_VECS_2D[index2]; + double ygo = RAND_VECS_2D[index2 | 1]; + xo = value * xgo; + yo = value * ygo; + } + vx += bbbb * xo; + vy += bbbb * yo; + } + } else { + double x1 = x0 + (G2 - 1); + double y1 = y0 + G2; + double b = 0.5f - x1 * x1 - y1 * y1; + if(b > 0) { + double bbbb = (b * b) * (b * b); + double xo, yo; + if(outGradOnly) { + int hash = hash(seed, i + PRIME_X, j) & (255 << 1); + xo = RAND_VECS_2D[hash]; + yo = RAND_VECS_2D[hash | 1]; + } else { + int hash = hash(seed, i + PRIME_X, j); + int index1 = hash & (127 << 1); + int index2 = (hash >> 7) & (255 << 1); + double xg = GRADIENTS_2_D[index1]; + double yg = GRADIENTS_2_D[index1 | 1]; + double value = x1 * xg + y1 * yg; + double xgo = RAND_VECS_2D[index2]; + double ygo = RAND_VECS_2D[index2 | 1]; + xo = value * xgo; + yo = value * ygo; + } + vx += bbbb * xo; + vy += bbbb * yo; + } + } + + coord.add(vx * warpAmp, + vy * warpAmp); + } + + // Domain Warp Fractal Progressive + private void singleDomainWarpOpenSimplex2Gradient(int seed, double warpAmp, double frequency, double x, + double y, double z, Vector3 coord, boolean outGradOnly) { + x *= frequency; + y *= frequency; + z *= frequency; + + /* + * --- Rotation moved to switch statements before fractal evaluation --- + * final FNLdouble R3 = (FNLdouble)(2.0 / 3.0); + * FNLdouble r = (x + y + z) * R3; // Rotation, not skew + * x = r - x; y = r - y; z = r - z; + */ + + int i = fastRound(x); + int j = fastRound(y); + int k = fastRound(z); + double x0 = x - i; + double y0 = y - j; + double z0 = z - k; + + int xNSign = (int) (-x0 - 1.0f) | 1; + int yNSign = (int) (-y0 - 1.0f) | 1; + int zNSign = (int) (-z0 - 1.0f) | 1; + + double ax0 = xNSign * -x0; + double ay0 = yNSign * -y0; + double az0 = zNSign * -z0; + + i *= PRIME_X; + j *= PRIME_Y; + k *= PRIME_Z; + + double vx, vy, vz; + vx = vy = vz = 0; + + double a = (0.6f - x0 * x0) - (y0 * y0 + z0 * z0); + for(int l = 0; ; l++) { + if(a > 0) { + double aaaa = (a * a) * (a * a); + double xo, yo, zo; + if(outGradOnly) { + int hash = hash(seed, i, j, k) & (255 << 2); + xo = RAND_VECS_3D[hash]; + yo = RAND_VECS_3D[hash | 1]; + zo = RAND_VECS_3D[hash | 2]; + } else { + int hash = hash(seed, i, j, k); + int index1 = hash & (63 << 2); + int index2 = (hash >> 6) & (255 << 2); + double xg = GRADIENTS_3D[index1]; + double yg = GRADIENTS_3D[index1 | 1]; + double zg = GRADIENTS_3D[index1 | 2]; + double value = x0 * xg + y0 * yg + z0 * zg; + double xgo = RAND_VECS_3D[index2]; + double ygo = RAND_VECS_3D[index2 | 1]; + double zgo = RAND_VECS_3D[index2 | 2]; + xo = value * xgo; + yo = value * ygo; + zo = value * zgo; + } + vx += aaaa * xo; + vy += aaaa * yo; + vz += aaaa * zo; + } + + double b = a; + int i1 = i; + int j1 = j; + int k1 = k; + double x1 = x0; + double y1 = y0; + double z1 = z0; + + if(ax0 >= ay0 && ax0 >= az0) { + x1 += xNSign; + b = b + ax0 + ax0; + i1 -= xNSign * PRIME_X; + } else if(ay0 > ax0 && ay0 >= az0) { + y1 += yNSign; + b = b + ay0 + ay0; + j1 -= yNSign * PRIME_Y; + } else { + z1 += zNSign; + b = b + az0 + az0; + k1 -= zNSign * PRIME_Z; + } + + if(b > 1) { + b -= 1; + double bbbb = (b * b) * (b * b); + double xo, yo, zo; + if(outGradOnly) { + int hash = hash(seed, i1, j1, k1) & (255 << 2); + xo = RAND_VECS_3D[hash]; + yo = RAND_VECS_3D[hash | 1]; + zo = RAND_VECS_3D[hash | 2]; + } else { + int hash = hash(seed, i1, j1, k1); + int index1 = hash & (63 << 2); + int index2 = (hash >> 6) & (255 << 2); + double xg = GRADIENTS_3D[index1]; + double yg = GRADIENTS_3D[index1 | 1]; + double zg = GRADIENTS_3D[index1 | 2]; + double value = x1 * xg + y1 * yg + z1 * zg; + double xgo = RAND_VECS_3D[index2]; + double ygo = RAND_VECS_3D[index2 | 1]; + double zgo = RAND_VECS_3D[index2 | 2]; + xo = value * xgo; + yo = value * ygo; + zo = value * zgo; + } + vx += bbbb * xo; + vy += bbbb * yo; + vz += bbbb * zo; + } + + if(l == 1) break; + + ax0 = 0.5f - ax0; + ay0 = 0.5f - ay0; + az0 = 0.5f - az0; + + x0 = xNSign * ax0; + y0 = yNSign * ay0; + z0 = zNSign * az0; + + a += (0.75f - ax0) - (ay0 + az0); + + i += (xNSign >> 1) & PRIME_X; + j += (yNSign >> 1) & PRIME_Y; + k += (zNSign >> 1) & PRIME_Z; + + xNSign = -xNSign; + yNSign = -yNSign; + zNSign = -zNSign; + + seed += 1293373; + } + + coord.add(vx * warpAmp, + vy * warpAmp, + vz * warpAmp); + } + + public enum NoiseType { + OpenSimplex2, + OpenSimplex2S, + Cellular, + Perlin, + ValueCubic, + Value, + WhiteNoise + } + + + public enum RotationType3D { + None, + ImproveXYPlanes, + ImproveXZPlanes + } + + + public enum FractalType { + None, + FBm, + Ridged, + PingPong, + DomainWarpProgressive, + DomainWarpIndependent + } + + // Domain Warp Basic Grid + + + public enum CellularDistanceFunction { + Euclidean, + EuclideanSq, + Manhattan, + Hybrid + } + + + public enum CellularReturnType { + CellValue, + Distance, + Distance2, + Distance2Add, + Distance2Sub, + Distance2Mul, + Distance2Div, + NoiseLookup + } + + + public enum DomainWarpType { + OpenSimplex2, + OpenSimplex2Reduced, + BasicGrid + } + + + private enum TransformType3D { + None, + ImproveXYPlanes, + ImproveXZPlanes, + DefaultOpenSimplex2 + } +} \ No newline at end of file diff --git a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/NoiseSampler.java b/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/NoiseSampler.java new file mode 100644 index 000000000..55ce7cb38 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/NoiseSampler.java @@ -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 + *

+ * Noise output bounded between -1...1 + */ + double getNoise(/*FNLdouble*/ double x, /*FNLdouble*/ double y); + + /** + * 3D noise at given position using current settings + *

+ * 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()); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/Normalizer.java b/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/Normalizer.java new file mode 100644 index 000000000..2d24939c7 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/Normalizer.java @@ -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)); + } +} diff --git a/src/main/java/com/dfsek/terra/math/BlankFunction.java b/common/src/main/java/com/dfsek/terra/api/math/parsii/BlankFunction.java similarity index 92% rename from src/main/java/com/dfsek/terra/math/BlankFunction.java rename to common/src/main/java/com/dfsek/terra/api/math/parsii/BlankFunction.java index def469f97..a95ebc971 100644 --- a/src/main/java/com/dfsek/terra/math/BlankFunction.java +++ b/common/src/main/java/com/dfsek/terra/api/math/parsii/BlankFunction.java @@ -1,4 +1,4 @@ -package com.dfsek.terra.math; +package com.dfsek.terra.api.math.parsii; import parsii.eval.Expression; import parsii.eval.Function; diff --git a/src/main/java/com/dfsek/terra/math/RandomFunction.java b/common/src/main/java/com/dfsek/terra/api/math/parsii/RandomFunction.java similarity index 76% rename from src/main/java/com/dfsek/terra/math/RandomFunction.java rename to common/src/main/java/com/dfsek/terra/api/math/parsii/RandomFunction.java index bad8d3d6e..1804ef9fb 100644 --- a/src/main/java/com/dfsek/terra/math/RandomFunction.java +++ b/common/src/main/java/com/dfsek/terra/api/math/parsii/RandomFunction.java @@ -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.Function; 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}) *

* Takes 1 argument, which sets the seed */ diff --git a/src/main/java/com/dfsek/terra/procgen/pixel/Distribution.java b/common/src/main/java/com/dfsek/terra/api/math/pixel/Distribution.java similarity index 73% rename from src/main/java/com/dfsek/terra/procgen/pixel/Distribution.java rename to common/src/main/java/com/dfsek/terra/api/math/pixel/Distribution.java index d182cca82..a91f07028 100644 --- a/src/main/java/com/dfsek/terra/procgen/pixel/Distribution.java +++ b/common/src/main/java/com/dfsek/terra/api/math/pixel/Distribution.java @@ -1,4 +1,4 @@ -package com.dfsek.terra.procgen.pixel; +package com.dfsek.terra.api.math.pixel; public class Distribution { public Distribution(Rectangle bound, int numPoints, double minRad) { diff --git a/src/main/java/com/dfsek/terra/procgen/pixel/Polygon.java b/common/src/main/java/com/dfsek/terra/api/math/pixel/Polygon.java similarity index 61% rename from src/main/java/com/dfsek/terra/procgen/pixel/Polygon.java rename to common/src/main/java/com/dfsek/terra/api/math/pixel/Polygon.java index fde36b4f0..00f996fd7 100644 --- a/src/main/java/com/dfsek/terra/procgen/pixel/Polygon.java +++ b/common/src/main/java/com/dfsek/terra/api/math/pixel/Polygon.java @@ -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; diff --git a/src/main/java/com/dfsek/terra/procgen/pixel/Rectangle.java b/common/src/main/java/com/dfsek/terra/api/math/pixel/Rectangle.java similarity index 92% rename from src/main/java/com/dfsek/terra/procgen/pixel/Rectangle.java rename to common/src/main/java/com/dfsek/terra/api/math/pixel/Rectangle.java index fb2df4824..0eecb2f40 100644 --- a/src/main/java/com/dfsek/terra/procgen/pixel/Rectangle.java +++ b/common/src/main/java/com/dfsek/terra/api/math/pixel/Rectangle.java @@ -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 java.util.HashSet; diff --git a/common/src/main/java/com/dfsek/terra/api/math/vector/Location.java b/common/src/main/java/com/dfsek/terra/api/math/vector/Location.java new file mode 100644 index 000000000..a030f9e49 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/math/vector/Location.java @@ -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() + ")]"; + } +} diff --git a/src/main/java/com/dfsek/terra/procgen/math/Vector2.java b/common/src/main/java/com/dfsek/terra/api/math/vector/Vector2.java similarity index 91% rename from src/main/java/com/dfsek/terra/procgen/math/Vector2.java rename to common/src/main/java/com/dfsek/terra/api/math/vector/Vector2.java index 6ec295b17..d78b0acc0 100644 --- a/src/main/java/com/dfsek/terra/procgen/math/Vector2.java +++ b/common/src/main/java/com/dfsek/terra/api/math/vector/Vector2.java @@ -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; /** @@ -157,11 +158,9 @@ public class Vector2 implements Cloneable { @Override public boolean equals(Object obj) { - if(!(obj instanceof Vector2)) { - return false; - } + if(!(obj instanceof Vector2)) return false; 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 @@ -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 public String toString() { return "(" + x + ", " + z + ")"; diff --git a/common/src/main/java/com/dfsek/terra/api/math/vector/Vector3.java b/common/src/main/java/com/dfsek/terra/api/math/vector/Vector3.java new file mode 100644 index 000000000..cafff1ea7 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/math/vector/Vector3.java @@ -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. + *

+ * This piece of math is based on the standard rotation matrix for vectors + * in three dimensional space. This matrix can be found here: + * Rotation + * Matrix. + * + * @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. + *

+ * This piece of math is based on the standard rotation matrix for vectors + * in three dimensional space. This matrix can be found here: + * Rotation + * Matrix. + * + * @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 + *

+ * This piece of math is based on the standard rotation matrix for vectors + * in three dimensional space. This matrix can be found here: + * Rotation + * Matrix. + * + * @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. + * + *

+ * Rotation will follow the general Right-Hand-Rule, which means rotation + * will be counterclockwise when the axis is pointing towards the observer. + *

+ * 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. + * + *

+ * Rotation will follow the general Right-Hand-Rule, which means rotation + * will be counterclockwise when the axis is pointing towards the observer. + *

+ * 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. + *

+ * 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() + ")"; + } + +} diff --git a/common/src/main/java/com/dfsek/terra/api/math/voxel/Cylinder.java b/common/src/main/java/com/dfsek/terra/api/math/voxel/Cylinder.java new file mode 100644 index 000000000..44d5558c3 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/math/voxel/Cylinder.java @@ -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) { + + } +} diff --git a/src/main/java/com/dfsek/terra/procgen/voxel/DeformedSphere.java b/common/src/main/java/com/dfsek/terra/api/math/voxel/DeformedSphere.java similarity index 58% rename from src/main/java/com/dfsek/terra/procgen/voxel/DeformedSphere.java rename to common/src/main/java/com/dfsek/terra/api/math/voxel/DeformedSphere.java index 8a30bccb0..325f74753 100644 --- a/src/main/java/com/dfsek/terra/procgen/voxel/DeformedSphere.java +++ b/common/src/main/java/com/dfsek/terra/api/math/voxel/DeformedSphere.java @@ -1,14 +1,14 @@ -package com.dfsek.terra.procgen.voxel; +package com.dfsek.terra.api.math.voxel; -import org.bukkit.util.Vector; -import org.polydev.gaea.math.FastNoiseLite; +import com.dfsek.terra.api.math.noise.samplers.NoiseSampler; +import com.dfsek.terra.api.math.vector.Vector3; 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 y = -rad; y <= rad; y++) { 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)) { addVector(c.add(start)); } diff --git a/src/main/java/com/dfsek/terra/procgen/voxel/Sphere.java b/common/src/main/java/com/dfsek/terra/api/math/voxel/Sphere.java similarity index 65% rename from src/main/java/com/dfsek/terra/procgen/voxel/Sphere.java rename to common/src/main/java/com/dfsek/terra/api/math/voxel/Sphere.java index 8ed97dec7..ced0cb3cd 100644 --- a/src/main/java/com/dfsek/terra/procgen/voxel/Sphere.java +++ b/common/src/main/java/com/dfsek/terra/api/math/voxel/Sphere.java @@ -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 Sphere(Vector start, int rad) { + public Sphere(Vector3 start, int rad) { for(int x = -rad; x <= rad; x++) { for(int y = -rad; y <= rad; y++) { 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) { addVector(c.add(start)); } diff --git a/common/src/main/java/com/dfsek/terra/api/math/voxel/Tube.java b/common/src/main/java/com/dfsek/terra/api/math/voxel/Tube.java new file mode 100644 index 000000000..7e0af69fc --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/math/voxel/Tube.java @@ -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); + } + } +} diff --git a/src/main/java/com/dfsek/terra/procgen/voxel/VoxelGeometry.java b/common/src/main/java/com/dfsek/terra/api/math/voxel/VoxelGeometry.java similarity index 54% rename from src/main/java/com/dfsek/terra/procgen/voxel/VoxelGeometry.java rename to common/src/main/java/com/dfsek/terra/api/math/voxel/VoxelGeometry.java index 3d0405722..dccbe3f1c 100644 --- a/src/main/java/com/dfsek/terra/procgen/voxel/VoxelGeometry.java +++ b/common/src/main/java/com/dfsek/terra/api/math/voxel/VoxelGeometry.java @@ -1,23 +1,23 @@ -package com.dfsek.terra.procgen.voxel; +package com.dfsek.terra.api.math.voxel; -import org.bukkit.util.Vector; -import org.polydev.gaea.util.GlueList; +import com.dfsek.terra.api.math.vector.Vector3; +import com.dfsek.terra.api.util.GlueList; import java.util.List; public abstract class VoxelGeometry { - private final List geometry = new GlueList<>(); + private final List geometry = new GlueList<>(); public static VoxelGeometry getBlank() { return new VoxelGeometry() { }; } - public List getGeometry() { + public List getGeometry() { return geometry; } - protected void addVector(Vector v) { + protected void addVector(Vector3 v) { geometry.add(v); } diff --git a/common/src/main/java/com/dfsek/terra/api/platform/CommandSender.java b/common/src/main/java/com/dfsek/terra/api/platform/CommandSender.java new file mode 100644 index 000000000..5fd7d60a7 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/platform/CommandSender.java @@ -0,0 +1,5 @@ +package com.dfsek.terra.api.platform; + +public interface CommandSender extends Handle { + void sendMessage(String message); +} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/Handle.java b/common/src/main/java/com/dfsek/terra/api/platform/Handle.java new file mode 100644 index 000000000..e0419aca3 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/platform/Handle.java @@ -0,0 +1,8 @@ +package com.dfsek.terra.api.platform; + +/** + * An interface that contains a platform delegate. + */ +public interface Handle { + Object getHandle(); +} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/TerraPlugin.java b/common/src/main/java/com/dfsek/terra/api/platform/TerraPlugin.java new file mode 100644 index 000000000..bb5be0618 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/platform/TerraPlugin.java @@ -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(); +} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/block/Axis.java b/common/src/main/java/com/dfsek/terra/api/platform/block/Axis.java new file mode 100644 index 000000000..38236b3b1 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/platform/block/Axis.java @@ -0,0 +1,5 @@ +package com.dfsek.terra.api.platform.block; + +public enum Axis { + X, Y, Z +} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/block/Block.java b/common/src/main/java/com/dfsek/terra/api/platform/block/Block.java new file mode 100644 index 000000000..47242d6e2 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/platform/block/Block.java @@ -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(); +} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/block/BlockData.java b/common/src/main/java/com/dfsek/terra/api/platform/block/BlockData.java new file mode 100644 index 000000000..d58979fa6 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/platform/block/BlockData.java @@ -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(); +} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/block/BlockFace.java b/common/src/main/java/com/dfsek/terra/api/platform/block/BlockFace.java new file mode 100644 index 000000000..4f9bcb904 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/platform/block/BlockFace.java @@ -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; + } +} + diff --git a/common/src/main/java/com/dfsek/terra/api/platform/block/MaterialData.java b/common/src/main/java/com/dfsek/terra/api/platform/block/MaterialData.java new file mode 100644 index 000000000..c5f3037b1 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/platform/block/MaterialData.java @@ -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(); +} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/block/data/AnaloguePowerable.java b/common/src/main/java/com/dfsek/terra/api/platform/block/data/AnaloguePowerable.java new file mode 100644 index 000000000..7c9ea0a7e --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/platform/block/data/AnaloguePowerable.java @@ -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); +} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/block/data/Bisected.java b/common/src/main/java/com/dfsek/terra/api/platform/block/data/Bisected.java new file mode 100644 index 000000000..a1061e33b --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/platform/block/data/Bisected.java @@ -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 + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/block/data/Directional.java b/common/src/main/java/com/dfsek/terra/api/platform/block/data/Directional.java new file mode 100644 index 000000000..6857121e3 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/platform/block/data/Directional.java @@ -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); +} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/block/data/MultipleFacing.java b/common/src/main/java/com/dfsek/terra/api/platform/block/data/MultipleFacing.java new file mode 100644 index 000000000..bf57c54d4 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/platform/block/data/MultipleFacing.java @@ -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 getFaces(); + + void setFace(BlockFace face, boolean facing); + + Set getAllowedFaces(); + + boolean hasFace(BlockFace f); +} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/block/data/Orientable.java b/common/src/main/java/com/dfsek/terra/api/platform/block/data/Orientable.java new file mode 100644 index 000000000..ff3cf79e3 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/platform/block/data/Orientable.java @@ -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 getAxes(); + + Axis getAxis(); + + void setAxis(Axis axis); +} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/block/data/Rail.java b/common/src/main/java/com/dfsek/terra/api/platform/block/data/Rail.java new file mode 100644 index 000000000..4436d11fb --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/platform/block/data/Rail.java @@ -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 + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/block/data/RedstoneWire.java b/common/src/main/java/com/dfsek/terra/api/platform/block/data/RedstoneWire.java new file mode 100644 index 000000000..6f9602de8 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/platform/block/data/RedstoneWire.java @@ -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 getAllowedFaces(); + Connection getFace(BlockFace face); + void setFace(BlockFace face, Connection connection); + enum Connection { + NONE, SIDE, UP + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/block/data/Rotatable.java b/common/src/main/java/com/dfsek/terra/api/platform/block/data/Rotatable.java new file mode 100644 index 000000000..58f23989e --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/platform/block/data/Rotatable.java @@ -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); +} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/block/data/Slab.java b/common/src/main/java/com/dfsek/terra/api/platform/block/data/Slab.java new file mode 100644 index 000000000..d813c8938 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/platform/block/data/Slab.java @@ -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 + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/block/data/Stairs.java b/common/src/main/java/com/dfsek/terra/api/platform/block/data/Stairs.java new file mode 100644 index 000000000..9ed5382aa --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/platform/block/data/Stairs.java @@ -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 + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/block/data/Wall.java b/common/src/main/java/com/dfsek/terra/api/platform/block/data/Wall.java new file mode 100644 index 000000000..5d891a0da --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/platform/block/data/Wall.java @@ -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 + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/block/data/Waterlogged.java b/common/src/main/java/com/dfsek/terra/api/platform/block/data/Waterlogged.java new file mode 100644 index 000000000..3d5d3fed8 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/platform/block/data/Waterlogged.java @@ -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); +} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/block/state/BlockState.java b/common/src/main/java/com/dfsek/terra/api/platform/block/state/BlockState.java new file mode 100644 index 000000000..47f5f51b7 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/platform/block/state/BlockState.java @@ -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. + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/block/state/Container.java b/common/src/main/java/com/dfsek/terra/api/platform/block/state/Container.java new file mode 100644 index 000000000..450b8d09a --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/platform/block/state/Container.java @@ -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 { +} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/block/state/MobSpawner.java b/common/src/main/java/com/dfsek/terra/api/platform/block/state/MobSpawner.java new file mode 100644 index 000000000..6f2772135 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/platform/block/state/MobSpawner.java @@ -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); +} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/block/state/SerialState.java b/common/src/main/java/com/dfsek/terra/api/platform/block/state/SerialState.java new file mode 100644 index 000000000..7c05c1253 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/platform/block/state/SerialState.java @@ -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> properties = new HashMap<>(); + + public SerialState() { + } + + public static Map parse(String props) { + String[] sep = props.split(","); + Map 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 get(String id, Class clazz) { + checkExists(id); + Property prop = properties.get(id); + checkType(clazz, prop.getValue(), id); + return (T) prop.getValue(); + } + + protected static class Property { + private final Class clazz; + private Object value; + + public Property(Class clazz) { + this.clazz = clazz; + } + + public Class getValueClass() { + return clazz; + } + + @SuppressWarnings("unchecked") + public T getValue() { + return (T) value; + } + + public void setValue(Object value) { + this.value = value; + } + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/block/state/Sign.java b/common/src/main/java/com/dfsek/terra/api/platform/block/state/Sign.java new file mode 100644 index 000000000..0cc901816 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/platform/block/state/Sign.java @@ -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; +} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/generator/BlockPopulator.java b/common/src/main/java/com/dfsek/terra/api/platform/generator/BlockPopulator.java new file mode 100644 index 000000000..cebe7f3da --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/platform/generator/BlockPopulator.java @@ -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); +} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/generator/ChunkGenerator.java b/common/src/main/java/com/dfsek/terra/api/platform/generator/ChunkGenerator.java new file mode 100644 index 000000000..266ce760b --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/platform/generator/ChunkGenerator.java @@ -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 getDefaultPopulators(World world); + + @Nullable + TerraChunkGenerator getTerraGenerator(); + + interface ChunkData extends Handle { + /** + * Get the maximum height for the chunk. + *

+ * 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. + *

+ * 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. + *

+ * 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); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/generator/GeneratorWrapper.java b/common/src/main/java/com/dfsek/terra/api/platform/generator/GeneratorWrapper.java new file mode 100644 index 000000000..60a05b386 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/platform/generator/GeneratorWrapper.java @@ -0,0 +1,6 @@ +package com.dfsek.terra.api.platform.generator; + +import com.dfsek.terra.api.platform.Handle; + +public interface GeneratorWrapper extends Handle { +} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/handle/ItemHandle.java b/common/src/main/java/com/dfsek/terra/api/platform/handle/ItemHandle.java new file mode 100644 index 000000000..fe2fe39d0 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/platform/handle/ItemHandle.java @@ -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 getEnchantments(); +} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/handle/WorldHandle.java b/common/src/main/java/com/dfsek/terra/api/platform/handle/WorldHandle.java new file mode 100644 index 000000000..c03cda1bf --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/platform/handle/WorldHandle.java @@ -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); +} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/inventory/BlockInventoryHolder.java b/common/src/main/java/com/dfsek/terra/api/platform/inventory/BlockInventoryHolder.java new file mode 100644 index 000000000..157d8837e --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/platform/inventory/BlockInventoryHolder.java @@ -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(); +} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/inventory/Inventory.java b/common/src/main/java/com/dfsek/terra/api/platform/inventory/Inventory.java new file mode 100644 index 000000000..776a23614 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/platform/inventory/Inventory.java @@ -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); +} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/inventory/InventoryHolder.java b/common/src/main/java/com/dfsek/terra/api/platform/inventory/InventoryHolder.java new file mode 100644 index 000000000..c8550a121 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/platform/inventory/InventoryHolder.java @@ -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(); +} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/inventory/ItemStack.java b/common/src/main/java/com/dfsek/terra/api/platform/inventory/ItemStack.java new file mode 100644 index 000000000..95b1d299a --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/platform/inventory/ItemStack.java @@ -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); +} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/inventory/item/Damageable.java b/common/src/main/java/com/dfsek/terra/api/platform/inventory/item/Damageable.java new file mode 100644 index 000000000..160388c94 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/platform/inventory/item/Damageable.java @@ -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(); +} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/inventory/item/Enchantment.java b/common/src/main/java/com/dfsek/terra/api/platform/inventory/item/Enchantment.java new file mode 100644 index 000000000..e8f404f34 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/platform/inventory/item/Enchantment.java @@ -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(); +} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/inventory/item/ItemMeta.java b/common/src/main/java/com/dfsek/terra/api/platform/inventory/item/ItemMeta.java new file mode 100644 index 000000000..0189c5755 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/platform/inventory/item/ItemMeta.java @@ -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 getEnchantments(); + + void addEnchantment(Enchantment enchantment, int level); +} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/package-info.java b/common/src/main/java/com/dfsek/terra/api/platform/package-info.java new file mode 100644 index 000000000..f1b97f5ed --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/platform/package-info.java @@ -0,0 +1,4 @@ +/** + * API for platform implementations. Mostly interfaces to be implemented by platform delegates. + */ +package com.dfsek.terra.api.platform; diff --git a/common/src/main/java/com/dfsek/terra/api/platform/world/Biome.java b/common/src/main/java/com/dfsek/terra/api/platform/world/Biome.java new file mode 100644 index 000000000..ec1b2060d --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/platform/world/Biome.java @@ -0,0 +1,6 @@ +package com.dfsek.terra.api.platform.world; + +import com.dfsek.terra.api.platform.Handle; + +public interface Biome extends Handle { +} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/world/BiomeGrid.java b/common/src/main/java/com/dfsek/terra/api/platform/world/BiomeGrid.java new file mode 100644 index 000000000..0fe72dd42 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/platform/world/BiomeGrid.java @@ -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); +} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/world/Chunk.java b/common/src/main/java/com/dfsek/terra/api/platform/world/Chunk.java new file mode 100644 index 000000000..edd1f63a3 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/platform/world/Chunk.java @@ -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); +} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/world/Tree.java b/common/src/main/java/com/dfsek/terra/api/platform/world/Tree.java new file mode 100644 index 000000000..c9a6a1cb5 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/platform/world/Tree.java @@ -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 { +} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/world/World.java b/common/src/main/java/com/dfsek/terra/api/platform/world/World.java new file mode 100644 index 000000000..52ff12e25 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/platform/world/World.java @@ -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); +} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/world/entity/Entity.java b/common/src/main/java/com/dfsek/terra/api/platform/world/entity/Entity.java new file mode 100644 index 000000000..2972749d5 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/platform/world/entity/Entity.java @@ -0,0 +1,6 @@ +package com.dfsek.terra.api.platform.world.entity; + +import com.dfsek.terra.api.platform.Handle; + +public interface Entity extends Handle { +} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/world/entity/EntityType.java b/common/src/main/java/com/dfsek/terra/api/platform/world/entity/EntityType.java new file mode 100644 index 000000000..45699b60b --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/platform/world/entity/EntityType.java @@ -0,0 +1,6 @@ +package com.dfsek.terra.api.platform.world.entity; + +import com.dfsek.terra.api.platform.Handle; + +public interface EntityType extends Handle { +} diff --git a/common/src/main/java/com/dfsek/terra/api/profiler/DataHolder.java b/common/src/main/java/com/dfsek/terra/api/profiler/DataHolder.java new file mode 100644 index 000000000..14fa9b1b3 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/profiler/DataHolder.java @@ -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.
+ * GREEN if the value is better than desired and outside of acceptable range.
+ * YELLOW if the value is better or worse than desired, and within acceptable range.
+ * RED if the value is worse than desired and outside of acceptable range.
+ * + * @param data The data to format. + * @return String - The formatted data. + */ + public String getFormattedData(long data) { + return type.getFormatted(data); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/profiler/DataType.java b/common/src/main/java/com/dfsek/terra/api/profiler/DataType.java new file mode 100644 index 000000000..70f6c5fd1 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/profiler/DataType.java @@ -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; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/profiler/Desire.java b/common/src/main/java/com/dfsek/terra/api/profiler/Desire.java new file mode 100644 index 000000000..43aae5a47 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/profiler/Desire.java @@ -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 + +} diff --git a/common/src/main/java/com/dfsek/terra/api/profiler/Measurement.java b/common/src/main/java/com/dfsek/terra/api/profiler/Measurement.java new file mode 100644 index 000000000..d90fe8bfd --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/profiler/Measurement.java @@ -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 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 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(); + } + +} diff --git a/common/src/main/java/com/dfsek/terra/api/profiler/ProfileFuture.java b/common/src/main/java/com/dfsek/terra/api/profiler/ProfileFuture.java new file mode 100644 index 000000000..724d82707 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/profiler/ProfileFuture.java @@ -0,0 +1,18 @@ +package com.dfsek.terra.api.profiler; + +import java.util.concurrent.CompletableFuture; + +public class ProfileFuture extends CompletableFuture implements AutoCloseable { + public ProfileFuture() { + super(); + } + + public boolean complete() { + return super.complete(true); + } + + @Override + public void close() { + this.complete(); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/profiler/WorldProfiler.java b/common/src/main/java/com/dfsek/terra/api/profiler/WorldProfiler.java new file mode 100644 index 000000000..87697095a --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/profiler/WorldProfiler.java @@ -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 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 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 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; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/loot/Entry.java b/common/src/main/java/com/dfsek/terra/api/structures/loot/Entry.java new file mode 100644 index 000000000..d676a1b25 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/loot/Entry.java @@ -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 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; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/loot/LootTable.java b/common/src/main/java/com/dfsek/terra/api/structures/loot/LootTable.java new file mode 100644 index 000000000..9e57de215 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/loot/LootTable.java @@ -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 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 getLoot(Random r) { + List 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 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++; + } + } + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/loot/Pool.java b/common/src/main/java/com/dfsek/terra/api/structures/loot/Pool.java new file mode 100644 index 000000000..d45be375f --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/loot/Pool.java @@ -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 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 getItems(Random r) { + + int rolls = r.nextInt(max - min + 1) + min; + List items = new GlueList<>(); + for(int i = 0; i < rolls; i++) { + items.add(entries.get(r).getItem(r)); + } + return items; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/loot/functions/AmountFunction.java b/common/src/main/java/com/dfsek/terra/api/structures/loot/functions/AmountFunction.java new file mode 100644 index 000000000..f83498fec --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/loot/functions/AmountFunction.java @@ -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; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/loot/functions/DamageFunction.java b/common/src/main/java/com/dfsek/terra/api/structures/loot/functions/DamageFunction.java new file mode 100644 index 000000000..704fdcfa8 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/loot/functions/DamageFunction.java @@ -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; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/loot/functions/EnchantFunction.java b/common/src/main/java/com/dfsek/terra/api/structures/loot/functions/EnchantFunction.java new file mode 100644 index 000000000..0debec4ee --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/loot/functions/EnchantFunction.java @@ -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 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; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/loot/functions/LootFunction.java b/common/src/main/java/com/dfsek/terra/api/structures/loot/functions/LootFunction.java new file mode 100644 index 000000000..5b882c830 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/loot/functions/LootFunction.java @@ -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); +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/Parser.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/Parser.java new file mode 100644 index 000000000..885ad7f49 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/Parser.java @@ -0,0 +1,441 @@ +package com.dfsek.terra.api.structures.parser; + +import com.dfsek.terra.api.structures.parser.exceptions.ParseException; +import com.dfsek.terra.api.structures.parser.lang.Block; +import com.dfsek.terra.api.structures.parser.lang.Item; +import com.dfsek.terra.api.structures.parser.lang.Keyword; +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.parser.lang.constants.BooleanConstant; +import com.dfsek.terra.api.structures.parser.lang.constants.ConstantExpression; +import com.dfsek.terra.api.structures.parser.lang.constants.NumericConstant; +import com.dfsek.terra.api.structures.parser.lang.constants.StringConstant; +import com.dfsek.terra.api.structures.parser.lang.functions.Function; +import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.api.structures.parser.lang.keywords.flow.BreakKeyword; +import com.dfsek.terra.api.structures.parser.lang.keywords.flow.ContinueKeyword; +import com.dfsek.terra.api.structures.parser.lang.keywords.flow.FailKeyword; +import com.dfsek.terra.api.structures.parser.lang.keywords.flow.ReturnKeyword; +import com.dfsek.terra.api.structures.parser.lang.keywords.looplike.ForKeyword; +import com.dfsek.terra.api.structures.parser.lang.keywords.looplike.IfKeyword; +import com.dfsek.terra.api.structures.parser.lang.keywords.looplike.WhileKeyword; +import com.dfsek.terra.api.structures.parser.lang.operations.BinaryOperation; +import com.dfsek.terra.api.structures.parser.lang.operations.BooleanAndOperation; +import com.dfsek.terra.api.structures.parser.lang.operations.BooleanNotOperation; +import com.dfsek.terra.api.structures.parser.lang.operations.BooleanOrOperation; +import com.dfsek.terra.api.structures.parser.lang.operations.ConcatenationOperation; +import com.dfsek.terra.api.structures.parser.lang.operations.DivisionOperation; +import com.dfsek.terra.api.structures.parser.lang.operations.ModuloOperation; +import com.dfsek.terra.api.structures.parser.lang.operations.MultiplicationOperation; +import com.dfsek.terra.api.structures.parser.lang.operations.NegationOperation; +import com.dfsek.terra.api.structures.parser.lang.operations.NumberAdditionOperation; +import com.dfsek.terra.api.structures.parser.lang.operations.SubtractionOperation; +import com.dfsek.terra.api.structures.parser.lang.operations.statements.EqualsStatement; +import com.dfsek.terra.api.structures.parser.lang.operations.statements.GreaterOrEqualsThanStatement; +import com.dfsek.terra.api.structures.parser.lang.operations.statements.GreaterThanStatement; +import com.dfsek.terra.api.structures.parser.lang.operations.statements.LessThanOrEqualsStatement; +import com.dfsek.terra.api.structures.parser.lang.operations.statements.LessThanStatement; +import com.dfsek.terra.api.structures.parser.lang.operations.statements.NotEqualsStatement; +import com.dfsek.terra.api.structures.parser.lang.variables.Assignment; +import com.dfsek.terra.api.structures.parser.lang.variables.BooleanVariable; +import com.dfsek.terra.api.structures.parser.lang.variables.Getter; +import com.dfsek.terra.api.structures.parser.lang.variables.NumberVariable; +import com.dfsek.terra.api.structures.parser.lang.variables.StringVariable; +import com.dfsek.terra.api.structures.parser.lang.variables.Variable; +import com.dfsek.terra.api.structures.tokenizer.Position; +import com.dfsek.terra.api.structures.tokenizer.Token; +import com.dfsek.terra.api.structures.tokenizer.Tokenizer; +import com.dfsek.terra.api.util.GlueList; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@SuppressWarnings("unchecked") +public class Parser { + private final String data; + private final Map>> functions = new HashMap<>(); + + private String id; + + public Parser(String data) { + this.data = data; + } + + public Parser registerFunction(String name, FunctionBuilder> functionBuilder) { + functions.put(name, functionBuilder); + return this; + } + + public String getID() { + return id; + } + + /** + * Parse input + * + * @return executable {@link Block} + * @throws ParseException If parsing fails. + */ + public Block parse() throws ParseException { + Tokenizer tokens = new Tokenizer(data); + + // Parse ID + ParserUtil.checkType(tokens.consume(), Token.Type.ID); // First token must be ID + Token idToken = tokens.get(); + ParserUtil.checkType(tokens.consume(), Token.Type.STRING); // Second token must be string literal containing ID + ParserUtil.checkType(tokens.consume(), Token.Type.STATEMENT_END); + this.id = idToken.getContent(); + + + return parseBlock(tokens, new HashMap<>(), false); + } + + + private Keyword parseLoopLike(Tokenizer tokens, Map> variableMap, boolean loop) throws ParseException { + + Token identifier = tokens.consume(); + ParserUtil.checkType(identifier, Token.Type.IF_STATEMENT, Token.Type.WHILE_LOOP, Token.Type.FOR_LOOP); + + ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_BEGIN); + + switch(identifier.getType()) { + case FOR_LOOP: + return parseForLoop(tokens, variableMap, identifier.getPosition()); + case IF_STATEMENT: + return parseIfStatement(tokens, variableMap, identifier.getPosition(), loop); + case WHILE_LOOP: + return parseWhileLoop(tokens, variableMap, identifier.getPosition()); + default: + throw new UnsupportedOperationException("Unknown keyword " + identifier.getContent() + ": " + identifier.getPosition()); + } + } + + private WhileKeyword parseWhileLoop(Tokenizer tokens, Map> variableMap, Position start) throws ParseException { + Returnable first = parseExpression(tokens, true, variableMap); + ParserUtil.checkReturnType(first, Returnable.ReturnType.BOOLEAN); + + ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_END); + + return new WhileKeyword(parseStatementBlock(tokens, variableMap, true), (Returnable) first, start); // While loop + } + + private IfKeyword parseIfStatement(Tokenizer tokens, Map> variableMap, Position start, boolean loop) throws ParseException { + Returnable condition = parseExpression(tokens, true, variableMap); + ParserUtil.checkReturnType(condition, Returnable.ReturnType.BOOLEAN); + + ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_END); + + Block elseBlock = null; + Block statement = parseStatementBlock(tokens, variableMap, loop); + + List, Block>> elseIf = new GlueList<>(); + + while(tokens.hasNext() && tokens.get().getType().equals(Token.Type.ELSE)) { + tokens.consume(); // Consume else. + if(tokens.get().getType().equals(Token.Type.IF_STATEMENT)) { + tokens.consume(); // Consume if. + Returnable elseCondition = parseExpression(tokens, true, variableMap); + ParserUtil.checkReturnType(elseCondition, Returnable.ReturnType.BOOLEAN); + elseIf.add(new IfKeyword.Pair<>((Returnable) elseCondition, parseStatementBlock(tokens, variableMap, loop))); + } else { + elseBlock = parseStatementBlock(tokens, variableMap, loop); + break; // Else must be last. + } + } + + return new IfKeyword(statement, (Returnable) condition, elseIf, elseBlock, start); // If statement + } + + private Block parseStatementBlock(Tokenizer tokens, Map> variableMap, boolean loop) throws ParseException { + + if(tokens.get().getType().equals(Token.Type.BLOCK_BEGIN)) { + ParserUtil.checkType(tokens.consume(), Token.Type.BLOCK_BEGIN); + Block block = parseBlock(tokens, variableMap, loop); + ParserUtil.checkType(tokens.consume(), Token.Type.BLOCK_END); + return block; + } else { + Position position = tokens.get().getPosition(); + Block block = new Block(Collections.singletonList(parseItem(tokens, variableMap, loop)), position); + ParserUtil.checkType(tokens.consume(), Token.Type.STATEMENT_END); + return block; + } + } + + private ForKeyword parseForLoop(Tokenizer tokens, Map> old, Position start) throws ParseException { + Map> variableMap = new HashMap<>(old); // New scope + Token f = tokens.get(); + ParserUtil.checkType(f, Token.Type.NUMBER_VARIABLE, Token.Type.STRING_VARIABLE, Token.Type.BOOLEAN_VARIABLE, Token.Type.IDENTIFIER); + Item initializer; + if(f.isVariableDeclaration()) { + Variable forVar = parseVariableDeclaration(tokens, ParserUtil.getVariableReturnType(f)); + ParserUtil.checkType(tokens.consume(), Token.Type.STRING_VARIABLE, Token.Type.BOOLEAN_VARIABLE, Token.Type.NUMBER_VARIABLE); + Token name = tokens.get(); + + if(functions.containsKey(name.getContent()) || variableMap.containsKey(name.getContent())) + throw new ParseException(name.getContent() + " is already defined in this scope", name.getPosition()); + + initializer = parseAssignment(forVar, tokens, variableMap); + variableMap.put(name.getContent(), forVar); + } else initializer = parseExpression(tokens, true, variableMap); + ParserUtil.checkType(tokens.consume(), Token.Type.STATEMENT_END); + Returnable conditional = parseExpression(tokens, true, variableMap); + ParserUtil.checkReturnType(conditional, Returnable.ReturnType.BOOLEAN); + ParserUtil.checkType(tokens.consume(), Token.Type.STATEMENT_END); + + Item incrementer; + Token token = tokens.get(); + if(variableMap.containsKey(token.getContent())) { // Assume variable assignment + Variable variable = variableMap.get(token.getContent()); + incrementer = parseAssignment(variable, tokens, variableMap); + } else incrementer = parseFunction(tokens, true, variableMap); + + ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_END); + + return new ForKeyword(parseStatementBlock(tokens, variableMap, true), initializer, (Returnable) conditional, incrementer, start); + } + + private Returnable parseExpression(Tokenizer tokens, boolean full, Map> variableMap) throws ParseException { + boolean booleanInverted = false; // Check for boolean not operator + boolean negate = false; + if(tokens.get().getType().equals(Token.Type.BOOLEAN_NOT)) { + booleanInverted = true; + tokens.consume(); + } else if(tokens.get().getType().equals(Token.Type.SUBTRACTION_OPERATOR)) { + negate = true; + tokens.consume(); + } + + Token id = tokens.get(); + + ParserUtil.checkType(id, Token.Type.IDENTIFIER, Token.Type.BOOLEAN, Token.Type.STRING, Token.Type.NUMBER, Token.Type.GROUP_BEGIN); + + Returnable expression; + if(id.isConstant()) { + expression = parseConstantExpression(tokens); + } else if(id.getType().equals(Token.Type.GROUP_BEGIN)) { // Parse grouped expression + expression = parseGroup(tokens, variableMap); + } else { + if(functions.containsKey(id.getContent())) + expression = parseFunction(tokens, false, variableMap); + else if(variableMap.containsKey(id.getContent())) { + ParserUtil.checkType(tokens.consume(), Token.Type.IDENTIFIER); + expression = new Getter(variableMap.get(id.getContent())); + } else throw new ParseException("Unexpected token \" " + id.getContent() + "\"", id.getPosition()); + } + + if(booleanInverted) { // Invert operation if boolean not detected + ParserUtil.checkReturnType(expression, Returnable.ReturnType.BOOLEAN); + expression = new BooleanNotOperation((Returnable) expression, expression.getPosition()); + } else if(negate) { + ParserUtil.checkReturnType(expression, Returnable.ReturnType.NUMBER); + expression = new NegationOperation((Returnable) expression, expression.getPosition()); + } + + if(full && tokens.get().isBinaryOperator()) { // Parse binary operations + return parseBinaryOperation(expression, tokens, variableMap); + } + return expression; + } + + private ConstantExpression parseConstantExpression(Tokenizer tokens) throws ParseException { + Token constantToken = tokens.consume(); + Position position = constantToken.getPosition(); + switch(constantToken.getType()) { + case NUMBER: + String content = constantToken.getContent(); + return new NumericConstant(content.contains(".") ? Double.parseDouble(content) : Integer.parseInt(content), position); + case STRING: + return new StringConstant(constantToken.getContent(), position); + case BOOLEAN: + return new BooleanConstant(Boolean.parseBoolean(constantToken.getContent()), position); + default: + throw new UnsupportedOperationException("Unsupported constant token: " + constantToken.getType() + " at position: " + position); + } + } + + private Returnable parseGroup(Tokenizer tokens, Map> variableMap) throws ParseException { + ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_BEGIN); + Returnable expression = parseExpression(tokens, true, variableMap); // Parse inside of group as a separate expression + ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_END); + return expression; + } + + + private BinaryOperation parseBinaryOperation(Returnable left, Tokenizer tokens, Map> variableMap) throws ParseException { + Token binaryOperator = tokens.consume(); + ParserUtil.checkBinaryOperator(binaryOperator); + + Returnable right = parseExpression(tokens, false, variableMap); + + Token other = tokens.get(); + if(ParserUtil.hasPrecedence(binaryOperator.getType(), other.getType())) { + return assemble(left, parseBinaryOperation(right, tokens, variableMap), binaryOperator); + } else if(other.isBinaryOperator()) { + return parseBinaryOperation(assemble(left, right, binaryOperator), tokens, variableMap); + } + return assemble(left, right, binaryOperator); + } + + private BinaryOperation assemble(Returnable left, Returnable right, Token binaryOperator) throws ParseException { + if(binaryOperator.isStrictNumericOperator()) + ParserUtil.checkArithmeticOperation(left, right, binaryOperator); // Numeric type checking + if(binaryOperator.isStrictBooleanOperator()) ParserUtil.checkBooleanOperation(left, right, binaryOperator); // Boolean type checking + switch(binaryOperator.getType()) { + case ADDITION_OPERATOR: + if(left.returnType().equals(Returnable.ReturnType.NUMBER) && right.returnType().equals(Returnable.ReturnType.NUMBER)) { + return new NumberAdditionOperation((Returnable) left, (Returnable) right, binaryOperator.getPosition()); + } + return new ConcatenationOperation((Returnable) left, (Returnable) right, binaryOperator.getPosition()); + case SUBTRACTION_OPERATOR: + return new SubtractionOperation((Returnable) left, (Returnable) right, binaryOperator.getPosition()); + case MULTIPLICATION_OPERATOR: + return new MultiplicationOperation((Returnable) left, (Returnable) right, binaryOperator.getPosition()); + case DIVISION_OPERATOR: + return new DivisionOperation((Returnable) left, (Returnable) right, binaryOperator.getPosition()); + case EQUALS_OPERATOR: + return new EqualsStatement((Returnable) left, (Returnable) right, binaryOperator.getPosition()); + case NOT_EQUALS_OPERATOR: + return new NotEqualsStatement((Returnable) left, (Returnable) right, binaryOperator.getPosition()); + case GREATER_THAN_OPERATOR: + return new GreaterThanStatement((Returnable) left, (Returnable) right, binaryOperator.getPosition()); + case LESS_THAN_OPERATOR: + return new LessThanStatement((Returnable) left, (Returnable) right, binaryOperator.getPosition()); + case GREATER_THAN_OR_EQUALS_OPERATOR: + return new GreaterOrEqualsThanStatement((Returnable) left, (Returnable) right, binaryOperator.getPosition()); + case LESS_THAN_OR_EQUALS_OPERATOR: + return new LessThanOrEqualsStatement((Returnable) left, (Returnable) right, binaryOperator.getPosition()); + case BOOLEAN_AND: + return new BooleanAndOperation((Returnable) left, (Returnable) right, binaryOperator.getPosition()); + case BOOLEAN_OR: + return new BooleanOrOperation((Returnable) left, (Returnable) right, binaryOperator.getPosition()); + case MODULO_OPERATOR: + return new ModuloOperation((Returnable) left, (Returnable) right, binaryOperator.getPosition()); + default: + throw new UnsupportedOperationException("Unsupported binary operator: " + binaryOperator.getType()); + } + } + + private Variable parseVariableDeclaration(Tokenizer tokens, Returnable.ReturnType type) throws ParseException { + ParserUtil.checkVarType(tokens.get(), type); // Check for type mismatch + switch(type) { + case NUMBER: + return new NumberVariable(0d, tokens.get().getPosition()); + case STRING: + return new StringVariable("", tokens.get().getPosition()); + case BOOLEAN: + return new BooleanVariable(false, tokens.get().getPosition()); + } + throw new UnsupportedOperationException("Unsupported variable type: " + type); + } + + private Block parseBlock(Tokenizer tokens, Map> superVars, boolean loop) throws ParseException { + List> parsedItems = new GlueList<>(); + + Map> parsedVariables = new HashMap<>(superVars); // New hashmap as to not mutate parent scope's declarations. + + Token first = tokens.get(); + + while(tokens.hasNext()) { + Token token = tokens.get(); + if(token.getType().equals(Token.Type.BLOCK_END)) break; // Stop parsing at block end. + parsedItems.add(parseItem(tokens, parsedVariables, loop)); + if(tokens.hasNext() && !token.isLoopLike()) ParserUtil.checkType(tokens.consume(), Token.Type.STATEMENT_END); + } + return new Block(parsedItems, first.getPosition()); + } + + private Item parseItem(Tokenizer tokens, Map> variableMap, boolean loop) throws ParseException { + Token token = tokens.get(); + if(loop) ParserUtil.checkType(token, Token.Type.IDENTIFIER, Token.Type.IF_STATEMENT, Token.Type.WHILE_LOOP, Token.Type.FOR_LOOP, + Token.Type.NUMBER_VARIABLE, Token.Type.STRING_VARIABLE, Token.Type.BOOLEAN_VARIABLE, Token.Type.RETURN, Token.Type.BREAK, Token.Type.CONTINUE, Token.Type.FAIL); + else ParserUtil.checkType(token, Token.Type.IDENTIFIER, Token.Type.IF_STATEMENT, Token.Type.WHILE_LOOP, Token.Type.FOR_LOOP, + Token.Type.NUMBER_VARIABLE, Token.Type.STRING_VARIABLE, Token.Type.BOOLEAN_VARIABLE, Token.Type.RETURN, Token.Type.FAIL); + + if(token.isLoopLike()) { // Parse loop-like tokens (if, while, etc) + return parseLoopLike(tokens, variableMap, loop); + } else if(token.isIdentifier()) { // Parse identifiers + if(variableMap.containsKey(token.getContent())) { // Assume variable assignment + Variable variable = variableMap.get(token.getContent()); + return parseAssignment(variable, tokens, variableMap); + } else return parseFunction(tokens, true, variableMap); + } else if(token.isVariableDeclaration()) { + Variable temp = parseVariableDeclaration(tokens, ParserUtil.getVariableReturnType(token)); + + ParserUtil.checkType(tokens.consume(), Token.Type.STRING_VARIABLE, Token.Type.BOOLEAN_VARIABLE, Token.Type.NUMBER_VARIABLE); + Token name = tokens.get(); + ParserUtil.checkType(name, Token.Type.IDENTIFIER); // Name must be an identifier. + + if(functions.containsKey(name.getContent()) || variableMap.containsKey(name.getContent())) + throw new ParseException(name.getContent() + " is already defined in this scope", name.getPosition()); + + variableMap.put(name.getContent(), temp); + + + return parseAssignment(temp, tokens, variableMap); + } else if(token.getType().equals(Token.Type.RETURN)) return new ReturnKeyword(tokens.consume().getPosition()); + else if(token.getType().equals(Token.Type.BREAK)) return new BreakKeyword(tokens.consume().getPosition()); + else if(token.getType().equals(Token.Type.CONTINUE)) return new ContinueKeyword(tokens.consume().getPosition()); + else if(token.getType().equals(Token.Type.FAIL)) return new FailKeyword(tokens.consume().getPosition()); + else throw new UnsupportedOperationException("Unexpected token " + token.getType() + ": " + token.getPosition()); + } + + private Assignment parseAssignment(Variable variable, Tokenizer tokens, Map> variableMap) throws ParseException { + Token name = tokens.get(); + + ParserUtil.checkType(tokens.consume(), Token.Type.IDENTIFIER); + + ParserUtil.checkType(tokens.consume(), Token.Type.ASSIGNMENT); + + Returnable expression = parseExpression(tokens, true, variableMap); + + ParserUtil.checkReturnType(expression, variable.getType()); + + return new Assignment<>((Variable) variable, (Returnable) expression, name.getPosition()); + } + + private Function parseFunction(Tokenizer tokens, boolean fullStatement, Map> variableMap) throws ParseException { + Token identifier = tokens.consume(); + ParserUtil.checkType(identifier, Token.Type.IDENTIFIER); // First token must be identifier + + if(!functions.containsKey(identifier.getContent())) + throw new ParseException("No such function \"" + identifier.getContent() + "\"", identifier.getPosition()); + + ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_BEGIN); // Second is body begin + + + List> args = getArgs(tokens, variableMap); // Extract arguments, consume the rest. + + ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_END); // Remove body end + + if(fullStatement) ParserUtil.checkType(tokens.get(), Token.Type.STATEMENT_END); + + if(functions.containsKey(identifier.getContent())) { + FunctionBuilder builder = functions.get(identifier.getContent()); + + if(builder.argNumber() != -1 && args.size() != builder.argNumber()) + throw new ParseException("Expected " + builder.argNumber() + " arguments, found " + args.size(), identifier.getPosition()); + + for(int i = 0; i < args.size(); i++) { + Returnable argument = args.get(i); + if(builder.getArgument(i) == null) + throw new ParseException("Unexpected argument at position " + i + " in function " + identifier.getContent(), identifier.getPosition()); + ParserUtil.checkReturnType(argument, builder.getArgument(i)); + } + return builder.build(args, identifier.getPosition()); + } + throw new UnsupportedOperationException("Unsupported function: " + identifier.getContent()); + } + + + private List> getArgs(Tokenizer tokens, Map> variableMap) throws ParseException { + List> args = new GlueList<>(); + + while(!tokens.get().getType().equals(Token.Type.GROUP_END)) { + args.add(parseExpression(tokens, true, variableMap)); + ParserUtil.checkType(tokens.get(), Token.Type.SEPARATOR, Token.Type.GROUP_END); + if(tokens.get().getType().equals(Token.Type.SEPARATOR)) tokens.consume(); + } + return args; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/ParserUtil.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/ParserUtil.java new file mode 100644 index 000000000..724ac9099 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/ParserUtil.java @@ -0,0 +1,100 @@ +package com.dfsek.terra.api.structures.parser; + +import com.dfsek.terra.api.structures.parser.exceptions.ParseException; +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.tokenizer.Token; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class ParserUtil { + + private static final Map> PRECEDENCE = new HashMap<>(); // If second has precedence, true. + private static final List ARITHMETIC = Arrays.asList(Token.Type.ADDITION_OPERATOR, Token.Type.SUBTRACTION_OPERATOR, Token.Type.MULTIPLICATION_OPERATOR, Token.Type.DIVISION_OPERATOR, Token.Type.MODULO_OPERATOR); + private static final List COMPARISON = Arrays.asList(Token.Type.EQUALS_OPERATOR, Token.Type.NOT_EQUALS_OPERATOR, Token.Type.LESS_THAN_OPERATOR, Token.Type.LESS_THAN_OR_EQUALS_OPERATOR, Token.Type.GREATER_THAN_OPERATOR, Token.Type.GREATER_THAN_OR_EQUALS_OPERATOR); + + static { // Setup precedence + Map add = new HashMap<>(); // Addition/subtraction before Multiplication/division. + add.put(Token.Type.MULTIPLICATION_OPERATOR, true); + add.put(Token.Type.DIVISION_OPERATOR, true); + + PRECEDENCE.put(Token.Type.ADDITION_OPERATOR, add); + PRECEDENCE.put(Token.Type.SUBTRACTION_OPERATOR, add); + + Map numericBoolean = new HashMap<>(); + + ARITHMETIC.forEach(op -> numericBoolean.put(op, true)); // Numbers before comparison + COMPARISON.forEach(op -> PRECEDENCE.put(op, numericBoolean)); + + + Map booleanOps = new HashMap<>(); + ARITHMETIC.forEach(op -> booleanOps.put(op, true)); // Everything before boolean + COMPARISON.forEach(op -> booleanOps.put(op, true)); + + + PRECEDENCE.put(Token.Type.BOOLEAN_AND, booleanOps); + PRECEDENCE.put(Token.Type.BOOLEAN_OR, booleanOps); + } + + public static void checkType(Token token, Token.Type... expected) throws ParseException { + for(Token.Type type : expected) if(token.getType().equals(type)) return; + throw new ParseException("Expected " + Arrays.toString(expected) + " but found " + token.getType(), token.getPosition()); + } + + public static void checkReturnType(Returnable returnable, Returnable.ReturnType... types) throws ParseException { + for(Returnable.ReturnType type : types) if(returnable.returnType().equals(type)) return; + throw new ParseException("Expected " + Arrays.toString(types) + " but found " + returnable.returnType(), returnable.getPosition()); + } + + public static void checkArithmeticOperation(Returnable left, Returnable right, Token operation) throws ParseException { + if(!left.returnType().equals(Returnable.ReturnType.NUMBER) || !right.returnType().equals(Returnable.ReturnType.NUMBER)) { + throw new ParseException("Operation " + operation.getType() + " not supported between " + left.returnType() + " and " + right.returnType(), operation.getPosition()); + } + } + + public static void checkBooleanOperation(Returnable left, Returnable right, Token operation) throws ParseException { + if(!left.returnType().equals(Returnable.ReturnType.BOOLEAN) || !right.returnType().equals(Returnable.ReturnType.BOOLEAN)) { + throw new ParseException("Operation " + operation.getType() + " not supported between " + left.returnType() + " and " + right.returnType(), operation.getPosition()); + } + } + + public static void checkVarType(Token token, Returnable.ReturnType returnType) throws ParseException { + if(returnType.equals(Returnable.ReturnType.STRING) && token.getType().equals(Token.Type.STRING_VARIABLE)) return; + if(returnType.equals(Returnable.ReturnType.NUMBER) && token.getType().equals(Token.Type.NUMBER_VARIABLE)) return; + if(returnType.equals(Returnable.ReturnType.BOOLEAN) && token.getType().equals(Token.Type.BOOLEAN_VARIABLE)) return; + throw new ParseException("Type mismatch, cannot convert from " + returnType + " to " + token.getType(), token.getPosition()); + } + + /** + * Checks if token is a binary operator + * + * @param token Token to check + * @throws ParseException If token isn't a binary operator + */ + public static void checkBinaryOperator(Token token) throws ParseException { + if(!token.isBinaryOperator()) + throw new ParseException("Expected binary operator, found " + token.getType(), token.getPosition()); + } + + public static Returnable.ReturnType getVariableReturnType(Token varToken) throws ParseException { + switch(varToken.getType()) { + case NUMBER_VARIABLE: + return Returnable.ReturnType.NUMBER; + case STRING_VARIABLE: + return Returnable.ReturnType.STRING; + case BOOLEAN_VARIABLE: + return Returnable.ReturnType.BOOLEAN; + default: + throw new ParseException("Unexpected token " + varToken.getType() + "; expected variable declaration", varToken.getPosition()); + } + } + + public static boolean hasPrecedence(Token.Type first, Token.Type second) { + if(!PRECEDENCE.containsKey(first)) return false; + Map pre = PRECEDENCE.get(first); + if(!pre.containsKey(second)) return false; + return pre.get(second); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/exceptions/ParseException.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/exceptions/ParseException.java new file mode 100644 index 000000000..df833972f --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/exceptions/ParseException.java @@ -0,0 +1,26 @@ +package com.dfsek.terra.api.structures.parser.exceptions; + +import com.dfsek.terra.api.structures.tokenizer.Position; + +public class ParseException extends Exception { + private final Position position; + + public ParseException(String message, Position position) { + super(message); + this.position = position; + } + + public ParseException(String message, Position position, Throwable cause) { + super(message, cause); + this.position = position; + } + + @Override + public String getMessage() { + return super.getMessage() + ": " + position; + } + + public Position getPosition() { + return position; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/Block.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/Block.java new file mode 100644 index 000000000..e709a0a73 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/Block.java @@ -0,0 +1,68 @@ +package com.dfsek.terra.api.structures.parser.lang; + +import com.dfsek.terra.api.structures.tokenizer.Position; + +import java.util.List; + +public class Block implements Item> { + private final List> items; + private final Position position; + + public Block(List> items, Position position) { + this.items = items; + this.position = position; + } + + public List> getItems() { + return items; + } + + @Override + public synchronized ReturnInfo apply(ImplementationArguments implementationArguments) { + for(Item item : items) { + Object result = item.apply(implementationArguments); + if(result instanceof ReturnInfo) { + ReturnInfo level = (ReturnInfo) result; + if(!level.getLevel().equals(ReturnLevel.NONE)) return level; + } + } + return new ReturnInfo<>(ReturnLevel.NONE, null); + } + + @Override + public Position getPosition() { + return position; + } + + public static class ReturnInfo { + private final ReturnLevel level; + private final T data; + + public ReturnInfo(ReturnLevel level, T data) { + this.level = level; + this.data = data; + } + + public ReturnLevel getLevel() { + return level; + } + + public T getData() { + return data; + } + } + + public enum ReturnLevel { + NONE(false), BREAK(false), CONTINUE(false), RETURN(true), FAIL(true); + + private final boolean returnFast; + + ReturnLevel(boolean returnFast) { + this.returnFast = returnFast; + } + + public boolean isReturnFast() { + return returnFast; + } + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/ImplementationArguments.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/ImplementationArguments.java new file mode 100644 index 000000000..cd71207a2 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/ImplementationArguments.java @@ -0,0 +1,7 @@ +package com.dfsek.terra.api.structures.parser.lang; + +/** + * Arguments passed to {@link Item}s by the implementation + */ +public interface ImplementationArguments { +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/Item.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/Item.java new file mode 100644 index 000000000..f8b714d87 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/Item.java @@ -0,0 +1,9 @@ +package com.dfsek.terra.api.structures.parser.lang; + +import com.dfsek.terra.api.structures.tokenizer.Position; + +public interface Item { + T apply(ImplementationArguments implementationArguments); + + Position getPosition(); +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/Keyword.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/Keyword.java new file mode 100644 index 000000000..be0a9f085 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/Keyword.java @@ -0,0 +1,4 @@ +package com.dfsek.terra.api.structures.parser.lang; + +public interface Keyword extends Returnable { +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/Returnable.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/Returnable.java new file mode 100644 index 000000000..3d02ae4cb --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/Returnable.java @@ -0,0 +1,19 @@ +package com.dfsek.terra.api.structures.parser.lang; + +public interface Returnable extends Item { + ReturnType returnType(); + + enum ReturnType { + NUMBER(true), STRING(true), BOOLEAN(false), VOID(false), OBJECT(false); + + private final boolean comparable; + + ReturnType(boolean comparable) { + this.comparable = comparable; + } + + public boolean isComparable() { + return comparable; + } + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/Statement.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/Statement.java new file mode 100644 index 000000000..f268f4592 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/Statement.java @@ -0,0 +1,4 @@ +package com.dfsek.terra.api.structures.parser.lang; + +public interface Statement extends Item { +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/constants/BooleanConstant.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/constants/BooleanConstant.java new file mode 100644 index 000000000..7d57f561f --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/constants/BooleanConstant.java @@ -0,0 +1,14 @@ +package com.dfsek.terra.api.structures.parser.lang.constants; + +import com.dfsek.terra.api.structures.tokenizer.Position; + +public class BooleanConstant extends ConstantExpression { + public BooleanConstant(Boolean constant, Position position) { + super(constant, position); + } + + @Override + public ReturnType returnType() { + return ReturnType.BOOLEAN; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/constants/ConstantExpression.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/constants/ConstantExpression.java new file mode 100644 index 000000000..730270f5e --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/constants/ConstantExpression.java @@ -0,0 +1,29 @@ +package com.dfsek.terra.api.structures.parser.lang.constants; + +import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.tokenizer.Position; + +public abstract class ConstantExpression implements Returnable { + private final T constant; + private final Position position; + + public ConstantExpression(T constant, Position position) { + this.constant = constant; + this.position = position; + } + + @Override + public T apply(ImplementationArguments implementationArguments) { + return constant; + } + + @Override + public Position getPosition() { + return position; + } + + public T getConstant() { + return constant; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/constants/NumericConstant.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/constants/NumericConstant.java new file mode 100644 index 000000000..caf68836e --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/constants/NumericConstant.java @@ -0,0 +1,14 @@ +package com.dfsek.terra.api.structures.parser.lang.constants; + +import com.dfsek.terra.api.structures.tokenizer.Position; + +public class NumericConstant extends ConstantExpression { + public NumericConstant(Number constant, Position position) { + super(constant, position); + } + + @Override + public ReturnType returnType() { + return ReturnType.NUMBER; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/constants/StringConstant.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/constants/StringConstant.java new file mode 100644 index 000000000..19a93353f --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/constants/StringConstant.java @@ -0,0 +1,14 @@ +package com.dfsek.terra.api.structures.parser.lang.constants; + +import com.dfsek.terra.api.structures.tokenizer.Position; + +public class StringConstant extends ConstantExpression { + public StringConstant(String constant, Position position) { + super(constant, position); + } + + @Override + public ReturnType returnType() { + return ReturnType.STRING; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/functions/Function.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/functions/Function.java new file mode 100644 index 000000000..aaa826d12 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/functions/Function.java @@ -0,0 +1,6 @@ +package com.dfsek.terra.api.structures.parser.lang.functions; + +import com.dfsek.terra.api.structures.parser.lang.Returnable; + +public interface Function extends Returnable { +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/functions/FunctionBuilder.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/functions/FunctionBuilder.java new file mode 100644 index 000000000..7d1cbe4ba --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/functions/FunctionBuilder.java @@ -0,0 +1,15 @@ +package com.dfsek.terra.api.structures.parser.lang.functions; + +import com.dfsek.terra.api.structures.parser.exceptions.ParseException; +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.tokenizer.Position; + +import java.util.List; + +public interface FunctionBuilder> { + T build(List> argumentList, Position position) throws ParseException; + + int argNumber(); + + Returnable.ReturnType getArgument(int position); +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/functions/def/DefinedFunction.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/functions/def/DefinedFunction.java new file mode 100644 index 000000000..cfecc9f98 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/functions/def/DefinedFunction.java @@ -0,0 +1,27 @@ +package com.dfsek.terra.api.structures.parser.lang.functions.def; + +import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; +import com.dfsek.terra.api.structures.parser.lang.functions.Function; +import com.dfsek.terra.api.structures.tokenizer.Position; + +public abstract class DefinedFunction implements Function { + private final FunctionBlock block; + private final String name; + private final Position position; + + protected DefinedFunction(FunctionBlock block, String name, Position position) { + this.block = block; + this.name = name; + this.position = position; + } + + @Override + public T apply(ImplementationArguments implementationArguments) { + return block.apply(implementationArguments); + } + + @Override + public Position getPosition() { + return position; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/functions/def/FunctionBlock.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/functions/def/FunctionBlock.java new file mode 100644 index 000000000..0bf74c60c --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/functions/def/FunctionBlock.java @@ -0,0 +1,42 @@ +package com.dfsek.terra.api.structures.parser.lang.functions.def; + +import com.dfsek.terra.api.structures.parser.lang.Block; +import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; +import com.dfsek.terra.api.structures.parser.lang.Item; +import com.dfsek.terra.api.structures.tokenizer.Position; + +import java.util.List; + +public class FunctionBlock implements Item { + private final List> items; + private final Position position; + private final T defaultVal; + + public FunctionBlock(List> items, T defaultVal, Position position) { + this.items = items; + this.position = position; + this.defaultVal = defaultVal; + } + + public List> getItems() { + return items; + } + + @SuppressWarnings("unchecked") + @Override + public synchronized T apply(ImplementationArguments implementationArguments) { + for(Item item : items) { + Object result = item.apply(implementationArguments); + if(result instanceof Block.ReturnInfo) { + Block.ReturnInfo level = (Block.ReturnInfo) result; + if(level.getLevel().equals(Block.ReturnLevel.RETURN)) return level.getData(); + } + } + return defaultVal; + } + + @Override + public Position getPosition() { + return position; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/flow/BreakKeyword.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/flow/BreakKeyword.java new file mode 100644 index 000000000..04068f356 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/flow/BreakKeyword.java @@ -0,0 +1,29 @@ +package com.dfsek.terra.api.structures.parser.lang.keywords.flow; + +import com.dfsek.terra.api.structures.parser.lang.Block; +import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; +import com.dfsek.terra.api.structures.parser.lang.Keyword; +import com.dfsek.terra.api.structures.tokenizer.Position; + +public class BreakKeyword implements Keyword> { + private final Position position; + + public BreakKeyword(Position position) { + this.position = position; + } + + @Override + public Block.ReturnInfo apply(ImplementationArguments implementationArguments) { + return new Block.ReturnInfo<>(Block.ReturnLevel.BREAK, null); + } + + @Override + public Position getPosition() { + return position; + } + + @Override + public ReturnType returnType() { + return ReturnType.VOID; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/flow/ContinueKeyword.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/flow/ContinueKeyword.java new file mode 100644 index 000000000..fc345a9fd --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/flow/ContinueKeyword.java @@ -0,0 +1,29 @@ +package com.dfsek.terra.api.structures.parser.lang.keywords.flow; + +import com.dfsek.terra.api.structures.parser.lang.Block; +import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; +import com.dfsek.terra.api.structures.parser.lang.Keyword; +import com.dfsek.terra.api.structures.tokenizer.Position; + +public class ContinueKeyword implements Keyword> { + private final Position position; + + public ContinueKeyword(Position position) { + this.position = position; + } + + @Override + public Block.ReturnInfo apply(ImplementationArguments implementationArguments) { + return new Block.ReturnInfo<>(Block.ReturnLevel.CONTINUE, null); + } + + @Override + public Position getPosition() { + return position; + } + + @Override + public ReturnType returnType() { + return ReturnType.VOID; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/flow/FailKeyword.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/flow/FailKeyword.java new file mode 100644 index 000000000..0b08a04e4 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/flow/FailKeyword.java @@ -0,0 +1,29 @@ +package com.dfsek.terra.api.structures.parser.lang.keywords.flow; + +import com.dfsek.terra.api.structures.parser.lang.Block; +import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; +import com.dfsek.terra.api.structures.parser.lang.Keyword; +import com.dfsek.terra.api.structures.tokenizer.Position; + +public class FailKeyword implements Keyword> { + private final Position position; + + public FailKeyword(Position position) { + this.position = position; + } + + @Override + public Block.ReturnInfo apply(ImplementationArguments implementationArguments) { + return new Block.ReturnInfo<>(Block.ReturnLevel.FAIL, null); + } + + @Override + public Position getPosition() { + return position; + } + + @Override + public ReturnType returnType() { + return ReturnType.VOID; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/flow/ReturnKeyword.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/flow/ReturnKeyword.java new file mode 100644 index 000000000..3895cdfc5 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/flow/ReturnKeyword.java @@ -0,0 +1,29 @@ +package com.dfsek.terra.api.structures.parser.lang.keywords.flow; + +import com.dfsek.terra.api.structures.parser.lang.Block; +import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; +import com.dfsek.terra.api.structures.parser.lang.Keyword; +import com.dfsek.terra.api.structures.tokenizer.Position; + +public class ReturnKeyword implements Keyword> { + private final Position position; + + public ReturnKeyword(Position position) { + this.position = position; + } + + @Override + public Block.ReturnInfo apply(ImplementationArguments implementationArguments) { + return new Block.ReturnInfo<>(Block.ReturnLevel.RETURN, null); + } + + @Override + public Position getPosition() { + return position; + } + + @Override + public ReturnType returnType() { + return ReturnType.VOID; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/looplike/ForKeyword.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/looplike/ForKeyword.java new file mode 100644 index 000000000..10d33e25b --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/looplike/ForKeyword.java @@ -0,0 +1,44 @@ +package com.dfsek.terra.api.structures.parser.lang.keywords.looplike; + +import com.dfsek.terra.api.structures.parser.lang.Block; +import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; +import com.dfsek.terra.api.structures.parser.lang.Item; +import com.dfsek.terra.api.structures.parser.lang.Keyword; +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.tokenizer.Position; + +public class ForKeyword implements Keyword> { + private final Block conditional; + private final Item initializer; + private final Returnable statement; + private final Item incrementer; + private final Position position; + + public ForKeyword(Block conditional, Item initializer, Returnable statement, Item incrementer, Position position) { + this.conditional = conditional; + this.initializer = initializer; + this.statement = statement; + this.incrementer = incrementer; + this.position = position; + } + + @Override + public Block.ReturnInfo apply(ImplementationArguments implementationArguments) { + for(initializer.apply(implementationArguments); statement.apply(implementationArguments); incrementer.apply(implementationArguments)) { + Block.ReturnInfo level = conditional.apply(implementationArguments); + if(level.getLevel().equals(Block.ReturnLevel.BREAK)) break; + if(level.getLevel().isReturnFast()) return level; + } + return new Block.ReturnInfo<>(Block.ReturnLevel.NONE, null); + } + + @Override + public Position getPosition() { + return position; + } + + @Override + public ReturnType returnType() { + return ReturnType.VOID; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/looplike/IfKeyword.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/looplike/IfKeyword.java new file mode 100644 index 000000000..b6e0845f6 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/looplike/IfKeyword.java @@ -0,0 +1,69 @@ +package com.dfsek.terra.api.structures.parser.lang.keywords.looplike; + +import com.dfsek.terra.api.structures.parser.lang.Block; +import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; +import com.dfsek.terra.api.structures.parser.lang.Keyword; +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.tokenizer.Position; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +public class IfKeyword implements Keyword> { + private final Block conditional; + private final Returnable statement; + private final Position position; + private final List, Block>> elseIf; + private final Block elseBlock; + + public IfKeyword(Block conditional, Returnable statement, List, Block>> elseIf, @Nullable Block elseBlock, Position position) { + this.conditional = conditional; + this.statement = statement; + this.position = position; + this.elseIf = elseIf; + this.elseBlock = elseBlock; + } + + @Override + public Block.ReturnInfo apply(ImplementationArguments implementationArguments) { + if(statement.apply(implementationArguments)) return conditional.apply(implementationArguments); + else { + for(Pair, Block> pair : elseIf) { + if(pair.getLeft().apply(implementationArguments)) { + return pair.getRight().apply(implementationArguments); + } + } + if(elseBlock != null) return elseBlock.apply(implementationArguments); + } + return new Block.ReturnInfo<>(Block.ReturnLevel.NONE, null); + } + + + @Override + public Position getPosition() { + return position; + } + + @Override + public ReturnType returnType() { + return ReturnType.VOID; + } + + public static class Pair { + private final L left; + private final R right; + + public Pair(L left, R right) { + this.left = left; + this.right = right; + } + + public L getLeft() { + return left; + } + + public R getRight() { + return right; + } + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/looplike/WhileKeyword.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/looplike/WhileKeyword.java new file mode 100644 index 000000000..72029f7e2 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/looplike/WhileKeyword.java @@ -0,0 +1,39 @@ +package com.dfsek.terra.api.structures.parser.lang.keywords.looplike; + +import com.dfsek.terra.api.structures.parser.lang.Block; +import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; +import com.dfsek.terra.api.structures.parser.lang.Keyword; +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.tokenizer.Position; + +public class WhileKeyword implements Keyword> { + private final Block conditional; + private final Returnable statement; + private final Position position; + + public WhileKeyword(Block conditional, Returnable statement, Position position) { + this.conditional = conditional; + this.statement = statement; + this.position = position; + } + + @Override + public Block.ReturnInfo apply(ImplementationArguments implementationArguments) { + while(statement.apply(implementationArguments)) { + Block.ReturnInfo level = conditional.apply(implementationArguments); + if(level.getLevel().equals(Block.ReturnLevel.BREAK)) break; + if(level.getLevel().isReturnFast()) return level; + } + return new Block.ReturnInfo<>(Block.ReturnLevel.NONE, null); + } + + @Override + public Position getPosition() { + return position; + } + + @Override + public ReturnType returnType() { + return ReturnType.VOID; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/BinaryOperation.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/BinaryOperation.java new file mode 100644 index 000000000..6d35d49b2 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/BinaryOperation.java @@ -0,0 +1,29 @@ +package com.dfsek.terra.api.structures.parser.lang.operations; + +import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.tokenizer.Position; + +public abstract class BinaryOperation implements Returnable { + private final Returnable left; + private final Returnable right; + private final Position start; + + public BinaryOperation(Returnable left, Returnable right, Position start) { + this.left = left; + this.right = right; + this.start = start; + } + + public abstract O apply(I left, I right); + + @Override + public Position getPosition() { + return start; + } + + @Override + public O apply(ImplementationArguments implementationArguments) { + return apply(left.apply(implementationArguments), right.apply(implementationArguments)); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/BooleanAndOperation.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/BooleanAndOperation.java new file mode 100644 index 000000000..3bca80717 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/BooleanAndOperation.java @@ -0,0 +1,20 @@ +package com.dfsek.terra.api.structures.parser.lang.operations; + +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.tokenizer.Position; + +public class BooleanAndOperation extends BinaryOperation { + public BooleanAndOperation(Returnable left, Returnable right, Position start) { + super(left, right, start); + } + + @Override + public Boolean apply(Boolean left, Boolean right) { + return left && right; + } + + @Override + public ReturnType returnType() { + return ReturnType.BOOLEAN; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/BooleanNotOperation.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/BooleanNotOperation.java new file mode 100644 index 000000000..ebf59abd2 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/BooleanNotOperation.java @@ -0,0 +1,20 @@ +package com.dfsek.terra.api.structures.parser.lang.operations; + +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.tokenizer.Position; + +public class BooleanNotOperation extends UnaryOperation { + public BooleanNotOperation(Returnable input, Position position) { + super(input, position); + } + + @Override + public Boolean apply(Boolean input) { + return !input; + } + + @Override + public ReturnType returnType() { + return ReturnType.BOOLEAN; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/BooleanOrOperation.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/BooleanOrOperation.java new file mode 100644 index 000000000..513c35be5 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/BooleanOrOperation.java @@ -0,0 +1,20 @@ +package com.dfsek.terra.api.structures.parser.lang.operations; + +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.tokenizer.Position; + +public class BooleanOrOperation extends BinaryOperation { + public BooleanOrOperation(Returnable left, Returnable right, Position start) { + super(left, right, start); + } + + @Override + public Boolean apply(Boolean left, Boolean right) { + return left || right; + } + + @Override + public ReturnType returnType() { + return ReturnType.BOOLEAN; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/ConcatenationOperation.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/ConcatenationOperation.java new file mode 100644 index 000000000..b0eea6f50 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/ConcatenationOperation.java @@ -0,0 +1,20 @@ +package com.dfsek.terra.api.structures.parser.lang.operations; + +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.tokenizer.Position; + +public class ConcatenationOperation extends BinaryOperation { + public ConcatenationOperation(Returnable left, Returnable right, Position position) { + super(left, right, position); + } + + @Override + public String apply(Object left, Object right) { + return left.toString() + right.toString(); + } + + @Override + public ReturnType returnType() { + return ReturnType.STRING; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/DivisionOperation.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/DivisionOperation.java new file mode 100644 index 000000000..3054f8981 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/DivisionOperation.java @@ -0,0 +1,20 @@ +package com.dfsek.terra.api.structures.parser.lang.operations; + +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.tokenizer.Position; + +public class DivisionOperation extends BinaryOperation { + public DivisionOperation(Returnable left, Returnable right, Position position) { + super(left, right, position); + } + + @Override + public Number apply(Number left, Number right) { + return left.doubleValue() / right.doubleValue(); + } + + @Override + public ReturnType returnType() { + return ReturnType.NUMBER; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/ModuloOperation.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/ModuloOperation.java new file mode 100644 index 000000000..44ef9a7d1 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/ModuloOperation.java @@ -0,0 +1,20 @@ +package com.dfsek.terra.api.structures.parser.lang.operations; + +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.tokenizer.Position; + +public class ModuloOperation extends BinaryOperation { + public ModuloOperation(Returnable left, Returnable right, Position start) { + super(left, right, start); + } + + @Override + public Number apply(Number left, Number right) { + return left.doubleValue() % right.doubleValue(); + } + + @Override + public ReturnType returnType() { + return ReturnType.NUMBER; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/MultiplicationOperation.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/MultiplicationOperation.java new file mode 100644 index 000000000..b6269a6c7 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/MultiplicationOperation.java @@ -0,0 +1,20 @@ +package com.dfsek.terra.api.structures.parser.lang.operations; + +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.tokenizer.Position; + +public class MultiplicationOperation extends BinaryOperation { + public MultiplicationOperation(Returnable left, Returnable right, Position position) { + super(left, right, position); + } + + @Override + public Number apply(Number left, Number right) { + return left.doubleValue() * right.doubleValue(); + } + + @Override + public ReturnType returnType() { + return ReturnType.NUMBER; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/NegationOperation.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/NegationOperation.java new file mode 100644 index 000000000..cf4b01de7 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/NegationOperation.java @@ -0,0 +1,20 @@ +package com.dfsek.terra.api.structures.parser.lang.operations; + +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.tokenizer.Position; + +public class NegationOperation extends UnaryOperation { + public NegationOperation(Returnable input, Position position) { + super(input, position); + } + + @Override + public Number apply(Number input) { + return -input.doubleValue(); + } + + @Override + public ReturnType returnType() { + return ReturnType.NUMBER; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/NumberAdditionOperation.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/NumberAdditionOperation.java new file mode 100644 index 000000000..969d13b5e --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/NumberAdditionOperation.java @@ -0,0 +1,20 @@ +package com.dfsek.terra.api.structures.parser.lang.operations; + +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.tokenizer.Position; + +public class NumberAdditionOperation extends BinaryOperation { + public NumberAdditionOperation(Returnable left, Returnable right, Position position) { + super(left, right, position); + } + + @Override + public Number apply(Number left, Number right) { + return left.doubleValue() + right.doubleValue(); + } + + @Override + public ReturnType returnType() { + return ReturnType.NUMBER; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/SubtractionOperation.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/SubtractionOperation.java new file mode 100644 index 000000000..d2bc82203 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/SubtractionOperation.java @@ -0,0 +1,20 @@ +package com.dfsek.terra.api.structures.parser.lang.operations; + +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.tokenizer.Position; + +public class SubtractionOperation extends BinaryOperation { + public SubtractionOperation(Returnable left, Returnable right, Position position) { + super(left, right, position); + } + + @Override + public Number apply(Number left, Number right) { + return left.doubleValue() - right.doubleValue(); + } + + @Override + public ReturnType returnType() { + return ReturnType.NUMBER; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/UnaryOperation.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/UnaryOperation.java new file mode 100644 index 000000000..312975fdd --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/UnaryOperation.java @@ -0,0 +1,27 @@ +package com.dfsek.terra.api.structures.parser.lang.operations; + +import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.tokenizer.Position; + +public abstract class UnaryOperation implements Returnable { + private final Returnable input; + private final Position position; + + public UnaryOperation(Returnable input, Position position) { + this.input = input; + this.position = position; + } + + public abstract T apply(T input); + + @Override + public T apply(ImplementationArguments implementationArguments) { + return apply(input.apply(implementationArguments)); + } + + @Override + public Position getPosition() { + return position; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/statements/EqualsStatement.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/statements/EqualsStatement.java new file mode 100644 index 000000000..b7dface16 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/statements/EqualsStatement.java @@ -0,0 +1,29 @@ +package com.dfsek.terra.api.structures.parser.lang.operations.statements; + +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.parser.lang.operations.BinaryOperation; +import com.dfsek.terra.api.structures.tokenizer.Position; +import net.jafama.FastMath; + +public class EqualsStatement extends BinaryOperation { + private static final double EPSILON = 0.000000001D; + + public EqualsStatement(Returnable left, Returnable right, Position position) { + super(left, right, position); + } + + @Override + public Boolean apply(Object left, Object right) { + if(left instanceof Number && right instanceof Number) { + return FastMath.abs(((Number) left).doubleValue() - ((Number) right).doubleValue()) <= EPSILON; + } + + return left.equals(right); + } + + + @Override + public ReturnType returnType() { + return ReturnType.BOOLEAN; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/statements/GreaterOrEqualsThanStatement.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/statements/GreaterOrEqualsThanStatement.java new file mode 100644 index 000000000..36b1ab446 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/statements/GreaterOrEqualsThanStatement.java @@ -0,0 +1,22 @@ +package com.dfsek.terra.api.structures.parser.lang.operations.statements; + +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.parser.lang.operations.BinaryOperation; +import com.dfsek.terra.api.structures.tokenizer.Position; + +public class GreaterOrEqualsThanStatement extends BinaryOperation { + public GreaterOrEqualsThanStatement(Returnable left, Returnable right, Position position) { + super(left, right, position); + } + + @Override + public Boolean apply(Number left, Number right) { + return left.doubleValue() >= right.doubleValue(); + } + + + @Override + public ReturnType returnType() { + return ReturnType.BOOLEAN; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/statements/GreaterThanStatement.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/statements/GreaterThanStatement.java new file mode 100644 index 000000000..c9a12357b --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/statements/GreaterThanStatement.java @@ -0,0 +1,22 @@ +package com.dfsek.terra.api.structures.parser.lang.operations.statements; + +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.parser.lang.operations.BinaryOperation; +import com.dfsek.terra.api.structures.tokenizer.Position; + +public class GreaterThanStatement extends BinaryOperation { + public GreaterThanStatement(Returnable left, Returnable right, Position position) { + super(left, right, position); + } + + @Override + public Boolean apply(Number left, Number right) { + return left.doubleValue() > right.doubleValue(); + } + + + @Override + public ReturnType returnType() { + return ReturnType.BOOLEAN; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/statements/LessThanOrEqualsStatement.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/statements/LessThanOrEqualsStatement.java new file mode 100644 index 000000000..6904acb62 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/statements/LessThanOrEqualsStatement.java @@ -0,0 +1,22 @@ +package com.dfsek.terra.api.structures.parser.lang.operations.statements; + +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.parser.lang.operations.BinaryOperation; +import com.dfsek.terra.api.structures.tokenizer.Position; + +public class LessThanOrEqualsStatement extends BinaryOperation { + public LessThanOrEqualsStatement(Returnable left, Returnable right, Position position) { + super(left, right, position); + } + + @Override + public Boolean apply(Number left, Number right) { + return left.doubleValue() <= right.doubleValue(); + } + + + @Override + public ReturnType returnType() { + return ReturnType.BOOLEAN; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/statements/LessThanStatement.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/statements/LessThanStatement.java new file mode 100644 index 000000000..03fff20c1 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/statements/LessThanStatement.java @@ -0,0 +1,22 @@ +package com.dfsek.terra.api.structures.parser.lang.operations.statements; + +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.parser.lang.operations.BinaryOperation; +import com.dfsek.terra.api.structures.tokenizer.Position; + +public class LessThanStatement extends BinaryOperation { + public LessThanStatement(Returnable left, Returnable right, Position position) { + super(left, right, position); + } + + @Override + public Boolean apply(Number left, Number right) { + return left.doubleValue() < right.doubleValue(); + } + + + @Override + public ReturnType returnType() { + return ReturnType.BOOLEAN; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/statements/NotEqualsStatement.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/statements/NotEqualsStatement.java new file mode 100644 index 000000000..e0e57783c --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/statements/NotEqualsStatement.java @@ -0,0 +1,22 @@ +package com.dfsek.terra.api.structures.parser.lang.operations.statements; + +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.parser.lang.operations.BinaryOperation; +import com.dfsek.terra.api.structures.tokenizer.Position; + +public class NotEqualsStatement extends BinaryOperation { + public NotEqualsStatement(Returnable left, Returnable right, Position position) { + super(left, right, position); + } + + @Override + public Boolean apply(Object left, Object right) { + return !left.equals(right); + } + + + @Override + public ReturnType returnType() { + return ReturnType.BOOLEAN; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/variables/Assignment.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/variables/Assignment.java new file mode 100644 index 000000000..52a588191 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/variables/Assignment.java @@ -0,0 +1,30 @@ +package com.dfsek.terra.api.structures.parser.lang.variables; + +import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; +import com.dfsek.terra.api.structures.parser.lang.Item; +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.tokenizer.Position; + +public class Assignment implements Item { + private final Variable delegate; + private final Returnable value; + private final Position position; + + public Assignment(Variable delegate, Returnable value, Position position) { + this.delegate = delegate; + this.value = value; + this.position = position; + } + + @Override + public synchronized T apply(ImplementationArguments implementationArguments) { + T val = value.apply(implementationArguments); + delegate.setValue(val); + return val; + } + + @Override + public Position getPosition() { + return position; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/variables/BooleanVariable.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/variables/BooleanVariable.java new file mode 100644 index 000000000..ad0ed5400 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/variables/BooleanVariable.java @@ -0,0 +1,34 @@ +package com.dfsek.terra.api.structures.parser.lang.variables; + +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.tokenizer.Position; + +public class BooleanVariable implements Variable { + private final Position position; + private Boolean value; + + public BooleanVariable(Boolean value, Position position) { + this.value = value; + this.position = position; + } + + @Override + public Boolean getValue() { + return value; + } + + @Override + public void setValue(Boolean value) { + this.value = value; + } + + @Override + public Returnable.ReturnType getType() { + return Returnable.ReturnType.BOOLEAN; + } + + @Override + public Position getPosition() { + return position; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/variables/Getter.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/variables/Getter.java new file mode 100644 index 000000000..b7a1ca856 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/variables/Getter.java @@ -0,0 +1,28 @@ +package com.dfsek.terra.api.structures.parser.lang.variables; + +import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.tokenizer.Position; + +public class Getter implements Returnable { + private final Variable delegate; + + public Getter(Variable delegate) { + this.delegate = delegate; + } + + @Override + public ReturnType returnType() { + return delegate.getType(); + } + + @Override + public synchronized Object apply(ImplementationArguments implementationArguments) { + return delegate.getValue(); + } + + @Override + public Position getPosition() { + return delegate.getPosition(); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/variables/NumberVariable.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/variables/NumberVariable.java new file mode 100644 index 000000000..6f7355cb4 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/variables/NumberVariable.java @@ -0,0 +1,34 @@ +package com.dfsek.terra.api.structures.parser.lang.variables; + +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.tokenizer.Position; + +public class NumberVariable implements Variable { + private final Position position; + private Number value; + + public NumberVariable(Number value, Position position) { + this.value = value; + this.position = position; + } + + @Override + public Number getValue() { + return value; + } + + @Override + public void setValue(Number value) { + this.value = value; + } + + @Override + public Returnable.ReturnType getType() { + return Returnable.ReturnType.NUMBER; + } + + @Override + public Position getPosition() { + return position; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/variables/StringVariable.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/variables/StringVariable.java new file mode 100644 index 000000000..a2b48e73e --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/variables/StringVariable.java @@ -0,0 +1,34 @@ +package com.dfsek.terra.api.structures.parser.lang.variables; + +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.tokenizer.Position; + +public class StringVariable implements Variable { + private final Position position; + private String value; + + public StringVariable(String value, Position position) { + this.value = value; + this.position = position; + } + + @Override + public String getValue() { + return value; + } + + @Override + public void setValue(String value) { + this.value = value; + } + + @Override + public Returnable.ReturnType getType() { + return Returnable.ReturnType.STRING; + } + + @Override + public Position getPosition() { + return position; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/variables/Variable.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/variables/Variable.java new file mode 100644 index 000000000..4db60a3bf --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/variables/Variable.java @@ -0,0 +1,14 @@ +package com.dfsek.terra.api.structures.parser.lang.variables; + +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.tokenizer.Position; + +public interface Variable { + T getValue(); + + void setValue(T value); + + Returnable.ReturnType getType(); + + Position getPosition(); +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/StructureScript.java b/common/src/main/java/com/dfsek/terra/api/structures/script/StructureScript.java new file mode 100644 index 000000000..70826823a --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/StructureScript.java @@ -0,0 +1,155 @@ +package com.dfsek.terra.api.structures.script; + +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.platform.world.Chunk; +import com.dfsek.terra.api.structures.parser.Parser; +import com.dfsek.terra.api.structures.parser.exceptions.ParseException; +import com.dfsek.terra.api.structures.parser.lang.Block; +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.script.builders.BinaryNumberFunctionBuilder; +import com.dfsek.terra.api.structures.script.builders.BiomeFunctionBuilder; +import com.dfsek.terra.api.structures.script.builders.BlockFunctionBuilder; +import com.dfsek.terra.api.structures.script.builders.CheckBlockFunctionBuilder; +import com.dfsek.terra.api.structures.script.builders.CheckFunctionBuilder; +import com.dfsek.terra.api.structures.script.builders.EntityFunctionBuilder; +import com.dfsek.terra.api.structures.script.builders.GetMarkFunctionBuilder; +import com.dfsek.terra.api.structures.script.builders.LootFunctionBuilder; +import com.dfsek.terra.api.structures.script.builders.PullFunctionBuilder; +import com.dfsek.terra.api.structures.script.builders.RandomFunctionBuilder; +import com.dfsek.terra.api.structures.script.builders.RecursionsFunctionBuilder; +import com.dfsek.terra.api.structures.script.builders.SetMarkFunctionBuilder; +import com.dfsek.terra.api.structures.script.builders.StateFunctionBuilder; +import com.dfsek.terra.api.structures.script.builders.StructureFunctionBuilder; +import com.dfsek.terra.api.structures.script.builders.UnaryNumberFunctionBuilder; +import com.dfsek.terra.api.structures.script.builders.UnaryStringFunctionBuilder; +import com.dfsek.terra.api.structures.script.builders.ZeroArgFunctionBuilder; +import com.dfsek.terra.api.structures.structure.Rotation; +import com.dfsek.terra.api.structures.structure.buffer.Buffer; +import com.dfsek.terra.api.structures.structure.buffer.DirectBuffer; +import com.dfsek.terra.api.structures.structure.buffer.StructureBuffer; +import com.dfsek.terra.debug.Debug; +import com.dfsek.terra.generation.math.SamplerCache; +import com.dfsek.terra.registry.LootRegistry; +import com.dfsek.terra.registry.ScriptRegistry; +import net.jafama.FastMath; +import org.apache.commons.io.IOUtils; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Random; + +public class StructureScript { + private final Block block; + private final String id; + String tempID; + private final Map cache; + private final TerraPlugin main; + + public StructureScript(InputStream inputStream, TerraPlugin main, ScriptRegistry registry, LootRegistry lootRegistry, SamplerCache cache) throws ParseException { + Parser parser; + try { + parser = new Parser(IOUtils.toString(inputStream)); + } catch(IOException e) { + throw new RuntimeException(e); + } + + parser.registerFunction("block", new BlockFunctionBuilder(main)) + .registerFunction("check", new CheckFunctionBuilder(main, cache)) + .registerFunction("structure", new StructureFunctionBuilder(registry, main)) + .registerFunction("randomInt", new RandomFunctionBuilder()) + .registerFunction("recursions", new RecursionsFunctionBuilder()) + .registerFunction("setMark", new SetMarkFunctionBuilder()) + .registerFunction("getMark", new GetMarkFunctionBuilder()) + .registerFunction("pull", new PullFunctionBuilder(main)) + .registerFunction("loot", new LootFunctionBuilder(main, lootRegistry)) + .registerFunction("entity", new EntityFunctionBuilder(main)) + .registerFunction("getBiome", new BiomeFunctionBuilder(main)) + .registerFunction("getBlock", new CheckBlockFunctionBuilder()) + .registerFunction("state", new StateFunctionBuilder(main)) + .registerFunction("originX", new ZeroArgFunctionBuilder(arguments -> arguments.getBuffer().getOrigin().getX(), Returnable.ReturnType.NUMBER)) + .registerFunction("originY", new ZeroArgFunctionBuilder(arguments -> arguments.getBuffer().getOrigin().getY(), Returnable.ReturnType.NUMBER)) + .registerFunction("originZ", new ZeroArgFunctionBuilder(arguments -> arguments.getBuffer().getOrigin().getZ(), Returnable.ReturnType.NUMBER)) + .registerFunction("print", new UnaryStringFunctionBuilder(string -> Debug.info("[" + tempID + "] " + string))) + .registerFunction("abs", new UnaryNumberFunctionBuilder(number -> FastMath.abs(number.doubleValue()))) + .registerFunction("pow", new BinaryNumberFunctionBuilder((number, number2) -> FastMath.pow(number.doubleValue(), number2.doubleValue()))) + .registerFunction("sqrt", new UnaryNumberFunctionBuilder(number -> FastMath.sqrt(number.doubleValue()))) + .registerFunction("floor", new UnaryNumberFunctionBuilder(number -> FastMath.floor(number.doubleValue()))) + .registerFunction("ceil", new UnaryNumberFunctionBuilder(number -> FastMath.ceil(number.doubleValue()))) + .registerFunction("log", new UnaryNumberFunctionBuilder(number -> FastMath.log(number.doubleValue()))) + .registerFunction("round", new UnaryNumberFunctionBuilder(number -> FastMath.round(number.doubleValue()))) + .registerFunction("max", new BinaryNumberFunctionBuilder((number, number2) -> FastMath.max(number.doubleValue(), number2.doubleValue()))) + .registerFunction("min", new BinaryNumberFunctionBuilder((number, number2) -> FastMath.min(number.doubleValue(), number2.doubleValue()))); + + block = parser.parse(); + this.id = parser.getID(); + tempID = id; + this.main = main; + this.cache = Collections.synchronizedMap(new LinkedHashMap() { + @Override + protected boolean removeEldestEntry(Map.Entry eldest) { + return this.size() > main.getTerraConfig().getStructureCache(); + } + }); + } + + /** + * Paste the structure at a location + * + * @param location Location to paste structure + * @param rotation Rotation of structure + * @return Whether generation was successful + */ + public boolean execute(Location location, Random random, Rotation rotation) { + StructureBuffer buffer = new StructureBuffer(location); + boolean level = applyBlock(new TerraImplementationArguments(buffer, rotation, random, 0)); + buffer.paste(); + return level; + } + + public boolean execute(Location location, Chunk chunk, Random random, Rotation rotation) { + StructureBuffer buffer = computeBuffer(location, random, rotation); + buffer.paste(chunk); + return buffer.succeeded(); + } + + public boolean test(Location location, Random random, Rotation rotation) { + StructureBuffer buffer = computeBuffer(location, random, rotation); + return buffer.succeeded(); + } + + private StructureBuffer computeBuffer(Location location, Random random, Rotation rotation) { + synchronized(cache) { + return cache.computeIfAbsent(location, loc -> { + StructureBuffer buf = new StructureBuffer(loc); + buf.setSucceeded(applyBlock(new TerraImplementationArguments(buf, rotation, random, 0))); + return buf; + }); + } + } + + public boolean executeInBuffer(Buffer buffer, Random random, Rotation rotation, int recursions) { + return applyBlock(new TerraImplementationArguments(buffer, rotation, random, recursions)); + } + + public boolean executeDirect(Location location, Random random, Rotation rotation) { + DirectBuffer buffer = new DirectBuffer(location); + return applyBlock(new TerraImplementationArguments(buffer, rotation, random, 0)); + } + + public String getId() { + return id; + } + + private boolean applyBlock(TerraImplementationArguments arguments) { + try { + return !block.apply(arguments).getLevel().equals(Block.ReturnLevel.FAIL); + } catch(RuntimeException e) { + main.getLogger().severe("Failed to generate structure at " + arguments.getBuffer().getOrigin() + ": " + e.getMessage()); + return false; + } + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/TerraImplementationArguments.java b/common/src/main/java/com/dfsek/terra/api/structures/script/TerraImplementationArguments.java new file mode 100644 index 000000000..4183bc583 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/TerraImplementationArguments.java @@ -0,0 +1,37 @@ +package com.dfsek.terra.api.structures.script; + +import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; +import com.dfsek.terra.api.structures.structure.Rotation; +import com.dfsek.terra.api.structures.structure.buffer.Buffer; + +import java.util.Random; + +public class TerraImplementationArguments implements ImplementationArguments { + private final Buffer buffer; + private final Rotation rotation; + private final Random random; + private final int recursions; + + public TerraImplementationArguments(Buffer buffer, Rotation rotation, Random random, int recursions) { + this.buffer = buffer; + this.rotation = rotation; + this.random = random; + this.recursions = recursions; + } + + public Buffer getBuffer() { + return buffer; + } + + public int getRecursions() { + return recursions; + } + + public Random getRandom() { + return random; + } + + public Rotation getRotation() { + return rotation; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/BinaryNumberFunctionBuilder.java b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/BinaryNumberFunctionBuilder.java new file mode 100644 index 000000000..52deee579 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/BinaryNumberFunctionBuilder.java @@ -0,0 +1,51 @@ +package com.dfsek.terra.api.structures.script.builders; + +import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.parser.lang.functions.Function; +import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.api.structures.tokenizer.Position; + +import java.util.List; +import java.util.function.BiFunction; + +public class BinaryNumberFunctionBuilder implements FunctionBuilder> { + + private final BiFunction function; + + public BinaryNumberFunctionBuilder(BiFunction function) { + this.function = function; + } + + @Override + public Function build(List> argumentList, Position position) { + return new Function() { + @Override + public ReturnType returnType() { + return ReturnType.NUMBER; + } + + @SuppressWarnings("unchecked") + @Override + public Number apply(ImplementationArguments implementationArguments) { + return function.apply(((Returnable) argumentList.get(0)).apply(implementationArguments), ((Returnable) argumentList.get(1)).apply(implementationArguments)); + } + + @Override + public Position getPosition() { + return position; + } + }; + } + + @Override + public int argNumber() { + return 2; + } + + @Override + public Returnable.ReturnType getArgument(int position) { + if(position == 0 || position == 1) return Returnable.ReturnType.NUMBER; + return null; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/BiomeFunctionBuilder.java b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/BiomeFunctionBuilder.java new file mode 100644 index 000000000..cceb13fb7 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/BiomeFunctionBuilder.java @@ -0,0 +1,40 @@ +package com.dfsek.terra.api.structures.script.builders; + +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.api.structures.script.functions.BiomeFunction; +import com.dfsek.terra.api.structures.tokenizer.Position; + +import java.util.List; + +public class BiomeFunctionBuilder implements FunctionBuilder { + private final TerraPlugin main; + + public BiomeFunctionBuilder(TerraPlugin main) { + this.main = main; + } + + @SuppressWarnings("unchecked") + @Override + public BiomeFunction build(List> argumentList, Position position) { + return new BiomeFunction(main, (Returnable) argumentList.get(0), (Returnable) argumentList.get(1), (Returnable) argumentList.get(2), position); + } + + @Override + public int argNumber() { + return 3; + } + + @Override + public Returnable.ReturnType getArgument(int position) { + switch(position) { + case 0: + case 1: + case 2: + return Returnable.ReturnType.NUMBER; + default: + return null; + } + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/BlockFunctionBuilder.java b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/BlockFunctionBuilder.java new file mode 100644 index 000000000..116681866 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/BlockFunctionBuilder.java @@ -0,0 +1,49 @@ +package com.dfsek.terra.api.structures.script.builders; + +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.structures.parser.exceptions.ParseException; +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.parser.lang.constants.BooleanConstant; +import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.api.structures.script.functions.BlockFunction; +import com.dfsek.terra.api.structures.tokenizer.Position; + +import java.util.List; + +public class BlockFunctionBuilder implements FunctionBuilder { + private final TerraPlugin main; + + public BlockFunctionBuilder(TerraPlugin main) { + this.main = main; + } + + @SuppressWarnings("unchecked") + @Override + public BlockFunction build(List> argumentList, Position position) throws ParseException { + if(argumentList.size() < 4) throw new ParseException("Expected data", position); + Returnable booleanReturnable = new BooleanConstant(true, position); + if(argumentList.size() == 5) booleanReturnable = (Returnable) argumentList.get(4); + return new BlockFunction((Returnable) argumentList.get(0), (Returnable) argumentList.get(1), (Returnable) argumentList.get(2), (Returnable) argumentList.get(3), booleanReturnable, main, position); + } + + @Override + public int argNumber() { + return -1; + } + + @Override + public Returnable.ReturnType getArgument(int position) { + switch(position) { + case 0: + case 1: + case 2: + return Returnable.ReturnType.NUMBER; + case 3: + return Returnable.ReturnType.STRING; + case 4: + return Returnable.ReturnType.BOOLEAN; + default: + return null; + } + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/CheckBlockFunctionBuilder.java b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/CheckBlockFunctionBuilder.java new file mode 100644 index 000000000..98eeb2665 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/CheckBlockFunctionBuilder.java @@ -0,0 +1,33 @@ +package com.dfsek.terra.api.structures.script.builders; + +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.api.structures.script.functions.CheckBlockFunction; +import com.dfsek.terra.api.structures.tokenizer.Position; + +import java.util.List; + +public class CheckBlockFunctionBuilder implements FunctionBuilder { + @SuppressWarnings("unchecked") + @Override + public CheckBlockFunction build(List> argumentList, Position position) { + return new CheckBlockFunction((Returnable) argumentList.get(0), (Returnable) argumentList.get(1), (Returnable) argumentList.get(2), position); + } + + @Override + public int argNumber() { + return 3; + } + + @Override + public Returnable.ReturnType getArgument(int position) { + switch(position) { + case 0: + case 1: + case 2: + return Returnable.ReturnType.NUMBER; + default: + return null; + } + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/CheckFunctionBuilder.java b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/CheckFunctionBuilder.java new file mode 100644 index 000000000..81399b183 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/CheckFunctionBuilder.java @@ -0,0 +1,44 @@ +package com.dfsek.terra.api.structures.script.builders; + +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.structures.parser.exceptions.ParseException; +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.api.structures.script.functions.CheckFunction; +import com.dfsek.terra.api.structures.tokenizer.Position; +import com.dfsek.terra.generation.math.SamplerCache; + +import java.util.List; + +public class CheckFunctionBuilder implements FunctionBuilder { + private final TerraPlugin main; + private final SamplerCache cache; + + public CheckFunctionBuilder(TerraPlugin main, SamplerCache cache) { + this.main = main; + this.cache = cache; + } + + @SuppressWarnings("unchecked") + @Override + public CheckFunction build(List> argumentList, Position position) throws ParseException { + return new CheckFunction(main, (Returnable) argumentList.get(0), (Returnable) argumentList.get(1), (Returnable) argumentList.get(2), cache, position); + } + + @Override + public int argNumber() { + return 3; + } + + @Override + public Returnable.ReturnType getArgument(int position) { + switch(position) { + case 0: + case 1: + case 2: + return Returnable.ReturnType.NUMBER; + default: + return null; + } + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/EntityFunctionBuilder.java b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/EntityFunctionBuilder.java new file mode 100644 index 000000000..fff23ce78 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/EntityFunctionBuilder.java @@ -0,0 +1,43 @@ +package com.dfsek.terra.api.structures.script.builders; + +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.structures.parser.exceptions.ParseException; +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.api.structures.script.functions.EntityFunction; +import com.dfsek.terra.api.structures.tokenizer.Position; + +import java.util.List; + +public class EntityFunctionBuilder implements FunctionBuilder { + private final TerraPlugin main; + + public EntityFunctionBuilder(TerraPlugin main) { + this.main = main; + } + + @SuppressWarnings("unchecked") + @Override + public EntityFunction build(List> argumentList, Position position) throws ParseException { + return new EntityFunction((Returnable) argumentList.get(0), (Returnable) argumentList.get(1), (Returnable) argumentList.get(2), (Returnable) argumentList.get(3), main, position); + } + + @Override + public int argNumber() { + return 4; + } + + @Override + public Returnable.ReturnType getArgument(int position) { + switch(position) { + case 0: + case 1: + case 2: + return Returnable.ReturnType.NUMBER; + case 3: + return Returnable.ReturnType.STRING; + default: + return null; + } + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/GetMarkFunctionBuilder.java b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/GetMarkFunctionBuilder.java new file mode 100644 index 000000000..e93fbdc2b --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/GetMarkFunctionBuilder.java @@ -0,0 +1,37 @@ +package com.dfsek.terra.api.structures.script.builders; + +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.api.structures.script.functions.GetMarkFunction; +import com.dfsek.terra.api.structures.tokenizer.Position; + +import java.util.List; + +public class GetMarkFunctionBuilder implements FunctionBuilder { + + public GetMarkFunctionBuilder() { + } + + @SuppressWarnings("unchecked") + @Override + public GetMarkFunction build(List> argumentList, Position position) { + return new GetMarkFunction((Returnable) argumentList.get(0), (Returnable) argumentList.get(1), (Returnable) argumentList.get(2), position); + } + + @Override + public int argNumber() { + return 3; + } + + @Override + public Returnable.ReturnType getArgument(int position) { + switch(position) { + case 0: + case 1: + case 2: + return Returnable.ReturnType.NUMBER; + default: + return null; + } + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/LootFunctionBuilder.java b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/LootFunctionBuilder.java new file mode 100644 index 000000000..db9677e54 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/LootFunctionBuilder.java @@ -0,0 +1,45 @@ +package com.dfsek.terra.api.structures.script.builders; + +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.api.structures.script.functions.LootFunction; +import com.dfsek.terra.api.structures.tokenizer.Position; +import com.dfsek.terra.registry.LootRegistry; + +import java.util.List; + +public class LootFunctionBuilder implements FunctionBuilder { + private final TerraPlugin main; + private final LootRegistry registry; + + public LootFunctionBuilder(TerraPlugin main, LootRegistry registry) { + this.main = main; + this.registry = registry; + } + + @SuppressWarnings("unchecked") + @Override + public LootFunction build(List> argumentList, Position position) { + return new LootFunction(registry, (Returnable) argumentList.get(0), (Returnable) argumentList.get(1), (Returnable) argumentList.get(2), (Returnable) argumentList.get(3), main, position); + } + + @Override + public int argNumber() { + return 4; + } + + @Override + public Returnable.ReturnType getArgument(int position) { + switch(position) { + case 0: + case 1: + case 2: + return Returnable.ReturnType.NUMBER; + case 3: + return Returnable.ReturnType.STRING; + default: + return null; + } + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/PullFunctionBuilder.java b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/PullFunctionBuilder.java new file mode 100644 index 000000000..0c5ab641d --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/PullFunctionBuilder.java @@ -0,0 +1,43 @@ +package com.dfsek.terra.api.structures.script.builders; + +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.structures.parser.exceptions.ParseException; +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.api.structures.script.functions.PullFunction; +import com.dfsek.terra.api.structures.tokenizer.Position; + +import java.util.List; + +public class PullFunctionBuilder implements FunctionBuilder { + private final TerraPlugin main; + + public PullFunctionBuilder(TerraPlugin main) { + this.main = main; + } + + @SuppressWarnings("unchecked") + @Override + public PullFunction build(List> argumentList, Position position) throws ParseException { + return new PullFunction((Returnable) argumentList.get(0), (Returnable) argumentList.get(1), (Returnable) argumentList.get(2), (Returnable) argumentList.get(3), main, position); + } + + @Override + public int argNumber() { + return 4; + } + + @Override + public Returnable.ReturnType getArgument(int position) { + switch(position) { + case 0: + case 1: + case 2: + return Returnable.ReturnType.NUMBER; + case 3: + return Returnable.ReturnType.STRING; + default: + return null; + } + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/RandomFunctionBuilder.java b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/RandomFunctionBuilder.java new file mode 100644 index 000000000..ec84d5c36 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/RandomFunctionBuilder.java @@ -0,0 +1,28 @@ +package com.dfsek.terra.api.structures.script.builders; + +import com.dfsek.terra.api.structures.parser.exceptions.ParseException; +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.api.structures.script.functions.RandomFunction; +import com.dfsek.terra.api.structures.tokenizer.Position; + +import java.util.List; + +public class RandomFunctionBuilder implements FunctionBuilder { + @SuppressWarnings("unchecked") + @Override + public RandomFunction build(List> argumentList, Position position) throws ParseException { + return new RandomFunction((Returnable) argumentList.get(0), position); + } + + @Override + public int argNumber() { + return 1; + } + + @Override + public Returnable.ReturnType getArgument(int position) { + if(position == 0) return Returnable.ReturnType.NUMBER; + return null; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/RecursionsFunctionBuilder.java b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/RecursionsFunctionBuilder.java new file mode 100644 index 000000000..5fc66977d --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/RecursionsFunctionBuilder.java @@ -0,0 +1,26 @@ +package com.dfsek.terra.api.structures.script.builders; + +import com.dfsek.terra.api.structures.parser.exceptions.ParseException; +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.api.structures.script.functions.RecursionsFunction; +import com.dfsek.terra.api.structures.tokenizer.Position; + +import java.util.List; + +public class RecursionsFunctionBuilder implements FunctionBuilder { + @Override + public RecursionsFunction build(List> argumentList, Position position) throws ParseException { + return new RecursionsFunction(position); + } + + @Override + public int argNumber() { + return 0; + } + + @Override + public Returnable.ReturnType getArgument(int position) { + return null; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/SetMarkFunctionBuilder.java b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/SetMarkFunctionBuilder.java new file mode 100644 index 000000000..76fc5ec39 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/SetMarkFunctionBuilder.java @@ -0,0 +1,40 @@ +package com.dfsek.terra.api.structures.script.builders; + +import com.dfsek.terra.api.structures.parser.exceptions.ParseException; +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.api.structures.script.functions.SetMarkFunction; +import com.dfsek.terra.api.structures.tokenizer.Position; + +import java.util.List; + +public class SetMarkFunctionBuilder implements FunctionBuilder { + + public SetMarkFunctionBuilder() { + } + + @SuppressWarnings("unchecked") + @Override + public SetMarkFunction build(List> argumentList, Position position) throws ParseException { + return new SetMarkFunction((Returnable) argumentList.get(0), (Returnable) argumentList.get(1), (Returnable) argumentList.get(2), (Returnable) argumentList.get(3), position); + } + + @Override + public int argNumber() { + return 4; + } + + @Override + public Returnable.ReturnType getArgument(int position) { + switch(position) { + case 0: + case 1: + case 2: + return Returnable.ReturnType.NUMBER; + case 3: + return Returnable.ReturnType.STRING; + default: + return null; + } + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/StateFunctionBuilder.java b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/StateFunctionBuilder.java new file mode 100644 index 000000000..0ebf71c9b --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/StateFunctionBuilder.java @@ -0,0 +1,44 @@ +package com.dfsek.terra.api.structures.script.builders; + +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.structures.parser.exceptions.ParseException; +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.api.structures.script.functions.StateFunction; +import com.dfsek.terra.api.structures.tokenizer.Position; + +import java.util.List; + +public class StateFunctionBuilder implements FunctionBuilder { + private final TerraPlugin main; + + public StateFunctionBuilder(TerraPlugin main) { + this.main = main; + } + + @SuppressWarnings("unchecked") + @Override + public StateFunction build(List> argumentList, Position position) throws ParseException { + if(argumentList.size() < 4) throw new ParseException("Expected data", position); + return new StateFunction((Returnable) argumentList.get(0), (Returnable) argumentList.get(1), (Returnable) argumentList.get(2), (Returnable) argumentList.get(3), main, position); + } + + @Override + public int argNumber() { + return 4; + } + + @Override + public Returnable.ReturnType getArgument(int position) { + switch(position) { + case 0: + case 1: + case 2: + return Returnable.ReturnType.NUMBER; + case 3: + return Returnable.ReturnType.STRING; + default: + return null; + } + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/StructureFunctionBuilder.java b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/StructureFunctionBuilder.java new file mode 100644 index 000000000..e61a3527b --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/StructureFunctionBuilder.java @@ -0,0 +1,48 @@ +package com.dfsek.terra.api.structures.script.builders; + +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.structures.parser.exceptions.ParseException; +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.api.structures.script.functions.StructureFunction; +import com.dfsek.terra.api.structures.tokenizer.Position; +import com.dfsek.terra.registry.ScriptRegistry; + +import java.util.List; +import java.util.stream.Collectors; + +public class StructureFunctionBuilder implements FunctionBuilder { + private final ScriptRegistry registry; + private final TerraPlugin main; + + public StructureFunctionBuilder(ScriptRegistry registry, TerraPlugin main) { + this.registry = registry; + this.main = main; + } + + @SuppressWarnings("unchecked") + @Override + public StructureFunction build(List> argumentList, Position position) throws ParseException { + if(argumentList.size() < 5) throw new ParseException("Expected rotations", position); + + return new StructureFunction((Returnable) argumentList.remove(0), (Returnable) argumentList.remove(0), (Returnable) argumentList.remove(0), (Returnable) argumentList.remove(0), + argumentList.stream().map(item -> ((Returnable) item)).collect(Collectors.toList()), registry, position, main); + } + + @Override + public int argNumber() { + return -1; + } + + @Override + public Returnable.ReturnType getArgument(int position) { + switch(position) { + case 0: + case 1: + case 2: + return Returnable.ReturnType.NUMBER; + default: + return Returnable.ReturnType.STRING; + } + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/UnaryNumberFunctionBuilder.java b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/UnaryNumberFunctionBuilder.java new file mode 100644 index 000000000..93bfe01ba --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/UnaryNumberFunctionBuilder.java @@ -0,0 +1,50 @@ +package com.dfsek.terra.api.structures.script.builders; + +import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.parser.lang.functions.Function; +import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.api.structures.tokenizer.Position; + +import java.util.List; + +public class UnaryNumberFunctionBuilder implements FunctionBuilder> { + + private final java.util.function.Function function; + + public UnaryNumberFunctionBuilder(java.util.function.Function function) { + this.function = function; + } + + @Override + public Function build(List> argumentList, Position position) { + return new Function() { + @Override + public ReturnType returnType() { + return ReturnType.NUMBER; + } + + @SuppressWarnings("unchecked") + @Override + public Number apply(ImplementationArguments implementationArguments) { + return function.apply(((Returnable) argumentList.get(0)).apply(implementationArguments)); + } + + @Override + public Position getPosition() { + return position; + } + }; + } + + @Override + public int argNumber() { + return 1; + } + + @Override + public Returnable.ReturnType getArgument(int position) { + if(position == 0) return Returnable.ReturnType.NUMBER; + return null; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/UnaryStringFunctionBuilder.java b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/UnaryStringFunctionBuilder.java new file mode 100644 index 000000000..619326773 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/UnaryStringFunctionBuilder.java @@ -0,0 +1,51 @@ +package com.dfsek.terra.api.structures.script.builders; + +import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.parser.lang.functions.Function; +import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.api.structures.tokenizer.Position; + +import java.util.List; + +public class UnaryStringFunctionBuilder implements FunctionBuilder> { + + private final java.util.function.Consumer function; + + public UnaryStringFunctionBuilder(java.util.function.Consumer function) { + this.function = function; + } + + @Override + public Function build(List> argumentList, Position position) { + return new Function() { + @Override + public ReturnType returnType() { + return ReturnType.VOID; + } + + @SuppressWarnings("unchecked") + @Override + public Void apply(ImplementationArguments implementationArguments) { + function.accept(((Returnable) argumentList.get(0)).apply(implementationArguments)); + return null; + } + + @Override + public Position getPosition() { + return position; + } + }; + } + + @Override + public int argNumber() { + return 1; + } + + @Override + public Returnable.ReturnType getArgument(int position) { + if(position == 0) return Returnable.ReturnType.STRING; + return null; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/ZeroArgFunctionBuilder.java b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/ZeroArgFunctionBuilder.java new file mode 100644 index 000000000..ef96b451b --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/ZeroArgFunctionBuilder.java @@ -0,0 +1,51 @@ +package com.dfsek.terra.api.structures.script.builders; + +import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.parser.lang.functions.Function; +import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.api.structures.script.TerraImplementationArguments; +import com.dfsek.terra.api.structures.tokenizer.Position; + +import java.util.List; + +public class ZeroArgFunctionBuilder implements FunctionBuilder> { + private final java.util.function.Function function; + private final Returnable.ReturnType type; + + public ZeroArgFunctionBuilder(java.util.function.Function function, Returnable.ReturnType type) { + this.function = function; + this.type = type; + } + + @Override + public Function build(List> argumentList, Position position) { + return new Function() { + @Override + public ReturnType returnType() { + return type; + } + + @Override + public T apply(ImplementationArguments implementationArguments) { + return function.apply((TerraImplementationArguments) implementationArguments); + } + + @Override + public Position getPosition() { + return position; + } + }; + } + + @Override + public int argNumber() { + return 1; + } + + @Override + public Returnable.ReturnType getArgument(int position) { + if(position == 0) return type; + return null; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/BiomeFunction.java b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/BiomeFunction.java new file mode 100644 index 000000000..55b88e140 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/BiomeFunction.java @@ -0,0 +1,54 @@ +package com.dfsek.terra.api.structures.script.functions; + +import com.dfsek.terra.api.math.vector.Vector2; +import com.dfsek.terra.api.math.vector.Vector3; +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.parser.lang.functions.Function; +import com.dfsek.terra.api.structures.script.TerraImplementationArguments; +import com.dfsek.terra.api.structures.structure.RotationUtil; +import com.dfsek.terra.api.structures.tokenizer.Position; +import com.dfsek.terra.biome.UserDefinedBiome; +import com.dfsek.terra.biome.grid.master.TerraBiomeGrid; +import net.jafama.FastMath; + +public class BiomeFunction implements Function { + private final TerraPlugin main; + private final Returnable x, y, z; + private final Position position; + + + public BiomeFunction(TerraPlugin main, Returnable x, Returnable y, Returnable z, Position position) { + this.main = main; + this.x = x; + this.y = y; + this.z = z; + this.position = position; + } + + + @Override + public String apply(ImplementationArguments implementationArguments) { + TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments; + + Vector2 xz = new Vector2(x.apply(implementationArguments).doubleValue(), z.apply(implementationArguments).doubleValue()); + + RotationUtil.rotateVector(xz, arguments.getRotation()); + + TerraBiomeGrid grid = main.getWorld(arguments.getBuffer().getOrigin().getWorld()).getGrid(); + + return ((UserDefinedBiome) grid.getBiome(arguments.getBuffer().getOrigin().clone().add(new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments).intValue(), FastMath.roundToInt(xz.getZ()))))).getID(); + } + + + @Override + public Position getPosition() { + return position; + } + + @Override + public ReturnType returnType() { + return ReturnType.STRING; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/BlockFunction.java b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/BlockFunction.java new file mode 100644 index 000000000..d32e9e01f --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/BlockFunction.java @@ -0,0 +1,62 @@ +package com.dfsek.terra.api.structures.script.functions; + +import com.dfsek.terra.api.math.vector.Vector2; +import com.dfsek.terra.api.math.vector.Vector3; +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.structures.parser.exceptions.ParseException; +import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.parser.lang.constants.ConstantExpression; +import com.dfsek.terra.api.structures.parser.lang.functions.Function; +import com.dfsek.terra.api.structures.script.TerraImplementationArguments; +import com.dfsek.terra.api.structures.structure.RotationUtil; +import com.dfsek.terra.api.structures.structure.buffer.items.BufferedBlock; +import com.dfsek.terra.api.structures.tokenizer.Position; +import net.jafama.FastMath; + +public class BlockFunction implements Function { + private final BlockData data; + private final Returnable x, y, z; + private final Position position; + private final Returnable overwrite; + + public BlockFunction(Returnable x, Returnable y, Returnable z, Returnable data, Returnable overwrite, TerraPlugin main, Position position) throws ParseException { + this.position = position; + if(!(data instanceof ConstantExpression)) throw new ParseException("Block data must be constant", data.getPosition()); + + try { + this.data = main.getWorldHandle().createBlockData(((ConstantExpression) data).getConstant()); + } catch(IllegalArgumentException e) { + throw new ParseException("Could not parse block data", data.getPosition(), e); + } + this.x = x; + this.y = y; + this.z = z; + this.overwrite = overwrite; + } + + @Override + public Void apply(ImplementationArguments implementationArguments) { + TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments; + BlockData rot = data.clone(); + + Vector2 xz = new Vector2(x.apply(implementationArguments).doubleValue(), z.apply(implementationArguments).doubleValue()); + + RotationUtil.rotateVector(xz, arguments.getRotation()); + + RotationUtil.rotateBlockData(rot, arguments.getRotation().inverse()); + arguments.getBuffer().addItem(new BufferedBlock(rot, overwrite.apply(implementationArguments)), new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments).doubleValue(), FastMath.roundToInt(xz.getZ())).toLocation(arguments.getBuffer().getOrigin().getWorld())); + return null; + } + + @Override + public Position getPosition() { + return position; + } + + @Override + public ReturnType returnType() { + return ReturnType.VOID; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/CheckBlockFunction.java b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/CheckBlockFunction.java new file mode 100644 index 000000000..8582af9ba --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/CheckBlockFunction.java @@ -0,0 +1,48 @@ +package com.dfsek.terra.api.structures.script.functions; + +import com.dfsek.terra.api.math.vector.Vector2; +import com.dfsek.terra.api.math.vector.Vector3; +import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.parser.lang.functions.Function; +import com.dfsek.terra.api.structures.script.TerraImplementationArguments; +import com.dfsek.terra.api.structures.structure.RotationUtil; +import com.dfsek.terra.api.structures.tokenizer.Position; +import net.jafama.FastMath; + +public class CheckBlockFunction implements Function { + private final Returnable x, y, z; + private final Position position; + + public CheckBlockFunction(Returnable x, Returnable y, Returnable z, Position position) { + this.x = x; + this.y = y; + this.z = z; + this.position = position; + } + + + @Override + public String apply(ImplementationArguments implementationArguments) { + TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments; + + Vector2 xz = new Vector2(x.apply(implementationArguments).doubleValue(), z.apply(implementationArguments).doubleValue()); + + RotationUtil.rotateVector(xz, arguments.getRotation()); + + String data = arguments.getBuffer().getOrigin().clone().add(new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments).doubleValue(), FastMath.roundToInt(xz.getZ()))).getBlock().getBlockData().getAsString(); + if(data.contains("[")) return data.substring(0, data.indexOf('[')); // Strip properties + else return data; + } + + + @Override + public Position getPosition() { + return position; + } + + @Override + public ReturnType returnType() { + return ReturnType.STRING; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/CheckFunction.java b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/CheckFunction.java new file mode 100644 index 000000000..0be6ac4a1 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/CheckFunction.java @@ -0,0 +1,80 @@ +package com.dfsek.terra.api.structures.script.functions; + +import com.dfsek.terra.TerraWorld; +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.math.vector.Vector2; +import com.dfsek.terra.api.math.vector.Vector3; +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.parser.lang.functions.Function; +import com.dfsek.terra.api.structures.script.TerraImplementationArguments; +import com.dfsek.terra.api.structures.structure.RotationUtil; +import com.dfsek.terra.api.structures.tokenizer.Position; +import com.dfsek.terra.api.world.generation.GenerationPhase; +import com.dfsek.terra.biome.UserDefinedBiome; +import com.dfsek.terra.biome.grid.master.TerraBiomeGrid; +import com.dfsek.terra.config.templates.BiomeTemplate; +import com.dfsek.terra.generation.math.SamplerCache; +import net.jafama.FastMath; + +public class CheckFunction implements Function { + private final TerraPlugin main; + private final Returnable x, y, z; + private final Position position; + private final SamplerCache cache; + + public CheckFunction(TerraPlugin main, Returnable x, Returnable y, Returnable z, SamplerCache cache, Position position) { + this.main = main; + this.x = x; + this.y = y; + this.z = z; + this.position = position; + this.cache = cache; + } + + + @Override + public String apply(ImplementationArguments implementationArguments) { + TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments; + + Vector2 xz = new Vector2(x.apply(implementationArguments).doubleValue(), z.apply(implementationArguments).doubleValue()); + + RotationUtil.rotateVector(xz, arguments.getRotation()); + + Location location = arguments.getBuffer().getOrigin().clone().add(new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments).doubleValue(), FastMath.roundToInt(xz.getZ()))); + + return apply(location, arguments.getBuffer().getOrigin().getWorld()); + } + + private String apply(Location vector, World world) { + TerraWorld tw = main.getWorld(world); + double comp = sample(vector.getBlockX(), vector.getBlockY(), vector.getBlockZ(), world); + + if(comp > 0) return "LAND"; // If noise val is greater than zero, location will always be land. + + TerraBiomeGrid grid = tw.getGrid(); + UserDefinedBiome b = (UserDefinedBiome) grid.getBiome(vector.getBlockX(), vector.getBlockZ(), GenerationPhase.POPULATE); + BiomeTemplate c = b.getConfig(); + + if(vector.getY() > c.getSeaLevel()) return "AIR"; // Above sea level + return "OCEAN"; // Below sea level + } + + private double sample(int x, int y, int z, World w) { + int cx = FastMath.floorDiv(x, 16); + int cz = FastMath.floorDiv(z, 16); + return cache.get(w, x, z).sample(x - (cx << 4), y, z - (cz << 4)); + } + + @Override + public Position getPosition() { + return position; + } + + @Override + public ReturnType returnType() { + return ReturnType.STRING; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/EntityFunction.java b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/EntityFunction.java new file mode 100644 index 000000000..e96d5c5d1 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/EntityFunction.java @@ -0,0 +1,53 @@ +package com.dfsek.terra.api.structures.script.functions; + +import com.dfsek.terra.api.math.vector.Vector2; +import com.dfsek.terra.api.math.vector.Vector3; +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.platform.world.entity.EntityType; +import com.dfsek.terra.api.structures.parser.exceptions.ParseException; +import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.parser.lang.constants.ConstantExpression; +import com.dfsek.terra.api.structures.parser.lang.functions.Function; +import com.dfsek.terra.api.structures.script.TerraImplementationArguments; +import com.dfsek.terra.api.structures.structure.RotationUtil; +import com.dfsek.terra.api.structures.structure.buffer.items.BufferedEntity; +import com.dfsek.terra.api.structures.tokenizer.Position; +import net.jafama.FastMath; + +public class EntityFunction implements Function { + private final EntityType data; + private final Returnable x, y, z; + private final Position position; + + public EntityFunction(Returnable x, Returnable y, Returnable z, Returnable data, TerraPlugin main, Position position) throws ParseException { + this.position = position; + if(!(data instanceof ConstantExpression)) throw new ParseException("Entity data must be constant", data.getPosition()); + + this.data = main.getWorldHandle().getEntity(((ConstantExpression) data).getConstant()); + this.x = x; + this.y = y; + this.z = z; + } + + @Override + public Void apply(ImplementationArguments implementationArguments) { + TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments; + Vector2 xz = new Vector2(x.apply(implementationArguments).doubleValue(), z.apply(implementationArguments).doubleValue()); + + RotationUtil.rotateVector(xz, arguments.getRotation()); + + arguments.getBuffer().addItem(new BufferedEntity(data), new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments).intValue(), FastMath.roundToInt(xz.getZ())).toLocation(arguments.getBuffer().getOrigin().getWorld())); + return null; + } + + @Override + public Position getPosition() { + return position; + } + + @Override + public ReturnType returnType() { + return ReturnType.VOID; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/GetMarkFunction.java b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/GetMarkFunction.java new file mode 100644 index 000000000..b2610b9cd --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/GetMarkFunction.java @@ -0,0 +1,43 @@ +package com.dfsek.terra.api.structures.script.functions; + +import com.dfsek.terra.api.math.vector.Vector2; +import com.dfsek.terra.api.math.vector.Vector3; +import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.parser.lang.functions.Function; +import com.dfsek.terra.api.structures.script.TerraImplementationArguments; +import com.dfsek.terra.api.structures.structure.RotationUtil; +import com.dfsek.terra.api.structures.tokenizer.Position; +import net.jafama.FastMath; + +public class GetMarkFunction implements Function { + private final Returnable x, y, z; + private final Position position; + + public GetMarkFunction(Returnable x, Returnable y, Returnable z, Position position) { + this.position = position; + this.x = x; + this.y = y; + this.z = z; + } + + @Override + public String apply(ImplementationArguments implementationArguments) { + TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments; + Vector2 xz = new Vector2(x.apply(implementationArguments).doubleValue(), z.apply(implementationArguments).doubleValue()); + + RotationUtil.rotateVector(xz, arguments.getRotation()); + String mark = arguments.getBuffer().getMark(new Vector3(FastMath.floorToInt(xz.getX()), FastMath.floorToInt(y.apply(implementationArguments).doubleValue()), FastMath.floorToInt(xz.getZ())).toLocation(arguments.getBuffer().getOrigin().getWorld())); + return mark == null ? "" : mark; + } + + @Override + public Position getPosition() { + return position; + } + + @Override + public ReturnType returnType() { + return ReturnType.STRING; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/LootFunction.java b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/LootFunction.java new file mode 100644 index 000000000..a8421f81c --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/LootFunction.java @@ -0,0 +1,62 @@ +package com.dfsek.terra.api.structures.script.functions; + +import com.dfsek.terra.api.math.vector.Vector2; +import com.dfsek.terra.api.math.vector.Vector3; +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.structures.loot.LootTable; +import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.parser.lang.functions.Function; +import com.dfsek.terra.api.structures.script.TerraImplementationArguments; +import com.dfsek.terra.api.structures.structure.RotationUtil; +import com.dfsek.terra.api.structures.structure.buffer.items.BufferedLootApplication; +import com.dfsek.terra.api.structures.tokenizer.Position; +import com.dfsek.terra.registry.LootRegistry; +import net.jafama.FastMath; + +public class LootFunction implements Function { + private final LootRegistry registry; + private final Returnable data; + private final Returnable x, y, z; + private final Position position; + private final TerraPlugin main; + + public LootFunction(LootRegistry registry, Returnable x, Returnable y, Returnable z, Returnable data, TerraPlugin main, Position position) { + this.registry = registry; + this.position = position; + this.data = data; + this.x = x; + this.y = y; + this.z = z; + this.main = main; + } + + @Override + public Void apply(ImplementationArguments implementationArguments) { + TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments; + Vector2 xz = new Vector2(x.apply(implementationArguments).doubleValue(), z.apply(implementationArguments).doubleValue()); + + RotationUtil.rotateVector(xz, arguments.getRotation()); + + String id = data.apply(implementationArguments); + LootTable table = registry.get(id); + + if(table == null) { + main.getLogger().severe("No such loot table " + id); + return null; + } + + arguments.getBuffer().addItem(new BufferedLootApplication(table, main), new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments).intValue(), FastMath.roundToInt(xz.getZ())).toLocation(arguments.getBuffer().getOrigin().getWorld())); + return null; + } + + @Override + public Position getPosition() { + return position; + } + + @Override + public ReturnType returnType() { + return ReturnType.VOID; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/PullFunction.java b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/PullFunction.java new file mode 100644 index 000000000..e3722dbc1 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/PullFunction.java @@ -0,0 +1,54 @@ +package com.dfsek.terra.api.structures.script.functions; + +import com.dfsek.terra.api.math.vector.Vector2; +import com.dfsek.terra.api.math.vector.Vector3; +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.structures.parser.exceptions.ParseException; +import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.parser.lang.constants.ConstantExpression; +import com.dfsek.terra.api.structures.parser.lang.functions.Function; +import com.dfsek.terra.api.structures.script.TerraImplementationArguments; +import com.dfsek.terra.api.structures.structure.RotationUtil; +import com.dfsek.terra.api.structures.structure.buffer.items.BufferedPulledBlock; +import com.dfsek.terra.api.structures.tokenizer.Position; +import net.jafama.FastMath; + +public class PullFunction implements Function { + private final BlockData data; + private final Returnable x, y, z; + private final Position position; + + public PullFunction(Returnable x, Returnable y, Returnable z, Returnable data, TerraPlugin main, Position position) throws ParseException { + this.position = position; + if(!(data instanceof ConstantExpression)) throw new ParseException("Block data must be constant", data.getPosition()); + + this.data = main.getWorldHandle().createBlockData(((ConstantExpression) data).getConstant()); + this.x = x; + this.y = y; + this.z = z; + } + + @Override + public Void apply(ImplementationArguments implementationArguments) { + TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments; + Vector2 xz = new Vector2(x.apply(implementationArguments).doubleValue(), z.apply(implementationArguments).doubleValue()); + + RotationUtil.rotateVector(xz, arguments.getRotation()); + BlockData rot = data.clone(); + RotationUtil.rotateBlockData(rot, arguments.getRotation().inverse()); + arguments.getBuffer().addItem(new BufferedPulledBlock(rot), new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments).intValue(), FastMath.roundToInt(xz.getZ())).toLocation(arguments.getBuffer().getOrigin().getWorld())); + return null; + } + + @Override + public Position getPosition() { + return position; + } + + @Override + public ReturnType returnType() { + return ReturnType.VOID; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/RandomFunction.java b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/RandomFunction.java new file mode 100644 index 000000000..e61952bfe --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/RandomFunction.java @@ -0,0 +1,33 @@ +package com.dfsek.terra.api.structures.script.functions; + +import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.parser.lang.functions.Function; +import com.dfsek.terra.api.structures.script.TerraImplementationArguments; +import com.dfsek.terra.api.structures.tokenizer.Position; + +public class RandomFunction implements Function { + private final Returnable numberReturnable; + private final Position position; + + public RandomFunction(Returnable numberReturnable, Position position) { + this.numberReturnable = numberReturnable; + this.position = position; + } + + + @Override + public ReturnType returnType() { + return ReturnType.NUMBER; + } + + @Override + public Integer apply(ImplementationArguments implementationArguments) { + return ((TerraImplementationArguments) implementationArguments).getRandom().nextInt(numberReturnable.apply(implementationArguments).intValue()); + } + + @Override + public Position getPosition() { + return position; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/RecursionsFunction.java b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/RecursionsFunction.java new file mode 100644 index 000000000..a8725d57f --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/RecursionsFunction.java @@ -0,0 +1,29 @@ +package com.dfsek.terra.api.structures.script.functions; + +import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; +import com.dfsek.terra.api.structures.parser.lang.functions.Function; +import com.dfsek.terra.api.structures.script.TerraImplementationArguments; +import com.dfsek.terra.api.structures.tokenizer.Position; + +public class RecursionsFunction implements Function { + private final Position position; + + public RecursionsFunction(Position position) { + this.position = position; + } + + @Override + public ReturnType returnType() { + return ReturnType.NUMBER; + } + + @Override + public Number apply(ImplementationArguments implementationArguments) { + return ((TerraImplementationArguments) implementationArguments).getRecursions(); + } + + @Override + public Position getPosition() { + return position; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/SetMarkFunction.java b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/SetMarkFunction.java new file mode 100644 index 000000000..f439d5acc --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/SetMarkFunction.java @@ -0,0 +1,46 @@ +package com.dfsek.terra.api.structures.script.functions; + +import com.dfsek.terra.api.math.vector.Vector2; +import com.dfsek.terra.api.math.vector.Vector3; +import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.parser.lang.functions.Function; +import com.dfsek.terra.api.structures.script.TerraImplementationArguments; +import com.dfsek.terra.api.structures.structure.RotationUtil; +import com.dfsek.terra.api.structures.tokenizer.Position; +import net.jafama.FastMath; + +public class SetMarkFunction implements Function { + private final Returnable x, y, z; + private final Position position; + private final Returnable mark; + + public SetMarkFunction(Returnable x, Returnable y, Returnable z, Returnable mark, Position position) { + this.position = position; + this.mark = mark; + this.x = x; + this.y = y; + this.z = z; + } + + @Override + public Void apply(ImplementationArguments implementationArguments) { + TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments; + Vector2 xz = new Vector2(x.apply(implementationArguments).doubleValue(), z.apply(implementationArguments).doubleValue()); + + RotationUtil.rotateVector(xz, arguments.getRotation()); + + arguments.getBuffer().setMark(mark.apply(implementationArguments), new Vector3(FastMath.floorToInt(xz.getX()), FastMath.floorToInt(y.apply(implementationArguments).doubleValue()), FastMath.floorToInt(xz.getZ())).toLocation(arguments.getBuffer().getOrigin().getWorld())); + return null; + } + + @Override + public Position getPosition() { + return position; + } + + @Override + public ReturnType returnType() { + return ReturnType.VOID; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/StateFunction.java b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/StateFunction.java new file mode 100644 index 000000000..341a34d2d --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/StateFunction.java @@ -0,0 +1,49 @@ +package com.dfsek.terra.api.structures.script.functions; + +import com.dfsek.terra.api.math.vector.Vector2; +import com.dfsek.terra.api.math.vector.Vector3; +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.parser.lang.functions.Function; +import com.dfsek.terra.api.structures.script.TerraImplementationArguments; +import com.dfsek.terra.api.structures.structure.RotationUtil; +import com.dfsek.terra.api.structures.structure.buffer.items.BufferedStateManipulator; +import com.dfsek.terra.api.structures.tokenizer.Position; +import net.jafama.FastMath; + +public class StateFunction implements Function { + private final Returnable data; + private final Returnable x, y, z; + private final Position position; + private final TerraPlugin main; + + public StateFunction(Returnable x, Returnable y, Returnable z, Returnable data, TerraPlugin main, Position position) { + this.position = position; + this.main = main; + this.data = data; + this.x = x; + this.y = y; + this.z = z; + } + + @Override + public Void apply(ImplementationArguments implementationArguments) { + TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments; + Vector2 xz = new Vector2(x.apply(implementationArguments).doubleValue(), z.apply(implementationArguments).doubleValue()); + RotationUtil.rotateVector(xz, arguments.getRotation()); + + arguments.getBuffer().addItem(new BufferedStateManipulator(main, data.apply(implementationArguments)), new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments).intValue(), FastMath.roundToInt(xz.getZ())).toLocation(arguments.getBuffer().getOrigin().getWorld())); + return null; + } + + @Override + public Position getPosition() { + return position; + } + + @Override + public ReturnType returnType() { + return ReturnType.VOID; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/StructureFunction.java b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/StructureFunction.java new file mode 100644 index 000000000..313290d95 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/StructureFunction.java @@ -0,0 +1,80 @@ +package com.dfsek.terra.api.structures.script.functions; + +import com.dfsek.terra.api.math.vector.Vector2; +import com.dfsek.terra.api.math.vector.Vector3; +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.parser.lang.functions.Function; +import com.dfsek.terra.api.structures.script.StructureScript; +import com.dfsek.terra.api.structures.script.TerraImplementationArguments; +import com.dfsek.terra.api.structures.structure.Rotation; +import com.dfsek.terra.api.structures.structure.RotationUtil; +import com.dfsek.terra.api.structures.structure.buffer.IntermediateBuffer; +import com.dfsek.terra.api.structures.tokenizer.Position; +import com.dfsek.terra.registry.ScriptRegistry; +import net.jafama.FastMath; + +import java.util.List; + +public class StructureFunction implements Function { + private final ScriptRegistry registry; + private final Returnable id; + private final Returnable x, y, z; + private final Position position; + private final TerraPlugin main; + private final List> rotations; + + public StructureFunction(Returnable x, Returnable y, Returnable z, Returnable id, List> rotations, ScriptRegistry registry, Position position, TerraPlugin main) { + this.registry = registry; + this.id = id; + this.position = position; + this.x = x; + this.y = y; + this.z = z; + this.main = main; + this.rotations = rotations; + } + + @Override + public ReturnType returnType() { + return ReturnType.BOOLEAN; + } + + @Override + public Boolean apply(ImplementationArguments implementationArguments) { + TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments; + + if(arguments.getRecursions() > main.getTerraConfig().getMaxRecursion()) + throw new RuntimeException("Structure recursion too deep: " + arguments.getRecursions()); + + Vector2 xz = new Vector2(x.apply(implementationArguments).doubleValue(), z.apply(implementationArguments).doubleValue()); + + RotationUtil.rotateVector(xz, arguments.getRotation()); + + String app = id.apply(implementationArguments); + StructureScript script = registry.get(app); + if(script == null) { + main.getLogger().severe("No such structure " + app); + return null; + } + + Rotation rotation1; + String rotString = rotations.get(arguments.getRandom().nextInt(rotations.size())).apply(implementationArguments); + try { + rotation1 = Rotation.valueOf(rotString); + } catch(IllegalArgumentException e) { + main.getLogger().severe("Invalid rotation " + rotString); + return null; + } + + Vector3 offset = new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments).doubleValue(), FastMath.roundToInt(xz.getZ())); + + return script.executeInBuffer(new IntermediateBuffer(arguments.getBuffer(), offset), arguments.getRandom(), arguments.getRotation().rotate(rotation1), arguments.getRecursions() + 1); + } + + @Override + public Position getPosition() { + return position; + } +} diff --git a/src/main/java/com/dfsek/terra/structure/Rotation.java b/common/src/main/java/com/dfsek/terra/api/structures/structure/Rotation.java similarity index 86% rename from src/main/java/com/dfsek/terra/structure/Rotation.java rename to common/src/main/java/com/dfsek/terra/api/structures/structure/Rotation.java index e9aac096e..f81c8f63e 100644 --- a/src/main/java/com/dfsek/terra/structure/Rotation.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/structure/Rotation.java @@ -1,8 +1,9 @@ -package com.dfsek.terra.structure; +package com.dfsek.terra.api.structures.structure; import net.jafama.FastMath; public enum Rotation { + CW_90(90), CW_180(180), CCW_90(270), NONE(0); private final int degrees; @@ -44,6 +45,10 @@ public enum Rotation { } } + public Rotation rotate(Rotation rotation) { + return fromDegrees(this.getDegrees() + rotation.getDegrees()); + } + public enum Axis { X, Y, Z } diff --git a/src/main/java/com/dfsek/terra/util/structure/RotationUtil.java b/common/src/main/java/com/dfsek/terra/api/structures/structure/RotationUtil.java similarity index 89% rename from src/main/java/com/dfsek/terra/util/structure/RotationUtil.java rename to common/src/main/java/com/dfsek/terra/api/structures/structure/RotationUtil.java index c83661315..1d77977d3 100644 --- a/src/main/java/com/dfsek/terra/util/structure/RotationUtil.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/structure/RotationUtil.java @@ -1,32 +1,33 @@ -package com.dfsek.terra.util.structure; +package com.dfsek.terra.api.structures.structure; -import com.dfsek.terra.procgen.math.Vector2; -import com.dfsek.terra.structure.Rotation; +import com.dfsek.terra.api.math.vector.Vector2; +import com.dfsek.terra.api.platform.block.Axis; +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.block.BlockFace; +import com.dfsek.terra.api.platform.block.data.Directional; +import com.dfsek.terra.api.platform.block.data.MultipleFacing; +import com.dfsek.terra.api.platform.block.data.Orientable; +import com.dfsek.terra.api.platform.block.data.Rail; +import com.dfsek.terra.api.platform.block.data.RedstoneWire; +import com.dfsek.terra.api.platform.block.data.Rotatable; +import com.dfsek.terra.api.platform.block.data.Wall; import com.google.common.collect.Sets; import net.jafama.FastMath; -import org.bukkit.block.BlockFace; -import org.bukkit.block.data.BlockData; -import org.bukkit.block.data.Directional; -import org.bukkit.block.data.MultipleFacing; -import org.bukkit.block.data.Orientable; -import org.bukkit.block.data.Rail; -import org.bukkit.block.data.Rotatable; -import org.bukkit.block.data.type.RedstoneWire; -import org.bukkit.block.data.type.Wall; import java.util.EnumMap; import java.util.Map; import java.util.Set; -public final class RotationUtil { +public class RotationUtil { + private static final Set CARDINALS = Sets.newHashSet(BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST, BlockFace.WEST); + /** * Rotate and mirror a coordinate pair. * * @param orig Vector to rotate. * @param r Rotation - * @return Rotated coordinate pair */ - public static Vector2 getRotatedCoords(Vector2 orig, Rotation r) { + public static void rotateVector(Vector2 orig, Rotation r) { Vector2 copy = orig.clone(); switch(r) { case CW_90: @@ -39,7 +40,8 @@ public final class RotationUtil { copy.multiply(-1); break; } - return copy; + orig.setX(copy.getX()); + orig.setZ(copy.getZ()); } /** @@ -149,15 +151,15 @@ public final class RotationUtil { } } - public static org.bukkit.Axis getRotatedAxis(org.bukkit.Axis orig, Rotation r) { - org.bukkit.Axis other = orig; + public static Axis getRotatedAxis(Axis orig, Rotation r) { + Axis other = orig; final boolean shouldSwitch = r.equals(Rotation.CW_90) || r.equals(Rotation.CCW_90); switch(orig) { case X: - if(shouldSwitch) other = org.bukkit.Axis.Z; + if(shouldSwitch) other = Axis.Z; break; case Z: - if(shouldSwitch) other = org.bukkit.Axis.X; + if(shouldSwitch) other = Axis.X; break; } return other; @@ -246,8 +248,6 @@ public final class RotationUtil { return orig; } - private static final Set CARDINALS = Sets.newHashSet(BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST, BlockFace.WEST); - public static void rotateBlockData(BlockData data, Rotation r) { if(data instanceof Rotatable) { BlockFace rt = getRotatedFace(((Rotatable) data).getRotation(), r); @@ -268,7 +268,7 @@ public final class RotationUtil { Rail.Shape newShape = getRotatedRail(((Rail) data).getShape(), r); ((Rail) data).setShape(newShape); } else if(data instanceof Orientable) { - org.bukkit.Axis newAxis = getRotatedAxis(((Orientable) data).getAxis(), r); + Axis newAxis = getRotatedAxis(((Orientable) data).getAxis(), r); ((Orientable) data).setAxis(newAxis); } else if(data instanceof RedstoneWire) { Map connections = new EnumMap<>(BlockFace.class); diff --git a/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/Buffer.java b/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/Buffer.java new file mode 100644 index 000000000..319534b78 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/Buffer.java @@ -0,0 +1,14 @@ +package com.dfsek.terra.api.structures.structure.buffer; + +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.structures.structure.buffer.items.BufferedItem; + +public interface Buffer { + Buffer addItem(BufferedItem item, Location location); + + Location getOrigin(); + + String getMark(Location location); + + Buffer setMark(String mark, Location location); +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/Cell.java b/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/Cell.java new file mode 100644 index 000000000..faf4860ab --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/Cell.java @@ -0,0 +1,30 @@ +package com.dfsek.terra.api.structures.structure.buffer; + +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.structures.structure.buffer.items.BufferedItem; +import com.dfsek.terra.api.util.GlueList; + +import java.util.List; + +public class Cell implements BufferedItem { + private final List items = new GlueList<>(); + private String mark = null; + + + @Override + public void paste(Location origin) { + items.forEach(item -> item.paste(origin)); + } + + public void add(BufferedItem item) { + items.add(item); + } + + public String getMark() { + return mark; + } + + public void setMark(String mark) { + this.mark = mark; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/DirectBuffer.java b/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/DirectBuffer.java new file mode 100644 index 000000000..40881ec0c --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/DirectBuffer.java @@ -0,0 +1,41 @@ +package com.dfsek.terra.api.structures.structure.buffer; + +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.structures.structure.buffer.items.BufferedItem; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * Buffer implementation that directly pastes to the world. + */ +public class DirectBuffer implements Buffer { + private final Location origin; + private final Map marks = new LinkedHashMap<>(); + + public DirectBuffer(Location origin) { + this.origin = origin; + } + + @Override + public Buffer addItem(BufferedItem item, Location location) { + item.paste(origin.clone().add(location)); + return this; + } + + @Override + public Location getOrigin() { + return origin; + } + + @Override + public String getMark(Location location) { + return marks.get(location); + } + + @Override + public Buffer setMark(String mark, Location location) { + marks.put(location, mark); + return this; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/IntermediateBuffer.java b/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/IntermediateBuffer.java new file mode 100644 index 000000000..34250571f --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/IntermediateBuffer.java @@ -0,0 +1,36 @@ +package com.dfsek.terra.api.structures.structure.buffer; + +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.math.vector.Vector3; +import com.dfsek.terra.api.structures.structure.buffer.items.BufferedItem; + +public class IntermediateBuffer implements Buffer { + private final Buffer original; + private final Vector3 offset; + + public IntermediateBuffer(Buffer original, Vector3 offset) { + this.original = original; + this.offset = offset.clone(); + } + + @Override + public Buffer addItem(BufferedItem item, Location location) { + return original.addItem(item, location.add(offset)); + } + + @Override + public Location getOrigin() { + return original.getOrigin().clone().add(offset); + } + + @Override + public String getMark(Location location) { + return original.getMark(location.add(offset)); + } + + @Override + public Buffer setMark(String mark, Location location) { + original.setMark(mark, location.add(offset)); + return this; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/StructureBuffer.java b/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/StructureBuffer.java new file mode 100644 index 000000000..6ff3029c6 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/StructureBuffer.java @@ -0,0 +1,66 @@ +package com.dfsek.terra.api.structures.structure.buffer; + +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.platform.world.Chunk; +import com.dfsek.terra.api.structures.structure.buffer.items.BufferedItem; +import net.jafama.FastMath; + +import java.util.LinkedHashMap; +import java.util.Map; + +public class StructureBuffer implements Buffer { + private final Map bufferedItemMap = new LinkedHashMap<>(); + private final Location origin; + private boolean succeeded; + + public StructureBuffer(Location origin) { + this.origin = origin; + } + + public void paste() { + bufferedItemMap.forEach(((vector3, item) -> item.paste(origin.clone().add(vector3)))); + } + + public void paste(Chunk chunk) { + bufferedItemMap.forEach(((vector3, item) -> { + Location current = origin.clone().add(vector3); + if(FastMath.floorDiv(current.getBlockX(), 16) != chunk.getX() || FastMath.floorDiv(current.getBlockZ(), 16) != chunk.getZ()) + return; + item.paste(origin.clone().add(vector3)); + })); + } + + @Override + public Buffer addItem(BufferedItem item, Location location) { + bufferedItemMap.computeIfAbsent(location, l -> new Cell()).add(item); + return this; + } + + @Override + public String getMark(Location location) { + Cell cell = bufferedItemMap.get(location); + if(cell != null) { + return cell.getMark(); + } + return null; + } + + @Override + public Buffer setMark(String mark, Location location) { + bufferedItemMap.computeIfAbsent(location, l -> new Cell()).setMark(mark); + return this; + } + + public void setSucceeded(boolean succeeded) { + this.succeeded = succeeded; + } + + public boolean succeeded() { + return succeeded; + } + + @Override + public Location getOrigin() { + return origin.clone(); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedBlock.java b/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedBlock.java new file mode 100644 index 000000000..932efbd15 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedBlock.java @@ -0,0 +1,21 @@ +package com.dfsek.terra.api.structures.structure.buffer.items; + +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.platform.block.Block; +import com.dfsek.terra.api.platform.block.BlockData; + +public class BufferedBlock implements BufferedItem { + private final BlockData data; + private final boolean overwrite; + + public BufferedBlock(BlockData data, boolean overwrite) { + this.data = data; + this.overwrite = overwrite; + } + + @Override + public void paste(Location origin) { + Block block = origin.getBlock(); + if(overwrite || block.isEmpty()) block.setBlockData(data, false); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedEntity.java b/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedEntity.java new file mode 100644 index 000000000..f75b4383b --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedEntity.java @@ -0,0 +1,18 @@ +package com.dfsek.terra.api.structures.structure.buffer.items; + +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.platform.world.entity.EntityType; + +public class BufferedEntity implements BufferedItem { + + private final EntityType type; + + public BufferedEntity(EntityType type) { + this.type = type; + } + + @Override + public void paste(Location origin) { + origin.getWorld().spawnEntity(origin, type); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedItem.java b/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedItem.java new file mode 100644 index 000000000..a4cfa2e17 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedItem.java @@ -0,0 +1,7 @@ +package com.dfsek.terra.api.structures.structure.buffer.items; + +import com.dfsek.terra.api.math.vector.Location; + +public interface BufferedItem { + void paste(Location origin); +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedLootApplication.java b/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedLootApplication.java new file mode 100644 index 000000000..87d475a26 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedLootApplication.java @@ -0,0 +1,29 @@ +package com.dfsek.terra.api.structures.structure.buffer.items; + +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.platform.block.state.BlockState; +import com.dfsek.terra.api.platform.block.state.Container; +import com.dfsek.terra.api.structures.loot.LootTable; +import com.dfsek.terra.api.util.FastRandom; + +public class BufferedLootApplication implements BufferedItem { + private final LootTable table; + private final TerraPlugin main; + + public BufferedLootApplication(LootTable table, TerraPlugin main) { + this.table = table; + this.main = main; + } + + @Override + public void paste(Location origin) { + BlockState data = origin.getBlock().getState(); + if(!(data instanceof Container)) { + main.getLogger().severe("Failed to place loot at " + origin + "; block " + data + " is not container."); + return; + } + Container container = (Container) data; + table.fillInventory(container.getInventory(), new FastRandom(origin.hashCode())); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedPulledBlock.java b/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedPulledBlock.java new file mode 100644 index 000000000..8132a53a8 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedPulledBlock.java @@ -0,0 +1,26 @@ +package com.dfsek.terra.api.structures.structure.buffer.items; + +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.platform.block.Block; +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.block.BlockFace; + +public class BufferedPulledBlock implements BufferedItem { + private final BlockData data; + + public BufferedPulledBlock(BlockData data) { + this.data = data; + } + + @Override + public void paste(Location origin) { + Block pos = origin.getBlock(); + while(pos.getY() > 0) { + if(!pos.isEmpty()) { + pos.setBlockData(data, false); + break; + } + pos = pos.getRelative(BlockFace.DOWN); + } + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedStateManipulator.java b/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedStateManipulator.java new file mode 100644 index 000000000..f17de342d --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedStateManipulator.java @@ -0,0 +1,26 @@ +package com.dfsek.terra.api.structures.structure.buffer.items; + +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.platform.block.state.BlockState; + +public class BufferedStateManipulator implements BufferedItem { + private final TerraPlugin main; + private final String data; + + public BufferedStateManipulator(TerraPlugin main, String state) { + this.main = main; + this.data = state; + } + + @Override + public void paste(Location origin) { + BlockState state = origin.getBlock().getState(); + try { + state.applyState(data); + state.update(false); + } catch(Exception e) { + main.getLogger().warning("Could not apply BlockState at " + origin + ": " + e.getMessage()); + } + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/Char.java b/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/Char.java new file mode 100644 index 000000000..5b655cd31 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/Char.java @@ -0,0 +1,56 @@ +package com.dfsek.terra.api.structures.tokenizer; + +public class Char { + private final char character; + private final int index; + private final int line; + + + public Char(char character, int index, int line) { + this.character = character; + this.index = index; + this.line = line; + } + + public char getCharacter() { + return character; + } + + public int getIndex() { + return index; + } + + public int getLine() { + return line; + } + + public boolean isWhitespace() { + return Character.isWhitespace(character); + } + + public boolean isNewLine() { + return character == '\n'; + } + + public boolean isDigit() { + return Character.isDigit(character); + } + + public boolean is(char... tests) { + for(char test : tests) { + if(test == character && test != '\0') { + return true; + } + } + return false; + } + + public boolean isEOF() { + return character == '\0'; + } + + @Override + public String toString() { + return Character.toString(character); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/Lookahead.java b/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/Lookahead.java new file mode 100644 index 000000000..cfbec6d6b --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/Lookahead.java @@ -0,0 +1,121 @@ +package com.dfsek.terra.api.structures.tokenizer; + +import com.dfsek.terra.api.util.GlueList; + +import java.io.IOException; +import java.io.Reader; +import java.util.List; + +/** + * Stream-like data structure that allows viewing future elements without consuming current. + */ +public class Lookahead { + private final List buffer = new GlueList<>(); + private final Reader input; + private int index = 0; + private int line = 0; + private boolean end = false; + + public Lookahead(Reader r) { + this.input = r; + } + + /** + * Get the current character without consuming it. + * + * @return current character + */ + public Char current() { + return next(0); + } + + + /** + * Consume and return one character. + * + * @return Character that was consumed. + */ + public Char consume() { + Char consumed = current(); + consume(1); + return consumed; + } + + /** + * Fetch the next character. + * + * @return Next character + */ + private Char fetch() { + try { + int c = input.read(); + if(c == -1) return null; + if(c == '\n') { + line++; + index = 0; + } + index++; + return new Char((char) c, line, index); + } catch(IOException e) { + e.printStackTrace(); + return null; + } + } + + /** + * Fetch a future character without consuming it. + * + * @param ahead Distance ahead to peek + * @return Character + */ + public Char next(int ahead) { + if(ahead < 0) throw new IllegalArgumentException(); + + while(buffer.size() <= ahead && !end) { + Char item = fetch(); + if(item != null) { + buffer.add(item); + } else end = true; + } + + if(ahead >= buffer.size()) { + return null; + } else return buffer.get(ahead); + } + + public int getLine() { + return line; + } + + public int getIndex() { + return index; + } + + /** + * Consume an amount of characters + * + * @param amount Number of characters to consume + */ + public void consume(int amount) { + if(amount < 0) throw new IllegalArgumentException(); + while(amount-- > 0) { + if(!buffer.isEmpty()) buffer.remove(0); // Remove top item from buffer. + else { + if(end) return; + Char item = fetch(); + if(item == null) end = true; + } + } + } + + public boolean matches(String check, boolean consume) { + if(check == null) return false; + + for(int i = 0; i < check.length(); i++) { + if(!next(i).is(check.charAt(i))) return false; + } + + if(consume) consume(check.length()); // Consume string + return true; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/Position.java b/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/Position.java new file mode 100644 index 000000000..17d319edb --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/Position.java @@ -0,0 +1,16 @@ +package com.dfsek.terra.api.structures.tokenizer; + +public class Position { + private final int line; + private final int index; + + public Position(int line, int index) { + this.line = line; + this.index = index; + } + + @Override + public String toString() { + return (line + 1) + ":" + index; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/Token.java b/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/Token.java new file mode 100644 index 000000000..b74a206f7 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/Token.java @@ -0,0 +1,234 @@ +package com.dfsek.terra.api.structures.tokenizer; + +public class Token { + private final String content; + private final Type type; + private final Position start; + + public Token(String content, Type type, Position start) { + this.content = content; + this.type = type; + this.start = start; + } + + public Type getType() { + return type; + } + + public String getContent() { + return content; + } + + public Position getPosition() { + return start; + } + + @Override + public String toString() { + return type + ": '" + content + "'"; + } + + public boolean isConstant() { + return this.type.equals(Type.NUMBER) || this.type.equals(Type.STRING) || this.type.equals(Type.BOOLEAN); + } + + public boolean isBinaryOperator() { + return type.equals(Type.ADDITION_OPERATOR) + || type.equals(Type.SUBTRACTION_OPERATOR) + || type.equals(Type.MULTIPLICATION_OPERATOR) + || type.equals(Type.DIVISION_OPERATOR) + || type.equals(Type.EQUALS_OPERATOR) + || type.equals(Type.NOT_EQUALS_OPERATOR) + || type.equals(Type.LESS_THAN_OPERATOR) + || type.equals(Type.GREATER_THAN_OPERATOR) + || type.equals(Type.LESS_THAN_OR_EQUALS_OPERATOR) + || type.equals(Type.GREATER_THAN_OR_EQUALS_OPERATOR) + || type.equals(Type.BOOLEAN_OR) + || type.equals(Type.BOOLEAN_AND) + || type.equals(Type.MODULO_OPERATOR); + } + + public boolean isStrictNumericOperator() { + return type.equals(Type.SUBTRACTION_OPERATOR) + || type.equals(Type.MULTIPLICATION_OPERATOR) + || type.equals(Type.DIVISION_OPERATOR) + || type.equals(Type.GREATER_THAN_OPERATOR) + || type.equals(Type.LESS_THAN_OPERATOR) + || type.equals(Type.LESS_THAN_OR_EQUALS_OPERATOR) + || type.equals(Type.GREATER_THAN_OR_EQUALS_OPERATOR) + || type.equals(Type.MODULO_OPERATOR); + } + + public boolean isStrictBooleanOperator() { + return type.equals(Type.BOOLEAN_AND) + || type.equals(Type.BOOLEAN_OR); + } + + public boolean isVariableDeclaration() { + return type.equals(Type.STRING_VARIABLE) + || type.equals(Type.BOOLEAN_VARIABLE) + || type.equals(Type.NUMBER_VARIABLE); + } + + public boolean isLoopLike() { + return type.equals(Type.IF_STATEMENT) + || type.equals(Type.WHILE_LOOP) + || type.equals(Type.FOR_LOOP); + } + + public boolean isIdentifier() { + return type.equals(Type.IDENTIFIER); + } + + public enum Type { + /** + * Function identifier or language keyword + */ + IDENTIFIER, + + /** + * Numeric literal + */ + NUMBER, + /** + * String literal + */ + STRING, + /** + * Boolean literal + */ + BOOLEAN, + /** + * Beginning of group + */ + GROUP_BEGIN, + /** + * Ending of group + */ + GROUP_END, + /** + * End of statement + */ + STATEMENT_END, + /** + * Argument separator + */ + SEPARATOR, + /** + * Beginning of code block + */ + BLOCK_BEGIN, + /** + * End of code block + */ + BLOCK_END, + /** + * assignment operator + */ + ASSIGNMENT, + /** + * Boolean equals operator + */ + EQUALS_OPERATOR, + /** + * Boolean not equals operator + */ + NOT_EQUALS_OPERATOR, + /** + * Boolean greater than operator + */ + GREATER_THAN_OPERATOR, + /** + * Boolean less than operator + */ + LESS_THAN_OPERATOR, + /** + * Boolean greater than or equal to operator + */ + GREATER_THAN_OR_EQUALS_OPERATOR, + /** + * Boolean less than or equal to operator + */ + LESS_THAN_OR_EQUALS_OPERATOR, + /** + * Addition/concatenation operator + */ + ADDITION_OPERATOR, + /** + * Subtraction operator + */ + SUBTRACTION_OPERATOR, + /** + * Multiplication operator + */ + MULTIPLICATION_OPERATOR, + /** + * Division operator + */ + DIVISION_OPERATOR, + /** + * Modulo operator. + */ + MODULO_OPERATOR, + /** + * Boolean not operator + */ + BOOLEAN_NOT, + /** + * Boolean or + */ + BOOLEAN_OR, + /** + * Boolean and + */ + BOOLEAN_AND, + /** + * Numeric variable declaration + */ + NUMBER_VARIABLE, + /** + * String variable declaration + */ + STRING_VARIABLE, + /** + * Boolean variable declaration + */ + BOOLEAN_VARIABLE, + /** + * If statement declaration + */ + IF_STATEMENT, + /** + * While loop declaration + */ + WHILE_LOOP, + /** + * Return statement + */ + RETURN, + /** + * Continue statement + */ + CONTINUE, + /** + * Break statement + */ + BREAK, + /** + * Fail statement. Like return keyword, but specifies that generation has failed. + */ + FAIL, + /** + * ID declaration + */ + ID, + /** + * For loop initializer token + */ + FOR_LOOP, + /** + * Else keyword + */ + ELSE + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/Tokenizer.java b/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/Tokenizer.java new file mode 100644 index 000000000..2fb3e4e1f --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/Tokenizer.java @@ -0,0 +1,234 @@ +package com.dfsek.terra.api.structures.tokenizer; + +import com.dfsek.terra.api.structures.parser.exceptions.ParseException; +import com.dfsek.terra.api.structures.tokenizer.exceptions.EOFException; +import com.dfsek.terra.api.structures.tokenizer.exceptions.FormatException; +import com.dfsek.terra.api.structures.tokenizer.exceptions.TokenizerException; +import com.google.common.collect.Sets; + +import java.io.StringReader; +import java.util.Set; +import java.util.Stack; + +public class Tokenizer { + public static final Set syntaxSignificant = Sets.newHashSet(';', '(', ')', '"', ',', '\\', '=', '{', '}', '+', '-', '*', '/', '>', '<', '!'); // Reserved chars + private final Lookahead reader; + private final Stack brackets = new Stack<>(); + private Token current; + + public Tokenizer(String data) throws ParseException { + reader = new Lookahead(new StringReader(data + '\0')); + current = fetchCheck(); + } + + /** + * Get the first token. + * + * @return First token + * @throws ParseException If token does not exist + */ + public Token get() throws ParseException { + if(!hasNext()) throw new ParseException("Unexpected end of input", current.getPosition()); + return current; + } + + /** + * Consume (get and remove) the first token. + * + * @return First token + * @throws ParseException If token does not exist + */ + public Token consume() throws ParseException { + if(!hasNext()) throw new ParseException("Unexpected end of input", current.getPosition()); + Token temp = current; + current = fetchCheck(); + return temp; + } + + /** + * Whether this {@code Tokenizer} contains additional tokens. + * + * @return {@code true} if more tokens are present, otherwise {@code false} + */ + public boolean hasNext() { + return !(current == null); + } + + private Token fetchCheck() throws ParseException { + Token fetch = fetch(); + if(fetch != null) { + if(fetch.getType().equals(Token.Type.BLOCK_BEGIN)) brackets.push(fetch); // Opening bracket + else if(fetch.getType().equals(Token.Type.BLOCK_END)) { + if(!brackets.isEmpty()) brackets.pop(); + else throw new ParseException("Dangling opening brace", new Position(0, 0)); + } + } else if(!brackets.isEmpty()) { + throw new ParseException("Dangling closing brace", brackets.peek().getPosition()); + } + return fetch; + } + + private Token fetch() throws TokenizerException { + while(!reader.current().isEOF() && reader.current().isWhitespace()) reader.consume(); + + while(reader.matches("//", true)) skipLine(); // Skip line if comment + + if(reader.matches("/*", true)) skipTo("*/"); // Skip multi line comment + + if(reader.current().isEOF()) return null; // EOF + + if(reader.matches("==", true)) + return new Token("==", Token.Type.EQUALS_OPERATOR, new Position(reader.getLine(), reader.getIndex())); + if(reader.matches("!=", true)) + return new Token("!=", Token.Type.NOT_EQUALS_OPERATOR, new Position(reader.getLine(), reader.getIndex())); + if(reader.matches(">=", true)) + return new Token(">=", Token.Type.GREATER_THAN_OR_EQUALS_OPERATOR, new Position(reader.getLine(), reader.getIndex())); + if(reader.matches("<=", true)) + return new Token("<=", Token.Type.LESS_THAN_OR_EQUALS_OPERATOR, new Position(reader.getLine(), reader.getIndex())); + if(reader.matches(">", true)) + return new Token(">", Token.Type.GREATER_THAN_OPERATOR, new Position(reader.getLine(), reader.getIndex())); + if(reader.matches("<", true)) + return new Token("<", Token.Type.LESS_THAN_OPERATOR, new Position(reader.getLine(), reader.getIndex())); + + + if(reader.matches("||", true)) + return new Token("||", Token.Type.BOOLEAN_OR, new Position(reader.getLine(), reader.getIndex())); + if(reader.matches("&&", true)) + return new Token("&&", Token.Type.BOOLEAN_AND, new Position(reader.getLine(), reader.getIndex())); + + + if(isNumberStart()) { + StringBuilder num = new StringBuilder(); + while(!reader.current().isEOF() && isNumberLike()) { + num.append(reader.consume()); + } + return new Token(num.toString(), Token.Type.NUMBER, new Position(reader.getLine(), reader.getIndex())); + } + + if(reader.current().is('"')) { + reader.consume(); // Consume first quote + StringBuilder string = new StringBuilder(); + boolean ignoreNext = false; + while((!reader.current().is('"')) || ignoreNext) { + if(reader.current().is('\\') && !ignoreNext) { + ignoreNext = true; + reader.consume(); + continue; + } else ignoreNext = false; + if(reader.current().isEOF()) + throw new FormatException("No end of string literal found. ", new Position(reader.getLine(), reader.getIndex())); + string.append(reader.consume()); + } + reader.consume(); // Consume last quote + + return new Token(string.toString(), Token.Type.STRING, new Position(reader.getLine(), reader.getIndex())); + } + + if(reader.current().is('(')) + return new Token(reader.consume().toString(), Token.Type.GROUP_BEGIN, new Position(reader.getLine(), reader.getIndex())); + if(reader.current().is(')')) + return new Token(reader.consume().toString(), Token.Type.GROUP_END, new Position(reader.getLine(), reader.getIndex())); + if(reader.current().is(';')) + return new Token(reader.consume().toString(), Token.Type.STATEMENT_END, new Position(reader.getLine(), reader.getIndex())); + if(reader.current().is(',')) + return new Token(reader.consume().toString(), Token.Type.SEPARATOR, new Position(reader.getLine(), reader.getIndex())); + if(reader.current().is('{')) + return new Token(reader.consume().toString(), Token.Type.BLOCK_BEGIN, new Position(reader.getLine(), reader.getIndex())); + if(reader.current().is('}')) + return new Token(reader.consume().toString(), Token.Type.BLOCK_END, new Position(reader.getLine(), reader.getIndex())); + if(reader.current().is('=')) + return new Token(reader.consume().toString(), Token.Type.ASSIGNMENT, new Position(reader.getLine(), reader.getIndex())); + if(reader.current().is('+')) + return new Token(reader.consume().toString(), Token.Type.ADDITION_OPERATOR, new Position(reader.getLine(), reader.getIndex())); + if(reader.current().is('-')) + return new Token(reader.consume().toString(), Token.Type.SUBTRACTION_OPERATOR, new Position(reader.getLine(), reader.getIndex())); + if(reader.current().is('*')) + return new Token(reader.consume().toString(), Token.Type.MULTIPLICATION_OPERATOR, new Position(reader.getLine(), reader.getIndex())); + if(reader.current().is('/')) + return new Token(reader.consume().toString(), Token.Type.DIVISION_OPERATOR, new Position(reader.getLine(), reader.getIndex())); + if(reader.current().is('%')) + return new Token(reader.consume().toString(), Token.Type.MODULO_OPERATOR, new Position(reader.getLine(), reader.getIndex())); + if(reader.current().is('!')) + return new Token(reader.consume().toString(), Token.Type.BOOLEAN_NOT, new Position(reader.getLine(), reader.getIndex())); + + StringBuilder token = new StringBuilder(); + while(!reader.current().isEOF() && !isSyntaxSignificant(reader.current().getCharacter())) { + Char c = reader.consume(); + if(c.isWhitespace()) break; + token.append(c); + } + + String tokenString = token.toString(); + + if(tokenString.equals("true")) + return new Token(tokenString, Token.Type.BOOLEAN, new Position(reader.getLine(), reader.getIndex())); + if(tokenString.equals("false")) + return new Token(tokenString, Token.Type.BOOLEAN, new Position(reader.getLine(), reader.getIndex())); + + if(tokenString.equals("num")) + return new Token(tokenString, Token.Type.NUMBER_VARIABLE, new Position(reader.getLine(), reader.getIndex())); + if(tokenString.equals("str")) + return new Token(tokenString, Token.Type.STRING_VARIABLE, new Position(reader.getLine(), reader.getIndex())); + if(tokenString.equals("bool")) + return new Token(tokenString, Token.Type.BOOLEAN_VARIABLE, new Position(reader.getLine(), reader.getIndex())); + + if(tokenString.equals("if")) + return new Token(tokenString, Token.Type.IF_STATEMENT, new Position(reader.getLine(), reader.getIndex())); + if(tokenString.equals("else")) + return new Token(tokenString, Token.Type.ELSE, new Position(reader.getLine(), reader.getIndex())); + if(tokenString.equals("while")) + return new Token(tokenString, Token.Type.WHILE_LOOP, new Position(reader.getLine(), reader.getIndex())); + if(tokenString.equals("for")) + return new Token(tokenString, Token.Type.FOR_LOOP, new Position(reader.getLine(), reader.getIndex())); + + if(tokenString.equals("return")) + return new Token(tokenString, Token.Type.RETURN, new Position(reader.getLine(), reader.getIndex())); + if(tokenString.equals("continue")) + return new Token(tokenString, Token.Type.CONTINUE, new Position(reader.getLine(), reader.getIndex())); + if(tokenString.equals("break")) + return new Token(tokenString, Token.Type.BREAK, new Position(reader.getLine(), reader.getIndex())); + if(tokenString.equals("fail")) + return new Token(tokenString, Token.Type.FAIL, new Position(reader.getLine(), reader.getIndex())); + + if(tokenString.equals("id")) + return new Token(tokenString, Token.Type.ID, new Position(reader.getLine(), reader.getIndex())); + + return new Token(tokenString, Token.Type.IDENTIFIER, new Position(reader.getLine(), reader.getIndex())); + } + + private boolean isNumberLike() { + return reader.current().isDigit() + || reader.current().is('_', '.', 'E'); + } + + private boolean isNumberStart() { + return reader.current().isDigit() + || reader.current().is('.') && reader.next(1).isDigit(); + } + + private void skipLine() { + while(!reader.current().isEOF() && !reader.current().isNewLine()) reader.consume(); + consumeWhitespace(); + } + + private void consumeWhitespace() { + while(!reader.current().isEOF() && reader.current().isWhitespace()) reader.consume(); // Consume whitespace. + } + + private void skipTo(String s) throws EOFException { + Position begin = new Position(reader.getLine(), reader.getIndex()); + while(!reader.current().isEOF()) { + if(reader.matches(s, true)) { + consumeWhitespace(); + return; + } + reader.consume(); + } + throw new EOFException("No end of expression found.", begin); + } + + public boolean isSyntaxSignificant(char c) { + return syntaxSignificant.contains(c); + } + +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/exceptions/EOFException.java b/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/exceptions/EOFException.java new file mode 100644 index 000000000..8602e6c2f --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/exceptions/EOFException.java @@ -0,0 +1,14 @@ +package com.dfsek.terra.api.structures.tokenizer.exceptions; + +import com.dfsek.terra.api.structures.tokenizer.Position; + +public class EOFException extends TokenizerException { + + public EOFException(String message, Position position) { + super(message, position); + } + + public EOFException(String message, Position position, Throwable cause) { + super(message, position, cause); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/exceptions/FormatException.java b/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/exceptions/FormatException.java new file mode 100644 index 000000000..039c8fe60 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/exceptions/FormatException.java @@ -0,0 +1,14 @@ +package com.dfsek.terra.api.structures.tokenizer.exceptions; + +import com.dfsek.terra.api.structures.tokenizer.Position; + +public class FormatException extends TokenizerException { + + public FormatException(String message, Position position) { + super(message, position); + } + + public FormatException(String message, Position position, Throwable cause) { + super(message, position, cause); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/exceptions/TokenizerException.java b/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/exceptions/TokenizerException.java new file mode 100644 index 000000000..994a65361 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/exceptions/TokenizerException.java @@ -0,0 +1,15 @@ +package com.dfsek.terra.api.structures.tokenizer.exceptions; + +import com.dfsek.terra.api.structures.parser.exceptions.ParseException; +import com.dfsek.terra.api.structures.tokenizer.Position; + +public abstract class TokenizerException extends ParseException { + + public TokenizerException(String message, Position position) { + super(message, position); + } + + public TokenizerException(String message, Position position, Throwable cause) { + super(message, position, cause); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/transform/AttemptsFailedException.java b/common/src/main/java/com/dfsek/terra/api/transform/AttemptsFailedException.java new file mode 100644 index 000000000..256ad5e57 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/transform/AttemptsFailedException.java @@ -0,0 +1,19 @@ +package com.dfsek.terra.api.transform; + +public class AttemptsFailedException extends RuntimeException { + public AttemptsFailedException() { + super(); + } + + public AttemptsFailedException(String message) { + super(message); + } + + public AttemptsFailedException(String message, Throwable cause) { + super(message, cause); + } + + public AttemptsFailedException(Throwable cause) { + super(cause); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/transform/MapTransform.java b/common/src/main/java/com/dfsek/terra/api/transform/MapTransform.java new file mode 100644 index 000000000..efd409194 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/transform/MapTransform.java @@ -0,0 +1,32 @@ +package com.dfsek.terra.api.transform; + +import java.util.HashMap; +import java.util.Map; + +public class MapTransform implements Transform { + private final Map map; + + public MapTransform(Map map) { + this.map = map; + } + + public MapTransform() { + this.map = new HashMap<>(); + } + + public MapTransform add(F from, T to) { + map.put(from, to); + return this; + } + + public MapTransform remove(F from) { + map.remove(from); + return this; + } + + @Override + public T transform(F input) throws TransformException { + if(!map.containsKey(input)) throw new TransformException("No key matching " + input.toString() + " found in map."); + return map.get(input); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/transform/NotNullValidator.java b/common/src/main/java/com/dfsek/terra/api/transform/NotNullValidator.java new file mode 100644 index 000000000..b94b7be39 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/transform/NotNullValidator.java @@ -0,0 +1,8 @@ +package com.dfsek.terra.api.transform; + +public class NotNullValidator implements Validator { + @Override + public boolean validate(T value) { + return !(value == null); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/transform/Transform.java b/common/src/main/java/com/dfsek/terra/api/transform/Transform.java new file mode 100644 index 000000000..2732b1da7 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/transform/Transform.java @@ -0,0 +1,9 @@ +package com.dfsek.terra.api.transform; + +/** + * Interface to transform data from one type to another. + */ +@FunctionalInterface +public interface Transform { + T transform(F input) throws TransformException; +} diff --git a/common/src/main/java/com/dfsek/terra/api/transform/TransformException.java b/common/src/main/java/com/dfsek/terra/api/transform/TransformException.java new file mode 100644 index 000000000..9643d9673 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/transform/TransformException.java @@ -0,0 +1,19 @@ +package com.dfsek.terra.api.transform; + +public class TransformException extends Exception { + public TransformException() { + super(); + } + + public TransformException(String message) { + super(message); + } + + public TransformException(String message, Throwable cause) { + super(message, cause); + } + + public TransformException(Throwable cause) { + super(cause); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/transform/Transformer.java b/common/src/main/java/com/dfsek/terra/api/transform/Transformer.java new file mode 100644 index 000000000..aabdf331c --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/transform/Transformer.java @@ -0,0 +1,73 @@ +package com.dfsek.terra.api.transform; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +/** + * Class to translate types from one style/platform to another. + * + * @param Data type to transform from. + * @param Data type to transform to. + */ +public class Transformer { + private final LinkedHashMap, List>> transformers; + + private Transformer(LinkedHashMap, List>> transformer) { + this.transformers = transformer; + } + + /** + * Translate data from {@code from} type to {@code to} type. + * + * @param from Data to translate + * @return Result + */ + public T translate(F from) { + List exceptions = new ArrayList<>(); + for(Map.Entry, List>> transform : transformers.entrySet()) { + try { + T result = transform.getKey().transform(from); + for(Validator validator : transform.getValue()) { + if(!validator.validate(result)) { + throw new TransformException("Failed to validate result: " + result.toString()); + } + } + return result; + } catch(Exception exception) { + exceptions.add(exception); + } + } + StringBuilder exBuilder = new StringBuilder("Could not transform input; all attempts failed: ").append(from.toString()).append("\n"); + for(Exception exception : exceptions) { + StringWriter writer = new StringWriter(); + exception.printStackTrace(new PrintWriter(writer)); + exBuilder.append("\n").append(writer.toString()); + } + throw new AttemptsFailedException(exBuilder.toString()); + } + + /** + * Builder pattern for building Transformers + * + * @param + * @param + */ + public static final class Builder { + private final LinkedHashMap, List>> transforms = new LinkedHashMap<>(); + + @SafeVarargs + public final Builder addTransform(Transform transform, Validator... validators) { + transforms.put(transform, Arrays.asList(validators)); + return this; + } + + public final Transformer build() { + return new Transformer<>(transforms); + } + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/transform/Validator.java b/common/src/main/java/com/dfsek/terra/api/transform/Validator.java new file mode 100644 index 000000000..c9ba5db9e --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/transform/Validator.java @@ -0,0 +1,6 @@ +package com.dfsek.terra.api.transform; + + +public interface Validator { + boolean validate(T value) throws TransformException; +} diff --git a/common/src/main/java/com/dfsek/terra/api/util/FastRandom.java b/common/src/main/java/com/dfsek/terra/api/util/FastRandom.java new file mode 100644 index 000000000..66d9023e7 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/util/FastRandom.java @@ -0,0 +1,65 @@ +package com.dfsek.terra.api.util; + + +import org.apache.commons.rng.core.source64.XoRoShiRo128PlusPlus; + +import java.util.Random; +import java.util.SplittableRandom; + +public class FastRandom extends Random { + + private XoRoShiRo128PlusPlus random; + + public FastRandom() { + super(); + SplittableRandom randomseed = new SplittableRandom(); + this.random = new XoRoShiRo128PlusPlus(randomseed.nextLong(), randomseed.nextLong()); + } + + public FastRandom(long seed) { + super(seed); + SplittableRandom randomseed = new SplittableRandom(seed); + this.random = new XoRoShiRo128PlusPlus(randomseed.nextLong(), randomseed.nextLong()); + } + + @Override + public boolean nextBoolean() { + return random.nextBoolean(); + } + + @Override + public int nextInt() { + return random.nextInt(); + } + + @Override + public float nextFloat() { + return (float) random.nextDouble(); + } + + @Override + public double nextDouble() { + return random.nextDouble(); + } + + @Override + public synchronized void setSeed(long seed) { + SplittableRandom randomseed = new SplittableRandom(seed); + this.random = new XoRoShiRo128PlusPlus(randomseed.nextLong(), randomseed.nextLong()); + } + + @Override + public void nextBytes(byte[] bytes) { + random.nextBytes(bytes); + } + + @Override + public int nextInt(int bound) { + return random.nextInt(bound); + } + + @Override + public long nextLong() { + return random.nextLong(); + } +} \ No newline at end of file diff --git a/common/src/main/java/com/dfsek/terra/api/util/GlueList.java b/common/src/main/java/com/dfsek/terra/api/util/GlueList.java new file mode 100644 index 000000000..e75d47777 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/util/GlueList.java @@ -0,0 +1,1048 @@ +/* + * Copyright 2015 Ertuğrul Çetin + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.dfsek.terra.api.util; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.AbstractList; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.ConcurrentModificationException; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.ListIterator; +import java.util.NoSuchElementException; +import java.util.Objects; + +import static net.jafama.FastMath.*; + + +/** + * GlueList is a brand new List implementation which is way faster than ArrayList and LinkedList. + * This implementation inspired from ArrayList and LinkedList working mechanism. + *
+ * Nodes holding data in arrays, in the beginning the world just like ArrayList ,inserts data into array one by one when there is no space for insertion to array + * new Node will be created and linked with the last Node. + *
+ * The array which belongs to newly created node has half of the size of list , just like ArrayList. + * In ArrayList when there is no space for it it creates new array with double of old size and inserts old data into new one. + * Unlike ArrayList GlueList does it dynamically way with creating new node so old data does NOT have to be moved to another array. + * You can think that GlueList is dynamic version of ArrayList. + *
+ * Adding and removing operations much faster than ArrayList and LinkedList. + * Searching operations nearly same with ArrayList and way better than LinkedList. + *

+ * Best Case
+ * Add O(1)
+ * Remove O(1)
+ * Search O(1)
+ * Access O(1) + *

+ * "m" number of created nodes.
+ * "n" size of node array.
+ * If you insert 10_000_000 record into List there will be just 36 nodes.

+ * Worst Case
+ * Add O(n*m)
+ * Remove O(n*m)
+ * Search O(m)
+ * Access O(m) + * + * version v1.0 + * + * Date: 03.11.2015 + * + * + * @author Ertuğrul Çetin ~ ertu.ctn@gmail.com + * @see Collection + * @see List + * @see LinkedList + * @see ArrayList + * @param the type of elements held in this collection + */ +public class GlueList extends AbstractList implements List, Cloneable, Serializable { + + transient Node first; + transient Node last; + + int size; + + int initialCapacity; + + private static final int DEFAULT_CAPACITY = 10; + + private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; + + public GlueList() { + + Node initNode = new Node<>(null, null, 0, DEFAULT_CAPACITY); + + first = initNode; + last = initNode; + } + + public GlueList(int initialCapacity) { + + this.initialCapacity = (initialCapacity > MAX_ARRAY_SIZE) ? MAX_ARRAY_SIZE : initialCapacity; + + Node initNode = new Node<>(null, null, 0, initialCapacity); + + first = initNode; + last = initNode; + } + + public GlueList(Collection c) { + + Objects.requireNonNull(c); + + Object[] arr = c.toArray(); + + int len = arr.length; + + if (len != 0) { + + Node initNode = new Node<>(null, null, 0, len); + + first = initNode; + last = initNode; + + System.arraycopy(arr, 0, last.elementData, 0, len); + + last.elementDataPointer += len; + } else { + + Node initNode = new Node<>(null, null, 0, DEFAULT_CAPACITY); + + first = initNode; + last = initNode; + } + + modCount++; + size += len; + } + + @Override + public boolean add(T element) { + + Node l = last; + + if (l.isAddable()) { + l.add(element); + } else { + Node newNode = new Node<>(l, null, size); + newNode.add(element); + last = newNode; + l.next = last; + } + + modCount++; + size++; + + return true; + } + + @SuppressWarnings("unchecked") + @Override + public void add(int index, T element) { + + rangeCheckForAdd(index); + + Node node = getNodeForAdd(index); + + if (node == null) { + + Node l = last; + + Node newNode = new Node<>(l, null, size); + + last = newNode; + + l.next = last; + + node = newNode; + } + + //if it is last and has extra space for element... + if (node == last && node.elementData.length - node.elementDataPointer > 0) { + + int nodeArrIndex = index - node.startingIndex; + + System.arraycopy(node.elementData, nodeArrIndex, node.elementData, nodeArrIndex + 1, node.elementDataPointer - nodeArrIndex); + + node.elementData[nodeArrIndex] = element; + + if (nodeArrIndex > 0) { + System.arraycopy(node.elementData, 0, node.elementData, 0, nodeArrIndex); + } + + node.elementDataPointer++; + } else { + + int newLen = node.elementData.length + 1; + T[] newElementData = (T[]) new Object[newLen]; + + int nodeArrIndex = index - node.startingIndex; + + System.arraycopy(node.elementData, nodeArrIndex, newElementData, nodeArrIndex + 1, node.elementDataPointer - nodeArrIndex); + + newElementData[nodeArrIndex] = element; + + if (nodeArrIndex > 0) { + System.arraycopy(node.elementData, 0, newElementData, 0, nodeArrIndex); + } + + node.elementData = newElementData; + node.endingIndex++; + node.elementDataPointer++; + } + + updateNodesAfterAdd(node); + + modCount++; + size++; + } + + private void rangeCheckForAdd(int index) { + + if (index > size || index < 0) { + throw new ArrayIndexOutOfBoundsException(index); + } + } + + private void updateNodesAfterAdd(Node nodeFrom) { + + for (Node node = nodeFrom.next; node != null; node = node.next) { + + node.startingIndex++; + node.endingIndex++; + } + } + + @SuppressWarnings("unchecked") + @Override + public boolean addAll(Collection c) { + + Objects.requireNonNull(c); + + Object[] collection = c.toArray(); + + int len = collection.length; + + if (len == 0) { + return false; + } + + if (size == 0) { + + if (initialCapacity >= len) { + System.arraycopy(collection, 0, last.elementData, 0, len); + } else { + last.elementData = Arrays.copyOf((T[]) collection, len); + last.endingIndex = len - 1; + } + + last.elementDataPointer += len; + + modCount++; + size += len; + + return true; + } + + int elementDataLen = last.elementData.length; + int elementSize = last.elementDataPointer; + + int remainedStorage = elementDataLen - elementSize; + + if (remainedStorage == 0) { + + Node l = last; + + int newLen = (size >>> 1); + int initialLen = (len > newLen) ? len : newLen; + + Node newNode = new Node<>(l, null, size, initialLen); + + System.arraycopy(collection, 0, newNode.elementData, 0, len); + + newNode.elementDataPointer += len; + + last = newNode; + l.next = last; + + modCount++; + size += len; + + return true; + } + + if (len <= remainedStorage) { + + System.arraycopy(collection, 0, last.elementData, elementSize, len); + + last.elementDataPointer += len; + + modCount++; + size += len; + + return true; + } + + if (len > remainedStorage) { + + System.arraycopy(collection, 0, last.elementData, elementSize, remainedStorage); + + last.elementDataPointer += remainedStorage; + size += remainedStorage; + + int newLen = (size >>> 1); + int remainedDataLen = len - remainedStorage; + + int initialLen = (newLen > remainedDataLen) ? newLen : remainedDataLen; + + Node l = last; + + Node newNode = new Node<>(l, null, size, initialLen); + + System.arraycopy(collection, remainedStorage, newNode.elementData, 0, remainedDataLen); + + newNode.elementDataPointer += remainedDataLen; + + last = newNode; + l.next = last; + + modCount++; + size += remainedDataLen; + + return true; + } + + return false; + } + + @Override + public T set(int index, T element) { + + rangeCheck(index); + + Node node = getNode(index); + + int nodeArrIndex = index - node.startingIndex; + + T oldValue = node.elementData[nodeArrIndex]; + + node.elementData[nodeArrIndex] = element; + + return oldValue; + } + + @Override + public T get(int index) { + + rangeCheck(index); + + Node node = getNode(index); + + return node.elementData[index - node.startingIndex]; + } + + @Override + public int indexOf(Object o) { + + int index = 0; + + if (o == null) { + + for (Node node = first; node != null; node = node.next) { + for (int i = 0; i < node.elementDataPointer; i++) { + if (node.elementData[i] == null) { + return index; + } + index++; + } + } + } else { + + for (Node node = first; node != null; node = node.next) { + for (int i = 0; i < node.elementDataPointer; i++) { + if (o.equals(node.elementData[i])) { + return index; + } + index++; + } + } + } + + return -1; + } + + @Override + public int lastIndexOf(Object o) { + + int index = size - 1; + + if (o == null) { + for (Node node = last; node != null; node = node.pre) { + for (int i = node.elementDataPointer - 1; i >= 0; i--) { + if (node.elementData[i] == null) { + return index; + } + index--; + } + } + } else { + + for (Node node = last; node != null; node = node.pre) { + for (int i = node.elementDataPointer - 1; i >= 0; i--) { + if (o.equals(node.elementData[i])) { + return index; + } + index--; + } + } + } + + return -1; + } + + @Override + public boolean contains(Object o) { + return indexOf(o) != -1; + } + + @SuppressWarnings("unchecked") + @Override + public T remove(int index) { + + rangeCheck(index); + + Node node; + + if (size == 2 && first != last) { + + Node newNode = new Node<>(null, null, 0, 2); + newNode.add(first.elementData[0]); + newNode.add(last.elementData[0]); + + node = first = last = newNode; + } else { + node = getNode(index); + } + + T[] elementData = node.elementData; + + int elementSize = node.elementDataPointer; + + int nodeArrIndex = index - node.startingIndex; + + T oldValue = elementData[nodeArrIndex]; + + int numMoved = elementSize - nodeArrIndex - 1; + + if (numMoved > 0) { + System.arraycopy(node.elementData, nodeArrIndex + 1, node.elementData, nodeArrIndex, numMoved); + } + + if (first == last || node == last) { + node.elementData[elementSize - 1] = null; + } else { + node.elementData = Arrays.copyOf(node.elementData, elementSize - 1); + node.endingIndex = (--node.endingIndex < 0) ? 0 : node.endingIndex; + } + + node.elementDataPointer--; + + updateNodesAfterRemove(node); + + if (node.elementDataPointer == 0 && first != last) { + + Node next = node.next; + Node prev = node.pre; + + if (prev == null) { + first = next; + } else { + prev.next = next; + node.pre = null; + } + + if (next == null) { + last = prev; + } else { + next.pre = prev; + node.next = null; + } + + node.elementData = null; + } + + size--; + modCount++; + + return oldValue; + } + + @Override + public boolean removeAll(Collection c) { + + Objects.requireNonNull(c); + + Object[] arr = c.toArray(); + if (arr.length == 0) { + return false; + } + + boolean isModified = false; + + for (Object o : arr) { + isModified |= remove(o); + } + + return isModified; + } + + @Override + public boolean retainAll(Collection c) { + + Objects.requireNonNull(c); + + Object[] arr = c.toArray(); + if (arr.length == 0) { + return false; + } + + boolean isModified = false; + + Object[] elements = toArray(); + + for (Object element : elements) { + + if (!c.contains(element)) { + isModified |= remove(element); + } + } + + return isModified; + } + + @Override + public boolean remove(Object o) { + + int index = indexOf(o); + + if (index != -1) { + remove(index); + return true; + } else { + return false; + } + } + + private void updateNodesAfterRemove(Node fromNode) { + + for (Node node = fromNode.next; node != null; node = node.next) { + + node.startingIndex = (--node.startingIndex < 0) ? 0 : node.startingIndex; + node.endingIndex = (--node.endingIndex < 0) ? 0 : node.endingIndex; + } + } + + private Node getNode(int index) { + + int firstStartingIndex = first.startingIndex; + int firstEndingIndex = first.endingIndex; + + int firstMinDistance = min(abs(index - firstStartingIndex), abs(index - firstEndingIndex)); + + int lastStartingIndex = last.startingIndex; + int lastEndingIndex = last.endingIndex; + + int lastMinDistance = min(abs(index - lastStartingIndex), abs(index - lastEndingIndex)); + + if (firstMinDistance <= lastMinDistance) { + + Node node = first; + do { + + if (node.startingIndex <= index && index <= node.endingIndex) { + return node; + } + + node = node.next; + } while (true); + } else { + + Node node = last; + do { + + if (node.startingIndex <= index && index <= node.endingIndex) { + return node; + } + + node = node.pre; + } while (true); + } + } + + private Node getNodeForAdd(int index) { + + if (index == size && !(last.startingIndex <= index && index <= last.endingIndex)) { + return null; + } + + return getNode(index); + } + + private void rangeCheck(int index) { + + if (index >= size || index < 0) { + throw new ArrayIndexOutOfBoundsException(index); + } + } + + @Override + public void clear() { + + for (Node node = first; node != null; ) { + + Node next = node.next; + + node.next = null; + node.pre = null; + node.elementData = null; + + node = next; + } + + first = last = null; + + int capacity = min(MAX_ARRAY_SIZE, max(size, max(initialCapacity, DEFAULT_CAPACITY))); + + Node initNode = new Node<>(null, null, 0, capacity); + + initialCapacity = capacity; + + first = initNode; + last = initNode; + + modCount++; + size = 0; + } + + public void trimToSize() { + + int pointer = last.elementDataPointer; + int arrLen = last.elementData.length; + + if (pointer < arrLen && arrLen > 2) { + + if (pointer < 2) { + last.elementData = Arrays.copyOf(last.elementData, 2); + last.endingIndex -= arrLen - 2; + } else { + last.elementData = Arrays.copyOf(last.elementData, pointer); + last.endingIndex -= arrLen - pointer; + } + } + } + + @Override + public List subList(int fromIndex, int toIndex) { + return super.subList(fromIndex, toIndex); + } + + @Override + public Object[] toArray() { + + Object[] objects = new Object[size]; + + int i = 0; + for (Node node = first; node != null; node = node.next) { + + int len = node.elementDataPointer; + + if (len > 0) { + System.arraycopy(node.elementData, 0, objects, i, len); + } + + i += len; + } + + return objects; + } + + @SuppressWarnings("unchecked") + @Override + public T[] toArray(T[] a) { + return (T[]) Arrays.copyOf(toArray(), size, a.getClass()); + } + + public boolean isEmpty() { + return size == 0; + } + + @Override + public Iterator iterator() { + return new Itr(); + } + + @SuppressWarnings("unchecked") + @Override + public Object clone() { + + try { + com.dfsek.terra.api.util.GlueList clone = (com.dfsek.terra.api.util.GlueList) super.clone(); + + clone.first = clone.last = null; + + int capacity = min(MAX_ARRAY_SIZE, max(clone.size, max(clone.initialCapacity, DEFAULT_CAPACITY))); + + Node initNode = new Node<>(null, null, 0, capacity); + + clone.initialCapacity = capacity; + + clone.first = clone.last = initNode; + + clone.modCount = 0; + clone.size = 0; + + for(Node node = first; node != null; node = node.next) { + + for(int i = 0; i < node.elementDataPointer; i++) { + clone.add(node.elementData[i]); + } + } + + return clone; + } catch(CloneNotSupportedException e) { + throw new InternalError(); + } + } + + @Override + public ListIterator listIterator(int index) { + + checkPositionIndex(index); + + return new ListItr(index); + } + + private void checkPositionIndex(int index) { + + if(!(index >= 0 && index <= size)) { + throw new ArrayIndexOutOfBoundsException(index); + } + } + + @Override + public ListIterator listIterator() { + return new ListItr(0); + } + + private class Itr implements Iterator { + + Node node = first; + + int i = 0;//inner-array index + int j = 0;//total index -> cursor + + int lastReturn = -1; + + int expectedModCount = modCount; + int elementDataPointer = node.elementDataPointer; + + @Override + public boolean hasNext() { + return j != size; + } + + @Override + public T next() { + + checkForComodification(); + + if (j >= size) { + throw new NoSuchElementException(); + } + + if (j >= last.endingIndex + 1) { + throw new ConcurrentModificationException(); + } + + if (j == 0) {// it's for listIterator.when node becomes null. + node = first; + elementDataPointer = node.elementDataPointer; + i = 0; + } + + T val = node.elementData[i++]; + + if (i >= elementDataPointer) { + node = node.next; + i = 0; + elementDataPointer = (node != null) ? node.elementDataPointer : 0; + } + + lastReturn = j++; + + return val; + } + + @Override + public void remove() { + + if (lastReturn < 0) { + throw new IllegalStateException(); + } + + checkForComodification(); + + try { + com.dfsek.terra.api.util.GlueList.this.remove(lastReturn); + + j = lastReturn; + + lastReturn = -1; + + i = (--i < 0) ? 0 : i; + + elementDataPointer = (node != null) ? node.elementDataPointer : 0; + + expectedModCount = modCount; + } catch (IndexOutOfBoundsException e) { + throw new ConcurrentModificationException(); + } + } + + void checkForComodification() { + if (modCount != expectedModCount) { + throw new ConcurrentModificationException(); + } + } + } + + @Override + public int size() { + return size; + } + + private class ListItr extends Itr implements ListIterator { + + public ListItr(int index) { + node = (index == size) ? last : getNode(index); + j = index; + i = index - node.startingIndex; + elementDataPointer = node.elementDataPointer; + } + + @Override + public boolean hasPrevious() { + return j != 0; + } + + @Override + public T previous() { + + checkForComodification(); + + int temp = j - 1; + + if (temp < 0) { + throw new NoSuchElementException(); + } + + if (temp >= last.endingIndex + 1) { + throw new ConcurrentModificationException(); + } + + if (j == size) { + + node = last; + + elementDataPointer = node.elementDataPointer; + + i = elementDataPointer; + } + + int index = j - node.startingIndex; + if (index == 0) { + + node = node.pre; + + elementDataPointer = node.elementDataPointer; + + i = elementDataPointer; + } + + T val = node.elementData[--i]; + + if (i < 0) { + node = node.pre; + i = (node != null) ? node.elementDataPointer : 0; + } + + j = temp; + + lastReturn = j; + + return val; + } + + @Override + public int nextIndex() { + return j; + } + + @Override + public int previousIndex() { + return j - 1; + } + + @Override + public void set(T t) { + + if (lastReturn < 0) { + throw new IllegalStateException(); + } + + checkForComodification(); + + try { + com.dfsek.terra.api.util.GlueList.this.set(lastReturn, t); + } catch (IndexOutOfBoundsException e) { + throw new ConcurrentModificationException(); + } + } + + @Override + public void add(T t) { + + checkForComodification(); + + try { + int temp = j; + + com.dfsek.terra.api.util.GlueList.this.add(temp, t); + + j = temp + 1; + + lastReturn = -1; + + i++; + elementDataPointer = (node != null) ? node.elementDataPointer : 0; + + expectedModCount = modCount; + } catch (IndexOutOfBoundsException e) { + throw new ConcurrentModificationException(); + } + } + } + + private void writeObject(ObjectOutputStream s) throws IOException { + + int expectedModCount = modCount; + + s.defaultWriteObject(); + + s.writeInt(size); + + for (Node node = first; node != null; node = node.next) { + for (int i = 0; i < node.elementDataPointer; i++) { + s.writeObject(node.elementData[i]); + } + } + + if (modCount != expectedModCount) { + throw new ConcurrentModificationException(); + } + } + + + @SuppressWarnings("unchecked") + private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { + + clear(); + + s.defaultReadObject(); + + int size = s.readInt(); + + for (int i = 0; i < size; i++) { + last.add((T) s.readObject()); + } + } + + static class Node { + + Node pre; + Node next; + + int listSize; + + int startingIndex; + int endingIndex; + + T[] elementData; + int elementDataPointer; + + @SuppressWarnings("unchecked") + Node(Node pre, Node next, int listSize) { + this.pre = pre; + this.next = next; + this.listSize = listSize; + this.elementData = (T[]) new Object[listSize >>> 1]; + this.startingIndex = listSize; + this.endingIndex = listSize + elementData.length - 1; + } + + Node(Node pre, Node next, int listSize, int initialCapacity) { + this.pre = pre; + this.next = next; + this.listSize = listSize; + this.elementData = createElementData(initialCapacity); + this.startingIndex = listSize; + this.endingIndex = listSize + elementData.length - 1; + } + + @SuppressWarnings("unchecked") + T[] createElementData(int capacity) { + + if (capacity == 0 || capacity == 1) { + return (T[]) new Object[DEFAULT_CAPACITY]; + } else if (capacity > 1) { + return (T[]) new Object[capacity]; + } else { + throw new IllegalArgumentException("Illegal Capacity: " + capacity); + } + } + + boolean isAddable() { + return elementDataPointer < elementData.length; + } + + void add(T element) { + elementData[elementDataPointer++] = element; + } + + @Override + public String toString() { + return String.format("[sIndex: %d - eIndex: %d | elementDataPointer: %d | elementDataLength: %d]", startingIndex, endingIndex, elementDataPointer, elementData.length); + } + } +} \ No newline at end of file diff --git a/common/src/main/java/com/dfsek/terra/api/util/JarUtil.java b/common/src/main/java/com/dfsek/terra/api/util/JarUtil.java new file mode 100644 index 000000000..9109cacfd --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/util/JarUtil.java @@ -0,0 +1,38 @@ +package com.dfsek.terra.api.util; + +import com.dfsek.terra.debug.Debug; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Enumeration; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; + +public class JarUtil { + public static void copyResourcesToDirectory(JarFile fromJar, String sourceDir, String destDir) throws IOException { + for(Enumeration entries = fromJar.entries(); entries.hasMoreElements(); ) { + JarEntry entry = entries.nextElement(); + if(entry.getName().startsWith(sourceDir + "/") && ! entry.isDirectory()) { + File dest = new File(destDir + File.separator + entry.getName().substring(sourceDir.length() + 1)); + if(dest.exists()) continue; + File parent = dest.getParentFile(); + if(parent != null) { + parent.mkdirs(); + } + Debug.info("Output does not already exist. Creating... "); + try(FileOutputStream out = new FileOutputStream(dest); InputStream in = fromJar.getInputStream(entry)) { + byte[] buffer = new byte[(8192)]; + + int s; + while((s = in.read(buffer)) > 0) { + out.write(buffer, 0, s); + } + } catch(IOException e) { + throw new IOException("Could not copy asset from jar file", e); + } + } + } + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/util/SerializationUtil.java b/common/src/main/java/com/dfsek/terra/api/util/SerializationUtil.java new file mode 100644 index 000000000..3b6c781ec --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/util/SerializationUtil.java @@ -0,0 +1,70 @@ +package com.dfsek.terra.api.util; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.ObjectStreamClass; +import java.io.Serializable; +import java.lang.reflect.Field; + +public class SerializationUtil { + public static Object fromFile(File f) throws IOException, ClassNotFoundException { + ObjectInputStream ois = new MovedObjectInputStream(new FileInputStream(f), "org.polydev.gaea", "com.dfsek.terra.api.gaea"); // Backwards compat with old Gaea location + Object o = ois.readObject(); + ois.close(); + return o; + } + + public static void toFile(Serializable o, File f) throws IOException { + ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(f)); + oos.writeObject(o); + oos.close(); + } + + public static class MovedObjectInputStream extends ObjectInputStream { + private final String oldNameSpace; + private final String newNameSpace; + + public MovedObjectInputStream(InputStream in, String oldNameSpace, String newNameSpace) throws IOException { + super(in); + this.oldNameSpace = oldNameSpace; + this.newNameSpace = newNameSpace; + } + + @Override + protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException { + ObjectStreamClass result = super.readClassDescriptor(); + try { + if(result.getName().contains(oldNameSpace)) { + String newClassName = result.getName().replace(oldNameSpace, newNameSpace); + Class localClass = Class.forName(newClassName); + + Field nameField = ObjectStreamClass.class.getDeclaredField("name"); + nameField.setAccessible(true); + nameField.set(result, newClassName); + + ObjectStreamClass localClassDescriptor = ObjectStreamClass.lookup(localClass); + Field suidField = ObjectStreamClass.class.getDeclaredField("suid"); + suidField.setAccessible(true); + suidField.set(result, localClassDescriptor.getSerialVersionUID()); + } + } catch(Exception e) { + throw new IOException("Exception when trying to replace namespace", e); + } + return result; + } + + @Override + protected Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { + if(desc.getName().contains(oldNameSpace)) { + String newClassName = desc.getName().replace(oldNameSpace, newNameSpace); + return Class.forName(newClassName); + } + return super.resolveClass(desc); + } + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/world/biome/Biome.java b/common/src/main/java/com/dfsek/terra/api/world/biome/Biome.java new file mode 100644 index 000000000..36a8caa4e --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/world/biome/Biome.java @@ -0,0 +1,25 @@ +package com.dfsek.terra.api.world.biome; + + +import com.dfsek.terra.api.platform.world.World; + +/** + * Interface to be implemented by a custom generator's Biome enum.
+ * Represents a custom biome, and contains methods to retrieve information about each type. + */ +public interface Biome { + + /** + * Gets the Vanilla biome to represent the custom biome. + * + * @return Biome - The Vanilla biome. + */ + com.dfsek.terra.api.platform.world.Biome getVanillaBiome(); + + /** + * Gets the BiomeTerrain instance used to generate the biome. + * + * @return BiomeTerrain - The terrain generation instance. + */ + Generator getGenerator(World w); +} diff --git a/common/src/main/java/com/dfsek/terra/api/world/biome/BiomeGrid.java b/common/src/main/java/com/dfsek/terra/api/world/biome/BiomeGrid.java new file mode 100644 index 000000000..87685a6a1 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/world/biome/BiomeGrid.java @@ -0,0 +1,114 @@ +package com.dfsek.terra.api.world.biome; + +import com.dfsek.terra.api.math.noise.samplers.FastNoiseLite; +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.world.generation.GenerationPhase; + +public abstract class BiomeGrid { + private final FastNoiseLite noiseX; + private final FastNoiseLite noiseZ; + private final int sizeX; + private final int sizeZ; + private Biome[][] grid; + + + public BiomeGrid(long seed, double freq1, double freq2, int sizeX, int sizeZ) { + this.sizeX = sizeX; + this.sizeZ = sizeZ; + this.noiseX = new FastNoiseLite((int) seed); + this.noiseZ = new FastNoiseLite((int) seed + 1); + this.noiseX.setNoiseType(FastNoiseLite.NoiseType.OpenSimplex2); + this.noiseX.setFractalType(FastNoiseLite.FractalType.FBm); + this.noiseX.setFractalOctaves(4); + this.noiseZ.setNoiseType(FastNoiseLite.NoiseType.OpenSimplex2); + this.noiseZ.setFractalType(FastNoiseLite.FractalType.FBm); + this.noiseZ.setFractalOctaves(4); + this.noiseX.setFrequency(freq1); + this.noiseZ.setFrequency(freq2); + } + + + /** + * Gets the biome at a pair of coordinates. + * + * @param x - X-coordinate at which to fetch biome + * @param z - Z-coordinate at which to fetch biome + * @return Biome - Biome at the given coordinates. + */ + public Biome getBiome(int x, int z, GenerationPhase phase) { + return grid[getBiomeNoiseX(x, z)][getBiomeNoiseZ(x, z)]; + } + + /** + * Gets the biome at a location. + * + * @param l - The location at which to fetch the biome. + * @return Biome - Biome at the given coordinates. + */ + public Biome getBiome(Location l) { + return getBiome(l, GenerationPhase.POST_GEN); + } + + public double[] getRawNoise(int x, int z) { + return new double[] {noiseX.getNoise(x, z), noiseZ.getNoise(x, z)}; + } + + /** + * Get the raw X-noise for coordinates in the Grid. + * + * @param x X coordinate + * @param z Z coordinate + * @return Normalized noise + */ + public int getBiomeNoiseX(int x, int z) { + return normalize(noiseX.getNoise(x, z), sizeX); + } + + /** + * Get the raw Z-noise for coordinates in the Grid. + * + * @param x X coordinate + * @param z Z coordinate + * @return Normalized noise + */ + public int getBiomeNoiseZ(int x, int z) { + return normalize(noiseZ.getNoise(x, z), sizeZ); + } + + public Biome[][] getGrid() { + return grid; + } + + public void setGrid(Biome[][] grid) { + if(grid.length != sizeX) throw new IllegalArgumentException("Invalid length for grid, expected " + sizeX + ", got " + grid.length); + for(Biome[] gridLayer : grid) { + if(gridLayer.length != sizeZ) throw new IllegalArgumentException("Invalid length for grid layer, expected " + sizeZ + ", got " + gridLayer.length); + } + this.grid = grid; + } + + public Biome getBiome(Location l, GenerationPhase phase) { + double biomeNoise = noiseX.getNoise(l.getBlockX(), l.getBlockZ()); + double climateNoise = noiseZ.getNoise(l.getBlockX(), l.getBlockZ()); + return grid[normalize(biomeNoise, sizeX)][normalize(climateNoise, sizeZ)]; + } + + public int getSizeX() { + return sizeX; + } + + public int getSizeZ() { + return sizeZ; + } + + /** + * Takes a noise input and normalizes it to a value between 0 and 15 inclusive. + * + * @param i - The noise value to normalize. + * @return int - The normalized value. + */ + protected int normalize(double i, int range) { + return NormalizationUtil.normalize(i, range, 4); + } + +} diff --git a/common/src/main/java/com/dfsek/terra/api/world/biome/Generator.java b/common/src/main/java/com/dfsek/terra/api/world/biome/Generator.java new file mode 100644 index 000000000..794838860 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/world/biome/Generator.java @@ -0,0 +1,27 @@ +package com.dfsek.terra.api.world.biome; + +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.world.palette.Palette; + +public interface Generator { + /** + * Gets the 3D noise at a pair of coordinates using the provided FastNoiseLite instance. + * + * @param x - The x coordinate. + * @param y - The y coordinate. + * @param z - The z coordinate. + * @return double - Noise value at the specified coordinates. + */ + double getNoise(int x, int y, int z); + + /** + * Gets the BlocPalette to generate the biome with. + * + * @return BlocPalette - The biome's palette. + */ + Palette getPalette(int y); + + boolean is2d(); + + double get2dBase(); +} diff --git a/common/src/main/java/com/dfsek/terra/api/world/biome/NormalizationUtil.java b/common/src/main/java/com/dfsek/terra/api/world/biome/NormalizationUtil.java new file mode 100644 index 000000000..8d277a275 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/world/biome/NormalizationUtil.java @@ -0,0 +1,48 @@ +package com.dfsek.terra.api.world.biome; + +import net.jafama.FastMath; + +/** + * Ultra-fast normalization utility for pre-defined lookup table based on 160 million points of Cellular noise generated from 1-octave Simplex noise. + */ +public class NormalizationUtil { + private static final double[] normalMap4 = new double[] {- 0.5522426962852478D, - 0.5356624126434326D, - 0.5250319838523865D, - 0.5172030329704285D, - 0.5108230710029602D, - 0.5051751136779785D, - 0.5003848075866699D, - 0.496286541223526D, - 0.49219056963920593D, - 0.488725870847702D, - 0.48548242449760437D, - 0.48233601450920105D, - 0.4794590473175049D, - 0.47680431604385376D, - 0.4741802513599396D, - 0.4716983437538147D, - 0.46938973665237427D, - 0.4671768844127655D, - 0.46493932604789734D, - 0.4628496468067169D, - 0.46085309982299805D, - 0.45893776416778564D, - 0.4571230709552765D, - 0.45534923672676086D, - 0.4535684585571289D, - 0.4518905282020569D, - 0.45032820105552673D, - 0.44873151183128357D, - 0.4472157657146454D, - 0.445724755525589D, - 0.4442773759365082D, - 0.44282811880111694D, - 0.44138428568840027D, - 0.43998438119888306D, - 0.43863797187805176D, - 0.4373200237751007D, - 0.43603432178497314D, - 0.4348065257072449D, - 0.4335438907146454D, - 0.43234220147132874D, - 0.4311666488647461D, - 0.42999887466430664D, - 0.4288702607154846D, - 0.4277186393737793D, - 0.42660200595855713D, - 0.425540030002594D, - 0.42445454001426697D, - 0.42338213324546814D, - 0.42237231135368347D, - 0.4213787317276001D, - 0.42034342885017395D, - 0.41934314370155334D, - 0.41838738322257996D, - 0.41747593879699707D, - 0.4165368676185608D, - 0.41563472151756287D, - 0.41473135352134705D, - 0.41381341218948364D, - 0.412920743227005D, - 0.4120390713214874D, - 0.41113483905792236D, - 0.41027551889419556D, - 0.40940171480178833D, - 0.4085462987422943D, - 0.40771594643592834D, - 0.4068986475467682D, - 0.4060843288898468D, - 0.4052877426147461D, - 0.40450364351272583D, - 0.40370258688926697D, - 0.40295007824897766D, - 0.4022042751312256D, - 0.40143170952796936D, - 0.40068766474723816D, - 0.3999272882938385D, - 0.39916759729385376D, - 0.3984144926071167D, - 0.3977096378803253D, - 0.3969724774360657D, - 0.3962542712688446D, - 0.3955434262752533D, - 0.39482179284095764D, - 0.39413219690322876D, - 0.3934393525123596D, - 0.39274853467941284D, - 0.3920603394508362D, - 0.3913818895816803D, - 0.3907110095024109D, - 0.39001911878585815D, - 0.3893643021583557D, - 0.38873276114463806D, - 0.38809072971343994D, - 0.38744935393333435D, - 0.38681110739707947D, - 0.38617849349975586D, - 0.3855555057525635D, - 0.3849259316921234D, - 0.38428404927253723D, - 0.38368701934814453D, - 0.38305720686912537D, - 0.3824397325515747D, - 0.38183310627937317D, - 0.3812190294265747D, - 0.38061732053756714D, - 0.3800400495529175D, - 0.37945547699928284D, - 0.37887564301490784D, - 0.3783135712146759D, - 0.3777320683002472D, - 0.3771609365940094D, - 0.3765930235385895D, - 0.3760446608066559D, - 0.37546253204345703D, - 0.37489989399909973D, - 0.37433329224586487D, - 0.3737635910511017D, - 0.37320101261138916D, - 0.37265515327453613D, - 0.3721090257167816D, - 0.3715764880180359D, - 0.3710474967956543D, - 0.3705263137817383D, - 0.37000274658203125D, - 0.36946558952331543D, - 0.3689403533935547D, - 0.3684338629245758D, - 0.3679268956184387D, - 0.3674132525920868D, - 0.3668895363807678D, - 0.36637264490127563D, - 0.3658500015735626D, - 0.3653477430343628D, - 0.3648494482040405D, - 0.3643417954444885D, - 0.36385640501976013D, - 0.36335185170173645D, - 0.3628855347633362D, - 0.3624073565006256D, - 0.3619007468223572D, - 0.36142677068710327D, - 0.3609183132648468D, - 0.3604544401168823D, - 0.3599613606929779D, - 0.3594810962677002D, - 0.3590005338191986D, - 0.3585355281829834D, - 0.35805660486221313D, - 0.35758334398269653D, - 0.3571120500564575D, - 0.356632798910141D, - 0.35616397857666016D, - 0.3557022213935852D, - 0.35522621870040894D, - 0.35475999116897583D, - 0.3543040454387665D, - 0.3538462817668915D, - 0.35339656472206116D, - 0.35294967889785767D, - 0.3525013029575348D, - 0.35205140709877014D, - 0.3516044616699219D, - 0.3511776924133301D, - 0.3507419228553772D, - 0.350308358669281D, - 0.34987354278564453D, - 0.3494442403316498D, - 0.34901976585388184D, - 0.34858623147010803D, - 0.3481590747833252D, - 0.3477269113063812D, - 0.34729984402656555D, - 0.34686949849128723D, - 0.34644952416419983D, - 0.3460380733013153D, - 0.345601350069046D, - 0.3451806306838989D, - 0.34476256370544434D, - 0.3443388342857361D, - 0.34393346309661865D, - 0.3435156047344208D, - 0.34309715032577515D, - 0.34269776940345764D, - 0.34230056405067444D, - 0.34190237522125244D, - 0.3415068984031677D, - 0.3411085307598114D, - 0.3407077193260193D, - 0.3403150737285614D, - 0.3399060070514679D, - 0.3395008146762848D, - 0.33910876512527466D, - 0.3387194573879242D, - 0.3383338451385498D, - 0.3379477858543396D, - 0.33756473660469055D, - 0.33716049790382385D, - 0.336769163608551D, - 0.33637988567352295D, - 0.3360031843185425D, - 0.33561065793037415D, - 0.33522093296051025D, - 0.33484047651290894D, - 0.3344566524028778D, - 0.3340719938278198D, - 0.33369651436805725D, - 0.33331871032714844D, - 0.3329450190067291D, - 0.3325762152671814D, - 0.3321962356567383D, - 0.3318250775337219D, - 0.33146360516548157D, - 0.331096351146698D, - 0.3307240307331085D, - 0.33036690950393677D, - 0.3300083577632904D, - 0.3296314477920532D, - 0.32925838232040405D, - 0.3289034366607666D, - 0.32853060960769653D, - 0.3281768262386322D, - 0.32781481742858887D, - 0.32745665311813354D, - 0.3271014988422394D, - 0.3267449736595154D, - 0.32637742161750793D, - 0.32601433992385864D, - 0.3256617784500122D, - 0.325309157371521D, - 0.32495537400245667D, - 0.3246041238307953D, - 0.324260413646698D, - 0.32391706109046936D, - 0.32356011867523193D, - 0.3232196569442749D, - 0.3228764235973358D, - 0.3225192129611969D, - 0.3221615254878998D, - 0.32181763648986816D, - 0.32147231698036194D, - 0.32113757729530334D, - 0.3207913041114807D, - 0.3204527795314789D, - 0.3200984597206116D, - 0.31977012753486633D, - 0.3194332718849182D, - 0.31908634305000305D, - 0.3187503516674042D, - 0.3184075951576233D, - 0.3180627226829529D, - 0.3177427053451538D, - 0.31741446256637573D, - 0.31707704067230225D, - 0.316744863986969D, - 0.31642594933509827D, - 0.3161090612411499D, - 0.31578725576400757D, - 0.3154592216014862D, - 0.31513524055480957D, - 0.3148083984851837D, - 0.31448230147361755D, - 0.3141593337059021D, - 0.3138306438922882D, - 0.313511461019516D, - 0.3132011592388153D, - 0.31286999583244324D, - 0.31256046891212463D, - 0.31223684549331665D, - 0.3119199573993683D, - 0.31160062551498413D, - 0.31128641963005066D, - 0.31096261739730835D, - 0.3106483519077301D, - 0.31033560633659363D, - 0.31001248955726624D, - 0.30969613790512085D, - 0.3093807101249695D, - 0.3090643584728241D, - 0.3087562322616577D, - 0.3084530532360077D, - 0.3081410229206085D, - 0.30783092975616455D, - 0.3075273334980011D, - 0.30720987915992737D, - 0.3068995177745819D, - 0.30659666657447815D, - 0.3062874376773834D, - 0.3059786558151245D, - 0.305671364068985D, - 0.3053743839263916D, - 0.30506861209869385D, - 0.30476105213165283D, - 0.3044643998146057D, - 0.3041706383228302D, - 0.3038659393787384D, - 0.30357563495635986D, - 0.3032696545124054D, - 0.30296090245246887D, - 0.30266377329826355D, - 0.3023788034915924D, - 0.302080899477005D, - 0.3017835319042206D, - 0.3014954924583435D, - 0.3012062609195709D, - 0.30091601610183716D, - 0.3006187677383423D, - 0.30032220482826233D, - 0.3000366985797882D, - 0.29973816871643066D, - 0.2994519770145416D, - 0.29914233088493347D, - 0.2988555431365967D, - 0.29856425523757935D, - 0.2982824742794037D, - 0.29798826575279236D, - 0.2976938486099243D, - 0.29739657044410706D, - 0.29710277915000916D, - 0.29681164026260376D, - 0.29652127623558044D, - 0.29623138904571533D, - 0.29592910408973694D, - 0.2956419289112091D, - 0.29535165429115295D, - 0.29506999254226685D, - 0.29478344321250916D, - 0.2944985330104828D, - 0.2942177355289459D, - 0.29393965005874634D, - 0.2936561107635498D, - 0.29337379336357117D, - 0.2930947542190552D, - 0.29281559586524963D, - 0.29254022240638733D, - 0.29226312041282654D, - 0.2919958531856537D, - 0.29172608256340027D, - 0.291446328163147D, - 0.2911716103553772D, - 0.29089251160621643D, - 0.2906162738800049D, - 0.290350079536438D, - 0.29007789492607117D, - 0.28980758786201477D, - 0.28953540325164795D, - 0.2892584502696991D, - 0.2889859974384308D, - 0.2887132167816162D, - 0.2884424030780792D, - 0.28817737102508545D, - 0.2879084348678589D, - 0.28764015436172485D, - 0.2873786389827728D, - 0.28710025548934937D, - 0.28683197498321533D, - 0.28656822443008423D, - 0.28629666566848755D, - 0.28602135181427D, - 0.2857580780982971D, - 0.2854946255683899D, - 0.2852350175380707D, - 0.28497231006622314D, - 0.2847127616405487D, - 0.2844494581222534D, - 0.28418153524398804D, - 0.2839117646217346D, - 0.28364670276641846D, - 0.2833735942840576D, - 0.2831180989742279D, - 0.28285273909568787D, - 0.282595694065094D, - 0.28233304619789124D, - 0.28208285570144653D, - 0.28183260560035706D, - 0.28156495094299316D, - 0.2813194692134857D, - 0.28106340765953064D, - 0.2807980179786682D, - 0.2805359661579132D, - 0.2802804410457611D, - 0.28002557158470154D, - 0.27975931763648987D, - 0.2795126140117645D, - 0.27925795316696167D, - 0.27899473905563354D, - 0.278735488653183D, - 0.27847906947135925D, - 0.27822330594062805D, - 0.27796468138694763D, - 0.27770230174064636D, - 0.2774444818496704D, - 0.27718687057495117D, - 0.27694857120513916D, - 0.2766880989074707D, - 0.27643832564353943D, - 0.2761860489845276D, - 0.2759307324886322D, - 0.2756873071193695D, - 0.2754386067390442D, - 0.2751883268356323D, - 0.27494344115257263D, - 0.2746928334236145D, - 0.274436354637146D, - 0.27417975664138794D, - 0.2739262282848358D, - 0.27367040514945984D, - 0.2734193205833435D, - 0.273158460855484D, - 0.27291545271873474D, - 0.2726711928844452D, - 0.27241599559783936D, - 0.27216801047325134D, - 0.2719186842441559D, - 0.27167946100234985D, - 0.2714363932609558D, - 0.271190345287323D, - 0.2709449231624603D, - 0.2706972360610962D, - 0.27045026421546936D, - 0.27020177245140076D, - 0.26996636390686035D, - 0.2697167992591858D, - 0.2694661319255829D, - 0.2692175805568695D, - 0.2689802348613739D, - 0.2687402367591858D, - 0.2684989869594574D, - 0.2682455778121948D, - 0.2680189311504364D, - 0.26777616143226624D, - 0.267528235912323D, - 0.2672905921936035D, - 0.2670466899871826D, - 0.26680880784988403D, - 0.2665674090385437D, - 0.26632341742515564D, - 0.2660820782184601D, - 0.2658466100692749D, - 0.26560917496681213D, - 0.26536619663238525D, - 0.26512911915779114D, - 0.2648910880088806D, - 0.2646530270576477D, - 0.26441332697868347D, - 0.26417455077171326D, - 0.26393792033195496D, - 0.2637031376361847D, - 0.2634584307670593D, - 0.2632187306880951D, - 0.2629868984222412D, - 0.26276034116744995D, - 0.2625255584716797D, - 0.26228949427604675D, - 0.2620560824871063D, - 0.26182571053504944D, - 0.261595219373703D, - 0.2613618075847626D, - 0.26113298535346985D, - 0.2608985900878906D, - 0.26066386699676514D, - 0.26042836904525757D, - 0.2601918876171112D, - 0.25995346903800964D, - 0.2597239911556244D, - 0.25948530435562134D, - 0.25925174355506897D, - 0.25902727246284485D, - 0.25878533720970154D, - 0.2585568130016327D, - 0.25832033157348633D, - 0.25808852910995483D, - 0.25785645842552185D, - 0.2576303482055664D, - 0.25740429759025574D, - 0.25717857480049133D, - 0.2569526731967926D, - 0.25671908259391785D, - 0.25648829340934753D, - 0.25625646114349365D, - 0.2560245394706726D, - 0.25578436255455017D, - 0.2555571496486664D, - 0.25532659888267517D, - 0.25509998202323914D, - 0.2548714876174927D, - 0.2546450197696686D, - 0.2544119656085968D, - 0.25418850779533386D, - 0.25395628809928894D, - 0.25373202562332153D, - 0.2535029947757721D, - 0.2532775402069092D, - 0.2530599534511566D, - 0.25283512473106384D, - 0.2526094317436218D, - 0.2523849904537201D, - 0.25216206908226013D, - 0.2519350051879883D, - 0.2517090141773224D, - 0.2514895796775818D, - 0.2512630820274353D, - 0.25103917717933655D, - 0.2508082687854767D, - 0.25058355927467346D, - 0.25036174058914185D, - 0.2501283586025238D, - 0.24990904331207275D, - 0.249681293964386D, - 0.24945379793643951D, - 0.24923056364059448D, - 0.24901220202445984D, - 0.24878771603107452D, - 0.24855589866638184D, - 0.24833829700946808D, - 0.24811571836471558D, - 0.24789805710315704D, - 0.24767984449863434D, - 0.24746781587600708D, - 0.24724344909191132D, - 0.247017040848732D, - 0.24679675698280334D, - 0.24657492339611053D, - 0.2463507503271103D, - 0.24612344801425934D, - 0.2459094524383545D, - 0.24569448828697205D, - 0.2454809844493866D, - 0.2452625036239624D, - 0.24504707753658295D, - 0.2448272854089737D, - 0.24461260437965393D, - 0.2443927526473999D, - 0.24417124688625336D, - 0.243961900472641D, - 0.24374017119407654D, - 0.24352549016475677D, - 0.2433115839958191D, - 0.24308589100837708D, - 0.24287600815296173D, - 0.24265910685062408D, - 0.24244506657123566D, - 0.24222184717655182D, - 0.2420046031475067D, - 0.24178411066532135D, - 0.2415642887353897D, - 0.24134574830532074D, - 0.24113741517066956D, - 0.24092262983322144D, - 0.24071024358272552D, - 0.2404916137456894D, - 0.24028095602989197D, - 0.2400677651166916D, - 0.23985490202903748D, - 0.23963676393032074D, - 0.23942221701145172D, - 0.23919777572155D, - 0.23898695409297943D, - 0.23877480626106262D, - 0.2385605275630951D, - 0.23833821713924408D, - 0.23812562227249146D, - 0.23791590332984924D, - 0.2377057671546936D, - 0.23749561607837677D, - 0.2372775822877884D, - 0.23707041144371033D, - 0.23685894906520844D, - 0.23664598166942596D, - 0.2364351749420166D, - 0.23622725903987885D, - 0.23601093888282776D, - 0.23579688370227814D, - 0.2355896234512329D, - 0.2353767305612564D, - 0.23516340553760529D, - 0.23495911061763763D, - 0.23474349081516266D, - 0.23453089594841003D, - 0.234323650598526D, - 0.2341182678937912D, - 0.23391124606132507D, - 0.23369914293289185D, - 0.23348599672317505D, - 0.23327989876270294D, - 0.23307158052921295D, - 0.23286454379558563D, - 0.23266181349754333D, - 0.2324516326189041D, - 0.23224829137325287D, - 0.2320389449596405D, - 0.23183543980121613D, - 0.23162415623664856D, - 0.23141750693321228D, - 0.2312154620885849D, - 0.23101359605789185D, - 0.2308085411787033D, - 0.23060521483421326D, - 0.2303977906703949D, - 0.23019705712795258D, - 0.22999277710914612D, - 0.22978724539279938D, - 0.22957871854305267D, - 0.2293720841407776D, - 0.2291649729013443D, - 0.22895236313343048D, - 0.2287459373474121D, - 0.22854582965373993D, - 0.2283381223678589D, - 0.22812990844249725D, - 0.2279345691204071D, - 0.2277294397354126D, - 0.22752392292022705D, - 0.22731730341911316D, - 0.22711612284183502D, - 0.22691002488136292D, - 0.2267099916934967D, - 0.2265053242444992D, - 0.22630846500396729D, - 0.22610722482204437D, - 0.22590836882591248D, - 0.2257007658481598D, - 0.22550742328166962D, - 0.22530819475650787D, - 0.22511185705661774D, - 0.22490867972373962D, - 0.2247025966644287D, - 0.22450992465019226D, - 0.22430776059627533D, - 0.22410835325717926D, - 0.2239159643650055D, - 0.22370943427085876D, - 0.22351300716400146D, - 0.22331230342388153D, - 0.22311504185199738D, - 0.2229161113500595D, - 0.2227165549993515D, - 0.22251492738723755D, - 0.22231879830360413D, - 0.222111314535141D, - 0.2219131737947464D, - 0.22171789407730103D, - 0.22152048349380493D, - 0.221323162317276D, - 0.2211257964372635D, - 0.22093181312084198D, - 0.2207297384738922D, - 0.22052015364170074D, - 0.22031758725643158D, - 0.22012105584144592D, - 0.21992850303649902D, - 0.21972830593585968D, - 0.2195286750793457D, - 0.2193296104669571D, - 0.2191292941570282D, - 0.21894055604934692D, - 0.21874472498893738D, - 0.21854627132415771D, - 0.21834976971149445D, - 0.21815654635429382D, - 0.21795278787612915D, - 0.21775475144386292D, - 0.2175593227148056D, - 0.21736285090446472D, - 0.21716663241386414D, - 0.2169671356678009D, - 0.21677885949611664D, - 0.21658332645893097D, - 0.21638570725917816D, - 0.21619734168052673D, - 0.21600238978862762D, - 0.21581146121025085D, - 0.21561749279499054D, - 0.21542775630950928D, - 0.21523769199848175D, - 0.2150374948978424D, - 0.21483974158763885D, - 0.21464426815509796D, - 0.2144438624382019D, - 0.2142522931098938D, - 0.21405142545700073D, - 0.2138548493385315D, - 0.21365608274936676D, - 0.21346205472946167D, - 0.21327044069766998D, - 0.2130790650844574D, - 0.21289238333702087D, - 0.21269790828227997D, - 0.21250642836093903D, - 0.2123108059167862D, - 0.21211734414100647D, - 0.21193185448646545D, - 0.2117394357919693D, - 0.2115425020456314D, - 0.21135464310646057D, - 0.21115921437740326D, - 0.2109653651714325D, - 0.2107720673084259D, - 0.2105797827243805D, - 0.2103857845067978D, - 0.21019317209720612D, - 0.20999492704868317D, - 0.20980359613895416D, - 0.20961257815361023D, - 0.20942623913288116D, - 0.209233820438385D, - 0.20904646813869476D, - 0.2088536024093628D, - 0.20866578817367554D, - 0.20847372710704803D, - 0.20828045904636383D, - 0.20809443295001984D, - 0.20790085196495056D, - 0.20771846175193787D, - 0.20753352344036102D, - 0.20734763145446777D, - 0.20716027915477753D, - 0.2069670557975769D, - 0.20677906274795532D, - 0.20658759772777557D, - 0.20640024542808533D, - 0.20621001720428467D, - 0.2060190588235855D, - 0.20582759380340576D, - 0.20564205944538116D, - 0.20544962584972382D, - 0.2052612006664276D, - 0.2050696611404419D, - 0.2048760950565338D, - 0.2046886533498764D, - 0.20449654757976532D, - 0.20430676639080048D, - 0.2041216492652893D, - 0.20393186807632446D, - 0.20373943448066711D, - 0.20355398952960968D, - 0.20336341857910156D, - 0.20317570865154266D, - 0.20299416780471802D, - 0.2028021663427353D, - 0.20261310040950775D, - 0.20243166387081146D, - 0.20224738121032715D, - 0.20206642150878906D, - 0.20188181102275848D, - 0.20169363915920258D, - 0.2015080600976944D, - 0.2013179212808609D, - 0.20112863183021545D, - 0.20093776285648346D, - 0.20075495541095734D, - 0.2005680948495865D, - 0.2003868669271469D, - 0.20020489394664764D, - 0.20001673698425293D, - 0.19983160495758057D, - 0.1996394246816635D, - 0.19945387542247772D, - 0.19926834106445312D, - 0.19908671081066132D, - 0.1988958865404129D, - 0.19870947301387787D, - 0.19852466881275177D, - 0.19834156334400177D, - 0.19815687835216522D, - 0.19796614348888397D, - 0.19778570532798767D, - 0.19759665429592133D, - 0.19740843772888184D, - 0.19722165167331696D, - 0.19703587889671326D, - 0.19684910774230957D, - 0.19666774570941925D, - 0.1964777112007141D, - 0.19629596173763275D, - 0.19611066579818726D, - 0.1959228813648224D, - 0.19573974609375D, - 0.19555895030498505D, - 0.1953638643026352D, - 0.19518616795539856D, - 0.19500669836997986D, - 0.19482499361038208D, - 0.1946471929550171D, - 0.194466695189476D, - 0.19428104162216187D, - 0.1940973550081253D, - 0.19391575455665588D, - 0.19373083114624023D, - 0.19354969263076782D, - 0.1933702528476715D, - 0.19318976998329163D, - 0.19300931692123413D, - 0.19283118844032288D, - 0.19264520704746246D, - 0.1924607753753662D, - 0.1922810971736908D, - 0.19210171699523926D, - 0.1919163316488266D, - 0.19173482060432434D, - 0.19155943393707275D, - 0.19138532876968384D, - 0.19119767844676971D, - 0.19101446866989136D, - 0.1908339560031891D, - 0.19065433740615845D, - 0.19047808647155762D, - 0.19029070436954498D, - 0.19011610746383667D, - 0.1899399310350418D, - 0.1897595226764679D, - 0.18958213925361633D, - 0.18940195441246033D, - 0.18922074139118195D, - 0.1890474408864975D, - 0.18887129426002502D, - 0.18868793547153473D, - 0.18850910663604736D, - 0.18833401799201965D, - 0.1881609410047531D, - 0.1879805475473404D, - 0.1877983957529068D, - 0.18762242794036865D, - 0.18744400143623352D, - 0.18727153539657593D, - 0.18709038197994232D, - 0.186911940574646D, - 0.18673141300678253D, - 0.1865476816892624D, - 0.18636727333068848D, - 0.1861869841814041D, - 0.18600544333457947D, - 0.18582187592983246D, - 0.18564167618751526D, - 0.18546094000339508D, - 0.18528078496456146D, - 0.1851012110710144D, - 0.18491904437541962D, - 0.1847427636384964D, - 0.18456260859966278D, - 0.18438087403774261D, - 0.1842058300971985D, - 0.1840263456106186D, - 0.1838521808385849D, - 0.1836727261543274D, - 0.18349887430667877D, - 0.18331634998321533D, - 0.18313662707805634D, - 0.18296116590499878D, - 0.18278826773166656D, - 0.1826159507036209D, - 0.18243756890296936D, - 0.18226413428783417D, - 0.18208879232406616D, - 0.18189701437950134D, - 0.1817188709974289D, - 0.18154506385326385D, - 0.18136811256408691D, - 0.18119221925735474D, - 0.18101762235164642D, - 0.18084242939949036D, - 0.18066288530826569D, - 0.18048758804798126D, - 0.1803077757358551D, - 0.1801341325044632D, - 0.1799568086862564D, - 0.17978443205356598D, - 0.17961187660694122D, - 0.17943669855594635D, - 0.17925851047039032D, - 0.17908446490764618D, - 0.17891113460063934D, - 0.17873777449131012D, - 0.17856022715568542D, - 0.17838963866233826D, - 0.17821721732616425D, - 0.17804166674613953D, - 0.1778649091720581D, - 0.17769235372543335D, - 0.17751924693584442D, - 0.17734745144844055D, - 0.1771826446056366D, - 0.1770143061876297D, - 0.17684297263622284D, - 0.17666888236999512D, - 0.1764875054359436D, - 0.17631016671657562D, - 0.1761368215084076D, - 0.17596030235290527D, - 0.1757875680923462D, - 0.17561489343643188D, - 0.17543856799602509D, - 0.175258606672287D, - 0.17508889734745026D, - 0.1749197393655777D, - 0.17475321888923645D, - 0.17457622289657593D, - 0.17440469563007355D, - 0.17423614859580994D, - 0.17406317591667175D, - 0.1738888919353485D, - 0.17371085286140442D, - 0.17354506254196167D, - 0.1733754277229309D, - 0.17320691049098969D, - 0.17303411662578583D, - 0.17286333441734314D, - 0.1726849228143692D, - 0.17251433432102203D, - 0.1723429262638092D, - 0.17217423021793365D, - 0.17199841141700745D, - 0.17183169722557068D, - 0.17165900766849518D, - 0.17149260640144348D, - 0.1713184118270874D, - 0.17114870250225067D, - 0.17097310721874237D, - 0.17080703377723694D, - 0.1706410050392151D, - 0.17047066986560822D, - 0.17030231654644012D, - 0.17013415694236755D, - 0.16996319591999054D, - 0.1697862595319748D, - 0.16962021589279175D, - 0.1694522649049759D, - 0.16928495466709137D, - 0.1691145896911621D, - 0.16894133388996124D, - 0.16877424716949463D, - 0.1686055213212967D, - 0.16844305396080017D, - 0.16827253997325897D, - 0.16810156404972076D, - 0.16793574392795563D, - 0.16776280105113983D, - 0.16759483516216278D, - 0.16742615401744843D, - 0.16726046800613403D, - 0.16708528995513916D, - 0.16691190004348755D, - 0.16673815250396729D, - 0.16657349467277527D, - 0.16640760004520416D, - 0.1662367582321167D, - 0.16606061160564423D, - 0.16588932275772095D, - 0.16572310030460358D, - 0.16555465757846832D, - 0.16538579761981964D, - 0.16521978378295898D, - 0.16504855453968048D, - 0.16488133370876312D, - 0.1647077053785324D, - 0.16454964876174927D, - 0.16438791155815125D, - 0.16421759128570557D, - 0.16404742002487183D, - 0.16388101875782013D, - 0.16371379792690277D, - 0.16355162858963013D, - 0.1633833944797516D, - 0.16321513056755066D, - 0.16304640471935272D, - 0.1628739833831787D, - 0.16270378232002258D, - 0.16253381967544556D, - 0.16236473619937897D, - 0.16219766438007355D, - 0.1620299369096756D, - 0.1618584245443344D, - 0.16168925166130066D, - 0.16151995956897736D, - 0.16134582459926605D, - 0.1611795872449875D, - 0.16101405024528503D, - 0.1608451008796692D, - 0.16068188846111298D, - 0.1605166792869568D, - 0.16034835577011108D, - 0.16018332540988922D, - 0.16001814603805542D, - 0.15985408425331116D, - 0.15968838334083557D, - 0.15952043235301971D, - 0.1593540459871292D, - 0.1591864973306656D, - 0.15901817381381989D, - 0.15885035693645477D, - 0.1586897224187851D, - 0.15852101147174835D, - 0.15835918486118317D, - 0.15819862484931946D, - 0.15802861750125885D, - 0.1578657180070877D, - 0.15770186483860016D, - 0.157541885972023D, - 0.15737460553646088D, - 0.15719760954380035D, - 0.15703265368938446D, - 0.15686756372451782D, - 0.15670160949230194D, - 0.15654122829437256D, - 0.15637557208538055D, - 0.15620650351047516D, - 0.15603956580162048D, - 0.15587256848812103D, - 0.15570658445358276D, - 0.1555391401052475D, - 0.15537893772125244D, - 0.15521250665187836D, - 0.15504445135593414D, - 0.1548793762922287D, - 0.15472041070461273D, - 0.15455928444862366D, - 0.1543930172920227D, - 0.15422186255455017D, - 0.15405680239200592D, - 0.15389008820056915D, - 0.15371909737586975D, - 0.15355190634727478D, - 0.1533874124288559D, - 0.15322037041187286D, - 0.15305693447589874D, - 0.15288913249969482D, - 0.15272565186023712D, - 0.15255971252918243D, - 0.15239514410495758D, - 0.15223248302936554D, - 0.15206488966941833D, - 0.15189997851848602D, - 0.1517343968153D, - 0.15157388150691986D, - 0.15141001343727112D, - 0.15124376118183136D, - 0.1510799080133438D, - 0.15091581642627716D, - 0.15075315535068512D, - 0.1505943238735199D, - 0.15042626857757568D, - 0.15026342868804932D, - 0.15009838342666626D, - 0.14992687106132507D, - 0.14975950121879578D, - 0.14959338307380676D, - 0.1494319885969162D, - 0.14927686750888824D, - 0.1491170972585678D, - 0.1489545851945877D, - 0.1487915962934494D, - 0.14862462878227234D, - 0.14846675097942352D, - 0.1482943892478943D, - 0.14813122153282166D, - 0.14796608686447144D, - 0.1478019803762436D, - 0.14763972163200378D, - 0.14748099446296692D, - 0.1473177820444107D, - 0.14715023338794708D, - 0.14698868989944458D, - 0.14682012796401978D, - 0.14665497839450836D, - 0.14649364352226257D, - 0.14632706344127655D, - 0.14616291224956512D, - 0.14600065350532532D, - 0.1458369493484497D, - 0.14567570388317108D, - 0.14551441371440887D, - 0.1453484296798706D, - 0.14518843591213226D, - 0.14502838253974915D, - 0.1448645293712616D, - 0.14470131695270538D, - 0.14454562962055206D, - 0.144387349486351D, - 0.14422045648097992D, - 0.14406554400920868D, - 0.14389978349208832D, - 0.14373210072517395D, - 0.14357031881809235D, - 0.14340740442276D, - 0.1432454138994217D, - 0.1430845707654953D, - 0.14292079210281372D, - 0.1427599936723709D, - 0.14259862899780273D, - 0.14243145287036896D, - 0.142270028591156D, - 0.1421079933643341D, - 0.1419392079114914D, - 0.1417788565158844D, - 0.14161263406276703D, - 0.14144699275493622D, - 0.1412813663482666D, - 0.14111489057540894D, - 0.14095115661621094D, - 0.140792116522789D, - 0.14062824845314026D, - 0.1404629498720169D, - 0.14029960334300995D, - 0.14013166725635529D, - 0.13997189700603485D, - 0.13981026411056519D, - 0.13965271413326263D, - 0.13948722183704376D, - 0.1393279731273651D, - 0.13916252553462982D, - 0.13900236785411835D, - 0.1388358473777771D, - 0.13866667449474335D, - 0.13850988447666168D, - 0.13835175335407257D, - 0.138188436627388D, - 0.13802814483642578D, - 0.13786524534225464D, - 0.1377078741788864D, - 0.13754159212112427D, - 0.1373801976442337D, - 0.1372184306383133D, - 0.13705679774284363D, - 0.13689808547496796D, - 0.13673967123031616D, - 0.13657420873641968D, - 0.13640782237052917D, - 0.13624517619609833D, - 0.13608133792877197D, - 0.13591967523097992D, - 0.13575933873653412D, - 0.13559971749782562D, - 0.13544517755508423D, - 0.1352863609790802D, - 0.13513325154781342D, - 0.13497786223888397D, - 0.13481275737285614D, - 0.13465309143066406D, - 0.13449665904045105D, - 0.13433897495269775D, - 0.1341773420572281D, - 0.13402383029460907D, - 0.1338663548231125D, - 0.1337081789970398D, - 0.13354714214801788D, - 0.13338331878185272D, - 0.13322538137435913D, - 0.13306425511837006D, - 0.13290470838546753D, - 0.13275213539600372D, - 0.13259844481945038D, - 0.1324356645345688D, - 0.13227884471416473D, - 0.1321146935224533D, - 0.1319541037082672D, - 0.131797656416893D, - 0.13164083659648895D, - 0.13147978484630585D, - 0.13131381571292877D, - 0.13115201890468597D, - 0.13099059462547302D, - 0.1308245062828064D, - 0.1306670606136322D, - 0.1305040717124939D, - 0.13035070896148682D, - 0.13019300997257233D, - 0.1300356239080429D, - 0.1298762559890747D, - 0.1297183632850647D, - 0.12956057488918304D, - 0.12940144538879395D, - 0.12924081087112427D, - 0.12908275425434113D, - 0.1289270669221878D, - 0.12876754999160767D, - 0.12860682606697083D, - 0.12844565510749817D, - 0.12828676402568817D, - 0.12812906503677368D, - 0.12797008454799652D, - 0.12781330943107605D, - 0.12765750288963318D, - 0.12749481201171875D, - 0.127337247133255D, - 0.1271742433309555D, - 0.1270153522491455D, - 0.12685935199260712D, - 0.1267004907131195D, - 0.12653754651546478D, - 0.12637701630592346D, - 0.1262156367301941D, - 0.12606389820575714D, - 0.12590430676937103D, - 0.12574836611747742D, - 0.12559638917446136D, - 0.12544165551662445D, - 0.1252770870923996D, - 0.1251228302717209D, - 0.12496986985206604D, - 0.12481474876403809D, - 0.1246587485074997D, - 0.12450014054775238D, - 0.1243380680680275D, - 0.12417808920145035D, - 0.12401260435581207D, - 0.12385917454957962D, - 0.12369806319475174D, - 0.12354270368814468D, - 0.12338215857744217D, - 0.12322761118412018D, - 0.12307074666023254D, - 0.12291423231363297D, - 0.12275463342666626D, - 0.12259893864393234D, - 0.12243746966123581D, - 0.12228085845708847D, - 0.12212485074996948D, - 0.12196937203407288D, - 0.12180796265602112D, - 0.12165087461471558D, - 0.12149342894554138D, - 0.12132823467254639D, - 0.12117192149162292D, - 0.12100870162248611D, - 0.12084946036338806D, - 0.12069331109523773D, - 0.12053768336772919D, - 0.12037955224514008D, - 0.1202208548784256D, - 0.12006158381700516D, - 0.11990135163068771D, - 0.11974664032459259D, - 0.11959299445152283D, - 0.11944324523210526D, - 0.11928992718458176D, - 0.11913513392210007D, - 0.11898119002580643D, - 0.11882483214139938D, - 0.1186707392334938D, - 0.11851347982883453D, - 0.11835876107215881D, - 0.11820124834775925D, - 0.11804813891649246D, - 0.11789484322071075D, - 0.11773931980133057D, - 0.11758462339639664D, - 0.117423877120018D, - 0.11726968735456467D, - 0.11711079627275467D, - 0.11694814264774323D, - 0.11679580062627792D, - 0.11663621664047241D, - 0.11648730933666229D, - 0.11632833629846573D, - 0.11617368459701538D, - 0.11601484566926956D, - 0.1158570870757103D, - 0.11570281535387039D, - 0.11555135250091553D, - 0.11539247632026672D, - 0.11523469537496567D, - 0.11507617682218552D, - 0.11491613835096359D, - 0.11476139724254608D, - 0.11460647732019424D, - 0.11445080488920212D, - 0.11429022997617722D, - 0.11413708329200745D, - 0.11397743970155716D, - 0.11382514238357544D, - 0.11366745084524155D, - 0.11351797729730606D, - 0.11336144059896469D, - 0.11320804059505463D, - 0.11305557936429977D, - 0.11289967596530914D, - 0.11274378001689911D, - 0.11258506029844284D, - 0.11242981255054474D, - 0.11227528750896454D, - 0.11211802810430527D, - 0.11196192353963852D, - 0.11180936545133591D, - 0.1116519570350647D, - 0.11149086058139801D, - 0.11133705824613571D, - 0.11118285357952118D, - 0.11102371662855148D, - 0.11086839437484741D, - 0.11070949584245682D, - 0.11055301874876022D, - 0.11039435863494873D, - 0.11024358123540878D, - 0.11008933931589127D, - 0.10994099080562592D, - 0.10978744924068451D, - 0.1096331849694252D, - 0.1094803735613823D, - 0.10932327806949615D, - 0.1091662347316742D, - 0.10901220887899399D, - 0.10886164009571075D, - 0.10870997607707977D, - 0.1085532084107399D, - 0.10839588195085526D, - 0.10824001580476761D, - 0.10808181017637253D, - 0.10793018341064453D, - 0.10777948796749115D, - 0.10762609541416168D, - 0.10746936500072479D, - 0.10731363296508789D, - 0.10715664178133011D, - 0.10699828714132309D, - 0.1068406030535698D, - 0.10668957233428955D, - 0.106535904109478D, - 0.1063794493675232D, - 0.1062263771891594D, - 0.10607559233903885D, - 0.1059180200099945D, - 0.1057700365781784D, - 0.1056135967373848D, - 0.10546034574508667D, - 0.10531051456928253D, - 0.10515706241130829D, - 0.10500892251729965D, - 0.10485366731882095D, - 0.10469770431518555D, - 0.1045420691370964D, - 0.10438660532236099D, - 0.10423186421394348D, - 0.10408131033182144D, - 0.10392504185438156D, - 0.103775754570961D, - 0.10362043231725693D, - 0.10346867889165878D, - 0.1033216342329979D, - 0.10317199677228928D, - 0.1030234843492508D, - 0.1028713583946228D, - 0.102719247341156D, - 0.10256177186965942D, - 0.10241074860095978D, - 0.1022588387131691D, - 0.10210096091032028D, - 0.10195054113864899D, - 0.10179688781499863D, - 0.10164371132850647D, - 0.10149170458316803D, - 0.10133637487888336D, - 0.1011854037642479D, - 0.10102973878383636D, - 0.10087919235229492D, - 0.10073055326938629D, - 0.10058251768350601D, - 0.10042925179004669D, - 0.10028298944234848D, - 0.10012997686862946D, - 0.09998201578855515D, - 0.09982899576425552D, - 0.0996730700135231D, - 0.09951788932085037D, - 0.09936707466840744D, - 0.09921209514141083D, - 0.09906535595655441D, - 0.09891849011182785D, - 0.0987686887383461D, - 0.0986199602484703D, - 0.09847044944763184D, - 0.09832371026277542D, - 0.09816580265760422D, - 0.09800924360752106D, - 0.09785451740026474D, - 0.0977015420794487D, - 0.09754469245672226D, - 0.0973912850022316D, - 0.09723710268735886D, - 0.09708409756422043D, - 0.09692969173192978D, - 0.09677083045244217D, - 0.09661783277988434D, - 0.09646695107221603D, - 0.09631767868995667D, - 0.09616906195878983D, - 0.0960221216082573D, - 0.09587518125772476D, - 0.09572049975395203D, - 0.09557510167360306D, - 0.09542537480592728D, - 0.09527473896741867D, - 0.09512560814619064D, - 0.09497389942407608D, - 0.09482252597808838D, - 0.09466812759637833D, - 0.0945177897810936D, - 0.09436610341072083D, - 0.0942160040140152D, - 0.09406259655952454D, - 0.09391862154006958D, - 0.09376517683267593D, - 0.09361439198255539D, - 0.09346404671669006D, - 0.09330684691667557D, - 0.09315872937440872D, - 0.09300410747528076D, - 0.09285490214824677D, - 0.09270570427179337D, - 0.09255209565162659D, - 0.09239742159843445D, - 0.09224936366081238D, - 0.09209839254617691D, - 0.09194477647542953D, - 0.09178774058818817D, - 0.09163559973239899D, - 0.09148869663476944D, - 0.09133746474981308D, - 0.09118695557117462D, - 0.09104108810424805D, - 0.09089026600122452D, - 0.09074579924345016D, - 0.09059691429138184D, - 0.0904451310634613D, - 0.09029250591993332D, - 0.09014249593019485D, - 0.08999146521091461D, - 0.08984044194221497D, - 0.0896981805562973D, - 0.08955065906047821D, - 0.08939830958843231D, - 0.08925025165081024D, - 0.08909676969051361D, - 0.0889468863606453D, - 0.0888008326292038D, - 0.08865290880203247D, - 0.08850424736738205D, - 0.08835210651159286D, - 0.08819899708032608D, - 0.08805057406425476D, - 0.08789926767349243D, - 0.0877542570233345D, - 0.08760009706020355D, - 0.08745313435792923D, - 0.08730407804250717D, - 0.08714929223060608D, - 0.08699973672628403D, - 0.08685608208179474D, - 0.08670856803655624D, - 0.08656258881092072D, - 0.08641660213470459D, - 0.086270771920681D, - 0.08612503111362457D, - 0.08597104996442795D, - 0.08581869304180145D, - 0.08567001670598984D, - 0.08551899343729019D, - 0.08536837995052338D, - 0.08521687984466553D, - 0.0850711539387703D, - 0.08492837101221085D, - 0.08477798104286194D, - 0.08462752401828766D, - 0.08447655290365219D, - 0.08432706445455551D, - 0.08418617397546768D, - 0.08403434604406357D, - 0.08388318866491318D, - 0.0837327241897583D, - 0.08358580619096756D, - 0.08344066143035889D, - 0.08329291641712189D, - 0.08314470201730728D, - 0.08299455791711807D, - 0.08284270763397217D, - 0.08269276469945908D, - 0.08254578709602356D, - 0.08239870518445969D, - 0.08224755525588989D, - 0.08210334926843643D, - 0.08195140957832336D, - 0.08179952949285507D, - 0.08164890855550766D, - 0.08149830996990204D, - 0.08135122805833817D, - 0.08120505511760712D, - 0.08105988055467606D, - 0.08091382682323456D, - 0.08076044917106628D, - 0.0806116908788681D, - 0.08046256750822067D, - 0.08032169938087463D, - 0.0801742672920227D, - 0.08002588152885437D, - 0.079876609146595D, - 0.07973120361566544D, - 0.07958308607339859D, - 0.07943569868803024D, - 0.0792907252907753D, - 0.07914266735315323D, - 0.07899928838014603D, - 0.0788513645529747D, - 0.07870672643184662D, - 0.07855851948261261D, - 0.07841243594884872D, - 0.07826675474643707D, - 0.07811979949474335D, - 0.07797133177518845D, - 0.07782232016324997D, - 0.07767399400472641D, - 0.07752782851457596D, - 0.0773797407746315D, - 0.0772305428981781D, - 0.07708588242530823D, - 0.07694590836763382D, - 0.07679516822099686D, - 0.07664846628904343D, - 0.07649309933185577D, - 0.07634805887937546D, - 0.07619959115982056D, - 0.07605158537626266D, - 0.07590463012456894D, - 0.07575789093971252D, - 0.0756126120686531D, - 0.0754665955901146D, - 0.07531381398439407D, - 0.07516654580831528D, - 0.07501640915870667D, - 0.07486724108457565D, - 0.07472105324268341D, - 0.07457690685987473D, - 0.07442717999219894D, - 0.07427489012479782D, - 0.07413031905889511D, - 0.0739874318242073D, - 0.07384069263935089D, - 0.07369356602430344D, - 0.07354933023452759D, - 0.07339967787265778D, - 0.07325538247823715D, - 0.07310646027326584D, - 0.072956882417202D, - 0.0728110745549202D, - 0.07266359776258469D, - 0.0725211426615715D, - 0.07237620651721954D, - 0.07222937792539597D, - 0.07207916676998138D, - 0.07193435728549957D, - 0.07179314643144608D, - 0.07164552807807922D, - 0.07149890810251236D, - 0.07135166227817535D, - 0.07120280712842941D, - 0.07105418294668198D, - 0.07091175019741058D, - 0.07076039910316467D, - 0.07061431556940079D, - 0.07047049701213837D, - 0.07032421231269836D, - 0.07017634063959122D, - 0.07002970576286316D, - 0.06988793611526489D, - 0.06974132359027863D, - 0.06959310919046402D, - 0.06945087015628815D, - 0.06930480152368546D, - 0.06915923953056335D, - 0.06900786608457565D, - 0.0688617154955864D, - 0.06871413439512253D, - 0.06856607645750046D, - 0.06841415911912918D, - 0.06826581805944443D, - 0.06812670081853867D, - 0.06798086315393448D, - 0.06783780455589294D, - 0.06768807768821716D, - 0.06754382699728012D, - 0.06739568710327148D, - 0.06724487990140915D, - 0.06709926575422287D, - 0.06695383787155151D, - 0.06680747866630554D, - 0.06665907055139542D, - 0.06651457399129868D, - 0.06636756658554077D, - 0.06622058898210526D, - 0.06607180833816528D, - 0.06592177599668503D, - 0.06577412784099579D, - 0.0656253919005394D, - 0.06547900289297104D, - 0.0653318390250206D, - 0.06518644094467163D, - 0.06504128873348236D, - 0.06489810347557068D, - 0.06475608795881271D, - 0.06460591405630112D, - 0.06446024030447006D, - 0.064316026866436D, - 0.06417583674192429D, - 0.06403206288814545D, - 0.06388941407203674D, - 0.06374424695968628D, - 0.06360013782978058D, - 0.0634584054350853D, - 0.06331267207860947D, - 0.0631692036986351D, - 0.06302201002836227D, - 0.06288087368011475D, - 0.06273243576288223D, - 0.06258194893598557D, - 0.06243429332971573D, - 0.06229083240032196D, - 0.06214556843042374D, - 0.062002599239349365D, - 0.06185929477214813D, - 0.061716437339782715D, - 0.061570484191179276D, - 0.06142384186387062D, - 0.06127782538533211D, - 0.061132557690143585D, - 0.060989513993263245D, - 0.060844529420137405D, - 0.06069890409708023D, - 0.06055354326963425D, - 0.060405682772397995D, - 0.06026533991098404D, - 0.06011749058961868D, - 0.059968482702970505D, - 0.05982600525021553D, - 0.059680480509996414D, - 0.059535522013902664D, - 0.059390582144260406D, - 0.05924614518880844D, - 0.05910341069102287D, - 0.05896386876702309D, - 0.05881671980023384D, - 0.05867418646812439D, - 0.05852854624390602D, - 0.05838187783956528D, - 0.05823810026049614D, - 0.05809527635574341D, - 0.057948093861341476D, - 0.0578012652695179D, - 0.05765361711382866D, - 0.05750838667154312D, - 0.05736393481492996D, - 0.057217638939619064D, - 0.05706694349646568D, - 0.05692378431558609D, - 0.05678245425224304D, - 0.05663757398724556D, - 0.05649363622069359D, - 0.05634985491633415D, - 0.056205663830041885D, - 0.05606226995587349D, - 0.05592307448387146D, - 0.05577968433499336D, - 0.05563392862677574D, - 0.05549056455492973D, - 0.05534479022026062D, - 0.055201154202222824D, - 0.05505699664354324D, - 0.0549137219786644D, - 0.05476832762360573D, - 0.05462126433849335D, - 0.05447656661272049D, - 0.05434228852391243D, - 0.05420103296637535D, - 0.05406308174133301D, - 0.05391890928149223D, - 0.0537768192589283D, - 0.05362963303923607D, - 0.0534859336912632D, - 0.05334062874317169D, - 0.05319816619157791D, - 0.05305417627096176D, - 0.0529022179543972D, - 0.0527631975710392D, - 0.05261426791548729D, - 0.05247179791331291D, - 0.05232933536171913D, - 0.05218454450368881D, - 0.05203909054398537D, - 0.05189083516597748D, - 0.05174766480922699D, - 0.05160299316048622D, - 0.051458291709423065D, - 0.051309190690517426D, - 0.05115984380245209D, - 0.05101843550801277D, - 0.05087246745824814D, - 0.05072947219014168D, - 0.05057992786169052D, - 0.05043843761086464D, - 0.05029204860329628D, - 0.05014629662036896D, - 0.05000283941626549D, - 0.049857232719659805D, - 0.049713216722011566D, - 0.04957091435790062D, - 0.04942091554403305D, - 0.04927506670355797D, - 0.04913335666060448D, - 0.048989035189151764D, - 0.048844993114471436D, - 0.0487007237970829D, - 0.048562195152044296D, - 0.048413559794425964D, - 0.048270318657159805D, - 0.04812940955162048D, - 0.04798140004277229D, - 0.0478396899998188D, - 0.047694046050310135D, - 0.047547876834869385D, - 0.04740189015865326D, - 0.04726110398769379D, - 0.04712127149105072D, - 0.046977218240499496D, - 0.04683265835046768D, - 0.046689197421073914D, - 0.04654806852340698D, - 0.046403829008340836D, - 0.046261515468358994D, - 0.04611881449818611D, - 0.04596831649541855D, - 0.04582914337515831D, - 0.04568442329764366D, - 0.04553995281457901D, - 0.04539845883846283D, - 0.04524900019168854D, - 0.045108482241630554D, - 0.04496757686138153D, - 0.04482390731573105D, - 0.04467904940247536D, - 0.04453316330909729D, - 0.044389624148607254D, - 0.04424721747636795D, - 0.04410555958747864D, - 0.043958716094493866D, - 0.04381263256072998D, - 0.04366842657327652D, - 0.04352462291717529D, - 0.04338620603084564D, - 0.04324391856789589D, - 0.043100159615278244D, - 0.04295606166124344D, - 0.042808517813682556D, - 0.04266786947846413D, - 0.04252271726727486D, - 0.04237944632768631D, - 0.042232923209667206D, - 0.042089663445949554D, - 0.0419427864253521D, - 0.041796110570430756D, - 0.04165620356798172D, - 0.04151580110192299D, - 0.04137476161122322D, - 0.04122743010520935D, - 0.04108310863375664D, - 0.0409451425075531D, - 0.04079899191856384D, - 0.0406576506793499D, - 0.04051866754889488D, - 0.04037083312869072D, - 0.04022456333041191D, - 0.040080901235342026D, - 0.03993881866335869D, - 0.03979869186878204D, - 0.039654675871133804D, - 0.03950592130422592D, - 0.039364293217659D, - 0.03922411799430847D, - 0.039080843329429626D, - 0.038942210376262665D, - 0.038799673318862915D, - 0.03865673393011093D, - 0.038515783846378326D, - 0.03837844729423523D, - 0.03823413327336311D, - 0.0380907878279686D, - 0.03794614225625992D, - 0.037802569568157196D, - 0.0376591794192791D, - 0.03751154989004135D, - 0.037371594458818436D, - 0.03723229467868805D, - 0.0370887815952301D, - 0.03694836050271988D, - 0.036804623901844025D, - 0.036663684993982315D, - 0.03652269020676613D, - 0.03638038784265518D, - 0.03623593971133232D, - 0.03609330207109451D, - 0.03595142811536789D, - 0.03580619767308235D, - 0.035664405673742294D, - 0.03552398458123207D, - 0.03537818789482117D, - 0.035238854587078094D, - 0.03509785979986191D, - 0.03495733439922333D, - 0.034811608493328094D, - 0.034666016697883606D, - 0.034524593502283096D, - 0.034383177757263184D, - 0.03424632549285889D, - 0.03410206362605095D, - 0.03395908698439598D, - 0.03381533920764923D, - 0.03367502987384796D, - 0.03353389352560043D, - 0.0333939865231514D, - 0.0332530252635479D, - 0.0331089124083519D, - 0.03296489268541336D, - 0.03281978890299797D, - 0.03268205374479294D, - 0.032543547451496124D, - 0.03239939734339714D, - 0.03225564956665039D, - 0.03211319074034691D, - 0.031970299780368805D, - 0.03183053806424141D, - 0.031690504401922226D, - 0.0315515473484993D, - 0.03140871226787567D, - 0.03127032518386841D, - 0.03113543428480625D, - 0.03099132515490055D, - 0.03084556572139263D, - 0.030708063393831253D, - 0.030564403161406517D, - 0.03042270988225937D, - 0.030277878046035767D, - 0.030134053900837898D, - 0.0299934484064579D, - 0.029853519052267075D, - 0.02970750257372856D, - 0.02956370636820793D, - 0.029423074796795845D, - 0.029277591034770012D, - 0.02913256548345089D, - 0.028991548344492912D, - 0.028849191963672638D, - 0.028712045401334763D, - 0.028571665287017822D, - 0.028429850935935974D, - 0.028289183974266052D, - 0.028145452961325645D, - 0.02800772339105606D, - 0.027868105098605156D, - 0.027727505192160606D, - 0.027587590739130974D, - 0.027444127947092056D, - 0.02730259671807289D, - 0.027155976742506027D, - 0.027012743055820465D, - 0.026867320761084557D, - 0.02672656998038292D, - 0.026584992185235023D, - 0.026440242305397987D, - 0.026296602562069893D, - 0.026151999831199646D, - 0.02601231448352337D, - 0.025870999321341515D, - 0.025728831067681313D, - 0.025589263066649437D, - 0.0254491176456213D, - 0.025309832766652107D, - 0.025158962234854698D, - 0.02501760981976986D, - 0.024877915158867836D, - 0.024732133373618126D, - 0.024590589106082916D, - 0.024444540962576866D, - 0.02430100180208683D, - 0.02415304444730282D, - 0.02401198446750641D, - 0.023868655785918236D, - 0.023721497505903244D, - 0.023579789325594902D, - 0.023435594514012337D, - 0.023291146382689476D, - 0.02314934879541397D, - 0.023010551929473877D, - 0.0228724405169487D, - 0.02272932231426239D, - 0.0225907564163208D, - 0.022446082904934883D, - 0.02230372652411461D, - 0.022165967151522636D, - 0.022024204954504967D, - 0.021882086992263794D, - 0.02174002304673195D, - 0.02160024642944336D, - 0.021454278379678726D, - 0.02131497487425804D, - 0.02117258496582508D, - 0.021028701215982437D, - 0.02088312990963459D, - 0.020745303481817245D, - 0.020600121468305588D, - 0.020457785576581955D, - 0.0203145369887352D, - 0.020174575969576836D, - 0.020029140636324883D, - 0.019890660420060158D, - 0.01975022256374359D, - 0.01960756629705429D, - 0.019467037171125412D, - 0.019320420920848846D, - 0.019179683178663254D, - 0.01904134452342987D, - 0.018906118348240852D, - 0.01876520924270153D, - 0.018623512238264084D, - 0.018482543528079987D, - 0.01834135875105858D, - 0.01820279471576214D, - 0.018056906759738922D, - 0.017920710146427155D, - 0.01777799427509308D, - 0.01763162389397621D, - 0.017489714547991753D, - 0.017347203567624092D, - 0.017202477902173996D, - 0.017058173194527626D, - 0.01691833697259426D, - 0.01677481085062027D, - 0.016630994156003D, - 0.016491299495100975D, - 0.016348596662282944D, - 0.01620868779718876D, - 0.016068479046225548D, - 0.015927160158753395D, - 0.015780296176671982D, - 0.015641076490283012D, - 0.01549579482525587D, - 0.015356827527284622D, - 0.015214596875011921D, - 0.015070712193846703D, - 0.014923106878995895D, - 0.014777173288166523D, - 0.014636659994721413D, - 0.014497545547783375D, - 0.01435788907110691D, - 0.014213880524039268D, - 0.014070038683712482D, - 0.013929210603237152D, - 0.013789304532110691D, - 0.013650632463395596D, - 0.013506708666682243D, - 0.013362940400838852D, - 0.013227197341620922D, - 0.01308612059801817D, - 0.012950407341122627D, - 0.012812728062272072D, - 0.012670092284679413D, - 0.012525119818747044D, - 0.012382328510284424D, - 0.012240074574947357D, - 0.012100824154913425D, - 0.011954340152442455D, - 0.011809084564447403D, - 0.011668648570775986D, - 0.011526428163051605D, - 0.011384048499166965D, - 0.011242672801017761D, - 0.011099583469331264D, - 0.010958466678857803D, - 0.010816705413162708D, - 0.010674509219825268D, - 0.01053413562476635D, - 0.010388684459030628D, - 0.010249142535030842D, - 0.01011234987527132D, - 0.009969789534807205D, - 0.009829124435782433D, - 0.009690780192613602D, - 0.00955201406031847D, - 0.009414111264050007D, - 0.009270462207496166D, - 0.009133466519415379D, - 0.008997434750199318D, - 0.008857715874910355D, - 0.008718002587556839D, - 0.00857506226748228D, - 0.008436493575572968D, - 0.0082900645211339D, - 0.008144848048686981D, - 0.008006873540580273D, - 0.007865924388170242D, - 0.007721261121332645D, - 0.00757999112829566D, - 0.007438249886035919D, - 0.0072948825545609D, - 0.007154085673391819D, - 0.007011679001152515D, - 0.00687157129868865D, - 0.00673050107434392D, - 0.006592079531401396D, - 0.006459984928369522D, - 0.006322549190372229D, - 0.006178436800837517D, - 0.0060307616367936134D, - 0.005891833920031786D, - 0.005752726923674345D, - 0.005611956585198641D, - 0.0054701571352779865D, - 0.005323751829564571D, - 0.0051832739263772964D, - 0.005041905678808689D, - 0.00490262545645237D, - 0.004762133117765188D, - 0.004622789565473795D, - 0.004480161238461733D, - 0.004337271209806204D, - 0.004192086402326822D, - 0.004049763083457947D, - 0.003913718741387129D, - 0.0037738564424216747D, - 0.0036340609658509493D, - 0.003496516030281782D, - 0.0033569824881851673D, - 0.0032230240758508444D, - 0.003080387134104967D, - 0.002938604447990656D, - 0.002798959845677018D, - 0.0026581448037177324D, - 0.0025131211150437593D, - 0.002374080941081047D, - 0.0022358258720487356D, - 0.002095262985676527D, - 0.0019611597526818514D, - 0.0018215921008959413D, - 0.001680250046774745D, - 0.0015372197376564145D, - 0.0014027993893250823D, - 0.0012627525720745325D, - 0.0011206334456801414D, - 9.801845299080014E-4D, - 8.360585197806358E-4D, - 6.988595123402774E-4D, - 5.616724956780672E-4D, - 4.2402747203595936E-4D, - 2.863466797862202E-4D, - 1.5011828509159386E-4D, - 1.1911492038052529E-5D, 1.0044277587439865E-4D, 2.4089615908451378E-4D, 3.8259042776189744E-4D, 5.168318748474121E-4D, 6.586313829757273E-4D, 7.998387445695698E-4D, 9.450495708733797E-4D, 0.0010857662418857217D, 0.0012270103907212615D, 0.0013727317564189434D, 0.0015129010425880551D, 0.0016575645422562957D, 0.0017949064495041966D, 0.0019364129984751344D, 0.0020784020889550447D, 0.0022141814697533846D, 0.002355905482545495D, 0.0024919311981648207D, 0.0026356957387179136D, 0.002776813693344593D, 0.002913307398557663D, 0.0030520898289978504D, 0.0031952024437487125D, 0.003334963461384177D, 0.0034765605814754963D, 0.0036186855286359787D, 0.003756078891456127D, 0.003890153020620346D, 0.00403519906103611D, 0.004175015725195408D, 0.004315280355513096D, 0.004453583620488644D, 0.004600624553859234D, 0.004738769959658384D, 0.0048819067887961864D, 0.00502460403367877D, 0.005163980647921562D, 0.00530367624014616D, 0.0054444135166704655D, 0.005587113089859486D, 0.005727327894419432D, 0.005868169944733381D, 0.006005023140460253D, 0.006145890802145004D, 0.006285244598984718D, 0.006429470144212246D, 0.006562682334333658D, 0.006704656407237053D, 0.006846507545560598D, 0.006985656917095184D, 0.007125002332031727D, 0.0072641754522919655D, 0.007406939286738634D, 0.007548102177679539D, 0.007690674625337124D, 0.007831089198589325D, 0.007975874468684196D, 0.008120712824165821D, 0.008261434733867645D, 0.008401445113122463D, 0.008544900454580784D, 0.008687532506883144D, 0.008825301192700863D, 0.008967659436166286D, 0.00910977553576231D, 0.009249896742403507D, 0.009386919438838959D, 0.009527354501187801D, 0.009668641723692417D, 0.009810841642320156D, 0.009948905557394028D, 0.010086851194500923D, 0.010232945904135704D, 0.010377375409007072D, 0.010519984178245068D, 0.01066502183675766D, 0.010805521160364151D, 0.01095004752278328D, 0.011089478619396687D, 0.011232255026698112D, 0.011374537833034992D, 0.011516883037984371D, 0.011656570248305798D, 0.01180147286504507D, 0.011942529119551182D, 0.012080904096364975D, 0.012226544320583344D, 0.012367763556540012D, 0.01251029223203659D, 0.012649907730519772D, 0.012789136730134487D, 0.012928737327456474D, 0.01306520588696003D, 0.01320936344563961D, 0.013349758461117744D, 0.01349073089659214D, 0.01362910307943821D, 0.013771780766546726D, 0.013916674070060253D, 0.014057740569114685D, 0.014193498529493809D, 0.014332176186144352D, 0.014474655501544476D, 0.014616861939430237D, 0.01476175058633089D, 0.014896937645971775D, 0.015033396892249584D, 0.015173542313277721D, 0.015313568525016308D, 0.015453768894076347D, 0.01559944823384285D, 0.015740878880023956D, 0.0158759206533432D, 0.016010040417313576D, 0.01614815928041935D, 0.016291707754135132D, 0.01642908714711666D, 0.016571102663874626D, 0.0167134590446949D, 0.016856668516993523D, 0.01699613407254219D, 0.017135608941316605D, 0.017271164804697037D, 0.017408248037099838D, 0.017549676820635796D, 0.017692318186163902D, 0.01783503033220768D, 0.017975015565752983D, 0.018124109134078026D, 0.018262648954987526D, 0.01840408705174923D, 0.01854878105223179D, 0.01869070902466774D, 0.01883384957909584D, 0.01896996609866619D, 0.019111407920718193D, 0.019254807382822037D, 0.01939486153423786D, 0.019534043967723846D, 0.019675271585583687D, 0.01981993578374386D, 0.0199629794806242D, 0.020102735608816147D, 0.02024231106042862D, 0.02038371004164219D, 0.02052323706448078D, 0.020661482587456703D, 0.02080468460917473D, 0.020946234464645386D, 0.021089831367135048D, 0.021232876926660538D, 0.021373441442847252D, 0.021513110026717186D, 0.021651804447174072D, 0.021792175248265266D, 0.02193247526884079D, 0.02207680605351925D, 0.022216327488422394D, 0.022360535338521004D, 0.022502677515149117D, 0.022643806412816048D, 0.022783884778618813D, 0.022923531010746956D, 0.023063546046614647D, 0.023204835131764412D, 0.02334384247660637D, 0.0234853345900774D, 0.023626044392585754D, 0.023764535784721375D, 0.023903118446469307D, 0.024048229679465294D, 0.024190595373511314D, 0.024332139641046524D, 0.024473512545228004D, 0.024614179506897926D, 0.02475305274128914D, 0.02489588037133217D, 0.025042027235031128D, 0.02518259361386299D, 0.02532017230987549D, 0.025456052273511887D, 0.025593649595975876D, 0.02572823315858841D, 0.025868959724903107D, 0.026007654145359993D, 0.026148367673158646D, 0.0262919794768095D, 0.026437588036060333D, 0.02657989040017128D, 0.02672424539923668D, 0.02686365135014057D, 0.027008309960365295D, 0.02714969776570797D, 0.0272962786257267D, 0.027433041483163834D, 0.027577880769968033D, 0.027716439217329025D, 0.02785547636449337D, 0.02799663133919239D, 0.028138086199760437D, 0.028283756226301193D, 0.02842445857822895D, 0.028564687818288803D, 0.02871151641011238D, 0.028853772208094597D, 0.028992416337132454D, 0.029137132689356804D, 0.02927905134856701D, 0.02942042425274849D, 0.029561731964349747D, 0.02970500849187374D, 0.029843736439943314D, 0.029985306784510612D, 0.030128538608551025D, 0.030271068215370178D, 0.030412210151553154D, 0.030556289479136467D, 0.030699994415044785D, 0.030839497223496437D, 0.030983222648501396D, 0.031125547364354134D, 0.03126153349876404D, 0.03140360862016678D, 0.03154664859175682D, 0.03168836608529091D, 0.03183047100901604D, 0.031973324716091156D, 0.032119471579790115D, 0.032263923436403275D, 0.03240408003330231D, 0.03255024179816246D, 0.03268946334719658D, 0.032828912138938904D, 0.03296731039881706D, 0.033110037446022034D, 0.0332510732114315D, 0.033393360674381256D, 0.03353823721408844D, 0.03368401527404785D, 0.033826667815446854D, 0.03397251293063164D, 0.03411085903644562D, 0.03425149992108345D, 0.03439020738005638D, 0.03453071042895317D, 0.03467126935720444D, 0.03481120616197586D, 0.03495373949408531D, 0.03510218858718872D, 0.03524219989776611D, 0.03538297861814499D, 0.03552223742008209D, 0.03566665202379227D, 0.035811614245176315D, 0.03595492243766785D, 0.036098580807447433D, 0.03623691946268082D, 0.036375124007463455D, 0.03651357814669609D, 0.03665870800614357D, 0.03680017217993736D, 0.03694377467036247D, 0.03708707168698311D, 0.03722917661070824D, 0.03737087547779083D, 0.03751356527209282D, 0.037658076733350754D, 0.03780198469758034D, 0.03794156014919281D, 0.03808009997010231D, 0.038226112723350525D, 0.03837020695209503D, 0.03851321339607239D, 0.03865883871912956D, 0.038796741515398026D, 0.0389384850859642D, 0.039080578833818436D, 0.039222534745931625D, 0.03936350718140602D, 0.03950297087430954D, 0.039649803191423416D, 0.03979025036096573D, 0.03993142768740654D, 0.04007851704955101D, 0.04022213816642761D, 0.04036031663417816D, 0.04050862044095993D, 0.04065130278468132D, 0.04079713299870491D, 0.04093990474939346D, 0.04108305647969246D, 0.041225969791412354D, 0.041370511054992676D, 0.04151448979973793D, 0.041656360030174255D, 0.04179975762963295D, 0.0419391430914402D, 0.04208112135529518D, 0.042221635580062866D, 0.04236719012260437D, 0.04251044988632202D, 0.042655352503061295D, 0.04279865324497223D, 0.04294498264789581D, 0.04309157654643059D, 0.0432388074696064D, 0.043379221111536026D, 0.04352143779397011D, 0.0436660498380661D, 0.043809980154037476D, 0.043953701853752136D, 0.04409695789217949D, 0.044244274497032166D, 0.04439061880111694D, 0.04453623667359352D, 0.044679705053567886D, 0.04482024908065796D, 0.044966381043195724D, 0.04511309415102005D, 0.04525725916028023D, 0.04540384188294411D, 0.04554888978600502D, 0.04569651558995247D, 0.045842498540878296D, 0.04599529504776001D, 0.04613592103123665D, 0.04628181457519531D, 0.04642462357878685D, 0.046567466109991074D, 0.04671074077486992D, 0.04685356095433235D, 0.04699184000492096D, 0.04713955894112587D, 0.047283634543418884D, 0.04742766171693802D, 0.047572653740644455D, 0.04771960899233818D, 0.04786102473735809D, 0.048005830496549606D, 0.04814976453781128D, 0.04828828200697899D, 0.04843548312783241D, 0.04858119785785675D, 0.048723604530096054D, 0.048864372074604034D, 0.049006760120391846D, 0.04914587363600731D, 0.049290046095848083D, 0.04943503066897392D, 0.0495775006711483D, 0.04972691833972931D, 0.04986768960952759D, 0.05001039057970047D, 0.050152115523815155D, 0.05029670521616936D, 0.050433799624443054D, 0.05058044195175171D, 0.05072341486811638D, 0.050868451595306396D, 0.05100876837968826D, 0.05115212872624397D, 0.05129583179950714D, 0.051437895745038986D, 0.051578447222709656D, 0.05172283574938774D, 0.05186808481812477D, 0.05201121047139168D, 0.052156444638967514D, 0.05230209603905678D, 0.05244390666484833D, 0.05258335545659065D, 0.052733324468135834D, 0.052873220294713974D, 0.053014714270830154D, 0.053156204521656036D, 0.05330459401011467D, 0.05344386771321297D, 0.05358799546957016D, 0.05373207479715347D, 0.05387803167104721D, 0.05401966720819473D, 0.054165832698345184D, 0.05431075394153595D, 0.05445530638098717D, 0.05459970980882645D, 0.05474735423922539D, 0.054893892258405685D, 0.055043041706085205D, 0.055188897997140884D, 0.05533526465296745D, 0.055484600365161896D, 0.055627673864364624D, 0.05576412007212639D, 0.05590971186757088D, 0.05605686828494072D, 0.056200768798589706D, 0.05634428188204765D, 0.056488286703825D, 0.05663173645734787D, 0.056780435144901276D, 0.056926608085632324D, 0.05707206204533577D, 0.05721326544880867D, 0.057361286133527756D, 0.05750444158911705D, 0.05764487013220787D, 0.0577898845076561D, 0.05793076753616333D, 0.058076728135347366D, 0.058221399784088135D, 0.05836668983101845D, 0.0585147961974144D, 0.05866195634007454D, 0.058808885514736176D, 0.05895547941327095D, 0.05910357087850571D, 0.05925220251083374D, 0.059399936348199844D, 0.059544846415519714D, 0.0596906840801239D, 0.05983436480164528D, 0.059979792684316635D, 0.06012662872672081D, 0.06027741730213165D, 0.060420021414756775D, 0.06056952476501465D, 0.06071772798895836D, 0.06086060404777527D, 0.06100845709443092D, 0.06115204840898514D, 0.06129597872495651D, 0.061436720192432404D, 0.06158551573753357D, 0.061730656772851944D, 0.061872199177742004D, 0.062023792415857315D, 0.06216789036989212D, 0.062311336398124695D, 0.06245182454586029D, 0.06259559094905853D, 0.06274344027042389D, 0.06288424134254456D, 0.06303341686725616D, 0.06318292021751404D, 0.06332501769065857D, 0.0634644404053688D, 0.06361117213964462D, 0.06375652551651001D, 0.06389967352151871D, 0.06404681503772736D, 0.06419290602207184D, 0.06433777511119843D, 0.06448273360729218D, 0.06462704390287399D, 0.06476743519306183D, 0.06491541117429733D, 0.06506048142910004D, 0.06520365178585052D, 0.06535018980503082D, 0.06549554318189621D, 0.06563982367515564D, 0.06578198075294495D, 0.06592462956905365D, 0.06607501208782196D, 0.06622092425823212D, 0.06637339293956757D, 0.06651996076107025D, 0.06666484475135803D, 0.06681187450885773D, 0.06696231663227081D, 0.06711585819721222D, 0.06726408004760742D, 0.06741142272949219D, 0.06756040453910828D, 0.06770794093608856D, 0.06785459071397781D, 0.06800307333469391D, 0.0681459829211235D, 0.06829492747783661D, 0.06843948364257812D, 0.06858658790588379D, 0.06873581558465958D, 0.06887979060411453D, 0.06902722269296646D, 0.06917352229356766D, 0.06932160258293152D, 0.06947020441293716D, 0.06961338222026825D, 0.0697583258152008D, 0.06990432739257812D, 0.07005196064710617D, 0.07020289450883865D, 0.07034890353679657D, 0.0704943984746933D, 0.07064209878444672D, 0.07078889012336731D, 0.07093801349401474D, 0.07108846306800842D, 0.07123790681362152D, 0.0713827982544899D, 0.07153139263391495D, 0.07167878746986389D, 0.0718243345618248D, 0.07197458297014236D, 0.0721186175942421D, 0.07226993888616562D, 0.07241969555616379D, 0.07256375253200531D, 0.07271335273981094D, 0.0728621557354927D, 0.07300735265016556D, 0.07315520942211151D, 0.0733007937669754D, 0.07344561070203781D, 0.07359104603528976D, 0.07373455911874771D, 0.07388798892498016D, 0.07403958588838577D, 0.07419036328792572D, 0.07433661073446274D, 0.07448694854974747D, 0.07463737577199936D, 0.07478373497724533D, 0.07492654025554657D, 0.07507633417844772D, 0.07522371411323547D, 0.07537233084440231D, 0.07551730424165726D, 0.07567018270492554D, 0.07581793516874313D, 0.07596828043460846D, 0.07611866295337677D, 0.07626424729824066D, 0.07641275972127914D, 0.07655782997608185D, 0.07670912891626358D, 0.07685425132513046D, 0.0769948735833168D, 0.07714076340198517D, 0.07728724926710129D, 0.07743407785892487D, 0.07758434861898422D, 0.07773226499557495D, 0.07788585126399994D, 0.07802983373403549D, 0.07818049192428589D, 0.07832662761211395D, 0.0784769281744957D, 0.07862069457769394D, 0.07877039164304733D, 0.07891900837421417D, 0.07907077670097351D, 0.07921970635652542D, 0.07936611026525497D, 0.07951349020004272D, 0.07966248691082001D, 0.07980795949697495D, 0.07995842397212982D, 0.08010289818048477D, 0.08025183528661728D, 0.08040019869804382D, 0.0805511549115181D, 0.08069602400064468D, 0.08084388077259064D, 0.08099634200334549D, 0.08114219456911087D, 0.08129317313432693D, 0.08143977075815201D, 0.08159446716308594D, 0.08174245059490204D, 0.08189191669225693D, 0.08204131573438644D, 0.08219429105520248D, 0.08234331756830215D, 0.08249454945325851D, 0.08264464884996414D, 0.08279923349618912D, 0.08295143395662308D, 0.08310498297214508D, 0.08325477689504623D, 0.08341126888990402D, 0.08355995267629623D, 0.08371108770370483D, 0.0838567465543747D, 0.0840054377913475D, 0.08415643125772476D, 0.0843018889427185D, 0.08445502817630768D, 0.08460331708192825D, 0.08475178480148315D, 0.08490157872438431D, 0.0850466936826706D, 0.08519754558801651D, 0.08534461259841919D, 0.08549437671899796D, 0.08564329892396927D, 0.08579885959625244D, 0.08595023304224014D, 0.08609388023614883D, 0.08624261617660522D, 0.08639498800039291D, 0.08654710650444031D, 0.08670050650835037D, 0.08685077726840973D, 0.08700422197580338D, 0.08715102076530457D, 0.0872977003455162D, 0.08744174242019653D, 0.08759422600269318D, 0.08774594217538834D, 0.08788730204105377D, 0.0880391076207161D, 0.08819255977869034D, 0.08835027366876602D, 0.08849414438009262D, 0.08864499628543854D, 0.08879048377275467D, 0.0889355018734932D, 0.08908633887767792D, 0.08923996984958649D, 0.08938561379909515D, 0.08953885734081268D, 0.08968373388051987D, 0.08983418345451355D, 0.0899851843714714D, 0.09013000875711441D, 0.09028015285730362D, 0.09042900800704956D, 0.09057943522930145D, 0.09072867780923843D, 0.09087312966585159D, 0.0910261869430542D, 0.09117311239242554D, 0.09132302552461624D, 0.09147395193576813D, 0.09162616729736328D, 0.09177488088607788D, 0.09192109853029251D, 0.09207016974687576D, 0.09221813082695007D, 0.09237463772296906D, 0.09252386540174484D, 0.0926787331700325D, 0.09283152222633362D, 0.0929817333817482D, 0.09312929958105087D, 0.09328164160251617D, 0.09343400597572327D, 0.09358806163072586D, 0.09373386949300766D, 0.09388978779315948D, 0.09403824061155319D, 0.09419355541467667D, 0.09434627741575241D, 0.09449343383312225D, 0.09464648365974426D, 0.09479928016662598D, 0.0949493870139122D, 0.09509287029504776D, 0.09524017572402954D, 0.09539571404457092D, 0.0955447256565094D, 0.09569557756185532D, 0.0958479791879654D, 0.09600166976451874D, 0.09614894539117813D, 0.0962982177734375D, 0.09644953906536102D, 0.09659972786903381D, 0.09674496948719025D, 0.09690061956644058D, 0.09705154597759247D, 0.09720408916473389D, 0.09735329449176788D, 0.09750240296125412D, 0.09765297919511795D, 0.09780307859182358D, 0.09795534610748291D, 0.09811047464609146D, 0.09826676547527313D, 0.09841451048851013D, 0.09856410324573517D, 0.09871689975261688D, 0.09886790066957474D, 0.099018894135952D, 0.09916773438453674D, 0.09932077676057816D, 0.09947634488344193D, 0.09962969273328781D, 0.09978242218494415D, 0.09993064403533936D, 0.10008084774017334D, 0.10023438930511475D, 0.10038559883832932D, 0.10053691267967224D, 0.10068517923355103D, 0.1008366048336029D, 0.10099314153194427D, 0.10114269703626633D, 0.10129916667938232D, 0.10144601762294769D, 0.10159671306610107D, 0.10175005346536636D, 0.10190296918153763D, 0.10205913335084915D, 0.10221262276172638D, 0.10236292332410812D, 0.10252030938863754D, 0.10267956554889679D, 0.10282602161169052D, 0.10297860950231552D, 0.10312694311141968D, 0.10327927768230438D, 0.10343994200229645D, 0.10359508544206619D, 0.10374914109706879D, 0.10390400141477585D, 0.10405304282903671D, 0.10420652478933334D, 0.10436088591814041D, 0.10451732575893402D, 0.10467734932899475D, 0.1048327088356018D, 0.10498455911874771D, 0.10513525456190109D, 0.10528642684221268D, 0.1054416224360466D, 0.10559043288230896D, 0.10574282705783844D, 0.10589909553527832D, 0.10605556517839432D, 0.10620948672294617D, 0.10636616498231888D, 0.10651878267526627D, 0.10667099058628082D, 0.1068253219127655D, 0.10697854310274124D, 0.10713843256235123D, 0.10728807747364044D, 0.10744231194257736D, 0.10759419202804565D, 0.1077449843287468D, 0.10790048539638519D, 0.1080583855509758D, 0.10821515321731567D, 0.1083710640668869D, 0.10852231085300446D, 0.10867666453123093D, 0.10882777720689774D, 0.10898458957672119D, 0.10913711041212082D, 0.10929664224386215D, 0.10945430397987366D, 0.10961125046014786D, 0.10976684093475342D, 0.10992513597011566D, 0.11008249223232269D, 0.11024082452058792D, 0.1103985533118248D, 0.11054976284503937D, 0.11070134490728378D, 0.1108558252453804D, 0.11100988835096359D, 0.11115804314613342D, 0.11131478101015091D, 0.11147209256887436D, 0.11162741482257843D, 0.11178641021251678D, 0.11193942278623581D, 0.1120971292257309D, 0.11224858462810516D, 0.11240638792514801D, 0.11256378889083862D, 0.11272016912698746D, 0.11287200450897217D, 0.11303041875362396D, 0.11318613588809967D, 0.11333518475294113D, 0.11348620057106018D, 0.11363913863897324D, 0.11379265785217285D, 0.11394768208265305D, 0.1140977144241333D, 0.11425047367811203D, 0.1144118458032608D, 0.11457011848688126D, 0.11472522467374802D, 0.11488304287195206D, 0.11503463238477707D, 0.11518769711256027D, 0.11534227430820465D, 0.11550097167491913D, 0.11565592885017395D, 0.11581210047006607D, 0.11596544831991196D, 0.11612154543399811D, 0.11628284305334091D, 0.11644155532121658D, 0.11660086363554001D, 0.11675584316253662D, 0.1169113963842392D, 0.11706878989934921D, 0.11722639948129654D, 0.11737873405218124D, 0.11753018200397491D, 0.11769700050354004D, 0.1178499087691307D, 0.11800309270620346D, 0.11816198378801346D, 0.1183200553059578D, 0.11847332119941711D, 0.11863360553979874D, 0.1187887191772461D, 0.11894822865724564D, 0.11911315470933914D, 0.11926519870758057D, 0.11942169815301895D, 0.11957871168851852D, 0.11973323673009872D, 0.11989237368106842D, 0.12004467844963074D, 0.12020543962717056D, 0.12036484479904175D, 0.1205243393778801D, 0.12068185210227966D, 0.12084473669528961D, 0.12100447714328766D, 0.12115930765867233D, 0.12131694704294205D, 0.1214812844991684D, 0.12163779884576797D, 0.12179568409919739D, 0.12195295840501785D, 0.12211063504219055D, 0.12226805835962296D, 0.12242195755243301D, 0.12257634848356247D, 0.12273655086755753D, 0.12289784848690033D, 0.12306149303913116D, 0.1232261061668396D, 0.12338338792324066D, 0.12354311347007751D, 0.12370559573173523D, 0.12387170642614365D, 0.12403009831905365D, 0.12418466806411743D, 0.12434112280607224D, 0.1244964450597763D, 0.12465308606624603D, 0.12481117248535156D, 0.12496909499168396D, 0.12512359023094177D, 0.12528195977210999D, 0.12543469667434692D, 0.12559561431407928D, 0.12575115263462067D, 0.12590746581554413D, 0.12606586515903473D, 0.12622293829917908D, 0.12637664377689362D, 0.12653762102127075D, 0.12669754028320312D, 0.12685619294643402D, 0.1270214170217514D, 0.12718062102794647D, 0.12733519077301025D, 0.12749606370925903D, 0.12765872478485107D, 0.12782463431358337D, 0.12798020243644714D, 0.1281414031982422D, 0.1283019781112671D, 0.12846773862838745D, 0.1286260485649109D, 0.12878255546092987D, 0.12894503772258759D, 0.1291048526763916D, 0.12926606833934784D, 0.12942789494991302D, 0.12959156930446625D, 0.12974515557289124D, 0.12989819049835205D, 0.1300552934408188D, 0.13021644949913025D, 0.13037624955177307D, 0.13053417205810547D, 0.13069522380828857D, 0.13085974752902985D, 0.13101573288440704D, 0.1311684399843216D, 0.13133539259433746D, 0.13149294257164001D, 0.13164502382278442D, 0.13180053234100342D, 0.1319563388824463D, 0.13211700320243835D, 0.1322767436504364D, 0.13244172930717468D, 0.1325972080230713D, 0.13275986909866333D, 0.13291573524475098D, 0.1330719292163849D, 0.1332334727048874D, 0.13339528441429138D, 0.13355481624603271D, 0.1337166279554367D, 0.13387836515903473D, 0.13404130935668945D, 0.13420721888542175D, 0.1343671977519989D, 0.1345280408859253D, 0.1346929669380188D, 0.13485346734523773D, 0.13500912487506866D, 0.13516193628311157D, 0.13532406091690063D, 0.13548418879508972D, 0.13564568758010864D, 0.135810986161232D, 0.13597291707992554D, 0.13613833487033844D, 0.1363004446029663D, 0.13646268844604492D, 0.1366201788187027D, 0.13678020238876343D, 0.13693927228450775D, 0.13709722459316254D, 0.1372576802968979D, 0.13741405308246613D, 0.13756953179836273D, 0.13772514462471008D, 0.13788801431655884D, 0.13804712891578674D, 0.13820964097976685D, 0.13837288320064545D, 0.13853824138641357D, 0.13870278000831604D, 0.13886971771717072D, 0.13903354108333588D, 0.13919901847839355D, 0.13936829566955566D, 0.13953237235546112D, 0.13969917595386505D, 0.1398545652627945D, 0.14002016186714172D, 0.14017291367053986D, 0.1403316706418991D, 0.14050057530403137D, 0.14065955579280853D, 0.14082512259483337D, 0.1409870684146881D, 0.14115603268146515D, 0.14131535589694977D, 0.14147478342056274D, 0.14164136350154877D, 0.14179907739162445D, 0.14195680618286133D, 0.14212191104888916D, 0.14228470623493195D, 0.14245115220546722D, 0.14261163771152496D, 0.14276936650276184D, 0.14292646944522858D, 0.14308787882328033D, 0.14325685799121857D, 0.14342321455478668D, 0.14359009265899658D, 0.1437581181526184D, 0.14392387866973877D, 0.14408327639102936D, 0.14425180852413177D, 0.14441044628620148D, 0.14458023011684418D, 0.1447472721338272D, 0.14490540325641632D, 0.14506784081459045D, 0.14523136615753174D, 0.14539727568626404D, 0.14555899798870087D, 0.1457156389951706D, 0.14588384330272675D, 0.146047443151474D, 0.14621107280254364D, 0.14637504518032074D, 0.14653868973255157D, 0.14670564234256744D, 0.1468755155801773D, 0.14703933894634247D, 0.14720577001571655D, 0.14737312495708466D, 0.14753885567188263D, 0.14770390093326569D, 0.14786669611930847D, 0.14803257584571838D, 0.14819718897342682D, 0.14836236834526062D, 0.14852797985076904D, 0.14869222044944763D, 0.14885452389717102D, 0.1490185558795929D, 0.14917722344398499D, 0.1493404656648636D, 0.14950552582740784D, 0.14966335892677307D, 0.14982236921787262D, 0.14998695254325867D, 0.1501506268978119D, 0.15031972527503967D, 0.1504816859960556D, 0.15064984560012817D, 0.15081049501895905D, 0.1509808599948883D, 0.15114429593086243D, 0.151309534907341D, 0.15147188305854797D, 0.15163883566856384D, 0.1517990082502365D, 0.15196684002876282D, 0.15213605761528015D, 0.1523030698299408D, 0.15247197449207306D, 0.1526411473751068D, 0.1528036892414093D, 0.15297077596187592D, 0.15313620865345D, 0.1533014178276062D, 0.1534666270017624D, 0.153630793094635D, 0.15379439294338226D, 0.15396162867546082D, 0.15412606298923492D, 0.15429098904132843D, 0.15445642173290253D, 0.15462461113929749D, 0.1547926366329193D, 0.15496547520160675D, 0.15512865781784058D, 0.15529468655586243D, 0.15546265244483948D, 0.1556297242641449D, 0.1557958573102951D, 0.1559613198041916D, 0.15613020956516266D, 0.15629254281520844D, 0.15645910799503326D, 0.15662696957588196D, 0.15679779648780823D, 0.1569603830575943D, 0.1571267694234848D, 0.15729504823684692D, 0.15745952725410461D, 0.15762628614902496D, 0.15778855979442596D, 0.15795747935771942D, 0.1581190824508667D, 0.15828733146190643D, 0.15845201909542084D, 0.15861950814723969D, 0.1587860882282257D, 0.1589500457048416D, 0.15911708772182465D, 0.15928740799427032D, 0.1594506800174713D, 0.1596156507730484D, 0.1597830355167389D, 0.15995223820209503D, 0.1601230353116989D, 0.16028858721256256D, 0.16046783328056335D, 0.16063354909420013D, 0.16080449521541595D, 0.16097332537174225D, 0.16114337742328644D, 0.16131465137004852D, 0.161483496427536D, 0.1616491973400116D, 0.16181625425815582D, 0.1619846075773239D, 0.16215431690216064D, 0.16232497990131378D, 0.16249686479568481D, 0.1626671552658081D, 0.16284231841564178D, 0.16301144659519196D, 0.16317616403102875D, 0.1633453667163849D, 0.1635095179080963D, 0.1636842042207718D, 0.1638593226671219D, 0.16402937471866608D, 0.16418977081775665D, 0.1643621176481247D, 0.16453686356544495D, 0.1647082269191742D, 0.16487736999988556D, 0.16504469513893127D, 0.16521750390529633D, 0.16538292169570923D, 0.16555410623550415D, 0.16572774946689606D, 0.16590924561023712D, 0.1660730093717575D, 0.16624289751052856D, 0.16641287505626678D, 0.16657964885234833D, 0.1667483001947403D, 0.16692405939102173D, 0.16709285974502563D, 0.16726498305797577D, 0.1674390435218811D, 0.1676134467124939D, 0.16778451204299927D, 0.16795344650745392D, 0.16812381148338318D, 0.16829201579093933D, 0.1684664785861969D, 0.1686391979455948D, 0.16881050169467926D, 0.16898894309997559D, 0.16915665566921234D, 0.16932551562786102D, 0.16949592530727386D, 0.1696702241897583D, 0.16984823346138D, 0.17002031207084656D, 0.1701897382736206D, 0.17036403715610504D, 0.17053993046283722D, 0.17071034014225006D, 0.1708792746067047D, 0.1710500866174698D, 0.17121891677379608D, 0.17139190435409546D, 0.17156367003917694D, 0.17173637449741364D, 0.17190755903720856D, 0.1720849573612213D, 0.17225277423858643D, 0.17242112755775452D, 0.17259423434734344D, 0.17276640236377716D, 0.17293871939182281D, 0.17311054468154907D, 0.17328397929668427D, 0.17345906794071198D, 0.17363303899765015D, 0.1738104373216629D, 0.17397917807102203D, 0.17414800822734833D, 0.17431917786598206D, 0.17449432611465454D, 0.17466172575950623D, 0.1748395413160324D, 0.17501668632030487D, 0.17519143223762512D, 0.17536838352680206D, 0.1755412071943283D, 0.17571064829826355D, 0.17589080333709717D, 0.17606942355632782D, 0.176247239112854D, 0.17641842365264893D, 0.17658698558807373D, 0.17676332592964172D, 0.176935613155365D, 0.17710785567760468D, 0.17728090286254883D, 0.17745928466320038D, 0.1776321828365326D, 0.17780578136444092D, 0.17798294126987457D, 0.17815785109996796D, 0.17833979427814484D, 0.17851093411445618D, 0.1786835491657257D, 0.17886051535606384D, 0.1790376603603363D, 0.17921648919582367D, 0.17939159274101257D, 0.17957083880901337D, 0.1797502636909485D, 0.17992530763149261D, 0.1801026463508606D, 0.18028408288955688D, 0.18045489490032196D, 0.1806340366601944D, 0.1808105707168579D, 0.18098872900009155D, 0.1811632215976715D, 0.18134437501430511D, 0.18152523040771484D, 0.18170255422592163D, 0.18187786638736725D, 0.18205541372299194D, 0.18223069608211517D, 0.18240229785442352D, 0.1825835108757019D, 0.18276111781597137D, 0.18293944001197815D, 0.18311530351638794D, 0.18329167366027832D, 0.18346892297267914D, 0.1836460679769516D, 0.1838228851556778D, 0.18399597704410553D, 0.18417446315288544D, 0.1843516230583191D, 0.184530109167099D, 0.18470726907253265D, 0.18488577008247375D, 0.18506748974323273D, 0.185249924659729D, 0.18543273210525513D, 0.1856096237897873D, 0.18578913807868958D, 0.1859683245420456D, 0.18614578247070312D, 0.18632252514362335D, 0.1864963322877884D, 0.18667510151863098D, 0.1868581920862198D, 0.18703486025333405D, 0.18721888959407806D, 0.18739253282546997D, 0.18757246434688568D, 0.1877577155828476D, 0.18793287873268127D, 0.18811465799808502D, 0.1882943958044052D, 0.18847425282001495D, 0.18864761292934418D, 0.18882161378860474D, 0.18899816274642944D, 0.18917573988437653D, 0.18935945630073547D, 0.18953947722911835D, 0.189716637134552D, 0.18990230560302734D, 0.19007518887519836D, 0.19025564193725586D, 0.1904321163892746D, 0.19061104953289032D, 0.19078995287418365D, 0.190964937210083D, 0.19114817678928375D, 0.19132809340953827D, 0.19151580333709717D, 0.19169238209724426D, 0.19187597930431366D, 0.19205956161022186D, 0.19224511086940765D, 0.19242414832115173D, 0.19260457158088684D, 0.19278565049171448D, 0.19296668469905853D, 0.19314511120319366D, 0.193329855799675D, 0.19351661205291748D, 0.1937016248703003D, 0.19387923181056976D, 0.1940610557794571D, 0.194246307015419D, 0.19443221390247345D, 0.19460652768611908D, 0.19479267299175262D, 0.1949712485074997D, 0.1951516568660736D, 0.19533394277095795D, 0.1955246925354004D, 0.19570086896419525D, 0.19588221609592438D, 0.19606895744800568D, 0.19625340402126312D, 0.19644010066986084D, 0.19662165641784668D, 0.1968076378107071D, 0.19699516892433167D, 0.1971805989742279D, 0.1973554939031601D, 0.1975409835577011D, 0.1977252960205078D, 0.19790977239608765D, 0.1980927288532257D, 0.19827796518802643D, 0.19846612215042114D, 0.19864800572395325D, 0.19883641600608826D, 0.19901731610298157D, 0.1992063969373703D, 0.19938835501670837D, 0.1995694637298584D, 0.19975224137306213D, 0.19993893802165985D, 0.20012065768241882D, 0.20030593872070312D, 0.20049719512462616D, 0.20067352056503296D, 0.20086051523685455D, 0.20104587078094482D, 0.2012348473072052D, 0.20142585039138794D, 0.20161063969135284D, 0.20179665088653564D, 0.20198526978492737D, 0.20217211544513702D, 0.20235659182071686D, 0.20254142582416534D, 0.20272696018218994D, 0.20291101932525635D, 0.20309440791606903D, 0.20328234136104584D, 0.20347049832344055D, 0.20365656912326813D, 0.203854501247406D, 0.20404016971588135D, 0.2042284607887268D, 0.20441436767578125D, 0.20460355281829834D, 0.20478859543800354D, 0.2049754112958908D, 0.20516854524612427D, 0.20535217225551605D, 0.20553888380527496D, 0.20573171973228455D, 0.20591837167739868D, 0.20610769093036652D, 0.2063007354736328D, 0.20649467408657074D, 0.2066875845193863D, 0.20687413215637207D, 0.2070641964673996D, 0.2072521448135376D, 0.20743364095687866D, 0.20761997997760773D, 0.20781198143959045D, 0.20800599455833435D, 0.20819956064224243D, 0.2083868831396103D, 0.2085733562707901D, 0.20876942574977875D, 0.20896922051906586D, 0.20915867388248444D, 0.2093524932861328D, 0.20954589545726776D, 0.2097388058900833D, 0.20992672443389893D, 0.21011590957641602D, 0.21031244099140167D, 0.21050217747688293D, 0.21069328486919403D, 0.2108885496854782D, 0.21107973158359528D, 0.21127483248710632D, 0.21146471798419952D, 0.21166469156742096D, 0.21185675263404846D, 0.2120511382818222D, 0.21224676072597504D, 0.2124384641647339D, 0.21262727677822113D, 0.2128206193447113D, 0.21302452683448792D, 0.2132214456796646D, 0.2134128361940384D, 0.21360456943511963D, 0.2137957513332367D, 0.21398882567882538D, 0.21418625116348267D, 0.21438726782798767D, 0.21458405256271362D, 0.21478569507598877D, 0.2149859517812729D, 0.2151806354522705D, 0.21538639068603516D, 0.21557798981666565D, 0.2157720923423767D, 0.21596337854862213D, 0.21616080403327942D, 0.2163562923669815D, 0.21655449271202087D, 0.2167525738477707D, 0.21694263815879822D, 0.21713177859783173D, 0.21732954680919647D, 0.21752935647964478D, 0.21772217750549316D, 0.21791480481624603D, 0.21811674535274506D, 0.21831247210502625D, 0.21851235628128052D, 0.21870890259742737D, 0.2189081758260727D, 0.21910427510738373D, 0.21930015087127686D, 0.21949778497219086D, 0.21969933807849884D, 0.21990087628364563D, 0.22009927034378052D, 0.22029325366020203D, 0.22049371898174286D, 0.22069047391414642D, 0.22089248895645142D, 0.22109095752239227D, 0.22129462659358978D, 0.22148814797401428D, 0.22169452905654907D, 0.2218969613313675D, 0.22209632396697998D, 0.22230185568332672D, 0.22250638902187347D, 0.2227063924074173D, 0.22290310263633728D, 0.22311145067214966D, 0.2233133167028427D, 0.22350966930389404D, 0.2237071990966797D, 0.22390885651111603D, 0.2241075336933136D, 0.22431014478206635D, 0.22450794279575348D, 0.22470755875110626D, 0.22491036355495453D, 0.22511586546897888D, 0.2253158539533615D, 0.22551269829273224D, 0.2257266342639923D, 0.22592762112617493D, 0.22613157331943512D, 0.22633376717567444D, 0.22653743624687195D, 0.22674024105072021D, 0.2269410938024521D, 0.22714996337890625D, 0.22734971344470978D, 0.22755438089370728D, 0.22775733470916748D, 0.22795677185058594D, 0.22816292941570282D, 0.22837083041667938D, 0.22858299314975739D, 0.2287832796573639D, 0.2289920300245285D, 0.22919484972953796D, 0.2293976992368698D, 0.22960828244686127D, 0.22981193661689758D, 0.2300211489200592D, 0.23022563755512238D, 0.2304365634918213D, 0.2306395173072815D, 0.23084834218025208D, 0.23105144500732422D, 0.2312522679567337D, 0.23145829141139984D, 0.23166124522686005D, 0.23187236487865448D, 0.23208360373973846D, 0.23229150474071503D, 0.23250751197338104D, 0.2327122539281845D, 0.23292763531208038D, 0.23313376307487488D, 0.23334120213985443D, 0.23354649543762207D, 0.23375554382801056D, 0.23396620154380798D, 0.23417723178863525D, 0.2343829721212387D, 0.23458978533744812D, 0.23479892313480377D, 0.23500783741474152D, 0.2352222204208374D, 0.2354322373867035D, 0.23564279079437256D, 0.23585160076618195D, 0.23605337738990784D, 0.23626479506492615D, 0.23648226261138916D, 0.2366953194141388D, 0.23690584301948547D, 0.23711639642715454D, 0.23733076453208923D, 0.23753586411476135D, 0.23774738609790802D, 0.23796023428440094D, 0.23817838728427887D, 0.2383866310119629D, 0.23860763013362885D, 0.23882152140140533D, 0.23903527855873108D, 0.23924735188484192D, 0.23945917189121246D, 0.23966942727565765D, 0.23988419771194458D, 0.2400980293750763D, 0.24030447006225586D, 0.240516796708107D, 0.24073119461536407D, 0.24094410240650177D, 0.24115683138370514D, 0.24137572944164276D, 0.24158714711666107D, 0.24180005490779877D, 0.2420184463262558D, 0.24223656952381134D, 0.24244916439056396D, 0.24266721308231354D, 0.2428855299949646D, 0.24310968816280365D, 0.243327334523201D, 0.2435457706451416D, 0.24375973641872406D, 0.2439749389886856D, 0.24419187009334564D, 0.24440546333789825D, 0.2446216642856598D, 0.24483764171600342D, 0.24505628645420074D, 0.2452733963727951D, 0.24548429250717163D, 0.24571490287780762D, 0.2459365725517273D, 0.24615846574306488D, 0.2463839054107666D, 0.2465975135564804D, 0.24682526290416718D, 0.24704609811306D, 0.24726620316505432D, 0.24748526513576508D, 0.24770237505435944D, 0.24791458249092102D, 0.24813757836818695D, 0.24836552143096924D, 0.24859130382537842D, 0.2488095611333847D, 0.24903202056884766D, 0.2492518126964569D, 0.24946889281272888D, 0.2496860921382904D, 0.2499072104692459D, 0.25012969970703125D, 0.25036224722862244D, 0.2505870461463928D, 0.2508128881454468D, 0.2510356307029724D, 0.25126001238822937D, 0.25148099660873413D, 0.25170382857322693D, 0.25192201137542725D, 0.2521439790725708D, 0.25237786769866943D, 0.25259867310523987D, 0.2528284192085266D, 0.2530532777309418D, 0.25327783823013306D, 0.25350385904312134D, 0.2537325918674469D, 0.2539677619934082D, 0.2541946470737457D, 0.2544255256652832D, 0.2546565532684326D, 0.25487953424453735D, 0.25510382652282715D, 0.25533539056777954D, 0.2555716931819916D, 0.25579825043678284D, 0.2560243308544159D, 0.25624626874923706D, 0.2564801275730133D, 0.2567085325717926D, 0.2569340765476227D, 0.2571656405925751D, 0.25739872455596924D, 0.2576286792755127D, 0.25786054134368896D, 0.2580936551094055D, 0.2583216726779938D, 0.25856003165245056D, 0.2587873339653015D, 0.25902122259140015D, 0.2592563033103943D, 0.2594849765300751D, 0.2597160339355469D, 0.25995558500289917D, 0.2601858973503113D, 0.2604183256626129D, 0.2606464922428131D, 0.26088303327560425D, 0.2611151337623596D, 0.26134592294692993D, 0.2615800201892853D, 0.2618105709552765D, 0.2620517909526825D, 0.2622908055782318D, 0.26252609491348267D, 0.2627618610858917D, 0.262994647026062D, 0.26323479413986206D, 0.26346999406814575D, 0.26371172070503235D, 0.26394981145858765D, 0.2641925811767578D, 0.26443660259246826D, 0.2646687924861908D, 0.26490625739097595D, 0.26514482498168945D, 0.2653883397579193D, 0.2656254470348358D, 0.26586461067199707D, 0.2660968005657196D, 0.26632776856422424D, 0.2665672302246094D, 0.2668079137802124D, 0.2670527696609497D, 0.26729103922843933D, 0.26753705739974976D, 0.267774760723114D, 0.2680116295814514D, 0.2682532072067261D, 0.2684982419013977D, 0.26874080300331116D, 0.26898348331451416D, 0.2692258656024933D, 0.26946553587913513D, 0.26971226930618286D, 0.26995396614074707D, 0.2702105641365051D, 0.2704511284828186D, 0.2706947326660156D, 0.2709454596042633D, 0.27119338512420654D, 0.2714472711086273D, 0.271695613861084D, 0.2719452679157257D, 0.2721904516220093D, 0.272445946931839D, 0.2727034091949463D, 0.27296075224876404D, 0.2732025980949402D, 0.27344566583633423D, 0.2736923396587372D, 0.273937851190567D, 0.2741943597793579D, 0.2744433581829071D, 0.2747053802013397D, 0.2749590575695038D, 0.27520620822906494D, 0.2754532992839813D, 0.27570030093193054D, 0.27594417333602905D, 0.2761920094490051D, 0.27644631266593933D, 0.2766968309879303D, 0.2769581079483032D, 0.277214914560318D, 0.2774685323238373D, 0.27772653102874756D, 0.2779829204082489D, 0.2782370150089264D, 0.2784930467605591D, 0.27874892950057983D, 0.2790064215660095D, 0.2792629301548004D, 0.2795135974884033D, 0.27977338433265686D, 0.28003010153770447D, 0.2802872657775879D, 0.2805541753768921D, 0.28081098198890686D, 0.28106915950775146D, 0.2813355028629303D, 0.2816014885902405D, 0.28186270594596863D, 0.28211551904678345D, 0.28238385915756226D, 0.28264784812927246D, 0.2829170227050781D, 0.28318625688552856D, 0.28344595432281494D, 0.2837064266204834D, 0.2839750647544861D, 0.28424525260925293D, 0.2845102846622467D, 0.2847710847854614D, 0.28503847122192383D, 0.285302072763443D, 0.2855624556541443D, 0.28583529591560364D, 0.28610533475875854D, 0.2863694727420807D, 0.28663894534111023D, 0.28690820932388306D, 0.2871835231781006D, 0.2874460816383362D, 0.28770965337753296D, 0.28797629475593567D, 0.28824037313461304D, 0.2885114252567291D, 0.28877952694892883D, 0.28905394673347473D, 0.2893272340297699D, 0.2896009385585785D, 0.2898753881454468D, 0.2901516556739807D, 0.29043030738830566D, 0.2906986474990845D, 0.2909756600856781D, 0.2912502586841583D, 0.2915216088294983D, 0.2917991578578949D, 0.2920747995376587D, 0.29235514998435974D, 0.29263055324554443D, 0.29290643334388733D, 0.29318350553512573D, 0.2934582233428955D, 0.2937442362308502D, 0.29402175545692444D, 0.2943044602870941D, 0.29458490014076233D, 0.294856458902359D, 0.29513412714004517D, 0.2954207956790924D, 0.2957027554512024D, 0.29599303007125854D, 0.2962748110294342D, 0.29655298590660095D, 0.29684072732925415D, 0.2971268594264984D, 0.297414630651474D, 0.29770198464393616D, 0.2979874312877655D, 0.2982670068740845D, 0.2985551059246063D, 0.2988506555557251D, 0.29913589358329773D, 0.29941803216934204D, 0.29970577359199524D, 0.2999911904335022D, 0.30029740929603577D, 0.30059298872947693D, 0.30088740587234497D, 0.30117687582969666D, 0.3014709949493408D, 0.3017614483833313D, 0.3020592927932739D, 0.3023589253425598D, 0.30265122652053833D, 0.3029458820819855D, 0.3032380938529968D, 0.3035353124141693D, 0.3038356900215149D, 0.30413827300071716D, 0.3044430613517761D, 0.3047422170639038D, 0.30505242943763733D, 0.3053557276725769D, 0.3056688904762268D, 0.30598193407058716D, 0.3062831461429596D, 0.3065822124481201D, 0.3068911135196686D, 0.3071833848953247D, 0.30748212337493896D, 0.30779045820236206D, 0.30809691548347473D, 0.30840522050857544D, 0.30872541666030884D, 0.30904072523117065D, 0.30936363339424133D, 0.3096707761287689D, 0.3099910020828247D, 0.31029611825942993D, 0.3106105327606201D, 0.31092625856399536D, 0.3112245798110962D, 0.3115399479866028D, 0.3118637800216675D, 0.31218570470809937D, 0.31249749660491943D, 0.3128180205821991D, 0.3131491243839264D, 0.3134590685367584D, 0.3137769103050232D, 0.31409183144569397D, 0.31440991163253784D, 0.3147423267364502D, 0.315074622631073D, 0.31538769602775574D, 0.3157178461551666D, 0.31604892015457153D, 0.3163736164569855D, 0.31670817732810974D, 0.31702810525894165D, 0.317355751991272D, 0.31768372654914856D, 0.31801432371139526D, 0.31834226846694946D, 0.31866806745529175D, 0.31899839639663696D, 0.31932738423347473D, 0.3196604251861572D, 0.32000088691711426D, 0.3203379511833191D, 0.32066595554351807D, 0.32100751996040344D, 0.3213508725166321D, 0.3216894865036011D, 0.322036474943161D, 0.322383314371109D, 0.32273414731025696D, 0.323082834482193D, 0.32343026995658875D, 0.3237669765949249D, 0.32412171363830566D, 0.3244626522064209D, 0.32481491565704346D, 0.32516875863075256D, 0.3255179226398468D, 0.325869619846344D, 0.3262259066104889D, 0.32658839225769043D, 0.3269360065460205D, 0.32728952169418335D, 0.3276480734348297D, 0.3280147612094879D, 0.3283637762069702D, 0.32871752977371216D, 0.32907935976982117D, 0.32943716645240784D, 0.3297964036464691D, 0.3301599621772766D, 0.33051931858062744D, 0.3308880627155304D, 0.3312579095363617D, 0.33161529898643494D, 0.3319781720638275D, 0.3323523998260498D, 0.3327375650405884D, 0.33311545848846436D, 0.33348867297172546D, 0.3338663876056671D, 0.3342553377151489D, 0.33464017510414124D, 0.33502036333084106D, 0.335401713848114D, 0.3357864320278168D, 0.3361833691596985D, 0.3365689218044281D, 0.33695119619369507D, 0.3373405933380127D, 0.33773842453956604D, 0.3381268084049225D, 0.3385128974914551D, 0.33890458941459656D, 0.3392952084541321D, 0.33968889713287354D, 0.3400922119617462D, 0.34048500657081604D, 0.3408714830875397D, 0.3412691354751587D, 0.34166914224624634D, 0.34207582473754883D, 0.3424929678440094D, 0.3428908586502075D, 0.3432921767234802D, 0.34369343519210815D, 0.3441072404384613D, 0.34452903270721436D, 0.3449375331401825D, 0.34534019231796265D, 0.3457581698894501D, 0.3461754322052002D, 0.3465886414051056D, 0.34700435400009155D, 0.34742265939712524D, 0.34784501791000366D, 0.34826958179473877D, 0.34871307015419006D, 0.3491317629814148D, 0.3495660424232483D, 0.3500021994113922D, 0.35043758153915405D, 0.35088497400283813D, 0.3513285517692566D, 0.3517633378505707D, 0.35219472646713257D, 0.3526288568973541D, 0.35309097170829773D, 0.35355913639068604D, 0.35399898886680603D, 0.35447028279304504D, 0.3549261689186096D, 0.35538268089294434D, 0.3558322489261627D, 0.3562908172607422D, 0.35675758123397827D, 0.35722026228904724D, 0.3576938509941101D, 0.35815972089767456D, 0.35862985253334045D, 0.35909539461135864D, 0.35957416892051697D, 0.36005738377571106D, 0.36053022742271423D, 0.36100655794143677D, 0.36148983240127563D, 0.3619798719882965D, 0.3624771535396576D, 0.36297959089279175D, 0.36347851157188416D, 0.3639810383319855D, 0.36445868015289307D, 0.36495158076286316D, 0.36546313762664795D, 0.3659844994544983D, 0.36649754643440247D, 0.36702680587768555D, 0.3675394356250763D, 0.3680706322193146D, 0.36859145760536194D, 0.3691083490848541D, 0.3696277141571045D, 0.3701637089252472D, 0.3707152307033539D, 0.37122446298599243D, 0.37175998091697693D, 0.3722837269306183D, 0.3728159964084625D, 0.3733748495578766D, 0.37392672896385193D, 0.37447816133499146D, 0.37505069375038147D, 0.375622421503067D, 0.3761715888977051D, 0.37675145268440247D, 0.37734055519104004D, 0.3779241442680359D, 0.3785025477409363D, 0.3791196346282959D, 0.37970981001853943D, 0.38029128313064575D, 0.3808829188346863D, 0.38146936893463135D, 0.3820830285549164D, 0.3827105760574341D, 0.3833059072494507D, 0.38394442200660706D, 0.3845558762550354D, 0.3851664662361145D, 0.38580548763275146D, 0.3864295184612274D, 0.3870803415775299D, 0.38771069049835205D, 0.3883456885814667D, 0.38899171352386475D, 0.38965052366256714D, 0.3903161883354187D, 0.3909873962402344D, 0.39163389801979065D, 0.3923026919364929D, 0.3929727375507355D, 0.3936687409877777D, 0.39436736702919006D, 0.395059734582901D, 0.395771861076355D, 0.3964758813381195D, 0.3972088098526001D, 0.39794230461120605D, 0.39865103363990784D, 0.39939573407173157D, 0.4001447558403015D, 0.4009042978286743D, 0.40168482065200806D, 0.40247029066085815D, 0.4032696485519409D, 0.4040483832359314D, 0.4048703610897064D, 0.40569815039634705D, 0.4065134525299072D, 0.4073511064052582D, 0.4082093834877014D, 0.40910643339157104D, 0.40995070338249207D, 0.4108522832393646D, 0.4117118716239929D, 0.41257336735725403D, 0.4134874641895294D, 0.41438743472099304D, 0.41531622409820557D, 0.4162694215774536D, 0.4172126054763794D, 0.41816097497940063D, 0.41914936900138855D, 0.42015671730041504D, 0.4211525321006775D, 0.4221918284893036D, 0.42320090532302856D, 0.4242560863494873D, 0.4253188669681549D, 0.4263918697834015D, 0.42751896381378174D, 0.42864561080932617D, 0.4297972321510315D, 0.4309712052345276D, 0.43211647868156433D, 0.43333739042282104D, 0.43459197878837585D, 0.4358139634132385D, 0.43709370493888855D, 0.43841537833213806D, 0.43972235918045044D, 0.4410899579524994D, 0.44247907400131226D, 0.44390785694122314D, 0.4453846514225006D, 0.44687512516975403D, 0.44836026430130005D, 0.4498823583126068D, 0.45146554708480835D, 0.4531130790710449D, 0.45482560992240906D, 0.4566359221935272D, 0.45852598547935486D, 0.4604836702346802D, 0.46249786019325256D, 0.4645693302154541D, 0.4668006896972656D, 0.46896860003471375D, 0.4712623059749603D, 0.473666787147522D, 0.4763219356536865D, 0.4791247844696045D, 0.48207300901412964D, 0.4851433336734772D, 0.48835480213165283D, 0.49189335107803345D, 0.49576520919799805D, 0.500032901763916D, 0.5047979354858398D, 0.510280966758728D, 0.5167609453201294D, 0.5248829126358032D, 0.5349445343017578D, 0.550952136516571D, 0.6102362275123596D}; + private static final double[] normalMap1 = new double[] {-0.993981122970581D, -0.9867534041404724D, -0.9814018607139587D, -0.9777977466583252D, -0.9740672707557678D, -0.9704886674880981D, -0.9673173427581787D, -0.964655876159668D, -0.9624447226524353D, -0.9604035019874573D, -0.9586348533630371D, -0.956900417804718D, -0.955359697341919D, -0.9537981152534485D, -0.9522461891174316D, -0.9506949186325073D, -0.9491915702819824D, -0.947837233543396D, -0.9465093612670898D, -0.9452851414680481D, -0.9440163969993591D, -0.9427854418754578D, -0.9415590167045593D, -0.9404380321502686D, -0.9392384886741638D, -0.9381521344184875D, -0.9370340704917908D, -0.9359375238418579D, -0.9349455237388611D, -0.9338868260383606D, -0.9328497648239136D, -0.931911826133728D, -0.9309902191162109D, -0.9300264716148376D, -0.9290929436683655D, -0.9282076954841614D, -0.9272778034210205D, -0.9263636469841003D, -0.9254574179649353D, -0.9245976209640503D, -0.9237018823623657D, -0.9228191375732422D, -0.9219982624053955D, -0.921193540096283D, -0.9204187393188477D, -0.9196520447731018D, -0.918891191482544D, -0.91814786195755D, -0.9173845052719116D, -0.9166402816772461D, -0.9158709645271301D, -0.9151347875595093D, -0.9144362807273865D, -0.9137468338012695D, -0.9130550622940063D, -0.9123724102973938D, -0.9117192029953003D, -0.9110715389251709D, -0.9104556441307068D, -0.9098379611968994D, -0.9092051982879639D, -0.908571720123291D, -0.9079737067222595D, -0.9073951840400696D, -0.906777024269104D, -0.9061700701713562D, -0.9055814743041992D, -0.9050177335739136D, -0.9044249057769775D, -0.903881847858429D, -0.9033547043800354D, -0.9028249979019165D, -0.902289092540741D, -0.9017468094825745D, -0.9012556672096252D, -0.9007599353790283D, -0.9002755880355835D, -0.8997661471366882D, -0.8992534279823303D, -0.8987354636192322D, -0.8982405066490173D, -0.8977617621421814D, -0.8972391486167908D, -0.8967417478561401D, -0.896254301071167D, -0.8957591652870178D, -0.895301878452301D, -0.8948580026626587D, -0.8943824768066406D, -0.8938983082771301D, -0.8934217095375061D, -0.8929500579833984D, -0.8924669027328491D, -0.8919958472251892D, -0.8915202021598816D, -0.8910564184188843D, -0.8906219005584717D, -0.8901892304420471D, -0.8897593021392822D, -0.8893160820007324D, -0.888887882232666D, -0.8884394764900208D, -0.8880050778388977D, -0.8875910043716431D, -0.8871419429779053D, -0.8867276906967163D, -0.8862883448600769D, -0.8858384490013123D, -0.8854177594184875D, -0.8849796652793884D, -0.8845346570014954D, -0.8840920925140381D, -0.8836329579353333D, -0.8831575512886047D, -0.882702112197876D, -0.8822483420372009D, -0.8818038105964661D, -0.8813790082931519D, -0.8809268474578857D, -0.8804680705070496D, -0.8800069093704224D, -0.8795323967933655D, -0.879081666469574D, -0.8786211013793945D, -0.8781455159187317D, -0.8776878714561462D, -0.8772246241569519D, -0.8767819404602051D, -0.876311182975769D, -0.8758470416069031D, -0.8753729462623596D, -0.8749485611915588D, -0.8744806051254272D, -0.8740207552909851D, -0.873558521270752D, -0.8731053471565247D, -0.8726766705513D, -0.8722361326217651D, -0.8717890977859497D, -0.8713359832763672D, -0.8708965182304382D, -0.8704631924629211D, -0.8700135350227356D, -0.8695434331893921D, -0.8690747022628784D, -0.8685927987098694D, -0.8681243062019348D, -0.8676489591598511D, -0.8671760559082031D, -0.8667223453521729D, -0.8662542700767517D, -0.8658044338226318D, -0.8653705716133118D, -0.8648831844329834D, -0.8644269108772278D, -0.863974392414093D, -0.8635271787643433D, -0.8630731105804443D, -0.8626294136047363D, -0.8622041344642639D, -0.8617463707923889D, -0.8612802624702454D, -0.8608363270759583D, -0.8603652715682983D, -0.8599016666412354D, -0.8594528436660767D, -0.8590061068534851D, -0.8585623502731323D, -0.8581123352050781D, -0.8576651215553284D, -0.8571998476982117D, -0.8567615151405334D, -0.8563039898872375D, -0.855833113193512D, -0.8553852438926697D, -0.8549563884735107D, -0.8545076251029968D, -0.854032576084137D, -0.8535919189453125D, -0.8531304597854614D, -0.8526818156242371D, -0.8522078990936279D, -0.8517653942108154D, -0.8513281345367432D, -0.8508611917495728D, -0.8504223227500916D, -0.8499665260314941D, -0.849520206451416D, -0.849053680896759D, -0.8485954403877258D, -0.8481417298316956D, -0.847692608833313D, -0.8472627401351929D, -0.8468097448348999D, -0.8463746905326843D, -0.8459068536758423D, -0.8454430103302002D, -0.8449950814247131D, -0.8445459604263306D, -0.8440717458724976D, -0.8435981273651123D, -0.8431227803230286D, -0.8426408767700195D, -0.8421630859375D, -0.8417009711265564D, -0.8412379026412964D, -0.8407769799232483D, -0.8403106331825256D, -0.8398558497428894D, -0.8393968343734741D, -0.8389428853988647D, -0.8384616374969482D, -0.8379984498023987D, -0.8375331163406372D, -0.8370792865753174D, -0.8366209864616394D, -0.8361372947692871D, -0.8356479406356812D, -0.8351752161979675D, -0.8347142934799194D, -0.8342487812042236D, -0.8338004350662231D, -0.8333517909049988D, -0.8328940272331238D, -0.8324223756790161D, -0.831952691078186D, -0.8314595222473145D, -0.8309986591339111D, -0.8305644392967224D, -0.8301018476486206D, -0.8296616077423096D, -0.8291927576065063D, -0.8287414312362671D, -0.8282740116119385D, -0.8278439044952393D, -0.8274041414260864D, -0.82695072889328D, -0.8264832496643066D, -0.8260218501091003D, -0.8255581855773926D, -0.8250904679298401D, -0.824647068977356D, -0.8241927623748779D, -0.823721170425415D, -0.8232881426811218D, -0.8228266835212708D, -0.8223466277122498D, -0.8218891024589539D, -0.8214482665061951D, -0.8209536075592041D, -0.8205164074897766D, -0.8200206160545349D, -0.8195541501045227D, -0.8191131353378296D, -0.8186835050582886D, -0.8182293772697449D, -0.8177539706230164D, -0.8172938227653503D, -0.8168179988861084D, -0.8163681626319885D, -0.8159137964248657D, -0.8154714703559875D, -0.8150300979614258D, -0.8145816922187805D, -0.8141164183616638D, -0.8136304020881653D, -0.813171923160553D, -0.812709391117096D, -0.8122345805168152D, -0.8117756247520447D, -0.8113128542900085D, -0.810836672782898D, -0.8103585243225098D, -0.8099002838134766D, -0.809456467628479D, -0.808990478515625D, -0.8085386157035828D, -0.8080651164054871D, -0.8075961470603943D, -0.807146430015564D, -0.8066928386688232D, -0.8062372207641602D, -0.8057619333267212D, -0.8053189516067505D, -0.8048828840255737D, -0.804431676864624D, -0.803987979888916D, -0.803577184677124D, -0.8031604290008545D, -0.8027421832084656D, -0.8023148775100708D, -0.8018929958343506D, -0.8014708757400513D, -0.8010631799697876D, -0.8006236553192139D, -0.8002043962478638D, -0.7997668385505676D, -0.7993491888046265D, -0.7989336252212524D, -0.7984876036643982D, -0.7980768084526062D, -0.7976296544075012D, -0.7971917390823364D, -0.7967548966407776D, -0.7962918877601624D, -0.7958443760871887D, -0.795405387878418D, -0.7949764728546143D, -0.7945268154144287D, -0.7940919399261475D, -0.7936583161354065D, -0.7932078838348389D, -0.7927955389022827D, -0.7923596501350403D, -0.7919219136238098D, -0.7914819121360779D, -0.791064441204071D, -0.7906320691108704D, -0.79017174243927D, -0.7897169589996338D, -0.7892693281173706D, -0.7888533473014832D, -0.788398802280426D, -0.7879447340965271D, -0.7875177264213562D, -0.7870922088623047D, -0.7866427302360535D, -0.7862313985824585D, -0.7857956290245056D, -0.7853496670722961D, -0.7849026918411255D, -0.7844541072845459D, -0.7840293645858765D, -0.7835724353790283D, -0.7831109166145325D, -0.7826611399650574D, -0.7821875214576721D, -0.7817301154136658D, -0.7812873721122742D, -0.7808514833450317D, -0.7803935408592224D, -0.7799123525619507D, -0.7794713377952576D, -0.7790182828903198D, -0.7785621881484985D, -0.7781559228897095D, -0.7776877880096436D, -0.7772501707077026D, -0.7768174409866333D, -0.7763848900794983D, -0.7759107351303101D, -0.7754525542259216D, -0.7749996185302734D, -0.7745270133018494D, -0.7740670442581177D, -0.7736034989356995D, -0.773161768913269D, -0.7726963758468628D, -0.7722465395927429D, -0.7717506289482117D, -0.7712973952293396D, -0.7708300352096558D, -0.7703608274459839D, -0.7698842287063599D, -0.7694273591041565D, -0.768983006477356D, -0.7685385942459106D, -0.76810622215271D, -0.7676629424095154D, -0.7671942710876465D, -0.7667547464370728D, -0.7662950754165649D, -0.7658786773681641D, -0.7654168605804443D, -0.76496821641922D, -0.764512300491333D, -0.7640527486801147D, -0.7636140584945679D, -0.7631645798683167D, -0.7627111077308655D, -0.7622628808021545D, -0.7618300914764404D, -0.7613887190818787D, -0.7609382271766663D, -0.760509729385376D, -0.7600770592689514D, -0.7596333622932434D, -0.7592030763626099D, -0.758743941783905D, -0.7582821846008301D, -0.7578146457672119D, -0.7573472261428833D, -0.7569139003753662D, -0.7564945220947266D, -0.7560456991195679D, -0.7555922865867615D, -0.7551515698432922D, -0.7547208070755005D, -0.7542534470558167D, -0.7538049221038818D, -0.7533339262008667D, -0.752889096736908D, -0.7524533867835999D, -0.7520151734352112D, -0.7515751719474792D, -0.7511124014854431D, -0.7506847381591797D, -0.7502515912055969D, -0.7498141527175903D, -0.7493629455566406D, -0.7488939762115479D, -0.7484484314918518D, -0.7480183243751526D, -0.7475797533988953D, -0.7471202611923218D, -0.7466857433319092D, -0.746245265007019D, -0.7458525896072388D, -0.7454100847244263D, -0.7449892163276672D, -0.744547426700592D, -0.7441168427467346D, -0.7436603903770447D, -0.7432155609130859D, -0.7427309155464172D, -0.7422654032707214D, -0.7418230175971985D, -0.7413456439971924D, -0.7408867478370667D, -0.7404426336288452D, -0.7399845719337463D, -0.7395214438438416D, -0.7390555739402771D, -0.7385861277580261D, -0.738116443157196D, -0.7376468777656555D, -0.7371915578842163D, -0.7367280721664429D, -0.7362213730812073D, -0.7357624769210815D, -0.735304057598114D, -0.7348542809486389D, -0.7343930006027222D, -0.7338942885398865D, -0.7334224581718445D, -0.7329620122909546D, -0.7324798703193665D, -0.7320289611816406D, -0.7315279245376587D, -0.7310631275177002D, -0.7305946350097656D, -0.7301591634750366D, -0.7297176718711853D, -0.7292467951774597D, -0.7288281321525574D, -0.7283647060394287D, -0.7278772592544556D, -0.727400541305542D, -0.7269569039344788D, -0.7264780402183533D, -0.7260096669197083D, -0.725562334060669D, -0.7250648140907288D, -0.7245859503746033D, -0.7241119146347046D, -0.723630428314209D, -0.7231666445732117D, -0.7227104902267456D, -0.7222658395767212D, -0.7217769622802734D, -0.7213007211685181D, -0.7208353877067566D, -0.720391571521759D, -0.7199460864067078D, -0.7194427847862244D, -0.7189367413520813D, -0.7185240983963013D, -0.7180306911468506D, -0.7175722718238831D, -0.7170929908752441D, -0.7166170477867126D, -0.7161218523979187D, -0.7156761288642883D, -0.7152342200279236D, -0.7147595882415771D, -0.7143203020095825D, -0.7138813734054565D, -0.7134413123130798D, -0.7129658460617065D, -0.712531566619873D, -0.7120937705039978D, -0.7116792798042297D, -0.7112746238708496D, -0.7108534574508667D, -0.7104528546333313D, -0.7100372314453125D, -0.7095867395401001D, -0.7091600298881531D, -0.7087348103523254D, -0.7083083987236023D, -0.7078754305839539D, -0.7074360251426697D, -0.7070069313049316D, -0.7065709233283997D, -0.7061734199523926D, -0.7057405710220337D, -0.7053127288818359D, -0.7048872113227844D, -0.7044483423233032D, -0.7040207386016846D, -0.7036097049713135D, -0.7031928896903992D, -0.7027456164360046D, -0.7023111581802368D, -0.7018752694129944D, -0.7014437317848206D, -0.7010111808776855D, -0.7005510926246643D, -0.7001100778579712D, -0.6996980905532837D, -0.6992843747138977D, -0.6988713145256042D, -0.6983832716941833D, -0.6979185938835144D, -0.6974824666976929D, -0.6970443725585938D, -0.6965860724449158D, -0.6961517333984375D, -0.6956964135169983D, -0.6952543258666992D, -0.6948185563087463D, -0.6944015622138977D, -0.6939572691917419D, -0.6935084462165833D, -0.6930390000343323D, -0.6925643086433411D, -0.6920949816703796D, -0.6916420459747314D, -0.6911906003952026D, -0.6907227039337158D, -0.690259575843811D, -0.6897680163383484D, -0.6892983913421631D, -0.6888791918754578D, -0.6883915066719055D, -0.6879323124885559D, -0.6874868869781494D, -0.6870161294937134D, -0.6865673065185547D, -0.6861105561256409D, -0.685651421546936D, -0.6852194666862488D, -0.6847624778747559D, -0.6842747330665588D, -0.6838182210922241D, -0.6833785176277161D, -0.6829265356063843D, -0.6824387311935425D, -0.6819712519645691D, -0.6814887523651123D, -0.6810264587402344D, -0.6805755496025085D, -0.6800896525382996D, -0.6796098947525024D, -0.6791496276855469D, -0.6786936521530151D, -0.6782419085502625D, -0.677756130695343D, -0.6773126125335693D, -0.6768563389778137D, -0.6764082908630371D, -0.6759566068649292D, -0.6755016446113586D, -0.6750813722610474D, -0.6746301651000977D, -0.6741729974746704D, -0.6736992001533508D, -0.6732316613197327D, -0.6727883815765381D, -0.6723057627677917D, -0.6718435287475586D, -0.6713894009590149D, -0.6709365844726562D, -0.6704763770103455D, -0.6700304746627808D, -0.6695900559425354D, -0.6691245436668396D, -0.6686742305755615D, -0.668216347694397D, -0.6677833199501038D, -0.6673141717910767D, -0.6668790578842163D, -0.6664288640022278D, -0.6659941673278809D, -0.6655833125114441D, -0.6651661396026611D, -0.6647082567214966D, -0.6642827391624451D, -0.6638473868370056D, -0.6633561253547668D, -0.6628942489624023D, -0.6624237298965454D, -0.6619466543197632D, -0.6615045666694641D, -0.661072850227356D, -0.6605978608131409D, -0.6601710915565491D, -0.6597480773925781D, -0.6592699885368347D, -0.6588332056999207D, -0.658392608165741D, -0.6579496264457703D, -0.657446026802063D, -0.656986653804779D, -0.6565669775009155D, -0.6561056971549988D, -0.6556894779205322D, -0.6552327275276184D, -0.6548108458518982D, -0.6544176936149597D, -0.6539667248725891D, -0.6535317897796631D, -0.6530807018280029D, -0.6526519060134888D, -0.6522371768951416D, -0.6518018841743469D, -0.6513494849205017D, -0.6508753299713135D, -0.6504021883010864D, -0.6499971151351929D, -0.6495323181152344D, -0.6490973234176636D, -0.6486873626708984D, -0.6482400894165039D, -0.6477917432785034D, -0.6473706364631653D, -0.646914541721344D, -0.6464476585388184D, -0.645993173122406D, -0.6455405950546265D, -0.6450999975204468D, -0.64466792345047D, -0.6442462205886841D, -0.6438097357749939D, -0.6433576941490173D, -0.6429150700569153D, -0.6425103545188904D, -0.6420614719390869D, -0.6415934562683105D, -0.6411587595939636D, -0.6407563090324402D, -0.6403141617774963D, -0.6398285031318665D, -0.6393874287605286D, -0.638950526714325D, -0.6384929418563843D, -0.6380735039710999D, -0.6376455426216125D, -0.6371946334838867D, -0.6367603540420532D, -0.6363311409950256D, -0.6358823180198669D, -0.63546222448349D, -0.6350165605545044D, -0.6345629692077637D, -0.6341010332107544D, -0.6336252689361572D, -0.6331813335418701D, -0.63270503282547D, -0.6322590708732605D, -0.6318042278289795D, -0.6313715577125549D, -0.6309155225753784D, -0.630476176738739D, -0.6300145387649536D, -0.6295765042304993D, -0.6291170716285706D, -0.6286421418190002D, -0.6281881332397461D, -0.6277390122413635D, -0.6272373795509338D, -0.6267513632774353D, -0.6262896656990051D, -0.6258484721183777D, -0.6253910064697266D, -0.6249442100524902D, -0.6244901418685913D, -0.6240485310554504D, -0.6236206889152527D, -0.6231616139411926D, -0.6226596832275391D, -0.6221743226051331D, -0.6217489242553711D, -0.621291995048523D, -0.6208148002624512D, -0.6203911900520325D, -0.6199749112129211D, -0.6195303797721863D, -0.6190845370292664D, -0.6185699701309204D, -0.6181412935256958D, -0.6176934242248535D, -0.6172602772712708D, -0.6167842149734497D, -0.6163712739944458D, -0.6158850789070129D, -0.6154088377952576D, -0.6149631142616272D, -0.6145434379577637D, -0.6141135692596436D, -0.6136382222175598D, -0.6131902933120728D, -0.612743079662323D, -0.6123250126838684D, -0.6118547916412354D, -0.6114357113838196D, -0.6109917163848877D, -0.6105717420578003D, -0.6101329922676086D, -0.6097121834754944D, -0.6092851161956787D, -0.6088412404060364D, -0.6084098815917969D, -0.6079666614532471D, -0.607525646686554D, -0.6070682406425476D, -0.6065964102745056D, -0.6061907410621643D, -0.6057188510894775D, -0.605266809463501D, -0.6048122048377991D, -0.604347288608551D, -0.6038910746574402D, -0.6034500002861023D, -0.6030161380767822D, -0.6025460362434387D, -0.6021080017089844D, -0.6016576290130615D, -0.6012001037597656D, -0.6007413864135742D, -0.6002840399742126D, -0.5998591184616089D, -0.5994294881820679D, -0.5989652276039124D, -0.5984882712364197D, -0.5980018973350525D, -0.5975683331489563D, -0.5971066951751709D, -0.5966431498527527D, -0.59619140625D, -0.5958024859428406D, -0.5953621864318848D, -0.5949565172195435D, -0.5945692658424377D, -0.5941520929336548D, -0.5936878323554993D, -0.5932301878929138D, -0.5927911996841431D, -0.5923627018928528D, -0.5918761491775513D, -0.5914469957351685D, -0.5909724831581116D, -0.5905429720878601D, -0.5900884866714478D, -0.5896493792533875D, -0.5892290472984314D, -0.5887760519981384D, -0.5883501768112183D, -0.5878588557243347D, -0.58735191822052D, -0.5868979692459106D, -0.586448073387146D, -0.5860018730163574D, -0.5855519771575928D, -0.5850552916526794D, -0.5845991969108582D, -0.5841348767280579D, -0.5837119221687317D, -0.5832936763763428D, -0.5828707218170166D, -0.5824082493782043D, -0.5820251703262329D, -0.5815789699554443D, -0.5810984969139099D, -0.5806310176849365D, -0.5801907777786255D, -0.5797252058982849D, -0.5792809724807739D, -0.5788083076477051D, -0.5783213973045349D, -0.5778913497924805D, -0.5774275660514832D, -0.5769709348678589D, -0.5765695571899414D, -0.5761199593544006D, -0.5756808519363403D, -0.5751828551292419D, -0.574739396572113D, -0.5742871761322021D, -0.5738288164138794D, -0.5733629465103149D, -0.5729423761367798D, -0.572485089302063D, -0.5720058679580688D, -0.5715680122375488D, -0.5710999965667725D, -0.5706731081008911D, -0.5702232718467712D, -0.56974858045578D, -0.5693201422691345D, -0.568897545337677D, -0.5684503316879272D, -0.5680347084999084D, -0.5675626397132874D, -0.5670663714408875D, -0.5666159987449646D, -0.5661755204200745D, -0.5656933784484863D, -0.5652275681495667D, -0.5647632479667664D, -0.5643265247344971D, -0.5638944506645203D, -0.5634651184082031D, -0.5630204677581787D, -0.5625607967376709D, -0.5621016621589661D, -0.5616597533226013D, -0.5612028241157532D, -0.5607337355613708D, -0.5603100657463074D, -0.5598271489143372D, -0.5593815445899963D, -0.5589413046836853D, -0.5584782958030701D, -0.5580465197563171D, -0.5575783848762512D, -0.5571232438087463D, -0.5566560626029968D, -0.5562322735786438D, -0.555738627910614D, -0.5552665591239929D, -0.554823637008667D, -0.5543604493141174D, -0.5538782477378845D, -0.5534418225288391D, -0.5529850721359253D, -0.5525240898132324D, -0.5520437359809875D, -0.5515938997268677D, -0.5511279106140137D, -0.5506861209869385D, -0.550226628780365D, -0.5497331619262695D, -0.549257218837738D, -0.5488153100013733D, -0.5483522415161133D, -0.5478795170783997D, -0.5474520921707153D, -0.5469785332679749D, -0.5465142130851746D, -0.546062171459198D, -0.54566890001297D, -0.5452328324317932D, -0.5447759628295898D, -0.5443392395973206D, -0.5438827872276306D, -0.5434367656707764D, -0.5430113077163696D, -0.5425428152084351D, -0.5420520305633545D, -0.5415939092636108D, -0.5411363840103149D, -0.5407477617263794D, -0.5402787923812866D, -0.5398295521736145D, -0.5393424034118652D, -0.5388583540916443D, -0.5384265184402466D, -0.5379411578178406D, -0.5374878644943237D, -0.5370199084281921D, -0.5365350842475891D, -0.5360611081123352D, -0.5355649590492249D, -0.5351121425628662D, -0.5345990657806396D, -0.5341669321060181D, -0.5337467789649963D, -0.5333049297332764D, -0.5328750014305115D, -0.5324127078056335D, -0.5319854617118835D, -0.5315192937850952D, -0.5310415029525757D, -0.5306323766708374D, -0.5301699042320251D, -0.5297111868858337D, -0.5292492508888245D, -0.5287858843803406D, -0.5283259153366089D, -0.5278311967849731D, -0.5273903608322144D, -0.526936948299408D, -0.5265194773674011D, -0.5260910391807556D, -0.5256368517875671D, -0.5252177119255066D, -0.5247905254364014D, -0.5243833065032959D, -0.5239353775978088D, -0.5234636068344116D, -0.5229857563972473D, -0.5225380659103394D, -0.5220516920089722D, -0.5216032266616821D, -0.5211589932441711D, -0.5207035541534424D, -0.5202432870864868D, -0.519791841506958D, -0.5193343162536621D, -0.5189166069030762D, -0.5184645056724548D, -0.5180600881576538D, -0.5176355838775635D, -0.5171905755996704D, -0.516732394695282D, -0.5162793397903442D, -0.5158212184906006D, -0.5153780579566956D, -0.5149728059768677D, -0.5145182013511658D, -0.5140626430511475D, -0.5135531425476074D, -0.5130990147590637D, -0.5126319527626038D, -0.5121858716011047D, -0.5117676258087158D, -0.5113520622253418D, -0.5108791589736938D, -0.5104767084121704D, -0.5100153088569641D, -0.5095524191856384D, -0.5091241002082825D, -0.5086731314659119D, -0.5082252025604248D, -0.5077710151672363D, -0.507340133190155D, -0.5068773031234741D, -0.5063926577568054D, -0.5059119462966919D, -0.5054774880409241D, -0.505023717880249D, -0.5045510530471802D, -0.5040978193283081D, -0.503696858882904D, -0.5032621622085571D, -0.5028178095817566D, -0.502354085445404D, -0.50189208984375D, -0.5014151334762573D, -0.5009788870811462D, -0.5005399584770203D, -0.5000848770141602D, -0.4996296167373657D, -0.49916690587997437D, -0.49872907996177673D, -0.49828365445137024D, -0.49784278869628906D, -0.4973927140235901D, -0.4969747066497803D, -0.496499627828598D, -0.49605849385261536D, -0.49562790989875793D, -0.49520403146743774D, -0.49475109577178955D, -0.49428069591522217D, -0.4938359260559082D, -0.4933910667896271D, -0.49294254183769226D, -0.4924793839454651D, -0.49202969670295715D, -0.49162542819976807D, -0.4911677837371826D, -0.49067744612693787D, -0.49027812480926514D, -0.48984992504119873D, -0.4894086420536041D, -0.48893997073173523D, -0.48848411440849304D, -0.48805075883865356D, -0.4876094460487366D, -0.4871782958507538D, -0.4867188334465027D, -0.486240416765213D, -0.4857710599899292D, -0.4853622615337372D, -0.484923779964447D, -0.48443329334259033D, -0.4839499890804291D, -0.48351210355758667D, -0.4830566346645355D, -0.48261359333992004D, -0.48216360807418823D, -0.4817146360874176D, -0.4812493324279785D, -0.48077741265296936D, -0.48034119606018066D, -0.4799092411994934D, -0.4794424772262573D, -0.4789618253707886D, -0.47851404547691345D, -0.47807857394218445D, -0.47761446237564087D, -0.47712457180023193D, -0.47667333483695984D, -0.47622331976890564D, -0.4757482409477234D, -0.4752673804759979D, -0.4748130440711975D, -0.47434619069099426D, -0.47390732169151306D, -0.47345981001853943D, -0.4729853868484497D, -0.4725019633769989D, -0.47202643752098083D, -0.47158005833625793D, -0.47112029790878296D, -0.47066575288772583D, -0.47026416659355164D, -0.46979641914367676D, -0.4693371057510376D, -0.4688774645328522D, -0.46840471029281616D, -0.46793320775032043D, -0.4674986004829407D, -0.46702343225479126D, -0.46656137704849243D, -0.4661322236061096D, -0.46566006541252136D, -0.46519672870635986D, -0.46473783254623413D, -0.46439436078071594D, -0.46398577094078064D, -0.46354690194129944D, -0.46305525302886963D, -0.46262606978416443D, -0.4621753990650177D, -0.4616986811161041D, -0.46126776933670044D, -0.4608273208141327D, -0.4603559076786041D, -0.4598826467990875D, -0.4594634771347046D, -0.45901820063591003D, -0.45853206515312195D, -0.45805060863494873D, -0.4576207399368286D, -0.45715758204460144D, -0.4567049443721771D, -0.45628368854522705D, -0.45583370327949524D, -0.45539772510528564D, -0.45492687821388245D, -0.4544738233089447D, -0.4540203809738159D, -0.45354411005973816D, -0.45309826731681824D, -0.4526641070842743D, -0.4522310495376587D, -0.45176005363464355D, -0.45129984617233276D, -0.4508618116378784D, -0.450420081615448D, -0.4499739110469818D, -0.449531227350235D, -0.44908884167671204D, -0.4486551284790039D, -0.4482029676437378D, -0.4477347731590271D, -0.4472775161266327D, -0.44681406021118164D, -0.4463559091091156D, -0.44590938091278076D, -0.44546636939048767D, -0.44499215483665466D, -0.4445340037345886D, -0.4440937936306D, -0.4436649680137634D, -0.44318997859954834D, -0.44273874163627625D, -0.4422561824321747D, -0.44178012013435364D, -0.44134721159935D, -0.44089630246162415D, -0.4404234290122986D, -0.4399433732032776D, -0.43953943252563477D, -0.4390520751476288D, -0.43859511613845825D, -0.43811362981796265D, -0.43765103816986084D, -0.4372456967830658D, -0.43681710958480835D, -0.4363972842693329D, -0.4359303414821625D, -0.43546876311302185D, -0.43497487902641296D, -0.43451398611068726D, -0.4340492784976959D, -0.43363693356513977D, -0.4331943094730377D, -0.4327276945114136D, -0.43224164843559265D, -0.4318208396434784D, -0.43134722113609314D, -0.43084287643432617D, -0.4303792715072632D, -0.429912805557251D, -0.4294090270996094D, -0.42893385887145996D, -0.42844635248184204D, -0.42798569798469543D, -0.42753586173057556D, -0.4270614683628082D, -0.4265874922275543D, -0.4261167347431183D, -0.4256487786769867D, -0.42519906163215637D, -0.4247068464756012D, -0.4242536425590515D, -0.42379605770111084D, -0.42333462834358215D, -0.42286252975463867D, -0.4224444329738617D, -0.4219934046268463D, -0.4215393364429474D, -0.4210718274116516D, -0.42061617970466614D, -0.4201585054397583D, -0.41968807578086853D, -0.41920599341392517D, -0.4187593162059784D, -0.4182948172092438D, -0.41779500246047974D, -0.4173271656036377D, -0.41686588525772095D, -0.41638249158859253D, -0.41590481996536255D, -0.4154355227947235D, -0.4149766266345978D, -0.41452762484550476D, -0.4140367805957794D, -0.4136026203632355D, -0.4131450653076172D, -0.41266801953315735D, -0.41221460700035095D, -0.4117613732814789D, -0.4112788140773773D, -0.41078534722328186D, -0.41030487418174744D, -0.40985924005508423D, -0.40937814116477966D, -0.4089410901069641D, -0.40847721695899963D, -0.408033549785614D, -0.40757739543914795D, -0.40711915493011475D, -0.4066314697265625D, -0.4061741828918457D, -0.4056779444217682D, -0.4052165448665619D, -0.404753714799881D, -0.4042343497276306D, -0.4037852883338928D, -0.40332233905792236D, -0.402822881937027D, -0.4023677110671997D, -0.40190503001213074D, -0.4014160633087158D, -0.400924414396286D, -0.4004696011543274D, -0.3999839723110199D, -0.3995433449745178D, -0.39907631278038025D, -0.398613303899765D, -0.39813822507858276D, -0.3976576626300812D, -0.3971708416938782D, -0.3967016339302063D, -0.3961956202983856D, -0.3957078456878662D, -0.395264208316803D, -0.3948236107826233D, -0.3943391442298889D, -0.39385995268821716D, -0.39338982105255127D, -0.39291146397590637D, -0.39242783188819885D, -0.3919692933559418D, -0.39151468873023987D, -0.3910646140575409D, -0.39060062170028687D, -0.3901495039463043D, -0.38966214656829834D, -0.3891756236553192D, -0.3887067139148712D, -0.388319730758667D, -0.38788723945617676D, -0.3874429166316986D, -0.3869704306125641D, -0.38652777671813965D, -0.3860969543457031D, -0.38564804196357727D, -0.3851816952228546D, -0.3847781717777252D, -0.38431960344314575D, -0.38389864563941956D, -0.3834582567214966D, -0.383012592792511D, -0.3825145661830902D, -0.38205742835998535D, -0.3816487789154053D, -0.3812359869480133D, -0.38080450892448425D, -0.3803378641605377D, -0.3799078166484833D, -0.3794780373573303D, -0.3790120482444763D, -0.3785163164138794D, -0.37803179025650024D, -0.37758001685142517D, -0.37714439630508423D, -0.37673377990722656D, -0.3762897551059723D, -0.375853031873703D, -0.3754011392593384D, -0.37497463822364807D, -0.3745007812976837D, -0.37405502796173096D, -0.37361258268356323D, -0.3731582462787628D, -0.3727110028266907D, -0.3722643256187439D, -0.3717980980873108D, -0.37136033177375793D, -0.370922327041626D, -0.3704998791217804D, -0.3700500428676605D, -0.36958378553390503D, -0.36913618445396423D, -0.36870965361595154D, -0.368268221616745D, -0.3678186535835266D, -0.36736854910850525D, -0.3669017553329468D, -0.36642682552337646D, -0.3659965991973877D, -0.3655521273612976D, -0.3650961220264435D, -0.36464881896972656D, -0.36418700218200684D, -0.3637397885322571D, -0.3632592260837555D, -0.3628367483615875D, -0.36235979199409485D, -0.36191582679748535D, -0.3614809513092041D, -0.3609961271286011D, -0.36047661304473877D, -0.36004626750946045D, -0.3595779836177826D, -0.35911795496940613D, -0.35861992835998535D, -0.35819077491760254D, -0.35775429010391235D, -0.3572559058666229D, -0.3567827641963959D, -0.356319397687912D, -0.35587993264198303D, -0.3554006516933441D, -0.3549196124076843D, -0.35444262623786926D, -0.354030966758728D, -0.35353973507881165D, -0.35312512516975403D, -0.3526640236377716D, -0.3521788716316223D, -0.3517155945301056D, -0.35133352875709534D, -0.3508608043193817D, -0.3503953516483307D, -0.3499474823474884D, -0.34947678446769714D, -0.34898048639297485D, -0.3484885096549988D, -0.3480057716369629D, -0.34755030274391174D, -0.3470558226108551D, -0.34659838676452637D, -0.346110999584198D, -0.3456391990184784D, -0.34520697593688965D, -0.34475353360176086D, -0.34428736567497253D, -0.3437964916229248D, -0.3433292508125305D, -0.3428596258163452D, -0.34236952662467957D, -0.3418951630592346D, -0.3414383828639984D, -0.34095871448516846D, -0.3404501676559448D, -0.33999693393707275D, -0.3395421802997589D, -0.33909496665000916D, -0.3386416435241699D, -0.3381812274456024D, -0.33769848942756653D, -0.3371901512145996D, -0.33668965101242065D, -0.33621102571487427D, -0.3357529044151306D, -0.3353078067302704D, -0.33485859632492065D, -0.33441001176834106D, -0.3339252173900604D, -0.3334873914718628D, -0.33301955461502075D, -0.3325522541999817D, -0.33208945393562317D, -0.33160969614982605D, -0.3311447203159332D, -0.3306768536567688D, -0.3301656246185303D, -0.32972973585128784D, -0.3292653560638428D, -0.32879796624183655D, -0.3283538818359375D, -0.3278607130050659D, -0.32736411690711975D, -0.3268917202949524D, -0.3264242112636566D, -0.32594919204711914D, -0.3254433870315552D, -0.324996680021286D, -0.3245857357978821D, -0.32412344217300415D, -0.32368534803390503D, -0.32324400544166565D, -0.32283321022987366D, -0.3223881423473358D, -0.32192009687423706D, -0.32143840193748474D, -0.32099202275276184D, -0.3204992711544037D, -0.3200390934944153D, -0.31957361102104187D, -0.31912466883659363D, -0.3186745047569275D, -0.31821349263191223D, -0.3178000748157501D, -0.3173747658729553D, -0.3168794810771942D, -0.3164204955101013D, -0.31596946716308594D, -0.31547701358795166D, -0.3150102198123932D, -0.3145200312137604D, -0.31411561369895935D, -0.3136584758758545D, -0.31319522857666016D, -0.3127117455005646D, -0.31223630905151367D, -0.31175631284713745D, -0.31128260493278503D, -0.31085309386253357D, -0.31039923429489136D, -0.30996254086494446D, -0.3094765543937683D, -0.3090311288833618D, -0.30857518315315247D, -0.3081330358982086D, -0.3076905608177185D, -0.30722951889038086D, -0.3068021237850189D, -0.3063276410102844D, -0.3058644235134125D, -0.3054058253765106D, -0.30498620867729187D, -0.3045206069946289D, -0.30405446887016296D, -0.3035971522331238D, -0.3031606376171112D, -0.30267849564552307D, -0.30223074555397034D, -0.3017795979976654D, -0.30132225155830383D, -0.30085089802742004D, -0.3004004657268524D, -0.2999022901058197D, -0.2994162440299988D, -0.2989705502986908D, -0.2984963655471802D, -0.29802581667900085D, -0.2975752055644989D, -0.29712194204330444D, -0.2966841459274292D, -0.2962263226509094D, -0.29578348994255066D, -0.2953060269355774D, -0.2948493957519531D, -0.2943715751171112D, -0.2939140200614929D, -0.2934216856956482D, -0.29297780990600586D, -0.2924797832965851D, -0.2920304834842682D, -0.29154303669929504D, -0.2910688817501068D, -0.29058271646499634D, -0.2901535928249359D, -0.2897447347640991D, -0.28926438093185425D, -0.28879716992378235D, -0.28835800290107727D, -0.2878970801830292D, -0.28745236992836D, -0.28701406717300415D, -0.28658148646354675D, -0.2860986292362213D, -0.2856302857398987D, -0.28513821959495544D, -0.2846760153770447D, -0.28417059779167175D, -0.28370192646980286D, -0.28323373198509216D, -0.28278112411499023D, -0.2823112905025482D, -0.2818357050418854D, -0.28138846158981323D, -0.2808930575847626D, -0.28043779730796814D, -0.27998489141464233D, -0.27951040863990784D, -0.2790610194206238D, -0.27859342098236084D, -0.27810347080230713D, -0.2776254117488861D, -0.27716052532196045D, -0.2767277657985687D, -0.2762927711009979D, -0.2758132815361023D, -0.27532944083213806D, -0.27486521005630493D, -0.27437639236450195D, -0.27392253279685974D, -0.2734636664390564D, -0.2730155289173126D, -0.27252086997032166D, -0.27201488614082336D, -0.2715776860713959D, -0.27112340927124023D, -0.2706716060638428D, -0.27024176716804504D, -0.2697767913341522D, -0.2693377435207367D, -0.2688935697078705D, -0.2684306800365448D, -0.2679275572299957D, -0.26745349168777466D, -0.2669237554073334D, -0.2665085792541504D, -0.26604485511779785D, -0.26556864380836487D, -0.2651185989379883D, -0.2646579146385193D, -0.2641691565513611D, -0.26368823647499084D, -0.2632249593734741D, -0.2627500593662262D, -0.2623361349105835D, -0.2618766725063324D, -0.2614266276359558D, -0.26093974709510803D, -0.2604479491710663D, -0.2599739730358124D, -0.2594825029373169D, -0.2590617537498474D, -0.25859859585762024D, -0.25814205408096313D, -0.25771430134773254D, -0.25722840428352356D, -0.25672265887260437D, -0.25625374913215637D, -0.2558176815509796D, -0.25536519289016724D, -0.25488874316215515D, -0.2544580101966858D, -0.2539685368537903D, -0.25348523259162903D, -0.253075510263443D, -0.25262975692749023D, -0.2521655261516571D, -0.2516859173774719D, -0.2512474060058594D, -0.25079748034477234D, -0.25033846497535706D, -0.24987804889678955D, -0.2494303584098816D, -0.24893410503864288D, -0.24847693741321564D, -0.24801473319530487D, -0.2475225180387497D, -0.24707607924938202D, -0.24662980437278748D, -0.24618923664093018D, -0.24574166536331177D, -0.24528750777244568D, -0.24482272565364838D, -0.24436645209789276D, -0.24388155341148376D, -0.24341869354248047D, -0.24293887615203857D, -0.24248577654361725D, -0.24203507602214813D, -0.24156378209590912D, -0.2410905808210373D, -0.2406443953514099D, -0.24019907414913177D, -0.23976480960845947D, -0.23933319747447968D, -0.2388959676027298D, -0.23842927813529968D, -0.23793959617614746D, -0.23746173083782196D, -0.23699915409088135D, -0.23651842772960663D, -0.23605220019817352D, -0.235618457198143D, -0.23517906665802002D, -0.23475384712219238D, -0.23428522050380707D, -0.23381267488002777D, -0.23333056271076202D, -0.23285725712776184D, -0.232443168759346D, -0.23195216059684753D, -0.23147986829280853D, -0.2310148924589157D, -0.23055219650268555D, -0.23004120588302612D, -0.22958838939666748D, -0.2291288524866104D, -0.22862781584262848D, -0.22818373143672943D, -0.2277383655309677D, -0.22724731266498566D, -0.2267656922340393D, -0.2263106256723404D, -0.22584769129753113D, -0.22541046142578125D, -0.2249441146850586D, -0.22448818385601044D, -0.22402751445770264D, -0.22359701991081238D, -0.22311480343341827D, -0.2226535975933075D, -0.22214914858341217D, -0.2217063307762146D, -0.22119589149951935D, -0.2207522839307785D, -0.22028227150440216D, -0.2198103964328766D, -0.21932831406593323D, -0.2188776433467865D, -0.21837788820266724D, -0.21794435381889343D, -0.2174680083990097D, -0.2170126587152481D, -0.21653933823108673D, -0.2160915583372116D, -0.21563227474689484D, -0.21518409252166748D, -0.21474571526050568D, -0.2142743170261383D, -0.21381691098213196D, -0.21334433555603027D, -0.21288271248340607D, -0.2123873084783554D, -0.21193847060203552D, -0.2114948183298111D, -0.21100975573062897D, -0.21056903898715973D, -0.21009771525859833D, -0.20959174633026123D, -0.2091664969921112D, -0.20870351791381836D, -0.2082373946905136D, -0.2077392190694809D, -0.20726850628852844D, -0.2067907601594925D, -0.2063116431236267D, -0.20583796501159668D, -0.20534458756446838D, -0.20489037036895752D, -0.20444543659687042D, -0.2040008306503296D, -0.20351454615592957D, -0.20304752886295319D, -0.20254746079444885D, -0.2020740658044815D, -0.2015744149684906D, -0.20112964510917664D, -0.20067822933197021D, -0.200225830078125D, -0.19977039098739624D, -0.19926966726779938D, -0.19877131283283234D, -0.19831915199756622D, -0.1978578269481659D, -0.1973981410264969D, -0.19692765176296234D, -0.19644327461719513D, -0.19598513841629028D, -0.1955469399690628D, -0.19506791234016418D, -0.19460316002368927D, -0.1940772980451584D, -0.19364812970161438D, -0.1931820958852768D, -0.19273783266544342D, -0.1922660917043686D, -0.19177058339118958D, -0.1913253366947174D, -0.19083912670612335D, -0.1903299242258072D, -0.1898471564054489D, -0.18940511345863342D, -0.18894870579242706D, -0.18847599625587463D, -0.18803250789642334D, -0.18753890693187714D, -0.1870977133512497D, -0.1866195946931839D, -0.18615631759166718D, -0.1857069730758667D, -0.1852405071258545D, -0.18479567766189575D, -0.1843431293964386D, -0.1838725507259369D, -0.18344098329544067D, -0.1830095797777176D, -0.18253810703754425D, -0.18209238350391388D, -0.1816622018814087D, -0.18118171393871307D, -0.18071290850639343D, -0.180253803730011D, -0.179769366979599D, -0.1793292909860611D, -0.17883707582950592D, -0.178366020321846D, -0.1778915673494339D, -0.17741069197654724D, -0.17693915963172913D, -0.17645516991615295D, -0.17598532140254974D, -0.17547713220119476D, -0.1749715358018875D, -0.17450954020023346D, -0.1740640103816986D, -0.17359958589076996D, -0.1731225997209549D, -0.17268459498882294D, -0.1722080111503601D, -0.1717744767665863D, -0.17135664820671082D, -0.170857772231102D, -0.17039941251277924D, -0.16989468038082123D, -0.16943596303462982D, -0.16898159682750702D, -0.16854242980480194D, -0.16809329390525818D, -0.16760970652103424D, -0.16718792915344238D, -0.1666894555091858D, -0.1662272959947586D, -0.16578102111816406D, -0.16531381011009216D, -0.1648193895816803D, -0.16437332332134247D, -0.16389940679073334D, -0.1634543091058731D, -0.162981316447258D, -0.1625393033027649D, -0.16209138929843903D, -0.1616077572107315D, -0.16111062467098236D, -0.1606225222349167D, -0.16015741229057312D, -0.15968406200408936D, -0.15919706225395203D, -0.15878324210643768D, -0.1583307534456253D, -0.15784773230552673D, -0.1573367863893509D, -0.1568923145532608D, -0.15643681585788727D, -0.1559513509273529D, -0.1554512083530426D, -0.15502944588661194D, -0.15453824400901794D, -0.1541012078523636D, -0.15362413227558136D, -0.1531377136707306D, -0.152687206864357D, -0.15223318338394165D, -0.1517704725265503D, -0.1513061374425888D, -0.15085582435131073D, -0.15041625499725342D, -0.149865061044693D, -0.14939723908901215D, -0.1489189863204956D, -0.1484673172235489D, -0.14795278012752533D, -0.1475195735692978D, -0.1471049189567566D, -0.1466224193572998D, -0.14613521099090576D, -0.14566345512866974D, -0.14521154761314392D, -0.14471805095672607D, -0.14419704675674438D, -0.14375221729278564D, -0.14330840110778809D, -0.1428687870502472D, -0.14242301881313324D, -0.14195817708969116D, -0.14148111641407013D, -0.14101140201091766D, -0.14054565131664276D, -0.14008617401123047D, -0.13962242007255554D, -0.13913913071155548D, -0.1386719048023224D, -0.13822419941425323D, -0.13781346380710602D, -0.13734480738639832D, -0.1368473321199417D, -0.1363864243030548D, -0.1359218806028366D, -0.13546185195446014D, -0.13499535620212555D, -0.13451282680034637D, -0.13403449952602386D, -0.1335677057504654D, -0.13311335444450378D, -0.13265040516853333D, -0.13223102688789368D, -0.1318179965019226D, -0.13135839998722076D, -0.13091857731342316D, -0.1304430514574051D, -0.1299501210451126D, -0.12952110171318054D, -0.12904620170593262D, -0.12858985364437103D, -0.12813624739646912D, -0.12764878571033478D, -0.12717436254024506D, -0.12671279907226562D, -0.12626932561397552D, -0.1258126050233841D, -0.12532095611095428D, -0.12483920902013779D, -0.12435654550790787D, -0.12389810383319855D, -0.12345582246780396D, -0.12299700826406479D, -0.12249735742807388D, -0.1220179870724678D, -0.12155383825302124D, -0.12107869982719421D, -0.1206524446606636D, -0.12021951377391815D, -0.11980114877223969D, -0.11933659762144089D, -0.11889223009347916D, -0.11844123899936676D, -0.1179727166891098D, -0.11748640239238739D, -0.1170230507850647D, -0.11659178137779236D, -0.11614589393138885D, -0.11567246168851852D, -0.11520460993051529D, -0.1147543415427208D, -0.11429299414157867D, -0.11382859200239182D, -0.11335264891386032D, -0.11292024701833725D, -0.1124499961733818D, -0.11199361830949783D, -0.11152473092079163D, -0.11108040064573288D, -0.11064787954092026D, -0.11018948256969452D, -0.10975238680839539D, -0.10929903388023376D, -0.10885120928287506D, -0.10839029401540756D, -0.10796593129634857D, -0.1075151339173317D, -0.1070588231086731D, -0.10662193596363068D, -0.10614380240440369D, -0.10572738200426102D, -0.10525882989168167D, -0.10484708100557327D, -0.10437420755624771D, -0.10390757024288177D, -0.10347313433885574D, -0.1030469536781311D, -0.10260704159736633D, -0.10216134041547775D, -0.10169082880020142D, -0.10123983770608902D, -0.10074019432067871D, -0.10024909675121307D, -0.09978712350130081D, -0.09936016798019409D, -0.09888911992311478D, -0.09846487641334534D, -0.09800232201814651D, -0.09751661866903305D, -0.0970243439078331D, -0.09657711535692215D, -0.09613432735204697D, -0.0956689789891243D, -0.09518304467201233D, -0.09470118582248688D, -0.09423696994781494D, -0.09374787658452988D, -0.09331570565700531D, -0.09284882992506027D, -0.09236712008714676D, -0.0918976366519928D, -0.09143716841936111D, -0.09097806364297867D, -0.09050887823104858D, -0.09006129950284958D, -0.08960632979869843D, -0.08917775005102158D, -0.08866771310567856D, -0.08821896463632584D, -0.0877581313252449D, -0.08728067576885223D, -0.08678260445594788D, -0.08633118122816086D, -0.08584354817867279D, -0.0853717178106308D, -0.08489247411489487D, -0.08442585915327072D, -0.08395987749099731D, -0.08352631330490112D, -0.08305583149194717D, -0.08258084207773209D, -0.08210133016109467D, -0.08160284906625748D, -0.08113317936658859D, -0.08069101721048355D, -0.08020471036434174D, -0.07976270467042923D, -0.07930315285921097D, -0.07882215827703476D, -0.07839109003543854D, -0.07788340002298355D, -0.07738876342773438D, -0.07692108303308487D, -0.07646818459033966D, -0.07600755244493484D, -0.07554172724485397D, -0.0750839039683342D, -0.07462136447429657D, -0.07418619096279144D, -0.07369257509708405D, -0.07323087751865387D, -0.07274939864873886D, -0.07232934981584549D, -0.0718294009566307D, -0.0713631734251976D, -0.07090400904417038D, -0.07045546174049377D, -0.06996987015008926D, -0.0694737657904625D, -0.06901108473539352D, -0.06850951164960861D, -0.06804317235946655D, -0.0676044300198555D, -0.06714358180761337D, -0.06665648519992828D, -0.06620483845472336D, -0.06572776287794113D, -0.06529750674962997D, -0.06478378176689148D, -0.06431610882282257D, -0.06385191529989243D, -0.06336922943592072D, -0.0629018023610115D, -0.062440142035484314D, -0.061978090554475784D, -0.06151474267244339D, -0.061009474098682404D, -0.0605136975646019D, -0.06004589796066284D, -0.05957134813070297D, -0.059127721935510635D, -0.05862615630030632D, -0.058159153908491135D, -0.0576748289167881D, -0.05721447244286537D, -0.056762006133794785D, -0.05628581345081329D, -0.055841170251369476D, -0.0554051548242569D, -0.05493675544857979D, -0.05444927141070366D, -0.05396290495991707D, -0.05345846712589264D, -0.05297686532139778D, -0.052506621927022934D, -0.052009958773851395D, -0.051531676203012466D, -0.051076509058475494D, -0.0506112314760685D, -0.05013972148299217D, -0.04966387152671814D, -0.04918888956308365D, -0.04871213063597679D, -0.04824038967490196D, -0.04775635525584221D, -0.04728744924068451D, -0.046815820038318634D, -0.04631710797548294D, -0.04582008346915245D, -0.04536677524447441D, -0.04491899907588959D, -0.044470835477113724D, -0.04400596767663956D, -0.043535444885492325D, -0.04307795315980911D, -0.04260599613189697D, -0.042175114154815674D, -0.04172958806157112D, -0.04125590994954109D, -0.04082314670085907D, -0.04037400707602501D, -0.03990166634321213D, -0.039449382573366165D, -0.038977205753326416D, -0.03857160359621048D, -0.03812842443585396D, -0.0376502126455307D, -0.03714657574892044D, -0.03665357083082199D, -0.03620750829577446D, -0.035722747445106506D, -0.03526165336370468D, -0.03478018939495087D, -0.03431404381990433D, -0.033867765218019485D, -0.03341749310493469D, -0.03296608477830887D, -0.0324828140437603D, -0.03204398974776268D, -0.031582657247781754D, -0.031121470034122467D, -0.030629586428403854D, -0.03019966371357441D, -0.02972709760069847D, -0.029238028451800346D, -0.02879139594733715D, -0.02834215760231018D, -0.02785702981054783D, -0.027348829433321953D, -0.026903830468654633D, -0.026418806985020638D, -0.025951212272047997D, -0.02550702914595604D, -0.025065308436751366D, -0.02460712380707264D, -0.0241254810243845D, -0.02367357909679413D, -0.023214267566800117D, -0.02273659221827984D, -0.022288724780082703D, -0.021809976547956467D, -0.021356219425797462D, -0.02091222070157528D, -0.02044014073908329D, -0.019984910264611244D, -0.019542459398508072D, -0.019069962203502655D, -0.018573816865682602D, -0.018139785155653954D, -0.017709843814373016D, -0.01719387248158455D, -0.01673675887286663D, -0.01623465307056904D, -0.01578424498438835D, -0.015328689478337765D, -0.014845888130366802D, -0.014361053705215454D, -0.01387764047831297D, -0.013408266007900238D, -0.012936233542859554D, -0.012468288652598858D, -0.012004869058728218D, -0.01153097115457058D, -0.011026769876480103D, -0.01058868132531643D, -0.010118640959262848D, -0.009648044593632221D, -0.009180471301078796D, -0.00874828826636076D, -0.008231979794800282D, -0.007815088145434856D, -0.007339174393564463D, -0.006868409458547831D, -0.006415967363864183D, -0.00596375809982419D, -0.00553414411842823D, -0.005092580337077379D, -0.004615438170731068D, -0.004147601779550314D, -0.0036700163036584854D, -0.003234181785956025D, -0.002747706137597561D, -0.002275948878377676D, -0.0018008529441431165D, -0.0013390094973146915D, -9.023041930049658E-4D, -4.4535082997754216E-4D, 0.0D, 4.168656305409968E-4D, 8.610964869149029E-4D, 0.0013082061195746064D, 0.0017705500358715653D, 0.0022286938037723303D, 0.0027038094121962786D, 0.0031797823030501604D, 0.0036177479196339846D, 0.004092853982001543D, 0.00455115782096982D, 0.005024673882871866D, 0.0054508778266608715D, 0.005874452646821737D, 0.006345030386000872D, 0.006781958043575287D, 0.007221095263957977D, 0.007751896511763334D, 0.008183642290532589D, 0.008649589493870735D, 0.009099786169826984D, 0.009520403109490871D, 0.01000619400292635D, 0.01046296488493681D, 0.010907409712672234D, 0.011398875154554844D, 0.011837021447718143D, 0.012319699861109257D, 0.012789001688361168D, 0.013266430236399174D, 0.013758053071796894D, 0.014256741851568222D, 0.0147450752556324D, 0.015211586840450764D, 0.01564781181514263D, 0.016076650470495224D, 0.016586629673838615D, 0.017026731744408607D, 0.017525365576148033D, 0.01798558607697487D, 0.018427804112434387D, 0.018891869112849236D, 0.01935114525258541D, 0.019804034382104874D, 0.020264199003577232D, 0.020725706592202187D, 0.021203743293881416D, 0.021654309704899788D, 0.022142447531223297D, 0.02260545641183853D, 0.02308838628232479D, 0.023543886840343475D, 0.02397369220852852D, 0.024441862478852272D, 0.024915242567658424D, 0.025360191240906715D, 0.025840288028120995D, 0.02631484717130661D, 0.026808904483914375D, 0.02727837674319744D, 0.027765285223722458D, 0.028254829347133636D, 0.028705906122922897D, 0.029156357049942017D, 0.029635854065418243D, 0.030102955177426338D, 0.030535848811268806D, 0.03101063147187233D, 0.0314723402261734D, 0.03192717581987381D, 0.032385364174842834D, 0.03285473957657814D, 0.03331996127963066D, 0.033790718764066696D, 0.03424150124192238D, 0.03469865396618843D, 0.03515125438570976D, 0.035605255514383316D, 0.03608577698469162D, 0.03652714565396309D, 0.036979805678129196D, 0.03746131435036659D, 0.0379425548017025D, 0.038345664739608765D, 0.03882379084825516D, 0.0392477810382843D, 0.03971483185887337D, 0.0401901938021183D, 0.04066096618771553D, 0.041114721447229385D, 0.04158128425478935D, 0.0420382022857666D, 0.04248936101794243D, 0.042961087077856064D, 0.04341959208250046D, 0.043904419988393784D, 0.0443427637219429D, 0.04480225220322609D, 0.04524291679263115D, 0.04567072167992592D, 0.04613497108221054D, 0.04659995064139366D, 0.047081708908081055D, 0.04757154732942581D, 0.04803965613245964D, 0.048478204756975174D, 0.048989493399858475D, 0.049454182386398315D, 0.04991860315203667D, 0.050365593284368515D, 0.0508514903485775D, 0.05132327973842621D, 0.05179283022880554D, 0.052248794585466385D, 0.05268503352999687D, 0.053198836743831635D, 0.05368649214506149D, 0.05421089380979538D, 0.054658785462379456D, 0.05512617900967598D, 0.05555638298392296D, 0.0560036227107048D, 0.05645635724067688D, 0.05692245066165924D, 0.05738668516278267D, 0.05786433443427086D, 0.058321356773376465D, 0.05880298092961311D, 0.05926252529025078D, 0.05970615893602371D, 0.06018388643860817D, 0.06063615530729294D, 0.061135876923799515D, 0.06162475049495697D, 0.06207337975502014D, 0.06256981939077377D, 0.0630052387714386D, 0.0634310320019722D, 0.0638926699757576D, 0.06436608731746674D, 0.0648551806807518D, 0.06531759351491928D, 0.065772145986557D, 0.06625805050134659D, 0.06672851741313934D, 0.06720802187919617D, 0.06766702234745026D, 0.06809297949075699D, 0.06856777518987656D, 0.06906134635210037D, 0.0695035383105278D, 0.06995517015457153D, 0.07043462246656418D, 0.07087671756744385D, 0.07131607830524445D, 0.07179289311170578D, 0.07225023955106735D, 0.07268200069665909D, 0.07317853718996048D, 0.07361547648906708D, 0.07412286102771759D, 0.07458420842885971D, 0.07503563165664673D, 0.07551742345094681D, 0.07598724961280823D, 0.07641705870628357D, 0.07686413079500198D, 0.07736052572727203D, 0.07785376906394958D, 0.07831523567438126D, 0.07877857238054276D, 0.07922326028347015D, 0.07968610525131226D, 0.08015176653862D, 0.08060047775506973D, 0.08107147365808487D, 0.08151480555534363D, 0.08202660828828812D, 0.08250529319047928D, 0.08296989649534225D, 0.08345716446638107D, 0.08391540497541428D, 0.08433298021554947D, 0.08479931950569153D, 0.08524123579263687D, 0.08570325374603271D, 0.0861559808254242D, 0.08659818768501282D, 0.08707676082849503D, 0.08756472170352936D, 0.08801695704460144D, 0.08853187412023544D, 0.08898908644914627D, 0.08946547657251358D, 0.08992484211921692D, 0.0903463140130043D, 0.09079413115978241D, 0.09125514328479767D, 0.09171689301729202D, 0.09216631948947906D, 0.09262130409479141D, 0.09305017441511154D, 0.09349587559700012D, 0.09393535554409027D, 0.09437032788991928D, 0.09485276788473129D, 0.09533093869686127D, 0.09582594037055969D, 0.09629540890455246D, 0.09672483801841736D, 0.09716562926769257D, 0.09765120595693588D, 0.09813567996025085D, 0.0985914096236229D, 0.0990055575966835D, 0.09946183115243912D, 0.09987382590770721D, 0.10033174604177475D, 0.10079345107078552D, 0.10127578675746918D, 0.10172127932310104D, 0.10217364132404327D, 0.10263688117265701D, 0.10307306051254272D, 0.10350827872753143D, 0.10397220402956009D, 0.10442768037319183D, 0.10491803288459778D, 0.1053432822227478D, 0.10581864416599274D, 0.10627686977386475D, 0.1067519336938858D, 0.10721217095851898D, 0.10764270275831223D, 0.10811315476894379D, 0.10855291038751602D, 0.1089974045753479D, 0.10945462435483932D, 0.10991151630878448D, 0.11035595089197159D, 0.11079936474561691D, 0.11126214265823364D, 0.11171538382768631D, 0.11215132474899292D, 0.11261577159166336D, 0.11305342614650726D, 0.11349684000015259D, 0.11396090686321259D, 0.11440304666757584D, 0.1148676946759224D, 0.11534382402896881D, 0.11578971147537231D, 0.11626245826482773D, 0.11670893430709839D, 0.11717358231544495D, 0.11763584613800049D, 0.11809416860342026D, 0.1185641959309578D, 0.1190362498164177D, 0.11947569251060486D, 0.11995163559913635D, 0.12034139782190323D, 0.12079598009586334D, 0.12123335897922516D, 0.12171798199415207D, 0.12220712006092072D, 0.12266131490468979D, 0.12311149388551712D, 0.12358853965997696D, 0.12402278184890747D, 0.12447427213191986D, 0.12492292374372482D, 0.12536488473415375D, 0.1258557140827179D, 0.12631472945213318D, 0.12678931653499603D, 0.1272418200969696D, 0.1276789903640747D, 0.12812837958335876D, 0.12855777144432068D, 0.12901000678539276D, 0.1295066773891449D, 0.12997055053710938D, 0.13041932880878448D, 0.13086055219173431D, 0.13131678104400635D, 0.13173618912696838D, 0.13217733800411224D, 0.13257558643817902D, 0.13303515315055847D, 0.13347606360912323D, 0.1339293271303177D, 0.13438007235527039D, 0.1348496675491333D, 0.1352933943271637D, 0.13577623665332794D, 0.13623352348804474D, 0.13667674362659454D, 0.1371779888868332D, 0.13767582178115845D, 0.13814261555671692D, 0.13862669467926025D, 0.13910050690174103D, 0.13954664766788483D, 0.14002522826194763D, 0.1404792070388794D, 0.14095349609851837D, 0.14145132899284363D, 0.14194148778915405D, 0.14239490032196045D, 0.14285248517990112D, 0.14331306517124176D, 0.14375628530979156D, 0.14420928061008453D, 0.14471451938152313D, 0.1451774686574936D, 0.14563149213790894D, 0.14607255160808563D, 0.14652425050735474D, 0.1469966620206833D, 0.14742255210876465D, 0.14784209430217743D, 0.14830715954303741D, 0.14879651367664337D, 0.149237722158432D, 0.14971013367176056D, 0.15021756291389465D, 0.15068085491657257D, 0.15116679668426514D, 0.15161839127540588D, 0.152106374502182D, 0.1525515913963318D, 0.15302610397338867D, 0.15346159040927887D, 0.15394625067710876D, 0.15438704192638397D, 0.15487033128738403D, 0.1553371548652649D, 0.15580454468727112D, 0.156284898519516D, 0.15671078860759735D, 0.15717515349388123D, 0.15761828422546387D, 0.15807723999023438D, 0.15852780640125275D, 0.15896621346473694D, 0.1594497412443161D, 0.15990334749221802D, 0.1603526622056961D, 0.16084396839141846D, 0.16133654117584229D, 0.16182120144367218D, 0.16228310763835907D, 0.16274477541446686D, 0.1631993055343628D, 0.16370509564876556D, 0.16416113078594208D, 0.16461949050426483D, 0.16509303450584412D, 0.16555249691009521D, 0.16599228978157043D, 0.16644693911075592D, 0.16691160202026367D, 0.1673542857170105D, 0.16779595613479614D, 0.16828018426895142D, 0.16872042417526245D, 0.16914832592010498D, 0.1696404069662094D, 0.17009416222572327D, 0.17058154940605164D, 0.17106236517429352D, 0.17150871455669403D, 0.17193780839443207D, 0.1723848581314087D, 0.17284345626831055D, 0.17332123219966888D, 0.17382800579071045D, 0.17429354786872864D, 0.17473028600215912D, 0.1752118319272995D, 0.17569267749786377D, 0.17617307603359222D, 0.17664162814617157D, 0.17711058259010315D, 0.177546888589859D, 0.17802934348583221D, 0.17847880721092224D, 0.17895878851413727D, 0.17944811284542084D, 0.17991696298122406D, 0.18034568428993225D, 0.18083885312080383D, 0.18134140968322754D, 0.1817953884601593D, 0.18224695324897766D, 0.1827344000339508D, 0.18319717049598694D, 0.18362371623516083D, 0.18408402800559998D, 0.1845383197069168D, 0.18500585854053497D, 0.18543913960456848D, 0.18589206039905548D, 0.18638618290424347D, 0.18683254718780518D, 0.18729357421398163D, 0.1877458542585373D, 0.1881948709487915D, 0.18867141008377075D, 0.1891425997018814D, 0.1896383911371231D, 0.19008977711200714D, 0.19059477746486664D, 0.1910955309867859D, 0.19154046475887299D, 0.1920085996389389D, 0.1924976259469986D, 0.19297999143600464D, 0.19346415996551514D, 0.1938929706811905D, 0.19440758228302002D, 0.1948833465576172D, 0.1953524500131607D, 0.19580426812171936D, 0.19628435373306274D, 0.19678011536598206D, 0.1972467005252838D, 0.19772139191627502D, 0.19817455112934113D, 0.19861629605293274D, 0.19908666610717773D, 0.19956916570663452D, 0.20003587007522583D, 0.2004714459180832D, 0.20093294978141785D, 0.2013975977897644D, 0.20189401507377625D, 0.20238760113716125D, 0.20286208391189575D, 0.203344464302063D, 0.2038167268037796D, 0.20429755747318268D, 0.20473958551883698D, 0.20518158376216888D, 0.2056620866060257D, 0.20609739422798157D, 0.2065676748752594D, 0.20705540478229523D, 0.2075486183166504D, 0.2080535888671875D, 0.20851968228816986D, 0.20897184312343597D, 0.20944087207317352D, 0.20993351936340332D, 0.2104172706604004D, 0.210901141166687D, 0.2113402634859085D, 0.21182526648044586D, 0.21224695444107056D, 0.2126944214105606D, 0.21317575871944427D, 0.21366049349308014D, 0.2141040563583374D, 0.21457503736019135D, 0.2150408923625946D, 0.2154938280582428D, 0.2159576565027237D, 0.21639752388000488D, 0.2168862372636795D, 0.2173519879579544D, 0.2177966684103012D, 0.21821701526641846D, 0.21873435378074646D, 0.21923255920410156D, 0.21964925527572632D, 0.22016601264476776D, 0.22062964737415314D, 0.22109317779541016D, 0.22157219052314758D, 0.22205998003482819D, 0.22250258922576904D, 0.22299329936504364D, 0.22346089780330658D, 0.22386358678340912D, 0.22431528568267822D, 0.22480542957782745D, 0.2252291440963745D, 0.2257033735513687D, 0.2261507213115692D, 0.22663995623588562D, 0.227098748087883D, 0.22758157551288605D, 0.2280273586511612D, 0.2284591943025589D, 0.22891086339950562D, 0.2293635904788971D, 0.22981512546539307D, 0.2303115725517273D, 0.2307835817337036D, 0.2312321662902832D, 0.23169724643230438D, 0.23218663036823273D, 0.23266419768333435D, 0.23312914371490479D, 0.233600914478302D, 0.23405154049396515D, 0.23452113568782806D, 0.23498238623142242D, 0.2354474514722824D, 0.23587417602539062D, 0.23632276058197021D, 0.2367987036705017D, 0.23725953698158264D, 0.23771677911281586D, 0.23819883167743683D, 0.23865287005901337D, 0.23909300565719604D, 0.23953081667423248D, 0.23997336626052856D, 0.24042324721813202D, 0.24086444079875946D, 0.2413105070590973D, 0.24174147844314575D, 0.24222896993160248D, 0.24265654385089874D, 0.24309583008289337D, 0.2435549646615982D, 0.2439824342727661D, 0.24444152414798737D, 0.2448790967464447D, 0.24534952640533447D, 0.24579569697380066D, 0.24623432755470276D, 0.24664406478405D, 0.24708445370197296D, 0.24750955402851105D, 0.24798931181430817D, 0.24846124649047852D, 0.2489023059606552D, 0.24936534464359283D, 0.24984745681285858D, 0.2503180503845215D, 0.25077712535858154D, 0.25124165415763855D, 0.25171688199043274D, 0.25217753648757935D, 0.25262942910194397D, 0.2530757188796997D, 0.25351011753082275D, 0.25398433208465576D, 0.2544580101966858D, 0.2548938989639282D, 0.25534236431121826D, 0.25578323006629944D, 0.2562248408794403D, 0.2566409409046173D, 0.2571069300174713D, 0.25757265090942383D, 0.2580459415912628D, 0.25851020216941833D, 0.25894230604171753D, 0.25939860939979553D, 0.2598321735858917D, 0.26028236746788025D, 0.26076990365982056D, 0.26125451922416687D, 0.2616814374923706D, 0.2621334493160248D, 0.26258885860443115D, 0.2630382478237152D, 0.2634872794151306D, 0.2639560103416443D, 0.26442626118659973D, 0.26490315794944763D, 0.26534172892570496D, 0.2657735347747803D, 0.26625367999076843D, 0.26668620109558105D, 0.26711753010749817D, 0.26758676767349243D, 0.2680959403514862D, 0.26854223012924194D, 0.26900240778923035D, 0.2694344222545624D, 0.2698785364627838D, 0.2703325152397156D, 0.27079638838768005D, 0.27121323347091675D, 0.27164754271507263D, 0.2721148729324341D, 0.27261990308761597D, 0.2730520963668823D, 0.2735033929347992D, 0.27395889163017273D, 0.2744174897670746D, 0.2749277353286743D, 0.2753666937351227D, 0.27583181858062744D, 0.2762593924999237D, 0.27671781182289124D, 0.2771632969379425D, 0.27762773633003235D, 0.27808821201324463D, 0.2785561978816986D, 0.2790210247039795D, 0.2794676721096039D, 0.27997758984565735D, 0.2804442048072815D, 0.2809334099292755D, 0.2814132869243622D, 0.2819100320339203D, 0.2823738157749176D, 0.2828632891178131D, 0.2832971513271332D, 0.2837606370449066D, 0.2842257022857666D, 0.284706175327301D, 0.28517892956733704D, 0.2856413722038269D, 0.28612804412841797D, 0.2866162955760956D, 0.2870566248893738D, 0.28752243518829346D, 0.28795307874679565D, 0.2884029150009155D, 0.28882715106010437D, 0.2893234193325043D, 0.28977981209754944D, 0.29021215438842773D, 0.29065024852752686D, 0.29114648699760437D, 0.29163259267807007D, 0.29209470748901367D, 0.29254150390625D, 0.29303133487701416D, 0.29347801208496094D, 0.2939077317714691D, 0.29437002539634705D, 0.2948186695575714D, 0.2952706217765808D, 0.29571935534477234D, 0.29619288444519043D, 0.29662781953811646D, 0.2970706522464752D, 0.2975059449672699D, 0.2979780435562134D, 0.2984209656715393D, 0.2989175319671631D, 0.29936090111732483D, 0.29983457922935486D, 0.30030179023742676D, 0.3007870316505432D, 0.30124491453170776D, 0.3017134666442871D, 0.30218929052352905D, 0.30264225602149963D, 0.3031245768070221D, 0.30356884002685547D, 0.3040228486061096D, 0.3044879138469696D, 0.30492523312568665D, 0.30536073446273804D, 0.30580392479896545D, 0.3062219023704529D, 0.30666860938072205D, 0.3070964515209198D, 0.30755335092544556D, 0.30799052119255066D, 0.3084643483161926D, 0.3089260160923004D, 0.3093597888946533D, 0.3098238706588745D, 0.31024208664894104D, 0.31071120500564575D, 0.3111429512500763D, 0.31156468391418457D, 0.3120630085468292D, 0.31250911951065063D, 0.3129652738571167D, 0.3134596645832062D, 0.31389009952545166D, 0.3142957389354706D, 0.314715176820755D, 0.31520751118659973D, 0.3156639337539673D, 0.3161354660987854D, 0.31650006771087646D, 0.31700363755226135D, 0.3174765706062317D, 0.3179265558719635D, 0.31831637024879456D, 0.31879016757011414D, 0.3192623555660248D, 0.3196816146373749D, 0.32012230157852173D, 0.32058221101760864D, 0.32105132937431335D, 0.3214877247810364D, 0.321958065032959D, 0.3224197030067444D, 0.32287776470184326D, 0.3232984244823456D, 0.32375460863113403D, 0.32420462369918823D, 0.3246663212776184D, 0.3250793516635895D, 0.32551777362823486D, 0.32601094245910645D, 0.32646849751472473D, 0.3269194960594177D, 0.327384352684021D, 0.32789483666419983D, 0.32835909724235535D, 0.32883167266845703D, 0.3293091654777527D, 0.32977598905563354D, 0.330209881067276D, 0.3306809663772583D, 0.3311329483985901D, 0.33160221576690674D, 0.33207982778549194D, 0.3325675427913666D, 0.3330262303352356D, 0.3335005044937134D, 0.33391913771629333D, 0.33441251516342163D, 0.3348396420478821D, 0.3353181481361389D, 0.3357672095298767D, 0.33621659874916077D, 0.3367024064064026D, 0.3371727168560028D, 0.3376167416572571D, 0.3381151854991913D, 0.33856678009033203D, 0.339025616645813D, 0.33946481347084045D, 0.33994701504707336D, 0.3403969705104828D, 0.3408898115158081D, 0.34135758876800537D, 0.3418196737766266D, 0.34231361746788025D, 0.3427829146385193D, 0.3432021141052246D, 0.343667596578598D, 0.34414032101631165D, 0.34463152289390564D, 0.34506839513778687D, 0.3455321788787842D, 0.3459724187850952D, 0.3464416563510895D, 0.3468835651874542D, 0.3473498225212097D, 0.34777554869651794D, 0.34825536608695984D, 0.34872201085090637D, 0.3492021858692169D, 0.34968751668930054D, 0.35015514492988586D, 0.3506210446357727D, 0.35111862421035767D, 0.3515591323375702D, 0.35197773575782776D, 0.35246777534484863D, 0.35293281078338623D, 0.3533059060573578D, 0.35381144285202026D, 0.3542632758617401D, 0.35472649335861206D, 0.35519418120384216D, 0.3557141423225403D, 0.3561652600765228D, 0.3566296100616455D, 0.35712379217147827D, 0.35762926936149597D, 0.3580913543701172D, 0.35853779315948486D, 0.3590478003025055D, 0.3594883680343628D, 0.3599258363246918D, 0.3603578805923462D, 0.3608366549015045D, 0.36130017042160034D, 0.3617651164531708D, 0.3622173070907593D, 0.3626740574836731D, 0.36311766505241394D, 0.3635890483856201D, 0.36403384804725647D, 0.36449429392814636D, 0.3649645745754242D, 0.36542847752571106D, 0.3658938407897949D, 0.366346538066864D, 0.3668064475059509D, 0.3672544062137604D, 0.3676927983760834D, 0.3681465983390808D, 0.368583083152771D, 0.3690279722213745D, 0.36952367424964905D, 0.3699638843536377D, 0.370394766330719D, 0.3708454668521881D, 0.3712919354438782D, 0.3717401921749115D, 0.37220123410224915D, 0.37264400720596313D, 0.37307944893836975D, 0.37358567118644714D, 0.37402620911598206D, 0.3744513988494873D, 0.37491515278816223D, 0.37531962990760803D, 0.3757742941379547D, 0.3762052357196808D, 0.37664008140563965D, 0.37707191705703735D, 0.3775149881839752D, 0.3779565095901489D, 0.3784351944923401D, 0.3788757920265198D, 0.37933775782585144D, 0.37975525856018066D, 0.38018184900283813D, 0.3806290328502655D, 0.3810517489910126D, 0.3814375102519989D, 0.3818727433681488D, 0.3823419213294983D, 0.3828076124191284D, 0.3832823932170868D, 0.3837049901485443D, 0.3841449022293091D, 0.3846031129360199D, 0.3850502371788025D, 0.385475754737854D, 0.38596659898757935D, 0.3864104151725769D, 0.38683876395225525D, 0.3873252868652344D, 0.3877384662628174D, 0.388178288936615D, 0.3885806202888489D, 0.3890480697154999D, 0.3895305395126343D, 0.3900220990180969D, 0.39047881960868835D, 0.39091551303863525D, 0.39139822125434875D, 0.39183932542800903D, 0.392275869846344D, 0.392767995595932D, 0.3932383060455322D, 0.3937053978443146D, 0.3941604793071747D, 0.3946269154548645D, 0.39507585763931274D, 0.39548471570014954D, 0.3959529995918274D, 0.39645472168922424D, 0.39692774415016174D, 0.39741259813308716D, 0.39785870909690857D, 0.3983263075351715D, 0.3988035321235657D, 0.39925169944763184D, 0.3996838927268982D, 0.4001287519931793D, 0.4006178677082062D, 0.4010898768901825D, 0.4015604555606842D, 0.40202707052230835D, 0.40245679020881653D, 0.40293094515800476D, 0.4034392535686493D, 0.4039093255996704D, 0.4043821692466736D, 0.40486443042755127D, 0.4053739905357361D, 0.4058074355125427D, 0.40630874037742615D, 0.4067918658256531D, 0.4072363078594208D, 0.40767401456832886D, 0.4081343412399292D, 0.4085795283317566D, 0.4090270400047302D, 0.4094325006008148D, 0.4099096357822418D, 0.4103759229183197D, 0.4108376204967499D, 0.4113309681415558D, 0.4117901027202606D, 0.41226187348365784D, 0.41273775696754456D, 0.41322728991508484D, 0.4136919677257538D, 0.41412317752838135D, 0.4145846366882324D, 0.415062814950943D, 0.415499746799469D, 0.41598421335220337D, 0.4164329767227173D, 0.4168729782104492D, 0.4173301160335541D, 0.41776272654533386D, 0.4181908071041107D, 0.4186636209487915D, 0.4190938472747803D, 0.4195532202720642D, 0.4200260639190674D, 0.4205058813095093D, 0.4209406077861786D, 0.42138221859931946D, 0.421817421913147D, 0.4222801923751831D, 0.4227195084095001D, 0.4231964647769928D, 0.4236719608306885D, 0.42410510778427124D, 0.42456895112991333D, 0.42507311701774597D, 0.4255290925502777D, 0.4260011315345764D, 0.42646899819374084D, 0.42692455649375916D, 0.4274055063724518D, 0.42785710096359253D, 0.42829200625419617D, 0.4287801682949066D, 0.4292578399181366D, 0.4297063946723938D, 0.4301692843437195D, 0.430625319480896D, 0.4311210811138153D, 0.4315798580646515D, 0.4320110082626343D, 0.43246930837631226D, 0.4329104423522949D, 0.4333850145339966D, 0.43380045890808105D, 0.4342290759086609D, 0.43472087383270264D, 0.4351579248905182D, 0.4356578290462494D, 0.4361093044281006D, 0.43657541275024414D, 0.4369976818561554D, 0.43740877509117126D, 0.43785667419433594D, 0.4383409023284912D, 0.4387859106063843D, 0.4392130672931671D, 0.4396638870239258D, 0.4401101768016815D, 0.4405667185783386D, 0.4410354793071747D, 0.4415227770805359D, 0.44195571541786194D, 0.4424566924571991D, 0.44294804334640503D, 0.44344770908355713D, 0.4438609778881073D, 0.44431737065315247D, 0.4447491466999054D, 0.4451911747455597D, 0.44563400745391846D, 0.4461042881011963D, 0.4465523660182953D, 0.44701021909713745D, 0.44744202494621277D, 0.44790083169937134D, 0.44836023449897766D, 0.4487965404987335D, 0.44924411177635193D, 0.4496929347515106D, 0.45014363527297974D, 0.45060500502586365D, 0.4510105848312378D, 0.45146453380584717D, 0.4519331455230713D, 0.45240896940231323D, 0.45286038517951965D, 0.45329752564430237D, 0.4537377655506134D, 0.4542039632797241D, 0.45463576912879944D, 0.45509567856788635D, 0.4555233418941498D, 0.45594367384910583D, 0.4564257264137268D, 0.45684814453125D, 0.45732614398002625D, 0.45778998732566833D, 0.4582274556159973D, 0.4586721658706665D, 0.4591447114944458D, 0.45960500836372375D, 0.4600178301334381D, 0.46047934889793396D, 0.4609234929084778D, 0.46136897802352905D, 0.4618026316165924D, 0.462283194065094D, 0.4627189636230469D, 0.4631398916244507D, 0.4636479616165161D, 0.46408990025520325D, 0.46446308493614197D, 0.46488359570503235D, 0.4653341770172119D, 0.46579721570014954D, 0.46624305844306946D, 0.4666842520236969D, 0.4671739637851715D, 0.4676412045955658D, 0.4681183695793152D, 0.468619704246521D, 0.4690823554992676D, 0.4695432782173157D, 0.47002753615379333D, 0.47044625878334045D, 0.4709080457687378D, 0.4713667631149292D, 0.47178512811660767D, 0.4722518026828766D, 0.4727015495300293D, 0.4732007086277008D, 0.4736599624156952D, 0.47416114807128906D, 0.4746391177177429D, 0.4750903248786926D, 0.47553959488868713D, 0.4759838581085205D, 0.47645294666290283D, 0.47691580653190613D, 0.4773806631565094D, 0.47785019874572754D, 0.47835424542427063D, 0.4787907898426056D, 0.4792308509349823D, 0.47971123456954956D, 0.48016679286956787D, 0.4806031286716461D, 0.4810718894004822D, 0.4815417528152466D, 0.4820031523704529D, 0.48243653774261475D, 0.4828621745109558D, 0.4833242893218994D, 0.4837735593318939D, 0.48425227403640747D, 0.4847247004508972D, 0.48517146706581116D, 0.48558691143989563D, 0.48607468605041504D, 0.4865155518054962D, 0.48698723316192627D, 0.4874122142791748D, 0.4878520965576172D, 0.4882693886756897D, 0.4887109100818634D, 0.48919129371643066D, 0.48964065313339233D, 0.49008241295814514D, 0.49052369594573975D, 0.4909614324569702D, 0.4914078414440155D, 0.491849422454834D, 0.4922744333744049D, 0.49270620942115784D, 0.4931676983833313D, 0.49362602829933167D, 0.49406757950782776D, 0.49453216791152954D, 0.49497801065444946D, 0.4954409599304199D, 0.4958536922931671D, 0.4962973892688751D, 0.49675166606903076D, 0.49723342061042786D, 0.4976520836353302D, 0.4981245696544647D, 0.49855509400367737D, 0.49899476766586304D, 0.4994736909866333D, 0.49990856647491455D, 0.5003674030303955D, 0.50080406665802D, 0.5012417435646057D, 0.5017043948173523D, 0.5021814703941345D, 0.5026438236236572D, 0.5030980110168457D, 0.5035042762756348D, 0.503902018070221D, 0.5043559074401855D, 0.5048004388809204D, 0.5052796006202698D, 0.5057178735733032D, 0.5061670541763306D, 0.5066263675689697D, 0.5070849061012268D, 0.5075520873069763D, 0.5079953670501709D, 0.5084426999092102D, 0.5088971853256226D, 0.509351909160614D, 0.5097948312759399D, 0.5102611184120178D, 0.5107103586196899D, 0.5111591815948486D, 0.5115908980369568D, 0.5120378136634827D, 0.5124511122703552D, 0.5129324793815613D, 0.5134246945381165D, 0.5138871073722839D, 0.5143778324127197D, 0.5148214101791382D, 0.5152270793914795D, 0.5156940817832947D, 0.5161502361297607D, 0.5166060328483582D, 0.5170818567276001D, 0.517525315284729D, 0.5179942846298218D, 0.5183911919593811D, 0.5188703536987305D, 0.5193058252334595D, 0.5197564959526062D, 0.5202117562294006D, 0.5207022428512573D, 0.5211948156356812D, 0.5216438174247742D, 0.5221007466316223D, 0.5225681662559509D, 0.5230153203010559D, 0.5234923958778381D, 0.5239441990852356D, 0.5243942141532898D, 0.5248235464096069D, 0.5252488851547241D, 0.5256743431091309D, 0.526077926158905D, 0.5265212059020996D, 0.5269445180892944D, 0.5274064540863037D, 0.52787184715271D, 0.5283424854278564D, 0.5288335680961609D, 0.5292720198631287D, 0.5297167301177979D, 0.5302064418792725D, 0.5306571125984192D, 0.531088650226593D, 0.5315560102462769D, 0.5319926738739014D, 0.5324088931083679D, 0.532862663269043D, 0.5333322286605835D, 0.5337752103805542D, 0.5341958999633789D, 0.5346767902374268D, 0.5351715087890625D, 0.5356220602989197D, 0.5361113548278809D, 0.536573052406311D, 0.5370585322380066D, 0.5375128984451294D, 0.5379542112350464D, 0.538433849811554D, 0.5388942956924438D, 0.5393670201301575D, 0.5398485660552979D, 0.5402945876121521D, 0.5407204031944275D, 0.541131317615509D, 0.5416036248207092D, 0.5420829057693481D, 0.5425488948822021D, 0.5430117249488831D, 0.5434421896934509D, 0.54389888048172D, 0.5443391799926758D, 0.5447611212730408D, 0.545224130153656D, 0.545673131942749D, 0.5460936427116394D, 0.5465660691261292D, 0.5470452308654785D, 0.5475273728370667D, 0.5479429960250854D, 0.5484063625335693D, 0.5488631129264832D, 0.5493146181106567D, 0.549760639667511D, 0.5502592921257019D, 0.5507493019104004D, 0.5511957406997681D, 0.5516489744186401D, 0.5521084666252136D, 0.5525751709938049D, 0.5530290603637695D, 0.553477942943573D, 0.5539233684539795D, 0.5544093251228333D, 0.5548952221870422D, 0.5553575158119202D, 0.5558218359947205D, 0.5563178062438965D, 0.5567854642868042D, 0.5572537779808044D, 0.5577130317687988D, 0.5581837296485901D, 0.5586464405059814D, 0.5590561628341675D, 0.559502899646759D, 0.5599905848503113D, 0.5604462623596191D, 0.5608773231506348D, 0.5613529086112976D, 0.5618170499801636D, 0.5622658133506775D, 0.5627509355545044D, 0.5631857514381409D, 0.5636336207389832D, 0.5640740394592285D, 0.5644878149032593D, 0.5649570822715759D, 0.5654452443122864D, 0.5659193992614746D, 0.566391110420227D, 0.5668405294418335D, 0.5673339366912842D, 0.5678455829620361D, 0.5682653188705444D, 0.5687336325645447D, 0.5691594481468201D, 0.5696210861206055D, 0.5700470805168152D, 0.5705402493476868D, 0.5709607005119324D, 0.5714168548583984D, 0.5718520283699036D, 0.57235187292099D, 0.5728260278701782D, 0.5732724070549011D, 0.5737460255622864D, 0.574226438999176D, 0.5747095346450806D, 0.5751391649246216D, 0.5756227374076843D, 0.576072096824646D, 0.5765191316604614D, 0.5769604444503784D, 0.5774073600769043D, 0.5778785347938538D, 0.5783064365386963D, 0.5787573456764221D, 0.5792401432991028D, 0.5796770453453064D, 0.5801228880882263D, 0.580571711063385D, 0.5810607075691223D, 0.5815511345863342D, 0.5820316672325134D, 0.5824490785598755D, 0.5829075574874878D, 0.5833353400230408D, 0.583755612373352D, 0.5841545462608337D, 0.5846143960952759D, 0.5850520730018616D, 0.5855194926261902D, 0.5859699249267578D, 0.5864249467849731D, 0.5868760943412781D, 0.5873154401779175D, 0.5878191590309143D, 0.5882934927940369D, 0.5887097716331482D, 0.5891896486282349D, 0.5895995497703552D, 0.590004563331604D, 0.5904493927955627D, 0.5908958911895752D, 0.5913615226745605D, 0.5917897820472717D, 0.5922753810882568D, 0.5927274823188782D, 0.5931650400161743D, 0.5936287045478821D, 0.5940912365913391D, 0.594519317150116D, 0.5949195623397827D, 0.5953518152236938D, 0.5957903861999512D, 0.5961790680885315D, 0.5966396927833557D, 0.5971011519432068D, 0.5975552201271057D, 0.5979733467102051D, 0.5984484553337097D, 0.5989205837249756D, 0.5993812084197998D, 0.5998334288597107D, 0.6002959609031677D, 0.6007367968559265D, 0.6011759638786316D, 0.6016338467597961D, 0.6020973324775696D, 0.6025475859642029D, 0.6030203700065613D, 0.6034669876098633D, 0.6039260029792786D, 0.6043735146522522D, 0.6048296689987183D, 0.6052897572517395D, 0.6057608723640442D, 0.6062213778495789D, 0.606634259223938D, 0.6071000695228577D, 0.6075388789176941D, 0.6079697012901306D, 0.6084229946136475D, 0.608896791934967D, 0.6093420386314392D, 0.6098447442054749D, 0.6102806925773621D, 0.6107364296913147D, 0.611167311668396D, 0.6116251349449158D, 0.6120520830154419D, 0.6124976277351379D, 0.6129326224327087D, 0.613406777381897D, 0.6138620972633362D, 0.6143354177474976D, 0.6147979497909546D, 0.6152039766311646D, 0.6156638860702515D, 0.6161479353904724D, 0.6165993809700012D, 0.6170254349708557D, 0.6174780130386353D, 0.6178731918334961D, 0.6183233857154846D, 0.6187865734100342D, 0.6192396283149719D, 0.6197004318237305D, 0.6201303601264954D, 0.6205298900604248D, 0.6209881901741028D, 0.6214309930801392D, 0.6218465566635132D, 0.6223141551017761D, 0.622797966003418D, 0.6232821345329285D, 0.6237058043479919D, 0.6241947412490845D, 0.6246213912963867D, 0.6250787377357483D, 0.6255142092704773D, 0.6259811520576477D, 0.6264455914497375D, 0.6269148588180542D, 0.6274139881134033D, 0.6278729438781738D, 0.6283060908317566D, 0.6287518739700317D, 0.6292106509208679D, 0.6296188235282898D, 0.6300769448280334D, 0.6305136680603027D, 0.63094162940979D, 0.6313846707344055D, 0.6318341493606567D, 0.6322691440582275D, 0.63270103931427D, 0.6331589818000793D, 0.6335994601249695D, 0.6340522170066833D, 0.6345309615135193D, 0.6349889039993286D, 0.6354559659957886D, 0.6359289884567261D, 0.6363810896873474D, 0.6368818879127502D, 0.6373507976531982D, 0.6378063559532166D, 0.6382505893707275D, 0.6386348009109497D, 0.6391111016273499D, 0.6395545601844788D, 0.6399886608123779D, 0.6404418349266052D, 0.6408824920654297D, 0.6413149833679199D, 0.6417574882507324D, 0.6421859860420227D, 0.6426514387130737D, 0.6430553793907166D, 0.6434748768806458D, 0.6439327001571655D, 0.6443507075309753D, 0.6448029279708862D, 0.6452566385269165D, 0.6457155346870422D, 0.6461554765701294D, 0.646624743938446D, 0.6471140384674072D, 0.6475616097450256D, 0.6480266451835632D, 0.6484441757202148D, 0.6489031314849854D, 0.6492921113967896D, 0.6497485041618347D, 0.6501544713973999D, 0.6505953669548035D, 0.651073157787323D, 0.6515265703201294D, 0.6519653797149658D, 0.6524019837379456D, 0.6528423428535461D, 0.6533025503158569D, 0.6537554860115051D, 0.6541864275932312D, 0.6545959711074829D, 0.6550230979919434D, 0.6554749608039856D, 0.6558961272239685D, 0.6563379764556885D, 0.6567652225494385D, 0.6571946740150452D, 0.6576496362686157D, 0.6581230163574219D, 0.6585628390312195D, 0.6589741110801697D, 0.6594311594963074D, 0.65990149974823D, 0.6603091955184937D, 0.6607440114021301D, 0.6612043976783752D, 0.6616629362106323D, 0.6620782017707825D, 0.6625047326087952D, 0.6629456281661987D, 0.6633908152580261D, 0.6638535857200623D, 0.664313554763794D, 0.6647982597351074D, 0.6652121543884277D, 0.6656287312507629D, 0.6660541296005249D, 0.666519284248352D, 0.6669577360153198D, 0.667389452457428D, 0.6678563952445984D, 0.6683056950569153D, 0.6687613129615784D, 0.669194221496582D, 0.6696628928184509D, 0.6701160669326782D, 0.6705893874168396D, 0.671051561832428D, 0.6715012192726135D, 0.6719493865966797D, 0.6724033355712891D, 0.6728721857070923D, 0.6733037233352661D, 0.6737868189811707D, 0.6742551326751709D, 0.674736738204956D, 0.6752104759216309D, 0.6756134033203125D, 0.6760555505752563D, 0.6765036582946777D, 0.6769419312477112D, 0.6774052381515503D, 0.6778636574745178D, 0.678312361240387D, 0.6787456274032593D, 0.6792286038398743D, 0.6796970963478088D, 0.6801307201385498D, 0.6806089282035828D, 0.6810600757598877D, 0.6815366148948669D, 0.6819941997528076D, 0.6824822425842285D, 0.6829573512077332D, 0.6834262013435364D, 0.6839010715484619D, 0.6843841075897217D, 0.6848191618919373D, 0.6852960586547852D, 0.6857536435127258D, 0.6862004399299622D, 0.686630368232727D, 0.6870884299278259D, 0.6875705718994141D, 0.6880114674568176D, 0.6884872317314148D, 0.6889537572860718D, 0.6893516778945923D, 0.6898297667503357D, 0.6903215646743774D, 0.6907835602760315D, 0.6912608742713928D, 0.6916805505752563D, 0.6921491622924805D, 0.6926259398460388D, 0.693117082118988D, 0.6935994029045105D, 0.6940702795982361D, 0.6945260167121887D, 0.694933295249939D, 0.6953966617584229D, 0.695817232131958D, 0.6962674260139465D, 0.6967014074325562D, 0.6971595883369446D, 0.6976086497306824D, 0.6980371475219727D, 0.698500394821167D, 0.6989566683769226D, 0.6993935108184814D, 0.699805736541748D, 0.7002291083335876D, 0.7006635665893555D, 0.7011353373527527D, 0.7015767097473145D, 0.7020057439804077D, 0.7024185061454773D, 0.702873170375824D, 0.7033316493034363D, 0.7037590146064758D, 0.7041760683059692D, 0.7046096324920654D, 0.7050333023071289D, 0.705449640750885D, 0.7058889269828796D, 0.7063031196594238D, 0.7067270874977112D, 0.7071360945701599D, 0.7075799703598022D, 0.7080233097076416D, 0.708462119102478D, 0.7088784575462341D, 0.7093037962913513D, 0.7097235918045044D, 0.7101668119430542D, 0.710568904876709D, 0.7110000252723694D, 0.7114360928535461D, 0.7118644118309021D, 0.7122891545295715D, 0.712740421295166D, 0.7131741046905518D, 0.7136558294296265D, 0.714096188545227D, 0.7145424485206604D, 0.7150042057037354D, 0.7154485583305359D, 0.7159069776535034D, 0.7163503766059875D, 0.7168262600898743D, 0.7172953486442566D, 0.7177931666374207D, 0.7182849049568176D, 0.7187356948852539D, 0.7191860675811768D, 0.7196926474571228D, 0.7201302647590637D, 0.7206245064735413D, 0.721052885055542D, 0.7215341925621033D, 0.7220497131347656D, 0.7225143313407898D, 0.7229704260826111D, 0.7234534025192261D, 0.7239010334014893D, 0.7243943810462952D, 0.7248682379722595D, 0.7253683805465698D, 0.7258584499359131D, 0.7263447642326355D, 0.7268060445785522D, 0.727271556854248D, 0.7277473211288452D, 0.7282049059867859D, 0.7286691665649414D, 0.7291152477264404D, 0.7295757532119751D, 0.7300469875335693D, 0.7304925918579102D, 0.7309231758117676D, 0.7313723564147949D, 0.7318642139434814D, 0.7323406934738159D, 0.7328342795372009D, 0.7333183288574219D, 0.7338053584098816D, 0.7342978715896606D, 0.7347720861434937D, 0.735258936882019D, 0.7357116937637329D, 0.7361682653427124D, 0.7366530299186707D, 0.7371487617492676D, 0.7375858426094055D, 0.7380438446998596D, 0.7385260462760925D, 0.7389861345291138D, 0.7394406795501709D, 0.7399086356163025D, 0.7403405904769897D, 0.7408083081245422D, 0.7412325739860535D, 0.7416885495185852D, 0.7421688437461853D, 0.7426281571388245D, 0.7430750727653503D, 0.7435256242752075D, 0.7439917325973511D, 0.7444330453872681D, 0.7448722124099731D, 0.7452989816665649D, 0.7457219362258911D, 0.7461889982223511D, 0.7466121315956116D, 0.7470548748970032D, 0.7475171685218811D, 0.7479655742645264D, 0.7484027743339539D, 0.7488356828689575D, 0.7493087649345398D, 0.7497596144676208D, 0.7502181529998779D, 0.7506919503211975D, 0.751112699508667D, 0.7515501976013184D, 0.7520002126693726D, 0.7524545788764954D, 0.752912700176239D, 0.7533755302429199D, 0.7538471221923828D, 0.7542758584022522D, 0.7547116279602051D, 0.7551352381706238D, 0.7555804252624512D, 0.7560284733772278D, 0.7564794421195984D, 0.7569202184677124D, 0.7573555111885071D, 0.7578279376029968D, 0.7582671046257019D, 0.7587181925773621D, 0.7591692805290222D, 0.7595980763435364D, 0.760042130947113D, 0.7604596614837646D, 0.7608898282051086D, 0.7613398432731628D, 0.7617748975753784D, 0.7622143626213074D, 0.762671947479248D, 0.7631086707115173D, 0.7635783553123474D, 0.764057993888855D, 0.7645062208175659D, 0.7649529576301575D, 0.7654212713241577D, 0.765864372253418D, 0.7662825584411621D, 0.766756534576416D, 0.7671942114830017D, 0.7676814794540405D, 0.7680966854095459D, 0.7685232758522034D, 0.7689768671989441D, 0.7694152593612671D, 0.7698799967765808D, 0.7703273296356201D, 0.7707749009132385D, 0.7712304592132568D, 0.7716863751411438D, 0.7721555829048157D, 0.7726178765296936D, 0.7730773091316223D, 0.7735387086868286D, 0.77399080991745D, 0.7744596600532532D, 0.7749037146568298D, 0.7753519415855408D, 0.7757992744445801D, 0.7762538194656372D, 0.7767177820205688D, 0.7771676182746887D, 0.7776274681091309D, 0.7780811786651611D, 0.7785055637359619D, 0.778935968875885D, 0.7793811559677124D, 0.7798669338226318D, 0.7803198099136353D, 0.7807332277297974D, 0.7811895608901978D, 0.7816259860992432D, 0.7821038961410522D, 0.7825713157653809D, 0.7830300331115723D, 0.7834687829017639D, 0.7839145064353943D, 0.7843395471572876D, 0.7847908735275269D, 0.7852175235748291D, 0.7856557965278625D, 0.7861036658287048D, 0.7865192890167236D, 0.7869370579719543D, 0.7874005436897278D, 0.7878574728965759D, 0.7883076667785645D, 0.7887727618217468D, 0.7891872525215149D, 0.7896168231964111D, 0.7900912165641785D, 0.7905020713806152D, 0.7909590005874634D, 0.7913734912872314D, 0.7918078303337097D, 0.7922688722610474D, 0.792708158493042D, 0.7931526899337769D, 0.7935686707496643D, 0.7939856648445129D, 0.7944181561470032D, 0.7948570847511292D, 0.7952694892883301D, 0.7957113981246948D, 0.7961326837539673D, 0.7965633869171143D, 0.7970308065414429D, 0.7974699139595032D, 0.7978954315185547D, 0.798319399356842D, 0.798710286617279D, 0.799150288105011D, 0.799579918384552D, 0.8000137805938721D, 0.8004805445671082D, 0.8009114861488342D, 0.8013453483581543D, 0.8017767667770386D, 0.8022176027297974D, 0.8026309013366699D, 0.8030619621276855D, 0.8034893274307251D, 0.8039072751998901D, 0.8043564558029175D, 0.804783284664154D, 0.805206298828125D, 0.8056594729423523D, 0.8061367273330688D, 0.806596040725708D, 0.8070647716522217D, 0.8075343370437622D, 0.8080013394355774D, 0.8084481954574585D, 0.8088930249214172D, 0.8093382120132446D, 0.8098229169845581D, 0.8102787137031555D, 0.810730516910553D, 0.811210036277771D, 0.8116769790649414D, 0.812152624130249D, 0.8126338124275208D, 0.813092052936554D, 0.8135685324668884D, 0.8140095472335815D, 0.81447833776474D, 0.8149551749229431D, 0.8154143691062927D, 0.8158760666847229D, 0.8163301348686218D, 0.8167980313301086D, 0.817247211933136D, 0.8176859021186829D, 0.818127453327179D, 0.8185797333717346D, 0.8190116286277771D, 0.8194664716720581D, 0.8199171423912048D, 0.820368766784668D, 0.820813000202179D, 0.8212815523147583D, 0.8217201232910156D, 0.8221539855003357D, 0.822625458240509D, 0.8230755925178528D, 0.8235254287719727D, 0.823959469795227D, 0.8244135975837708D, 0.8248838186264038D, 0.8253191113471985D, 0.8257774114608765D, 0.82623690366745D, 0.8267050981521606D, 0.8271421194076538D, 0.8275777101516724D, 0.8280438184738159D, 0.828515350818634D, 0.8289567232131958D, 0.8294112086296082D, 0.8298828601837158D, 0.8303140997886658D, 0.8307706713676453D, 0.83122318983078D, 0.8316763639450073D, 0.8321682214736938D, 0.8326238393783569D, 0.8331080675125122D, 0.8335604071617126D, 0.8340092301368713D, 0.834452748298645D, 0.8349207639694214D, 0.8353868722915649D, 0.835853636264801D, 0.8363184332847595D, 0.8368146419525146D, 0.8372671604156494D, 0.8377043008804321D, 0.8381913900375366D, 0.8386459946632385D, 0.8391138911247253D, 0.8395722508430481D, 0.8400129675865173D, 0.8404837250709534D, 0.8409408330917358D, 0.8414034247398376D, 0.8418894410133362D, 0.8423717021942139D, 0.842841625213623D, 0.8433132171630859D, 0.8437666296958923D, 0.8442238569259644D, 0.8446865677833557D, 0.8451375961303711D, 0.8456094861030579D, 0.84608393907547D, 0.8465566635131836D, 0.8470044732093811D, 0.8474630117416382D, 0.8479244112968445D, 0.8483870625495911D, 0.8488436341285706D, 0.8492886424064636D, 0.8497526049613953D, 0.8502447009086609D, 0.8507117629051208D, 0.8511672616004944D, 0.8516263961791992D, 0.8520602583885193D, 0.8525027632713318D, 0.852948784828186D, 0.8534206748008728D, 0.8538854718208313D, 0.8543459177017212D, 0.8548005819320679D, 0.8552507162094116D, 0.8557122349739075D, 0.856152355670929D, 0.8566517233848572D, 0.8570873141288757D, 0.8575365543365479D, 0.857970654964447D, 0.8584120273590088D, 0.858855664730072D, 0.8592962622642517D, 0.8597331047058105D, 0.8601778149604797D, 0.8606115579605103D, 0.8610638380050659D, 0.8615244626998901D, 0.861991286277771D, 0.8624619841575623D, 0.862913191318512D, 0.8633754849433899D, 0.8638368844985962D, 0.8642979860305786D, 0.8647482395172119D, 0.8652056455612183D, 0.8656649589538574D, 0.866115927696228D, 0.8665704131126404D, 0.8670414090156555D, 0.8674944639205933D, 0.8679722547531128D, 0.8684281706809998D, 0.8689029216766357D, 0.86937415599823D, 0.8698508143424988D, 0.870283842086792D, 0.8707519769668579D, 0.8712092041969299D, 0.8716691732406616D, 0.8721535801887512D, 0.8726065158843994D, 0.8730449676513672D, 0.8734990954399109D, 0.8739246726036072D, 0.874381422996521D, 0.8748207092285156D, 0.875253438949585D, 0.875724196434021D, 0.876218318939209D, 0.8766701817512512D, 0.8771216869354248D, 0.8775990009307861D, 0.8780642747879028D, 0.8785414099693298D, 0.8790207505226135D, 0.8794875144958496D, 0.8799788355827332D, 0.880420446395874D, 0.880905270576477D, 0.881375253200531D, 0.8818048238754272D, 0.8822588920593262D, 0.8827162384986877D, 0.8831582069396973D, 0.8836075663566589D, 0.8840537667274475D, 0.8845331072807312D, 0.8850046992301941D, 0.8854608535766602D, 0.8858955502510071D, 0.8863389492034912D, 0.8867753744125366D, 0.8872137069702148D, 0.887676477432251D, 0.8881357908248901D, 0.8885685205459595D, 0.889004111289978D, 0.8894510865211487D, 0.8899015784263611D, 0.8903590440750122D, 0.890826940536499D, 0.8913052082061768D, 0.8918041586875916D, 0.8922762870788574D, 0.8927425742149353D, 0.8931938409805298D, 0.8936666250228882D, 0.894100546836853D, 0.894587516784668D, 0.8950610756874084D, 0.8955479264259338D, 0.8960167765617371D, 0.8965259790420532D, 0.896999716758728D, 0.8974786400794983D, 0.8979550004005432D, 0.8984525203704834D, 0.8989295959472656D, 0.8994243144989014D, 0.899922251701355D, 0.9004544615745544D, 0.900951087474823D, 0.9014334678649902D, 0.9019694924354553D, 0.9024796485900879D, 0.9030163288116455D, 0.9035549163818359D, 0.9041017293930054D, 0.9046435356140137D, 0.9052310585975647D, 0.905797004699707D, 0.9064053893089294D, 0.9070045351982117D, 0.9076210260391235D, 0.9082058668136597D, 0.908807635307312D, 0.9094119071960449D, 0.9100490212440491D, 0.9107301831245422D, 0.9113752245903015D, 0.9120429754257202D, 0.912749707698822D, 0.9134305119514465D, 0.9141203165054321D, 0.9147968888282776D, 0.9155049920082092D, 0.9162451028823853D, 0.9169884324073792D, 0.9177526235580444D, 0.9185255765914917D, 0.9192798137664795D, 0.9200562834739685D, 0.9208371639251709D, 0.9216248989105225D, 0.9224410653114319D, 0.9232978820800781D, 0.9241725206375122D, 0.9250988960266113D, 0.9260335564613342D, 0.9269416928291321D, 0.9278931617736816D, 0.9288076758384705D, 0.9297255873680115D, 0.9306380152702332D, 0.9316264986991882D, 0.9326559901237488D, 0.9336634874343872D, 0.9347042441368103D, 0.9357998967170715D, 0.9368151426315308D, 0.9378435015678406D, 0.9390134215354919D, 0.9402108788490295D, 0.9414093494415283D, 0.9425628185272217D, 0.9438204169273376D, 0.9450675249099731D, 0.9462559223175049D, 0.9474560022354126D, 0.9487866759300232D, 0.9501336812973022D, 0.9516785144805908D, 0.9532408714294434D, 0.9547208547592163D, 0.9561983942985535D, 0.9577432870864868D, 0.9593563675880432D, 0.9611396789550781D, 0.9630594849586487D, 0.9652234315872192D, 0.9678966403007507D, 0.9710233807563782D, 0.9745553135871887D, 0.9781689047813416D, 0.981545090675354D, 0.9869863986968994D, 0.9941355586051941D, 0.9998435378074646D}; + /** + * Normalize a double d to a value from zero to num.
+ * This assumes that the value d was generated by a FastNoiseLite instance using SimplexFractal noise type with 4 Octaves. + * + * @param d The value to be normalized. + * @param num The maximum value. + * @return The normalized value. + */ + public static int normalize(double d, int num, int octaves) { + int start = 0; + double[] normalMap; + switch(octaves) { + case 1: + normalMap = normalMap1; + break; + case 4: + normalMap = normalMap4; + break; + default: throw new IllegalArgumentException("Illegal octave amount: " + octaves); + } + + int end = normalMap.length - 1; + while(start + 1 < end) { + int mid = start + (end - start) / 2; + if(normalMap[mid] <= d) { + start = mid; + } else { + end = mid; + } + } + double left = FastMath.abs(normalMap[start] - d); + double right = FastMath.abs(normalMap[end] - d); + if(left <= right) { + return start * (num) / (normalMap.length); + } + return end * (num) / (normalMap.length); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/world/carving/Carver.java b/common/src/main/java/com/dfsek/terra/api/world/carving/Carver.java new file mode 100644 index 000000000..c0b21ae26 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/world/carving/Carver.java @@ -0,0 +1,38 @@ +package com.dfsek.terra.api.world.carving; + +import com.dfsek.terra.api.math.vector.Vector3; +import com.dfsek.terra.api.platform.world.World; +import net.jafama.FastMath; + +import java.util.Random; +import java.util.function.BiConsumer; + +public abstract class Carver { + private final int minY; + private final int maxY; + private final double sixtyFourSq = FastMath.pow(64, 2); + private int carvingRadius = 4; + + public Carver(int minY, int maxY) { + this.minY = minY; + this.maxY = maxY; + } + + public abstract void carve(int chunkX, int chunkZ, World w, BiConsumer consumer); + + public int getCarvingRadius() { + return carvingRadius; + } + + public void setCarvingRadius(int carvingRadius) { + this.carvingRadius = carvingRadius; + } + + public abstract Worm getWorm(long seed, Vector3 l); + + public abstract boolean isChunkCarved(World w, int chunkX, int chunkZ, Random r); + + public enum CarvingType { + CENTER, WALL, TOP, BOTTOM + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/world/carving/Worm.java b/common/src/main/java/com/dfsek/terra/api/world/carving/Worm.java new file mode 100644 index 000000000..71e2b0de5 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/world/carving/Worm.java @@ -0,0 +1,119 @@ +package com.dfsek.terra.api.world.carving; + +import com.dfsek.terra.api.math.vector.Vector3; +import net.jafama.FastMath; + +import java.util.Random; +import java.util.function.BiConsumer; + +public abstract class Worm { + private final Random r; + private final Vector3 origin; + private final Vector3 running; + private final int length; + private int topCut = 0; + private int bottomCut = 0; + private int[] radius = new int[] {0, 0, 0}; + + public Worm(int length, Random r, Vector3 origin) { + this.r = r; + this.length = length; + this.origin = origin; + this.running = origin; + } + + public void setBottomCut(int bottomCut) { + this.bottomCut = bottomCut; + } + + public void setTopCut(int topCut) { + this.topCut = topCut; + } + + public Vector3 getOrigin() { + return origin; + } + + public int getLength() { + return length; + } + + public Vector3 getRunning() { + return running; + } + + public WormPoint getPoint() { + return new WormPoint(running, radius, topCut, bottomCut); + } + + public int[] getRadius() { + return radius; + } + + public void setRadius(int[] radius) { + this.radius = radius; + } + + public Random getRandom() { + return r; + } + + public abstract void step(); + + public static class WormPoint { + private final Vector3 origin; + private final int topCut; + private final int bottomCut; + private final int[] rad; + + public WormPoint(Vector3 origin, int[] rad, int topCut, int bottomCut) { + this.origin = origin; + this.rad = rad; + this.topCut = topCut; + this.bottomCut = bottomCut; + } + + private static double ellipseEquation(int x, int y, int z, double xr, double yr, double zr) { + return (FastMath.pow2(x) / FastMath.pow2(xr + 0.5D)) + (FastMath.pow2(y) / FastMath.pow2(yr + 0.5D)) + (FastMath.pow2(z) / FastMath.pow2(zr + 0.5D)); + } + + public Vector3 getOrigin() { + return origin; + } + + public int getRadius(int index) { + return rad[index]; + } + + public void carve(int chunkX, int chunkZ, BiConsumer consumer) { + int xRad = getRadius(0); + int yRad = getRadius(1); + int zRad = getRadius(2); + int originX = (chunkX << 4); + int originZ = (chunkZ << 4); + for(int x = -xRad - 1; x <= xRad + 1; x++) { + if(!(FastMath.floorDiv(origin.getBlockX() + x, 16) == chunkX)) continue; + for(int z = -zRad - 1; z <= zRad + 1; z++) { + if(!(FastMath.floorDiv(origin.getBlockZ() + z, 16) == chunkZ)) continue; + for(int y = -yRad - 1; y <= yRad + 1; y++) { + Vector3 position = origin.clone().add(new Vector3(x, y, z)); + if(position.getY() < 0 || position.getY() > 255) continue; + double eq = ellipseEquation(x, y, z, xRad, yRad, zRad); + if(eq <= 1 && + y >= -yRad - 1 + bottomCut && y <= yRad + 1 - topCut) { + consumer.accept(new Vector3(position.getBlockX() - originX, position.getBlockY(), position.getBlockZ() - originZ), Carver.CarvingType.CENTER); + } else if(eq <= 1.5) { + Carver.CarvingType type = Carver.CarvingType.WALL; + if(y <= -yRad - 1 + bottomCut) { + type = Carver.CarvingType.BOTTOM; + } else if(y >= yRad + 1 - topCut) { + type = Carver.CarvingType.TOP; + } + consumer.accept(new Vector3(position.getBlockX() - originX, position.getBlockY(), position.getBlockZ() - originZ), type); + } + } + } + } + } + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/world/flora/Flora.java b/common/src/main/java/com/dfsek/terra/api/world/flora/Flora.java new file mode 100644 index 000000000..82d57f9b0 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/world/flora/Flora.java @@ -0,0 +1,14 @@ +package com.dfsek.terra.api.world.flora; + +import com.dfsek.terra.api.math.Range; +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.platform.block.Block; +import com.dfsek.terra.api.platform.world.Chunk; + +import java.util.List; + +public interface Flora { + List getValidSpawnsAt(Chunk chunk, int x, int z, Range check); + + boolean plant(Location l); +} diff --git a/common/src/main/java/com/dfsek/terra/api/world/generation/GenerationPhase.java b/common/src/main/java/com/dfsek/terra/api/world/generation/GenerationPhase.java new file mode 100644 index 000000000..6dfee8985 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/world/generation/GenerationPhase.java @@ -0,0 +1,8 @@ +package com.dfsek.terra.api.world.generation; + +/** + * The phase of terrain generation. Used for modifying values based on the phase of generation. + */ +public enum GenerationPhase { + BASE, POPULATE, GENERATION_POPULATE, PALETTE_APPLY, POST_GEN +} diff --git a/common/src/main/java/com/dfsek/terra/api/world/generation/TerraBlockPopulator.java b/common/src/main/java/com/dfsek/terra/api/world/generation/TerraBlockPopulator.java new file mode 100644 index 000000000..1d0e47577 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/world/generation/TerraBlockPopulator.java @@ -0,0 +1,8 @@ +package com.dfsek.terra.api.world.generation; + +import com.dfsek.terra.api.platform.world.Chunk; +import com.dfsek.terra.api.platform.world.World; + +public interface TerraBlockPopulator { + void populate(World world, Chunk chunk); +} diff --git a/common/src/main/java/com/dfsek/terra/api/world/generation/TerraChunkGenerator.java b/common/src/main/java/com/dfsek/terra/api/world/generation/TerraChunkGenerator.java new file mode 100644 index 000000000..5273916a1 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/world/generation/TerraChunkGenerator.java @@ -0,0 +1,30 @@ +package com.dfsek.terra.api.world.generation; + +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.platform.generator.ChunkGenerator; +import com.dfsek.terra.api.platform.world.BiomeGrid; +import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.config.base.ConfigPack; +import org.jetbrains.annotations.NotNull; + +import java.util.Random; + +public interface TerraChunkGenerator { + ChunkGenerator.ChunkData generateChunkData(@NotNull World world, Random random, int x, int z, ChunkGenerator.ChunkData original); + + void generateBiomes(@NotNull World world, @NotNull Random random, int x, int z, @NotNull BiomeGrid biome); + + boolean isParallelCapable(); + + boolean shouldGenerateCaves(); + + boolean shouldGenerateDecorations(); + + boolean shouldGenerateMobs(); + + boolean shouldGenerateStructures(); + + ConfigPack getConfigPack(); + + TerraPlugin getMain(); +} diff --git a/common/src/main/java/com/dfsek/terra/api/world/generation/population/ChunkCoordinate.java b/common/src/main/java/com/dfsek/terra/api/world/generation/population/ChunkCoordinate.java new file mode 100644 index 000000000..befa179d5 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/world/generation/population/ChunkCoordinate.java @@ -0,0 +1,50 @@ +package com.dfsek.terra.api.world.generation.population; + + +import com.dfsek.terra.api.platform.world.Chunk; + +import java.io.Serializable; +import java.util.UUID; + +public class ChunkCoordinate implements Serializable { + public static final long serialVersionUID = 7102462856296750285L; + private final int x; + private final int z; + private final UUID worldID; + + public ChunkCoordinate(int x, int z, UUID worldID) { + this.x = x; + this.z = z; + this.worldID = worldID; + } + + public ChunkCoordinate(Chunk c) { + this.x = c.getX(); + this.z = c.getZ(); + this.worldID = c.getWorld().getUID(); + } + + public UUID getWorldID() { + return worldID; + } + + public int getX() { + return x; + } + + public int getZ() { + return z; + } + + @Override + public int hashCode() { + return x * 31 + z; + } + + @Override + public boolean equals(Object obj) { + if(!(obj instanceof ChunkCoordinate)) return false; + com.dfsek.terra.api.world.generation.population.ChunkCoordinate other = (com.dfsek.terra.api.world.generation.population.ChunkCoordinate) obj; + return other.getX() == x && other.getZ() == z; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/world/generation/population/PopulationManager.java b/common/src/main/java/com/dfsek/terra/api/world/generation/population/PopulationManager.java new file mode 100644 index 000000000..6c7bab57c --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/world/generation/population/PopulationManager.java @@ -0,0 +1,94 @@ +package com.dfsek.terra.api.world.generation.population; + +import com.dfsek.terra.api.Gaea; +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.platform.world.Chunk; +import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.api.profiler.ProfileFuture; +import com.dfsek.terra.api.profiler.WorldProfiler; +import com.dfsek.terra.api.util.FastRandom; +import com.dfsek.terra.api.util.GlueList; +import com.dfsek.terra.api.util.SerializationUtil; +import com.dfsek.terra.api.world.generation.TerraBlockPopulator; +import org.jetbrains.annotations.NotNull; + +import java.io.File; +import java.io.IOException; +import java.util.HashSet; +import java.util.List; +import java.util.Random; + +public class PopulationManager implements TerraBlockPopulator { + private final List attachedPopulators = new GlueList<>(); + private final HashSet needsPop = new HashSet<>(); + private final TerraPlugin main; + private WorldProfiler profiler; + + public PopulationManager(TerraPlugin main) { + this.main = main; + } + + public void attach(TerraBlockPopulator populator) { + this.attachedPopulators.add(populator); + } + + @Override + @SuppressWarnings("try") + public void populate(@NotNull World world, @NotNull Chunk chunk) { + try(ProfileFuture ignored = measure()) { + needsPop.add(new ChunkCoordinate(chunk)); + int x = chunk.getX(); + int z = chunk.getZ(); + if(main.isEnabled()) { + for(int xi = -1; xi <= 1; xi++) { + for(int zi = -1; zi <= 1; zi++) { + if(xi == 0 && zi == 0) continue; + if(world.isChunkGenerated(xi + x, zi + z)) checkNeighbors(xi + x, zi + z, world); + } + } + } + } + } + + private ProfileFuture measure() { + if(profiler != null) return profiler.measure("PopulationManagerTime"); + return null; + } + + public void attachProfiler(WorldProfiler p) { + this.profiler = p; + } + + @SuppressWarnings("unchecked") + public synchronized void saveBlocks(World w) throws IOException { + File f = new File(Gaea.getGaeaFolder(w), "chunks.bin"); + f.createNewFile(); + SerializationUtil.toFile((HashSet) needsPop.clone(), f); + } + + @SuppressWarnings("unchecked") + public synchronized void loadBlocks(World w) throws IOException, ClassNotFoundException { + File f = new File(Gaea.getGaeaFolder(w), "chunks.bin"); + needsPop.addAll((HashSet) SerializationUtil.fromFile(f)); + } + + + // Synchronize to prevent chunks from being queued for population multiple times. + public synchronized void checkNeighbors(int x, int z, World w) { + ChunkCoordinate c = new ChunkCoordinate(x, z, w.getUID()); + if(w.isChunkGenerated(x + 1, z) + && w.isChunkGenerated(x - 1, z) + && w.isChunkGenerated(x, z + 1) + && w.isChunkGenerated(x, z - 1) && needsPop.contains(c)) { + Random random = new FastRandom(w.getSeed()); + long xRand = (random.nextLong() / 2L << 1L) + 1L; + long zRand = (random.nextLong() / 2L << 1L) + 1L; + random.setSeed((long) x * xRand + (long) z * zRand ^ w.getSeed()); + Chunk currentChunk = w.getChunkAt(x, z); + for(TerraBlockPopulator r : attachedPopulators) { + r.populate(w, currentChunk); + } + needsPop.remove(c); + } + } +} \ No newline at end of file diff --git a/common/src/main/java/com/dfsek/terra/api/world/palette/Palette.java b/common/src/main/java/com/dfsek/terra/api/world/palette/Palette.java new file mode 100644 index 000000000..f10ecfbf8 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/world/palette/Palette.java @@ -0,0 +1,116 @@ +package com.dfsek.terra.api.world.palette; + +import com.dfsek.terra.api.math.ProbabilityCollection; +import com.dfsek.terra.api.math.noise.samplers.NoiseSampler; +import com.dfsek.terra.api.util.GlueList; + +import java.util.List; +import java.util.Random; + +/** + * A class representation of a "slice" of the world. + * Used to get a section of blocks, based on the depth at which they are found. + */ +public abstract class Palette { + private final List> pallet = new GlueList<>(); + + /** + * Constructs a blank palette. + */ + public Palette() { + + } + + /** + * Adds a material to the palette, for a number of layers. + * + * @param m - The material to add to the palette. + * @param layers - The number of layers the material occupies. + * @return - BlockPalette instance for chaining. + */ + public com.dfsek.terra.api.world.palette.Palette add(E m, int layers) { + for(int i = 0; i < layers; i++) { + pallet.add(new PaletteLayer<>(m)); + } + return this; + } + + /** + * Adds a ProbabilityCollection to the palette, for a number of layers. + * + * @param m - The ProbabilityCollection to add to the palette. + * @param layers - The number of layers the material occupies. + * @return - BlockPalette instance for chaining. + */ + public com.dfsek.terra.api.world.palette.Palette add(ProbabilityCollection m, int layers) { + for(int i = 0; i < layers; i++) { + pallet.add(new PaletteLayer<>(m)); + } + return this; + } + + /** + * Fetches a material from the palette, at a given layer. + * + * @param layer - The layer at which to fetch the material. + * @return BlockData - The material fetched. + */ + public abstract E get(int layer, int x, int z); + + + public int getSize() { + return pallet.size(); + } + + public List> getLayers() { + return pallet; + } + + /** + * Class representation of a layer of a BlockPalette. + */ + public static class PaletteLayer { + private final boolean col; // Is layer using a collection? + private ProbabilityCollection collection; + private E m; + + /** + * Constructs a PaletteLayer with a ProbabilityCollection of materials and a number of layers. + * + * @param type - The collection of materials to choose from. + */ + public PaletteLayer(ProbabilityCollection type) { + this.col = true; + this.collection = type; + } + + /** + * Constructs a PaletteLayer with a single Material and a number of layers. + * + * @param type - The material to use. + */ + public PaletteLayer(E type) { + this.col = false; + this.m = type; + } + + /** + * Gets a material from the layer. + * + * @return Material - the material.. + */ + public E get(Random random) { + if(col) return this.collection.get(random); + return m; + } + + public E get(NoiseSampler random, int x, int z) { + if(col) return this.collection.get(random, x, z); + return m; + } + + public ProbabilityCollection getCollection() { + return collection; + } + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/world/palette/RandomPalette.java b/common/src/main/java/com/dfsek/terra/api/world/palette/RandomPalette.java new file mode 100644 index 000000000..88452d953 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/world/palette/RandomPalette.java @@ -0,0 +1,20 @@ +package com.dfsek.terra.api.world.palette; + +import java.util.List; +import java.util.Random; + +public class RandomPalette extends Palette { + private final Random r; + + public RandomPalette(Random r) { + this.r = r; + } + + @Override + public E get(int layer, int x, int z) { + if(layer > this.getSize()) return this.getLayers().get(this.getLayers().size() - 1).get(r); + List> pl = getLayers(); + if(layer >= pl.size()) return pl.get(pl.size() - 1).get(r); + return pl.get(layer).get(r); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/world/palette/SimplexPalette.java b/common/src/main/java/com/dfsek/terra/api/world/palette/SimplexPalette.java new file mode 100644 index 000000000..6ac97f88b --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/world/palette/SimplexPalette.java @@ -0,0 +1,21 @@ +package com.dfsek.terra.api.world.palette; + +import com.dfsek.terra.api.math.noise.samplers.NoiseSampler; + +import java.util.List; + +public class SimplexPalette extends Palette { + private final NoiseSampler r; + + public SimplexPalette(NoiseSampler r) { + this.r = r; + } + + @Override + public E get(int layer, int x, int z) { + if(layer > this.getSize()) return this.getLayers().get(this.getLayers().size() - 1).get(r, x, z); + List> pl = getLayers(); + if(layer >= pl.size()) return pl.get(pl.size() - 1).get(r, x, z); + return pl.get(layer).get(r, x, z); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/world/tree/Tree.java b/common/src/main/java/com/dfsek/terra/api/world/tree/Tree.java new file mode 100644 index 000000000..47221fd20 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/world/tree/Tree.java @@ -0,0 +1,14 @@ +package com.dfsek.terra.api.world.tree; + + +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.platform.block.MaterialData; + +import java.util.Random; +import java.util.Set; + +public interface Tree { + boolean plant(Location l, Random r); + + Set getSpawnable(); +} diff --git a/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/EntitySpawnHolder.java b/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/EntitySpawnHolder.java new file mode 100644 index 000000000..ed485dd60 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/EntitySpawnHolder.java @@ -0,0 +1,32 @@ +package com.dfsek.terra.api.world.tree.fractal; + +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.platform.world.entity.Entity; + +import java.util.function.Consumer; + + +public class EntitySpawnHolder { + private final Location l; + private final Class e; + private final Consumer c; + + public EntitySpawnHolder(Location l, Class e, Consumer c) { + this.l = l; + this.e = e; + this.c = c; + } + + @SuppressWarnings("rawtypes") + public Class getEntity() { + return e; + } + + public Consumer getConsumer() { + return c; + } + + public Location getLocation() { + return l; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/FractalTree.java b/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/FractalTree.java new file mode 100644 index 000000000..76be0e183 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/FractalTree.java @@ -0,0 +1,48 @@ +package com.dfsek.terra.api.world.tree.fractal; + +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.world.entity.Entity; +import com.dfsek.terra.api.platform.world.entity.EntityType; +import com.dfsek.terra.util.MaterialSet; + +import java.util.Random; +import java.util.function.Consumer; + + +public abstract class FractalTree { + protected final TerraPlugin main; + + public abstract MaterialSet getSpawnable(); + + /** + * Instantiates a TreeGrower at an origin location. + */ + public FractalTree(TerraPlugin plugin) { + this.main = plugin; + } + + /** + * Sets a block in the tree's storage map to a material. + * + * @param l - The location to set. + * @param m - The material to which it will be set. + */ + public void setBlock(Location l, BlockData m) { + l.getBlock().setBlockData(m, false); + } + + public TerraPlugin getMain() { + return main; + } + + /** + * Grows the tree in memory. Intended to be invoked from an async thread. + */ + public abstract void grow(Location origin, Random random); + + public void spawnEntity(Location spawn, EntityType type, Consumer consumer) { + consumer.accept(spawn.getWorld().spawnEntity(spawn, type)); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/TreeGeometry.java b/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/TreeGeometry.java new file mode 100644 index 000000000..bd9ac089b --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/TreeGeometry.java @@ -0,0 +1,68 @@ +package com.dfsek.terra.api.world.tree.fractal; + +import com.dfsek.terra.api.math.ProbabilityCollection; +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.math.vector.Vector3; +import com.dfsek.terra.api.platform.block.BlockData; + +import java.util.Random; + +public class TreeGeometry { + private final FractalTree tree; + + public TreeGeometry(FractalTree tree) { + this.tree = tree; + } + + public static Vector3 getPerpendicular(Vector3 v) { + return v.getZ() < v.getX() ? new Vector3(v.getY(), - v.getX(), 0) : new Vector3(0, - v.getZ(), v.getY()); + } + + public FractalTree getTree() { + return tree; + } + + public void generateSphere(Location l, BlockData m, int radius, boolean overwrite) { + generateSphere(l, new ProbabilityCollection().add(m, 1), radius, overwrite); + } + + public void generateCylinder(Location l, BlockData m, int radius, int height, boolean overwrite) { + generateCylinder(l, new ProbabilityCollection().add(m, 1), radius, height, overwrite); + } + + public void generateSphere(Location l, ProbabilityCollection m, int radius, boolean overwrite) { + for(int x = - radius; x <= radius; x++) { + for(int y = - radius; y <= radius; y++) { + for(int z = - radius; z <= radius; z++) { + Vector3 position = l.toVector().clone().add(new Vector3(x, y, z)); + if(l.toVector().distance(position) <= radius + 0.5 && (overwrite || position.toLocation(l.getWorld()).getBlock().isEmpty())) + tree.setBlock(position.toLocation(l.getWorld()), m.get()); + } + } + } + } + + public void generateSponge(Location l, ProbabilityCollection m, int radius, boolean overwrite, int sponginess, Random r) { + for(int x = -radius; x <= radius; x++) { + for(int y = -radius; y <= radius; y++) { + for(int z = -radius; z <= radius; z++) { + Vector3 position = l.toVector().clone().add(new Vector3(x, y, z)); + if(r.nextInt(100) < sponginess && l.toVector().distance(position) <= radius + 0.5 && (overwrite || position.toLocation(l.getWorld()).getBlock().isEmpty())) + tree.setBlock(position.toLocation(l.getWorld()), m.get()); + } + } + } + } + + public void generateCylinder(Location l, ProbabilityCollection m, int radius, int height, boolean overwrite) { + for(int x = - radius; x <= radius; x++) { + for(int y = 0; y <= height; y++) { + for(int z = - radius; z <= radius; z++) { + Vector3 position = l.toVector().clone().add(new Vector3(x, 0, z)); + if(l.toVector().distance(position) <= radius + 0.5 && (overwrite || position.toLocation(l.getWorld()).getBlock().isEmpty())) + tree.setBlock(position.toLocation(l.getWorld()), m.get()); + } + } + } + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/trees/Cactus.java b/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/trees/Cactus.java new file mode 100644 index 000000000..e7a965ccb --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/trees/Cactus.java @@ -0,0 +1,35 @@ +package com.dfsek.terra.api.world.tree.fractal.trees; + +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.world.tree.fractal.FractalTree; +import com.dfsek.terra.util.MaterialSet; + +import java.util.Random; + +public class Cactus extends FractalTree { + @Override + public MaterialSet getSpawnable() { + return MaterialSet.get(main.getWorldHandle().createMaterialData("minecraft:sand"), + main.getWorldHandle().createMaterialData("minecraft:red_sand")); + } + + + /** + * Instantiates a TreeGrower at an origin location. + */ + public Cactus(TerraPlugin main) { + super(main); + } + + /** + * Grows the tree in memory. Intended to be invoked from an async thread. + */ + @Override + public void grow(Location origin, Random random) { + BlockData cactus = getMain().getWorldHandle().createBlockData("minecraft:cactus"); + int h = random.nextInt(4) + 1; + for(int i = 0; i < h; i++) setBlock(origin.clone().add(0, i, 0), cactus); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/trees/IceSpike.java b/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/trees/IceSpike.java new file mode 100644 index 000000000..ea45144dd --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/trees/IceSpike.java @@ -0,0 +1,57 @@ +package com.dfsek.terra.api.world.tree.fractal.trees; + +import com.dfsek.terra.api.math.ProbabilityCollection; +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.math.vector.Vector3; +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.handle.WorldHandle; +import com.dfsek.terra.api.world.tree.fractal.FractalTree; +import com.dfsek.terra.api.world.tree.fractal.TreeGeometry; +import com.dfsek.terra.util.MaterialSet; + +import java.util.Random; + + +public class IceSpike extends FractalTree { + private final TreeGeometry geo; + private final ProbabilityCollection ice; + + @Override + public MaterialSet getSpawnable() { + return MaterialSet.get(main.getWorldHandle().createMaterialData("minecraft:stone"), + main.getWorldHandle().createMaterialData("minecraft:gravel"), + main.getWorldHandle().createMaterialData("minecraft:snow_block"), + main.getWorldHandle().createMaterialData("minecraft:grass_block")); + } + + /** + * Instantiates a TreeGrower at an origin location. + */ + public IceSpike(TerraPlugin main) { + super(main); + geo = new TreeGeometry(this); + WorldHandle handle = main.getWorldHandle(); + ice = new ProbabilityCollection().add(handle.createBlockData("minecraft:packed_ice"), 95).add(handle.createBlockData("minecraft:blue_ice"), 5); + } + + private double getOffset(Random r) { + return (r.nextDouble() - 0.5D); + } + + /** + * Grows the tree in memory. Intended to be invoked from an async thread. + */ + @Override + public void grow(Location origin, Random random) { + Vector3 direction = new Vector3(getOffset(random), 0, getOffset(random)); + Location l1 = origin.clone(); + int h = random.nextInt(16) + 8; + for(int i = 0; i < h; i++) { + geo.generateSponge(l1.clone().add(0, i, 0).add(direction.clone().multiply(i)), ice, (int) ((1 - ((double) i / h)) * 2 + 1), true, 80, random); + } + for(int i = 0; i < h / 3; i++) { + setBlock(l1.clone().add(0, h + i, 0).add(direction.clone().multiply(h + i)), ice.get(random)); + } + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/trees/OakTree.java b/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/trees/OakTree.java new file mode 100644 index 000000000..4a24b7a90 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/trees/OakTree.java @@ -0,0 +1,66 @@ +package com.dfsek.terra.api.world.tree.fractal.trees; + +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.math.vector.Vector3; +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.world.tree.fractal.FractalTree; +import com.dfsek.terra.api.world.tree.fractal.TreeGeometry; +import com.dfsek.terra.util.MaterialSet; +import net.jafama.FastMath; + +import java.util.Random; + + +public class OakTree extends FractalTree { + private final TreeGeometry geo; + + @Override + public MaterialSet getSpawnable() { + return MaterialSet.get(main.getWorldHandle().createMaterialData("minecraft:podzol"), + main.getWorldHandle().createMaterialData("minecraft:grass_block")); + } + + /** + * Instantiates a TreeGrower at an origin location. + */ + public OakTree(TerraPlugin main) { + super(main); + geo = new TreeGeometry(this); + } + + /** + * Grows the tree in memory. Intended to be invoked from an async thread. + */ + @Override + public void grow(Location origin, Random random) { + growBranch(origin.clone(), new Vector3(random.nextInt(5) - 2, random.nextInt(4) + 6, random.nextInt(5) - 2), 2, 0, random); + } + + private void growBranch(Location l1, Vector3 diff, double d1, int recursions, Random r) { + BlockData wood = getMain().getWorldHandle().createBlockData("minecraft:oak_wood"); + BlockData leaves = getMain().getWorldHandle().createBlockData("minecraft:oak_leave"); + if(recursions > 1) { + geo.generateSphere(l1, leaves, 1 + r.nextInt(2) + (3 - recursions), false); + if(recursions > 2) return; + } + if(diff.getY() < 0) diff.rotateAroundAxis(TreeGeometry.getPerpendicular(diff.clone()).normalize(), FastMath.PI); + int d = (int) diff.length(); + for(int i = 0; i < d; i++) { + geo.generateSphere(l1.clone().add(diff.clone().multiply((double) i / d)), wood, FastMath.max((int) d1, 0), true); + } + double runningAngle = (double) 45 / (recursions + 1); + growBranch(l1.clone().add(diff), diff.clone().multiply(0.75).rotateAroundX(FastMath.toRadians(runningAngle + getNoise(r))).rotateAroundZ(FastMath.toRadians(getNoise(r))), + d1 - 1, recursions + 1, r); + growBranch(l1.clone().add(diff), diff.clone().multiply(0.75).rotateAroundX(FastMath.toRadians(-runningAngle + getNoise(r))).rotateAroundZ(FastMath.toRadians(getNoise(r))), + d1 - 1, recursions + 1, r); + growBranch(l1.clone().add(diff), diff.clone().multiply(0.75).rotateAroundZ(FastMath.toRadians(runningAngle + getNoise(r))).rotateAroundX(FastMath.toRadians(getNoise(r))), + d1 - 1, recursions + 1, r); + growBranch(l1.clone().add(diff), diff.clone().multiply(0.75).rotateAroundZ(FastMath.toRadians(-runningAngle + getNoise(r))).rotateAroundX(FastMath.toRadians(getNoise(r))), + d1 - 1, recursions + 1, r); + } + + private int getNoise(Random r) { + return r.nextInt(60) - 30; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/trees/ShatteredPillar.java b/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/trees/ShatteredPillar.java new file mode 100644 index 000000000..a1ceafdb5 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/trees/ShatteredPillar.java @@ -0,0 +1,56 @@ +package com.dfsek.terra.api.world.tree.fractal.trees; + +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.world.tree.fractal.FractalTree; +import com.dfsek.terra.util.MaterialSet; + +import java.util.Random; + +public class ShatteredPillar extends FractalTree { + + @Override + public MaterialSet getSpawnable() { + return MaterialSet.get(main.getWorldHandle().createMaterialData("minecraft:end_stone")); + } + + /** + * Instantiates a TreeGrower at an origin location. + */ + public ShatteredPillar(TerraPlugin main) { + super(main); + } + + /** + * Grows the tree in memory. Intended to be invoked from an async thread. + * @param origin + * @param random + */ + @Override + public void grow(Location origin, Random random) { + BlockData obsidian = getMain().getWorldHandle().createBlockData("minecraft:obsidian"); + int h = random.nextInt(5) + 8; + int max = h; + for(int i = -h; i < h; i++) setBlock(origin.clone().add(0, i, 0), obsidian); + h = h + (random.nextBoolean() ? random.nextInt(3) + 1 : -(random.nextInt(3) + 1)); + int[] crystalLoc = new int[] {0, 0}; + if(h > max) { + max = h; + crystalLoc = new int[] {1, 0}; + } + for(int i = -h; i < h; i++) setBlock(origin.clone().add(1, i, 0), obsidian); + h = h + (random.nextBoolean() ? random.nextInt(3) + 1 : -(random.nextInt(3) + 1)); + if(h > max) { + max = h; + crystalLoc = new int[] {0, 1}; + } + for(int i = -h; i < h; i++) setBlock(origin.clone().add(0, i, 1), obsidian); + h = h + (random.nextBoolean() ? random.nextInt(3) + 1 : -(random.nextInt(3) + 1)); + if(h > max) { + max = h; + crystalLoc = new int[] {1, 1}; + } + for(int i = -h; i < h; i++) setBlock(origin.clone().add(1, i, 1), obsidian); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/trees/ShatteredTree.java b/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/trees/ShatteredTree.java new file mode 100644 index 000000000..50839b746 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/trees/ShatteredTree.java @@ -0,0 +1,75 @@ +package com.dfsek.terra.api.world.tree.fractal.trees; + +import com.dfsek.terra.api.math.ProbabilityCollection; +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.math.vector.Vector3; +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.handle.WorldHandle; +import com.dfsek.terra.api.world.tree.fractal.FractalTree; +import com.dfsek.terra.api.world.tree.fractal.TreeGeometry; +import com.dfsek.terra.util.MaterialSet; +import net.jafama.FastMath; + +import java.util.Random; + +public class ShatteredTree extends FractalTree { + private final TreeGeometry geo; + private final ProbabilityCollection bark; + private final ProbabilityCollection leaves; + + @Override + public MaterialSet getSpawnable() { + return MaterialSet.get(main.getWorldHandle().createMaterialData("minecraft:end_stone")); + } + + /** + * Instantiates a TreeGrower at an origin location. + */ + public ShatteredTree(TerraPlugin main) { + super(main); + geo = new TreeGeometry(this); + WorldHandle handle = main.getWorldHandle(); + + bark = new ProbabilityCollection() + .add(handle.createBlockData("minecraft:obsidian"), 1) + .add(handle.createBlockData("minecraft:black_concrete"), 1); + leaves = new ProbabilityCollection() + .add(handle.createBlockData("minecraft:purple_stained_glass"), 1) + .add(handle.createBlockData("minecraft:magenta_stained_glass"), 1); + } + + /** + * Grows the tree in memory. Intended to be invoked from an async thread. + */ + @Override + public void grow(Location origin, Random random) { + growBranch(origin.clone(), new Vector3(random.nextInt(5) - 2, random.nextInt(4) + 6, random.nextInt(5) - 2), 1, 0, random); + + } + + private void growBranch(Location l1, Vector3 diff, double d1, int recursions, Random r) { + if(recursions > 2) { + geo.generateSphere(l1, leaves, 1 + r.nextInt(2), false); + return; + } + if(diff.getY() < 0) diff.rotateAroundAxis(TreeGeometry.getPerpendicular(diff.clone()).normalize(), FastMath.PI); + int d = (int) diff.length(); + for(int i = 0; i < d; i++) { + geo.generateSphere(l1.clone().add(diff.clone().multiply((double) i / d)), bark, FastMath.max((int) d1, 0), true); + } + double runningAngle = (double) 45 / (recursions + 1); + growBranch(l1.clone().add(diff), diff.clone().multiply(0.9).rotateAroundX(FastMath.toRadians(runningAngle + getNoise(r))).rotateAroundZ(FastMath.toRadians(getNoise(r))), + d1 - 1, recursions + 1, r); + growBranch(l1.clone().add(diff), diff.clone().multiply(0.9).rotateAroundX(FastMath.toRadians(-runningAngle + getNoise(r))).rotateAroundZ(FastMath.toRadians(getNoise(r))), + d1 - 1, recursions + 1, r); + growBranch(l1.clone().add(diff), diff.clone().multiply(0.9).rotateAroundZ(FastMath.toRadians(runningAngle + getNoise(r))).rotateAroundX(FastMath.toRadians(getNoise(r))), + d1 - 1, recursions + 1, r); + growBranch(l1.clone().add(diff), diff.clone().multiply(0.9).rotateAroundZ(FastMath.toRadians(-runningAngle + getNoise(r))).rotateAroundX(FastMath.toRadians(getNoise(r))), + d1 - 1, recursions + 1, r); + } + + private int getNoise(Random r) { + return r.nextInt(90) - 45; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/trees/SmallShatteredPillar.java b/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/trees/SmallShatteredPillar.java new file mode 100644 index 000000000..423a5ed7c --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/trees/SmallShatteredPillar.java @@ -0,0 +1,36 @@ +package com.dfsek.terra.api.world.tree.fractal.trees; + +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.world.tree.fractal.FractalTree; +import com.dfsek.terra.util.MaterialSet; + +import java.util.Random; + +public class SmallShatteredPillar extends FractalTree { + + @Override + public MaterialSet getSpawnable() { + return MaterialSet.get(main.getWorldHandle().createMaterialData("minecraft:end_stone")); + } + + /** + * Instantiates a TreeGrower at an origin location. + */ + public SmallShatteredPillar(TerraPlugin main) { + super(main); + } + + /** + * Grows the tree in memory. Intended to be invoked from an async thread. + * @param origin + * @param random + */ + @Override + public void grow(Location origin, Random random) { + int h = random.nextInt(5) + 5; + BlockData obsidian = getMain().getWorldHandle().createBlockData("minecraft:obsidian"); + for(int i = -h; i < h; i++) setBlock(origin.clone().add(0, i, 0), obsidian); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/trees/SmallShatteredTree.java b/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/trees/SmallShatteredTree.java new file mode 100644 index 000000000..50e681870 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/trees/SmallShatteredTree.java @@ -0,0 +1,75 @@ +package com.dfsek.terra.api.world.tree.fractal.trees; + +import com.dfsek.terra.api.math.ProbabilityCollection; +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.math.vector.Vector3; +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.handle.WorldHandle; +import com.dfsek.terra.api.world.tree.fractal.FractalTree; +import com.dfsek.terra.api.world.tree.fractal.TreeGeometry; +import com.dfsek.terra.util.MaterialSet; +import net.jafama.FastMath; + +import java.util.Random; + +public class SmallShatteredTree extends FractalTree { + private final TreeGeometry geo; + private final ProbabilityCollection bark; + private final ProbabilityCollection leaves; + + @Override + public MaterialSet getSpawnable() { + return MaterialSet.get(main.getWorldHandle().createMaterialData("minecraft:end_stone")); + } + + /** + * Instantiates a TreeGrower at an origin location. + */ + public SmallShatteredTree(TerraPlugin main) { + super(main); + geo = new TreeGeometry(this); + + WorldHandle handle = main.getWorldHandle(); + bark = new ProbabilityCollection() + .add(handle.createBlockData("minecraft:obsidian"), 1) + .add(handle.createBlockData("minecraft:black_concrete"), 1); + leaves = new ProbabilityCollection() + .add(handle.createBlockData("minecraft:purple_stained_glass"), 1) + .add(handle.createBlockData("minecraft:magenta_stained_glass"), 1); + } + + /** + * Grows the tree in memory. Intended to be invoked from an async thread. + */ + @Override + public void grow(Location origin, Random random) { + growBranch(origin.clone(), new Vector3(random.nextInt(5) - 2, random.nextInt(3) + 4, random.nextInt(5) - 2), 1.5, 0, random); + + } + + private void growBranch(Location l1, Vector3 diff, double d1, int recursions, Random r) { + if(recursions > 2) { + geo.generateSphere(l1, leaves, 1 + r.nextInt(2) + (3 - recursions), false); + return; + } + if(diff.getY() < 0) diff.rotateAroundAxis(TreeGeometry.getPerpendicular(diff.clone()).normalize(), FastMath.PI); + int d = (int) diff.length(); + for(int i = 0; i < d; i++) { + geo.generateSphere(l1.clone().add(diff.clone().multiply((double) i / d)), bark, FastMath.max((int) d1, 0), true); + } + double runningAngle = (double) 45 / (recursions + 1); + growBranch(l1.clone().add(diff), diff.clone().multiply(0.7).rotateAroundX(FastMath.toRadians(runningAngle + getNoise(r))).rotateAroundZ(FastMath.toRadians(getNoise(r))), + d1 - 1, recursions + 1, r); + growBranch(l1.clone().add(diff), diff.clone().multiply(0.7).rotateAroundX(FastMath.toRadians(-runningAngle + getNoise(r))).rotateAroundZ(FastMath.toRadians(getNoise(r))), + d1 - 1, recursions + 1, r); + growBranch(l1.clone().add(diff), diff.clone().multiply(0.7).rotateAroundZ(FastMath.toRadians(runningAngle + getNoise(r))).rotateAroundX(FastMath.toRadians(getNoise(r))), + d1 - 1, recursions + 1, r); + growBranch(l1.clone().add(diff), diff.clone().multiply(0.7).rotateAroundZ(FastMath.toRadians(-runningAngle + getNoise(r))).rotateAroundX(FastMath.toRadians(getNoise(r))), + d1 - 1, recursions + 1, r); + } + + private int getNoise(Random r) { + return r.nextInt(90) - 45; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/trees/SpruceTree.java b/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/trees/SpruceTree.java new file mode 100644 index 000000000..640cd6177 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/world/tree/fractal/trees/SpruceTree.java @@ -0,0 +1,53 @@ +package com.dfsek.terra.api.world.tree.fractal.trees; + +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.math.vector.Vector3; +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.world.tree.fractal.FractalTree; +import com.dfsek.terra.api.world.tree.fractal.TreeGeometry; +import com.dfsek.terra.util.MaterialSet; +import net.jafama.FastMath; + +import java.util.Random; + +public class SpruceTree extends FractalTree { + private final TreeGeometry geo; + + @Override + public MaterialSet getSpawnable() { + return MaterialSet.get(main.getWorldHandle().createMaterialData("minecraft:podzol"), + main.getWorldHandle().createMaterialData("minecraft:grass_block")); + } + + /** + * Instantiates a TreeGrower at an origin location. + */ + public SpruceTree(TerraPlugin main) { + super(main); + geo = new TreeGeometry(this); + } + + /** + * Grows the tree in memory. Intended to be invoked from an async thread. + */ + @Override + public void grow(Location origin, Random random) { + growTrunk(origin.clone(), new Vector3(0, 16 + random.nextInt(5), 0)); + } + + private void growTrunk(Location l1, Vector3 diff) { + if(diff.getY() < 0) diff.rotateAroundAxis(TreeGeometry.getPerpendicular(diff.clone()).normalize(), FastMath.PI); + int d = (int) diff.length(); + int rad = 7; + BlockData wood = getMain().getWorldHandle().createBlockData("minecraft:spruce_wood"); + BlockData leaves = getMain().getWorldHandle().createBlockData("minecraft:spruce_leave"); + for(int i = 0; i < d; i++) { + geo.generateSphere(l1.clone().add(diff.clone().multiply((double) i / d)), wood, (int) ((i > d * 0.65) ? 0.5 : 1.5), true); + if(i > 3) + geo.generateCylinder(l1.clone().add(diff.clone().multiply((double) i / d)), leaves, (int) (((6 - (i % 4))) * (1.25 - ((double) i / d))), 1, false); + } + setBlock(l1.clone().add(diff), leaves); + setBlock(l1.clone().add(diff).add(0, 1, 0), leaves); + } +} diff --git a/src/main/java/com/dfsek/terra/async/AsyncBiomeFinder.java b/common/src/main/java/com/dfsek/terra/async/AsyncBiomeFinder.java similarity index 74% rename from src/main/java/com/dfsek/terra/async/AsyncBiomeFinder.java rename to common/src/main/java/com/dfsek/terra/async/AsyncBiomeFinder.java index 7b03a5995..52f6fad9e 100644 --- a/src/main/java/com/dfsek/terra/async/AsyncBiomeFinder.java +++ b/common/src/main/java/com/dfsek/terra/async/AsyncBiomeFinder.java @@ -1,12 +1,12 @@ package com.dfsek.terra.async; -import com.dfsek.terra.Terra; +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.math.vector.Vector3; +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.world.biome.Biome; +import com.dfsek.terra.api.world.generation.GenerationPhase; import com.dfsek.terra.biome.grid.master.TerraBiomeGrid; -import org.bukkit.Location; -import org.bukkit.util.Vector; import org.jetbrains.annotations.NotNull; -import org.polydev.gaea.biome.Biome; -import org.polydev.gaea.generation.GenerationPhase; import java.util.function.Consumer; @@ -15,7 +15,7 @@ import java.util.function.Consumer; */ public class AsyncBiomeFinder extends AsyncFeatureFinder { - public AsyncBiomeFinder(TerraBiomeGrid grid, Biome target, @NotNull Location origin, int startRadius, int maxRadius, Consumer callback, Terra main) { + public AsyncBiomeFinder(TerraBiomeGrid grid, Biome target, @NotNull Location origin, int startRadius, int maxRadius, Consumer callback, TerraPlugin main) { super(grid, target, origin, startRadius, maxRadius, callback, main); } @@ -33,7 +33,7 @@ public class AsyncBiomeFinder extends AsyncFeatureFinder { } @Override - public Vector finalizeVector(Vector orig) { + public Vector3 finalizeVector(Vector3 orig) { return orig.multiply(main.getTerraConfig().getBiomeSearchResolution()); } } diff --git a/src/main/java/com/dfsek/terra/async/AsyncFeatureFinder.java b/common/src/main/java/com/dfsek/terra/async/AsyncFeatureFinder.java similarity index 81% rename from src/main/java/com/dfsek/terra/async/AsyncFeatureFinder.java rename to common/src/main/java/com/dfsek/terra/async/AsyncFeatureFinder.java index d26418bf5..c3c9f7941 100644 --- a/src/main/java/com/dfsek/terra/async/AsyncFeatureFinder.java +++ b/common/src/main/java/com/dfsek/terra/async/AsyncFeatureFinder.java @@ -1,11 +1,10 @@ package com.dfsek.terra.async; -import com.dfsek.terra.Terra; +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.math.vector.Vector3; +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.platform.world.World; import com.dfsek.terra.biome.grid.master.TerraBiomeGrid; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.World; -import org.bukkit.util.Vector; import org.jetbrains.annotations.NotNull; import java.util.function.Consumer; @@ -18,11 +17,11 @@ public abstract class AsyncFeatureFinder implements Runnable { protected final int centerX; protected final int centerZ; protected final World world; - private final Consumer callback; + private final Consumer callback; protected int searchSize = 1; - protected final Terra main; + protected final TerraPlugin main; - public AsyncFeatureFinder(TerraBiomeGrid grid, T target, @NotNull Location origin, int startRadius, int maxRadius, Consumer callback, Terra main) { + public AsyncFeatureFinder(TerraBiomeGrid grid, T target, @NotNull Location origin, int startRadius, int maxRadius, Consumer callback, TerraPlugin main) { this.grid = grid; this.target = target; this.main = main; @@ -67,12 +66,12 @@ public abstract class AsyncFeatureFinder implements Runnable { run++; toggle = !toggle; } - Vector finalSpawn = found ? finalizeVector(new Vector(x, 0, z)) : null; - Bukkit.getScheduler().runTask(main, () -> callback.accept(finalSpawn)); + Vector3 finalSpawn = found ? finalizeVector(new Vector3(x, 0, z)) : null; + callback.accept(finalSpawn); } - public abstract Vector finalizeVector(Vector orig); + public abstract Vector3 finalizeVector(Vector3 orig); public abstract boolean isValid(int x, int z, T target); diff --git a/common/src/main/java/com/dfsek/terra/async/AsyncStructureFinder.java b/common/src/main/java/com/dfsek/terra/async/AsyncStructureFinder.java new file mode 100644 index 000000000..74fc0418a --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/async/AsyncStructureFinder.java @@ -0,0 +1,36 @@ +package com.dfsek.terra.async; + +import com.dfsek.terra.api.math.MathUtil; +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.math.vector.Vector3; +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.structures.structure.Rotation; +import com.dfsek.terra.api.util.FastRandom; +import com.dfsek.terra.biome.UserDefinedBiome; +import com.dfsek.terra.biome.grid.master.TerraBiomeGrid; +import com.dfsek.terra.population.items.TerraStructure; +import net.jafama.FastMath; +import org.jetbrains.annotations.NotNull; + +import java.util.Random; +import java.util.function.Consumer; + +public class AsyncStructureFinder extends AsyncFeatureFinder { + public AsyncStructureFinder(TerraBiomeGrid grid, TerraStructure target, @NotNull Location origin, int startRadius, int maxRadius, Consumer callback, TerraPlugin main) { + super(grid, target, origin, startRadius, maxRadius, callback, main); + setSearchSize(target.getSpawn().getWidth() + 2 * target.getSpawn().getSeparation()); + } + + @Override + public Vector3 finalizeVector(Vector3 orig) { + return target.getSpawn().getChunkSpawn(orig.getBlockX(), orig.getBlockZ(), world.getSeed()); + } + + @Override + public boolean isValid(int x, int z, TerraStructure target) { + Location spawn = target.getSpawn().getChunkSpawn(x, z, world.getSeed()).toLocation(world); + if(!((UserDefinedBiome) grid.getBiome(spawn)).getConfig().getStructures().contains(target)) return false; + Random random = new FastRandom(MathUtil.getCarverChunkSeed(FastMath.floorDiv(spawn.getBlockX(), 16), FastMath.floorDiv(spawn.getBlockZ(), 16), world.getSeed())); + return target.getStructure().get(random).test(spawn.setY(target.getSpawnStart().get(random)), random, Rotation.fromDegrees(90 * random.nextInt(4))); + } +} diff --git a/src/main/java/com/dfsek/terra/biome/BiomeZone.java b/common/src/main/java/com/dfsek/terra/biome/BiomeZone.java similarity index 71% rename from src/main/java/com/dfsek/terra/biome/BiomeZone.java rename to common/src/main/java/com/dfsek/terra/biome/BiomeZone.java index a907599d2..294dc0b66 100644 --- a/src/main/java/com/dfsek/terra/biome/BiomeZone.java +++ b/common/src/main/java/com/dfsek/terra/biome/BiomeZone.java @@ -1,13 +1,12 @@ package com.dfsek.terra.biome; +import com.dfsek.terra.api.math.noise.samplers.FastNoiseLite; +import com.dfsek.terra.api.world.biome.BiomeGrid; +import com.dfsek.terra.api.world.biome.NormalizationUtil; import com.dfsek.terra.config.base.ConfigPack; import com.dfsek.terra.config.base.ConfigPackTemplate; import com.dfsek.terra.image.ImageLoader; -import org.bukkit.World; import org.jetbrains.annotations.Nullable; -import org.polydev.gaea.biome.BiomeGrid; -import org.polydev.gaea.biome.NormalizationUtil; -import org.polydev.gaea.math.FastNoiseLite; import java.util.Objects; @@ -22,13 +21,13 @@ public class BiomeZone { private final boolean useImage; private final ImageLoader.Channel channel; - public BiomeZone(World w, ConfigPack wc, BiomeGrid[] grids) { - this.noise = new FastNoiseLite((int) w.getSeed() + 2); + public BiomeZone(long seed, ConfigPack wc, BiomeGrid[] grids) { + this.noise = new FastNoiseLite((int) seed + 2); this.noise.setNoiseType(FastNoiseLite.NoiseType.OpenSimplex2); this.noise.setFractalType(FastNoiseLite.FractalType.FBm); this.noise.setFractalOctaves(4); ConfigPackTemplate t = wc.getTemplate(); - this.noise.setFrequency(1D / t.getZoneFreq()); + this.noise.setFrequency(1D / (t.getZoneFreq() * grids.length)); this.grids = grids; imageLoader = t.getImageLoader(); useImage = t.isFromImage(); @@ -43,7 +42,7 @@ public class BiomeZone { * @return BiomeGrid at coordinates. */ public BiomeGrid getGrid(int x, int z) { - return grids[NormalizationUtil.normalize(useImage ? Objects.requireNonNull(imageLoader).getNoiseVal(x, z, channel) : noise.getNoise(x, z), grids.length, 4)]; + return grids[getNoise(x, z)]; } /** @@ -63,7 +62,7 @@ public class BiomeZone { * @return Normalized noise at coordinates */ public int getNoise(int x, int z) { - return NormalizationUtil.normalize(useImage ? Objects.requireNonNull(imageLoader).getNoiseVal(x, z, channel) : noise.getNoise(x, z), grids.length, 4); + return useImage ? Objects.requireNonNull(imageLoader).getNoiseVal(x, z, getSize() - 1, channel) : NormalizationUtil.normalize(noise.getNoise(x, z), grids.length, 4); } /** @@ -74,6 +73,6 @@ public class BiomeZone { * @return Raw noise at coordinates */ public double getRawNoise(int x, int z) { - return useImage ? Objects.requireNonNull(imageLoader).getNoiseVal(x, z, channel) : noise.getNoise(x, z); + return useImage ? Objects.requireNonNull(imageLoader).getNoiseVal(x, z, getSize() - 1, channel) : noise.getNoise(x, z); } } diff --git a/common/src/main/java/com/dfsek/terra/biome/UserDefinedBiome.java b/common/src/main/java/com/dfsek/terra/biome/UserDefinedBiome.java new file mode 100644 index 000000000..8e6baac81 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/biome/UserDefinedBiome.java @@ -0,0 +1,61 @@ +package com.dfsek.terra.biome; + +import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.api.world.biome.Biome; +import com.dfsek.terra.api.world.biome.Generator; +import com.dfsek.terra.config.base.ConfigPack; +import com.dfsek.terra.config.builder.GeneratorBuilder; +import com.dfsek.terra.config.templates.BiomeTemplate; + +/** + * Class representing a config-defined biome + */ +public class UserDefinedBiome implements Biome { + private final GeneratorBuilder gen; + private final com.dfsek.terra.api.platform.world.Biome vanilla; + private final String id; + private final BiomeTemplate config; + private final ConfigPack pack; + private UserDefinedBiome erode; + + + public UserDefinedBiome(com.dfsek.terra.api.platform.world.Biome vanilla, GeneratorBuilder gen, BiomeTemplate config, ConfigPack pack) { + this.vanilla = vanilla; + this.gen = gen; + this.id = config.getID(); + this.config = config; + this.pack = pack; + } + + /** + * Gets the Vanilla biome to represent the custom biome. + * + * @return Biome - The Vanilla biome. + */ + @Override + public com.dfsek.terra.api.platform.world.Biome getVanillaBiome() { + return vanilla; + } + + + public String getID() { + return id; + } + + public UserDefinedBiome getErode() { + if(erode == null) { + erode = (config.getErode() == null) ? this : pack.getBiome(config.getErode()); + } + return erode; + } + + + public BiomeTemplate getConfig() { + return config; + } + + @Override + public Generator getGenerator(World w) { + return gen.build(w.getSeed()); + } +} diff --git a/src/main/java/com/dfsek/terra/biome/grid/SingleBiomeGrid.java b/common/src/main/java/com/dfsek/terra/biome/grid/SingleBiomeGrid.java similarity index 58% rename from src/main/java/com/dfsek/terra/biome/grid/SingleBiomeGrid.java rename to common/src/main/java/com/dfsek/terra/biome/grid/SingleBiomeGrid.java index 43219dbec..682bdff9b 100644 --- a/src/main/java/com/dfsek/terra/biome/grid/SingleBiomeGrid.java +++ b/common/src/main/java/com/dfsek/terra/biome/grid/SingleBiomeGrid.java @@ -1,10 +1,9 @@ package com.dfsek.terra.biome.grid; -import org.bukkit.Location; -import org.bukkit.World; -import org.polydev.gaea.biome.Biome; -import org.polydev.gaea.biome.BiomeGrid; -import org.polydev.gaea.generation.GenerationPhase; +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.world.biome.Biome; +import com.dfsek.terra.api.world.biome.BiomeGrid; +import com.dfsek.terra.api.world.generation.GenerationPhase; /** * BiomeGrid implementation that holds a single biome. @@ -12,8 +11,8 @@ import org.polydev.gaea.generation.GenerationPhase; public class SingleBiomeGrid extends BiomeGrid { private final Biome biome; - public SingleBiomeGrid(World w, Biome biome) { - super(w, 0, 0, 1, 1); + public SingleBiomeGrid(long seed, Biome biome) { + super(seed, 0, 0, 1, 1); this.biome = biome; } diff --git a/src/main/java/com/dfsek/terra/biome/grid/UserDefinedGrid.java b/common/src/main/java/com/dfsek/terra/biome/grid/UserDefinedGrid.java similarity index 60% rename from src/main/java/com/dfsek/terra/biome/grid/UserDefinedGrid.java rename to common/src/main/java/com/dfsek/terra/biome/grid/UserDefinedGrid.java index c2404cc68..e51996e70 100644 --- a/src/main/java/com/dfsek/terra/biome/grid/UserDefinedGrid.java +++ b/common/src/main/java/com/dfsek/terra/biome/grid/UserDefinedGrid.java @@ -1,14 +1,12 @@ package com.dfsek.terra.biome.grid; +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.world.biome.Biome; +import com.dfsek.terra.api.world.biome.BiomeGrid; +import com.dfsek.terra.api.world.generation.GenerationPhase; import com.dfsek.terra.config.base.ConfigPack; import com.dfsek.terra.config.base.ConfigPackTemplate; import com.dfsek.terra.image.ImageLoader; -import org.bukkit.Location; -import org.bukkit.World; -import org.polydev.gaea.biome.Biome; -import org.polydev.gaea.biome.BiomeGrid; -import org.polydev.gaea.biome.NormalizationUtil; -import org.polydev.gaea.generation.GenerationPhase; public class UserDefinedGrid extends BiomeGrid { private final ImageLoader imageLoader; @@ -16,8 +14,8 @@ public class UserDefinedGrid extends BiomeGrid { private final ImageLoader.Channel channelX; private final ImageLoader.Channel channelZ; - public UserDefinedGrid(World w, double freq1, double freq2, Biome[][] b, ConfigPack c) { - super(w, freq1, freq2, b.length, b[0].length); + public UserDefinedGrid(long seed, double freq1, double freq2, Biome[][] b, ConfigPack c) { + super(seed, freq1, freq2, b.length, b[0].length); super.setGrid(b); ConfigPackTemplate t = c.getTemplate(); imageLoader = t.getImageLoader(); @@ -29,9 +27,9 @@ public class UserDefinedGrid extends BiomeGrid { @Override public Biome getBiome(int x, int z, GenerationPhase phase) { if(fromImage) { - double xi = imageLoader.getNoiseVal(x, z, channelX); - double zi = imageLoader.getNoiseVal(x, z, channelZ); - return super.getGrid()[NormalizationUtil.normalize(xi, getSizeX(), 4)][NormalizationUtil.normalize(zi, getSizeZ(), 4)]; + int xi = imageLoader.getNoiseVal(x, z, getSizeX() - 1, channelX); + int zi = imageLoader.getNoiseVal(x, z, getSizeZ() - 1, channelZ); + return super.getGrid()[xi][zi]; } return super.getBiome(x, z, phase); } diff --git a/common/src/main/java/com/dfsek/terra/biome/grid/master/TerraBiomeGrid.java b/common/src/main/java/com/dfsek/terra/biome/grid/master/TerraBiomeGrid.java new file mode 100644 index 000000000..a0fec53ec --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/biome/grid/master/TerraBiomeGrid.java @@ -0,0 +1,71 @@ +package com.dfsek.terra.biome.grid.master; + +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.world.biome.BiomeGrid; +import com.dfsek.terra.biome.BiomeZone; +import com.dfsek.terra.biome.grid.UserDefinedGrid; +import com.dfsek.terra.config.base.ConfigPack; +import com.dfsek.terra.config.base.ConfigPackTemplate; +import com.dfsek.terra.config.builder.biomegrid.BiomeGridBuilder; +import com.dfsek.terra.debug.Debug; + +public abstract class TerraBiomeGrid extends BiomeGrid { + protected final BiomeZone zone; + + public TerraBiomeGrid(long seed, int sizeX, int sizeZ, BiomeZone zone) { + super(seed, 0, 0, sizeX, sizeZ); + this.zone = zone; + } + + public BiomeZone getZone() { + return zone; + } + + public abstract UserDefinedGrid getGrid(int x, int z); + + public enum Type { + RADIAL, STANDARD + } + + public abstract boolean isEroded(int x, int z); + + public static final class TerraBiomeGridBuilder { + private final long seed; + private final ConfigPack config; + private final TerraPlugin main; + + public TerraBiomeGridBuilder(long seed, ConfigPack config, TerraPlugin main) { + this.seed = seed; + this.config = config; + this.main = main; + } + + public TerraBiomeGrid build() { + ConfigPackTemplate template = config.getTemplate(); + + int zoneSize = template.getGrids().size(); + + BiomeGrid[] definedGrids = new BiomeGrid[zoneSize]; + for(int i = 0; i < zoneSize; i++) { + String partName = template.getGrids().get(i); + try { + BiomeGridBuilder g = config.getBiomeGrid(partName); + BiomeGrid b = g.build(seed, config); + definedGrids[i] = b; + } catch(NullPointerException e) { + Debug.stack(e); + main.getLogger().severe("No such BiomeGrid " + partName); + main.getLogger().severe("Please check configuration files for errors. Configuration errors will have been reported during initialization."); + main.getLogger().severe("ONLY report this to Terra if you are SURE your config is error-free."); + main.getLogger().severe("Terrain will NOT generate properly at this point. Correct your config before using your server!"); + } + } + BiomeZone zone = new BiomeZone(seed, config, definedGrids); + + if(template.getGridType().equals(TerraBiomeGrid.Type.RADIAL)) { + BiomeGrid internal = config.getBiomeGrid(template.getRadialInternalGrid()).build(seed, config); + return new TerraRadialBiomeGrid(seed, zone, config, template.getRadialGridRadius(), internal); + } else return new TerraStandardBiomeGrid(seed, zone, config); + } + } +} diff --git a/src/main/java/com/dfsek/terra/biome/grid/master/TerraRadialBiomeGrid.java b/common/src/main/java/com/dfsek/terra/biome/grid/master/TerraRadialBiomeGrid.java similarity index 74% rename from src/main/java/com/dfsek/terra/biome/grid/master/TerraRadialBiomeGrid.java rename to common/src/main/java/com/dfsek/terra/biome/grid/master/TerraRadialBiomeGrid.java index 85fbc414a..4bd66f86b 100644 --- a/src/main/java/com/dfsek/terra/biome/grid/master/TerraRadialBiomeGrid.java +++ b/common/src/main/java/com/dfsek/terra/biome/grid/master/TerraRadialBiomeGrid.java @@ -1,5 +1,10 @@ package com.dfsek.terra.biome.grid.master; +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.math.vector.Vector2; +import com.dfsek.terra.api.world.biome.Biome; +import com.dfsek.terra.api.world.biome.BiomeGrid; +import com.dfsek.terra.api.world.generation.GenerationPhase; import com.dfsek.terra.biome.BiomeZone; import com.dfsek.terra.biome.UserDefinedBiome; import com.dfsek.terra.biome.grid.UserDefinedGrid; @@ -7,31 +12,22 @@ import com.dfsek.terra.biome.postprocessing.CoordinatePerturb; import com.dfsek.terra.biome.postprocessing.ErosionNoise; import com.dfsek.terra.config.base.ConfigPack; import com.dfsek.terra.config.base.ConfigPackTemplate; -import com.dfsek.terra.procgen.math.Vector2; import net.jafama.FastMath; -import org.bukkit.Location; -import org.bukkit.World; -import org.polydev.gaea.biome.Biome; -import org.polydev.gaea.biome.BiomeGrid; -import org.polydev.gaea.generation.GenerationPhase; public class TerraRadialBiomeGrid extends TerraBiomeGrid { - private static final int failNum = 0; - private final BiomeZone zone; private final double radiusSq; private final BiomeGrid internal; private CoordinatePerturb perturb; private ErosionNoise erode; - public TerraRadialBiomeGrid(World w, double freq1, double freq2, BiomeZone zone, ConfigPack c, double radius, BiomeGrid internal) { - super(w, freq1, freq2, 0, 0); + public TerraRadialBiomeGrid(long seed, BiomeZone zone, ConfigPack c, double radius, BiomeGrid internal) { + super(seed, 0, 0, zone); ConfigPackTemplate t = c.getTemplate(); if(c.getTemplate().isBlend()) { - perturb = new CoordinatePerturb(t.getBlendFreq(), t.getBlendAmp(), w.getSeed()); + perturb = new CoordinatePerturb(t.getBlendFreq(), t.getBlendAmp(), seed); } - this.zone = zone; if(c.getTemplate().isErode()) { - erode = new ErosionNoise(t.getErodeFreq(), t.getErodeThresh(), t.getErodeOctaves(), w.getSeed()); + erode = new ErosionNoise(t.getErodeFreq(), t.getErodeThresh(), t.getErodeOctaves(), seed); } this.radiusSq = FastMath.pow2(radius); this.internal = internal; @@ -42,6 +38,11 @@ public class TerraRadialBiomeGrid extends TerraBiomeGrid { return (UserDefinedGrid) zone.getGrid(x, z); } + @Override + public boolean isEroded(int x, int z) { + return erode != null && erode.isEroded(x, z); + } + @Override public Biome getBiome(int x, int z, GenerationPhase phase) { int xp = x, zp = z; @@ -57,7 +58,7 @@ public class TerraRadialBiomeGrid extends TerraBiomeGrid { } else { b = (UserDefinedBiome) internal.getBiome(xp, zp, phase); } - if(erode != null && erode.isEroded(xp, zp)) return b.getErode(); + if(isEroded(xp, zp)) return b.getErode(); return b; } diff --git a/src/main/java/com/dfsek/terra/biome/grid/master/TerraStandardBiomeGrid.java b/common/src/main/java/com/dfsek/terra/biome/grid/master/TerraStandardBiomeGrid.java similarity index 73% rename from src/main/java/com/dfsek/terra/biome/grid/master/TerraStandardBiomeGrid.java rename to common/src/main/java/com/dfsek/terra/biome/grid/master/TerraStandardBiomeGrid.java index 3ade9babf..e17e88fbb 100644 --- a/src/main/java/com/dfsek/terra/biome/grid/master/TerraStandardBiomeGrid.java +++ b/common/src/main/java/com/dfsek/terra/biome/grid/master/TerraStandardBiomeGrid.java @@ -1,5 +1,9 @@ package com.dfsek.terra.biome.grid.master; +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.math.vector.Vector2; +import com.dfsek.terra.api.world.biome.Biome; +import com.dfsek.terra.api.world.generation.GenerationPhase; import com.dfsek.terra.biome.BiomeZone; import com.dfsek.terra.biome.UserDefinedBiome; import com.dfsek.terra.biome.grid.UserDefinedGrid; @@ -7,27 +11,19 @@ import com.dfsek.terra.biome.postprocessing.CoordinatePerturb; import com.dfsek.terra.biome.postprocessing.ErosionNoise; import com.dfsek.terra.config.base.ConfigPack; import com.dfsek.terra.config.base.ConfigPackTemplate; -import com.dfsek.terra.procgen.math.Vector2; -import org.bukkit.Location; -import org.bukkit.World; -import org.polydev.gaea.biome.Biome; -import org.polydev.gaea.generation.GenerationPhase; public class TerraStandardBiomeGrid extends TerraBiomeGrid { - private static final int failNum = 0; - private final BiomeZone zone; private CoordinatePerturb perturb; private ErosionNoise erode; - public TerraStandardBiomeGrid(World w, double freq1, double freq2, BiomeZone zone, ConfigPack c) { - super(w, freq1, freq2, 0, 0); + public TerraStandardBiomeGrid(long seed, BiomeZone zone, ConfigPack c) { + super(seed, 0, 0, zone); ConfigPackTemplate t = c.getTemplate(); if(c.getTemplate().isBlend()) { - perturb = new CoordinatePerturb(t.getBlendFreq(), t.getBlendAmp(), w.getSeed()); + perturb = new CoordinatePerturb(t.getBlendFreq(), t.getBlendAmp(), seed); } - this.zone = zone; if(c.getTemplate().isErode()) { - erode = new ErosionNoise(t.getErodeFreq(), t.getErodeThresh(), t.getErodeOctaves(), w.getSeed()); + erode = new ErosionNoise(t.getErodeFreq(), t.getErodeThresh(), t.getErodeOctaves(), seed); } } @@ -36,6 +32,11 @@ public class TerraStandardBiomeGrid extends TerraBiomeGrid { return (UserDefinedGrid) zone.getGrid(x, z); } + @Override + public boolean isEroded(int x, int z) { + return erode != null && erode.isEroded(x, z); + } + @Override public Biome getBiome(int x, int z, GenerationPhase phase) { int xp = x, zp = z; @@ -46,10 +47,11 @@ public class TerraStandardBiomeGrid extends TerraBiomeGrid { } UserDefinedBiome b = (UserDefinedBiome) zone.getGrid(xp, zp).getBiome(xp, zp, phase); - if(erode != null && erode.isEroded(xp, zp)) return b.getErode(); + if(isEroded(xp, zp)) return b.getErode(); return b; } + @Override public Biome getBiome(Location l, GenerationPhase phase) { return getBiome(l.getBlockX(), l.getBlockZ(), phase); diff --git a/src/main/java/com/dfsek/terra/biome/palette/PaletteHolder.java b/common/src/main/java/com/dfsek/terra/biome/palette/PaletteHolder.java similarity index 74% rename from src/main/java/com/dfsek/terra/biome/palette/PaletteHolder.java rename to common/src/main/java/com/dfsek/terra/biome/palette/PaletteHolder.java index 3dd6cf88d..27a86a10e 100644 --- a/src/main/java/com/dfsek/terra/biome/palette/PaletteHolder.java +++ b/common/src/main/java/com/dfsek/terra/biome/palette/PaletteHolder.java @@ -1,7 +1,7 @@ package com.dfsek.terra.biome.palette; -import org.bukkit.block.data.BlockData; -import org.polydev.gaea.world.palette.Palette; +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.world.palette.Palette; public class PaletteHolder { private final Palette[] palettes; diff --git a/src/main/java/com/dfsek/terra/biome/palette/PaletteHolderBuilder.java b/common/src/main/java/com/dfsek/terra/biome/palette/PaletteHolderBuilder.java similarity index 80% rename from src/main/java/com/dfsek/terra/biome/palette/PaletteHolderBuilder.java rename to common/src/main/java/com/dfsek/terra/biome/palette/PaletteHolderBuilder.java index ee5b20b02..f615b1edd 100644 --- a/src/main/java/com/dfsek/terra/biome/palette/PaletteHolderBuilder.java +++ b/common/src/main/java/com/dfsek/terra/biome/palette/PaletteHolderBuilder.java @@ -1,9 +1,8 @@ package com.dfsek.terra.biome.palette; -import com.dfsek.terra.util.PaletteUtil; +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.world.palette.Palette; import net.jafama.FastMath; -import org.bukkit.block.data.BlockData; -import org.polydev.gaea.world.palette.Palette; import java.util.Map; import java.util.TreeMap; @@ -20,13 +19,14 @@ public class PaletteHolderBuilder { public PaletteHolder build() { Palette[] palettes = new Palette[paletteMap.lastKey() + 1]; for(int y = 0; y <= FastMath.max(paletteMap.lastKey(), 255); y++) { - Palette d = PaletteUtil.BLANK_PALETTE; + Palette d = null; for(Map.Entry> e : paletteMap.entrySet()) { if(e.getKey() >= y) { d = e.getValue(); break; } } + if(d == null) throw new IllegalArgumentException("No palette for Y=" + y); palettes[y] = d; } return new PaletteHolder(palettes); diff --git a/src/main/java/com/dfsek/terra/biome/palette/PaletteLayer.java b/common/src/main/java/com/dfsek/terra/biome/palette/PaletteLayer.java similarity index 82% rename from src/main/java/com/dfsek/terra/biome/palette/PaletteLayer.java rename to common/src/main/java/com/dfsek/terra/biome/palette/PaletteLayer.java index 21a57e049..56953b1b2 100644 --- a/src/main/java/com/dfsek/terra/biome/palette/PaletteLayer.java +++ b/common/src/main/java/com/dfsek/terra/biome/palette/PaletteLayer.java @@ -1,8 +1,8 @@ package com.dfsek.terra.biome.palette; -import org.bukkit.block.data.BlockData; +import com.dfsek.terra.api.math.ProbabilityCollection; +import com.dfsek.terra.api.platform.block.BlockData; import org.jetbrains.annotations.NotNull; -import org.polydev.gaea.math.ProbabilityCollection; public class PaletteLayer { private final ProbabilityCollection layer; diff --git a/src/main/java/com/dfsek/terra/biome/palette/SinglePalette.java b/common/src/main/java/com/dfsek/terra/biome/palette/SinglePalette.java similarity index 84% rename from src/main/java/com/dfsek/terra/biome/palette/SinglePalette.java rename to common/src/main/java/com/dfsek/terra/biome/palette/SinglePalette.java index cb6ad3ca3..76e01281e 100644 --- a/src/main/java/com/dfsek/terra/biome/palette/SinglePalette.java +++ b/common/src/main/java/com/dfsek/terra/biome/palette/SinglePalette.java @@ -1,6 +1,6 @@ package com.dfsek.terra.biome.palette; -import org.polydev.gaea.world.palette.Palette; +import com.dfsek.terra.api.world.palette.Palette; public class SinglePalette extends Palette { private final E item; diff --git a/src/main/java/com/dfsek/terra/biome/postprocessing/CoordinatePerturb.java b/common/src/main/java/com/dfsek/terra/biome/postprocessing/CoordinatePerturb.java similarity index 91% rename from src/main/java/com/dfsek/terra/biome/postprocessing/CoordinatePerturb.java rename to common/src/main/java/com/dfsek/terra/biome/postprocessing/CoordinatePerturb.java index 334caefea..2dfb066ed 100644 --- a/src/main/java/com/dfsek/terra/biome/postprocessing/CoordinatePerturb.java +++ b/common/src/main/java/com/dfsek/terra/biome/postprocessing/CoordinatePerturb.java @@ -1,7 +1,7 @@ package com.dfsek.terra.biome.postprocessing; -import com.dfsek.terra.procgen.math.Vector2; -import org.polydev.gaea.math.FastNoiseLite; +import com.dfsek.terra.api.math.noise.samplers.FastNoiseLite; +import com.dfsek.terra.api.math.vector.Vector2; /** * Offset a coordinate pair by an amount. diff --git a/src/main/java/com/dfsek/terra/biome/postprocessing/ErosionNoise.java b/common/src/main/java/com/dfsek/terra/biome/postprocessing/ErosionNoise.java similarity index 85% rename from src/main/java/com/dfsek/terra/biome/postprocessing/ErosionNoise.java rename to common/src/main/java/com/dfsek/terra/biome/postprocessing/ErosionNoise.java index 3202dde91..fce056c9f 100644 --- a/src/main/java/com/dfsek/terra/biome/postprocessing/ErosionNoise.java +++ b/common/src/main/java/com/dfsek/terra/biome/postprocessing/ErosionNoise.java @@ -1,14 +1,15 @@ package com.dfsek.terra.biome.postprocessing; +import com.dfsek.terra.api.math.noise.samplers.FastNoiseLite; +import com.dfsek.terra.api.math.noise.samplers.NoiseSampler; import net.jafama.FastMath; -import org.polydev.gaea.math.FastNoiseLite; /** * Class to hold noise function to determine erosion. */ public class ErosionNoise { private final double thresh; - private final FastNoiseLite noise; + private final NoiseSampler noise; public ErosionNoise(double freq1, double thresh, int octaves, long seed) { FastNoiseLite main = new FastNoiseLite((int) (seed + 1)); diff --git a/common/src/main/java/com/dfsek/terra/carving/CarverCache.java b/common/src/main/java/com/dfsek/terra/carving/CarverCache.java new file mode 100644 index 000000000..e48fc08f7 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/carving/CarverCache.java @@ -0,0 +1,62 @@ +package com.dfsek.terra.carving; + +import com.dfsek.terra.api.math.MathUtil; +import com.dfsek.terra.api.math.vector.Vector3; +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.api.util.FastRandom; +import com.dfsek.terra.api.util.GlueList; +import com.dfsek.terra.api.world.biome.Biome; +import com.dfsek.terra.api.world.carving.Worm; +import com.dfsek.terra.api.world.generation.GenerationPhase; +import com.dfsek.terra.biome.UserDefinedBiome; +import com.dfsek.terra.biome.grid.master.TerraBiomeGrid; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; + +public class CarverCache { + + private final World w; + private final Map> carvers; + private final TerraPlugin main; + + public CarverCache(World w, TerraPlugin main) { + this.w = w; + this.main = main; + carvers = Collections.synchronizedMap(new LinkedHashMap>() { + @Override + protected boolean removeEldestEntry(Map.Entry eldest) { + return this.size() > main.getTerraConfig().getCarverCacheSize(); + } + }); + } + + public List getPoints(int chunkX, int chunkZ, UserDefinedCarver carver) { + synchronized(carvers) { + return carvers.computeIfAbsent(MathUtil.squash(chunkX, chunkZ), key -> { + TerraBiomeGrid grid = main.getWorld(w).getGrid(); + if(carver.isChunkCarved(w, chunkX, chunkZ, new FastRandom(MathUtil.getCarverChunkSeed(chunkX, chunkZ, w.getSeed() + carver.hashCode())))) { + long seed = MathUtil.getCarverChunkSeed(chunkX, chunkZ, w.getSeed()); + carver.getSeedVar().setValue(seed); + Random r = new FastRandom(seed); + Worm carving = carver.getWorm(seed, new Vector3((chunkX << 4) + r.nextInt(16), carver.getConfig().getHeight().get(r), (chunkZ << 4) + r.nextInt(16))); + List points = new GlueList<>(); + for(int i = 0; i < carving.getLength(); i++) { + carving.step(); + Biome biome = grid.getBiome(carving.getRunning().toLocation(w), GenerationPhase.POPULATE); + if(!((UserDefinedBiome) biome).getConfig().getCarvers().containsKey(carver)) { // Stop if we enter a biome this carver is not present in + return new GlueList<>(); + } + points.add(carving.getPoint()); + } + return points; + } + return new GlueList<>(); + }); + } + } +} diff --git a/src/main/java/com/dfsek/terra/carving/CarverPalette.java b/common/src/main/java/com/dfsek/terra/carving/CarverPalette.java similarity index 78% rename from src/main/java/com/dfsek/terra/carving/CarverPalette.java rename to common/src/main/java/com/dfsek/terra/carving/CarverPalette.java index bc6001104..249c36957 100644 --- a/src/main/java/com/dfsek/terra/carving/CarverPalette.java +++ b/common/src/main/java/com/dfsek/terra/carving/CarverPalette.java @@ -1,9 +1,9 @@ package com.dfsek.terra.carving; +import com.dfsek.terra.api.math.ProbabilityCollection; +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.block.MaterialData; import com.dfsek.terra.util.MaterialSet; -import org.bukkit.Material; -import org.bukkit.block.data.BlockData; -import org.polydev.gaea.math.ProbabilityCollection; import java.util.Map; import java.util.TreeMap; @@ -29,7 +29,7 @@ public class CarverPalette { return layers[y]; } - public boolean canReplace(Material material) { + public boolean canReplace(MaterialData material) { return blacklist != replace.contains(material); } @@ -40,13 +40,14 @@ public class CarverPalette { int size = map.lastKey() + 1; layers = new ProbabilityCollection[size]; for(int y = 0; y < size; y++) { - ProbabilityCollection d = new ProbabilityCollection().add(Material.AIR.createBlockData(), 1); // Blank layer + ProbabilityCollection d = null; for(Map.Entry> e : map.entrySet()) { if(e.getKey() >= y) { d = e.getValue(); break; } } + if(d == null) throw new IllegalArgumentException("Null collection at Y=" + y); layers[y] = d; } } diff --git a/src/main/java/com/dfsek/terra/carving/UserDefinedCarver.java b/common/src/main/java/com/dfsek/terra/carving/UserDefinedCarver.java similarity index 85% rename from src/main/java/com/dfsek/terra/carving/UserDefinedCarver.java rename to common/src/main/java/com/dfsek/terra/carving/UserDefinedCarver.java index 83977a9b4..0f6e6c840 100644 --- a/src/main/java/com/dfsek/terra/carving/UserDefinedCarver.java +++ b/common/src/main/java/com/dfsek/terra/carving/UserDefinedCarver.java @@ -1,18 +1,18 @@ package com.dfsek.terra.carving; -import com.dfsek.terra.Terra; +import com.dfsek.terra.api.math.Range; +import com.dfsek.terra.api.math.parsii.RandomFunction; +import com.dfsek.terra.api.math.vector.Vector3; +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.api.util.FastRandom; +import com.dfsek.terra.api.world.carving.Carver; +import com.dfsek.terra.api.world.carving.Worm; +import com.dfsek.terra.api.world.generation.GenerationPhase; import com.dfsek.terra.biome.UserDefinedBiome; import com.dfsek.terra.config.templates.BiomeTemplate; import com.dfsek.terra.config.templates.CarverTemplate; -import com.dfsek.terra.math.RandomFunction; import net.jafama.FastMath; -import org.bukkit.World; -import org.bukkit.util.Vector; -import org.polydev.gaea.generation.GenerationPhase; -import org.polydev.gaea.math.Range; -import org.polydev.gaea.util.FastRandom; -import org.polydev.gaea.world.carving.Carver; -import org.polydev.gaea.world.carving.Worm; import parsii.eval.Expression; import parsii.eval.Parser; import parsii.eval.Scope; @@ -43,9 +43,9 @@ public class UserDefinedCarver extends Carver { private double step = 2; private Range recalc = new Range(8, 10); private double recalcMagnitude = 3; - private final Terra main; + private final TerraPlugin main; - public UserDefinedCarver(Range height, Range length, double[] start, double[] mutate, List radii, Scope parent, long hash, int topCut, int bottomCut, CarverTemplate config, Terra main) throws ParseException { + public UserDefinedCarver(Range height, Range length, double[] start, double[] mutate, List radii, Scope parent, long hash, int topCut, int bottomCut, CarverTemplate config, TerraPlugin main) throws ParseException { super(height.getMin(), height.getMax()); this.length = length; this.start = start; @@ -74,7 +74,7 @@ public class UserDefinedCarver extends Carver { } @Override - public Worm getWorm(long l, Vector vector) { + public Worm getWorm(long l, Vector3 vector) { Random r = new FastRandom(l + hash); return new UserDefinedWorm(length.get(r) / 2, r, vector, topCut, bottomCut); } @@ -100,13 +100,13 @@ public class UserDefinedCarver extends Carver { } @Override - public void carve(int chunkX, int chunkZ, World w, BiConsumer consumer) { + public void carve(int chunkX, int chunkZ, World w, BiConsumer consumer) { CarverCache cache = cacheMap.computeIfAbsent(w, world -> new CarverCache(world, main)); int carvingRadius = getCarvingRadius(); for(int x = chunkX - carvingRadius; x <= chunkX + carvingRadius; x++) { for(int z = chunkZ - carvingRadius; z <= chunkZ + carvingRadius; z++) { cache.getPoints(x, z, this).forEach(point -> { - Vector origin = point.getOrigin(); + Vector3 origin = point.getOrigin(); if(FastMath.floorDiv(origin.getBlockX(), 16) != chunkX && FastMath.floorDiv(origin.getBlockZ(), 16) != chunkZ) // We only want to carve this chunk. return; point.carve(chunkX, chunkZ, consumer); @@ -133,16 +133,16 @@ public class UserDefinedCarver extends Carver { } private class UserDefinedWorm extends Worm { - private final Vector direction; + private final Vector3 direction; private int steps; private int nextDirection = 0; private double[] currentRotation = new double[3]; - public UserDefinedWorm(int length, Random r, Vector origin, int topCut, int bottomCut) { + public UserDefinedWorm(int length, Random r, Vector3 origin, int topCut, int bottomCut) { super(length, r, origin); super.setTopCut(topCut); super.setBottomCut(bottomCut); - direction = new Vector((r.nextDouble() - 0.5D) * start[0], (r.nextDouble() - 0.5D) * start[1], (r.nextDouble() - 0.5D) * start[2]).normalize().multiply(step); + direction = new Vector3((r.nextDouble() - 0.5D) * start[0], (r.nextDouble() - 0.5D) * start[1], (r.nextDouble() - 0.5D) * start[2]).normalize().multiply(step); position.setValue(0); lengthVar.setValue(length); setRadius(new int[] {(int) (xRad.evaluate()), (int) (yRad.evaluate()), (int) (zRad.evaluate())}); diff --git a/src/main/java/com/dfsek/terra/config/base/ConfigPack.java b/common/src/main/java/com/dfsek/terra/config/base/ConfigPack.java similarity index 58% rename from src/main/java/com/dfsek/terra/config/base/ConfigPack.java rename to common/src/main/java/com/dfsek/terra/config/base/ConfigPack.java index c0e53e82d..e7df3880f 100644 --- a/src/main/java/com/dfsek/terra/config/base/ConfigPack.java +++ b/common/src/main/java/com/dfsek/terra/config/base/ConfigPack.java @@ -4,7 +4,15 @@ import com.dfsek.tectonic.abstraction.AbstractConfigLoader; import com.dfsek.tectonic.exception.ConfigException; import com.dfsek.tectonic.exception.LoadException; import com.dfsek.tectonic.loading.ConfigLoader; -import com.dfsek.terra.Terra; +import com.dfsek.tectonic.loading.TypeRegistry; +import com.dfsek.terra.api.LoaderRegistrar; +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.structures.loot.LootTable; +import com.dfsek.terra.api.structures.script.StructureScript; +import com.dfsek.terra.api.world.biome.Biome; +import com.dfsek.terra.api.world.flora.Flora; +import com.dfsek.terra.api.world.palette.Palette; +import com.dfsek.terra.api.world.tree.Tree; import com.dfsek.terra.biome.UserDefinedBiome; import com.dfsek.terra.biome.grid.master.TerraBiomeGrid; import com.dfsek.terra.carving.UserDefinedCarver; @@ -23,8 +31,6 @@ import com.dfsek.terra.config.files.FolderLoader; import com.dfsek.terra.config.files.Loader; import com.dfsek.terra.config.files.ZIPLoader; import com.dfsek.terra.config.lang.LangUtil; -import com.dfsek.terra.config.loaders.LootTableLoader; -import com.dfsek.terra.config.loaders.StructureLoader; import com.dfsek.terra.config.templates.AbstractableTemplate; import com.dfsek.terra.config.templates.BiomeGridTemplate; import com.dfsek.terra.config.templates.BiomeTemplate; @@ -34,24 +40,22 @@ import com.dfsek.terra.config.templates.OreTemplate; import com.dfsek.terra.config.templates.PaletteTemplate; import com.dfsek.terra.config.templates.StructureTemplate; import com.dfsek.terra.config.templates.TreeTemplate; -import com.dfsek.terra.generation.items.TerraStructure; -import com.dfsek.terra.generation.items.ores.Ore; +import com.dfsek.terra.generation.math.SamplerCache; +import com.dfsek.terra.population.items.TerraStructure; +import com.dfsek.terra.population.items.ores.Ore; import com.dfsek.terra.registry.BiomeGridRegistry; import com.dfsek.terra.registry.BiomeRegistry; import com.dfsek.terra.registry.CarverRegistry; import com.dfsek.terra.registry.FloraRegistry; +import com.dfsek.terra.registry.LootRegistry; import com.dfsek.terra.registry.OreRegistry; import com.dfsek.terra.registry.PaletteRegistry; +import com.dfsek.terra.registry.ScriptRegistry; import com.dfsek.terra.registry.StructureRegistry; import com.dfsek.terra.registry.TerraRegistry; import com.dfsek.terra.registry.TreeRegistry; -import com.dfsek.terra.structure.Structure; -import com.dfsek.terra.util.StructureTypeEnum; -import org.polydev.gaea.biome.Biome; -import org.polydev.gaea.structures.loot.LootTable; -import org.polydev.gaea.tree.Tree; -import org.polydev.gaea.world.Flora; -import org.polydev.gaea.world.palette.Palette; +import org.apache.commons.io.IOUtils; +import org.json.simple.parser.ParseException; import parsii.eval.Scope; import java.io.File; @@ -59,10 +63,10 @@ import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collection; import java.util.Enumeration; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; @@ -74,39 +78,37 @@ import java.util.zip.ZipFile; /** * Represents a Terra configuration pack. */ -public class ConfigPack { +public class ConfigPack implements LoaderRegistrar { private final ConfigPackTemplate template = new ConfigPackTemplate(); + private final BiomeRegistry biomeRegistry = new BiomeRegistry(); private final BiomeGridRegistry biomeGridRegistry = new BiomeGridRegistry(biomeRegistry); private final StructureRegistry structureRegistry = new StructureRegistry(); private final CarverRegistry carverRegistry = new CarverRegistry(); - private final PaletteRegistry paletteRegistry = new PaletteRegistry(); - private final FloraRegistry floraRegistry = new FloraRegistry(); + private final PaletteRegistry paletteRegistry; + private final FloraRegistry floraRegistry; private final OreRegistry oreRegistry = new OreRegistry(); - private final TreeRegistry treeRegistry = new TreeRegistry(); + private final TreeRegistry treeRegistry; + private final ScriptRegistry scriptRegistry = new ScriptRegistry(); + private final LootRegistry lootRegistry = new LootRegistry(); private final AbstractConfigLoader abstractConfigLoader = new AbstractConfigLoader(); private final ConfigLoader selfLoader = new ConfigLoader(); private final Scope varScope = new Scope(); - private final Map structureMap = new HashMap<>(); + private final SamplerCache samplerCache; - { - abstractConfigLoader - .registerLoader(Palette.class, paletteRegistry) - .registerLoader(Biome.class, biomeRegistry) - .registerLoader(UserDefinedCarver.class, carverRegistry) - .registerLoader(Flora.class, floraRegistry) - .registerLoader(Ore.class, oreRegistry) - .registerLoader(Tree.class, treeRegistry) - .registerLoader(TerraStructure.class, structureRegistry); - } - public ConfigPack(File folder, Terra main) throws ConfigException { + public ConfigPack(File folder, TerraPlugin main) throws ConfigException { long l = System.nanoTime(); + this.samplerCache = new SamplerCache(main); + floraRegistry = new FloraRegistry(main); + paletteRegistry = new PaletteRegistry(main); + treeRegistry = new TreeRegistry(main); + register(abstractConfigLoader); - main.registerAllLoaders(selfLoader); - main.registerAllLoaders(abstractConfigLoader); + main.register(selfLoader); + main.register(abstractConfigLoader); File pack = new File(folder, "pack.yml"); @@ -119,11 +121,16 @@ public class ConfigPack { load(new FolderLoader(folder.toPath()), l, main); } - public ConfigPack(ZipFile file, Terra main) throws ConfigException { + public ConfigPack(ZipFile file, TerraPlugin main) throws ConfigException { long l = System.nanoTime(); + this.samplerCache = new SamplerCache(main); + floraRegistry = new FloraRegistry(main); + paletteRegistry = new PaletteRegistry(main); + treeRegistry = new TreeRegistry(main); + register(abstractConfigLoader); - main.registerAllLoaders(selfLoader); - main.registerAllLoaders(abstractConfigLoader); + main.register(selfLoader); + main.register(abstractConfigLoader); InputStream stream = null; @@ -143,21 +150,41 @@ public class ConfigPack { load(new ZIPLoader(file), l, main); } - private void load(Loader loader, long start, Terra main) throws ConfigException { + private void load(Loader loader, long start, TerraPlugin main) throws ConfigException { for(Map.Entry var : template.getVariables().entrySet()) { varScope.create(var.getKey()).setValue(var.getValue()); } - abstractConfigLoader.registerLoader(Structure.class, new StructureLoader(loader)) - .registerLoader(LootTable.class, new LootTableLoader(loader)); // These loaders need access to the Loader instance to get files. + + loader.open("structures/data", ".tesf").thenEntries(entries -> { + for(Map.Entry entry : entries) { + try { + StructureScript structureScript = new StructureScript(entry.getValue(), main, scriptRegistry, lootRegistry, samplerCache); + scriptRegistry.add(structureScript.getId(), structureScript); + } catch(com.dfsek.terra.api.structures.parser.exceptions.ParseException e) { + throw new LoadException("Unable to load script \"" + entry.getKey() + "\"", e); + } + } + }).close().open("structures/loot", ".json").thenEntries(entries -> { + for(Map.Entry entry : entries) { + try { + lootRegistry.add(entry.getKey(), new LootTable(IOUtils.toString(entry.getValue(), StandardCharsets.UTF_8), main)); + } catch(ParseException | IOException | NullPointerException e) { + throw new LoadException("Unable to load loot table \"" + entry.getKey() + "\"", e); + } + } + }).close(); + loader - .open("palettes").then(streams -> buildAll(new PaletteFactory(), paletteRegistry, abstractConfigLoader.load(streams, PaletteTemplate::new), main)).close() - .open("ores").then(streams -> buildAll(new OreFactory(), oreRegistry, abstractConfigLoader.load(streams, OreTemplate::new), main)).close() - .open("flora").then(streams -> buildAll(new FloraFactory(), floraRegistry, abstractConfigLoader.load(streams, FloraTemplate::new), main)).close() - .open("carving").then(streams -> buildAll(new CarverFactory(this), carverRegistry, abstractConfigLoader.load(streams, CarverTemplate::new), main)).close() - .open("structures/trees").then(streams -> buildAll(new TreeFactory(), treeRegistry, abstractConfigLoader.load(streams, TreeTemplate::new), main)).close() - .open("structures/single").then(streams -> buildAll(new StructureFactory(), structureRegistry, abstractConfigLoader.load(streams, StructureTemplate::new), main)).close() - .open("biomes").then(streams -> buildAll(new BiomeFactory(this), biomeRegistry, abstractConfigLoader.load(streams, () -> new BiomeTemplate(this)), main)).close() - .open("grids").then(streams -> buildAll(new BiomeGridFactory(), biomeGridRegistry, abstractConfigLoader.load(streams, BiomeGridTemplate::new), main)).close(); + .open("palettes", ".yml").then(streams -> buildAll(new PaletteFactory(), paletteRegistry, abstractConfigLoader.load(streams, PaletteTemplate::new), main)).close() + .open("ores", ".yml").then(streams -> buildAll(new OreFactory(), oreRegistry, abstractConfigLoader.load(streams, OreTemplate::new), main)).close() + .open("structures/trees", ".yml").then(streams -> buildAll(new TreeFactory(), treeRegistry, abstractConfigLoader.load(streams, TreeTemplate::new), main)).close() + .open("structures/structures", ".yml").then(streams -> buildAll(new StructureFactory(), structureRegistry, abstractConfigLoader.load(streams, StructureTemplate::new), main)).close() + .open("flora", ".yml").then(streams -> buildAll(new FloraFactory(), floraRegistry, abstractConfigLoader.load(streams, FloraTemplate::new), main)).close() + .open("carving", ".yml").then(streams -> buildAll(new CarverFactory(this), carverRegistry, abstractConfigLoader.load(streams, CarverTemplate::new), main)).close() + .open("biomes", ".yml").then(streams -> buildAll(new BiomeFactory(this), biomeRegistry, abstractConfigLoader.load(streams, () -> new BiomeTemplate(this, main)), main)).close() + .open("grids", ".yml").then(streams -> buildAll(new BiomeGridFactory(), biomeGridRegistry, abstractConfigLoader.load(streams, BiomeGridTemplate::new), main)).close(); + + for(UserDefinedBiome b : biomeRegistry.entries()) { try { Objects.requireNonNull(b.getErode()); // Throws NPE if it cannot load erosion biomes. @@ -174,12 +201,10 @@ public class ConfigPack { throw new LoadException("No such BiomeGrid \"" + template.getRadialInternalGrid() + "\""); } - template.getStructureLocatables().forEach((type, name) -> structureMap.put(Objects.requireNonNull(type), Objects.requireNonNull(structureRegistry.get(name)))); - LangUtil.log("config-pack.loaded", Level.INFO, template.getID(), String.valueOf((System.nanoTime() - start) / 1000000D), template.getAuthor(), template.getVersion()); } - private void buildAll(TerraFactory factory, TerraRegistry registry, List configTemplates, Terra main) throws LoadException { + private void buildAll(TerraFactory factory, TerraRegistry registry, List configTemplates, TerraPlugin main) throws LoadException { for(C template : configTemplates) registry.add(template.getID(), factory.build(template, main)); } @@ -231,7 +256,30 @@ public class ConfigPack { return varScope; } - public TerraStructure getStructureLocatable(StructureTypeEnum type) { - return structureMap.get(type); + + @Override + public void register(TypeRegistry registry) { + registry + .registerLoader(Palette.class, paletteRegistry) + .registerLoader(Biome.class, biomeRegistry) + .registerLoader(UserDefinedCarver.class, carverRegistry) + .registerLoader(Flora.class, floraRegistry) + .registerLoader(Ore.class, oreRegistry) + .registerLoader(Tree.class, treeRegistry) + .registerLoader(StructureScript.class, scriptRegistry) + .registerLoader(TerraStructure.class, structureRegistry) + .registerLoader(LootTable.class, lootRegistry); + } + + public ScriptRegistry getScriptRegistry() { + return scriptRegistry; + } + + public BiomeRegistry getBiomeRegistry() { + return biomeRegistry; + } + + public SamplerCache getSamplerCache() { + return samplerCache; } } diff --git a/src/main/java/com/dfsek/terra/config/base/ConfigPackTemplate.java b/common/src/main/java/com/dfsek/terra/config/base/ConfigPackTemplate.java similarity index 83% rename from src/main/java/com/dfsek/terra/config/base/ConfigPackTemplate.java rename to common/src/main/java/com/dfsek/terra/config/base/ConfigPackTemplate.java index a916ca01a..5ce37ec73 100644 --- a/src/main/java/com/dfsek/terra/config/base/ConfigPackTemplate.java +++ b/common/src/main/java/com/dfsek/terra/config/base/ConfigPackTemplate.java @@ -4,10 +4,11 @@ import com.dfsek.tectonic.annotations.Default; import com.dfsek.tectonic.annotations.Value; import com.dfsek.tectonic.config.ValidatedConfigTemplate; import com.dfsek.tectonic.exception.ValidationException; +import com.dfsek.terra.api.math.MathUtil; import com.dfsek.terra.biome.grid.master.TerraBiomeGrid; import com.dfsek.terra.generation.config.NoiseBuilder; import com.dfsek.terra.image.ImageLoader; -import com.dfsek.terra.util.StructureTypeEnum; +import net.jafama.FastMath; import java.util.HashMap; import java.util.List; @@ -25,24 +26,12 @@ public class ConfigPackTemplate implements ValidatedConfigTemplate { @Default private Map variables = new HashMap<>(); - @Value("locatable") - @Default - private Map structureLocatables = new HashMap<>(); - @Value("grids") private List grids; - @Value("frequencies.grid-x") - @Default - private int gridFreqX = 4096; - - @Value("frequencies.grid-z") - @Default - private int gridFreqZ = 4096; - @Value("frequencies.zone") @Default - private int zoneFreq = 2048; + private int zoneFreq = 256; @Value("blend.enable") @Default @@ -56,6 +45,18 @@ public class ConfigPackTemplate implements ValidatedConfigTemplate { @Default private double blendAmp = 4.0D; + @Value("blend.terrain.base") + @Default + private int baseBlend = 4; + + @Value("structures.locatable") + @Default + private Map locatable = new HashMap<>(); + + @Value("blend.terrain.elevation") + @Default + private int elevationBlend = 4; + @Value("erode.enable") @Default private boolean erode = false; @@ -171,22 +172,11 @@ public class ConfigPackTemplate implements ValidatedConfigTemplate { return variables; } - public Map getStructureLocatables() { - return structureLocatables; - } public List getGrids() { return grids; } - public int getGridFreqX() { - return gridFreqX; - } - - public int getGridFreqZ() { - return gridFreqZ; - } - public int getZoneFreq() { return zoneFreq; } @@ -251,12 +241,31 @@ public class ConfigPackTemplate implements ValidatedConfigTemplate { return imageLoader; } + public int getBaseBlend() { + return baseBlend; + } + + public int getElevationBlend() { + return elevationBlend; + } + + public Map getLocatable() { + return locatable; + } + @Override public boolean validate() throws ValidationException { if(gridType.equals(TerraBiomeGrid.Type.RADIAL) && internalGrid == null) throw new ValidationException("No internal BiomeGrid specified"); if(biomeZChannel.equals(biomeXChannel) || zoneChannel.equals(biomeXChannel) || zoneChannel.equals(biomeZChannel)) throw new ValidationException("2 objects share the same image channels: biome-x and biome-z"); + + if(!MathUtil.equals(FastMath.log(baseBlend) / FastMath.log(2d), FastMath.round(FastMath.log(baseBlend) / FastMath.log(2d)))) { + throw new ValidationException("Biome base blend value \"" + baseBlend + "\" is not a power of 2."); + } + if(!MathUtil.equals(FastMath.log(elevationBlend) / FastMath.log(2d), FastMath.round(FastMath.log(elevationBlend) / FastMath.log(2d)))) { + throw new ValidationException("Biome elevation blend value \"" + baseBlend + "\" is not a power of 2."); + } return true; } } diff --git a/src/main/java/com/dfsek/terra/config/base/PluginConfig.java b/common/src/main/java/com/dfsek/terra/config/base/PluginConfig.java similarity index 72% rename from src/main/java/com/dfsek/terra/config/base/PluginConfig.java rename to common/src/main/java/com/dfsek/terra/config/base/PluginConfig.java index 44fa5c697..9b7691f73 100644 --- a/src/main/java/com/dfsek/terra/config/base/PluginConfig.java +++ b/common/src/main/java/com/dfsek/terra/config/base/PluginConfig.java @@ -5,10 +5,9 @@ import com.dfsek.tectonic.annotations.Value; import com.dfsek.tectonic.config.ConfigTemplate; import com.dfsek.tectonic.exception.ConfigException; import com.dfsek.tectonic.loading.ConfigLoader; -import com.dfsek.terra.Terra; +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.util.JarUtil; import com.dfsek.terra.debug.Debug; -import org.polydev.gaea.GaeaPlugin; -import org.polydev.gaea.util.JarUtil; import java.io.File; import java.io.FileInputStream; @@ -36,22 +35,34 @@ public class PluginConfig implements ConfigTemplate { @Default private int biomeSearch = 4; - @Value("cache-size") + @Value("cache.carver") @Default - private int cacheSize = 384; + private int carverCache = 512; + + @Value("cache.structure") + @Default + private int structureCache = 128; + + @Value("cache.sampler") + @Default + private int samplerCache = 512; @Value("dump-default") @Default private boolean dumpDefaultConfig = true; - public void load(GaeaPlugin main) { + @Value("script.max-recursion") + @Default + private int maxRecursion = 1000; + + public void load(TerraPlugin main) { Logger logger = main.getLogger(); logger.info("Loading config values"); try(FileInputStream file = new FileInputStream(new File(main.getDataFolder(), "config.yml"))) { ConfigLoader loader = new ConfigLoader(); loader.load(this, file); if(dumpDefaultConfig) { // Don't dump default config if already loaded. - try(JarFile jar = new JarFile(new File(Terra.class.getProtectionDomain().getCodeSource().getLocation().toURI()))) { + try(JarFile jar = new JarFile(new File(TerraPlugin.class.getProtectionDomain().getCodeSource().getLocation().toURI()))) { JarUtil.copyResourcesToDirectory(jar, "packs", new File(main.getDataFolder(), "packs").toString()); } catch(IOException | URISyntaxException e) { Debug.error("Failed to dump default config files!"); @@ -81,7 +92,19 @@ public class PluginConfig implements ConfigTemplate { return biomeSearch; } - public int getCacheSize() { - return cacheSize; + public int getCarverCacheSize() { + return carverCache; + } + + public int getStructureCache() { + return structureCache; + } + + public int getSamplerCache() { + return samplerCache; + } + + public int getMaxRecursion() { + return maxRecursion; } } diff --git a/src/main/java/com/dfsek/terra/config/builder/GeneratorBuilder.java b/common/src/main/java/com/dfsek/terra/config/builder/GeneratorBuilder.java similarity index 85% rename from src/main/java/com/dfsek/terra/config/builder/GeneratorBuilder.java rename to common/src/main/java/com/dfsek/terra/config/builder/GeneratorBuilder.java index d63460942..1767ce2f6 100644 --- a/src/main/java/com/dfsek/terra/config/builder/GeneratorBuilder.java +++ b/common/src/main/java/com/dfsek/terra/config/builder/GeneratorBuilder.java @@ -27,8 +27,29 @@ public class GeneratorBuilder { private boolean interpolateElevation; + private boolean noise2d; + + private double base; + + public WorldGenerator build(long seed) { - return gens.computeIfAbsent(seed, k -> new WorldGenerator(seed, noiseEquation, elevationEquation, varScope, noiseBuilderMap, palettes, slantPalettes, preventInterpolation, interpolateElevation)); + return gens.computeIfAbsent(seed, k -> new WorldGenerator(seed, noiseEquation, elevationEquation, varScope, noiseBuilderMap, palettes, slantPalettes, interpolateElevation, noise2d, base)); + } + + public boolean isNoise2d() { + return noise2d; + } + + public void setNoise2d(boolean noise2d) { + this.noise2d = noise2d; + } + + public double getBase() { + return base; + } + + public void setBase(double base) { + this.base = base; } public String getNoiseEquation() { diff --git a/src/main/java/com/dfsek/terra/config/builder/biomegrid/BiomeGridBuilder.java b/common/src/main/java/com/dfsek/terra/config/builder/biomegrid/BiomeGridBuilder.java similarity index 53% rename from src/main/java/com/dfsek/terra/config/builder/biomegrid/BiomeGridBuilder.java rename to common/src/main/java/com/dfsek/terra/config/builder/biomegrid/BiomeGridBuilder.java index ce203c754..7bd7fda29 100644 --- a/src/main/java/com/dfsek/terra/config/builder/biomegrid/BiomeGridBuilder.java +++ b/common/src/main/java/com/dfsek/terra/config/builder/biomegrid/BiomeGridBuilder.java @@ -1,9 +1,8 @@ package com.dfsek.terra.config.builder.biomegrid; +import com.dfsek.terra.api.world.biome.BiomeGrid; import com.dfsek.terra.config.base.ConfigPack; -import org.bukkit.World; -import org.polydev.gaea.biome.BiomeGrid; public interface BiomeGridBuilder { - BiomeGrid build(World world, ConfigPack config); + BiomeGrid build(long seed, ConfigPack config); } diff --git a/src/main/java/com/dfsek/terra/config/builder/biomegrid/SingleGridBuilder.java b/common/src/main/java/com/dfsek/terra/config/builder/biomegrid/SingleGridBuilder.java similarity index 65% rename from src/main/java/com/dfsek/terra/config/builder/biomegrid/SingleGridBuilder.java rename to common/src/main/java/com/dfsek/terra/config/builder/biomegrid/SingleGridBuilder.java index 1776c6ef4..92b12caa2 100644 --- a/src/main/java/com/dfsek/terra/config/builder/biomegrid/SingleGridBuilder.java +++ b/common/src/main/java/com/dfsek/terra/config/builder/biomegrid/SingleGridBuilder.java @@ -1,9 +1,8 @@ package com.dfsek.terra.config.builder.biomegrid; +import com.dfsek.terra.api.world.biome.Biome; import com.dfsek.terra.biome.grid.SingleBiomeGrid; import com.dfsek.terra.config.base.ConfigPack; -import org.bukkit.World; -import org.polydev.gaea.biome.Biome; public class SingleGridBuilder implements BiomeGridBuilder { private final Biome biome; @@ -13,7 +12,7 @@ public class SingleGridBuilder implements BiomeGridBuilder { } @Override - public SingleBiomeGrid build(World world, ConfigPack config) { - return new SingleBiomeGrid(world, biome); + public SingleBiomeGrid build(long seed, ConfigPack config) { + return new SingleBiomeGrid(seed, biome); } } diff --git a/src/main/java/com/dfsek/terra/config/builder/biomegrid/UserDefinedGridBuilder.java b/common/src/main/java/com/dfsek/terra/config/builder/biomegrid/UserDefinedGridBuilder.java similarity index 77% rename from src/main/java/com/dfsek/terra/config/builder/biomegrid/UserDefinedGridBuilder.java rename to common/src/main/java/com/dfsek/terra/config/builder/biomegrid/UserDefinedGridBuilder.java index 2b3b2d9b1..9c71fb1f2 100644 --- a/src/main/java/com/dfsek/terra/config/builder/biomegrid/UserDefinedGridBuilder.java +++ b/common/src/main/java/com/dfsek/terra/config/builder/biomegrid/UserDefinedGridBuilder.java @@ -1,9 +1,8 @@ package com.dfsek.terra.config.builder.biomegrid; +import com.dfsek.terra.api.world.biome.Biome; import com.dfsek.terra.biome.grid.UserDefinedGrid; import com.dfsek.terra.config.base.ConfigPack; -import org.bukkit.World; -import org.polydev.gaea.biome.Biome; public class UserDefinedGridBuilder implements BiomeGridBuilder { private double xFreq; @@ -12,8 +11,8 @@ public class UserDefinedGridBuilder implements BiomeGridBuilder { private Biome[][] biomes; @Override - public UserDefinedGrid build(World world, ConfigPack config) { - return new UserDefinedGrid(world, 1D / xFreq, 1D / zFreq, biomes, config); + public UserDefinedGrid build(long seed, ConfigPack config) { + return new UserDefinedGrid(seed, 1D / xFreq, 1D / zFreq, biomes, config); } public double getXFreq() { diff --git a/src/main/java/com/dfsek/terra/config/exception/FileMissingException.java b/common/src/main/java/com/dfsek/terra/config/exception/FileMissingException.java similarity index 100% rename from src/main/java/com/dfsek/terra/config/exception/FileMissingException.java rename to common/src/main/java/com/dfsek/terra/config/exception/FileMissingException.java diff --git a/src/main/java/com/dfsek/terra/config/factories/BiomeFactory.java b/common/src/main/java/com/dfsek/terra/config/factories/BiomeFactory.java similarity index 70% rename from src/main/java/com/dfsek/terra/config/factories/BiomeFactory.java rename to common/src/main/java/com/dfsek/terra/config/factories/BiomeFactory.java index 6e4c5f97d..b4d158c9b 100644 --- a/src/main/java/com/dfsek/terra/config/factories/BiomeFactory.java +++ b/common/src/main/java/com/dfsek/terra/config/factories/BiomeFactory.java @@ -1,12 +1,10 @@ package com.dfsek.terra.config.factories; -import com.dfsek.terra.Terra; +import com.dfsek.terra.api.platform.TerraPlugin; import com.dfsek.terra.biome.UserDefinedBiome; import com.dfsek.terra.config.base.ConfigPack; import com.dfsek.terra.config.builder.GeneratorBuilder; import com.dfsek.terra.config.templates.BiomeTemplate; -import com.dfsek.terra.generation.UserDefinedDecorator; -import org.polydev.gaea.math.ProbabilityCollection; public class BiomeFactory implements TerraFactory { private final ConfigPack pack; @@ -16,8 +14,7 @@ public class BiomeFactory implements TerraFactory(), new ProbabilityCollection<>(), 0, 0); + public UserDefinedBiome build(BiomeTemplate template, TerraPlugin main) { GeneratorBuilder generatorBuilder = new GeneratorBuilder(); generatorBuilder.setElevationEquation(template.getElevationEquation()); generatorBuilder.setNoiseEquation(template.getNoiseEquation()); @@ -26,8 +23,10 @@ public class BiomeFactory implements TerraFactory { @Override - public UserDefinedGridBuilder build(BiomeGridTemplate config, Terra main) { + public UserDefinedGridBuilder build(BiomeGridTemplate config, TerraPlugin main) throws LoadException { UserDefinedGridBuilder holder = new UserDefinedGridBuilder(); - holder.setXFreq(config.getXFreq()); - holder.setZFreq(config.getZFreq()); int xSize = config.getGrid().size(); int zSize = config.getGrid().get(0).size(); + holder.setXFreq(config.getXFreq() * xSize); + holder.setZFreq(config.getZFreq() * zSize); + Biome[][] biomes = new UserDefinedBiome[xSize][zSize]; for(int x = 0; x < xSize; x++) { List layer = config.getGrid().get(x); - if(!(layer.size() == zSize)) throw new IllegalArgumentException(); + if(!(layer.size() == zSize)) throw new LoadException("Expected " + zSize + " biomes in row " + x + ", found " + layer.size()); for(int z = 0; z < zSize; z++) { biomes[x][z] = layer.get(z); } diff --git a/src/main/java/com/dfsek/terra/config/factories/CarverFactory.java b/common/src/main/java/com/dfsek/terra/config/factories/CarverFactory.java similarity index 88% rename from src/main/java/com/dfsek/terra/config/factories/CarverFactory.java rename to common/src/main/java/com/dfsek/terra/config/factories/CarverFactory.java index a9fcdba11..214cf0b2e 100644 --- a/src/main/java/com/dfsek/terra/config/factories/CarverFactory.java +++ b/common/src/main/java/com/dfsek/terra/config/factories/CarverFactory.java @@ -1,11 +1,11 @@ package com.dfsek.terra.config.factories; import com.dfsek.tectonic.exception.LoadException; -import com.dfsek.terra.Terra; +import com.dfsek.terra.api.math.MathUtil; +import com.dfsek.terra.api.platform.TerraPlugin; import com.dfsek.terra.carving.UserDefinedCarver; import com.dfsek.terra.config.base.ConfigPack; import com.dfsek.terra.config.templates.CarverTemplate; -import org.polydev.gaea.math.MathUtil; import parsii.tokenizer.ParseException; import java.util.Arrays; @@ -19,7 +19,7 @@ public class CarverFactory implements TerraFactory radius = Arrays.asList(config.getRadMX(), config.getRadMY(), config.getRadMZ()); diff --git a/src/main/java/com/dfsek/terra/config/factories/FloraFactory.java b/common/src/main/java/com/dfsek/terra/config/factories/FloraFactory.java similarity index 63% rename from src/main/java/com/dfsek/terra/config/factories/FloraFactory.java rename to common/src/main/java/com/dfsek/terra/config/factories/FloraFactory.java index b29268677..fbef851e5 100644 --- a/src/main/java/com/dfsek/terra/config/factories/FloraFactory.java +++ b/common/src/main/java/com/dfsek/terra/config/factories/FloraFactory.java @@ -1,18 +1,18 @@ package com.dfsek.terra.config.factories; -import com.dfsek.terra.Terra; +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.util.FastRandom; +import com.dfsek.terra.api.world.flora.Flora; +import com.dfsek.terra.api.world.palette.Palette; +import com.dfsek.terra.api.world.palette.RandomPalette; import com.dfsek.terra.biome.palette.PaletteLayer; import com.dfsek.terra.config.templates.FloraTemplate; -import com.dfsek.terra.generation.items.flora.TerraFlora; -import org.bukkit.block.data.BlockData; -import org.polydev.gaea.util.FastRandom; -import org.polydev.gaea.world.Flora; -import org.polydev.gaea.world.palette.Palette; -import org.polydev.gaea.world.palette.RandomPalette; +import com.dfsek.terra.population.items.flora.TerraFlora; public class FloraFactory implements TerraFactory { @Override - public TerraFlora build(FloraTemplate config, Terra main) { + public TerraFlora build(FloraTemplate config, TerraPlugin main) { Palette palette = new RandomPalette<>(new FastRandom(2403)); for(PaletteLayer layer : config.getFloraPalette()) { palette.add(layer.getLayer(), layer.getSize()); diff --git a/src/main/java/com/dfsek/terra/config/factories/OreFactory.java b/common/src/main/java/com/dfsek/terra/config/factories/OreFactory.java similarity index 65% rename from src/main/java/com/dfsek/terra/config/factories/OreFactory.java rename to common/src/main/java/com/dfsek/terra/config/factories/OreFactory.java index db8c4bfdf..401074c52 100644 --- a/src/main/java/com/dfsek/terra/config/factories/OreFactory.java +++ b/common/src/main/java/com/dfsek/terra/config/factories/OreFactory.java @@ -1,15 +1,15 @@ package com.dfsek.terra.config.factories; -import com.dfsek.terra.Terra; +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.platform.block.BlockData; import com.dfsek.terra.config.templates.OreTemplate; -import com.dfsek.terra.generation.items.ores.DeformedSphereOre; -import com.dfsek.terra.generation.items.ores.Ore; -import com.dfsek.terra.generation.items.ores.VanillaOre; -import org.bukkit.block.data.BlockData; +import com.dfsek.terra.population.items.ores.DeformedSphereOre; +import com.dfsek.terra.population.items.ores.Ore; +import com.dfsek.terra.population.items.ores.VanillaOre; public class OreFactory implements TerraFactory { @Override - public Ore build(OreTemplate config, Terra main) { + public Ore build(OreTemplate config, TerraPlugin main) { BlockData m = config.getMaterial(); switch(config.getType()) { case SPHERE: diff --git a/src/main/java/com/dfsek/terra/config/factories/PaletteFactory.java b/common/src/main/java/com/dfsek/terra/config/factories/PaletteFactory.java similarity index 67% rename from src/main/java/com/dfsek/terra/config/factories/PaletteFactory.java rename to common/src/main/java/com/dfsek/terra/config/factories/PaletteFactory.java index 7b8dcd5a4..137ab4dbd 100644 --- a/src/main/java/com/dfsek/terra/config/factories/PaletteFactory.java +++ b/common/src/main/java/com/dfsek/terra/config/factories/PaletteFactory.java @@ -1,18 +1,18 @@ package com.dfsek.terra.config.factories; -import com.dfsek.terra.Terra; +import com.dfsek.terra.api.math.noise.samplers.FastNoiseLite; +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.util.FastRandom; +import com.dfsek.terra.api.world.palette.Palette; +import com.dfsek.terra.api.world.palette.RandomPalette; +import com.dfsek.terra.api.world.palette.SimplexPalette; import com.dfsek.terra.biome.palette.PaletteLayer; import com.dfsek.terra.config.templates.PaletteTemplate; -import org.bukkit.block.data.BlockData; -import org.polydev.gaea.math.FastNoiseLite; -import org.polydev.gaea.util.FastRandom; -import org.polydev.gaea.world.palette.Palette; -import org.polydev.gaea.world.palette.RandomPalette; -import org.polydev.gaea.world.palette.SimplexPalette; public class PaletteFactory implements TerraFactory> { @Override - public Palette build(PaletteTemplate config, Terra main) { + public Palette build(PaletteTemplate config, TerraPlugin main) { Palette palette; if(config.isSimplex()) { FastNoiseLite noise = new FastNoiseLite((int) config.getSeed()); diff --git a/common/src/main/java/com/dfsek/terra/config/factories/StructureFactory.java b/common/src/main/java/com/dfsek/terra/config/factories/StructureFactory.java new file mode 100644 index 000000000..07ff0f902 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/config/factories/StructureFactory.java @@ -0,0 +1,12 @@ +package com.dfsek.terra.config.factories; + +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.config.templates.StructureTemplate; +import com.dfsek.terra.population.items.TerraStructure; + +public class StructureFactory implements TerraFactory { + @Override + public TerraStructure build(StructureTemplate config, TerraPlugin main) { + return new TerraStructure(config.getStructures(), config.getY(), config.getSpawn(), config); + } +} diff --git a/src/main/java/com/dfsek/terra/config/factories/TerraFactory.java b/common/src/main/java/com/dfsek/terra/config/factories/TerraFactory.java similarity index 65% rename from src/main/java/com/dfsek/terra/config/factories/TerraFactory.java rename to common/src/main/java/com/dfsek/terra/config/factories/TerraFactory.java index ebc4d87d7..485d7f8af 100644 --- a/src/main/java/com/dfsek/terra/config/factories/TerraFactory.java +++ b/common/src/main/java/com/dfsek/terra/config/factories/TerraFactory.java @@ -2,8 +2,8 @@ package com.dfsek.terra.config.factories; import com.dfsek.tectonic.config.ConfigTemplate; import com.dfsek.tectonic.exception.LoadException; -import com.dfsek.terra.Terra; +import com.dfsek.terra.api.platform.TerraPlugin; public interface TerraFactory { - O build(C config, Terra main) throws LoadException; + O build(C config, TerraPlugin main) throws LoadException; } diff --git a/src/main/java/com/dfsek/terra/config/factories/TreeFactory.java b/common/src/main/java/com/dfsek/terra/config/factories/TreeFactory.java similarity index 53% rename from src/main/java/com/dfsek/terra/config/factories/TreeFactory.java rename to common/src/main/java/com/dfsek/terra/config/factories/TreeFactory.java index 2bd2e3281..d1bd32ede 100644 --- a/src/main/java/com/dfsek/terra/config/factories/TreeFactory.java +++ b/common/src/main/java/com/dfsek/terra/config/factories/TreeFactory.java @@ -1,14 +1,13 @@ package com.dfsek.terra.config.factories; -import com.dfsek.tectonic.exception.LoadException; -import com.dfsek.terra.Terra; +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.world.tree.Tree; import com.dfsek.terra.config.templates.TreeTemplate; -import com.dfsek.terra.generation.items.tree.TerraTree; -import org.polydev.gaea.tree.Tree; +import com.dfsek.terra.population.items.tree.TerraTree; public class TreeFactory implements TerraFactory { @Override - public Tree build(TreeTemplate config, Terra main) throws LoadException { + public Tree build(TreeTemplate config, TerraPlugin main) { return new TerraTree(config.getSpawnable(), config.getyOffset(), config.getStructures()); } } diff --git a/src/main/java/com/dfsek/terra/config/files/ExceptionalConsumer.java b/common/src/main/java/com/dfsek/terra/config/files/ExceptionalConsumer.java similarity index 100% rename from src/main/java/com/dfsek/terra/config/files/ExceptionalConsumer.java rename to common/src/main/java/com/dfsek/terra/config/files/ExceptionalConsumer.java diff --git a/src/main/java/com/dfsek/terra/config/files/FolderLoader.java b/common/src/main/java/com/dfsek/terra/config/files/FolderLoader.java similarity index 79% rename from src/main/java/com/dfsek/terra/config/files/FolderLoader.java rename to common/src/main/java/com/dfsek/terra/config/files/FolderLoader.java index 12c73eb39..6c5a483dd 100644 --- a/src/main/java/com/dfsek/terra/config/files/FolderLoader.java +++ b/common/src/main/java/com/dfsek/terra/config/files/FolderLoader.java @@ -25,13 +25,14 @@ public class FolderLoader extends Loader { } @Override - protected void load(String directory) { + protected void load(String directory, String extension) { File newPath = new File(path.toFile(), directory); newPath.mkdirs(); try(Stream paths = Files.walk(newPath.toPath())) { - paths.filter(Files::isRegularFile).filter(file -> file.toString().toLowerCase().endsWith(".yml")).forEach(file -> { + paths.filter(Files::isRegularFile).filter(file -> file.toString().toLowerCase().endsWith(extension)).forEach(file -> { try { - streams.add(new FileInputStream(file.toFile())); + String rel = newPath.toPath().relativize(file).toString(); + streams.put(rel, new FileInputStream(file.toFile())); } catch(FileNotFoundException e) { e.printStackTrace(); } diff --git a/src/main/java/com/dfsek/terra/config/files/Loader.java b/common/src/main/java/com/dfsek/terra/config/files/Loader.java similarity index 58% rename from src/main/java/com/dfsek/terra/config/files/Loader.java rename to common/src/main/java/com/dfsek/terra/config/files/Loader.java index 4d7257208..5c06ec7ac 100644 --- a/src/main/java/com/dfsek/terra/config/files/Loader.java +++ b/common/src/main/java/com/dfsek/terra/config/files/Loader.java @@ -1,14 +1,17 @@ package com.dfsek.terra.config.files; import com.dfsek.tectonic.exception.ConfigException; +import com.dfsek.terra.api.util.GlueList; import java.io.IOException; import java.io.InputStream; -import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.Set; public abstract class Loader { - protected final List streams = new ArrayList<>(); + protected final Map streams = new HashMap<>(); /** * Do something with the InputStreams. @@ -16,7 +19,17 @@ public abstract class Loader { * @param consumer Something to do with the streams. */ public Loader then(ExceptionalConsumer> consumer) throws ConfigException { - consumer.accept(streams); + consumer.accept(new GlueList<>(streams.values())); + return this; + } + + public Loader thenNames(ExceptionalConsumer> consumer) throws ConfigException { + consumer.accept(new GlueList<>(streams.keySet())); + return this; + } + + public Loader thenEntries(ExceptionalConsumer>> consumer) throws ConfigException { + consumer.accept(streams.entrySet()); return this; } @@ -32,20 +45,21 @@ public abstract class Loader { * Open a subdirectory. * * @param directory Directory to open + * @param extension */ - public Loader open(String directory) { + public Loader open(String directory, String extension) { if(streams.size() != 0) throw new IllegalStateException("Attempted to load new directory before closing existing InputStreams"); - load(directory); + load(directory, extension); return this; } - protected abstract void load(String directory); + protected abstract void load(String directory, String extension); /** * Close all InputStreams opened. */ public Loader close() { - streams.forEach(input -> { + streams.forEach((name, input) -> { try { input.close(); } catch(IOException e) { diff --git a/src/main/java/com/dfsek/terra/config/files/ZIPLoader.java b/common/src/main/java/com/dfsek/terra/config/files/ZIPLoader.java similarity index 81% rename from src/main/java/com/dfsek/terra/config/files/ZIPLoader.java rename to common/src/main/java/com/dfsek/terra/config/files/ZIPLoader.java index 85da05f98..7e4003e77 100644 --- a/src/main/java/com/dfsek/terra/config/files/ZIPLoader.java +++ b/common/src/main/java/com/dfsek/terra/config/files/ZIPLoader.java @@ -24,13 +24,14 @@ public class ZIPLoader extends Loader { } @Override - protected void load(String directory) { + protected void load(String directory, String extension) { Enumeration entries = file.entries(); while(entries.hasMoreElements()) { ZipEntry entry = entries.nextElement(); - if(!entry.isDirectory() && entry.getName().startsWith(directory) && entry.getName().endsWith(".yml")) { + if(!entry.isDirectory() && entry.getName().startsWith(directory) && entry.getName().endsWith(extension)) { try { - streams.add(file.getInputStream(entry)); + String rel = entry.getName().substring(directory.length() + 1); + streams.put(rel, file.getInputStream(entry)); } catch(IOException e) { e.printStackTrace(); } diff --git a/src/main/java/com/dfsek/terra/config/lang/LangUtil.java b/common/src/main/java/com/dfsek/terra/config/lang/LangUtil.java similarity index 67% rename from src/main/java/com/dfsek/terra/config/lang/LangUtil.java rename to common/src/main/java/com/dfsek/terra/config/lang/LangUtil.java index bd4b9a93d..a7f24fc45 100644 --- a/src/main/java/com/dfsek/terra/config/lang/LangUtil.java +++ b/common/src/main/java/com/dfsek/terra/config/lang/LangUtil.java @@ -1,11 +1,9 @@ package com.dfsek.terra.config.lang; -import com.dfsek.terra.Terra; +import com.dfsek.terra.api.language.Language; +import com.dfsek.terra.api.platform.CommandSender; +import com.dfsek.terra.api.platform.TerraPlugin; import com.dfsek.terra.debug.Debug; -import org.bukkit.command.CommandSender; -import org.bukkit.configuration.InvalidConfigurationException; -import org.bukkit.plugin.java.JavaPlugin; -import org.polydev.gaea.lang.Language; import java.io.File; import java.io.IOException; @@ -14,16 +12,16 @@ import java.util.jar.JarFile; import java.util.logging.Level; import java.util.logging.Logger; -import static org.polydev.gaea.util.JarUtil.copyResourcesToDirectory; +import static com.dfsek.terra.api.util.JarUtil.copyResourcesToDirectory; public final class LangUtil { private static Language language; private static Logger logger; - public static void load(String langID, JavaPlugin main) { + public static void load(String langID, TerraPlugin main) { logger = main.getLogger(); File file = new File(main.getDataFolder(), "lang"); - try(JarFile jar = new JarFile(new File(Terra.class.getProtectionDomain().getCodeSource().getLocation().toURI()))) { + try(JarFile jar = new JarFile(new File(TerraPlugin.class.getProtectionDomain().getCodeSource().getLocation().toURI()))) { copyResourcesToDirectory(jar, "lang", file.toString()); } catch(IOException | URISyntaxException e) { Debug.error("Failed to dump language files!"); @@ -31,8 +29,11 @@ public final class LangUtil { Debug.error("Report this to Terra!"); } try { - language = new Language(new File(main.getDataFolder(), "lang" + File.separator + langID + ".yml")); - } catch(InvalidConfigurationException | IOException e) { + File file1 = new File(file, langID + ".yml"); + logger.info(file1.getAbsolutePath()); + language = new Language(file1); + logger.info("Loaded language " + langID); + } catch(IOException e) { logger.severe("Unable to load language: " + langID); e.printStackTrace(); logger.severe("Double-check your configuration before reporting this to Terra!"); diff --git a/src/main/java/com/dfsek/terra/config/loaders/ImageLoaderLoader.java b/common/src/main/java/com/dfsek/terra/config/loaders/ImageLoaderLoader.java similarity index 100% rename from src/main/java/com/dfsek/terra/config/loaders/ImageLoaderLoader.java rename to common/src/main/java/com/dfsek/terra/config/loaders/ImageLoaderLoader.java diff --git a/src/main/java/com/dfsek/terra/config/loaders/MaterialSetLoader.java b/common/src/main/java/com/dfsek/terra/config/loaders/MaterialSetLoader.java similarity index 81% rename from src/main/java/com/dfsek/terra/config/loaders/MaterialSetLoader.java rename to common/src/main/java/com/dfsek/terra/config/loaders/MaterialSetLoader.java index f9af8b732..53ec78a2b 100644 --- a/src/main/java/com/dfsek/terra/config/loaders/MaterialSetLoader.java +++ b/common/src/main/java/com/dfsek/terra/config/loaders/MaterialSetLoader.java @@ -3,8 +3,8 @@ package com.dfsek.terra.config.loaders; import com.dfsek.tectonic.exception.LoadException; import com.dfsek.tectonic.loading.ConfigLoader; import com.dfsek.tectonic.loading.TypeLoader; +import com.dfsek.terra.api.platform.block.MaterialData; import com.dfsek.terra.util.MaterialSet; -import org.bukkit.Material; import java.lang.reflect.Type; import java.util.List; @@ -18,8 +18,7 @@ public class MaterialSetLoader implements TypeLoader { for(String string : stringData) { try { - if(string.startsWith("#")) set.addTag(string.substring(1)); - else set.add((Material) configLoader.loadType(Material.class, string)); + set.add((MaterialData) configLoader.loadType(MaterialData.class, string)); } catch(NullPointerException e) { throw new LoadException("Invalid data identifier \"" + string + "\"", e); } diff --git a/src/main/java/com/dfsek/terra/config/loaders/ProbabilityCollectionLoader.java b/common/src/main/java/com/dfsek/terra/config/loaders/ProbabilityCollectionLoader.java similarity index 96% rename from src/main/java/com/dfsek/terra/config/loaders/ProbabilityCollectionLoader.java rename to common/src/main/java/com/dfsek/terra/config/loaders/ProbabilityCollectionLoader.java index 5680d153c..dbff2f29b 100644 --- a/src/main/java/com/dfsek/terra/config/loaders/ProbabilityCollectionLoader.java +++ b/common/src/main/java/com/dfsek/terra/config/loaders/ProbabilityCollectionLoader.java @@ -3,7 +3,7 @@ package com.dfsek.terra.config.loaders; import com.dfsek.tectonic.exception.LoadException; import com.dfsek.tectonic.loading.ConfigLoader; import com.dfsek.tectonic.loading.TypeLoader; -import org.polydev.gaea.math.ProbabilityCollection; +import com.dfsek.terra.api.math.ProbabilityCollection; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; diff --git a/src/main/java/com/dfsek/terra/config/loaders/RangeLoader.java b/common/src/main/java/com/dfsek/terra/config/loaders/RangeLoader.java similarity index 93% rename from src/main/java/com/dfsek/terra/config/loaders/RangeLoader.java rename to common/src/main/java/com/dfsek/terra/config/loaders/RangeLoader.java index 5e08691a7..7b0913ba7 100644 --- a/src/main/java/com/dfsek/terra/config/loaders/RangeLoader.java +++ b/common/src/main/java/com/dfsek/terra/config/loaders/RangeLoader.java @@ -3,7 +3,7 @@ package com.dfsek.terra.config.loaders; import com.dfsek.tectonic.exception.LoadException; import com.dfsek.tectonic.loading.ConfigLoader; import com.dfsek.tectonic.loading.TypeLoader; -import org.polydev.gaea.math.Range; +import com.dfsek.terra.api.math.Range; import java.lang.reflect.Type; import java.util.Map; diff --git a/src/main/java/com/dfsek/terra/config/loaders/Types.java b/common/src/main/java/com/dfsek/terra/config/loaders/Types.java similarity index 78% rename from src/main/java/com/dfsek/terra/config/loaders/Types.java rename to common/src/main/java/com/dfsek/terra/config/loaders/Types.java index 553d53df9..d4f0d17cc 100644 --- a/src/main/java/com/dfsek/terra/config/loaders/Types.java +++ b/common/src/main/java/com/dfsek/terra/config/loaders/Types.java @@ -1,11 +1,11 @@ package com.dfsek.terra.config.loaders; -import org.bukkit.Material; -import org.bukkit.block.data.BlockData; -import org.polydev.gaea.math.ProbabilityCollection; -import org.polydev.gaea.tree.Tree; -import org.polydev.gaea.world.Flora; -import org.polydev.gaea.world.palette.Palette; +import com.dfsek.terra.api.math.ProbabilityCollection; +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.block.MaterialData; +import com.dfsek.terra.api.world.flora.Flora; +import com.dfsek.terra.api.world.palette.Palette; +import com.dfsek.terra.api.world.tree.Tree; import java.lang.reflect.Type; import java.util.Set; @@ -31,9 +31,9 @@ public final class Types { TREE_PROBABILITY_COLLECTION_TYPE = getType("treeProbabilityCollection"); } - private Set materialSet; + private Set materialSet; private Palette blockDataPalette; - private ProbabilityCollection materialProbabilityCollection; + private ProbabilityCollection materialProbabilityCollection; private ProbabilityCollection blockDataProbabilityCollection; private ProbabilityCollection floraProbabilityCollection; private ProbabilityCollection treeProbabilityCollection; diff --git a/src/main/java/com/dfsek/terra/config/loaders/config/FloraLayerLoader.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/FloraLayerLoader.java similarity index 83% rename from src/main/java/com/dfsek/terra/config/loaders/config/FloraLayerLoader.java rename to common/src/main/java/com/dfsek/terra/config/loaders/config/FloraLayerLoader.java index 4a2ed5f30..72990fd61 100644 --- a/src/main/java/com/dfsek/terra/config/loaders/config/FloraLayerLoader.java +++ b/common/src/main/java/com/dfsek/terra/config/loaders/config/FloraLayerLoader.java @@ -3,12 +3,12 @@ package com.dfsek.terra.config.loaders.config; import com.dfsek.tectonic.exception.LoadException; import com.dfsek.tectonic.loading.ConfigLoader; import com.dfsek.tectonic.loading.TypeLoader; +import com.dfsek.terra.api.math.ProbabilityCollection; +import com.dfsek.terra.api.math.Range; +import com.dfsek.terra.api.math.noise.samplers.FastNoiseLite; +import com.dfsek.terra.api.world.flora.Flora; import com.dfsek.terra.config.loaders.Types; -import com.dfsek.terra.generation.items.flora.FloraLayer; -import org.polydev.gaea.math.FastNoiseLite; -import org.polydev.gaea.math.ProbabilityCollection; -import org.polydev.gaea.math.Range; -import org.polydev.gaea.world.Flora; +import com.dfsek.terra.population.items.flora.FloraLayer; import java.lang.reflect.Type; import java.util.Map; diff --git a/src/main/java/com/dfsek/terra/config/loaders/config/GridSpawnLoader.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/GridSpawnLoader.java similarity index 87% rename from src/main/java/com/dfsek/terra/config/loaders/config/GridSpawnLoader.java rename to common/src/main/java/com/dfsek/terra/config/loaders/config/GridSpawnLoader.java index bae39cbcc..493d0b0eb 100644 --- a/src/main/java/com/dfsek/terra/config/loaders/config/GridSpawnLoader.java +++ b/common/src/main/java/com/dfsek/terra/config/loaders/config/GridSpawnLoader.java @@ -2,7 +2,7 @@ package com.dfsek.terra.config.loaders.config; import com.dfsek.tectonic.loading.ConfigLoader; import com.dfsek.tectonic.loading.TypeLoader; -import com.dfsek.terra.procgen.GridSpawn; +import com.dfsek.terra.api.math.GridSpawn; import java.lang.reflect.Type; import java.util.Map; @@ -12,6 +12,6 @@ public class GridSpawnLoader implements TypeLoader { @Override public GridSpawn load(Type type, Object o, ConfigLoader configLoader) { Map map = (Map) o; - return new GridSpawn(map.get("width"), map.get("padding"), map.getOrDefault("seed", 0)); + return new GridSpawn(map.get("width"), map.get("padding"), map.getOrDefault("salt", 0)); } } diff --git a/src/main/java/com/dfsek/terra/config/loaders/config/NoiseBuilderLoader.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/NoiseBuilderLoader.java similarity index 96% rename from src/main/java/com/dfsek/terra/config/loaders/config/NoiseBuilderLoader.java rename to common/src/main/java/com/dfsek/terra/config/loaders/config/NoiseBuilderLoader.java index 8f135b178..e83a8dd8a 100644 --- a/src/main/java/com/dfsek/terra/config/loaders/config/NoiseBuilderLoader.java +++ b/common/src/main/java/com/dfsek/terra/config/loaders/config/NoiseBuilderLoader.java @@ -5,8 +5,8 @@ import com.dfsek.tectonic.exception.ConfigException; import com.dfsek.tectonic.exception.LoadException; import com.dfsek.tectonic.loading.ConfigLoader; import com.dfsek.tectonic.loading.TypeLoader; +import com.dfsek.terra.api.math.noise.samplers.FastNoiseLite; import com.dfsek.terra.generation.config.NoiseBuilder; -import org.polydev.gaea.math.FastNoiseLite; import java.lang.reflect.Type; import java.util.Map; diff --git a/src/main/java/com/dfsek/terra/config/loaders/config/OreConfigLoader.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/OreConfigLoader.java similarity index 78% rename from src/main/java/com/dfsek/terra/config/loaders/config/OreConfigLoader.java rename to common/src/main/java/com/dfsek/terra/config/loaders/config/OreConfigLoader.java index 31a7e62a0..595cf28de 100644 --- a/src/main/java/com/dfsek/terra/config/loaders/config/OreConfigLoader.java +++ b/common/src/main/java/com/dfsek/terra/config/loaders/config/OreConfigLoader.java @@ -1,10 +1,9 @@ package com.dfsek.terra.config.loaders.config; -import com.dfsek.tectonic.exception.LoadException; import com.dfsek.tectonic.loading.ConfigLoader; import com.dfsek.tectonic.loading.TypeLoader; -import com.dfsek.terra.generation.items.ores.OreConfig; -import org.polydev.gaea.math.Range; +import com.dfsek.terra.api.math.Range; +import com.dfsek.terra.population.items.ores.OreConfig; import java.lang.reflect.Type; import java.util.Map; @@ -12,7 +11,7 @@ import java.util.Map; @SuppressWarnings("unchecked") public class OreConfigLoader implements TypeLoader { @Override - public OreConfig load(Type type, Object o, ConfigLoader configLoader) throws LoadException { + public OreConfig load(Type type, Object o, ConfigLoader configLoader) { Map map = (Map) o; Range amount = new Range(map.get("min"), map.get("max")); Range height = new Range(map.get("min-height"), map.get("max-height")); diff --git a/src/main/java/com/dfsek/terra/config/loaders/config/OreHolderLoader.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/OreHolderLoader.java similarity index 83% rename from src/main/java/com/dfsek/terra/config/loaders/config/OreHolderLoader.java rename to common/src/main/java/com/dfsek/terra/config/loaders/config/OreHolderLoader.java index 859d3c467..9986391c8 100644 --- a/src/main/java/com/dfsek/terra/config/loaders/config/OreHolderLoader.java +++ b/common/src/main/java/com/dfsek/terra/config/loaders/config/OreHolderLoader.java @@ -3,9 +3,9 @@ package com.dfsek.terra.config.loaders.config; import com.dfsek.tectonic.exception.LoadException; import com.dfsek.tectonic.loading.ConfigLoader; import com.dfsek.tectonic.loading.TypeLoader; -import com.dfsek.terra.generation.items.ores.Ore; -import com.dfsek.terra.generation.items.ores.OreConfig; -import com.dfsek.terra.generation.items.ores.OreHolder; +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 java.lang.reflect.Type; import java.util.Map; diff --git a/src/main/java/com/dfsek/terra/config/loaders/config/TreeLayerLoader.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/TreeLayerLoader.java similarity index 73% rename from src/main/java/com/dfsek/terra/config/loaders/config/TreeLayerLoader.java rename to common/src/main/java/com/dfsek/terra/config/loaders/config/TreeLayerLoader.java index 25c2cee82..123718bf0 100644 --- a/src/main/java/com/dfsek/terra/config/loaders/config/TreeLayerLoader.java +++ b/common/src/main/java/com/dfsek/terra/config/loaders/config/TreeLayerLoader.java @@ -3,23 +3,20 @@ package com.dfsek.terra.config.loaders.config; import com.dfsek.tectonic.exception.LoadException; import com.dfsek.tectonic.loading.ConfigLoader; import com.dfsek.tectonic.loading.TypeLoader; +import com.dfsek.terra.api.math.ProbabilityCollection; +import com.dfsek.terra.api.math.Range; +import com.dfsek.terra.api.math.noise.samplers.FastNoiseLite; +import com.dfsek.terra.api.world.tree.Tree; import com.dfsek.terra.config.loaders.Types; -import com.dfsek.terra.generation.items.tree.TreeLayer; -import org.polydev.gaea.GaeaPlugin; -import org.polydev.gaea.math.FastNoiseLite; -import org.polydev.gaea.math.ProbabilityCollection; -import org.polydev.gaea.math.Range; -import org.polydev.gaea.tree.Tree; +import com.dfsek.terra.population.items.tree.TreeLayer; import java.lang.reflect.Type; import java.util.Map; @SuppressWarnings("unchecked") public class TreeLayerLoader implements TypeLoader { - private final GaeaPlugin main; - public TreeLayerLoader(GaeaPlugin main) { - this.main = main; + public TreeLayerLoader() { } @Override @@ -33,9 +30,9 @@ public class TreeLayerLoader implements TypeLoader { if(map.containsKey("simplex-frequency")) { FastNoiseLite noiseLite = new FastNoiseLite(); noiseLite.setFrequency((Double) map.get("simplex-frequency")); - return new TreeLayer(density, range, items, noiseLite, main); + return new TreeLayer(density, range, items, noiseLite); } - return new TreeLayer(density, range, items, null, main); + return new TreeLayer(density, range, items, null); } } diff --git a/src/main/java/com/dfsek/terra/config/loaders/palette/CarverPaletteLoader.java b/common/src/main/java/com/dfsek/terra/config/loaders/palette/CarverPaletteLoader.java similarity index 92% rename from src/main/java/com/dfsek/terra/config/loaders/palette/CarverPaletteLoader.java rename to common/src/main/java/com/dfsek/terra/config/loaders/palette/CarverPaletteLoader.java index dfd74887c..ed5bd12fb 100644 --- a/src/main/java/com/dfsek/terra/config/loaders/palette/CarverPaletteLoader.java +++ b/common/src/main/java/com/dfsek/terra/config/loaders/palette/CarverPaletteLoader.java @@ -4,11 +4,11 @@ import com.dfsek.tectonic.config.Configuration; import com.dfsek.tectonic.exception.LoadException; import com.dfsek.tectonic.loading.ConfigLoader; import com.dfsek.tectonic.loading.TypeLoader; +import com.dfsek.terra.api.math.ProbabilityCollection; +import com.dfsek.terra.api.platform.block.BlockData; import com.dfsek.terra.carving.CarverPalette; import com.dfsek.terra.config.loaders.Types; import com.dfsek.terra.util.MaterialSet; -import org.bukkit.block.data.BlockData; -import org.polydev.gaea.math.ProbabilityCollection; import java.lang.reflect.Type; import java.util.List; diff --git a/src/main/java/com/dfsek/terra/config/loaders/palette/PaletteHolderLoader.java b/common/src/main/java/com/dfsek/terra/config/loaders/palette/PaletteHolderLoader.java similarity index 91% rename from src/main/java/com/dfsek/terra/config/loaders/palette/PaletteHolderLoader.java rename to common/src/main/java/com/dfsek/terra/config/loaders/palette/PaletteHolderLoader.java index fa9f9b826..6b5fc82a8 100644 --- a/src/main/java/com/dfsek/terra/config/loaders/palette/PaletteHolderLoader.java +++ b/common/src/main/java/com/dfsek/terra/config/loaders/palette/PaletteHolderLoader.java @@ -3,11 +3,11 @@ package com.dfsek.terra.config.loaders.palette; import com.dfsek.tectonic.exception.LoadException; import com.dfsek.tectonic.loading.ConfigLoader; import com.dfsek.tectonic.loading.TypeLoader; +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.world.palette.Palette; import com.dfsek.terra.biome.palette.PaletteHolder; import com.dfsek.terra.biome.palette.PaletteHolderBuilder; import com.dfsek.terra.config.loaders.Types; -import org.bukkit.block.data.BlockData; -import org.polydev.gaea.world.palette.Palette; import java.lang.reflect.Type; import java.util.List; diff --git a/src/main/java/com/dfsek/terra/config/loaders/palette/PaletteLayerLoader.java b/common/src/main/java/com/dfsek/terra/config/loaders/palette/PaletteLayerLoader.java similarity index 90% rename from src/main/java/com/dfsek/terra/config/loaders/palette/PaletteLayerLoader.java rename to common/src/main/java/com/dfsek/terra/config/loaders/palette/PaletteLayerLoader.java index d96cfb1fc..6513bef8d 100644 --- a/src/main/java/com/dfsek/terra/config/loaders/palette/PaletteLayerLoader.java +++ b/common/src/main/java/com/dfsek/terra/config/loaders/palette/PaletteLayerLoader.java @@ -3,10 +3,10 @@ package com.dfsek.terra.config.loaders.palette; import com.dfsek.tectonic.exception.LoadException; import com.dfsek.tectonic.loading.ConfigLoader; import com.dfsek.tectonic.loading.TypeLoader; +import com.dfsek.terra.api.math.ProbabilityCollection; +import com.dfsek.terra.api.platform.block.BlockData; import com.dfsek.terra.biome.palette.PaletteLayer; import com.dfsek.terra.config.loaders.Types; -import org.bukkit.block.data.BlockData; -import org.polydev.gaea.math.ProbabilityCollection; import java.lang.reflect.Type; import java.util.Map; diff --git a/src/main/java/com/dfsek/terra/config/templates/AbstractableTemplate.java b/common/src/main/java/com/dfsek/terra/config/templates/AbstractableTemplate.java similarity index 100% rename from src/main/java/com/dfsek/terra/config/templates/AbstractableTemplate.java rename to common/src/main/java/com/dfsek/terra/config/templates/AbstractableTemplate.java diff --git a/src/main/java/com/dfsek/terra/config/templates/BiomeGridTemplate.java b/common/src/main/java/com/dfsek/terra/config/templates/BiomeGridTemplate.java similarity index 76% rename from src/main/java/com/dfsek/terra/config/templates/BiomeGridTemplate.java rename to common/src/main/java/com/dfsek/terra/config/templates/BiomeGridTemplate.java index 2180f1e8a..b508f9c9f 100644 --- a/src/main/java/com/dfsek/terra/config/templates/BiomeGridTemplate.java +++ b/common/src/main/java/com/dfsek/terra/config/templates/BiomeGridTemplate.java @@ -2,24 +2,32 @@ package com.dfsek.terra.config.templates; import com.dfsek.tectonic.annotations.Abstractable; import com.dfsek.tectonic.annotations.Value; -import org.polydev.gaea.biome.Biome; +import com.dfsek.terra.api.world.biome.Biome; import java.util.List; @SuppressWarnings("unused") public class BiomeGridTemplate extends AbstractableTemplate { + @Value("id") + private String id; + /** + * A 2D array of {@link Biome} IDs that make up this grid. + */ @Value("grid") @Abstractable private List> grid; - @Value("id") - private String id; - + /** + * X frequency of noise function + */ @Value("frequency.x") @Abstractable private double xFreq; + /** + * Z frequency of noise function + */ @Value("frequency.z") @Abstractable private double zFreq; diff --git a/src/main/java/com/dfsek/terra/config/templates/BiomeTemplate.java b/common/src/main/java/com/dfsek/terra/config/templates/BiomeTemplate.java similarity index 78% rename from src/main/java/com/dfsek/terra/config/templates/BiomeTemplate.java rename to common/src/main/java/com/dfsek/terra/config/templates/BiomeTemplate.java index 824d7e310..61bc18964 100644 --- a/src/main/java/com/dfsek/terra/config/templates/BiomeTemplate.java +++ b/common/src/main/java/com/dfsek/terra/config/templates/BiomeTemplate.java @@ -5,20 +5,21 @@ import com.dfsek.tectonic.annotations.Default; import com.dfsek.tectonic.annotations.Value; import com.dfsek.tectonic.config.ValidatedConfigTemplate; import com.dfsek.tectonic.exception.ValidationException; +import com.dfsek.terra.api.math.parsii.BlankFunction; +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.block.MaterialData; +import com.dfsek.terra.api.platform.world.Biome; +import com.dfsek.terra.api.util.GlueList; +import com.dfsek.terra.api.world.palette.Palette; import com.dfsek.terra.biome.palette.PaletteHolder; import com.dfsek.terra.biome.palette.SinglePalette; import com.dfsek.terra.carving.UserDefinedCarver; import com.dfsek.terra.config.base.ConfigPack; -import com.dfsek.terra.generation.items.TerraStructure; -import com.dfsek.terra.generation.items.flora.FloraLayer; -import com.dfsek.terra.generation.items.ores.OreHolder; -import com.dfsek.terra.generation.items.tree.TreeLayer; -import com.dfsek.terra.math.BlankFunction; -import org.bukkit.Material; -import org.bukkit.block.Biome; -import org.bukkit.block.data.BlockData; -import org.polydev.gaea.util.GlueList; -import org.polydev.gaea.world.palette.Palette; +import com.dfsek.terra.population.items.TerraStructure; +import com.dfsek.terra.population.items.flora.FloraLayer; +import com.dfsek.terra.population.items.ores.OreHolder; +import com.dfsek.terra.population.items.tree.TreeLayer; import parsii.eval.Parser; import parsii.eval.Scope; import parsii.tokenizer.ParseException; @@ -31,6 +32,7 @@ import java.util.Map; public class BiomeTemplate extends AbstractableTemplate implements ValidatedConfigTemplate { private final ConfigPack pack; + @Value("id") private String id; @@ -38,6 +40,16 @@ public class BiomeTemplate extends AbstractableTemplate implements ValidatedConf @Default private String extend = null; + @Value("noise-2d.enable") + @Default + @Abstractable + private boolean noise2d = false; + + @Value("noise-2d.base") + @Default + @Abstractable + private double noise2dBase = 64; + @Value("palette") @Abstractable private PaletteHolder palette; @@ -74,7 +86,7 @@ public class BiomeTemplate extends AbstractableTemplate implements ValidatedConf @Value("ocean.palette") @Abstractable @Default - private Palette oceanPalette = new SinglePalette<>(Material.WATER.createBlockData()); + private Palette oceanPalette; @Value("elevation.equation") @Default @@ -104,12 +116,12 @@ public class BiomeTemplate extends AbstractableTemplate implements ValidatedConf @Value("slabs.palettes") @Abstractable @Default - private Map> slabPalettes; + private Map> slabPalettes; @Value("slabs.stair-palettes") @Abstractable @Default - private Map> stairPalettes; + private Map> stairPalettes; @Value("slant.threshold") @Abstractable @@ -145,16 +157,17 @@ public class BiomeTemplate extends AbstractableTemplate implements ValidatedConf return doSlabs; } - public Map> getSlabPalettes() { + public Map> getSlabPalettes() { return slabPalettes; } - public Map> getStairPalettes() { + public Map> getStairPalettes() { return stairPalettes; } - public BiomeTemplate(ConfigPack pack) { + public BiomeTemplate(ConfigPack pack, TerraPlugin main) { this.pack = pack; + oceanPalette = new SinglePalette<>(main.getWorldHandle().createBlockData("minecraft:water")); } public String getElevationEquation() { @@ -213,6 +226,14 @@ public class BiomeTemplate extends AbstractableTemplate implements ValidatedConf return oreHolder; } + public boolean isNoise2d() { + return noise2d; + } + + public double getNoise2dBase() { + return noise2dBase; + } + @Override public boolean validate() throws ValidationException { Parser tester = new Parser(); diff --git a/src/main/java/com/dfsek/terra/config/templates/CarverTemplate.java b/common/src/main/java/com/dfsek/terra/config/templates/CarverTemplate.java similarity index 94% rename from src/main/java/com/dfsek/terra/config/templates/CarverTemplate.java rename to common/src/main/java/com/dfsek/terra/config/templates/CarverTemplate.java index fba1810ac..4f9bf1b12 100644 --- a/src/main/java/com/dfsek/terra/config/templates/CarverTemplate.java +++ b/common/src/main/java/com/dfsek/terra/config/templates/CarverTemplate.java @@ -3,10 +3,10 @@ package com.dfsek.terra.config.templates; import com.dfsek.tectonic.annotations.Abstractable; import com.dfsek.tectonic.annotations.Default; import com.dfsek.tectonic.annotations.Value; +import com.dfsek.terra.api.math.Range; +import com.dfsek.terra.api.platform.block.MaterialData; import com.dfsek.terra.carving.CarverPalette; import com.dfsek.terra.util.MaterialSet; -import org.bukkit.Material; -import org.polydev.gaea.math.Range; import java.util.HashMap; import java.util.Map; @@ -104,7 +104,7 @@ public class CarverTemplate extends AbstractableTemplate { @Value("shift") @Abstractable @Default - private Map shift = new HashMap<>(); + private Map shift = new HashMap<>(); @Value("update") @Abstractable @@ -187,7 +187,7 @@ public class CarverTemplate extends AbstractableTemplate { return inner; } - public Map getShift() { + public Map getShift() { return shift; } diff --git a/src/main/java/com/dfsek/terra/config/templates/FloraTemplate.java b/common/src/main/java/com/dfsek/terra/config/templates/FloraTemplate.java similarity index 93% rename from src/main/java/com/dfsek/terra/config/templates/FloraTemplate.java rename to common/src/main/java/com/dfsek/terra/config/templates/FloraTemplate.java index 26f38b7a7..19d91544e 100644 --- a/src/main/java/com/dfsek/terra/config/templates/FloraTemplate.java +++ b/common/src/main/java/com/dfsek/terra/config/templates/FloraTemplate.java @@ -4,9 +4,8 @@ import com.dfsek.tectonic.annotations.Abstractable; import com.dfsek.tectonic.annotations.Default; import com.dfsek.tectonic.annotations.Value; import com.dfsek.terra.biome.palette.PaletteLayer; -import com.dfsek.terra.generation.items.flora.TerraFlora; +import com.dfsek.terra.population.items.flora.TerraFlora; import com.dfsek.terra.util.MaterialSet; -import org.bukkit.Material; import java.util.List; @@ -28,7 +27,7 @@ public class FloraTemplate extends AbstractableTemplate { @Value("replaceable") @Abstractable @Default - private MaterialSet replaceable = MaterialSet.singleton(Material.AIR); + private MaterialSet replaceable = new MaterialSet(); @Value("irrigable") @Abstractable diff --git a/src/main/java/com/dfsek/terra/config/templates/OreTemplate.java b/common/src/main/java/com/dfsek/terra/config/templates/OreTemplate.java similarity index 91% rename from src/main/java/com/dfsek/terra/config/templates/OreTemplate.java rename to common/src/main/java/com/dfsek/terra/config/templates/OreTemplate.java index c11d81867..64465e5c7 100644 --- a/src/main/java/com/dfsek/terra/config/templates/OreTemplate.java +++ b/common/src/main/java/com/dfsek/terra/config/templates/OreTemplate.java @@ -3,10 +3,10 @@ package com.dfsek.terra.config.templates; import com.dfsek.tectonic.annotations.Abstractable; import com.dfsek.tectonic.annotations.Default; import com.dfsek.tectonic.annotations.Value; -import com.dfsek.terra.generation.items.ores.Ore; +import com.dfsek.terra.api.math.Range; +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.population.items.ores.Ore; import com.dfsek.terra.util.MaterialSet; -import org.bukkit.block.data.BlockData; -import org.polydev.gaea.math.Range; @SuppressWarnings({"unused", "FieldMayBeFinal"}) public class OreTemplate extends AbstractableTemplate { diff --git a/src/main/java/com/dfsek/terra/config/templates/PaletteTemplate.java b/common/src/main/java/com/dfsek/terra/config/templates/PaletteTemplate.java similarity index 100% rename from src/main/java/com/dfsek/terra/config/templates/PaletteTemplate.java rename to common/src/main/java/com/dfsek/terra/config/templates/PaletteTemplate.java diff --git a/common/src/main/java/com/dfsek/terra/config/templates/StructureTemplate.java b/common/src/main/java/com/dfsek/terra/config/templates/StructureTemplate.java new file mode 100644 index 000000000..8da29ddf8 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/config/templates/StructureTemplate.java @@ -0,0 +1,56 @@ +package com.dfsek.terra.config.templates; + +import com.dfsek.tectonic.annotations.Abstractable; +import com.dfsek.tectonic.annotations.Default; +import com.dfsek.tectonic.annotations.Value; +import com.dfsek.tectonic.config.ConfigTemplate; +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.structures.script.StructureScript; +import com.dfsek.terra.api.util.GlueList; + +import java.util.List; + +@SuppressWarnings({"unused", "FieldMayBeFinal"}) +public class StructureTemplate extends AbstractableTemplate implements ConfigTemplate { + @Value("id") + private String id; + + @Value("scripts") + @Abstractable + private ProbabilityCollection structure; + + @Value("spawn.start") + @Abstractable + private Range y; + + @Value("spawn") + @Abstractable + private GridSpawn spawn; + + @Value("features") + @Abstractable + @Default + private List features = new GlueList<>(); + + public String getID() { + return id; + } + + public ProbabilityCollection getStructures() { + return structure; + } + + public Range getY() { + return y; + } + + public List getFeatures() { + return features; + } + + public GridSpawn getSpawn() { + return spawn; + } +} diff --git a/src/main/java/com/dfsek/terra/config/templates/TreeTemplate.java b/common/src/main/java/com/dfsek/terra/config/templates/TreeTemplate.java similarity index 71% rename from src/main/java/com/dfsek/terra/config/templates/TreeTemplate.java rename to common/src/main/java/com/dfsek/terra/config/templates/TreeTemplate.java index f41d18d4a..33702c5a4 100644 --- a/src/main/java/com/dfsek/terra/config/templates/TreeTemplate.java +++ b/common/src/main/java/com/dfsek/terra/config/templates/TreeTemplate.java @@ -3,15 +3,15 @@ package com.dfsek.terra.config.templates; import com.dfsek.tectonic.annotations.Abstractable; import com.dfsek.tectonic.annotations.Default; import com.dfsek.tectonic.annotations.Value; -import com.dfsek.terra.structure.Structure; +import com.dfsek.terra.api.math.ProbabilityCollection; +import com.dfsek.terra.api.structures.script.StructureScript; import com.dfsek.terra.util.MaterialSet; -import org.polydev.gaea.math.ProbabilityCollection; @SuppressWarnings({"unused", "FieldMayBeFinal"}) public class TreeTemplate extends AbstractableTemplate { - @Value("files") + @Value("scripts") @Abstractable - private ProbabilityCollection structures; + private ProbabilityCollection structure; @Value("id") private String id; @@ -25,8 +25,8 @@ public class TreeTemplate extends AbstractableTemplate { @Abstractable private MaterialSet spawnable; - public ProbabilityCollection getStructures() { - return structures; + public ProbabilityCollection getStructures() { + return structure; } public String getID() { diff --git a/src/main/java/com/dfsek/terra/debug/Debug.java b/common/src/main/java/com/dfsek/terra/debug/Debug.java similarity index 100% rename from src/main/java/com/dfsek/terra/debug/Debug.java rename to common/src/main/java/com/dfsek/terra/debug/Debug.java diff --git a/src/main/java/com/dfsek/terra/debug/gui/DebugFrame.java b/common/src/main/java/com/dfsek/terra/debug/gui/DebugFrame.java similarity index 80% rename from src/main/java/com/dfsek/terra/debug/gui/DebugFrame.java rename to common/src/main/java/com/dfsek/terra/debug/gui/DebugFrame.java index 31e860b62..cce1b0a80 100644 --- a/src/main/java/com/dfsek/terra/debug/gui/DebugFrame.java +++ b/common/src/main/java/com/dfsek/terra/debug/gui/DebugFrame.java @@ -1,13 +1,6 @@ package com.dfsek.terra.debug.gui; -import com.dfsek.terra.Terra; -import com.dfsek.terra.biome.UserDefinedBiome; -import com.dfsek.terra.generation.TerraChunkGenerator; -import com.dfsek.terra.image.ImageLoader; -import net.jafama.FastMath; -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; -import org.polydev.gaea.generation.GenerationPhase; +import com.dfsek.terra.api.platform.TerraPlugin; import javax.swing.*; import java.awt.*; @@ -20,9 +13,9 @@ public class DebugFrame extends JFrame implements ActionListener { private final int x; private final int z; private final BufferedImage img; - private final Terra main; + private final TerraPlugin main; - public DebugFrame(BufferedImage image, String s, Terra main) { + public DebugFrame(BufferedImage image, String s, TerraPlugin main) { super(s); this.x = image.getWidth(); this.z = image.getHeight(); @@ -34,8 +27,8 @@ public class DebugFrame extends JFrame implements ActionListener { @Override public void paint(Graphics g) { super.paintComponents(g); + /* for(Player p : Bukkit.getOnlinePlayers()) { - if(!(p.getWorld().getGenerator() instanceof TerraChunkGenerator)) break; int xp = (int) (((double) FastMath.floorMod(p.getLocation().getBlockX() - (img.getWidth() / 2), x) / x) * getWidth()); int zp = (int) (((double) FastMath.floorMod(p.getLocation().getBlockZ() - (img.getHeight() / 2), z) / z) * getHeight()); ImageLoader loader = main.getWorld(p.getWorld()).getConfig().getTemplate().getImageLoader(); @@ -53,6 +46,8 @@ public class DebugFrame extends JFrame implements ActionListener { g.setColor(Color.RED); g.fillOval(xp + 3, zp + 3, 5, 5); } + + */ } @Override diff --git a/src/main/java/com/dfsek/terra/debug/gui/DebugGUI.java b/common/src/main/java/com/dfsek/terra/debug/gui/DebugGUI.java similarity index 85% rename from src/main/java/com/dfsek/terra/debug/gui/DebugGUI.java rename to common/src/main/java/com/dfsek/terra/debug/gui/DebugGUI.java index ecca7eace..77a22e76e 100644 --- a/src/main/java/com/dfsek/terra/debug/gui/DebugGUI.java +++ b/common/src/main/java/com/dfsek/terra/debug/gui/DebugGUI.java @@ -1,6 +1,6 @@ package com.dfsek.terra.debug.gui; -import com.dfsek.terra.Terra; +import com.dfsek.terra.api.platform.TerraPlugin; import javax.swing.*; import java.awt.*; @@ -9,9 +9,9 @@ import java.awt.image.BufferedImage; public class DebugGUI extends Thread { private final BufferedImage img; - private final Terra main; + private final TerraPlugin main; - public DebugGUI(BufferedImage img, Terra main) { + public DebugGUI(BufferedImage img, TerraPlugin main) { this.img = img; this.main = main; } diff --git a/common/src/main/java/com/dfsek/terra/generation/MasterChunkGenerator.java b/common/src/main/java/com/dfsek/terra/generation/MasterChunkGenerator.java new file mode 100644 index 000000000..a2265b5a2 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/generation/MasterChunkGenerator.java @@ -0,0 +1,229 @@ +package com.dfsek.terra.generation; + +import com.dfsek.terra.TerraWorld; +import com.dfsek.terra.api.math.vector.Vector3; +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.block.BlockFace; +import com.dfsek.terra.api.platform.block.MaterialData; +import com.dfsek.terra.api.platform.block.data.Bisected; +import com.dfsek.terra.api.platform.block.data.Slab; +import com.dfsek.terra.api.platform.block.data.Stairs; +import com.dfsek.terra.api.platform.block.data.Waterlogged; +import com.dfsek.terra.api.platform.generator.ChunkGenerator; +import com.dfsek.terra.api.platform.world.BiomeGrid; +import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.api.profiler.ProfileFuture; +import com.dfsek.terra.api.world.biome.Biome; +import com.dfsek.terra.api.world.generation.GenerationPhase; +import com.dfsek.terra.api.world.generation.TerraChunkGenerator; +import com.dfsek.terra.api.world.palette.Palette; +import com.dfsek.terra.biome.UserDefinedBiome; +import com.dfsek.terra.biome.palette.SinglePalette; +import com.dfsek.terra.config.base.ConfigPack; +import com.dfsek.terra.config.templates.BiomeTemplate; +import com.dfsek.terra.generation.math.Sampler; +import com.dfsek.terra.generation.math.SamplerCache; +import com.dfsek.terra.util.PaletteUtil; +import org.jetbrains.annotations.NotNull; + +import java.util.Map; +import java.util.Random; + +public class MasterChunkGenerator implements TerraChunkGenerator { + + + private final ConfigPack configPack; + private final TerraPlugin main; + private final MaterialData water; + private final SinglePalette blank; + + private final SamplerCache cache; + + + public MasterChunkGenerator(ConfigPack c, TerraPlugin main, SamplerCache cache) { + this.configPack = c; + this.main = main; + water = main.getWorldHandle().createMaterialData("minecraft:water"); + blank = new SinglePalette<>(main.getWorldHandle().createBlockData("minecraft:air")); + this.cache = cache; + } + + @Override + public boolean isParallelCapable() { + return true; + } + + @Override + public boolean shouldGenerateCaves() { + return configPack.getTemplate().vanillaCaves(); + } + + @Override + public boolean shouldGenerateDecorations() { + return configPack.getTemplate().vanillaDecorations(); + } + + @Override + public boolean shouldGenerateMobs() { + return configPack.getTemplate().vanillaMobs(); + } + + @Override + public boolean shouldGenerateStructures() { + return configPack.getTemplate().vanillaStructures(); + } + + @Override + public ConfigPack getConfigPack() { + return configPack; + } + + @Override + public TerraPlugin getMain() { + return main; + } + + @Override + @SuppressWarnings({"try"}) + public ChunkGenerator.ChunkData generateChunkData(@NotNull World world, Random random, int chunkX, int chunkZ, ChunkGenerator.ChunkData chunk) { + TerraWorld tw = main.getWorld(world); + com.dfsek.terra.api.world.biome.BiomeGrid grid = tw.getGrid(); + try(ProfileFuture ignore = tw.getProfiler().measure("TotalChunkGenTime")) { + if(!tw.isSafe()) return chunk; + int xOrig = (chunkX << 4); + int zOrig = (chunkZ << 4); + + Sampler sampler = cache.getChunk(world, chunkX, chunkZ); + + for(byte x = 0; x < 16; x++) { + for(byte z = 0; z < 16; z++) { + int paletteLevel = 0; + + int cx = xOrig + x; + int cz = zOrig + z; + + Biome b = grid.getBiome(xOrig + x, zOrig + z, GenerationPhase.PALETTE_APPLY); + BiomeTemplate c = ((UserDefinedBiome) b).getConfig(); + + int sea = c.getSeaLevel(); + Palette seaPalette = c.getOceanPalette(); + + boolean justSet = false; + BlockData data = null; + for(int y = world.getMaxHeight() - 1; y >= 0; y--) { + if(sampler.sample(x, y, z) > 0) { + justSet = true; + data = PaletteUtil.getPalette(x, y, z, c, sampler).get(paletteLevel, cx, cz); + chunk.setBlock(x, y, z, data); + if(paletteLevel == 0 && c.doSlabs() && y < 255) { + prepareBlockPartFloor(data, chunk.getBlockData(x, y + 1, z), chunk, new Vector3(x, y + 1, z), c.getSlabPalettes(), + c.getStairPalettes(), c.getSlabThreshold(), sampler); + } + paletteLevel++; + } else if(y <= sea) { + chunk.setBlock(x, y, z, seaPalette.get(sea - y, x + xOrig, z + zOrig)); + if(justSet && c.doSlabs()) { + prepareBlockPartCeiling(data, chunk.getBlockData(x, y, z), chunk, new Vector3(x, y, z), c.getSlabPalettes(), c.getStairPalettes(), c.getSlabThreshold(), sampler); + } + justSet = false; + paletteLevel = 0; + } else { + if(justSet && c.doSlabs()) { + prepareBlockPartCeiling(data, chunk.getBlockData(x, y, z), chunk, new Vector3(x, y, z), c.getSlabPalettes(), c.getStairPalettes(), c.getSlabThreshold(), sampler); + } + justSet = false; + paletteLevel = 0; + } + } + } + } + return chunk; + } + } + + private void prepareBlockPartFloor(BlockData down, BlockData orig, ChunkGenerator.ChunkData chunk, Vector3 block, Map> slabs, + Map> stairs, double thresh, Sampler sampler) { + if(sampler.sample(block.getBlockX(), block.getBlockY() - 0.4, block.getBlockZ()) > thresh) { + if(stairs != null) { + Palette stairPalette = stairs.get(down.getMaterial()); + if(stairPalette != null) { + BlockData stair = stairPalette.get(0, block.getBlockX(), block.getBlockZ()).clone(); + if(stair instanceof Stairs) { + Stairs stairNew = (Stairs) stair; + if(placeStair(orig, chunk, block, thresh, sampler, stairNew)) return; // Successfully placed part. + } + } + } + BlockData slab = slabs.getOrDefault(down.getMaterial(), blank).get(0, block.getBlockX(), block.getBlockZ()); + if(slab instanceof Waterlogged) { + ((Waterlogged) slab).setWaterlogged(orig.matches(water)); + } else if(orig.matches(water)) return; + chunk.setBlock(block.getBlockX(), block.getBlockY(), block.getBlockZ(), slab); + } + } + + private void prepareBlockPartCeiling(BlockData up, BlockData orig, ChunkGenerator.ChunkData chunk, Vector3 block, Map> slabs, + Map> stairs, double thresh, Sampler sampler) { + if(sampler.sample(block.getBlockX(), block.getBlockY() + 0.4, block.getBlockZ()) > thresh) { + if(stairs != null) { + Palette stairPalette = stairs.get(up.getMaterial()); + if(stairPalette != null) { + BlockData stair = stairPalette.get(0, block.getBlockX(), block.getBlockZ()).clone(); + if(stair instanceof Stairs) { + Stairs stairNew = (Stairs) stair.clone(); + stairNew.setHalf(Bisected.Half.TOP); + if(placeStair(orig, chunk, block, thresh, sampler, stairNew)) return; // Successfully placed part. + } + } + } + BlockData slab = slabs.getOrDefault(up.getMaterial(), blank).get(0, block.getBlockX(), block.getBlockZ()).clone(); + if(slab instanceof Bisected) ((Bisected) slab).setHalf(Bisected.Half.TOP); + if(slab instanceof Slab) ((Slab) slab).setType(Slab.Type.TOP); + if(slab instanceof Waterlogged) { + ((Waterlogged) slab).setWaterlogged(orig.matches(water)); + } else if(orig.matches(water)) return; // Only replace water if waterlogged. + chunk.setBlock(block.getBlockX(), block.getBlockY(), block.getBlockZ(), slab); + } + } + + private boolean placeStair(BlockData orig, ChunkGenerator.ChunkData chunk, Vector3 block, double thresh, Sampler sampler, Stairs stairNew) { + + if(sampler.sample(block.getBlockX() - 0.55, block.getBlockY(), block.getBlockZ()) > thresh) { + + stairNew.setFacing(BlockFace.WEST); + } else if(sampler.sample(block.getBlockX(), block.getBlockY(), block.getBlockZ() - 0.55) > thresh) { + stairNew.setFacing(BlockFace.NORTH); + } else if(sampler.sample(block.getBlockX(), block.getBlockY(), block.getBlockZ() + 0.55) > thresh) { + stairNew.setFacing(BlockFace.SOUTH); + } else if(sampler.sample(block.getBlockX() + 0.55, block.getBlockY(), block.getBlockZ()) > thresh) { + stairNew.setFacing(BlockFace.EAST); + } else stairNew = null; + if(stairNew != null) { + if(orig.matches(water)) stairNew.setWaterlogged(orig.matches(water)); + chunk.setBlock(block.getBlockX(), block.getBlockY(), block.getBlockZ(), stairNew); + return true; + } + return false; + } + + @Override + public void generateBiomes(@NotNull World world, @NotNull Random random, int chunkX, int chunkZ, @NotNull BiomeGrid biome) { + int xOrig = (chunkX << 4); + int zOrig = (chunkZ << 4); + com.dfsek.terra.api.world.biome.BiomeGrid grid = main.getWorld(world).getGrid(); + for(int x = 0; x < 4; x++) { + for(byte z = 0; z < 4; z++) { + int cx = xOrig + (x << 2); + int cz = zOrig + (z << 2); + Biome b = grid.getBiome(cx, cz, GenerationPhase.PALETTE_APPLY); + + biome.setBiome(x << 2, z << 2, b.getVanillaBiome()); + } + } + } + + public SamplerCache getCache() { + return cache; + } +} diff --git a/src/main/java/com/dfsek/terra/generation/config/NoiseBuilder.java b/common/src/main/java/com/dfsek/terra/generation/config/NoiseBuilder.java similarity index 97% rename from src/main/java/com/dfsek/terra/generation/config/NoiseBuilder.java rename to common/src/main/java/com/dfsek/terra/generation/config/NoiseBuilder.java index e8e957a43..b86a6d764 100644 --- a/src/main/java/com/dfsek/terra/generation/config/NoiseBuilder.java +++ b/common/src/main/java/com/dfsek/terra/generation/config/NoiseBuilder.java @@ -3,7 +3,8 @@ package com.dfsek.terra.generation.config; import com.dfsek.tectonic.annotations.Default; import com.dfsek.tectonic.annotations.Value; import com.dfsek.tectonic.config.ConfigTemplate; -import org.polydev.gaea.math.FastNoiseLite; +import com.dfsek.terra.api.math.noise.samplers.FastNoiseLite; +import com.dfsek.terra.api.math.noise.samplers.NoiseSampler; public class NoiseBuilder implements ConfigTemplate { @Value("type") @@ -70,7 +71,7 @@ public class NoiseBuilder implements ConfigTemplate { @Default private int dimensions = 2; - public FastNoiseLite build(int seed) { + public NoiseSampler build(int seed) { FastNoiseLite noise = new FastNoiseLite(seed + seedOffset); if(!fractalType.equals(FastNoiseLite.FractalType.None)) { noise.setFractalType(fractalType); diff --git a/src/main/java/com/dfsek/terra/generation/config/WorldGenerator.java b/common/src/main/java/com/dfsek/terra/generation/config/WorldGenerator.java similarity index 75% rename from src/main/java/com/dfsek/terra/generation/config/WorldGenerator.java rename to common/src/main/java/com/dfsek/terra/generation/config/WorldGenerator.java index 576ab7f28..f3faef1e3 100644 --- a/src/main/java/com/dfsek/terra/generation/config/WorldGenerator.java +++ b/common/src/main/java/com/dfsek/terra/generation/config/WorldGenerator.java @@ -1,15 +1,12 @@ package com.dfsek.terra.generation.config; +import com.dfsek.terra.api.math.noise.NoiseFunction2; +import com.dfsek.terra.api.math.noise.NoiseFunction3; +import com.dfsek.terra.api.math.parsii.RandomFunction; +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.world.biome.Generator; +import com.dfsek.terra.api.world.palette.Palette; import com.dfsek.terra.biome.palette.PaletteHolder; -import com.dfsek.terra.math.NoiseFunction2; -import com.dfsek.terra.math.NoiseFunction3; -import com.dfsek.terra.math.RandomFunction; -import org.bukkit.World; -import org.bukkit.block.data.BlockData; -import org.polydev.gaea.biome.Generator; -import org.polydev.gaea.math.FastNoiseLite; -import org.polydev.gaea.math.Interpolator; -import org.polydev.gaea.world.palette.Palette; import parsii.eval.Expression; import parsii.eval.Parser; import parsii.eval.Scope; @@ -18,13 +15,12 @@ import parsii.tokenizer.ParseException; import java.util.Map; -public class WorldGenerator extends Generator { +public class WorldGenerator implements Generator { @SuppressWarnings({"unchecked", "rawtypes", "RedundantSuppression"}) private final PaletteHolder palettes; @SuppressWarnings({"unchecked", "rawtypes", "RedundantSuppression"}) private final PaletteHolder slantPalettes; - private final boolean preventSmooth; private final Expression noiseExp; private final Expression elevationExp; private final Variable xVar; @@ -33,9 +29,17 @@ public class WorldGenerator extends Generator { private final Variable elevationXVar; private final Variable elevationZVar; private final boolean elevationInterpolation; + private final boolean noise2d; + private final double base; + + public WorldGenerator(long seed, String equation, String elevateEquation, Scope vScope, Map noiseBuilders, PaletteHolder palettes, PaletteHolder slantPalettes, boolean elevationInterpolation, boolean noise2d, double base) { + this.palettes = palettes; + this.slantPalettes = slantPalettes; + + this.elevationInterpolation = elevationInterpolation; + this.noise2d = noise2d; + this.base = base; - @SuppressWarnings({"rawtypes", "unchecked"}) - public WorldGenerator(long seed, String equation, String elevateEquation, Scope vScope, Map noiseBuilders, PaletteHolder palettes, PaletteHolder slantPalettes, boolean preventSmooth, boolean elevationInterpolation) { Parser p = new Parser(); p.registerFunction("rand", new RandomFunction()); Parser ep = new Parser(); @@ -43,16 +47,11 @@ public class WorldGenerator extends Generator { Scope s = new Scope().withParent(vScope); xVar = s.create("x"); - yVar = s.create("y"); + if(!noise2d) yVar = s.create("y"); + else yVar = null; zVar = s.create("z"); s.create("seed").setValue(seed); - this.preventSmooth = preventSmooth; - - this.palettes = palettes; - this.slantPalettes = slantPalettes; - - this.elevationInterpolation = elevationInterpolation; for(Map.Entry e : noiseBuilders.entrySet()) { switch(e.getValue().getDimensions()) { @@ -91,17 +90,9 @@ public class WorldGenerator extends Generator { } @Override - public synchronized double getNoise(FastNoiseLite fastNoiseLite, World world, int x, int z) { + public synchronized double getNoise(int x, int y, int z) { xVar.setValue(x); - yVar.setValue(0); - zVar.setValue(z); - return noiseExp.evaluate(); - } - - @Override - public synchronized double getNoise(FastNoiseLite fastNoiseLite, World world, int x, int y, int z) { - xVar.setValue(x); - yVar.setValue(y); + if(!noise2d) yVar.setValue(y); zVar.setValue(z); return noiseExp.evaluate(); } @@ -116,21 +107,21 @@ public class WorldGenerator extends Generator { return palettes.getPalette(y); } + @Override + public boolean is2d() { + return noise2d; + } + + @Override + public double get2dBase() { + return base; + } + public Palette getSlantPalette(int y) { return slantPalettes.getPalette(y); } - @Override - public boolean useMinimalInterpolation() { - return preventSmooth; - } - - @Override - public Interpolator.Type getInterpolationType() { - return Interpolator.Type.LINEAR; - } - public boolean interpolateElevation() { return elevationInterpolation; } diff --git a/common/src/main/java/com/dfsek/terra/generation/math/Sampler.java b/common/src/main/java/com/dfsek/terra/generation/math/Sampler.java new file mode 100644 index 000000000..7d1773008 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/generation/math/Sampler.java @@ -0,0 +1,21 @@ +package com.dfsek.terra.generation.math; + +import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.biome.grid.master.TerraBiomeGrid; +import com.dfsek.terra.generation.math.interpolation.ChunkInterpolator; +import com.dfsek.terra.generation.math.interpolation.ElevationInterpolator; +import net.jafama.FastMath; + +public class Sampler { + private final ChunkInterpolator interpolator; + private final ElevationInterpolator elevationInterpolator; + + public Sampler(int x, int z, TerraBiomeGrid grid, World world, int elevationSmooth, int generationSmooth) { + this.interpolator = new ChunkInterpolator(world, x, z, grid, generationSmooth); + this.elevationInterpolator = new ElevationInterpolator(world, x, z, grid, elevationSmooth); + } + + public double sample(double x, double y, double z) { + return interpolator.getNoise(x, y, z) + elevationInterpolator.getElevation(FastMath.roundToInt(x), FastMath.roundToInt(z)); + } +} diff --git a/common/src/main/java/com/dfsek/terra/generation/math/SamplerCache.java b/common/src/main/java/com/dfsek/terra/generation/math/SamplerCache.java new file mode 100644 index 000000000..421a7d2e9 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/generation/math/SamplerCache.java @@ -0,0 +1,63 @@ +package com.dfsek.terra.generation.math; + +import com.dfsek.terra.TerraWorld; +import com.dfsek.terra.api.math.MathUtil; +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.platform.world.World; +import net.jafama.FastMath; + +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; + +public class SamplerCache { + private final Map containerMap; + private final TerraPlugin main; + + public SamplerCache(TerraPlugin main) { + containerMap = new HashMap<>(); + this.main = main; + } + + public Sampler get(World world, int x, int z) { + return containerMap.computeIfAbsent(world.getSeed(), seed -> new Container(world)).get(x, z); + } + + public Sampler getChunk(World world, int chunkX, int chunkZ) { + return containerMap.computeIfAbsent(world.getSeed(), seed -> new Container(world)).getChunk(chunkX, chunkZ); + } + + public void clear() { + containerMap.clear(); + } + + private class Container { + private final World world; + private final TerraWorld terraWorld; + private final Map cache = Collections.synchronizedMap(new LinkedHashMap() { + @Override + protected boolean removeEldestEntry(Map.Entry eldest) { + return this.size() > main.getTerraConfig().getSamplerCache(); + } + }); + + private Container(World world) { + this.world = world; + terraWorld = main.getWorld(world); + } + + public Sampler get(int x, int z) { + int cx = FastMath.floorDiv(x, 16); + int cz = FastMath.floorDiv(z, 16); + return getChunk(cx, cz); + } + + public Sampler getChunk(int cx, int cz) { + long key = MathUtil.squash(cx, cz); + synchronized(cache) { + return cache.computeIfAbsent(key, k -> new Sampler(cx, cz, terraWorld.getGrid(), world, terraWorld.getConfig().getTemplate().getBaseBlend(), terraWorld.getConfig().getTemplate().getElevationBlend())); + } + } + } +} diff --git a/common/src/main/java/com/dfsek/terra/generation/math/interpolation/ChunkInterpolator.java b/common/src/main/java/com/dfsek/terra/generation/math/interpolation/ChunkInterpolator.java new file mode 100644 index 000000000..e97e9d151 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/generation/math/interpolation/ChunkInterpolator.java @@ -0,0 +1,128 @@ +package com.dfsek.terra.generation.math.interpolation; + +import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.api.world.biome.Generator; +import com.dfsek.terra.api.world.generation.GenerationPhase; +import com.dfsek.terra.biome.grid.master.TerraBiomeGrid; +import net.jafama.FastMath; + +/** + * Class to abstract away the 16 Interpolators needed to generate a chunk.
+ * Contains method to get interpolated noise at a coordinate within the chunk. + */ +public class ChunkInterpolator { + private final Interpolator3[][][] interpGrid = new Interpolator3[4][64][4]; + private final Generator[][] gens = new Generator[7][7]; + private final boolean[][] needsBiomeInterp = new boolean[5][5]; + private final double[][][] noiseStorage = new double[7][7][65]; + private final int smooth; + + /** + * Instantiates a 3D ChunkInterpolator at a pair of chunk coordinates. + * + * @param chunkX X coordinate of the chunk. + * @param chunkZ Z coordinate of the chunk. + * @param grid BiomeGrid to use for noise fetching. + */ + public ChunkInterpolator(World w, int chunkX, int chunkZ, TerraBiomeGrid grid, int smooth) { + int xOrigin = chunkX << 4; + int zOrigin = chunkZ << 4; + this.smooth = smooth; + + for(int x = -1; x < 6; x++) { + for(int z = -1; z < 6; z++) { + gens[x + 1][z + 1] = grid.getBiome(xOrigin + (x * smooth), zOrigin + (z * smooth), GenerationPhase.BASE).getGenerator(w); + } + } + + for(int x = 0; x < 5; x++) { + for(int z = 0; z < 5; z++) { + needsBiomeInterp[x][z] = compareGens(x + 1, z + 1); + } + } + + for(byte x = -1; x < 6; x++) { + for(byte z = -1; z < 6; z++) { + Generator generator = gens[x + 1][z + 1]; + if(generator.is2d()) { + double n = generator.getNoise((x * smooth) + xOrigin, 0, (z * smooth) + zOrigin); + for(int y = 0; y < 65; y++) { + noiseStorage[x + 1][z + 1][y] = n + noise2dExtrude(y << 2, generator.get2dBase()); + } + } else { + for(int y = 0; y < 65; y++) { + noiseStorage[x + 1][z + 1][y] = generator.getNoise((x * smooth) + xOrigin, y << 2, (z * smooth) + zOrigin); + } + } + } + } + + for(byte x = 0; x < 4; x++) { + for(byte z = 0; z < 4; z++) { + for(int y = 0; y < 64; y++) { + interpGrid[x][y][z] = new Interpolator3( + biomeAvg(x, y, z), + biomeAvg(x + 1, y, z), + biomeAvg(x, y + 1, z), + biomeAvg(x + 1, y + 1, z), + biomeAvg(x, y, z + 1), + biomeAvg(x + 1, y, z + 1), + biomeAvg(x, y + 1, z + 1), + biomeAvg(x + 1, y + 1, z + 1)); + } + } + } + } + + private static int reRange(int value, int high) { + return FastMath.max(FastMath.min(value, high), 0); + } + + private boolean compareGens(int x, int z) { + Generator comp = gens[x][z]; + if(!comp.equals(gens[x + 1][z])) return true; + + if(!comp.equals(gens[x][z + 1])) return true; + + if(!comp.equals(gens[x - 1][z])) return true; + + if(!comp.equals(gens[x][z - 1])) return true; + + if(!comp.equals(gens[x + 1][z + 1])) return true; + + if(!comp.equals(gens[x - 1][z - 1])) return true; + + if(!comp.equals(gens[x + 1][z - 1])) return true; + + return !comp.equals(gens[x - 1][z + 1]); + } + + private double biomeAvg(int x, int y, int z) { + if(needsBiomeInterp[x][z]) { + double t = 0d; + for(int xi = 0; xi <= 2; xi++) { + for(int zi = 0; zi <= 2; zi++) { + t += noiseStorage[x + xi][z + zi][y]; + } + } + return t / 9d; + } else { + return noiseStorage[x + 1][z + 1][y]; + } + } + + /** + * Gets the noise at a pair of internal chunk coordinates. + * + * @param x The internal X coordinate (0-15). + * @param z The internal Z coordinate (0-15). + * @return double - The interpolated noise at the coordinates. + */ + public double getNoise(double x, double y, double z) { + return interpGrid[reRange(((int) x) / smooth, 3)][reRange(((int) y) / 4, 63)][reRange(((int) z) / smooth, 3)].trilerp((x % smooth) / smooth, (y % 4) / 4, (z % smooth) / smooth); + } + + private static double noise2dExtrude(double y, double base) { + return ((-FastMath.pow2((y / base))) + 1); + } +} diff --git a/common/src/main/java/com/dfsek/terra/generation/math/interpolation/ElevationInterpolator.java b/common/src/main/java/com/dfsek/terra/generation/math/interpolation/ElevationInterpolator.java new file mode 100644 index 000000000..f037c7b94 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/generation/math/interpolation/ElevationInterpolator.java @@ -0,0 +1,85 @@ +package com.dfsek.terra.generation.math.interpolation; + +import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.api.world.biome.BiomeGrid; +import com.dfsek.terra.api.world.generation.GenerationPhase; +import com.dfsek.terra.generation.config.WorldGenerator; +import net.jafama.FastMath; + +public class ElevationInterpolator { + private final WorldGenerator[][] gens; + private final double[][] values = new double[18][18]; + private final int xOrigin; + private final int zOrigin; + private final BiomeGrid grid; + private final int smooth; + private final int pow; + private final World world; + + public ElevationInterpolator(World world, int chunkX, int chunkZ, BiomeGrid grid, int smooth) { + this.xOrigin = chunkX << 4; + this.zOrigin = chunkZ << 4; + this.grid = grid; + this.smooth = smooth; + this.pow = FastMath.log2(smooth); + this.gens = new WorldGenerator[6 + 2 * pow][6 + 2 * pow]; + this.world = world; + + + for(int x = -pow; x < 6 + pow; x++) { + for(int z = -pow; z < 6 + pow; z++) { + gens[x + pow][z + pow] = (WorldGenerator) grid.getBiome(xOrigin + (x * smooth), zOrigin + (z * smooth), GenerationPhase.BASE).getGenerator(world); + } + } + + for(byte x = -1; x <= 16; x++) { + for(byte z = -1; z <= 16; z++) { + WorldGenerator generator = getGenerator(x, z); + if(compareGens((x / smooth), (z / smooth), generator) && generator.interpolateElevation()) { + Interpolator interpolator = new Interpolator(biomeAvg(x / smooth, z / smooth), + biomeAvg((x / smooth) + 1, z / smooth), + biomeAvg(x / smooth, (z / smooth) + 1), + biomeAvg((x / smooth) + 1, (z / smooth) + 1)); + values[x + 1][z + 1] = interpolator.bilerp((double) (x % smooth) / smooth, (double) (z % smooth) / smooth); + } else values[x + 1][z + 1] = elevate(generator, xOrigin + x, zOrigin + z); + } + } + } + + private WorldGenerator getGenerator(int x, int z) { + return (WorldGenerator) grid.getBiome(xOrigin + x, zOrigin + z, GenerationPhase.BASE).getGenerator(world); + } + + private WorldGenerator getStoredGen(int x, int z) { + return gens[x + pow][z + pow]; + } + + private boolean compareGens(int x, int z, WorldGenerator comp) { + for(int xi = x - pow; xi <= x + pow; xi++) { + for(int zi = z - pow; zi <= z + pow; zi++) { + if(!comp.equals(getStoredGen(xi, zi))) return true; + } + } + return false; + } + + private double biomeAvg(int x, int z) { + return (elevate(getStoredGen(x + 1, z), (x * smooth) + smooth + xOrigin, (z * smooth) + zOrigin) + + elevate(getStoredGen(x - 1, z), (x * smooth) - smooth + xOrigin, (z * smooth) + zOrigin) + + elevate(getStoredGen(x, z + 1), (x * smooth) + xOrigin, (z * smooth) + smooth + zOrigin) + + elevate(getStoredGen(x, z - 1), (x * smooth) + xOrigin, (z * smooth) - smooth + zOrigin) + + elevate(getStoredGen(x, z), (x * smooth) + xOrigin, (z * smooth) + zOrigin) + + elevate(getStoredGen(x - 1, z - 1), (x * smooth) - smooth + xOrigin, (z * smooth) - smooth + zOrigin) + + elevate(getStoredGen(x - 1, z + 1), (x * smooth) - smooth + xOrigin, (z * smooth) + smooth + zOrigin) + + elevate(getStoredGen(x + 1, z - 1), (x * smooth) + smooth + xOrigin, (z * smooth) - smooth + zOrigin) + + elevate(getStoredGen(x + 1, z + 1), (x * smooth) + smooth + xOrigin, (z * smooth) + smooth + zOrigin)) / 9D; + } + + private double elevate(WorldGenerator g, int x, int z) { + return g.getElevation(x, z); + } + + public double getElevation(int x, int z) { + return values[x + 1][z + 1]; + } +} diff --git a/common/src/main/java/com/dfsek/terra/generation/math/interpolation/Interpolator.java b/common/src/main/java/com/dfsek/terra/generation/math/interpolation/Interpolator.java new file mode 100644 index 000000000..7d6c403bd --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/generation/math/interpolation/Interpolator.java @@ -0,0 +1,49 @@ +package com.dfsek.terra.generation.math.interpolation; + +/** + * Class for bilinear interpolation of values arranged on a unit square. + */ +public class Interpolator { + private final double v0, v1, v2, v3; + + /** + * Constructs an interpolator with given values as vertices of a unit square. + * + * @param v0 - (0,0) + * @param v1 - (1,0) + * @param v2 - (0,1) + * @param v3 - (1,1) + */ + public Interpolator(double v0, double v1, double v2, double v3) { + this.v0 = v0; + this.v1 = v1; + this.v2 = v2; + this.v3 = v3; + } + + /** + * 1D Linear interpolation between 2 points 1 unit apart. + * + * @param t - Distance from v0. Total distance between v0 and v1 is 1 unit. + * @param v0 - Value at v0. + * @param v1 - Value at v1. + * @return double - The interpolated value. + */ + public static double lerp(double t, double v0, double v1) { + return v0 + t * (v1 - v0); + + } + + /** + * 2D Bilinear interpolation between 4 points on a unit square. + * + * @param s - X value + * @param t - Z value + * @return double - The interpolated value. + */ + public double bilerp(double s, double t) { + double v01 = lerp(s, v0, v1); + double v23 = lerp(s, v2, v3); + return lerp(t, v01, v23); + } +} \ No newline at end of file diff --git a/common/src/main/java/com/dfsek/terra/generation/math/interpolation/Interpolator3.java b/common/src/main/java/com/dfsek/terra/generation/math/interpolation/Interpolator3.java new file mode 100644 index 000000000..e464ae8ba --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/generation/math/interpolation/Interpolator3.java @@ -0,0 +1,38 @@ +package com.dfsek.terra.generation.math.interpolation; + +/** + * Class for bilinear interpolation of values arranged on a unit square. + */ +public class Interpolator3 { + private final double _000, _100, _010, _110, _001, _101, _011, _111; + + /** + * Constructs an interpolator with given values as vertices of a unit cube. + * * @param _000 The value at (t, u, v) = (0, 0, 0). + * * @param _100 The value at (t, u, v) = (1, 0, 0). + * * @param _010 The value at (t, u, v) = (0, 1, 0). + * * @param _110 The value at (t, u, v) = (1, 1, 0). + * * @param _001 The value at (t, u, v) = (0, 0, 1). + * * @param _101 The value at (t, u, v) = (1, 0, 1). + * * @param _011 The value at (t, u, v) = (0, 1, 1). + * * @param _111 The value at (t, u, v) = (1, 1, 1). + */ + public Interpolator3(double _000, double _100, + double _010, double _110, double _001, double _101, + double _011, double _111) { + this._000 = _000; + this._001 = _001; + this._010 = _010; + this._011 = _011; + this._100 = _100; + this._101 = _101; + this._110 = _110; + this._111 = _111; + } + + public double trilerp(double x, double y, double z) { + Interpolator top = new Interpolator(_000, _010, _001, _011); + Interpolator bottom = new Interpolator(_100, _110, _101, _111); + return Interpolator.lerp(x, top.bilerp(y, z), bottom.bilerp(y, z)); + } +} \ No newline at end of file diff --git a/src/main/java/com/dfsek/terra/image/ImageLoader.java b/common/src/main/java/com/dfsek/terra/image/ImageLoader.java similarity index 84% rename from src/main/java/com/dfsek/terra/image/ImageLoader.java rename to common/src/main/java/com/dfsek/terra/image/ImageLoader.java index b5f28e9bd..1b2aec944 100644 --- a/src/main/java/com/dfsek/terra/image/ImageLoader.java +++ b/common/src/main/java/com/dfsek/terra/image/ImageLoader.java @@ -1,12 +1,12 @@ package com.dfsek.terra.image; -import com.dfsek.terra.Terra; +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.api.world.biome.NormalizationUtil; import com.dfsek.terra.biome.BiomeZone; import com.dfsek.terra.biome.grid.master.TerraBiomeGrid; import com.dfsek.terra.debug.gui.DebugGUI; import net.jafama.FastMath; -import org.bukkit.World; -import org.polydev.gaea.biome.NormalizationUtil; import javax.imageio.ImageIO; import java.awt.*; @@ -15,7 +15,6 @@ import java.io.File; import java.io.IOException; public class ImageLoader { - private static final double INVERSE_ROOT_2 = 0.7071067811865475; private final BufferedImage image; private final Align align; @@ -24,7 +23,7 @@ public class ImageLoader { this.align = align; } - public static void debugWorld(boolean genStep, World w, Terra main) { + public static void debugWorld(boolean genStep, World w, TerraPlugin main) { if(!main.isDebug()) return; BufferedImage newImg = new WorldImageGenerator(w, 1024, 1024, main).drawWorld(0, 0).getDraw(); if(genStep) newImg = redrawStepped(newImg, w, Align.CENTER, main); @@ -32,10 +31,10 @@ public class ImageLoader { debugGUI.start(); } - private static BufferedImage redrawStepped(BufferedImage original, World w, Align align, Terra main) { + private static BufferedImage redrawStepped(BufferedImage original, World w, Align align, TerraPlugin main) { BufferedImage newImg = copyImage(original); TerraBiomeGrid tb = main.getWorld(w).getGrid(); - BiomeZone z = main.getWorld(w).getZone(); + BiomeZone zone = main.getWorld(w).getZone(); for(int x = 0; x < newImg.getWidth(); x++) { for(int y = 0; y < newImg.getHeight(); y++) { double[] noise; @@ -44,13 +43,17 @@ public class ImageLoader { else noise = tb.getGrid(x, y).getRawNoise(x, y); newImg.setRGB(x, y, new Color((int) (NormalizationUtil.normalize(noise[0], tb.getGrid(x, y).getSizeX(), 4) * ((double) 255 / tb.getGrid(x, y).getSizeX())), (int) (NormalizationUtil.normalize(noise[1], tb.getGrid(x, y).getSizeZ(), 4) * ((double) 255 / tb.getGrid(x, y).getSizeZ())), - (int) (NormalizationUtil.normalize(z.getNoise(x, y), z.getSize(), 4) * ((double) 255 / z.getSize()))) + (int) (NormalizationUtil.normalize(zone.getNoise(x, y), zone.getSize(), 4) * ((double) 255 / zone.getSize()))) .getRGB()); } } return newImg; } + private static int normal(double val) { + return FastMath.floorToInt(FastMath.min(FastMath.max(val, 255), 0)); + } + private static BufferedImage copyImage(BufferedImage source) { BufferedImage b = new BufferedImage(source.getWidth(), source.getHeight(), source.getType()); Graphics g = b.getGraphics(); @@ -59,7 +62,7 @@ public class ImageLoader { return b; } - public void debug(boolean genStep, World w, Terra main) { + public void debug(boolean genStep, World w, TerraPlugin main) { if(!main.isDebug()) return; BufferedImage newImg = copyImage(image); if(genStep) { @@ -69,8 +72,8 @@ public class ImageLoader { debugGUI.start(); } - public double getNoiseVal(int x, int y, Channel channel) { - return ((double) (getChannel(x, y, channel) - 128) / 128) * INVERSE_ROOT_2; + public int getNoiseVal(int x, int y, int size, Channel channel) { + return (size * getChannel(x, y, channel)) / 255; } public int getChannel(int x, int y, Channel channel) { diff --git a/src/main/java/com/dfsek/terra/image/WorldImageGenerator.java b/common/src/main/java/com/dfsek/terra/image/WorldImageGenerator.java similarity index 88% rename from src/main/java/com/dfsek/terra/image/WorldImageGenerator.java rename to common/src/main/java/com/dfsek/terra/image/WorldImageGenerator.java index 2ae7188f0..3e3d0d8c5 100644 --- a/src/main/java/com/dfsek/terra/image/WorldImageGenerator.java +++ b/common/src/main/java/com/dfsek/terra/image/WorldImageGenerator.java @@ -1,10 +1,10 @@ package com.dfsek.terra.image; -import com.dfsek.terra.Terra; import com.dfsek.terra.TerraWorld; +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.api.world.biome.NormalizationUtil; import com.dfsek.terra.biome.grid.master.TerraBiomeGrid; -import org.bukkit.World; -import org.polydev.gaea.biome.NormalizationUtil; import javax.imageio.ImageIO; import java.awt.*; @@ -15,9 +15,9 @@ import java.io.IOException; public class WorldImageGenerator { private final World w; private final BufferedImage draw; - private final Terra main; + private final TerraPlugin main; - public WorldImageGenerator(World w, int width, int height, Terra main) { + public WorldImageGenerator(World w, int width, int height, TerraPlugin main) { draw = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); this.w = w; this.main = main; diff --git a/src/main/java/com/dfsek/terra/population/CavePopulator.java b/common/src/main/java/com/dfsek/terra/population/CavePopulator.java similarity index 72% rename from src/main/java/com/dfsek/terra/population/CavePopulator.java rename to common/src/main/java/com/dfsek/terra/population/CavePopulator.java index cae23efbc..b256a37f0 100644 --- a/src/main/java/com/dfsek/terra/population/CavePopulator.java +++ b/common/src/main/java/com/dfsek/terra/population/CavePopulator.java @@ -1,22 +1,21 @@ package com.dfsek.terra.population; -import com.dfsek.terra.Terra; import com.dfsek.terra.TerraWorld; -import com.dfsek.terra.api.generic.world.WorldHandle; +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.platform.TerraPlugin; +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.handle.WorldHandle; +import com.dfsek.terra.api.platform.world.Chunk; +import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.api.profiler.ProfileFuture; +import com.dfsek.terra.api.world.generation.TerraBlockPopulator; import com.dfsek.terra.carving.UserDefinedCarver; import com.dfsek.terra.config.base.ConfigPack; import com.dfsek.terra.config.templates.CarverTemplate; import com.dfsek.terra.util.PopulationUtil; -import org.bukkit.Chunk; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.World; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.block.data.BlockData; -import org.bukkit.generator.BlockPopulator; import org.jetbrains.annotations.NotNull; -import org.polydev.gaea.profiler.ProfileFuture; import java.util.HashMap; import java.util.HashSet; @@ -24,20 +23,20 @@ import java.util.Map; import java.util.Random; import java.util.Set; -public class CavePopulator extends BlockPopulator { - private final Terra main; - private static final Map shiftStorage = new HashMap<>(); // Persist BlockData created for shifts, to avoid re-calculating each time. - private static final BlockData AIR = Material.AIR.createBlockData(); +public class CavePopulator implements TerraBlockPopulator { + private final TerraPlugin main; + private static final Map shiftStorage = new HashMap<>(); // Persist BlockData created for shifts, to avoid re-calculating each time. - public CavePopulator(Terra main) { + public CavePopulator(TerraPlugin main) { this.main = main; } @SuppressWarnings("try") @Override - public void populate(@NotNull World world, @NotNull Random r, @NotNull Chunk chunk) { + public void populate(@NotNull World world, @NotNull Chunk chunk) { TerraWorld tw = main.getWorld(world); - WorldHandle handle = main.getHandle(); + WorldHandle handle = main.getWorldHandle(); + BlockData AIR = handle.createBlockData("minecraft:air"); try(ProfileFuture ignored = tw.getProfiler().measure("CaveTime")) { Random random = PopulationUtil.getRandom(chunk); if(!tw.isSafe()) return; @@ -45,11 +44,11 @@ public class CavePopulator extends BlockPopulator { for(UserDefinedCarver c : config.getCarvers()) { CarverTemplate template = c.getConfig(); - Map shiftCandidate = new HashMap<>(); + Map shiftCandidate = new HashMap<>(); Set updateNeeded = new HashSet<>(); c.carve(chunk.getX(), chunk.getZ(), world, (v, type) -> { Block b = chunk.getBlock(v.getBlockX(), v.getBlockY(), v.getBlockZ()); - Material m = handle.getType(b); + MaterialData m = handle.getType(b); switch(type) { case CENTER: if(template.getInner().canReplace(m)) { @@ -81,15 +80,15 @@ public class CavePopulator extends BlockPopulator { break; } }); - for(Map.Entry entry : shiftCandidate.entrySet()) { + for(Map.Entry entry : shiftCandidate.entrySet()) { Location l = entry.getKey(); Location mut = l.clone(); - Material orig = handle.getType(l.getBlock()); + MaterialData orig = handle.getType(l.getBlock()); do mut.subtract(0, 1, 0); - while(handle.getType(mut.getBlock()).equals(orig)); + while(mut.getY() > 0 && handle.getType(mut.getBlock()).equals(orig)); try { if(template.getShift().get(entry.getValue()).contains(mut.getBlock().getType())) { - handle.setBlockData(mut.getBlock(), shiftStorage.computeIfAbsent(entry.getValue(), Material::createBlockData), false); + handle.setBlockData(mut.getBlock(), shiftStorage.computeIfAbsent(entry.getValue(), MaterialData::createBlockData), false); } } catch(NullPointerException ignore) { } @@ -103,8 +102,4 @@ public class CavePopulator extends BlockPopulator { } } - - private boolean borderingOcean(Block b) { - return b.getRelative(BlockFace.UP).getType().equals(Material.WATER) || b.getType().equals(Material.LAVA); - } } diff --git a/src/main/java/com/dfsek/terra/population/FloraPopulator.java b/common/src/main/java/com/dfsek/terra/population/FloraPopulator.java similarity index 68% rename from src/main/java/com/dfsek/terra/population/FloraPopulator.java rename to common/src/main/java/com/dfsek/terra/population/FloraPopulator.java index 779e7d106..09aeca00e 100644 --- a/src/main/java/com/dfsek/terra/population/FloraPopulator.java +++ b/common/src/main/java/com/dfsek/terra/population/FloraPopulator.java @@ -1,17 +1,18 @@ package com.dfsek.terra.population; -import com.dfsek.terra.Terra; import com.dfsek.terra.TerraWorld; +import com.dfsek.terra.api.math.vector.Vector2; +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.platform.world.Chunk; +import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.api.profiler.ProfileFuture; +import com.dfsek.terra.api.world.generation.GenerationPhase; +import com.dfsek.terra.api.world.generation.TerraBlockPopulator; import com.dfsek.terra.biome.UserDefinedBiome; import com.dfsek.terra.biome.grid.master.TerraBiomeGrid; -import com.dfsek.terra.generation.items.flora.FloraLayer; -import com.dfsek.terra.procgen.math.Vector2; -import org.bukkit.Chunk; -import org.bukkit.World; +import com.dfsek.terra.population.items.flora.FloraLayer; +import com.dfsek.terra.util.PopulationUtil; import org.jetbrains.annotations.NotNull; -import org.polydev.gaea.generation.GenerationPhase; -import org.polydev.gaea.population.GaeaBlockPopulator; -import org.polydev.gaea.profiler.ProfileFuture; import java.util.HashMap; import java.util.List; @@ -19,18 +20,18 @@ import java.util.Map; import java.util.Random; /** - * Populates Flora and Trees + * Populates Flora */ -public class FloraPopulator extends GaeaBlockPopulator { - private final Terra main; +public class FloraPopulator implements TerraBlockPopulator { + private final TerraPlugin main; - public FloraPopulator(Terra main) { + public FloraPopulator(TerraPlugin main) { this.main = main; } @SuppressWarnings("try") @Override - public void populate(@NotNull World world, @NotNull Random random, @NotNull Chunk chunk) { + public void populate(@NotNull World world, @NotNull Chunk chunk) { TerraWorld tw = main.getWorld(world); try(ProfileFuture ignored = tw.getProfiler().measure("FloraTime")) { if(!tw.isSafe()) return; @@ -43,6 +44,9 @@ public class FloraPopulator extends GaeaBlockPopulator { layers.put(l, biome.getConfig().getFlora()); } } + + Random random = PopulationUtil.getRandom(chunk); + int iter = 0; boolean finished = false; while(!finished) { diff --git a/src/main/java/com/dfsek/terra/population/OrePopulator.java b/common/src/main/java/com/dfsek/terra/population/OrePopulator.java similarity index 57% rename from src/main/java/com/dfsek/terra/population/OrePopulator.java rename to common/src/main/java/com/dfsek/terra/population/OrePopulator.java index 4443ae591..6f22eeb64 100644 --- a/src/main/java/com/dfsek/terra/population/OrePopulator.java +++ b/common/src/main/java/com/dfsek/terra/population/OrePopulator.java @@ -1,32 +1,32 @@ package com.dfsek.terra.population; -import com.dfsek.terra.Terra; import com.dfsek.terra.TerraWorld; +import com.dfsek.terra.api.math.MathUtil; +import com.dfsek.terra.api.math.vector.Vector3; +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.platform.world.Chunk; +import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.api.profiler.ProfileFuture; +import com.dfsek.terra.api.util.FastRandom; +import com.dfsek.terra.api.world.biome.Biome; +import com.dfsek.terra.api.world.generation.GenerationPhase; +import com.dfsek.terra.api.world.generation.TerraBlockPopulator; import com.dfsek.terra.biome.UserDefinedBiome; import com.dfsek.terra.config.templates.BiomeTemplate; -import org.bukkit.Chunk; -import org.bukkit.World; -import org.bukkit.util.Vector; import org.jetbrains.annotations.NotNull; -import org.polydev.gaea.biome.Biome; -import org.polydev.gaea.generation.GenerationPhase; -import org.polydev.gaea.math.MathUtil; -import org.polydev.gaea.population.GaeaBlockPopulator; -import org.polydev.gaea.profiler.ProfileFuture; -import org.polydev.gaea.util.FastRandom; import java.util.Random; -public class OrePopulator extends GaeaBlockPopulator { - private final Terra main; +public class OrePopulator implements TerraBlockPopulator { + private final TerraPlugin main; - public OrePopulator(Terra main) { + public OrePopulator(TerraPlugin main) { this.main = main; } @SuppressWarnings("try") @Override - public void populate(@NotNull World world, @NotNull Random r, @NotNull Chunk chunk) { + public void populate(@NotNull World world, @NotNull Chunk chunk) { TerraWorld tw = main.getWorld(world); try(ProfileFuture ignored = tw.getProfiler().measure("OreTime")) { if(!tw.isSafe()) return; @@ -35,14 +35,14 @@ public class OrePopulator extends GaeaBlockPopulator { Random random = new FastRandom(MathUtil.getCarverChunkSeed(chunk.getX() + cx, chunk.getZ() + cz, world.getSeed())); int originX = ((chunk.getX() + cx) << 4); int originZ = ((chunk.getZ() + cz) << 4); - Biome b = main.getWorld(world).getGrid().getBiome(originX + 8, originZ + 8, GenerationPhase.POPULATE); + Biome b = tw.getGrid().getBiome(originX + 8, originZ + 8, GenerationPhase.POPULATE); BiomeTemplate config = ((UserDefinedBiome) b).getConfig(); int finalCx = cx; int finalCz = cz; config.getOreHolder().forEach((ore, oreConfig) -> { int amount = oreConfig.getAmount().get(random); for(int i = 0; i < amount; i++) { - Vector location = new Vector(random.nextInt(16) + 16 * finalCx, oreConfig.getHeight().get(random), random.nextInt(16) + 16 * finalCz); + Vector3 location = new Vector3(random.nextInt(16) + 16 * finalCx, oreConfig.getHeight().get(random), random.nextInt(16) + 16 * finalCz); ore.generate(location, chunk, random); } }); diff --git a/common/src/main/java/com/dfsek/terra/population/StructurePopulator.java b/common/src/main/java/com/dfsek/terra/population/StructurePopulator.java new file mode 100644 index 000000000..9bf55e86d --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/population/StructurePopulator.java @@ -0,0 +1,49 @@ +package com.dfsek.terra.population; + +import com.dfsek.terra.TerraWorld; +import com.dfsek.terra.api.math.MathUtil; +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.platform.world.Chunk; +import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.api.profiler.ProfileFuture; +import com.dfsek.terra.api.structures.structure.Rotation; +import com.dfsek.terra.api.util.FastRandom; +import com.dfsek.terra.api.world.generation.TerraBlockPopulator; +import com.dfsek.terra.biome.UserDefinedBiome; +import com.dfsek.terra.biome.grid.master.TerraBiomeGrid; +import com.dfsek.terra.config.base.ConfigPack; +import com.dfsek.terra.population.items.TerraStructure; +import net.jafama.FastMath; +import org.jetbrains.annotations.NotNull; + +import java.util.Random; + +public class StructurePopulator implements TerraBlockPopulator { + private final TerraPlugin main; + + public StructurePopulator(TerraPlugin main) { + this.main = main; + } + + @SuppressWarnings("try") + @Override + public void populate(@NotNull World world, @NotNull Chunk chunk) { + TerraWorld tw = main.getWorld(world); + try(ProfileFuture ignored = tw.getProfiler().measure("StructureTime")) { + int cx = (chunk.getX() << 4); + int cz = (chunk.getZ() << 4); + if(!tw.isSafe()) return; + TerraBiomeGrid grid = tw.getGrid(); + ConfigPack config = tw.getConfig(); + for(TerraStructure conf : config.getStructures()) { + Location spawn = conf.getSpawn().getNearestSpawn(cx + 8, cz + 8, world.getSeed()).toLocation(world); + + if(!((UserDefinedBiome) grid.getBiome(spawn)).getConfig().getStructures().contains(conf)) + continue; + Random random = new FastRandom(MathUtil.getCarverChunkSeed(FastMath.floorDiv(spawn.getBlockX(), 16), FastMath.floorDiv(spawn.getBlockZ(), 16), world.getSeed())); + conf.getStructure().get(random).execute(spawn.setY(conf.getSpawnStart().get(random)), chunk, random, Rotation.fromDegrees(90 * random.nextInt(4))); + } + } + } +} diff --git a/src/main/java/com/dfsek/terra/population/TreePopulator.java b/common/src/main/java/com/dfsek/terra/population/TreePopulator.java similarity index 62% rename from src/main/java/com/dfsek/terra/population/TreePopulator.java rename to common/src/main/java/com/dfsek/terra/population/TreePopulator.java index b2b2a95fe..2d3c4d212 100644 --- a/src/main/java/com/dfsek/terra/population/TreePopulator.java +++ b/common/src/main/java/com/dfsek/terra/population/TreePopulator.java @@ -1,26 +1,27 @@ package com.dfsek.terra.population; -import com.dfsek.terra.Terra; import com.dfsek.terra.TerraWorld; +import com.dfsek.terra.api.math.vector.Vector2; +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.platform.world.Chunk; +import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.api.profiler.ProfileFuture; +import com.dfsek.terra.api.world.generation.GenerationPhase; +import com.dfsek.terra.api.world.generation.TerraBlockPopulator; import com.dfsek.terra.biome.UserDefinedBiome; import com.dfsek.terra.biome.grid.master.TerraBiomeGrid; -import com.dfsek.terra.generation.items.tree.TreeLayer; -import com.dfsek.terra.procgen.math.Vector2; +import com.dfsek.terra.population.items.tree.TreeLayer; +import com.dfsek.terra.util.PopulationUtil; import net.jafama.FastMath; -import org.bukkit.Chunk; -import org.bukkit.World; import org.jetbrains.annotations.NotNull; -import org.polydev.gaea.generation.GenerationPhase; -import org.polydev.gaea.population.GaeaBlockPopulator; -import org.polydev.gaea.profiler.ProfileFuture; import java.util.Random; -public class TreePopulator extends GaeaBlockPopulator { - private final Terra main; +public class TreePopulator implements TerraBlockPopulator { + private final TerraPlugin main; - public TreePopulator(Terra main) { + public TreePopulator(TerraPlugin main) { this.main = main; } @@ -30,11 +31,12 @@ public class TreePopulator extends GaeaBlockPopulator { @Override @SuppressWarnings("try") - public void populate(@NotNull World world, @NotNull Random random, @NotNull Chunk chunk) { + public void populate(@NotNull World world, @NotNull Chunk chunk) { TerraWorld tw = main.getWorld(world); try(ProfileFuture ignored = tw.getProfiler().measure("TreeTime")) { if(!tw.isSafe()) return; TerraBiomeGrid grid = tw.getGrid(); + Random random = PopulationUtil.getRandom(chunk); for(int x = 0; x < 16; x += 2) { for(int z = 0; z < 16; z += 2) { UserDefinedBiome biome = (UserDefinedBiome) grid.getBiome((chunk.getX() << 4) + x, (chunk.getZ() << 4) + z, GenerationPhase.POPULATE); diff --git a/src/main/java/com/dfsek/terra/generation/items/PlaceableLayer.java b/common/src/main/java/com/dfsek/terra/population/items/PlaceableLayer.java similarity index 62% rename from src/main/java/com/dfsek/terra/generation/items/PlaceableLayer.java rename to common/src/main/java/com/dfsek/terra/population/items/PlaceableLayer.java index f688b63b1..1f68c579a 100644 --- a/src/main/java/com/dfsek/terra/generation/items/PlaceableLayer.java +++ b/common/src/main/java/com/dfsek/terra/population/items/PlaceableLayer.java @@ -1,10 +1,10 @@ -package com.dfsek.terra.generation.items; +package com.dfsek.terra.population.items; -import com.dfsek.terra.procgen.math.Vector2; -import org.bukkit.Chunk; -import org.polydev.gaea.math.FastNoiseLite; -import org.polydev.gaea.math.ProbabilityCollection; -import org.polydev.gaea.math.Range; +import com.dfsek.terra.api.math.ProbabilityCollection; +import com.dfsek.terra.api.math.Range; +import com.dfsek.terra.api.math.noise.samplers.NoiseSampler; +import com.dfsek.terra.api.math.vector.Vector2; +import com.dfsek.terra.api.platform.world.Chunk; import java.util.Random; @@ -12,16 +12,16 @@ public abstract class PlaceableLayer { protected final double density; protected final Range level; protected final ProbabilityCollection layer; - protected final FastNoiseLite noise; + protected final NoiseSampler noise; - public PlaceableLayer(double density, Range level, ProbabilityCollection layer, FastNoiseLite noise) { + public PlaceableLayer(double density, Range level, ProbabilityCollection layer, NoiseSampler noise) { this.density = density; this.level = level; this.layer = layer; this.noise = noise; } - public FastNoiseLite getNoise() { + public NoiseSampler getNoise() { return noise; } diff --git a/common/src/main/java/com/dfsek/terra/population/items/TerraStructure.java b/common/src/main/java/com/dfsek/terra/population/items/TerraStructure.java new file mode 100644 index 000000000..9e8e51a2a --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/population/items/TerraStructure.java @@ -0,0 +1,37 @@ +package com.dfsek.terra.population.items; + +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.structures.script.StructureScript; +import com.dfsek.terra.config.templates.StructureTemplate; + +public class TerraStructure { + private final ProbabilityCollection structure; + private final Range spawnStart; + private final GridSpawn spawn; + private final StructureTemplate template; + + public TerraStructure(ProbabilityCollection structures, Range spawnStart, GridSpawn spawn, StructureTemplate template) { + this.structure = structures; + this.spawnStart = spawnStart; + this.spawn = spawn; + this.template = template; + } + + public StructureTemplate getTemplate() { + return template; + } + + public ProbabilityCollection getStructure() { + return structure; + } + + public Range getSpawnStart() { + return spawnStart; + } + + public GridSpawn getSpawn() { + return spawn; + } +} diff --git a/src/main/java/com/dfsek/terra/generation/items/flora/BlockFlora.java b/common/src/main/java/com/dfsek/terra/population/items/flora/BlockFlora.java similarity index 64% rename from src/main/java/com/dfsek/terra/generation/items/flora/BlockFlora.java rename to common/src/main/java/com/dfsek/terra/population/items/flora/BlockFlora.java index a061371c9..75ae1431f 100644 --- a/src/main/java/com/dfsek/terra/generation/items/flora/BlockFlora.java +++ b/common/src/main/java/com/dfsek/terra/population/items/flora/BlockFlora.java @@ -1,13 +1,13 @@ -package com.dfsek.terra.generation.items.flora; +package com.dfsek.terra.population.items.flora; -import org.bukkit.Chunk; -import org.bukkit.Location; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.block.data.BlockData; -import org.polydev.gaea.math.Range; -import org.polydev.gaea.util.GlueList; -import org.polydev.gaea.world.Flora; +import com.dfsek.terra.api.math.Range; +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.platform.block.Block; +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.block.BlockFace; +import com.dfsek.terra.api.platform.world.Chunk; +import com.dfsek.terra.api.util.GlueList; +import com.dfsek.terra.api.world.flora.Flora; import java.util.List; @@ -38,7 +38,7 @@ public class BlockFlora implements Flora { @Override public boolean plant(Location location) { - location.add(0, 1, 0).getBlock().setBlockData(data); + location.add(0, 1, 0).getBlock().setBlockData(data, true); return true; } } diff --git a/common/src/main/java/com/dfsek/terra/population/items/flora/ConstantFlora.java b/common/src/main/java/com/dfsek/terra/population/items/flora/ConstantFlora.java new file mode 100644 index 000000000..0cdb224ba --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/population/items/flora/ConstantFlora.java @@ -0,0 +1,52 @@ +package com.dfsek.terra.population.items.flora; + +import com.dfsek.terra.api.math.Range; +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.platform.block.Block; +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.block.BlockFace; +import com.dfsek.terra.api.platform.world.Chunk; +import com.dfsek.terra.api.util.GlueList; +import com.dfsek.terra.api.world.flora.Flora; +import com.dfsek.terra.util.MaterialSet; + +import java.util.List; + +public class ConstantFlora implements Flora { + private final List data; + + private final MaterialSet spawns; + + public ConstantFlora(MaterialSet spawns, List data) { + this.data = data; + this.spawns = spawns; + } + + @Override + public List getValidSpawnsAt(Chunk chunk, int x, int z, Range check) { + List blocks = new GlueList<>(); + for(int y : check) { + Block block = chunk.getBlock(x, y, z); + if(spawns.contains(block.getType()) && valid(block)) { + blocks.add(chunk.getBlock(x, y, z)); + } + } + return blocks; + } + + private boolean valid(Block block) { + for(int i = 1; i < data.size() + 1; i++) { + block = block.getRelative(BlockFace.UP); + if(!block.isEmpty()) return false; + } + return true; + } + + @Override + public boolean plant(Location l) { + for(int i = 1; i < data.size() + 1; i++) { + l.clone().add(0, i, 0).getBlock().setBlockData(data.get(i - 1), false); + } + return true; + } +} diff --git a/src/main/java/com/dfsek/terra/generation/items/flora/FloraLayer.java b/common/src/main/java/com/dfsek/terra/population/items/flora/FloraLayer.java similarity index 57% rename from src/main/java/com/dfsek/terra/generation/items/flora/FloraLayer.java rename to common/src/main/java/com/dfsek/terra/population/items/flora/FloraLayer.java index 2f8198000..66799f357 100644 --- a/src/main/java/com/dfsek/terra/generation/items/flora/FloraLayer.java +++ b/common/src/main/java/com/dfsek/terra/population/items/flora/FloraLayer.java @@ -1,18 +1,18 @@ -package com.dfsek.terra.generation.items.flora; +package com.dfsek.terra.population.items.flora; -import com.dfsek.terra.generation.items.PlaceableLayer; -import com.dfsek.terra.procgen.math.Vector2; -import org.bukkit.Chunk; -import org.polydev.gaea.math.FastNoiseLite; -import org.polydev.gaea.math.ProbabilityCollection; -import org.polydev.gaea.math.Range; -import org.polydev.gaea.world.Flora; +import com.dfsek.terra.api.math.ProbabilityCollection; +import com.dfsek.terra.api.math.Range; +import com.dfsek.terra.api.math.noise.samplers.NoiseSampler; +import com.dfsek.terra.api.math.vector.Vector2; +import com.dfsek.terra.api.platform.world.Chunk; +import com.dfsek.terra.api.world.flora.Flora; +import com.dfsek.terra.population.items.PlaceableLayer; import java.util.Random; public class FloraLayer extends PlaceableLayer { - public FloraLayer(double density, Range level, ProbabilityCollection layer, FastNoiseLite noise) { + public FloraLayer(double density, Range level, ProbabilityCollection layer, NoiseSampler noise) { super(density, level, layer, noise); } @@ -20,6 +20,7 @@ public class FloraLayer extends PlaceableLayer { return density; } + @Override public void place(Chunk chunk, Vector2 coords, Random random) { Flora item = noise == null ? layer.get(random) : layer.get(noise, (chunk.getX() << 4) + coords.getX(), (chunk.getZ() << 4) + coords.getZ()); item.getValidSpawnsAt(chunk, (int) coords.getX(), (int) coords.getZ(), level).forEach(block -> item.plant(block.getLocation())); diff --git a/src/main/java/com/dfsek/terra/generation/items/flora/TerraFlora.java b/common/src/main/java/com/dfsek/terra/population/items/flora/TerraFlora.java similarity index 84% rename from src/main/java/com/dfsek/terra/generation/items/flora/TerraFlora.java rename to common/src/main/java/com/dfsek/terra/population/items/flora/TerraFlora.java index cbcb15d9b..34b2b974a 100644 --- a/src/main/java/com/dfsek/terra/generation/items/flora/TerraFlora.java +++ b/common/src/main/java/com/dfsek/terra/population/items/flora/TerraFlora.java @@ -1,22 +1,22 @@ -package com.dfsek.terra.generation.items.flora; +package com.dfsek.terra.population.items.flora; -import com.dfsek.terra.Terra; -import com.dfsek.terra.api.generic.world.WorldHandle; +import com.dfsek.terra.api.math.Range; +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.platform.block.Block; +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.block.BlockFace; +import com.dfsek.terra.api.platform.block.data.Directional; +import com.dfsek.terra.api.platform.block.data.MultipleFacing; +import com.dfsek.terra.api.platform.block.data.Rotatable; +import com.dfsek.terra.api.platform.handle.WorldHandle; +import com.dfsek.terra.api.platform.world.Chunk; +import com.dfsek.terra.api.util.FastRandom; +import com.dfsek.terra.api.util.GlueList; +import com.dfsek.terra.api.world.flora.Flora; +import com.dfsek.terra.api.world.palette.Palette; import com.dfsek.terra.util.MaterialSet; import net.jafama.FastMath; -import org.bukkit.Chunk; -import org.bukkit.Location; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.block.data.BlockData; -import org.bukkit.block.data.Directional; -import org.bukkit.block.data.MultipleFacing; -import org.bukkit.block.data.Rotatable; -import org.polydev.gaea.math.Range; -import org.polydev.gaea.util.FastRandom; -import org.polydev.gaea.util.GlueList; -import org.polydev.gaea.world.Flora; -import org.polydev.gaea.world.palette.Palette; import java.util.ArrayList; import java.util.List; @@ -41,9 +41,9 @@ public class TerraFlora implements Flora { private final int irrigableOffset; - private final Terra main; + private final TerraPlugin main; - public TerraFlora(Palette floraPalette, boolean physics, boolean ceiling, MaterialSet irrigable, MaterialSet spawnable, MaterialSet replaceable, MaterialSet testRotation, int maxPlacements, Search search, boolean spawnBlacklist, int irrigableOffset, Terra main) { + public TerraFlora(Palette floraPalette, boolean physics, boolean ceiling, MaterialSet irrigable, MaterialSet spawnable, MaterialSet replaceable, MaterialSet testRotation, int maxPlacements, Search search, boolean spawnBlacklist, int irrigableOffset, TerraPlugin main) { this.floraPalette = floraPalette; this.physics = physics; this.testRotation = testRotation; @@ -94,7 +94,7 @@ public class TerraFlora implements Flora { @Override public boolean plant(Location location) { - WorldHandle handle = main.getHandle(); + WorldHandle handle = main.getWorldHandle(); boolean doRotation = testRotation.size() > 0; int size = floraPalette.getSize(); diff --git a/src/main/java/com/dfsek/terra/generation/items/ores/DeformedSphereOre.java b/common/src/main/java/com/dfsek/terra/population/items/ores/DeformedSphereOre.java similarity index 69% rename from src/main/java/com/dfsek/terra/generation/items/ores/DeformedSphereOre.java rename to common/src/main/java/com/dfsek/terra/population/items/ores/DeformedSphereOre.java index d5534a20c..de53fcf08 100644 --- a/src/main/java/com/dfsek/terra/generation/items/ores/DeformedSphereOre.java +++ b/common/src/main/java/com/dfsek/terra/population/items/ores/DeformedSphereOre.java @@ -1,14 +1,14 @@ -package com.dfsek.terra.generation.items.ores; +package com.dfsek.terra.population.items.ores; -import com.dfsek.terra.Terra; -import com.dfsek.terra.api.generic.world.WorldHandle; +import com.dfsek.terra.api.math.Range; +import com.dfsek.terra.api.math.noise.samplers.FastNoiseLite; +import com.dfsek.terra.api.math.vector.Vector3; +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.platform.block.Block; +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.handle.WorldHandle; +import com.dfsek.terra.api.platform.world.Chunk; import com.dfsek.terra.util.MaterialSet; -import org.bukkit.Chunk; -import org.bukkit.block.Block; -import org.bukkit.block.data.BlockData; -import org.bukkit.util.Vector; -import org.polydev.gaea.math.FastNoiseLite; -import org.polydev.gaea.math.Range; import java.util.Random; @@ -17,7 +17,7 @@ public class DeformedSphereOre extends Ore { private final double deformFrequency; private final Range size; - public DeformedSphereOre(BlockData material, MaterialSet replaceable, boolean applyGravity, double deform, double deformFrequency, Range size, Terra main) { + public DeformedSphereOre(BlockData material, MaterialSet replaceable, boolean applyGravity, double deform, double deformFrequency, Range size, TerraPlugin main) { super(material, replaceable, applyGravity, main); this.deform = deform; this.deformFrequency = deformFrequency; @@ -26,8 +26,8 @@ public class DeformedSphereOre extends Ore { @Override - public void generate(Vector origin, Chunk c, Random r) { - WorldHandle handle = main.getHandle(); + public void generate(Vector3 origin, Chunk c, Random r) { + WorldHandle handle = main.getWorldHandle(); FastNoiseLite ore = new FastNoiseLite(r.nextInt()); ore.setNoiseType(FastNoiseLite.NoiseType.OpenSimplex2); ore.setFrequency(deformFrequency); @@ -35,7 +35,7 @@ public class DeformedSphereOre extends Ore { for(int x = -rad; x <= rad; x++) { for(int y = -rad; y <= rad; y++) { for(int z = -rad; z <= rad; z++) { - Vector oreLoc = origin.clone().add(new Vector(x, y, z)); + Vector3 oreLoc = origin.clone().add(new Vector3(x, y, z)); if(oreLoc.getBlockX() > 15 || oreLoc.getBlockZ() > 15 || oreLoc.getBlockY() > 255 || oreLoc.getBlockX() < 0 || oreLoc.getBlockZ() < 0 || oreLoc.getBlockY() < 0) continue; if(oreLoc.distance(origin) < (rad + 0.5) * ((ore.getNoise(x, y, z) + 1) * deform)) { diff --git a/src/main/java/com/dfsek/terra/generation/items/ores/Ore.java b/common/src/main/java/com/dfsek/terra/population/items/ores/Ore.java similarity index 64% rename from src/main/java/com/dfsek/terra/generation/items/ores/Ore.java rename to common/src/main/java/com/dfsek/terra/population/items/ores/Ore.java index 84ee34db9..2c60b97e4 100644 --- a/src/main/java/com/dfsek/terra/generation/items/ores/Ore.java +++ b/common/src/main/java/com/dfsek/terra/population/items/ores/Ore.java @@ -1,10 +1,10 @@ -package com.dfsek.terra.generation.items.ores; +package com.dfsek.terra.population.items.ores; -import com.dfsek.terra.Terra; +import com.dfsek.terra.api.math.vector.Vector3; +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.world.Chunk; import com.dfsek.terra.util.MaterialSet; -import org.bukkit.Chunk; -import org.bukkit.block.data.BlockData; -import org.bukkit.util.Vector; import java.util.Random; @@ -13,9 +13,9 @@ public abstract class Ore { private final BlockData material; private final MaterialSet replaceable; private final boolean applyGravity; - protected Terra main; + protected TerraPlugin main; - public Ore(BlockData material, MaterialSet replaceable, boolean applyGravity, Terra main) { + public Ore(BlockData material, MaterialSet replaceable, boolean applyGravity, TerraPlugin main) { this.material = material; this.replaceable = replaceable; @@ -23,7 +23,7 @@ public abstract class Ore { this.main = main; } - public abstract void generate(Vector origin, Chunk c, Random r); + public abstract void generate(Vector3 origin, Chunk c, Random r); public BlockData getMaterial() { return material; diff --git a/src/main/java/com/dfsek/terra/generation/items/ores/OreConfig.java b/common/src/main/java/com/dfsek/terra/population/items/ores/OreConfig.java similarity index 79% rename from src/main/java/com/dfsek/terra/generation/items/ores/OreConfig.java rename to common/src/main/java/com/dfsek/terra/population/items/ores/OreConfig.java index 305ca5785..2c9bf9bc0 100644 --- a/src/main/java/com/dfsek/terra/generation/items/ores/OreConfig.java +++ b/common/src/main/java/com/dfsek/terra/population/items/ores/OreConfig.java @@ -1,6 +1,6 @@ -package com.dfsek.terra.generation.items.ores; +package com.dfsek.terra.population.items.ores; -import org.polydev.gaea.math.Range; +import com.dfsek.terra.api.math.Range; public class OreConfig { private final Range amount; diff --git a/src/main/java/com/dfsek/terra/generation/items/ores/OreHolder.java b/common/src/main/java/com/dfsek/terra/population/items/ores/OreHolder.java similarity index 90% rename from src/main/java/com/dfsek/terra/generation/items/ores/OreHolder.java rename to common/src/main/java/com/dfsek/terra/population/items/ores/OreHolder.java index fde4fb7ab..d7668ba0f 100644 --- a/src/main/java/com/dfsek/terra/generation/items/ores/OreHolder.java +++ b/common/src/main/java/com/dfsek/terra/population/items/ores/OreHolder.java @@ -1,6 +1,6 @@ -package com.dfsek.terra.generation.items.ores; +package com.dfsek.terra.population.items.ores; -import org.polydev.gaea.util.GlueList; +import com.dfsek.terra.api.util.GlueList; import java.util.List; import java.util.function.BiConsumer; diff --git a/src/main/java/com/dfsek/terra/generation/items/ores/VanillaOre.java b/common/src/main/java/com/dfsek/terra/population/items/ores/VanillaOre.java similarity index 83% rename from src/main/java/com/dfsek/terra/generation/items/ores/VanillaOre.java rename to common/src/main/java/com/dfsek/terra/population/items/ores/VanillaOre.java index 9b283fb2c..39e27c4d4 100644 --- a/src/main/java/com/dfsek/terra/generation/items/ores/VanillaOre.java +++ b/common/src/main/java/com/dfsek/terra/population/items/ores/VanillaOre.java @@ -1,14 +1,14 @@ -package com.dfsek.terra.generation.items.ores; +package com.dfsek.terra.population.items.ores; -import com.dfsek.terra.Terra; -import com.dfsek.terra.api.generic.world.WorldHandle; +import com.dfsek.terra.api.math.Range; +import com.dfsek.terra.api.math.vector.Vector3; +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.platform.block.Block; +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.handle.WorldHandle; +import com.dfsek.terra.api.platform.world.Chunk; import com.dfsek.terra.util.MaterialSet; import net.jafama.FastMath; -import org.bukkit.Chunk; -import org.bukkit.block.Block; -import org.bukkit.block.data.BlockData; -import org.bukkit.util.Vector; -import org.polydev.gaea.math.Range; import java.util.Random; @@ -16,14 +16,14 @@ import java.util.Random; public class VanillaOre extends Ore { private final Range sizeRange; - public VanillaOre(BlockData material, MaterialSet replaceable, boolean applyGravity, Range size, Terra main) { + public VanillaOre(BlockData material, MaterialSet replaceable, boolean applyGravity, Range size, TerraPlugin main) { super(material, replaceable, applyGravity, main); this.sizeRange = size; } @Override - public void generate(Vector location, Chunk chunk, Random random) { - WorldHandle handle = main.getHandle(); + public void generate(Vector3 location, Chunk chunk, Random random) { + WorldHandle handle = main.getWorldHandle(); double size = sizeRange.get(random); int centerX = location.getBlockX(); diff --git a/common/src/main/java/com/dfsek/terra/population/items/tree/TerraTree.java b/common/src/main/java/com/dfsek/terra/population/items/tree/TerraTree.java new file mode 100644 index 000000000..1bfa207af --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/population/items/tree/TerraTree.java @@ -0,0 +1,32 @@ +package com.dfsek.terra.population.items.tree; + +import com.dfsek.terra.api.math.ProbabilityCollection; +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.structures.script.StructureScript; +import com.dfsek.terra.api.structures.structure.Rotation; +import com.dfsek.terra.api.world.tree.Tree; +import com.dfsek.terra.util.MaterialSet; + +import java.util.Random; + +public class TerraTree implements Tree { + private final MaterialSet spawnable; + private final int yOffset; + private final ProbabilityCollection structure; + + public TerraTree(MaterialSet spawnable, int yOffset, ProbabilityCollection structure) { + this.spawnable = spawnable; + this.yOffset = yOffset; + this.structure = structure; + } + + @Override + public synchronized boolean plant(Location location, Random random) { + return structure.get(random).executeDirect(location.clone().add(0, yOffset, 0), random, Rotation.fromDegrees(90 * random.nextInt(4))); + } + + @Override + public MaterialSet getSpawnable() { + return spawnable; + } +} diff --git a/common/src/main/java/com/dfsek/terra/population/items/tree/TreeLayer.java b/common/src/main/java/com/dfsek/terra/population/items/tree/TreeLayer.java new file mode 100644 index 000000000..c30ecda71 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/population/items/tree/TreeLayer.java @@ -0,0 +1,32 @@ +package com.dfsek.terra.population.items.tree; + +import com.dfsek.terra.api.math.ProbabilityCollection; +import com.dfsek.terra.api.math.Range; +import com.dfsek.terra.api.math.noise.samplers.NoiseSampler; +import com.dfsek.terra.api.math.vector.Vector2; +import com.dfsek.terra.api.platform.block.Block; +import com.dfsek.terra.api.platform.block.BlockFace; +import com.dfsek.terra.api.platform.world.Chunk; +import com.dfsek.terra.api.world.tree.Tree; +import com.dfsek.terra.population.items.PlaceableLayer; + +import java.util.Random; + +public class TreeLayer extends PlaceableLayer { + + public TreeLayer(double density, Range level, ProbabilityCollection layer, NoiseSampler noise) { + super(density, level, layer, noise); + } + + @Override + public void place(Chunk chunk, Vector2 coords, Random random) { + Tree item = layer.get(random); + Block current = chunk.getBlock((int) coords.getX(), level.getMax(), (int) coords.getZ()); + for(int ignored : level) { + current = current.getRelative(BlockFace.DOWN); + if(item.getSpawnable().contains(current.getType())) { + item.plant(current.getLocation().add(0, 1, 0), random); + } + } + } +} diff --git a/src/main/java/com/dfsek/terra/registry/BiomeGridRegistry.java b/common/src/main/java/com/dfsek/terra/registry/BiomeGridRegistry.java similarity index 100% rename from src/main/java/com/dfsek/terra/registry/BiomeGridRegistry.java rename to common/src/main/java/com/dfsek/terra/registry/BiomeGridRegistry.java diff --git a/src/main/java/com/dfsek/terra/registry/BiomeRegistry.java b/common/src/main/java/com/dfsek/terra/registry/BiomeRegistry.java similarity index 100% rename from src/main/java/com/dfsek/terra/registry/BiomeRegistry.java rename to common/src/main/java/com/dfsek/terra/registry/BiomeRegistry.java diff --git a/src/main/java/com/dfsek/terra/registry/CarverRegistry.java b/common/src/main/java/com/dfsek/terra/registry/CarverRegistry.java similarity index 100% rename from src/main/java/com/dfsek/terra/registry/CarverRegistry.java rename to common/src/main/java/com/dfsek/terra/registry/CarverRegistry.java diff --git a/src/main/java/com/dfsek/terra/registry/ConfigRegistry.java b/common/src/main/java/com/dfsek/terra/registry/ConfigRegistry.java similarity index 80% rename from src/main/java/com/dfsek/terra/registry/ConfigRegistry.java rename to common/src/main/java/com/dfsek/terra/registry/ConfigRegistry.java index 54037ac2c..0fdc6163a 100644 --- a/src/main/java/com/dfsek/terra/registry/ConfigRegistry.java +++ b/common/src/main/java/com/dfsek/terra/registry/ConfigRegistry.java @@ -1,7 +1,7 @@ package com.dfsek.terra.registry; import com.dfsek.tectonic.exception.ConfigException; -import com.dfsek.terra.Terra; +import com.dfsek.terra.api.platform.TerraPlugin; import com.dfsek.terra.config.base.ConfigPack; import com.dfsek.terra.debug.Debug; @@ -13,14 +13,15 @@ import java.util.zip.ZipFile; * Class to hold config packs */ public class ConfigRegistry extends TerraRegistry { - public void load(File folder, Terra main) throws ConfigException { + public void load(File folder, TerraPlugin main) throws ConfigException { ConfigPack pack = new ConfigPack(folder, main); add(pack.getTemplate().getID(), pack); } - public boolean loadAll(Terra main) { + public boolean loadAll(TerraPlugin main) { boolean valid = true; File packsFolder = new File(main.getDataFolder(), "packs"); + packsFolder.mkdirs(); for(File dir : packsFolder.listFiles(File::isDirectory)) { try { load(dir, main); @@ -29,7 +30,7 @@ public class ConfigRegistry extends TerraRegistry { valid = false; } } - for(File zip : packsFolder.listFiles(file -> file.getName().endsWith(".zip") || file.getName().endsWith(".jar") || file.getName().endsWith(".terra"))) { + for(File zip : packsFolder.listFiles(file -> file.getName().endsWith(".zip") || file.getName().endsWith(".jar") || file.getName().endsWith(".com.dfsek.terra"))) { try { Debug.info("Loading ZIP archive: " + zip.getName()); load(new ZipFile(zip), main); @@ -41,7 +42,7 @@ public class ConfigRegistry extends TerraRegistry { return valid; } - public void load(ZipFile file, Terra main) throws ConfigException { + public void load(ZipFile file, TerraPlugin main) throws ConfigException { ConfigPack pack = new ConfigPack(file, main); add(pack.getTemplate().getID(), pack); } diff --git a/common/src/main/java/com/dfsek/terra/registry/FloraRegistry.java b/common/src/main/java/com/dfsek/terra/registry/FloraRegistry.java new file mode 100644 index 000000000..194948b45 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/registry/FloraRegistry.java @@ -0,0 +1,75 @@ +package com.dfsek.terra.registry; + +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.block.MaterialData; +import com.dfsek.terra.api.world.flora.Flora; +import com.dfsek.terra.population.items.flora.ConstantFlora; +import com.dfsek.terra.util.MaterialSet; + +import java.util.Arrays; +import java.util.Collections; +import java.util.concurrent.Callable; + +public class FloraRegistry extends TerraRegistry { + private final TerraPlugin main; + + public FloraRegistry(TerraPlugin main) { + this.main = main; + MaterialSet grassy = MaterialSet.get(create("minecraft:grass_block"), create("minecraft:podzol")); + addItem("TALL_GRASS", () -> new ConstantFlora(grassy, Arrays.asList(data("minecraft:tall_grass[half=lower]"), data("minecraft:tall_grass[half=upper]")))); + addItem("TALL_FERN", () -> new ConstantFlora(grassy, Arrays.asList(data("minecraft:large_fern[half=lower]"), data("minecraft:large_fern[half=upper]")))); + addItem("SUNFLOWER", () -> new ConstantFlora(grassy, Arrays.asList(data("minecraft:sunflower[half=lower]"), data("minecraft:sunflower[half=upper]")))); + addItem("ROSE_BUSH", () -> new ConstantFlora(grassy, Arrays.asList(data("minecraft:rose_bush[half=lower]"), data("minecraft:rose_bush[half=upper]")))); + addItem("LILAC", () -> new ConstantFlora(grassy, Arrays.asList(data("minecraft:lilac[half=lower]"), data("minecraft:lilac[half=upper]")))); + addItem("PEONY", () -> new ConstantFlora(grassy, Arrays.asList(data("minecraft:peony[half=lower]"), data("minecraft:peony[half=upper]")))); + addItem("GRASS", () -> new ConstantFlora(grassy, Collections.singletonList(data("minecraft:grass")))); + addItem("FERN", () -> new ConstantFlora(grassy, Collections.singletonList(data("minecraft:fern")))); + addItem("AZURE_BLUET", () -> new ConstantFlora(grassy, Collections.singletonList(data("minecraft:azure_bluet")))); + addItem("LILY_OF_THE_VALLEY", () -> new ConstantFlora(grassy, Collections.singletonList(data("minecraft:lily_of_the_valley")))); + addItem("BLUE_ORCHID", () -> new ConstantFlora(grassy, Collections.singletonList(data("minecraft:blue_orchid")))); + addItem("POPPY", () -> new ConstantFlora(grassy, Collections.singletonList(data("minecraft:poppy")))); + addItem("DANDELION", () -> new ConstantFlora(grassy, Collections.singletonList(data("minecraft:dandelion")))); + addItem("WITHER_ROSE", () -> new ConstantFlora(grassy, Collections.singletonList(data("minecraft:wither_rose")))); + addItem("DEAD_BUSH", () -> new ConstantFlora(MaterialSet.get(create("minecraft:terracotta"), create("minecraft:black_terracotta"), + create("minecraft:blue_terracotta"), create("minecraft:brown_terracotta"), create("minecraft:cyan_terracotta"), + create("minecraft:gray_terracotta"), create("minecraft:green_terracotta"), create("minecraft:light_blue_terracotta"), + create("minecraft:light_gray_terracotta"), create("minecraft:lime_terracotta"), create("minecraft:magenta_terracotta"), + create("minecraft:orange_terracotta"), create("minecraft:pink_terracotta"), create("minecraft:purple_terracotta"), + create("minecraft:red_terracotta"), create("minecraft:white_terracotta"), create("minecraft:yellow_terracotta"), + create("minecraft:red_sand"), create("minecraft:sand")), Collections.singletonList(data("minecraft:dead_bush")))); + addItem("RED_TULIP", () -> new ConstantFlora(grassy, Collections.singletonList(data("minecraft:red_tulip")))); + addItem("ORANGE_TULIP", () -> new ConstantFlora(grassy, Collections.singletonList(data("minecraft:orange_tulip")))); + addItem("WHITE_TULIP", () -> new ConstantFlora(grassy, Collections.singletonList(data("minecraft:white_tulip")))); + addItem("PINK_TULIP", () -> new ConstantFlora(grassy, Collections.singletonList(data("minecraft:pink_tulip")))); + addItem("OXEYE_DAISY", () -> new ConstantFlora(grassy, Collections.singletonList(data("minecraft:oxeye_daisy")))); + addItem("ALLIUM", () -> new ConstantFlora(grassy, Collections.singletonList(data("minecraft:allium")))); + addItem("CORNFLOWER", () -> new ConstantFlora(grassy, Collections.singletonList(data("minecraft:cornflower")))); + addItem("LILY_PAD", () -> new ConstantFlora(MaterialSet.get(create("minecraft:water")), Collections.singletonList(data("minecraft:lily_pad")))); + MaterialSet mushroom = MaterialSet.get(create("minecraft:grass_block"), create("minecraft:stone"), create("minecraft:podzol"), create("minecraft:netherrack"), create("minecraft:mycelium")); + addItem("RED_MUSHROOM", () -> new ConstantFlora(mushroom, Collections.singletonList(data("minecraft:red_mushroom")))); + addItem("BROWN_MUSHROOM", () -> new ConstantFlora(mushroom, Collections.singletonList(data("minecraft:brown_mushroom")))); + } + + private MaterialData create(String s) { + return main.getWorldHandle().createMaterialData(s); + } + + private void addItem(String id, Callable flora) { + try { + add(id, flora.call()); + } catch(Exception e) { + main.getLogger().warning("Failed to load Flora item: " + id + ": " + e.getMessage()); + } + } + + private BlockData data(String s) { + return main.getWorldHandle().createBlockData(s); + } + + + @Override + public Flora get(String id) { + return super.get(id); + } +} diff --git a/common/src/main/java/com/dfsek/terra/registry/LootRegistry.java b/common/src/main/java/com/dfsek/terra/registry/LootRegistry.java new file mode 100644 index 000000000..0104bb66c --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/registry/LootRegistry.java @@ -0,0 +1,6 @@ +package com.dfsek.terra.registry; + +import com.dfsek.terra.api.structures.loot.LootTable; + +public class LootRegistry extends TerraRegistry { +} diff --git a/src/main/java/com/dfsek/terra/registry/OreRegistry.java b/common/src/main/java/com/dfsek/terra/registry/OreRegistry.java similarity index 64% rename from src/main/java/com/dfsek/terra/registry/OreRegistry.java rename to common/src/main/java/com/dfsek/terra/registry/OreRegistry.java index 69091898a..b5abf80d1 100644 --- a/src/main/java/com/dfsek/terra/registry/OreRegistry.java +++ b/common/src/main/java/com/dfsek/terra/registry/OreRegistry.java @@ -1,6 +1,6 @@ package com.dfsek.terra.registry; -import com.dfsek.terra.generation.items.ores.Ore; +import com.dfsek.terra.population.items.ores.Ore; public class OreRegistry extends TerraRegistry { } diff --git a/common/src/main/java/com/dfsek/terra/registry/PaletteRegistry.java b/common/src/main/java/com/dfsek/terra/registry/PaletteRegistry.java new file mode 100644 index 000000000..e5b5dbeb9 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/registry/PaletteRegistry.java @@ -0,0 +1,21 @@ +package com.dfsek.terra.registry; + +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.world.palette.Palette; +import com.dfsek.terra.biome.palette.SinglePalette; + +public class PaletteRegistry extends TerraRegistry> { + private final TerraPlugin main; + public PaletteRegistry(TerraPlugin main) { + this.main = main; + } + + + @Override + public Palette get(String id) { + if(id.startsWith("BLOCK:")) + return new SinglePalette<>(main.getWorldHandle().createBlockData(id.substring(6))); // Return single palette for BLOCK: shortcut. + return super.get(id); + } +} diff --git a/common/src/main/java/com/dfsek/terra/registry/ScriptRegistry.java b/common/src/main/java/com/dfsek/terra/registry/ScriptRegistry.java new file mode 100644 index 000000000..703f971b6 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/registry/ScriptRegistry.java @@ -0,0 +1,6 @@ +package com.dfsek.terra.registry; + +import com.dfsek.terra.api.structures.script.StructureScript; + +public class ScriptRegistry extends TerraRegistry { +} diff --git a/src/main/java/com/dfsek/terra/registry/StructureRegistry.java b/common/src/main/java/com/dfsek/terra/registry/StructureRegistry.java similarity index 66% rename from src/main/java/com/dfsek/terra/registry/StructureRegistry.java rename to common/src/main/java/com/dfsek/terra/registry/StructureRegistry.java index 70af101f2..a66878751 100644 --- a/src/main/java/com/dfsek/terra/registry/StructureRegistry.java +++ b/common/src/main/java/com/dfsek/terra/registry/StructureRegistry.java @@ -1,6 +1,6 @@ package com.dfsek.terra.registry; -import com.dfsek.terra.generation.items.TerraStructure; +import com.dfsek.terra.population.items.TerraStructure; public class StructureRegistry extends TerraRegistry { } diff --git a/src/main/java/com/dfsek/terra/registry/TerraRegistry.java b/common/src/main/java/com/dfsek/terra/registry/TerraRegistry.java similarity index 100% rename from src/main/java/com/dfsek/terra/registry/TerraRegistry.java rename to common/src/main/java/com/dfsek/terra/registry/TerraRegistry.java diff --git a/common/src/main/java/com/dfsek/terra/registry/TreeRegistry.java b/common/src/main/java/com/dfsek/terra/registry/TreeRegistry.java new file mode 100644 index 000000000..b705de472 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/registry/TreeRegistry.java @@ -0,0 +1,102 @@ +package com.dfsek.terra.registry; + +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.platform.block.BlockFace; +import com.dfsek.terra.api.platform.block.MaterialData; +import com.dfsek.terra.api.world.tree.Tree; +import com.dfsek.terra.api.world.tree.fractal.FractalTree; +import com.dfsek.terra.api.world.tree.fractal.trees.Cactus; +import com.dfsek.terra.api.world.tree.fractal.trees.IceSpike; +import com.dfsek.terra.api.world.tree.fractal.trees.OakTree; +import com.dfsek.terra.api.world.tree.fractal.trees.ShatteredPillar; +import com.dfsek.terra.api.world.tree.fractal.trees.ShatteredTree; +import com.dfsek.terra.api.world.tree.fractal.trees.SmallShatteredPillar; +import com.dfsek.terra.api.world.tree.fractal.trees.SmallShatteredTree; +import com.dfsek.terra.api.world.tree.fractal.trees.SpruceTree; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.Random; +import java.util.Set; + +public class TreeRegistry extends TerraRegistry { + private final TerraPlugin main; + + public TreeRegistry(TerraPlugin main) { + this.main = main; + addTree("ACACIA"); + addTree("BIRCH"); + addTree("BROWN_MUSHROOM"); + tryAdd("CACTUS", Cactus.class); + addTree("CHORUS_PLANT"); + addTree("DARK_OAK"); + tryAdd("GIANT_OAK", OakTree.class); + tryAdd("GIANT_SPRUCE", SpruceTree.class); + addTree("JUNGLE"); + addTree("JUNGLE_COCOA"); + addTree("JUNGLE_BUSH"); + addTree("LARGE_OAK"); + tryAdd("LARGE_SHATTERED_PILLAR", ShatteredPillar.class); + addTree("LARGE_SPRUCE"); + addTree("MEGA_SPRUCE"); + addTree("OAK"); + addTree("RED_MUSHROOM"); + tryAdd("SHATTERED_LARGE", ShatteredTree.class); + tryAdd("SHATTERED_SMALL", SmallShatteredTree.class); + addTree("SMALL_JUNGLE"); + addTree("SPRUCE"); + addTree("SWAMP_OAK"); + tryAdd("SMALL_SHATTERED_PILLAR", SmallShatteredPillar.class); + tryAdd("ICE_SPIKE", IceSpike.class); + addTree("TALL_BIRCH"); + } + + private void addTree(String id) { + try { + add(id, main.getWorldHandle().getTree(id)); + } catch(IllegalArgumentException e) { + main.getLogger().warning("Unable to load tree " + id + ": " + e.getMessage()); + } + } + + private void tryAdd(String id, Class value) { + try { + add(id, new FractalTreeHolder(value)); + } catch(Exception e) { + main.getLogger().warning("Unable to load tree " + id + ": " + e.getMessage()); + } + } + + @Override + public boolean add(String name, Tree value) { + return super.add(name, value); + } + + private final class FractalTreeHolder implements Tree { + private final FractalTree tree; + + private FractalTreeHolder(Class clazz) throws NoSuchMethodException { + Constructor constructor = clazz.getConstructor(TerraPlugin.class); + try { + tree = constructor.newInstance(main); + } catch(InstantiationException | IllegalAccessException | InvocationTargetException e) { + e.printStackTrace(); + throw new IllegalArgumentException("Unable to load tree: " + clazz); + } + } + + @Override + public boolean plant(Location l, Random r) { + if(!getSpawnable().contains(l.getBlock().getType())) return false; + if(!l.getBlock().getRelative(BlockFace.UP).isEmpty()) return false; + tree.grow(l.add(0, 1, 0), r); + return true; + } + + @Override + public Set getSpawnable() { + return tree.getSpawnable(); + } + } +} diff --git a/src/main/java/com/dfsek/terra/util/MaterialSet.java b/common/src/main/java/com/dfsek/terra/util/MaterialSet.java similarity index 58% rename from src/main/java/com/dfsek/terra/util/MaterialSet.java rename to common/src/main/java/com/dfsek/terra/util/MaterialSet.java index e60321207..455051d97 100644 --- a/src/main/java/com/dfsek/terra/util/MaterialSet.java +++ b/common/src/main/java/com/dfsek/terra/util/MaterialSet.java @@ -1,30 +1,26 @@ package com.dfsek.terra.util; -import org.bukkit.Material; -import org.bukkit.block.data.BlockData; +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.block.MaterialData; import java.util.Arrays; import java.util.HashSet; -public class MaterialSet extends HashSet { +public class MaterialSet extends HashSet { private static final long serialVersionUID = 3056512763631017301L; - public static MaterialSet singleton(Material material) { + public static MaterialSet singleton(MaterialData material) { MaterialSet set = new MaterialSet(); set.add(material); return set; } - public static MaterialSet get(Material... materials) { + public static MaterialSet get(MaterialData... materials) { MaterialSet set = new MaterialSet(); set.addAll(Arrays.asList(materials)); return set; } - public void addTag(String tag) { - this.addAll(TagUtil.getTag(tag)); - } - private void add(BlockData data) { add(data.getMaterial()); } diff --git a/common/src/main/java/com/dfsek/terra/util/PaletteUtil.java b/common/src/main/java/com/dfsek/terra/util/PaletteUtil.java new file mode 100644 index 000000000..7a2b5fa93 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/util/PaletteUtil.java @@ -0,0 +1,18 @@ +package com.dfsek.terra.util; + +import com.dfsek.terra.api.math.MathUtil; +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.world.palette.Palette; +import com.dfsek.terra.biome.palette.PaletteHolder; +import com.dfsek.terra.config.templates.BiomeTemplate; +import com.dfsek.terra.generation.math.Sampler; + +public final class PaletteUtil { + public static Palette getPalette(int x, int y, int z, BiomeTemplate c, Sampler sampler) { + PaletteHolder slant = c.getSlantPalette(); + if(slant != null && MathUtil.derivative(sampler, x, y, z) > c.getSlantThreshold()) { + return slant.getPalette(y); + } + return c.getPalette().getPalette(y); + } +} diff --git a/src/main/java/com/dfsek/terra/util/PopulationUtil.java b/common/src/main/java/com/dfsek/terra/util/PopulationUtil.java similarity index 63% rename from src/main/java/com/dfsek/terra/util/PopulationUtil.java rename to common/src/main/java/com/dfsek/terra/util/PopulationUtil.java index eb0638175..ec668dcf5 100644 --- a/src/main/java/com/dfsek/terra/util/PopulationUtil.java +++ b/common/src/main/java/com/dfsek/terra/util/PopulationUtil.java @@ -1,8 +1,8 @@ package com.dfsek.terra.util; -import org.bukkit.Chunk; -import org.polydev.gaea.math.MathUtil; -import org.polydev.gaea.util.FastRandom; +import com.dfsek.terra.api.math.MathUtil; +import com.dfsek.terra.api.platform.world.Chunk; +import com.dfsek.terra.api.util.FastRandom; public final class PopulationUtil { public static FastRandom getRandom(Chunk c) { diff --git a/src/main/java/com/dfsek/terra/util/hash/HashIntrinsic.java b/common/src/main/java/com/dfsek/terra/util/hash/HashIntrinsic.java similarity index 100% rename from src/main/java/com/dfsek/terra/util/hash/HashIntrinsic.java rename to common/src/main/java/com/dfsek/terra/util/hash/HashIntrinsic.java diff --git a/src/main/java/com/dfsek/terra/util/hash/HashMapDoubleDouble.java b/common/src/main/java/com/dfsek/terra/util/hash/HashMapDoubleDouble.java similarity index 100% rename from src/main/java/com/dfsek/terra/util/hash/HashMapDoubleDouble.java rename to common/src/main/java/com/dfsek/terra/util/hash/HashMapDoubleDouble.java diff --git a/common/src/test/java/structure/LookaheadTest.java b/common/src/test/java/structure/LookaheadTest.java new file mode 100644 index 000000000..fd1e10724 --- /dev/null +++ b/common/src/test/java/structure/LookaheadTest.java @@ -0,0 +1,20 @@ +package structure; + +import com.dfsek.terra.api.structures.tokenizer.Lookahead; +import org.junit.jupiter.api.Test; + +import java.io.StringReader; + +public class LookaheadTest { + @Test + public void lookahead() { + Lookahead lookahead = new Lookahead(new StringReader("Test string...")); + + for(int i = 0; lookahead.next(i) != null; i++) { + System.out.print(lookahead.next(i).getCharacter()); + } + while(lookahead.next(0) != null) { + System.out.print(lookahead.consume().getCharacter()); + } + } +} diff --git a/common/src/test/java/structure/ParserTest.java b/common/src/test/java/structure/ParserTest.java new file mode 100644 index 000000000..4dd7e1b68 --- /dev/null +++ b/common/src/test/java/structure/ParserTest.java @@ -0,0 +1,84 @@ +package structure; + +import com.dfsek.terra.api.structures.parser.Parser; +import com.dfsek.terra.api.structures.parser.exceptions.ParseException; +import com.dfsek.terra.api.structures.parser.lang.Block; +import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.parser.lang.functions.Function; +import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.api.structures.tokenizer.Position; +import org.apache.commons.io.IOUtils; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.util.List; + +public class ParserTest { + @Test + public void parse() throws IOException, ParseException { + Parser parser = new Parser(IOUtils.toString(getClass().getResourceAsStream("/test.tesf"))); + + parser.registerFunction("test", new FunctionBuilder() { + @Override + public Test1 build(List> argumentList, Position position) { + return new Test1(argumentList.get(0), argumentList.get(1), position); + } + + @Override + public int argNumber() { + return 2; + } + + @Override + public Returnable.ReturnType getArgument(int position) { + switch(position) { + case 0: + return Returnable.ReturnType.STRING; + case 1: + return Returnable.ReturnType.NUMBER; + default: + return null; + } + } + + }); + + long l = System.nanoTime(); + Block block = parser.parse(); + long t = System.nanoTime() - l; + System.out.println("Took " + (double) t / 1000000); + + block.apply(null); + + block.apply(null); + } + + private static class Test1 implements Function { + private final Returnable a; + private final Returnable b; + private final Position position; + + public Test1(Returnable a, Returnable b, Position position) { + this.a = a; + this.b = b; + this.position = position; + } + + @Override + public Void apply(ImplementationArguments implementationArguments) { + System.out.println("string: " + a.apply(implementationArguments) + ", double: " + b.apply(implementationArguments)); + return null; + } + + @Override + public Position getPosition() { + return position; + } + + @Override + public ReturnType returnType() { + return ReturnType.VOID; + } + } +} diff --git a/common/src/test/resources/test.tesf b/common/src/test/resources/test.tesf new file mode 100644 index 000000000..93fe11eda --- /dev/null +++ b/common/src/test/resources/test.tesf @@ -0,0 +1,99 @@ +id "testScript"; + +bool thing1 = 2 > (2+2) || false; + +if(2 > 2 || 3 + 4 <= 2 && 4 + 5 > 2 / 3) { + test("ok", 2); +} + +test("minecraft:green_w" + "ool", (2 * (3+1) * (2 * (1+1)))); +// + +num testVar = 3.4; +bool boolean = true; +str stringVar = "hello!"; + +num precedence = 3 + 2 * 2 + 3; +test("precedence: " + precedence, 2); +num precedence2 = 3 * 2 + 2 * 3; +test("precedence 2: " + precedence2, 2); + +bool iftest = false; + +bool truetest = false; + +num iterator = 0; +num thing = 4 - 2-2+2-2+2; +test("4 - 2 = " + thing, 2); + +thing = -2; +test("-2 = " + thing, 2); +thing = -thing; +test("--2 = " + thing, 2); + + + +for(num i = 0; i < 5; i = i + 1) { + test("i = " + i, iterator); + if(i > 1 + 1) { + test("more than 2", iterator); + continue; + } +} + +for(num i = 0; i < 5; i = i + 1) { + test("i = " + i, iterator); +} + +for(num j = 0; j < 5; j = j + 1) test("single statement j = " + j, iterator); + +if(4 + 2 == 2 + 4) { + test("new thing " + 2, iterator); +} + +while(iterator < 5) { + test("always, even after " + 2, iterator); + iterator = iterator + 1; + if(iterator > 2) { + continue; + } + test("not after " + 2, iterator); +} + +if(true) test("single statement" + 2, iterator); +else if(true) test("another single statement" + 2, iterator); + +if(true) { + test("true!" + 2, iterator); +} else { + test("false!" + 2, iterator); + } + +if(false) { + test("true!" + 2, iterator); +} else { + test("false!" + 2, iterator); +} + +if(false) { + test("true again!" + 2, iterator); +} else if(true == true) { + test("false again!" + 2, iterator); +} else { + test("not logged!" + 2, iterator); +} + + + +// comment + +/* +fsdfsd +*/ + +test("fdsgdf" + 2, 1 + testVar); + +if(true && !(boolean && false) && true) { + num scopedVar = 2; + test("if statement" + 2 + stringVar, 1 + testVar + scopedVar); +} \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 62d4c0535..e708b1c02 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 12d38de6a..be52383ef 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/platforms/bukkit/build.gradle.kts b/platforms/bukkit/build.gradle.kts new file mode 100644 index 000000000..2a04443bf --- /dev/null +++ b/platforms/bukkit/build.gradle.kts @@ -0,0 +1,111 @@ +import com.dfsek.terra.configureCommon +import com.dfsek.terra.gitClone +import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar +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 { + `java-library` +} +configureCommon() + +group = "com.dfsek.terra.bukkit" + +repositories { + mavenCentral() + 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/") } +} + +dependencies { + "shadedApi"(project(":common")) + + "compileOnly"("org.spigotmc:spigot-api:1.16.2-R0.1-SNAPSHOT") + "shadedImplementation"("io.papermc:paperlib:1.0.5") + + "shadedImplementation"("org.bstats:bstats-bukkit:1.7") + + "compileOnly"("com.sk89q.worldedit:worldedit-bukkit:7.2.0-SNAPSHOT") +} + +tasks.withType { + include("**/*.yml") + filter( + "tokens" to mapOf( + "VERSION" to project.version.toString() + ) + ) +} + +val testDir = "target/server/" + +val setupServer = tasks.create("setupServer") { + dependsOn("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 testWithPaper = task(name = "testWithPaper") { + standardInput = System.`in` + dependsOn("shadowJar") + // Copy Terra into dir + doFirst { + copy { + from("${buildDir}/libs/bukkit-${version}-shaded.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 = "3G" + minHeapSize = "3G" + args = listOf("nogui") + workingDir = file("${testDir}/") + classpath = files("${testDir}/paper.jar") +} + +tasks.named("shadowJar") { + relocate("org.bstats.bukkit", "com.dfsek.terra.lib.bstats") + relocate("io.papermc.lib", "com.dfsek.terra.lib.paperlib") +} \ No newline at end of file diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/BukkitCommandSender.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/BukkitCommandSender.java new file mode 100644 index 000000000..ed65c569a --- /dev/null +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/BukkitCommandSender.java @@ -0,0 +1,22 @@ +package com.dfsek.terra.bukkit; + +import com.dfsek.terra.api.platform.CommandSender; +import org.bukkit.ChatColor; + +public class BukkitCommandSender implements CommandSender { + private final org.bukkit.command.CommandSender delegate; + + public BukkitCommandSender(org.bukkit.command.CommandSender delegate) { + this.delegate = delegate; + } + + @Override + public void sendMessage(String message) { + delegate.sendMessage(ChatColor.translateAlternateColorCodes('&', message)); + } + + @Override + public org.bukkit.command.CommandSender getHandle() { + return delegate; + } +} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/BukkitEntity.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/BukkitEntity.java new file mode 100644 index 000000000..5ef812e0f --- /dev/null +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/BukkitEntity.java @@ -0,0 +1,16 @@ +package com.dfsek.terra.bukkit; + +import com.dfsek.terra.api.platform.world.entity.Entity; + +public class BukkitEntity implements Entity { + private final org.bukkit.entity.Entity entity; + + public BukkitEntity(org.bukkit.entity.Entity entity) { + this.entity = entity; + } + + @Override + public org.bukkit.entity.Entity getHandle() { + return entity; + } +} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/BukkitPlayer.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/BukkitPlayer.java new file mode 100644 index 000000000..c59491a59 --- /dev/null +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/BukkitPlayer.java @@ -0,0 +1,24 @@ +package com.dfsek.terra.bukkit; + +import com.dfsek.terra.api.Player; +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.bukkit.world.BukkitAdapter; + +public class BukkitPlayer implements Player { + private final org.bukkit.entity.Player delegate; + + public BukkitPlayer(org.bukkit.entity.Player delegate) { + this.delegate = delegate; + } + + @Override + public org.bukkit.entity.Player getHandle() { + return delegate; + } + + @Override + public Location getLocation() { + org.bukkit.Location bukkit = delegate.getLocation(); + return new Location(BukkitAdapter.adapt(bukkit.getWorld()), bukkit.getX(), bukkit.getY(), bukkit.getZ()); + } +} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/TerraBukkitPlugin.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/TerraBukkitPlugin.java new file mode 100644 index 000000000..b81acd213 --- /dev/null +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/TerraBukkitPlugin.java @@ -0,0 +1,243 @@ +package com.dfsek.terra.bukkit; + +import com.dfsek.tectonic.loading.TypeRegistry; +import com.dfsek.terra.TerraWorld; +import com.dfsek.terra.api.GenericLoaders; +import com.dfsek.terra.api.language.Language; +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.block.MaterialData; +import com.dfsek.terra.api.platform.handle.ItemHandle; +import com.dfsek.terra.api.platform.handle.WorldHandle; +import com.dfsek.terra.api.platform.world.Biome; +import com.dfsek.terra.api.platform.world.Tree; +import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.api.transform.MapTransform; +import com.dfsek.terra.api.transform.Transformer; +import com.dfsek.terra.bukkit.command.command.TerraCommand; +import com.dfsek.terra.bukkit.command.command.structure.LocateCommand; +import com.dfsek.terra.bukkit.generator.BukkitChunkGeneratorWrapper; +import com.dfsek.terra.bukkit.handles.BukkitItemHandle; +import com.dfsek.terra.bukkit.handles.BukkitWorldHandle; +import com.dfsek.terra.bukkit.listeners.EventListener; +import com.dfsek.terra.bukkit.listeners.SpigotListener; +import com.dfsek.terra.bukkit.util.PaperUtil; +import com.dfsek.terra.bukkit.world.BukkitBiome; +import com.dfsek.terra.bukkit.world.BukkitTree; +import com.dfsek.terra.config.base.ConfigPack; +import com.dfsek.terra.config.base.PluginConfig; +import com.dfsek.terra.config.lang.LangUtil; +import com.dfsek.terra.debug.Debug; +import com.dfsek.terra.generation.MasterChunkGenerator; +import com.dfsek.terra.registry.ConfigRegistry; +import org.bstats.bukkit.Metrics; +import org.bukkit.Bukkit; +import org.bukkit.TreeType; +import org.bukkit.command.PluginCommand; +import org.bukkit.entity.EntityType; +import org.bukkit.generator.ChunkGenerator; +import org.bukkit.plugin.java.JavaPlugin; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + + +public class TerraBukkitPlugin extends JavaPlugin implements TerraPlugin { + private final Map generatorMap = new HashMap<>(); + private final Map worldMap = new HashMap<>(); + private final Map worlds = new HashMap<>(); + private final ConfigRegistry registry = new ConfigRegistry(); + private final PluginConfig config = new PluginConfig(); + private final ItemHandle itemHandle = new BukkitItemHandle(); + private WorldHandle handle = new BukkitWorldHandle(this); + private final GenericLoaders genericLoaders = new GenericLoaders(this); + + public static final Version BUKKIT_VERSION; + + static { + String ver = Bukkit.getServer().getClass().getPackage().getName(); + if(ver.contains("1_16")) BUKKIT_VERSION = Version.V1_16; + else if(ver.contains("1_15")) BUKKIT_VERSION = Version.V1_15; + else if(ver.contains("1_14")) BUKKIT_VERSION = Version.V1_14; + else if(ver.contains("1_13")) BUKKIT_VERSION = Version.V1_13; + else BUKKIT_VERSION = Version.UNKNOWN; + } + + + public void reload() { + Map newMap = new HashMap<>(); + worldMap.forEach((world, tw) -> { + ((MasterChunkGenerator) ((BukkitChunkGeneratorWrapper) world.getGenerator().getHandle()).getHandle()).getCache().clear(); + String packID = tw.getConfig().getTemplate().getID(); + newMap.put(world, new TerraWorld(world, registry.get(packID), this)); + }); + worldMap.clear(); + worldMap.putAll(newMap); + } + + @Override + public ItemHandle getItemHandle() { + return itemHandle; + } + + @Override + public String platformName() { + return "Bukkit"; + } + + public void setHandle(WorldHandle handle) { + getLogger().warning("|-------------------------------------------------------|"); + getLogger().warning("A third-party addon has injected a custom WorldHandle!"); + getLogger().warning("If you encounter issues, try *without* the addon before"); + getLogger().warning("reporting to Terra. Report issues with the addon to the"); + getLogger().warning("addon's maintainers!"); + getLogger().warning("|-------------------------------------------------------|"); + this.handle = handle; + } + + @Override + public void onDisable() { + BukkitChunkGeneratorWrapper.saveAll(); + } + + @Override + public void onEnable() { + Debug.setLogger(getLogger()); // Set debug logger. + + getLogger().info("Running on version " + BUKKIT_VERSION); + if(BUKKIT_VERSION.equals(Version.UNKNOWN)) { + getLogger().warning("Terra is running on an unknown Bukkit version. Proceed with caution."); + } + + ((BukkitWorldHandle) handle).setTreeTransformer(new Transformer.Builder() + .addTransform(id -> new BukkitTree(TreeType.valueOf(id), this)) // First try getting directly from enum + .addTransform(new MapTransform() // Then try map of less stupid names + .add("JUNGLE_COCOA", new BukkitTree(TreeType.COCOA_TREE, this)) + .add("LARGE_OAK", new BukkitTree(TreeType.BIG_TREE, this)) + .add("LARGE_SPRUCE", new BukkitTree(TreeType.TALL_REDWOOD, this)) + .add("SPRUCE", new BukkitTree(TreeType.REDWOOD, this)) + .add("OAK", new BukkitTree(TreeType.TREE, this)) + .add("MEGA_SPRUCE", new BukkitTree(TreeType.MEGA_REDWOOD, this)) + .add("SWAMP_OAK", new BukkitTree(TreeType.SWAMP, this))) + .addTransform(id -> new BukkitTree(TreeType.valueOf(id), this)) // Finally, try stripping minecraft namespace. + .build()); + + saveDefaultConfig(); + + Metrics metrics = new Metrics(this, 9017); // Set up bStats. + metrics.addCustomChart(new Metrics.SingleLineChart("worlds", worldMap::size)); // World number chart. + + config.load(this); // Load master config.yml + LangUtil.load(config.getLanguage(), this); // Load language. + Debug.setDebug(isDebug()); + + registry.loadAll(this); // Load all config packs. + + PluginCommand c = Objects.requireNonNull(getCommand("terra")); + TerraCommand command = new TerraCommand(this); // Set up main Terra command. + c.setExecutor(command); + c.setTabCompleter(command); + + LocateCommand locate = new LocateCommand(command); + PluginCommand locatePl = Objects.requireNonNull(getCommand("locate")); + locatePl.setExecutor(locate); // Override locate command. Once Paper accepts StructureLocateEvent this will be unneeded on Paper implementations. + locatePl.setTabCompleter(locate); + + + long save = config.getDataSaveInterval(); + Bukkit.getScheduler().runTaskTimerAsynchronously(this, BukkitChunkGeneratorWrapper::saveAll, save, save); // Schedule population data saving + + Bukkit.getPluginManager().registerEvents(new EventListener(this), this); // Register master event listener + Bukkit.getPluginManager().registerEvents(new SpigotListener(this), this); // Register Spigot event listener, once Paper accepts StructureLocateEvent PR Spigot and Paper events will be separate. + + PaperUtil.checkPaper(this); + } + + @Override + public @Nullable ChunkGenerator getDefaultWorldGenerator(@NotNull String worldName, @Nullable String id) { + return new BukkitChunkGeneratorWrapper(generatorMap.computeIfAbsent(worldName, name -> { + if(!registry.contains(id)) throw new IllegalArgumentException("No such config pack \"" + id + "\""); + ConfigPack pack = registry.get(id); + worlds.put(worldName, pack); + return new MasterChunkGenerator(registry.get(id), this, pack.getSamplerCache()); + })); + } + + @Override + public boolean isDebug() { + return config.isDebug(); + } + + + @Override + public Language getLanguage() { + return LangUtil.getLanguage(); + } + + public ConfigRegistry getRegistry() { + return registry; + } + + public TerraWorld getWorld(World w) { + if(!TerraWorld.isTerraWorld(w)) + throw new IllegalArgumentException("Not a Terra world! " + w.getGenerator()); + if(!worlds.containsKey(w.getName())) { + getLogger().warning("Unexpected world load detected: \"" + w.getName() + "\""); + return new TerraWorld(w, ((MasterChunkGenerator) w.getGenerator().getHandle()).getConfigPack(), this); + } + return worldMap.computeIfAbsent(w, world -> new TerraWorld(w, worlds.get(w.getName()), this)); + } + + @NotNull + @Override + public PluginConfig getTerraConfig() { + return config; + } + + @Override + public WorldHandle getWorldHandle() { + return handle; + } + + + @Override + public void register(TypeRegistry registry) { + registry + .registerLoader(BlockData.class, (t, o, l) -> handle.createBlockData((String) o)) + .registerLoader(MaterialData.class, (t, o, l) -> handle.createMaterialData((String) o)) + .registerLoader(Biome.class, (t, o, l) -> new BukkitBiome(org.bukkit.block.Biome.valueOf((String) o))) + .registerLoader(EntityType.class, (t, o, l) -> EntityType.valueOf((String) o)); + genericLoaders.register(registry); + } + + public enum Version { + V1_13(13), + + V1_14(14), + + V1_15(15), + + V1_16(16), + + UNKNOWN(Integer.MAX_VALUE); // Assume unknown version is latest. + + private final int index; + + Version(int index) { + this.index = index; + } + + /** + * Gets if this version is above or equal to another. + * + * @param other Other version + * @return Whether this version is equal to or later than other. + */ + public boolean above(Version other) { + return this.index >= other.index; + } + } +} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/Command.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/Command.java new file mode 100644 index 000000000..913e07798 --- /dev/null +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/Command.java @@ -0,0 +1,112 @@ +package com.dfsek.terra.bukkit.command; + +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.bukkit.BukkitCommandSender; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.command.TabCompleter; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * Represents a command or subcommand, can be nested via getSubCommands. + */ +public abstract class Command implements CommandExecutor, TabCompleter { + private final TerraPlugin main; + public Command(TerraPlugin main) { + this.main = main; + } + public Command(Command parent) { + main = parent.getMain(); + } + + public TerraPlugin getMain() { + return main; + } + + /** + * Gets the name of the command/subcommand + * @return Name of command + */ + public abstract String getName(); + + /** + * Gets a list of subcommands + * @return List of subcommands + */ + public abstract List getSubCommands(); + + /** + * Executes the given command, returning its success. + *
+ * If false is returned, then the "usage" plugin.yml entry for this command + * (if defined) will be sent to the player. + * + * @param sender Source of the command + * @param command Command which was executed + * @param label Alias of the command which was used + * @param args Passed command arguments + * @return true if a valid command, otherwise false + */ + + public abstract boolean execute(@NotNull CommandSender sender, @NotNull org.bukkit.command.Command command, @NotNull String label, @NotNull String[] args); + /** + * Gets the number of arguments + * @return Number of arguments + */ + public abstract int arguments(); + + /** + * Executes the given command, invoking subcommands if applicable and returning its success. + *
+ * If false is returned, then the "usage" plugin.yml entry for this command + * (if defined) will be sent to the player. + * + * @param sender Source of the command + * @param command Command which was executed + * @param label Alias of the command which was used + * @param args Passed command arguments + * @return true if a valid command, otherwise false + */ + @Override + public final boolean onCommand(@NotNull CommandSender sender, @NotNull org.bukkit.command.Command command, @NotNull String label, @NotNull String[] args) { + if(this instanceof DebugCommand && ! main.isDebug()) { + main.getLanguage().send("command.debug-only", new BukkitCommandSender(sender)); + return true; + } + if(args.length > 0) { + for(Command c : getSubCommands()) { + if(c.getName().equals(args[0])) { + return c.onCommand(sender, command, label, Arrays.stream(args, 1, args.length).toArray(String[]::new)); + } + } + if(args.length != arguments()) { + main.getLanguage().send("command.invalid", new BukkitCommandSender(sender), String.valueOf(arguments()), String.valueOf(args.length)); + return true; + } + return execute(sender, command, label, args); + } + if(args.length != arguments()) { + main.getLanguage().send("command.invalid", new BukkitCommandSender(sender), String.valueOf(arguments()), String.valueOf(args.length)); + return true; + } + return execute(sender, command, label, new String[] {}); + } + + public abstract List getTabCompletions(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args); + + @Override + public final @Nullable List onTabComplete(@NotNull CommandSender sender, org.bukkit.command.@NotNull Command command, @NotNull String alias, @NotNull String[] args) { + List complete = new ArrayList<>(); + if(args.length > 0) for(Command c : getSubCommands()) { + if(c.getName().startsWith(args[0])) complete.add(c.getName()); + if(c.getName().equals(args[0])) return c.onTabComplete(sender, command, alias, Arrays.stream(args, 1, args.length).toArray(String[]::new)); + } + complete.addAll(getTabCompletions(sender, alias, args)); + return complete; + } +} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/DebugCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/DebugCommand.java new file mode 100644 index 000000000..738dde4fc --- /dev/null +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/DebugCommand.java @@ -0,0 +1,8 @@ +package com.dfsek.terra.bukkit.command; + +/** + * Implementing this interface marks a command as debug-only. + * If a parent command implements this interface, all child commands will be considered debug commands, regardless of whether they implement DebugCommand as well. + */ +public interface DebugCommand { +} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/PlayerCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/PlayerCommand.java new file mode 100644 index 000000000..4f19eb741 --- /dev/null +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/PlayerCommand.java @@ -0,0 +1,50 @@ +package com.dfsek.terra.bukkit.command; + +import com.dfsek.terra.bukkit.BukkitCommandSender; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +/** + * A command that may only be executed by a player. If executor is not a player, a message will be displayed and no action will be performed. + */ +public abstract class PlayerCommand extends Command { + public PlayerCommand(Command parent) { + super(parent); + } + + /** + * Executes the given command, returning its success. + *
+ * If false is returned, then the "usage" plugin.yml entry for this command + * (if defined) will be sent to the player. + * + * @param sender Source of the command + * @param command Command which was executed + * @param label Alias of the command which was used + * @param args Passed command arguments + * @return true if a valid command, otherwise false + */ + @Override + public final boolean execute(@NotNull CommandSender sender, org.bukkit.command.@NotNull Command command, @NotNull String label, @NotNull String[] args) { + if(!(sender instanceof Player)) { + getMain().getLanguage().send("command.players-only", new BukkitCommandSender(sender)); + return true; + } + Player p = (Player) sender; + return execute(p, command, label, args); + } + /** + * Executes the given command, returning its success. + *
+ * If false is returned, then the "usage" plugin.yml entry for this command + * (if defined) will be sent to the player. + * + * @param sender Player that executed command + * @param command Command which was executed + * @param label Alias of the command which was used + * @param args Passed command arguments + * @return true if a valid command, otherwise false + */ + public abstract boolean execute(@NotNull Player sender, org.bukkit.command.@NotNull Command command, @NotNull String label, @NotNull String[] args); +} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/WorldCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/WorldCommand.java new file mode 100644 index 000000000..65738d220 --- /dev/null +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/WorldCommand.java @@ -0,0 +1,53 @@ +package com.dfsek.terra.bukkit.command; + +import com.dfsek.terra.bukkit.BukkitCommandSender; +import org.bukkit.World; +import org.bukkit.entity.Player; +import org.bukkit.generator.ChunkGenerator; +import org.jetbrains.annotations.NotNull; + +/** + * A command that must be executed by a player, in a Terra world. + */ +public abstract class WorldCommand extends PlayerCommand { + public WorldCommand(Command parent) { + super(parent); + } + + /** + * Executes the given command, returning its success. + *
+ * If false is returned, then the "usage" plugin.yml entry for this command + * (if defined) will be sent to the player. + * + * @param sender Source of the command + * @param command Command which was executed + * @param label Alias of the command which was used + * @param args Passed command arguments + * @return true if a valid command, otherwise false + */ + @Override + public boolean execute(@NotNull Player sender, org.bukkit.command.@NotNull Command command, @NotNull String label, @NotNull String[] args) { + if(sender.getWorld().getGenerator() instanceof ChunkGenerator) { // TODO: implementation + return execute(sender, command, label, args, sender.getWorld()); + } else { + getMain().getLanguage().send("command.world", new BukkitCommandSender(sender)); + } + return true; + } + + /** + * Executes the given command, returning its success. + *
+ * If false is returned, then the "usage" plugin.yml entry for this command + * (if defined) will be sent to the player. + * + * @param sender Player that executed command + * @param command Command which was executed + * @param label Alias of the command which was used + * @param args Passed command arguments + * @param world World in which command was executed + * @return true if a valid command, otherwise false + */ + public abstract boolean execute(@NotNull Player sender, @NotNull org.bukkit.command.Command command, @NotNull String label, @NotNull String[] args, World world); +} diff --git a/src/main/java/com/dfsek/terra/command/FixChunkCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/FixChunkCommand.java similarity index 65% rename from src/main/java/com/dfsek/terra/command/FixChunkCommand.java rename to platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/FixChunkCommand.java index 5eec78eca..4b9d730d7 100644 --- a/src/main/java/com/dfsek/terra/command/FixChunkCommand.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/FixChunkCommand.java @@ -1,24 +1,25 @@ -package com.dfsek.terra.command; +package com.dfsek.terra.bukkit.command.command; -import com.dfsek.terra.generation.TerraChunkGenerator; +import com.dfsek.terra.bukkit.command.WorldCommand; +import com.dfsek.terra.bukkit.generator.BukkitChunkGeneratorWrapper; +import com.dfsek.terra.bukkit.world.BukkitAdapter; import org.bukkit.World; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; -import org.polydev.gaea.command.WorldCommand; import java.util.Collections; import java.util.List; public class FixChunkCommand extends WorldCommand { - public FixChunkCommand(org.polydev.gaea.command.Command parent) { + public FixChunkCommand(com.dfsek.terra.bukkit.command.Command parent) { super(parent); } @Override public boolean execute(@NotNull Player player, @NotNull Command command, @NotNull String s, @NotNull String[] strings, World world) { - TerraChunkGenerator.fixChunk(player.getLocation().getChunk()); + BukkitChunkGeneratorWrapper.fixChunk(BukkitAdapter.adapt(player.getLocation().getChunk())); return true; } @@ -28,7 +29,7 @@ public class FixChunkCommand extends WorldCommand { } @Override - public List getSubCommands() { + public List getSubCommands() { return Collections.emptyList(); } diff --git a/src/main/java/com/dfsek/terra/command/PacksCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/PacksCommand.java similarity index 70% rename from src/main/java/com/dfsek/terra/command/PacksCommand.java rename to platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/PacksCommand.java index 583f71a8d..4b0e08e04 100644 --- a/src/main/java/com/dfsek/terra/command/PacksCommand.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/PacksCommand.java @@ -1,12 +1,12 @@ -package com.dfsek.terra.command; +package com.dfsek.terra.bukkit.command.command; -import com.dfsek.terra.Terra; +import com.dfsek.terra.bukkit.BukkitCommandSender; +import com.dfsek.terra.bukkit.command.Command; import com.dfsek.terra.config.base.ConfigPackTemplate; import com.dfsek.terra.config.lang.LangUtil; import com.dfsek.terra.registry.ConfigRegistry; import org.bukkit.command.CommandSender; import org.jetbrains.annotations.NotNull; -import org.polydev.gaea.command.Command; import java.util.Collections; import java.util.List; @@ -29,17 +29,17 @@ public class PacksCommand extends Command { @Override public boolean execute(@NotNull CommandSender commandSender, org.bukkit.command.@NotNull Command command, @NotNull String s, @NotNull String[] strings) { - ConfigRegistry registry = ((Terra) getMain()).getRegistry(); + ConfigRegistry registry = getMain().getRegistry(); if(registry.entries().size() == 0) { - LangUtil.send("command.packs.none", commandSender); + LangUtil.send("command.packs.none", new BukkitCommandSender(commandSender)); return true; } - LangUtil.send("command.packs.main", commandSender); + LangUtil.send("command.packs.main", new BukkitCommandSender(commandSender)); registry.entries().forEach(entry -> { ConfigPackTemplate template = entry.getTemplate(); - LangUtil.send("command.packs.pack", commandSender, template.getID(), template.getAuthor(), template.getVersion()); + LangUtil.send("command.packs.pack", new BukkitCommandSender(commandSender), template.getID(), template.getAuthor(), template.getVersion()); }); return true; diff --git a/src/main/java/com/dfsek/terra/command/ReloadCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/ReloadCommand.java similarity index 62% rename from src/main/java/com/dfsek/terra/command/ReloadCommand.java rename to platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/ReloadCommand.java index 306bc3bc8..b6b4093ac 100644 --- a/src/main/java/com/dfsek/terra/command/ReloadCommand.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/ReloadCommand.java @@ -1,11 +1,12 @@ -package com.dfsek.terra.command; +package com.dfsek.terra.bukkit.command.command; -import com.dfsek.terra.Terra; + +import com.dfsek.terra.bukkit.BukkitCommandSender; +import com.dfsek.terra.bukkit.command.Command; +import com.dfsek.terra.bukkit.command.DebugCommand; import com.dfsek.terra.config.lang.LangUtil; import org.bukkit.command.CommandSender; import org.jetbrains.annotations.NotNull; -import org.polydev.gaea.command.Command; -import org.polydev.gaea.command.DebugCommand; import java.util.Collections; import java.util.List; @@ -27,14 +28,14 @@ public class ReloadCommand extends Command implements DebugCommand { @Override public boolean execute(@NotNull CommandSender sender, org.bukkit.command.@NotNull Command command, @NotNull String label, @NotNull String[] args) { - ((Terra) getMain()).getTerraConfig().load(getMain()); - LangUtil.load(((Terra) getMain()).getTerraConfig().getLanguage(), getMain()); // Load language. - if(!((Terra) getMain()).getRegistry().loadAll((Terra) getMain())) { - LangUtil.send("command.reload-error", sender); + getMain().getTerraConfig().load(getMain()); + LangUtil.load(getMain().getTerraConfig().getLanguage(), getMain()); // Load language. + if(!getMain().getRegistry().loadAll(getMain())) { + LangUtil.send("command.reload-error", new BukkitCommandSender(sender)); return true; } - ((Terra) getMain()).reload(); - LangUtil.send("command.reload", sender); + getMain().reload(); + LangUtil.send("command.reload", new BukkitCommandSender(sender)); return true; } diff --git a/src/main/java/com/dfsek/terra/command/SaveDataCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/SaveDataCommand.java similarity index 71% rename from src/main/java/com/dfsek/terra/command/SaveDataCommand.java rename to platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/SaveDataCommand.java index 99c648e12..4cb09daba 100644 --- a/src/main/java/com/dfsek/terra/command/SaveDataCommand.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/SaveDataCommand.java @@ -1,13 +1,14 @@ -package com.dfsek.terra.command; +package com.dfsek.terra.bukkit.command.command; +import com.dfsek.terra.bukkit.BukkitCommandSender; +import com.dfsek.terra.bukkit.command.Command; +import com.dfsek.terra.bukkit.command.WorldCommand; +import com.dfsek.terra.bukkit.generator.BukkitChunkGeneratorWrapper; import com.dfsek.terra.config.lang.LangUtil; -import com.dfsek.terra.generation.TerraChunkGenerator; import org.bukkit.World; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; -import org.polydev.gaea.command.Command; -import org.polydev.gaea.command.WorldCommand; import java.util.Collections; import java.util.List; @@ -39,8 +40,8 @@ public class SaveDataCommand extends WorldCommand { @Override public boolean execute(@NotNull Player sender, org.bukkit.command.@NotNull Command command, @NotNull String label, @NotNull String[] args, World w) { - TerraChunkGenerator.saveAll(); - LangUtil.send("debug.data-save", sender, w.getName()); + BukkitChunkGeneratorWrapper.saveAll(); + LangUtil.send("debug.data-save", new BukkitCommandSender(sender), w.getName()); return true; } } diff --git a/src/main/java/com/dfsek/terra/command/TerraCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/TerraCommand.java similarity index 64% rename from src/main/java/com/dfsek/terra/command/TerraCommand.java rename to platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/TerraCommand.java index 07a8d23a7..ba3f16e96 100644 --- a/src/main/java/com/dfsek/terra/command/TerraCommand.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/TerraCommand.java @@ -1,15 +1,16 @@ -package com.dfsek.terra.command; +package com.dfsek.terra.bukkit.command.command; -import com.dfsek.terra.command.biome.BiomeCommand; -import com.dfsek.terra.command.geometry.GeometryCommand; -import com.dfsek.terra.command.image.ImageCommand; -import com.dfsek.terra.command.profile.ProfileCommand; -import com.dfsek.terra.command.structure.StructureCommand; +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.bukkit.BukkitCommandSender; +import com.dfsek.terra.bukkit.command.Command; +import com.dfsek.terra.bukkit.command.command.biome.BiomeCommand; +import com.dfsek.terra.bukkit.command.command.geometry.GeometryCommand; +import com.dfsek.terra.bukkit.command.command.image.ImageCommand; +import com.dfsek.terra.bukkit.command.command.profile.ProfileCommand; +import com.dfsek.terra.bukkit.command.command.structure.StructureCommand; import com.dfsek.terra.config.lang.LangUtil; import org.bukkit.command.CommandSender; import org.jetbrains.annotations.NotNull; -import org.polydev.gaea.GaeaPlugin; -import org.polydev.gaea.command.Command; import java.util.Arrays; import java.util.Collections; @@ -18,7 +19,6 @@ import java.util.List; public class TerraCommand extends Command { private final List commands = Arrays.asList(new ReloadCommand(this), new BiomeCommand(this), - new OreCommand(this), new ProfileCommand(this), new SaveDataCommand(this), new StructureCommand(this), @@ -28,13 +28,13 @@ public class TerraCommand extends Command { new VersionCommand(this), new PacksCommand(this)); - public TerraCommand(GaeaPlugin main) { + public TerraCommand(TerraPlugin main) { super(main); } @Override public String getName() { - return "terra"; + return "com/dfsek/terra"; } @Override @@ -44,7 +44,7 @@ public class TerraCommand extends Command { @Override public boolean execute(@NotNull CommandSender sender, org.bukkit.command.@NotNull Command command, @NotNull String label, @NotNull String[] args) { - LangUtil.send("command.main-menu", sender); + LangUtil.send("command.main-menu", new BukkitCommandSender(sender)); return true; } diff --git a/src/main/java/com/dfsek/terra/command/VersionCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/VersionCommand.java similarity index 66% rename from src/main/java/com/dfsek/terra/command/VersionCommand.java rename to platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/VersionCommand.java index 6cf7b7a28..b9686d186 100644 --- a/src/main/java/com/dfsek/terra/command/VersionCommand.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/VersionCommand.java @@ -1,15 +1,14 @@ -package com.dfsek.terra.command; +package com.dfsek.terra.bukkit.command.command; +import com.dfsek.terra.bukkit.BukkitCommandSender; +import com.dfsek.terra.bukkit.TerraBukkitPlugin; +import com.dfsek.terra.bukkit.command.Command; import com.dfsek.terra.config.lang.LangUtil; -import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; -import org.bukkit.plugin.Plugin; import org.jetbrains.annotations.NotNull; -import org.polydev.gaea.command.Command; import java.util.Collections; import java.util.List; -import java.util.Objects; public class VersionCommand extends Command { public VersionCommand(Command parent) { @@ -28,12 +27,8 @@ public class VersionCommand extends Command { @Override public boolean execute(@NotNull CommandSender sender, org.bukkit.command.@NotNull Command command, @NotNull String label, @NotNull String[] args) { - Plugin gaea = Objects.requireNonNull(Bukkit.getPluginManager().getPlugin("Gaea")); - String gaeaVersion = gaea.getDescription().getVersion(); - - String terraVersion = getMain().getDescription().getVersion(); - LangUtil.send("command.version", sender, terraVersion, gaeaVersion); - + String terraVersion = ((TerraBukkitPlugin) getMain()).getDescription().getVersion(); + LangUtil.send("command.version", new BukkitCommandSender(sender), terraVersion, getMain().platformName()); return true; } diff --git a/src/main/java/com/dfsek/terra/command/biome/BiomeCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/biome/BiomeCommand.java similarity index 60% rename from src/main/java/com/dfsek/terra/command/biome/BiomeCommand.java rename to platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/biome/BiomeCommand.java index 5a956e8b8..f7d131903 100644 --- a/src/main/java/com/dfsek/terra/command/biome/BiomeCommand.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/biome/BiomeCommand.java @@ -1,31 +1,31 @@ -package com.dfsek.terra.command.biome; +package com.dfsek.terra.bukkit.command.command.biome; -import com.dfsek.terra.Terra; +import com.dfsek.terra.api.world.generation.GenerationPhase; import com.dfsek.terra.biome.UserDefinedBiome; import com.dfsek.terra.biome.grid.master.TerraBiomeGrid; +import com.dfsek.terra.bukkit.command.WorldCommand; +import com.dfsek.terra.bukkit.world.BukkitAdapter; import com.dfsek.terra.config.lang.LangUtil; import org.bukkit.World; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; -import org.polydev.gaea.command.WorldCommand; -import org.polydev.gaea.generation.GenerationPhase; import java.util.Arrays; import java.util.Collections; import java.util.List; public class BiomeCommand extends WorldCommand { - public BiomeCommand(org.polydev.gaea.command.Command parent) { + public BiomeCommand(com.dfsek.terra.bukkit.command.Command parent) { super(parent); } @Override public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args, World w) { - TerraBiomeGrid grid = ((Terra) getMain()).getWorld(sender.getWorld()).getGrid(); - UserDefinedBiome biome = (UserDefinedBiome) grid.getBiome(sender.getLocation(), GenerationPhase.POPULATE); - LangUtil.send("command.biome.in", sender, biome.getID()); + TerraBiomeGrid grid = getMain().getWorld(BukkitAdapter.adapt(sender.getWorld())).getGrid(); + UserDefinedBiome biome = (UserDefinedBiome) grid.getBiome(BukkitAdapter.adapt(sender.getLocation()), GenerationPhase.POPULATE); + LangUtil.send("command.biome.in", BukkitAdapter.adapt(sender), biome.getID()); return true; } @@ -35,8 +35,8 @@ public class BiomeCommand extends WorldCommand { } @Override - public List getSubCommands() { - return Arrays.asList(new BiomeLocateCommand(this, true), new BiomeLocateCommand(this, false), new BiomeInfoCommand(this)); + public List getSubCommands() { + return Arrays.asList(new BiomeLocateCommand(this), new BiomeInfoCommand(this)); } @Override diff --git a/src/main/java/com/dfsek/terra/command/biome/BiomeInfoCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/biome/BiomeInfoCommand.java similarity index 76% rename from src/main/java/com/dfsek/terra/command/biome/BiomeInfoCommand.java rename to platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/biome/BiomeInfoCommand.java index 4a9025444..3d1c008f1 100644 --- a/src/main/java/com/dfsek/terra/command/biome/BiomeInfoCommand.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/biome/BiomeInfoCommand.java @@ -1,19 +1,20 @@ -package com.dfsek.terra.command.biome; +package com.dfsek.terra.bukkit.command.command.biome; -import com.dfsek.terra.Terra; +import com.dfsek.terra.TerraWorld; import com.dfsek.terra.biome.UserDefinedBiome; +import com.dfsek.terra.bukkit.BukkitCommandSender; +import com.dfsek.terra.bukkit.command.WorldCommand; +import com.dfsek.terra.bukkit.world.BukkitAdapter; import com.dfsek.terra.carving.UserDefinedCarver; import com.dfsek.terra.config.base.ConfigPack; import com.dfsek.terra.config.lang.LangUtil; import com.dfsek.terra.config.templates.BiomeTemplate; -import com.dfsek.terra.generation.TerraChunkGenerator; -import com.dfsek.terra.generation.items.TerraStructure; +import com.dfsek.terra.population.items.TerraStructure; import org.bukkit.World; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; -import org.polydev.gaea.command.WorldCommand; import java.util.Collections; import java.util.List; @@ -21,19 +22,19 @@ import java.util.Map; import java.util.stream.Collectors; public class BiomeInfoCommand extends WorldCommand { - public BiomeInfoCommand(org.polydev.gaea.command.Command parent) { + public BiomeInfoCommand(com.dfsek.terra.bukkit.command.Command parent) { super(parent); } @Override public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args, World world) { String id = args[0]; - ConfigPack cfg = ((Terra) getMain()).getWorld(world).getConfig(); + ConfigPack cfg = getMain().getWorld(BukkitAdapter.adapt(world)).getConfig(); UserDefinedBiome b; try { b = cfg.getBiome(id); } catch(IllegalArgumentException | NullPointerException e) { - LangUtil.send("command.biome.invalid", sender, id); + LangUtil.send("command.biome.invalid", new BukkitCommandSender(sender), id); return true; } sender.sendMessage("Biome info for \"" + b.getID() + "\"."); @@ -74,7 +75,7 @@ public class BiomeInfoCommand extends WorldCommand { } @Override - public List getSubCommands() { + public List getSubCommands() { return Collections.emptyList(); } @@ -85,9 +86,9 @@ public class BiomeInfoCommand extends WorldCommand { @Override public List getTabCompletions(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) { - if(!(sender instanceof Player) || !(((Player) sender).getWorld().getGenerator() instanceof TerraChunkGenerator)) + if(!(sender instanceof Player) || !TerraWorld.isTerraWorld(BukkitAdapter.adapt(((Player) sender).getWorld()))) return Collections.emptyList(); - List ids = ((Terra) getMain()).getWorld(((Player) sender).getWorld()).getConfig().getBiomeIDs(); + List ids = getMain().getWorld(BukkitAdapter.adapt(((Player) sender).getWorld())).getConfig().getBiomeIDs(); if(args.length == 1) return ids.stream().filter(string -> string.toUpperCase().startsWith(args[0].toUpperCase())).collect(Collectors.toList()); return Collections.emptyList(); diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/biome/BiomeLocateCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/biome/BiomeLocateCommand.java new file mode 100644 index 000000000..28d4faa7c --- /dev/null +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/biome/BiomeLocateCommand.java @@ -0,0 +1,91 @@ +package com.dfsek.terra.bukkit.command.command.biome; + +import com.dfsek.terra.TerraWorld; +import com.dfsek.terra.api.math.vector.Vector3; +import com.dfsek.terra.async.AsyncBiomeFinder; +import com.dfsek.terra.biome.UserDefinedBiome; +import com.dfsek.terra.bukkit.TerraBukkitPlugin; +import com.dfsek.terra.bukkit.command.WorldCommand; +import com.dfsek.terra.bukkit.world.BukkitAdapter; +import com.dfsek.terra.config.lang.LangUtil; +import net.md_5.bungee.api.ChatColor; +import net.md_5.bungee.api.chat.BaseComponent; +import net.md_5.bungee.api.chat.ClickEvent; +import net.md_5.bungee.api.chat.ComponentBuilder; +import net.md_5.bungee.api.chat.HoverEvent; +import net.md_5.bungee.api.chat.TextComponent; +import org.bukkit.Bukkit; +import org.bukkit.World; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +public class BiomeLocateCommand extends WorldCommand { + public BiomeLocateCommand(com.dfsek.terra.bukkit.command.Command parent) { + super(parent); + } + + @SuppressWarnings("DuplicatedCode") + @Override + public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args, World world) { + String id = args[0]; + int maxRadius; + try { + maxRadius = Integer.parseInt(args[1]); + } catch(NumberFormatException e) { + LangUtil.send("command.biome.invalid-radius", BukkitAdapter.adapt(sender), args[1]); + return true; + } + UserDefinedBiome b; + try { + b = getMain().getWorld(BukkitAdapter.adapt(world)).getConfig().getBiome(id); + } catch(IllegalArgumentException | NullPointerException e) { + LangUtil.send("command.biome.invalid", BukkitAdapter.adapt(sender), id); + return true; + } + Bukkit.getScheduler().runTaskAsynchronously((TerraBukkitPlugin) getMain(), new AsyncBiomeFinder(getMain().getWorld(BukkitAdapter.adapt(world)).getGrid(), b, BukkitAdapter.adapt(sender.getLocation().clone().multiply((1D / ((TerraBukkitPlugin) getMain()).getTerraConfig().getBiomeSearchResolution()))), 0, maxRadius, location -> { + if(location != null) { + ComponentBuilder cm = new ComponentBuilder(String.format("The nearest %s is at ", id.toLowerCase())) + .append(String.format("[%d, ~, %d]", location.getBlockX(), location.getBlockZ()), ComponentBuilder.FormatRetention.NONE) + .event(new ClickEvent(ClickEvent.Action.RUN_COMMAND, String.format("/minecraft:tp %s %d.0 %.2f %d.0", sender.getName(), location.getBlockX(), sender.getLocation().getY(), location.getBlockZ()))) + .event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new BaseComponent[] {new TextComponent("Click to teleport")})) + .color(ChatColor.GREEN) + .append(String.format(" (%.1f blocks away)", location.add(new Vector3(0, sender.getLocation().getY(), 0)).distance(BukkitAdapter.adapt(sender.getLocation().toVector()))), ComponentBuilder.FormatRetention.NONE); + sender.spigot().sendMessage(cm.create()); + // LangUtil.send("command.biome.biome-found", sender, String.valueOf(location.getBlockX()), String.valueOf(location.getBlockZ())); + } else LangUtil.send("command.biome.unable-to-locate", BukkitAdapter.adapt(sender)); + }, getMain())); + + return true; + } + + @Override + public String getName() { + return "locate"; + } + + @Override + public List getSubCommands() { + return Collections.emptyList(); + } + + @Override + public int arguments() { + return 2; + } + + @Override + public List getTabCompletions(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) { + if(!(sender instanceof Player) || !TerraWorld.isTerraWorld(BukkitAdapter.adapt(((Player) sender).getWorld()))) + return Collections.emptyList(); + List ids = getMain().getWorld(BukkitAdapter.adapt(((Player) sender).getWorld())).getConfig().getBiomeIDs(); + if(args.length == 1) + return ids.stream().filter(string -> string.toUpperCase().startsWith(args[0].toUpperCase())).collect(Collectors.toList()); + return Collections.emptyList(); + } +} diff --git a/src/main/java/com/dfsek/terra/command/geometry/DeformedSphereCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/geometry/DeformedSphereCommand.java similarity index 62% rename from src/main/java/com/dfsek/terra/command/geometry/DeformedSphereCommand.java rename to platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/geometry/DeformedSphereCommand.java index 14dc547ce..9fcce970f 100644 --- a/src/main/java/com/dfsek/terra/command/geometry/DeformedSphereCommand.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/geometry/DeformedSphereCommand.java @@ -1,21 +1,23 @@ -package com.dfsek.terra.command.geometry; +package com.dfsek.terra.bukkit.command.command.geometry; +import com.dfsek.terra.api.math.noise.samplers.FastNoiseLite; +import com.dfsek.terra.api.math.vector.Vector3; +import com.dfsek.terra.api.math.voxel.DeformedSphere; +import com.dfsek.terra.bukkit.BukkitCommandSender; +import com.dfsek.terra.bukkit.BukkitPlayer; +import com.dfsek.terra.bukkit.command.PlayerCommand; +import com.dfsek.terra.bukkit.world.BukkitAdapter; import com.dfsek.terra.config.lang.LangUtil; -import com.dfsek.terra.procgen.voxel.DeformedSphere; -import org.bukkit.Material; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -import org.bukkit.util.Vector; import org.jetbrains.annotations.NotNull; -import org.polydev.gaea.command.PlayerCommand; -import org.polydev.gaea.math.FastNoiseLite; import java.util.Collections; import java.util.List; public class DeformedSphereCommand extends PlayerCommand { - public DeformedSphereCommand(org.polydev.gaea.command.Command parent) { + public DeformedSphereCommand(com.dfsek.terra.bukkit.command.Command parent) { super(parent); } @@ -25,14 +27,14 @@ public class DeformedSphereCommand extends PlayerCommand { try { radius = Integer.parseInt(args[0]); } catch(NumberFormatException e) { - LangUtil.send("command.geometry.deform.invalid-radius", sender, args[0]); + LangUtil.send("command.geometry.deform.invalid-radius", new BukkitCommandSender(sender), args[0]); return true; } double deform; try { deform = Double.parseDouble(args[1]); } catch(NumberFormatException e) { - LangUtil.send("command.geometry.deform.invalid-deform", sender, args[1]); + LangUtil.send("command.geometry.deform.invalid-deform", new BukkitCommandSender(sender), args[1]); return true; } @@ -40,15 +42,15 @@ public class DeformedSphereCommand extends PlayerCommand { try { freq = Float.parseFloat(args[2]); } catch(NumberFormatException e) { - LangUtil.send("command.geometry.deform.invalid-frequency", sender, args[2]); + LangUtil.send("command.geometry.deform.invalid-frequency", new BukkitCommandSender(sender), args[2]); return true; } FastNoiseLite n = new FastNoiseLite((int) sender.getWorld().getSeed()); n.setNoiseType(FastNoiseLite.NoiseType.OpenSimplex2); n.setFrequency(freq); - DeformedSphere sphere = new DeformedSphere(sender.getLocation().toVector(), radius, deform, n); - for(Vector v : sphere.getGeometry()) { - v.toLocation(sender.getWorld()).getBlock().setType(Material.STONE); + DeformedSphere sphere = new DeformedSphere(new BukkitPlayer(sender).getLocation().toVector(), radius, deform, n); + for(Vector3 v : sphere.getGeometry()) { + v.toLocation(BukkitAdapter.adapt(sender.getWorld())).getBlock().setBlockData(getMain().getWorldHandle().createBlockData("minecraft:stone"), false); } return true; } @@ -59,7 +61,7 @@ public class DeformedSphereCommand extends PlayerCommand { } @Override - public List getSubCommands() { + public List getSubCommands() { return Collections.emptyList(); } diff --git a/src/main/java/com/dfsek/terra/command/geometry/GeometryCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/geometry/GeometryCommand.java similarity index 69% rename from src/main/java/com/dfsek/terra/command/geometry/GeometryCommand.java rename to platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/geometry/GeometryCommand.java index 82da4973c..8e9b2d89e 100644 --- a/src/main/java/com/dfsek/terra/command/geometry/GeometryCommand.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/geometry/GeometryCommand.java @@ -1,25 +1,26 @@ -package com.dfsek.terra.command.geometry; +package com.dfsek.terra.bukkit.command.command.geometry; +import com.dfsek.terra.bukkit.BukkitCommandSender; +import com.dfsek.terra.bukkit.command.DebugCommand; +import com.dfsek.terra.bukkit.command.PlayerCommand; import com.dfsek.terra.config.lang.LangUtil; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; -import org.polydev.gaea.command.DebugCommand; -import org.polydev.gaea.command.PlayerCommand; import java.util.Arrays; import java.util.Collections; import java.util.List; public class GeometryCommand extends PlayerCommand implements DebugCommand { - public GeometryCommand(org.polydev.gaea.command.Command parent) { + public GeometryCommand(com.dfsek.terra.bukkit.command.Command parent) { super(parent); } @Override public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { - LangUtil.send("command.geometry.main-menu", sender); + LangUtil.send("command.geometry.main-menu", new BukkitCommandSender(sender)); return true; } @@ -29,7 +30,7 @@ public class GeometryCommand extends PlayerCommand implements DebugCommand { } @Override - public List getSubCommands() { + public List getSubCommands() { return Arrays.asList(new SphereCommand(this), new TubeCommand(this), new DeformedSphereCommand(this)); } diff --git a/src/main/java/com/dfsek/terra/command/geometry/SphereCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/geometry/SphereCommand.java similarity index 56% rename from src/main/java/com/dfsek/terra/command/geometry/SphereCommand.java rename to platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/geometry/SphereCommand.java index 33387f124..a726d7b02 100644 --- a/src/main/java/com/dfsek/terra/command/geometry/SphereCommand.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/geometry/SphereCommand.java @@ -1,20 +1,22 @@ -package com.dfsek.terra.command.geometry; +package com.dfsek.terra.bukkit.command.command.geometry; +import com.dfsek.terra.api.math.vector.Vector3; +import com.dfsek.terra.api.math.voxel.Sphere; +import com.dfsek.terra.bukkit.BukkitCommandSender; +import com.dfsek.terra.bukkit.BukkitPlayer; +import com.dfsek.terra.bukkit.command.PlayerCommand; +import com.dfsek.terra.bukkit.world.BukkitAdapter; import com.dfsek.terra.config.lang.LangUtil; -import com.dfsek.terra.procgen.voxel.Sphere; -import org.bukkit.Material; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -import org.bukkit.util.Vector; import org.jetbrains.annotations.NotNull; -import org.polydev.gaea.command.PlayerCommand; import java.util.Collections; import java.util.List; public class SphereCommand extends PlayerCommand { - public SphereCommand(org.polydev.gaea.command.Command parent) { + public SphereCommand(com.dfsek.terra.bukkit.command.Command parent) { super(parent); } @@ -24,12 +26,12 @@ public class SphereCommand extends PlayerCommand { try { radius = Integer.parseInt(args[0]); } catch(NumberFormatException e) { - LangUtil.send("command.geometry.sphere.invalid-radius", sender, args[0]); + LangUtil.send("command.geometry.sphere.invalid-radius", new BukkitCommandSender(sender), args[0]); return true; } - Sphere sphere = new Sphere(sender.getLocation().toVector(), radius); - for(Vector v : sphere.getGeometry()) { - v.toLocation(sender.getWorld()).getBlock().setType(Material.STONE); + Sphere sphere = new Sphere(new BukkitPlayer(sender).getLocation().toVector(), radius); + for(Vector3 v : sphere.getGeometry()) { + v.toLocation(BukkitAdapter.adapt(sender.getWorld())).getBlock().setBlockData(getMain().getWorldHandle().createBlockData("minecraft:stone"), false); } return true; } @@ -40,7 +42,7 @@ public class SphereCommand extends PlayerCommand { } @Override - public List getSubCommands() { + public List getSubCommands() { return Collections.emptyList(); } diff --git a/src/main/java/com/dfsek/terra/command/geometry/TubeCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/geometry/TubeCommand.java similarity index 58% rename from src/main/java/com/dfsek/terra/command/geometry/TubeCommand.java rename to platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/geometry/TubeCommand.java index 42187be78..33bd17ad5 100644 --- a/src/main/java/com/dfsek/terra/command/geometry/TubeCommand.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/geometry/TubeCommand.java @@ -1,22 +1,23 @@ -package com.dfsek.terra.command.geometry; +package com.dfsek.terra.bukkit.command.command.geometry; +import com.dfsek.terra.api.math.vector.Vector3; +import com.dfsek.terra.api.math.voxel.Tube; +import com.dfsek.terra.bukkit.BukkitCommandSender; +import com.dfsek.terra.bukkit.command.PlayerCommand; +import com.dfsek.terra.bukkit.structure.WorldEditUtil; +import com.dfsek.terra.bukkit.world.BukkitAdapter; import com.dfsek.terra.config.lang.LangUtil; -import com.dfsek.terra.procgen.voxel.Tube; -import com.dfsek.terra.util.structure.WorldEditUtil; import org.bukkit.Location; -import org.bukkit.Material; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -import org.bukkit.util.Vector; import org.jetbrains.annotations.NotNull; -import org.polydev.gaea.command.PlayerCommand; import java.util.Collections; import java.util.List; public class TubeCommand extends PlayerCommand { - public TubeCommand(org.polydev.gaea.command.Command parent) { + public TubeCommand(com.dfsek.terra.bukkit.command.Command parent) { super(parent); } @@ -28,12 +29,12 @@ public class TubeCommand extends PlayerCommand { try { radius = Integer.parseInt(args[0]); } catch(NumberFormatException e) { - LangUtil.send("command.geometry.tube.invalid-radius", sender, args[0]); + LangUtil.send("command.geometry.tube.invalid-radius", new BukkitCommandSender(sender), args[0]); return true; } - Tube tube = new Tube(l[0].toVector(), l[1].toVector(), radius); - for(Vector v : tube.getGeometry()) { - v.toLocation(sender.getWorld()).getBlock().setType(Material.STONE); + Tube tube = new Tube(BukkitAdapter.adapt(l[0].toVector()), BukkitAdapter.adapt(l[1].toVector()), radius); + for(Vector3 v : tube.getGeometry()) { + v.toLocation(BukkitAdapter.adapt(sender.getWorld())).getBlock().setBlockData(getMain().getWorldHandle().createBlockData("minecraft:stone"), false); } return true; } @@ -44,7 +45,7 @@ public class TubeCommand extends PlayerCommand { } @Override - public List getSubCommands() { + public List getSubCommands() { return Collections.emptyList(); } diff --git a/src/main/java/com/dfsek/terra/command/image/ImageCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/image/ImageCommand.java similarity index 68% rename from src/main/java/com/dfsek/terra/command/image/ImageCommand.java rename to platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/image/ImageCommand.java index 7aa1aac8a..8f9f2cb08 100644 --- a/src/main/java/com/dfsek/terra/command/image/ImageCommand.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/image/ImageCommand.java @@ -1,26 +1,27 @@ -package com.dfsek.terra.command.image; +package com.dfsek.terra.bukkit.command.command.image; -import com.dfsek.terra.command.image.gui.GUICommand; +import com.dfsek.terra.bukkit.BukkitCommandSender; +import com.dfsek.terra.bukkit.command.WorldCommand; +import com.dfsek.terra.bukkit.command.command.image.gui.GUICommand; import com.dfsek.terra.config.lang.LangUtil; import org.bukkit.World; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; -import org.polydev.gaea.command.WorldCommand; import java.util.Arrays; import java.util.Collections; import java.util.List; public class ImageCommand extends WorldCommand { - public ImageCommand(org.polydev.gaea.command.Command parent) { + public ImageCommand(com.dfsek.terra.bukkit.command.Command parent) { super(parent); } @Override public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args, World w) { - LangUtil.send("command.image.main-menu", sender); + LangUtil.send("command.image.main-menu", new BukkitCommandSender(sender)); return true; } @@ -30,7 +31,7 @@ public class ImageCommand extends WorldCommand { } @Override - public List getSubCommands() { + public List getSubCommands() { return Arrays.asList(new RenderCommand(this), new GUICommand(this)); } diff --git a/src/main/java/com/dfsek/terra/command/image/RenderCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/image/RenderCommand.java similarity index 70% rename from src/main/java/com/dfsek/terra/command/image/RenderCommand.java rename to platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/image/RenderCommand.java index 28f6536e8..7e4355d3d 100644 --- a/src/main/java/com/dfsek/terra/command/image/RenderCommand.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/image/RenderCommand.java @@ -1,6 +1,7 @@ -package com.dfsek.terra.command.image; +package com.dfsek.terra.bukkit.command.command.image; -import com.dfsek.terra.Terra; +import com.dfsek.terra.bukkit.command.WorldCommand; +import com.dfsek.terra.bukkit.world.BukkitAdapter; import com.dfsek.terra.config.lang.LangUtil; import com.dfsek.terra.image.WorldImageGenerator; import org.bukkit.World; @@ -8,21 +9,20 @@ import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; -import org.polydev.gaea.command.WorldCommand; import java.io.File; import java.util.Collections; import java.util.List; public class RenderCommand extends WorldCommand { - public RenderCommand(org.polydev.gaea.command.Command parent) { + public RenderCommand(com.dfsek.terra.bukkit.command.Command parent) { super(parent); } @Override public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args, World world) { try { - WorldImageGenerator g = new WorldImageGenerator(world, Integer.parseInt(args[0]), Integer.parseInt(args[1]), (Terra) getMain()); + WorldImageGenerator g = new WorldImageGenerator(BukkitAdapter.adapt(world), Integer.parseInt(args[0]), Integer.parseInt(args[1]), getMain()); g.drawWorld(sender.getLocation().getBlockX(), sender.getLocation().getBlockZ()); File file = new File(getMain().getDataFolder() + File.separator + "export" + File.separator + "map" + File.separator + "map_" + System.currentTimeMillis() + ".png"); //noinspection ResultOfMethodCallIgnored @@ -30,11 +30,11 @@ public class RenderCommand extends WorldCommand { //noinspection ResultOfMethodCallIgnored file.createNewFile(); g.save(file); - LangUtil.send("command.image.render.save", sender, file.getAbsolutePath()); + LangUtil.send("command.image.render.save", BukkitAdapter.adapt(sender), file.getAbsolutePath()); return true; } catch(Exception e) { e.printStackTrace(); - LangUtil.send("command.image.render.error", sender); + LangUtil.send("command.image.render.error", BukkitAdapter.adapt(sender)); return true; } } @@ -45,7 +45,7 @@ public class RenderCommand extends WorldCommand { } @Override - public List getSubCommands() { + public List getSubCommands() { return Collections.emptyList(); } diff --git a/src/main/java/com/dfsek/terra/command/image/gui/GUICommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/image/gui/GUICommand.java similarity index 69% rename from src/main/java/com/dfsek/terra/command/image/gui/GUICommand.java rename to platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/image/gui/GUICommand.java index 95bf12f9f..13d9fee7f 100644 --- a/src/main/java/com/dfsek/terra/command/image/gui/GUICommand.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/image/gui/GUICommand.java @@ -1,26 +1,27 @@ -package com.dfsek.terra.command.image.gui; +package com.dfsek.terra.bukkit.command.command.image.gui; +import com.dfsek.terra.bukkit.BukkitCommandSender; +import com.dfsek.terra.bukkit.command.DebugCommand; +import com.dfsek.terra.bukkit.command.WorldCommand; import com.dfsek.terra.config.lang.LangUtil; import org.bukkit.World; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; -import org.polydev.gaea.command.DebugCommand; -import org.polydev.gaea.command.WorldCommand; import java.util.Arrays; import java.util.Collections; import java.util.List; public class GUICommand extends WorldCommand implements DebugCommand { - public GUICommand(org.polydev.gaea.command.Command parent) { + public GUICommand(com.dfsek.terra.bukkit.command.Command parent) { super(parent); } @Override public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args, World world) { - LangUtil.send("command.image.gui.main-menu", sender); + LangUtil.send("command.image.gui.main-menu", new BukkitCommandSender(sender)); return true; } @@ -30,7 +31,7 @@ public class GUICommand extends WorldCommand implements DebugCommand { } @Override - public List getSubCommands() { + public List getSubCommands() { return Arrays.asList(new StepGUICommand(this), new RawGUICommand(this)); } diff --git a/src/main/java/com/dfsek/terra/command/image/gui/RawGUICommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/image/gui/RawGUICommand.java similarity index 53% rename from src/main/java/com/dfsek/terra/command/image/gui/RawGUICommand.java rename to platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/image/gui/RawGUICommand.java index a7e8fc84b..c52e56ca6 100644 --- a/src/main/java/com/dfsek/terra/command/image/gui/RawGUICommand.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/image/gui/RawGUICommand.java @@ -1,32 +1,28 @@ -package com.dfsek.terra.command.image.gui; +package com.dfsek.terra.bukkit.command.command.image.gui; -import com.dfsek.terra.Terra; -import com.dfsek.terra.config.lang.LangUtil; +import com.dfsek.terra.bukkit.command.DebugCommand; +import com.dfsek.terra.bukkit.command.WorldCommand; +import com.dfsek.terra.bukkit.world.BukkitAdapter; import com.dfsek.terra.image.ImageLoader; import org.bukkit.World; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; -import org.polydev.gaea.command.WorldCommand; import java.util.Collections; import java.util.List; -public class RawGUICommand extends WorldCommand { - public RawGUICommand(org.polydev.gaea.command.Command parent) { +public class RawGUICommand extends WorldCommand implements DebugCommand { + public RawGUICommand(com.dfsek.terra.bukkit.command.Command parent) { super(parent); } @Override public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args, World world) { - if(!getMain().isDebug()) { - LangUtil.send("command.image.gui.debug", sender); - return true; - } - ImageLoader loader = ((Terra) getMain()).getWorld(world).getConfig().getTemplate().getImageLoader(); - if(loader != null) loader.debug(false, sender.getWorld(), (Terra) getMain()); - else ImageLoader.debugWorld(false, world, (Terra) getMain()); + ImageLoader loader = getMain().getWorld(BukkitAdapter.adapt(world)).getConfig().getTemplate().getImageLoader(); + if(loader != null) loader.debug(false, BukkitAdapter.adapt(sender.getWorld()), getMain()); + else ImageLoader.debugWorld(false, BukkitAdapter.adapt(world), getMain()); return true; } @@ -36,7 +32,7 @@ public class RawGUICommand extends WorldCommand { } @Override - public List getSubCommands() { + public List getSubCommands() { return Collections.emptyList(); } diff --git a/src/main/java/com/dfsek/terra/command/image/gui/StepGUICommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/image/gui/StepGUICommand.java similarity index 53% rename from src/main/java/com/dfsek/terra/command/image/gui/StepGUICommand.java rename to platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/image/gui/StepGUICommand.java index ed87a78c8..ae082d7d2 100644 --- a/src/main/java/com/dfsek/terra/command/image/gui/StepGUICommand.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/image/gui/StepGUICommand.java @@ -1,32 +1,28 @@ -package com.dfsek.terra.command.image.gui; +package com.dfsek.terra.bukkit.command.command.image.gui; -import com.dfsek.terra.Terra; -import com.dfsek.terra.config.lang.LangUtil; +import com.dfsek.terra.bukkit.command.DebugCommand; +import com.dfsek.terra.bukkit.command.WorldCommand; +import com.dfsek.terra.bukkit.world.BukkitAdapter; import com.dfsek.terra.image.ImageLoader; import org.bukkit.World; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; -import org.polydev.gaea.command.WorldCommand; import java.util.Collections; import java.util.List; -public class StepGUICommand extends WorldCommand { - public StepGUICommand(org.polydev.gaea.command.Command parent) { +public class StepGUICommand extends WorldCommand implements DebugCommand { + public StepGUICommand(com.dfsek.terra.bukkit.command.Command parent) { super(parent); } @Override public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args, World world) { - if(!getMain().isDebug()) { - LangUtil.send("command.image.gui.debug", sender); - return true; - } - ImageLoader loader = ((Terra) getMain()).getWorld(world).getConfig().getTemplate().getImageLoader(); - if(loader != null) loader.debug(true, sender.getWorld(), (Terra) getMain()); - else ImageLoader.debugWorld(true, world, (Terra) getMain()); + ImageLoader loader = (getMain()).getWorld(BukkitAdapter.adapt(world)).getConfig().getTemplate().getImageLoader(); + if(loader != null) loader.debug(true, BukkitAdapter.adapt(sender.getWorld()), getMain()); + else ImageLoader.debugWorld(true, BukkitAdapter.adapt(world), getMain()); return true; } @@ -36,7 +32,7 @@ public class StepGUICommand extends WorldCommand { } @Override - public List getSubCommands() { + public List getSubCommands() { return Collections.emptyList(); } diff --git a/src/main/java/com/dfsek/terra/command/profile/ProfileCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/profile/ProfileCommand.java similarity index 72% rename from src/main/java/com/dfsek/terra/command/profile/ProfileCommand.java rename to platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/profile/ProfileCommand.java index 9295cbe22..5eb4b4ec1 100644 --- a/src/main/java/com/dfsek/terra/command/profile/ProfileCommand.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/profile/ProfileCommand.java @@ -1,25 +1,26 @@ -package com.dfsek.terra.command.profile; +package com.dfsek.terra.bukkit.command.command.profile; +import com.dfsek.terra.bukkit.BukkitCommandSender; +import com.dfsek.terra.bukkit.command.WorldCommand; import com.dfsek.terra.config.lang.LangUtil; import org.bukkit.World; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; -import org.polydev.gaea.command.WorldCommand; import java.util.Arrays; import java.util.Collections; import java.util.List; public class ProfileCommand extends WorldCommand { - public ProfileCommand(org.polydev.gaea.command.Command parent) { + public ProfileCommand(com.dfsek.terra.bukkit.command.Command parent) { super(parent); } @Override public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args, World w) { - LangUtil.send("command.profile.main-menu", sender); + LangUtil.send("command.profile.main-menu", new BukkitCommandSender(sender)); return true; } @@ -29,7 +30,7 @@ public class ProfileCommand extends WorldCommand { } @Override - public List getSubCommands() { + public List getSubCommands() { return Arrays.asList(new QueryCommand(this), new ResetCommand(this), new StartCommand(this), new StopCommand(this)); } diff --git a/src/main/java/com/dfsek/terra/command/profile/QueryCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/profile/QueryCommand.java similarity index 67% rename from src/main/java/com/dfsek/terra/command/profile/QueryCommand.java rename to platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/profile/QueryCommand.java index 62f6bc88f..9cdf9f10a 100644 --- a/src/main/java/com/dfsek/terra/command/profile/QueryCommand.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/profile/QueryCommand.java @@ -1,25 +1,25 @@ -package com.dfsek.terra.command.profile; +package com.dfsek.terra.bukkit.command.command.profile; -import com.dfsek.terra.Terra; +import com.dfsek.terra.api.profiler.WorldProfiler; +import com.dfsek.terra.bukkit.command.WorldCommand; +import com.dfsek.terra.bukkit.world.BukkitAdapter; import org.bukkit.World; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; -import org.polydev.gaea.command.WorldCommand; -import org.polydev.gaea.profiler.WorldProfiler; import java.util.Collections; import java.util.List; public class QueryCommand extends WorldCommand { - public QueryCommand(org.polydev.gaea.command.Command parent) { + public QueryCommand(com.dfsek.terra.bukkit.command.Command parent) { super(parent); } @Override public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args, World world) { - WorldProfiler profile = ((Terra) getMain()).getWorld(world).getProfiler(); + WorldProfiler profile = getMain().getWorld(BukkitAdapter.adapt(world)).getProfiler(); sender.sendMessage(profile.getResultsFormatted()); return true; } @@ -30,7 +30,7 @@ public class QueryCommand extends WorldCommand { } @Override - public List getSubCommands() { + public List getSubCommands() { return Collections.emptyList(); } diff --git a/src/main/java/com/dfsek/terra/command/profile/ResetCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/profile/ResetCommand.java similarity index 61% rename from src/main/java/com/dfsek/terra/command/profile/ResetCommand.java rename to platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/profile/ResetCommand.java index 9ac0b02fe..eb7e5a3b7 100644 --- a/src/main/java/com/dfsek/terra/command/profile/ResetCommand.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/profile/ResetCommand.java @@ -1,28 +1,29 @@ -package com.dfsek.terra.command.profile; +package com.dfsek.terra.bukkit.command.command.profile; -import com.dfsek.terra.Terra; +import com.dfsek.terra.api.profiler.WorldProfiler; +import com.dfsek.terra.bukkit.BukkitCommandSender; +import com.dfsek.terra.bukkit.command.WorldCommand; +import com.dfsek.terra.bukkit.world.BukkitAdapter; import com.dfsek.terra.config.lang.LangUtil; import org.bukkit.World; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; -import org.polydev.gaea.command.WorldCommand; -import org.polydev.gaea.profiler.WorldProfiler; import java.util.Collections; import java.util.List; public class ResetCommand extends WorldCommand { - public ResetCommand(org.polydev.gaea.command.Command parent) { + public ResetCommand(com.dfsek.terra.bukkit.command.Command parent) { super(parent); } @Override public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args, World world) { - WorldProfiler profile = ((Terra) getMain()).getWorld(world).getProfiler(); + WorldProfiler profile = getMain().getWorld(BukkitAdapter.adapt(world)).getProfiler(); profile.reset(); - LangUtil.send("command.profile.reset", sender); + LangUtil.send("command.profile.reset", new BukkitCommandSender(sender)); return true; } @@ -32,7 +33,7 @@ public class ResetCommand extends WorldCommand { } @Override - public List getSubCommands() { + public List getSubCommands() { return Collections.emptyList(); } diff --git a/src/main/java/com/dfsek/terra/command/profile/StartCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/profile/StartCommand.java similarity index 62% rename from src/main/java/com/dfsek/terra/command/profile/StartCommand.java rename to platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/profile/StartCommand.java index a5f71b0f5..cadcb1446 100644 --- a/src/main/java/com/dfsek/terra/command/profile/StartCommand.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/profile/StartCommand.java @@ -1,28 +1,29 @@ -package com.dfsek.terra.command.profile; +package com.dfsek.terra.bukkit.command.command.profile; -import com.dfsek.terra.Terra; +import com.dfsek.terra.api.profiler.WorldProfiler; +import com.dfsek.terra.bukkit.BukkitCommandSender; +import com.dfsek.terra.bukkit.command.WorldCommand; +import com.dfsek.terra.bukkit.world.BukkitAdapter; import com.dfsek.terra.config.lang.LangUtil; import org.bukkit.World; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; -import org.polydev.gaea.command.WorldCommand; -import org.polydev.gaea.profiler.WorldProfiler; import java.util.Collections; import java.util.List; public class StartCommand extends WorldCommand { - public StartCommand(org.polydev.gaea.command.Command parent) { + public StartCommand(com.dfsek.terra.bukkit.command.Command parent) { super(parent); } @Override public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args, World world) { - WorldProfiler profile = ((Terra) getMain()).getWorld(world).getProfiler(); + WorldProfiler profile = getMain().getWorld(BukkitAdapter.adapt(world)).getProfiler(); profile.setProfiling(true); - LangUtil.send("command.profile.start", sender); + LangUtil.send("command.profile.start", new BukkitCommandSender(sender)); return true; } @@ -32,7 +33,7 @@ public class StartCommand extends WorldCommand { } @Override - public List getSubCommands() { + public List getSubCommands() { return Collections.emptyList(); } diff --git a/src/main/java/com/dfsek/terra/command/profile/StopCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/profile/StopCommand.java similarity index 62% rename from src/main/java/com/dfsek/terra/command/profile/StopCommand.java rename to platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/profile/StopCommand.java index dd9921b87..f5d24b1d3 100644 --- a/src/main/java/com/dfsek/terra/command/profile/StopCommand.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/profile/StopCommand.java @@ -1,28 +1,29 @@ -package com.dfsek.terra.command.profile; +package com.dfsek.terra.bukkit.command.command.profile; -import com.dfsek.terra.Terra; +import com.dfsek.terra.api.profiler.WorldProfiler; +import com.dfsek.terra.bukkit.BukkitCommandSender; +import com.dfsek.terra.bukkit.command.WorldCommand; +import com.dfsek.terra.bukkit.world.BukkitAdapter; import com.dfsek.terra.config.lang.LangUtil; import org.bukkit.World; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; -import org.polydev.gaea.command.WorldCommand; -import org.polydev.gaea.profiler.WorldProfiler; import java.util.Collections; import java.util.List; public class StopCommand extends WorldCommand { - public StopCommand(org.polydev.gaea.command.Command parent) { + public StopCommand(com.dfsek.terra.bukkit.command.Command parent) { super(parent); } @Override public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args, World world) { - WorldProfiler profile = ((Terra) getMain()).getWorld(world).getProfiler(); + WorldProfiler profile = getMain().getWorld(BukkitAdapter.adapt(world)).getProfiler(); profile.setProfiling(false); - LangUtil.send("command.profile.stop", sender); + LangUtil.send("command.profile.stop", new BukkitCommandSender(sender)); return true; } @@ -32,7 +33,7 @@ public class StopCommand extends WorldCommand { } @Override - public List getSubCommands() { + public List getSubCommands() { return Collections.emptyList(); } diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/structure/ExportCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/structure/ExportCommand.java new file mode 100644 index 000000000..77ec5abef --- /dev/null +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/structure/ExportCommand.java @@ -0,0 +1,121 @@ +package com.dfsek.terra.bukkit.command.command.structure; + +import com.dfsek.terra.bukkit.command.PlayerCommand; +import com.dfsek.terra.bukkit.structure.WorldEditUtil; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockState; +import org.bukkit.block.Sign; +import org.bukkit.block.data.BlockData; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.Collections; +import java.util.List; + +public class ExportCommand extends PlayerCommand { + public ExportCommand(com.dfsek.terra.bukkit.command.Command parent) { + super(parent); + } + + @Override + public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + Location[] l = WorldEditUtil.getSelectionLocations(sender); + if(l == null) return true; + + Location l1 = l[0]; + Location l2 = l[1]; + + StringBuilder scriptBuilder = new StringBuilder("id \"" + args[0] + "\";\nnum y = 0;\n"); + + int centerX = 0; + int centerY = 0; + int centerZ = 0; + + for(int x = l1.getBlockX(); x <= l2.getBlockX(); x++) { + for(int y = l1.getBlockY(); y <= l2.getBlockY(); y++) { + for(int z = l1.getBlockZ(); z <= l2.getBlockZ(); z++) { + Block block = new Location(l1.getWorld(), x, y, z).getBlock(); + BlockState state = block.getState(); + if(state instanceof Sign) { + Sign sign = (Sign) state; + if(sign.getLine(0).equals("[TERRA]") && sign.getLine(1).equals("[CENTER]")) { + centerX = x - l1.getBlockX(); + centerY = y - l1.getBlockY(); + centerZ = z - l1.getBlockZ(); + } + } + } + } + } + + for(int x = l1.getBlockX(); x <= l2.getBlockX(); x++) { + for(int y = l1.getBlockY(); y <= l2.getBlockY(); y++) { + for(int z = l1.getBlockZ(); z <= l2.getBlockZ(); z++) { + + Block block = new Location(l1.getWorld(), x, y, z).getBlock(); + BlockData data = block.getBlockData(); + if(block.getType().equals(Material.STRUCTURE_VOID)) continue; + BlockState state = block.getState(); + if(state instanceof Sign) { + Sign sign = (Sign) state; + if(sign.getLine(0).equals("[TERRA]")) { + data = Bukkit.createBlockData(sign.getLine(2) + sign.getLine(3)); + } + } + if(!data.getMaterial().equals(Material.STRUCTURE_VOID)) { + scriptBuilder.append("block(").append(x - l1.getBlockX() - centerX).append(", y + ").append(y - l1.getBlockY() - centerY).append(", ").append(z - l1.getBlockZ() - centerZ).append(", ") + .append("\""); + scriptBuilder.append(data.getAsString(false)).append("\");\n"); + } + } + } + } + + File file = new File(getMain().getDataFolder() + File.separator + "export" + File.separator + "structures", args[0] + ".tesf"); + try { + file.getParentFile().mkdirs(); + file.createNewFile(); + } catch(IOException e) { + e.printStackTrace(); + } + try(BufferedWriter writer = new BufferedWriter(new FileWriter(file))) { + writer.write(scriptBuilder.toString()); + } catch(IOException e) { + e.printStackTrace(); + } + + + + sender.sendMessage("Exported structure to " + file.getAbsolutePath()); + return true; + } + + @Override + public String getName() { + return "export"; + } + + @Override + public List getSubCommands() { + return Collections.emptyList(); + } + + @Override + public int arguments() { + return 1; + } + + @Override + public List getTabCompletions(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) { + return Collections.emptyList(); + } +} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/structure/LocateCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/structure/LocateCommand.java new file mode 100644 index 000000000..c884f97af --- /dev/null +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/structure/LocateCommand.java @@ -0,0 +1,99 @@ +package com.dfsek.terra.bukkit.command.command.structure; + +import com.dfsek.terra.TerraWorld; +import com.dfsek.terra.api.math.vector.Vector3; +import com.dfsek.terra.async.AsyncStructureFinder; +import com.dfsek.terra.bukkit.TerraBukkitPlugin; +import com.dfsek.terra.bukkit.command.WorldCommand; +import com.dfsek.terra.bukkit.world.BukkitAdapter; +import com.dfsek.terra.config.lang.LangUtil; +import com.dfsek.terra.population.items.TerraStructure; +import net.md_5.bungee.api.ChatColor; +import net.md_5.bungee.api.chat.BaseComponent; +import net.md_5.bungee.api.chat.ClickEvent; +import net.md_5.bungee.api.chat.ComponentBuilder; +import net.md_5.bungee.api.chat.HoverEvent; +import net.md_5.bungee.api.chat.TextComponent; +import org.bukkit.Bukkit; +import org.bukkit.World; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +public class LocateCommand extends WorldCommand { + + public LocateCommand(com.dfsek.terra.bukkit.command.Command parent) { + super(parent); + } + + @SuppressWarnings({"DuplicatedCode", "deprecation"}) + @Override + public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args, World world) { + String id = args[0]; + int maxRadius; + + try { + maxRadius = Integer.parseInt(args[1]); + } catch(NumberFormatException e) { + LangUtil.send("command.structure.invalid-radius", BukkitAdapter.adapt(sender), args[1]); + return true; + } + TerraStructure s; + try { + s = Objects.requireNonNull(getMain().getWorld(BukkitAdapter.adapt(world)).getConfig().getStructure(id)); + } catch(IllegalArgumentException | NullPointerException e) { + LangUtil.send("command.structure.invalid", BukkitAdapter.adapt(sender), id); + return true; + } + Bukkit.getScheduler().runTaskAsynchronously((TerraBukkitPlugin) getMain(), new AsyncStructureFinder(getMain().getWorld(BukkitAdapter.adapt(world)).getGrid(), s, BukkitAdapter.adapt(sender.getLocation()), 0, maxRadius, (location) -> { + if(sender.isOnline()) { + if(location != null) { + ComponentBuilder cm = new ComponentBuilder(String.format("The nearest %s is at ", id.toLowerCase())) + .append(String.format("[%d, ~, %d]", location.getBlockX(), location.getBlockZ()), ComponentBuilder.FormatRetention.NONE) + .event(new ClickEvent(ClickEvent.Action.RUN_COMMAND, String.format("/minecraft:tp %s %d.0 %.2f %d.0", sender.getName(), location.getBlockX(), sender.getLocation().getY(), location.getBlockZ()))) + .event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new BaseComponent[] {new TextComponent("Click to teleport")})) + .color(ChatColor.GREEN) + .append(String.format(" (%.1f blocks away)", location.add(new Vector3(0, sender.getLocation().getY(), 0)).distance( + BukkitAdapter.adapt(sender.getLocation().toVector()))), ComponentBuilder.FormatRetention.NONE); + sender.spigot().sendMessage(cm.create()); + } else + sender.sendMessage("Unable to locate structure. "); + } + }, getMain())); + + return true; + } + + @Override + public String getName() { + return "locate"; + } + + @Override + public List getSubCommands() { + return Collections.emptyList(); + } + + @Override + public int arguments() { + return 2; + } + + @Override + public List getTabCompletions(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) { + if(!(sender instanceof Player) || !(TerraWorld.isTerraWorld(BukkitAdapter.adapt(((Player) sender).getWorld())))) + return Collections.emptyList(); + + List ids = getMain().getWorld(BukkitAdapter.adapt(((Player) sender).getWorld())).getConfig().getStructureIDs(); + if(args.length == 1) + return ids.stream().filter(string -> string.toUpperCase().startsWith(args[0].toUpperCase())).collect(Collectors.toList()); + + return Collections.emptyList(); + } +} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/structure/SpawnCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/structure/SpawnCommand.java new file mode 100644 index 000000000..fb65819de --- /dev/null +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/structure/SpawnCommand.java @@ -0,0 +1,63 @@ +package com.dfsek.terra.bukkit.command.command.structure; + +import com.dfsek.terra.api.structures.parser.lang.constants.NumericConstant; +import com.dfsek.terra.api.structures.script.TerraImplementationArguments; +import com.dfsek.terra.api.structures.script.functions.CheckFunction; +import com.dfsek.terra.api.structures.structure.Rotation; +import com.dfsek.terra.api.structures.structure.buffer.StructureBuffer; +import com.dfsek.terra.api.structures.tokenizer.Position; +import com.dfsek.terra.api.util.FastRandom; +import com.dfsek.terra.bukkit.command.DebugCommand; +import com.dfsek.terra.bukkit.command.WorldCommand; +import com.dfsek.terra.bukkit.world.BukkitAdapter; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +import java.util.Collections; +import java.util.List; + +public class SpawnCommand extends WorldCommand implements DebugCommand { + public SpawnCommand(com.dfsek.terra.bukkit.command.Command parent) { + super(parent); + } + + @Override + public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args, World world) { + Location p = sender.getLocation(); + int x = p.getBlockX(); + int y = p.getBlockY(); + int z = p.getBlockZ(); + Position dummy = new Position(0, 0); + com.dfsek.terra.api.platform.world.World w = BukkitAdapter.adapt(world); + String check = new CheckFunction(getMain(), new NumericConstant(0, dummy), new NumericConstant(0, dummy), new NumericConstant(0, dummy), getMain().getWorld(w).getConfig().getSamplerCache(), dummy).apply(new TerraImplementationArguments(new StructureBuffer( + new com.dfsek.terra.api.math.vector.Location(w, x, y, z) + ), Rotation.NONE, new FastRandom(), 0)); + + sender.sendMessage("Found: " + check); + return true; + } + + @Override + public String getName() { + return "spawn"; + } + + @Override + public List getSubCommands() { + return Collections.emptyList(); + } + + @Override + public int arguments() { + return 0; + } + + @Override + public List getTabCompletions(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) { + return Collections.emptyList(); + } +} diff --git a/src/main/java/com/dfsek/terra/command/structure/StructureCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/structure/StructureCommand.java similarity index 63% rename from src/main/java/com/dfsek/terra/command/structure/StructureCommand.java rename to platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/structure/StructureCommand.java index af1a7ed74..16c6b277a 100644 --- a/src/main/java/com/dfsek/terra/command/structure/StructureCommand.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/structure/StructureCommand.java @@ -1,25 +1,26 @@ -package com.dfsek.terra.command.structure; +package com.dfsek.terra.bukkit.command.command.structure; -import com.dfsek.terra.command.structure.load.LoadCommand; +import com.dfsek.terra.bukkit.BukkitCommandSender; +import com.dfsek.terra.bukkit.command.PlayerCommand; +import com.dfsek.terra.bukkit.command.command.structure.load.LoadCommand; import com.dfsek.terra.config.lang.LangUtil; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; -import org.polydev.gaea.command.PlayerCommand; import java.util.Arrays; import java.util.Collections; import java.util.List; public class StructureCommand extends PlayerCommand { - public StructureCommand(org.polydev.gaea.command.Command parent) { + public StructureCommand(com.dfsek.terra.bukkit.command.Command parent) { super(parent); } @Override public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { - LangUtil.send("command.structure.main-menu", sender); + LangUtil.send("command.structure.main-menu", new BukkitCommandSender(sender)); return true; } @@ -29,8 +30,8 @@ public class StructureCommand extends PlayerCommand { } @Override - public List getSubCommands() { - return Arrays.asList(new ExportCommand(this), new LoadCommand(this), new LocateCommand(this, false), new LocateCommand(this, true), new SpawnCommand(this)); + public List getSubCommands() { + return Arrays.asList(new ExportCommand(this), new LoadCommand(this), new LocateCommand(this), new SpawnCommand(this)); } @Override diff --git a/src/main/java/com/dfsek/terra/command/structure/load/LoadCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/structure/load/LoadCommand.java similarity index 53% rename from src/main/java/com/dfsek/terra/command/structure/load/LoadCommand.java rename to platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/structure/load/LoadCommand.java index 7e5421b0a..d83a39a94 100644 --- a/src/main/java/com/dfsek/terra/command/structure/load/LoadCommand.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/structure/load/LoadCommand.java @@ -1,36 +1,30 @@ -package com.dfsek.terra.command.structure.load; +package com.dfsek.terra.bukkit.command.command.structure.load; +import com.dfsek.terra.TerraWorld; +import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.bukkit.command.DebugCommand; +import com.dfsek.terra.bukkit.command.PlayerCommand; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; -import org.polydev.gaea.command.DebugCommand; -import org.polydev.gaea.command.PlayerCommand; -import java.io.File; -import java.io.FilenameFilter; -import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; public class LoadCommand extends PlayerCommand implements DebugCommand { - public LoadCommand(org.polydev.gaea.command.Command parent) { + public LoadCommand(com.dfsek.terra.bukkit.command.Command parent) { super(parent); } - public List getStructureNames() { + public List getStructureNames(World world) { List names = new ArrayList<>(); - File structureDir = new File(getMain().getDataFolder() + File.separator + "export" + File.separator + "structures"); - if(!structureDir.exists()) return Collections.emptyList(); - Path structurePath = structureDir.toPath(); + TerraWorld terraWorld = getMain().getWorld(world); + + terraWorld.getConfig().getScriptRegistry().forEach(script -> names.add(script.getId())); - FilenameFilter filter = (dir, name) -> name.endsWith(".tstructure"); - for(File f : structureDir.listFiles(filter)) { - String path = structurePath.relativize(f.toPath()).toString(); - names.add(path.substring(0, path.length() - 11)); - } return names; } @@ -45,7 +39,7 @@ public class LoadCommand extends PlayerCommand implements DebugCommand { } @Override - public List getSubCommands() { + public List getSubCommands() { return Arrays.asList(new LoadRawCommand(this), new LoadFullCommand(this, true), new LoadFullCommand(this, false)); } diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/structure/load/LoadFullCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/structure/load/LoadFullCommand.java new file mode 100644 index 000000000..7308063b8 --- /dev/null +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/structure/load/LoadFullCommand.java @@ -0,0 +1,70 @@ +package com.dfsek.terra.bukkit.command.command.structure.load; + +import com.dfsek.terra.TerraWorld; +import com.dfsek.terra.api.structures.structure.Rotation; +import com.dfsek.terra.api.util.FastRandom; +import com.dfsek.terra.bukkit.command.DebugCommand; +import com.dfsek.terra.bukkit.world.BukkitAdapter; +import com.dfsek.terra.bukkit.world.BukkitChunk; +import com.dfsek.terra.util.PopulationUtil; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class LoadFullCommand extends LoadCommand implements DebugCommand { + private final boolean chunk; + + public LoadFullCommand(com.dfsek.terra.bukkit.command.Command parent, boolean chunk) { + super(parent); + this.chunk = chunk; + } + + @Override + public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String s, @NotNull String[] args) { + TerraWorld terraWorld = getMain().getWorld(BukkitAdapter.adapt(sender.getWorld())); + long t = System.nanoTime(); + FastRandom chunk = PopulationUtil.getRandom(new BukkitChunk(sender.getLocation().getChunk())); + + if(this.chunk) { + terraWorld.getConfig().getScriptRegistry().get(args[0]).execute(BukkitAdapter.adapt(sender.getLocation()), BukkitAdapter.adapt(sender.getLocation().getChunk()), chunk, Rotation.fromDegrees(90 * chunk.nextInt(4))); + } else { + terraWorld.getConfig().getScriptRegistry().get(args[0]).execute(BukkitAdapter.adapt(sender.getLocation()), chunk, Rotation.fromDegrees(90 * chunk.nextInt(4))); + } + long l = System.nanoTime() - t; + + sender.sendMessage("Took " + ((double) l) / 1000000 + "ms"); + return true; + } + + @Override + public String getName() { + return chunk ? "chunk" : "full"; + } + + @Override + public List getSubCommands() { + return Collections.emptyList(); + } + + @Override + public int arguments() { + return 2; + } + + @Override + public List getTabCompletions(@NotNull CommandSender commandSender, @NotNull String s, @NotNull String[] args) { + switch(args.length) { + case 1: + return Collections.emptyList(); //getStructureNames().stream().filter(string -> string.toUpperCase().startsWith(args[0].toUpperCase())).collect(Collectors.toList()); + case 2: + return Stream.of("0", "90", "180", "270").filter(string -> string.toUpperCase().startsWith(args[1].toUpperCase())).collect(Collectors.toList()); + } + return Collections.emptyList(); + } +} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/structure/load/LoadRawCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/structure/load/LoadRawCommand.java new file mode 100644 index 000000000..1c5defcb9 --- /dev/null +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/structure/load/LoadRawCommand.java @@ -0,0 +1,71 @@ +package com.dfsek.terra.bukkit.command.command.structure.load; + +import com.dfsek.terra.TerraWorld; +import com.dfsek.terra.api.structures.structure.Rotation; +import com.dfsek.terra.api.util.FastRandom; +import com.dfsek.terra.bukkit.command.DebugCommand; +import com.dfsek.terra.bukkit.world.BukkitAdapter; +import com.dfsek.terra.util.PopulationUtil; +import org.bukkit.block.Sign; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +public class LoadRawCommand extends LoadCommand implements DebugCommand { + public LoadRawCommand(com.dfsek.terra.bukkit.command.Command parent) { + super(parent); + } + + private static void setTerraSign(Sign sign, String data) { + sign.setLine(0, "[TERRA]"); + if(data.length() > 16) { + sign.setLine(2, data.substring(0, 16)); + sign.setLine(3, data.substring(16)); + } else sign.setLine(2, data); + } + + + @Override + public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String s, @NotNull String[] args) { + + + TerraWorld terraWorld = getMain().getWorld(BukkitAdapter.adapt(sender.getWorld())); + long t = System.nanoTime(); + FastRandom chunk = PopulationUtil.getRandom(BukkitAdapter.adapt(sender.getLocation().getChunk())); + + boolean success = terraWorld.getConfig().getScriptRegistry().get(args[0]).execute(BukkitAdapter.adapt(sender.getLocation()), chunk, Rotation.fromDegrees(90 * chunk.nextInt(4))); + long l = System.nanoTime() - t; + + sender.sendMessage("Took " + ((double) l) / 1000000 + "ms. Success: " + success); + + return true; + } + + @Override + public String getName() { + return "raw"; + } + + @Override + public List getSubCommands() { + return Collections.emptyList(); + } + + @Override + public int arguments() { + return 1; + } + + @Override + public List getTabCompletions(@NotNull CommandSender commandSender, @NotNull String s, @NotNull String[] args) { + if(args.length == 1) { + return getStructureNames(BukkitAdapter.adapt(((Player) commandSender).getWorld())).stream().filter(string -> string.toUpperCase().startsWith(args[0].toUpperCase())).collect(Collectors.toList()); + } + return Collections.emptyList(); + } +} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/generator/BukkitChunkGenerator.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/generator/BukkitChunkGenerator.java new file mode 100644 index 000000000..624354589 --- /dev/null +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/generator/BukkitChunkGenerator.java @@ -0,0 +1,101 @@ +package com.dfsek.terra.bukkit.generator; + +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.generator.BlockPopulator; +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 com.dfsek.terra.bukkit.world.BukkitBiomeGrid; +import com.dfsek.terra.bukkit.world.BukkitWorld; +import com.dfsek.terra.bukkit.world.block.data.BukkitBlockData; +import org.bukkit.generator.ChunkGenerator; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; +import java.util.Random; +import java.util.stream.Collectors; + +public class BukkitChunkGenerator implements com.dfsek.terra.api.platform.generator.ChunkGenerator { + private final ChunkGenerator delegate; + + public BukkitChunkGenerator(ChunkGenerator delegate) { + this.delegate = delegate; + } + + @Override + public ChunkGenerator getHandle() { + return delegate; + } + + @Override + public boolean isParallelCapable() { + return delegate.isParallelCapable(); + } + + @Override + public boolean shouldGenerateCaves() { + return delegate.shouldGenerateCaves(); + } + + @Override + public boolean shouldGenerateDecorations() { + return delegate.shouldGenerateDecorations(); + } + + @Override + public boolean shouldGenerateMobs() { + return delegate.shouldGenerateMobs(); + } + + @Override + public boolean shouldGenerateStructures() { + return delegate.shouldGenerateStructures(); + } + + @Override + public ChunkData generateChunkData(@NotNull World world, @NotNull Random random, int x, int z, @NotNull BiomeGrid biome) { + return new BukkitChunkData(delegate.generateChunkData(((BukkitWorld) world).getHandle(), random, x, z, ((BukkitBiomeGrid) biome).getHandle())); + } + + @Override + public List getDefaultPopulators(World world) { + return delegate.getDefaultPopulators(((BukkitWorld) world).getHandle()).stream().map(BukkitPopulator::new).collect(Collectors.toList()); + } + + @Override + public @Nullable TerraChunkGenerator getTerraGenerator() { + return delegate instanceof BukkitChunkGeneratorWrapper ? ((BukkitChunkGeneratorWrapper) delegate).getHandle() : null; + } + + public static class BukkitChunkData implements ChunkData { + + private final ChunkGenerator.ChunkData delegate; + + public BukkitChunkData(ChunkGenerator.ChunkData delegate) { + this.delegate = delegate; + } + + @Override + public ChunkGenerator.ChunkData getHandle() { + return delegate; + } + + @Override + public int getMaxHeight() { + return delegate.getMaxHeight(); + } + + + @Override + public void setBlock(int x, int y, int z, @NotNull BlockData blockData) { + delegate.setBlock(x, y, z, ((BukkitBlockData) blockData).getHandle()); + } + + + @Override + public @NotNull BlockData getBlockData(int x, int y, int z) { + return BukkitBlockData.newInstance(delegate.getBlockData(x, y, z)); + } + } +} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/generator/BukkitChunkGeneratorWrapper.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/generator/BukkitChunkGeneratorWrapper.java new file mode 100644 index 000000000..673ad3ed2 --- /dev/null +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/generator/BukkitChunkGeneratorWrapper.java @@ -0,0 +1,125 @@ +package com.dfsek.terra.bukkit.generator; + +import com.dfsek.terra.TerraWorld; +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.platform.generator.GeneratorWrapper; +import com.dfsek.terra.api.platform.world.Chunk; +import com.dfsek.terra.api.world.generation.TerraChunkGenerator; +import com.dfsek.terra.api.world.generation.population.PopulationManager; +import com.dfsek.terra.bukkit.world.BukkitAdapter; +import com.dfsek.terra.bukkit.world.BukkitBiomeGrid; +import com.dfsek.terra.config.lang.LangUtil; +import com.dfsek.terra.debug.Debug; +import com.dfsek.terra.population.CavePopulator; +import com.dfsek.terra.population.FloraPopulator; +import com.dfsek.terra.population.OrePopulator; +import com.dfsek.terra.population.StructurePopulator; +import com.dfsek.terra.population.TreePopulator; +import org.bukkit.World; +import org.bukkit.generator.BlockPopulator; +import org.bukkit.generator.ChunkGenerator; +import org.jetbrains.annotations.NotNull; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.logging.Level; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class BukkitChunkGeneratorWrapper extends ChunkGenerator implements GeneratorWrapper { + + private static final Map popMap = new HashMap<>(); + + private final PopulationManager popMan; + + private final TerraChunkGenerator delegate; + + private final TerraPlugin main; + + private boolean needsLoad = true; + + public BukkitChunkGeneratorWrapper(TerraChunkGenerator delegate) { + this.delegate = delegate; + this.main = delegate.getMain(); + popMan = new PopulationManager(main); + popMan.attach(new OrePopulator(main)); + popMan.attach(new TreePopulator(main)); + popMan.attach(new FloraPopulator(main)); + } + + + public static synchronized void saveAll() { + for(Map.Entry e : popMap.entrySet()) { + try { + e.getValue().saveBlocks(e.getKey()); + Debug.info("Saved data for world " + e.getKey().getName()); + } catch(IOException ioException) { + ioException.printStackTrace(); + } + } + } + + public static synchronized void fixChunk(Chunk c) { + if(!TerraWorld.isTerraWorld(c.getWorld())) throw new IllegalArgumentException(); + popMap.get(c.getWorld()).checkNeighbors(c.getX(), c.getZ(), c.getWorld()); + } + + private void load(com.dfsek.terra.api.platform.world.World w) { + try { + popMan.loadBlocks(w); + } catch(FileNotFoundException e) { + LangUtil.log("warning.no-population", Level.WARNING); + } catch(IOException | ClassNotFoundException e) { + e.printStackTrace(); + } + popMap.put(w, popMan); + needsLoad = false; + } + + @Override + public @NotNull ChunkData generateChunkData(@NotNull World world, @NotNull Random random, int x, int z, @NotNull BiomeGrid biome) { + com.dfsek.terra.api.platform.world.World bukkitWorld = BukkitAdapter.adapt(world); + if(needsLoad) load(bukkitWorld); // Load population data for world. + delegate.generateBiomes(bukkitWorld, random, x, z, new BukkitBiomeGrid(biome)); + return (ChunkData) delegate.generateChunkData(bukkitWorld, random, x, z, new BukkitChunkGenerator.BukkitChunkData(createChunkData(world))).getHandle(); + } + + @Override + public @NotNull List getDefaultPopulators(@NotNull World world) { + return Stream.of(new CavePopulator(main), new StructurePopulator(main), popMan).map(BukkitPopulatorWrapper::new).collect(Collectors.toList()); + } + + @Override + public boolean isParallelCapable() { + return delegate.isParallelCapable(); + } + + @Override + public boolean shouldGenerateCaves() { + return delegate.shouldGenerateCaves(); + } + + @Override + public boolean shouldGenerateDecorations() { + return delegate.shouldGenerateDecorations(); + } + + @Override + public boolean shouldGenerateMobs() { + return delegate.shouldGenerateMobs(); + } + + @Override + public boolean shouldGenerateStructures() { + return super.shouldGenerateStructures(); + } + + @Override + public TerraChunkGenerator getHandle() { + return delegate; + } +} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/generator/BukkitPopulator.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/generator/BukkitPopulator.java new file mode 100644 index 000000000..a8f72122f --- /dev/null +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/generator/BukkitPopulator.java @@ -0,0 +1,27 @@ +package com.dfsek.terra.bukkit.generator; + +import com.dfsek.terra.api.platform.generator.BlockPopulator; +import com.dfsek.terra.api.platform.world.Chunk; +import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.bukkit.world.BukkitChunk; +import com.dfsek.terra.bukkit.world.BukkitWorld; + +import java.util.Random; + +public class BukkitPopulator implements BlockPopulator { + private final org.bukkit.generator.BlockPopulator handle; + + public BukkitPopulator(org.bukkit.generator.BlockPopulator handle) { + this.handle = handle; + } + + @Override + public void populate(World world, Random random, Chunk chunk) { + handle.populate(((BukkitWorld) world).getHandle(), random, ((BukkitChunk) chunk).getHandle()); + } + + @Override + public org.bukkit.generator.BlockPopulator getHandle() { + return handle; + } +} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/generator/BukkitPopulatorWrapper.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/generator/BukkitPopulatorWrapper.java new file mode 100644 index 000000000..22b1a2a53 --- /dev/null +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/generator/BukkitPopulatorWrapper.java @@ -0,0 +1,23 @@ +package com.dfsek.terra.bukkit.generator; + +import com.dfsek.terra.api.world.generation.TerraBlockPopulator; +import com.dfsek.terra.bukkit.world.BukkitAdapter; +import org.bukkit.Chunk; +import org.bukkit.World; +import org.bukkit.generator.BlockPopulator; +import org.jetbrains.annotations.NotNull; + +import java.util.Random; + +public class BukkitPopulatorWrapper extends BlockPopulator { + private final TerraBlockPopulator delegate; + + public BukkitPopulatorWrapper(TerraBlockPopulator delegate) { + this.delegate = delegate; + } + + @Override + public void populate(@NotNull World world, @NotNull Random random, @NotNull Chunk source) { + delegate.populate(BukkitAdapter.adapt(world), BukkitAdapter.adapt(source)); + } +} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/handles/BukkitItemHandle.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/handles/BukkitItemHandle.java new file mode 100644 index 000000000..aa8531e67 --- /dev/null +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/handles/BukkitItemHandle.java @@ -0,0 +1,32 @@ +package com.dfsek.terra.bukkit.handles; + +import com.dfsek.terra.api.platform.block.MaterialData; +import com.dfsek.terra.api.platform.handle.ItemHandle; +import com.dfsek.terra.api.platform.inventory.ItemStack; +import com.dfsek.terra.api.platform.inventory.item.Enchantment; +import com.dfsek.terra.bukkit.util.MinecraftUtils; +import com.dfsek.terra.bukkit.world.BukkitAdapter; +import com.dfsek.terra.bukkit.world.block.BukkitMaterialData; +import com.dfsek.terra.bukkit.world.inventory.BukkitItemStack; +import org.bukkit.NamespacedKey; + +import java.util.Arrays; +import java.util.Set; +import java.util.stream.Collectors; + +public class BukkitItemHandle implements ItemHandle { + @Override + public ItemStack newItemStack(MaterialData material, int amount) { + return new BukkitItemStack(new org.bukkit.inventory.ItemStack(((BukkitMaterialData) material).getHandle(), amount)); + } + + @Override + public Enchantment getEnchantment(String id) { + return BukkitAdapter.adapt(org.bukkit.enchantments.Enchantment.getByKey(NamespacedKey.minecraft(MinecraftUtils.stripMinecraftNamespace(id)))); + } + + @Override + public Set getEnchantments() { + return Arrays.stream(org.bukkit.enchantments.Enchantment.values()).map(BukkitAdapter::adapt).collect(Collectors.toSet()); + } +} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/handles/BukkitWorldHandle.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/handles/BukkitWorldHandle.java new file mode 100644 index 000000000..6841a4e19 --- /dev/null +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/handles/BukkitWorldHandle.java @@ -0,0 +1,62 @@ +package com.dfsek.terra.bukkit.handles; + +import com.dfsek.terra.api.platform.TerraPlugin; +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.handle.WorldHandle; +import com.dfsek.terra.api.platform.world.Tree; +import com.dfsek.terra.api.platform.world.entity.EntityType; +import com.dfsek.terra.api.transform.Transformer; +import com.dfsek.terra.bukkit.world.block.BukkitMaterialData; +import com.dfsek.terra.bukkit.world.block.data.BukkitBlockData; +import com.dfsek.terra.bukkit.world.entity.BukkitEntityType; +import org.bukkit.Bukkit; +import org.bukkit.Material; + +public class BukkitWorldHandle implements WorldHandle { + private Transformer treeTransformer; + + public BukkitWorldHandle(TerraPlugin main) { + } + + public void setTreeTransformer(Transformer treeTransformer) { + this.treeTransformer = treeTransformer; + } + + @Override + public void setBlockData(Block block, BlockData data, boolean physics) { + block.setBlockData(data, physics); + } + + @Override + public BlockData getBlockData(Block block) { + return block.getBlockData(); + } + + @Override + public MaterialData getType(Block block) { + return block.getType(); + } + + @Override + public BlockData createBlockData(String data) { + org.bukkit.block.data.BlockData bukkitData = Bukkit.createBlockData(data); + return BukkitBlockData.newInstance(bukkitData); + } + + @Override + public MaterialData createMaterialData(String data) { + return new BukkitMaterialData(Material.matchMaterial(data)); + } + + @Override + public Tree getTree(String id) { + return treeTransformer.translate(id); + } + + @Override + public EntityType getEntity(String id) { + return new BukkitEntityType(org.bukkit.entity.EntityType.valueOf(id)); + } +} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/listeners/EventListener.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/listeners/EventListener.java new file mode 100644 index 000000000..cea3e77eb --- /dev/null +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/listeners/EventListener.java @@ -0,0 +1,59 @@ +package com.dfsek.terra.bukkit.listeners; + +import com.dfsek.terra.TerraWorld; +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.api.transform.MapTransform; +import com.dfsek.terra.api.transform.Transformer; +import com.dfsek.terra.api.util.FastRandom; +import com.dfsek.terra.api.world.tree.Tree; +import com.dfsek.terra.bukkit.world.BukkitAdapter; +import com.dfsek.terra.config.base.ConfigPack; +import com.dfsek.terra.registry.TreeRegistry; +import org.bukkit.Material; +import org.bukkit.TreeType; +import org.bukkit.block.Block; +import org.bukkit.block.data.BlockData; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.world.StructureGrowEvent; + +/** + * Listener for events on all implementations. + */ +public class EventListener implements Listener { + private final TerraPlugin main; + + public EventListener(TerraPlugin main) { + this.main = main; + } + + private static final Transformer TREE_TYPE_STRING_TRANSFORMER = new Transformer.Builder() + .addTransform(new MapTransform() + .add(TreeType.COCOA_TREE, "JUNGLE_COCOA") + .add(TreeType.BIG_TREE, "LARGE_OAK") + .add(TreeType.TALL_REDWOOD, "LARGE_SPRUCE") + .add(TreeType.REDWOOD, "SPRUCE") + .add(TreeType.TREE, "OAK") + .add(TreeType.MEGA_REDWOOD, "MEGA_SPRUCE") + .add(TreeType.SWAMP, "SWAMP_OAK")) + .addTransform(TreeType::toString).build(); + + @EventHandler + public void onSaplingGrow(StructureGrowEvent e) { + World bukkit = BukkitAdapter.adapt(e.getWorld()); + if(!TerraWorld.isTerraWorld(bukkit)) return; + TerraWorld tw = main.getWorld(bukkit); + ConfigPack c = tw.getConfig(); + if(c.getTemplate().isDisableSaplings()) return; + e.setCancelled(true); + Block block = e.getLocation().getBlock(); + BlockData data = block.getBlockData(); + block.setType(Material.AIR); + TreeRegistry registry = c.getTreeRegistry(); + Tree tree = registry.get(TREE_TYPE_STRING_TRANSFORMER.translate(e.getSpecies())); + org.bukkit.Location location = e.getLocation(); + if(!tree.plant(new Location(bukkit, location.getX(), location.getY(), location.getZ()), new FastRandom())) block.setBlockData(data); + } +} diff --git a/src/main/java/com/dfsek/terra/listeners/PaperListener.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/listeners/PaperListener.java similarity index 80% rename from src/main/java/com/dfsek/terra/listeners/PaperListener.java rename to platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/listeners/PaperListener.java index 97f38ef04..ae8e74b06 100644 --- a/src/main/java/com/dfsek/terra/listeners/PaperListener.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/listeners/PaperListener.java @@ -1,4 +1,4 @@ -package com.dfsek.terra.listeners; +package com.dfsek.terra.bukkit.listeners; import org.bukkit.event.Listener; diff --git a/src/main/java/com/dfsek/terra/listeners/SpigotListener.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/listeners/SpigotListener.java similarity index 70% rename from src/main/java/com/dfsek/terra/listeners/SpigotListener.java rename to platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/listeners/SpigotListener.java index 0e1147a7d..9d4e52065 100644 --- a/src/main/java/com/dfsek/terra/listeners/SpigotListener.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/listeners/SpigotListener.java @@ -1,11 +1,11 @@ -package com.dfsek.terra.listeners; +package com.dfsek.terra.bukkit.listeners; -import com.dfsek.terra.Terra; import com.dfsek.terra.TerraWorld; +import com.dfsek.terra.api.platform.TerraPlugin; import com.dfsek.terra.async.AsyncStructureFinder; +import com.dfsek.terra.bukkit.world.BukkitAdapter; import com.dfsek.terra.debug.Debug; -import com.dfsek.terra.generation.items.TerraStructure; -import com.dfsek.terra.util.StructureTypeEnum; +import com.dfsek.terra.population.items.TerraStructure; import org.bukkit.entity.EnderSignal; import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; @@ -24,9 +24,9 @@ import org.bukkit.event.entity.VillagerCareerChangeEvent; * StructureLocateEvent). */ public class SpigotListener implements Listener { - private final Terra main; + private final TerraPlugin main; - public SpigotListener(Terra main) { + public SpigotListener(TerraPlugin main) { this.main = main; } @@ -35,14 +35,15 @@ public class SpigotListener implements Listener { Entity entity = e.getEntity(); if(e.getEntityType().equals(EntityType.ENDER_SIGNAL)) { Debug.info("Detected Ender Signal..."); - if(!TerraWorld.isTerraWorld(e.getEntity().getWorld())) return; - TerraWorld tw = main.getWorld(e.getEntity().getWorld()); + if(!TerraWorld.isTerraWorld(BukkitAdapter.adapt(e.getEntity().getWorld()))) return; + TerraWorld tw = main.getWorld(BukkitAdapter.adapt(e.getEntity().getWorld())); EnderSignal signal = (EnderSignal) entity; - TerraStructure config = tw.getConfig().getStructureLocatable(StructureTypeEnum.STRONGHOLD); + TerraStructure config = tw.getConfig().getStructure(tw.getConfig().getTemplate().getLocatable().get("STRONGHOLD")); if(config != null) { Debug.info("Overriding Ender Signal..."); - AsyncStructureFinder finder = new AsyncStructureFinder(tw.getGrid(), config, e.getLocation(), 0, 500, location -> { - if(location != null) signal.setTargetLocation(location.toLocation(signal.getWorld())); + AsyncStructureFinder finder = new AsyncStructureFinder(tw.getGrid(), config, BukkitAdapter.adapt(e.getLocation()), 0, 500, location -> { + if(location != null) + signal.setTargetLocation(BukkitAdapter.adapt(location.toLocation(BukkitAdapter.adapt(signal.getWorld())))); Debug.info("Location: " + location); }, main); finder.run(); // Do this synchronously so eye doesn't change direction several ticks after spawning. @@ -53,7 +54,7 @@ public class SpigotListener implements Listener { @EventHandler public void onCartographerChange(VillagerAcquireTradeEvent e) { - if(!TerraWorld.isTerraWorld(e.getEntity().getWorld())) return; + if(!TerraWorld.isTerraWorld(BukkitAdapter.adapt(e.getEntity().getWorld()))) return; if(!(e.getEntity() instanceof Villager)) return; if(((Villager) e.getEntity()).getProfession().equals(Villager.Profession.CARTOGRAPHER)) e.setCancelled(true); // Cancel leveling if the villager is a Cartographer, to prevent crashing server. @@ -61,7 +62,7 @@ public class SpigotListener implements Listener { @EventHandler public void onCartographerLevel(VillagerCareerChangeEvent e) { - if(!TerraWorld.isTerraWorld(e.getEntity().getWorld())) return; + if(!TerraWorld.isTerraWorld(BukkitAdapter.adapt(e.getEntity().getWorld()))) return; if(e.getProfession().equals(Villager.Profession.CARTOGRAPHER)) { e.getEntity().setProfession(Villager.Profession.NITWIT); // Give villager new profession to prevent server crash. e.setCancelled(true); diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/structure/WorldEditNotFoundException.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/structure/WorldEditNotFoundException.java new file mode 100644 index 000000000..5b7ec6e0d --- /dev/null +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/structure/WorldEditNotFoundException.java @@ -0,0 +1,22 @@ +package com.dfsek.terra.bukkit.structure; + +public class WorldEditNotFoundException extends RuntimeException { + public WorldEditNotFoundException() { + } + + public WorldEditNotFoundException(String message) { + super(message); + } + + public WorldEditNotFoundException(String message, Throwable cause) { + super(message, cause); + } + + public WorldEditNotFoundException(Throwable cause) { + super(cause); + } + + public WorldEditNotFoundException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } +} diff --git a/src/main/java/com/dfsek/terra/util/structure/WorldEditUtil.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/structure/WorldEditUtil.java similarity index 80% rename from src/main/java/com/dfsek/terra/util/structure/WorldEditUtil.java rename to platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/structure/WorldEditUtil.java index d4813ef22..e1a15dc4b 100644 --- a/src/main/java/com/dfsek/terra/util/structure/WorldEditUtil.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/structure/WorldEditUtil.java @@ -1,4 +1,4 @@ -package com.dfsek.terra.util.structure; +package com.dfsek.terra.bukkit.structure; import com.sk89q.worldedit.IncompleteRegionException; import com.sk89q.worldedit.bukkit.BukkitAdapter; @@ -10,13 +10,16 @@ import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.entity.Player; import org.bukkit.plugin.Plugin; +import org.jetbrains.annotations.NotNull; public final class WorldEditUtil { public static Location[] getSelectionLocations(Player sender) { - WorldEditPlugin we = WorldEditUtil.getWorldEdit(); - if(we == null) { + WorldEditPlugin we; + try { + we = WorldEditUtil.getWorldEdit(); + } catch(WorldEditNotFoundException e) { sender.sendMessage("WorldEdit is not installed! Please install WorldEdit before attempting to export structures."); - return null; + throw e; } Region selection; try { @@ -36,18 +39,27 @@ public final class WorldEditUtil { return new Location[] {l1, l2}; } + /** + * Gets an instance of the WorldEditPlugin class. + * + * @return The world edit plugin instance. + * @throws WorldEditNotFoundException Thrown when worldedit cannot be found. + */ + @NotNull public static WorldEditPlugin getWorldEdit() { Plugin p = Bukkit.getServer().getPluginManager().getPlugin("WorldEdit"); if(p instanceof WorldEditPlugin) return (WorldEditPlugin) p; Bukkit.getLogger().severe("[Terra] a command requiring WorldEdit was executed, but WorldEdit was not detected!"); - return null; + throw new WorldEditNotFoundException("Could not find World Edit!"); } public static Location[] getSelectionPositions(Player sender) { - WorldEditPlugin we = WorldEditUtil.getWorldEdit(); - if(we == null) { + WorldEditPlugin we; + try { + we = WorldEditUtil.getWorldEdit(); + } catch(WorldEditNotFoundException e) { sender.sendMessage("WorldEdit is not installed! Please install WorldEdit before attempting to export structures."); - return null; + throw e; } CuboidRegion selection; try { diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/util/MinecraftUtils.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/util/MinecraftUtils.java new file mode 100644 index 000000000..0c36bc946 --- /dev/null +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/util/MinecraftUtils.java @@ -0,0 +1,8 @@ +package com.dfsek.terra.bukkit.util; + +public final class MinecraftUtils { + public static String stripMinecraftNamespace(String in) { + if(in.startsWith("minecraft:")) return in.substring("minecraft:".length()); + return in; + } +} diff --git a/src/main/java/com/dfsek/terra/util/PaperUtil.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/util/PaperUtil.java similarity index 91% rename from src/main/java/com/dfsek/terra/util/PaperUtil.java rename to platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/util/PaperUtil.java index 08f1fc2bc..05eba8c9b 100644 --- a/src/main/java/com/dfsek/terra/util/PaperUtil.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/util/PaperUtil.java @@ -1,4 +1,4 @@ -package com.dfsek.terra.util; +package com.dfsek.terra.bukkit.util; import io.papermc.lib.PaperLib; import org.bukkit.Bukkit; diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitAdapter.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitAdapter.java new file mode 100644 index 000000000..462474a4e --- /dev/null +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitAdapter.java @@ -0,0 +1,351 @@ +package com.dfsek.terra.bukkit.world; + + +import com.dfsek.terra.api.math.vector.Vector3; +import com.dfsek.terra.api.platform.CommandSender; +import com.dfsek.terra.api.platform.block.Axis; +import com.dfsek.terra.api.platform.block.BlockFace; +import com.dfsek.terra.api.platform.block.data.Bisected; +import com.dfsek.terra.api.platform.block.data.Rail; +import com.dfsek.terra.api.platform.block.data.RedstoneWire; +import com.dfsek.terra.api.platform.block.data.Slab; +import com.dfsek.terra.api.platform.block.data.Stairs; +import com.dfsek.terra.api.platform.inventory.item.Enchantment; +import com.dfsek.terra.api.platform.world.Chunk; +import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.bukkit.BukkitCommandSender; +import com.dfsek.terra.bukkit.world.inventory.meta.BukkitEnchantment; +import org.bukkit.Location; +import org.bukkit.util.Vector; + +/** + * Utility class to adapt Bukkit enums to Terra enums. + */ +public final class BukkitAdapter { + public static Stairs.Shape adapt(org.bukkit.block.data.type.Stairs.Shape shape) { + switch(shape) { + case STRAIGHT: + return Stairs.Shape.STRAIGHT; + case INNER_LEFT: + return Stairs.Shape.INNER_LEFT; + case OUTER_LEFT: + return Stairs.Shape.OUTER_LEFT; + case INNER_RIGHT: + return Stairs.Shape.INNER_RIGHT; + case OUTER_RIGHT: + return Stairs.Shape.OUTER_RIGHT; + default: + throw new IllegalStateException(); + } + } + + public static Axis adapt(org.bukkit.Axis axis) { + switch(axis) { + case X: + return Axis.X; + case Y: + return Axis.Y; + case Z: + return Axis.Z; + default: + throw new IllegalStateException(); + } + } + + public static Bisected.Half adapt(org.bukkit.block.data.Bisected.Half half) { + switch(half) { + case BOTTOM: + return Bisected.Half.BOTTOM; + case TOP: + return Bisected.Half.TOP; + default: + throw new IllegalStateException(); + } + } + + public static BlockFace adapt(org.bukkit.block.BlockFace face) { + switch(face) { + case DOWN: + return BlockFace.DOWN; + case UP: + return BlockFace.UP; + case NORTH_WEST: + return BlockFace.NORTH_WEST; + case NORTH_EAST: + return BlockFace.NORTH_EAST; + case SOUTH_EAST: + return BlockFace.SOUTH_EAST; + case SOUTH_WEST: + return BlockFace.SOUTH_WEST; + case NORTH_NORTH_WEST: + return BlockFace.NORTH_NORTH_WEST; + case WEST_NORTH_WEST: + return BlockFace.WEST_NORTH_WEST; + case WEST_SOUTH_WEST: + return BlockFace.WEST_SOUTH_WEST; + case SOUTH_SOUTH_WEST: + return BlockFace.SOUTH_SOUTH_WEST; + case EAST_NORTH_EAST: + return BlockFace.EAST_NORTH_EAST; + case WEST: + return BlockFace.WEST; + case SOUTH: + return BlockFace.SOUTH; + case EAST: + return BlockFace.EAST; + case NORTH: + return BlockFace.NORTH; + case SELF: + return BlockFace.SELF; + case EAST_SOUTH_EAST: + return BlockFace.EAST_SOUTH_EAST; + case NORTH_NORTH_EAST: + return BlockFace.NORTH_NORTH_EAST; + case SOUTH_SOUTH_EAST: + return BlockFace.SOUTH_SOUTH_EAST; + default: + throw new IllegalStateException(); + } + } + + public static Slab.Type adapt(org.bukkit.block.data.type.Slab.Type type) { + switch(type) { + case BOTTOM: + return Slab.Type.BOTTOM; + case TOP: + return Slab.Type.TOP; + case DOUBLE: + return Slab.Type.DOUBLE; + default: + throw new IllegalStateException(); + } + } + + public static RedstoneWire.Connection adapt(org.bukkit.block.data.type.RedstoneWire.Connection connection) { + switch(connection) { + case NONE: + return RedstoneWire.Connection.NONE; + case UP: + return RedstoneWire.Connection.UP; + case SIDE: + return RedstoneWire.Connection.SIDE; + default: + throw new IllegalStateException(); + } + } + + public static org.bukkit.block.data.type.RedstoneWire.Connection adapt(RedstoneWire.Connection connection) { + switch(connection) { + case SIDE: + return org.bukkit.block.data.type.RedstoneWire.Connection.SIDE; + case UP: + return org.bukkit.block.data.type.RedstoneWire.Connection.UP; + case NONE: + return org.bukkit.block.data.type.RedstoneWire.Connection.NONE; + default: + throw new IllegalStateException(); + } + } + + public static org.bukkit.block.data.type.Stairs.Shape adapt(Stairs.Shape shape) { + switch(shape) { + case STRAIGHT: + return org.bukkit.block.data.type.Stairs.Shape.STRAIGHT; + case INNER_LEFT: + return org.bukkit.block.data.type.Stairs.Shape.INNER_LEFT; + case OUTER_LEFT: + return org.bukkit.block.data.type.Stairs.Shape.OUTER_LEFT; + case INNER_RIGHT: + return org.bukkit.block.data.type.Stairs.Shape.INNER_RIGHT; + case OUTER_RIGHT: + return org.bukkit.block.data.type.Stairs.Shape.OUTER_RIGHT; + default: + throw new IllegalStateException(); + } + } + + public static Rail.Shape adapt(org.bukkit.block.data.Rail.Shape shape) { + switch(shape) { + case SOUTH_WEST: + return Rail.Shape.SOUTH_WEST; + case SOUTH_EAST: + return Rail.Shape.SOUTH_EAST; + case NORTH_EAST: + return Rail.Shape.NORTH_EAST; + case NORTH_WEST: + return Rail.Shape.NORTH_WEST; + case ASCENDING_EAST: + return Rail.Shape.ASCENDING_EAST; + case ASCENDING_WEST: + return Rail.Shape.ASCENDING_WEST; + case ASCENDING_SOUTH: + return Rail.Shape.ASCENDING_SOUTH; + case ASCENDING_NORTH: + return Rail.Shape.ASCENDING_NORTH; + case NORTH_SOUTH: + return Rail.Shape.NORTH_SOUTH; + case EAST_WEST: + return Rail.Shape.EAST_WEST; + default: + throw new IllegalStateException(); + } + } + + public static org.bukkit.block.data.Rail.Shape adapt(Rail.Shape shape) { + switch(shape) { + case EAST_WEST: + return org.bukkit.block.data.Rail.Shape.EAST_WEST; + case NORTH_SOUTH: + return org.bukkit.block.data.Rail.Shape.NORTH_SOUTH; + case ASCENDING_NORTH: + return org.bukkit.block.data.Rail.Shape.ASCENDING_NORTH; + case ASCENDING_SOUTH: + return org.bukkit.block.data.Rail.Shape.ASCENDING_SOUTH; + case ASCENDING_WEST: + return org.bukkit.block.data.Rail.Shape.ASCENDING_WEST; + case ASCENDING_EAST: + return org.bukkit.block.data.Rail.Shape.ASCENDING_EAST; + case NORTH_WEST: + return org.bukkit.block.data.Rail.Shape.NORTH_WEST; + case NORTH_EAST: + return org.bukkit.block.data.Rail.Shape.NORTH_EAST; + case SOUTH_EAST: + return org.bukkit.block.data.Rail.Shape.SOUTH_EAST; + case SOUTH_WEST: + return org.bukkit.block.data.Rail.Shape.SOUTH_WEST; + default: + throw new IllegalStateException(); + } + } + + + public static org.bukkit.block.data.Bisected.Half adapt(Bisected.Half half) { + switch(half) { + case TOP: + return org.bukkit.block.data.Bisected.Half.TOP; + case BOTTOM: + return org.bukkit.block.data.Bisected.Half.BOTTOM; + default: + throw new IllegalStateException(); + } + } + + public static org.bukkit.Axis adapt(Axis axis) { + switch(axis) { + case Z: + return org.bukkit.Axis.Z; + case Y: + return org.bukkit.Axis.Y; + case X: + return org.bukkit.Axis.X; + default: + throw new IllegalStateException(); + } + } + + public static org.bukkit.block.BlockFace adapt(BlockFace face) { + switch(face) { + case DOWN: + return org.bukkit.block.BlockFace.DOWN; + case UP: + return org.bukkit.block.BlockFace.UP; + case NORTH_WEST: + return org.bukkit.block.BlockFace.NORTH_WEST; + case NORTH_EAST: + return org.bukkit.block.BlockFace.NORTH_EAST; + case SOUTH_EAST: + return org.bukkit.block.BlockFace.SOUTH_EAST; + case SOUTH_WEST: + return org.bukkit.block.BlockFace.SOUTH_WEST; + case NORTH_NORTH_WEST: + return org.bukkit.block.BlockFace.NORTH_NORTH_WEST; + case WEST_NORTH_WEST: + return org.bukkit.block.BlockFace.WEST_NORTH_WEST; + case WEST_SOUTH_WEST: + return org.bukkit.block.BlockFace.WEST_SOUTH_WEST; + case SOUTH_SOUTH_WEST: + return org.bukkit.block.BlockFace.SOUTH_SOUTH_WEST; + case EAST_NORTH_EAST: + return org.bukkit.block.BlockFace.EAST_NORTH_EAST; + case WEST: + return org.bukkit.block.BlockFace.WEST; + case SOUTH: + return org.bukkit.block.BlockFace.SOUTH; + case EAST: + return org.bukkit.block.BlockFace.EAST; + case NORTH: + return org.bukkit.block.BlockFace.NORTH; + case SELF: + return org.bukkit.block.BlockFace.SELF; + case EAST_SOUTH_EAST: + return org.bukkit.block.BlockFace.EAST_SOUTH_EAST; + case NORTH_NORTH_EAST: + return org.bukkit.block.BlockFace.NORTH_NORTH_EAST; + case SOUTH_SOUTH_EAST: + return org.bukkit.block.BlockFace.SOUTH_SOUTH_EAST; + default: + throw new IllegalStateException(); + } + } + + public static org.bukkit.block.data.type.Slab.Type adapt(Slab.Type type) { + switch(type) { + case TOP: + return org.bukkit.block.data.type.Slab.Type.TOP; + case DOUBLE: + return org.bukkit.block.data.type.Slab.Type.DOUBLE; + case BOTTOM: + return org.bukkit.block.data.type.Slab.Type.BOTTOM; + default: + throw new IllegalStateException(); + } + } + + public static Location adapt(com.dfsek.terra.api.math.vector.Location location) { + return new Location(((BukkitWorld) location.getWorld()).getHandle(), location.getX(), location.getY(), location.getZ()); + } + + public static com.dfsek.terra.api.math.vector.Location adapt(Location location) { + return new com.dfsek.terra.api.math.vector.Location(adapt(location.getWorld()), location.getX(), location.getY(), location.getZ()); + } + + public static Vector adapt(Vector3 vector3) { + return new Vector(vector3.getX(), vector3.getY(), vector3.getZ()); + } + + public static Vector3 adapt(Vector vector) { + return new Vector3(vector.getX(), vector.getY(), vector.getZ()); + } + + public static CommandSender adapt(org.bukkit.command.CommandSender sender) { + return new BukkitCommandSender(sender); + } + + public static org.bukkit.command.CommandSender adapt(CommandSender sender) { + return ((BukkitCommandSender) sender).getHandle(); + } + + public static World adapt(org.bukkit.World world) { + return new BukkitWorld(world); + } + + public static org.bukkit.World adapt(World world) { + return (org.bukkit.World) world.getHandle(); + } + + public static Chunk adapt(org.bukkit.Chunk chunk) { + return new BukkitChunk(chunk); + } + + public static org.bukkit.Chunk adapt(Chunk chunk) { + return (org.bukkit.Chunk) chunk.getHandle(); + } + + public static Enchantment adapt(org.bukkit.enchantments.Enchantment enchantment) { + return new BukkitEnchantment(enchantment); + } + + public static org.bukkit.enchantments.Enchantment adapt(Enchantment enchantment) { + return ((BukkitEnchantment) enchantment).getHandle(); + } +} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitBiome.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitBiome.java new file mode 100644 index 000000000..843268183 --- /dev/null +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitBiome.java @@ -0,0 +1,16 @@ +package com.dfsek.terra.bukkit.world; + +import com.dfsek.terra.api.platform.world.Biome; + +public class BukkitBiome implements Biome { + private final org.bukkit.block.Biome biome; + + public BukkitBiome(org.bukkit.block.Biome biome) { + this.biome = biome; + } + + @Override + public org.bukkit.block.Biome getHandle() { + return biome; + } +} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitBiomeGrid.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitBiomeGrid.java new file mode 100644 index 000000000..da1fdfc51 --- /dev/null +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitBiomeGrid.java @@ -0,0 +1,39 @@ +package com.dfsek.terra.bukkit.world; + +import com.dfsek.terra.api.platform.world.Biome; +import com.dfsek.terra.api.platform.world.BiomeGrid; +import org.bukkit.generator.ChunkGenerator; +import org.jetbrains.annotations.NotNull; + +public class BukkitBiomeGrid implements BiomeGrid { + private final ChunkGenerator.BiomeGrid delegate; + + public BukkitBiomeGrid(ChunkGenerator.BiomeGrid biomeGrid) { + this.delegate = biomeGrid; + } + + @Override + public ChunkGenerator.BiomeGrid getHandle() { + return delegate; + } + + @Override + public @NotNull Biome getBiome(int x, int z) { + return new BukkitBiome(delegate.getBiome(x, z)); + } + + @Override + public @NotNull Biome getBiome(int x, int y, int z) { + return new BukkitBiome(delegate.getBiome(x, y, z)); + } + + @Override + public void setBiome(int x, int z, @NotNull Biome bio) { + delegate.setBiome(x, z, ((BukkitBiome) bio).getHandle()); + } + + @Override + public void setBiome(int x, int y, int z, @NotNull Biome bio) { + delegate.setBiome(x, y, z, ((BukkitBiome) bio).getHandle()); + } +} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitChunk.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitChunk.java new file mode 100644 index 000000000..c3cdafb51 --- /dev/null +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitChunk.java @@ -0,0 +1,39 @@ +package com.dfsek.terra.bukkit.world; + +import com.dfsek.terra.api.platform.block.Block; +import com.dfsek.terra.api.platform.world.Chunk; +import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.bukkit.world.block.BukkitBlock; + +public class BukkitChunk implements Chunk { + private final org.bukkit.Chunk delegate; + + public BukkitChunk(org.bukkit.Chunk delegate) { + this.delegate = delegate; + } + + @Override + public int getX() { + return delegate.getX(); + } + + @Override + public int getZ() { + return delegate.getZ(); + } + + @Override + public World getWorld() { + return BukkitAdapter.adapt(delegate.getWorld()); + } + + @Override + public Block getBlock(int x, int y, int z) { + return new BukkitBlock(delegate.getBlock(x, y, z)); + } + + @Override + public org.bukkit.Chunk getHandle() { + return delegate; + } +} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitTree.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitTree.java new file mode 100644 index 000000000..b8de9bbbc --- /dev/null +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitTree.java @@ -0,0 +1,58 @@ +package com.dfsek.terra.bukkit.world; + +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.platform.block.MaterialData; +import com.dfsek.terra.api.platform.handle.WorldHandle; +import com.dfsek.terra.api.platform.world.Tree; +import com.dfsek.terra.util.MaterialSet; +import org.bukkit.TreeType; + +import java.util.Random; +import java.util.Set; + +public class BukkitTree implements Tree { + private final TreeType delegate; + private final MaterialSet spawnable; + private final TerraPlugin main; + + public BukkitTree(TreeType delegate, TerraPlugin main) { + this.delegate = delegate; + this.main = main; + this.spawnable = getSpawnable(delegate); + } + + private MaterialSet getSpawnable(TreeType type) { + WorldHandle handle = main.getWorldHandle(); + switch(type) { + case CRIMSON_FUNGUS: + return MaterialSet.get(handle.createMaterialData("minecraft:crimson_nylium")); + case WARPED_FUNGUS: + return MaterialSet.get(handle.createMaterialData("minecraft:warped_nylium")); + case BROWN_MUSHROOM: + case RED_MUSHROOM: + return MaterialSet.get(handle.createMaterialData("minecraft:mycelium"), handle.createMaterialData("minecraft:grass_block"), + handle.createMaterialData("minecraft:podzol")); + case CHORUS_PLANT: + return MaterialSet.get(handle.createMaterialData("minecraft:end_stone")); + default: + return MaterialSet.get(handle.createMaterialData("minecraft:grass_block"), handle.createMaterialData("minecraft:dirt"), + handle.createMaterialData("minecraft:podzol")); + } + } + + @Override + public TreeType getHandle() { + return delegate; + } + + @Override + public boolean plant(Location l, Random r) { + return ((BukkitWorld) l.getWorld()).getHandle().generateTree(BukkitAdapter.adapt(l), delegate); + } + + @Override + public Set getSpawnable() { + return spawnable; + } +} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitWorld.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitWorld.java new file mode 100644 index 000000000..4180de888 --- /dev/null +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitWorld.java @@ -0,0 +1,107 @@ +package com.dfsek.terra.bukkit.world; + +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.platform.block.Block; +import com.dfsek.terra.api.platform.generator.ChunkGenerator; +import com.dfsek.terra.api.platform.world.Chunk; +import com.dfsek.terra.api.platform.world.Tree; +import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.api.platform.world.entity.Entity; +import com.dfsek.terra.api.platform.world.entity.EntityType; +import com.dfsek.terra.bukkit.BukkitEntity; +import com.dfsek.terra.bukkit.generator.BukkitChunkGenerator; +import com.dfsek.terra.bukkit.world.block.BukkitBlock; +import com.dfsek.terra.bukkit.world.entity.BukkitEntityType; + +import java.io.File; +import java.util.UUID; + +public class BukkitWorld implements World { + private final org.bukkit.World delegate; + + public BukkitWorld(org.bukkit.World delegate) { + this.delegate = delegate; + } + + @Override + public long getSeed() { + return delegate.getSeed(); + } + + @Override + public int getMaxHeight() { + return delegate.getMaxHeight(); + } + + @Override + public ChunkGenerator getGenerator() { + return new BukkitChunkGenerator(delegate.getGenerator()); + } + + @Override + public String getName() { + return delegate.getName(); + } + + @Override + public UUID getUID() { + return delegate.getUID(); + } + + @Override + public boolean isChunkGenerated(int x, int z) { + return delegate.isChunkGenerated(x, z); + } + + @Override + public Chunk getChunkAt(int x, int z) { + return BukkitAdapter.adapt(delegate.getChunkAt(x, z)); + } + + @Override + public File getWorldFolder() { + return delegate.getWorldFolder(); + } + + @Override + public Block getBlockAt(int x, int y, int z) { + return new BukkitBlock(delegate.getBlockAt(x, y, z)); + } + + @Override + public Block getBlockAt(Location l) { + return new BukkitBlock(delegate.getBlockAt(l.getBlockX(), l.getBlockY(), l.getBlockZ())); + } + + @Override + public boolean generateTree(Location l, Tree vanillaTreeType) { + return delegate.generateTree(new org.bukkit.Location(delegate, l.getX(), l.getY(), l.getZ()), ((BukkitTree) vanillaTreeType).getHandle()); + } + + @Override + public Entity spawnEntity(Location location, EntityType entityType) { + return new BukkitEntity(delegate.spawnEntity(BukkitAdapter.adapt(location), ((BukkitEntityType) entityType).getHandle())); + } + + @Override + public org.bukkit.World getHandle() { + return delegate; + } + + @Override + public boolean equals(Object obj) { + if(!(obj instanceof BukkitWorld)) return false; + BukkitWorld other = (BukkitWorld) obj; + return other.getHandle().equals(delegate); + } + + @Override + public int hashCode() { + return delegate.hashCode(); + } + + @Override + public String toString() { + return delegate.toString(); + } +} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/BukkitBlock.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/BukkitBlock.java new file mode 100644 index 000000000..aaa5a9b47 --- /dev/null +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/BukkitBlock.java @@ -0,0 +1,84 @@ +package com.dfsek.terra.bukkit.world.block; + +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.platform.block.Block; +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.block.BlockFace; +import com.dfsek.terra.api.platform.block.MaterialData; +import com.dfsek.terra.api.platform.block.state.BlockState; +import com.dfsek.terra.bukkit.world.BukkitAdapter; +import com.dfsek.terra.bukkit.world.block.data.BukkitBlockData; +import com.dfsek.terra.bukkit.world.block.state.BukkitBlockState; + +public class BukkitBlock implements Block { + private final org.bukkit.block.Block delegate; + + public BukkitBlock(org.bukkit.block.Block delegate) { + this.delegate = delegate; + } + + @Override + public void setBlockData(BlockData data, boolean physics) { + delegate.setBlockData(((BukkitBlockData) data).getHandle(), physics); + } + + @Override + public BlockData getBlockData() { + return BukkitBlockData.newInstance(delegate.getBlockData()); + } + + @Override + public BlockState getState() { + return BukkitBlockState.newInstance(delegate.getState()); + } + + @Override + public Block getRelative(BlockFace face) { + return new BukkitBlock(delegate.getRelative(BukkitAdapter.adapt(face))); + } + + @Override + public Block getRelative(BlockFace face, int len) { + return new BukkitBlock(delegate.getRelative(BukkitAdapter.adapt(face), len)); + } + + @Override + public boolean isEmpty() { + return delegate.isEmpty(); + } + + @Override + public Location getLocation() { + return BukkitAdapter.adapt(delegate.getLocation()); + } + + @Override + public MaterialData getType() { + return new BukkitMaterialData(delegate.getType()); + } + + @Override + public int getX() { + return delegate.getX(); + } + + @Override + public int getZ() { + return delegate.getZ(); + } + + @Override + public int getY() { + return delegate.getY(); + } + + @Override + public boolean isPassable() { + return delegate.isPassable(); + } + + @Override + public org.bukkit.block.Block getHandle() { + return delegate; + } +} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/BukkitMaterialData.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/BukkitMaterialData.java new file mode 100644 index 000000000..e0bfba568 --- /dev/null +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/BukkitMaterialData.java @@ -0,0 +1,62 @@ +package com.dfsek.terra.bukkit.world.block; + +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.block.MaterialData; +import com.dfsek.terra.bukkit.world.block.data.BukkitBlockData; +import org.bukkit.Material; + +public class BukkitMaterialData implements MaterialData { + private final Material delegate; + + public BukkitMaterialData(Material delegate) { + this.delegate = delegate; + } + + @Override + public boolean matches(MaterialData other) { + return ((BukkitMaterialData) other).getHandle().equals(delegate); + } + + @Override + public boolean matches(BlockData other) { + return ((BukkitMaterialData) other.getMaterial()).getHandle().equals(delegate); + } + + @Override + public boolean isSolid() { + return delegate.isSolid(); + } + + @Override + public boolean isAir() { + return delegate.isAir(); + } + + @Override + public double getMaxDurability() { + return delegate.getMaxDurability(); + } + + @Override + public BlockData createBlockData() { + return BukkitBlockData.newInstance(delegate.createBlockData()); + } + + @Override + public Material getHandle() { + return delegate; + } + + @Override + public int hashCode() { + return delegate.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if(!(obj instanceof BukkitMaterialData)) return false; + BukkitMaterialData other = (BukkitMaterialData) obj; + + return other.getHandle().equals(this.delegate); + } +} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitAnaloguePowerable.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitAnaloguePowerable.java new file mode 100644 index 000000000..71cd99513 --- /dev/null +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitAnaloguePowerable.java @@ -0,0 +1,24 @@ +package com.dfsek.terra.bukkit.world.block.data; + +import com.dfsek.terra.api.platform.block.data.AnaloguePowerable; + +public class BukkitAnaloguePowerable extends BukkitBlockData implements AnaloguePowerable { + public BukkitAnaloguePowerable(org.bukkit.block.data.AnaloguePowerable delegate) { + super(delegate); + } + + @Override + public int getMaximumPower() { + return ((org.bukkit.block.data.AnaloguePowerable) getHandle()).getMaximumPower(); + } + + @Override + public int getPower() { + return ((org.bukkit.block.data.AnaloguePowerable) getHandle()).getPower(); + } + + @Override + public void setPower(int power) { + ((org.bukkit.block.data.AnaloguePowerable) getHandle()).setPower(power); + } +} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitBlockData.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitBlockData.java new file mode 100644 index 000000000..dc3295f73 --- /dev/null +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitBlockData.java @@ -0,0 +1,79 @@ +package com.dfsek.terra.bukkit.world.block.data; + +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.block.MaterialData; +import com.dfsek.terra.bukkit.TerraBukkitPlugin; +import com.dfsek.terra.bukkit.world.block.BukkitMaterialData; +import org.bukkit.block.data.AnaloguePowerable; +import org.bukkit.block.data.Directional; +import org.bukkit.block.data.MultipleFacing; +import org.bukkit.block.data.Orientable; +import org.bukkit.block.data.Rail; +import org.bukkit.block.data.Rotatable; +import org.bukkit.block.data.Waterlogged; +import org.bukkit.block.data.type.RedstoneWire; +import org.bukkit.block.data.type.Slab; +import org.bukkit.block.data.type.Stairs; +import org.bukkit.block.data.type.Wall; + +public class BukkitBlockData implements BlockData { + private org.bukkit.block.data.BlockData delegate; + + protected BukkitBlockData(org.bukkit.block.data.BlockData delegate) { + this.delegate = delegate; + } + + public static BukkitBlockData newInstance(org.bukkit.block.data.BlockData bukkitData) { + + if(bukkitData instanceof Rail) return new BukkitRail((Rail) bukkitData); + if(bukkitData instanceof Stairs) return new BukkitStairs((Stairs) bukkitData); + if(bukkitData instanceof Slab) return new BukkitSlab((Slab) bukkitData); + if(TerraBukkitPlugin.BUKKIT_VERSION.above(TerraBukkitPlugin.Version.V1_16) && bukkitData instanceof Wall) { // Wall only exists on 1.16 and up. + return new BukkitWall((Wall) bukkitData); + } + + if(bukkitData instanceof RedstoneWire) return new BukkitRedstoneWire((RedstoneWire) bukkitData); + if(bukkitData instanceof AnaloguePowerable) return new BukkitAnaloguePowerable((AnaloguePowerable) bukkitData); + + if(bukkitData instanceof MultipleFacing) return new BukkitMultipleFacing((MultipleFacing) bukkitData); + if(bukkitData instanceof Rotatable) return new BukkitRotatable((Rotatable) bukkitData); + if(bukkitData instanceof Directional) return new BukkitDirectional((Directional) bukkitData); + if(bukkitData instanceof Orientable) return new BukkitOrientable((Orientable) bukkitData); + + if(bukkitData instanceof Waterlogged) return new BukkitWaterlogged((Waterlogged) bukkitData); + + return new BukkitBlockData(bukkitData); + } + + + @Override + public org.bukkit.block.data.BlockData getHandle() { + return delegate; + } + + @Override + public MaterialData getMaterial() { + return new BukkitMaterialData(delegate.getMaterial()); + } + + @Override + public boolean matches(MaterialData materialData) { + return delegate.getMaterial().equals(((BukkitMaterialData) materialData).getHandle()); + } + + @Override + public BukkitBlockData clone() { + try { + BukkitBlockData n = (BukkitBlockData) super.clone(); + n.delegate = delegate.clone(); + return n; + } catch(CloneNotSupportedException e) { + throw new Error(e); + } + } + + @Override + public String getAsString() { + return delegate.getAsString(false); + } +} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitDirectional.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitDirectional.java new file mode 100644 index 000000000..13d610774 --- /dev/null +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitDirectional.java @@ -0,0 +1,21 @@ +package com.dfsek.terra.bukkit.world.block.data; + +import com.dfsek.terra.api.platform.block.BlockFace; +import com.dfsek.terra.api.platform.block.data.Directional; +import com.dfsek.terra.bukkit.world.BukkitAdapter; + +public class BukkitDirectional extends BukkitBlockData implements Directional { + public BukkitDirectional(org.bukkit.block.data.Directional delegate) { + super(delegate); + } + + @Override + public BlockFace getFacing() { + return BukkitAdapter.adapt(((org.bukkit.block.data.Directional) getHandle()).getFacing()); + } + + @Override + public void setFacing(BlockFace facing) { + ((org.bukkit.block.data.Directional) getHandle()).setFacing(BukkitAdapter.adapt(facing)); + } +} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitMultipleFacing.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitMultipleFacing.java new file mode 100644 index 000000000..4e01a62f3 --- /dev/null +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitMultipleFacing.java @@ -0,0 +1,35 @@ +package com.dfsek.terra.bukkit.world.block.data; + +import com.dfsek.terra.api.platform.block.BlockFace; +import com.dfsek.terra.api.platform.block.data.MultipleFacing; +import com.dfsek.terra.bukkit.world.BukkitAdapter; + +import java.util.Set; +import java.util.stream.Collectors; + +public class BukkitMultipleFacing extends BukkitBlockData implements MultipleFacing { + + public BukkitMultipleFacing(org.bukkit.block.data.MultipleFacing delegate) { + super(delegate); + } + + @Override + public Set getFaces() { + return ((org.bukkit.block.data.MultipleFacing) super.getHandle()).getFaces().stream().map(BukkitAdapter::adapt).collect(Collectors.toSet()); + } + + @Override + public void setFace(BlockFace face, boolean facing) { + ((org.bukkit.block.data.MultipleFacing) super.getHandle()).setFace(BukkitAdapter.adapt(face), facing); + } + + @Override + public Set getAllowedFaces() { + return ((org.bukkit.block.data.MultipleFacing) super.getHandle()).getAllowedFaces().stream().map(BukkitAdapter::adapt).collect(Collectors.toSet()); + } + + @Override + public boolean hasFace(BlockFace f) { + return ((org.bukkit.block.data.MultipleFacing) super.getHandle()).hasFace(BukkitAdapter.adapt(f)); + } +} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitOrientable.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitOrientable.java new file mode 100644 index 000000000..c6cfdca18 --- /dev/null +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitOrientable.java @@ -0,0 +1,30 @@ +package com.dfsek.terra.bukkit.world.block.data; + +import com.dfsek.terra.api.platform.block.Axis; +import com.dfsek.terra.api.platform.block.data.Orientable; +import com.dfsek.terra.bukkit.world.BukkitAdapter; + +import java.util.Set; +import java.util.stream.Collectors; + +public class BukkitOrientable extends BukkitBlockData implements Orientable { + + public BukkitOrientable(org.bukkit.block.data.Orientable delegate) { + super(delegate); + } + + @Override + public Set getAxes() { + return ((org.bukkit.block.data.Orientable) getHandle()).getAxes().stream().map(BukkitAdapter::adapt).collect(Collectors.toSet()); + } + + @Override + public Axis getAxis() { + return BukkitAdapter.adapt(((org.bukkit.block.data.Orientable) getHandle()).getAxis()); + } + + @Override + public void setAxis(Axis axis) { + ((org.bukkit.block.data.Orientable) getHandle()).setAxis(BukkitAdapter.adapt(axis)); + } +} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitRail.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitRail.java new file mode 100644 index 000000000..ae85d2b76 --- /dev/null +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitRail.java @@ -0,0 +1,20 @@ +package com.dfsek.terra.bukkit.world.block.data; + +import com.dfsek.terra.api.platform.block.data.Rail; +import com.dfsek.terra.bukkit.world.BukkitAdapter; + +public class BukkitRail extends BukkitBlockData implements Rail { + public BukkitRail(org.bukkit.block.data.Rail delegate) { + super(delegate); + } + + @Override + public Shape getShape() { + return BukkitAdapter.adapt(((org.bukkit.block.data.Rail) getHandle()).getShape()); + } + + @Override + public void setShape(Shape newShape) { + ((org.bukkit.block.data.Rail) getHandle()).setShape(BukkitAdapter.adapt(newShape)); + } +} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitRedstoneWire.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitRedstoneWire.java new file mode 100644 index 000000000..708c1316b --- /dev/null +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitRedstoneWire.java @@ -0,0 +1,29 @@ +package com.dfsek.terra.bukkit.world.block.data; + +import com.dfsek.terra.api.platform.block.BlockFace; +import com.dfsek.terra.api.platform.block.data.RedstoneWire; +import com.dfsek.terra.bukkit.world.BukkitAdapter; + +import java.util.Set; +import java.util.stream.Collectors; + +public class BukkitRedstoneWire extends BukkitAnaloguePowerable implements RedstoneWire { + public BukkitRedstoneWire(org.bukkit.block.data.type.RedstoneWire delegate) { + super(delegate); + } + + @Override + public Set getAllowedFaces() { + return ((org.bukkit.block.data.type.RedstoneWire) getHandle()).getAllowedFaces().stream().map(BukkitAdapter::adapt).collect(Collectors.toSet()); + } + + @Override + public Connection getFace(BlockFace face) { + return BukkitAdapter.adapt(((org.bukkit.block.data.type.RedstoneWire) getHandle()).getFace(BukkitAdapter.adapt(face))); + } + + @Override + public void setFace(BlockFace face, Connection connection) { + ((org.bukkit.block.data.type.RedstoneWire) getHandle()).setFace(BukkitAdapter.adapt(face), BukkitAdapter.adapt(connection)); + } +} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitRotatable.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitRotatable.java new file mode 100644 index 000000000..0da5c04b9 --- /dev/null +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitRotatable.java @@ -0,0 +1,21 @@ +package com.dfsek.terra.bukkit.world.block.data; + +import com.dfsek.terra.api.platform.block.BlockFace; +import com.dfsek.terra.api.platform.block.data.Rotatable; +import com.dfsek.terra.bukkit.world.BukkitAdapter; + +public class BukkitRotatable extends BukkitBlockData implements Rotatable { + public BukkitRotatable(org.bukkit.block.data.Rotatable delegate) { + super(delegate); + } + + @Override + public BlockFace getRotation() { + return BukkitAdapter.adapt(((org.bukkit.block.data.Rotatable) getHandle()).getRotation()); + } + + @Override + public void setRotation(BlockFace face) { + ((org.bukkit.block.data.Rotatable) getHandle()).setRotation(BukkitAdapter.adapt(face)); + } +} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitSlab.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitSlab.java new file mode 100644 index 000000000..6ddf160b3 --- /dev/null +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitSlab.java @@ -0,0 +1,20 @@ +package com.dfsek.terra.bukkit.world.block.data; + +import com.dfsek.terra.api.platform.block.data.Slab; +import com.dfsek.terra.bukkit.world.BukkitAdapter; + +public class BukkitSlab extends BukkitWaterlogged implements Slab { + public BukkitSlab(org.bukkit.block.data.type.Slab delegate) { + super(delegate); + } + + @Override + public Type getType() { + return BukkitAdapter.adapt(((org.bukkit.block.data.type.Slab) getHandle()).getType()); + } + + @Override + public void setType(Type type) { + ((org.bukkit.block.data.type.Slab) getHandle()).setType(BukkitAdapter.adapt(type)); + } +} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitStairs.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitStairs.java new file mode 100644 index 000000000..c54d4a993 --- /dev/null +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitStairs.java @@ -0,0 +1,52 @@ +package com.dfsek.terra.bukkit.world.block.data; + +import com.dfsek.terra.api.platform.block.BlockFace; +import com.dfsek.terra.api.platform.block.data.Stairs; +import com.dfsek.terra.bukkit.world.BukkitAdapter; + +public class BukkitStairs extends BukkitBlockData implements Stairs { + + public BukkitStairs(org.bukkit.block.data.type.Stairs delegate) { + super(delegate); + } + + @Override + public Shape getShape() { + return BukkitAdapter.adapt(((org.bukkit.block.data.type.Stairs) super.getHandle()).getShape()); + } + + @Override + public void setShape(Shape shape) { + ((org.bukkit.block.data.type.Stairs) super.getHandle()).setShape(BukkitAdapter.adapt(shape)); + } + + @Override + public Half getHalf() { + return BukkitAdapter.adapt(((org.bukkit.block.data.type.Stairs) super.getHandle()).getHalf()); + } + + @Override + public void setHalf(Half half) { + ((org.bukkit.block.data.type.Stairs) super.getHandle()).setHalf(BukkitAdapter.adapt(half)); + } + + @Override + public BlockFace getFacing() { + return BukkitAdapter.adapt(((org.bukkit.block.data.type.Stairs) super.getHandle()).getFacing()); + } + + @Override + public void setFacing(BlockFace facing) { + ((org.bukkit.block.data.type.Stairs) super.getHandle()).setFacing(BukkitAdapter.adapt(facing)); + } + + @Override + public boolean isWaterlogged() { + return ((org.bukkit.block.data.type.Stairs) super.getHandle()).isWaterlogged(); + } + + @Override + public void setWaterlogged(boolean waterlogged) { + ((org.bukkit.block.data.type.Stairs) super.getHandle()).setWaterlogged(waterlogged); + } +} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitWall.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitWall.java new file mode 100644 index 000000000..2addb83b7 --- /dev/null +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitWall.java @@ -0,0 +1,57 @@ +package com.dfsek.terra.bukkit.world.block.data; + +import com.dfsek.terra.api.platform.block.BlockFace; +import com.dfsek.terra.api.platform.block.data.Wall; +import com.dfsek.terra.bukkit.world.BukkitAdapter; + +public class BukkitWall extends BukkitWaterlogged implements Wall { + public BukkitWall(org.bukkit.block.data.type.Wall delegate) { + super(delegate); + } + + @Override + public boolean isUp() { + return ((org.bukkit.block.data.type.Wall) getHandle()).isUp(); + } + + @Override + public void setUp(boolean up) { + ((org.bukkit.block.data.type.Wall) getHandle()).setUp(up); + } + + public static org.bukkit.block.data.type.Wall.Height adapt(com.dfsek.terra.api.platform.block.data.Wall.Height height) { + switch(height) { + case NONE: + return org.bukkit.block.data.type.Wall.Height.NONE; + case LOW: + return org.bukkit.block.data.type.Wall.Height.LOW; + case TALL: + return org.bukkit.block.data.type.Wall.Height.TALL; + default: + throw new IllegalStateException(); + } + } + + public static com.dfsek.terra.api.platform.block.data.Wall.Height adapt(org.bukkit.block.data.type.Wall.Height height) { + switch(height) { + case TALL: + return com.dfsek.terra.api.platform.block.data.Wall.Height.TALL; + case LOW: + return com.dfsek.terra.api.platform.block.data.Wall.Height.LOW; + case NONE: + return com.dfsek.terra.api.platform.block.data.Wall.Height.NONE; + default: + throw new IllegalStateException(); + } + } + + @Override + public void setHeight(BlockFace face, Height height) { + ((org.bukkit.block.data.type.Wall) getHandle()).setHeight(BukkitAdapter.adapt(face), adapt(height)); + } + + @Override + public Height getHeight(BlockFace face) { + return adapt(((org.bukkit.block.data.type.Wall) getHandle()).getHeight(BukkitAdapter.adapt(face))); + } +} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitWaterlogged.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitWaterlogged.java new file mode 100644 index 000000000..b75c6c170 --- /dev/null +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitWaterlogged.java @@ -0,0 +1,19 @@ +package com.dfsek.terra.bukkit.world.block.data; + +import com.dfsek.terra.api.platform.block.data.Waterlogged; + +public class BukkitWaterlogged extends BukkitBlockData implements Waterlogged { + public BukkitWaterlogged(org.bukkit.block.data.Waterlogged delegate) { + super(delegate); + } + + @Override + public boolean isWaterlogged() { + return ((org.bukkit.block.data.Waterlogged) super.getHandle()).isWaterlogged(); + } + + @Override + public void setWaterlogged(boolean waterlogged) { + ((org.bukkit.block.data.Waterlogged) super.getHandle()).setWaterlogged(waterlogged); + } +} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/state/BukkitBlockState.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/state/BukkitBlockState.java new file mode 100644 index 000000000..c96c520de --- /dev/null +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/state/BukkitBlockState.java @@ -0,0 +1,60 @@ +package com.dfsek.terra.bukkit.world.block.state; + +import com.dfsek.terra.api.platform.block.Block; +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.block.state.BlockState; +import com.dfsek.terra.bukkit.world.block.BukkitBlock; +import com.dfsek.terra.bukkit.world.block.data.BukkitBlockData; +import org.bukkit.block.Container; +import org.bukkit.block.CreatureSpawner; +import org.bukkit.block.Sign; + +public class BukkitBlockState implements BlockState { + private final org.bukkit.block.BlockState delegate; + + protected BukkitBlockState(org.bukkit.block.BlockState block) { + this.delegate = block; + } + + public static BukkitBlockState newInstance(org.bukkit.block.BlockState block) { + if(block instanceof Container) return new BukkitContainer((Container) block); + if(block instanceof Sign) return new BukkitSign((Sign) block); + if(block instanceof CreatureSpawner) return new BukkitMobSpawner((CreatureSpawner) block); + return new BukkitBlockState(block); + } + + @Override + public org.bukkit.block.BlockState getHandle() { + return delegate; + } + + @Override + public Block getBlock() { + return new BukkitBlock(delegate.getBlock()); + } + + @Override + public int getX() { + return delegate.getX(); + } + + @Override + public int getY() { + return delegate.getY(); + } + + @Override + public int getZ() { + return delegate.getZ(); + } + + @Override + public BlockData getBlockData() { + return BukkitBlockData.newInstance(delegate.getBlockData()); + } + + @Override + public boolean update(boolean applyPhysics) { + return delegate.update(true, applyPhysics); + } +} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/state/BukkitContainer.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/state/BukkitContainer.java new file mode 100644 index 000000000..c95040f8c --- /dev/null +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/state/BukkitContainer.java @@ -0,0 +1,18 @@ +package com.dfsek.terra.bukkit.world.block.state; + +import com.dfsek.terra.api.platform.block.state.Container; +import com.dfsek.terra.api.platform.inventory.Inventory; +import com.dfsek.terra.bukkit.world.inventory.BukkitInventory; + +public class BukkitContainer extends BukkitBlockState implements Container { + + protected BukkitContainer(org.bukkit.block.Container block) { + super(block); + } + + @Override + public Inventory getInventory() { + return new BukkitInventory(((org.bukkit.block.Container) getHandle()).getInventory()); + } + +} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/state/BukkitMobSpawner.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/state/BukkitMobSpawner.java new file mode 100644 index 000000000..458c0ad71 --- /dev/null +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/state/BukkitMobSpawner.java @@ -0,0 +1,128 @@ +package com.dfsek.terra.bukkit.world.block.state; + +import com.dfsek.terra.api.platform.block.state.MobSpawner; +import com.dfsek.terra.api.platform.block.state.SerialState; +import com.dfsek.terra.api.platform.world.entity.EntityType; +import com.dfsek.terra.bukkit.world.entity.BukkitEntityType; +import org.bukkit.block.CreatureSpawner; +import org.jetbrains.annotations.NotNull; + +public class BukkitMobSpawner extends BukkitBlockState implements MobSpawner { + protected BukkitMobSpawner(CreatureSpawner block) { + super(block); + } + + @Override + public EntityType getSpawnedType() { + return new BukkitEntityType(((CreatureSpawner) getHandle()).getSpawnedType()); + } + + @Override + public void setSpawnedType(@NotNull EntityType creatureType) { + ((CreatureSpawner) getHandle()).setSpawnedType(((BukkitEntityType) creatureType).getHandle()); + } + + @Override + public int getDelay() { + return ((CreatureSpawner) getHandle()).getDelay(); + } + + @Override + public void setDelay(int delay) { + ((CreatureSpawner) getHandle()).setDelay(delay); + } + + @Override + public int getMinSpawnDelay() { + return ((CreatureSpawner) getHandle()).getMinSpawnDelay(); + } + + @Override + public void setMinSpawnDelay(int delay) { + ((CreatureSpawner) getHandle()).setMinSpawnDelay(delay); + } + + @Override + public int getMaxSpawnDelay() { + return ((CreatureSpawner) getHandle()).getMaxSpawnDelay(); + } + + @Override + public void setMaxSpawnDelay(int delay) { + ((CreatureSpawner) getHandle()).setMaxSpawnDelay(delay); + } + + @Override + public int getSpawnCount() { + return ((CreatureSpawner) getHandle()).getSpawnCount(); + } + + @Override + public void setSpawnCount(int spawnCount) { + ((CreatureSpawner) getHandle()).setSpawnCount(spawnCount); + } + + @Override + public int getMaxNearbyEntities() { + return ((CreatureSpawner) getHandle()).getMaxNearbyEntities(); + } + + @Override + public void setMaxNearbyEntities(int maxNearbyEntities) { + ((CreatureSpawner) getHandle()).setMaxNearbyEntities(maxNearbyEntities); + } + + @Override + public int getRequiredPlayerRange() { + return ((CreatureSpawner) getHandle()).getRequiredPlayerRange(); + } + + @Override + public void setRequiredPlayerRange(int requiredPlayerRange) { + ((CreatureSpawner) getHandle()).setRequiredPlayerRange(requiredPlayerRange); + } + + @Override + public int getSpawnRange() { + return ((CreatureSpawner) getHandle()).getSpawnRange(); + } + + @Override + public void setSpawnRange(int spawnRange) { + ((CreatureSpawner) getHandle()).setSpawnRange(spawnRange); + } + + @Override + public void applyState(String state) { + SerialState.parse(state).forEach((k, v) -> { + switch(k) { + case "type": + setSpawnedType(new BukkitEntityType(org.bukkit.entity.EntityType.valueOf(v.toUpperCase()))); + return; + case "delay": + setDelay(Integer.parseInt(v)); + return; + case "min_delay": + setMinSpawnDelay(Integer.parseInt(v)); + return; + case "max_delay": + setMaxSpawnDelay(Integer.parseInt(v)); + return; + case "spawn_count": + setSpawnCount(Integer.parseInt(v)); + return; + case "spawn_range": + setSpawnRange(Integer.parseInt(v)); + return; + case "max_nearby": + setMaxNearbyEntities(Integer.parseInt(v)); + return; + case "required_player_range": + setRequiredPlayerRange(Integer.parseInt(v)); + return; + default: + throw new IllegalArgumentException("Invalid property: " + k); + } + }); + } +} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/state/BukkitSign.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/state/BukkitSign.java new file mode 100644 index 000000000..6b90ec18f --- /dev/null +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/state/BukkitSign.java @@ -0,0 +1,35 @@ +package com.dfsek.terra.bukkit.world.block.state; + +import com.dfsek.terra.api.platform.block.state.SerialState; +import com.dfsek.terra.api.platform.block.state.Sign; +import org.jetbrains.annotations.NotNull; + +public class BukkitSign extends BukkitBlockState implements Sign { + protected BukkitSign(org.bukkit.block.Sign block) { + super(block); + } + + @Override + public @NotNull String[] getLines() { + return ((org.bukkit.block.Sign) getHandle()).getLines(); + } + + @Override + public @NotNull String getLine(int index) throws IndexOutOfBoundsException { + return ((org.bukkit.block.Sign) getHandle()).getLine(index); + } + + @Override + public void setLine(int index, @NotNull String line) throws IndexOutOfBoundsException { + ((org.bukkit.block.Sign) getHandle()).setLine(index, line); + } + + + @Override + public void applyState(String state) { + SerialState.parse(state).forEach((k, v) -> { + if(!v.startsWith("text")) throw new IllegalArgumentException("Invalid property: " + k); + setLine(Integer.parseInt(k) + 1, v.substring(4)); + }); + } +} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/entity/BukkitEntityType.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/entity/BukkitEntityType.java new file mode 100644 index 000000000..58732bada --- /dev/null +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/entity/BukkitEntityType.java @@ -0,0 +1,16 @@ +package com.dfsek.terra.bukkit.world.entity; + +import com.dfsek.terra.api.platform.world.entity.EntityType; + +public class BukkitEntityType implements EntityType { + private final org.bukkit.entity.EntityType delegate; + + public BukkitEntityType(org.bukkit.entity.EntityType delegate) { + this.delegate = delegate; + } + + @Override + public org.bukkit.entity.EntityType getHandle() { + return delegate; + } +} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/inventory/BukkitInventory.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/inventory/BukkitInventory.java new file mode 100644 index 000000000..f567bff01 --- /dev/null +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/inventory/BukkitInventory.java @@ -0,0 +1,33 @@ +package com.dfsek.terra.bukkit.world.inventory; + +import com.dfsek.terra.api.platform.inventory.Inventory; +import com.dfsek.terra.api.platform.inventory.ItemStack; + +public class BukkitInventory implements Inventory { + private final org.bukkit.inventory.Inventory delegate; + + public BukkitInventory(org.bukkit.inventory.Inventory delegate) { + this.delegate = delegate; + } + + @Override + public int getSize() { + return delegate.getSize(); + } + + @Override + public ItemStack getItem(int slot) { + org.bukkit.inventory.ItemStack itemStack = delegate.getItem(slot); + return itemStack == null ? null : new BukkitItemStack(itemStack); + } + + @Override + public void setItem(int slot, ItemStack newStack) { + delegate.setItem(slot, ((BukkitItemStack) newStack).getHandle()); + } + + @Override + public org.bukkit.inventory.Inventory getHandle() { + return delegate; + } +} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/inventory/BukkitItemMeta.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/inventory/BukkitItemMeta.java new file mode 100644 index 000000000..a8bc30131 --- /dev/null +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/inventory/BukkitItemMeta.java @@ -0,0 +1,41 @@ +package com.dfsek.terra.bukkit.world.inventory; + +import com.dfsek.terra.api.platform.inventory.item.Enchantment; +import com.dfsek.terra.api.platform.inventory.item.ItemMeta; +import com.dfsek.terra.bukkit.world.BukkitAdapter; +import com.dfsek.terra.bukkit.world.inventory.meta.BukkitDamageable; +import com.dfsek.terra.bukkit.world.inventory.meta.BukkitEnchantment; +import org.bukkit.inventory.meta.Damageable; + +import java.util.HashMap; +import java.util.Map; + +public class BukkitItemMeta implements ItemMeta { + private final org.bukkit.inventory.meta.ItemMeta delegate; + + protected BukkitItemMeta(org.bukkit.inventory.meta.ItemMeta delegate) { + this.delegate = delegate; + } + + public static BukkitItemMeta newInstance(org.bukkit.inventory.meta.ItemMeta delegate) { + if(delegate instanceof Damageable) return new BukkitDamageable((Damageable) delegate); + return new BukkitItemMeta(delegate); + } + + @Override + public org.bukkit.inventory.meta.ItemMeta getHandle() { + return delegate; + } + + @Override + public Map getEnchantments() { + Map map = new HashMap<>(); + delegate.getEnchants().forEach((enchantment, integer) -> map.put(BukkitAdapter.adapt(enchantment), integer)); + return map; + } + + @Override + public void addEnchantment(Enchantment enchantment, int level) { + delegate.addEnchant(((BukkitEnchantment) enchantment).getHandle(), level, true); + } +} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/inventory/BukkitItemStack.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/inventory/BukkitItemStack.java new file mode 100644 index 000000000..5d94c45c5 --- /dev/null +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/inventory/BukkitItemStack.java @@ -0,0 +1,56 @@ +package com.dfsek.terra.bukkit.world.inventory; + +import com.dfsek.terra.api.platform.block.MaterialData; +import com.dfsek.terra.api.platform.inventory.ItemStack; +import com.dfsek.terra.api.platform.inventory.item.ItemMeta; +import com.dfsek.terra.bukkit.world.block.BukkitMaterialData; + +public class BukkitItemStack implements ItemStack { + private org.bukkit.inventory.ItemStack delegate; + + public BukkitItemStack(org.bukkit.inventory.ItemStack delegate) { + this.delegate = delegate; + } + + @Override + public int getAmount() { + return delegate.getAmount(); + } + + @Override + public void setAmount(int i) { + delegate.setAmount(i); + } + + @Override + public MaterialData getType() { + return new BukkitMaterialData(delegate.getType()); + } + + @Override + public ItemStack clone() { + BukkitItemStack clone; + try { + clone = (BukkitItemStack) super.clone(); + clone.delegate = delegate.clone(); + } catch(CloneNotSupportedException e) { + throw new Error(e); + } + return clone; + } + + @Override + public ItemMeta getItemMeta() { + return BukkitItemMeta.newInstance(delegate.getItemMeta()); + } + + @Override + public void setItemMeta(ItemMeta meta) { + delegate.setItemMeta(((BukkitItemMeta) meta).getHandle()); + } + + @Override + public org.bukkit.inventory.ItemStack getHandle() { + return delegate; + } +} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/inventory/meta/BukkitDamageable.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/inventory/meta/BukkitDamageable.java new file mode 100644 index 000000000..0c2ba018f --- /dev/null +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/inventory/meta/BukkitDamageable.java @@ -0,0 +1,26 @@ +package com.dfsek.terra.bukkit.world.inventory.meta; + +import com.dfsek.terra.api.platform.inventory.item.Damageable; +import com.dfsek.terra.bukkit.world.inventory.BukkitItemMeta; +import org.bukkit.inventory.meta.ItemMeta; + +public class BukkitDamageable extends BukkitItemMeta implements Damageable { + public BukkitDamageable(org.bukkit.inventory.meta.Damageable delegate) { + super((ItemMeta) delegate); + } + + @Override + public int getDamage() { + return ((org.bukkit.inventory.meta.Damageable) getHandle()).getDamage(); + } + + @Override + public void setDamage(int damage) { + ((org.bukkit.inventory.meta.Damageable) getHandle()).setDamage(damage); + } + + @Override + public boolean hasDamage() { + return ((org.bukkit.inventory.meta.Damageable) getHandle()).hasDamage(); + } +} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/inventory/meta/BukkitEnchantment.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/inventory/meta/BukkitEnchantment.java new file mode 100644 index 000000000..577414c28 --- /dev/null +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/inventory/meta/BukkitEnchantment.java @@ -0,0 +1,38 @@ +package com.dfsek.terra.bukkit.world.inventory.meta; + +import com.dfsek.terra.api.platform.inventory.ItemStack; +import com.dfsek.terra.api.platform.inventory.item.Enchantment; +import com.dfsek.terra.bukkit.world.inventory.BukkitItemStack; + +public class BukkitEnchantment implements Enchantment { + private final org.bukkit.enchantments.Enchantment delegate; + + public BukkitEnchantment(org.bukkit.enchantments.Enchantment delegate) { + this.delegate = delegate; + } + + @Override + public org.bukkit.enchantments.Enchantment getHandle() { + return delegate; + } + + @Override + public boolean canEnchantItem(ItemStack itemStack) { + return delegate.canEnchantItem(((BukkitItemStack) itemStack).getHandle()); + } + + @Override + public String getID() { + return delegate.getKey().toString(); + } + + @Override + public boolean conflictsWith(Enchantment other) { + return delegate.conflictsWith(((BukkitEnchantment) other).getHandle()); + } + + @Override + public int getMaxLevel() { + return delegate.getMaxLevel(); + } +} diff --git a/platforms/bukkit/src/main/resources/config.yml b/platforms/bukkit/src/main/resources/config.yml new file mode 100644 index 000000000..adb7d8522 --- /dev/null +++ b/platforms/bukkit/src/main/resources/config.yml @@ -0,0 +1,13 @@ +debug: false +data-save: PT6M +language: "en_us" +dump-default: true +biome-search-resolution: 4 +cache: + carver: 512 + structure: 32 + sampler: 128 +master-disable: + caves: false +script: + max-recursion: 1000 \ No newline at end of file diff --git a/src/main/resources/lang/afr_sa.yml b/platforms/bukkit/src/main/resources/lang/afr_sa.yml similarity index 100% rename from src/main/resources/lang/afr_sa.yml rename to platforms/bukkit/src/main/resources/lang/afr_sa.yml diff --git a/src/main/resources/lang/de_de.yml b/platforms/bukkit/src/main/resources/lang/de_de.yml similarity index 100% rename from src/main/resources/lang/de_de.yml rename to platforms/bukkit/src/main/resources/lang/de_de.yml diff --git a/src/main/resources/lang/en_us.yml b/platforms/bukkit/src/main/resources/lang/en_us.yml similarity index 98% rename from src/main/resources/lang/en_us.yml rename to platforms/bukkit/src/main/resources/lang/en_us.yml index 1e3d5f5f3..048e36e0f 100644 --- a/src/main/resources/lang/en_us.yml +++ b/platforms/bukkit/src/main/resources/lang/en_us.yml @@ -12,7 +12,7 @@ command: world: "This command must be executed in a Terra world!" reload: "Reloaded Terra config." reload-error: "Errors occurred while reloading Terra configurations. See logs for more information." - version: "This server is running Terra version \"%1$s\", implementing Gaea version \"%2$s\"" + version: "This server is running Terra version \"%1$s\", on platform \"%2$s\"" main-menu: - "--------------------Terra--------------------" - "reload - Reload configuration data" diff --git a/src/main/resources/lang/es.yml b/platforms/bukkit/src/main/resources/lang/es.yml similarity index 100% rename from src/main/resources/lang/es.yml rename to platforms/bukkit/src/main/resources/lang/es.yml diff --git a/platforms/bukkit/src/main/resources/lang/it_it.yml b/platforms/bukkit/src/main/resources/lang/it_it.yml new file mode 100644 index 000000000..09237b315 --- /dev/null +++ b/platforms/bukkit/src/main/resources/lang/it_it.yml @@ -0,0 +1,121 @@ +enable: + - "Se ti piace Terra, per favore considera di sostenere il progetto su Patreon!" + - "Avrai accesso a funzionalità sperimentali prima che vengano rilasciate!" + - "Sostieni il progetto qui: https://www.patreon.com/dfsek" +disable: + - "Grazie per aver usato Terra!" +command: + debug-only: "Questo comando deve essere usato con la modalità debug attivata!" + player-only: "Solo i giocatori possono eseguire questo comando!" + invalid: "Comando invalido. (%1$s argomenti previsti, %2$s trovati)." + players-only: "Solo i giocatori possono eseguire questo comando!" + world: "Questo comando può solo essere eseguito in un mondo creato da Terra!" + reload: "Configurazione Terra ricaricata." + reload-error: "Si sono verificati errori durante il ricaricamento delle configurazioni Terra. Vedere i log per ulteriori informazioni." + version: "Questo server sta usando la versione \"%1$s\" Terra, sulla piattaforma \"%2$s\"" + main-menu: + - "--------------------Terra--------------------" + - "reload - Ricarica i dati di configurazione" + - "biome - Ottieni il bioma attuale" + - "ore - Genera una vena minerale davanti a te (per fare debug)" + - "save-data - Salva i dati sulla popolazione" + - "structure - Carica ed esporta strutture" + - "profile - Opzioni dell'analizzatore" + - "image - Opzioni immagine / menu" + biome: + biome-found: "Trovato un bioma alle coordinate (%1$s, %2$s)" + unable-to-locate: "Ricerca bioma fallita." + invalid-radius: "Raggio invalido: \"%s\"" + invalid: "ID bioma invalido: \"%s\"" + in: "Tu sei nel bioma \"%s\"" + packs: + main: "Pacchetti di configurazione installati:" + pack: " - %1$s v%3$s (autore: %2$s)" + none: "Nessun pacchetto di configurazione è installato." + ore: + main-menu: + - "---------------Terra/ore---------------" + - "Genera una vena di minerale nel blocco che stai guardando." + out-of-range: "Blocco fuori portata" + invalid-ore: "Ricerca minerale \"%s\" fallita!" + geometry: + main-menu: + - "---------------Terra/geometry----------------" + - "Vari comandi di debug della geometria voxel" + - "sphere - Genera una sfera" + - "deformsphere - Genera una sfera deformata" + - "tube - Genera un tubo" + deform: + invalid-radius: "Raggio non valido: \"%s\"" + invalid-deform: "Deformazione non valida: \"%s\"" + invalid-frequency: "Frequenza non valida: \"%s\"" + sphere: + invalid-radius: "Raggio non valido: \"%s\"" + tube: + invalid-radius: "Raggio non valido: \"%s\"" + image: + main-menu: + - "---------------Terra/image---------------" + - "render - Renderizza un'immagine con una data larghezza e altezza, che può essere successivamente importata come mondo." + - "gui - Apri il menu di debug (deve essere abilitato nella configurazione)" + gui: + main-menu: + - "-------------Terra/image/gui-------------" + - "raw - Apri il menu con dati grezzi sui biomi" + - "step - Riesegui il rendering dei dati per mostrare i bordi più chiaramente" + debug: "La modalità di debug deve essere abilitata per utilizzare la GUI di debug! La GUI di debug NON È SICURA PER LA PRODUZIONE!" + render: + save: "Immagine salvata come \"%s\"" + error: "Si è verificato un errore durante la generazione dell'immagine!" + profile: + main-menu: + - "---------------Terra/profile---------------" + - "start - Inizia il profiler" + - "stop - Ferma il profiler" + - "query - Recupera i dati del profiler" + - "reset - Resetta i dati del profiler" + reset: "Il profiler è stato resettato." + start: "Il profiler è stato avviato." + stop: "Il profiler è stato fermato." + structure: + main-menu: + - "---------------Terra/structure---------------" + - "export - Esporta la tua selezione attuale di WorldEdit come struttura Terra." + - "load - Carica una struttura Terra" + invalid-radius: "Raggio invalido: \"%s\"" + invalid-rotation: "Rotazione invalida: \"%s\"" + invalid: "ID struttura invalido: \"%s\"" + export: "Struttura salvata come \"%s\"" +world-config: + load: "Caricamento dei valori di configurazione per il mondo \"%s\"..." + not-found: "Configurazione per il mondo \"%s\" non trovata. La configurazione predefinita sarà utilizzata." + using-image: "Caricamento mondo da immagine." + error: "Impossibile caricare la configurazione per il mondo \"%s\"" + done: "Caricamento del mondo \"%1$s\" completato. Tempo trascorso: %2$sms" +config-pack: + loaded: "Pacchetto di configurazione %1$s v%4$s (autore: %3$s) caricato in %2$sms." +config: + loaded: "Caricato %1$s dal file %2$s" + loaded-all: "Caricato %1$s %2$s(s) in %3$sms." + error: + invalid-failover: "Tipo di failover non valido: \"%s\"" + duplicate: "ID duplicato trovato nel file: %s" + file: + - "Errore di configurazione Terra nel file: %1$s" + - "%2$s" + - "Correggilo prima di procedere!" + generic: + - "Si è verificato un errore durante il caricamento delle configurazioni." + - "Per favore, segnalatelo a Terra." +warning: + no-population: "Non sono stati caricati chunk preesistenti. Se è la prima volta che avvii il tuo server con Terra, o se stai creando un nuovo mondo, è normale." +error: + severe-config: "Un grave errore di configurazione ha impedito a Terra di generare correttamente il terreno alle coordinate: %1$s, %2$s. Controlla la tua configurazione per errori. Eventuali errori di configurazione saranno stati segnalati sopra." +debug: + data-save: "Dati sulla popolazione salvati per il mondo \"%s\"" +use-paper: + - "Sembra che tu stia usando Spigot/CraftBukkit." + - "Nonostante Terra &ofunzioni&r su Spigot, delle funzionalità verranno perse. (Terra non è testato su CraftBukkit; nessun supporto verrà dato per la piattaforma CraftBukkit)." + - "Inoltre, Paper offre enormi miglioramenti delle prestazioni rispetto a Spigot e tutti i plug-in di Spigot dovrebbero funzionare con Paper!" + - "Per avere la migliore esperienza con Terra e tutti i tuoi plugin, usa Paper." + - "Scopri di più sul sito web di Paper: https://papermc.io/" \ No newline at end of file diff --git a/src/main/resources/lang/ja_jp.yml b/platforms/bukkit/src/main/resources/lang/ja_jp.yml similarity index 100% rename from src/main/resources/lang/ja_jp.yml rename to platforms/bukkit/src/main/resources/lang/ja_jp.yml diff --git a/platforms/bukkit/src/main/resources/lang/nl_NL.yml b/platforms/bukkit/src/main/resources/lang/nl_NL.yml new file mode 100644 index 000000000..f34f8241e --- /dev/null +++ b/platforms/bukkit/src/main/resources/lang/nl_NL.yml @@ -0,0 +1,122 @@ +enable: + - "Als je Terra leuk vindt, overweeg dan om het project op Patreon te steunen!" + - "Je krijgt toegang tot experimentele functies voordat ze uitgebracht worden!" + - "Steun het project hier: https://www.patreon.com/dfsek" +disable: + - "Bedankt voor het gebruiken van Terra!" +command: + debug-only: "Dit commando moet worden gebruikt met debug-modus ingeschakeld!" + player-only: "Dit commando is alleen voor spelers!" + invalid: "Ongeldig commando. (Verwachte %1$s argumenten, vond er %2$s)." + players-only: "Dit commando is alleen voor spelers." + world: "Dit commando moet worden uitgevoerd in een Terra-wereld!" + reload: "Terra configuratie herladen." + reload-error: "Er zijn fouten opgetreden tijdens het herladen van de Terra-configuratie. Zie de logboeken voor meer informatie." + version: "Deze server draait Terra versie \"%1$s\", op platform \"%2$s\"" + main-menu: + - "--------------------Terra--------------------" + - "reload - Herlaad de configuratie gegevens" + - "biome - Find het huidige bioom (klimaatgebied)" + - "ore - Genereer een ertsader op de locatie waar je heen kijkt (voor debuggen)" + - "save-data - Sla populatie data op" + - "structure - Laad en exporteer constructies" + - "profile - Profiler opties" + - "image - Afbeelding/GUI opties" + biome: + biome-found: "bioom (klimaatgebied) gevonden op (%1$s, %2$s)" + unable-to-locate: "Geen bioom (klimaatgebied) kunnen vinden." + invalid-radius: "Ongeldige straal: \"%s\"" + invalid: "Ongeldig bioom ID: \"%s\"" + in: "Je bent in \"%s\"" + packs: + main: "Momenteel geïnstalleerde configuratiepakketten:" + pack: " - %1$s v%3$s door %2$s" + none: "Er zijn geen configuratiepakketten geïnstalleerd." + ore: + main-menu: + - "---------------Terra/erts---------------" + - "Genereer een ertsader bij het blok waar je naar kijkt." + out-of-range: "Blok buiten bereik" + invalid-ore: "Kan \"%s\" erts niet vinden" + geometry: + main-menu: + - "---------------Terra/geometrie----------------" + - "Diverse voxelgeometrie debug commando's" + - "sphere - Genereer een bol" + - "deformsphere - Genereer een vervormde bol" + - "tube - Genereer een tube" + deform: + invalid-radius: "Ongeldige straal: \"%s\"" + invalid-deform: "Ongeldige vervorming: \"%s\"" + invalid-frequency: "Ongeldige frequentie: \"%s\"" + sphere: + invalid-radius: "Ongeldige straal: \"%s\"" + tube: + invalid-radius: "Ongeldige straal: \"%s\"" + image: + main-menu: + - "---------------Terra/afbeelding---------------" + - "render - Genereer en beeld met een bepaalde breedte en hoogte, deze kan later als een wereld worden geïmporteerd." + - "gui - Open debug GUI (moet worden ingeschakeld in de configuratie)." + gui: + main-menu: + - "-------------Terra/afbeelding/gui-------------" + - "raw - Open GUI met ruwe bioom (klimaatgebied) gegevens" + - "step - Regenereer de gegevens om de grenzen duidelijker te laten zien"" + debug: "De debug-modus moet ingeschakeld zijn om de debug GUI te kunnen gebruiken! Gebruik de debug GUI alleen om te testen, HET IS NIET VEILIG OM TE GEBRUIKEN IN PRODUCTIE!" + render: + save: "Afbeelding opgeslagen als \"%s\"" + error: "Er is een fout opgetreden tijdens het genereren van het beeld!" + profile: + main-menu: + - "---------------Terra/profile---------------" + - "start - Start de profiler" + - "stop - Stop de profiler" + - "query - Haal profiler gegevens op" + - "reset - Resets profiler gegevens" + reset: "Profiler is gereset." + start: "Profiler is gestart." + stop: "Profiler is gestopt." + structure: + main-menu: + - "---------------Terra/constructies---------------" + - "export - Exporteer je huidige WorldEdit selectie als een Terra constructie." + - "load - Laad een Terra constructie" + invalid-radius: "Ongeldige straal: \"%s\"" + invalid-rotation: "Ongeldige rotatie: \"%s\"" + invalid: "Ongeldig constructie ID: \"%s\"" + export: "Constructie opgeslagen naar \"%s\"" +world-config: + load: "Laden van configuratiewaarden voor wereld \"%s\"..." + not-found: "Configuratie voor wereld \"%s\" niet gevonden. Standaard configuratie wordt gebruikt" + using-image: "Laden van wereld uit een afbeelding." + error: "Niet in staat om de configuratie voor wereld %s te laden" + done: "Laden van wereld \"%1$s\" compleet. Tijd verstreken: %2$sms" +config-pack: + loaded: "Configuratiepakket %1$s v%4$s door %3$s geladen in %2$sms." +config: + loaded: "%1$s geladen van bestand %2$s" + loaded-all: "%1$s %2$s(s) in %3$sms geladen." + error: + invalid-failover: "Ongeldig failover type: \"%s\"" + duplicate: "Duplicaat ID gevonden in bestand: %s" + file: + - "Configuratiefout voor Terra-object. Bestand: %1$s" + - "%2$s" + - "Corrigeer dit voordat je verder gaat!" + generic: + - "Er is een fout opgetreden tijdens het laden van de configuraties." + - "Rapporteer dit alsjeblieft aan Terra." +warning: + no-population: "Geen populatie chunks kunnen laden. Als dit de eerste keer is dat de server met Terra gestart wordt is er niks aan de hand." +error: + severe-config: "Een ernstige configuratiefout heeft ervoor gezorgd dat Terra geen terrein op de coördinaten %1$s, %2$s heeft kunnen genereren. Controleer je configuratie op fouten. Eventuele configuratiefouten zullen hierboven zijn gemeld." +debug: + data-save: "Populatie gegevens voor wereld \"%s\" opgeslagen" +use-paper: + - "Het lijkt erop dat je Spigot/CraftBukkit gebruikt." + - "Terra &owerkt&r op Spigot, maar sommige functionaliteit zal verloren gaan. (Terra is niet getest op CraftBukkit; er wordt dus ook geen ondersteuning voor gegeven)." + - "Om het meeste uit Terra te halen, schakel dan over op Paper." + - "Bovendien biedt Paper enorme prestatieverbeteringen ten opzichte van Spigot, en zelfs alle Spigot plugins zouden met Paper moeten werken!" + - "Om de beste ervaring met Terra, en al je andere plugins, te hebben, gebruik dan Paper." + - "Lees meer op de website van Paper: https://papermc.io/" diff --git a/src/main/resources/lang/pl.yml b/platforms/bukkit/src/main/resources/lang/pl.yml similarity index 100% rename from src/main/resources/lang/pl.yml rename to platforms/bukkit/src/main/resources/lang/pl.yml diff --git a/src/main/resources/lang/zh_cn.yml b/platforms/bukkit/src/main/resources/lang/zh_cn.yml similarity index 100% rename from src/main/resources/lang/zh_cn.yml rename to platforms/bukkit/src/main/resources/lang/zh_cn.yml diff --git a/src/main/resources/plugin.yml b/platforms/bukkit/src/main/resources/plugin.yml similarity index 83% rename from src/main/resources/plugin.yml rename to platforms/bukkit/src/main/resources/plugin.yml index 1ea9b8982..0b0a1fafc 100644 --- a/src/main/resources/plugin.yml +++ b/platforms/bukkit/src/main/resources/plugin.yml @@ -1,9 +1,9 @@ name: "Terra" -depend: [ "Gaea" ] -main: "com.dfsek.terra.Terra" +main: "com.dfsek.terra.bukkit.TerraBukkitPlugin" version: "@VERSION@" load: "STARTUP" -api-version: "1.16" +author: dfsek +api-version: "1.13" description: "An insanely powerful free & open-source data-driven world generator." softdepend: [ "WorldEdit" ] commands: diff --git a/platforms/bukkit/src/main/resources/world.yml b/platforms/bukkit/src/main/resources/world.yml new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/platforms/bukkit/src/main/resources/world.yml @@ -0,0 +1 @@ + diff --git a/platforms/fabric/build.gradle.kts b/platforms/fabric/build.gradle.kts new file mode 100644 index 000000000..78d279159 --- /dev/null +++ b/platforms/fabric/build.gradle.kts @@ -0,0 +1,56 @@ +import com.dfsek.terra.configureCommon +import net.fabricmc.loom.LoomGradleExtension +import net.fabricmc.loom.task.RemapJarTask + +buildscript { + repositories { + mavenCentral() + maven { + name = "Fabric" + url = uri("https://maven.fabricmc.net/") + } + } +// dependencies { +// classpath("net.fabricmc:fabric-loom:+") +// } +} + +plugins { + id("fabric-loom").version("0.5.9") + `java-library` +} +//apply(plugin = "fabric-loom") + +configureCommon() + +group = "com.dfsek.terra.fabric" + + +configure { + accessWidener("src/main/resources/terra.accesswidener") +} + +tasks.register("remapShadedJar") { + setProperty("input", file("build/libs/fabric-${version}-shaded.jar")) + setProperty("addNestedDependencies", false) + setProperty("remapAccessWidener", true) +} + +dependencies { + "shadedApi"(project(":common")) + "shadedImplementation"("org.yaml:snakeyaml:1.27") + "shadedImplementation"("com.googlecode.json-simple:json-simple:1.1.1") + + + // To change the versions see the gradle.properties file + "minecraft"("com.mojang:minecraft:1.16.4") + "mappings"("net.fabricmc:yarn:1.16.4+build.6:v2") + "modImplementation"("net.fabricmc:fabric-loader:0.10.6+build.214") + + // Fabric API. This is technically optional, but you probably want it anyway. + "modImplementation"("net.fabricmc.fabric-api:fabric-api:0.25.1+build.416-1.16") + + "compileOnly"("net.fabricmc:sponge-mixin:+") + "annotationProcessor"("net.fabricmc:sponge-mixin:+") + "annotationProcessor"("net.fabricmc:fabric-loom:+") +} \ No newline at end of file diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/TerraFabricPlugin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/TerraFabricPlugin.java new file mode 100644 index 000000000..07a7b0499 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/TerraFabricPlugin.java @@ -0,0 +1,282 @@ +package com.dfsek.terra.fabric; + +import com.dfsek.tectonic.loading.TypeRegistry; +import com.dfsek.terra.TerraWorld; +import com.dfsek.terra.api.GenericLoaders; +import com.dfsek.terra.api.language.Language; +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.block.MaterialData; +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.api.transform.MapTransform; +import com.dfsek.terra.api.transform.NotNullValidator; +import com.dfsek.terra.api.transform.Transformer; +import com.dfsek.terra.biome.UserDefinedBiome; +import com.dfsek.terra.config.base.ConfigPack; +import com.dfsek.terra.config.base.PluginConfig; +import com.dfsek.terra.config.lang.LangUtil; +import com.dfsek.terra.fabric.inventory.FabricItemHandle; +import com.dfsek.terra.fabric.mixin.GeneratorTypeAccessor; +import com.dfsek.terra.fabric.world.FabricBiome; +import com.dfsek.terra.fabric.world.FabricWorldHandle; +import com.dfsek.terra.fabric.world.TerraBiomeSource; +import com.dfsek.terra.fabric.world.features.PopulatorFeature; +import com.dfsek.terra.fabric.world.generator.FabricChunkGeneratorWrapper; +import com.dfsek.terra.registry.ConfigRegistry; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.ModInitializer; +import net.fabricmc.loader.api.FabricLoader; +import net.minecraft.block.Blocks; +import net.minecraft.client.world.GeneratorType; +import net.minecraft.util.Identifier; +import net.minecraft.util.registry.BuiltinRegistries; +import net.minecraft.util.registry.Registry; +import net.minecraft.util.registry.RegistryKey; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.biome.BiomeEffects; +import net.minecraft.world.biome.GenerationSettings; +import net.minecraft.world.biome.SpawnSettings; +import net.minecraft.world.gen.GenerationStep; +import net.minecraft.world.gen.chunk.ChunkGenerator; +import net.minecraft.world.gen.chunk.ChunkGeneratorSettings; +import net.minecraft.world.gen.decorator.Decorator; +import net.minecraft.world.gen.decorator.NopeDecoratorConfig; +import net.minecraft.world.gen.feature.ConfiguredFeature; +import net.minecraft.world.gen.feature.ConfiguredFeatures; +import net.minecraft.world.gen.feature.DefaultBiomeFeatures; +import net.minecraft.world.gen.feature.DefaultFeatureConfig; +import net.minecraft.world.gen.feature.FeatureConfig; +import net.minecraft.world.gen.surfacebuilder.SurfaceBuilder; +import net.minecraft.world.gen.surfacebuilder.TernarySurfaceConfig; +import org.apache.commons.io.FileUtils; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; + +public class TerraFabricPlugin implements TerraPlugin, ModInitializer { + + private final Map worldMap = new HashMap<>(); + private static TerraFabricPlugin instance; + + public static TerraFabricPlugin getInstance() { + return instance; + } + + public static final PopulatorFeature POPULATOR_FEATURE = new PopulatorFeature(DefaultFeatureConfig.CODEC); + public static final ConfiguredFeature POPULATOR_CONFIGURED_FEATURE = POPULATOR_FEATURE.configure(FeatureConfig.DEFAULT).decorate(Decorator.NOPE.configure(NopeDecoratorConfig.INSTANCE)); + + private final GenericLoaders genericLoaders = new GenericLoaders(this); + private final Logger logger = Logger.getLogger("Terra"); + private final ItemHandle itemHandle = new FabricItemHandle(); + private final WorldHandle worldHandle = new FabricWorldHandle(); + private final ConfigRegistry registry = new ConfigRegistry(); + private File config; + private static final Transformer> TREE_TRANSFORMER = new Transformer.Builder>() + .addTransform(TerraFabricPlugin::getFeature) + .addTransform(new MapTransform>() + .add("BROWN_MUSHROOM", ConfiguredFeatures.BROWN_MUSHROOM_GIANT) + .add("RED_MUSHROOM", ConfiguredFeatures.RED_MUSHROOM_GIANT) + .add("JUNGLE", ConfiguredFeatures.MEGA_JUNGLE_TREE) + .add("JUNGLE_COCOA", ConfiguredFeatures.JUNGLE_TREE) + .add("LARGE_OAK", ConfiguredFeatures.FANCY_OAK) + .add("LARGE_SPRUCE", ConfiguredFeatures.PINE) + .add("SMALL_JUNGLE", ConfiguredFeatures.JUNGLE_TREE) + .add("SWAMP_OAK", ConfiguredFeatures.SWAMP_TREE) + .add("TALL_BIRCH", ConfiguredFeatures.BIRCH_TALL) + .add("ACACIA", ConfiguredFeatures.ACACIA) + .add("BIRCH", ConfiguredFeatures.BIRCH) + .add("DARK_OAK", ConfiguredFeatures.DARK_OAK) + .add("OAK", ConfiguredFeatures.OAK) + .add("CHORUS_PLANT", ConfiguredFeatures.CHORUS_PLANT) + .add("SPRUCE", ConfiguredFeatures.SPRUCE) + .add("JUNGLE_BUSH", ConfiguredFeatures.JUNGLE_BUSH) + .add("MEGA_SPRUCE", ConfiguredFeatures.MEGA_SPRUCE) + .add("CRIMSON_FUNGUS", ConfiguredFeatures.CRIMSON_FUNGI) + .add("WARPED_FUNGUS", ConfiguredFeatures.WARPED_FUNGI)).build(); + private final PluginConfig plugin = new PluginConfig(); + + @Override + public WorldHandle getWorldHandle() { + return worldHandle; + } + + @Override + public boolean isEnabled() { + return false; + } + + @Override + public TerraWorld getWorld(World world) { + return worldMap.computeIfAbsent(world.getSeed(), w -> { + logger.info("Loading world " + w); + return new TerraWorld(world, getRegistry().get("DEFAULT"), this); + }); + } + + @Override + public Logger getLogger() { + return logger; + } + + @Override + public PluginConfig getTerraConfig() { + return plugin; + } + + @Override + public File getDataFolder() { + return config; + } + + @Override + public boolean isDebug() { + return false; + } + + @Override + public Language getLanguage() { + try { + return new Language(new File(getDataFolder(), "lang/en_us.yml")); + } catch(IOException e) { + throw new IllegalArgumentException(); + } + } + + @Override + public ConfigRegistry getRegistry() { + return registry; + } + + @Override + public void reload() { + + } + + @Override + public ItemHandle getItemHandle() { + return itemHandle; + } + + @Override + public void saveDefaultConfig() { + try(InputStream stream = getClass().getResourceAsStream("/config.yml")) { + File configFile = new File(getDataFolder(), "config.yml"); + if(!configFile.exists()) FileUtils.copyInputStreamToFile(stream, configFile); + } catch(IOException e) { + e.printStackTrace(); + } + } + + @Override + public String platformName() { + return "Fabric"; + } + + Transformer biomeFixer = new Transformer.Builder() + .addTransform(id -> BuiltinRegistries.BIOME.get(Identifier.tryParse(id)), new NotNullValidator<>()) + .addTransform(id -> BuiltinRegistries.BIOME.get(Identifier.tryParse("minecraft:" + id.toLowerCase())), new NotNullValidator<>()).build(); + + @Override + public void register(TypeRegistry registry) { + genericLoaders.register(registry); + registry + .registerLoader(BlockData.class, (t, o, l) -> worldHandle.createBlockData((String) o)) + .registerLoader(MaterialData.class, (t, o, l) -> worldHandle.createMaterialData((String) o)) + .registerLoader(com.dfsek.terra.api.platform.world.Biome.class, (t, o, l) -> new FabricBiome(biomeFixer.translate((String) o))); + } + + public static String createBiomeID(ConfigPack pack, UserDefinedBiome biome) { + return pack.getTemplate().getID().toLowerCase() + "/" + biome.getID().toLowerCase(); + } + + private Biome createBiome(UserDefinedBiome biome) { + SpawnSettings.Builder spawnSettings = new SpawnSettings.Builder(); + DefaultBiomeFeatures.addFarmAnimals(spawnSettings); + DefaultBiomeFeatures.addMonsters(spawnSettings, 95, 5, 100); + + Biome vanilla = ((FabricBiome) biome.getVanillaBiome()).getHandle(); + + GenerationSettings.Builder generationSettings = new GenerationSettings.Builder(); + generationSettings.surfaceBuilder(SurfaceBuilder.DEFAULT.withConfig(new TernarySurfaceConfig(Blocks.GRASS_BLOCK.getDefaultState(), Blocks.DIRT.getDefaultState(), Blocks.GRAVEL.getDefaultState()))); // It needs a surfacebuilder, even though we dont use it. + generationSettings.feature(GenerationStep.Feature.VEGETAL_DECORATION, POPULATOR_CONFIGURED_FEATURE); + + BiomeEffects.Builder effects = new BiomeEffects.Builder() + .waterColor(vanilla.getWaterColor()) + .waterFogColor(vanilla.getWaterFogColor()) + .fogColor(vanilla.getFogColor()) + .skyColor(vanilla.getSkyColor()) + .grassColorModifier(vanilla.getEffects().getGrassColorModifier()); + if(vanilla.getEffects().getGrassColor().isPresent()) { + effects.grassColor(vanilla.getEffects().getGrassColor().get()); + } + if(vanilla.getEffects().getFoliageColor().isPresent()) { + effects.foliageColor(vanilla.getEffects().getFoliageColor().get()); + } + + return (new Biome.Builder()) + .precipitation(vanilla.getPrecipitation()) + .category(vanilla.getCategory()) + .depth(vanilla.getDepth()) + .scale(vanilla.getScale()) + .temperature(vanilla.getTemperature()) + .downfall(vanilla.getDownfall()) + .effects(vanilla.getEffects()) // TODO: configurable + .spawnSettings(spawnSettings.build()) + .generationSettings(generationSettings.build()) + .build(); + } + + private static ConfiguredFeature getFeature(String name) { + Class featuresClass = ConfiguredFeatures.class; + Field feature; + try { + feature = featuresClass.getField(name); + return (ConfiguredFeature) feature.get(null); + } catch(NoSuchFieldException | IllegalAccessException e) { + throw new IllegalArgumentException("No such feature: " + name); + } + } + + @Override + public void onInitialize() { + logger.setLevel(Level.INFO); + instance = this; + + ((FabricWorldHandle) worldHandle).setTreeTransformer(TREE_TRANSFORMER); + + config = new File(FabricLoader.getInstance().getConfigDir().toFile(), "Terra"); + saveDefaultConfig(); + plugin.load(this); + LangUtil.load("en_us", this); + logger.info("Initializing Terra..."); + + registry.loadAll(this); + + Registry.register(Registry.FEATURE, new Identifier("terra", "flora_populator"), POPULATOR_FEATURE); + RegistryKey> floraKey = RegistryKey.of(Registry.CONFIGURED_FEATURE_WORLDGEN, new Identifier("terra", "flora_populator")); + Registry.register(BuiltinRegistries.CONFIGURED_FEATURE, floraKey.getValue(), POPULATOR_CONFIGURED_FEATURE); + + registry.forEach(pack -> pack.getBiomeRegistry().forEach(biome -> Registry.register(BuiltinRegistries.BIOME, new Identifier("terra", createBiomeID(pack, biome)), createBiome(biome)))); // Register all Terra biomes. + Registry.register(Registry.CHUNK_GENERATOR, new Identifier("terra:terra"), FabricChunkGeneratorWrapper.CODEC); + Registry.register(Registry.BIOME_SOURCE, new Identifier("terra:terra"), TerraBiomeSource.CODEC); + + if(FabricLoader.getInstance().getEnvironmentType().equals(EnvType.CLIENT)) { + GeneratorTypeAccessor.getValues().add(new GeneratorType("terra") { + @Override + protected ChunkGenerator getChunkGenerator(Registry biomeRegistry, Registry chunkGeneratorSettingsRegistry, long seed) { + ConfigPack pack = registry.get("DEFAULT"); + return new FabricChunkGeneratorWrapper(new TerraBiomeSource(biomeRegistry, seed, pack), seed, pack); + } + }); + } + + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/inventory/FabricItemHandle.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/inventory/FabricItemHandle.java new file mode 100644 index 000000000..afe191821 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/inventory/FabricItemHandle.java @@ -0,0 +1,18 @@ +package com.dfsek.terra.fabric.inventory; + +import com.dfsek.terra.api.platform.block.MaterialData; +import com.dfsek.terra.api.platform.handle.ItemHandle; +import com.dfsek.terra.api.platform.inventory.ItemStack; +import com.dfsek.terra.api.platform.inventory.item.Enchantment; + +public class FabricItemHandle implements ItemHandle { + @Override + public ItemStack newItemStack(MaterialData material, int amount) { + return null; + } + + @Override + public Enchantment getEnchantment(String id) { + return null; + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/inventory/FabricItemStack.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/inventory/FabricItemStack.java new file mode 100644 index 000000000..c6caae3e3 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/inventory/FabricItemStack.java @@ -0,0 +1,44 @@ +package com.dfsek.terra.fabric.inventory; + +import com.dfsek.terra.api.platform.block.MaterialData; +import com.dfsek.terra.api.platform.inventory.ItemStack; +import com.dfsek.terra.api.platform.inventory.item.ItemMeta; + +public class FabricItemStack implements ItemStack { + net.minecraft.item.ItemStack delegate; + + @Override + public int getAmount() { + return delegate.getCount(); + } + + @Override + public void setAmount(int i) { + delegate.setCount(i); + } + + @Override + public MaterialData getType() { + return null; + } + + @Override + public ItemStack clone() { + return null; + } + + @Override + public ItemMeta getItemMeta() { + return null; + } + + @Override + public void setItemMeta(ItemMeta meta) { + + } + + @Override + public Object getHandle() { + return delegate; + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/GeneratorTypeAccessor.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/GeneratorTypeAccessor.java new file mode 100644 index 000000000..e251ebd59 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/GeneratorTypeAccessor.java @@ -0,0 +1,15 @@ +package com.dfsek.terra.fabric.mixin; + +import net.minecraft.client.world.GeneratorType; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import java.util.List; + +@Mixin(GeneratorType.class) +public interface GeneratorTypeAccessor { + @Accessor("VALUES") + static List getValues() { + throw new AssertionError(); + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/FabricAdapters.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/FabricAdapters.java new file mode 100644 index 000000000..a65e456d5 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/FabricAdapters.java @@ -0,0 +1,14 @@ +package com.dfsek.terra.fabric.world; + +import com.dfsek.terra.api.math.vector.Vector3; +import net.minecraft.util.math.BlockPos; + +public final class FabricAdapters { + public static BlockPos fromVector(Vector3 v) { + return new BlockPos(v.getBlockX(), v.getBlockY(), v.getBlockZ()); + } + + public static Vector3 toVector(BlockPos pos) { + return new Vector3(pos.getX(), pos.getY(), pos.getZ()); + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/FabricBiome.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/FabricBiome.java new file mode 100644 index 000000000..99dab1c2c --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/FabricBiome.java @@ -0,0 +1,17 @@ +package com.dfsek.terra.fabric.world; + +import com.dfsek.terra.api.platform.world.Biome; + +public class FabricBiome implements Biome { + private final net.minecraft.world.biome.Biome delegate; + + public FabricBiome(net.minecraft.world.biome.Biome delegate) { + this.delegate = delegate; + } + + + @Override + public net.minecraft.world.biome.Biome getHandle() { + return delegate; + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/FabricTree.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/FabricTree.java new file mode 100644 index 000000000..4006afd73 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/FabricTree.java @@ -0,0 +1,42 @@ +package com.dfsek.terra.fabric.world; + +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.platform.block.MaterialData; +import com.dfsek.terra.api.platform.world.Tree; +import com.dfsek.terra.fabric.TerraFabricPlugin; +import com.dfsek.terra.fabric.world.generator.FabricChunkGenerator; +import com.dfsek.terra.fabric.world.handles.world.FabricWorldAccess; +import com.dfsek.terra.util.MaterialSet; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.StructureWorldAccess; +import net.minecraft.world.gen.chunk.ChunkGenerator; +import net.minecraft.world.gen.feature.ConfiguredFeature; + +import java.util.Random; +import java.util.Set; + +public class FabricTree implements Tree { + private final ConfiguredFeature delegate; + + public FabricTree(ConfiguredFeature delegate) { + this.delegate = delegate; + } + + @Override + public boolean plant(Location l, Random r) { + FabricWorldAccess fabricWorldAccess = ((FabricWorldAccess) l.getWorld()); + ChunkGenerator generatorWrapper = ((FabricChunkGenerator) fabricWorldAccess.getGenerator()).getHandle(); + return delegate.generate((StructureWorldAccess) fabricWorldAccess.getHandle(), generatorWrapper, r, new BlockPos(l.getBlockX(), l.getBlockY(), l.getBlockZ())); + } + + @Override + public Set getSpawnable() { + return MaterialSet.get(TerraFabricPlugin.getInstance().getWorldHandle().createMaterialData("minecraft:grass_block"), + TerraFabricPlugin.getInstance().getWorldHandle().createMaterialData("minecraft:podzol")); + } + + @Override + public ConfiguredFeature getHandle() { + return delegate; + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/FabricWorldHandle.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/FabricWorldHandle.java new file mode 100644 index 000000000..452a55e8a --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/FabricWorldHandle.java @@ -0,0 +1,84 @@ +package com.dfsek.terra.fabric.world; + +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.handle.WorldHandle; +import com.dfsek.terra.api.platform.world.Tree; +import com.dfsek.terra.api.platform.world.entity.EntityType; +import com.dfsek.terra.api.transform.Transformer; +import com.dfsek.terra.fabric.world.block.FabricBlockData; +import com.dfsek.terra.fabric.world.block.FabricMaterialData; +import com.dfsek.terra.fabric.world.block.data.FabricMultipleFacing; +import com.dfsek.terra.fabric.world.block.data.FabricOrientable; +import com.dfsek.terra.fabric.world.block.data.FabricSlab; +import com.dfsek.terra.fabric.world.block.data.FabricStairs; +import com.dfsek.terra.fabric.world.block.data.FabricWaterlogged; +import com.mojang.brigadier.StringReader; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import net.minecraft.block.BlockState; +import net.minecraft.command.argument.BlockArgumentParser; +import net.minecraft.state.property.Properties; +import net.minecraft.world.gen.feature.ConfiguredFeature; + +import java.util.Arrays; + +public class FabricWorldHandle implements WorldHandle { + private Transformer> treeTransformer; + + public void setTreeTransformer(Transformer> treeTransformer) { + this.treeTransformer = treeTransformer; + } + + @Override + public void setBlockData(Block block, BlockData data, boolean physics) { + block.setBlockData(data, physics); + } + + @Override + public BlockData getBlockData(Block block) { + return block.getBlockData(); + } + + @Override + public MaterialData getType(Block block) { + return block.getType(); + } + + @Override + public FabricBlockData createBlockData(String data) { + BlockArgumentParser parser = new BlockArgumentParser(new StringReader(data), true); + try { + BlockState state = parser.parse(true).getBlockState(); + if(state == null) throw new IllegalArgumentException("Invalid data: " + data); + + if(state.contains(Properties.STAIR_SHAPE)) return new FabricStairs(state); + + if(state.contains(Properties.SLAB_TYPE)) return new FabricSlab(state); + + if(state.contains(Properties.AXIS)) return new FabricOrientable(state); + + if(state.getProperties().containsAll(Arrays.asList(Properties.NORTH, Properties.SOUTH, Properties.EAST, Properties.WEST))) + return new FabricMultipleFacing(state); + if(state.contains(Properties.WATERLOGGED)) return new FabricWaterlogged(state); + return new FabricBlockData(state); + } catch(CommandSyntaxException e) { + throw new IllegalArgumentException(e); + } + } + + @Override + public MaterialData createMaterialData(String data) { + return new FabricMaterialData(createBlockData(data).getHandle().getBlock()); + } + + @Override + public Tree getTree(String id) { + return new FabricTree(treeTransformer.translate(id)); + } + + @Override + public EntityType getEntity(String id) { + return null; + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/TerraBiomeSource.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/TerraBiomeSource.java new file mode 100644 index 000000000..529cec805 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/TerraBiomeSource.java @@ -0,0 +1,65 @@ +package com.dfsek.terra.fabric.world; + +import com.dfsek.terra.api.world.generation.GenerationPhase; +import com.dfsek.terra.biome.UserDefinedBiome; +import com.dfsek.terra.biome.grid.master.TerraBiomeGrid; +import com.dfsek.terra.config.base.ConfigPack; +import com.dfsek.terra.fabric.TerraFabricPlugin; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import net.minecraft.util.Identifier; +import net.minecraft.util.registry.Registry; +import net.minecraft.util.registry.RegistryLookupCodec; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.biome.source.BiomeSource; +import net.minecraft.world.gen.feature.StructureFeature; + +import java.util.stream.Collectors; + +public class TerraBiomeSource extends BiomeSource { + public static final Codec PACK_CODEC = (RecordCodecBuilder.create(config -> config.group( + Codec.STRING.fieldOf("pack").forGetter(pack -> pack.getTemplate().getID()) + ).apply(config, config.stable(TerraFabricPlugin.getInstance().getRegistry()::get)))); + public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( + RegistryLookupCodec.of(Registry.BIOME_KEY).forGetter(source -> source.biomeRegistry), + Codec.LONG.fieldOf("seed").stable().forGetter(source -> source.seed), + PACK_CODEC.fieldOf("pack").stable().forGetter(source -> source.pack)) + .apply(instance, instance.stable(TerraBiomeSource::new))); + + private final Registry biomeRegistry; + private final long seed; + private final TerraBiomeGrid grid; + private final ConfigPack pack; + + public TerraBiomeSource(Registry biomes, long seed, ConfigPack pack) { + super(biomes.stream().collect(Collectors.toList())); + this.biomeRegistry = biomes; + this.seed = seed; + this.grid = new TerraBiomeGrid.TerraBiomeGridBuilder(seed, pack, TerraFabricPlugin.getInstance()).build(); + this.pack = pack; + } + + @Override + protected Codec getCodec() { + return CODEC; + } + + @Override + public BiomeSource withSeed(long seed) { + return new TerraBiomeSource(this.biomeRegistry, seed, pack); + } + + @Override + public Biome getBiomeForNoiseGen(int biomeX, int biomeY, int biomeZ) { + UserDefinedBiome biome = (UserDefinedBiome) grid.getBiome(biomeX * 4, biomeZ * 4, GenerationPhase.BASE); + return biomeRegistry.get(new Identifier("terra", TerraFabricPlugin.createBiomeID(pack, biome))); + } + + + @Override + public boolean hasStructureFeature(StructureFeature feature) { + return false; + } + + +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/FabricBlock.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/FabricBlock.java new file mode 100644 index 000000000..2b22b99ba --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/FabricBlock.java @@ -0,0 +1,96 @@ +package com.dfsek.terra.fabric.world.block; + +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.platform.block.Block; +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.block.BlockFace; +import com.dfsek.terra.api.platform.block.MaterialData; +import com.dfsek.terra.api.platform.block.state.BlockState; +import com.dfsek.terra.fabric.world.FabricAdapters; +import com.dfsek.terra.fabric.world.handles.world.FabricWorldAccess; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.WorldAccess; + +public class FabricBlock implements Block { + private final Handle delegate; + + public FabricBlock(BlockPos position, WorldAccess worldAccess) { + this.delegate = new Handle(position, worldAccess); + } + + @Override + public void setBlockData(BlockData data, boolean physics) { + delegate.worldAccess.setBlockState(delegate.position, ((FabricBlockData) data).getHandle(), 0, 0); + } + + @Override + public BlockData getBlockData() { + return new FabricBlockData(delegate.worldAccess.getBlockState(delegate.position)); + } + + @Override + public BlockState getState() { + return null; + } + + @Override + public Block getRelative(BlockFace face) { + return getRelative(face, 1); + } + + @Override + public Block getRelative(BlockFace face, int len) { + BlockPos newPos = delegate.position.add(face.getModX() * len, face.getModY() * len, face.getModZ() * len); + return new FabricBlock(newPos, delegate.worldAccess); + } + + @Override + public boolean isEmpty() { + return getBlockData().getMaterial().isAir(); + } + + @Override + public Location getLocation() { + return FabricAdapters.toVector(delegate.position).toLocation(new FabricWorldAccess(delegate.worldAccess)); + } + + @Override + public MaterialData getType() { + return getBlockData().getMaterial(); + } + + @Override + public int getX() { + return delegate.position.getX(); + } + + @Override + public int getZ() { + return delegate.position.getZ(); + } + + @Override + public int getY() { + return delegate.position.getY(); + } + + @Override + public boolean isPassable() { + return isEmpty(); + } + + @Override + public Handle getHandle() { + return delegate; + } + + public static final class Handle { + private final BlockPos position; + private final WorldAccess worldAccess; + + public Handle(BlockPos position, WorldAccess worldAccess) { + this.position = position; + this.worldAccess = worldAccess; + } + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/FabricBlockData.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/FabricBlockData.java new file mode 100644 index 000000000..f7fac5fb4 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/FabricBlockData.java @@ -0,0 +1,42 @@ +package com.dfsek.terra.fabric.world.block; + +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.block.MaterialData; +import net.minecraft.block.BlockState; + +public class FabricBlockData implements BlockData { + protected BlockState delegate; + + public FabricBlockData(BlockState delegate) { + this.delegate = delegate; + } + + @Override + public MaterialData getMaterial() { + return new FabricMaterialData(delegate.getBlock()); + } + + @Override + public boolean matches(MaterialData materialData) { + return ((FabricMaterialData) materialData).getHandle().is(delegate.getBlock()); + } + + @Override + public BlockData clone() { + try { + return (FabricBlockData) super.clone(); + } catch(CloneNotSupportedException e) { + throw new Error(e); + } + } + + @Override + public String getAsString() { + return delegate.toString(); + } + + @Override + public BlockState getHandle() { + return delegate; + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/FabricMaterialData.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/FabricMaterialData.java new file mode 100644 index 000000000..dd9941d03 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/FabricMaterialData.java @@ -0,0 +1,63 @@ +package com.dfsek.terra.fabric.world.block; + +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.block.MaterialData; +import net.minecraft.block.Block; +import net.minecraft.block.Blocks; + +public class FabricMaterialData implements MaterialData { + private final Block delegate; + + public FabricMaterialData(Block delegate) { + this.delegate = delegate; + } + + @Override + public boolean matches(MaterialData other) { + return delegate.equals(((FabricMaterialData) other).getHandle()); + } + + @Override + public boolean matches(BlockData other) { + return delegate.equals(((FabricMaterialData) other.getMaterial()).getHandle()); + } + + @Override + public boolean isSolid() { + return !delegate.is(Blocks.AIR); + } + + @Override + public boolean isAir() { + return delegate.is(Blocks.AIR); // TODO: better impl + } + + @Override + public double getMaxDurability() { + return 0; + } + + @Override + public BlockData createBlockData() { + return new FabricBlockData(delegate.getDefaultState()); + } + + @Override + public Block getHandle() { + return delegate; + } + + + @Override + public int hashCode() { + return delegate.asItem().hashCode(); + } + + @Override + public boolean equals(Object obj) { + if(obj instanceof FabricMaterialData) { + return ((FabricMaterialData) obj).matches(this); + } + return false; + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/data/FabricAnaloguePowerable.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/data/FabricAnaloguePowerable.java new file mode 100644 index 000000000..2e7a55347 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/data/FabricAnaloguePowerable.java @@ -0,0 +1,29 @@ +package com.dfsek.terra.fabric.world.block.data; + +import com.dfsek.terra.api.platform.block.data.AnaloguePowerable; +import com.dfsek.terra.fabric.world.block.FabricBlockData; +import net.minecraft.block.BlockState; + +/** + * None of this actually has implementation, TODO: implement this if we ever end up needing it. + */ +public class FabricAnaloguePowerable extends FabricBlockData implements AnaloguePowerable { + public FabricAnaloguePowerable(BlockState delegate) { + super(delegate); + } + + @Override + public int getMaximumPower() { + return 0; + } + + @Override + public int getPower() { + return 0; + } + + @Override + public void setPower(int power) { + + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/data/FabricEnumAdapter.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/data/FabricEnumAdapter.java new file mode 100644 index 000000000..98f883059 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/data/FabricEnumAdapter.java @@ -0,0 +1,159 @@ +package com.dfsek.terra.fabric.world.block.data; + +import com.dfsek.terra.api.platform.block.Axis; +import com.dfsek.terra.api.platform.block.BlockFace; +import com.dfsek.terra.api.platform.block.data.Bisected; +import com.dfsek.terra.api.platform.block.data.Slab; +import com.dfsek.terra.api.platform.block.data.Stairs; +import net.minecraft.block.enums.BlockHalf; +import net.minecraft.block.enums.SlabType; +import net.minecraft.block.enums.StairShape; +import net.minecraft.util.math.Direction; + +public final class FabricEnumAdapter { + public static Stairs.Shape adapt(StairShape shape) { + switch(shape) { + case OUTER_RIGHT: + return Stairs.Shape.OUTER_RIGHT; + case INNER_RIGHT: + return Stairs.Shape.INNER_RIGHT; + case OUTER_LEFT: + return Stairs.Shape.OUTER_LEFT; + case INNER_LEFT: + return Stairs.Shape.INNER_LEFT; + case STRAIGHT: + return Stairs.Shape.STRAIGHT; + default: + throw new IllegalStateException(); + } + } + + public static Bisected.Half adapt(BlockHalf half) { + switch(half) { + case BOTTOM: + return Bisected.Half.BOTTOM; + case TOP: + return Bisected.Half.TOP; + default: + throw new IllegalStateException(); + } + } + + public static BlockFace adapt(Direction direction) { + switch(direction) { + case DOWN: + return BlockFace.DOWN; + case UP: + return BlockFace.UP; + case WEST: + return BlockFace.WEST; + case EAST: + return BlockFace.EAST; + case NORTH: + return BlockFace.NORTH; + case SOUTH: + return BlockFace.SOUTH; + default: + throw new IllegalStateException(); + } + } + + public static Slab.Type adapt(SlabType type) { + switch(type) { + case BOTTOM: + return Slab.Type.BOTTOM; + case TOP: + return Slab.Type.TOP; + case DOUBLE: + return Slab.Type.DOUBLE; + default: + throw new IllegalStateException(); + } + } + + public static StairShape adapt(Stairs.Shape shape) { + switch(shape) { + case STRAIGHT: + return StairShape.STRAIGHT; + case INNER_LEFT: + return StairShape.INNER_LEFT; + case OUTER_LEFT: + return StairShape.OUTER_LEFT; + case INNER_RIGHT: + return StairShape.INNER_RIGHT; + case OUTER_RIGHT: + return StairShape.OUTER_RIGHT; + default: + throw new IllegalStateException(); + } + } + + public static BlockHalf adapt(Bisected.Half half) { + switch(half) { + case TOP: + return BlockHalf.TOP; + case BOTTOM: + return BlockHalf.BOTTOM; + default: + throw new IllegalStateException(); + } + } + + public static Direction adapt(BlockFace face) { + switch(face) { + case SOUTH: + return Direction.SOUTH; + case NORTH: + return Direction.NORTH; + case EAST: + return Direction.EAST; + case WEST: + return Direction.WEST; + case UP: + return Direction.UP; + case DOWN: + return Direction.DOWN; + default: + throw new IllegalArgumentException(); + } + } + + public static SlabType adapt(Slab.Type type) { + switch(type) { + case DOUBLE: + return SlabType.DOUBLE; + case TOP: + return SlabType.TOP; + case BOTTOM: + return SlabType.BOTTOM; + default: + throw new IllegalStateException(); + } + } + + public static Axis adapt(Direction.Axis axis) { + switch(axis) { + case X: + return Axis.X; + case Y: + return Axis.Y; + case Z: + return Axis.Z; + default: + throw new IllegalStateException(); + } + } + + public static Direction.Axis adapt(Axis axis) { + switch(axis) { + case Z: + return Direction.Axis.Z; + case Y: + return Direction.Axis.Y; + case X: + return Direction.Axis.X; + default: + throw new IllegalStateException(); + } + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/data/FabricMultipleFacing.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/data/FabricMultipleFacing.java new file mode 100644 index 000000000..c4c1bf40f --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/data/FabricMultipleFacing.java @@ -0,0 +1,69 @@ +package com.dfsek.terra.fabric.world.block.data; + +import com.dfsek.terra.api.platform.block.BlockFace; +import com.dfsek.terra.api.platform.block.data.MultipleFacing; +import com.dfsek.terra.fabric.world.block.FabricBlockData; +import net.minecraft.block.BlockState; +import net.minecraft.state.property.Properties; + +import java.util.HashSet; +import java.util.Set; + +public class FabricMultipleFacing extends FabricBlockData implements MultipleFacing { + public FabricMultipleFacing(BlockState delegate) { + super(delegate); + } + + @Override + public Set getFaces() { + Set set = new HashSet<>(); + if(delegate.get(Properties.NORTH)) set.add(BlockFace.NORTH); + if(delegate.get(Properties.SOUTH)) set.add(BlockFace.SOUTH); + if(delegate.get(Properties.EAST)) set.add(BlockFace.EAST); + if(delegate.get(Properties.WEST)) set.add(BlockFace.WEST); + if(delegate.contains(Properties.UP) && delegate.get(Properties.UP)) set.add(BlockFace.UP); + if(delegate.contains(Properties.DOWN) && delegate.get(Properties.DOWN)) set.add(BlockFace.DOWN); + return set; + } + + @Override + public void setFace(BlockFace face, boolean facing) { + switch(face) { + case NORTH: + delegate = delegate.with(Properties.NORTH, facing); + break; + case SOUTH: + delegate = delegate.with(Properties.SOUTH, facing); + break; + case EAST: + delegate = delegate.with(Properties.EAST, facing); + break; + case WEST: + delegate = delegate.with(Properties.WEST, facing); + break; + case UP: + delegate = delegate.with(Properties.UP, facing); + break; + case DOWN: + delegate = delegate.with(Properties.DOWN, facing); + break; + } + } + + @Override + public Set getAllowedFaces() { + Set set = new HashSet<>(); + if(delegate.contains(Properties.NORTH)) set.add(BlockFace.NORTH); + if(delegate.contains(Properties.SOUTH)) set.add(BlockFace.SOUTH); + if(delegate.contains(Properties.EAST)) set.add(BlockFace.EAST); + if(delegate.contains(Properties.WEST)) set.add(BlockFace.WEST); + if(delegate.contains(Properties.UP)) set.add(BlockFace.UP); + if(delegate.contains(Properties.DOWN)) set.add(BlockFace.DOWN); + return set; + } + + @Override + public boolean hasFace(BlockFace f) { + return getFaces().contains(f); + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/data/FabricOrientable.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/data/FabricOrientable.java new file mode 100644 index 000000000..c817a917a --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/data/FabricOrientable.java @@ -0,0 +1,32 @@ +package com.dfsek.terra.fabric.world.block.data; + +import com.dfsek.terra.api.platform.block.Axis; +import com.dfsek.terra.api.platform.block.data.Orientable; +import com.dfsek.terra.fabric.world.block.FabricBlockData; +import net.minecraft.block.BlockState; +import net.minecraft.state.property.Properties; + +import java.util.Arrays; +import java.util.Set; +import java.util.stream.Collectors; + +public class FabricOrientable extends FabricBlockData implements Orientable { + public FabricOrientable(BlockState delegate) { + super(delegate); + } + + @Override + public Set getAxes() { + return Arrays.stream(Axis.values()).collect(Collectors.toSet()); + } + + @Override + public Axis getAxis() { + return FabricEnumAdapter.adapt(getHandle().get(Properties.AXIS)); + } + + @Override + public void setAxis(Axis axis) { + delegate = delegate.with(Properties.AXIS, FabricEnumAdapter.adapt(axis)); + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/data/FabricSlab.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/data/FabricSlab.java new file mode 100644 index 000000000..a6ca5f5de --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/data/FabricSlab.java @@ -0,0 +1,21 @@ +package com.dfsek.terra.fabric.world.block.data; + +import com.dfsek.terra.api.platform.block.data.Slab; +import net.minecraft.block.BlockState; +import net.minecraft.state.property.Properties; + +public class FabricSlab extends FabricWaterlogged implements Slab { + public FabricSlab(BlockState delegate) { + super(delegate); + } + + @Override + public Type getType() { + return FabricEnumAdapter.adapt(delegate.get(Properties.SLAB_TYPE)); + } + + @Override + public void setType(Type type) { + delegate = delegate.with(Properties.SLAB_TYPE, FabricEnumAdapter.adapt(type)); + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/data/FabricStairs.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/data/FabricStairs.java new file mode 100644 index 000000000..ec268f784 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/data/FabricStairs.java @@ -0,0 +1,42 @@ +package com.dfsek.terra.fabric.world.block.data; + +import com.dfsek.terra.api.platform.block.BlockFace; +import com.dfsek.terra.api.platform.block.data.Stairs; +import net.minecraft.block.BlockState; +import net.minecraft.state.property.Properties; + +public class FabricStairs extends FabricWaterlogged implements Stairs { + public FabricStairs(BlockState delegate) { + super(delegate); + } + + @Override + public Shape getShape() { + return FabricEnumAdapter.adapt(getHandle().get(Properties.STAIR_SHAPE)); + } + + @Override + public void setShape(Shape shape) { + super.delegate = getHandle().with(Properties.STAIR_SHAPE, FabricEnumAdapter.adapt(shape)); + } + + @Override + public Half getHalf() { + return FabricEnumAdapter.adapt(getHandle().get(Properties.BLOCK_HALF)); + } + + @Override + public void setHalf(Half half) { + super.delegate = getHandle().with(Properties.BLOCK_HALF, FabricEnumAdapter.adapt(half)); + } + + @Override + public BlockFace getFacing() { + return FabricEnumAdapter.adapt(getHandle().get(Properties.HORIZONTAL_FACING)); + } + + @Override + public void setFacing(BlockFace facing) { + super.delegate = getHandle().with(Properties.HORIZONTAL_FACING, FabricEnumAdapter.adapt(facing)); + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/data/FabricWaterlogged.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/data/FabricWaterlogged.java new file mode 100644 index 000000000..95960e295 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/block/data/FabricWaterlogged.java @@ -0,0 +1,22 @@ +package com.dfsek.terra.fabric.world.block.data; + +import com.dfsek.terra.api.platform.block.data.Waterlogged; +import com.dfsek.terra.fabric.world.block.FabricBlockData; +import net.minecraft.block.BlockState; +import net.minecraft.state.property.Properties; + +public class FabricWaterlogged extends FabricBlockData implements Waterlogged { + public FabricWaterlogged(BlockState delegate) { + super(delegate); + } + + @Override + public boolean isWaterlogged() { + return delegate.get(Properties.WATERLOGGED); + } + + @Override + public void setWaterlogged(boolean waterlogged) { + super.delegate = delegate.with(Properties.WATERLOGGED, waterlogged); + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/features/PopulatorFeature.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/features/PopulatorFeature.java new file mode 100644 index 000000000..0e2d741a7 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/features/PopulatorFeature.java @@ -0,0 +1,37 @@ +package com.dfsek.terra.fabric.world.features; + +import com.dfsek.terra.fabric.world.generator.FabricChunkGenerator; +import com.dfsek.terra.fabric.world.generator.FabricChunkGeneratorWrapper; +import com.dfsek.terra.fabric.world.handles.FabricWorld; +import com.dfsek.terra.fabric.world.handles.chunk.FabricChunkWorldAccess; +import com.dfsek.terra.fabric.world.handles.world.FabricSeededWorldAccess; +import com.mojang.serialization.Codec; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.StructureWorldAccess; +import net.minecraft.world.gen.chunk.ChunkGenerator; +import net.minecraft.world.gen.feature.DefaultFeatureConfig; +import net.minecraft.world.gen.feature.Feature; + +import java.util.Random; + +/** + * Feature wrapper for Terra populator + */ +public class PopulatorFeature extends Feature { + public PopulatorFeature(Codec codec) { + super(codec); + } + + @Override + public boolean generate(StructureWorldAccess world, ChunkGenerator chunkGenerator, Random random, BlockPos pos, DefaultFeatureConfig config) { + FabricChunkGeneratorWrapper gen = (FabricChunkGeneratorWrapper) chunkGenerator; + FabricChunkWorldAccess chunk = new FabricChunkWorldAccess(world, pos.getX() >> 4, pos.getZ() >> 4); + FabricWorld world1 = new FabricWorld(world.toServerWorld(), new FabricChunkGenerator(chunkGenerator)); + gen.getCavePopulator().populate(world1, chunk); + gen.getStructurePopulator().populate(new FabricSeededWorldAccess(world, world.getSeed(), chunkGenerator), chunk); + gen.getOrePopulator().populate(world1, chunk); + gen.getTreePopulator().populate(world1, chunk); + gen.getFloraPopulator().populate(world1, chunk); + return true; + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/generator/FabricChunkData.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/generator/FabricChunkData.java new file mode 100644 index 000000000..5c5d26462 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/generator/FabricChunkData.java @@ -0,0 +1,36 @@ +package com.dfsek.terra.fabric.world.generator; + +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.generator.ChunkGenerator; +import com.dfsek.terra.fabric.world.block.FabricBlockData; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.chunk.Chunk; +import org.jetbrains.annotations.NotNull; + +public class FabricChunkData implements ChunkGenerator.ChunkData { + private final Chunk handle; + + public FabricChunkData(Chunk handle) { + this.handle = handle; + } + + @Override + public Chunk getHandle() { + return handle; + } + + @Override + public int getMaxHeight() { + return handle.getHeight(); + } + + @Override + public void setBlock(int x, int y, int z, @NotNull BlockData blockData) { + handle.setBlockState(new BlockPos(x, y, z), ((FabricBlockData) blockData).getHandle(), false); + } + + @Override + public @NotNull BlockData getBlockData(int x, int y, int z) { + return new FabricBlockData(handle.getBlockState(new BlockPos(x, y, z))); + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/generator/FabricChunkGenerator.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/generator/FabricChunkGenerator.java new file mode 100644 index 000000000..5ec22b9e3 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/generator/FabricChunkGenerator.java @@ -0,0 +1,66 @@ +package com.dfsek.terra.fabric.world.generator; + +import com.dfsek.terra.api.platform.generator.BlockPopulator; +import com.dfsek.terra.api.platform.generator.ChunkGenerator; +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 class FabricChunkGenerator implements ChunkGenerator { + private final net.minecraft.world.gen.chunk.ChunkGenerator delegate; + + public FabricChunkGenerator(net.minecraft.world.gen.chunk.ChunkGenerator delegate) { + this.delegate = delegate; + } + + @Override + public boolean isParallelCapable() { + return false; + } + + @Override + public boolean shouldGenerateCaves() { + return false; + } + + @Override + public boolean shouldGenerateDecorations() { + return false; + } + + @Override + public boolean shouldGenerateMobs() { + return false; + } + + @Override + public boolean shouldGenerateStructures() { + return false; + } + + @Override + public ChunkData generateChunkData(@NotNull World world, @NotNull Random random, int x, int z, @NotNull BiomeGrid biome) { + return null; + } + + @Override + public List getDefaultPopulators(World world) { + return null; + } + + @Override + public @Nullable TerraChunkGenerator getTerraGenerator() { + if(delegate instanceof FabricChunkGeneratorWrapper) return ((FabricChunkGeneratorWrapper) delegate).getHandle(); + return null; + } + + @Override + public net.minecraft.world.gen.chunk.ChunkGenerator getHandle() { + return delegate; + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/generator/FabricChunkGeneratorWrapper.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/generator/FabricChunkGeneratorWrapper.java new file mode 100644 index 000000000..24c830b78 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/generator/FabricChunkGeneratorWrapper.java @@ -0,0 +1,150 @@ +package com.dfsek.terra.fabric.world.generator; + +import com.dfsek.terra.api.platform.generator.GeneratorWrapper; +import com.dfsek.terra.api.util.FastRandom; +import com.dfsek.terra.config.base.ConfigPack; +import com.dfsek.terra.fabric.TerraFabricPlugin; +import com.dfsek.terra.fabric.world.TerraBiomeSource; +import com.dfsek.terra.fabric.world.handles.world.FabricSeededWorldAccess; +import com.dfsek.terra.generation.MasterChunkGenerator; +import com.dfsek.terra.population.CavePopulator; +import com.dfsek.terra.population.FloraPopulator; +import com.dfsek.terra.population.OrePopulator; +import com.dfsek.terra.population.StructurePopulator; +import com.dfsek.terra.population.TreePopulator; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.structure.StructureManager; +import net.minecraft.util.math.ChunkPos; +import net.minecraft.util.registry.DynamicRegistryManager; +import net.minecraft.world.BlockView; +import net.minecraft.world.ChunkRegion; +import net.minecraft.world.Heightmap; +import net.minecraft.world.WorldAccess; +import net.minecraft.world.biome.source.BiomeAccess; +import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.gen.GenerationStep; +import net.minecraft.world.gen.StructureAccessor; +import net.minecraft.world.gen.chunk.ChunkGenerator; +import net.minecraft.world.gen.chunk.StructuresConfig; +import net.minecraft.world.gen.chunk.VerticalBlockSample; + +public class FabricChunkGeneratorWrapper extends ChunkGenerator implements GeneratorWrapper { + private final long seed; + private final MasterChunkGenerator delegate; + private final TerraBiomeSource biomeSource; + public static final Codec PACK_CODEC = (RecordCodecBuilder.create(config -> config.group( + Codec.STRING.fieldOf("pack").forGetter(pack -> pack.getTemplate().getID()) + ).apply(config, config.stable(TerraFabricPlugin.getInstance().getRegistry()::get)))); + public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( + TerraBiomeSource.CODEC.fieldOf("biome_source").forGetter(generator -> generator.biomeSource), + Codec.LONG.fieldOf("seed").stable().forGetter(generator -> generator.seed), + PACK_CODEC.fieldOf("pack").stable().forGetter(generator -> generator.pack)) + .apply(instance, instance.stable(FabricChunkGeneratorWrapper::new))); + private final ConfigPack pack; + + + private final CavePopulator cavePopulator = new CavePopulator(TerraFabricPlugin.getInstance()); + private final FloraPopulator floraPopulator = new FloraPopulator(TerraFabricPlugin.getInstance()); + private final OrePopulator orePopulator = new OrePopulator(TerraFabricPlugin.getInstance()); + private final TreePopulator treePopulator = new TreePopulator(TerraFabricPlugin.getInstance()); + private final StructurePopulator structurePopulator = new StructurePopulator(TerraFabricPlugin.getInstance()); + + public TreePopulator getTreePopulator() { + return treePopulator; + } + + public CavePopulator getCavePopulator() { + return cavePopulator; + } + + public OrePopulator getOrePopulator() { + return orePopulator; + } + + public FloraPopulator getFloraPopulator() { + return floraPopulator; + } + + public StructurePopulator getStructurePopulator() { + return structurePopulator; + } + + public FabricChunkGeneratorWrapper(TerraBiomeSource biomeSource, long seed, ConfigPack configPack) { + super(biomeSource, new StructuresConfig(false)); + this.pack = configPack; + + this.delegate = new MasterChunkGenerator(configPack, TerraFabricPlugin.getInstance(), pack.getSamplerCache()); + delegate.getMain().getLogger().info("Loading world..."); + this.biomeSource = biomeSource; + + this.seed = seed; + } + + @Override + public MasterChunkGenerator getHandle() { + return delegate; + } + + @Override + protected Codec getCodec() { + return CODEC; + } + + @Override + public ChunkGenerator withSeed(long seed) { + return new FabricChunkGeneratorWrapper((TerraBiomeSource) this.biomeSource.withSeed(seed), seed, pack); + } + + @Override + public void buildSurface(ChunkRegion region, Chunk chunk) { + + } + + @Override + public void populateNoise(WorldAccess world, StructureAccessor accessor, Chunk chunk) { + FabricSeededWorldAccess worldAccess = new FabricSeededWorldAccess(world, seed, this); + delegate.generateChunkData(worldAccess, new FastRandom(), chunk.getPos().x, chunk.getPos().z, new FabricChunkData(chunk)); + } + + @Override + public void carve(long seed, BiomeAccess access, Chunk chunk, GenerationStep.Carver carver) { + // No caves + } + + @Override + public void setStructureStarts(DynamicRegistryManager dynamicRegistryManager, StructureAccessor structureAccessor, Chunk chunk, StructureManager structureManager, long worldSeed) { + + } + + @Override + public boolean isStrongholdStartingChunk(ChunkPos chunkPos) { + return false; + } + + @Override + public int getHeight(int x, int z, Heightmap.Type heightmapType) { + return 0; + } + + @Override + public BlockView getColumnSample(int x, int z) { + int height = 64; // TODO: implementation + BlockState[] array = new BlockState[256]; + for(int y = 255; y >= 0; y--) { + if(y > height) { + if(y > getSeaLevel()) { + array[y] = Blocks.AIR.getDefaultState(); + } else { + array[y] = Blocks.WATER.getDefaultState(); + } + } else { + array[y] = Blocks.STONE.getDefaultState(); + } + } + + return new VerticalBlockSample(array); + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/handles/FabricWorld.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/handles/FabricWorld.java new file mode 100644 index 000000000..5ac4f144c --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/handles/FabricWorld.java @@ -0,0 +1,113 @@ +package com.dfsek.terra.fabric.world.handles; + +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.platform.block.Block; +import com.dfsek.terra.api.platform.generator.ChunkGenerator; +import com.dfsek.terra.api.platform.world.Chunk; +import com.dfsek.terra.api.platform.world.Tree; +import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.api.platform.world.entity.Entity; +import com.dfsek.terra.api.platform.world.entity.EntityType; +import com.dfsek.terra.fabric.world.block.FabricBlock; +import com.dfsek.terra.fabric.world.handles.chunk.FabricChunk; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.math.BlockPos; + +import java.io.File; +import java.util.UUID; + +public class FabricWorld implements World { + + private final Handle delegate; + + public FabricWorld(ServerWorld world, ChunkGenerator generator) { + this.delegate = new Handle(world, generator); + } + + @Override + public long getSeed() { + return delegate.world.getSeed(); + } + + @Override + public int getMaxHeight() { + return delegate.world.getHeight(); + } + + @Override + public ChunkGenerator getGenerator() { + return delegate.generator; + } + + @Override + public String getName() { + return delegate.world.worldProperties.getLevelName(); + } + + @Override + public UUID getUID() { + return null; + } + + @Override + public boolean isChunkGenerated(int x, int z) { + return false; + } + + @Override + public Chunk getChunkAt(int x, int z) { + return new FabricChunk(delegate.world.getChunk(x, z)); + } + + @Override + public File getWorldFolder() { + return null; + } + + @Override + public Block getBlockAt(int x, int y, int z) { + BlockPos pos = new BlockPos(x, y, z); + return new FabricBlock(pos, delegate.world); + } + + @Override + public int hashCode() { + return delegate.generator.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if(!(obj instanceof FabricWorld)) return false; + return ((FabricWorld) obj).delegate.generator.equals(delegate.generator); + } + + @Override + public Block getBlockAt(Location l) { + return getBlockAt(l.getBlockX(), l.getBlockY(), l.getBlockZ()); + } + + @Override + public boolean generateTree(Location l, Tree vanillaTreeType) { + return false; + } + + @Override + public Entity spawnEntity(Location location, EntityType entityType) { + return null; + } + + @Override + public Handle getHandle() { + return null; + } + + private static final class Handle { + private final ServerWorld world; + private final ChunkGenerator generator; + + private Handle(ServerWorld world, ChunkGenerator generator) { + this.world = world; + this.generator = generator; + } + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/handles/chunk/FabricChunk.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/handles/chunk/FabricChunk.java new file mode 100644 index 000000000..7c14d02ea --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/handles/chunk/FabricChunk.java @@ -0,0 +1,38 @@ +package com.dfsek.terra.fabric.world.handles.chunk; + +import com.dfsek.terra.api.platform.block.Block; +import com.dfsek.terra.api.platform.world.Chunk; +import com.dfsek.terra.api.platform.world.World; + +public class FabricChunk implements Chunk { + private final net.minecraft.world.chunk.Chunk chunk; + + public FabricChunk(net.minecraft.world.chunk.Chunk chunk) { + this.chunk = chunk; + } + + @Override + public int getX() { + return chunk.getPos().x; + } + + @Override + public int getZ() { + return chunk.getPos().z; + } + + @Override + public World getWorld() { + return null; + } + + @Override + public Block getBlock(int x, int y, int z) { + return null; + } + + @Override + public net.minecraft.world.chunk.Chunk getHandle() { + return chunk; + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/handles/chunk/FabricChunkWorldAccess.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/handles/chunk/FabricChunkWorldAccess.java new file mode 100644 index 000000000..4472b8523 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/handles/chunk/FabricChunkWorldAccess.java @@ -0,0 +1,47 @@ +package com.dfsek.terra.fabric.world.handles.chunk; + +import com.dfsek.terra.api.platform.block.Block; +import com.dfsek.terra.api.platform.world.Chunk; +import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.fabric.world.block.FabricBlock; +import com.dfsek.terra.fabric.world.handles.world.FabricWorldAccess; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.WorldAccess; + +public class FabricChunkWorldAccess implements Chunk { + private final WorldAccess chunkRegion; + private final int x; + private final int z; + + public FabricChunkWorldAccess(WorldAccess chunkRegion, int x, int z) { + this.chunkRegion = chunkRegion; + this.x = x << 4; + this.z = z << 4; + } + + @Override + public int getX() { + return x >> 4; + } + + @Override + public int getZ() { + return z >> 4; + } + + @Override + public World getWorld() { + return new FabricWorldAccess(chunkRegion); + } + + @Override + public Block getBlock(int x, int y, int z) { + BlockPos pos = new BlockPos(x + this.x, y, z + this.z); + return new FabricBlock(pos, chunkRegion); + } + + @Override + public WorldAccess getHandle() { + return chunkRegion; + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/handles/world/FabricSeededWorldAccess.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/handles/world/FabricSeededWorldAccess.java new file mode 100644 index 000000000..c2e2bf946 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/handles/world/FabricSeededWorldAccess.java @@ -0,0 +1,126 @@ +package com.dfsek.terra.fabric.world.handles.world; + +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.platform.block.Block; +import com.dfsek.terra.api.platform.generator.ChunkGenerator; +import com.dfsek.terra.api.platform.world.Chunk; +import com.dfsek.terra.api.platform.world.Tree; +import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.api.platform.world.entity.Entity; +import com.dfsek.terra.api.platform.world.entity.EntityType; +import com.dfsek.terra.fabric.world.block.FabricBlock; +import com.dfsek.terra.fabric.world.generator.FabricChunkGenerator; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.WorldAccess; + +import java.io.File; +import java.util.UUID; + +public class FabricSeededWorldAccess implements World { + + private final Handle handle; + + public FabricSeededWorldAccess(WorldAccess access, long seed, net.minecraft.world.gen.chunk.ChunkGenerator generator) { + this.handle = new Handle(access, seed, generator); + } + + @Override + public long getSeed() { + return handle.getSeed(); + } + + @Override + public int getMaxHeight() { + return handle.getWorldAccess().getDimensionHeight(); + } + + @Override + public ChunkGenerator getGenerator() { + return new FabricChunkGenerator(handle.getGenerator()); + } + + @Override + public String getName() { + return handle.toString(); // TODO: implementation + } + + @Override + public UUID getUID() { + return UUID.randomUUID(); // TODO: implementation + } + + @Override + public boolean isChunkGenerated(int x, int z) { + return false; + } + + @Override + public Chunk getChunkAt(int x, int z) { + return null; + } + + @Override + public File getWorldFolder() { + return null; + } + + @Override + public Block getBlockAt(int x, int y, int z) { + BlockPos pos = new BlockPos(x, y, z); + return new FabricBlock(pos, handle.worldAccess); + } + + @Override + public Block getBlockAt(Location l) { + return getBlockAt(l.getBlockX(), l.getBlockY(), l.getBlockZ()); + } + + @Override + public boolean generateTree(Location l, Tree vanillaTreeType) { + return false; + } + + @Override + public Entity spawnEntity(Location location, EntityType entityType) { + return null; + } + + @Override + public int hashCode() { + return handle.worldAccess.hashCode(); + } + + @Override + public boolean equals(Object obj) { + return super.equals(obj); + } + + @Override + public Handle getHandle() { + return handle; + } + + public static class Handle { + private final WorldAccess worldAccess; + private final long seed; + private final net.minecraft.world.gen.chunk.ChunkGenerator generator; + + public Handle(WorldAccess worldAccess, long seed, net.minecraft.world.gen.chunk.ChunkGenerator generator) { + this.worldAccess = worldAccess; + this.seed = seed; + this.generator = generator; + } + + public net.minecraft.world.gen.chunk.ChunkGenerator getGenerator() { + return generator; + } + + public long getSeed() { + return seed; + } + + public WorldAccess getWorldAccess() { + return worldAccess; + } + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/handles/world/FabricWorldAccess.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/handles/world/FabricWorldAccess.java new file mode 100644 index 000000000..4dbb4adf9 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/handles/world/FabricWorldAccess.java @@ -0,0 +1,93 @@ +package com.dfsek.terra.fabric.world.handles.world; + +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.platform.block.Block; +import com.dfsek.terra.api.platform.generator.ChunkGenerator; +import com.dfsek.terra.api.platform.world.Chunk; +import com.dfsek.terra.api.platform.world.Tree; +import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.api.platform.world.entity.Entity; +import com.dfsek.terra.api.platform.world.entity.EntityType; +import com.dfsek.terra.fabric.world.block.FabricBlock; +import com.dfsek.terra.fabric.world.generator.FabricChunkGenerator; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.ServerWorldAccess; +import net.minecraft.world.StructureWorldAccess; +import net.minecraft.world.WorldAccess; + +import java.io.File; +import java.util.UUID; + +public class FabricWorldAccess implements World { + private final WorldAccess delegate; + + public FabricWorldAccess(WorldAccess delegate) { + this.delegate = delegate; + } + + @Override + public long getSeed() { + return ((StructureWorldAccess) delegate).getSeed(); + } + + @Override + public int getMaxHeight() { + return delegate.getDimensionHeight(); + } + + @Override + public ChunkGenerator getGenerator() { + return new FabricChunkGenerator(((ServerWorldAccess) delegate).toServerWorld().getChunkManager().getChunkGenerator()); + } + + @Override + public String getName() { + return ((ServerWorldAccess) delegate).toServerWorld().worldProperties.getLevelName(); + } + + @Override + public UUID getUID() { + return null; + } + + @Override + public boolean isChunkGenerated(int x, int z) { + return false; + } + + @Override + public Chunk getChunkAt(int x, int z) { + return null; + } + + @Override + public File getWorldFolder() { + return null; + } + + @Override + public Block getBlockAt(int x, int y, int z) { + BlockPos pos = new BlockPos(x, y, z); + return new FabricBlock(pos, delegate); + } + + @Override + public Block getBlockAt(Location l) { + return getBlockAt(l.getBlockX(), l.getBlockY(), l.getBlockZ()); + } + + @Override + public boolean generateTree(Location l, Tree vanillaTreeType) { + return false; + } + + @Override + public Entity spawnEntity(Location location, EntityType entityType) { + return null; + } + + @Override + public WorldAccess getHandle() { + return delegate; + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/handles/world/FabricWorldChunkRegion.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/handles/world/FabricWorldChunkRegion.java new file mode 100644 index 000000000..e0e2fadb1 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/handles/world/FabricWorldChunkRegion.java @@ -0,0 +1,120 @@ +package com.dfsek.terra.fabric.world.handles.world; + +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.platform.block.Block; +import com.dfsek.terra.api.platform.generator.ChunkGenerator; +import com.dfsek.terra.api.platform.world.Chunk; +import com.dfsek.terra.api.platform.world.Tree; +import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.api.platform.world.entity.Entity; +import com.dfsek.terra.api.platform.world.entity.EntityType; +import com.dfsek.terra.fabric.world.block.FabricBlock; +import com.dfsek.terra.fabric.world.generator.FabricChunkGenerator; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.ChunkRegion; + +import java.io.File; +import java.util.UUID; + +public class FabricWorldChunkRegion implements World { + private final Handle delegate; + + public FabricWorldChunkRegion(ChunkRegion delegate, net.minecraft.world.gen.chunk.ChunkGenerator generator) { + this.delegate = new Handle(delegate, generator); + } + + @Override + public long getSeed() { + return delegate.getChunk().getSeed(); + } + + @Override + public int getMaxHeight() { + return delegate.getChunk().getHeight(); + } + + @Override + public ChunkGenerator getGenerator() { + return new FabricChunkGenerator(delegate.getGenerator()); + } + + @Override + public String getName() { + return delegate.chunk.toString(); + } + + @Override + public UUID getUID() { + return UUID.randomUUID(); + } + + @Override + public boolean isChunkGenerated(int x, int z) { + return delegate.chunk.isChunkLoaded(x, z); + } + + @Override + public Chunk getChunkAt(int x, int z) { + return null; + } + + @Override + public File getWorldFolder() { + return null; + } + + @Override + public Block getBlockAt(int x, int y, int z) { + BlockPos pos = new BlockPos(x, y, z); + return new FabricBlock(pos, delegate.chunk); + } + + @Override + public int hashCode() { + return delegate.generator.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if(!(obj instanceof FabricWorldChunkRegion)) return false; + return ((FabricWorldChunkRegion) obj).delegate.generator.equals(delegate.generator); + } + + @Override + public Block getBlockAt(Location l) { + return getBlockAt(l.getBlockX(), l.getBlockY(), l.getBlockZ()); + } + + @Override + public boolean generateTree(Location l, Tree vanillaTreeType) { + return false; + } + + @Override + public Entity spawnEntity(Location location, EntityType entityType) { + return null; + } + + @Override + public Object getHandle() { + return null; + } + + public static final class Handle { + private final ChunkRegion chunk; + private final net.minecraft.world.gen.chunk.ChunkGenerator generator; + + public Handle(ChunkRegion chunk, net.minecraft.world.gen.chunk.ChunkGenerator generator) { + this.chunk = chunk; + this.generator = generator; + } + + public net.minecraft.world.gen.chunk.ChunkGenerator getGenerator() { + return generator; + } + + public ChunkRegion getChunk() { + return chunk; + } + } +} diff --git a/platforms/fabric/src/main/resources/assets/terra/icon.png b/platforms/fabric/src/main/resources/assets/terra/icon.png new file mode 100644 index 000000000..39b6d20f6 Binary files /dev/null and b/platforms/fabric/src/main/resources/assets/terra/icon.png differ diff --git a/platforms/fabric/src/main/resources/assets/terra/lang/en_us.json b/platforms/fabric/src/main/resources/assets/terra/lang/en_us.json new file mode 100644 index 000000000..517b70815 --- /dev/null +++ b/platforms/fabric/src/main/resources/assets/terra/lang/en_us.json @@ -0,0 +1,4 @@ +{ + "generator.terra": "Terra" +} + diff --git a/src/main/resources/config.yml b/platforms/fabric/src/main/resources/config.yml similarity index 100% rename from src/main/resources/config.yml rename to platforms/fabric/src/main/resources/config.yml diff --git a/platforms/fabric/src/main/resources/fabric.mod.json b/platforms/fabric/src/main/resources/fabric.mod.json new file mode 100644 index 000000000..d86abc872 --- /dev/null +++ b/platforms/fabric/src/main/resources/fabric.mod.json @@ -0,0 +1,31 @@ +{ + "schemaVersion": 1, + "id": "terra", + "version": "@VERSION@", + "name": "Terra", + "description": "An insanely powerful free & open-source data-driven world generator.", + "authors": [ + "dfsek" + ], + "contact": { + "homepage": "https://github.com/PolyhedralDev/Terra/wiki", + "sources": "https://github.com/PolyhedralDev/Terra" + }, + "license": "GPL-3.0", + "icon": "assets/terra/icon.png", + "environment": "*", + "entrypoints": { + "main": [ + "com.dfsek.terra.fabric.TerraFabricPlugin" + ] + }, + "mixins": [ + "terra.mixins.json" + ], + "depends": { + "fabricloader": ">=0.7.4", + "fabric": "*", + "minecraft": "1.16.x" + }, + "accessWidener": "terra.accesswidener" +} \ No newline at end of file diff --git a/platforms/fabric/src/main/resources/terra.accesswidener b/platforms/fabric/src/main/resources/terra.accesswidener new file mode 100644 index 000000000..edfa21bd4 --- /dev/null +++ b/platforms/fabric/src/main/resources/terra.accesswidener @@ -0,0 +1,6 @@ +accessWidener v1 named + +extendable method net/minecraft/client/world/GeneratorType (Ljava/lang/String;)V + +accessible field net/minecraft/server/world/ServerWorld worldProperties Lnet/minecraft/world/level/ServerWorldProperties; +mutable field net/minecraft/server/world/ServerWorld worldProperties Lnet/minecraft/world/level/ServerWorldProperties; \ No newline at end of file diff --git a/platforms/fabric/src/main/resources/terra.mixins.json b/platforms/fabric/src/main/resources/terra.mixins.json new file mode 100644 index 000000000..a6b050657 --- /dev/null +++ b/platforms/fabric/src/main/resources/terra.mixins.json @@ -0,0 +1,14 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "com.dfsek.terra.fabric.mixin", + "compatibilityLevel": "JAVA_8", + "mixins": [], + "client": [ + "GeneratorTypeAccessor" + ], + "server": [], + "injectors": { + "defaultRequire": 1 + } +} \ No newline at end of file diff --git a/platforms/region/build.gradle.kts b/platforms/region/build.gradle.kts new file mode 100644 index 000000000..3d467c794 --- /dev/null +++ b/platforms/region/build.gradle.kts @@ -0,0 +1,26 @@ +import com.dfsek.terra.configureCommon +import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar + +plugins { + `java-library` +} + +configureCommon() + +group = "com.dfsek.terra" + +repositories { + mavenCentral() + maven { url = uri("https://jitpack.io/") } +} + +dependencies { + "shadedApi"(project(":common")) + "shadedImplementation"("com.github.Querz:NBT:5.2") // Standalone NBT API + "shadedImplementation"("org.yaml:snakeyaml:1.27") + "shadedImplementation"("com.googlecode.json-simple:json-simple:1.1.1") +} + +tasks.named("shadowJar") { + relocate("net.querz", "com.dfsek.terra.libs.nbt") +} \ No newline at end of file diff --git a/platforms/region/src/main/java/com/dfsek/terra/DirectUtils.java b/platforms/region/src/main/java/com/dfsek/terra/DirectUtils.java new file mode 100644 index 000000000..2be2ebf6e --- /dev/null +++ b/platforms/region/src/main/java/com/dfsek/terra/DirectUtils.java @@ -0,0 +1,18 @@ +package com.dfsek.terra; + +import com.dfsek.terra.api.math.MathUtil; +import net.querz.mca.MCAUtil; + +public final class DirectUtils { + + /** + * Compute long region ID from chunk coords + * + * @param x X + * @param z Z + * @return Region IS + */ + public static long regionID(int x, int z) { + return MathUtil.squash(MCAUtil.chunkToRegion(x), MCAUtil.chunkToRegion(z)); + } +} diff --git a/platforms/region/src/main/java/com/dfsek/terra/RegionGenerator.java b/platforms/region/src/main/java/com/dfsek/terra/RegionGenerator.java new file mode 100644 index 000000000..cf57a310b --- /dev/null +++ b/platforms/region/src/main/java/com/dfsek/terra/RegionGenerator.java @@ -0,0 +1,19 @@ +package com.dfsek.terra; + +import com.dfsek.terra.region.Generator; + +import java.io.IOException; +import java.util.concurrent.ThreadLocalRandom; + +public class RegionGenerator { + public static void main(String[] args) throws IOException { + long seed; + if(args.length == 1) seed = Long.parseLong(args[0]); + else seed = ThreadLocalRandom.current().nextLong(); + + StandalonePlugin plugin = new StandalonePlugin(); + Generator generator = new Generator(seed, plugin); + + generator.generate(); + } +} diff --git a/platforms/region/src/main/java/com/dfsek/terra/StandalonePlugin.java b/platforms/region/src/main/java/com/dfsek/terra/StandalonePlugin.java new file mode 100644 index 000000000..394d1badf --- /dev/null +++ b/platforms/region/src/main/java/com/dfsek/terra/StandalonePlugin.java @@ -0,0 +1,111 @@ +package com.dfsek.terra; + +import com.dfsek.tectonic.loading.TypeRegistry; +import com.dfsek.terra.api.GenericLoaders; +import com.dfsek.terra.api.language.Language; +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.block.MaterialData; +import com.dfsek.terra.api.platform.handle.ItemHandle; +import com.dfsek.terra.api.platform.handle.WorldHandle; +import com.dfsek.terra.api.platform.world.Biome; +import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.config.base.PluginConfig; +import com.dfsek.terra.config.lang.LangUtil; +import com.dfsek.terra.platform.RawBiome; +import com.dfsek.terra.platform.RawWorldHandle; +import com.dfsek.terra.registry.ConfigRegistry; + +import java.io.File; +import java.io.IOException; +import java.util.logging.Logger; + +public class StandalonePlugin implements TerraPlugin { + private final ConfigRegistry registry = new ConfigRegistry(); + private final PluginConfig config = new PluginConfig(); + private final RawWorldHandle worldHandle = new RawWorldHandle(); + + @Override + public WorldHandle getWorldHandle() { + return worldHandle; + } + + @Override + public boolean isEnabled() { + return true; + } + + @Override + public TerraWorld getWorld(World world) { + return new TerraWorld(world, registry.get("DEFAULT"), this); + } + + @Override + public Logger getLogger() { + return Logger.getLogger("Terra"); + } + + @Override + public PluginConfig getTerraConfig() { + return config; + } + + @Override + public File getDataFolder() { + return new File("."); + } + + @Override + public boolean isDebug() { + return true; + } + + @Override + public Language getLanguage() { + try { + return new Language(new File(getDataFolder(), "lang/en_us.yml")); + } catch(IOException e) { + throw new IllegalArgumentException(); + } + } + + @Override + public ConfigRegistry getRegistry() { + return registry; + } + + @Override + public void reload() { + throw new UnsupportedOperationException(); + } + + @Override + public ItemHandle getItemHandle() { + return null; + } + + @Override + public void saveDefaultConfig() { + + } + + @Override + public String platformName() { + return "Standalone"; + } + + @Override + public void register(TypeRegistry registry) { + registry + .registerLoader(BlockData.class, (t, o, l) -> worldHandle.createBlockData((String) o)) + .registerLoader(Biome.class, (t, o, l) -> new RawBiome(o.toString())) + .registerLoader(MaterialData.class, (t, o, l) -> worldHandle.createMaterialData((String) o)); + new GenericLoaders(this).register(registry); + } + + public void load() { + LangUtil.load("en_us", this); + registry.loadAll(this); + config.load(this); + } +} diff --git a/platforms/region/src/main/java/com/dfsek/terra/platform/Data.java b/platforms/region/src/main/java/com/dfsek/terra/platform/Data.java new file mode 100644 index 000000000..0ba30f150 --- /dev/null +++ b/platforms/region/src/main/java/com/dfsek/terra/platform/Data.java @@ -0,0 +1,104 @@ +package com.dfsek.terra.platform; + +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.block.MaterialData; +import net.querz.nbt.tag.CompoundTag; + +public class Data implements BlockData, MaterialData { + private final CompoundTag data; + private final String noProp; + + public Data(String data) { + this.data = new CompoundTag(); + if(data.contains("[")) { + noProp = data.substring(0, data.indexOf('[')); // Strip properties + String properties = data.substring(data.indexOf('[') + 1, data.indexOf(']')); + String[] props = properties.split(","); + CompoundTag pTag = new CompoundTag(); + for(String property : props) { + String name = property.substring(0, property.indexOf('=')); + String val = property.substring(property.indexOf('=') + 1); + + pTag.putString(name, val); + } + this.data.put("Properties", pTag); + } else noProp = data; + this.data.putString("Name", noProp); + } + + public Data(CompoundTag tag) { + if(tag == null) { + this.data = new CompoundTag(); + data.putString("Name", "minecraft:air"); + } else { + this.data = tag; + } + noProp = data.getString("Name"); + } + + + @Override + public MaterialData getMaterial() { + return this; + } + + @Override + public boolean matches(MaterialData materialData) { + return ((Data) materialData).noProp.equals(noProp); + } + + @Override + public boolean matches(BlockData other) { + return ((Data) other).noProp.equals(noProp); + } + + @Override + public boolean isSolid() { + return !isAir(); //TODO: actual implementation + } + + @Override + public boolean isAir() { + return noProp.equals("minecraft:air"); + } + + @Override + public double getMaxDurability() { + return 0; + } + + @Override + public BlockData createBlockData() { + return this; + } + + @Override + public BlockData clone() { + try { + return (BlockData) super.clone(); + } catch(CloneNotSupportedException e) { + throw new Error(e); + } + } + + @Override + public String getAsString() { + return noProp; + } + + @Override + public CompoundTag getHandle() { + return data; + } + + @Override + public int hashCode() { + return noProp.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if(!(obj instanceof Data)) return false; + return ((Data) obj).noProp.equals(noProp); + } +} diff --git a/platforms/region/src/main/java/com/dfsek/terra/platform/DirectBlock.java b/platforms/region/src/main/java/com/dfsek/terra/platform/DirectBlock.java new file mode 100644 index 000000000..55372978b --- /dev/null +++ b/platforms/region/src/main/java/com/dfsek/terra/platform/DirectBlock.java @@ -0,0 +1,87 @@ +package com.dfsek.terra.platform; + +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.math.vector.Vector3; +import com.dfsek.terra.api.platform.block.Block; +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.block.BlockFace; +import com.dfsek.terra.api.platform.block.MaterialData; +import com.dfsek.terra.api.platform.block.state.BlockState; +import net.jafama.FastMath; + +public class DirectBlock implements Block { + private final DirectWorld world; + private final Vector3 pos; + + public DirectBlock(DirectWorld world, Vector3 pos) { + this.world = world; + this.pos = pos; + } + + @Override + public void setBlockData(BlockData data, boolean physics) { + synchronized(world) { + world.compute(FastMath.floorDiv(pos.getBlockX(), 16), FastMath.floorDiv(pos.getBlockZ(), 16)).setBlockStateAt(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ(), ((Data) data).getHandle(), false); + } + } + + @Override + public BlockData getBlockData() { + return new Data(world.getData(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ())); + } + + @Override + public BlockState getState() { + return new DirectBlockState(); + } + + @Override + public Block getRelative(BlockFace face) { + return world.getBlockAt(pos.getBlockX() + face.getModX(), pos.getBlockY() + face.getModY(), pos.getBlockZ() + face.getModZ()); + } + + @Override + public Block getRelative(BlockFace face, int len) { + return world.getBlockAt(pos.getBlockX() + face.getModX() * len, pos.getBlockY() + face.getModY() * len, pos.getBlockZ() + face.getModZ() * len); + } + + @Override + public boolean isEmpty() { + return getBlockData().getAsString().equals("minecraft:air"); + } + + @Override + public Location getLocation() { + return pos.toLocation(world); + } + + @Override + public MaterialData getType() { + return new Data(world.getData(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ())); + } + + @Override + public int getX() { + return pos.getBlockX(); + } + + @Override + public int getZ() { + return pos.getBlockY(); + } + + @Override + public int getY() { + return pos.getBlockY(); + } + + @Override + public boolean isPassable() { + return false; + } + + @Override + public Object getHandle() { + return world; + } +} diff --git a/platforms/region/src/main/java/com/dfsek/terra/platform/DirectBlockState.java b/platforms/region/src/main/java/com/dfsek/terra/platform/DirectBlockState.java new file mode 100644 index 000000000..db759cb44 --- /dev/null +++ b/platforms/region/src/main/java/com/dfsek/terra/platform/DirectBlockState.java @@ -0,0 +1,42 @@ +package com.dfsek.terra.platform; + +import com.dfsek.terra.api.platform.block.Block; +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.block.state.BlockState; + +public class DirectBlockState implements BlockState { + @Override + public Block getBlock() { + return null; + } + + @Override + public int getX() { + return 0; + } + + @Override + public int getY() { + return 0; + } + + @Override + public int getZ() { + return 0; + } + + @Override + public BlockData getBlockData() { + return null; + } + + @Override + public boolean update(boolean applyPhysics) { + return false; + } + + @Override + public Object getHandle() { + return null; + } +} diff --git a/platforms/region/src/main/java/com/dfsek/terra/platform/DirectChunkData.java b/platforms/region/src/main/java/com/dfsek/terra/platform/DirectChunkData.java new file mode 100644 index 000000000..4a2c0a82a --- /dev/null +++ b/platforms/region/src/main/java/com/dfsek/terra/platform/DirectChunkData.java @@ -0,0 +1,66 @@ +package com.dfsek.terra.platform; + +import com.dfsek.terra.api.math.vector.Vector3; +import com.dfsek.terra.api.platform.block.Block; +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.generator.ChunkGenerator; +import com.dfsek.terra.api.platform.world.World; +import net.querz.mca.Chunk; +import net.querz.nbt.tag.CompoundTag; +import org.jetbrains.annotations.NotNull; + +public class DirectChunkData implements ChunkGenerator.ChunkData, com.dfsek.terra.api.platform.world.Chunk { + private final Chunk delegate; + private final DirectWorld world; + private final int x; + private final int z; + + public DirectChunkData(Chunk delegate, DirectWorld world, int x, int z) { + this.delegate = delegate; + this.world = world; + this.x = x; + this.z = z; + } + + @Override + public Object getHandle() { + return delegate; + } + + @Override + public int getMaxHeight() { + return 255; + } + + @Override + public void setBlock(int x, int y, int z, @NotNull BlockData blockData) { + delegate.setBlockStateAt(x, y, z, ((Data) blockData).getHandle(), false); + } + + @Override + public @NotNull BlockData getBlockData(int x, int y, int z) { + CompoundTag tag = delegate.getBlockStateAt(x, y, z); + if(tag == null) return new Data("minecraft:air"); + return new Data(tag.getString("Name")); + } + + @Override + public int getX() { + return x; + } + + @Override + public int getZ() { + return z; + } + + @Override + public World getWorld() { + return world; + } + + @Override + public Block getBlock(int x, int y, int z) { + return new DirectBlock(world, new Vector3(x + (this.x << 4), y, z + (this.z << 4))); + } +} diff --git a/platforms/region/src/main/java/com/dfsek/terra/platform/DirectWorld.java b/platforms/region/src/main/java/com/dfsek/terra/platform/DirectWorld.java new file mode 100644 index 000000000..b3c3b344a --- /dev/null +++ b/platforms/region/src/main/java/com/dfsek/terra/platform/DirectWorld.java @@ -0,0 +1,130 @@ +package com.dfsek.terra.platform; + +import com.dfsek.terra.DirectUtils; +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.math.vector.Vector3; +import com.dfsek.terra.api.platform.block.Block; +import com.dfsek.terra.api.platform.generator.ChunkGenerator; +import com.dfsek.terra.api.platform.world.Chunk; +import com.dfsek.terra.api.platform.world.Tree; +import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.api.platform.world.entity.Entity; +import com.dfsek.terra.api.platform.world.entity.EntityType; +import net.jafama.FastMath; +import net.querz.mca.MCAFile; +import net.querz.mca.MCAUtil; +import net.querz.nbt.tag.CompoundTag; + +import java.io.File; +import java.io.IOException; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +public class DirectWorld implements World { + private final long seed; + private final GenWrapper generator; + private final Map files = Collections.synchronizedMap(new HashMap<>()); + + public DirectWorld(long seed, GenWrapper generator) { + this.seed = seed; + this.generator = generator; + } + + @Override + public long getSeed() { + return seed; + } + + @Override + public int getMaxHeight() { + return 255; + } + + @Override + public ChunkGenerator getGenerator() { + return generator; + } + + @Override + public String getName() { + return null; + } + + @Override + public UUID getUID() { + return null; + } + + @Override + public boolean isChunkGenerated(int x, int z) { + return false; + } + + @Override + public Chunk getChunkAt(int x, int z) { + MCAFile file = compute(x, z); + net.querz.mca.Chunk chunk = file.getChunk(x, z); + if(chunk == null) { + chunk = net.querz.mca.Chunk.newChunk(); + file.setChunk(x, z, chunk); + } + return new DirectChunkData(chunk, this, x, z); + } + + @Override + public File getWorldFolder() { + return null; + } + + @Override + public Block getBlockAt(int x, int y, int z) { + return new DirectBlock(this, new Vector3(x, y, z)); + } + + @Override + public Block getBlockAt(Location l) { + return getBlockAt(l.getBlockX(), l.getBlockY(), l.getBlockZ()); + } + + @Override + public boolean generateTree(Location l, Tree vanillaTreeType) { + return false; + } + + @Override + public Entity spawnEntity(Location location, EntityType entityType) { + return null; + } + + @Override + public Object getHandle() { + return generator; + } + + public MCAFile compute(int x, int z) { + synchronized(files) { + return files.computeIfAbsent(DirectUtils.regionID(x, z), k -> { + File test = new File("region", MCAUtil.createNameFromChunkLocation(x, z)); + if(test.exists()) { + try { + System.out.println("Re-loading " + MCAUtil.createNameFromChunkLocation(x, z)); + return MCAUtil.read(test); + } catch(IOException e) { + e.printStackTrace(); + } + } + return new MCAFile(MCAUtil.chunkToRegion(x), MCAUtil.chunkToRegion(z)); + }); + } + } + + public CompoundTag getData(int x, int y, int z) { + return compute(FastMath.floorDiv(x, 16), FastMath.floorDiv(z, 16)).getBlockStateAt(x, y, z); + } + + public Map getFiles() { + return files; + } +} diff --git a/platforms/region/src/main/java/com/dfsek/terra/platform/GenWrapper.java b/platforms/region/src/main/java/com/dfsek/terra/platform/GenWrapper.java new file mode 100644 index 000000000..9b68bc4a2 --- /dev/null +++ b/platforms/region/src/main/java/com/dfsek/terra/platform/GenWrapper.java @@ -0,0 +1,67 @@ +package com.dfsek.terra.platform; + +import com.dfsek.terra.api.platform.generator.BlockPopulator; +import com.dfsek.terra.api.platform.generator.ChunkGenerator; +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 com.dfsek.terra.generation.MasterChunkGenerator; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collections; +import java.util.List; +import java.util.Random; + +public class GenWrapper implements ChunkGenerator { + private final MasterChunkGenerator generator; + + public GenWrapper(MasterChunkGenerator generator) { + this.generator = generator; + } + + @Override + public Object getHandle() { + return generator; + } + + @Override + public boolean isParallelCapable() { + return true; + } + + @Override + public boolean shouldGenerateCaves() { + return true; + } + + @Override + public boolean shouldGenerateDecorations() { + return true; + } + + @Override + public boolean shouldGenerateMobs() { + return true; + } + + @Override + public boolean shouldGenerateStructures() { + return true; + } + + @Override + public ChunkData generateChunkData(@NotNull World world, @NotNull Random random, int x, int z, @NotNull BiomeGrid biome) { + throw new UnsupportedOperationException(); // gen is directly handled by Generator + } + + @Override + public List getDefaultPopulators(World world) { + return Collections.emptyList(); + } + + @Override + public @Nullable TerraChunkGenerator getTerraGenerator() { + return generator; + } +} diff --git a/platforms/region/src/main/java/com/dfsek/terra/platform/RawBiome.java b/platforms/region/src/main/java/com/dfsek/terra/platform/RawBiome.java new file mode 100644 index 000000000..d9082aa4c --- /dev/null +++ b/platforms/region/src/main/java/com/dfsek/terra/platform/RawBiome.java @@ -0,0 +1,16 @@ +package com.dfsek.terra.platform; + +import com.dfsek.terra.api.platform.world.Biome; + +public class RawBiome implements Biome { + private final String id; + + public RawBiome(String id) { + this.id = id; + } + + @Override + public Object getHandle() { + return id; + } +} diff --git a/platforms/region/src/main/java/com/dfsek/terra/platform/RawTree.java b/platforms/region/src/main/java/com/dfsek/terra/platform/RawTree.java new file mode 100644 index 000000000..36110aaf5 --- /dev/null +++ b/platforms/region/src/main/java/com/dfsek/terra/platform/RawTree.java @@ -0,0 +1,26 @@ +package com.dfsek.terra.platform; + +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.platform.block.MaterialData; +import com.dfsek.terra.api.platform.world.Tree; + +import java.util.Collections; +import java.util.Random; +import java.util.Set; + +public class RawTree implements Tree { // TODO: implement + @Override + public Object getHandle() { + return null; + } + + @Override + public boolean plant(Location l, Random r) { + return false; + } + + @Override + public Set getSpawnable() { + return Collections.emptySet(); + } +} diff --git a/platforms/region/src/main/java/com/dfsek/terra/platform/RawWorldHandle.java b/platforms/region/src/main/java/com/dfsek/terra/platform/RawWorldHandle.java new file mode 100644 index 000000000..c88ef66a7 --- /dev/null +++ b/platforms/region/src/main/java/com/dfsek/terra/platform/RawWorldHandle.java @@ -0,0 +1,45 @@ +package com.dfsek.terra.platform; + +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.handle.WorldHandle; +import com.dfsek.terra.api.platform.world.Tree; +import com.dfsek.terra.api.platform.world.entity.EntityType; + +public class RawWorldHandle implements WorldHandle { + @Override + public void setBlockData(Block block, BlockData data, boolean physics) { + + } + + @Override + public BlockData getBlockData(Block block) { + return null; + } + + @Override + public MaterialData getType(Block block) { + return null; + } + + @Override + public BlockData createBlockData(String data) { + return new Data(data); + } + + @Override + public MaterialData createMaterialData(String data) { + return new Data(data); + } + + @Override + public Tree getTree(String id) { + return new RawTree(); + } + + @Override + public EntityType getEntity(String id) { + return null; + } +} diff --git a/platforms/region/src/main/java/com/dfsek/terra/region/Generator.java b/platforms/region/src/main/java/com/dfsek/terra/region/Generator.java new file mode 100644 index 000000000..1fc48fe3f --- /dev/null +++ b/platforms/region/src/main/java/com/dfsek/terra/region/Generator.java @@ -0,0 +1,92 @@ +package com.dfsek.terra.region; + +import com.dfsek.terra.StandalonePlugin; +import com.dfsek.terra.generation.MasterChunkGenerator; +import com.dfsek.terra.generation.math.SamplerCache; +import com.dfsek.terra.platform.DirectChunkData; +import com.dfsek.terra.platform.DirectWorld; +import com.dfsek.terra.platform.GenWrapper; +import com.dfsek.terra.population.CavePopulator; +import com.dfsek.terra.population.FloraPopulator; +import com.dfsek.terra.population.OrePopulator; +import com.dfsek.terra.population.StructurePopulator; +import com.dfsek.terra.population.TreePopulator; +import net.querz.mca.MCAFile; +import net.querz.mca.MCAUtil; + +import java.io.File; +import java.io.IOException; +import java.util.Map; + +public class Generator { + private final long seed; + FloraPopulator floraPopulator; + StructurePopulator structurePopulator; + TreePopulator treePopulator; + OrePopulator orePopulator; + CavePopulator cavePopulator; + MasterChunkGenerator generator; + + public Generator(long seed, StandalonePlugin plugin) { + plugin.load(); + floraPopulator = new FloraPopulator(plugin); + structurePopulator = new StructurePopulator(plugin); + treePopulator = new TreePopulator(plugin); + orePopulator = new OrePopulator(plugin); + cavePopulator = new CavePopulator(plugin); + generator = new MasterChunkGenerator(plugin.getRegistry().get("DEFAULT"), plugin, new SamplerCache(plugin)); + this.seed = seed; + } + + public void generate() throws IOException { + + int rad = 64; + System.out.println("Total mem: " + Runtime.getRuntime().maxMemory() / 1024 / 1024 / 1024 + "GB"); + + + GenWrapper wrapper = new GenWrapper(generator); + DirectWorld world = new DirectWorld(seed, wrapper); + + long l = System.nanoTime(); + int count = 0; + + for(int cx = -rad; cx <= rad; cx++) { + for(int cz = -rad; cz <= rad; cz++) { + DirectChunkData chunkData = (DirectChunkData) world.getChunkAt(cx, cz); + generator.generateChunkData(world, null, cx, cz, chunkData); + + cavePopulator.populate(world, chunkData); + structurePopulator.populate(world, chunkData); + orePopulator.populate(world, chunkData); + floraPopulator.populate(world, chunkData); + treePopulator.populate(world, chunkData); + count++; + + if(count % 200 == 0) { + long n = System.nanoTime(); + + System.out.println("Generated " + count + " chunks. " + 200 / ((double) (n - l) / 1000000) * 1000 + "cps."); + + l = System.nanoTime(); + + } + } + } + + + + System.out.println("Saving..."); + + for(Map.Entry entry : world.getFiles().entrySet()) { + if(entry.getValue() == null) continue; + entry.getValue().cleanupPalettesAndBlockStates(); + int x = (int) (entry.getKey() >> 32); + int z = (int) (long) entry.getKey(); + File file = new File("region", MCAUtil.createNameFromRegionLocation(x, z)); + file.getParentFile().mkdirs(); + MCAUtil.write(entry.getValue(), file); + } + + System.out.println("Done in " + (System.nanoTime() - l) / 1000000000 + "s"); + } +} diff --git a/platforms/region/src/main/java/com/dfsek/terra/region/RegionWriter.java b/platforms/region/src/main/java/com/dfsek/terra/region/RegionWriter.java new file mode 100644 index 000000000..7ae434669 --- /dev/null +++ b/platforms/region/src/main/java/com/dfsek/terra/region/RegionWriter.java @@ -0,0 +1,5 @@ +package com.dfsek.terra.region; + +public class RegionWriter { + +} diff --git a/settings.gradle.kts b/settings.gradle.kts index 2f7b22af2..682f7912b 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -8,3 +8,28 @@ */ rootProject.name = "Terra" +include("common") +include("platforms:bukkit") +include("platforms:fabric") +include("platforms:region") + +pluginManagement { + repositories { + maven(url = "http://maven.fabricmc.net") { + name = "Fabric" + } + gradlePluginPortal() + } +} + +plugins { + id("com.gradle.enterprise") version "3.4.1" +} + +gradleEnterprise { + buildScan { + termsOfServiceUrl = "https://gradle.com/terms-of-service" + termsOfServiceAgree = "yes" +// publishAlwaysIf(true) + } +} diff --git a/src/main/java/com/dfsek/terra/Terra.java b/src/main/java/com/dfsek/terra/Terra.java deleted file mode 100644 index 6a1203ed2..000000000 --- a/src/main/java/com/dfsek/terra/Terra.java +++ /dev/null @@ -1,211 +0,0 @@ -package com.dfsek.terra; - -import com.dfsek.tectonic.loading.TypeRegistry; -import com.dfsek.terra.api.bukkit.BukkitWorldHandle; -import com.dfsek.terra.api.generic.TerraPlugin; -import com.dfsek.terra.api.generic.world.WorldHandle; -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.command.TerraCommand; -import com.dfsek.terra.command.structure.LocateCommand; -import com.dfsek.terra.config.base.ConfigPack; -import com.dfsek.terra.config.base.PluginConfig; -import com.dfsek.terra.config.lang.LangUtil; -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.StructureFeatureLoader; -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.debug.Debug; -import com.dfsek.terra.generation.TerraChunkGenerator; -import com.dfsek.terra.generation.config.NoiseBuilder; -import com.dfsek.terra.generation.items.flora.FloraLayer; -import com.dfsek.terra.generation.items.flora.TerraFlora; -import com.dfsek.terra.generation.items.ores.Ore; -import com.dfsek.terra.generation.items.ores.OreConfig; -import com.dfsek.terra.generation.items.ores.OreHolder; -import com.dfsek.terra.generation.items.tree.TreeLayer; -import com.dfsek.terra.image.ImageLoader; -import com.dfsek.terra.listeners.EventListener; -import com.dfsek.terra.listeners.SpigotListener; -import com.dfsek.terra.procgen.GridSpawn; -import com.dfsek.terra.registry.ConfigRegistry; -import com.dfsek.terra.structure.features.Feature; -import com.dfsek.terra.util.MaterialSet; -import com.dfsek.terra.util.PaperUtil; -import com.dfsek.terra.util.StructureTypeEnum; -import org.bstats.bukkit.Metrics; -import org.bukkit.Bukkit; -import org.bukkit.Material; -import org.bukkit.World; -import org.bukkit.block.Biome; -import org.bukkit.block.data.BlockData; -import org.bukkit.command.PluginCommand; -import org.bukkit.entity.EntityType; -import org.bukkit.generator.ChunkGenerator; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.polydev.gaea.GaeaPlugin; -import org.polydev.gaea.generation.GaeaChunkGenerator; -import org.polydev.gaea.lang.Language; -import org.polydev.gaea.math.ProbabilityCollection; -import org.polydev.gaea.math.Range; - -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; - - -public class Terra extends GaeaPlugin implements TerraPlugin { - private final Map generatorMap = new HashMap<>(); - private final Map worldMap = new HashMap<>(); - private final Map worlds = new HashMap<>(); - private final ConfigRegistry registry = new ConfigRegistry(); - private final PluginConfig config = new PluginConfig(); - private WorldHandle handle = new BukkitWorldHandle(); - - public void reload() { - Map newMap = new HashMap<>(); - worldMap.forEach((world, tw) -> { - String packID = tw.getConfig().getTemplate().getID(); - newMap.put(world, new TerraWorld(world, registry.get(packID))); - }); - worldMap.clear(); - worldMap.putAll(newMap); - } - - public void setHandle(WorldHandle handle) { - getLogger().warning("|-------------------------------------------------------|"); - getLogger().warning("A third-party addon has injected a custom WorldHandle!"); - getLogger().warning("If you encounter issues, try *without* the addon before"); - getLogger().warning("reporting to Terra. Report issues with the addon to the"); - getLogger().warning("addon's maintainers!"); - getLogger().warning("|-------------------------------------------------------|"); - this.handle = handle; - } - - @Override - public void onDisable() { - TerraChunkGenerator.saveAll(); - } - - @Override - public void onEnable() { - Debug.setLogger(getLogger()); // Set debug logger. - - saveDefaultConfig(); - - Metrics metrics = new Metrics(this, 9017); // Set up bStats. - metrics.addCustomChart(new Metrics.SingleLineChart("worlds", worldMap::size)); // World number chart. - - config.load(this); // Load master config.yml - LangUtil.load(config.getLanguage(), this); // Load language. - Debug.setDebug(isDebug()); - - registry.loadAll(this); // Load all config packs. - - PluginCommand c = Objects.requireNonNull(getCommand("terra")); - TerraCommand command = new TerraCommand(this); // Set up main Terra command. - c.setExecutor(command); - c.setTabCompleter(command); - - LocateCommand locate = new LocateCommand(command, false); - PluginCommand locatePl = Objects.requireNonNull(getCommand("locate")); - locatePl.setExecutor(locate); // Override locate command. Once Paper accepts StructureLocateEvent this will be unneeded on Paper implementations. - locatePl.setTabCompleter(locate); - - - long save = config.getDataSaveInterval(); - Bukkit.getScheduler().runTaskTimerAsynchronously(this, TerraChunkGenerator::saveAll, save, save); // Schedule population data saving - - Bukkit.getPluginManager().registerEvents(new EventListener(this), this); // Register master event listener - Bukkit.getPluginManager().registerEvents(new SpigotListener(this), this); // Register Spigot event listener, once Paper accepts StructureLocateEvent PR Spigot and Paper events will be separate. - - PaperUtil.checkPaper(this); - } - - @Override - public @Nullable ChunkGenerator getDefaultWorldGenerator(@NotNull String worldName, @Nullable String id) { - return generatorMap.computeIfAbsent(worldName, name -> { - if(!registry.contains(id)) throw new IllegalArgumentException("No such config pack \"" + id + "\""); - worlds.put(worldName, registry.get(id)); - return new TerraChunkGenerator(registry.get(id), this); - }); - } - - @Override - public boolean isDebug() { - return config.isDebug(); - } - - @Override - public Class getGeneratorClass() { - return TerraChunkGenerator.class; - } - - @Override - public Language getLanguage() { - return LangUtil.getLanguage(); - } - - public void registerAllLoaders(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(Biome.class, (t, o, l) -> Biome.valueOf((String) o)) - .registerLoader(BlockData.class, (t, o, l) -> Bukkit.createBlockData((String) o)) - .registerLoader(Material.class, (t, o, l) -> Material.matchMaterial((String) o)) - .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(this)) - .registerLoader(MaterialSet.class, new MaterialSetLoader()) - .registerLoader(OreHolder.class, new OreHolderLoader()) - .registerLoader(Feature.class, new StructureFeatureLoader()) - .registerLoader(ImageLoader.class, new ImageLoaderLoader()) - .registerLoader(EntityType.class, (t, o, l) -> EntityType.valueOf((String) o)) - .registerLoader(TerraBiomeGrid.Type.class, (t, o, l) -> TerraBiomeGrid.Type.valueOf((String) o)) - .registerLoader(StructureTypeEnum.class, (t, o, l) -> StructureTypeEnum.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)); - } - - public ConfigRegistry getRegistry() { - return registry; - } - - public TerraWorld getWorld(World w) { - if(!(w.getGenerator() instanceof TerraChunkGenerator)) throw new IllegalArgumentException("Not a Terra world!"); - if(!worlds.containsKey(w.getName())) { - getLogger().warning("Unexpected world load detected: \"" + w.getName() + "\""); - return new TerraWorld(w, ((TerraChunkGenerator) w.getGenerator()).getConfigPack()); - } - return worldMap.computeIfAbsent(w, world -> new TerraWorld(w, worlds.get(w.getName()))); - } - - @NotNull - public PluginConfig getTerraConfig() { - return config; - } - - @Override - public WorldHandle getHandle() { - return handle; - } -} diff --git a/src/main/java/com/dfsek/terra/TerraWorld.java b/src/main/java/com/dfsek/terra/TerraWorld.java deleted file mode 100644 index 8d2fa9d92..000000000 --- a/src/main/java/com/dfsek/terra/TerraWorld.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.dfsek.terra; - -import com.dfsek.terra.biome.BiomeZone; -import com.dfsek.terra.biome.grid.master.TerraBiomeGrid; -import com.dfsek.terra.biome.grid.master.TerraRadialBiomeGrid; -import com.dfsek.terra.biome.grid.master.TerraStandardBiomeGrid; -import com.dfsek.terra.config.base.ConfigPack; -import com.dfsek.terra.config.base.ConfigPackTemplate; -import com.dfsek.terra.config.builder.biomegrid.BiomeGridBuilder; -import com.dfsek.terra.debug.Debug; -import com.dfsek.terra.generation.TerraChunkGenerator; -import org.bukkit.Bukkit; -import org.bukkit.World; -import org.polydev.gaea.biome.BiomeGrid; - -public class TerraWorld { - private final TerraBiomeGrid grid; - private final BiomeZone zone; - private final ConfigPack config; - private boolean safe; - private final TerraProfiler profiler; - - - public TerraWorld(World w, ConfigPack c) { - safe = true; - config = c; - profiler = new TerraProfiler(w); - - ConfigPackTemplate template = config.getTemplate(); - - int zoneSize = template.getGrids().size(); - - BiomeGrid[] definedGrids = new BiomeGrid[zoneSize]; - for(int i = 0; i < zoneSize; i++) { - String partName = template.getGrids().get(i); - try { - BiomeGridBuilder g = config.getBiomeGrid(partName); - BiomeGrid b = g.build(w, c); - definedGrids[i] = b; - } catch(NullPointerException e) { - safe = false; - Debug.stack(e); - Bukkit.getLogger().severe("No such BiomeGrid " + partName); - Bukkit.getLogger().severe("Please check configuration files for errors. Configuration errors will have been reported during initialization."); - Bukkit.getLogger().severe("ONLY report this to Terra if you are SURE your config is error-free."); - Bukkit.getLogger().severe("Terrain will NOT generate properly at this point. Correct your config before using your server!"); - } - } - zone = new BiomeZone(w, c, definedGrids); - - if(template.getGridType().equals(TerraBiomeGrid.Type.RADIAL)) { - BiomeGrid internal = config.getBiomeGrid(template.getRadialInternalGrid()).build(w, c); - grid = new TerraRadialBiomeGrid(w, template.getGridFreqX(), template.getGridFreqZ(), zone, config, template.getRadialGridRadius(), internal); - } else grid = new TerraStandardBiomeGrid(w, template.getGridFreqX(), template.getGridFreqZ(), zone, config); - } - - public static boolean isTerraWorld(World w) { - return w.getGenerator() instanceof TerraChunkGenerator; - } - - 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; - } -} diff --git a/src/main/java/com/dfsek/terra/api/bukkit/BukkitWorldHandle.java b/src/main/java/com/dfsek/terra/api/bukkit/BukkitWorldHandle.java deleted file mode 100644 index 93ace5702..000000000 --- a/src/main/java/com/dfsek/terra/api/bukkit/BukkitWorldHandle.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.dfsek.terra.api.bukkit; - -import com.dfsek.terra.api.generic.world.WorldHandle; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.block.data.BlockData; - -public class BukkitWorldHandle implements WorldHandle { - @Override - public void setBlockData(Block block, BlockData data, boolean physics) { - block.setBlockData(data, physics); - } - - @Override - public BlockData getBlockData(Block block) { - return block.getBlockData(); - } - - @Override - public Material getType(Block block) { - return block.getType(); - } -} diff --git a/src/main/java/com/dfsek/terra/api/generic/TerraPlugin.java b/src/main/java/com/dfsek/terra/api/generic/TerraPlugin.java deleted file mode 100644 index 8926d69ff..000000000 --- a/src/main/java/com/dfsek/terra/api/generic/TerraPlugin.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.dfsek.terra.api.generic; - -import com.dfsek.terra.api.generic.world.WorldHandle; - -public interface TerraPlugin { - WorldHandle getHandle(); -} diff --git a/src/main/java/com/dfsek/terra/api/generic/world/WorldHandle.java b/src/main/java/com/dfsek/terra/api/generic/world/WorldHandle.java deleted file mode 100644 index fb4359d9d..000000000 --- a/src/main/java/com/dfsek/terra/api/generic/world/WorldHandle.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.dfsek.terra.api.generic.world; - -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.block.data.BlockData; - -/** - * Interface to be implemented for world manipulation. - */ -public interface WorldHandle { - void setBlockData(Block block, BlockData data, boolean physics); - - BlockData getBlockData(Block block); - - Material getType(Block block); -} diff --git a/src/main/java/com/dfsek/terra/async/AsyncStructureFinder.java b/src/main/java/com/dfsek/terra/async/AsyncStructureFinder.java deleted file mode 100644 index aa2d203f0..000000000 --- a/src/main/java/com/dfsek/terra/async/AsyncStructureFinder.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.dfsek.terra.async; - -import com.dfsek.terra.Terra; -import com.dfsek.terra.biome.UserDefinedBiome; -import com.dfsek.terra.biome.grid.master.TerraBiomeGrid; -import com.dfsek.terra.generation.items.TerraStructure; -import com.dfsek.terra.procgen.GridSpawn; -import com.dfsek.terra.structure.Rotation; -import com.dfsek.terra.structure.Structure; -import org.bukkit.Location; -import org.bukkit.World; -import org.bukkit.util.Vector; -import org.jetbrains.annotations.NotNull; -import org.polydev.gaea.util.FastRandom; - -import java.util.Random; -import java.util.function.Consumer; - -/** - * Runnable to locate structures asynchronously - */ -public class AsyncStructureFinder extends AsyncFeatureFinder { - public AsyncStructureFinder(TerraBiomeGrid grid, TerraStructure target, @NotNull Location origin, int startRadius, int maxRadius, Consumer callback, Terra main) { - super(grid, target, origin, startRadius, maxRadius, callback, main); - setSearchSize(target.getSpawn().getWidth() + 2 * target.getSpawn().getSeparation()); - } - - /** - * Check if coordinate pair is a valid structure spawn - * - * @param x X coordinate - * @param z Z coordinate - * @return Whether location is a valid spawn for StructureConfig - */ - public boolean isValid(int x, int z, TerraStructure target) { - World world = getWorld(); - Location spawn = target.getSpawn().getChunkSpawn(x, z, world.getSeed()).toLocation(world); - if(!((UserDefinedBiome) grid.getBiome(spawn)).getConfig().getStructures().contains(target)) return false; - Random r2 = new FastRandom(spawn.hashCode()); - Structure struc = target.getStructures().get(r2); - Rotation rotation = Rotation.fromDegrees(r2.nextInt(4) * 90); - for(int y = target.getSpawnStart().get(r2); y > target.getBound().getMin(); y--) { - if(!target.getBound().isInRange(y)) return false; - spawn.setY(y); - if(!struc.checkSpawns(spawn, rotation, main)) continue; - return true; - } - return false; - } - - @Override - public Vector finalizeVector(Vector orig) { - GridSpawn spawn = target.getSpawn(); - return spawn.getChunkSpawn(orig.getBlockX(), orig.getBlockZ(), world.getSeed()); - } -} diff --git a/src/main/java/com/dfsek/terra/biome/UserDefinedBiome.java b/src/main/java/com/dfsek/terra/biome/UserDefinedBiome.java deleted file mode 100644 index 295772b59..000000000 --- a/src/main/java/com/dfsek/terra/biome/UserDefinedBiome.java +++ /dev/null @@ -1,97 +0,0 @@ -package com.dfsek.terra.biome; - -import com.dfsek.terra.config.base.ConfigPack; -import com.dfsek.terra.config.builder.GeneratorBuilder; -import com.dfsek.terra.config.templates.BiomeTemplate; -import com.dfsek.terra.generation.UserDefinedDecorator; -import org.bukkit.World; -import org.polydev.gaea.biome.Biome; -import org.polydev.gaea.biome.Decorator; -import org.polydev.gaea.biome.Generator; -import org.polydev.gaea.structures.features.Feature; - -import java.util.List; - -/** - * Class representing a config-defined biome - */ -public class UserDefinedBiome implements Biome { - private final GeneratorBuilder gen; - private final UserDefinedDecorator decorator; - private final org.bukkit.block.Biome vanilla; - private final String id; - private final BiomeTemplate config; - private final ConfigPack pack; - private UserDefinedBiome erode; - - - public UserDefinedBiome(org.bukkit.block.Biome vanilla, UserDefinedDecorator dec, GeneratorBuilder gen, BiomeTemplate config, ConfigPack pack) { - this.vanilla = vanilla; - this.decorator = dec; - this.gen = gen; - this.id = config.getID(); - this.config = config; - this.pack = pack; - } - - /** - * Gets the Vanilla biome to represent the custom biome. - * - * @return Biome - The Vanilla biome. - */ - @Override - public org.bukkit.block.Biome getVanillaBiome() { - return vanilla; - } - - /** - * Gets the Generator instance used to generate the biome. - * - * @return Generator - The terrain generation instance. - */ - @Override - public Generator getGenerator() { - return gen.build(0); - } - - /** - * Gets a list of Structure Features to be applied to all structures in the biome. - * - * @return List<Feature> - The list of Features. - */ - @Override - public List getStructureFeatures() { - return null; - } - - /** - * Returns the Decorator instance containing information about the population in the biome. - * - * @return Decorator - the Decorator instance. - */ - @Override - public Decorator getDecorator() { - return decorator; - } - - public String getID() { - return id; - } - - public UserDefinedBiome getErode() { - if(erode == null) { - erode = (config.getErode() == null) ? this : pack.getBiome(config.getErode()); - } - return erode; - } - - - public BiomeTemplate getConfig() { - return config; - } - - @Override - public Generator getGenerator(World w) { - return gen.build(w.getSeed()); - } -} diff --git a/src/main/java/com/dfsek/terra/biome/grid/master/TerraBiomeGrid.java b/src/main/java/com/dfsek/terra/biome/grid/master/TerraBiomeGrid.java deleted file mode 100644 index 4b4c8dd92..000000000 --- a/src/main/java/com/dfsek/terra/biome/grid/master/TerraBiomeGrid.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.dfsek.terra.biome.grid.master; - -import com.dfsek.terra.biome.grid.UserDefinedGrid; -import org.bukkit.World; -import org.polydev.gaea.biome.BiomeGrid; - -public abstract class TerraBiomeGrid extends BiomeGrid { - public TerraBiomeGrid(World w, double freq1, double freq2, int sizeX, int sizeZ) { - super(w, freq1, freq2, sizeX, sizeZ); - } - - public abstract UserDefinedGrid getGrid(int x, int z); - - public enum Type { - RADIAL, STANDARD - } -} diff --git a/src/main/java/com/dfsek/terra/carving/CarverCache.java b/src/main/java/com/dfsek/terra/carving/CarverCache.java deleted file mode 100644 index 1706dd705..000000000 --- a/src/main/java/com/dfsek/terra/carving/CarverCache.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.dfsek.terra.carving; - -import com.dfsek.terra.Terra; -import com.dfsek.terra.biome.UserDefinedBiome; -import com.dfsek.terra.biome.grid.master.TerraBiomeGrid; -import org.bukkit.World; -import org.bukkit.util.Vector; -import org.polydev.gaea.biome.Biome; -import org.polydev.gaea.generation.GenerationPhase; -import org.polydev.gaea.math.MathUtil; -import org.polydev.gaea.util.FastRandom; -import org.polydev.gaea.util.GlueList; -import org.polydev.gaea.world.carving.Worm; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Random; - -public class CarverCache { - - private final World w; - private final Map> carvers = new HashMap<>(); - private final Terra main; - - public CarverCache(World w, Terra main) { - this.w = w; - this.main = main; - } - - public List getPoints(int chunkX, int chunkZ, UserDefinedCarver carver) { - if(carvers.size() > main.getTerraConfig().getCacheSize() * 2) carvers.clear(); - return carvers.computeIfAbsent((((long) chunkX) << 32) | (chunkZ & 0xffffffffL), key -> { - TerraBiomeGrid grid = main.getWorld(w).getGrid(); - if(carver.isChunkCarved(w, chunkX, chunkZ, new FastRandom(MathUtil.getCarverChunkSeed(chunkX, chunkZ, w.getSeed() + carver.hashCode())))) { - long seed = MathUtil.getCarverChunkSeed(chunkX, chunkZ, w.getSeed()); - carver.getSeedVar().setValue(seed); - Random r = new FastRandom(seed); - Worm carving = carver.getWorm(seed, new Vector((chunkX << 4) + r.nextInt(16), carver.getConfig().getHeight().get(r), (chunkZ << 4) + r.nextInt(16))); - List points = new GlueList<>(); - for(int i = 0; i < carving.getLength(); i++) { - carving.step(); - Biome biome = grid.getBiome(carving.getRunning().toLocation(w), GenerationPhase.POPULATE); - if(!((UserDefinedBiome) biome).getConfig().getCarvers().containsKey(carver)) { // Stop if we enter a biome this carver is not present in - return new GlueList<>(); - } - points.add(carving.getPoint()); - } - return points; - } - return new GlueList<>(); - }); - } -} diff --git a/src/main/java/com/dfsek/terra/carving/Cavern.java b/src/main/java/com/dfsek/terra/carving/Cavern.java deleted file mode 100644 index 46f94626a..000000000 --- a/src/main/java/com/dfsek/terra/carving/Cavern.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.dfsek.terra.carving; - -import com.dfsek.terra.procgen.GridSpawn; -import com.dfsek.terra.procgen.voxel.DeformedSphere; -import com.dfsek.terra.procgen.voxel.Tube; -import com.dfsek.terra.procgen.voxel.VoxelGeometry; -import org.bukkit.Bukkit; -import org.bukkit.World; -import org.bukkit.util.Vector; -import org.polydev.gaea.math.FastNoiseLite; -import org.polydev.gaea.math.MathUtil; -import org.polydev.gaea.util.FastRandom; - -import java.util.Random; - -public class Cavern { - private final Node node; - private final long seed; - - public Cavern(World w) { - this.node = new Node(w); - this.seed = w.getSeed(); - } - - public VoxelGeometry carveChunk(int chunkX, int chunkZ) { - long seedC = MathUtil.getCarverChunkSeed(chunkX, chunkZ, seed); - Random chunk = new FastRandom(seedC); - Vector org = node.getNodeLocation((chunkX << 4) + 8, (chunkZ << 4) + 8).clone().setY(chunk.nextInt(128)); - VoxelGeometry carve = VoxelGeometry.getBlank(); - - FastNoiseLite smpl = new FastNoiseLite((int) seedC); - smpl.setFrequency(0.01f); - smpl.setNoiseType(FastNoiseLite.NoiseType.OpenSimplex2); - Bukkit.getLogger().info("Cavern: " + org.toString()); - carve.merge(new DeformedSphere(org.clone(), chunk.nextInt(4) + 3, 0.75, smpl)); - - Vector _00 = new Vector(org.getX() + 16, new FastRandom(MathUtil.getCarverChunkSeed(chunkX + 1, chunkZ, seed)).nextInt(128), org.getZ()); - - carve.merge(new Tube(org, _00, 4)); - return carve; - } - - public static class Node { - private final long seed; - private final GridSpawn spawn = new GridSpawn(16, 0, 0); - - public Node(World w) { - this.seed = w.getSeed(); - } - - public Vector getNodeLocation(int x, int z) { - return spawn.getNearestSpawn(x, z, seed); - } - } -} diff --git a/src/main/java/com/dfsek/terra/command/OreCommand.java b/src/main/java/com/dfsek/terra/command/OreCommand.java deleted file mode 100644 index 337f8848f..000000000 --- a/src/main/java/com/dfsek/terra/command/OreCommand.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.dfsek.terra.command; - -import org.bukkit.World; -import org.bukkit.command.Command; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; -import org.polydev.gaea.command.WorldCommand; - -import java.util.Collections; -import java.util.List; - -public class OreCommand extends WorldCommand { - public OreCommand(org.polydev.gaea.command.Command parent) { - super(parent); - } - - @Override - public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args, World w) { - /* - Block bl = sender.getTargetBlockExact(25); - if(args.length > 0) { - OreConfig ore = TerraWorld.getWorld(w).getConfig().getOre(args[0]); - if(ore == null) { - LangUtil.send("command.ore.invalid-ore", sender, args[0]); - return true; - } - if(bl == null) { - LangUtil.send("command.ore.out-of-range", sender); - return true; - } - Vector source = new Vector(FastMath.floorMod(bl.getX(), 16), bl.getY(), FastMath.floorMod(bl.getZ(), 16)); - ore.doVein(source, bl.getChunk(), new FastRandom()); - } else { - LangUtil.send("command.ore.main-menu", sender); - } - */ - return true; - - - // TODO: implementation - } - - @Override - public String getName() { - return "ore"; - } - - @Override - public List getSubCommands() { - return Collections.emptyList(); - } - - @Override - public int arguments() { - return 1; - } - - @Override - public List getTabCompletions(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) { - return Collections.emptyList(); - } -} diff --git a/src/main/java/com/dfsek/terra/command/biome/BiomeLocateCommand.java b/src/main/java/com/dfsek/terra/command/biome/BiomeLocateCommand.java deleted file mode 100644 index 4f7765547..000000000 --- a/src/main/java/com/dfsek/terra/command/biome/BiomeLocateCommand.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.dfsek.terra.command.biome; - -import com.dfsek.terra.Terra; -import com.dfsek.terra.async.AsyncBiomeFinder; -import com.dfsek.terra.biome.UserDefinedBiome; -import com.dfsek.terra.config.lang.LangUtil; -import com.dfsek.terra.generation.TerraChunkGenerator; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.World; -import org.bukkit.command.Command; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; -import org.polydev.gaea.command.WorldCommand; - -import java.util.Collections; -import java.util.List; -import java.util.stream.Collectors; - -public class BiomeLocateCommand extends WorldCommand { - private final boolean tp; - - public BiomeLocateCommand(org.polydev.gaea.command.Command parent, boolean teleport) { - super(parent); - this.tp = teleport; - } - - @Override - public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args, World world) { - String id = args[0]; - int maxRadius; - try { - maxRadius = Integer.parseInt(args[1]); - } catch(NumberFormatException e) { - LangUtil.send("command.biome.invalid-radius", sender, args[1]); - return true; - } - UserDefinedBiome b; - try { - b = ((Terra) getMain()).getWorld(world).getConfig().getBiome(id); - } catch(IllegalArgumentException | NullPointerException e) { - LangUtil.send("command.biome.invalid", sender, id); - return true; - } - Bukkit.getScheduler().runTaskAsynchronously(getMain(), new AsyncBiomeFinder(((Terra) getMain()).getWorld(world).getGrid(), b, sender.getLocation().clone().multiply((1D / ((Terra) getMain()).getTerraConfig().getBiomeSearchResolution())), 0, maxRadius, location -> { - if(location != null) { - LangUtil.send("command.biome.biome-found", sender, String.valueOf(location.getBlockX()), String.valueOf(location.getBlockZ())); - if(tp) { - Location l = new Location(sender.getWorld(), location.getX(), sender.getLocation().getY(), location.getZ()); - Bukkit.getScheduler().runTask(getMain(), () -> sender.teleport(l)); - } - } else LangUtil.send("command.biome.unable-to-locate", sender); - }, (Terra) getMain())); - return true; - } - - @Override - public String getName() { - return tp ? "teleport" : "locate"; - } - - @Override - public List getSubCommands() { - return Collections.emptyList(); - } - - @Override - public int arguments() { - return 2; - } - - @Override - public List getTabCompletions(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) { - if(!(sender instanceof Player) || !(((Player) sender).getWorld().getGenerator() instanceof TerraChunkGenerator)) - return Collections.emptyList(); - List ids = ((Terra) getMain()).getWorld(((Player) sender).getWorld()).getConfig().getBiomeIDs(); - if(args.length == 1) - return ids.stream().filter(string -> string.toUpperCase().startsWith(args[0].toUpperCase())).collect(Collectors.toList()); - return Collections.emptyList(); - } -} diff --git a/src/main/java/com/dfsek/terra/command/structure/ExportCommand.java b/src/main/java/com/dfsek/terra/command/structure/ExportCommand.java deleted file mode 100644 index 58df083d5..000000000 --- a/src/main/java/com/dfsek/terra/command/structure/ExportCommand.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.dfsek.terra.command.structure; - -import com.dfsek.terra.config.lang.LangUtil; -import com.dfsek.terra.structure.InitializationException; -import com.dfsek.terra.structure.Structure; -import com.dfsek.terra.util.structure.WorldEditUtil; -import org.bukkit.Location; -import org.bukkit.command.Command; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; -import org.polydev.gaea.command.PlayerCommand; - -import java.io.File; -import java.io.IOException; -import java.util.Collections; -import java.util.List; - -public class ExportCommand extends PlayerCommand { - public ExportCommand(org.polydev.gaea.command.Command parent) { - super(parent); - } - - @Override - public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { - Location[] l = WorldEditUtil.getSelectionLocations(sender); - if(l == null) return true; - Location l1 = l[0]; - Location l2 = l[1]; - Structure structure; - try { - structure = new Structure(l1, l2, args[0]); - } catch(InitializationException e) { - sender.sendMessage(e.getMessage()); - return true; - } - try { - File file = new File(getMain().getDataFolder() + File.separator + "export" + File.separator + "structures", args[0] + ".tstructure"); - //noinspection ResultOfMethodCallIgnored - file.getParentFile().mkdirs(); - //noinspection ResultOfMethodCallIgnored - file.createNewFile(); - structure.save(file); - LangUtil.send("command.structure.export", sender, file.getAbsolutePath()); - } catch(IOException e) { - e.printStackTrace(); - } - return true; - } - - @Override - public String getName() { - return "export"; - } - - @Override - public List getSubCommands() { - return Collections.emptyList(); - } - - @Override - public int arguments() { - return 1; - } - - @Override - public List getTabCompletions(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) { - return Collections.emptyList(); - } -} diff --git a/src/main/java/com/dfsek/terra/command/structure/LocateCommand.java b/src/main/java/com/dfsek/terra/command/structure/LocateCommand.java deleted file mode 100644 index 407a6f10a..000000000 --- a/src/main/java/com/dfsek/terra/command/structure/LocateCommand.java +++ /dev/null @@ -1,86 +0,0 @@ -package com.dfsek.terra.command.structure; - -import com.dfsek.terra.Terra; -import com.dfsek.terra.async.AsyncStructureFinder; -import com.dfsek.terra.config.lang.LangUtil; -import com.dfsek.terra.generation.TerraChunkGenerator; -import com.dfsek.terra.generation.items.TerraStructure; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.World; -import org.bukkit.command.Command; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; -import org.polydev.gaea.command.WorldCommand; - -import java.util.Collections; -import java.util.List; -import java.util.Objects; -import java.util.stream.Collectors; - -public class LocateCommand extends WorldCommand { - private final boolean tp; - - public LocateCommand(org.polydev.gaea.command.Command parent, boolean tp) { - super(parent); - this.tp = tp; - } - - @Override - public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args, World world) { - String id = args[0]; - int maxRadius; - try { - maxRadius = Integer.parseInt(args[1]); - } catch(NumberFormatException e) { - LangUtil.send("command.structure.invalid-radius", sender, args[1]); - return true; - } - TerraStructure s; - try { - s = Objects.requireNonNull(((Terra) getMain()).getWorld(world).getConfig().getStructure(id)); - } catch(IllegalArgumentException | NullPointerException e) { - LangUtil.send("command.structure.invalid", sender, id); - return true; - } - Bukkit.getScheduler().runTaskAsynchronously(getMain(), new AsyncStructureFinder(((Terra) getMain()).getWorld(world).getGrid(), s, sender.getLocation(), 0, maxRadius, (location) -> { - if(sender.isOnline()) { - if(location != null) { - sender.sendMessage("Located structure at (" + location.getBlockX() + ", " + location.getBlockZ() + ")."); - if(tp) { - int finalX = location.getBlockX(); - int finalZ = location.getBlockZ(); - Bukkit.getScheduler().runTask(getMain(), () -> sender.teleport(new Location(sender.getWorld(), finalX, sender.getLocation().getY(), finalZ))); - } - } else sender.sendMessage("Unable to locate structure. "); - } - }, (Terra) getMain())); - return true; - } - - @Override - public String getName() { - return tp ? "teleport" : "locate"; - } - - @Override - public List getSubCommands() { - return Collections.emptyList(); - } - - @Override - public int arguments() { - return 2; - } - - @Override - public List getTabCompletions(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) { - if(!(sender instanceof Player) || !(((Player) sender).getWorld().getGenerator() instanceof TerraChunkGenerator)) - return Collections.emptyList(); - List ids = ((Terra) getMain()).getWorld(((Player) sender).getWorld()).getConfig().getStructureIDs(); - if(args.length == 1) - return ids.stream().filter(string -> string.toUpperCase().startsWith(args[0].toUpperCase())).collect(Collectors.toList()); - return Collections.emptyList(); - } -} diff --git a/src/main/java/com/dfsek/terra/command/structure/SpawnCommand.java b/src/main/java/com/dfsek/terra/command/structure/SpawnCommand.java deleted file mode 100644 index b9fd6534d..000000000 --- a/src/main/java/com/dfsek/terra/command/structure/SpawnCommand.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.dfsek.terra.command.structure; - -import com.dfsek.terra.Terra; -import com.dfsek.terra.structure.StructureSpawnRequirement; -import org.bukkit.Location; -import org.bukkit.World; -import org.bukkit.command.Command; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; -import org.polydev.gaea.command.DebugCommand; -import org.polydev.gaea.command.WorldCommand; - -import java.util.Collections; -import java.util.List; - -public class SpawnCommand extends WorldCommand implements DebugCommand { - public SpawnCommand(org.polydev.gaea.command.Command parent) { - super(parent); - } - - @Override - public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args, World world) { - Location p = sender.getLocation(); - int x = p.getBlockX(); - int y = p.getBlockY(); - int z = p.getBlockZ(); - boolean air = StructureSpawnRequirement.AIR.getInstance(world, (Terra) getMain()).matches(x, y, z); - boolean ground = StructureSpawnRequirement.LAND.getInstance(world, (Terra) getMain()).matches(x, y, z); - boolean sea = StructureSpawnRequirement.OCEAN.getInstance(world, (Terra) getMain()).matches(x, y, z); - - sender.sendMessage("AIR: " + air + "\nLAND: " + ground + "\nOCEAN: " + sea); - return true; - } - - @Override - public String getName() { - return "spawn"; - } - - @Override - public List getSubCommands() { - return Collections.emptyList(); - } - - @Override - public int arguments() { - return 0; - } - - @Override - public List getTabCompletions(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) { - return Collections.emptyList(); - } -} diff --git a/src/main/java/com/dfsek/terra/command/structure/load/LoadFullCommand.java b/src/main/java/com/dfsek/terra/command/structure/load/LoadFullCommand.java deleted file mode 100644 index 1aaed376e..000000000 --- a/src/main/java/com/dfsek/terra/command/structure/load/LoadFullCommand.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.dfsek.terra.command.structure.load; - -import com.dfsek.terra.Terra; -import com.dfsek.terra.config.lang.LangUtil; -import com.dfsek.terra.structure.Rotation; -import com.dfsek.terra.structure.Structure; -import org.bukkit.command.Command; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; -import org.polydev.gaea.command.DebugCommand; - -import java.io.File; -import java.io.IOException; -import java.util.Collections; -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -public class LoadFullCommand extends LoadCommand implements DebugCommand { - private final boolean chunk; - - public LoadFullCommand(org.polydev.gaea.command.Command parent, boolean chunk) { - super(parent); - this.chunk = chunk; - } - - @Override - public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String s, @NotNull String[] args) { - try { - Rotation r; - try { - r = Rotation.fromDegrees(Integer.parseInt(args[1])); - } catch(NumberFormatException e) { - LangUtil.send("command.structure.invalid-rotation", sender, args[1]); - return true; - } - Structure struc = Structure.load(new File(getMain().getDataFolder() + File.separator + "export" + File.separator + "structures", args[0] + ".tstructure")); - if(chunk) struc.paste(sender.getLocation(), sender.getLocation().getChunk(), r, (Terra) getMain()); - else struc.paste(sender.getLocation(), r, (Terra) getMain()); - //sender.sendMessage(String.valueOf(struc.checkSpawns(sender.getLocation(), r))); - } catch(IOException e) { - e.printStackTrace(); - LangUtil.send("command.structure.invalid", sender, args[0]); - } - return true; - } - - @Override - public String getName() { - return chunk ? "chunk" : "full"; - } - - @Override - public List getSubCommands() { - return Collections.emptyList(); - } - - @Override - public int arguments() { - return 2; - } - - @Override - public List getTabCompletions(@NotNull CommandSender commandSender, @NotNull String s, @NotNull String[] args) { - switch(args.length) { - case 1: - return getStructureNames().stream().filter(string -> string.toUpperCase().startsWith(args[0].toUpperCase())).collect(Collectors.toList()); - case 2: - return Stream.of("0", "90", "180", "270").filter(string -> string.toUpperCase().startsWith(args[1].toUpperCase())).collect(Collectors.toList()); - } - return Collections.emptyList(); - } -} diff --git a/src/main/java/com/dfsek/terra/command/structure/load/LoadRawCommand.java b/src/main/java/com/dfsek/terra/command/structure/load/LoadRawCommand.java deleted file mode 100644 index 94fb53580..000000000 --- a/src/main/java/com/dfsek/terra/command/structure/load/LoadRawCommand.java +++ /dev/null @@ -1,116 +0,0 @@ -package com.dfsek.terra.command.structure.load; - -import com.dfsek.terra.Terra; -import com.dfsek.terra.api.generic.world.WorldHandle; -import com.dfsek.terra.config.lang.LangUtil; -import com.dfsek.terra.structure.Structure; -import com.dfsek.terra.structure.StructureContainedBlock; -import com.dfsek.terra.structure.StructureInfo; -import com.dfsek.terra.structure.StructureSpawnRequirement; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.block.Sign; -import org.bukkit.command.Command; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; -import org.polydev.gaea.command.DebugCommand; - -import java.io.File; -import java.io.IOException; -import java.util.Collections; -import java.util.List; -import java.util.stream.Collectors; - -public class LoadRawCommand extends LoadCommand implements DebugCommand { - public LoadRawCommand(org.polydev.gaea.command.Command parent) { - super(parent); - } - - private static void setTerraSign(Sign sign, String data) { - sign.setLine(0, "[TERRA]"); - if(data.length() > 16) { - sign.setLine(2, data.substring(0, 16)); - sign.setLine(3, data.substring(16)); - } else sign.setLine(2, data); - } - - @Override - public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String s, @NotNull String[] args) { - try { - WorldHandle handle = ((Terra) getMain()).getHandle(); - Structure struc = Structure.load(new File(getMain().getDataFolder() + File.separator + "export" + File.separator + "structures", args[0] + ".tstructure")); - StructureInfo info = struc.getStructureInfo(); - int centerX = info.getCenterX(); - int centerZ = info.getCenterZ(); - for(StructureContainedBlock[][] level0 : struc.getRawStructure()) { - for(StructureContainedBlock[] level1 : level0) { - for(StructureContainedBlock block : level1) { - Location bLocation = sender.getLocation().add(block.getX() - centerX, block.getY(), block.getZ() - centerZ); - if(!block.getPull().equals(StructureContainedBlock.Pull.NONE)) { - handle.setBlockData(bLocation.getBlock(), Material.OAK_SIGN.createBlockData(), false); - Sign sign = (Sign) bLocation.getBlock().getState(); - sign.setLine(1, "[PULL=" + block.getPull() + "_" + block.getPullOffset() + "]"); - String data = block.getBlockData().getAsString(true); - setTerraSign(sign, data); - sign.update(); - } else if(!block.getRequirement().equals(StructureSpawnRequirement.BLANK)) { - handle.setBlockData(bLocation.getBlock(), Material.OAK_SIGN.createBlockData(), false); - Sign sign = (Sign) bLocation.getBlock().getState(); - sign.setLine(1, "[SPAWN=" + block.getRequirement() + "]"); - String data = block.getBlockData().getAsString(true); - setTerraSign(sign, data); - sign.update(); - } else { - handle.setBlockData(bLocation.getBlock(), block.getBlockData(), false); - if(block.getState() != null) { - block.getState().getState(bLocation.getBlock().getState()).update(true, false); - } - } - } - } - } - - for(int y = 0; y < struc.getStructureInfo().getSizeY(); y++) { - StructureContainedBlock block = struc.getRawStructure()[centerX][centerZ][y]; - if(block.getRequirement().equals(StructureSpawnRequirement.BLANK) && block.getPull().equals(StructureContainedBlock.Pull.NONE)) { - Location bLocation = sender.getLocation().add(block.getX() - centerX, block.getY(), block.getZ() - centerZ); - handle.setBlockData(bLocation.getBlock(), Material.OAK_SIGN.createBlockData(), false); - Sign sign = (Sign) bLocation.getBlock().getState(); - sign.setLine(1, "[CENTER]"); - String data = block.getBlockData().getAsString(true); - setTerraSign(sign, data); - sign.update(); - break; - } - } - } catch(IOException e) { - e.printStackTrace(); - LangUtil.send("command.structure.invalid", sender, args[0]); - } - return true; - } - - @Override - public String getName() { - return "raw"; - } - - @Override - public List getSubCommands() { - return Collections.emptyList(); - } - - @Override - public int arguments() { - return 1; - } - - @Override - public List getTabCompletions(@NotNull CommandSender commandSender, @NotNull String s, @NotNull String[] args) { - if(args.length == 1) { - return getStructureNames().stream().filter(string -> string.toUpperCase().startsWith(args[0].toUpperCase())).collect(Collectors.toList()); - } - return Collections.emptyList(); - } -} diff --git a/src/main/java/com/dfsek/terra/config/factories/StructureFactory.java b/src/main/java/com/dfsek/terra/config/factories/StructureFactory.java deleted file mode 100644 index 5f578dc19..000000000 --- a/src/main/java/com/dfsek/terra/config/factories/StructureFactory.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.dfsek.terra.config.factories; - -import com.dfsek.tectonic.exception.LoadException; -import com.dfsek.terra.Terra; -import com.dfsek.terra.config.templates.StructureTemplate; -import com.dfsek.terra.generation.items.TerraStructure; - -public class StructureFactory implements TerraFactory { - @Override - public TerraStructure build(StructureTemplate config, Terra main) throws LoadException { - return new TerraStructure(config.getStructures(), config.getBound(), config.getY(), config.getSpawn(), config.getLoot(), config); - } -} diff --git a/src/main/java/com/dfsek/terra/config/loaders/LootTableLoader.java b/src/main/java/com/dfsek/terra/config/loaders/LootTableLoader.java deleted file mode 100644 index 460335d80..000000000 --- a/src/main/java/com/dfsek/terra/config/loaders/LootTableLoader.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.dfsek.terra.config.loaders; - -import com.dfsek.tectonic.exception.LoadException; -import com.dfsek.tectonic.loading.ConfigLoader; -import com.dfsek.tectonic.loading.TypeLoader; -import com.dfsek.terra.config.files.Loader; -import org.apache.commons.io.IOUtils; -import org.json.simple.parser.ParseException; -import org.polydev.gaea.structures.loot.LootTable; - -import java.io.IOException; -import java.io.InputStream; -import java.lang.reflect.Type; -import java.nio.charset.StandardCharsets; - -public class LootTableLoader implements TypeLoader { - private final Loader loader; - - public LootTableLoader(Loader loader) { - this.loader = loader; - } - - @Override - public LootTable load(Type type, Object o, ConfigLoader configLoader) throws LoadException { - try(InputStream stream = loader.get("structures/loot/" + o + ".json")) { - return new LootTable(IOUtils.toString(stream, StandardCharsets.UTF_8)); - } catch(IOException | ParseException | NullPointerException e) { - throw new LoadException("Unable to load loot", e); - } - } -} diff --git a/src/main/java/com/dfsek/terra/config/loaders/StructureLoader.java b/src/main/java/com/dfsek/terra/config/loaders/StructureLoader.java deleted file mode 100644 index 3f29eca06..000000000 --- a/src/main/java/com/dfsek/terra/config/loaders/StructureLoader.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.dfsek.terra.config.loaders; - -import com.dfsek.tectonic.exception.LoadException; -import com.dfsek.tectonic.loading.ConfigLoader; -import com.dfsek.tectonic.loading.TypeLoader; -import com.dfsek.terra.config.files.Loader; -import com.dfsek.terra.structure.Structure; - -import java.io.IOException; -import java.io.InputStream; -import java.lang.reflect.Type; - -public class StructureLoader implements TypeLoader { - private final Loader loader; - - public StructureLoader(Loader loader) { - this.loader = loader; - } - - @Override - public Structure load(Type type, Object o, ConfigLoader configLoader) throws LoadException { - try(InputStream stream = loader.get("structures/data/" + o + ".tstructure")) { - return Structure.fromStream(stream); - } catch(IOException | ClassNotFoundException e) { - throw new LoadException("Unable to load structure", e); - } - } -} diff --git a/src/main/java/com/dfsek/terra/config/loaders/config/StructureFeatureLoader.java b/src/main/java/com/dfsek/terra/config/loaders/config/StructureFeatureLoader.java deleted file mode 100644 index 35acae3ee..000000000 --- a/src/main/java/com/dfsek/terra/config/loaders/config/StructureFeatureLoader.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.dfsek.terra.config.loaders.config; - -import com.dfsek.tectonic.exception.LoadException; -import com.dfsek.tectonic.loading.ConfigLoader; -import com.dfsek.tectonic.loading.TypeLoader; -import com.dfsek.terra.structure.features.EntityFeature; -import com.dfsek.terra.structure.features.Feature; -import com.dfsek.terra.util.MaterialSet; -import org.bukkit.entity.EntityType; -import org.polydev.gaea.math.Range; - -import java.lang.reflect.Type; -import java.util.Map; - -@SuppressWarnings({"unchecked", "SwitchStatementWithTooFewBranches"}) // We will do more features laterTM -public class StructureFeatureLoader implements TypeLoader { - @Override - public Feature load(Type type, Object o, ConfigLoader configLoader) throws LoadException { - Map map = (Map) o; - switch((String) map.get("type")) { - case "ENTITY_FEATURE": - MaterialSet stand = (MaterialSet) configLoader.loadType(MaterialSet.class, map.get("spawnable-on")); - MaterialSet in = (MaterialSet) configLoader.loadType(MaterialSet.class, map.get("spawnable-in")); - Range amount = (Range) configLoader.loadType(Range.class, map.get("amount")); - EntityType entityType = (EntityType) configLoader.loadType(EntityType.class, map.get("entity")); - Integer height = (Integer) configLoader.loadType(Integer.class, map.get("in-height")); - return new EntityFeature(entityType, amount, stand, in, height); - default: - throw new LoadException("Invalid feature type: \"" + map.get("type") + "\""); - } - } -} diff --git a/src/main/java/com/dfsek/terra/config/templates/StructureTemplate.java b/src/main/java/com/dfsek/terra/config/templates/StructureTemplate.java deleted file mode 100644 index 0bbab8b7c..000000000 --- a/src/main/java/com/dfsek/terra/config/templates/StructureTemplate.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.dfsek.terra.config.templates; - -import com.dfsek.tectonic.annotations.Abstractable; -import com.dfsek.tectonic.annotations.Default; -import com.dfsek.tectonic.annotations.Value; -import com.dfsek.terra.procgen.GridSpawn; -import com.dfsek.terra.structure.Structure; -import com.dfsek.terra.structure.features.Feature; -import org.polydev.gaea.math.ProbabilityCollection; -import org.polydev.gaea.math.Range; -import org.polydev.gaea.structures.loot.LootTable; -import org.polydev.gaea.util.GlueList; - -import java.util.List; -import java.util.Map; - -@SuppressWarnings({"unused", "FieldMayBeFinal"}) -public class StructureTemplate extends AbstractableTemplate { - @Value("id") - private String id; - - @Value("files") - @Abstractable - private ProbabilityCollection structures; - - @Value("spawn.start") - @Abstractable - private Range y; - - @Value("spawn.bound") - @Abstractable - private Range bound; - - @Value("spawn") - @Abstractable - private GridSpawn spawn; - - @Value("loot") - @Abstractable - private Map loot; - - @Value("features") - @Abstractable - @Default - private List features = new GlueList<>(); - - public Map getLoot() { - return loot; - } - - public String getID() { - return id; - } - - public ProbabilityCollection getStructures() { - return structures; - } - - public Range getY() { - return y; - } - - public Range getBound() { - return bound; - } - - public List getFeatures() { - return features; - } - - public GridSpawn getSpawn() { - return spawn; - } -} diff --git a/src/main/java/com/dfsek/terra/generation/ElevationInterpolator.java b/src/main/java/com/dfsek/terra/generation/ElevationInterpolator.java deleted file mode 100644 index e02ddb546..000000000 --- a/src/main/java/com/dfsek/terra/generation/ElevationInterpolator.java +++ /dev/null @@ -1,79 +0,0 @@ -package com.dfsek.terra.generation; - -import com.dfsek.terra.biome.grid.master.TerraBiomeGrid; -import com.dfsek.terra.generation.config.WorldGenerator; -import org.polydev.gaea.generation.GenerationPhase; -import org.polydev.gaea.math.Interpolator; - -public class ElevationInterpolator { - private final WorldGenerator[][] gens = new WorldGenerator[10][10]; - private final double[][] values = new double[18][18]; - private final int xOrigin; - private final int zOrigin; - private final TerraBiomeGrid grid; - - public ElevationInterpolator(int chunkX, int chunkZ, TerraBiomeGrid grid) { - this.xOrigin = chunkX << 4; - this.zOrigin = chunkZ << 4; - this.grid = grid; - - for(int x = -2; x < 8; x++) { - for(int z = -2; z < 8; z++) { - gens[x + 2][z + 2] = (WorldGenerator) grid.getBiome(xOrigin + (x << 2), zOrigin + (z << 2), GenerationPhase.BASE).getGenerator(); - } - } - - for(byte x = -1; x <= 16; x++) { - for(byte z = -1; z <= 16; z++) { - WorldGenerator generator = getGenerator(x, z); - if(compareGens((x / 4), (z / 4)) && generator.interpolateElevation()) { - Interpolator interpolator = new Interpolator(biomeAvg(x / 4, z / 4), - biomeAvg((x / 4) + 1, z / 4), - biomeAvg(x / 4, (z / 4) + 1), - biomeAvg((x / 4) + 1, (z / 4) + 1), - Interpolator.Type.LINEAR); - values[x + 1][z + 1] = interpolator.bilerp((double) (x % 4) / 4, (double) (z % 4) / 4); - } else values[x + 1][z + 1] = elevate(generator, xOrigin + x, zOrigin + z); - } - } - } - - private WorldGenerator getGenerator(int x, int z) { - return (WorldGenerator) grid.getBiome(xOrigin + x, zOrigin + z, GenerationPhase.BASE).getGenerator(); - } - - private WorldGenerator getStoredGen(int x, int z) { - return gens[x + 2][z + 2]; - } - - private boolean compareGens(int x, int z) { - WorldGenerator comp = getStoredGen(x, z); - - for(int xi = x - 2; xi <= x + 2; xi++) { - for(int zi = z - 2; zi <= z + 2; zi++) { - if(!comp.equals(getStoredGen(xi, zi))) return true; - } - } - return false; - } - - private double biomeAvg(int x, int z) { - return (elevate(getStoredGen(x + 1, z), (x << 2) + 4 + xOrigin, (z << 2) + zOrigin) - + elevate(getStoredGen(x - 1, z), (x << 2) - 4 + xOrigin, (z << 2) + zOrigin) - + elevate(getStoredGen(x, z + 1), (x << 2) + xOrigin, (z << 2) + 4 + zOrigin) - + elevate(getStoredGen(x, z - 1), (x << 2) + xOrigin, (z << 2) - 4 + zOrigin) - + elevate(getStoredGen(x, z), (x << 2) + xOrigin, (z << 2) + zOrigin) - + elevate(getStoredGen(x - 1, z - 1), (x << 2) + xOrigin, (z << 2) + zOrigin) - + elevate(getStoredGen(x - 1, z + 1), (x << 2) + xOrigin, (z << 2) + zOrigin) - + elevate(getStoredGen(x + 1, z - 1), (x << 2) + xOrigin, (z << 2) + zOrigin) - + elevate(getStoredGen(x + 1, z + 1), (x << 2) + xOrigin, (z << 2) + zOrigin)) / 9D; - } - - private double elevate(WorldGenerator g, int x, int z) { - return g.getElevation(x, z); - } - - public double getElevation(int x, int z) { - return values[x + 1][z + 1]; - } -} diff --git a/src/main/java/com/dfsek/terra/generation/Sampler.java b/src/main/java/com/dfsek/terra/generation/Sampler.java deleted file mode 100644 index 1bc098331..000000000 --- a/src/main/java/com/dfsek/terra/generation/Sampler.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.dfsek.terra.generation; - -import net.jafama.FastMath; -import org.polydev.gaea.math.ChunkInterpolator; - -public class Sampler { - private final ChunkInterpolator interpolator; - private final ElevationInterpolator elevationInterpolator; - - public Sampler(ChunkInterpolator interpolator, ElevationInterpolator elevationInterpolator) { - this.interpolator = interpolator; - this.elevationInterpolator = elevationInterpolator; - } - - public double sample(double x, double y, double z) { - return interpolator.getNoise(x, y, z) + elevationInterpolator.getElevation(FastMath.roundToInt(x), FastMath.roundToInt(z)); - } -} diff --git a/src/main/java/com/dfsek/terra/generation/TerraChunkGenerator.java b/src/main/java/com/dfsek/terra/generation/TerraChunkGenerator.java deleted file mode 100644 index da0fd8892..000000000 --- a/src/main/java/com/dfsek/terra/generation/TerraChunkGenerator.java +++ /dev/null @@ -1,212 +0,0 @@ -package com.dfsek.terra.generation; - -import com.dfsek.terra.Terra; -import com.dfsek.terra.TerraWorld; -import com.dfsek.terra.biome.UserDefinedBiome; -import com.dfsek.terra.config.base.ConfigPack; -import com.dfsek.terra.config.lang.LangUtil; -import com.dfsek.terra.config.templates.BiomeTemplate; -import com.dfsek.terra.debug.Debug; -import com.dfsek.terra.population.CavePopulator; -import com.dfsek.terra.population.FloraPopulator; -import com.dfsek.terra.population.OrePopulator; -import com.dfsek.terra.population.StructurePopulator; -import com.dfsek.terra.population.TreePopulator; -import com.dfsek.terra.util.PaletteUtil; -import com.dfsek.terra.util.SlabUtil; -import org.bukkit.Chunk; -import org.bukkit.World; -import org.bukkit.block.data.BlockData; -import org.bukkit.generator.BlockPopulator; -import org.bukkit.util.Vector; -import org.jetbrains.annotations.NotNull; -import org.polydev.gaea.biome.Biome; -import org.polydev.gaea.generation.GaeaChunkGenerator; -import org.polydev.gaea.generation.GenerationPhase; -import org.polydev.gaea.generation.GenerationPopulator; -import org.polydev.gaea.math.ChunkInterpolator; -import org.polydev.gaea.population.PopulationManager; -import org.polydev.gaea.profiler.ProfileFuture; -import org.polydev.gaea.profiler.WorldProfiler; -import org.polydev.gaea.world.palette.Palette; - -import java.io.FileNotFoundException; -import java.io.IOException; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Random; -import java.util.logging.Level; - - -public class TerraChunkGenerator extends GaeaChunkGenerator { - private static final Map popMap = new HashMap<>(); - private final PopulationManager popMan; - private final ConfigPack configPack; - private boolean needsLoad = true; - private final Terra main; - - public ConfigPack getConfigPack() { - return configPack; - } - - - public TerraChunkGenerator(ConfigPack c, Terra main) { - super(ChunkInterpolator.InterpolationType.TRILINEAR); - popMan = new PopulationManager(main); - this.configPack = c; - this.main = main; - popMan.attach(new OrePopulator(main)); - popMan.attach(new TreePopulator(main)); - popMan.attach(new FloraPopulator(main)); - } - - public static synchronized void saveAll() { - for(Map.Entry e : popMap.entrySet()) { - try { - e.getValue().saveBlocks(e.getKey()); - Debug.info("Saved data for world " + e.getKey().getName()); - } catch(IOException ioException) { - ioException.printStackTrace(); - } - } - } - - public static synchronized void fixChunk(Chunk c) { - if(!(c.getWorld().getGenerator() instanceof TerraChunkGenerator)) throw new IllegalArgumentException(); - popMap.get(c.getWorld()).checkNeighbors(c.getX(), c.getZ(), c.getWorld()); - } - - @Override - public void attachProfiler(WorldProfiler p) { - super.attachProfiler(p); - popMan.attachProfiler(p); - } - - @Override - @SuppressWarnings("try") - public ChunkData generateBase(@NotNull World world, @NotNull Random random, int chunkX, int chunkZ, ChunkInterpolator interpolator) { - if(needsLoad) load(world); // Load population data for world. - ChunkData chunk = createChunkData(world); - TerraWorld tw = main.getWorld(world); - if(!tw.isSafe()) return chunk; - int xOrig = (chunkX << 4); - int zOrig = (chunkZ << 4); - org.polydev.gaea.biome.BiomeGrid grid = getBiomeGrid(world); - - ElevationInterpolator elevationInterpolator; - try(ProfileFuture ignore = tw.getProfiler().measure("ElevationTime")) { - elevationInterpolator = new ElevationInterpolator(chunkX, chunkZ, tw.getGrid()); - } - - Sampler sampler = new Sampler(interpolator, elevationInterpolator); - - for(byte x = 0; x < 16; x++) { - for(byte z = 0; z < 16; z++) { - int paletteLevel = 0; - - int cx = xOrig + x; - int cz = zOrig + z; - - Biome b = grid.getBiome(xOrig + x, zOrig + z, GenerationPhase.PALETTE_APPLY); - BiomeTemplate c = ((UserDefinedBiome) b).getConfig(); - - int sea = c.getSeaLevel(); - Palette seaPalette = c.getOceanPalette(); - - boolean justSet = false; - BlockData data = null; - for(int y = world.getMaxHeight() - 1; y >= 0; y--) { - if(sampler.sample(x, y, z) > 0) { - justSet = true; - data = PaletteUtil.getPalette(x, y, z, c, sampler).get(paletteLevel, cx, cz); - chunk.setBlock(x, y, z, data); - if(paletteLevel == 0 && c.doSlabs() && y < 255) { - SlabUtil.prepareBlockPartFloor(data, chunk.getBlockData(x, y + 1, z), chunk, new Vector(x, y + 1, z), c.getSlabPalettes(), - c.getStairPalettes(), c.getSlabThreshold(), sampler); - } - paletteLevel++; - } else if(y <= sea) { - chunk.setBlock(x, y, z, seaPalette.get(sea - y, x + xOrig, z + zOrig)); - if(justSet && c.doSlabs()) { - SlabUtil.prepareBlockPartCeiling(data, chunk.getBlockData(x, y, z), chunk, new Vector(x, y, z), c.getSlabPalettes(), c.getStairPalettes(), c.getSlabThreshold(), sampler); - } - justSet = false; - paletteLevel = 0; - } else { - if(justSet && c.doSlabs()) { - SlabUtil.prepareBlockPartCeiling(data, chunk.getBlockData(x, y, z), chunk, new Vector(x, y, z), c.getSlabPalettes(), c.getStairPalettes(), c.getSlabThreshold(), sampler); - } - justSet = false; - paletteLevel = 0; - } - } - } - } - return chunk; - } - - private void load(World w) { - try { - popMan.loadBlocks(w); - } catch(FileNotFoundException e) { - LangUtil.log("warning.no-population", Level.WARNING); - } catch(IOException | ClassNotFoundException e) { - e.printStackTrace(); - } - popMap.put(w, popMan); - needsLoad = false; - } - - @Override - public int getNoiseOctaves(World world) { - return 1; - } - - @Override - public double getNoiseFrequency(World world) { - return 0.02; - } - - @Override - public List getGenerationPopulators(World world) { - return Collections.emptyList(); - } - - @Override - public org.polydev.gaea.biome.BiomeGrid getBiomeGrid(World world) { - return main.getWorld(world).getGrid(); - } - - @Override - public @NotNull List getDefaultPopulators(@NotNull World world) { - return Arrays.asList(new CavePopulator(main), new StructurePopulator(main), popMan); - } - - @Override - public boolean isParallelCapable() { - return true; - } - - @Override - public boolean shouldGenerateCaves() { - return configPack.getTemplate().vanillaCaves(); - } - - @Override - public boolean shouldGenerateDecorations() { - return configPack.getTemplate().vanillaDecorations(); - } - - @Override - public boolean shouldGenerateMobs() { - return configPack.getTemplate().vanillaMobs(); - } - - @Override - public boolean shouldGenerateStructures() { - return configPack.getTemplate().vanillaStructures(); - } -} diff --git a/src/main/java/com/dfsek/terra/generation/UserDefinedDecorator.java b/src/main/java/com/dfsek/terra/generation/UserDefinedDecorator.java deleted file mode 100644 index 347aed9ab..000000000 --- a/src/main/java/com/dfsek/terra/generation/UserDefinedDecorator.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.dfsek.terra.generation; - -import org.bukkit.block.Biome; -import org.polydev.gaea.biome.Decorator; -import org.polydev.gaea.math.ProbabilityCollection; -import org.polydev.gaea.tree.Tree; -import org.polydev.gaea.world.Flora; - -public class UserDefinedDecorator extends Decorator { - - private final ProbabilityCollection flora; - private final ProbabilityCollection trees; - private final int floraChance; - private final int treeDensity; - - public UserDefinedDecorator(ProbabilityCollection flora, ProbabilityCollection trees, int floraChance, int treeDensity) { - this.flora = flora; - this.trees = trees; - - this.floraChance = floraChance; - this.treeDensity = treeDensity; - } - - @Override - public ProbabilityCollection getTrees() { - return trees; - } - - @Override - public int getTreeDensity() { - return treeDensity; - } - - @Override - public boolean overrideStructureChance() { - return false; - } - - @Override - public Biome getVanillaBiome() { - return null; - } - - @Override - public ProbabilityCollection getFlora() { - return flora; - } - - @Override - public int getFloraChance() { - return floraChance; - } -} diff --git a/src/main/java/com/dfsek/terra/generation/items/TerraStructure.java b/src/main/java/com/dfsek/terra/generation/items/TerraStructure.java deleted file mode 100644 index af6019197..000000000 --- a/src/main/java/com/dfsek/terra/generation/items/TerraStructure.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.dfsek.terra.generation.items; - -import com.dfsek.terra.config.templates.StructureTemplate; -import com.dfsek.terra.procgen.GridSpawn; -import com.dfsek.terra.structure.Structure; -import org.polydev.gaea.math.ProbabilityCollection; -import org.polydev.gaea.math.Range; -import org.polydev.gaea.structures.loot.LootTable; - -import java.util.Map; - -// TODO: implementation -public class TerraStructure { - private final ProbabilityCollection structures; - private final Range bound; - private final Range spawnStart; - private final GridSpawn spawn; - private final Map loot; - private final StructureTemplate template; - - public TerraStructure(ProbabilityCollection structures, Range bound, Range spawnStart, GridSpawn spawn, Map loot, StructureTemplate template) { - this.structures = structures; - this.bound = bound; - this.spawnStart = spawnStart; - this.spawn = spawn; - this.loot = loot; - this.template = template; - } - - public StructureTemplate getTemplate() { - return template; - } - - public ProbabilityCollection getStructures() { - return structures; - } - - public Range getBound() { - return bound; - } - - public Range getSpawnStart() { - return spawnStart; - } - - public GridSpawn getSpawn() { - return spawn; - } - - public Map getLoot() { - return loot; - } -} diff --git a/src/main/java/com/dfsek/terra/generation/items/tree/TerraTree.java b/src/main/java/com/dfsek/terra/generation/items/tree/TerraTree.java deleted file mode 100644 index 54dfe5829..000000000 --- a/src/main/java/com/dfsek/terra/generation/items/tree/TerraTree.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.dfsek.terra.generation.items.tree; - -import com.dfsek.terra.Terra; -import com.dfsek.terra.procgen.math.Vector2; -import com.dfsek.terra.structure.Rotation; -import com.dfsek.terra.structure.Structure; -import com.dfsek.terra.structure.StructureContainedBlock; -import com.dfsek.terra.structure.StructureInfo; -import com.dfsek.terra.util.MaterialSet; -import com.dfsek.terra.util.structure.RotationUtil; -import org.bukkit.Location; -import org.bukkit.plugin.java.JavaPlugin; -import org.polydev.gaea.math.ProbabilityCollection; -import org.polydev.gaea.tree.Tree; - -import java.util.Random; - -public class TerraTree implements Tree { - private final MaterialSet spawnable; - private final int yOffset; - private final ProbabilityCollection structure; - - public TerraTree(MaterialSet spawnable, int yOffset, ProbabilityCollection structure) { - this.spawnable = spawnable; - this.yOffset = yOffset; - this.structure = structure; - } - - @Override - public boolean plant(Location location, Random random, JavaPlugin main) { - Location mut = location.clone().subtract(0, yOffset, 0); - if(!spawnable.contains(location.getBlock().getType())) return false; - Structure struc = structure.get(random); - Rotation rotation = Rotation.fromDegrees(random.nextInt(4) * 90); - if(!struc.checkSpawns(mut, rotation, (Terra) main)) return false; - struc.paste(mut, rotation, (Terra) main); - return true; - } - - @Override - public MaterialSet getSpawnable() { - return spawnable; - } - - public boolean plantBlockCheck(Location location, Random random, Terra main) { - Location mut = location.clone().subtract(0, yOffset, 0); - if(!spawnable.contains(location.getBlock().getType())) return false; - Structure struc = structure.get(random); - Rotation rotation = Rotation.fromDegrees(random.nextInt(4) * 90); - StructureInfo info = struc.getStructureInfo(); - for(StructureContainedBlock spawn : struc.getSpawns()) { - Vector2 rot = RotationUtil.getRotatedCoords(new Vector2(spawn.getX() - info.getCenterX(), spawn.getZ() - info.getCenterZ()), rotation); - int x = (int) rot.getX(); - int z = (int) rot.getZ(); - switch(spawn.getRequirement()) { - case AIR: - if(!mut.clone().add(x, spawn.getY() - 1, z).getBlock().isPassable()) return false; - break; - case LAND: - if(!mut.clone().add(x, spawn.getY() - 1, z).getBlock().getType().isSolid()) return false; - break; - } - } - struc.paste(mut, rotation, main); - return true; - } -} diff --git a/src/main/java/com/dfsek/terra/generation/items/tree/TreeLayer.java b/src/main/java/com/dfsek/terra/generation/items/tree/TreeLayer.java deleted file mode 100644 index bcc24f7c6..000000000 --- a/src/main/java/com/dfsek/terra/generation/items/tree/TreeLayer.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.dfsek.terra.generation.items.tree; - -import com.dfsek.terra.generation.items.PlaceableLayer; -import com.dfsek.terra.procgen.math.Vector2; -import org.bukkit.Chunk; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.polydev.gaea.GaeaPlugin; -import org.polydev.gaea.math.FastNoiseLite; -import org.polydev.gaea.math.ProbabilityCollection; -import org.polydev.gaea.math.Range; -import org.polydev.gaea.tree.Tree; -import org.polydev.gaea.tree.TreeType; - -import java.util.Random; - -public class TreeLayer extends PlaceableLayer { - private final GaeaPlugin main; - - public TreeLayer(double density, Range level, ProbabilityCollection layer, FastNoiseLite noise, GaeaPlugin main) { - super(density, level, layer, noise); - this.main = main; - } - - @Override - public void place(Chunk chunk, Vector2 coords, Random random) { - Tree item = layer.get(random); - Block current = chunk.getBlock((int) coords.getX(), level.getMax(), (int) coords.getZ()); - for(int ignored : level) { - current = current.getRelative(BlockFace.DOWN); - if(item.getSpawnable().contains(current.getType())) { - if(item instanceof TreeType && current.getRelative(BlockFace.UP).isEmpty()) - item.plant(current.getLocation().add(0, 1, 0), random, main); - else if(!(item instanceof TreeType)) item.plant(current.getLocation(), random, main); - } - } - } -} diff --git a/src/main/java/com/dfsek/terra/listeners/EventListener.java b/src/main/java/com/dfsek/terra/listeners/EventListener.java deleted file mode 100644 index 25bd067ec..000000000 --- a/src/main/java/com/dfsek/terra/listeners/EventListener.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.dfsek.terra.listeners; - -import com.dfsek.terra.Terra; -import com.dfsek.terra.TerraWorld; -import com.dfsek.terra.config.base.ConfigPack; -import com.dfsek.terra.debug.Debug; -import com.dfsek.terra.generation.items.tree.TerraTree; -import com.dfsek.terra.registry.TreeRegistry; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.block.data.BlockData; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.world.StructureGrowEvent; -import org.polydev.gaea.tree.Tree; -import org.polydev.gaea.tree.TreeType; -import org.polydev.gaea.util.FastRandom; - -/** - * Listener for events on all implementations. - */ -public class EventListener implements Listener { - private final Terra main; - - public EventListener(Terra main) { - this.main = main; - } - - @EventHandler - public void onSaplingGrow(StructureGrowEvent e) { - if(!TerraWorld.isTerraWorld(e.getWorld())) return; - TerraWorld tw = main.getWorld(e.getWorld()); - ConfigPack c = tw.getConfig(); - if(c.getTemplate().isDisableSaplings()) return; - e.setCancelled(true); - Block block = e.getLocation().getBlock(); - BlockData data = block.getBlockData(); - block.setType(Material.AIR); - TreeRegistry registry = c.getTreeRegistry(); - Tree tree = registry.get(TreeType.fromBukkit(e.getSpecies()).toString()); - Debug.info("Overriding tree type: " + e.getSpecies()); - if(tree instanceof TerraTree) { - if(!((TerraTree) tree).plantBlockCheck(e.getLocation().subtract(0, 1, 0), new FastRandom(), main)) { - block.setBlockData(data); - } - } else if(!tree.plant(e.getLocation().subtract(0, 1, 0), new FastRandom(), main)) block.setBlockData(data); - } -} diff --git a/src/main/java/com/dfsek/terra/math/MathUtil.java b/src/main/java/com/dfsek/terra/math/MathUtil.java deleted file mode 100644 index bf084ceb3..000000000 --- a/src/main/java/com/dfsek/terra/math/MathUtil.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.dfsek.terra.math; - -import com.dfsek.terra.generation.Sampler; - -public final class MathUtil { - private static final double CONST = 0.55; - - public static double derivative(Sampler sampler, double x, double y, double z) { - double baseSample = sampler.sample(x, y, z); - - double xVal1 = (sampler.sample(x + CONST, y, z) - baseSample) / CONST; - double xVal2 = (sampler.sample(x - CONST, y, z) - baseSample) / CONST; - double zVal1 = (sampler.sample(x, y, z + CONST) - baseSample) / CONST; - double zVal2 = (sampler.sample(x, y, z - CONST) - baseSample) / CONST; - double yVal1 = (sampler.sample(x, y + CONST, z) - baseSample) / CONST; - double yVal2 = (sampler.sample(x, y - CONST, z) - baseSample) / CONST; - - return Math.sqrt(((xVal2 - xVal1) * (xVal2 - xVal1)) + ((zVal2 - zVal1) * (zVal2 - zVal1)) + ((yVal2 - yVal1) * (yVal2 - yVal1))); - } -} diff --git a/src/main/java/com/dfsek/terra/population/StructurePopulator.java b/src/main/java/com/dfsek/terra/population/StructurePopulator.java deleted file mode 100644 index 7185f7e1e..000000000 --- a/src/main/java/com/dfsek/terra/population/StructurePopulator.java +++ /dev/null @@ -1,83 +0,0 @@ -package com.dfsek.terra.population; - -import com.dfsek.terra.Terra; -import com.dfsek.terra.TerraWorld; -import com.dfsek.terra.biome.UserDefinedBiome; -import com.dfsek.terra.biome.grid.master.TerraBiomeGrid; -import com.dfsek.terra.config.base.ConfigPack; -import com.dfsek.terra.debug.Debug; -import com.dfsek.terra.generation.items.TerraStructure; -import com.dfsek.terra.procgen.math.Vector2; -import com.dfsek.terra.structure.Rotation; -import com.dfsek.terra.structure.Structure; -import com.dfsek.terra.structure.StructureContainedInventory; -import com.dfsek.terra.structure.features.Feature; -import com.dfsek.terra.util.PopulationUtil; -import com.dfsek.terra.util.structure.RotationUtil; -import net.jafama.FastMath; -import org.bukkit.Chunk; -import org.bukkit.Location; -import org.bukkit.World; -import org.bukkit.generator.BlockPopulator; -import org.bukkit.inventory.BlockInventoryHolder; -import org.jetbrains.annotations.NotNull; -import org.polydev.gaea.profiler.ProfileFuture; -import org.polydev.gaea.structures.loot.LootTable; -import org.polydev.gaea.util.FastRandom; - -import java.util.Random; - -public class StructurePopulator extends BlockPopulator { - private final Terra main; - - public StructurePopulator(Terra main) { - this.main = main; - } - - @SuppressWarnings("try") - @Override - public void populate(@NotNull World world, @NotNull Random r, @NotNull Chunk chunk) { - TerraWorld tw = main.getWorld(world); - try(ProfileFuture ignored = tw.getProfiler().measure("StructureTime")) { - Random random = PopulationUtil.getRandom(chunk); - int cx = (chunk.getX() << 4); - int cz = (chunk.getZ() << 4); - if(!tw.isSafe()) return; - TerraBiomeGrid grid = tw.getGrid(); - ConfigPack config = tw.getConfig(); - structure: - for(TerraStructure conf : config.getStructures()) { - Location spawn = conf.getSpawn().getNearestSpawn(cx + 8, cz + 8, world.getSeed()).toLocation(world); - if(!((UserDefinedBiome) grid.getBiome(spawn)).getConfig().getStructures().contains(conf)) continue; - Random r2 = new FastRandom(spawn.hashCode()); - Structure struc = conf.getStructures().get(r2); - Rotation rotation = Rotation.fromDegrees(r2.nextInt(4) * 90); - for(int y = conf.getSpawnStart().get(r2); y > 0; y--) { - if(!conf.getBound().isInRange(y)) continue structure; - spawn.setY(y); - if(!struc.checkSpawns(spawn, rotation, main)) continue; - double horizontal = struc.getStructureInfo().getMaxHorizontal(); - if(FastMath.abs((cx + 8) - spawn.getBlockX()) <= horizontal && FastMath.abs((cz + 8) - spawn.getBlockZ()) <= horizontal) { - struc.paste(spawn, chunk, rotation, main); - for(StructureContainedInventory i : struc.getInventories()) { - try { - Vector2 lootCoords = RotationUtil.getRotatedCoords(new Vector2(i.getX() - struc.getStructureInfo().getCenterX(), i.getZ() - struc.getStructureInfo().getCenterZ()), rotation.inverse()); - Location inv = spawn.clone().add(lootCoords.getX(), i.getY(), lootCoords.getZ()); - if(FastMath.floorDiv(inv.getBlockX(), 16) != chunk.getX() || FastMath.floorDiv(inv.getBlockZ(), 16) != chunk.getZ()) - continue; - LootTable table = conf.getLoot().get(i.getUid()); - if(table == null) continue; - table.fillInventory(((BlockInventoryHolder) inv.getBlock().getState()).getInventory(), random); - } catch(ClassCastException e) { - Debug.error("Could not populate structure loot!"); - Debug.stack(e); - } - } - for(Feature f : conf.getTemplate().getFeatures()) f.apply(struc, rotation, spawn, chunk); // Apply features. - break; - } - } - } - } - } -} diff --git a/src/main/java/com/dfsek/terra/procgen/voxel/Cylinder.java b/src/main/java/com/dfsek/terra/procgen/voxel/Cylinder.java deleted file mode 100644 index dfe02f06a..000000000 --- a/src/main/java/com/dfsek/terra/procgen/voxel/Cylinder.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.dfsek.terra.procgen.voxel; - -import org.bukkit.util.Vector; - -public class Cylinder extends VoxelGeometry { - public Cylinder(Vector start, int rad, int height) { - - } -} diff --git a/src/main/java/com/dfsek/terra/procgen/voxel/Tube.java b/src/main/java/com/dfsek/terra/procgen/voxel/Tube.java deleted file mode 100644 index 4fd131c1d..000000000 --- a/src/main/java/com/dfsek/terra/procgen/voxel/Tube.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.dfsek.terra.procgen.voxel; - -import org.bukkit.util.Vector; - -public class Tube extends VoxelGeometry { - public Tube(Vector start, Vector end, int radius) { - Vector step = start.clone().subtract(end).normalize(); - Vector run = start.clone(); - int steps = (int) start.distance(end); - for(int i = 0; i < steps; i++) { - merge(new Sphere(run, radius)); - run.add(step); - } - } -} diff --git a/src/main/java/com/dfsek/terra/registry/FloraRegistry.java b/src/main/java/com/dfsek/terra/registry/FloraRegistry.java deleted file mode 100644 index 336be4184..000000000 --- a/src/main/java/com/dfsek/terra/registry/FloraRegistry.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.dfsek.terra.registry; - -import com.dfsek.terra.generation.items.flora.BlockFlora; -import org.bukkit.Bukkit; -import org.polydev.gaea.world.Flora; -import org.polydev.gaea.world.FloraType; - -public class FloraRegistry extends TerraRegistry { - public FloraRegistry() { - for(FloraType f : FloraType.values()) add(f.toString(), f); - } - - @Override - public Flora get(String id) { - if(id.startsWith("BLOCK:")) - return new BlockFlora(Bukkit.createBlockData(id.substring(6))); // Return single flora for BLOCK: shortcut. - return super.get(id); - } -} diff --git a/src/main/java/com/dfsek/terra/registry/PaletteRegistry.java b/src/main/java/com/dfsek/terra/registry/PaletteRegistry.java deleted file mode 100644 index 2e318533a..000000000 --- a/src/main/java/com/dfsek/terra/registry/PaletteRegistry.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.dfsek.terra.registry; - -import com.dfsek.terra.biome.palette.SinglePalette; -import org.bukkit.Bukkit; -import org.bukkit.block.data.BlockData; -import org.polydev.gaea.world.palette.Palette; - -public class PaletteRegistry extends TerraRegistry> { - @Override - public Palette get(String id) { - if(id.startsWith("BLOCK:")) - return new SinglePalette<>(Bukkit.createBlockData(id.substring(6))); // Return single palette for BLOCK: shortcut. - return super.get(id); - } -} diff --git a/src/main/java/com/dfsek/terra/registry/TreeRegistry.java b/src/main/java/com/dfsek/terra/registry/TreeRegistry.java deleted file mode 100644 index 56ecf7ab5..000000000 --- a/src/main/java/com/dfsek/terra/registry/TreeRegistry.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.dfsek.terra.registry; - -import org.polydev.gaea.tree.Tree; -import org.polydev.gaea.tree.TreeType; - -public class TreeRegistry extends TerraRegistry { - public TreeRegistry() { - for(TreeType t : TreeType.values()) add(t.toString(), t); // Populate registry with default trees. - } -} diff --git a/src/main/java/com/dfsek/terra/structure/InitializationException.java b/src/main/java/com/dfsek/terra/structure/InitializationException.java deleted file mode 100644 index 6d38ede96..000000000 --- a/src/main/java/com/dfsek/terra/structure/InitializationException.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.dfsek.terra.structure; - -import org.bukkit.Location; -import org.jetbrains.annotations.Nullable; - -@SuppressWarnings("unused") -public class InitializationException extends Exception { - private static final long serialVersionUID = -3817726044758088486L; - private final Location worldLoc; - - public InitializationException(String message, @Nullable Location worldLoc) { - super(message); - this.worldLoc = worldLoc == null ? null : worldLoc.clone(); - } - - @Override - public String getMessage() { - return super.getMessage() + " (at location: " + worldLoc.toString() + ")"; - } - - @Nullable - public Location getWorldLoc() { - return worldLoc; - } -} diff --git a/src/main/java/com/dfsek/terra/structure/Structure.java b/src/main/java/com/dfsek/terra/structure/Structure.java deleted file mode 100644 index 7b541b19d..000000000 --- a/src/main/java/com/dfsek/terra/structure/Structure.java +++ /dev/null @@ -1,353 +0,0 @@ -package com.dfsek.terra.structure; - -import com.dfsek.terra.Terra; -import com.dfsek.terra.api.generic.world.WorldHandle; -import com.dfsek.terra.debug.Debug; -import com.dfsek.terra.procgen.math.Vector2; -import com.dfsek.terra.util.structure.RotationUtil; -import net.jafama.FastMath; -import org.bukkit.Bukkit; -import org.bukkit.Chunk; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.block.BlockState; -import org.bukkit.block.Sign; -import org.bukkit.block.data.BlockData; -import org.bukkit.inventory.BlockInventoryHolder; -import org.jetbrains.annotations.NotNull; -import org.polydev.gaea.math.Range; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.Serializable; -import java.util.HashSet; -import java.util.Objects; -import java.util.UUID; -import java.util.function.Consumer; - -import static com.dfsek.terra.util.structure.RotationUtil.getRotatedCoords; - -@SuppressWarnings("unused") -public class Structure implements Serializable { - private static final long serialVersionUID = -6664585217063842035L; - private final StructureContainedBlock[][][] structure; - private final StructureInfo structureInfo; - private final String id; - private final UUID uuid; - private final HashSet spawns; - private final HashSet inventories; - - public Structure(@NotNull Location l1, @NotNull Location l2, @NotNull String id) throws InitializationException { - int centerX = -1, centerZ = -1; - this.id = id; - this.uuid = UUID.randomUUID(); - this.spawns = new HashSet<>(); - this.inventories = new HashSet<>(); - if(l1.getX() > l2.getX() || l1.getY() > l2.getY() || l1.getZ() > l2.getZ()) - throw new IllegalArgumentException("Invalid locations provided!"); - structure = new StructureContainedBlock[l2.getBlockX() - l1.getBlockX() + 1][l2.getBlockZ() - l1.getBlockZ() + 1][l2.getBlockY() - l1.getBlockY() + 1]; - for(int x = 0; x <= l2.getBlockX() - l1.getBlockX(); x++) { - for(int z = 0; z <= l2.getBlockZ() - l1.getBlockZ(); z++) { - for(int y = 0; y <= l2.getBlockY() - l1.getBlockY(); y++) { - Block b = Objects.requireNonNull(l1.getWorld()).getBlockAt(l1.clone().add(x, y, z)); - BlockState state = b.getState(); - BlockData d = b.getBlockData(); - boolean useState = true; - StructureContainedBlock.Pull pull = StructureContainedBlock.Pull.NONE; - int pullOffset = 0; - StructureSpawnRequirement requirement = StructureSpawnRequirement.BLANK; - try { - if(state instanceof Sign) { // Magic sign stuff - Sign s = (Sign) b.getState(); - if(s.getLine(0).equals("[TERRA]")) { - try { - d = Bukkit.createBlockData(s.getLine(2) + s.getLine(3)); - useState = false; - if(s.getLine(1).equals("[CENTER]")) { - centerX = x; - centerZ = z; - } else if(s.getLine(1).startsWith("[SPAWN=") && s.getLine(1).endsWith("]")) { - String og = s.getLine(1); - String spawn = og.substring(og.indexOf("=") + 1, og.length() - 1); - try { - requirement = StructureSpawnRequirement.valueOf(spawn.toUpperCase()); - } catch(IllegalArgumentException e) { - throw new InitializationException("Invalid spawn type: " + spawn, b.getLocation()); - } - } else if(s.getLine(1).startsWith("[PULL=") && s.getLine(1).endsWith("]")) { - String og = s.getLine(1); - String spawn = og.substring(og.indexOf("=") + 1, og.indexOf("_")); - pullOffset = Integer.parseInt(og.substring(og.indexOf("_") + 1, og.length() - 1)); - try { - pull = StructureContainedBlock.Pull.valueOf(spawn); - } catch(IllegalArgumentException e) { - throw new InitializationException("Invalid pull type: " + spawn, b.getLocation()); - } - } else { - throw new InitializationException("Invalid Magic Sign: \"" + s.getLine(1) + "\"", b.getLocation()); - } - } catch(IllegalArgumentException e) { - throw new InitializationException("Invalid Block Data on sign: \"" + s.getLine(2) + s.getLine(3) + "\"", b.getLocation()); - } - } - } - } catch(StringIndexOutOfBoundsException e) { - throw new InitializationException("Invalid sign.", b.getLocation()); - } - StructureContainedBlock block = new StructureContainedBlock(x, y, z, useState ? state : null, d, requirement, pull, pullOffset); - if(state instanceof BlockInventoryHolder) { - inventories.add(new StructureContainedInventory(((BlockInventoryHolder) state).getInventory(), block)); - } - if(!requirement.equals(StructureSpawnRequirement.BLANK)) spawns.add(block); - structure[x][z][y] = block; - } - } - } - if(centerX < 0 || centerZ < 0) throw new InitializationException("No structure center specified.", null); - structureInfo = new StructureInfo(l2.getBlockX() - l1.getBlockX() + 1, l2.getBlockY() - l1.getBlockY() + 1, l2.getBlockZ() - l1.getBlockZ() + 1, new Vector2(centerX, centerZ)); - } - - @NotNull - public static Structure load(@NotNull File f) throws IOException { - try { - return fromFile(f); - } catch(ClassNotFoundException e) { - throw new IllegalArgumentException("Provided file does not contain a GaeaStructure."); - } - } - - /** - * Load a structure from a file. - * - * @param f File to load from - * @return The structure loaded - * @throws IOException If file access error occurs - * @throws ClassNotFoundException If structure data is invalid. - */ - @NotNull - private static Structure fromFile(@NotNull File f) throws IOException, ClassNotFoundException { - ObjectInputStream ois = new ObjectInputStream(new FileInputStream(f)); - Object o = ois.readObject(); - ois.close(); - return (Structure) o; - } - - @NotNull - public static Structure fromStream(@NotNull InputStream f) throws IOException, ClassNotFoundException { - ObjectInputStream ois = new ObjectInputStream(f); - Object o = ois.readObject(); - ois.close(); - return (Structure) o; - } - - private static void toFile(@NotNull Serializable o, @NotNull File f) throws IOException { - ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(f)); - oos.writeObject(o); - oos.close(); - } - - public StructureContainedBlock[][][] getRawStructure() { - return structure; - } - - /** - * Paste the structure at a Location, ignoring chunk boundaries. - * - * @param origin Origin location - * @param r Rotation - */ - public void paste(@NotNull Location origin, Rotation r, Terra main) { - Range xRange = getRange(Rotation.Axis.X, r); - Range zRange = getRange(Rotation.Axis.Z, r); - this.executeForBlocksInRange(xRange, getRange(Rotation.Axis.Y, r), zRange, block -> pasteBlock(block, origin, r, main.getHandle()), r); - } - - /** - * Paste a single StructureDefinedBlock at an origin location, offset by its coordinates. - * - * @param block The block to paste - * @param origin The origin location - * @param r The rotation of the structure - */ - private void pasteBlock(StructureContainedBlock block, Location origin, Rotation r, WorldHandle handle) { - BlockData data = block.getBlockData().clone(); - if(!data.getMaterial().equals(Material.STRUCTURE_VOID)) { - - Location loc = origin.clone().add(block.getX(), block.getY(), block.getZ()); - Block worldBlock = loc.getBlock(); - - main: - while(worldBlock.isEmpty()) { - if(worldBlock.getY() > 255 || worldBlock.getY() < 0) return; - if(block.getPull() == null) break; - switch(block.getPull()) { - case UP: - worldBlock = worldBlock.getRelative(BlockFace.UP); - break; - case DOWN: - worldBlock = worldBlock.getRelative(BlockFace.DOWN); - break; - default: - break main; - } - } - int offset = block.getPullOffset(); - if(offset != 0) - worldBlock = worldBlock.getRelative((offset > 0) ? BlockFace.UP : BlockFace.DOWN, FastMath.abs(offset)); - - RotationUtil.rotateBlockData(data, r); - - handle.setBlockData(worldBlock, data, false); - if(block.getState() != null) { - block.getState().getState(worldBlock.getState()).update(true, false); - } - } - } - - /** - * Execute a Consumer for all blocks in a cuboid region defined by 3 Ranges, accounting for rotation. - * - * @param xM X Range - * @param yM Y Range - * @param zM Z Range - * @param exec Consumer to execute for each block. - * @param r Rotation - */ - private void executeForBlocksInRange(Range xM, Range yM, Range zM, Consumer exec, Rotation r) { - for(int x : xM) { - for(int y : yM) { - for(int z : zM) { - Vector2 c = getRotatedCoords(new Vector2(x - structureInfo.getCenterX(), z - structureInfo.getCenterZ()), r); - c.add(new Vector2(structureInfo.getCenterX(), structureInfo.getCenterZ())); - if(isInStructure((int) c.getX(), y, (int) c.getZ())) { - StructureContainedBlock b = structure[(int) c.getX()][(int) c.getZ()][y]; - exec.accept(new StructureContainedBlock(x - getStructureInfo().getCenterX(), y, z - getStructureInfo().getCenterZ(), b.getState(), b.getBlockData(), b.getRequirement(), b.getPull(), b.getPullOffset())); - } - } - } - } - } - - /** - * Get GaeaStructureInfo object - * - * @return Structure Info - */ - @NotNull - public StructureInfo getStructureInfo() { - return structureInfo; - } - - /** - * Test whether a set of coordinates is within the current structure - * - * @param x X coordinate - * @param y Y coordinate - * @param z Z coordinate - * @return True if coordinate set is in structure, false if it is not. - */ - private boolean isInStructure(int x, int y, int z) { - return x < structureInfo.getSizeX() && y < structureInfo.getSizeY() && z < structureInfo.getSizeZ() && x >= 0 && y >= 0 && z >= 0; - } - - @NotNull - public Range getRange(@NotNull Rotation.Axis a, @NotNull Rotation r) { - if(a.equals(Rotation.Axis.Y)) return getRawRange(a); - Vector2 center = new Vector2(structureInfo.getCenterX(), structureInfo.getCenterZ()); - Range x = getRawRange(Rotation.Axis.X); - Range z = getRawRange(Rotation.Axis.Z); - Vector2 min = getRotatedCoords(new Vector2(x.getMin(), z.getMin()).subtract(center), r.inverse()).add(center); - Vector2 max = getRotatedCoords(new Vector2(x.getMax(), z.getMax()).subtract(center), r.inverse()).add(center); - - if(a.equals(Rotation.Axis.X)) - return new Range((int) FastMath.floor(FastMath.min(min.getX(), max.getX())), (int) FastMath.ceil(FastMath.max(min.getX(), max.getX())) + 1); - else - return new Range((int) FastMath.floor(FastMath.min(min.getZ(), max.getZ())), (int) FastMath.ceil(FastMath.max(min.getZ(), max.getZ())) + 1); - } - - @NotNull - private Range getRawRange(@NotNull Rotation.Axis a) { - switch(a) { - case X: - return new Range(0, structureInfo.getSizeX()); - case Y: - return new Range(0, structureInfo.getSizeY()); - case Z: - return new Range(0, structureInfo.getSizeZ()); - default: - throw new IllegalArgumentException(); - } - } - - public boolean checkSpawns(Location origin, Rotation r, Terra main) { - for(StructureContainedBlock b : spawns) { - Vector2 rot = getRotatedCoords(new Vector2(b.getX() - structureInfo.getCenterX(), b.getZ() - structureInfo.getCenterZ()), r); - if(!b.getRequirement().getInstance(origin.getWorld(), main).matches((int) rot.getX() + origin.getBlockX(), origin.getBlockY() + b.getY(), (int) rot.getZ() + origin.getBlockZ())) - return false; - } - return true; - } - - public HashSet getSpawns() { - return spawns; - } - - public HashSet getInventories() { - return inventories; - } - - /** - * Paste structure at an origin location, confined to a single chunk. - * - * @param origin Origin location - * @param chunk Chunk to confine pasting to - * @param r Rotation - */ - public void paste(Location origin, Chunk chunk, Rotation r, Terra main) { - int xOr = (chunk.getX() << 4); - int zOr = (chunk.getZ() << 4); - Range intersectX = new Range(xOr, xOr + 16).sub(origin.getBlockX() - structureInfo.getCenterX()); - Range intersectZ = new Range(zOr, zOr + 16).sub(origin.getBlockZ() - structureInfo.getCenterZ()); - if(intersectX == null || intersectZ == null) return; - executeForBlocksInRange(intersectX, getRange(Rotation.Axis.Y, r), intersectZ, block -> pasteBlock(block, origin, r, main.getHandle()), r); - Debug.info(intersectX.toString() + " : " + intersectZ.toString()); - } - - /** - * From an origin location (First bound) fetch the second bound. - * - * @param origin Origin location - * @return Other bound location - */ - public Location getOtherBound(Location origin) { - return origin.clone().add(structureInfo.getSizeX(), structureInfo.getSizeY(), structureInfo.getSizeZ()); - } - - /** - * Save the structure to a file - * - * @param f File to save to - * @throws IOException If file access error occurs - */ - public void save(@NotNull File f) throws IOException { - toFile(this, f); - } - - @NotNull - public String getId() { - return id; - } - - @NotNull - public UUID getUuid() { - return uuid; - } - -} diff --git a/src/main/java/com/dfsek/terra/structure/StructureContainedBlock.java b/src/main/java/com/dfsek/terra/structure/StructureContainedBlock.java deleted file mode 100644 index 0660288ee..000000000 --- a/src/main/java/com/dfsek/terra/structure/StructureContainedBlock.java +++ /dev/null @@ -1,98 +0,0 @@ -package com.dfsek.terra.structure; - -import com.dfsek.terra.debug.Debug; -import com.dfsek.terra.structure.serialize.SerializableBlockData; -import com.dfsek.terra.structure.serialize.block.SerializableBanner; -import com.dfsek.terra.structure.serialize.block.SerializableBlockState; -import com.dfsek.terra.structure.serialize.block.SerializableMonsterCage; -import com.dfsek.terra.structure.serialize.block.SerializableSign; -import org.bukkit.block.Banner; -import org.bukkit.block.BlockState; -import org.bukkit.block.CreatureSpawner; -import org.bukkit.block.Sign; -import org.bukkit.block.data.BlockData; - -import java.io.Serializable; - -public class StructureContainedBlock implements Serializable { - private static final long serialVersionUID = 6143969483382710947L; - private final SerializableBlockData bl; - private final Pull pull; - private final int pullOffset; - private final int x; - private final int y; - private final int z; - private final SerializableBlockState state; - private final StructureSpawnRequirement requirement; - private transient BlockData data; - - public StructureContainedBlock(int x, int y, int z, BlockState state, BlockData d, StructureSpawnRequirement spawn, Pull pull, int pullOffset) { - if(state instanceof Sign) { - Debug.info("Sign at (" + x + ", " + y + ", " + z + ")."); - this.state = new SerializableSign((org.bukkit.block.Sign) state); - } else if(state instanceof CreatureSpawner) { - Debug.info("Monster Spawner at (" + x + ", " + y + ", " + z + ")."); - this.state = new SerializableMonsterCage((CreatureSpawner) state); - } else if(state instanceof Banner) { - Debug.info("Banner at (" + x + ", " + y + ", " + z + ")."); - this.state = new SerializableBanner((Banner) state); - } else this.state = null; - this.x = x; - this.y = y; - this.z = z; - this.bl = new SerializableBlockData(d); - this.requirement = spawn; - this.pull = pull; - this.pullOffset = pullOffset; - } - - public StructureContainedBlock(int x, int y, int z, SerializableBlockState state, BlockData d, StructureSpawnRequirement spawn, Pull pull, int pullOffset) { - this.state = state; - this.x = x; - this.y = y; - this.z = z; - this.bl = new SerializableBlockData(d); - this.requirement = spawn; - this.pull = pull; - this.pullOffset = pullOffset; - } - - public StructureSpawnRequirement getRequirement() { - return requirement; - } - - public int getX() { - return x; - } - - public int getY() { - return y; - } - - public int getZ() { - return z; - } - - public BlockData getBlockData() { - if(data == null) { - data = bl.getData(); - } - return data; - } - - public Pull getPull() { - return pull; - } - - public int getPullOffset() { - return pullOffset; - } - - public SerializableBlockState getState() { - return state; - } - - public enum Pull { - UP, NONE, DOWN - } -} diff --git a/src/main/java/com/dfsek/terra/structure/StructureContainedInventory.java b/src/main/java/com/dfsek/terra/structure/StructureContainedInventory.java deleted file mode 100644 index 3e2527f4d..000000000 --- a/src/main/java/com/dfsek/terra/structure/StructureContainedInventory.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.dfsek.terra.structure; - -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; - -import java.io.Serializable; - -public class StructureContainedInventory implements Serializable { - private static final long serialVersionUID = -175339605585943678L; - private final int uid; - private final int x, y, z; - - public StructureContainedInventory(Inventory orig, StructureContainedBlock link) { - ItemStack stack = orig.getItem(0); - x = link.getX(); - y = link.getY(); - z = link.getZ(); - if(stack == null) { - uid = 0; - return; - } - uid = stack.getAmount(); - } - - public int getUid() { - return uid; - } - - public int getX() { - return x; - } - - public int getY() { - return y; - } - - public int getZ() { - return z; - } -} diff --git a/src/main/java/com/dfsek/terra/structure/StructureInfo.java b/src/main/java/com/dfsek/terra/structure/StructureInfo.java deleted file mode 100644 index e08fddcbf..000000000 --- a/src/main/java/com/dfsek/terra/structure/StructureInfo.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.dfsek.terra.structure; - -import com.dfsek.terra.procgen.math.Vector2; -import net.jafama.FastMath; - -import java.io.Serializable; - -public class StructureInfo implements Serializable { - private static final long serialVersionUID = -175639605885943678L; - private final int sizeX; - private final int sizeY; - private final int sizeZ; - private final int centerX; - private final int centerZ; - - public StructureInfo(int sizeX, int sizeY, int sizeZ, Vector2 center) { - this.sizeX = sizeX; - this.sizeY = sizeY; - this.sizeZ = sizeZ; - this.centerX = (int) center.getX(); - this.centerZ = (int) center.getZ(); - } - - public int getSizeX() { - return sizeX; - } - - public int getSizeZ() { - return sizeZ; - } - - public int getSizeY() { - return sizeY; - } - - public int getCenterX() { - return centerX; - } - - public int getCenterZ() { - return centerZ; - } - - public double getMaxHorizontal() { - return FastMath.sqrt(FastMath.pow(sizeX, 2) + FastMath.pow(sizeZ, 2)); - } -} diff --git a/src/main/java/com/dfsek/terra/structure/StructureSpawnRequirement.java b/src/main/java/com/dfsek/terra/structure/StructureSpawnRequirement.java deleted file mode 100644 index 18ef6605c..000000000 --- a/src/main/java/com/dfsek/terra/structure/StructureSpawnRequirement.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.dfsek.terra.structure; - -import com.dfsek.terra.Terra; -import com.dfsek.terra.structure.spawn.AirSpawn; -import com.dfsek.terra.structure.spawn.BlankSpawn; -import com.dfsek.terra.structure.spawn.LandSpawn; -import com.dfsek.terra.structure.spawn.OceanSpawn; -import com.dfsek.terra.structure.spawn.Requirement; -import org.bukkit.World; - -import java.io.Serializable; - -public enum StructureSpawnRequirement implements Serializable { - AIR { - @Override - public Requirement getInstance(World world, Terra main) { - return new AirSpawn(world, main); - } - }, OCEAN { - @Override - public Requirement getInstance(World world, Terra main) { - return new OceanSpawn(world, main); - } - }, LAND { - @Override - public Requirement getInstance(World world, Terra main) { - return new LandSpawn(world, main); - } - }, BLANK { - @Override - public Requirement getInstance(World world, Terra main) { - return new BlankSpawn(); - } - }; - private static final long serialVersionUID = -175639605885943679L; - - public abstract Requirement getInstance(World world, Terra main); -} diff --git a/src/main/java/com/dfsek/terra/structure/features/EntityFeature.java b/src/main/java/com/dfsek/terra/structure/features/EntityFeature.java deleted file mode 100644 index ff3b95009..000000000 --- a/src/main/java/com/dfsek/terra/structure/features/EntityFeature.java +++ /dev/null @@ -1,94 +0,0 @@ -package com.dfsek.terra.structure.features; - -import com.dfsek.terra.debug.Debug; -import com.dfsek.terra.structure.Rotation; -import com.dfsek.terra.structure.Structure; -import com.dfsek.terra.structure.StructureInfo; -import com.dfsek.terra.util.MaterialSet; -import net.jafama.FastMath; -import org.bukkit.Chunk; -import org.bukkit.Location; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.entity.EntityType; -import org.polydev.gaea.math.MathUtil; -import org.polydev.gaea.math.Range; -import org.polydev.gaea.util.FastRandom; -import org.polydev.gaea.util.GlueList; - -import java.util.List; -import java.util.Objects; -import java.util.Random; - -public class EntityFeature implements Feature { - private final EntityType type; - private final Range amount; - private final MaterialSet in; - private final MaterialSet stand; - private final int inSize; - - public EntityFeature(EntityType type, Range amount, MaterialSet stand, MaterialSet in, int inSize) { - this.type = type; - this.amount = amount; - this.in = in; - this.stand = stand; - this.inSize = inSize; - } - - private static boolean isInChunk(Chunk c, Location l) { - return FastMath.floorDiv(l.getBlockX(), 16) == c.getX() && FastMath.floorDiv(l.getBlockZ(), 16) == c.getZ(); - } - - private static List getLocations(Structure structure, Rotation r, Location origin, Random random, int number) { - StructureInfo info = structure.getStructureInfo(); - Range x = structure.getRange(Rotation.Axis.X, r); - Range y = structure.getRange(Rotation.Axis.Y, r); - Range z = structure.getRange(Rotation.Axis.Z, r); - - int cx = info.getCenterX(); - int cz = info.getCenterZ(); - List locations = new GlueList<>(); - for(int i = 0; i < number; i++) - locations.add(origin.clone().add(x.get(random) - cx, y.get(random), z.get(random) - cz)); - return locations; - } - - @Override - public void apply(Structure structure, Rotation r, Location l, Chunk chunk) { - Random random = new FastRandom(MathUtil.getCarverChunkSeed(chunk.getX(), chunk.getZ(), chunk.getWorld().getSeed())); - for(Location attempt : getLocations(structure, r, l, random, amount.get(random))) { - if(!isInChunk(chunk, attempt)) continue; // Don't attempt spawn if not in current chunk. - attemptSpawn(attempt, l); - } - } - - private void attemptSpawn(Location attempt, Location origin) { - boolean canSpawn = false; - while(attempt.getBlockY() >= origin.getBlockY()) { // Go down, see if valid spawns exist. - canSpawn = true; - Block on = attempt.getBlock(); - attempt.subtract(0, 1, 0); - - if(!stand.contains(on.getType())) { - canSpawn = false; - continue; - } - - for(int j = 1; j < inSize + 1; j++) - if(!in.contains(on.getRelative(BlockFace.UP, j).getType())) canSpawn = false; - - if(canSpawn) break; - } - if(canSpawn) { - Debug.info("Spawning entity at " + attempt); - Objects.requireNonNull(attempt.getWorld()).spawnEntity(attempt.add(0.5, 2, 0.5), type); // Add 0.5 to X & Z so entity spawns in center of block. - } - } - - @Override - public void apply(Structure structure, Rotation r, Location l, Random random) { - for(Location attempt : getLocations(structure, r, l, random, amount.get(random))) { - attemptSpawn(attempt, l); - } - } -} diff --git a/src/main/java/com/dfsek/terra/structure/features/Feature.java b/src/main/java/com/dfsek/terra/structure/features/Feature.java deleted file mode 100644 index 8046dac67..000000000 --- a/src/main/java/com/dfsek/terra/structure/features/Feature.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.dfsek.terra.structure.features; - -import com.dfsek.terra.structure.Rotation; -import com.dfsek.terra.structure.Structure; -import org.bukkit.Chunk; -import org.bukkit.Location; - -import java.util.Random; - -public interface Feature { - void apply(Structure structure, Rotation r, Location l, Chunk chunk); - - void apply(Structure structure, Rotation r, Location l, Random random); -} diff --git a/src/main/java/com/dfsek/terra/structure/serialize/SerializableBlockData.java b/src/main/java/com/dfsek/terra/structure/serialize/SerializableBlockData.java deleted file mode 100644 index a22d0a2ae..000000000 --- a/src/main/java/com/dfsek/terra/structure/serialize/SerializableBlockData.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.dfsek.terra.structure.serialize; - -import org.bukkit.Bukkit; -import org.bukkit.block.data.BlockData; - -import java.io.Serializable; - -public class SerializableBlockData implements Serializable { - private static final long serialVersionUID = 5298928608478640008L; - private final String data; - - public SerializableBlockData(BlockData d) { - this.data = d.getAsString(false); - } - - public BlockData getData() { - return Bukkit.createBlockData(data); - } -} diff --git a/src/main/java/com/dfsek/terra/structure/serialize/block/SerializableBanner.java b/src/main/java/com/dfsek/terra/structure/serialize/block/SerializableBanner.java deleted file mode 100644 index 36a2ae145..000000000 --- a/src/main/java/com/dfsek/terra/structure/serialize/block/SerializableBanner.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.dfsek.terra.structure.serialize.block; - -import org.bukkit.DyeColor; -import org.bukkit.block.Banner; -import org.bukkit.block.BlockState; -import org.bukkit.block.banner.PatternType; - -import java.io.Serializable; -import java.util.ArrayList; - -public class SerializableBanner implements SerializableBlockState { - private static final long serialVersionUID = 5298928608478640004L; - private final DyeColor base; - private final ArrayList patterns = new ArrayList<>(); - - public SerializableBanner(Banner banner) { - this.base = banner.getBaseColor(); - for(org.bukkit.block.banner.Pattern bukkitPattern : banner.getPatterns()) { - patterns.add(new Pattern(bukkitPattern.getPattern(), bukkitPattern.getColor())); - } - } - - @Override - public BlockState getState(BlockState orig) { - if(!(orig instanceof Banner)) throw new IllegalArgumentException("Provided BlockState is not a banner."); - Banner banner = (Banner) orig; - banner.setBaseColor(base); - for(Pattern pattern : patterns) { - banner.addPattern(new org.bukkit.block.banner.Pattern(pattern.getColor(), pattern.getType())); - } - return banner; - } - - private static final class Pattern implements Serializable { - private static final long serialVersionUID = -7802163816361757171L; - private final DyeColor color; - private final PatternType type; - - public Pattern(PatternType type, DyeColor color) { - this.color = color; - this.type = type; - } - - public DyeColor getColor() { - return color; - } - - public PatternType getType() { - return type; - } - } -} diff --git a/src/main/java/com/dfsek/terra/structure/serialize/block/SerializableBlockState.java b/src/main/java/com/dfsek/terra/structure/serialize/block/SerializableBlockState.java deleted file mode 100644 index 218db7cef..000000000 --- a/src/main/java/com/dfsek/terra/structure/serialize/block/SerializableBlockState.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.dfsek.terra.structure.serialize.block; - -import org.bukkit.block.BlockState; - -import java.io.Serializable; - -public interface SerializableBlockState extends Serializable { - long serialVersionUID = 5298928608478640000L; - - BlockState getState(BlockState orig); -} diff --git a/src/main/java/com/dfsek/terra/structure/serialize/block/SerializableMonsterCage.java b/src/main/java/com/dfsek/terra/structure/serialize/block/SerializableMonsterCage.java deleted file mode 100644 index 66d5d07af..000000000 --- a/src/main/java/com/dfsek/terra/structure/serialize/block/SerializableMonsterCage.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.dfsek.terra.structure.serialize.block; - -import org.bukkit.block.BlockState; -import org.bukkit.block.CreatureSpawner; -import org.bukkit.entity.EntityType; - -public class SerializableMonsterCage implements SerializableBlockState { - private static final long serialVersionUID = 529892860847864007L; - private final EntityType type; - private final int minDelay; - private final int maxDelay; - private final int maxNear; - private final int playerRange; - private final int delay; - private final int count; - - public SerializableMonsterCage(CreatureSpawner orig) { - this.type = orig.getSpawnedType(); - this.minDelay = orig.getMinSpawnDelay(); - this.maxDelay = orig.getMaxSpawnDelay(); - this.maxNear = orig.getMaxNearbyEntities(); - this.playerRange = orig.getRequiredPlayerRange(); - this.delay = orig.getDelay(); - this.count = orig.getSpawnCount(); - } - - @Override - public BlockState getState(BlockState orig) { - if(!(orig instanceof CreatureSpawner)) - throw new IllegalArgumentException("BlockState is not a Monster Spawner!"); - CreatureSpawner spawner = (CreatureSpawner) orig; - spawner.setSpawnedType(type); - spawner.setMinSpawnDelay(minDelay); - spawner.setMaxSpawnDelay(maxDelay); - spawner.setMaxNearbyEntities(maxNear); - spawner.setRequiredPlayerRange(playerRange); - spawner.setDelay(delay); - spawner.setSpawnCount(count); - return spawner; - } -} diff --git a/src/main/java/com/dfsek/terra/structure/serialize/block/SerializableSign.java b/src/main/java/com/dfsek/terra/structure/serialize/block/SerializableSign.java deleted file mode 100644 index 9786e5c76..000000000 --- a/src/main/java/com/dfsek/terra/structure/serialize/block/SerializableSign.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.dfsek.terra.structure.serialize.block; - -import org.bukkit.block.BlockState; -import org.bukkit.block.Sign; - -public class SerializableSign implements SerializableBlockState { - private static final long serialVersionUID = 5298928608478640001L; - private final String[] text; - private final boolean isEditable; - - public SerializableSign(Sign orig) { - text = orig.getLines(); - this.isEditable = orig.isEditable(); - } - - @Override - public BlockState getState(BlockState orig) { - if(!(orig instanceof Sign)) throw new IllegalArgumentException("Provided BlockState is not a sign."); - Sign sign = (Sign) orig; - for(int i = 0; i < text.length; i++) { - sign.setLine(i, text[i]); - } - sign.setEditable(isEditable); - return sign; - } - - public String[] getLines() { - return text; - } - - public String getLine(int index) { - return text[index]; - } - - public boolean isEditable() { - return isEditable; - } -} diff --git a/src/main/java/com/dfsek/terra/structure/spawn/AirSpawn.java b/src/main/java/com/dfsek/terra/structure/spawn/AirSpawn.java deleted file mode 100644 index cfb37f30b..000000000 --- a/src/main/java/com/dfsek/terra/structure/spawn/AirSpawn.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.dfsek.terra.structure.spawn; - -import com.dfsek.terra.Terra; -import com.dfsek.terra.TerraWorld; -import com.dfsek.terra.biome.UserDefinedBiome; -import com.dfsek.terra.config.templates.BiomeTemplate; -import com.dfsek.terra.generation.config.WorldGenerator; -import org.bukkit.World; -import org.polydev.gaea.generation.GenerationPhase; - -public class AirSpawn extends Requirement { - public AirSpawn(World world, Terra main) { - super(world, main); - } - - @Override - public boolean matches(int x, int y, int z) { - TerraWorld tw = main.getWorld(world); - UserDefinedBiome b = (UserDefinedBiome) tw.getGrid().getBiome(x, z, GenerationPhase.POPULATE); - BiomeTemplate c = b.getConfig(); - if(y <= c.getSeaLevel()) return false; - double elevation = ((WorldGenerator) b.getGenerator()).getElevation(x, z); - return b.getGenerator().getNoise(getNoise(), world, x, y, z) + elevation <= 0; - } -} diff --git a/src/main/java/com/dfsek/terra/structure/spawn/BlankSpawn.java b/src/main/java/com/dfsek/terra/structure/spawn/BlankSpawn.java deleted file mode 100644 index 910d53cee..000000000 --- a/src/main/java/com/dfsek/terra/structure/spawn/BlankSpawn.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.dfsek.terra.structure.spawn; - -public class BlankSpawn extends Requirement { - public BlankSpawn() { - super(null, null); - } - - @Override - public boolean matches(int x, int y, int z) { - return true; - } -} diff --git a/src/main/java/com/dfsek/terra/structure/spawn/LandSpawn.java b/src/main/java/com/dfsek/terra/structure/spawn/LandSpawn.java deleted file mode 100644 index 696cda4ec..000000000 --- a/src/main/java/com/dfsek/terra/structure/spawn/LandSpawn.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.dfsek.terra.structure.spawn; - -import com.dfsek.terra.Terra; -import com.dfsek.terra.TerraWorld; -import com.dfsek.terra.biome.UserDefinedBiome; -import com.dfsek.terra.generation.config.WorldGenerator; -import org.bukkit.World; -import org.polydev.gaea.generation.GenerationPhase; - -public class LandSpawn extends Requirement { - public LandSpawn(World world, Terra main) { - super(world, main); - } - - @Override - public boolean matches(int x, int y, int z) { - TerraWorld tw = main.getWorld(world); - UserDefinedBiome b = (UserDefinedBiome) tw.getGrid().getBiome(x, z, GenerationPhase.POPULATE); - double elevation = ((WorldGenerator) b.getGenerator()).getElevation(x, z); - return b.getGenerator().getNoise(getNoise(), world, x, y, z) + elevation > 0; - } -} diff --git a/src/main/java/com/dfsek/terra/structure/spawn/OceanSpawn.java b/src/main/java/com/dfsek/terra/structure/spawn/OceanSpawn.java deleted file mode 100644 index d17815d50..000000000 --- a/src/main/java/com/dfsek/terra/structure/spawn/OceanSpawn.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.dfsek.terra.structure.spawn; - -import com.dfsek.terra.Terra; -import com.dfsek.terra.TerraWorld; -import com.dfsek.terra.biome.UserDefinedBiome; -import com.dfsek.terra.config.templates.BiomeTemplate; -import com.dfsek.terra.generation.config.WorldGenerator; -import org.bukkit.World; -import org.polydev.gaea.generation.GenerationPhase; - -public class OceanSpawn extends Requirement { - public OceanSpawn(World world, Terra main) { - super(world, main); - } - - @Override - public boolean matches(int x, int y, int z) { - TerraWorld tw = main.getWorld(world); - UserDefinedBiome b = (UserDefinedBiome) tw.getGrid().getBiome(x, z, GenerationPhase.POPULATE); - BiomeTemplate c = b.getConfig(); - if(y > c.getSeaLevel()) return false; - double elevation = ((WorldGenerator) b.getGenerator()).getElevation(x, z); - return b.getGenerator().getNoise(getNoise(), world, x, y, z) + elevation <= 0; - } -} diff --git a/src/main/java/com/dfsek/terra/structure/spawn/Requirement.java b/src/main/java/com/dfsek/terra/structure/spawn/Requirement.java deleted file mode 100644 index 0fd0b4174..000000000 --- a/src/main/java/com/dfsek/terra/structure/spawn/Requirement.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.dfsek.terra.structure.spawn; - -import com.dfsek.terra.Terra; -import com.dfsek.terra.generation.TerraChunkGenerator; -import org.bukkit.World; -import org.polydev.gaea.math.FastNoiseLite; - -import java.util.Objects; - -public abstract class Requirement { - protected final World world; - protected final Terra main; - - public Requirement(World world, Terra main) { - this.world = world; - this.main = main; - } - - public abstract boolean matches(int x, int y, int z); - - protected FastNoiseLite getNoise() { - return ((TerraChunkGenerator) Objects.requireNonNull(world.getGenerator())).getNoiseGenerator(); - } - - public World getWorld() { - return world; - } -} diff --git a/src/main/java/com/dfsek/terra/util/PaletteUtil.java b/src/main/java/com/dfsek/terra/util/PaletteUtil.java deleted file mode 100644 index c1d0e1469..000000000 --- a/src/main/java/com/dfsek/terra/util/PaletteUtil.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.dfsek.terra.util; - -import com.dfsek.terra.biome.palette.PaletteHolder; -import com.dfsek.terra.config.templates.BiomeTemplate; -import com.dfsek.terra.generation.Sampler; -import com.dfsek.terra.math.MathUtil; -import org.bukkit.Material; -import org.bukkit.block.data.BlockData; -import org.polydev.gaea.util.FastRandom; -import org.polydev.gaea.world.palette.Palette; -import org.polydev.gaea.world.palette.RandomPalette; - -public final class PaletteUtil { - public static final BlockData WATER = Material.WATER.createBlockData(); - public static final BlockData AIR = Material.AIR.createBlockData(); - public static final Palette BLANK_PALETTE = new RandomPalette(new FastRandom(2403)).add(AIR, 1); - - public static Palette getPalette(int x, int y, int z, BiomeTemplate c, Sampler sampler) { - PaletteHolder slant = c.getSlantPalette(); - if(slant != null && MathUtil.derivative(sampler, x, y, z) > c.getSlantThreshold()) { - return slant.getPalette(y); - } - return c.getPalette().getPalette(y); - } -} diff --git a/src/main/java/com/dfsek/terra/util/SlabUtil.java b/src/main/java/com/dfsek/terra/util/SlabUtil.java deleted file mode 100644 index 3ab30300c..000000000 --- a/src/main/java/com/dfsek/terra/util/SlabUtil.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.dfsek.terra.util; - -import com.dfsek.terra.generation.Sampler; -import org.bukkit.Material; -import org.bukkit.block.BlockFace; -import org.bukkit.block.data.Bisected; -import org.bukkit.block.data.BlockData; -import org.bukkit.block.data.Waterlogged; -import org.bukkit.block.data.type.Slab; -import org.bukkit.block.data.type.Stairs; -import org.bukkit.generator.ChunkGenerator; -import org.bukkit.util.Vector; -import org.polydev.gaea.world.palette.Palette; - -import java.util.Map; - -public final class SlabUtil { - public static void prepareBlockPartFloor(BlockData down, BlockData orig, ChunkGenerator.ChunkData chunk, Vector block, Map> slabs, - Map> stairs, double thresh, Sampler sampler) { - if(sampler.sample(block.getBlockX(), block.getBlockY() - 0.4, block.getBlockZ()) > thresh) { - if(stairs != null) { - Palette stairPalette = stairs.get(down.getMaterial()); - if(stairPalette != null) { - BlockData stair = stairPalette.get(0, block.getBlockX(), block.getBlockZ()); - Stairs stairNew = (Stairs) stair.clone(); - if(placeStair(orig, chunk, block, thresh, sampler, stairNew)) return; // Successfully placed part. - } - } - BlockData slab = slabs.getOrDefault(down.getMaterial(), PaletteUtil.BLANK_PALETTE).get(0, block.getBlockX(), block.getBlockZ()); - if(slab instanceof Waterlogged) { - ((Waterlogged) slab).setWaterlogged(orig.matches(PaletteUtil.WATER)); - } else if(orig.matches(PaletteUtil.WATER)) return; - chunk.setBlock(block.getBlockX(), block.getBlockY(), block.getBlockZ(), slab); - } - } - - public static void prepareBlockPartCeiling(BlockData up, BlockData orig, ChunkGenerator.ChunkData chunk, Vector block, Map> slabs, - Map> stairs, double thresh, Sampler sampler) { - if(sampler.sample(block.getBlockX(), block.getBlockY() + 0.4, block.getBlockZ()) > thresh) { - if(stairs != null) { - Palette stairPalette = stairs.get(up.getMaterial()); - if(stairPalette != null) { - BlockData stair = stairPalette.get(0, block.getBlockX(), block.getBlockZ()).clone(); - Stairs stairNew = (Stairs) stair.clone(); - stairNew.setHalf(Bisected.Half.TOP); - if(placeStair(orig, chunk, block, thresh, sampler, stairNew)) return; // Successfully placed part. - } - } - BlockData slab = slabs.getOrDefault(up.getMaterial(), PaletteUtil.BLANK_PALETTE).get(0, block.getBlockX(), block.getBlockZ()).clone(); - if(slab instanceof Bisected) ((Bisected) slab).setHalf(Bisected.Half.TOP); - if(slab instanceof Slab) ((Slab) slab).setType(Slab.Type.TOP); - if(slab instanceof Waterlogged) { - ((Waterlogged) slab).setWaterlogged(orig.matches(PaletteUtil.WATER)); - } else if(orig.matches(PaletteUtil.WATER)) return; // Only replace water if waterlogged. - chunk.setBlock(block.getBlockX(), block.getBlockY(), block.getBlockZ(), slab); - } - } - - private static boolean placeStair(BlockData orig, ChunkGenerator.ChunkData chunk, Vector block, double thresh, Sampler sampler, Stairs stairNew) { - if(sampler.sample(block.getBlockX() - 0.55, block.getBlockY(), block.getBlockZ()) > thresh) { - stairNew.setFacing(BlockFace.WEST); - } else if(sampler.sample(block.getBlockX(), block.getBlockY(), block.getBlockZ() - 0.55) > thresh) { - stairNew.setFacing(BlockFace.NORTH); - } else if(sampler.sample(block.getBlockX(), block.getBlockY(), block.getBlockZ() + 0.55) > thresh) { - stairNew.setFacing(BlockFace.SOUTH); - } else if(sampler.sample(block.getBlockX() + 0.55, block.getBlockY(), block.getBlockZ()) > thresh) { - stairNew.setFacing(BlockFace.EAST); - } else stairNew = null; - if(stairNew != null) { - if(orig.matches(PaletteUtil.WATER)) stairNew.setWaterlogged(true); - chunk.setBlock(block.getBlockX(), block.getBlockY(), block.getBlockZ(), stairNew); - return true; - } - return false; - } -} diff --git a/src/main/java/com/dfsek/terra/util/StructureTypeEnum.java b/src/main/java/com/dfsek/terra/util/StructureTypeEnum.java deleted file mode 100644 index 0cbfdbdcf..000000000 --- a/src/main/java/com/dfsek/terra/util/StructureTypeEnum.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.dfsek.terra.util; - -import org.bukkit.StructureType; - -/** - * Enum to represent StructureType, which is a class for some reason. - */ -@SuppressWarnings("unused") -public enum StructureTypeEnum { - MINESHAFT(StructureType.MINESHAFT), - VILLAGE(StructureType.VILLAGE), - NETHER_FORTRESS(StructureType.NETHER_FORTRESS), - /** - * Currently the only one used. - */ - STRONGHOLD(StructureType.STRONGHOLD), - JUNGLE_PYRAMID(StructureType.JUNGLE_PYRAMID), - OCEAN_RUIN(StructureType.OCEAN_RUIN), - DESERT_PYRAMID(StructureType.DESERT_PYRAMID), - IGLOO(StructureType.IGLOO), - SWAMP_HUT(StructureType.SWAMP_HUT), - OCEAN_MONUMENT(StructureType.OCEAN_MONUMENT), - END_CITY(StructureType.END_CITY), - WOODLAND_MANSION(StructureType.WOODLAND_MANSION), - BURIED_TREASURE(StructureType.BURIED_TREASURE), - SHIPWRECK(StructureType.SHIPWRECK), - PILLAGER_OUTPOST(StructureType.PILLAGER_OUTPOST), - NETHER_FOSSIL(StructureType.NETHER_FOSSIL), - RUINED_PORTAL(StructureType.RUINED_PORTAL), - BASTION_REMNANT(StructureType.BASTION_REMNANT); - - private final StructureType type; - - StructureTypeEnum(StructureType type) { - this.type = type; - } - - public StructureType getType() { - return type; - } -} diff --git a/src/main/java/com/dfsek/terra/util/TagUtil.java b/src/main/java/com/dfsek/terra/util/TagUtil.java deleted file mode 100644 index 375d014a9..000000000 --- a/src/main/java/com/dfsek/terra/util/TagUtil.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.dfsek.terra.util; - -import com.dfsek.terra.debug.Debug; -import org.bukkit.Material; -import org.bukkit.Tag; -import org.jetbrains.annotations.NotNull; - -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -@SuppressWarnings("unchecked") -public final class TagUtil { - private static final Map> tagMap; - - static { - Debug.info("Loading tags..."); - tagMap = new HashMap<>(); - - Field[] tags = Tag.class.getFields(); // Add Bukkit tags - for(Field field : tags) { - if(Modifier.isStatic(field.getModifiers())) { - try { - Tag tag = (Tag) field.get(new Object()); - tagMap.put(tag.getKey().toString(), tag.getValues()); - } catch(IllegalAccessException e) { - e.printStackTrace(); - } catch(ClassCastException ignore) { - } - } - } - putCustomSet("minecraft:base_stone_nether", Material.NETHERRACK, Material.BASALT, Material.BLACKSTONE); - putCustomSet("minecraft:base_stone_overworld", Material.STONE, Material.GRANITE, Material.DIORITE, Material.ANDESITE); - - Set snow = new HashSet<>(); - Set solid = new HashSet<>(); - for(Material m : Material.values()) { - if(m.isSolid()) solid.add(m); - String name = m.toString().toLowerCase(); - if(name.contains("slab") - || name.contains("stair") - || name.contains("wall") - || name.contains("fence") - || name.contains("lantern") - || name.contains("chest") - || name.contains("door") - || name.contains("repeater") - || name.equals("lily_pad") - || name.equals("snow") - || name.equals("pane") - || !m.isSolid()) snow.add(m); - } - tagMap.put("terra:snow_blacklist", snow); - tagMap.put("terra:solid", solid); - Debug.info("Added " + snow.size() + " materials to snow blacklist"); - Debug.info("Added " + solid.size() + " materials to solid list"); - Debug.info("Loaded " + tagMap.size() + " tags."); - } - - private static Set getSet(Material... materials) { - return Stream.of(materials).collect(Collectors.toSet()); - } - - private static void putCustomSet(String key, Material... materials) { - tagMap.put(key, getSet(materials)); - } - - @NotNull - public static Set getTag(String tag) { - return Objects.requireNonNull(tagMap.get(tag)); - } -} diff --git a/src/main/resources/lang/fr_fr.yml b/src/main/resources/lang/fr_fr.yml deleted file mode 100644 index 2ebcb0a5a..000000000 --- a/src/main/resources/lang/fr_fr.yml +++ /dev/null @@ -1,122 +0,0 @@ -enable: - - "Si vous aimez Terra, considérez de supporter le proket sur Patreon!" - - "Vous aurez accès à des fonctionnalités expérimentales avant leur sortie!!" - - "Supportez le projet ici: https://www.patreon.com/dfsek" -disable: - - "Merci à vous d'utiliser Terra!" -command: - debug-only: "Cette commande ne peut être utilisée sans le mode debug!" - player-only: "Cette commande ne peut être exécutée que par un joueur!" - invalid: "Commande invalide. (%1$s arguments attendus, %2$s trouvés)." - players-only: "La commande est seulement pour les joueurs." - world: "Cette commande ne peut être exécutée que dans un monde Terra!" - reload: "Configuration de Terra rechargée." - reload-error: "Des erreurs sont survenues pendant le rechargement de la configuration de Terra. Regardez les logs pour plus d'informations." - version: "Ce serveur utilise la version \"%1$s\" de Terra, avec l'implémentation \"%2$s\" de Gaea" - main-menu: - - "--------------------Terra--------------------" - - "reload - Recharger les données de configuration" - - "biome - Obtenir le biome actuel" - - "ore - Générer une veine de minerais à l'endroit où vous regardez (à des fins de debugging)" - - "save-data - Sauvegarder les données de population" - - "structure - Charger et exporter des structures" - - "profile - Options du Profiler" - - "image - Options des Image/GUI" - biome: - biome-found: "Biome trouvé en (%1$s, %2$s)" - unable-to-locate: "Impossible de trouver le biome." - invalid-radius: "Rayon invalide: \"%s\"" - invalid: "Biome ID invalide: \"%s\"" - in: "Vous êtes dans \"%s\"" - packs: - main: "Config packs actuellement installés:" - pack: " - %1$s v%3$s by %2$s" - none: "Aucun config pack n'est installé." - ore: - main-menu: - - "---------------Terra/minerais---------------" - - "Génère une veine de minerai sur le bloc que vous regardez." - out-of-range: "Bloc hors de portée" - invalid-ore: "Impossible de trouver le minerai \"%s\"" - geometry: - main-menu: - - "---------------Terra/géometrie----------------" - - "Diverses commandes de debugging pour la géométrie voxel" - - "sphere - Génère une sphère" - - "deformsphere - Génère une sphère déformée" - - "tube - Génère un tube" - deform: - invalid-radius: "Rayon invalide: \"%s\"" - invalid-deform: "Déformation invalide: \"%s\"" - invalid-frequency: "Fréquence invalide: \"%s\"" - sphere: - invalid-radius: "Rayon invalide: \"%s\"" - tube: - invalid-radius: "Rayon invalide: \"%s\"" - image: - main-menu: - - "---------------Terra/image---------------" - - "render - Rendre une image avec des dimensions données, qui pourra ensuite être importée dans le monde." - - "gui - Ouvrir le GUI de debug (doit être activé dans la configuration)" - gui: - main-menu: - - "-------------Terra/image/gui-------------" - - "raw - Ouvir le GUI avec les données de biomes brutes" - - "step - Re-rendre des données pour afficher les bordures plus clairement" - debug: "Le mode debug doit être activé pour utiliser le GUI de debug! Ce GUI n'est PAS SÛR EN PRODUCTION!" - render: - save: "Image sauvegardé vers \"%s\"" - error: "Une erreur est survenue pendant la génération de l'image!" - profile: - main-menu: - - "---------------Terra/profile---------------" - - "start - Lance le profiler" - - "stop - Arrête le profiler" - - "query - Récupère les données du profiler" - - "reset - Réinitialise les données du profiler" - reset: "Le profiler a été réinitialisé." - start: "Le profiler a démarré." - stop: "Le profiler s'est arrêté." - structure: - main-menu: - - "---------------Terra/structure---------------" - - "export - Exporte votre sélection WorldEdit actuelle en tant que structure Terra." - - "load - Charge une structure Terra" - invalid-radius: "Rayon invalide: \"%s\"" - invalid-rotation: "Rotation invalide: \"%s\"" - invalid: "Structure ID invalide: \"%s\"" - export: "Structure sauvegardée vers \"%s\"" -world-config: - load: "Chargement des valeurs de configuration pour le monde \"%s\"..." - not-found: "Configuration pour le monde \"%s\" inexistante. Cope de la config par défaut." - using-image: "Chargement du monde à partir d'une image." - error: "Impossible de charger la configuration du monde %s" - done: "Chargement du modne \"%1$s\" terminée. Temps écoulé: %2$sms" -config-pack: - loaded: "Config pack %1$s v%4$s par %3$s chargé en %2$sms." -config: - loaded: "%1$s chargé à partir du fichier %2$s" - loaded-all: "%1$s %2$s(s) chargé(s) en %3$sms." - error: - invalid-failover: "Type de failover invalide: \"%s\"" - duplicate: "Duplication d'ID trouvée dans le fichier: %s" - file: - - "Erreur de configuration pour un objet Terra. Fichier: %1$s" - - "%2$s" - - "Corrigez ceci avant de procéder!" - generic: - - "Une erreur est survenue lors du chargement des configurations." - - "Veuillez reporter ceci à Terra." -warning: - no-population: "Aucun chunk de population n'était chargé. Si il s'agit du premier lancement de votre server avec Terra, ou si vous créez un nouveau monde, c'est normal." -error: - severe-config: "Une erreur configuration importante a empêché Terra de générer correctement le terrain aux coordonnées: %1$s, %2$s. Veuillez vérifier votre configuration. Tout erreur de configuration aura été reportée au-dessus." -debug: - data-save: "Données de population sauvegardées pour le monde \"%s\"" -use-paper: - - "Il semble que vous utilisez Spigot/CraftBukkit." - - "Bien que Terra &ofonctionne&r avec Spigot, des fonctionnalités seront perdues. (Terra n'est pas testé sur CraftBukkit; aucun support ne sera donné sur ce serveur)." - - "Pour obtenir le maximum de Terra, veuillez passer sur Paper." - - "De plus, Paper offre d'immenses optimisations de performances par rapport à Spigot, et tous les plugins Spigot devraient fonctionner avec Paper!" - - "To have the best experience with Terra, and all your plugins, please use Paper." - - "Plus d'infos sur le site web de Paper: https://papermc.io/" diff --git a/src/test/java/DistributionTest.java b/src/test/java/DistributionTest.java deleted file mode 100644 index 27f2d556b..000000000 --- a/src/test/java/DistributionTest.java +++ /dev/null @@ -1,83 +0,0 @@ -import net.jafama.FastMath; -import org.junit.jupiter.api.Test; -import org.polydev.gaea.math.FastNoiseLite; - -class DistributionTest { - private static final double[] normalMap = new double[] {-0.8408907651901245D, -0.8200346231460571D, -0.8070776462554932D, -0.7970088720321655D, -0.7890776991844177D, -0.7819743156433105D, -0.7759857773780823D, -0.7706204056739807D, -0.765608549118042D, -0.7611993551254272D, -0.7569039463996887D, -0.7528656125068665D, -0.7492497563362122D, -0.7458332777023315D, -0.7424643039703369D, -0.7392163872718811D, -0.736059844493866D, -0.7332375049591064D, -0.7305010557174683D, -0.7277776598930359D, -0.7251102924346924D, -0.7227165699005127D, -0.7203239798545837D, -0.7179931998252869D, -0.7157421112060547D, -0.7135322690010071D, -0.71131432056427D, -0.7092097997665405D, -0.7071162462234497D, -0.7050217390060425D, -0.703119695186615D, -0.7011850476264954D, -0.6992706060409546D, -0.6974170207977295D, -0.6955324411392212D, -0.6937324404716492D, -0.6919872760772705D, -0.690233588218689D, -0.6885692477226257D, -0.6869722008705139D, -0.6852975487709045D, -0.683682382106781D, -0.6821723580360413D, -0.6806833744049072D, -0.679179310798645D, -0.6776503324508667D, -0.676136314868927D, -0.6746450662612915D, -0.6731522083282471D, -0.6717588305473328D, -0.6702994704246521D, -0.6689524054527283D, -0.6675862073898315D, -0.6662633419036865D, -0.6649606823921204D, -0.6636543273925781D, -0.6623714566230774D, -0.6610865592956543D, -0.6598274111747742D, -0.6585804224014282D, -0.6573819518089294D, -0.6561920642852783D, -0.6549379825592041D, -0.6537073254585266D, -0.6525376439094543D, -0.6513495445251465D, -0.650168240070343D, -0.649040162563324D, -0.6479091048240662D, -0.6467820405960083D, -0.6456737518310547D, -0.6445609331130981D, -0.6434952020645142D, -0.6424031257629395D, -0.6413089632987976D, -0.640256941318512D, -0.6391684412956238D, -0.638137936592102D, -0.6371254324913025D, -0.6361099481582642D, -0.6350630521774292D, -0.6339953541755676D, -0.6330388188362122D, -0.632024347782135D, -0.6310704946517944D, -0.6300620436668396D, -0.6290494799613953D, -0.6280747056007385D, -0.6271024346351624D, -0.6261362433433533D, -0.6251688599586487D, -0.6242944002151489D, -0.6233505606651306D, -0.622406542301178D, -0.6214921474456787D, -0.6205630302429199D, -0.619683563709259D, -0.6187522411346436D, -0.6178513169288635D, -0.6170046925544739D, -0.6161392331123352D, -0.615269660949707D, -0.6144152879714966D, -0.6135557293891907D, -0.6127009391784668D, -0.6117991209030151D, -0.6109536290168762D, -0.6101033091545105D, -0.6092590689659119D, -0.6084139347076416D, -0.6075553894042969D, -0.6067432165145874D, -0.6058894991874695D, -0.6050370335578918D, -0.6042441725730896D, -0.6034530401229858D, -0.6026210784912109D, -0.6018084287643433D, -0.6010326743125916D, -0.6002528071403503D, -0.5994450449943542D, -0.5986629128456116D, -0.5978666543960571D, -0.5971032977104187D, -0.5963031649589539D, -0.5955566167831421D, -0.5947844982147217D, -0.5940142869949341D, -0.5932715535163879D, -0.5925368666648865D, -0.5917928218841553D, -0.591031014919281D, -0.5903055667877197D, -0.5895851850509644D, -0.5888315439224243D, -0.5880893468856812D, -0.5873630046844482D, -0.5866444110870361D, -0.5859208106994629D, -0.5852057933807373D, -0.5844889879226685D, -0.5837893486022949D, -0.5830587148666382D, -0.582359254360199D, -0.5816157460212708D, -0.5809139013290405D, -0.5802302956581116D, -0.5795474052429199D, -0.5788565874099731D, -0.5781614184379578D, -0.5774743556976318D, -0.5767905712127686D, -0.5760961771011353D, -0.5754467248916626D, -0.5747898817062378D, -0.5741211175918579D, -0.5734619498252869D, -0.5728112459182739D, -0.5721414089202881D, -0.5714717507362366D, -0.5708272457122803D, -0.5701769590377808D, -0.5695428252220154D, -0.568885087966919D, -0.5682525038719177D, -0.5675948262214661D, -0.5669249296188354D, -0.5663014054298401D, -0.5656630992889404D, -0.5650165677070618D, -0.5643728971481323D, -0.5637710094451904D, -0.5631371736526489D, -0.562507152557373D, -0.5618733167648315D, -0.5612503290176392D, -0.560631513595581D, -0.5600159168243408D, -0.559416651725769D, -0.5587995052337646D, -0.5581864714622498D, -0.5575871467590332D, -0.556957483291626D, -0.5563494563102722D, -0.555757999420166D, -0.5551457405090332D, -0.5545571446418762D, -0.5539442300796509D, -0.5533522367477417D, -0.5527352094650269D, -0.5521476864814758D, -0.5515644550323486D, -0.5509964823722839D, -0.550428032875061D, -0.5498668551445007D, -0.5492658615112305D, -0.5486577749252319D, -0.5480945110321045D, -0.5475296378135681D, -0.5469772815704346D, -0.5463858246803284D, -0.5458088517189026D, -0.545259952545166D, -0.5447098016738892D, -0.5441542863845825D, -0.5436179041862488D, -0.5430275201797485D, -0.5424584746360779D, -0.5419116616249084D, -0.5413541197776794D, -0.5408090353012085D, -0.5402546525001526D, -0.5396901369094849D, -0.539120078086853D, -0.5385692715644836D, -0.5380025506019592D, -0.5374376773834229D, -0.5369035601615906D, -0.5363785624504089D, -0.5358348488807678D, -0.5352905988693237D, -0.5347356796264648D, -0.5341591238975525D, -0.5336212515830994D, -0.5330695509910583D, -0.5325397849082947D, -0.5319978594779968D, -0.5314696431159973D, -0.530921220779419D, -0.530373752117157D, -0.5298687219619751D, -0.529342770576477D, -0.5288130044937134D, -0.5282856822013855D, -0.5277521014213562D, -0.5272186994552612D, -0.526702880859375D, -0.5261659026145935D, -0.5256563425064087D, -0.5251585245132446D, -0.524644136428833D, -0.5240897536277771D, -0.5235958695411682D, -0.5230914354324341D, -0.5225777626037598D, -0.5220786929130554D, -0.5215602517127991D, -0.5210496187210083D, -0.5205234885215759D, -0.5199909210205078D, -0.5194736123085022D, -0.5189557075500488D, -0.5184388160705566D, -0.517956018447876D, -0.5174460411071777D, -0.5169391632080078D, -0.5164353251457214D, -0.5159274935722351D, -0.5154002904891968D, -0.5149046778678894D, -0.5143994092941284D, -0.5139294862747192D, -0.5134499669075012D, -0.5129679441452026D, -0.5124912261962891D, -0.511996328830719D, -0.5114986300468445D, -0.5110247135162354D, -0.5105308294296265D, -0.5100609064102173D, -0.5095614194869995D, -0.5090870261192322D, -0.5085906982421875D, -0.5081197619438171D, -0.5076301097869873D, -0.507135808467865D, -0.5066789388656616D, -0.5062170624732971D, -0.5057358145713806D, -0.5052729845046997D, -0.5048062205314636D, -0.5043444037437439D, -0.5038503408432007D, -0.5033678412437439D, -0.5029129981994629D, -0.5024451017379761D, -0.5019713640213013D, -0.501503586769104D, -0.5010541677474976D, -0.500596284866333D, -0.5001118183135986D, -0.49962663650512695D, -0.4991636574268341D, -0.49869197607040405D, -0.4982263445854187D, -0.4977402091026306D, -0.49727755784988403D, -0.496805876493454D, -0.49637076258659363D, -0.4958948493003845D, -0.49544137716293335D, -0.49501892924308777D, -0.4945528209209442D, -0.49409356713294983D, -0.49364787340164185D, -0.49319401383399963D, -0.49275630712509155D, -0.4923110902309418D, -0.4918690621852875D, -0.49141621589660645D, -0.49096524715423584D, -0.4905273914337158D, -0.4900781512260437D, -0.48962411284446716D, -0.4891759753227234D, -0.48872804641723633D, -0.4882771670818329D, -0.48784005641937256D, -0.48739326000213623D, -0.48694151639938354D, -0.48648712038993835D, -0.48605871200561523D, -0.4856131374835968D, -0.4851803183555603D, -0.4847318232059479D, -0.4842924177646637D, -0.48386046290397644D, -0.4834265112876892D, -0.4829675257205963D, -0.482522189617157D, -0.4820839762687683D, -0.48165363073349D, -0.4812239706516266D, -0.4807860255241394D, -0.4803447425365448D, -0.4798981845378876D, -0.4794575572013855D, -0.4790170192718506D, -0.47858935594558716D, -0.4781353175640106D, -0.477681040763855D, -0.477261483669281D, -0.4768490791320801D, -0.4764252305030823D, -0.47600477933883667D, -0.47555917501449585D, -0.4751377999782562D, -0.47470518946647644D, -0.47426924109458923D, -0.4738460183143616D, -0.47342449426651D, -0.4730163812637329D, -0.4726114571094513D, -0.4721759557723999D, -0.4717848598957062D, -0.4713689088821411D, -0.4709392488002777D, -0.47049304842948914D, -0.4700826108455658D, -0.4696255028247833D, -0.46921586990356445D, -0.46877801418304443D, -0.46836233139038086D, -0.46794429421424866D, -0.46752703189849854D, -0.4670995771884918D, -0.4666939377784729D, -0.46625566482543945D, -0.4658403992652893D, -0.4654417932033539D, -0.465023398399353D, -0.46460986137390137D, -0.46419557929039D, -0.46378859877586365D, -0.46336546540260315D, -0.46295180916786194D, -0.4625388979911804D, -0.46212026476860046D, -0.4617091715335846D, -0.46131056547164917D, -0.46089276671409607D, -0.4604875445365906D, -0.46008041501045227D, -0.4596766233444214D, -0.4592905044555664D, -0.45886731147766113D, -0.4584708511829376D, -0.458060622215271D, -0.457650750875473D, -0.4572262763977051D, -0.45681101083755493D, -0.4564330577850342D, -0.4560151696205139D, -0.4556240141391754D, -0.4552316963672638D, -0.4548242688179016D, -0.4544048309326172D, -0.4539957046508789D, -0.45359495282173157D, -0.4532042443752289D, -0.4528181552886963D, -0.4524168372154236D, -0.4519919157028198D, -0.4515584409236908D, -0.45118191838264465D, -0.45078909397125244D, -0.4504043459892273D, -0.4500110447406769D, -0.44961291551589966D, -0.44922786951065063D, -0.4488254189491272D, -0.448411762714386D, -0.44801002740859985D, -0.4476070702075958D, -0.4472062289714813D, -0.44680875539779663D, -0.44641414284706116D, -0.44601938128471375D, -0.4456106126308441D, -0.4452301263809204D, -0.44483858346939087D, -0.44447171688079834D, -0.44407233595848083D, -0.44368883967399597D, -0.44329920411109924D, -0.4429243206977844D, -0.4425082802772522D, -0.4421197474002838D, -0.4417261481285095D, -0.4413236379623413D, -0.44093117117881775D, -0.4405667185783386D, -0.4401840567588806D, -0.43980535864830017D, -0.43940675258636475D, -0.439028263092041D, -0.43865975737571716D, -0.4382753372192383D, -0.43788960576057434D, -0.4374869465827942D, -0.4371262192726135D, -0.4367597997188568D, -0.43636399507522583D, -0.4359838366508484D, -0.4355921745300293D, -0.4352045953273773D, -0.43481752276420593D, -0.4344243109226227D, -0.4340437948703766D, -0.433651864528656D, -0.43328702449798584D, -0.43291205167770386D, -0.43252551555633545D, -0.4321480095386505D, -0.4317898750305176D, -0.4314233064651489D, -0.43104124069213867D, -0.43066880106925964D, -0.430292546749115D, -0.4299023747444153D, -0.4295300245285034D, -0.42915427684783936D, -0.4287806749343872D, -0.42839178442955017D, -0.4280126392841339D, -0.427650511264801D, -0.4272746443748474D, -0.426890105009079D, -0.4265204966068268D, -0.4261537194252014D, -0.42576107382774353D, -0.4253731369972229D, -0.4249960482120514D, -0.424624502658844D, -0.424255907535553D, -0.42388004064559937D, -0.42350152134895325D, -0.42311522364616394D, -0.4227565824985504D, -0.42240461707115173D, -0.4220307767391205D, -0.4216674268245697D, -0.42131006717681885D, -0.420943945646286D, -0.4205697178840637D, -0.42019638419151306D, -0.41983455419540405D, -0.4194658100605011D, -0.4190995693206787D, -0.41873085498809814D, -0.4183567464351654D, -0.4179975688457489D, -0.4176383316516876D, -0.41729846596717834D, -0.41692838072776794D, -0.41655758023262024D, -0.41620612144470215D, -0.4158278703689575D, -0.4154700040817261D, -0.4151083528995514D, -0.4147477149963379D, -0.4143727421760559D, -0.41399645805358887D, -0.41361644864082336D, -0.41325125098228455D, -0.4128910303115845D, -0.4125325381755829D, -0.412177711725235D, -0.41182252764701843D, -0.41146835684776306D, -0.411092609167099D, -0.4107370972633362D, -0.41037485003471375D, -0.41001537442207336D, -0.40966421365737915D, -0.4093012511730194D, -0.40894198417663574D, -0.40859392285346985D, -0.4082479178905487D, -0.4078933000564575D, -0.4075292944908142D, -0.40716227889060974D, -0.4068087041378021D, -0.4064478874206543D, -0.406091570854187D, -0.40573540329933167D, -0.40538454055786133D, -0.40504181385040283D, -0.4047034680843353D, -0.4043614864349365D, -0.40400779247283936D, -0.4036547839641571D, -0.4032823443412781D, -0.4029378592967987D, -0.4025970697402954D, -0.402246356010437D, -0.40188851952552795D, -0.40156131982803345D, -0.40120363235473633D, -0.4008401036262512D, -0.40048736333847046D, -0.4001263976097107D, -0.39976367354393005D, -0.39942193031311035D, -0.3990681767463684D, -0.3987242877483368D, -0.398363322019577D, -0.39801621437072754D, -0.39766016602516174D, -0.39731889963150024D, -0.39698633551597595D, -0.39662742614746094D, -0.39628860354423523D, -0.39593571424484253D, -0.395590215921402D, -0.3952309787273407D, -0.3948807716369629D, -0.39455100893974304D, -0.3942095935344696D, -0.39386501908302307D, -0.3935443162918091D, -0.3931947946548462D, -0.39285120368003845D, -0.3925047814846039D, -0.39214301109313965D, -0.39179378747940063D, -0.3914482891559601D, -0.39108943939208984D, -0.3907601833343506D, -0.3904222249984741D, -0.3900834023952484D, -0.38973814249038696D, -0.3894020617008209D, -0.38905972242355347D, -0.38871514797210693D, -0.3883773684501648D, -0.3880293369293213D, -0.3876887559890747D, -0.38734734058380127D, -0.386979341506958D, -0.38662150502204895D, -0.38627174496650696D, -0.3859280049800873D, -0.38558584451675415D, -0.3852563500404358D, -0.3849097490310669D, -0.38456815481185913D, -0.38420337438583374D, -0.38386270403862D, -0.38352808356285095D, -0.3831936717033386D, -0.3828587532043457D, -0.3825334906578064D, -0.3822133243083954D, -0.38188061118125916D, -0.3815428614616394D, -0.3812029957771301D, -0.38088124990463257D, -0.38053950667381287D, -0.38019588589668274D, -0.37985116243362427D, -0.3795320689678192D, -0.379200279712677D, -0.37889277935028076D, -0.37856200337409973D, -0.3782331347465515D, -0.3779050409793854D, -0.3775690197944641D, -0.3772413730621338D, -0.3769242763519287D, -0.3765946924686432D, -0.37626904249191284D, -0.3759467601776123D, -0.37560951709747314D, -0.3752872347831726D, -0.37494587898254395D, -0.3746064007282257D, -0.3742677569389343D, -0.3739333748817444D, -0.3736076056957245D, -0.37326452136039734D, -0.37293750047683716D, -0.3725985884666443D, -0.3722609877586365D, -0.37193018198013306D, -0.3715952932834625D, -0.3712655007839203D, -0.3709229826927185D, -0.3705999255180359D, -0.37027597427368164D, -0.369951069355011D, -0.3696173429489136D, -0.3692963123321533D, -0.36897599697113037D, -0.36867132782936096D, -0.3683592677116394D, -0.3680408298969269D, -0.3677233159542084D, -0.367404967546463D, -0.36708003282546997D, -0.36677178740501404D, -0.3664388358592987D, -0.36611905694007874D, -0.3658014237880707D, -0.36547884345054626D, -0.3651513159275055D, -0.36481767892837524D, -0.3644823729991913D, -0.364155650138855D, -0.36383169889450073D, -0.36351490020751953D, -0.3631979823112488D, -0.3628738224506378D, -0.36254048347473145D, -0.3622121512889862D, -0.3618980348110199D, -0.3615726828575134D, -0.3612515330314636D, -0.3609353005886078D, -0.36061736941337585D, -0.36030900478363037D, -0.3599989712238312D, -0.3596540689468384D, -0.35933634638786316D, -0.35900697112083435D, -0.3586837351322174D, -0.35836634039878845D, -0.3580488860607147D, -0.35772836208343506D, -0.3574066162109375D, -0.3570963144302368D, -0.3567792475223541D, -0.356449693441391D, -0.35615187883377075D, -0.3558260202407837D, -0.3555348217487335D, -0.3552199602127075D, -0.3548942804336548D, -0.3545764684677124D, -0.35425788164138794D, -0.3539428114891052D, -0.3536147177219391D, -0.35328033566474915D, -0.3529603183269501D, -0.3526480793952942D, -0.35232388973236084D, -0.35200271010398865D, -0.35168105363845825D, -0.35135796666145325D, -0.3510427176952362D, -0.3507138788700104D, -0.35040056705474854D, -0.3500818610191345D, -0.34976863861083984D, -0.34945595264434814D, -0.34914907813072205D, -0.3488360345363617D, -0.34851935505867004D, -0.3481927514076233D, -0.3478827476501465D, -0.3475636839866638D, -0.34725847840309143D, -0.3469395339488983D, -0.34662553668022156D, -0.34631386399269104D, -0.3460105359554291D, -0.3456878960132599D, -0.345344603061676D, -0.34503841400146484D, -0.3447076678276062D, -0.344401091337204D, -0.3441048264503479D, -0.3437953293323517D, -0.343493789434433D, -0.34316104650497437D, -0.34285077452659607D, -0.3425139784812927D, -0.34221309423446655D, -0.341905802488327D, -0.3415932357311249D, -0.3412908911705017D, -0.34100088477134705D, -0.34069502353668213D, -0.3403867483139038D, -0.3400827944278717D, -0.3397866189479828D, -0.3394818603992462D, -0.33916914463043213D, -0.3388570249080658D, -0.3385341763496399D, -0.33820855617523193D, -0.3379049599170685D, -0.3375984728336334D, -0.33730369806289673D, -0.33700433373451233D, -0.33670154213905334D, -0.33638641238212585D, -0.33607667684555054D, -0.33575505018234253D, -0.3354572057723999D, -0.3351454734802246D, -0.3348299264907837D, -0.334527850151062D, -0.3342225253582001D, -0.33391332626342773D, -0.3336237072944641D, -0.3332982063293457D, -0.3329954445362091D, -0.3326762020587921D, -0.3323662281036377D, -0.3320602774620056D, -0.33175498247146606D, -0.3314487636089325D, -0.33115020394325256D, -0.330841064453125D, -0.3305378258228302D, -0.3302415609359741D, -0.329933226108551D, -0.329643577337265D, -0.32934796810150146D, -0.32905206084251404D, -0.3287571668624878D, -0.328460156917572D, -0.32815226912498474D, -0.3278505206108093D, -0.3275279998779297D, -0.32723256945610046D, -0.3269461989402771D, -0.3266374468803406D, -0.32633867859840393D, -0.32603901624679565D, -0.32573506236076355D, -0.3254241645336151D, -0.3251294791698456D, -0.3248370289802551D, -0.32453545928001404D, -0.3242391347885132D, -0.32394152879714966D, -0.32363662123680115D, -0.32332345843315125D, -0.323017418384552D, -0.32272642850875854D, -0.32241278886795044D, -0.32211995124816895D, -0.321819007396698D, -0.3215320408344269D, -0.3212323486804962D, -0.3209359347820282D, -0.3206302225589752D, -0.32032862305641174D, -0.3200341463088989D, -0.3197453022003174D, -0.31943413615226746D, -0.31913426518440247D, -0.3188168704509735D, -0.3185330033302307D, -0.3182430863380432D, -0.3179488778114319D, -0.3176538050174713D, -0.31735554337501526D, -0.3170680105686188D, -0.3167757987976074D, -0.3164826035499573D, -0.3161925673484802D, -0.31590309739112854D, -0.3156057894229889D, -0.3153114318847656D, -0.3150043487548828D, -0.3147113621234894D, -0.3144054412841797D, -0.3141002655029297D, -0.3138138949871063D, -0.3135177195072174D, -0.3132264018058777D, -0.31294235587120056D, -0.3126477599143982D, -0.3123481869697571D, -0.31204888224601746D, -0.3117561936378479D, -0.3114587366580963D, -0.3111598491668701D, -0.31085237860679626D, -0.31057536602020264D, -0.31028178334236145D, -0.30997639894485474D, -0.30967190861701965D, -0.30936843156814575D, -0.30909404158592224D, -0.3088019788265228D, -0.30850961804389954D, -0.3082248866558075D, -0.3079489469528198D, -0.3076601028442383D, -0.3073663115501404D, -0.30707186460494995D, -0.306782066822052D, -0.3064883351325989D, -0.3061949610710144D, -0.30590012669563293D, -0.30561313033103943D, -0.3053309917449951D, -0.3050406575202942D, -0.304754376411438D, -0.30446040630340576D, -0.3041768968105316D, -0.3038821816444397D, -0.3035893738269806D, -0.30328431725502014D, -0.3030011057853699D, -0.3027121424674988D, -0.3024280369281769D, -0.30212947726249695D, -0.3018357753753662D, -0.30154919624328613D, -0.30126914381980896D, -0.30098485946655273D, -0.30068662762641907D, -0.30040308833122253D, -0.30009666085243225D, -0.2998005747795105D, -0.2994982898235321D, -0.29921627044677734D, -0.29892295598983765D, -0.2986327111721039D, -0.29834234714508057D, -0.2980586290359497D, -0.29778116941452026D, -0.2974989116191864D, -0.29720795154571533D, -0.2969287931919098D, -0.2966563403606415D, -0.2963668704032898D, -0.2960667610168457D, -0.29577767848968506D, -0.29548513889312744D, -0.29519715905189514D, -0.29489442706108093D, -0.2946091890335083D, -0.2943197190761566D, -0.29404720664024353D, -0.2937503457069397D, -0.2934649586677551D, -0.2931755483150482D, -0.29288724064826965D, -0.29261279106140137D, -0.29232826828956604D, -0.29203593730926514D, -0.2917509078979492D, -0.291476309299469D, -0.2911933362483978D, -0.29089832305908203D, -0.29060450196266174D, -0.29032155871391296D, -0.2900330424308777D, -0.28975367546081543D, -0.28948378562927246D, -0.28919175267219543D, -0.28892582654953003D, -0.28864026069641113D, -0.28835973143577576D, -0.28808465600013733D, -0.28779277205467224D, -0.2875235378742218D, -0.287244975566864D, -0.2869555354118347D, -0.28667202591896057D, -0.2863847613334656D, -0.28609588742256165D, -0.28580570220947266D, -0.28554603457450867D, -0.2852514386177063D, -0.2849790155887604D, -0.28469184041023254D, -0.28441160917282104D, -0.2841390371322632D, -0.2838601768016815D, -0.2835925221443176D, -0.28331464529037476D, -0.28303512930870056D, -0.28274592757225037D, -0.28246626257896423D, -0.28217896819114685D, -0.28188076615333557D, -0.28161147236824036D, -0.2813378572463989D, -0.2810610234737396D, -0.2807842195034027D, -0.2804943323135376D, -0.28019919991493225D, -0.2799144983291626D, -0.27964210510253906D, -0.2793615162372589D, -0.2790962755680084D, -0.27882760763168335D, -0.27854248881340027D, -0.27825871109962463D, -0.2779737710952759D, -0.2777007222175598D, -0.27742964029312134D, -0.27714890241622925D, -0.27688339352607727D, -0.2765926122665405D, -0.2763076424598694D, -0.2760260999202728D, -0.2757579982280731D, -0.27548402547836304D, -0.2751961052417755D, -0.274922251701355D, -0.2746416926383972D, -0.27436795830726624D, -0.2740943133831024D, -0.2738019824028015D, -0.27353906631469727D, -0.27326154708862305D, -0.2729891836643219D, -0.27270472049713135D, -0.27243277430534363D, -0.2721635699272156D, -0.2718750536441803D, -0.2715913951396942D, -0.27133479714393616D, -0.2710684835910797D, -0.2707928419113159D, -0.2705102860927582D, -0.2702246606349945D, -0.26995614171028137D, -0.269681841135025D, -0.26940596103668213D, -0.26912009716033936D, -0.26884424686431885D, -0.2685716450214386D, -0.2682885527610779D, -0.2680133283138275D, -0.2677347660064697D, -0.26747408509254456D, -0.2672025263309479D, -0.26692694425582886D, -0.2666434049606323D, -0.2663731873035431D, -0.26609575748443604D, -0.2658277153968811D, -0.265566885471344D, -0.2652873694896698D, -0.265009343624115D, -0.2647358775138855D, -0.26447242498397827D, -0.2642005383968353D, -0.2639273405075073D, -0.26365959644317627D, -0.26338252425193787D, -0.26311179995536804D, -0.2628440260887146D, -0.26257866621017456D, -0.2623051702976227D, -0.2620226740837097D, -0.26175981760025024D, -0.2614777684211731D, -0.26120269298553467D, -0.2609373927116394D, -0.2606671154499054D, -0.26038432121276855D, -0.2601143717765808D, -0.25984737277030945D, -0.2595686912536621D, -0.2592966556549072D, -0.25902673602104187D, -0.25875210762023926D, -0.25847649574279785D, -0.25820842385292053D, -0.2579323947429657D, -0.25765854120254517D, -0.2574003040790558D, -0.25713491439819336D, -0.2568623721599579D, -0.25658881664276123D, -0.2563152313232422D, -0.25604572892189026D, -0.2557758390903473D, -0.2554943561553955D, -0.25521519780158997D, -0.25494012236595154D, -0.2546757459640503D, -0.2544080913066864D, -0.25414639711380005D, -0.253864049911499D, -0.2535991072654724D, -0.25332823395729065D, -0.25306326150894165D, -0.25280603766441345D, -0.2525345981121063D, -0.25226184725761414D, -0.2519981563091278D, -0.2517358958721161D, -0.2514859139919281D, -0.25121521949768066D, -0.2509450614452362D, -0.2506673038005829D, -0.25037816166877747D, -0.2501011788845062D, -0.24982967972755432D, -0.24956010282039642D, -0.24929192662239075D, -0.24902109801769257D, -0.24874456226825714D, -0.24847736954689026D, -0.2482159286737442D, -0.24794703722000122D, -0.24767209589481354D, -0.24741970002651215D, -0.24716982245445251D, -0.24689742922782898D, -0.24662908911705017D, -0.2463528960943222D, -0.2460920661687851D, -0.2458297461271286D, -0.2455553114414215D, -0.2452864646911621D, -0.24501584470272064D, -0.24475401639938354D, -0.24448587000370026D, -0.24422040581703186D, -0.24395723640918732D, -0.24368800222873688D, -0.24342411756515503D, -0.24315224587917328D, -0.2428782880306244D, -0.24262136220932007D, -0.2423519641160965D, -0.242094025015831D, -0.24183285236358643D, -0.24157416820526123D, -0.24128861725330353D, -0.2410109043121338D, -0.24074263870716095D, -0.24047909677028656D, -0.2402070164680481D, -0.23994535207748413D, -0.23968873918056488D, -0.23940715193748474D, -0.23913469910621643D, -0.23886923491954803D, -0.23860231041908264D, -0.23833289742469788D, -0.23806728422641754D, -0.23780885338783264D, -0.23753899335861206D, -0.23726941645145416D, -0.2369997203350067D, -0.23672956228256226D, -0.23645663261413574D, -0.23618397116661072D, -0.23593071103096008D, -0.23566082119941711D, -0.2354077845811844D, -0.2351534217596054D, -0.23488231003284454D, -0.2346220165491104D, -0.23435726761817932D, -0.2340918332338333D, -0.2338235080242157D, -0.2335655242204666D, -0.2333153784275055D, -0.23306378722190857D, -0.2328043133020401D, -0.23254400491714478D, -0.23228463530540466D, -0.2320064902305603D, -0.23174738883972168D, -0.23149773478507996D, -0.23124253749847412D, -0.23097634315490723D, -0.23071180284023285D, -0.23045700788497925D, -0.230192169547081D, -0.22991830110549927D, -0.22963789105415344D, -0.22937417030334473D, -0.22910505533218384D, -0.22883500158786774D, -0.2285711020231247D, -0.22831669449806213D, -0.2280465066432953D, -0.2277848720550537D, -0.22753745317459106D, -0.22728675603866577D, -0.22702650725841522D, -0.22676996886730194D, -0.22651082277297974D, -0.22624187171459198D, -0.22597870230674744D, -0.22570855915546417D, -0.22543907165527344D, -0.22518296539783478D, -0.22492025792598724D, -0.22467266023159027D, -0.22439832985401154D, -0.22413182258605957D, -0.2238631248474121D, -0.22359998524188995D, -0.22333964705467224D, -0.2230590581893921D, -0.22280718386173248D, -0.22254756093025208D, -0.22228197753429413D, -0.22201159596443176D, -0.22175270318984985D, -0.22150228917598724D, -0.22124618291854858D, -0.22099649906158447D, -0.22074392437934875D, -0.22047969698905945D, -0.22022272646427155D, -0.21997378766536713D, -0.2197091281414032D, -0.21945351362228394D, -0.2192097306251526D, -0.21894562244415283D, -0.21867841482162476D, -0.2184201329946518D, -0.2181641310453415D, -0.21789231896400452D, -0.21763677895069122D, -0.21738234162330627D, -0.2171180546283722D, -0.2168525755405426D, -0.21659737825393677D, -0.2163332849740982D, -0.21607044339179993D, -0.21581339836120605D, -0.21555018424987793D, -0.2152981460094452D, -0.21504613757133484D, -0.21478135883808136D, -0.21452942490577698D, -0.21428382396697998D, -0.21401828527450562D, -0.21376505494117737D, -0.2135121375322342D, -0.21325898170471191D, -0.21300353109836578D, -0.2127491533756256D, -0.21248602867126465D, -0.212227463722229D, -0.21197248995304108D, -0.211714506149292D, -0.21144689619541168D, -0.21119168400764465D, -0.21092993021011353D, -0.2106601893901825D, -0.2104104608297348D, -0.2101590931415558D, -0.2099045366048813D, -0.20964594185352325D, -0.209390327334404D, -0.20913049578666687D, -0.20888525247573853D, -0.20861712098121643D, -0.20835545659065247D, -0.20807304978370667D, -0.20782627165317535D, -0.20756679773330688D, -0.2073090374469757D, -0.20704127848148346D, -0.20678317546844482D, -0.20653437077999115D, -0.20627987384796143D, -0.2060208022594452D, -0.2057662308216095D, -0.20550277829170227D, -0.20525488257408142D, -0.20500688254833221D, -0.20475590229034424D, -0.204499751329422D, -0.20424525439739227D, -0.2039918303489685D, -0.20372796058654785D, -0.2034660130739212D, -0.20319855213165283D, -0.2029460072517395D, -0.20268212258815765D, -0.20242102444171906D, -0.20215927064418793D, -0.20190972089767456D, -0.2016443908214569D, -0.20138707756996155D, -0.20113015174865723D, -0.20087777078151703D, -0.20062702894210815D, -0.2003677785396576D, -0.20011863112449646D, -0.1998559683561325D, -0.19960248470306396D, -0.19935469329357147D, -0.19909074902534485D, -0.19882997870445251D, -0.19857299327850342D, -0.1983131766319275D, -0.1980532854795456D, -0.19780057668685913D, -0.19753916561603546D, -0.19728423655033112D, -0.1970248520374298D, -0.19676361978054047D, -0.19650912284851074D, -0.19625143706798553D, -0.19600039720535278D, -0.1957373321056366D, -0.19547948241233826D, -0.1952110230922699D, -0.19495542347431183D, -0.19469761848449707D, -0.19444851577281952D, -0.19418317079544067D, -0.19392995536327362D, -0.19367724657058716D, -0.19342119991779327D, -0.193157359957695D, -0.19289681315422058D, -0.19262950122356415D, -0.19238001108169556D, -0.19211608171463013D, -0.1918654441833496D, -0.19162078201770782D, -0.19136491417884827D, -0.19111116230487823D, -0.1908569037914276D, -0.19059760868549347D, -0.19035883247852325D, -0.19009436666965485D, -0.18983271718025208D, -0.18957246840000153D, -0.1893143355846405D, -0.18905536830425262D, -0.1888037919998169D, -0.18855144083499908D, -0.18828624486923218D, -0.18803848326206207D, -0.18779553472995758D, -0.18753254413604736D, -0.18728092312812805D, -0.18703658878803253D, -0.18677440285682678D, -0.1865210384130478D, -0.18627333641052246D, -0.1860176920890808D, -0.18575197458267212D, -0.18549758195877075D, -0.18524503707885742D, -0.18499478697776794D, -0.18474870920181274D, -0.18449726700782776D, -0.1842447966337204D, -0.18398450314998627D, -0.18373912572860718D, -0.18347981572151184D, -0.1832396537065506D, -0.1829894334077835D, -0.1827465295791626D, -0.1824868768453598D, -0.18223384022712708D, -0.181983083486557D, -0.18173179030418396D, -0.18149229884147644D, -0.18125100433826447D, -0.1810166984796524D, -0.18076547980308533D, -0.18052025139331818D, -0.18028059601783752D, -0.18003447353839874D, -0.17976894974708557D, -0.1795182228088379D, -0.17926038801670074D, -0.17900227010250092D, -0.17875243723392487D, -0.17849260568618774D, -0.1782395988702774D, -0.17798492312431335D, -0.17773054540157318D, -0.1774715632200241D, -0.17721407115459442D, -0.17695027589797974D, -0.17670336365699768D, -0.17644056677818298D, -0.17620298266410828D, -0.17594093084335327D, -0.17569057643413544D, -0.17543667554855347D, -0.17517289519309998D, -0.17491887509822845D, -0.17465627193450928D, -0.17440259456634521D, -0.17415493726730347D, -0.17391294240951538D, -0.17365816235542297D, -0.1734064668416977D, -0.1731625646352768D, -0.17290157079696655D, -0.1726544052362442D, -0.17240196466445923D, -0.1721460521221161D, -0.17188984155654907D, -0.17164205014705658D, -0.1714034527540207D, -0.17115624248981476D, -0.17089448869228363D, -0.17063680291175842D, -0.17039979994297028D, -0.17014959454536438D, -0.1698901206254959D, -0.16964471340179443D, -0.1694014072418213D, -0.16913889348506927D, -0.16887636482715607D, -0.16862861812114716D, -0.16837315261363983D, -0.1681090146303177D, -0.1678696870803833D, -0.16762171685695648D, -0.16737119853496552D, -0.1671179234981537D, -0.16687534749507904D, -0.16663305461406708D, -0.1663946509361267D, -0.16613495349884033D, -0.16588224470615387D, -0.16563618183135986D, -0.16538074612617493D, -0.1651364266872406D, -0.16490191221237183D, -0.16465792059898376D, -0.16440246999263763D, -0.16415110230445862D, -0.16390496492385864D, -0.16366207599639893D, -0.1634174883365631D, -0.16316935420036316D, -0.1629198044538498D, -0.16267001628875732D, -0.16242310404777527D, -0.16217178106307983D, -0.16191552579402924D, -0.16166867315769196D, -0.1614210307598114D, -0.1611790955066681D, -0.16093122959136963D, -0.1606772541999817D, -0.16043275594711304D, -0.16018515825271606D, -0.15993653237819672D, -0.1596994400024414D, -0.15944430232048035D, -0.15919804573059082D, -0.15895970165729523D, -0.1587119996547699D, -0.15847010910511017D, -0.15822650492191315D, -0.15797394514083862D, -0.15772566199302673D, -0.15748535096645355D, -0.15724743902683258D, -0.15699094533920288D, -0.15675128996372223D, -0.15649347007274628D, -0.15624989569187164D, -0.15599365532398224D, -0.15574221312999725D, -0.15548446774482727D, -0.15522776544094086D, -0.15496757626533508D, -0.1547342836856842D, -0.1544916033744812D, -0.15425007045269012D, -0.1540067493915558D, -0.15374967455863953D, -0.15350456535816193D, -0.15324702858924866D, -0.15298958122730255D, -0.15275487303733826D, -0.15251053869724274D, -0.152267724275589D, -0.15201044082641602D, -0.15175509452819824D, -0.151505246758461D, -0.15124619007110596D, -0.15099188685417175D, -0.1507432460784912D, -0.15049618482589722D, -0.15025031566619873D, -0.1499987542629242D, -0.14975327253341675D, -0.1495012789964676D, -0.14925517141819D, -0.14899614453315735D, -0.14874862134456635D, -0.14850221574306488D, -0.14825864136219025D, -0.14800988137722015D, -0.14776690304279327D, -0.14751356840133667D, -0.14725728332996368D, -0.14701828360557556D, -0.1467764675617218D, -0.14652809500694275D, -0.1462775468826294D, -0.14603087306022644D, -0.14578372240066528D, -0.1455492079257965D, -0.14530538022518158D, -0.1450677067041397D, -0.1448247730731964D, -0.14457790553569794D, -0.14433254301548004D, -0.14408448338508606D, -0.14383292198181152D, -0.14358893036842346D, -0.14333432912826538D, -0.14308729767799377D, -0.1428370475769043D, -0.14258548617362976D, -0.14234289526939392D, -0.14209994673728943D, -0.14185495674610138D, -0.14160139858722687D, -0.14135192334651947D, -0.14110565185546875D, -0.14085626602172852D, -0.14060232043266296D, -0.14035870134830475D, -0.14011816680431366D, -0.1398662030696869D, -0.1396220326423645D, -0.13937823474407196D, -0.1391391158103943D, -0.1388905644416809D, -0.13864193856716156D, -0.13839447498321533D, -0.13814809918403625D, -0.13790713250637054D, -0.1376522183418274D, -0.13741502165794373D, -0.13717547059059143D, -0.13693785667419434D, -0.13668829202651978D, -0.13643985986709595D, -0.1362117975950241D, -0.1359674036502838D, -0.13571487367153168D, -0.13547922670841217D, -0.13521651923656464D, -0.13495062291622162D, -0.1347016990184784D, -0.13445797562599182D, -0.13421109318733215D, -0.13394372165203094D, -0.13369591534137726D, -0.1334560066461563D, -0.13321466743946075D, -0.1329614669084549D, -0.13270504772663116D, -0.13244760036468506D, -0.13218137621879578D, -0.1319417953491211D, -0.13170531392097473D, -0.1314602643251419D, -0.13120467960834503D, -0.13096478581428528D, -0.1307184249162674D, -0.13046908378601074D, -0.1302255094051361D, -0.12998691201210022D, -0.12974600493907928D, -0.1295071542263031D, -0.1292717605829239D, -0.12903152406215668D, -0.12879106402397156D, -0.12854063510894775D, -0.12829795479774475D, -0.12804800271987915D, -0.1277998685836792D, -0.12754665315151215D, -0.12730130553245544D, -0.12706024944782257D, -0.12681734561920166D, -0.12656420469284058D, -0.12631171941757202D, -0.1260722577571869D, -0.12582357227802277D, -0.1255764663219452D, -0.12533816695213318D, -0.12509363889694214D, -0.12485770136117935D, -0.12460377812385559D, -0.12436322122812271D, -0.12412640452384949D, -0.12387391924858093D, -0.12363933771848679D, -0.12340278923511505D, -0.12317416071891785D, -0.12292548269033432D, -0.12268528342247009D, -0.12244031578302383D, -0.12219351530075073D, -0.12195321917533875D, -0.1217072457075119D, -0.12145407497882843D, -0.12118937075138092D, -0.12093839049339294D, -0.12068343162536621D, -0.12044784426689148D, -0.12020371109247208D, -0.1199624091386795D, -0.11971180886030197D, -0.11945878714323044D, -0.11921756714582443D, -0.11896989494562149D, -0.11871515214443207D, -0.11847058683633804D, -0.11823519319295883D, -0.1179933100938797D, -0.11774738132953644D, -0.11750373244285583D, -0.1172565147280693D, -0.11700785160064697D, -0.11676418781280518D, -0.11652734875679016D, -0.11627509444952011D, -0.11602754890918732D, -0.11577780544757843D, -0.11553701758384705D, -0.11528782546520233D, -0.11505863815546036D, -0.11480346322059631D, -0.11456599831581116D, -0.11431010812520981D, -0.11407358199357986D, -0.11383143067359924D, -0.11360126733779907D, -0.11336424946784973D, -0.1131257489323616D, -0.11287946999073029D, -0.11264096945524216D, -0.11240296065807343D, -0.11215709149837494D, -0.11191694438457489D, -0.11166784912347794D, -0.1114199161529541D, -0.11117790639400482D, -0.110927514731884D, -0.11067363619804382D, -0.11044003069400787D, -0.11019321531057358D, -0.10995994508266449D, -0.10971911251544952D, -0.10947442054748535D, -0.10922731459140778D, -0.10898025333881378D, -0.10874222218990326D, -0.10849777609109879D, -0.1082630529999733D, -0.10802622139453888D, -0.1077839732170105D, -0.10753330588340759D, -0.10729499161243439D, -0.1070358008146286D, -0.10678865760564804D, -0.10653838515281677D, -0.10629342496395111D, -0.10604272782802582D, -0.10579723864793777D, -0.10554585605859756D, -0.10529976338148117D, -0.10505616664886475D, -0.1048198938369751D, -0.10458079725503922D, -0.10433512926101685D, -0.10408937931060791D, -0.10384517908096313D, -0.10361005365848541D, -0.10336779057979584D, -0.1031176820397377D, -0.10287676751613617D, -0.10262610018253326D, -0.10237167030572891D, -0.10212275385856628D, -0.10188750922679901D, -0.10163980722427368D, -0.10139568150043488D, -0.10115278512239456D, -0.10089636594057083D, -0.10065758973360062D, -0.10040846467018127D, -0.10017679631710052D, -0.09993906319141388D, -0.09969222545623779D, -0.0994405448436737D, -0.099197156727314D, -0.09895378351211548D, -0.09871632605791092D, -0.09848727285861969D, -0.09823883324861526D, -0.09799803793430328D, -0.09774011373519897D, -0.09750278294086456D, -0.09725803881883621D, -0.0970136970281601D, -0.09676622599363327D, -0.09651307016611099D, -0.09627290070056915D, -0.09603053331375122D, -0.09578799456357956D, -0.09554785490036011D, -0.09530899673700333D, -0.09506220370531082D, -0.09481719136238098D, -0.09456701576709747D, -0.09431912004947662D, -0.09408935904502869D, -0.09383450448513031D, -0.09358792006969452D, -0.09333662688732147D, -0.09308815002441406D, -0.09284839779138565D, -0.09261038154363632D, -0.09236297011375427D, -0.09211356192827225D, -0.09187184274196625D, -0.09162575006484985D, -0.0913834348320961D, -0.09114708006381989D, -0.09090118110179901D, -0.09066314250230789D, -0.09040945768356323D, -0.09017443656921387D, -0.08994124084711075D, -0.089698925614357D, -0.08944778144359589D, -0.08919527381658554D, -0.08896385133266449D, -0.08871737867593765D, -0.08848631381988525D, -0.08825340867042542D, -0.08800895512104034D, -0.0877874493598938D, -0.08753707259893417D, -0.08728936314582825D, -0.08704547584056854D, -0.08680916577577591D, -0.08656804263591766D, -0.08632045984268188D, -0.08607527613639832D, -0.08583015948534012D, -0.08558361977338791D, -0.08533721417188644D, -0.08509048074483871D, -0.08485028147697449D, -0.08460789173841476D, -0.08436190336942673D, -0.08410844951868057D, -0.0838729739189148D, -0.08363857865333557D, -0.08339942991733551D, -0.0831519365310669D, -0.08291947841644287D, -0.0826779305934906D, -0.08242892473936081D, -0.08219455182552338D, -0.08195057511329651D, -0.08170703053474426D, -0.081464022397995D, -0.08122886717319489D, -0.08100023120641708D, -0.08075392991304398D, -0.0805170014500618D, -0.08027160912752151D, -0.08002904802560806D, -0.07978925108909607D, -0.07955169677734375D, -0.07930881530046463D, -0.0790669322013855D, -0.07882830500602722D, -0.0785798504948616D, -0.07833991944789886D, -0.07809559255838394D, -0.07786226272583008D, -0.0776219591498375D, -0.07737678289413452D, -0.07714521139860153D, -0.07691224664449692D, -0.07665777206420898D, -0.07641151547431946D, -0.07617313414812088D, -0.07592753320932388D, -0.07569229602813721D, -0.0754416435956955D, -0.07519475370645523D, -0.07494813203811646D, -0.0747164636850357D, -0.07448276877403259D, -0.07423548400402069D, -0.07399512827396393D, -0.07376088201999664D, -0.07351675629615784D, -0.07327954471111298D, -0.07303505390882492D, -0.07279020547866821D, -0.07253576070070267D, -0.07229600846767426D, -0.07204475998878479D, -0.07179662585258484D, -0.07155118137598038D, -0.07129927724599838D, -0.07106245309114456D, -0.07081857323646545D, -0.07056738436222076D, -0.07032652199268341D, -0.07008545845746994D, -0.06985671073198318D, -0.06962361931800842D, -0.06937389075756073D, -0.06912381947040558D, -0.06887900829315186D, -0.0686340481042862D, -0.06838493049144745D, -0.0681314691901207D, -0.06789498031139374D, -0.06765970587730408D, -0.06742730736732483D, -0.06719651073217392D, -0.06694657355546951D, -0.06670555472373962D, -0.06645660102367401D, -0.06621503829956055D, -0.06598034501075745D, -0.06574320793151855D, -0.06549137830734253D, -0.06525201350450516D, -0.06501458585262299D, -0.06479227542877197D, -0.06455428898334503D, -0.06431309133768082D, -0.06407991051673889D, -0.0638367235660553D, -0.06359873712062836D, -0.06334324926137924D, -0.06310774385929108D, -0.06286437809467316D, -0.06262777745723724D, -0.06237030401825905D, -0.0621323436498642D, -0.06189025938510895D, -0.061647746711969376D, -0.06140772998332977D, -0.06117217615246773D, -0.060926057398319244D, -0.06067296862602234D, -0.06043364480137825D, -0.06018991395831108D, -0.05995730683207512D, -0.05970904603600502D, -0.05945960804820061D, -0.059217669069767D, -0.05897081643342972D, -0.05872904509305954D, -0.05849192291498184D, -0.058252234011888504D, -0.058004919439554214D, -0.057772375643253326D, -0.057538487017154694D, -0.05728022754192352D, -0.05705133080482483D, -0.0568150132894516D, -0.05658133700489998D, -0.05634107068181038D, -0.05609507858753204D, -0.05584454536437988D, -0.05560510605573654D, -0.055361032485961914D, -0.05511125177145004D, -0.05486954376101494D, -0.0546349361538887D, -0.054383497685194016D, -0.054135002195835114D, -0.05389668419957161D, -0.05365772172808647D, -0.053429946303367615D, -0.05319244787096977D, -0.05295149236917496D, -0.05270173400640488D, -0.05245363712310791D, -0.052212126553058624D, -0.05197114497423172D, -0.05172385275363922D, -0.05147520452737808D, -0.05123189836740494D, -0.050989679992198944D, -0.05073939263820648D, -0.050494953989982605D, -0.050253815948963165D, -0.05001272261142731D, -0.04977148026227951D, -0.049528926610946655D, -0.0492960549890995D, -0.049062661826610565D, -0.04881996288895607D, -0.04857254773378372D, -0.04833959415555D, -0.04808736592531204D, -0.04785143956542015D, -0.04761652648448944D, -0.04738566651940346D, -0.047138575464487076D, -0.046896256506443024D, -0.04665457457304001D, -0.046410854905843735D, -0.046181485056877136D, -0.04594765976071358D, -0.045701175928115845D, -0.04545196518301964D, -0.04520288109779358D, -0.04497365653514862D, -0.04473564028739929D, -0.044497597962617874D, -0.04426290839910507D, -0.04401934891939163D, -0.04377321898937225D, -0.04354047775268555D, -0.04330435022711754D, -0.04306349903345108D, -0.04282412305474281D, -0.042600978165864944D, -0.04235575720667839D, -0.042125359177589417D, -0.0418863445520401D, -0.04164663329720497D, -0.041397858411073685D, -0.04115602374076843D, -0.04090924188494682D, -0.040665313601493835D, -0.040422823280096054D, -0.04018530994653702D, -0.03994182497262955D, -0.03970673680305481D, -0.039466261863708496D, -0.03923157975077629D, -0.03900260105729103D, -0.03876923769712448D, -0.03853490203619003D, -0.03827759623527527D, -0.038032952696084976D, -0.03779587149620056D, -0.03755195438861847D, -0.037318892776966095D, -0.0370723120868206D, -0.03683407977223396D, -0.03659613057971001D, -0.036354124546051025D, -0.03612060472369194D, -0.035871125757694244D, -0.0356329046189785D, -0.03540351986885071D, -0.03516382724046707D, -0.03492915630340576D, -0.03468974679708481D, -0.03444032371044159D, -0.03418684005737305D, -0.033952150493860245D, -0.0337207056581974D, -0.03348376974463463D, -0.03324819356203079D, -0.03300824016332626D, -0.03275500610470772D, -0.03251590207219124D, -0.032279904931783676D, -0.032043423503637314D, -0.031806062906980515D, -0.03156071901321411D, -0.03131228685379028D, -0.031079325824975967D, -0.030846213921904564D, -0.030607648193836212D, -0.030370527878403664D, -0.03013504482805729D, -0.02989460527896881D, -0.029653780162334442D, -0.02942124754190445D, -0.02915763482451439D, -0.02890888601541519D, -0.028668014332652092D, -0.02843261882662773D, -0.028197886422276497D, -0.027968186885118484D, -0.027727065607905388D, -0.027480654418468475D, -0.027245230972766876D, -0.027006402611732483D, -0.02677249163389206D, -0.02654179185628891D, -0.026293570175766945D, -0.026052728295326233D, -0.02581942081451416D, -0.025574829429388046D, -0.025324739515781403D, -0.02508126199245453D, -0.02484128810465336D, -0.024607401341199875D, -0.024367906153202057D, -0.024130383506417274D, -0.023888912051916122D, -0.023636002093553543D, -0.02339264750480652D, -0.023146748542785645D, -0.022916993126273155D, -0.022678110748529434D, -0.022439364343881607D, -0.02219318598508835D, -0.02194978855550289D, -0.02171243354678154D, -0.021477043628692627D, -0.02123437076807022D, -0.02098814956843853D, -0.02074434421956539D, -0.020506832748651505D, -0.020272759720683098D, -0.02004285529255867D, -0.019803741946816444D, -0.01955583691596985D, -0.019311942160129547D, -0.019074883311986923D, -0.018838535994291306D, -0.018599458038806915D, -0.018360331654548645D, -0.01811789721250534D, -0.01788494735956192D, -0.017648138105869293D, -0.017405608668923378D, -0.017160717397928238D, -0.016933269798755646D, -0.016701746731996536D, -0.016470860689878464D, -0.016230151057243347D, -0.01599072851240635D, -0.01574883423745632D, -0.015508405864238739D, -0.015284917317330837D, -0.01503007858991623D, -0.014800170436501503D, -0.01455119252204895D, -0.014315657317638397D, -0.014065643772482872D, -0.013827585615217686D, -0.013587378896772861D, -0.013347174972295761D, -0.013102564960718155D, -0.012854132801294327D, -0.012623535469174385D, -0.012376610189676285D, -0.012131456285715103D, -0.01189560629427433D, -0.011651847511529922D, -0.01142079383134842D, -0.011175703257322311D, -0.010937604121863842D, -0.010689251124858856D, -0.010437887161970139D, -0.010197514668107033D, -0.009952478110790253D, -0.009725537151098251D, -0.009491712786257267D, -0.009257838129997253D, -0.009027864784002304D, -0.008777694776654243D, -0.008550971746444702D, -0.00831599161028862D, -0.008069436997175217D, -0.007820136845111847D, -0.007574319839477539D, -0.007336270064115524D, -0.007096525281667709D, -0.006860194727778435D, -0.00662708654999733D, -0.006389433518052101D, -0.006162447854876518D, -0.005919415503740311D, -0.005667705088853836D, -0.005427785217761993D, -0.005184531211853027D, -0.004940364509820938D, -0.00468367338180542D, -0.004453904926776886D, -0.004206191748380661D, -0.003969529643654823D, -0.0037299059331417084D, -0.003492492251098156D, -0.003242732025682926D, -0.0030055344104766846D, -0.0027720071375370026D, -0.00253082811832428D, -0.00228659575805068D, -0.002054929733276367D, -0.0018176455050706863D, -0.001599922776222229D, -0.0013567134737968445D, -0.0011234097182750702D, -9.045042097568512E-4D, -6.500082090497017E-4D, -4.1660130955278873E-4D, -1.7212703824043274E-4D, 1.8030405044555664E-5D, 2.5004614144563675E-4D, 4.7913193702697754E-4D, 7.338970899581909E-4D, 9.82176512479782E-4D, 0.0012129582464694977D, 0.0014488585293293D, 0.0016867630183696747D, 0.0019273310899734497D, 0.0021613668650388718D, 0.002390991896390915D, 0.0026295240968465805D, 0.0028657931834459305D, 0.0031123533844947815D, 0.003348197788000107D, 0.003588378429412842D, 0.0038277730345726013D, 0.0040658749639987946D, 0.004302076995372772D, 0.004537015222012997D, 0.00477440282702446D, 0.005008077248930931D, 0.005255784839391708D, 0.0054915063083171844D, 0.005724627524614334D, 0.00595773383975029D, 0.006182271987199783D, 0.006420166231691837D, 0.006653249729424715D, 0.00689283199608326D, 0.007140390574932098D, 0.007379662245512009D, 0.0076194386929273605D, 0.007851885631680489D, 0.008095469325780869D, 0.008320674300193787D, 0.008559394627809525D, 0.008799819275736809D, 0.009034939110279083D, 0.009275494143366814D, 0.009523751214146614D, 0.00976627878844738D, 0.009996486827731133D, 0.01023360900580883D, 0.010484512895345688D, 0.010711602866649628D, 0.010940506123006344D, 0.011187344789505005D, 0.011436786502599716D, 0.011673590168356895D, 0.01189296692609787D, 0.012140963226556778D, 0.012369673699140549D, 0.012593931518495083D, 0.012840654700994492D, 0.013081846758723259D, 0.013317383825778961D, 0.013564608991146088D, 0.013808630406856537D, 0.014055570587515831D, 0.014296349138021469D, 0.01453232578933239D, 0.014765492640435696D, 0.015003692358732224D, 0.015242312103509903D, 0.015490015037357807D, 0.015726767480373383D, 0.01596280187368393D, 0.01620377227663994D, 0.01644257828593254D, 0.01667718216776848D, 0.016922373324632645D, 0.017163371667265892D, 0.017399052157998085D, 0.01764657348394394D, 0.017877236008644104D, 0.01812145859003067D, 0.01835670694708824D, 0.018597178161144257D, 0.01882927119731903D, 0.019075646996498108D, 0.019314182922244072D, 0.019556086510419846D, 0.019792847335338593D, 0.02003338560461998D, 0.020272035151720047D, 0.02050381898880005D, 0.020733200013637543D, 0.020976442843675613D, 0.021210378035902977D, 0.02143765240907669D, 0.021682390943169594D, 0.021919602528214455D, 0.0221518874168396D, 0.022384680807590485D, 0.022622741758823395D, 0.022860225290060043D, 0.02310165762901306D, 0.023336874321103096D, 0.023573121055960655D, 0.02379993349313736D, 0.02404947392642498D, 0.024299774318933487D, 0.024536117911338806D, 0.02478577382862568D, 0.025020964443683624D, 0.025249026715755463D, 0.025489892810583115D, 0.025740530341863632D, 0.025998929515480995D, 0.026246890425682068D, 0.02648969367146492D, 0.026718705892562866D, 0.026957036927342415D, 0.027204863727092743D, 0.027444452047348022D, 0.027704622596502304D, 0.027947325259447098D, 0.02819725126028061D, 0.02844608575105667D, 0.028680214658379555D, 0.028920786455273628D, 0.029158281162381172D, 0.029388519003987312D, 0.029632214456796646D, 0.029864804819226265D, 0.030107151716947556D, 0.030348382890224457D, 0.030580196529626846D, 0.03082174062728882D, 0.031057609245181084D, 0.03129713609814644D, 0.031536027789115906D, 0.03177642449736595D, 0.032016344368457794D, 0.032250333577394485D, 0.03248574212193489D, 0.03272556513547897D, 0.032981544733047485D, 0.03322865441441536D, 0.03346912935376167D, 0.0337110199034214D, 0.033949390053749084D, 0.034183282405138016D, 0.034417230635881424D, 0.03465258330106735D, 0.0348886139690876D, 0.035128623247146606D, 0.03536383435130119D, 0.03560587763786316D, 0.03585127741098404D, 0.036084286868572235D, 0.03631396219134331D, 0.036562442779541016D, 0.03680244833230972D, 0.03704371303319931D, 0.037276409566402435D, 0.03751538693904877D, 0.037762030959129333D, 0.03801950067281723D, 0.03826010972261429D, 0.038504309952259064D, 0.0387469083070755D, 0.03899405896663666D, 0.039229098707437515D, 0.03947621211409569D, 0.039711613208055496D, 0.03995666652917862D, 0.040196262300014496D, 0.040436677634716034D, 0.04066110774874687D, 0.04089445620775223D, 0.04114403575658798D, 0.04137770086526871D, 0.04162734001874924D, 0.04187489300966263D, 0.04212113842368126D, 0.04237997904419899D, 0.04263453558087349D, 0.04288449138402939D, 0.04311514273285866D, 0.04335115849971771D, 0.04357973113656044D, 0.04382624477148056D, 0.04406590759754181D, 0.04431349039077759D, 0.04456290230154991D, 0.044805336743593216D, 0.0450420007109642D, 0.04527563601732254D, 0.04551904648542404D, 0.045769836753606796D, 0.04600602388381958D, 0.046249911189079285D, 0.04649045318365097D, 0.0467350110411644D, 0.0469646230340004D, 0.04720987752079964D, 0.0474463514983654D, 0.04768086224794388D, 0.047928351908922195D, 0.048162274062633514D, 0.048396602272987366D, 0.04864221811294556D, 0.048878930509090424D, 0.0491228923201561D, 0.0493641197681427D, 0.0496056005358696D, 0.049858272075653076D, 0.050106972455978394D, 0.0503457672894001D, 0.05058106780052185D, 0.050811801105737686D, 0.051054518669843674D, 0.051300615072250366D, 0.051533062011003494D, 0.051776714622974396D, 0.05200812220573425D, 0.052254874259233475D, 0.05247935280203819D, 0.05271238088607788D, 0.05296379327774048D, 0.053211115300655365D, 0.053449779748916626D, 0.05368578061461449D, 0.05392590910196304D, 0.05417390167713165D, 0.05440376326441765D, 0.05464910343289375D, 0.054876476526260376D, 0.055116206407547D, 0.05535535141825676D, 0.05559191852807999D, 0.05583671107888222D, 0.05606665462255478D, 0.05629488080739975D, 0.056531038135290146D, 0.05677127465605736D, 0.05701253190636635D, 0.05725562572479248D, 0.05749615281820297D, 0.05773595720529556D, 0.05798366293311119D, 0.05822004750370979D, 0.05847081169486046D, 0.05871637910604477D, 0.05896701663732529D, 0.05920988693833351D, 0.05945613235235214D, 0.059691719710826874D, 0.059922900050878525D, 0.06016569584608078D, 0.060413725674152374D, 0.06065669655799866D, 0.06089803948998451D, 0.061139024794101715D, 0.061384011059999466D, 0.061639074236154556D, 0.06188543885946274D, 0.06213250756263733D, 0.062370769679546356D, 0.06261318922042847D, 0.0628569945693016D, 0.06309330463409424D, 0.06332416087388992D, 0.06356460601091385D, 0.06382028758525848D, 0.06406866014003754D, 0.06430210918188095D, 0.06454354524612427D, 0.06478959321975708D, 0.06503751873970032D, 0.06529387086629868D, 0.06553513556718826D, 0.06577916443347931D, 0.06601770222187042D, 0.06625692546367645D, 0.06650961935520172D, 0.06674687564373016D, 0.0669788122177124D, 0.06722482293844223D, 0.0674588531255722D, 0.06768260151147842D, 0.06790776550769806D, 0.06814801692962646D, 0.06838471442461014D, 0.06863133609294891D, 0.06886210292577744D, 0.06910943239927292D, 0.06934362649917603D, 0.06958003342151642D, 0.06981192529201508D, 0.07004958391189575D, 0.07029459625482559D, 0.07055052369832993D, 0.07078401744365692D, 0.07101749628782272D, 0.07126064598560333D, 0.07150739431381226D, 0.07175813615322113D, 0.0720054879784584D, 0.07224322110414505D, 0.07248044013977051D, 0.07271689921617508D, 0.07295949757099152D, 0.0732078030705452D, 0.07345090061426163D, 0.07368715852499008D, 0.07393429428339005D, 0.07417695224285126D, 0.07441578805446625D, 0.07466088980436325D, 0.07489414513111115D, 0.07513600587844849D, 0.0753738135099411D, 0.07561701536178589D, 0.0758667066693306D, 0.07612309604883194D, 0.07638232409954071D, 0.076628178358078D, 0.07686847448348999D, 0.07710824906826019D, 0.07734467834234238D, 0.07758921384811401D, 0.07784561812877655D, 0.07808583974838257D, 0.07834410667419434D, 0.07858625054359436D, 0.07882437855005264D, 0.07906801998615265D, 0.0793083980679512D, 0.07955463230609894D, 0.07981622219085693D, 0.08005615323781967D, 0.08030057698488235D, 0.0805463120341301D, 0.08078382909297943D, 0.08103151619434357D, 0.08126095682382584D, 0.0815000832080841D, 0.08173040300607681D, 0.08196523785591125D, 0.08220580220222473D, 0.08243486285209656D, 0.08268188685178757D, 0.08292843401432037D, 0.0831647738814354D, 0.08339834958314896D, 0.0836380124092102D, 0.08387906104326248D, 0.08412414789199829D, 0.08436859399080276D, 0.0846082791686058D, 0.08485112339258194D, 0.08509281277656555D, 0.08533436059951782D, 0.08558444678783417D, 0.08581666648387909D, 0.08605876564979553D, 0.08630654215812683D, 0.08654367923736572D, 0.08678770065307617D, 0.08702260255813599D, 0.08725456148386002D, 0.08750993013381958D, 0.08773811906576157D, 0.08798518031835556D, 0.0882255807518959D, 0.08847689628601074D, 0.0887211263179779D, 0.08896452188491821D, 0.08920910954475403D, 0.08945497870445251D, 0.08969209343194962D, 0.08994311094284058D, 0.09017997980117798D, 0.09042559564113617D, 0.0906810313463211D, 0.09092381596565247D, 0.0911625400185585D, 0.09141795337200165D, 0.09166523069143295D, 0.09191490709781647D, 0.0921562910079956D, 0.09239944815635681D, 0.09264124929904938D, 0.09289426356554031D, 0.09314051270484924D, 0.09336643666028976D, 0.09361747652292252D, 0.09384654462337494D, 0.09409788250923157D, 0.0943448394536972D, 0.09459105134010315D, 0.0948304533958435D, 0.09507936984300613D, 0.09532738476991653D, 0.09556381404399872D, 0.09580858051776886D, 0.09604042023420334D, 0.09626977145671844D, 0.09650926291942596D, 0.0967506468296051D, 0.09699468314647675D, 0.09725047647953033D, 0.09750711917877197D, 0.09776434302330017D, 0.09801188111305237D, 0.09824371337890625D, 0.09848768264055252D, 0.09872874617576599D, 0.09896586090326309D, 0.09920790046453476D, 0.09944957494735718D, 0.09968200325965881D, 0.09992703795433044D, 0.10018682479858398D, 0.10043767094612122D, 0.10069596767425537D, 0.10094213485717773D, 0.10119457542896271D, 0.10144343972206116D, 0.10168857872486115D, 0.1019381657242775D, 0.1021813377737999D, 0.10242380201816559D, 0.10266663134098053D, 0.1029038205742836D, 0.10315491259098053D, 0.1034012958407402D, 0.10365647822618484D, 0.10389219224452972D, 0.104132741689682D, 0.10438927263021469D, 0.10462994873523712D, 0.10488337278366089D, 0.10512462258338928D, 0.10537828505039215D, 0.1056293249130249D, 0.10587567090988159D, 0.10612065345048904D, 0.10636690258979797D, 0.10661175101995468D, 0.10686026513576508D, 0.10710041970014572D, 0.10735155642032623D, 0.10758167505264282D, 0.10782761126756668D, 0.10806737840175629D, 0.1083139032125473D, 0.10856615751981735D, 0.108811154961586D, 0.10905927419662476D, 0.10930319875478745D, 0.10955643653869629D, 0.10979588329792023D, 0.11004279553890228D, 0.1102958396077156D, 0.11054527759552002D, 0.11079119145870209D, 0.11103609204292297D, 0.11127711832523346D, 0.1115172803401947D, 0.1117594912648201D, 0.1120046079158783D, 0.11223725229501724D, 0.11248401552438736D, 0.11272372305393219D, 0.11297810077667236D, 0.11322519183158875D, 0.11346785724163055D, 0.11372040957212448D, 0.11395683884620667D, 0.11420010775327682D, 0.11444250494241714D, 0.11468120664358139D, 0.11492819339036942D, 0.11517039686441422D, 0.11540466547012329D, 0.11564680933952332D, 0.11589252948760986D, 0.11613063514232635D, 0.11639325320720673D, 0.11663356423377991D, 0.11688605695962906D, 0.11712798476219177D, 0.11737510561943054D, 0.11761916428804398D, 0.11786546558141708D, 0.11810825765132904D, 0.11834405362606049D, 0.11859436333179474D, 0.11883425712585449D, 0.11908208578824997D, 0.11933384835720062D, 0.11957629024982452D, 0.11981932073831558D, 0.12006602436304092D, 0.1203235313296318D, 0.12056553363800049D, 0.12080793082714081D, 0.12105826288461685D, 0.12129639089107513D, 0.12155969440937042D, 0.12180247157812119D, 0.12205307930707932D, 0.12229906022548676D, 0.12254200130701065D, 0.12278658151626587D, 0.12303048372268677D, 0.12327433377504349D, 0.12352501600980759D, 0.12377308309078217D, 0.12401439994573593D, 0.12425234913825989D, 0.12449690699577332D, 0.12473757565021515D, 0.12498489767313004D, 0.12522444128990173D, 0.1254711002111435D, 0.1257123202085495D, 0.1259474903345108D, 0.12619467079639435D, 0.12644141912460327D, 0.12670068442821503D, 0.12694254517555237D, 0.12717880308628082D, 0.12742914259433746D, 0.12767036259174347D, 0.12791737914085388D, 0.12815646827220917D, 0.12838824093341827D, 0.1286291480064392D, 0.12887807190418243D, 0.1291383057832718D, 0.12939326465129852D, 0.1296338587999344D, 0.1298784613609314D, 0.1301174759864807D, 0.13036495447158813D, 0.130618155002594D, 0.13086116313934326D, 0.13110719621181488D, 0.13135799765586853D, 0.1315925568342209D, 0.1318426877260208D, 0.13207705318927765D, 0.13231460750102997D, 0.13256874680519104D, 0.1328187882900238D, 0.13305653631687164D, 0.13330477476119995D, 0.13354620337486267D, 0.13378751277923584D, 0.13402922451496124D, 0.1342799961566925D, 0.13453587889671326D, 0.13477690517902374D, 0.13502594828605652D, 0.13527695834636688D, 0.13551442325115204D, 0.13576547801494598D, 0.1360103189945221D, 0.1362583041191101D, 0.13651292026042938D, 0.13675719499588013D, 0.13699865341186523D, 0.13724200427532196D, 0.13749007880687714D, 0.1377292424440384D, 0.1379738599061966D, 0.13822335004806519D, 0.13847866654396057D, 0.13873206079006195D, 0.13898490369319916D, 0.13923271000385284D, 0.1394839584827423D, 0.13973473012447357D, 0.13997481763362885D, 0.1402241587638855D, 0.1404787302017212D, 0.14072586596012115D, 0.14096570014953613D, 0.14121803641319275D, 0.14146292209625244D, 0.14170925319194794D, 0.14195016026496887D, 0.14219069480895996D, 0.14244592189788818D, 0.14269237220287323D, 0.1429404616355896D, 0.1431778520345688D, 0.14341974258422852D, 0.14366695284843445D, 0.143928661942482D, 0.14417223632335663D, 0.144425168633461D, 0.14466984570026398D, 0.144924595952034D, 0.14517496526241302D, 0.14541681110858917D, 0.14565762877464294D, 0.14590227603912354D, 0.14615565538406372D, 0.146397665143013D, 0.14664502441883087D, 0.14689862728118896D, 0.14715076982975006D, 0.14740772545337677D, 0.14766333997249603D, 0.1479138731956482D, 0.14816024899482727D, 0.14840947091579437D, 0.14864777028560638D, 0.14889664947986603D, 0.1491481214761734D, 0.1493992805480957D, 0.14964887499809265D, 0.14990657567977905D, 0.150163471698761D, 0.15041270852088928D, 0.1506699174642563D, 0.1509278118610382D, 0.1511797457933426D, 0.15143243968486786D, 0.15168344974517822D, 0.15193966031074524D, 0.15217027068138123D, 0.1524168848991394D, 0.15265515446662903D, 0.15290214121341705D, 0.1531422883272171D, 0.1533876657485962D, 0.15364302694797516D, 0.15389402210712433D, 0.15414564311504364D, 0.15439721941947937D, 0.15463466942310333D, 0.15488171577453613D, 0.15513262152671814D, 0.15537695586681366D, 0.15562325716018677D, 0.1558755785226822D, 0.15611112117767334D, 0.15636210143566132D, 0.1566154956817627D, 0.15687504410743713D, 0.15712611377239227D, 0.15738089382648468D, 0.15762266516685486D, 0.15787272155284882D, 0.15813465416431427D, 0.15839409828186035D, 0.15864822268486023D, 0.15889886021614075D, 0.15914614498615265D, 0.1593829244375229D, 0.15962837636470795D, 0.15988434851169586D, 0.16013933718204498D, 0.1603895127773285D, 0.1606409102678299D, 0.16089800000190735D, 0.16113731265068054D, 0.16138312220573425D, 0.16164162755012512D, 0.1619039922952652D, 0.16216659545898438D, 0.1624208390712738D, 0.16268286108970642D, 0.16292384266853333D, 0.16317801177501678D, 0.16342324018478394D, 0.16366511583328247D, 0.16390013694763184D, 0.16414274275302887D, 0.16438521444797516D, 0.16463032364845276D, 0.16487151384353638D, 0.1651274561882019D, 0.1653711199760437D, 0.16560332477092743D, 0.16584159433841705D, 0.16609609127044678D, 0.16633854806423187D, 0.16659075021743774D, 0.16683602333068848D, 0.16707871854305267D, 0.16732636094093323D, 0.16758735477924347D, 0.16783970594406128D, 0.16809149086475372D, 0.16834628582000732D, 0.16860048472881317D, 0.16885283589363098D, 0.16911184787750244D, 0.1693841814994812D, 0.16964191198349D, 0.1698930859565735D, 0.1701383739709854D, 0.1703755259513855D, 0.17063964903354645D, 0.17089423537254333D, 0.1711474359035492D, 0.171388179063797D, 0.17163044214248657D, 0.17187903821468353D, 0.17215164005756378D, 0.1724054217338562D, 0.17266374826431274D, 0.17292089760303497D, 0.1731615662574768D, 0.17340199649333954D, 0.17366479337215424D, 0.1739150434732437D, 0.17417052388191223D, 0.1744164675474167D, 0.17465999722480774D, 0.1749131977558136D, 0.17516209185123444D, 0.1754201203584671D, 0.17568381130695343D, 0.17593267560005188D, 0.17619283497333527D, 0.17645525932312012D, 0.17671234905719757D, 0.17696595191955566D, 0.17722009122371674D, 0.17747735977172852D, 0.17772412300109863D, 0.17797930538654327D, 0.17823158204555511D, 0.17848974466323853D, 0.17873625457286835D, 0.17898991703987122D, 0.1792307198047638D, 0.1794891506433487D, 0.17973554134368896D, 0.17999310791492462D, 0.18024954199790955D, 0.18050163984298706D, 0.18076446652412415D, 0.18102599680423737D, 0.18126806616783142D, 0.18151478469371796D, 0.18176385760307312D, 0.18201972544193268D, 0.1822776347398758D, 0.18253739178180695D, 0.18278411030769348D, 0.18303966522216797D, 0.1832965612411499D, 0.1835542917251587D, 0.1838156133890152D, 0.1840553879737854D, 0.18431082367897034D, 0.1845688670873642D, 0.18482251465320587D, 0.18506990373134613D, 0.18532750010490417D, 0.18557335436344147D, 0.18582487106323242D, 0.18608145415782928D, 0.18633334338665009D, 0.18658064305782318D, 0.18683351576328278D, 0.18709410727024078D, 0.18735168874263763D, 0.18761134147644043D, 0.18786972761154175D, 0.18811970949172974D, 0.18837547302246094D, 0.18862836062908173D, 0.18887996673583984D, 0.1891300231218338D, 0.18938672542572021D, 0.18964359164237976D, 0.18990398943424225D, 0.19015058875083923D, 0.19040174782276154D, 0.19066479802131653D, 0.19092917442321777D, 0.19117361307144165D, 0.19143356382846832D, 0.19168759882450104D, 0.1919550895690918D, 0.1922134906053543D, 0.19246909022331238D, 0.1927301287651062D, 0.19298666715621948D, 0.19325979053974152D, 0.19350659847259521D, 0.1937701553106308D, 0.19402582943439484D, 0.19428086280822754D, 0.19453628361225128D, 0.19479681551456451D, 0.19505488872528076D, 0.19530737400054932D, 0.1955641359090805D, 0.1958162784576416D, 0.1960599720478058D, 0.19630758464336395D, 0.19656088948249817D, 0.19681763648986816D, 0.19707539677619934D, 0.1973382830619812D, 0.19758382439613342D, 0.19783498346805573D, 0.19810113310813904D, 0.19836364686489105D, 0.198616623878479D, 0.19888028502464294D, 0.1991325318813324D, 0.19938108325004578D, 0.19963473081588745D, 0.19988803565502167D, 0.2001369297504425D, 0.20039276778697968D, 0.20064187049865723D, 0.2009114772081375D, 0.20116636157035828D, 0.20142139494419098D, 0.2016759216785431D, 0.20193830132484436D, 0.20219115912914276D, 0.2024461179971695D, 0.20269548892974854D, 0.20295751094818115D, 0.2032078355550766D, 0.20346446335315704D, 0.20372796058654785D, 0.20398731529712677D, 0.20425032079219818D, 0.20450064539909363D, 0.20475132763385773D, 0.20501857995986938D, 0.20528261363506317D, 0.20554444193840027D, 0.20581212639808655D, 0.20607292652130127D, 0.20632115006446838D, 0.20657122135162354D, 0.20683971047401428D, 0.2071026861667633D, 0.2073436677455902D, 0.20759855210781097D, 0.20785433053970337D, 0.20810873806476593D, 0.20837277173995972D, 0.2086334526538849D, 0.20889252424240112D, 0.2091631293296814D, 0.20941714942455292D, 0.20966646075248718D, 0.20992329716682434D, 0.210189089179039D, 0.2104564607143402D, 0.21071530878543854D, 0.2109697461128235D, 0.21122780442237854D, 0.21149942278862D, 0.21177108585834503D, 0.212026447057724D, 0.21229231357574463D, 0.21255123615264893D, 0.2128051221370697D, 0.2130669802427292D, 0.21332398056983948D, 0.21358664333820343D, 0.2138541340827942D, 0.2141055166721344D, 0.21435829997062683D, 0.21462669968605042D, 0.21488457918167114D, 0.21513977646827698D, 0.21538878977298737D, 0.2156517058610916D, 0.21592454612255096D, 0.216178759932518D, 0.216445192694664D, 0.21670177578926086D, 0.21695657074451447D, 0.21721142530441284D, 0.21747595071792603D, 0.21773701906204224D, 0.2179940938949585D, 0.2182585597038269D, 0.21852922439575195D, 0.2187880575656891D, 0.21905365586280823D, 0.21932736039161682D, 0.21959064900875092D, 0.2198474109172821D, 0.22009959816932678D, 0.22036632895469666D, 0.22063975036144257D, 0.2208988517522812D, 0.2211713194847107D, 0.22143341600894928D, 0.22171543538570404D, 0.22197507321834564D, 0.22224444150924683D, 0.2225213348865509D, 0.22277890145778656D, 0.22304566204547882D, 0.22330500185489655D, 0.22357644140720367D, 0.22383159399032593D, 0.22409124672412872D, 0.22433821856975555D, 0.22459536790847778D, 0.22486494481563568D, 0.22513198852539062D, 0.22539369761943817D, 0.22565101087093353D, 0.22591067850589752D, 0.22616182267665863D, 0.22642919421195984D, 0.22670313715934753D, 0.2269665002822876D, 0.2272244691848755D, 0.22747714817523956D, 0.2277398705482483D, 0.22800278663635254D, 0.22826018929481506D, 0.22853484749794006D, 0.22879329323768616D, 0.22905567288398743D, 0.22932875156402588D, 0.22959567606449127D, 0.22985166311264038D, 0.23012641072273254D, 0.23038911819458008D, 0.23065757751464844D, 0.2309347689151764D, 0.23118633031845093D, 0.23145408928394318D, 0.2317189872264862D, 0.23198048770427704D, 0.2322455197572708D, 0.23250694572925568D, 0.232782781124115D, 0.23303967714309692D, 0.2333066314458847D, 0.23356512188911438D, 0.23384179174900055D, 0.2341168224811554D, 0.23438036441802979D, 0.23465333878993988D, 0.23490497469902039D, 0.2351686954498291D, 0.23543143272399902D, 0.2357012927532196D, 0.23596397042274475D, 0.23622770607471466D, 0.23648853600025177D, 0.23676562309265137D, 0.23701412975788116D, 0.2372843474149704D, 0.23755553364753723D, 0.23782414197921753D, 0.2380770742893219D, 0.23833540081977844D, 0.23858565092086792D, 0.2388562709093094D, 0.2391243726015091D, 0.23939518630504608D, 0.2396606057882309D, 0.2399381399154663D, 0.24020333588123322D, 0.24046452343463898D, 0.24074232578277588D, 0.24100619554519653D, 0.24127767980098724D, 0.24153725802898407D, 0.24180150032043457D, 0.2420664131641388D, 0.24233688414096832D, 0.24260331690311432D, 0.24287430942058563D, 0.24314293265342712D, 0.2434246838092804D, 0.24368378520011902D, 0.24393977224826813D, 0.24419629573822021D, 0.24446481466293335D, 0.24473105370998383D, 0.24499809741973877D, 0.24526169896125793D, 0.24553239345550537D, 0.24579843878746033D, 0.24606765806674957D, 0.24634045362472534D, 0.24660402536392212D, 0.2468681037425995D, 0.2471298724412918D, 0.24741238355636597D, 0.2476801872253418D, 0.2479431927204132D, 0.2482285499572754D, 0.24848723411560059D, 0.24875469505786896D, 0.24903346598148346D, 0.24929732084274292D, 0.24957558512687683D, 0.24984514713287354D, 0.25010985136032104D, 0.25036337971687317D, 0.2506392002105713D, 0.2509065270423889D, 0.25119492411613464D, 0.25146934390068054D, 0.25174203515052795D, 0.25201404094696045D, 0.25227802991867065D, 0.252545565366745D, 0.252820760011673D, 0.2530921697616577D, 0.2533664405345917D, 0.25363945960998535D, 0.2539142072200775D, 0.25417646765708923D, 0.2544398903846741D, 0.2547091245651245D, 0.25498032569885254D, 0.2552673816680908D, 0.25553467869758606D, 0.2558070719242096D, 0.2560715973377228D, 0.2563423812389374D, 0.2566147446632385D, 0.256882905960083D, 0.2571600079536438D, 0.257426381111145D, 0.2576892673969269D, 0.2579575479030609D, 0.25823888182640076D, 0.258513867855072D, 0.2587907612323761D, 0.25906962156295776D, 0.2593492269515991D, 0.25961726903915405D, 0.25989121198654175D, 0.2601594924926758D, 0.26043808460235596D, 0.2607068121433258D, 0.2609749138355255D, 0.26124802231788635D, 0.2615189850330353D, 0.2617867887020111D, 0.2620628774166107D, 0.26233547925949097D, 0.262612521648407D, 0.2628844082355499D, 0.26317137479782104D, 0.26344573497772217D, 0.2637230157852173D, 0.2639881670475006D, 0.26426470279693604D, 0.2645290791988373D, 0.26480042934417725D, 0.26508674025535583D, 0.26537132263183594D, 0.26565036177635193D, 0.2659280598163605D, 0.26621153950691223D, 0.2664932310581207D, 0.266765296459198D, 0.2670402526855469D, 0.26732540130615234D, 0.2676064372062683D, 0.2678873836994171D, 0.26817184686660767D, 0.26845213770866394D, 0.2687281370162964D, 0.2689865827560425D, 0.2692733108997345D, 0.2695508897304535D, 0.26984232664108276D, 0.2701159417629242D, 0.27039632201194763D, 0.2706771194934845D, 0.2709551453590393D, 0.27123481035232544D, 0.2715044319629669D, 0.2717909812927246D, 0.2720479965209961D, 0.27231383323669434D, 0.2725817859172821D, 0.2728441059589386D, 0.27311280369758606D, 0.2733941972255707D, 0.27368631958961487D, 0.2739763855934143D, 0.274264395236969D, 0.2745394706726074D, 0.2748079299926758D, 0.2750902473926544D, 0.2753576934337616D, 0.27563992142677307D, 0.27591678500175476D, 0.2762015461921692D, 0.2764870226383209D, 0.2767705023288727D, 0.2770461440086365D, 0.2773202061653137D, 0.277586430311203D, 0.2778612971305847D, 0.2781475782394409D, 0.27842074632644653D, 0.27869942784309387D, 0.27898266911506653D, 0.27925804257392883D, 0.27953964471817017D, 0.2798300087451935D, 0.28011223673820496D, 0.28038647770881653D, 0.28068000078201294D, 0.280953049659729D, 0.2812424302101135D, 0.2815268635749817D, 0.28180745244026184D, 0.2820815443992615D, 0.28235483169555664D, 0.28263142704963684D, 0.28291577100753784D, 0.2831827402114868D, 0.28346097469329834D, 0.28373128175735474D, 0.28402161598205566D, 0.2842971086502075D, 0.2845851182937622D, 0.2848743200302124D, 0.28514111042022705D, 0.2854291498661041D, 0.28570130467414856D, 0.28598201274871826D, 0.2862635850906372D, 0.2865474224090576D, 0.2868312895298004D, 0.28711485862731934D, 0.287393182516098D, 0.28767767548561096D, 0.2879578173160553D, 0.28823962807655334D, 0.2885189354419708D, 0.28880178928375244D, 0.2890920341014862D, 0.28937217593193054D, 0.28966113924980164D, 0.2899322509765625D, 0.29023706912994385D, 0.2905227243900299D, 0.29082342982292175D, 0.29111379384994507D, 0.2913990020751953D, 0.29169899225234985D, 0.2919909954071045D, 0.2922763526439667D, 0.2925618588924408D, 0.2928437292575836D, 0.29313600063323975D, 0.29342198371887207D, 0.29370519518852234D, 0.293990820646286D, 0.29427266120910645D, 0.29455944895744324D, 0.2948371469974518D, 0.2951136827468872D, 0.29540109634399414D, 0.29569217562675476D, 0.29599061608314514D, 0.29627665877342224D, 0.2965618371963501D, 0.29685071110725403D, 0.29713842272758484D, 0.2974165678024292D, 0.2977107763290405D, 0.29799580574035645D, 0.29828667640686035D, 0.2985561192035675D, 0.29883459210395813D, 0.2991248369216919D, 0.29942139983177185D, 0.2997003495693207D, 0.2999816834926605D, 0.3002794682979584D, 0.300558477640152D, 0.3008628785610199D, 0.3011316657066345D, 0.30142825841903687D, 0.30170485377311707D, 0.30200570821762085D, 0.30228835344314575D, 0.30257362127304077D, 0.3028506934642792D, 0.3031497299671173D, 0.3034270107746124D, 0.3037080466747284D, 0.30399709939956665D, 0.3042883276939392D, 0.30455490946769714D, 0.3048365116119385D, 0.3051189184188843D, 0.305414617061615D, 0.30569401383399963D, 0.3059791922569275D, 0.3062690496444702D, 0.3065638244152069D, 0.30685165524482727D, 0.3071337342262268D, 0.30742549896240234D, 0.3077087104320526D, 0.307993084192276D, 0.308301717042923D, 0.3085950016975403D, 0.30887916684150696D, 0.30916836857795715D, 0.30946359038352966D, 0.3097575008869171D, 0.3100418746471405D, 0.3103356957435608D, 0.3106286823749542D, 0.3109305202960968D, 0.31121826171875D, 0.3115043640136719D, 0.3117966055870056D, 0.3120863735675812D, 0.31238704919815063D, 0.312675416469574D, 0.3129754364490509D, 0.3132772445678711D, 0.31357139348983765D, 0.3138739764690399D, 0.314156711101532D, 0.31446096301078796D, 0.314767062664032D, 0.3150571882724762D, 0.31536349654197693D, 0.31567034125328064D, 0.31597578525543213D, 0.31626302003860474D, 0.3165755569934845D, 0.31686896085739136D, 0.31716006994247437D, 0.3174631595611572D, 0.31774675846099854D, 0.3180374503135681D, 0.31833595037460327D, 0.3186424672603607D, 0.31892913579940796D, 0.3192225694656372D, 0.31952160596847534D, 0.31980904936790466D, 0.32011789083480835D, 0.32043129205703735D, 0.32072004675865173D, 0.32100987434387207D, 0.3213180601596832D, 0.3216226398944855D, 0.3219207525253296D, 0.32221996784210205D, 0.32251104712486267D, 0.3228189945220947D, 0.32310861349105835D, 0.32341235876083374D, 0.32371604442596436D, 0.3240188658237457D, 0.3243238031864166D, 0.3246264159679413D, 0.3249231278896332D, 0.32521936297416687D, 0.32550862431526184D, 0.32581818103790283D, 0.3261036276817322D, 0.32640382647514343D, 0.3267083168029785D, 0.327004998922348D, 0.3272927403450012D, 0.3275948762893677D, 0.32788318395614624D, 0.3281833529472351D, 0.3284815549850464D, 0.32878002524375916D, 0.3290672302246094D, 0.3293750286102295D, 0.3296642303466797D, 0.3299630880355835D, 0.3302602469921112D, 0.3305669128894806D, 0.33086422085762024D, 0.3311595916748047D, 0.33145591616630554D, 0.33177000284194946D, 0.33208441734313965D, 0.3323875963687897D, 0.33268964290618896D, 0.33300232887268066D, 0.33329537510871887D, 0.3335980772972107D, 0.3338931202888489D, 0.334201455116272D, 0.33450081944465637D, 0.33479708433151245D, 0.3350889980792999D, 0.3354017734527588D, 0.3356862962245941D, 0.33597806096076965D, 0.3362779915332794D, 0.33658143877983093D, 0.3368886709213257D, 0.3372003436088562D, 0.3374904990196228D, 0.33780431747436523D, 0.3381199836730957D, 0.3384174108505249D, 0.3387186527252197D, 0.33900177478790283D, 0.33931413292884827D, 0.33961257338523865D, 0.3399102985858917D, 0.34022054076194763D, 0.3405352234840393D, 0.3408523499965668D, 0.3411627411842346D, 0.3414681553840637D, 0.3417760133743286D, 0.3420804738998413D, 0.3423832356929779D, 0.34269484877586365D, 0.34302496910095215D, 0.34334123134613037D, 0.3436470329761505D, 0.34394562244415283D, 0.3442646265029907D, 0.34457018971443176D, 0.34488752484321594D, 0.3452032506465912D, 0.3455159664154053D, 0.34581413865089417D, 0.3461098074913025D, 0.34641650319099426D, 0.3467230796813965D, 0.34702906012535095D, 0.3473309278488159D, 0.34764036536216736D, 0.3479456901550293D, 0.3482525050640106D, 0.34856411814689636D, 0.3488941192626953D, 0.3492147624492645D, 0.34952324628829956D, 0.3498258590698242D, 0.35016393661499023D, 0.3504606783390045D, 0.3507762551307678D, 0.35109102725982666D, 0.3514126241207123D, 0.35172921419143677D, 0.3520503044128418D, 0.35238561034202576D, 0.3527106046676636D, 0.3530224859714508D, 0.3533511757850647D, 0.35365211963653564D, 0.3539552092552185D, 0.35427314043045044D, 0.3545979857444763D, 0.35491013526916504D, 0.355211466550827D, 0.35551631450653076D, 0.35583731532096863D, 0.3561674952507019D, 0.356503427028656D, 0.35681140422821045D, 0.35713064670562744D, 0.3574579656124115D, 0.3577730655670166D, 0.3580852746963501D, 0.35840508341789246D, 0.3587261736392975D, 0.3590567708015442D, 0.35936981439590454D, 0.35967788100242615D, 0.3599919378757477D, 0.36031630635261536D, 0.3606279492378235D, 0.360944539308548D, 0.3612835109233856D, 0.36159858107566833D, 0.36191561818122864D, 0.3622327446937561D, 0.36255162954330444D, 0.36288535594940186D, 0.3632265329360962D, 0.36356231570243835D, 0.36387547850608826D, 0.3641921877861023D, 0.3645060658454895D, 0.36482110619544983D, 0.36514586210250854D, 0.3654731512069702D, 0.3657870292663574D, 0.366103857755661D, 0.3664219379425049D, 0.3667573034763336D, 0.3670819103717804D, 0.36740440130233765D, 0.3677348494529724D, 0.3680580258369446D, 0.3683835566043854D, 0.36869534850120544D, 0.3690166771411896D, 0.36936962604522705D, 0.3697071671485901D, 0.3700341284275055D, 0.3703477680683136D, 0.3706650137901306D, 0.37098345160484314D, 0.3713064193725586D, 0.3716377019882202D, 0.3719581365585327D, 0.3722735345363617D, 0.3726058304309845D, 0.3729363977909088D, 0.37326177954673767D, 0.37356603145599365D, 0.3738855719566345D, 0.3742108941078186D, 0.37452539801597595D, 0.3748537600040436D, 0.3751770555973053D, 0.3755142092704773D, 0.37582820653915405D, 0.3761524558067322D, 0.3764798045158386D, 0.3767988681793213D, 0.37712106108665466D, 0.37743860483169556D, 0.3777543902397156D, 0.37809327244758606D, 0.37840941548347473D, 0.37875550985336304D, 0.37908700108528137D, 0.37941306829452515D, 0.3797505497932434D, 0.38008758425712585D, 0.3804277181625366D, 0.3807571530342102D, 0.3810791075229645D, 0.38141703605651855D, 0.3817656934261322D, 0.38210225105285645D, 0.3824288845062256D, 0.382769376039505D, 0.38310790061950684D, 0.38344258069992065D, 0.3837745189666748D, 0.3841177821159363D, 0.38443708419799805D, 0.3847852945327759D, 0.3851090669631958D, 0.3854374289512634D, 0.38577699661254883D, 0.38612180948257446D, 0.38646358251571655D, 0.3868139684200287D, 0.38715416193008423D, 0.3874974548816681D, 0.3878219425678253D, 0.3881516456604004D, 0.38848888874053955D, 0.3888251483440399D, 0.38917040824890137D, 0.38950109481811523D, 0.38981884717941284D, 0.3901572823524475D, 0.39050623774528503D, 0.39083072543144226D, 0.39116042852401733D, 0.3915018141269684D, 0.3918399214744568D, 0.39218366146087646D, 0.3925294280052185D, 0.3928794264793396D, 0.39322105050086975D, 0.39356595277786255D, 0.39390116930007935D, 0.39424818754196167D, 0.39459410309791565D, 0.39493328332901D, 0.39526739716529846D, 0.39559459686279297D, 0.39594566822052D, 0.3962780237197876D, 0.39662104845046997D, 0.3969428539276123D, 0.3972987234592438D, 0.39764490723609924D, 0.39799994230270386D, 0.3983498811721802D, 0.39869624376296997D, 0.3990347385406494D, 0.39939403533935547D, 0.39974305033683777D, 0.4000907838344574D, 0.40044382214546204D, 0.4007917642593384D, 0.40111610293388367D, 0.4014665186405182D, 0.40181636810302734D, 0.40216636657714844D, 0.40252143144607544D, 0.4028819799423218D, 0.40323081612586975D, 0.4035872519016266D, 0.40394827723503113D, 0.4042988121509552D, 0.4046299159526825D, 0.40498116612434387D, 0.4053340256214142D, 0.4056835174560547D, 0.40604034066200256D, 0.40639346837997437D, 0.40674713253974915D, 0.4070903956890106D, 0.4074479639530182D, 0.4077978730201721D, 0.40815556049346924D, 0.4085153043270111D, 0.4088471829891205D, 0.40920335054397583D, 0.409536749124527D, 0.40988242626190186D, 0.4102332293987274D, 0.41057583689689636D, 0.4109056293964386D, 0.4112517535686493D, 0.41158610582351685D, 0.411954402923584D, 0.4123139977455139D, 0.4126741290092468D, 0.41304558515548706D, 0.4134019911289215D, 0.413760781288147D, 0.414113849401474D, 0.4144744575023651D, 0.4148549735546112D, 0.4152146577835083D, 0.4155882000923157D, 0.41595014929771423D, 0.41632524132728577D, 0.41668492555618286D, 0.4170358180999756D, 0.417406290769577D, 0.4177599251270294D, 0.4181312918663025D, 0.4184896945953369D, 0.4188544452190399D, 0.41922518610954285D, 0.419583797454834D, 0.41994741559028625D, 0.42030736804008484D, 0.4206812381744385D, 0.4210386574268341D, 0.4214108884334564D, 0.42178136110305786D, 0.42215496301651D, 0.4225171208381653D, 0.4228813350200653D, 0.42325109243392944D, 0.423615962266922D, 0.4239715337753296D, 0.42434579133987427D, 0.42472386360168457D, 0.42510300874710083D, 0.4254789650440216D, 0.4258454144001007D, 0.4262089729309082D, 0.4265795052051544D, 0.4269504249095917D, 0.42731940746307373D, 0.4276832640171051D, 0.42804470658302307D, 0.4284045994281769D, 0.42876332998275757D, 0.4291493892669678D, 0.4295348823070526D, 0.4299010634422302D, 0.43027088046073914D, 0.43064936995506287D, 0.43101370334625244D, 0.4313836097717285D, 0.43177637457847595D, 0.43216753005981445D, 0.4325481057167053D, 0.43293753266334534D, 0.4333171844482422D, 0.4336993396282196D, 0.4340720772743225D, 0.43445608019828796D, 0.43482720851898193D, 0.43520474433898926D, 0.4355813264846802D, 0.435965895652771D, 0.4363478720188141D, 0.4367339015007019D, 0.43710440397262573D, 0.4374915361404419D, 0.43787166476249695D, 0.4382757544517517D, 0.4386570155620575D, 0.4390236437320709D, 0.43937790393829346D, 0.43978676199913025D, 0.4401753544807434D, 0.44054529070854187D, 0.4409463107585907D, 0.4413623809814453D, 0.44173145294189453D, 0.44210049510002136D, 0.44250327348709106D, 0.4428851902484894D, 0.44325748085975647D, 0.44363629817962646D, 0.4440159797668457D, 0.4443915784358978D, 0.4447783827781677D, 0.44518083333969116D, 0.4455743432044983D, 0.44597482681274414D, 0.44637376070022583D, 0.4467555284500122D, 0.4471644163131714D, 0.44755885004997253D, 0.44794702529907227D, 0.44833505153656006D, 0.44871219992637634D, 0.44911694526672363D, 0.44951802492141724D, 0.44992169737815857D, 0.45028671622276306D, 0.45069053769111633D, 0.4510745704174042D, 0.45147672295570374D, 0.4518676698207855D, 0.45226404070854187D, 0.4526667594909668D, 0.45307374000549316D, 0.45347461104393005D, 0.453886479139328D, 0.4542858898639679D, 0.45466384291648865D, 0.4550491273403168D, 0.45543593168258667D, 0.4558371901512146D, 0.45624276995658875D, 0.4566361904144287D, 0.457043319940567D, 0.45746922492980957D, 0.4578607976436615D, 0.458267480134964D, 0.45867159962654114D, 0.4590873718261719D, 0.459495484828949D, 0.4598916471004486D, 0.46029186248779297D, 0.46069759130477905D, 0.46110185980796814D, 0.4615064859390259D, 0.46192145347595215D, 0.46233877539634705D, 0.46276673674583435D, 0.46316519379615784D, 0.4635927677154541D, 0.4640122056007385D, 0.46440884470939636D, 0.4648398756980896D, 0.4652484059333801D, 0.4656558334827423D, 0.46607261896133423D, 0.4665050506591797D, 0.4669226109981537D, 0.46733230352401733D, 0.4677324891090393D, 0.46813610196113586D, 0.4685579836368561D, 0.4689575731754303D, 0.46935874223709106D, 0.4697929620742798D, 0.4702039957046509D, 0.4706023335456848D, 0.47102463245391846D, 0.4714542329311371D, 0.47186529636383057D, 0.47227713465690613D, 0.47273728251457214D, 0.47315338253974915D, 0.4735952317714691D, 0.4740048050880432D, 0.4744380712509155D, 0.47486940026283264D, 0.47530895471572876D, 0.47574278712272644D, 0.4761829376220703D, 0.47661855816841125D, 0.4770328402519226D, 0.4774709641933441D, 0.477912038564682D, 0.47833552956581116D, 0.47877728939056396D, 0.4792020618915558D, 0.47962984442710876D, 0.48004886507987976D, 0.48047083616256714D, 0.48091474175453186D, 0.48136579990386963D, 0.4817824363708496D, 0.48223716020584106D, 0.4826858341693878D, 0.483129620552063D, 0.48356717824935913D, 0.48402535915374756D, 0.4844686985015869D, 0.48492634296417236D, 0.4853666424751282D, 0.48579952120780945D, 0.48623910546302795D, 0.4866853952407837D, 0.4871336817741394D, 0.4875692129135132D, 0.4880107045173645D, 0.48845070600509644D, 0.4888957142829895D, 0.48936671018600464D, 0.4898100197315216D, 0.49028757214546204D, 0.4907471537590027D, 0.49118760228157043D, 0.49167636036872864D, 0.4921429753303528D, 0.49261200428009033D, 0.49306604266166687D, 0.4935230314731598D, 0.4939839243888855D, 0.49443933367729187D, 0.49487918615341187D, 0.495321661233902D, 0.49577128887176514D, 0.4962393343448639D, 0.4967193901538849D, 0.4971999526023865D, 0.4976634979248047D, 0.4981079697608948D, 0.4985779821872711D, 0.4990575909614563D, 0.4995216429233551D, 0.49998214840888977D, 0.5004438757896423D, 0.5009346604347229D, 0.5013915300369263D, 0.5018666386604309D, 0.5023337006568909D, 0.5028214454650879D, 0.5032830238342285D, 0.5037580728530884D, 0.5042566061019897D, 0.5047234296798706D, 0.5052047967910767D, 0.5056884288787842D, 0.506147027015686D, 0.5066317915916443D, 0.5071203708648682D, 0.5075882077217102D, 0.5080697536468506D, 0.5085747838020325D, 0.5090773105621338D, 0.5095798373222351D, 0.5100753307342529D, 0.5105835199356079D, 0.5110831260681152D, 0.5115672945976257D, 0.5120378136634827D, 0.5125263929367065D, 0.5130169987678528D, 0.5135247707366943D, 0.5140180587768555D, 0.5145205855369568D, 0.5150368213653564D, 0.5155346989631653D, 0.516032874584198D, 0.5165354609489441D, 0.5170459747314453D, 0.517546534538269D, 0.5180581212043762D, 0.5185604691505432D, 0.5190833210945129D, 0.5195894837379456D, 0.5200911164283752D, 0.5206009149551392D, 0.5211076736450195D, 0.5216162204742432D, 0.5221534967422485D, 0.5226559638977051D, 0.5232011079788208D, 0.5237134099006653D, 0.524222731590271D, 0.5247693657875061D, 0.5253021121025085D, 0.5258720517158508D, 0.5263900756835938D, 0.5269289612770081D, 0.527440071105957D, 0.527983546257019D, 0.5285229086875916D, 0.5290459990501404D, 0.5295710563659668D, 0.5301372408866882D, 0.5306873917579651D, 0.5312291383743286D, 0.5317577123641968D, 0.5322787761688232D, 0.5328095555305481D, 0.5333465933799744D, 0.5338669419288635D, 0.5344110131263733D, 0.5349779725074768D, 0.535515308380127D, 0.5360614657402039D, 0.5366105437278748D, 0.5371830463409424D, 0.5377721190452576D, 0.5383244156837463D, 0.5388537049293518D, 0.5394071340560913D, 0.5399731397628784D, 0.5405322909355164D, 0.5410723090171814D, 0.541620671749115D, 0.5421631336212158D, 0.5427330136299133D, 0.5433263778686523D, 0.543902575969696D, 0.5445014834403992D, 0.5451188087463379D, 0.54570472240448D, 0.5462703108787537D, 0.5468359589576721D, 0.5474085211753845D, 0.5479677319526672D, 0.5485826134681702D, 0.5491936206817627D, 0.5497756004333496D, 0.550329864025116D, 0.5509083271026611D, 0.5514797568321228D, 0.5520867705345154D, 0.5526585578918457D, 0.5532442331314087D, 0.5538352131843567D, 0.554451048374176D, 0.5550478100776672D, 0.5556716322898865D, 0.5562905669212341D, 0.5568975210189819D, 0.5575076937675476D, 0.55810546875D, 0.5587112903594971D, 0.5593138933181763D, 0.5599293112754822D, 0.560528576374054D, 0.5611559748649597D, 0.5618165731430054D, 0.5624411702156067D, 0.5630917549133301D, 0.5637422204017639D, 0.5643942356109619D, 0.565030038356781D, 0.5656741857528687D, 0.5663131475448608D, 0.5669856071472168D, 0.5676253437995911D, 0.5682467818260193D, 0.5688928961753845D, 0.5695339441299438D, 0.5701755881309509D, 0.5708367824554443D, 0.5714528560638428D, 0.5721008777618408D, 0.572792112827301D, 0.5734336972236633D, 0.5740956664085388D, 0.5747833847999573D, 0.5754809975624084D, 0.5761705636978149D, 0.5768662095069885D, 0.5775163769721985D, 0.5782217979431152D, 0.5789486169815063D, 0.5796666145324707D, 0.5803557634353638D, 0.581061065196991D, 0.5817610025405884D, 0.5824694633483887D, 0.5831955671310425D, 0.5839105844497681D, 0.5846039056777954D, 0.5852735042572021D, 0.585961639881134D, 0.5866875052452087D, 0.5874256491661072D, 0.5881643891334534D, 0.5888875722885132D, 0.5896194577217102D, 0.5903604030609131D, 0.5911058783531189D, 0.5918967723846436D, 0.5926496982574463D, 0.5934140086174011D, 0.5941669344902039D, 0.5949351787567139D, 0.5956904292106628D, 0.5964735746383667D, 0.5972592830657959D, 0.5980729460716248D, 0.5988597869873047D, 0.599652111530304D, 0.6004453897476196D, 0.6012773513793945D, 0.6020792722702026D, 0.6028953194618225D, 0.6037645936012268D, 0.6045876145362854D, 0.6053803563117981D, 0.6061732172966003D, 0.6070164442062378D, 0.607831597328186D, 0.6086806058883667D, 0.6095685958862305D, 0.6104097962379456D, 0.6112634539604187D, 0.6120801568031311D, 0.6129648685455322D, 0.61387699842453D, 0.6147569417953491D, 0.6155954599380493D, 0.616402268409729D, 0.6172897219657898D, 0.6181901693344116D, 0.6190983653068542D, 0.6199691891670227D, 0.6208701133728027D, 0.6217461824417114D, 0.6226446032524109D, 0.6236084699630737D, 0.6245348453521729D, 0.6254535913467407D, 0.6264715194702148D, 0.627429187297821D, 0.6283873319625854D, 0.6293536424636841D, 0.6303542852401733D, 0.6313357353210449D, 0.6323064565658569D, 0.6332805156707764D, 0.6342861652374268D, 0.6353551745414734D, 0.6363866329193115D, 0.6374404430389404D, 0.6384573578834534D, 0.6395328044891357D, 0.640578031539917D, 0.6416310667991638D, 0.6427513360977173D, 0.6438618302345276D, 0.6449521780014038D, 0.6460468173027039D, 0.6471554636955261D, 0.6482812166213989D, 0.6493995189666748D, 0.6506232619285583D, 0.6517972946166992D, 0.6529961228370667D, 0.6542066931724548D, 0.6553934216499329D, 0.6565525531768799D, 0.6577653288841248D, 0.659013569355011D, 0.6602596640586853D, 0.6615633964538574D, 0.6628472805023193D, 0.6642037034034729D, 0.6654988527297974D, 0.6668195128440857D, 0.6681184768676758D, 0.6694334149360657D, 0.6707931756973267D, 0.6722204685211182D, 0.6736778020858765D, 0.6750837564468384D, 0.6765458583831787D, 0.6780242919921875D, 0.6794694662094116D, 0.6809762716293335D, 0.6825757026672363D, 0.6842136383056641D, 0.6857424974441528D, 0.6873693466186523D, 0.6890041828155518D, 0.6906958222389221D, 0.6923577785491943D, 0.6941602230072021D, 0.6958938241004944D, 0.6976979374885559D, 0.6996030807495117D, 0.7014617919921875D, 0.7033551931381226D, 0.7053101062774658D, 0.7073088884353638D, 0.7093900442123413D, 0.7115321159362793D, 0.7136979699134827D, 0.7159866690635681D, 0.7184513211250305D, 0.7208492159843445D, 0.7233277559280396D, 0.725836992263794D, 0.7282920479774475D, 0.7309600114822388D, 0.7337514162063599D, 0.7369317412376404D, 0.7400341629981995D, 0.7431910634040833D, 0.7465731501579285D, 0.7502389550209045D, 0.7539366483688354D, 0.7578595280647278D, 0.7620136737823486D, 0.7664995193481445D, 0.7713850736618042D, 0.7766971588134766D, 0.7824797630310059D, 0.7896102666854858D, 0.7976230382919312D, 0.8072929978370667D, 0.8200995326042175D, 0.8393367528915405D, 0.8953311443328857D}; - - @Test - static void testDistribution() { - - FastNoiseLite noise = new FastNoiseLite(); - noise.setNoiseType(FastNoiseLite.NoiseType.OpenSimplex2); - noise.setFrequency(0.02f); - noise.setFractalType(FastNoiseLite.FractalType.FBm); - noise.setFractalOctaves(4); - System.out.println(noise); - int attempts = 8; - int[] numbers = new int[attempts]; - double min = Integer.MAX_VALUE; - double max = Integer.MIN_VALUE; - - - for(int i = 0; i < attempts; i++) { - numbers[i] = 0; - } - - long l = System.nanoTime(); - for(int i = 0; i < 1000000; i++) { - double n = noise.getNoise(0, i); - max = FastMath.max(max, n); - min = FastMath.min(min, n); - numbers[normalize(n, attempts)]++; - } - long l2 = System.nanoTime() - l; - System.out.println("Took " + (double) l2 / 1000000 + "ms (" + ((double) l2 / 1000000) + "ns per."); - - l = System.nanoTime(); - for(int i = 0; i < 1000000; i++) { - double n = noise.getNoise(0, i); - max = FastMath.max(max, n); - min = FastMath.min(min, n); - } - l2 = System.nanoTime() - l; - System.out.println("Took " + (double) l2 / 1000000 + "ms (" + ((double) l2 / 1000000) + "ns per."); - - for(int i = 0; i < attempts; i++) { - System.out.println(i + ": " + numbers[i]); - } - for(int i = 0; i < attempts; i++) { - System.out.print(i + " |"); - for(int j = 0; j < numbers[i] / 250; j++) { - System.out.print("-"); - } - System.out.println("|"); - } - System.out.println("max: " + max); - System.out.println("min: " + min); - } - - public static int normalize(double d, int num) { - int start = 0; - int end = normalMap.length - 1; - while(start + 1 < end) { - int mid = start + (end - start) / 2; - if(normalMap[mid] <= d) { - start = mid; - } else { - end = mid; - } - } - double left = FastMath.abs(normalMap[start] - d); - double right = FastMath.abs(normalMap[end] - d); - if(left <= right) { - return start * (num) / (normalMap.length); - } - return end * (num) / (normalMap.length); - } - - public static int normal(double d, int max) { - double ranged = FastMath.max(0, FastMath.min((d + 1) / 2D, 1)); - return (int) (ranged * max); - } -} diff --git a/src/test/java/LookupGenerator.java b/src/test/java/LookupGenerator.java deleted file mode 100644 index eea731910..000000000 --- a/src/test/java/LookupGenerator.java +++ /dev/null @@ -1,136 +0,0 @@ -import net.jafama.FastMath; -import org.junit.jupiter.api.Test; -import org.polydev.gaea.math.FastNoiseLite; -import org.polydev.gaea.util.GlueList; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -class LookupGenerator { - private static double[] lookup; - - @Test - static void main(String[] args) throws InterruptedException { - int dist = 4096; - - List vals = new GlueList<>(); - FastNoiseLite noise = new FastNoiseLite(); - noise.setNoiseType(FastNoiseLite.NoiseType.OpenSimplex2); - noise.setFrequency(0.02f); - int[] numbers = new int[dist]; - double min = Integer.MAX_VALUE; - double max = Integer.MIN_VALUE; - for(int i = 0; i < dist; i++) { - numbers[i] = 0; - } - - int workerAmount = 16; - - List workers = new GlueList<>(); - - for(int i = 0; i < workerAmount; i++) { - workers.add(new Worker(new GlueList<>(), 5000000, noise)); - } - - for(Worker w : workers) { - w.start(); - } - for(Worker w : workers) { - System.out.println("Waiting for Worker " + workers.indexOf(w)); - w.join(); - } - - for(Worker w : workers) { - vals.addAll(w.getResult()); - } - - System.out.println("Generated " + vals.size() + " values."); - - for(int i = 0; i < dist; i++) { - System.out.println(i + ": " + numbers[i]); - } - for(int i = 0; i < dist; i++) { - System.out.print(i + (String.valueOf(i).length() == 1 ? " " : "") + " |"); - for(int j = 0; j < numbers[i] / 300; j++) { - System.out.print("-"); - } - System.out.println("|"); - } - System.out.println("max: " + max); - System.out.println("min: " + min); - Collections.sort(vals); - - lookup = new double[dist]; - StringBuilder s = new StringBuilder("{"); - for(int i = 0; i < dist; i++) { - int current = vals.size() / dist; - System.out.println(i + ", max: " + vals.get(current * (i + 1) - 1)); - lookup[i] = vals.get(current * (i + 1) - 1); - s.append(vals.get(current * (i + 1) - 1)).append("D, "); - } - s.delete(s.length() - 2, s.length()); - s.append("}"); - numbers = new int[dist]; - vals = new ArrayList<>(); - for(int i = 0; i < 10000000; i++) { - double n = noise.getNoise(0, i); - vals.add(n); - numbers[normalizeNew(n)]++; - } - - for(int i = 0; i < dist; i++) { - System.out.println(i + ": " + numbers[i]); - } - for(int i = 0; i < dist; i++) { - System.out.print(i + (String.valueOf(i).length() == 1 ? " " : "") + " |"); - for(int j = 0; j < numbers[i] / 100; j++) { - System.out.print("-"); - } - System.out.println("|"); - } - System.out.println(s.toString()); - - } - - public static int normalizeNew(double d) { - for(int i = 0; i < lookup.length; i++) { - if(d < lookup[i]) return i; - } - return lookup.length - 1; - } - - public static int normalize(double i, int n) { - i *= 1.42; // Magic simplex value (sqrt(2) plus a little) - i = FastMath.min(FastMath.max(i, -1), 1); - return FastMath.min((int) FastMath.floor((i + 1) * ((double) n / 2)), n - 1); - } - - private static class Worker extends Thread { - private final List l; - private final int searches; - private final FastNoiseLite noise; - - public Worker(List l, int searches, FastNoiseLite noise) { - this.l = l; - this.searches = searches; - this.noise = noise; - } - - @Override - public void run() { - for(int i = 0; i < searches; i++) { - double n = noise.getNoise(0, i); - l.add(n); - } - } - - public List getResult() { - return l; - } - - public String getStatus() { - return "Generating values. " + l.size() + "/" + searches + " (" + ((long) l.size() * 100L) / searches + "%)"; - } - } -} diff --git a/src/test/java/NoiseInstancePerformanceTest.java b/src/test/java/NoiseInstancePerformanceTest.java deleted file mode 100644 index ac3ecc72c..000000000 --- a/src/test/java/NoiseInstancePerformanceTest.java +++ /dev/null @@ -1,17 +0,0 @@ -import org.junit.jupiter.api.Test; -import org.polydev.gaea.math.FastNoiseLite; - -public class NoiseInstancePerformanceTest { - @Test - public void performance() { - FastNoiseLite noiseLite = new FastNoiseLite(2403); - long l = System.nanoTime(); - for(int i = 0; i < 10000000; i++) noiseLite.getNoise(i, i); - System.out.println("No instantiation: " + (System.nanoTime() - l) / 1000000 + "ms"); - for(int i = 0; i < 10000000; i++) { - FastNoiseLite noiseLite1 = new FastNoiseLite(2403); - noiseLite1.getNoise(i, i); - } - System.out.println("Instantiation: " + (System.nanoTime() - l) / 1000000 + "ms"); - } -} diff --git a/src/test/java/NoiseTest.java b/src/test/java/NoiseTest.java deleted file mode 100644 index 346b4e5a0..000000000 --- a/src/test/java/NoiseTest.java +++ /dev/null @@ -1,52 +0,0 @@ -import com.dfsek.terra.generation.config.NoiseBuilder; -import com.dfsek.terra.math.NoiseFunction2; -import org.junit.jupiter.api.Test; -import parsii.eval.Expression; - -import java.util.Arrays; - -public class NoiseTest { - @Test - public void noise() { - NoiseFunction2 noiseFunction = new NoiseFunction2(12345, new NoiseBuilder()); - System.out.println("Cache:"); - int a = 0; - for(int i = 0; i < 200; i++) { - long l = System.nanoTime(); - for(int j = 0; j < 1000; j++) { - for(int x = 0; x < 4; x++) { - for(int y = 0; y < 64; y++) { - for(int z = 0; z < 4; z++) { - noiseFunction.eval(Arrays.asList(get(j * 16 + (x * 4)), get(i * 16 + (z * 4)))); - } - } - } - } - double n = System.nanoTime() - l; - System.out.print((long) n / 1000000 + "ms" + ((a % 10 == 0) ? "\n" : " ")); - a++; - } - System.out.println(); - System.out.println(); - System.out.println("No Cache:"); - for(int i = 0; i < 200; i++) { - long l = System.nanoTime(); - for(int j = 0; j < 1000; j++) { - for(int x = 0; x < 4; x++) { - for(int y = 0; y < 64; y++) { - for(int z = 0; z < 4; z++) { - noiseFunction.evalNoCache(Arrays.asList(get(j * 16 + (x * 4)), get(i * 16 + (z * 4)))); - } - } - } - } - double n = System.nanoTime() - l; - System.out.print((long) n / 1000000 + "ms" + ((a % 10 == 0) ? "\n" : " ")); - a++; - } - } - - private Expression get(double val) { - return () -> val; - } -} diff --git a/src/test/java/RangeTest.java b/src/test/java/RangeTest.java deleted file mode 100644 index b9e12cccf..000000000 --- a/src/test/java/RangeTest.java +++ /dev/null @@ -1,39 +0,0 @@ -import org.junit.jupiter.api.Test; -import org.polydev.gaea.math.Range; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNull; - -public class RangeTest { - @Test - public void iterator() { - Range m = new Range(0, 100); - int i = 0; - for(int mint : m) { - assertEquals(i, mint); - i++; - } - assertEquals(100, i); - } - - @Test - public void intersect() { - Range one = new Range(10, 100); - Range two = new Range(1, 20); - Range intersect = one.intersects(two); - assertEquals(20, intersect.getMax()); - assertEquals(10, intersect.getMin()); - assertEquals(one.intersects(two), two.intersects(one)); - - one = new Range(25, 50); - assertNull(one.intersects(two)); - } - - @Test - public void reflect() { - Range t = new Range(3, 10); - Range other = t.reflect(5); - assertEquals(7, other.getMax()); - assertEquals(0, other.getMin()); - } -}