Compare commits

..

30 Commits

Author SHA1 Message Date
dfsek be3e50411e add AutoDocShadow 2021-04-26 23:13:44 -07:00
dfsek c87d0446d3 check and warn about dead links 2021-04-26 22:55:01 -07:00
dfsek e08a105d27 intellij really doesnt like adding imports 2021-04-26 22:45:41 -07:00
dfsek 03cecfb0fd generate pages for intermediate templates 2021-04-26 22:44:10 -07:00
dfsek 502b84722e children link improvements 2021-04-26 22:21:26 -07:00
dfsek 1abaace21b fix parent links 2021-04-26 22:12:12 -07:00
dfsek 951270c147 mostly working children list 2021-04-26 22:10:53 -07:00
dfsek 29cc8e9ffb cleanup buildscript imports 2021-04-26 21:35:39 -07:00
dfsek c5bd7e7646 document pipeline stages 2021-04-26 12:13:58 -07:00
dfsek 4cdcdc0fee aliasing 2021-04-26 12:05:14 -07:00
dfsek 9d4c4e35e7 cleanup 2021-04-26 12:01:42 -07:00
dfsek 3876cbc88e AutoDocAlias magic 2021-04-25 23:24:24 -07:00
dfsek 800b8bc3a7 only use main source set 2021-04-25 22:27:37 -07:00
dfsek 73ca08cb3d more default docs. 2021-04-25 22:26:19 -07:00
dfsek 664995e6eb generic types and "primitive" docs 2021-04-25 22:19:11 -07:00
dfsek 130d9648ee document more stuff 2021-04-25 17:08:10 -07:00
dfsek 869d95f5c8 begin work on automatic config docs 2021-04-25 16:53:11 -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
dfsek 5ac7257517 Merge pull request #119 from PolyhedralDev/ver/5.1.3
Fix Fabric Physics, add "dead" entry checking to registries.
2021-04-11 18:56:25 -07:00
dfsek 9f4f9702a6 bump version 2021-04-11 17:54:07 -07:00
dfsek 01d169256e properly relocate dependencies 2021-04-11 17:49:39 -07:00
dfsek 7a703ad091 add publication config to Fabric 2021-04-11 14:15:13 -07:00
dfsek ce9273c7e8 proper fluid updating on Fabric 2021-04-11 00:45:53 -07:00
dfsek 653a414ac1 should(tm) fix fabric physics 2021-04-10 23:49:02 -07:00
dfsek 2080db21ca warn about dead registry entries when debug mode is enabled 2021-04-10 19:22:41 -07:00
70 changed files with 758 additions and 248 deletions
-5
View File
@@ -8,11 +8,6 @@ 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)
## Licensing
Terra as a whole is licensed under the GNU General Public License, version 3.0. Terra's API is licensed under the GNU Lesser General Public
License, version 3.0, in order to allow linking to the API without GPL infection.
## Building and running Terra
To build, simply run `./gradlew build` (`gradlew.bat build` on Windows). This will produce a jar in `build/libs`
+1 -1
View File
@@ -1,6 +1,6 @@
import com.dfsek.terra.getGitHash
val versionObj = Version("5", "1", "2", true)
val versionObj = Version("5", "1", "3", true)
allprojects {
version = versionObj
@@ -18,9 +18,7 @@ fun Project.configureDependencies() {
dependencies {
"testImplementation"("org.junit.jupiter:junit-jupiter-api:5.7.0")
"testImplementation"("org.yaml:snakeyaml:1.27")
"testImplementation"("com.googlecode.json-simple:json-simple:1.1.1")
"testRuntimeOnly"("org.junit.jupiter:junit-jupiter-engine:5.7.0")
"testImplementation"("org.junit.jupiter:junit-jupiter-engine:5.7.0")
"compileOnly"("org.jetbrains:annotations:20.1.0")
}
}
@@ -62,8 +62,14 @@ fun Project.configureDistribution() {
archiveClassifier.set("shaded")
setVersion(project.version)
relocate("org.apache.commons", "com.dfsek.terra.lib.commons")
relocate("parsii", "com.dfsek.terra.lib.parsii")
relocate("net.jafama", "com.dfsek.terra.lib.jafama")
relocate("org.objectweb.asm", "com.dfsek.terra.lib.asm")
relocate("com.google.errorprone", "com.dfsek.terra.lib.google.errorprone")
relocate("com.google.j2objc", "com.dfsek.terra.lib.google.j2objc")
relocate("org.checkerframework", "com.dfsek.terra.lib.checkerframework")
relocate("org.javax.annotation", "com.dfsek.terra.lib.javax.annotation")
relocate("org.json", "com.dfsek.terra.lib.json")
relocate("org.yaml", "com.dfsek.terra.lib.yaml")
minimize()
}
convention.getPlugin<BasePluginConvention>().archivesBaseName = project.name
+214 -1
View File
@@ -1,10 +1,25 @@
import com.dfsek.terra.configureCommon
import com.github.javaparser.StaticJavaParser
import com.github.javaparser.ast.CompilationUnit
import com.github.javaparser.ast.body.FieldDeclaration
import com.github.javaparser.ast.expr.StringLiteralExpr
import com.github.javaparser.ast.type.PrimitiveType
import com.github.javaparser.ast.type.PrimitiveType.Primitive
import com.github.javaparser.ast.type.Type
import com.github.javaparser.ast.Node
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration
plugins {
`java-library`
`maven-publish`
}
buildscript {
dependencies {
classpath("com.github.javaparser:javaparser-symbol-solver-core:3.20.2")
}
}
configureCommon()
group = "com.dfsek.terra.common"
@@ -20,7 +35,8 @@ dependencies {
"shadedApi"("org.ow2.asm:asm:9.0")
"shadedApi"("commons-io:commons-io:2.6")
"compileOnly"("com.googlecode.json-simple:json-simple:1.1")
"shadedApi"("com.googlecode.json-simple:json-simple:1.1.1")
"shadedApi"("org.yaml:snakeyaml:1.27")
"compileOnly"("com.google.guava:guava:30.0-jre")
@@ -50,4 +66,201 @@ publishing {
}
}
}
}
sourceSets {
create("tectonic") {
}
}
tasks.create<SourceTask>("tectonicDocs") {
group = "terra"
println("Scanning sources...")
val docs = HashMap<String, String>()
val refactor = HashMap<String, String>()
val sources = HashMap<String, CompilationUnit>()
sourceSets.main.get().java.forEach {
sources[it.name.substring(0, it.name.length - 5)] = StaticJavaParser.parse(it)
}
sources.forEach { (name, unit) ->
unit.getClassByName(name).ifPresent { declaration ->
if (declaration.isAnnotationPresent("AutoDocAlias")) {
refactor[name] = (declaration.getAnnotationByName("AutoDocAlias").get().childNodes[1] as StringLiteralExpr).asString()
println("Refactoring $name to ${refactor[name]}.")
} else if (declaration.isAnnotationPresent("AutoDocShadow")) {
refactor[name] = (declaration.getAnnotationByName("AutoDocShadow").get().childNodes[1] as StringLiteralExpr).asString()
println("Shadowing $name to ${refactor[name]}.")
}
}
}
val children = HashMap<String, MutableList<ClassOrInterfaceDeclaration>>()
sources.forEach { (name, unit) ->
unit.getClassByName(name).ifPresent { declaration ->
if(!declaration.isAnnotationPresent("AutoDocShadow")) {
declaration.extendedTypes.forEach { classOrInterfaceType ->
val inherit = classOrInterfaceType.name.asString()
if (!children.containsKey(inherit)) children[inherit] = ArrayList()
children[inherit]!!.add(declaration)
}
}
}
}
val linksAll = HashMap<String, Set<String>>()
sources.forEach { (name, unit) ->
val doc = StringBuilder()
doc.append("# ${generify(name, refactor)}\n")
var applicable = false
val links = HashSet<String>()
unit.getClassByName(name).ifPresent { declaration ->
applicable = scanForParent(sources, declaration, "ConfigTemplate", "ValidatedConfigTemplate", "ObjectTemplate")
declaration.javadoc.ifPresent {
doc.append("${sanitizeJavadoc(it.toText())} \n")
}
declaration.extendedTypes.forEach {
if (!it.name.asString().equals("AbstractableTemplate")) {
doc.append("Inherits from ${parseTypeLink(it, refactor, links, false)} \n \n")
}
}
if (children.containsKey(name)) {
doc.append("Children:\n")
children[name]!!.forEach {
doc.append("* ${parseTypeLink(it.name, refactor, links)}\n")
}
doc.append(" \n\n")
}
doc.append("\n")
}
unit.findAll(FieldDeclaration::class.java).filter { it.isAnnotationPresent("Value") }.forEach { fieldDeclaration ->
doc.append("## ${(fieldDeclaration.getAnnotationByName("Value").get().childNodes[1] as StringLiteralExpr).asString()}\n")
if (fieldDeclaration.isAnnotationPresent("Default")) {
doc.append("* Default value: ${fieldDeclaration.variables[0]} \n")
}
val type = fieldDeclaration.commonType
doc.append("* Type: ${parseTypeLink(type, refactor, links)} \n")
doc.append("\n")
fieldDeclaration.javadoc.ifPresent {
doc.append(sanitizeJavadoc(it.toText()))
}
doc.append("\n\n")
applicable = true
}
val s = doc.toString()
if (s.isNotEmpty() && applicable) {
docs[generify(name, refactor)] = s
linksAll[name] = links
}
}
println("Done. Generated ${docs.size} files")
val docsDir = File(buildDir, "tectonic")
docsDir.mkdirs()
val files = HashSet<String>()
docs.forEach {
val save = File(docsDir, "${it.key}.md")
files.add(it.key)
if (save.exists()) save.delete()
save.createNewFile()
save.writeText(it.value)
}
sourceSets["tectonic"].resources.forEach {
files.add(it.name.substringBefore('.'))
it.copyTo(File(docsDir, it.name), true)
}
linksAll.forEach { (file, links) ->
links.forEach {
if(!files.contains(it)) println("WARNING: Dead link to \"$it\" in file \"$file\"")
}
}
}
fun scanForParent(map: HashMap<String, CompilationUnit>, current: ClassOrInterfaceDeclaration, vararg parent: String): Boolean {
for (type in current.implementedTypes) {
if(parent.contains(type.childNodes[0].toString())) return true
}
for(type in current.extendedTypes) {
val name = type.childNodes[0].toString()
if(map.containsKey(name)) {
val op = map[name]!!.getClassByName(name)
if(op.isPresent && scanForParent(map, op.get(), *parent)) {
return true
}
}
}
return false
}
fun parseTypeLink(type: Node, refactor: Map<String, String>, links: MutableSet<String>, generic: Boolean = true): String {
val st = parseType(type, refactor)
if (type is Type && type.childNodes.size > 1 && generic) {
val outer = generify(type.childNodes[0].toString(), refactor)
val builder = StringBuilder()
builder.append("[$outer](./$outer)\\<")
links.add(outer)
for (i in 1 until type.childNodes.size) {
builder.append(parseTypeLink(type.childNodes[i], refactor, links, generic))
if (i != type.childNodes.size - 1) builder.append(", ")
}
builder.append("\\>")
return builder.toString()
}
links.add(st)
return "[$st](./$st)"
}
fun parseType(type: Node, refactor: Map<String, String>): String {
if (type is PrimitiveType) {
return when (type.type) {
Primitive.BOOLEAN -> "Boolean"
Primitive.BYTE -> "Byte"
Primitive.DOUBLE -> "Double"
Primitive.INT -> "Integer"
Primitive.CHAR -> "Char"
Primitive.FLOAT -> "Float"
Primitive.SHORT -> "Short"
Primitive.LONG -> "Long"
else -> type.asString()
}
}
if(type is Type && type.childNodes.size > 1) return generify(type.childNodes[0].toString(), refactor)
return generify(type.toString(), refactor)
}
fun generify(type: String, refactor: Map<String, String>): String {
return when (type) {
"HashMap", "LinkedHashMap" -> "Map"
"ArrayList", "LinkedList", "GlueList" -> "List"
"HashSet" -> "Set"
else -> refactor.getOrDefault(type, type)
}
}
fun sanitizeJavadoc(doc: String): String {
return doc
.replace("<p>", "")
}
@@ -1,165 +0,0 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.
@@ -0,0 +1,17 @@
package com.dfsek.terra.api.docs;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* For use in Terra AutoDoc, to specify
* that references to the annotated class
* should be refactored in the documentation.
*/
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
public @interface AutoDocAlias {
String value();
}
@@ -0,0 +1,17 @@
package com.dfsek.terra.api.docs;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* For use in Terra AutoDoc, to specify
* that references to the annotated class
* should be shadowed to the target class.
*/
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
public @interface AutoDocShadow {
String value();
}
@@ -1,11 +1,13 @@
package com.dfsek.terra.config.builder;
import com.dfsek.terra.api.docs.AutoDocAlias;
import com.dfsek.terra.api.platform.world.Biome;
import com.dfsek.terra.api.util.collections.ProbabilityCollection;
import com.dfsek.terra.api.util.seeded.SeededBuilder;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.config.templates.BiomeTemplate;
@AutoDocAlias("TerraBiome")
public interface BiomeBuilder extends SeededBuilder<TerraBiome> {
ProbabilityCollection<Biome> getVanillaBiomes();
@@ -11,16 +11,28 @@ import com.dfsek.terra.api.world.biome.provider.StandardBiomeProvider;
import java.util.List;
/**
* Configures a biome pipeline.
*/
@SuppressWarnings({"FieldMayBeFinal", "unused"})
public class BiomePipelineTemplate extends BiomeProviderTemplate {
private final TerraPlugin main;
/**
* Initial size of biome pipeline chunks.
*/
@Value("pipeline.initial-size")
@Default
private int initialSize = 2;
/**
* Mutator stages to be used in this biome pipeline.
*/
@Value("pipeline.stages")
private List<StageSeeded> stages;
/**
* Biome source to initialize the pipeline.
*/
@Value("pipeline.source")
private SourceSeeded source;
@@ -8,10 +8,21 @@ import com.dfsek.terra.api.math.noise.samplers.noise.ConstantSampler;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.api.world.biome.provider.BiomeProvider;
/**
* Configures a biome provider.
*/
public abstract class BiomeProviderTemplate implements ObjectTemplate<BiomeProvider.BiomeProviderBuilder>, BiomeProvider.BiomeProviderBuilder {
/**
* Resolution of this provider.
* A resolution of 1 means that 1 block = 1 sample.
*/
@Value("resolution")
@Default
protected int resolution = 1;
/**
* Noise function to use for blending biomes at edges.
*/
@Value("blend.noise")
@Default
protected NoiseSeeded blend = new NoiseSeeded() {
@@ -25,11 +36,13 @@ public abstract class BiomeProviderTemplate implements ObjectTemplate<BiomeProvi
return 2;
}
};
/**
* Amplitude of edge blending, in blocks.
*/
@Value("blend.amplitude")
@Default
protected double blendAmp = 0d;
@Value("type")
BiomeProvider.Type type;
@Override
public BiomeProvider.BiomeProviderBuilder get() {
@@ -9,11 +9,21 @@ import com.dfsek.terra.config.builder.BiomeBuilder;
import java.awt.image.BufferedImage;
import java.util.stream.Collectors;
/**
* Configures an image biome provider.
*/
public class ImageProviderTemplate extends BiomeProviderTemplate {
private final Registry<BiomeBuilder> biomes;
/**
* Image to use for biome selection.
*/
@Value("image.name")
private BufferedImage image;
/**
* How the image should be aligned.
*/
@Value("image.align")
private ImageBiomeProvider.Align align;
@@ -5,7 +5,13 @@ import com.dfsek.terra.api.world.biome.provider.BiomeProvider;
import com.dfsek.terra.api.world.biome.provider.SingleBiomeProvider;
import com.dfsek.terra.config.builder.BiomeBuilder;
/**
* Configures a single-biome provider.
*/
public class SingleBiomeProviderTemplate extends BiomeProviderTemplate {
/**
* The biome.
*/
@Value("biome")
private BiomeBuilder biome;
@@ -1,16 +1,27 @@
package com.dfsek.terra.config.loaders.config.biome.templates.source;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.api.docs.AutoDocAlias;
import com.dfsek.terra.api.util.collections.ProbabilityCollection;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.api.world.biome.pipeline.source.BiomeSource;
import com.dfsek.terra.api.world.biome.pipeline.source.RandomSource;
import com.dfsek.terra.config.builder.BiomeBuilder;
/**
* Configures a noise-based biome source.
*/
@AutoDocAlias("NoiseSource")
public class NoiseSourceTemplate extends SourceTemplate {
/**
* Noise function to use for selecting biomes.
*/
@Value("noise")
private NoiseSeeded noise;
/**
* ProbabilityCollection of biomes to use.
*/
@Value("biomes")
private ProbabilityCollection<BiomeBuilder> biomes;
@@ -1,9 +1,11 @@
package com.dfsek.terra.config.loaders.config.biome.templates.source;
import com.dfsek.tectonic.loading.object.ObjectTemplate;
import com.dfsek.terra.api.docs.AutoDocAlias;
import com.dfsek.terra.api.util.seeded.SourceSeeded;
import com.dfsek.terra.api.world.biome.pipeline.source.BiomeSource;
@AutoDocAlias("SourceSeeded")
public abstract class SourceTemplate implements ObjectTemplate<SourceSeeded>, SourceSeeded {
@Override
public SourceSeeded get() {
@@ -2,12 +2,17 @@ package com.dfsek.terra.config.loaders.config.biome.templates.stage;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.tectonic.loading.object.ObjectTemplate;
import com.dfsek.terra.api.docs.AutoDocAlias;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.api.util.seeded.SeededBuilder;
import com.dfsek.terra.api.util.seeded.StageSeeded;
import com.dfsek.terra.api.world.biome.pipeline.stages.Stage;
@AutoDocAlias("StageSeeded")
public abstract class StageTemplate implements ObjectTemplate<SeededBuilder<Stage>>, StageSeeded {
/**
* Noise function to use for mutating biomes in this stage.
*/
@Value("noise")
protected NoiseSeeded noise;
@@ -1,6 +1,7 @@
package com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.api.docs.AutoDocAlias;
import com.dfsek.terra.api.util.collections.ProbabilityCollection;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.biome.pipeline.mutator.BiomeMutator;
@@ -11,16 +12,30 @@ import java.util.HashMap;
import java.util.Map;
@SuppressWarnings("unused")
@AutoDocAlias("BorderListMutator")
public class BorderListMutatorTemplate extends MutatorStageTemplate {
/**
* Tag of the biome on the external side of the border.
*/
@Value("from")
private String from;
/**
* Tag of biomes to replace when bordering biomes with
* tag "from".
*/
@Value("default-replace")
private String defaultReplace;
/**
* Default replacement biomes.
*/
@Value("default-to")
private ProbabilityCollection<BiomeBuilder> defaultTo;
/**
* Map of single biomes to their replacements.
*/
@Value("replace")
private Map<BiomeBuilder, ProbabilityCollection<BiomeBuilder>> replace;
@@ -1,19 +1,32 @@
package com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.api.docs.AutoDocAlias;
import com.dfsek.terra.api.util.collections.ProbabilityCollection;
import com.dfsek.terra.api.world.biome.pipeline.mutator.BiomeMutator;
import com.dfsek.terra.api.world.biome.pipeline.mutator.BorderMutator;
import com.dfsek.terra.config.builder.BiomeBuilder;
@SuppressWarnings("unused")
@AutoDocAlias("BorderMutator")
public class BorderMutatorTemplate extends MutatorStageTemplate {
/**
* Tag of the biome on the external side of the border.
*/
@Value("from")
private String from;
/**
* Tag of biomes to replace when bordering biomes
* with tag "from"
*/
@Value("replace")
private String replace;
/**
* Collection of biomes to place at borders
* of "from" and "to"
*/
@Value("to")
private ProbabilityCollection<BiomeBuilder> to;
@@ -1,10 +1,12 @@
package com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator;
import com.dfsek.terra.api.docs.AutoDocAlias;
import com.dfsek.terra.api.world.biome.pipeline.mutator.BiomeMutator;
import com.dfsek.terra.api.world.biome.pipeline.stages.MutatorStage;
import com.dfsek.terra.api.world.biome.pipeline.stages.Stage;
import com.dfsek.terra.config.loaders.config.biome.templates.stage.StageTemplate;
@AutoDocAlias("MutatorStage")
public abstract class MutatorStageTemplate extends StageTemplate {
public abstract BiomeMutator build(long seed);
@@ -1,6 +1,7 @@
package com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.api.docs.AutoDocAlias;
import com.dfsek.terra.api.util.collections.ProbabilityCollection;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.biome.pipeline.mutator.BiomeMutator;
@@ -11,7 +12,11 @@ import java.util.HashMap;
import java.util.Map;
@SuppressWarnings("unused")
@AutoDocAlias("ReplaceListMutator")
public class ReplaceListMutatorTemplate extends MutatorStageTemplate {
/**
* Default tag to replace from
*/
@Value("default-from")
private String defaultFrom;
@@ -1,16 +1,24 @@
package com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.api.docs.AutoDocAlias;
import com.dfsek.terra.api.util.collections.ProbabilityCollection;
import com.dfsek.terra.api.world.biome.pipeline.mutator.BiomeMutator;
import com.dfsek.terra.api.world.biome.pipeline.mutator.ReplaceMutator;
import com.dfsek.terra.config.builder.BiomeBuilder;
@SuppressWarnings("unused")
@AutoDocAlias("ReplaceMutator")
public class ReplaceMutatorTemplate extends MutatorStageTemplate {
/**
* Tag of biomes to replace.
*/
@Value("from")
private String from;
/**
* Biomes to replace with.
*/
@Value("to")
private ProbabilityCollection<BiomeBuilder> to;
@@ -1,8 +1,10 @@
package com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator;
import com.dfsek.terra.api.docs.AutoDocAlias;
import com.dfsek.terra.api.world.biome.pipeline.mutator.BiomeMutator;
import com.dfsek.terra.api.world.biome.pipeline.mutator.SmoothMutator;
@AutoDocAlias("SmoothMutator")
public class SmoothMutatorTemplate extends MutatorStageTemplate {
@Override
public BiomeMutator build(long seed) {
@@ -6,6 +6,7 @@ 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.docs.AutoDocAlias;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.registry.config.NoiseRegistry;
@@ -14,6 +15,7 @@ import java.util.Locale;
import java.util.Map;
@SuppressWarnings("unchecked")
@AutoDocAlias("NoiseSeeded")
public class NoiseSamplerBuilderLoader implements TypeLoader<NoiseSeeded> {
private final NoiseRegistry noiseRegistry;
@@ -2,28 +2,46 @@ package com.dfsek.terra.config.loaders.config.sampler.templates;
import com.dfsek.tectonic.annotations.Default;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.api.math.noise.NoiseSampler;
import com.dfsek.terra.api.docs.AutoDocAlias;
import com.dfsek.terra.api.math.noise.samplers.DomainWarpedSampler;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
/**
* Defines a domain-warped noise function.
*/
@SuppressWarnings({"unused", "FieldMayBeFinal"})
@AutoDocAlias("DomainWarpedSampler")
public class DomainWarpTemplate extends SamplerTemplate<DomainWarpedSampler> {
/**
* Noise function used to warp input function.
*/
@Value("warp")
private NoiseSeeded warp;
/**
* Input function (function to be warped)
*/
@Value("function")
private NoiseSeeded function;
/**
* Salt for both warp function and
* input function.
*/
@Value("salt")
@Default
private int salt = 0;
/**
* Amplitude of warping. Values provided by
* the warp function are multiplied by this constant.
*/
@Value("amplitude")
@Default
private double amplitude = 1;
@Override
public NoiseSampler apply(Long seed) {
public DomainWarpedSampler apply(Long seed) {
return new DomainWarpedSampler(function.apply(seed), warp.apply(seed), (int) (seed + salt), amplitude);
}
}
@@ -1,12 +1,13 @@
package com.dfsek.terra.config.loaders.config.sampler.templates;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.api.math.noise.NoiseSampler;
import com.dfsek.terra.api.docs.AutoDocAlias;
import com.dfsek.terra.api.math.noise.samplers.ImageSampler;
import java.awt.image.BufferedImage;
@SuppressWarnings({"unused", "FieldMayBeFinal"})
@AutoDocAlias("ImageSampler")
public class ImageSamplerTemplate extends SamplerTemplate<ImageSampler> {
@Value("image")
@@ -19,7 +20,7 @@ public class ImageSamplerTemplate extends SamplerTemplate<ImageSampler> {
private ImageSampler.Channel channel;
@Override
public NoiseSampler apply(Long seed) {
public ImageSampler apply(Long seed) {
return new ImageSampler(image, channel, frequency);
}
}
@@ -4,13 +4,14 @@ import com.dfsek.tectonic.annotations.Default;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.tectonic.config.ValidatedConfigTemplate;
import com.dfsek.tectonic.exception.ValidationException;
import com.dfsek.terra.api.math.noise.NoiseSampler;
import com.dfsek.terra.api.docs.AutoDocAlias;
import com.dfsek.terra.api.math.noise.samplers.KernelSampler;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import java.util.List;
@SuppressWarnings({"unused", "FieldMayBeFinal"})
@AutoDocAlias("KernelSampler")
public class KernelTemplate extends SamplerTemplate<KernelSampler> implements ValidatedConfigTemplate {
@Value("kernel")
@@ -28,7 +29,7 @@ public class KernelTemplate extends SamplerTemplate<KernelSampler> implements Va
private double frequency = 1;
@Override
public NoiseSampler apply(Long seed) {
public KernelSampler apply(Long seed) {
double[][] k = new double[kernel.size()][kernel.get(0).size()];
for(int x = 0; x < kernel.size(); x++) {
@@ -5,11 +5,16 @@ import com.dfsek.tectonic.annotations.Value;
import com.dfsek.tectonic.config.ValidatedConfigTemplate;
import com.dfsek.tectonic.exception.ValidationException;
import com.dfsek.tectonic.loading.object.ObjectTemplate;
import com.dfsek.terra.api.docs.AutoDocAlias;
import com.dfsek.terra.api.math.noise.NoiseSampler;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
@SuppressWarnings("FieldMayBeFinal")
@AutoDocAlias("NoiseSeeded")
public abstract class SamplerTemplate<T extends NoiseSampler> implements ValidatedConfigTemplate, ObjectTemplate<NoiseSeeded>, NoiseSeeded {
/**
* Number of dimensions for this sampler.
*/
@Value("dimensions")
@Default
private int dimensions = 2;
@@ -28,4 +33,7 @@ public abstract class SamplerTemplate<T extends NoiseSampler> implements Validat
public NoiseSeeded get() {
return this;
}
@Override
public abstract T apply(Long seed);
}
@@ -2,12 +2,14 @@ package com.dfsek.terra.config.loaders.config.sampler.templates.noise;
import com.dfsek.tectonic.annotations.Default;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.api.docs.AutoDocAlias;
import com.dfsek.terra.api.math.noise.NoiseSampler;
import com.dfsek.terra.api.math.noise.samplers.noise.CellularSampler;
import com.dfsek.terra.api.math.noise.samplers.noise.simplex.OpenSimplex2Sampler;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
@SuppressWarnings("FieldMayBeFinal")
@AutoDocAlias("CellularSampler")
public class CellularNoiseTemplate extends NoiseTemplate<CellularSampler> {
@Value("distance")
@Default
@@ -38,7 +40,7 @@ public class CellularNoiseTemplate extends NoiseTemplate<CellularSampler> {
};
@Override
public NoiseSampler apply(Long seed) {
public CellularSampler apply(Long seed) {
CellularSampler sampler = new CellularSampler((int) (long) seed + salt);
sampler.setNoiseLookup(lookup.apply(seed));
sampler.setFrequency(frequency);
@@ -2,18 +2,19 @@ package com.dfsek.terra.config.loaders.config.sampler.templates.noise;
import com.dfsek.tectonic.annotations.Default;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.api.math.noise.NoiseSampler;
import com.dfsek.terra.api.docs.AutoDocAlias;
import com.dfsek.terra.api.math.noise.samplers.noise.ConstantSampler;
import com.dfsek.terra.config.loaders.config.sampler.templates.SamplerTemplate;
@SuppressWarnings("FieldMayBeFinal")
@AutoDocAlias("ConstantSampler")
public class ConstantNoiseTemplate extends SamplerTemplate<ConstantSampler> {
@Value("value")
@Default
private double value = 0d;
@Override
public NoiseSampler apply(Long seed) {
public ConstantSampler apply(Long seed) {
return new ConstantSampler(value);
}
}
@@ -8,9 +8,8 @@ import com.dfsek.tectonic.annotations.Default;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.tectonic.config.ValidatedConfigTemplate;
import com.dfsek.tectonic.exception.ValidationException;
import com.dfsek.terra.api.math.noise.NoiseSampler;
import com.dfsek.terra.api.docs.AutoDocAlias;
import com.dfsek.terra.api.math.noise.samplers.noise.ExpressionFunction;
import com.dfsek.terra.api.math.paralithic.BlankFunction;
import com.dfsek.terra.api.math.paralithic.defined.UserDefinedFunction;
import com.dfsek.terra.api.math.paralithic.noise.NoiseFunction2;
import com.dfsek.terra.api.math.paralithic.noise.NoiseFunction3;
@@ -24,6 +23,7 @@ import java.util.Map;
@SuppressWarnings({"FieldMayBeFinal", "unused"})
@AutoDocAlias("ExpressionFunction")
public class ExpressionFunctionTemplate extends SamplerTemplate<ExpressionFunction> implements ValidatedConfigTemplate {
@Value("variables")
@Default
@@ -41,7 +41,7 @@ public class ExpressionFunctionTemplate extends SamplerTemplate<ExpressionFuncti
private LinkedHashMap<String, FunctionTemplate> expressions = new LinkedHashMap<>();
@Override
public NoiseSampler apply(Long seed) {
public ExpressionFunction apply(Long seed) {
try {
Map<String, Function> noiseFunctionMap = generateFunctions(seed);
return new ExpressionFunction(noiseFunctionMap, equation, vars);
@@ -2,18 +2,31 @@ package com.dfsek.terra.config.loaders.config.sampler.templates.noise;
import com.dfsek.tectonic.annotations.Default;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.api.math.noise.NoiseSampler;
import com.dfsek.terra.api.docs.AutoDocAlias;
import com.dfsek.terra.api.math.noise.samplers.noise.GaborNoiseSampler;
/**
* Defines a Gabor noise function.
*/
@AutoDocAlias("GaborNoiseSampler")
public class GaborNoiseTemplate extends NoiseTemplate<GaborNoiseSampler> {
/**
* Rotation to apply to noise. Only has noticeable effects in anisotropic mode.
*/
@Value("rotation")
@Default
private double rotation = 0.25;
/**
* Whether to use anisotropic or isotropic algorithm.
*/
@Value("isotropic")
@Default
private boolean isotropic = true;
/**
* Standard deviation of result values.
*/
@Value("deviation")
@Default
private double deviation = 1.0;
@@ -27,7 +40,7 @@ public class GaborNoiseTemplate extends NoiseTemplate<GaborNoiseSampler> {
private double f0 = 0.625;
@Override
public NoiseSampler apply(Long seed) {
public GaborNoiseSampler apply(Long seed) {
GaborNoiseSampler gaborNoiseSampler = new GaborNoiseSampler((int) (long) seed + salt);
gaborNoiseSampler.setFrequency(frequency);
gaborNoiseSampler.setRotation(rotation);
@@ -2,10 +2,12 @@ package com.dfsek.terra.config.loaders.config.sampler.templates.noise;
import com.dfsek.tectonic.annotations.Default;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.api.docs.AutoDocAlias;
import com.dfsek.terra.api.math.noise.samplers.noise.NoiseFunction;
import com.dfsek.terra.config.loaders.config.sampler.templates.SamplerTemplate;
@SuppressWarnings({"unused", "FieldMayBeFinal"})
@AutoDocAlias("NoiseFunction")
public abstract class NoiseTemplate<T extends NoiseFunction> extends SamplerTemplate<T> {
@Value("frequency")
@Default
@@ -1,10 +1,11 @@
package com.dfsek.terra.config.loaders.config.sampler.templates.noise;
import com.dfsek.terra.api.math.noise.NoiseSampler;
import com.dfsek.terra.api.docs.AutoDocShadow;
import com.dfsek.terra.api.math.noise.samplers.noise.NoiseFunction;
import java.util.function.Function;
@AutoDocShadow("NoiseFunction")
public class SimpleNoiseTemplate extends NoiseTemplate<NoiseFunction> {
private final Function<Integer, NoiseFunction> samplerSupplier;
@@ -13,7 +14,7 @@ public class SimpleNoiseTemplate extends NoiseTemplate<NoiseFunction> {
}
@Override
public NoiseSampler apply(Long seed) {
public NoiseFunction apply(Long seed) {
NoiseFunction sampler = samplerSupplier.apply((int) (long) seed + salt);
sampler.setFrequency(frequency);
return sampler;
@@ -1,11 +1,12 @@
package com.dfsek.terra.config.loaders.config.sampler.templates.noise.fractal;
import com.dfsek.terra.api.math.noise.NoiseSampler;
import com.dfsek.terra.api.docs.AutoDocAlias;
import com.dfsek.terra.api.math.noise.samplers.noise.fractal.BrownianMotionSampler;
@AutoDocAlias("BrownianMotionSampler")
public class BrownianMotionTemplate extends FractalTemplate<BrownianMotionSampler> {
@Override
public NoiseSampler apply(Long seed) {
public BrownianMotionSampler apply(Long seed) {
BrownianMotionSampler sampler = new BrownianMotionSampler((int) (long) seed, function.apply(seed));
sampler.setGain(fractalGain);
sampler.setLacunarity(fractalLacunarity);
@@ -2,10 +2,12 @@ package com.dfsek.terra.config.loaders.config.sampler.templates.noise.fractal;
import com.dfsek.tectonic.annotations.Default;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.api.docs.AutoDocAlias;
import com.dfsek.terra.api.math.noise.samplers.noise.fractal.FractalNoiseFunction;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.config.loaders.config.sampler.templates.SamplerTemplate;
@AutoDocAlias("FractalNoiseFunction")
public abstract class FractalTemplate<T extends FractalNoiseFunction> extends SamplerTemplate<T> {
@Value("octaves")
@Default
@@ -2,16 +2,17 @@ package com.dfsek.terra.config.loaders.config.sampler.templates.noise.fractal;
import com.dfsek.tectonic.annotations.Default;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.api.math.noise.NoiseSampler;
import com.dfsek.terra.api.docs.AutoDocAlias;
import com.dfsek.terra.api.math.noise.samplers.noise.fractal.PingPongSampler;
@SuppressWarnings({"unused", "FieldMayBeFinal"})
@AutoDocAlias("PingPongSampler")
public class PingPongTemplate extends FractalTemplate<PingPongSampler> {
@Value("ping-pong")
@Default
private double pingPong = 2.0D;
@Override
public NoiseSampler apply(Long seed) {
public PingPongSampler apply(Long seed) {
PingPongSampler sampler = new PingPongSampler((int) (long) seed, function.apply(seed));
sampler.setGain(fractalGain);
sampler.setLacunarity(fractalLacunarity);
@@ -1,11 +1,12 @@
package com.dfsek.terra.config.loaders.config.sampler.templates.noise.fractal;
import com.dfsek.terra.api.math.noise.NoiseSampler;
import com.dfsek.terra.api.docs.AutoDocAlias;
import com.dfsek.terra.api.math.noise.samplers.noise.fractal.RidgedFractalSampler;
@AutoDocAlias("RidgedFractalSampler")
public class RidgedFractalTemplate extends FractalTemplate<RidgedFractalSampler> {
@Override
public NoiseSampler apply(Long seed) {
public RidgedFractalSampler apply(Long seed) {
RidgedFractalSampler sampler = new RidgedFractalSampler((int) (long) seed, function.apply(seed));
sampler.setGain(fractalGain);
sampler.setLacunarity(fractalLacunarity);
@@ -1,12 +1,12 @@
package com.dfsek.terra.config.loaders.config.sampler.templates.normalizer;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.api.math.noise.NoiseSampler;
import com.dfsek.terra.api.docs.AutoDocAlias;
import com.dfsek.terra.api.math.noise.normalizer.ClampNormalizer;
import com.dfsek.terra.api.math.noise.normalizer.LinearNormalizer;
@SuppressWarnings({"unused", "FieldMayBeFinal"})
public class ClampNormalizerTemplate extends NormalizerTemplate<LinearNormalizer> {
@AutoDocAlias("ClampNormalizer")
public class ClampNormalizerTemplate extends NormalizerTemplate<ClampNormalizer> {
@Value("max")
private double max;
@@ -14,7 +14,7 @@ public class ClampNormalizerTemplate extends NormalizerTemplate<LinearNormalizer
private double min;
@Override
public NoiseSampler apply(Long seed) {
public ClampNormalizer apply(Long seed) {
return new ClampNormalizer(function.apply(seed), min, max);
}
}
@@ -1,10 +1,11 @@
package com.dfsek.terra.config.loaders.config.sampler.templates.normalizer;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.api.math.noise.NoiseSampler;
import com.dfsek.terra.api.docs.AutoDocAlias;
import com.dfsek.terra.api.math.noise.normalizer.LinearNormalizer;
@SuppressWarnings({"unused", "FieldMayBeFinal"})
@AutoDocAlias("LinearNormalizer")
public class LinearNormalizerTemplate extends NormalizerTemplate<LinearNormalizer> {
@Value("max")
private double max;
@@ -13,7 +14,7 @@ public class LinearNormalizerTemplate extends NormalizerTemplate<LinearNormalize
private double min;
@Override
public NoiseSampler apply(Long seed) {
public LinearNormalizer apply(Long seed) {
return new LinearNormalizer(function.apply(seed), min, max);
}
}
@@ -2,10 +2,11 @@ package com.dfsek.terra.config.loaders.config.sampler.templates.normalizer;
import com.dfsek.tectonic.annotations.Default;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.api.math.noise.NoiseSampler;
import com.dfsek.terra.api.docs.AutoDocAlias;
import com.dfsek.terra.api.math.noise.normalizer.NormalNormalizer;
@SuppressWarnings({"unused", "FieldMayBeFinal"})
@AutoDocAlias("NormalNormalizer")
public class NormalNormalizerTemplate extends NormalizerTemplate<NormalNormalizer> {
@Value("mean")
private double mean;
@@ -18,7 +19,7 @@ public class NormalNormalizerTemplate extends NormalizerTemplate<NormalNormalize
private int groups = 16384;
@Override
public NoiseSampler apply(Long seed) {
public NormalNormalizer apply(Long seed) {
return new NormalNormalizer(function.apply(seed), groups, mean, stdDev);
}
}
@@ -1,10 +1,12 @@
package com.dfsek.terra.config.loaders.config.sampler.templates.normalizer;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.api.docs.AutoDocAlias;
import com.dfsek.terra.api.math.noise.normalizer.Normalizer;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.config.loaders.config.sampler.templates.SamplerTemplate;
@AutoDocAlias("Normalizer")
public abstract class NormalizerTemplate<T extends Normalizer> extends SamplerTemplate<T> {
@Value("function")
protected NoiseSeeded function;
@@ -139,6 +139,7 @@ public class ConfigPack implements LoaderRegistrar {
selfLoader.load(packPostTemplate, new FileInputStream(pack));
biomeProviderBuilder = packPostTemplate.getProviderBuilder();
biomeProviderBuilder.build(0); // Build dummy provider to catch errors at load time.
checkDeadEntries(main);
} catch(FileNotFoundException e) {
throw new LoadException("No pack.yml file found in " + folder.getAbsolutePath(), e);
}
@@ -183,6 +184,7 @@ public class ConfigPack implements LoaderRegistrar {
selfLoader.load(packPostTemplate, file.getInputStream(pack));
biomeProviderBuilder = packPostTemplate.getProviderBuilder();
biomeProviderBuilder.build(0); // Build dummy provider to catch errors at load time.
checkDeadEntries(main);
} catch(IOException e) {
throw new LoadException("Unable to load pack.yml from ZIP file", e);
}
@@ -198,6 +200,16 @@ public class ConfigPack implements LoaderRegistrar {
for(C template : configTemplates) registry.add(template.getID(), factory.build(template, main));
}
private void checkDeadEntries(TerraPlugin main) {
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 + "'"));
}
private void load(long start, TerraPlugin main) throws ConfigException {
main.getEventManager().callEvent(new ConfigPackPreLoadEvent(this));
@@ -15,24 +15,52 @@ import java.util.Set;
@SuppressWarnings({"unused", "FieldMayBeFinal"})
public class ConfigPackTemplate implements ConfigTemplate {
/**
* The ID of the config pack.
*/
@Value("id")
private String id;
/**
* Noise functions to be made available
* to noise equations in the config pack.
* <p>
* Keys are Paralithic function IDs,
* values are noise functions.
*/
@Value("noise")
private Map<String, NoiseSeeded> noiseBuilderMap;
/**
* Addons this pack depends on.
*/
@Value("addons")
@Default
private Set<TerraAddon> addons = new HashSet<>();
/**
* Variables to be made available
* to noise equations in the config pack.
* <p>
* Keys are variable IDs,
* values are variable values.
*/
@Value("variables")
@Default
private Map<String, Double> variables = new HashMap<>();
/**
* Whether to enable beta noise
* carvers.
*/
@Value("beta.carving")
@Default
private boolean betaCarvers = false;
/**
*
*/
@Value("functions")
@Default
private LinkedHashMap<String, FunctionTemplate> functions = new LinkedHashMap<>();
@@ -9,6 +9,7 @@ import com.dfsek.tectonic.annotations.Value;
import com.dfsek.tectonic.config.ValidatedConfigTemplate;
import com.dfsek.tectonic.exception.ValidationException;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.docs.AutoDocAlias;
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;
@@ -38,6 +39,7 @@ import java.util.Map;
import java.util.Set;
@SuppressWarnings({"FieldMayBeFinal", "unused"})
@AutoDocAlias("TerraBiome")
public class BiomeTemplate extends AbstractableTemplate implements ValidatedConfigTemplate {
private final ConfigPack pack;
@@ -3,6 +3,7 @@ package com.dfsek.terra.config.templates;
import com.dfsek.tectonic.annotations.Abstractable;
import com.dfsek.tectonic.annotations.Default;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.api.docs.AutoDocAlias;
import com.dfsek.terra.api.math.Range;
import com.dfsek.terra.api.platform.block.BlockType;
import com.dfsek.terra.api.util.collections.MaterialSet;
@@ -12,6 +13,7 @@ import java.util.HashMap;
import java.util.Map;
@SuppressWarnings({"unused", "FieldMayBeFinal"})
@AutoDocAlias("UserDefinedCarver")
public class CarverTemplate extends AbstractableTemplate {
@Value("id")
private String id;
@@ -3,6 +3,7 @@ package com.dfsek.terra.config.templates;
import com.dfsek.tectonic.annotations.Abstractable;
import com.dfsek.tectonic.annotations.Default;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.api.docs.AutoDocAlias;
import com.dfsek.terra.api.util.collections.MaterialSet;
import com.dfsek.terra.api.world.palette.holder.PaletteLayerHolder;
import com.dfsek.terra.world.population.items.flora.TerraFlora;
@@ -10,6 +11,7 @@ import com.dfsek.terra.world.population.items.flora.TerraFlora;
import java.util.List;
@SuppressWarnings({"FieldMayBeFinal", "unused"})
@AutoDocAlias("Flora")
public class FloraTemplate extends AbstractableTemplate {
@Value("id")
private String id;
@@ -32,7 +34,7 @@ public class FloraTemplate extends AbstractableTemplate {
@Value("irrigable")
@Abstractable
@Default
private MaterialSet irrigable = null;
private MaterialSet irrigable = new MaterialSet();
@Value("rotatable")
@Abstractable
@@ -3,12 +3,14 @@ package com.dfsek.terra.config.templates;
import com.dfsek.tectonic.annotations.Abstractable;
import com.dfsek.tectonic.annotations.Default;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.api.docs.AutoDocAlias;
import com.dfsek.terra.api.math.Range;
import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.util.collections.MaterialSet;
import com.dfsek.terra.world.population.items.ores.Ore;
@SuppressWarnings({"unused", "FieldMayBeFinal"})
@AutoDocAlias("Ore")
public class OreTemplate extends AbstractableTemplate {
@Value("id")
private String id;
@@ -3,6 +3,7 @@ package com.dfsek.terra.config.templates;
import com.dfsek.tectonic.annotations.Abstractable;
import com.dfsek.tectonic.annotations.Default;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.api.docs.AutoDocAlias;
import com.dfsek.terra.api.math.noise.NoiseSampler;
import com.dfsek.terra.api.math.noise.samplers.noise.random.WhiteNoiseSampler;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
@@ -11,6 +12,7 @@ import com.dfsek.terra.api.world.palette.holder.PaletteLayerHolder;
import java.util.List;
@SuppressWarnings({"FieldMayBeFinal", "unused"})
@AutoDocAlias("Palette")
public class PaletteTemplate extends AbstractableTemplate {
@Value("noise")
@Abstractable
@@ -4,6 +4,7 @@ import com.dfsek.tectonic.annotations.Abstractable;
import com.dfsek.tectonic.annotations.Default;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.tectonic.config.ConfigTemplate;
import com.dfsek.terra.api.docs.AutoDocAlias;
import com.dfsek.terra.api.math.GridSpawn;
import com.dfsek.terra.api.math.Range;
import com.dfsek.terra.api.structures.script.StructureScript;
@@ -13,6 +14,7 @@ import com.dfsek.terra.api.util.collections.ProbabilityCollection;
import java.util.List;
@SuppressWarnings({"unused", "FieldMayBeFinal"})
@AutoDocAlias("TerraStructure")
public class StructureTemplate extends AbstractableTemplate implements ConfigTemplate {
@Value("id")
private String id;
@@ -3,11 +3,13 @@ package com.dfsek.terra.config.templates;
import com.dfsek.tectonic.annotations.Abstractable;
import com.dfsek.tectonic.annotations.Default;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.api.docs.AutoDocAlias;
import com.dfsek.terra.api.structures.script.StructureScript;
import com.dfsek.terra.api.util.collections.MaterialSet;
import com.dfsek.terra.api.util.collections.ProbabilityCollection;
@SuppressWarnings({"unused", "FieldMayBeFinal"})
@AutoDocAlias("Tree")
public class TreeTemplate extends AbstractableTemplate {
@Value("scripts")
@Abstractable
@@ -7,18 +7,19 @@ import com.dfsek.terra.registry.exception.DuplicateEntryException;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.stream.Collectors;
/**
* Registry implementation with read/write access. For internal use only.
* @param <T>
*/
public class OpenRegistry<T> implements Registry<T> {
private final Map<String, T> objects = new HashMap<>();
private final Map<String, Entry<T>> objects = new HashMap<>();
@Override
public T load(Type type, Object o, ConfigLoader configLoader) throws LoadException {
@@ -35,6 +36,10 @@ public class OpenRegistry<T> implements Registry<T> {
* @param value Value to add.
*/
public boolean add(String identifier, T value) {
return add(identifier, new Entry<>(value));
}
protected boolean add(String identifier, Entry<T> value) {
boolean exists = objects.containsKey(identifier);
objects.put(identifier, value);
return exists;
@@ -60,22 +65,22 @@ public class OpenRegistry<T> implements Registry<T> {
@Override
public T get(String identifier) {
return objects.get(identifier);
return objects.get(identifier).getValue();
}
@Override
public void forEach(Consumer<T> consumer) {
objects.forEach((id, obj) -> consumer.accept(obj));
objects.forEach((id, obj) -> consumer.accept(obj.getRaw()));
}
@Override
public void forEach(BiConsumer<String, T> consumer) {
objects.forEach(consumer);
objects.forEach((id, entry) -> consumer.accept(id, entry.getRaw()));
}
@Override
public Set<T> entries() {
return new HashSet<>(objects.values());
return objects.values().stream().map(Entry::getRaw).collect(Collectors.toSet());
}
@Override
@@ -83,10 +88,41 @@ public class OpenRegistry<T> implements Registry<T> {
return objects.keySet();
}
public Map<String, T> getDeadEntries() {
Map<String, T> dead = new HashMap<>();
objects.forEach((id, entry) -> {
if(entry.dead()) dead.put(id, entry.value); // dont increment value here.
});
return dead;
}
/**
* Clears all entries from the registry.
*/
public void clear() {
objects.clear();
}
protected static final class Entry<T> {
private final T value;
private final AtomicInteger access = new AtomicInteger(0);
public Entry(T value) {
this.value = value;
}
public T getValue() {
access.incrementAndGet();
return value;
}
private T getRaw() {
return value;
}
public boolean dead() {
return access.get() == 0;
}
}
}
@@ -57,7 +57,9 @@ public class FloraRegistry extends OpenRegistry<Flora> {
private void addItem(String id, Callable<ConstantFlora> flora) {
try {
add(id, flora.call());
Entry<Flora> entry = new Entry<>(flora.call());
entry.getValue(); // Mark as not dead.
add(id, entry);
} catch(Exception e) {
main.logger().warning("Failed to load Flora item: " + id + ": " + e.getMessage());
}
@@ -33,7 +33,7 @@ public class FloraPopulator implements TerraBlockPopulator {
public void populate(@NotNull World world, @NotNull Chunk chunk) {
TerraWorld tw = main.getWorld(world);
try(ProfileFuture ignored = tw.getProfiler().measure("FloraTime")) {
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(ProfileFuture ignored = tw.getProfiler().measure("OreTime")) {
if(tw.getConfig().getTemplate().disableCarvers()) return;
if(tw.getConfig().getTemplate().disableOres()) return;
if(!tw.isSafe()) return;
for(int cx = -1; cx <= 1; cx++) {
@@ -33,7 +33,7 @@ public class StructurePopulator implements TerraBlockPopulator, Chunkified {
public void populate(@NotNull World world, @NotNull Chunk chunk) {
TerraWorld tw = main.getWorld(world);
try(ProfileFuture ignored = tw.getProfiler().measure("StructureTime")) {
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(ProfileFuture ignored = tw.getProfiler().measure("TreeTime")) {
if(tw.getConfig().getTemplate().disableCarvers()) return;
if(tw.getConfig().getTemplate().disableTrees()) return;
if(!tw.isSafe()) return;
BiomeProvider provider = tw.getBiomeProvider();
+5
View File
@@ -0,0 +1,5 @@
# Boolean
A Boolean data type represents a logical boolean value, a value which can
be either `true` or `false`.
+10
View File
@@ -0,0 +1,10 @@
# Double
A Double type represents a double-precision floating point value.
Essentially, a Double is a decimal number.
Examples:
* `5`
* `0.3`
* `-12.5`
* `100.3`
+10
View File
@@ -0,0 +1,10 @@
# Integer
An Integer data type represents a Java integer, a whole number with
a minimum value of -2^31, and a maximum value of 2^31-1.
Examples:
* `0`
* `5`
* `-20`
* `123456`
+17
View File
@@ -0,0 +1,17 @@
# List
A List is an ordered collection of objects of a specific type.
Examples:
* A List of [Strings](./String)s
```yml
- "thing"
- "thing 2"
- "thing 3"
```
* A List of [Integers](./Integer)
```yml
- 1
- 2
- 3
```
+17
View File
@@ -0,0 +1,17 @@
# Map
A map is a data structure that "maps" one type (keys) to another (values).
Examples:
* Mapping [Strings](./String) to [Strings](./String)
```yml
a: "thing"
b: "thing 2"
c: "thing 3"
```
* Mapping [Strings](./String) to [Integers](./Integer)
```yml
a: 1
b: 2
c: 3
```
@@ -0,0 +1,50 @@
# ProbabilityCollection
A Probability Collection is a representation of a weighted pool.
Example:
* `a` has a 1/5 (20%) chance, `b` and `c` both have a 2/5 (40%) chance.
```yml
- a: 1
- b: 2
- c: 2
```
# Weighted Pool
A weighted pool is a way to randomly select one of many objects from a "pool" based on "weight".
## Pools
A pool is a list of objects from which selections will be pulled.
## Weight
Weight is the *relative* probability that any object will be selected from the pool. Each object in the pool has a
weight, meaning the chance of object O being selected from pool P is `weight(O)/sum(weight(P_n))`.
## Example
Here's an example pool:
```yaml
OPTION_A: 2
OPTION_B: 1
OPTION_C: 1
```
In this YAML-based pool, the keys are the objects, and the values are the weights. If we want the probability that
`OPTION_A` will be selected, we sum all weights, and divide the weight of `OPTION_A` by that sum.
`2 + 1 + 1 = 4`
Therefore the probability that OPTION_A will be selected is `2/4`, or 50%.
## Manipulating weights to get a desired probability
What if we want Option A to have a 60% chance of being selected? This requires manipulating the weights of all objects
in the pool, since with B and C having a weight of 1, there is no integer weight that can be assigned to A that will
give it a probability of 60%. What is usually done is that the weights are given a set sum that is easy to work with.
Usually this is 100, since with a sum of 100, every object's weight is equal to the percent chance it will be selected.
By applying this to the above example, we can produce this pool that has a 60% chance of A being selected:
```yaml
OPTION_A: 60
OPTION_B: 20
OPTION_C: 20
```
## Use Cases
Sometimes, it is undesirable to have an equal probability of all objects being selected, so you may want to "weight"
some objects higher, so they are selected more often.
+17
View File
@@ -0,0 +1,17 @@
# Set
A Set is very similar to a [List](./List), except it is *unordered*.
Examples:
* A Set of [Strings](./String).
```yml
- "thing"
- "thing 2"
- "thing 3"
```
* A Set of [Integers](./Integer).
```yml
- 1
- 2
- 3
```
+13
View File
@@ -0,0 +1,13 @@
# String
A String data type represents a string of characters.
Examples:
* `"Hello, World!"`
* ```
A
Multi
Line
String
```
* `"Something"`
+7 -13
View File
@@ -16,19 +16,12 @@ configureCommon()
group = "com.dfsek.terra.bukkit"
val mcVersion = "1.16.5"
val testDir = "target/server/"
val testDir = "target/server"
val testMem = "3G"
val paperURL = "https://papermc.io/api/v1/paper/%version%/latest/download/"
val purpurURL = "https://ci.pl3x.net/job/Purpur/lastSuccessfulBuild/artifact/final/purpurclip.jar"
repositories {
mavenCentral()
maven { url = uri("http://maven.enginehub.org/repo/") }
maven { url = uri("https://repo.codemc.org/repository/maven-public") }
maven { url = uri("https://papermc.io/repo/repository/maven-public/") }
}
dependencies {
"shadedApi"(project(":common"))
@@ -39,17 +32,17 @@ dependencies {
"compileOnly"("com.sk89q.worldedit:worldedit-bukkit:7.2.0-SNAPSHOT")
"shadedImplementation"("com.google.guava:guava:30.0-jre")
"shadedApi"("com.google.guava:guava:30.0-jre")
}
val aikarsFlags = listOf("-XX:+UseG1GC", "-XX:+ParallelRefProcEnabled", "-XX:MaxGCPauseMillis=200",
val jvmFlags = listOf("-XX:+UseG1GC", "-XX:+ParallelRefProcEnabled", "-XX:MaxGCPauseMillis=200",
"-XX:+UnlockExperimentalVMOptions", "-XX:+DisableExplicitGC", "-XX:+AlwaysPreTouch",
"-XX:G1NewSizePercent=30", "-XX:G1MaxNewSizePercent=40", "-XX:G1HeapRegionSize=8M",
"-XX:G1ReservePercent=20", "-XX:G1HeapWastePercent=5", "-XX:G1MixedGCCountTarget=4",
"-XX:InitiatingHeapOccupancyPercent=15", "-XX:G1MixedGCLiveThresholdPercent=90",
"-XX:G1RSetUpdatingPauseTimePercent=5", "-XX:SurvivorRatio=32", "-XX:+PerfDisableSharedMem",
"-XX:MaxTenuringThreshold=1", "-Dusing.aikars.flags=https://mcflags.emc.gs",
"-Daikars.new.flags=true", "-DIReallyKnowWhatIAmDoingISwear")
"-Daikars.new.flags=true", "-DIReallyKnowWhatIAmDoingISwear", "-javaagent:paperclip.jar")
fun downloadPaperclip(url: String, dir: String) {
val clip = URL(url.replace("%version%", mcVersion))
@@ -160,7 +153,7 @@ task<JavaExec>(name = "runPaper") {
}
main = "io.papermc.paperclip.Paperclip"
jvmArgs = aikarsFlags
jvmArgs = jvmFlags
maxHeapSize = testMem
minHeapSize = testMem
//args = listOf("nogui")
@@ -178,7 +171,7 @@ task<JavaExec>(name = "runPurpur") {
}
main = "io.papermc.paperclip.Paperclip"
jvmArgs = aikarsFlags
jvmArgs = jvmFlags
maxHeapSize = testMem
minHeapSize = testMem
//args = listOf("nogui")
@@ -189,6 +182,7 @@ task<JavaExec>(name = "runPurpur") {
tasks.named<ShadowJar>("shadowJar") {
relocate("org.bstats.bukkit", "com.dfsek.terra.lib.bstats")
relocate("io.papermc.lib", "com.dfsek.terra.lib.paperlib")
relocate("com.google.common", "com.dfsek.terra.lib.google.common")
}
publishing {
@@ -22,7 +22,9 @@ public class TerraListener implements EventListener {
public void injectTrees(ConfigPackPreLoadEvent event) {
for(TreeType value : TreeType.values()) {
try {
event.getPack().getTreeRegistry().add(BukkitAdapter.TREE_TRANSFORMER.translate(value), new BukkitTree(value, main));
String id = BukkitAdapter.TREE_TRANSFORMER.translate(value);
event.getPack().getTreeRegistry().add(id, new BukkitTree(value, main));
event.getPack().getTreeRegistry().get(id); // Platform trees should never be marked "dead"
} catch(DuplicateEntryException ignore) { // If another addon has already registered trees, do nothing.
}
}
+25 -7
View File
@@ -6,6 +6,7 @@ import net.fabricmc.loom.task.RemapJarTask
plugins {
`java-library`
`maven-publish`
id("fabric-loom").version("0.6-SNAPSHOT")
id("com.modrinth.minotaur").version("1.1.0")
}
@@ -21,8 +22,6 @@ group = "com.dfsek.terra.fabric"
dependencies {
"shadedApi"(project(":common"))
"shadedImplementation"("org.yaml:snakeyaml:1.27")
"shadedImplementation"("com.googlecode.json-simple:json-simple:1.1.1")
"minecraft"("com.mojang:minecraft:1.16.5")
"mappings"("net.fabricmc:yarn:1.16.5+build.5:v2")
@@ -31,11 +30,6 @@ dependencies {
"modImplementation"("net.fabricmc.fabric-api:fabric-api:0.31.0+1.16")
}
tasks.named<ShadowJar>("shadowJar") {
relocate("org.json", "com.dfsek.terra.lib.json")
relocate("org.yaml", "com.dfsek.terra.lib.yaml")
}
configure<LoomGradleExtension> {
accessWidener("src/main/resources/terra.accesswidener")
@@ -63,4 +57,28 @@ tasks.register<TaskModrinthUpload>("publishModrinth") {
addGameVersion("1.16.4")
addGameVersion("1.16.5")
addLoader("fabric")
}
publishing {
publications {
create<MavenPublication>("mavenJava") {
artifact(tasks["sourcesJar"])
artifact(tasks["jar"])
}
}
repositories {
val mavenUrl = "https://repo.codemc.io/repository/maven-releases/"
maven(mavenUrl) {
val mavenUsername: String? by project
val mavenPassword: String? by project
if (mavenUsername != null && mavenPassword != null) {
credentials {
username = mavenUsername
password = mavenPassword
}
}
}
}
}
@@ -157,6 +157,12 @@ public class TerraFabricPlugin implements TerraPlugin, ModInitializer {
});
}
public TerraWorld getWorld(long seed) {
TerraWorld world = worldMap.get(seed);
if(world == null) throw new IllegalArgumentException("No world exists with seed " + seed);
return world;
}
@Override
public Logger logger() {
return logger;
@@ -242,10 +248,6 @@ public class TerraFabricPlugin implements TerraPlugin, ModInitializer {
}
private Biome createBiome(BiomeBuilder biome) {
SpawnSettings.Builder spawnSettings = new SpawnSettings.Builder();
DefaultBiomeFeatures.addFarmAnimals(spawnSettings);
DefaultBiomeFeatures.addMonsters(spawnSettings, 95, 5, 100);
BiomeTemplate template = biome.getTemplate();
Map<String, Integer> colors = template.getColors();
@@ -283,7 +285,7 @@ public class TerraFabricPlugin implements TerraPlugin, ModInitializer {
.temperature(vanilla.getTemperature())
.downfall(vanilla.getDownfall())
.effects(effects.build())
.spawnSettings(spawnSettings.build())
.spawnSettings(vanilla.getSpawnSettings())
.generationSettings(generationSettings.build())
.build();
}
@@ -9,6 +9,7 @@ import com.dfsek.terra.api.platform.block.state.BlockState;
import com.dfsek.terra.fabric.world.FabricAdapter;
import com.dfsek.terra.fabric.world.block.state.FabricBlockState;
import com.dfsek.terra.fabric.world.handles.world.FabricWorldAccess;
import net.minecraft.block.FluidBlock;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.WorldAccess;
@@ -21,7 +22,10 @@ public class FabricBlock implements Block {
@Override
public void setBlockData(BlockData data, boolean physics) {
delegate.worldAccess.setBlockState(delegate.position, ((FabricBlockData) data).getHandle(), physics ? 3 : 1042, 0);
delegate.worldAccess.setBlockState(delegate.position, ((FabricBlockData) data).getHandle(), physics ? 3 : 1042);
if(physics && ((FabricBlockData) data).getHandle().getBlock() instanceof FluidBlock) {
delegate.worldAccess.getFluidTickScheduler().schedule(delegate.position, ((FluidBlock) ((FabricBlockData) data).getHandle().getBlock()).getFluidState(((FabricBlockData) data).getHandle()).getFluid(), 0);
}
}
@Override
@@ -7,7 +7,9 @@ import com.dfsek.terra.config.pack.ConfigPack;
import com.dfsek.terra.fabric.TerraFabricPlugin;
import com.dfsek.terra.fabric.world.TerraBiomeSource;
import com.dfsek.terra.fabric.world.handles.world.FabricSeededWorldAccess;
import com.dfsek.terra.world.TerraWorld;
import com.dfsek.terra.world.generation.generators.DefaultChunkGenerator3D;
import com.dfsek.terra.world.generation.math.samplers.Sampler;
import com.dfsek.terra.world.population.CavePopulator;
import com.dfsek.terra.world.population.FloraPopulator;
import com.dfsek.terra.world.population.OrePopulator;
@@ -15,6 +17,7 @@ import com.dfsek.terra.world.population.StructurePopulator;
import com.dfsek.terra.world.population.TreePopulator;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.jafama.FastMath;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.structure.StructureManager;
@@ -107,7 +110,18 @@ public class FabricChunkGeneratorWrapper extends ChunkGenerator implements Gener
@Override
public int getHeight(int x, int z, Heightmap.Type heightmapType) {
return 0;
TerraWorld world = TerraFabricPlugin.getInstance().getWorld(seed);
Sampler sampler = world.getConfig().getSamplerCache().getChunk(FastMath.floorDiv(x, 16), FastMath.floorDiv(z, 16));
int cx = FastMath.floorMod(x, 16);
int cz = FastMath.floorMod(z, 16);
int height = world.getWorld().getMaxHeight();
while (height >= 0 && sampler.sample(cx, height - 1, cz) < 0) {
height--;
}
return height;
}
@Override