Compare commits

..

112 Commits

Author SHA1 Message Date
dfsek 69ae803074 resolve merge conflicts 2021-05-09 16:23:13 -07:00
dfsek 8f9fc3e08f Merge remote-tracking branch 'origin/master' into dev/repeat-script
# Conflicts:
#	common/src/main/java/com/dfsek/terra/api/TerraPlugin.java
#	common/src/test/java/biome/DistributionTest.java
#	platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/TerraBukkitPlugin.java
#	platforms/fabric/src/main/java/com/dfsek/terra/fabric/TerraFabricPlugin.java
#	platforms/region/src/main/java/com/dfsek/terra/StandalonePlugin.java
#	platforms/sponge/src/main/java/com/dfsek/terra/sponge/TerraSpongePlugin.java
2021-05-09 15:20:57 -07:00
dfsek fd48f5f110 Merge pull request #158 from PolyhedralDev/dev/fabric-locate
Override structure location on Fabric
2021-05-04 16:45:25 -07:00
dfsek 77a4c95c4a override structure location on Fabric 2021-05-04 16:44:43 -07:00
dfsek dbc60b1d82 Merge pull request #153 from PolyhedralDev/dev/fabric-mixins
Implement Terra interfaces directly in Minecraft classes using Mixin.
2021-05-04 16:16:31 -07:00
dfsek ed942bb997 update README.md 2021-05-04 16:13:05 -07:00
dfsek 6866084872 SignBlockEntityMixin cleanup 2021-05-04 16:10:37 -07:00
dfsek 4c77419dcd fix sign getText on server 2021-05-04 15:04:53 -07:00
dfsek ecba6e0843 Merge remote-tracking branch 'origin/dev/fabric-mixins' into dev/fabric-mixins 2021-05-04 09:21:21 -07:00
dfsek 86dcb476f1 update README with modern build instructions and Forge download links 2021-05-04 09:21:12 -07:00
dfsek 13e0857882 merge FabricEnumAdapter into FabricAdapter 2021-05-03 22:49:21 -07:00
dfsek bf93a9239c bump version 2021-05-03 22:28:01 -07:00
dfsek 2d18aab709 fix funky yaml formatting 2021-05-03 22:13:42 -07:00
dfsek a1359da374 terrascript trig functions 2021-05-03 22:13:32 -07:00
dfsek f7bda835f9 fix itemmeta application 2021-05-03 20:52:03 -07:00
dfsek 7595896831 fix refmap issues 2021-05-03 20:40:56 -07:00
dfsek 6614d19845 suppress warnings 2021-05-03 20:14:06 -07:00
dfsek 6209b86560 mixin maintenance 2021-05-03 20:12:48 -07:00
dfsek a30859a3d4 dont try to remap Terra interfaces 2021-05-03 20:08:13 -07:00
dfsek ddbb46289b add package-info.java to implementation mixin package. 2021-05-03 20:03:25 -07:00
dfsek 64c35a9609 refactor Fabric project 2021-05-03 20:02:08 -07:00
dfsek f21069ab2e fix cache misses 2021-05-03 19:43:52 -07:00
dfsek 457729b832 replace most access wideners with mixins 2021-05-03 19:33:57 -07:00
dfsek 756f04a0b3 implement LockableContainerBlockEntityMixin 2021-05-03 18:38:40 -07:00
dfsek 5ee32cc3ba add ConfiguredFeatureMixin 2021-05-03 17:35:43 -07:00
dfsek 955558bc21 implement BlockMixin 2021-05-03 11:37:54 -07:00
dfsek c43a872c23 finish blockstate mixins 2021-05-03 11:27:36 -07:00
dfsek de41b92d5d add SignBlockEntityMixin 2021-05-03 10:27:40 -07:00
dfsek 03091230ed refactor mixins 2021-05-03 10:09:21 -07:00
dfsek a8c88915ea override chunkregion hashcode 2021-05-02 23:39:40 -07:00
dfsek 4cd4720101 fix loot NPE 2021-05-02 23:08:54 -07:00
dfsek 3b9280b19c start work on state mixins 2021-05-02 23:00:21 -07:00
dfsek 2d27e07441 implement BiomeMixin 2021-05-02 22:49:57 -07:00
dfsek 20a5762d2e refactor mixins 2021-05-02 22:48:21 -07:00
dfsek 146f71f704 finish World mixins 2021-05-02 22:45:34 -07:00
dfsek 1d4b0bc100 cleanup 2021-05-02 22:26:23 -07:00
dfsek 138ee0a448 refactor fabric handles 2021-05-02 22:22:32 -07:00
dfsek 2c8cae9d45 create ChunkGeneratorMixin 2021-05-02 22:21:50 -07:00
dfsek 061d2b6493 implement EntityTypeMixin 2021-05-02 21:48:06 -07:00
dfsek e71df936ab EnchantmentMixin 2021-05-02 21:35:39 -07:00
dfsek f4253acb78 item mixins 2021-05-02 21:27:25 -07:00
dfsek c12518fa49 delete FabricItem.java 2021-05-02 21:11:09 -07:00
dfsek 4704b2ebf7 implement ItemMixin 2021-05-02 21:10:48 -07:00
dfsek 89fdfdfb34 suppress warnings 2021-05-02 20:42:54 -07:00
dfsek 35d85f2aa3 PlayerEntityMixin and EntityMixin 2021-05-02 20:38:25 -07:00
dfsek c0368f1c6d implement ServerCommandSourceMixin 2021-05-02 20:17:59 -07:00
dfsek abc069046c add ProtoChunkMixin and WorldChunkMixin 2021-05-02 20:13:24 -07:00
dfsek 46d0b08068 implement ChunkRegionMixin 2021-05-02 19:49:59 -07:00
dfsek a7e3a0286e add -forge and -fabric to Modrinth version numbers. 2021-05-02 17:46:55 -07:00
dfsek 6da8924868 Merge pull request #145 from PolyhedralDev/dev/forge
Forge implementation
2021-05-02 17:38:56 -07:00
dfsek d9dd6afe4b Merge pull request #143 from solonovamax/improvement/better-gradle-performance
Improve gradle performance significantly
2021-05-02 17:37:36 -07:00
dfsek dfec26f789 fix forge modrinth task 2021-05-02 17:21:05 -07:00
dfsek d13be5e159 add Forge modrinth publish task 2021-05-02 17:16:03 -07:00
dfsek 51c5f70d64 forge jarfile nightmare "solution" 2021-05-02 17:08:59 -07:00
dfsek 05b1902c06 Merge pull request #151 from DJtheRedstoner/patch-mixin-ap
Fix mixin annotation processor issues
2021-05-02 15:47:32 -07:00
dfsek f4ae2cac68 add MixinGeneratorOptions 2021-05-02 15:46:03 -07:00
dfsek ea3995afce fix refmap name 2021-05-02 15:44:30 -07:00
dfsek c41d60c38f remove manual refmap 2021-05-02 15:43:12 -07:00
DJtheRedstoner 19edcbddd5 Fix mixin annotation processor issues
These issues were caused by CompilationConfig.configureCompilation()
overwriting JavaCompile's options.compilerArgs list which removed any
previously added arguments, including those added by fabric-loom and
mixingradle.
2021-05-02 18:17:18 -04:00
dfsek 4f65555e82 remove mixins until annotation processor gets fixed. 2021-05-02 14:37:34 -07:00
dfsek 9956cab507 dont use vanilla registries 2021-05-01 22:21:27 -07:00
dfsek fddf0c51b7 cleanup PopulationManager 2021-05-01 20:27:59 -07:00
dfsek e2a52afb67 remove methods only used for cursed Bukkit stuff from common World interface. 2021-05-01 19:07:19 -07:00
dfsek c8c3a33912 fix loot table issue 2021-05-01 18:40:31 -07:00
dfsek b178f69e47 Merge remote-tracking branch 'origin/dev/forge' into dev/forge 2021-05-01 18:20:23 -07:00
dfsek 049a56fcb0 Mixin on Forge 2021-05-01 18:20:11 -07:00
solonovamax 2d41dd8f08 Don't use all cores processors for tests
Signed-off-by: solonovamax <solonovamax@12oclockpoint.com>
2021-05-01 16:53:45 -04:00
solonovamax aa9e33af1d Remove old and deprecated compile configuration + some minor refactoring
Signed-off-by: solonovamax <solonovamax@12oclockpoint.com>
2021-05-01 16:53:45 -04:00
dfsek 02870805c7 hoist calculations in chunk generator 2021-04-30 09:35:15 -07:00
dfsek e493825ab7 bump version 2021-04-30 09:25:56 -07:00
dfsek 762b248641 update to latest Tectonic 2021-04-29 23:42:56 -07:00
dfsek f81ccee020 cleanup 2021-04-29 23:31:03 -07:00
dfsek 3561e5f30f commands on Forge 2021-04-29 23:19:49 -07:00
dfsek c67817b9d2 fix structure issues 2021-04-29 22:00:40 -07:00
dfsek 756619edb6 Forge actually loads to worlds now 2021-04-29 21:48:32 -07:00
dfsek ee1c889d54 world screen type 2021-04-29 21:11:26 -07:00
dfsek 9f3dcf07b6 Pack loading on Forge 2021-04-29 20:30:48 -07:00
dfsek 93a2f103f7 add pack.mcmeta 2021-04-29 16:41:14 -07:00
dfsek 3ea12ceeab start implementing terraplugin 2021-04-29 12:30:17 -07:00
dfsek ce8ec51ae4 forge actually loads now 2021-04-29 12:24:29 -07:00
dfsek 54bb4ef109 sort of working Forge project 2021-04-29 01:55:24 -07:00
dfsek 59b655ce5d working forge buildscript 2021-04-29 01:27:28 -07:00
solonovamax 4c1e1bb7d5 Improve gradle performance significantly
Signed-off-by: solonovamax <solonovamax@12oclockpoint.com>
2021-04-28 20:43:53 -04:00
dfsek eee54f507e Merge pull request #138 from PolyhedralDev/dev/profilerimpl
Fancy stack-based profiler
2021-04-26 21:32:42 -07:00
dfsek 6f1b1611ab fix dumb gradle issue 2021-04-26 21:26:44 -07:00
dfsek 205499220d profile more things 2021-04-26 20:59:21 -07:00
dfsek a0c5631eba bump version 2021-04-26 20:46:36 -07:00
dfsek 9323abc788 document Profiler 2021-04-26 19:04:20 -07:00
dfsek 632f898dc8 implement Profiler#reset 2021-04-26 19:01:53 -07:00
dfsek 8737b0d984 resolve merge conflict 2021-04-25 17:12:42 -07:00
dfsek bcb68853d5 @SuppressWarnings go brrr 2021-04-25 17:11:50 -07:00
dfsek 8823d6d65e fix stack size assumption at profiler start 2021-04-25 17:11:50 -07:00
dfsek 5d3a2b6e84 profile more things 2021-04-25 17:11:50 -07:00
dfsek 23fb7753ab fancy unicode symbols B) 2021-04-25 17:11:50 -07:00
dfsek f8e7e343cb fix % parent issue 2021-04-25 17:11:50 -07:00
dfsek e5f4c5dc8d implement terrascript profiling 2021-04-25 17:11:49 -07:00
dfsek 8a10867e5f implement new profiler 2021-04-25 17:11:04 -07:00
dfsek da366a75e8 add autocloseable option 2021-04-25 17:09:08 -07:00
dfsek eb4bf74cc6 implement TerraPlugin#getProfier 2021-04-25 17:09:08 -07:00
dfsek 168c0ced13 improve performance in deep operations 2021-04-25 17:09:07 -07:00
dfsek 5d4bdb431b improve data output 2021-04-25 17:09:07 -07:00
dfsek 40188c671f basic profiler implementation 2021-04-25 17:09:07 -07:00
dfsek 92339c904d equals and hashcode for Either and Pair 2021-04-22 11:57:14 -07:00
dfsek 56fb510d96 fabric scheduler impl 2021-04-22 10:31:56 -07:00
dfsek 5821302eb8 create TaskScheduler 2021-04-21 15:37:10 -07:00
dfsek 901677d2c3 add repeat script options 2021-04-21 11:10:27 -07:00
dfsek f396e0e5eb Merge pull request #133 from PolyhedralDev/ver/5.1.4
Fix minor Fabric issues
2021-04-16 09:01:29 -07:00
dfsek 942a8c9c8b Merge pull request #131 from xieve/fix-disable-config
Fixed populator disable config (#130)
2021-04-15 10:29:20 -07:00
dfsek 414dcdae3e use vanilla delegate spawn rules 2021-04-15 10:20:14 -07:00
dfsek 1195a6676f implement getHeight on Fabric 2021-04-15 10:00:22 -07:00
dfsek 5501f53056 implement TerraFabricPlugin#getWorld(long) 2021-04-15 09:59:13 -07:00
xieve 41d6e1c648 Fixed populator disable config (#130) 2021-04-15 18:18:27 +02:00
226 changed files with 5571 additions and 1813 deletions
+1 -1
View File
@@ -342,6 +342,6 @@ ij_json_wrap_long_lines = false
indent_size = 2
ij_yaml_keep_indents_on_empty_lines = true
ij_yaml_keep_line_breaks = true
ij_yaml_space_before_colon = true
ij_yaml_space_before_colon = false
ij_yaml_spaces_within_braces = true
ij_yaml_spaces_within_brackets = true
+25 -9
View File
@@ -7,20 +7,36 @@ to your specifications, with no knowledge of Java required.
* Paper+ servers (Paper, Tuinity, Purpur, etc): [SpigotMC](https://www.spigotmc.org/resources/85151/)
* Fabric: [Modrinth](https://modrinth.com/mod/terra) / [CurseForge](https://www.curseforge.com/minecraft/mc-mods/terra-world-generator)
* Forge: [Modrinth](https://modrinth.com/mod/terra) / [CurseForge](https://www.curseforge.com/minecraft/mc-mods/terra-world-generator)
## Building and running Terra
## Building and Running Terra
To build, simply run `./gradlew build` (`gradlew.bat build` on Windows). This will produce a jar in `build/libs`
called `Terra-[CURRENT VERSION].jar`. You can put this right into your plugins dir, along with the correct Gaea version.
To build, simply run `./gradlew build` (`gradlew.bat build` on Windows). This will build all platforms, and
produce JARs in `platforms/<platform>/build/libs`
If you would like to test it with a default server config, just run `./gradlew setupServer` or
`./gradlew.bat setupServer` to set up the server, then `./gradlew testWithPaper` or `gradlew.bat testWithPaper` to run the server. If you
want a clean installation of the server, re-run the `setupServer` task. This will download a default server config
from [here](https://github.com/PolyhedralDev/WorldGenTestServer)
and install the server in the `target/server` directory, along with all the needed plugins.
### Production JARs:
* Bukkit: `Terra-<version>-shaded.jar`
* Fabric: `Terra-<version>-shaded-mapped.jar`
* Forge: `Terra-<version>-shaded.jar`
**Note: You will need to adjust the `NAME` variable `bukkit.yml` of the test server if you are not using the default Terra config.**
### Building a Specific Platform
To build a specific platform, run `gradlew :platforms:<platform>:build`.
JARs are produced in `platforms/<platform>/build/libs`.
### Running Minecraft in the IDE
To run Minecraft with Terra in the IDE (for testing) use the following tasks:
* Bukkit
* `installPaper` - Install a [Paper](https://github.com/PaperMC/Paper) test server. (Only needs to be run once).
* `installPurpur` - Install a [Purpur](https://github.com/pl3xgaming/Purpur) test server. (Only needs to be run once).
* `runPaper` - Run the Paper test server with Terra (`installPaper` must have been run previously).
* `runPurpur` - Run the Purpur test server with Terra (`installPurpur` must have been run previously).
* Fabric
* `runClient` - Run a Minecraft client with Terra installed.
* `runServer` - Run a Minecraft server with Terra installed.
* Forge
* `runClient` - Run a Minecraft client with Terra installed.
* `runServer` - Run a Minecraft server with Terra installed.
## Contributing
Contributions are welcome! If you want to see a feature in Terra, please, open an issue, or implement it yourself and
submit a PR!
+18 -1
View File
@@ -1,10 +1,27 @@
import com.dfsek.terra.getGitHash
val versionObj = Version("6", "0", "0", true)
val versionObj = Version("5", "3", "0", true)
allprojects {
version = versionObj
group = "com.dfsek.terra"
tasks.withType<JavaCompile>().configureEach {
options.isFork = true
options.isIncremental = true
}
tasks.withType<Test>().configureEach {
useJUnitPlatform()
maxHeapSize = "2G"
ignoreFailures = false
failFast = true
maxParallelForks = (Runtime.getRuntime().availableProcessors() - 1).takeIf { it > 0 } ?: 1
reports.html.isEnabled = false
reports.junitXml.isEnabled = false
}
}
/**
* Version class that does version stuff.
@@ -7,26 +7,11 @@ import org.gradle.kotlin.dsl.withType
import java.io.ByteArrayOutputStream
fun Project.configureCommon() {
apply(plugin = "java-library")
apply(plugin = "maven-publish")
apply(plugin = "idea")
configureDependencies()
configureCompilation()
configureDistribution()
version = rootProject.version
tasks.withType<Test>().configureEach {
useJUnitPlatform()
maxHeapSize = "2G"
ignoreFailures = false
failFast = true
maxParallelForks = 12
}
}
fun Project.getGitHash(): String {
@@ -3,14 +3,16 @@ 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.bundling.Jar
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.filter
import org.gradle.kotlin.dsl.withType
import org.gradle.kotlin.dsl.*
import org.gradle.language.jvm.tasks.ProcessResources
fun Project.configureCompilation() {
apply(plugin = "maven-publish")
apply(plugin = "idea")
configure<JavaPluginConvention> {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
@@ -19,7 +21,7 @@ fun Project.configureCompilation() {
tasks.withType<JavaCompile> {
options.encoding = "UTF-8"
doFirst {
options.compilerArgs = mutableListOf("-Xlint:all")
options.compilerArgs.add("-Xlint:all")
}
}
@@ -35,4 +37,19 @@ fun Project.configureCompilation() {
tasks.withType<Javadoc> {
options.encoding = "UTF-8"
}
tasks.withType<Jar> {
archiveBaseName.set("Terra-${archiveBaseName.get()}")
from("../LICENSE", "../../LICENSE")
}
tasks.register<Jar>("sourcesJar") {
archiveClassifier.set("sources")
}
tasks.register<Jar>("javadocJar") {
dependsOn("javadoc")
archiveClassifier.set("javadoc")
from(tasks.getByName<Javadoc>("javadoc").destinationDir)
}
}
@@ -1,13 +1,27 @@
package com.dfsek.terra
import org.gradle.api.Project
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.dependencies
import org.gradle.kotlin.dsl.invoke
import org.gradle.kotlin.dsl.repositories
fun Project.configureDependencies() {
apply(plugin = "java")
apply(plugin = "java-library")
configurations {
val shaded = create("shaded")
val shadedApi = create("shadedApi")
shaded.extendsFrom(shadedApi)
getByName("api").extendsFrom(shadedApi)
val shadedImplementation = create("shadedImplementation")
shaded.extendsFrom(shadedImplementation)
getByName("implementation").extendsFrom(shadedImplementation)
}
repositories {
maven { url = uri("http://maven.enginehub.org/repo/") }
maven { url = uri("https://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/") }
@@ -19,6 +33,6 @@ fun Project.configureDependencies() {
dependencies {
"testImplementation"("org.junit.jupiter:junit-jupiter-api:5.7.0")
"testImplementation"("org.junit.jupiter:junit-jupiter-engine:5.7.0")
"compileOnly"("org.jetbrains:annotations:20.1.0")
"api"("org.jetbrains:annotations:20.1.0")
}
}
@@ -14,17 +14,6 @@ fun Project.configureDistribution() {
apply(plugin = "java-library")
apply(plugin = "com.github.johnrengelman.shadow")
configurations {
val shaded = create("shaded")
getByName("compile").extendsFrom(shaded)
val shadedApi = create("shadedApi")
shaded.extendsFrom(shadedApi)
getByName("api").extendsFrom(shadedApi)
val shadedImplementation = create("shadedImplementation")
shaded.extendsFrom(shadedImplementation)
getByName("implementation").extendsFrom(shadedImplementation)
}
val downloadDefaultPacks = tasks.create("downloadDefaultPacks") {
group = "terra"
doFirst {
@@ -38,21 +27,6 @@ fun Project.configureDistribution() {
}
tasks["processResources"].dependsOn(downloadDefaultPacks)
tasks.withType<Jar> {
archiveBaseName.set("Terra-${archiveBaseName.get()}")
from("../LICENSE", "../../LICENSE")
}
tasks.register<Jar>("sourcesJar") {
archiveClassifier.set("sources")
}
tasks.register<Jar>("javadocJar") {
dependsOn("javadoc")
archiveClassifier.set("javadoc")
from(tasks.getByName<Javadoc>("javadoc").destinationDir)
}
tasks.named<ShadowJar>("shadowJar") {
// Tell shadow to download the packs
dependsOn(downloadDefaultPacks)
+5 -2
View File
@@ -1,11 +1,14 @@
import com.dfsek.terra.configureCommon
import com.dfsek.terra.configureCompilation
import com.dfsek.terra.configureDependencies
plugins {
`java-library`
`maven-publish`
idea
}
configureCommon()
configureCompilation()
configureDependencies()
group = "com.dfsek.terra.common"
@@ -7,6 +7,8 @@ import com.dfsek.terra.api.platform.handle.WorldHandle;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.api.registry.CheckedRegistry;
import com.dfsek.terra.api.registry.LockedRegistry;
import com.dfsek.terra.api.task.TaskScheduler;
import com.dfsek.terra.api.util.JarUtil;
import com.dfsek.terra.api.util.logging.DebugLogger;
import com.dfsek.terra.api.util.logging.Logger;
import com.dfsek.terra.config.PluginConfig;
@@ -16,6 +18,9 @@ import com.dfsek.terra.profiler.Profiler;
import com.dfsek.terra.world.TerraWorld;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.jar.JarFile;
/**
* Represents a Terra mod/plugin instance.
@@ -67,4 +72,10 @@ public interface TerraPlugin extends LoaderRegistrar {
}
Profiler getProfiler();
default JarFile getModJar() throws URISyntaxException, IOException {
return JarUtil.getJarFile();
}
TaskScheduler getScheduler();
}
@@ -65,7 +65,7 @@ public class TerraCommandManager implements CommandManager {
return;
}
if(commandClass.isAnnotationPresent(WorldCommand.class) && (!(sender instanceof Player) || !TerraWorld.isTerraWorld(((Player) sender).getWorld()))) {
if(commandClass.isAnnotationPresent(WorldCommand.class) && (!(sender instanceof Player) || !(((Player) sender).getWorld()).isTerraWorld())) {
sender.sendMessage("Command must be executed in a Terra world.");
return;
}
@@ -1,6 +1,7 @@
package com.dfsek.terra.api.platform.inventory;
import com.dfsek.terra.api.platform.Handle;
import com.dfsek.terra.api.platform.inventory.item.Damageable;
import com.dfsek.terra.api.platform.inventory.item.ItemMeta;
public interface ItemStack extends Handle {
@@ -13,4 +14,8 @@ public interface ItemStack extends Handle {
ItemMeta getItemMeta();
void setItemMeta(ItemMeta meta);
default boolean isDamageable() {
return getItemMeta() instanceof Damageable;
}
}
@@ -6,6 +6,8 @@ import com.dfsek.terra.api.platform.block.Block;
import com.dfsek.terra.api.platform.entity.Entity;
import com.dfsek.terra.api.platform.entity.EntityType;
import com.dfsek.terra.api.platform.world.generator.ChunkGenerator;
import com.dfsek.terra.api.platform.world.generator.GeneratorWrapper;
import com.dfsek.terra.api.world.generation.TerraChunkGenerator;
import java.io.File;
import java.util.UUID;
@@ -17,20 +19,12 @@ public interface World extends Handle {
ChunkGenerator getGenerator();
String getName();
UUID getUID();
boolean isChunkGenerated(int x, int z);
Chunk getChunkAt(int x, int z);
default Chunk getChunkAt(Location location) {
return getChunkAt(location.getBlockX() >> 4, location.getBlockZ() >> 4);
}
File getWorldFolder();
Block getBlockAt(int x, int y, int z);
default Block getBlockAt(Location l) {
@@ -40,4 +34,12 @@ public interface World extends Handle {
Entity spawnEntity(Location location, EntityType entityType);
int getMinHeight();
default boolean isTerraWorld() {
return getGenerator().getHandle() instanceof GeneratorWrapper;
}
default TerraChunkGenerator getTerraGenerator() {
return ((GeneratorWrapper) getGenerator().getHandle()).getHandle();
}
}
@@ -6,7 +6,6 @@ import com.dfsek.terra.registry.OpenRegistry;
import com.dfsek.terra.registry.exception.DuplicateEntryException;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
@@ -69,7 +68,7 @@ public class CheckedRegistry<T> implements Registry<T> {
}
@Override
public Collection<T> entries() {
public Set<T> entries() {
return registry.entries();
}
@@ -4,7 +4,6 @@ import com.dfsek.tectonic.exception.LoadException;
import com.dfsek.tectonic.loading.ConfigLoader;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
@@ -42,7 +41,7 @@ public class LockedRegistry<T> implements Registry<T> {
}
@Override
public Collection<T> entries() {
public Set<T> entries() {
return registry.entries();
}
@@ -2,7 +2,6 @@ package com.dfsek.terra.api.registry;
import com.dfsek.tectonic.loading.TypeLoader;
import java.util.Collection;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
@@ -43,7 +42,7 @@ public interface Registry<T> extends TypeLoader<T> {
*
* @return Set containing all entries.
*/
Collection<T> entries();
Set<T> entries();
/**
* Get all the keys in this registry.
@@ -34,8 +34,8 @@ public class DamageFunction implements LootFunction {
@Override
public ItemStack apply(ItemStack original, Random r) {
if(original == null) return null;
if(!original.isDamageable()) return original;
ItemMeta meta = original.getItemMeta();
if(!(meta instanceof Damageable)) return original;
double itemDurability = (r.nextDouble() * (max - min)) + min;
Damageable damage = (Damageable) meta;
damage.setDamage((int) (original.getType().getMaxDurability() - (itemDurability / 100) * original.getType().getMaxDurability()));
@@ -3,13 +3,10 @@ package com.dfsek.terra.api.structures.script;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.platform.world.Chunk;
import com.dfsek.terra.api.registry.Registry;
import com.dfsek.terra.api.structures.loot.LootTable;
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.parser.lang.functions.FunctionBuilder;
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;
@@ -33,6 +30,9 @@ 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.profiler.ProfileFrame;
import com.dfsek.terra.registry.config.FunctionRegistry;
import com.dfsek.terra.registry.config.LootRegistry;
import com.dfsek.terra.registry.config.ScriptRegistry;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import net.jafama.FastMath;
@@ -51,7 +51,7 @@ public class StructureScript {
private final TerraPlugin main;
private String tempID;
public StructureScript(InputStream inputStream, TerraPlugin main, Registry<StructureScript> registry, Registry<LootTable> lootRegistry, Registry<FunctionBuilder<?>> functionRegistry) throws ParseException {
public StructureScript(InputStream inputStream, TerraPlugin main, ScriptRegistry registry, LootRegistry lootRegistry, FunctionRegistry functionRegistry) throws ParseException {
Parser parser;
try {
parser = new Parser(IOUtils.toString(inputStream, Charset.defaultCharset()));
@@ -89,6 +89,12 @@ public class StructureScript {
.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("sin", new UnaryNumberFunctionBuilder(number -> FastMath.sin(number.doubleValue())))
.registerFunction("cos", new UnaryNumberFunctionBuilder(number -> FastMath.cos(number.doubleValue())))
.registerFunction("tan", new UnaryNumberFunctionBuilder(number -> FastMath.tan(number.doubleValue())))
.registerFunction("asin", new UnaryNumberFunctionBuilder(number -> FastMath.asin(number.doubleValue())))
.registerFunction("acos", new UnaryNumberFunctionBuilder(number -> FastMath.acos(number.doubleValue())))
.registerFunction("atan", new UnaryNumberFunctionBuilder(number -> FastMath.atan(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())));
@@ -1,22 +1,21 @@
package com.dfsek.terra.api.structures.script.builders;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.registry.Registry;
import com.dfsek.terra.api.structures.loot.LootTable;
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.StructureScript;
import com.dfsek.terra.api.structures.script.functions.LootFunction;
import com.dfsek.terra.api.structures.tokenizer.Position;
import com.dfsek.terra.registry.config.LootRegistry;
import java.util.List;
public class LootFunctionBuilder implements FunctionBuilder<LootFunction> {
private final TerraPlugin main;
private final Registry<LootTable> registry;
private final LootRegistry registry;
private final StructureScript script;
public LootFunctionBuilder(TerraPlugin main, Registry<LootTable> registry, StructureScript script) {
public LootFunctionBuilder(TerraPlugin main, LootRegistry registry, StructureScript script) {
this.main = main;
this.registry = registry;
this.script = script;
@@ -1,22 +1,21 @@
package com.dfsek.terra.api.structures.script.builders;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.registry.Registry;
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.StructureScript;
import com.dfsek.terra.api.structures.script.functions.StructureFunction;
import com.dfsek.terra.api.structures.tokenizer.Position;
import com.dfsek.terra.registry.config.ScriptRegistry;
import java.util.List;
import java.util.stream.Collectors;
public class StructureFunctionBuilder implements FunctionBuilder<StructureFunction> {
private final Registry<StructureScript> registry;
private final ScriptRegistry registry;
private final TerraPlugin main;
public StructureFunctionBuilder(Registry<StructureScript> registry, TerraPlugin main) {
public StructureFunctionBuilder(ScriptRegistry registry, TerraPlugin main) {
this.registry = registry;
this.main = main;
}
@@ -3,7 +3,6 @@ package com.dfsek.terra.api.structures.script.functions;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.math.vector.Vector2;
import com.dfsek.terra.api.math.vector.Vector3;
import com.dfsek.terra.api.registry.Registry;
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;
@@ -14,19 +13,20 @@ 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.config.LootRegistry;
import net.jafama.FastMath;
import java.util.Map;
public class LootFunction implements Function<Void> {
private final Registry<LootTable> registry;
private final LootRegistry registry;
private final Returnable<String> data;
private final Returnable<Number> x, y, z;
private final Position position;
private final TerraPlugin main;
private final StructureScript script;
public LootFunction(Registry<LootTable> registry, Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, Returnable<String> data, TerraPlugin main, Position position, StructureScript script) {
public LootFunction(LootRegistry registry, Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, Returnable<String> data, TerraPlugin main, Position position, StructureScript script) {
this.registry = registry;
this.position = position;
this.data = data;
@@ -3,7 +3,6 @@ package com.dfsek.terra.api.structures.script.functions;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.math.vector.Vector2;
import com.dfsek.terra.api.math.vector.Vector3;
import com.dfsek.terra.api.registry.Registry;
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;
@@ -14,20 +13,21 @@ 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.config.ScriptRegistry;
import net.jafama.FastMath;
import java.util.List;
import java.util.Map;
public class StructureFunction implements Function<Boolean> {
private final Registry<StructureScript> registry;
private final ScriptRegistry registry;
private final Returnable<String> id;
private final Returnable<Number> x, y, z;
private final Position position;
private final TerraPlugin main;
private final List<Returnable<String>> rotations;
public StructureFunction(Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, Returnable<String> id, List<Returnable<String>> rotations, Registry<StructureScript> registry, Position position, TerraPlugin main) {
public StructureFunction(Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, Returnable<String> id, List<Returnable<String>> rotations, ScriptRegistry registry, Position position, TerraPlugin main) {
this.registry = registry;
this.id = id;
this.position = position;
@@ -19,6 +19,6 @@ public class BufferedEntity implements BufferedItem {
@Override
public void paste(Location origin) {
Entity entity = origin.clone().add(0.5, 0, 0.5).getWorld().spawnEntity(origin, type);
main.getEventManager().callEvent(new EntitySpawnEvent(main.getWorld(entity.getWorld()).getGenerator().getConfigPack(), entity, entity.getLocation()));
main.getEventManager().callEvent(new EntitySpawnEvent(entity.getWorld().getTerraGenerator().getConfigPack(), entity, entity.getLocation()));
}
}
@@ -32,7 +32,7 @@ public class BufferedLootApplication implements BufferedItem {
}
Container container = (Container) data;
LootPopulateEvent event = new LootPopulateEvent(block, container, table, main.getWorld(block.getLocation().getWorld()).getGenerator().getConfigPack(), structure);
LootPopulateEvent event = new LootPopulateEvent(block, container, table, block.getLocation().getWorld().getTerraGenerator().getConfigPack(), structure);
main.getEventManager().callEvent(event);
if(event.isCancelled()) return;
@@ -40,7 +40,7 @@ public class BufferedLootApplication implements BufferedItem {
data.update(false);
} catch(Exception e) {
main.logger().warning("Could not apply loot at " + origin + ": " + e.getMessage());
main.getDebugLogger().stack(e);
e.printStackTrace();
}
}
}
@@ -21,7 +21,7 @@ public class BufferedStateManipulator implements BufferedItem {
state.update(false);
} catch(Exception e) {
main.logger().warning("Could not apply BlockState at " + origin + ": " + e.getMessage());
main.getDebugLogger().stack(e);
e.printStackTrace();
}
}
}
@@ -15,7 +15,6 @@ public class Tokenizer {
private final Lookahead reader;
private final Stack<Token> brackets = new Stack<>();
private Token current;
private Token last;
public Tokenizer(String data) throws ParseException {
reader = new Lookahead(new StringReader(data + '\0'));
@@ -29,7 +28,7 @@ public class Tokenizer {
* @throws ParseException If token does not exist
*/
public Token get() throws ParseException {
if(!hasNext()) throw new ParseException("Unexpected end of input", last.getPosition());
if(!hasNext()) throw new ParseException("Unexpected end of input", current.getPosition());
return current;
}
@@ -40,7 +39,7 @@ public class Tokenizer {
* @throws ParseException If token does not exist
*/
public Token consume() throws ParseException {
if(!hasNext()) throw new ParseException("Unexpected end of input", last.getPosition());
if(!hasNext()) throw new ParseException("Unexpected end of input", current.getPosition());
Token temp = current;
current = fetchCheck();
return temp;
@@ -58,9 +57,8 @@ public class Tokenizer {
private Token fetchCheck() throws ParseException {
Token fetch = fetch();
if(fetch != null) {
last = fetch;
if(fetch.getType() == Token.Type.BLOCK_BEGIN) brackets.push(fetch); // Opening bracket
else if(fetch.getType() == Token.Type.BLOCK_END) {
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));
}
@@ -0,0 +1,35 @@
package com.dfsek.terra.api.task;
public interface TaskScheduler {
/**
* Run a task synchronously on the next tick.
* Functionally equivalent to {@link #runTask(Runnable, long)}
* @param task Task to run.
*/
default void runTask(Runnable task) {
runTask(task, 0);
}
/**
* Schedule a task asynchronously immediately.
* Functionally equivalent to {@link #runTaskAsynchronously(Runnable)} (Runnable, long)}
* @param task Task to run.
*/
default void runTaskAsynchronously(Runnable task) {
runTaskAsynchronously(task, 0);
}
/**
* Run a task asynchronously after a number of ticks.
* @param task Task to run.
* @param ticks Delay before running the task, in ticks.
*/
void runTaskAsynchronously(Runnable task, long ticks);
/**
* Run a task synchronously after a number of ticks.
* @param task Task to run.
* @param ticks Delay before running the task, in ticks.
*/
void runTask(Runnable task, long ticks);
}
@@ -1,9 +1,13 @@
package com.dfsek.terra.api.util;
import com.dfsek.terra.api.TerraPlugin;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
@@ -32,4 +36,12 @@ public class JarUtil {
}
}
}
public static JarFile getJarFile() throws URISyntaxException, IOException {
return new JarFile(new File(getJarURL().toURI()));
}
public static URL getJarURL() {
return TerraPlugin.class.getProtectionDomain().getCodeSource().getLocation();
}
}
@@ -49,4 +49,21 @@ public final class Either<L, R> {
public boolean hasRight() {
return !leftPresent;
}
@Override
public int hashCode() {
if(hasLeft()) return left.hashCode();
return right.hashCode();
}
@Override
public boolean equals(Object o) {
if(!(o instanceof Either<?, ?>)) return false;
Either<?, ?> that = (Either<?, ?>) o;
if(hasLeft() && that.hasLeft()) return left.equals(that.left);
if(hasRight() && that.hasRight()) return right.equals(that.right);
return false;
}
}
@@ -1,12 +1,12 @@
package com.dfsek.terra.api.util.generic.pair;
public final class ImmutablePair<L, R> {
import java.util.Objects;
public class ImmutablePair<L, R> {
private final L left;
private final R right;
private static final ImmutablePair<?, ?> NULL = new ImmutablePair<>(null, null);
private ImmutablePair(L left, R right) {
public ImmutablePair(L left, R right) {
this.left = left;
this.right = right;
}
@@ -23,12 +23,18 @@ public final class ImmutablePair<L, R> {
return left;
}
@SuppressWarnings("unchecked")
public static <L1, R1> ImmutablePair<L1, R1> ofNull() {
return (ImmutablePair<L1, R1>) NULL;
public Pair<L, R> mutable() {
return new Pair<>(left, right);
}
@Override
public int hashCode() {
return Objects.hash(left, right);
}
public Pair<L, R> mutable() {
return Pair.of(left, right);
@Override
public boolean equals(Object o) {
if(!(o instanceof ImmutablePair)) return false;
ImmutablePair<?, ?> that = (ImmutablePair<?, ?>) o;
return that.left.equals(left) && that.right.equals(right);
}
}
@@ -1,10 +1,12 @@
package com.dfsek.terra.api.util.generic.pair;
import java.util.Objects;
public class Pair<L, R> {
private L left;
private R right;
private Pair(L left, R right) {
public Pair(L left, R right) {
this.left = left;
this.right = right;
}
@@ -30,6 +32,18 @@ public class Pair<L, R> {
}
public ImmutablePair<L, R> immutable() {
return ImmutablePair.of(left, right);
return new ImmutablePair<>(left, right);
}
@Override
public int hashCode() {
return Objects.hash(left, right);
}
@Override
public boolean equals(Object o) {
if(!(o instanceof Pair)) return false;
Pair<?, ?> that = (Pair<?, ?>) o;
return that.left.equals(left) && that.right.equals(right);
}
}
@@ -1,9 +0,0 @@
package com.dfsek.terra.api.util.seeded;
import com.dfsek.tectonic.loading.object.ObjectTemplate;
import java.util.function.Supplier;
@FunctionalInterface
public interface NoiseProvider extends Supplier<ObjectTemplate<NoiseSeeded>> {
}
@@ -1,13 +1,14 @@
package com.dfsek.terra.api.util.world;
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.api.world.palette.holder.PaletteHolder;
import com.dfsek.terra.config.templates.BiomeTemplate;
import com.dfsek.terra.world.generation.math.samplers.Sampler;
public final class PaletteUtil {
public static Palette getPalette(int x, int y, int z, BiomeTemplate c, Sampler sampler) {
public static Palette<BlockData> 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);
@@ -1,10 +1,8 @@
package com.dfsek.terra.api.world.biome;
import com.dfsek.terra.api.math.noise.NoiseSampler;
import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.world.palette.Palette;
import com.dfsek.terra.world.generation.math.samplers.terrain.TerrainSampler;
import java.util.List;
public interface Generator {
/**
@@ -37,13 +35,11 @@ public interface Generator {
*
* @return BlocPalette - The biome's palette.
*/
Palette getPalette(int y);
Palette<BlockData> getPalette(int y);
NoiseSampler getBiomeNoise();
double getElevationWeight();
int getBlendStep();
List<TerrainSampler> getTerrainSamplers();
}
@@ -1,11 +1,10 @@
package com.dfsek.terra.api.world.palette;
import com.dfsek.terra.api.math.noise.NoiseSampler;
import com.dfsek.terra.api.platform.block.BlockData;
import java.util.List;
public class NoisePalette extends Palette {
public class NoisePalette<E> extends Palette<E> {
private final NoiseSampler sampler;
private final boolean is2D;
@@ -15,11 +14,11 @@ public class NoisePalette extends Palette {
}
@Override
public BlockData get(int layer, double x, double y, double z) {
PaletteLayer paletteLayer;
public E get(int layer, double x, double y, double z) {
PaletteLayer<E> paletteLayer;
if(layer > this.getSize()) paletteLayer = this.getLayers().get(this.getLayers().size() - 1);
else {
List<PaletteLayer> pl = getLayers();
List<PaletteLayer<E>> pl = getLayers();
if(layer >= pl.size()) paletteLayer = pl.get(pl.size() - 1);
else paletteLayer = pl.get(layer);
}
@@ -1,7 +1,6 @@
package com.dfsek.terra.api.world.palette;
import com.dfsek.terra.api.math.noise.NoiseSampler;
import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.util.GlueList;
import com.dfsek.terra.api.util.collections.ProbabilityCollection;
@@ -12,8 +11,8 @@ 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<PaletteLayer> pallet = new GlueList<>();
public abstract class Palette<E> {
private final List<PaletteLayer<E>> pallet = new GlueList<>();
/**
* Constructs a blank palette.
@@ -22,16 +21,16 @@ public abstract class Palette {
}
public com.dfsek.terra.api.world.palette.Palette add(BlockData m, int layers, NoiseSampler sampler) {
public com.dfsek.terra.api.world.palette.Palette<E> add(E m, int layers, NoiseSampler sampler) {
for(int i = 0; i < layers; i++) {
pallet.add(new PaletteLayer(m, sampler));
pallet.add(new PaletteLayer<>(m, sampler));
}
return this;
}
public com.dfsek.terra.api.world.palette.Palette add(ProbabilityCollection<BlockData> m, int layers, NoiseSampler sampler) {
public com.dfsek.terra.api.world.palette.Palette<E> add(ProbabilityCollection<E> m, int layers, NoiseSampler sampler) {
for(int i = 0; i < layers; i++) {
pallet.add(new PaletteLayer(m, sampler));
pallet.add(new PaletteLayer<>(m, sampler));
}
return this;
}
@@ -42,25 +41,25 @@ public abstract class Palette {
* @param layer - The layer at which to fetch the material.
* @return BlockData - The material fetched.
*/
public abstract BlockData get(int layer, double x, double y, double z);
public abstract E get(int layer, double x, double y, double z);
public int getSize() {
return pallet.size();
}
public List<PaletteLayer> getLayers() {
public List<PaletteLayer<E>> getLayers() {
return pallet;
}
/**
* Class representation of a layer of a BlockPalette.
*/
public static class PaletteLayer {
public static class PaletteLayer<E> {
private final boolean col; // Is layer using a collection?
private ProbabilityCollection<BlockData> collection;
private ProbabilityCollection<E> collection;
private final NoiseSampler sampler;
private BlockData m;
private E m;
/**
* Constructs a PaletteLayerHolder with a ProbabilityCollection of materials and a number of layers.
@@ -68,7 +67,7 @@ public abstract class Palette {
* @param type The collection of materials to choose from.
* @param sampler Noise sampler to use
*/
public PaletteLayer(ProbabilityCollection<BlockData> type, NoiseSampler sampler) {
public PaletteLayer(ProbabilityCollection<E> type, NoiseSampler sampler) {
this.sampler = sampler;
this.col = true;
this.collection = type;
@@ -80,7 +79,7 @@ public abstract class Palette {
* @param type The material to use.
* @param sampler Noise sampler to use
*/
public PaletteLayer(BlockData type, NoiseSampler sampler) {
public PaletteLayer(E type, NoiseSampler sampler) {
this.sampler = sampler;
this.col = false;
this.m = type;
@@ -95,18 +94,18 @@ public abstract class Palette {
*
* @return Material - the material..
*/
public BlockData get(Random random) {
public E get(Random random) {
if(col) return this.collection.get(random);
return m;
}
public BlockData get(NoiseSampler random, double x, double y, double z, boolean is2D) {
public E get(NoiseSampler random, double x, double y, double z, boolean is2D) {
if(col && is2D) return this.collection.get(random, x, z);
else if(col) return this.collection.get(random, x, y, z);
return m;
}
public ProbabilityCollection<BlockData> getCollection() {
public ProbabilityCollection<E> getCollection() {
return collection;
}
}
@@ -1,16 +1,14 @@
package com.dfsek.terra.api.world.palette;
import com.dfsek.terra.api.platform.block.BlockData;
public class SinglePalette<E> extends Palette<E> {
private final E item;
public class SinglePalette extends Palette {
private final BlockData item;
public SinglePalette(BlockData item) {
public SinglePalette(E item) {
this.item = item;
}
@Override
public BlockData get(int layer, double x, double y, double z) {
public E get(int layer, double x, double y, double z) {
return item;
}
}
@@ -1,15 +1,16 @@
package com.dfsek.terra.api.world.palette.holder;
import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.world.palette.Palette;
public class PaletteHolder {
private final Palette[] palettes;
private final Palette<BlockData>[] palettes;
protected PaletteHolder(Palette[] palettes) {
protected PaletteHolder(Palette<BlockData>[] palettes) {
this.palettes = palettes;
}
public Palette getPalette(int y) {
public Palette<BlockData> getPalette(int y) {
return palettes[y];
}
}
@@ -1,5 +1,6 @@
package com.dfsek.terra.api.world.palette.holder;
import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.world.palette.Palette;
import net.jafama.FastMath;
@@ -7,19 +8,19 @@ import java.util.Map;
import java.util.TreeMap;
public class PaletteHolderBuilder {
private final TreeMap<Integer, Palette> paletteMap = new TreeMap<>();
private final TreeMap<Integer, Palette<BlockData>> paletteMap = new TreeMap<>();
public PaletteHolderBuilder add(int y, Palette palette) {
public PaletteHolderBuilder add(int y, Palette<BlockData> palette) {
paletteMap.put(y, palette);
return this;
}
@SuppressWarnings({"unchecked", "rawtypes", "RedundantSuppression"})
public PaletteHolder build() {
Palette[] palettes = new Palette[paletteMap.lastKey() + 1];
Palette<BlockData>[] palettes = new Palette[paletteMap.lastKey() + 1];
for(int y = 0; y <= FastMath.max(paletteMap.lastKey(), 255); y++) {
Palette d = null;
for(Map.Entry<Integer, Palette> e : paletteMap.entrySet()) {
Palette<BlockData> d = null;
for(Map.Entry<Integer, Palette<BlockData>> e : paletteMap.entrySet()) {
if(e.getKey() >= y) {
d = e.getValue();
break;
@@ -14,6 +14,6 @@ public class BiomeArgumentParser implements ArgumentParser<TerraBiome> {
@Override
public TerraBiome parse(CommandSender sender, String arg) {
Player player = (Player) sender;
return main.getWorld(player.getWorld()).getConfig().getRegistry(TerraBiome.class).get(arg);
return main.getWorld(player.getWorld()).getConfig().getBiomeRegistry().get(arg);
}
}
@@ -17,6 +17,6 @@ public class BiomeTabCompleter implements TabCompleter {
@Override
public List<String> complete(CommandSender sender) {
Player player = (Player) sender;
return main.getWorld(player.getWorld()).getConfig().getRegistry(TerraBiome.class).entries().stream().map(TerraBiome::getID).collect(Collectors.toList());
return main.getWorld(player.getWorld()).getConfig().getBiomeRegistry().entries().stream().map(TerraBiome::getID).collect(Collectors.toList());
}
}
@@ -13,6 +13,6 @@ public class ScriptArgumentParser implements ArgumentParser<StructureScript> {
@Override
public StructureScript parse(CommandSender sender, String arg) {
return main.getWorld(((Player) sender).getWorld()).getConfig().getRegistry(StructureScript.class).get(arg);
return main.getWorld(((Player) sender).getWorld()).getConfig().getScriptRegistry().get(arg);
}
}
@@ -13,6 +13,6 @@ public class StructureArgumentParser implements ArgumentParser<TerraStructure> {
@Override
public TerraStructure parse(CommandSender sender, String arg) {
return main.getWorld(((Player) sender).getWorld()).getConfig().getRegistry(TerraStructure.class).get(arg);
return main.getWorld(((Player) sender).getWorld()).getConfig().getStructureRegistry().get(arg);
}
}
@@ -16,6 +16,6 @@ public class ScriptCompleter implements TabCompleter {
@Override
public List<String> complete(CommandSender sender) {
return main.getWorld(((Player) sender).getWorld()).getConfig().getRegistry(StructureScript.class).entries().stream().map(StructureScript::getId).collect(Collectors.toList());
return main.getWorld(((Player) sender).getWorld()).getConfig().getScriptRegistry().entries().stream().map(StructureScript::getId).collect(Collectors.toList());
}
}
@@ -5,7 +5,6 @@ import com.dfsek.terra.api.command.tab.TabCompleter;
import com.dfsek.terra.api.injection.annotations.Inject;
import com.dfsek.terra.api.platform.CommandSender;
import com.dfsek.terra.api.platform.entity.Player;
import com.dfsek.terra.world.population.items.TerraStructure;
import java.util.ArrayList;
import java.util.List;
@@ -17,6 +16,6 @@ public class StructureCompleter implements TabCompleter {
@Override
public List<String> complete(CommandSender sender) {
Player player = (Player) sender;
return new ArrayList<>(main.getWorld(player.getWorld()).getConfig().getRegistry(TerraStructure.class).keys());
return new ArrayList<>(main.getWorld(player.getWorld()).getConfig().getStructureRegistry().keys());
}
}
@@ -69,12 +69,12 @@ public class PluginConfig implements ConfigTemplate {
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(TerraPlugin.class.getProtectionDomain().getCodeSource().getLocation().toURI()))) {
try(JarFile jar = main.getModJar()) {
JarUtil.copyResourcesToDirectory(jar, "packs", new File(main.getDataFolder(), "packs").toString());
} catch(IOException | URISyntaxException e) {
main.getDebugLogger().error("Failed to dump default config files!");
e.printStackTrace();
main.getDebugLogger().error("Report this to Terra!");
main.getDebugLogger().error("Either you're on Forge, or this is a bug. If it's the latter, report this to Terra!");
}
}
} catch(ConfigException | IOException e) {
@@ -9,9 +9,6 @@ import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.api.platform.world.generator.ChunkGenerator;
import com.dfsek.terra.api.platform.world.generator.GeneratorWrapper;
import java.io.File;
import java.util.UUID;
public class DummyWorld implements World {
@Override
public Object getHandle() {
@@ -33,31 +30,11 @@ public class DummyWorld implements World {
return () -> (GeneratorWrapper) () -> null;
}
@Override
public String getName() {
return "DUMMY";
}
@Override
public UUID getUID() {
return UUID.randomUUID();
}
@Override
public boolean isChunkGenerated(int x, int z) {
return false;
}
@Override
public Chunk getChunkAt(int x, int z) {
throw new UnsupportedOperationException("Cannot get chunk in DummyWorld");
}
@Override
public File getWorldFolder() {
throw new UnsupportedOperationException("Cannot get folder of DummyWorld");
}
@Override
public Block getBlockAt(int x, int y, int z) {
throw new UnsupportedOperationException("Cannot get block in DummyWorld");
@@ -2,6 +2,7 @@ package com.dfsek.terra.config.factories;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.math.noise.samplers.noise.random.WhiteNoiseSampler;
import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.world.flora.Flora;
import com.dfsek.terra.api.world.palette.NoisePalette;
import com.dfsek.terra.api.world.palette.Palette;
@@ -12,7 +13,7 @@ import com.dfsek.terra.world.population.items.flora.TerraFlora;
public class FloraFactory implements ConfigFactory<FloraTemplate, Flora> {
@Override
public TerraFlora build(FloraTemplate config, TerraPlugin main) {
Palette palette = new NoisePalette(new WhiteNoiseSampler(2403), false);
Palette<BlockData> palette = new NoisePalette<>(new WhiteNoiseSampler(2403), false);
for(PaletteLayerHolder layer : config.getFloraPalette()) {
palette.add(layer.getLayer(), layer.getSize(), layer.getSampler());
}
@@ -1,15 +1,16 @@
package com.dfsek.terra.config.factories;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.world.palette.NoisePalette;
import com.dfsek.terra.api.world.palette.Palette;
import com.dfsek.terra.api.world.palette.holder.PaletteLayerHolder;
import com.dfsek.terra.config.templates.PaletteTemplate;
public class PaletteFactory implements ConfigFactory<PaletteTemplate, Palette> {
public class PaletteFactory implements ConfigFactory<PaletteTemplate, Palette<BlockData>> {
@Override
public Palette build(PaletteTemplate config, TerraPlugin main) {
NoisePalette palette = new NoisePalette(config.getNoise().apply(2403L), config.getNoise().getDimensions() == 2);
public Palette<BlockData> build(PaletteTemplate config, TerraPlugin main) {
NoisePalette<BlockData> palette = new NoisePalette<>(config.getNoise().apply(2403L), config.getNoise().getDimensions() == 2);
for(PaletteLayerHolder layer : config.getPalette()) {
palette.add(layer.getLayer(), layer.getSize(), layer.getSampler());
}
@@ -1,5 +1,6 @@
package com.dfsek.terra.config.fileloaders;
import com.dfsek.tectonic.config.Configuration;
import com.dfsek.tectonic.exception.ConfigException;
import com.dfsek.terra.api.util.GlueList;
@@ -18,8 +19,12 @@ public abstract class Loader {
*
* @param consumer Something to do with the streams.
*/
public Loader then(ExceptionalConsumer<List<InputStream>> consumer) throws ConfigException {
consumer.accept(new GlueList<>(streams.values()));
public Loader then(ExceptionalConsumer<List<Configuration>> consumer) throws ConfigException {
List<Configuration> list = new GlueList<>();
streams.forEach((id, stream) -> {
list.add(new Configuration(stream, id));
});
consumer.accept(list);
return this;
}
@@ -30,7 +30,7 @@ public class ZIPLoader extends Loader {
ZipEntry entry = entries.nextElement();
if(!entry.isDirectory() && entry.getName().startsWith(directory) && entry.getName().endsWith(extension)) {
try {
String rel = entry.getName().substring(directory.length());
String rel = entry.getName().substring(directory.length() + 1);
streams.put(rel, file.getInputStream(entry));
} catch(IOException e) {
e.printStackTrace();
@@ -17,7 +17,7 @@ public final class LangUtil {
public static void load(String langID, TerraPlugin main) {
Logger logger = main.logger();
File file = new File(main.getDataFolder(), "lang");
try(JarFile jar = new JarFile(new File(TerraPlugin.class.getProtectionDomain().getCodeSource().getLocation().toURI()))) {
try(JarFile jar = main.getModJar()) {
copyResourcesToDirectory(jar, "lang", file.toString());
} catch(IOException | URISyntaxException e) {
main.getDebugLogger().error("Failed to dump language files!");
@@ -5,6 +5,7 @@ import com.dfsek.terra.api.platform.world.Tree;
import com.dfsek.terra.api.util.collections.ProbabilityCollection;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.flora.Flora;
import com.dfsek.terra.api.world.palette.Palette;
import java.lang.reflect.Type;
import java.util.Map;
@@ -14,6 +15,7 @@ import java.util.Map;
*/
@SuppressWarnings("unused")
public final class Types {
public static final Type BLOCK_DATA_PALETTE_TYPE;
public static final Type BLOCK_DATA_PROBABILITY_COLLECTION_TYPE;
public static final Type FLORA_PROBABILITY_COLLECTION_TYPE;
public static final Type TREE_PROBABILITY_COLLECTION_TYPE;
@@ -21,6 +23,7 @@ public final class Types {
public static final Type TERRA_BIOME_TERRA_BIOME_PROBABILITY_COLLECTION_MAP;
static {
BLOCK_DATA_PALETTE_TYPE = getType("blockDataPalette");
BLOCK_DATA_PROBABILITY_COLLECTION_TYPE = getType("blockDataProbabilityCollection");
FLORA_PROBABILITY_COLLECTION_TYPE = getType("floraProbabilityCollection");
TREE_PROBABILITY_COLLECTION_TYPE = getType("treeProbabilityCollection");
@@ -28,6 +31,7 @@ public final class Types {
TERRA_BIOME_TERRA_BIOME_PROBABILITY_COLLECTION_MAP = getType("terraBiomeProbabilityCollectionMap");
}
private Palette<BlockData> blockDataPalette;
private ProbabilityCollection<BlockData> blockDataProbabilityCollection;
private ProbabilityCollection<Flora> floraProbabilityCollection;
private ProbabilityCollection<Tree> treeProbabilityCollection;
@@ -6,9 +6,8 @@ import com.dfsek.tectonic.exception.LoadException;
import com.dfsek.tectonic.loading.ConfigLoader;
import com.dfsek.tectonic.loading.TypeLoader;
import com.dfsek.tectonic.loading.object.ObjectTemplate;
import com.dfsek.terra.api.registry.Registry;
import com.dfsek.terra.api.util.seeded.NoiseProvider;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.registry.config.NoiseRegistry;
import java.lang.reflect.Type;
import java.util.Locale;
@@ -16,9 +15,9 @@ import java.util.Map;
@SuppressWarnings("unchecked")
public class NoiseSamplerBuilderLoader implements TypeLoader<NoiseSeeded> {
private final Registry<NoiseProvider> noiseRegistry;
private final NoiseRegistry noiseRegistry;
public NoiseSamplerBuilderLoader(Registry<NoiseProvider> noiseRegistry) {
public NoiseSamplerBuilderLoader(NoiseRegistry noiseRegistry) {
this.noiseRegistry = noiseRegistry;
}
@@ -3,9 +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.api.world.palette.holder.PaletteHolder;
import com.dfsek.terra.api.world.palette.holder.PaletteHolderBuilder;
import com.dfsek.terra.config.loaders.Types;
import java.lang.reflect.Type;
import java.util.List;
@@ -19,7 +21,7 @@ public class PaletteHolderLoader implements TypeLoader<PaletteHolder> {
PaletteHolderBuilder builder = new PaletteHolderBuilder();
for(Map<String, Integer> layer : palette) {
for(Map.Entry<String, Integer> entry : layer.entrySet()) {
builder.add(entry.getValue(), (Palette) configLoader.loadType(Palette.class, entry.getKey()));
builder.add(entry.getValue(), (Palette<BlockData>) configLoader.loadType(Types.BLOCK_DATA_PALETTE_TYPE, entry.getKey()));
}
}
return builder.build();
@@ -2,27 +2,36 @@ package com.dfsek.terra.config.pack;
import com.dfsek.paralithic.eval.parser.Scope;
import com.dfsek.tectonic.abstraction.AbstractConfigLoader;
import com.dfsek.tectonic.config.ConfigTemplate;
import com.dfsek.tectonic.config.Configuration;
import com.dfsek.tectonic.exception.ConfigException;
import com.dfsek.tectonic.exception.LoadException;
import com.dfsek.tectonic.loading.ConfigLoader;
import com.dfsek.tectonic.loading.TypeRegistry;
import com.dfsek.tectonic.loading.object.ObjectTemplate;
import com.dfsek.terra.api.LoaderRegistrar;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.event.events.config.ConfigPackPostLoadEvent;
import com.dfsek.terra.api.event.events.config.ConfigPackPreLoadEvent;
import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.platform.world.Tree;
import com.dfsek.terra.api.registry.CheckedRegistry;
import com.dfsek.terra.api.registry.Registry;
import com.dfsek.terra.api.structures.loot.LootTable;
import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder;
import com.dfsek.terra.api.structures.script.StructureScript;
import com.dfsek.terra.api.util.generic.pair.ImmutablePair;
import com.dfsek.terra.api.util.seeded.NoiseProvider;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.api.world.biome.provider.BiomeProvider;
import com.dfsek.terra.api.world.flora.Flora;
import com.dfsek.terra.api.world.palette.Palette;
import com.dfsek.terra.carving.UserDefinedCarver;
import com.dfsek.terra.config.builder.BiomeBuilder;
import com.dfsek.terra.config.dummy.DummyWorld;
import com.dfsek.terra.config.factories.BiomeFactory;
import com.dfsek.terra.config.factories.CarverFactory;
import com.dfsek.terra.config.factories.ConfigFactory;
import com.dfsek.terra.config.factories.FloraFactory;
import com.dfsek.terra.config.factories.OreFactory;
import com.dfsek.terra.config.factories.PaletteFactory;
import com.dfsek.terra.config.factories.StructureFactory;
import com.dfsek.terra.config.factories.TreeFactory;
import com.dfsek.terra.config.fileloaders.FolderLoader;
import com.dfsek.terra.config.fileloaders.Loader;
import com.dfsek.terra.config.fileloaders.ZIPLoader;
@@ -32,16 +41,29 @@ import com.dfsek.terra.config.loaders.config.biome.templates.provider.ImageProvi
import com.dfsek.terra.config.loaders.config.biome.templates.provider.SingleBiomeProviderTemplate;
import com.dfsek.terra.config.loaders.config.sampler.NoiseSamplerBuilderLoader;
import com.dfsek.terra.config.loaders.config.sampler.templates.ImageSamplerTemplate;
import com.dfsek.terra.config.prototype.ConfigType;
import com.dfsek.terra.config.prototype.ProtoConfig;
import com.dfsek.terra.config.templates.AbstractableTemplate;
import com.dfsek.terra.config.templates.BiomeTemplate;
import com.dfsek.terra.config.templates.CarverTemplate;
import com.dfsek.terra.config.templates.FloraTemplate;
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.registry.OpenRegistry;
import com.dfsek.terra.registry.config.ConfigTypeRegistry;
import com.dfsek.terra.registry.config.BiomeRegistry;
import com.dfsek.terra.registry.config.CarverRegistry;
import com.dfsek.terra.registry.config.FloraRegistry;
import com.dfsek.terra.registry.config.FunctionRegistry;
import com.dfsek.terra.registry.config.LootRegistry;
import com.dfsek.terra.registry.config.NoiseRegistry;
import com.dfsek.terra.registry.config.OreRegistry;
import com.dfsek.terra.registry.config.PaletteRegistry;
import com.dfsek.terra.registry.config.ScriptRegistry;
import com.dfsek.terra.registry.config.StructureRegistry;
import com.dfsek.terra.registry.config.TreeRegistry;
import com.dfsek.terra.world.TerraWorld;
import com.dfsek.terra.world.population.items.TerraStructure;
import com.dfsek.terra.world.population.items.ores.Ore;
import org.apache.commons.io.IOUtils;
import org.json.simple.parser.ParseException;
@@ -52,14 +74,12 @@ import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
@@ -69,27 +89,38 @@ import java.util.zip.ZipFile;
public class ConfigPack implements LoaderRegistrar {
private final ConfigPackTemplate template = new ConfigPackTemplate();
private final BiomeRegistry biomeRegistry = new BiomeRegistry();
private final StructureRegistry structureRegistry = new StructureRegistry();
private final PaletteRegistry paletteRegistry;
private final FloraRegistry floraRegistry;
private final OreRegistry oreRegistry = new OreRegistry();
private final TreeRegistry treeRegistry;
private final ScriptRegistry scriptRegistry = new ScriptRegistry();
private final LootRegistry lootRegistry = new LootRegistry();
private final CarverRegistry carverRegistry = new CarverRegistry();
private final NoiseRegistry noiseRegistry = new NoiseRegistry();
private final FunctionRegistry functionRegistry = new FunctionRegistry();
private final AbstractConfigLoader abstractConfigLoader = new AbstractConfigLoader();
private final ConfigLoader selfLoader = new ConfigLoader();
private final Scope varScope = new Scope();
private final TerraPlugin main;
private final Loader loader;
private final BiomeProvider.BiomeProviderBuilder biomeProviderBuilder;
private final ConfigTypeRegistry configTypeRegistry;
private final Map<Class<?>, ImmutablePair<OpenRegistry<?>, CheckedRegistry<?>>> registryMap = newRegistryMap();
public ConfigPack(File folder, TerraPlugin main) throws ConfigException {
try {
this.configTypeRegistry = new ConfigTypeRegistry(this, main, (id, configType) -> {
OpenRegistry<?> openRegistry = configType.registrySupplier().get();
registryMap.put(configType.getTypeClass(), ImmutablePair.of(openRegistry, new CheckedRegistry<>(openRegistry)));
});
this.loader = new FolderLoader(folder.toPath());
this.main = main;
long l = System.nanoTime();
floraRegistry = new FloraRegistry(main);
paletteRegistry = new PaletteRegistry(main);
treeRegistry = new TreeRegistry();
register(abstractConfigLoader);
register(selfLoader);
@@ -121,16 +152,17 @@ public class ConfigPack implements LoaderRegistrar {
public ConfigPack(ZipFile file, TerraPlugin main) throws ConfigException {
try {
this.configTypeRegistry = new ConfigTypeRegistry(this, main, (id, configType) -> {
OpenRegistry<?> openRegistry = configType.registrySupplier().get();
registryMap.put(configType.getTypeClass(), ImmutablePair.of(openRegistry, new CheckedRegistry<>(openRegistry)));
});
this.loader = new ZIPLoader(file);
this.main = main;
long l = System.nanoTime();
floraRegistry = new FloraRegistry(main);
paletteRegistry = new PaletteRegistry(main);
treeRegistry = new TreeRegistry();
register(abstractConfigLoader);
register(selfLoader);
main.register(selfLoader);
main.register(abstractConfigLoader);
try {
ZipEntry pack = null;
@@ -164,36 +196,20 @@ public class ConfigPack implements LoaderRegistrar {
toWorldConfig(new TerraWorld(new DummyWorld(), this, main)); // Build now to catch any errors immediately.
}
@SuppressWarnings({"unchecked", "rawtypes"})
private Map<Class<?>, ImmutablePair<OpenRegistry<?>, CheckedRegistry<?>>> newRegistryMap() {
Map<Class<?>, ImmutablePair<OpenRegistry<?>, CheckedRegistry<?>>> map = new HashMap<Class<?>, ImmutablePair<OpenRegistry<?>, CheckedRegistry<?>>>() {
private static final long serialVersionUID = 4015855819914064466L;
@Override
public ImmutablePair<OpenRegistry<?>, CheckedRegistry<?>> put(Class<?> key, ImmutablePair<OpenRegistry<?>, CheckedRegistry<?>> value) {
selfLoader.registerLoader(key, value.getLeft());
abstractConfigLoader.registerLoader(key, value.getLeft());
return super.put(key, value);
}
};
putPair(map, NoiseProvider.class, new NoiseRegistry());
putPair(map, FunctionBuilder.class, (OpenRegistry<FunctionBuilder>) (Object) new FunctionRegistry());
putPair(map, LootTable.class, new LootRegistry());
putPair(map, StructureScript.class, new ScriptRegistry());
return map;
}
private <R> void putPair(Map<Class<?>, ImmutablePair<OpenRegistry<?>, CheckedRegistry<?>>> map, Class<R> key, OpenRegistry<R> l) {
map.put(key, ImmutablePair.of(l, new CheckedRegistry<>(l)));
public static <C extends AbstractableTemplate, O> void buildAll(ConfigFactory<C, O> factory, OpenRegistry<O> registry, List<C> configTemplates, TerraPlugin main) throws LoadException {
for(C template : configTemplates) registry.add(template.getID(), factory.build(template, main));
}
private void checkDeadEntries(TerraPlugin main) {
registryMap.forEach((clazz, pair) -> pair.getLeft().getDeadEntries().forEach((id, value) -> main.getDebugLogger().warn("Dead entry in '" + clazz + "' registry: '" + id + "'")));
biomeRegistry.getDeadEntries().forEach((id, value) -> main.getDebugLogger().warn("Dead entry in biome registry: '" + id + "'"));
paletteRegistry.getDeadEntries().forEach((id, value) -> main.getDebugLogger().warn("Dead entry in palette registry: '" + id + "'"));
floraRegistry.getDeadEntries().forEach((id, value) -> main.getDebugLogger().warn("Dead entry in flora registry: '" + id + "'"));
carverRegistry.getDeadEntries().forEach((id, value) -> main.getDebugLogger().warn("Dead entry in carver registry: '" + id + "'"));
treeRegistry.getDeadEntries().forEach((id, value) -> main.getDebugLogger().warn("Dead entry in tree registry: '" + id + "'"));
oreRegistry.getDeadEntries().forEach((id, value) -> main.getDebugLogger().warn("Dead entry in ore registry: '" + id + "'"));
}
@SuppressWarnings({"unchecked", "rawtypes"})
private void load(long start, TerraPlugin main) throws ConfigException {
main.getEventManager().callEvent(new ConfigPackPreLoadEvent(this));
@@ -204,8 +220,8 @@ public class ConfigPack implements LoaderRegistrar {
loader.open("structures/data", ".tesf").thenEntries(entries -> {
for(Map.Entry<String, InputStream> entry : entries) {
try(InputStream stream = entry.getValue()) {
StructureScript structureScript = new StructureScript(stream, main, getRegistry(StructureScript.class), getRegistry(LootTable.class), (Registry<FunctionBuilder<?>>) (Object) getRegistry(FunctionBuilder.class));
getOpenRegistry(StructureScript.class).add(structureScript.getId(), structureScript);
StructureScript structureScript = new StructureScript(stream, main, scriptRegistry, lootRegistry, functionRegistry);
scriptRegistry.add(structureScript.getId(), structureScript);
} catch(com.dfsek.terra.api.structures.parser.exceptions.ParseException | IOException e) {
throw new LoadException("Unable to load script \"" + entry.getKey() + "\"", e);
}
@@ -213,38 +229,36 @@ public class ConfigPack implements LoaderRegistrar {
}).close().open("structures/loot", ".json").thenEntries(entries -> {
for(Map.Entry<String, InputStream> entry : entries) {
try {
getOpenRegistry(LootTable.class).add(entry.getKey(), new LootTable(IOUtils.toString(entry.getValue(), StandardCharsets.UTF_8), main));
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();
List<Configuration> configurations = new ArrayList<>();
loader.open("", ".yml").thenEntries(entries -> entries.forEach(stream -> configurations.add(new Configuration(stream.getValue(), stream.getKey()))));
Map<ConfigType<? extends ConfigTemplate, ?>, List<Configuration>> configs = new HashMap<>();
for(Configuration configuration : configurations) {
ProtoConfig config = new ProtoConfig();
selfLoader.load(config, configuration);
configs.computeIfAbsent(config.getType(), configType -> new ArrayList<>()).add(configuration);
}
for(ConfigType<?, ?> configType : configTypeRegistry.entries()) {
for(ConfigTemplate config : abstractConfigLoader.loadConfigs(configs.getOrDefault(configType, Collections.emptyList()), () -> configType.getTemplate(this, main))) {
((ConfigType) configType).callback(this, main, config);
}
}
loader
.open("carving", ".yml").then(configs -> buildAll(new CarverFactory(this), carverRegistry, abstractConfigLoader.loadConfigs(configs, CarverTemplate::new), main)).close()
.open("palettes", ".yml").then(configs -> buildAll(new PaletteFactory(), paletteRegistry, abstractConfigLoader.loadConfigs(configs, PaletteTemplate::new), main)).close()
.open("ores", ".yml").then(configs -> buildAll(new OreFactory(), oreRegistry, abstractConfigLoader.loadConfigs(configs, OreTemplate::new), main)).close()
.open("structures/trees", ".yml").then(configs -> buildAll(new TreeFactory(), treeRegistry, abstractConfigLoader.loadConfigs(configs, TreeTemplate::new), main)).close()
.open("structures/structures", ".yml").then(configs -> buildAll(new StructureFactory(), structureRegistry, abstractConfigLoader.loadConfigs(configs, StructureTemplate::new), main)).close()
.open("flora", ".yml").then(configs -> buildAll(new FloraFactory(), floraRegistry, abstractConfigLoader.loadConfigs(configs, FloraTemplate::new), main)).close()
.open("biomes", ".yml").then(configs -> buildAll(new BiomeFactory(this), biomeRegistry, abstractConfigLoader.loadConfigs(configs, () -> new BiomeTemplate(this, main)), main)).close();
main.getEventManager().callEvent(new ConfigPackPostLoadEvent(this));
main.logger().info("Loaded config pack \"" + template.getID() + "\" v" + template.getVersion() + " by " + template.getAuthor() + " in " + (System.nanoTime() - start) / 1000000D + "ms.");
}
public TerraStructure getStructure(String id) {
return structureRegistry.get(id);
}
public Set<TerraStructure> getStructures() {
return new HashSet<>(getRegistry(TerraStructure.class).entries());
return structureRegistry.entries();
}
public List<String> getStructureIDs() {
return structureRegistry.entries().stream().map(terraStructure -> terraStructure.getTemplate().getID()).collect(Collectors.toList());
}
public ConfigPackTemplate getTemplate() {
@@ -255,45 +269,80 @@ public class ConfigPack implements LoaderRegistrar {
return varScope;
}
@SuppressWarnings("unchecked")
public <T> CheckedRegistry<T> getRegistry(Class<T> clazz) {
return (CheckedRegistry<T>) registryMap.getOrDefault(clazz, ImmutablePair.ofNull()).getRight();
}
@SuppressWarnings("unchecked")
protected <T> OpenRegistry<T> getOpenRegistry(Class<T> clazz) {
return (OpenRegistry<T>) registryMap.getOrDefault(clazz, ImmutablePair.ofNull()).getLeft();
}
@Override
public void register(TypeRegistry registry) {
registry
.registerLoader(ConfigType.class, configTypeRegistry)
.registerLoader(Palette.class, paletteRegistry)
.registerLoader(BiomeBuilder.class, biomeRegistry)
.registerLoader(Flora.class, floraRegistry)
.registerLoader(Ore.class, oreRegistry)
.registerLoader(Tree.class, treeRegistry)
.registerLoader(StructureScript.class, scriptRegistry)
.registerLoader(TerraStructure.class, structureRegistry)
.registerLoader(LootTable.class, lootRegistry)
.registerLoader(UserDefinedCarver.class, carverRegistry)
.registerLoader(BufferedImage.class, new BufferedImageLoader(loader))
.registerLoader(NoiseSeeded.class, new NoiseSamplerBuilderLoader(noiseRegistry))
.registerLoader(SingleBiomeProviderTemplate.class, SingleBiomeProviderTemplate::new)
.registerLoader(BiomePipelineTemplate.class, () -> new BiomePipelineTemplate(main))
.registerLoader(ImageProviderTemplate.class, () -> new ImageProviderTemplate(getRegistry(BiomeBuilder.class)))
.registerLoader(ImageSamplerTemplate.class, () -> new ImageProviderTemplate(getRegistry(BiomeBuilder.class)))
.registerLoader(NoiseSeeded.class, new NoiseSamplerBuilderLoader(getOpenRegistry(NoiseProvider.class)));
.registerLoader(ImageProviderTemplate.class, () -> new ImageProviderTemplate(biomeRegistry))
.registerLoader(ImageSamplerTemplate.class, () -> new ImageProviderTemplate(biomeRegistry));
}
public Set<UserDefinedCarver> getCarvers() {
return carverRegistry.entries();
}
public BiomeProvider.BiomeProviderBuilder getBiomeProviderBuilder() {
return biomeProviderBuilder;
}
public CheckedRegistry<StructureScript> getScriptRegistry() {
return new CheckedRegistry<>(scriptRegistry);
}
public WorldConfig toWorldConfig(TerraWorld world) {
public CheckedRegistry<BiomeBuilder> getBiomeRegistry() {
return new CheckedRegistry<>(biomeRegistry);
}
public CheckedRegistry<Tree> getTreeRegistry() {
return new CheckedRegistry<>(treeRegistry);
}
public CheckedRegistry<FunctionBuilder<?>> getFunctionRegistry() {
return new CheckedRegistry<>(functionRegistry);
}
public CheckedRegistry<Supplier<ObjectTemplate<NoiseSeeded>>> getNormalizerRegistry() {
return new CheckedRegistry<>(noiseRegistry);
}
public CheckedRegistry<UserDefinedCarver> getCarverRegistry() {
return new CheckedRegistry<>(carverRegistry);
}
public CheckedRegistry<Flora> getFloraRegistry() {
return new CheckedRegistry<>(floraRegistry);
}
public CheckedRegistry<LootTable> getLootRegistry() {
return new CheckedRegistry<>(lootRegistry);
}
public CheckedRegistry<Ore> getOreRegistry() {
return new CheckedRegistry<>(oreRegistry);
}
public CheckedRegistry<Palette<BlockData>> getPaletteRegistry() {
return new CheckedRegistry<>(paletteRegistry);
}
public CheckedRegistry<TerraStructure> getStructureRegistry() {
return new CheckedRegistry<>(structureRegistry);
}
public WorldConfig toWorldConfig(TerraWorld world){
return new WorldConfig(world, this, main);
}
public CheckedRegistry<ConfigType<?, ?>> getConfigTypeRegistry() {
return new CheckedRegistry<ConfigType<?, ?>>(configTypeRegistry) {
@Override
@SuppressWarnings("deprecation")
public void addUnchecked(String identifier, ConfigType<?, ?> value) {
if(contains(identifier)) throw new UnsupportedOperationException("Cannot override values in ConfigTypeRegistry!");
}
};
}
}
@@ -1,51 +1,62 @@
package com.dfsek.terra.config.pack;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.platform.world.Tree;
import com.dfsek.terra.api.registry.LockedRegistry;
import com.dfsek.terra.api.structures.loot.LootTable;
import com.dfsek.terra.api.structures.script.StructureScript;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.biome.provider.BiomeProvider;
import com.dfsek.terra.api.world.flora.Flora;
import com.dfsek.terra.api.world.palette.Palette;
import com.dfsek.terra.carving.UserDefinedCarver;
import com.dfsek.terra.config.builder.BiomeBuilder;
import com.dfsek.terra.registry.OpenRegistry;
import com.dfsek.terra.world.TerraWorld;
import com.dfsek.terra.world.generation.math.SamplerCache;
import com.dfsek.terra.world.population.items.TerraStructure;
import com.dfsek.terra.world.population.items.ores.Ore;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public class WorldConfig {
private final LockedRegistry<StructureScript> scriptRegistry;
private final LockedRegistry<TerraBiome> biomeRegistry;
private final SamplerCache samplerCache;
private final LockedRegistry<UserDefinedCarver> carverRegistry;
private final LockedRegistry<Tree> treeRegistry;
private final LockedRegistry<Flora> floraRegistry;
private final LockedRegistry<LootTable> lootRegistry;
private final LockedRegistry<Ore> oreRegistry;
private final LockedRegistry<Palette<BlockData>> paletteRegistry;
private final LockedRegistry<TerraStructure> structureRegistry;
private final BiomeProvider provider;
private final TerraWorld world;
private final ConfigPack pack;
private final Map<Class<?>, LockedRegistry<?>> registryMap = new HashMap<>();
public WorldConfig(TerraWorld world, ConfigPack pack, TerraPlugin main) {
this.world = world;
this.pack = pack;
this.samplerCache = new SamplerCache(main, world);
pack.getConfigTypeRegistry().forEach(configType -> registryMap.put(configType.getTypeClass(), new LockedRegistry<>(pack.getRegistry(configType.getTypeClass()))));
this.scriptRegistry = new LockedRegistry<>(pack.getScriptRegistry());
OpenRegistry<TerraBiome> biomeOpenRegistry = new OpenRegistry<>();
pack.getRegistry(BiomeBuilder.class).forEach((id, biome) -> biomeOpenRegistry.add(id, biome.apply(world.getWorld().getSeed())));
registryMap.put(TerraBiome.class, new LockedRegistry<>(biomeOpenRegistry));
pack.getBiomeRegistry().forEach((id, biome) -> biomeOpenRegistry.add(id, biome.apply(world.getWorld().getSeed())));
this.biomeRegistry = new LockedRegistry<>(biomeOpenRegistry);
this.carverRegistry = new LockedRegistry<>(pack.getCarverRegistry());
this.treeRegistry = new LockedRegistry<>(pack.getTreeRegistry());
this.floraRegistry = new LockedRegistry<>(pack.getFloraRegistry());
this.lootRegistry = new LockedRegistry<>(pack.getLootRegistry());
this.oreRegistry = new LockedRegistry<>(pack.getOreRegistry());
this.paletteRegistry = new LockedRegistry<>(pack.getPaletteRegistry());
this.structureRegistry = new LockedRegistry<>(pack.getStructureRegistry());
this.provider = pack.getBiomeProviderBuilder().build(world.getWorld().getSeed());
}
@SuppressWarnings("unchecked")
public <T> LockedRegistry<T> getRegistry(Class<T> clazz) {
return (LockedRegistry<T>) registryMap.get(clazz);
}
public TerraWorld getWorld() {
return world;
}
@@ -55,7 +66,43 @@ public class WorldConfig {
}
public Set<UserDefinedCarver> getCarvers() {
return new HashSet<>(getRegistry(UserDefinedCarver.class).entries());
return carverRegistry.entries();
}
public LockedRegistry<StructureScript> getScriptRegistry() {
return scriptRegistry;
}
public LockedRegistry<TerraBiome> getBiomeRegistry() {
return biomeRegistry;
}
public LockedRegistry<Tree> getTreeRegistry() {
return treeRegistry;
}
public LockedRegistry<UserDefinedCarver> getCarverRegistry() {
return carverRegistry;
}
public LockedRegistry<Flora> getFloraRegistry() {
return floraRegistry;
}
public LockedRegistry<LootTable> getLootRegistry() {
return lootRegistry;
}
public LockedRegistry<Ore> getOreRegistry() {
return oreRegistry;
}
public LockedRegistry<Palette<BlockData>> getPaletteRegistry() {
return paletteRegistry;
}
public LockedRegistry<TerraStructure> getStructureRegistry() {
return structureRegistry;
}
public BiomeProvider getProvider() {
@@ -63,7 +110,7 @@ public class WorldConfig {
}
public Set<TerraStructure> getStructures() {
return new HashSet<>(getRegistry(TerraStructure.class).entries());
return structureRegistry.entries();
}
public ConfigPackTemplate getTemplate() {
@@ -1,19 +0,0 @@
package com.dfsek.terra.config.prototype;
import com.dfsek.tectonic.config.ConfigTemplate;
import com.dfsek.tectonic.exception.LoadException;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.config.pack.ConfigPack;
import com.dfsek.terra.registry.OpenRegistry;
import java.util.function.Supplier;
public interface ConfigType<T extends ConfigTemplate, R> {
T getTemplate(ConfigPack pack, TerraPlugin main);
void callback(ConfigPack pack, TerraPlugin main, T loadedConfig) throws LoadException;
Class<R> getTypeClass();
Supplier<OpenRegistry<R>> registrySupplier();
}
@@ -1,21 +0,0 @@
package com.dfsek.terra.config.prototype;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.tectonic.config.ConfigTemplate;
public class ProtoConfig implements ConfigTemplate {
@Value("id")
private String id;
@Value("type")
private ConfigType<?, ?> type;
public String getId() {
return id;
}
public ConfigType<?, ?> getType() {
return type;
}
}
@@ -13,6 +13,7 @@ import com.dfsek.terra.api.math.noise.NoiseSampler;
import com.dfsek.terra.api.math.noise.samplers.noise.ConstantSampler;
import com.dfsek.terra.api.math.paralithic.BlankFunction;
import com.dfsek.terra.api.math.paralithic.defined.UserDefinedFunction;
import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.platform.block.BlockType;
import com.dfsek.terra.api.platform.world.Biome;
import com.dfsek.terra.api.util.GlueList;
@@ -123,7 +124,7 @@ public class BiomeTemplate extends AbstractableTemplate implements ValidatedConf
@Value("ocean.palette")
@Abstractable
@Default
private Palette oceanPalette;
private Palette<BlockData> oceanPalette;
@Value("elevation.equation")
@Default
@@ -158,12 +159,12 @@ public class BiomeTemplate extends AbstractableTemplate implements ValidatedConf
@Value("slabs.palettes")
@Abstractable
@Default
private Map<BlockType, Palette> slabPalettes;
private Map<BlockType, Palette<BlockData>> slabPalettes;
@Value("slabs.stair-palettes")
@Abstractable
@Default
private Map<BlockType, Palette> stairPalettes;
private Map<BlockType, Palette<BlockData>> stairPalettes;
@Value("slant.threshold")
@Abstractable
@@ -246,6 +247,14 @@ public class BiomeTemplate extends AbstractableTemplate implements ValidatedConf
return doSlabs;
}
public Map<BlockType, Palette<BlockData>> getSlabPalettes() {
return slabPalettes;
}
public Map<BlockType, Palette<BlockData>> getStairPalettes() {
return stairPalettes;
}
public BiomeTemplate(ConfigPack pack, TerraPlugin main) {
this.pack = pack;
biomeNoise = new NoiseSeeded() {
@@ -259,15 +268,7 @@ public class BiomeTemplate extends AbstractableTemplate implements ValidatedConf
return 2;
}
};
oceanPalette = new SinglePalette(main.getWorldHandle().createBlockData("minecraft:water"));
}
public Map<BlockType, Palette> getSlabPalettes() {
return slabPalettes;
}
public Map<BlockType, Palette> getStairPalettes() {
return stairPalettes;
oceanPalette = new SinglePalette<>(main.getWorldHandle().createBlockData("minecraft:water"));
}
public NoiseSeeded getBiomeNoise() {
@@ -290,7 +291,7 @@ public class BiomeTemplate extends AbstractableTemplate implements ValidatedConf
return seaLevel;
}
public Palette getOceanPalette() {
public Palette<BlockData> getOceanPalette() {
return oceanPalette;
}
@@ -17,7 +17,7 @@ public class OreTemplate extends AbstractableTemplate {
@Abstractable
private BlockData material;
@Value("algorithm")
@Value("type")
@Abstractable
@Default
private Ore.Type oreType = Ore.Type.VANILLA;
@@ -4,16 +4,20 @@ 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.tectonic.config.ValidatedConfigTemplate;
import com.dfsek.tectonic.exception.ValidationException;
import com.dfsek.terra.api.math.GridSpawn;
import com.dfsek.terra.api.math.Range;
import com.dfsek.terra.api.structures.script.StructureScript;
import com.dfsek.terra.api.util.GlueList;
import com.dfsek.terra.api.util.collections.ProbabilityCollection;
import org.checkerframework.checker.units.qual.A;
import java.time.Duration;
import java.util.List;
@SuppressWarnings({"unused", "FieldMayBeFinal"})
public class StructureTemplate extends AbstractableTemplate implements ConfigTemplate {
public class StructureTemplate extends AbstractableTemplate implements ValidatedConfigTemplate {
@Value("id")
private String id;
@@ -34,6 +38,21 @@ public class StructureTemplate extends AbstractableTemplate implements ConfigTem
@Default
private List<Void> features = new GlueList<>();
@Value("repeat.scripts")
@Default
@Abstractable
private ProbabilityCollection<StructureScript> repeatScripts = new ProbabilityCollection<>();
@Value("repeat.ticks.min")
@Default
@Abstractable
private long minRepeat = 20;
@Value("repeat.ticks.max")
@Default
@Abstractable
private long maxRepeat = 20;
public String getID() {
return id;
}
@@ -53,4 +72,10 @@ public class StructureTemplate extends AbstractableTemplate implements ConfigTem
public GridSpawn getSpawn() {
return spawn;
}
@Override
public boolean validate() throws ValidationException {
if(maxRepeat < minRepeat) throw new ValidationException("repeat.ticks.max must be greater than repeat.ticks.min");
return true;
}
}
@@ -3,22 +3,54 @@ package com.dfsek.terra.profiler;
import java.util.Map;
public interface Profiler {
/**
* Push a frame to this profiler.
*
* @param frame ID of frame.
*/
void push(String frame);
/**
* Pop a frame from this profiler.
*
* @param frame ID of frame. Must match ID
* at the top of the profiler stack.
*/
void pop(String frame);
/**
* Start profiling.
*/
void start();
/**
* Stop profiling.
*/
void stop();
/**
* Get the profiler data.
*
* @return Profiler data.
*/
Map<String, Timings> getTimings();
/**
* Return a {@link AutoCloseable} implementation that
* may be used in a try-with-resources statement for
* more intuitive profiling, with auto-push/pop.
*
* @param frame ID of frame.
* @return {@link AutoCloseable} implementation for use
* in try-with-resources.
*/
default ProfileFrame profile(String frame) {
push(frame);
return new ProfileFrame(() -> pop(frame));
}
default void reset() {
// todo: impl
}
/**
* Clear the profiler data.
*/
void reset();
}
@@ -83,4 +83,9 @@ public class ProfilerImpl implements Profiler {
}));
return map;
}
@Override
public void reset() {
accessibleThreadMaps.forEach(Map::clear);
}
}
@@ -6,7 +6,6 @@ import com.dfsek.terra.api.registry.Registry;
import com.dfsek.terra.registry.exception.DuplicateEntryException;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
@@ -20,16 +19,7 @@ import java.util.stream.Collectors;
* @param <T>
*/
public class OpenRegistry<T> implements Registry<T> {
private final Map<String, Entry<T>> objects;
private static final Entry<?> NULL = new Entry<>(null);
public OpenRegistry() {
objects = new HashMap<>();
}
protected OpenRegistry(Map<String, Entry<T>> init) {
this.objects = init;
}
private final Map<String, Entry<T>> objects = new HashMap<>();
@Override
public T load(Type type, Object o, ConfigLoader configLoader) throws LoadException {
@@ -73,10 +63,11 @@ public class OpenRegistry<T> implements Registry<T> {
return objects.containsKey(identifier);
}
@SuppressWarnings("unchecked")
@Override
public T get(String identifier) {
return objects.getOrDefault(identifier, (Entry<T>) NULL).getValue();
Entry<T> entry = objects.get(identifier);
if(entry == null) return null;
return entry.getValue();
}
@Override
@@ -90,8 +81,8 @@ public class OpenRegistry<T> implements Registry<T> {
}
@Override
public Collection<T> entries() {
return objects.values().stream().map(Entry::getRaw).collect(Collectors.toList());
public Set<T> entries() {
return objects.values().stream().map(Entry::getRaw).collect(Collectors.toSet());
}
@Override
@@ -1,117 +0,0 @@
package com.dfsek.terra.registry.config;
import com.dfsek.tectonic.config.ConfigTemplate;
import com.dfsek.tectonic.exception.LoadException;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.platform.world.Tree;
import com.dfsek.terra.api.world.flora.Flora;
import com.dfsek.terra.api.world.palette.Palette;
import com.dfsek.terra.carving.UserDefinedCarver;
import com.dfsek.terra.config.builder.BiomeBuilder;
import com.dfsek.terra.config.factories.BiomeFactory;
import com.dfsek.terra.config.factories.CarverFactory;
import com.dfsek.terra.config.factories.ConfigFactory;
import com.dfsek.terra.config.factories.FloraFactory;
import com.dfsek.terra.config.factories.OreFactory;
import com.dfsek.terra.config.factories.PaletteFactory;
import com.dfsek.terra.config.factories.StructureFactory;
import com.dfsek.terra.config.factories.TreeFactory;
import com.dfsek.terra.config.pack.ConfigPack;
import com.dfsek.terra.config.prototype.ConfigType;
import com.dfsek.terra.config.templates.AbstractableTemplate;
import com.dfsek.terra.config.templates.BiomeTemplate;
import com.dfsek.terra.config.templates.CarverTemplate;
import com.dfsek.terra.config.templates.FloraTemplate;
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.registry.OpenRegistry;
import com.dfsek.terra.world.population.items.TerraStructure;
import com.dfsek.terra.world.population.items.ores.Ore;
import java.util.LinkedHashMap;
import java.util.function.BiConsumer;
import java.util.function.Supplier;
public class ConfigTypeRegistry extends OpenRegistry<ConfigType<?, ?>> {
private final BiConsumer<String, ConfigType<?, ?>> callback;
public ConfigTypeRegistry(ConfigPack pack, TerraPlugin main, BiConsumer<String, ConfigType<?, ?>> callback) {
super(new LinkedHashMap<>()); // Ordered
this.callback = callback;
add("PALETTE", new ConfigBuilder<>(new PaletteFactory(), PaletteTemplate::new, Palette.class, () -> new PaletteRegistry(main)));
add("ORE", new ConfigBuilder<>(new OreFactory(), OreTemplate::new, Ore.class, OreRegistry::new));
add("FLORA", new ConfigBuilder<>(new FloraFactory(), FloraTemplate::new, Flora.class, () -> new FloraRegistry(main)));
add("CARVER", new ConfigBuilder<>(new CarverFactory(pack), CarverTemplate::new, UserDefinedCarver.class, CarverRegistry::new));
add("STRUCTURE", new ConfigBuilder<>(new StructureFactory(), StructureTemplate::new, TerraStructure.class, StructureRegistry::new));
add("TREE", new ConfigBuilder<>(new TreeFactory(), TreeTemplate::new, Tree.class, TreeRegistry::new));
add("BIOME", new ConfigBuilder<>(new BiomeFactory(pack), () -> new BiomeTemplate(pack, main), BiomeBuilder.class, BiomeRegistry::new));
add("PACK", new PackBuilder());
}
@Override
protected boolean add(String identifier, Entry<ConfigType<?, ?>> value) {
callback.accept(identifier, value.getValue());
return super.add(identifier, value);
}
private static final class PackBuilder implements ConfigType<ConfigTemplate, ConfigPack> {
@Override
public ConfigTemplate getTemplate(ConfigPack pack, TerraPlugin main) {
return new ConfigTemplate() {
};
}
@Override
public void callback(ConfigPack pack, TerraPlugin main, ConfigTemplate loadedConfig) {
}
@Override
public Class<ConfigPack> getTypeClass() {
return ConfigPack.class;
}
@Override
public Supplier<OpenRegistry<ConfigPack>> registrySupplier() {
return OpenRegistry::new;
}
}
private static final class ConfigBuilder<T extends AbstractableTemplate, O> implements ConfigType<T, O> {
private final ConfigFactory<T, O> factory;
private final Supplier<T> provider;
private final Class<O> clazz;
private final Supplier<OpenRegistry<O>> registrySupplier;
private ConfigBuilder(ConfigFactory<T, O> factory, Supplier<T> provider, Class<O> clazz, Supplier<OpenRegistry<O>> registrySupplier) {
this.factory = factory;
this.provider = provider;
this.clazz = clazz;
this.registrySupplier = registrySupplier;
}
@Override
public T getTemplate(ConfigPack pack, TerraPlugin main) {
return provider.get();
}
@SuppressWarnings("deprecation")
@Override
public void callback(ConfigPack pack, TerraPlugin main, T loadedConfig) throws LoadException {
pack.getRegistry(clazz).addUnchecked(loadedConfig.getID(), factory.build(loadedConfig, main));
}
@Override
public Class<O> getTypeClass() {
return clazz;
}
@Override
public Supplier<OpenRegistry<O>> registrySupplier() {
return registrySupplier;
}
}
}
@@ -68,10 +68,4 @@ public class FloraRegistry extends OpenRegistry<Flora> {
private BlockData data(String s) {
return main.getWorldHandle().createBlockData(s);
}
@Override
public Flora get(String identifier) {
return super.get(identifier);
}
}
@@ -1,5 +1,6 @@
package com.dfsek.terra.registry.config;
import com.dfsek.tectonic.loading.object.ObjectTemplate;
import com.dfsek.terra.api.math.noise.samplers.noise.random.GaussianNoiseSampler;
import com.dfsek.terra.api.math.noise.samplers.noise.random.WhiteNoiseSampler;
import com.dfsek.terra.api.math.noise.samplers.noise.simplex.OpenSimplex2SSampler;
@@ -8,7 +9,7 @@ import com.dfsek.terra.api.math.noise.samplers.noise.simplex.PerlinSampler;
import com.dfsek.terra.api.math.noise.samplers.noise.simplex.SimplexSampler;
import com.dfsek.terra.api.math.noise.samplers.noise.value.ValueCubicSampler;
import com.dfsek.terra.api.math.noise.samplers.noise.value.ValueSampler;
import com.dfsek.terra.api.util.seeded.NoiseProvider;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.config.loaders.config.sampler.templates.DomainWarpTemplate;
import com.dfsek.terra.config.loaders.config.sampler.templates.ImageSamplerTemplate;
import com.dfsek.terra.config.loaders.config.sampler.templates.KernelTemplate;
@@ -25,7 +26,9 @@ import com.dfsek.terra.config.loaders.config.sampler.templates.normalizer.Linear
import com.dfsek.terra.config.loaders.config.sampler.templates.normalizer.NormalNormalizerTemplate;
import com.dfsek.terra.registry.OpenRegistry;
public class NoiseRegistry extends OpenRegistry<NoiseProvider> {
import java.util.function.Supplier;
public class NoiseRegistry extends OpenRegistry<Supplier<ObjectTemplate<NoiseSeeded>>> {
public NoiseRegistry() {
add("LINEAR", LinearNormalizerTemplate::new);
add("NORMAL", NormalNormalizerTemplate::new);
@@ -1,21 +1,22 @@
package com.dfsek.terra.registry.config;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.world.palette.Palette;
import com.dfsek.terra.api.world.palette.SinglePalette;
import com.dfsek.terra.registry.OpenRegistry;
public class PaletteRegistry extends OpenRegistry<Palette> {
public class PaletteRegistry extends OpenRegistry<Palette<BlockData>> {
private final TerraPlugin main;
public PaletteRegistry(TerraPlugin main) {
this.main = main;
}
@Override
public Palette get(String identifier) {
public Palette<BlockData> get(String identifier) {
if(identifier.startsWith("BLOCK:"))
return new SinglePalette(main.getWorldHandle().createBlockData(identifier.substring(6))); // Return single palette for BLOCK: shortcut.
return new SinglePalette<>(main.getWorldHandle().createBlockData(identifier.substring(6))); // Return single palette for BLOCK: shortcut.
return super.get(identifier);
}
}
@@ -25,7 +25,7 @@ public class TerraWorld {
public TerraWorld(World w, ConfigPack c, TerraPlugin main) {
if(!isTerraWorld(w)) throw new IllegalArgumentException("World " + w + " is not a Terra World!");
if(!w.isTerraWorld()) throw new IllegalArgumentException("World " + w + " is not a Terra World!");
this.world = w;
config = c.toWorldConfig(this);
this.provider = config.getProvider();
@@ -34,17 +34,11 @@ public class TerraWorld {
safe = true;
}
public static boolean isTerraWorld(World w) {
return w.getGenerator().getHandle() instanceof GeneratorWrapper;
}
public World getWorld() {
return world;
}
public TerraChunkGenerator getGenerator() {
return ((GeneratorWrapper) world.getGenerator().getHandle()).getHandle();
}
public BiomeProvider getBiomeProvider() {
return provider;
@@ -69,7 +63,7 @@ public class TerraWorld {
*/
public BlockData getUngeneratedBlock(int x, int y, int z) {
UserDefinedBiome biome = (UserDefinedBiome) provider.getBiome(x, z);
Palette palette = biome.getGenerator(world).getPalette(y);
Palette<BlockData> palette = biome.getGenerator(world).getPalette(y);
Sampler sampler = config.getSamplerCache().get(x, z);
int fdX = FastMath.floorMod(x, 16);
int fdZ = FastMath.floorMod(z, 16);
@@ -1,13 +1,10 @@
package com.dfsek.terra.world.generation;
import com.dfsek.terra.api.math.noise.NoiseSampler;
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.api.world.palette.holder.PaletteHolder;
import com.dfsek.terra.world.generation.math.samplers.terrain.TerrainSampler;
import java.util.Collections;
import java.util.List;
public class WorldGenerator implements Generator {
@SuppressWarnings({"unchecked", "rawtypes", "RedundantSuppression"})
@@ -70,7 +67,7 @@ public class WorldGenerator implements Generator {
* @return BlockPalette - The biome's palette.
*/
@Override
public Palette getPalette(int y) {
public Palette<BlockData> getPalette(int y) {
return palettes.getPalette(y);
}
@@ -89,12 +86,7 @@ public class WorldGenerator implements Generator {
return blendStep;
}
@Override
public List<TerrainSampler> getTerrainSamplers() {
return Collections.emptyList();
}
public Palette getSlantPalette(int y) {
public Palette<BlockData> getSlantPalette(int y) {
return slantPalettes.getPalette(y);
}
}
@@ -0,0 +1,146 @@
package com.dfsek.terra.world.generation.generators;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.math.Range;
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.platform.world.generator.ChunkData;
import com.dfsek.terra.api.util.world.PaletteUtil;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.biome.UserDefinedBiome;
import com.dfsek.terra.api.world.biome.provider.BiomeProvider;
import com.dfsek.terra.api.world.generation.TerraBlockPopulator;
import com.dfsek.terra.api.world.generation.TerraChunkGenerator;
import com.dfsek.terra.api.world.palette.Palette;
import com.dfsek.terra.config.pack.ConfigPack;
import com.dfsek.terra.config.templates.BiomeTemplate;
import com.dfsek.terra.profiler.ProfileFrame;
import com.dfsek.terra.world.Carver;
import com.dfsek.terra.world.TerraWorld;
import com.dfsek.terra.world.carving.NoiseCarver;
import com.dfsek.terra.world.generation.math.SamplerCache;
import com.dfsek.terra.world.generation.math.samplers.Sampler;
import com.dfsek.terra.world.generation.math.samplers.Sampler2D;
import com.dfsek.terra.world.population.CavePopulator;
import com.dfsek.terra.world.population.OrePopulator;
import com.dfsek.terra.world.population.StructurePopulator;
import com.dfsek.terra.world.population.TreePopulator;
import net.jafama.FastMath;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class DefaultChunkGenerator2D implements TerraChunkGenerator {
private final ConfigPack configPack;
private final TerraPlugin main;
private final Carver carver;
private final List<TerraBlockPopulator> blockPopulators = new ArrayList<>();
private final SamplerCache cache;
public DefaultChunkGenerator2D(ConfigPack c, TerraPlugin main, SamplerCache cache) {
this.configPack = c;
this.main = main;
blockPopulators.add(new CavePopulator(main));
blockPopulators.add(new StructurePopulator(main));
blockPopulators.add(new OrePopulator(main));
blockPopulators.add(new TreePopulator(main));
blockPopulators.add(new TreePopulator(main));
carver = new NoiseCarver(new Range(0, 255), main.getWorldHandle().createBlockData("minecraft:air"), main);
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 ChunkData generateChunkData(@NotNull World world, Random random, int chunkX, int chunkZ, ChunkData chunk) {
TerraWorld tw = main.getWorld(world);
BiomeProvider grid = tw.getBiomeProvider();
try(ProfileFrame ignore = main.getProfiler().profile("chunk_base_2d")) {
if(!tw.isSafe()) return chunk;
int xOrig = (chunkX << 4);
int zOrig = (chunkZ << 4);
Sampler sampler = cache.getChunk(chunkX, chunkZ);
for(int x = 0; x < 16; x++) {
for(int z = 0; z < 16; z++) {
int paletteLevel = 0;
int seaPaletteLevel = 0;
int cx = xOrig + x;
int cz = zOrig + z;
TerraBiome b = grid.getBiome(xOrig + x, zOrig + z);
BiomeTemplate c = ((UserDefinedBiome) b).getConfig();
Palette<BlockData> seaPalette = c.getOceanPalette();
int height = FastMath.min((int) sampler.sample(x, 0, z), world.getMaxHeight() - 1);
for(int y = FastMath.max(height, c.getSeaLevel()); y >= 0; y--) {
BlockData data = y > height ? seaPalette.get(seaPaletteLevel++, cx, y, cz) : PaletteUtil.getPalette(x, y, z, c, sampler).get(paletteLevel++, cx, y, cz);
chunk.setBlock(x, y, z, data);
}
}
}
if(configPack.getTemplate().doBetaCarvers()) {
carver.carve(world, chunkX, chunkZ, chunk);
}
return chunk;
}
}
@Override
public void generateBiomes(@NotNull World world, @NotNull Random random, int chunkX, int chunkZ, @NotNull BiomeGrid biome) {
DefaultChunkGenerator3D.biomes(world, chunkX, chunkZ, biome, main);
}
@Override
public Sampler createSampler(int chunkX, int chunkZ, BiomeProvider provider, World world, int elevationSmooth) {
return new Sampler2D(chunkX, chunkZ, provider, world, elevationSmooth);
}
@Override
public List<TerraBlockPopulator> getPopulators() {
return blockPopulators;
}
}
@@ -45,12 +45,11 @@ public class DefaultChunkGenerator3D implements TerraChunkGenerator {
private final ConfigPack configPack;
private final TerraPlugin main;
private final BlockType water;
private final SinglePalette blank;
private final SinglePalette<BlockData> blank;
private final List<TerraBlockPopulator> blockPopulators = new ArrayList<>();
private final Carver carver;
public DefaultChunkGenerator3D(ConfigPack c, TerraPlugin main) {
this.configPack = c;
this.main = main;
@@ -63,7 +62,7 @@ public class DefaultChunkGenerator3D implements TerraChunkGenerator {
carver = new NoiseCarver(new Range(0, 255), main.getWorldHandle().createBlockData("minecraft:air"), main);
water = main.getWorldHandle().createBlockData("minecraft:water").getBlockType();
blank = new SinglePalette(main.getWorldHandle().createBlockData("minecraft:air"));
blank = new SinglePalette<>(main.getWorldHandle().createBlockData("minecraft:air"));
}
@Override
@@ -104,9 +103,10 @@ public class DefaultChunkGenerator3D implements TerraChunkGenerator {
@Override
@SuppressWarnings({"try"})
public ChunkData generateChunkData(@NotNull World world, Random random, int chunkX, int chunkZ, ChunkData chunk) {
TerraWorld tw = main.getWorld(world);
BiomeProvider grid = tw.getBiomeProvider();
try(ProfileFrame ignore = main.getProfiler().profile("chunk_base_3d")) {
TerraWorld tw = main.getWorld(world);
BiomeProvider grid = tw.getBiomeProvider();
if(!tw.isSafe()) return chunk;
int xOrig = (chunkX << 4);
int zOrig = (chunkZ << 4);
@@ -120,11 +120,11 @@ public class DefaultChunkGenerator3D implements TerraChunkGenerator {
int cx = xOrig + x;
int cz = zOrig + z;
TerraBiome b = grid.getBiome(xOrig + x, zOrig + z);
TerraBiome b = grid.getBiome(cx, cz);
BiomeTemplate c = ((UserDefinedBiome) b).getConfig();
int sea = c.getSeaLevel();
Palette seaPalette = c.getOceanPalette();
Palette<BlockData> seaPalette = c.getOceanPalette();
boolean justSet = false;
BlockData data = null;
@@ -162,11 +162,11 @@ public class DefaultChunkGenerator3D implements TerraChunkGenerator {
}
}
private void prepareBlockPartFloor(BlockData down, BlockData orig, ChunkData chunk, Vector3 block, Map<BlockType, Palette> slabs,
Map<BlockType, Palette> stairs, double thresh, Sampler sampler) {
private void prepareBlockPartFloor(BlockData down, BlockData orig, ChunkData chunk, Vector3 block, Map<BlockType, Palette<BlockData>> slabs,
Map<BlockType, Palette<BlockData>> stairs, double thresh, Sampler sampler) {
if(sampler.sample(block.getX(), block.getY() - 0.4, block.getZ()) > thresh) {
if(stairs != null) {
Palette stairPalette = stairs.get(down.getBlockType());
Palette<BlockData> stairPalette = stairs.get(down.getBlockType());
if(stairPalette != null) {
BlockData stair = stairPalette.get(0, block.getX(), block.getY(), block.getZ()).clone();
if(stair instanceof Stairs) {
@@ -183,11 +183,11 @@ public class DefaultChunkGenerator3D implements TerraChunkGenerator {
}
}
private void prepareBlockPartCeiling(BlockData up, BlockData orig, ChunkData chunk, Vector3 block, Map<BlockType, Palette> slabs,
Map<BlockType, Palette> stairs, double thresh, Sampler sampler) {
private void prepareBlockPartCeiling(BlockData up, BlockData orig, ChunkData chunk, Vector3 block, Map<BlockType, Palette<BlockData>> slabs,
Map<BlockType, Palette<BlockData>> stairs, double thresh, Sampler sampler) {
if(sampler.sample(block.getX(), block.getY() + 0.4, block.getZ()) > thresh) {
if(stairs != null) {
Palette stairPalette = stairs.get(up.getBlockType());
Palette<BlockData> stairPalette = stairs.get(up.getBlockType());
if(stairPalette != null) {
BlockData stair = stairPalette.get(0, block.getX(), block.getY(), block.getZ()).clone();
if(stair instanceof Stairs) {
@@ -227,17 +227,20 @@ public class DefaultChunkGenerator3D implements TerraChunkGenerator {
return false;
}
@SuppressWarnings({"try"})
static void biomes(@NotNull World world, int chunkX, int chunkZ, @NotNull BiomeGrid biome, TerraPlugin main) {
int xOrig = (chunkX << 4);
int zOrig = (chunkZ << 4);
BiomeProvider grid = main.getWorld(world).getBiomeProvider();
for(int x = 0; x < 4; x++) {
for(int z = 0; z < 4; z++) {
int cx = xOrig + (x << 2);
int cz = zOrig + (z << 2);
TerraBiome b = grid.getBiome(cx, cz);
try(ProfileFrame ignore = main.getProfiler().profile("biomes")) {
int xOrig = (chunkX << 4);
int zOrig = (chunkZ << 4);
BiomeProvider grid = main.getWorld(world).getBiomeProvider();
for(int x = 0; x < 4; x++) {
for(int z = 0; z < 4; z++) {
int cx = xOrig + (x << 2);
int cz = zOrig + (z << 2);
TerraBiome b = grid.getBiome(cx, cz);
biome.setBiome(cx, cz, b.getVanillaBiomes().get(b.getGenerator(world).getBiomeNoise(), cx, 0, cz));
biome.setBiome(cx, cz, b.getVanillaBiomes().get(b.getGenerator(world).getBiomeNoise(), cx, 0, cz));
}
}
}
}
@@ -25,7 +25,7 @@ public class SamplerCache {
public Sampler load(@NotNull Long key) {
int cx = (int) (key >> 32);
int cz = (int) key.longValue();
return world.getGenerator().createSampler(cx, cz, world.getBiomeProvider(), world.getWorld(), world.getConfig().getTemplate().getElevationBlend());
return world.getWorld().getTerraGenerator().createSampler(cx, cz, world.getBiomeProvider(), world.getWorld(), world.getConfig().getTemplate().getElevationBlend());
}
});
}
@@ -0,0 +1,88 @@
package com.dfsek.terra.world.generation.math.interpolation;
import com.dfsek.terra.api.math.vector.Vector3;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.api.util.mutable.MutableInteger;
import com.dfsek.terra.api.world.biome.Generator;
import com.dfsek.terra.api.world.biome.provider.BiomeProvider;
import net.jafama.FastMath;
import java.util.HashMap;
import java.util.Map;
import java.util.function.BiFunction;
/**
* Class to abstract away the Interpolators needed to generate a chunk.<br>
* Contains method to get interpolated noise at a coordinate within the chunk.
*/
public class ChunkInterpolator2D implements ChunkInterpolator {
private final Interpolator[][] interpGrid = new Interpolator[4][4];
private final BiFunction<Generator, Vector3, Double> noiseGetter;
/**
* Instantiates a 3D ChunkInterpolator3D at a pair of chunk coordinates.
*
* @param chunkX X coordinate of the chunk.
* @param chunkZ Z coordinate of the chunk.
* @param provider Biome Provider to use for biome fetching.
*/
public ChunkInterpolator2D(World w, int chunkX, int chunkZ, BiomeProvider provider, BiFunction<Generator, Vector3, Double> noiseGetter) {
this.noiseGetter = noiseGetter;
int xOrigin = chunkX << 4;
int zOrigin = chunkZ << 4;
double[][] noiseStorage = new double[5][5];
for(int x = 0; x < 5; x++) {
for(int z = 0; z < 5; z++) {
Generator generator = provider.getBiome(xOrigin + (x << 2), zOrigin + (z << 2)).getGenerator(w);
Map<Generator, MutableInteger> genMap = new HashMap<>();
int step = generator.getBlendStep();
int blend = generator.getBlendDistance();
for(int xi = -blend; xi <= blend; xi++) {
for(int zi = -blend; zi <= blend; zi++) {
genMap.computeIfAbsent(provider.getBiome(xOrigin + (x << 2) + (xi * step), zOrigin + (z << 2) + (zi * step)).getGenerator(w), g -> new MutableInteger(0)).increment(); // Increment by 1
}
}
noiseStorage[x][z] = computeNoise(genMap, (x << 2) + xOrigin, 0, (z << 2) + zOrigin);
}
}
for(int x = 0; x < 4; x++) {
for(int z = 0; z < 4; z++) {
interpGrid[x][z] = new Interpolator(
noiseStorage[x][z],
noiseStorage[x + 1][z],
noiseStorage[x][z + 1],
noiseStorage[x + 1][z + 1]);
}
}
}
private static int reRange(int value, int high) {
return FastMath.max(FastMath.min(value, high), 0);
}
public double computeNoise(Generator generator, double x, double y, double z) {
return noiseGetter.apply(generator, new Vector3(x, y, z));
}
/**
* 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.
*/
@Override
public double getNoise(double x, double y, double z) {
return interpGrid[reRange(((int) x) / 4, 3)][reRange(((int) z) / 4, 3)].bilerp((x % 4) / 4, (z % 4) / 4);
}
public double getNoise(int x, int y, int z) {
return interpGrid[x / 4][z / 4].bilerp((double) (x % 4) / 4, (double) (z % 4) / 4);
}
}
@@ -67,7 +67,7 @@ public class ChunkInterpolator3D implements ChunkInterpolator {
for(int x = 0; x < 4; x++) {
for(int z = 0; z < 4; z++) {
for(int y = 0; y < size; y++) {
interpGrid[x][y][z] = new TrilinearInterpolator(
interpGrid[x][y][z] = new Interpolator3(
noiseStorage[x][z][y],
noiseStorage[x + 1][z][y],
noiseStorage[x][z][y + 1],
@@ -75,7 +75,7 @@ public class ChunkInterpolator3D implements ChunkInterpolator {
noiseStorage[x][z + 1][y],
noiseStorage[x + 1][z + 1][y],
noiseStorage[x][z + 1][y + 1],
noiseStorage[x + 1][z + 1][y + 1], 4, 4, 4);
noiseStorage[x + 1][z + 1][y + 1]);
}
}
}
@@ -98,10 +98,10 @@ public class ChunkInterpolator3D implements ChunkInterpolator {
*/
@Override
public double getNoise(double x, double y, double z) {
return interpGrid[reRange(((int) x) / 4, 3)][FastMath.max(FastMath.min(((int) y), max), min) / 4][reRange(((int) z) / 4, 3)].interpolate((x % 4), (y % 4), (z % 4));
return interpGrid[reRange(((int) x) / 4, 3)][FastMath.max(FastMath.min(((int) y), max), min) / 4][reRange(((int) z) / 4, 3)].trilerp((x % 4) / 4, (y % 4) / 4, (z % 4) / 4);
}
public double getNoise(int x, int y, int z) {
return interpGrid[x / 4][y / 4][z / 4].interpolate(x % 4, y % 4, z % 4);
return interpGrid[x / 4][y / 4][z / 4].trilerp((double) (x % 4) / 4, (double) (y % 4) / 4, (double) (z % 4) / 4);
}
}
@@ -3,26 +3,22 @@ package com.dfsek.terra.world.generation.math.interpolation;
/**
* Class for bilinear interpolation of values arranged on a unit square.
*/
public class BilinearInterpolator implements Interpolator2 {
public class Interpolator {
private final double v0, v1, v2, v3;
private final double width, height;
/**
* Constructs an interpolator with given values as vertices of a unit square.
* @param v0 - (0,0)
*
* @param v0 - (0,0)
* @param v1 - (1,0)
* @param v2 - (0,1)
* @param v3 - (1,1)
* @param width
* @param height
*/
public BilinearInterpolator(double v0, double v1, double v2, double v3, double width, double height) {
public Interpolator(double v0, double v1, double v2, double v3) {
this.v0 = v0;
this.v1 = v1;
this.v2 = v2;
this.v3 = v3;
this.width = width;
this.height = height;
}
/**
@@ -44,10 +40,7 @@ public class BilinearInterpolator implements Interpolator2 {
* @param t - Z value
* @return double - The interpolated value.
*/
@Override
public double interpolate(double s, double t) {
s/=width;
t/=height;
public double bilerp(double s, double t) {
double v01 = lerp(s, v0, v1);
double v23 = lerp(s, v2, v3);
return lerp(t, v01, v23);
@@ -1,12 +0,0 @@
package com.dfsek.terra.world.generation.math.interpolation;
public interface Interpolator2 {
/**
* 2D Bilinear interpolation between 4 points on a unit square.
*
* @param s - X value
* @param t - Z value
* @return double - The interpolated value.
*/
double interpolate(double s, double t);
}
@@ -1,5 +1,32 @@
package com.dfsek.terra.world.generation.math.interpolation;
public interface Interpolator3 {
double interpolate(double x, double y, double z);
/**
* Class for bilinear interpolation of values arranged on a unit square.
*/
public class Interpolator3 {
private final Interpolator bottom;
private final Interpolator top;
/**
* Constructs an interpolator with given values as vertices of a unit cube.
* * @param _000 The value at <code>(t, u, v) = (0, 0, 0)</code>.
* * @param _100 The value at <code>(t, u, v) = (1, 0, 0)</code>.
* * @param _010 The value at <code>(t, u, v) = (0, 1, 0)</code>.
* * @param _110 The value at <code>(t, u, v) = (1, 1, 0)</code>.
* * @param _001 The value at <code>(t, u, v) = (0, 0, 1)</code>.
* * @param _101 The value at <code>(t, u, v) = (1, 0, 1)</code>.
* * @param _011 The value at <code>(t, u, v) = (0, 1, 1)</code>.
* * @param _111 The value at <code>(t, u, v) = (1, 1, 1)</code>.
*/
public Interpolator3(double _000, double _100,
double _010, double _110,
double _001, double _101,
double _011, double _111) {
this.top = new Interpolator(_000, _010, _001, _011);
this.bottom = new Interpolator(_100, _110, _101, _111);
}
public double trilerp(double x, double y, double z) {
return Interpolator.lerp(x, top.bilerp(y, z), bottom.bilerp(y, z));
}
}
@@ -1,40 +0,0 @@
package com.dfsek.terra.world.generation.math.interpolation;
/**
* Class for bilinear interpolation of values arranged on a unit square.
*/
public class TrilinearInterpolator implements Interpolator3 {
private final BilinearInterpolator bottom;
private final BilinearInterpolator top;
private final double length, width, height;
/**
* Constructs an interpolator with given values as vertices of a unit cube.
* * @param _000 The value at <code>(t, u, v) = (0, 0, 0)</code>.
* * @param _100 The value at <code>(t, u, v) = (1, 0, 0)</code>.
* * @param _010 The value at <code>(t, u, v) = (0, 1, 0)</code>.
* * @param _110 The value at <code>(t, u, v) = (1, 1, 0)</code>.
* * @param _001 The value at <code>(t, u, v) = (0, 0, 1)</code>.
* * @param _101 The value at <code>(t, u, v) = (1, 0, 1)</code>.
* * @param _011 The value at <code>(t, u, v) = (0, 1, 1)</code>.
* * @param _111 The value at <code>(t, u, v) = (1, 1, 1)</code>.
*/
public TrilinearInterpolator(double _000, double _100,
double _010, double _110,
double _001, double _101,
double _011, double _111, double length, double width, double height) {
this.length = length;
this.width = width;
this.height = height;
this.top = new BilinearInterpolator(_000, _010, _001, _011, 1, 1);
this.bottom = new BilinearInterpolator(_100, _110, _101, _111, 1, 1);
}
@Override
public double interpolate(double x, double y, double z) {
x/=length;
z/=width;
y/=height;
return BilinearInterpolator.lerp(x, top.interpolate(y, z), bottom.interpolate(y, z));
}
}
@@ -0,0 +1,27 @@
package com.dfsek.terra.world.generation.math.samplers;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.api.world.biome.provider.BiomeProvider;
import com.dfsek.terra.world.generation.math.interpolation.ChunkInterpolator2D;
import com.dfsek.terra.world.generation.math.interpolation.ElevationInterpolator;
import net.jafama.FastMath;
public class Sampler2D implements Sampler {
private final ChunkInterpolator2D interpolator;
private final ElevationInterpolator elevationInterpolator;
public Sampler2D(int x, int z, BiomeProvider provider, World world, int elevationSmooth) {
this.interpolator = new ChunkInterpolator2D(world, x, z, provider, (generator, coord) -> generator.getBaseSampler().getNoise(coord));
this.elevationInterpolator = new ElevationInterpolator(world, x, z, provider, elevationSmooth);
}
@Override
public double sample(double x, double y, double z) {
return interpolator.getNoise(x, 0, z) + elevationInterpolator.getElevation(FastMath.roundToInt(x), FastMath.roundToInt(z));
}
@Override
public double sample(int x, int y, int z) {
return interpolator.getNoise(x, 0, z) + elevationInterpolator.getElevation(FastMath.roundToInt(x), FastMath.roundToInt(z));
}
}
@@ -1,22 +0,0 @@
package com.dfsek.terra.world.generation.math.samplers.terrain;
import com.dfsek.paralithic.Expression;
import com.dfsek.terra.world.generation.math.interpolation.Interpolator3;
public class ExpressionSampler implements TerrainSampler {
private final Expression expression;
public ExpressionSampler(Expression expression) {
this.expression = expression;
}
@Override
public Interpolator3 sample(double x, double y, double z) {
return (i, i1, i2) -> expression.evaluate(x, y, z);
}
@Override
public int getXResolution() {
return 1;
}
}
@@ -1,31 +0,0 @@
package com.dfsek.terra.world.generation.math.samplers.terrain;
import com.dfsek.terra.world.generation.math.interpolation.Interpolator3;
public class InterpolatedSampler implements TerrainSampler {
private final InterpolatorSupplier supplier;
public InterpolatedSampler(InterpolatorSupplier supplier) {
this.supplier = supplier;
}
@Override
public Interpolator3 sample(double x, double y, double z) {
return null;
}
@Override
public int getXResolution() {
return supplier.getXResolution();
}
@Override
public int getYResolution() {
return supplier.getYResolution();
}
@Override
public int getZResolution() {
return supplier.getZResolution();
}
}
@@ -1,19 +0,0 @@
package com.dfsek.terra.world.generation.math.samplers.terrain;
import com.dfsek.terra.world.generation.math.interpolation.Interpolator2;
import com.dfsek.terra.world.generation.math.interpolation.Interpolator3;
import java.util.function.Supplier;
public interface InterpolatorSupplier {
int getXResolution();
int getYResolution();
int getZResolution();
Interpolator2 get(double t, double v0, double v1);
Interpolator3 get(double _000, double _100,
double _010, double _110,
double _001, double _101,
double _011, double _111);
}
@@ -1,22 +0,0 @@
package com.dfsek.terra.world.generation.math.samplers.terrain;
import com.dfsek.terra.world.generation.math.interpolation.Interpolator2;
import com.dfsek.terra.world.generation.math.interpolation.Interpolator3;
public interface TerrainSampler {
Interpolator3 sample(double x, double y, double z);
default Interpolator2 sample(double x, double z) {
return (s, t) -> sample(x, 0, z).interpolate(s, 0, t);
}
int getXResolution();
default int getYResolution() {
return getXResolution();
}
default int getZResolution() {
return getXResolution();
}
}
@@ -33,7 +33,7 @@ public class FloraPopulator implements TerraBlockPopulator {
public void populate(@NotNull World world, @NotNull Chunk chunk) {
TerraWorld tw = main.getWorld(world);
try(ProfileFrame ignore = main.getProfiler().profile("flora")) {
if(tw.getConfig().getTemplate().disableCarvers()) return;
if(tw.getConfig().getTemplate().disableFlora()) return;
if(!tw.isSafe()) return;
BiomeProvider provider = tw.getBiomeProvider();
@@ -28,7 +28,7 @@ public class OrePopulator implements TerraBlockPopulator {
public void populate(@NotNull World world, @NotNull Chunk chunk) {
TerraWorld tw = main.getWorld(world);
try(ProfileFrame ignore = main.getProfiler().profile("ore")) {
if(tw.getConfig().getTemplate().disableCarvers()) return;
if(tw.getConfig().getTemplate().disableOres()) return;
if(!tw.isSafe()) return;
for(int cx = -1; cx <= 1; cx++) {
@@ -32,7 +32,7 @@ public class StructurePopulator implements TerraBlockPopulator, Chunkified {
public void populate(@NotNull World world, @NotNull Chunk chunk) {
TerraWorld tw = main.getWorld(world);
try(ProfileFrame ignore = main.getProfiler().profile("structure")) {
if(tw.getConfig().getTemplate().disableCarvers()) return;
if(tw.getConfig().getTemplate().disableStructures()) return;
int cx = (chunk.getX() << 4);
int cz = (chunk.getZ() << 4);
@@ -33,7 +33,7 @@ public class TreePopulator implements TerraBlockPopulator {
public void populate(@NotNull World world, @NotNull Chunk chunk) {
TerraWorld tw = main.getWorld(world);
try(ProfileFrame ignore = main.getProfiler().profile("tree")) {
if(tw.getConfig().getTemplate().disableCarvers()) return;
if(tw.getConfig().getTemplate().disableTrees()) return;
if(!tw.isSafe()) return;
BiomeProvider provider = tw.getBiomeProvider();
@@ -22,7 +22,7 @@ import java.util.ArrayList;
import java.util.List;
public class TerraFlora implements Flora {
private final Palette floraPalette;
private final Palette<BlockData> floraPalette;
private final boolean physics;
private final boolean ceiling;
@@ -43,7 +43,7 @@ public class TerraFlora implements Flora {
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, TerraPlugin main) {
public TerraFlora(Palette<BlockData> 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;
@@ -0,0 +1,364 @@
package biome;
import com.dfsek.tectonic.abstraction.AbstractConfigLoader;
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.tectonic.config.ValidatedConfigTemplate;
import com.dfsek.tectonic.exception.ConfigException;
import com.dfsek.tectonic.loading.ConfigLoader;
import com.dfsek.tectonic.loading.TypeRegistry;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.addons.TerraAddon;
import com.dfsek.terra.api.event.EventManager;
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.api.registry.CheckedRegistry;
import com.dfsek.terra.api.registry.LockedRegistry;
import com.dfsek.terra.api.task.TaskScheduler;
import com.dfsek.terra.api.util.collections.ProbabilityCollection;
import com.dfsek.terra.api.util.logging.DebugLogger;
import com.dfsek.terra.api.util.logging.JavaLogger;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.api.world.biome.Generator;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.biome.provider.BiomeProvider;
import com.dfsek.terra.config.GenericLoaders;
import com.dfsek.terra.config.PluginConfig;
import com.dfsek.terra.config.builder.BiomeBuilder;
import com.dfsek.terra.config.fileloaders.FolderLoader;
import com.dfsek.terra.config.lang.Language;
import com.dfsek.terra.config.loaders.ProbabilityCollectionLoader;
import com.dfsek.terra.config.loaders.config.BufferedImageLoader;
import com.dfsek.terra.config.loaders.config.biome.BiomeProviderBuilderLoader;
import com.dfsek.terra.config.loaders.config.biome.templates.provider.BiomePipelineTemplate;
import com.dfsek.terra.config.loaders.config.biome.templates.provider.ImageProviderTemplate;
import com.dfsek.terra.config.loaders.config.biome.templates.provider.SingleBiomeProviderTemplate;
import com.dfsek.terra.config.loaders.config.sampler.NoiseSamplerBuilderLoader;
import com.dfsek.terra.config.pack.ConfigPack;
import com.dfsek.terra.config.templates.AbstractableTemplate;
import com.dfsek.terra.config.templates.BiomeTemplate;
import com.dfsek.terra.profiler.Profiler;
import com.dfsek.terra.registry.config.BiomeRegistry;
import com.dfsek.terra.registry.config.NoiseRegistry;
import com.dfsek.terra.world.TerraWorld;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.WritableRaster;
import java.io.File;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ThreadLocalRandom;
import java.util.logging.Logger;
public class DistributionTest {
private static final TerraPlugin MAIN = new TerraPlugin() {
@Override
public WorldHandle getWorldHandle() {
return null;
}
@Override
public TerraWorld getWorld(World world) {
return null;
}
@Override
public com.dfsek.terra.api.util.logging.Logger logger() {
return new JavaLogger(Logger.getLogger("Terra"));
}
@Override
public PluginConfig getTerraConfig() {
return new PluginConfig();
}
@Override
public File getDataFolder() {
return null;
}
@Override
public boolean isDebug() {
return false;
}
@Override
public Language getLanguage() {
return null;
}
@Override
public CheckedRegistry<ConfigPack> getConfigRegistry() {
return null;
}
@Override
public LockedRegistry<TerraAddon> getAddons() {
return null;
}
@Override
public boolean reload() {
return true;
}
@Override
public ItemHandle getItemHandle() {
return null;
}
@Override
public void saveDefaultConfig() {
}
@Override
public String platformName() {
return null;
}
@Override
public DebugLogger getDebugLogger() {
return new DebugLogger(new JavaLogger(Logger.getLogger("Terra")));
}
@Override
public EventManager getEventManager() {
return null;
}
@Override
public TaskScheduler getScheduler() {
return null;
}
@Override
public Profiler getProfiler() {
return null;
}
@Override
public void register(TypeRegistry registry) {
}
};
private static BiomeProvider getProvider(long seed) throws ConfigException, IOException {
System.out.println(seed);
File pack = new File("/home/dfsek/Documents/Terra/platforms/bukkit/target/server/plugins/Terra/packs/default/");
FolderLoader folderLoader = new FolderLoader(pack.toPath());
AbstractConfigLoader loader = new AbstractConfigLoader();
new GenericLoaders(MAIN).register(loader);
BiomeRegistry biomeRegistry = new BiomeRegistry();
folderLoader.open("biomes", ".yml").then(inputStreams -> ConfigPack.buildAll((template, main) -> template, biomeRegistry, loader.loadConfigs(inputStreams, TestBiome::new), MAIN));
BiomeProviderTemplate template = new BiomeProviderTemplate();
ConfigLoader pipeLoader = new ConfigLoader()
.registerLoader(BiomeProvider.BiomeProviderBuilder.class, new BiomeProviderBuilderLoader())
.registerLoader(ProbabilityCollection.class, new ProbabilityCollectionLoader())
.registerLoader(BiomeBuilder.class, biomeRegistry)
.registerLoader(BufferedImage.class, new BufferedImageLoader(folderLoader))
.registerLoader(SingleBiomeProviderTemplate.class, SingleBiomeProviderTemplate::new)
.registerLoader(BiomePipelineTemplate.class, () -> new BiomePipelineTemplate(MAIN))
.registerLoader(ImageProviderTemplate.class, () -> new ImageProviderTemplate(biomeRegistry));
new GenericLoaders(MAIN).register(pipeLoader);
pipeLoader.registerLoader(NoiseSeeded.class, new NoiseSamplerBuilderLoader(new NoiseRegistry()));
pipeLoader.load(template, folderLoader.get("pack.yml"));
return template.getBiomeProviderBuilder().build(seed);
}
public static void main(String... args) throws ConfigException, IOException {
JFrame testFrame = new JFrame("Biome Viewer");
final BiomeProvider[] provider = {getProvider(2403)};
int size = 1024;
final BufferedImage[] image = {new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB)};
for(int x = 0; x < size; x++) {
for(int z = 0; z < size; z++) {
image[0].setRGB(x, z, provider[0].getBiome(x, z).getColor());
}
}
JLabel img = new JLabel(new ImageIcon(image[0]));
testFrame.add(img);
testFrame.pack();
img.addMouseListener(new MouseListener() {
@Override
public void mouseClicked(MouseEvent e) {
BufferedImage newImage = deepCopy(image[0]);
Graphics graphics = newImage.getGraphics();
graphics.setColor(Color.WHITE);
graphics.fillRect(0, 0, 512, 24);
graphics.setColor(Color.BLACK);
graphics.setFont(new Font("Monospace", Font.BOLD, 20));
graphics.drawString(provider[0].getBiome(e.getX(), e.getY()).toString(), 0, 20);
graphics.setColor(Color.WHITE);
graphics.fillOval(e.getX() - 2, e.getY() - 2, 12, 12);
graphics.setColor(Color.BLACK);
graphics.fillOval(e.getX(), e.getY(), 8, 8);
img.setIcon(new ImageIcon(newImage));
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
});
testFrame.addKeyListener(new KeyListener() {
@Override
public void keyTyped(KeyEvent e) {
if(e.getKeyChar() == 's') {
long l = System.nanoTime();
try {
provider[0] = getProvider(ThreadLocalRandom.current().nextLong());
} catch(ConfigException | IOException configException) {
configException.printStackTrace();
}
image[0] = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB);
for(int x = 0; x < size; x++) {
for(int z = 0; z < size; z++) {
image[0].setRGB(x, z, provider[0].getBiome(x, z).getColor());
}
}
long n = System.nanoTime();
double t = n - l;
System.out.println("Time: " + t / 1000000 + "ms");
img.setIcon(new ImageIcon(image[0]));
}
}
@Override
public void keyPressed(KeyEvent e) {
}
@Override
public void keyReleased(KeyEvent e) {
}
});
testFrame.setResizable(false);
testFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
testFrame.setVisible(true);
}
private static BufferedImage deepCopy(BufferedImage bi) {
ColorModel cm = bi.getColorModel();
boolean isAlphaPremultiplied = cm.isAlphaPremultiplied();
WritableRaster raster = bi.copyData(null);
return new BufferedImage(cm, raster, isAlphaPremultiplied, null);
}
private static final class BiomeProviderTemplate implements ConfigTemplate {
@Value("biomes")
BiomeProvider.BiomeProviderBuilder biomeProviderBuilder;
public BiomeProvider.BiomeProviderBuilder getBiomeProviderBuilder() {
return biomeProviderBuilder;
}
}
private static final class TestBiome extends AbstractableTemplate implements TerraBiome, ValidatedConfigTemplate, BiomeBuilder {
@Value("color")
@Default
@Abstractable
private int color;
@Value("tags")
@Abstractable
@Default
private Set<String> tags = new HashSet<>();
@Value("id")
private String id;
@Override
public ProbabilityCollection<Biome> getVanillaBiomes() {
return null;
}
@Override
public BiomeTemplate getTemplate() {
return null;
}
@Override
public Generator getGenerator(World w) {
return null;
}
@Override
public int getColor() {
return color;
}
@Override
public Set<String> getTags() {
return tags;
}
@Override
public boolean validate() {
color += (255 << 24); // Alpha adjustment
tags.add("BIOME:" + id);
return true;
}
@Override
public String getID() {
return id;
}
@Override
public String toString() {
return id;
}
@Override
public TestBiome apply(Long aLong) {
return this;
}
}
}
+218
View File
@@ -0,0 +1,218 @@
package biome;
import com.dfsek.tectonic.abstraction.AbstractConfigLoader;
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.tectonic.config.ValidatedConfigTemplate;
import com.dfsek.tectonic.exception.ConfigException;
import com.dfsek.terra.api.platform.world.Biome;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.api.util.collections.ProbabilityCollection;
import com.dfsek.terra.api.world.biome.Generator;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.biome.provider.BiomeProvider;
import com.dfsek.terra.api.world.biome.provider.ImageBiomeProvider;
import com.dfsek.terra.config.fileloaders.FolderLoader;
import com.dfsek.terra.config.pack.ConfigPack;
import com.dfsek.terra.config.templates.AbstractableTemplate;
import com.dfsek.terra.registry.OpenRegistry;
import org.junit.jupiter.api.Test;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.WritableRaster;
import java.io.File;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ThreadLocalRandom;
public class ImageTest {
private static ImageBiomeProvider getProvider(long seed) throws ConfigException, IOException {
System.out.println(seed);
File pack = new File("/home/dfsek/Documents/Terra/platforms/bukkit/target/server/plugins/Terra/packs/default/");
FolderLoader folderLoader = new FolderLoader(pack.toPath());
AbstractConfigLoader loader = new AbstractConfigLoader();
OpenRegistry<TerraBiome> biomeRegistry = new OpenRegistry<TerraBiome>() {
};
folderLoader.open("biomes", ".yml").then(inputStreams -> ConfigPack.buildAll((template, main) -> template, biomeRegistry, loader.loadConfigs(inputStreams, TestBiome::new), null));
return new ImageBiomeProvider(biomeRegistry.entries(), ImageIO.read(ImageTest.class.getResourceAsStream("/map.jpg")), 1, ImageBiomeProvider.Align.CENTER);
}
@Test
public static void main(String... args) throws ConfigException, IOException {
JFrame testFrame = new JFrame("Biome Viewer");
final BiomeProvider[] provider = {getProvider(2403)};
int size = 1024;
final BufferedImage[] image = {new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB)};
for(int x = 0; x < size; x++) {
for(int z = 0; z < size; z++) {
image[0].setRGB(x, z, provider[0].getBiome(x, z).getColor());
}
}
JLabel img = new JLabel(new ImageIcon(image[0]));
testFrame.add(img);
testFrame.pack();
img.addMouseListener(new MouseListener() {
@Override
public void mouseClicked(MouseEvent e) {
BufferedImage newImage = deepCopy(image[0]);
Graphics graphics = newImage.getGraphics();
graphics.setColor(Color.WHITE);
graphics.fillRect(0, 0, 512, 24);
graphics.setColor(Color.BLACK);
graphics.setFont(new Font("Monospace", Font.BOLD, 20));
graphics.drawString(provider[0].getBiome(e.getX(), e.getY()).toString(), 0, 20);
graphics.setColor(Color.WHITE);
graphics.fillOval(e.getX() - 2, e.getY() - 2, 12, 12);
graphics.setColor(Color.BLACK);
graphics.fillOval(e.getX(), e.getY(), 8, 8);
img.setIcon(new ImageIcon(newImage));
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
});
testFrame.addKeyListener(new KeyListener() {
@Override
public void keyTyped(KeyEvent e) {
if(e.getKeyChar() == 's') {
try {
provider[0] = getProvider(ThreadLocalRandom.current().nextLong());
} catch(ConfigException | IOException configException) {
configException.printStackTrace();
}
image[0] = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB);
for(int x = 0; x < size; x++) {
for(int z = 0; z < size; z++) {
image[0].setRGB(x, z, provider[0].getBiome(x, z).getColor());
}
}
img.setIcon(new ImageIcon(image[0]));
}
}
@Override
public void keyPressed(KeyEvent e) {
}
@Override
public void keyReleased(KeyEvent e) {
}
});
testFrame.setResizable(false);
testFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
testFrame.setVisible(true);
}
private static BufferedImage deepCopy(BufferedImage bi) {
ColorModel cm = bi.getColorModel();
boolean isAlphaPremultiplied = cm.isAlphaPremultiplied();
WritableRaster raster = bi.copyData(null);
return new BufferedImage(cm, raster, isAlphaPremultiplied, null);
}
private static final class BiomeProviderTemplate implements ConfigTemplate {
@Value("biome-pipeline")
BiomeProvider.BiomeProviderBuilder biomeProviderBuilder;
public BiomeProvider.BiomeProviderBuilder getBiomeProviderBuilder() {
return biomeProviderBuilder;
}
}
private static final class TestBiome extends AbstractableTemplate implements TerraBiome, ValidatedConfigTemplate {
@Value("color")
@Default
@Abstractable
private int color;
@Value("tags")
@Abstractable
@Default
private Set<String> tags = new HashSet<>();
@Value("id")
private String id;
@Override
public ProbabilityCollection<Biome> getVanillaBiomes() {
return null;
}
@Override
public Generator getGenerator(World w) {
return null;
}
@Override
public int getColor() {
return color;
}
@Override
public Set<String> getTags() {
return tags;
}
@Override
public boolean validate() {
color += (255 << 24); // Alpha adjustment
tags.add("BIOME:" + id);
return true;
}
@Override
public String getID() {
return id;
}
@Override
public String toString() {
return id;
}
}
}
+10
View File
@@ -0,0 +1,10 @@
# Magic options for more perf
org.gradle.jvmargs=-Xmx2048M -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -XX:+UseParallelGC
org.gradle.vfs.watch=true
kapt.use.worker.api=true
kapt.include.compile.classpath=false
org.gradle.parallel=true
org.gradle.caching=true
org.gradle.warning.mode=all
#org.gradle.logging.level=info
org.gradle.configureondemand=true
+1 -1
View File
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
org.gradle.jvmargs=-Xmx4096m
+2 -2
View File
@@ -70,8 +70,8 @@ fun installServer(dir: String) {
// Cloning test setup.
gitClone("https://github.com/PolyhedralDev/WorldGenTestServer")
// Copying plugins
Files.move(Paths.get("WorldGenTestServer/plugins"),
Paths.get("$testDir/$dir/plugins"),
Files.move(file("WorldGenTestServer/plugins").toPath(),
file("$testDir/$dir/plugins").toPath(),
StandardCopyOption.REPLACE_EXISTING)
// Copying config
val serverText = URL("https://raw.githubusercontent.com/PolyhedralDev/WorldGenTestServer/master/server.properties").readText()
@@ -18,6 +18,7 @@ import com.dfsek.terra.api.platform.world.Biome;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.api.registry.CheckedRegistry;
import com.dfsek.terra.api.registry.LockedRegistry;
import com.dfsek.terra.api.task.TaskScheduler;
import com.dfsek.terra.api.util.logging.DebugLogger;
import com.dfsek.terra.api.util.logging.JavaLogger;
import com.dfsek.terra.api.util.logging.Logger;
@@ -32,8 +33,10 @@ import com.dfsek.terra.bukkit.listeners.CommonListener;
import com.dfsek.terra.bukkit.listeners.PaperListener;
import com.dfsek.terra.bukkit.listeners.SpigotListener;
import com.dfsek.terra.bukkit.listeners.TerraListener;
import com.dfsek.terra.bukkit.task.BukkitTaskScheduler;
import com.dfsek.terra.bukkit.util.PaperUtil;
import com.dfsek.terra.bukkit.world.BukkitBiome;
import com.dfsek.terra.bukkit.world.BukkitWorld;
import com.dfsek.terra.commands.CommandUtil;
import com.dfsek.terra.config.GenericLoaders;
import com.dfsek.terra.config.PluginConfig;
@@ -68,6 +71,8 @@ public class TerraBukkitPlugin extends JavaPlugin implements TerraPlugin {
private final Profiler profiler = new ProfilerImpl();
private final TaskScheduler scheduler = new BukkitTaskScheduler(this);
private final ConfigRegistry registry = new ConfigRegistry();
private final CheckedRegistry<ConfigPack> checkedRegistry = new CheckedRegistry<>(registry);
@@ -150,6 +155,11 @@ public class TerraBukkitPlugin extends JavaPlugin implements TerraPlugin {
return profiler;
}
@Override
public TaskScheduler getScheduler() {
return scheduler;
}
@Override
public void onDisable() {
BukkitChunkGeneratorWrapper.saveAll();
@@ -268,14 +278,15 @@ public class TerraBukkitPlugin extends JavaPlugin implements TerraPlugin {
return checkedRegistry;
}
public TerraWorld getWorld(World w) {
if(!TerraWorld.isTerraWorld(w))
public TerraWorld getWorld(World world) {
BukkitWorld w = (BukkitWorld) world;
if(!w.isTerraWorld())
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, ((TerraChunkGenerator) w.getGenerator().getHandle()).getConfigPack(), this);
}
return worldMap.computeIfAbsent(w, world -> new TerraWorld(w, worlds.get(w.getName()), this));
return worldMap.computeIfAbsent(w, w2 -> new TerraWorld(w, worlds.get(w.getName()), this));
}
@Override
@@ -52,7 +52,7 @@ public class BukkitChunkGeneratorWrapper extends ChunkGenerator implements Gener
}
public static synchronized void fixChunk(Chunk c) {
if(!TerraWorld.isTerraWorld(c.getWorld())) throw new IllegalArgumentException();
if(!c.getWorld().isTerraWorld()) throw new IllegalArgumentException();
popMap.get(c.getWorld()).checkNeighbors(c.getX(), c.getZ(), c.getWorld());
}
@@ -28,6 +28,6 @@ public class BukkitWorldHandle implements WorldHandle {
@Override
public Pair<Location, Location> getSelectedLocation(Player player) {
org.bukkit.Location[] locations = WorldEditUtil.getSelectionLocations(BukkitAdapter.adapt(player));
return Pair.of(BukkitAdapter.adapt(locations[0]), BukkitAdapter.adapt(locations[1]));
return new Pair<>(BukkitAdapter.adapt(locations[0]), BukkitAdapter.adapt(locations[1]));
}
}
@@ -44,7 +44,7 @@ public class CommonListener implements Listener {
public void onSaplingGrow(StructureGrowEvent e) {
if(e.isCancelled()) return;
World bukkit = BukkitAdapter.adapt(e.getWorld());
if(!TerraWorld.isTerraWorld(bukkit)) return;
if(!bukkit.isTerraWorld()) return;
TerraWorld tw = main.getWorld(bukkit);
WorldConfig c = tw.getConfig();
if(c.getTemplate().isDisableSaplings()) return;
@@ -52,7 +52,7 @@ public class CommonListener implements Listener {
Block block = e.getLocation().getBlock();
BlockData data = block.getBlockData();
block.setType(Material.AIR);
Tree tree = c.getRegistry(Tree.class).get(TREE_TYPE_STRING_TRANSFORMER.translate(e.getSpecies()));
Tree tree = c.getTreeRegistry().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);
}
@@ -18,12 +18,12 @@ public class PaperListener implements Listener {
@EventHandler
public void onStructureLocate(StructureLocateEvent e) {
if(!TerraWorld.isTerraWorld(BukkitAdapter.adapt(e.getWorld()))) return;
if(!BukkitAdapter.adapt(e.getWorld()).isTerraWorld()) return;
e.setResult(null); // Assume no result.
String name = "minecraft:" + e.getType().getName();
main.getDebugLogger().info("Overriding structure location for \"" + name + "\"");
TerraWorld tw = main.getWorld(BukkitAdapter.adapt(e.getWorld()));
TerraStructure config = tw.getConfig().getRegistry(TerraStructure.class).get(tw.getConfig().getTemplate().getLocatable().get(name));
TerraStructure config = tw.getConfig().getStructureRegistry().get(tw.getConfig().getTemplate().getLocatable().get(name));
if(config != null) {
AsyncStructureFinder finder = new AsyncStructureFinder(tw.getBiomeProvider(), config, BukkitAdapter.adapt(e.getOrigin()), 0, 500, location -> {
if(location != null)
@@ -34,10 +34,10 @@ public class SpigotListener implements Listener {
Entity entity = e.getEntity();
if(e.getEntityType().equals(EntityType.ENDER_SIGNAL)) {
main.getDebugLogger().info("Detected Ender Signal...");
if(!TerraWorld.isTerraWorld(BukkitAdapter.adapt(e.getEntity().getWorld()))) return;
if(!BukkitAdapter.adapt(e.getEntity().getWorld()).isTerraWorld()) return;
TerraWorld tw = main.getWorld(BukkitAdapter.adapt(e.getEntity().getWorld()));
EnderSignal signal = (EnderSignal) entity;
TerraStructure config = tw.getConfig().getRegistry(TerraStructure.class).get(tw.getConfig().getTemplate().getLocatable().get("STRONGHOLD"));
TerraStructure config = tw.getConfig().getStructureRegistry().get(tw.getConfig().getTemplate().getLocatable().get("STRONGHOLD"));
if(config != null) {
main.getDebugLogger().info("Overriding Ender Signal...");
AsyncStructureFinder finder = new AsyncStructureFinder(tw.getBiomeProvider(), config, BukkitAdapter.adapt(e.getLocation()), 0, 500, location -> {
@@ -53,7 +53,7 @@ public class SpigotListener implements Listener {
@EventHandler
public void onCartographerChange(VillagerAcquireTradeEvent e) {
if(!TerraWorld.isTerraWorld(BukkitAdapter.adapt(e.getEntity().getWorld()))) return;
if(!BukkitAdapter.adapt(e.getEntity().getWorld()).isTerraWorld()) return;
if(!(e.getEntity() instanceof Villager)) return;
if(((Villager) e.getEntity()).getProfession().equals(Villager.Profession.CARTOGRAPHER)) {
main.logger().severe("Prevented server crash by stopping Cartographer villager from spawning.");
@@ -65,7 +65,7 @@ public class SpigotListener implements Listener {
@EventHandler
public void onCartographerLevel(VillagerCareerChangeEvent e) {
if(!TerraWorld.isTerraWorld(BukkitAdapter.adapt(e.getEntity().getWorld()))) return;
if(!BukkitAdapter.adapt(e.getEntity().getWorld()).isTerraWorld()) return;
if(e.getProfession().equals(Villager.Profession.CARTOGRAPHER)) {
main.logger().severe("Prevented server crash by stopping Cartographer villager from spawning.");
main.logger().severe("Please upgrade to Paper, which has a StructureLocateEvent that fixes this issue");

Some files were not shown because too many files have changed in this diff Show More