mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2026-02-16 18:40:46 +00:00
Compare commits
41 Commits
dev/minest
...
dev/sample
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
54e6fb0587 | ||
|
|
798f3423a5 | ||
|
|
111f6b05ba | ||
|
|
0693b03bba | ||
|
|
5397df57b8 | ||
|
|
aa0de88821 | ||
|
|
bd3136ca92 | ||
|
|
339413c0de | ||
|
|
31b55ca682 | ||
|
|
aaf0830d66 | ||
|
|
f78ee70609 | ||
|
|
9c1a35f444 | ||
|
|
f4716cb28f | ||
|
|
b3e3c28276 | ||
|
|
4eadbb7d83 | ||
|
|
7b3b341627 | ||
|
|
89267ce8cb | ||
|
|
78e3575d9b | ||
|
|
e671ef783f | ||
|
|
91144dc8f8 | ||
|
|
5ac7257517 | ||
|
|
9f4f9702a6 | ||
|
|
01d169256e | ||
|
|
7a703ad091 | ||
|
|
4202875675 | ||
|
|
4237657dad | ||
|
|
75cb6be36f | ||
|
|
88a7397bbe | ||
|
|
ce9273c7e8 | ||
|
|
653a414ac1 | ||
|
|
2080db21ca | ||
|
|
a6a1810b4a | ||
|
|
da4aebe498 | ||
|
|
03ebafc7b6 | ||
|
|
a78e64a9bb | ||
|
|
6374b0ab08 | ||
|
|
473ed45dee | ||
|
|
d96d834a08 | ||
|
|
f756ebef44 | ||
|
|
e6931a53d6 | ||
|
|
58b5f3a5fe |
@@ -1,6 +1,6 @@
|
||||
import com.dfsek.terra.getGitHash
|
||||
|
||||
val versionObj = Version("5", "1", "2", true)
|
||||
val versionObj = Version("6", "0", "0", 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
|
||||
|
||||
@@ -14,13 +14,14 @@ dependencies {
|
||||
"shadedApi"("commons-io:commons-io:2.4")
|
||||
|
||||
"shadedApi"("com.dfsek:Paralithic:0.3.2")
|
||||
"shadedApi"("com.dfsek:Tectonic:1.2.3")
|
||||
"shadedApi"("com.dfsek:Tectonic:1.3.1")
|
||||
"shadedApi"("net.jafama:jafama:2.3.2")
|
||||
"shadedApi"("org.yaml:snakeyaml:1.27")
|
||||
"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")
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.dfsek.terra.api.util.logging.Logger;
|
||||
import com.dfsek.terra.config.PluginConfig;
|
||||
import com.dfsek.terra.config.lang.Language;
|
||||
import com.dfsek.terra.config.pack.ConfigPack;
|
||||
import com.dfsek.terra.profiler.Profiler;
|
||||
import com.dfsek.terra.world.TerraWorld;
|
||||
|
||||
import java.io.File;
|
||||
@@ -64,4 +65,6 @@ public interface TerraPlugin extends LoaderRegistrar {
|
||||
default void runPossiblyUnsafeTask(Runnable task) {
|
||||
task.run();
|
||||
}
|
||||
|
||||
Profiler getProfiler();
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ 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;
|
||||
@@ -68,7 +69,7 @@ public class CheckedRegistry<T> implements Registry<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<T> entries() {
|
||||
public Collection<T> entries() {
|
||||
return registry.entries();
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ 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;
|
||||
@@ -41,7 +42,7 @@ public class LockedRegistry<T> implements Registry<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<T> entries() {
|
||||
public Collection<T> entries() {
|
||||
return registry.entries();
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ 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;
|
||||
@@ -42,7 +43,7 @@ public interface Registry<T> extends TypeLoader<T> {
|
||||
*
|
||||
* @return Set containing all entries.
|
||||
*/
|
||||
Set<T> entries();
|
||||
Collection<T> entries();
|
||||
|
||||
/**
|
||||
* Get all the keys in this registry.
|
||||
|
||||
@@ -3,10 +3,13 @@ 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;
|
||||
@@ -29,9 +32,7 @@ import com.dfsek.terra.api.structures.structure.Rotation;
|
||||
import com.dfsek.terra.api.structures.structure.buffer.Buffer;
|
||||
import com.dfsek.terra.api.structures.structure.buffer.DirectBuffer;
|
||||
import com.dfsek.terra.api.structures.structure.buffer.StructureBuffer;
|
||||
import com.dfsek.terra.registry.config.FunctionRegistry;
|
||||
import com.dfsek.terra.registry.config.LootRegistry;
|
||||
import com.dfsek.terra.registry.config.ScriptRegistry;
|
||||
import com.dfsek.terra.profiler.ProfileFrame;
|
||||
import com.google.common.cache.Cache;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import net.jafama.FastMath;
|
||||
@@ -39,6 +40,7 @@ import org.apache.commons.io.IOUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
@@ -49,10 +51,10 @@ public class StructureScript {
|
||||
private final TerraPlugin main;
|
||||
private String tempID;
|
||||
|
||||
public StructureScript(InputStream inputStream, TerraPlugin main, ScriptRegistry registry, LootRegistry lootRegistry, FunctionRegistry functionRegistry) throws ParseException {
|
||||
public StructureScript(InputStream inputStream, TerraPlugin main, Registry<StructureScript> registry, Registry<LootTable> lootRegistry, Registry<FunctionBuilder<?>> functionRegistry) throws ParseException {
|
||||
Parser parser;
|
||||
try {
|
||||
parser = new Parser(IOUtils.toString(inputStream));
|
||||
parser = new Parser(IOUtils.toString(inputStream, Charset.defaultCharset()));
|
||||
} catch(IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
@@ -104,22 +106,31 @@ public class StructureScript {
|
||||
* @param rotation Rotation of structure
|
||||
* @return Whether generation was successful
|
||||
*/
|
||||
@SuppressWarnings("try")
|
||||
public boolean execute(Location location, Random random, Rotation rotation) {
|
||||
StructureBuffer buffer = new StructureBuffer(location);
|
||||
boolean level = applyBlock(new TerraImplementationArguments(buffer, rotation, random, 0));
|
||||
buffer.paste();
|
||||
return level;
|
||||
try(ProfileFrame ignore = main.getProfiler().profile("terrascript:" + id)) {
|
||||
StructureBuffer buffer = new StructureBuffer(location);
|
||||
boolean level = applyBlock(new TerraImplementationArguments(buffer, rotation, random, 0));
|
||||
buffer.paste();
|
||||
return level;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("try")
|
||||
public boolean execute(Location location, Chunk chunk, Random random, Rotation rotation) {
|
||||
StructureBuffer buffer = computeBuffer(location, random, rotation);
|
||||
buffer.paste(chunk);
|
||||
return buffer.succeeded();
|
||||
try(ProfileFrame ignore = main.getProfiler().profile("terrascript_chunk:" + id)) {
|
||||
StructureBuffer buffer = computeBuffer(location, random, rotation);
|
||||
buffer.paste(chunk);
|
||||
return buffer.succeeded();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("try")
|
||||
public boolean test(Location location, Random random, Rotation rotation) {
|
||||
StructureBuffer buffer = computeBuffer(location, random, rotation);
|
||||
return buffer.succeeded();
|
||||
try(ProfileFrame ignore = main.getProfiler().profile("terrascript_test:" + id)) {
|
||||
StructureBuffer buffer = computeBuffer(location, random, rotation);
|
||||
return buffer.succeeded();
|
||||
}
|
||||
}
|
||||
|
||||
private StructureBuffer computeBuffer(Location location, Random random, Rotation rotation) {
|
||||
@@ -134,13 +145,19 @@ public class StructureScript {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("try")
|
||||
public boolean executeInBuffer(Buffer buffer, Random random, Rotation rotation, int recursions) {
|
||||
return applyBlock(new TerraImplementationArguments(buffer, rotation, random, recursions));
|
||||
try(ProfileFrame ignore = main.getProfiler().profile("terrascript_recursive:" + id)) {
|
||||
return applyBlock(new TerraImplementationArguments(buffer, rotation, random, recursions));
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("try")
|
||||
public boolean executeDirect(Location location, Random random, Rotation rotation) {
|
||||
DirectBuffer buffer = new DirectBuffer(location);
|
||||
return applyBlock(new TerraImplementationArguments(buffer, rotation, random, 0));
|
||||
try(ProfileFrame ignore = main.getProfiler().profile("terrascript_direct:" + id)) {
|
||||
DirectBuffer buffer = new DirectBuffer(location);
|
||||
return applyBlock(new TerraImplementationArguments(buffer, rotation, random, 0));
|
||||
}
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
|
||||
@@ -1,21 +1,22 @@
|
||||
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 LootRegistry registry;
|
||||
private final Registry<LootTable> registry;
|
||||
private final StructureScript script;
|
||||
|
||||
public LootFunctionBuilder(TerraPlugin main, LootRegistry registry, StructureScript script) {
|
||||
public LootFunctionBuilder(TerraPlugin main, Registry<LootTable> registry, StructureScript script) {
|
||||
this.main = main;
|
||||
this.registry = registry;
|
||||
this.script = script;
|
||||
|
||||
@@ -1,21 +1,22 @@
|
||||
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 ScriptRegistry registry;
|
||||
private final Registry<StructureScript> registry;
|
||||
private final TerraPlugin main;
|
||||
|
||||
public StructureFunctionBuilder(ScriptRegistry registry, TerraPlugin main) {
|
||||
public StructureFunctionBuilder(Registry<StructureScript> registry, TerraPlugin main) {
|
||||
this.registry = registry;
|
||||
this.main = main;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ 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;
|
||||
@@ -13,20 +14,19 @@ 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 LootRegistry registry;
|
||||
private final Registry<LootTable> 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(LootRegistry registry, Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, Returnable<String> data, TerraPlugin main, Position position, 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) {
|
||||
this.registry = registry;
|
||||
this.position = position;
|
||||
this.data = data;
|
||||
|
||||
@@ -3,6 +3,7 @@ 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;
|
||||
@@ -13,21 +14,20 @@ 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 ScriptRegistry registry;
|
||||
private final Registry<StructureScript> 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, ScriptRegistry registry, Position position, TerraPlugin main) {
|
||||
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) {
|
||||
this.registry = registry;
|
||||
this.id = id;
|
||||
this.position = position;
|
||||
|
||||
@@ -15,6 +15,7 @@ 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'));
|
||||
@@ -28,7 +29,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", current.getPosition());
|
||||
if(!hasNext()) throw new ParseException("Unexpected end of input", last.getPosition());
|
||||
return current;
|
||||
}
|
||||
|
||||
@@ -39,7 +40,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", current.getPosition());
|
||||
if(!hasNext()) throw new ParseException("Unexpected end of input", last.getPosition());
|
||||
Token temp = current;
|
||||
current = fetchCheck();
|
||||
return temp;
|
||||
@@ -57,8 +58,9 @@ public class Tokenizer {
|
||||
private Token fetchCheck() throws ParseException {
|
||||
Token fetch = fetch();
|
||||
if(fetch != null) {
|
||||
if(fetch.getType().equals(Token.Type.BLOCK_BEGIN)) brackets.push(fetch); // Opening bracket
|
||||
else if(fetch.getType().equals(Token.Type.BLOCK_END)) {
|
||||
last = fetch;
|
||||
if(fetch.getType() == Token.Type.BLOCK_BEGIN) brackets.push(fetch); // Opening bracket
|
||||
else if(fetch.getType() == Token.Type.BLOCK_END) {
|
||||
if(!brackets.isEmpty()) brackets.pop();
|
||||
else throw new ParseException("Dangling opening brace", new Position(0, 0));
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@ public class Transformer<F, T> {
|
||||
private final LinkedHashMap<Transform<F, T>, List<Validator<T>>> transforms = new LinkedHashMap<>();
|
||||
|
||||
@SafeVarargs
|
||||
@SuppressWarnings("varargs")
|
||||
public final Builder<F, T> addTransform(Transform<F, T> transform, Validator<T>... validators) {
|
||||
transforms.put(transform, Arrays.asList(validators));
|
||||
return this;
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
package com.dfsek.terra.api.util.generic.pair;
|
||||
|
||||
public class ImmutablePair<L, R> {
|
||||
public final class ImmutablePair<L, R> {
|
||||
private final L left;
|
||||
private final R right;
|
||||
|
||||
public ImmutablePair(L left, R right) {
|
||||
private static final ImmutablePair<?, ?> NULL = new ImmutablePair<>(null, null);
|
||||
|
||||
private ImmutablePair(L left, R right) {
|
||||
this.left = left;
|
||||
this.right = right;
|
||||
}
|
||||
@@ -21,7 +23,12 @@ public 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);
|
||||
return Pair.of(left, right);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ public class Pair<L, R> {
|
||||
private L left;
|
||||
private R right;
|
||||
|
||||
public Pair(L left, R right) {
|
||||
private Pair(L left, R right) {
|
||||
this.left = left;
|
||||
this.right = right;
|
||||
}
|
||||
@@ -30,6 +30,6 @@ public class Pair<L, R> {
|
||||
}
|
||||
|
||||
public ImmutablePair<L, R> immutable() {
|
||||
return new ImmutablePair<>(left, right);
|
||||
return ImmutablePair.of(left, right);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
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,14 +1,13 @@
|
||||
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<BlockData> getPalette(int x, int y, int z, BiomeTemplate c, Sampler sampler) {
|
||||
public static Palette getPalette(int x, int y, int z, BiomeTemplate c, Sampler sampler) {
|
||||
PaletteHolder slant = c.getSlantPalette();
|
||||
if(slant != null && MathUtil.derivative(sampler, x, y, z) > c.getSlantThreshold()) {
|
||||
return slant.getPalette(y);
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
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 {
|
||||
/**
|
||||
@@ -35,11 +37,13 @@ public interface Generator {
|
||||
*
|
||||
* @return BlocPalette - The biome's palette.
|
||||
*/
|
||||
Palette<BlockData> getPalette(int y);
|
||||
Palette getPalette(int y);
|
||||
|
||||
NoiseSampler getBiomeNoise();
|
||||
|
||||
double getElevationWeight();
|
||||
|
||||
int getBlendStep();
|
||||
|
||||
List<TerrainSampler> getTerrainSamplers();
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
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<E> extends Palette<E> {
|
||||
public class NoisePalette extends Palette {
|
||||
private final NoiseSampler sampler;
|
||||
private final boolean is2D;
|
||||
|
||||
@@ -14,11 +15,11 @@ public class NoisePalette<E> extends Palette<E> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public E get(int layer, double x, double y, double z) {
|
||||
PaletteLayer<E> paletteLayer;
|
||||
public BlockData get(int layer, double x, double y, double z) {
|
||||
PaletteLayer paletteLayer;
|
||||
if(layer > this.getSize()) paletteLayer = this.getLayers().get(this.getLayers().size() - 1);
|
||||
else {
|
||||
List<PaletteLayer<E>> pl = getLayers();
|
||||
List<PaletteLayer> pl = getLayers();
|
||||
if(layer >= pl.size()) paletteLayer = pl.get(pl.size() - 1);
|
||||
else paletteLayer = pl.get(layer);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
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;
|
||||
|
||||
@@ -11,8 +12,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<E> {
|
||||
private final List<PaletteLayer<E>> pallet = new GlueList<>();
|
||||
public abstract class Palette {
|
||||
private final List<PaletteLayer> pallet = new GlueList<>();
|
||||
|
||||
/**
|
||||
* Constructs a blank palette.
|
||||
@@ -21,16 +22,16 @@ public abstract class Palette<E> {
|
||||
|
||||
}
|
||||
|
||||
public com.dfsek.terra.api.world.palette.Palette<E> add(E m, int layers, NoiseSampler sampler) {
|
||||
public com.dfsek.terra.api.world.palette.Palette add(BlockData 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<E> add(ProbabilityCollection<E> m, int layers, NoiseSampler sampler) {
|
||||
public com.dfsek.terra.api.world.palette.Palette add(ProbabilityCollection<BlockData> 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;
|
||||
}
|
||||
@@ -41,25 +42,25 @@ public abstract class Palette<E> {
|
||||
* @param layer - The layer at which to fetch the material.
|
||||
* @return BlockData - The material fetched.
|
||||
*/
|
||||
public abstract E get(int layer, double x, double y, double z);
|
||||
public abstract BlockData get(int layer, double x, double y, double z);
|
||||
|
||||
|
||||
public int getSize() {
|
||||
return pallet.size();
|
||||
}
|
||||
|
||||
public List<PaletteLayer<E>> getLayers() {
|
||||
public List<PaletteLayer> getLayers() {
|
||||
return pallet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class representation of a layer of a BlockPalette.
|
||||
*/
|
||||
public static class PaletteLayer<E> {
|
||||
public static class PaletteLayer {
|
||||
private final boolean col; // Is layer using a collection?
|
||||
private ProbabilityCollection<E> collection;
|
||||
private ProbabilityCollection<BlockData> collection;
|
||||
private final NoiseSampler sampler;
|
||||
private E m;
|
||||
private BlockData m;
|
||||
|
||||
/**
|
||||
* Constructs a PaletteLayerHolder with a ProbabilityCollection of materials and a number of layers.
|
||||
@@ -67,7 +68,7 @@ public abstract class Palette<E> {
|
||||
* @param type The collection of materials to choose from.
|
||||
* @param sampler Noise sampler to use
|
||||
*/
|
||||
public PaletteLayer(ProbabilityCollection<E> type, NoiseSampler sampler) {
|
||||
public PaletteLayer(ProbabilityCollection<BlockData> type, NoiseSampler sampler) {
|
||||
this.sampler = sampler;
|
||||
this.col = true;
|
||||
this.collection = type;
|
||||
@@ -79,7 +80,7 @@ public abstract class Palette<E> {
|
||||
* @param type The material to use.
|
||||
* @param sampler Noise sampler to use
|
||||
*/
|
||||
public PaletteLayer(E type, NoiseSampler sampler) {
|
||||
public PaletteLayer(BlockData type, NoiseSampler sampler) {
|
||||
this.sampler = sampler;
|
||||
this.col = false;
|
||||
this.m = type;
|
||||
@@ -94,18 +95,18 @@ public abstract class Palette<E> {
|
||||
*
|
||||
* @return Material - the material..
|
||||
*/
|
||||
public E get(Random random) {
|
||||
public BlockData get(Random random) {
|
||||
if(col) return this.collection.get(random);
|
||||
return m;
|
||||
}
|
||||
|
||||
public E get(NoiseSampler random, double x, double y, double z, boolean is2D) {
|
||||
public BlockData 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<E> getCollection() {
|
||||
public ProbabilityCollection<BlockData> getCollection() {
|
||||
return collection;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
package com.dfsek.terra.api.world.palette;
|
||||
|
||||
public class SinglePalette<E> extends Palette<E> {
|
||||
private final E item;
|
||||
import com.dfsek.terra.api.platform.block.BlockData;
|
||||
|
||||
public SinglePalette(E item) {
|
||||
public class SinglePalette extends Palette {
|
||||
private final BlockData item;
|
||||
|
||||
public SinglePalette(BlockData item) {
|
||||
this.item = item;
|
||||
}
|
||||
|
||||
@Override
|
||||
public E get(int layer, double x, double y, double z) {
|
||||
public BlockData get(int layer, double x, double y, double z) {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
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<BlockData>[] palettes;
|
||||
private final Palette[] palettes;
|
||||
|
||||
protected PaletteHolder(Palette<BlockData>[] palettes) {
|
||||
protected PaletteHolder(Palette[] palettes) {
|
||||
this.palettes = palettes;
|
||||
}
|
||||
|
||||
public Palette<BlockData> getPalette(int y) {
|
||||
public Palette getPalette(int y) {
|
||||
return palettes[y];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
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;
|
||||
|
||||
@@ -8,19 +7,19 @@ import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
public class PaletteHolderBuilder {
|
||||
private final TreeMap<Integer, Palette<BlockData>> paletteMap = new TreeMap<>();
|
||||
private final TreeMap<Integer, Palette> paletteMap = new TreeMap<>();
|
||||
|
||||
public PaletteHolderBuilder add(int y, Palette<BlockData> palette) {
|
||||
public PaletteHolderBuilder add(int y, Palette palette) {
|
||||
paletteMap.put(y, palette);
|
||||
return this;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes", "RedundantSuppression"})
|
||||
public PaletteHolder build() {
|
||||
Palette<BlockData>[] palettes = new Palette[paletteMap.lastKey() + 1];
|
||||
Palette[] palettes = new Palette[paletteMap.lastKey() + 1];
|
||||
for(int y = 0; y <= FastMath.max(paletteMap.lastKey(), 255); y++) {
|
||||
Palette<BlockData> d = null;
|
||||
for(Map.Entry<Integer, Palette<BlockData>> e : paletteMap.entrySet()) {
|
||||
Palette d = null;
|
||||
for(Map.Entry<Integer, Palette> 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().getBiomeRegistry().get(arg);
|
||||
return main.getWorld(player.getWorld()).getConfig().getRegistry(TerraBiome.class).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().getBiomeRegistry().entries().stream().map(TerraBiome::getID).collect(Collectors.toList());
|
||||
return main.getWorld(player.getWorld()).getConfig().getRegistry(TerraBiome.class).entries().stream().map(TerraBiome::getID).collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,16 +4,10 @@ import com.dfsek.terra.api.TerraPlugin;
|
||||
import com.dfsek.terra.api.command.CommandTemplate;
|
||||
import com.dfsek.terra.api.command.annotation.Command;
|
||||
import com.dfsek.terra.api.command.annotation.type.DebugCommand;
|
||||
import com.dfsek.terra.api.command.annotation.type.PlayerCommand;
|
||||
import com.dfsek.terra.api.command.annotation.type.WorldCommand;
|
||||
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.TerraWorld;
|
||||
|
||||
@Command
|
||||
@WorldCommand
|
||||
@PlayerCommand
|
||||
@DebugCommand
|
||||
public class ProfileQueryCommand implements CommandTemplate {
|
||||
@Inject
|
||||
@@ -21,8 +15,9 @@ public class ProfileQueryCommand implements CommandTemplate {
|
||||
|
||||
@Override
|
||||
public void execute(CommandSender sender) {
|
||||
Player player = (Player) sender;
|
||||
TerraWorld world = main.getWorld(player.getWorld());
|
||||
player.sendMessage(world.getProfiler().getResultsFormatted());
|
||||
StringBuilder data = new StringBuilder("Terra Profiler data dump: \n");
|
||||
main.getProfiler().getTimings().forEach((id, timings) -> data.append(id).append(": ").append(timings.toString()).append('\n'));
|
||||
main.logger().info(data.toString());
|
||||
sender.sendMessage("Profiler data dumped to console.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,16 +4,10 @@ import com.dfsek.terra.api.TerraPlugin;
|
||||
import com.dfsek.terra.api.command.CommandTemplate;
|
||||
import com.dfsek.terra.api.command.annotation.Command;
|
||||
import com.dfsek.terra.api.command.annotation.type.DebugCommand;
|
||||
import com.dfsek.terra.api.command.annotation.type.PlayerCommand;
|
||||
import com.dfsek.terra.api.command.annotation.type.WorldCommand;
|
||||
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.TerraWorld;
|
||||
|
||||
@Command
|
||||
@WorldCommand
|
||||
@PlayerCommand
|
||||
@DebugCommand
|
||||
public class ProfileResetCommand implements CommandTemplate {
|
||||
@Inject
|
||||
@@ -21,9 +15,7 @@ public class ProfileResetCommand implements CommandTemplate {
|
||||
|
||||
@Override
|
||||
public void execute(CommandSender sender) {
|
||||
Player player = (Player) sender;
|
||||
TerraWorld world = main.getWorld(player.getWorld());
|
||||
world.getProfiler().reset();
|
||||
player.sendMessage("Profiler reset.");
|
||||
main.getProfiler().reset();
|
||||
sender.sendMessage("Profiler reset.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,16 +4,10 @@ import com.dfsek.terra.api.TerraPlugin;
|
||||
import com.dfsek.terra.api.command.CommandTemplate;
|
||||
import com.dfsek.terra.api.command.annotation.Command;
|
||||
import com.dfsek.terra.api.command.annotation.type.DebugCommand;
|
||||
import com.dfsek.terra.api.command.annotation.type.PlayerCommand;
|
||||
import com.dfsek.terra.api.command.annotation.type.WorldCommand;
|
||||
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.TerraWorld;
|
||||
|
||||
@Command
|
||||
@WorldCommand
|
||||
@PlayerCommand
|
||||
@DebugCommand
|
||||
public class ProfileStartCommand implements CommandTemplate {
|
||||
@Inject
|
||||
@@ -21,9 +15,7 @@ public class ProfileStartCommand implements CommandTemplate {
|
||||
|
||||
@Override
|
||||
public void execute(CommandSender sender) {
|
||||
Player player = (Player) sender;
|
||||
TerraWorld world = main.getWorld(player.getWorld());
|
||||
world.getProfiler().setProfiling(true);
|
||||
player.sendMessage("Profiling enabled.");
|
||||
main.getProfiler().start();
|
||||
sender.sendMessage("Profiling enabled.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,16 +4,10 @@ import com.dfsek.terra.api.TerraPlugin;
|
||||
import com.dfsek.terra.api.command.CommandTemplate;
|
||||
import com.dfsek.terra.api.command.annotation.Command;
|
||||
import com.dfsek.terra.api.command.annotation.type.DebugCommand;
|
||||
import com.dfsek.terra.api.command.annotation.type.PlayerCommand;
|
||||
import com.dfsek.terra.api.command.annotation.type.WorldCommand;
|
||||
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.TerraWorld;
|
||||
|
||||
@Command
|
||||
@WorldCommand
|
||||
@PlayerCommand
|
||||
@DebugCommand
|
||||
public class ProfileStopCommand implements CommandTemplate {
|
||||
@Inject
|
||||
@@ -21,9 +15,7 @@ public class ProfileStopCommand implements CommandTemplate {
|
||||
|
||||
@Override
|
||||
public void execute(CommandSender sender) {
|
||||
Player player = (Player) sender;
|
||||
TerraWorld world = main.getWorld(player.getWorld());
|
||||
world.getProfiler().setProfiling(false);
|
||||
player.sendMessage("Profiling disabled.");
|
||||
main.getProfiler().stop();
|
||||
sender.sendMessage("Profiling disabled.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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().getScriptRegistry().get(arg);
|
||||
return main.getWorld(((Player) sender).getWorld()).getConfig().getRegistry(StructureScript.class).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().getStructureRegistry().get(arg);
|
||||
return main.getWorld(((Player) sender).getWorld()).getConfig().getRegistry(TerraStructure.class).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().getScriptRegistry().entries().stream().map(StructureScript::getId).collect(Collectors.toList());
|
||||
return main.getWorld(((Player) sender).getWorld()).getConfig().getRegistry(StructureScript.class).entries().stream().map(StructureScript::getId).collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ 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;
|
||||
@@ -16,6 +17,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().getStructureRegistry().keys());
|
||||
return new ArrayList<>(main.getWorld(player.getWorld()).getConfig().getRegistry(TerraStructure.class).keys());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ 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;
|
||||
@@ -13,7 +12,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<BlockData> palette = new NoisePalette<>(new WhiteNoiseSampler(2403), false);
|
||||
Palette palette = new NoisePalette(new WhiteNoiseSampler(2403), false);
|
||||
for(PaletteLayerHolder layer : config.getFloraPalette()) {
|
||||
palette.add(layer.getLayer(), layer.getSize(), layer.getSampler());
|
||||
}
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
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<BlockData>> {
|
||||
public class PaletteFactory implements ConfigFactory<PaletteTemplate, Palette> {
|
||||
@Override
|
||||
public Palette<BlockData> build(PaletteTemplate config, TerraPlugin main) {
|
||||
NoisePalette<BlockData> palette = new NoisePalette<>(config.getNoise().apply(2403L), config.getNoise().getDimensions() == 2);
|
||||
public Palette build(PaletteTemplate config, TerraPlugin main) {
|
||||
NoisePalette palette = new NoisePalette(config.getNoise().apply(2403L), config.getNoise().getDimensions() == 2);
|
||||
for(PaletteLayerHolder layer : config.getPalette()) {
|
||||
palette.add(layer.getLayer(), layer.getSize(), layer.getSampler());
|
||||
}
|
||||
|
||||
@@ -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() + 1);
|
||||
String rel = entry.getName().substring(directory.length());
|
||||
streams.put(rel, file.getInputStream(entry));
|
||||
} catch(IOException e) {
|
||||
e.printStackTrace();
|
||||
|
||||
@@ -5,7 +5,6 @@ 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;
|
||||
@@ -15,7 +14,6 @@ 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;
|
||||
@@ -23,7 +21,6 @@ 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");
|
||||
@@ -31,7 +28,6 @@ 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;
|
||||
|
||||
@@ -18,7 +18,7 @@ public class OreHolderLoader implements TypeLoader<OreHolder> {
|
||||
Map<String, Object> map = (Map<String, Object>) o;
|
||||
|
||||
for(Map.Entry<String, Object> entry : map.entrySet()) {
|
||||
holder.add(configLoader.loadClass(Ore.class, entry.getKey()), (OreConfig) configLoader.loadType(OreConfig.class, entry.getValue()));
|
||||
holder.add(configLoader.loadClass(Ore.class, entry.getKey()), configLoader.loadClass(OreConfig.class, entry.getValue()), entry.getKey());
|
||||
}
|
||||
|
||||
return holder;
|
||||
|
||||
@@ -6,8 +6,9 @@ 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;
|
||||
@@ -15,9 +16,9 @@ import java.util.Map;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public class NoiseSamplerBuilderLoader implements TypeLoader<NoiseSeeded> {
|
||||
private final NoiseRegistry noiseRegistry;
|
||||
private final Registry<NoiseProvider> noiseRegistry;
|
||||
|
||||
public NoiseSamplerBuilderLoader(NoiseRegistry noiseRegistry) {
|
||||
public NoiseSamplerBuilderLoader(Registry<NoiseProvider> noiseRegistry) {
|
||||
this.noiseRegistry = noiseRegistry;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,11 +3,9 @@ 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;
|
||||
@@ -21,7 +19,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<BlockData>) configLoader.loadType(Types.BLOCK_DATA_PALETTE_TYPE, entry.getKey()));
|
||||
builder.add(entry.getValue(), (Palette) configLoader.loadType(Palette.class, entry.getKey()));
|
||||
}
|
||||
}
|
||||
return builder.build();
|
||||
|
||||
@@ -2,36 +2,27 @@ 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;
|
||||
@@ -41,29 +32,16 @@ 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.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.config.prototype.ConfigType;
|
||||
import com.dfsek.terra.config.prototype.ProtoConfig;
|
||||
import com.dfsek.terra.registry.OpenRegistry;
|
||||
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.ConfigTypeRegistry;
|
||||
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;
|
||||
|
||||
@@ -74,12 +52,14 @@ 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;
|
||||
|
||||
@@ -89,38 +69,27 @@ 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);
|
||||
|
||||
@@ -139,6 +108,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);
|
||||
}
|
||||
@@ -151,17 +121,16 @@ 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);
|
||||
|
||||
register(selfLoader);
|
||||
main.register(selfLoader);
|
||||
main.register(abstractConfigLoader);
|
||||
|
||||
try {
|
||||
ZipEntry pack = null;
|
||||
@@ -183,6 +152,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);
|
||||
}
|
||||
@@ -194,10 +164,36 @@ public class ConfigPack implements LoaderRegistrar {
|
||||
toWorldConfig(new TerraWorld(new DummyWorld(), this, main)); // Build now to catch any errors immediately.
|
||||
}
|
||||
|
||||
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));
|
||||
@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)));
|
||||
}
|
||||
|
||||
private void checkDeadEntries(TerraPlugin main) {
|
||||
registryMap.forEach((clazz, pair) -> pair.getLeft().getDeadEntries().forEach((id, value) -> main.getDebugLogger().warn("Dead entry in '" + clazz + "' registry: '" + id + "'")));
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
private void load(long start, TerraPlugin main) throws ConfigException {
|
||||
main.getEventManager().callEvent(new ConfigPackPreLoadEvent(this));
|
||||
|
||||
@@ -208,8 +204,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, scriptRegistry, lootRegistry, functionRegistry);
|
||||
scriptRegistry.add(structureScript.getId(), structureScript);
|
||||
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);
|
||||
} catch(com.dfsek.terra.api.structures.parser.exceptions.ParseException | IOException e) {
|
||||
throw new LoadException("Unable to load script \"" + entry.getKey() + "\"", e);
|
||||
}
|
||||
@@ -217,36 +213,38 @@ public class ConfigPack implements LoaderRegistrar {
|
||||
}).close().open("structures/loot", ".json").thenEntries(entries -> {
|
||||
for(Map.Entry<String, InputStream> entry : entries) {
|
||||
try {
|
||||
lootRegistry.add(entry.getKey(), new LootTable(IOUtils.toString(entry.getValue(), StandardCharsets.UTF_8), main));
|
||||
getOpenRegistry(LootTable.class).add(entry.getKey(), new LootTable(IOUtils.toString(entry.getValue(), StandardCharsets.UTF_8), main));
|
||||
} catch(ParseException | IOException | NullPointerException e) {
|
||||
throw new LoadException("Unable to load loot table \"" + entry.getKey() + "\"", e);
|
||||
}
|
||||
}
|
||||
}).close();
|
||||
|
||||
loader
|
||||
.open("carving", ".yml").then(streams -> buildAll(new CarverFactory(this), carverRegistry, abstractConfigLoader.load(streams, CarverTemplate::new), main)).close()
|
||||
.open("palettes", ".yml").then(streams -> buildAll(new PaletteFactory(), paletteRegistry, abstractConfigLoader.load(streams, PaletteTemplate::new), main)).close()
|
||||
.open("ores", ".yml").then(streams -> buildAll(new OreFactory(), oreRegistry, abstractConfigLoader.load(streams, OreTemplate::new), main)).close()
|
||||
.open("structures/trees", ".yml").then(streams -> buildAll(new TreeFactory(), treeRegistry, abstractConfigLoader.load(streams, TreeTemplate::new), main)).close()
|
||||
.open("structures/structures", ".yml").then(streams -> buildAll(new StructureFactory(), structureRegistry, abstractConfigLoader.load(streams, StructureTemplate::new), main)).close()
|
||||
.open("flora", ".yml").then(streams -> buildAll(new FloraFactory(), floraRegistry, abstractConfigLoader.load(streams, FloraTemplate::new), main)).close()
|
||||
.open("biomes", ".yml").then(streams -> buildAll(new BiomeFactory(this), biomeRegistry, abstractConfigLoader.load(streams, () -> new BiomeTemplate(this, main)), main)).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);
|
||||
}
|
||||
}
|
||||
|
||||
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 structureRegistry.entries();
|
||||
}
|
||||
|
||||
public List<String> getStructureIDs() {
|
||||
return structureRegistry.entries().stream().map(terraStructure -> terraStructure.getTemplate().getID()).collect(Collectors.toList());
|
||||
return new HashSet<>(getRegistry(TerraStructure.class).entries());
|
||||
}
|
||||
|
||||
public ConfigPackTemplate getTemplate() {
|
||||
@@ -257,80 +255,45 @@ 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(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(ConfigType.class, configTypeRegistry)
|
||||
.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(biomeRegistry))
|
||||
.registerLoader(ImageSamplerTemplate.class, () -> new ImageProviderTemplate(biomeRegistry));
|
||||
}
|
||||
|
||||
public Set<UserDefinedCarver> getCarvers() {
|
||||
return carverRegistry.entries();
|
||||
.registerLoader(ImageProviderTemplate.class, () -> new ImageProviderTemplate(getRegistry(BiomeBuilder.class)))
|
||||
.registerLoader(ImageSamplerTemplate.class, () -> new ImageProviderTemplate(getRegistry(BiomeBuilder.class)))
|
||||
.registerLoader(NoiseSeeded.class, new NoiseSamplerBuilderLoader(getOpenRegistry(NoiseProvider.class)));
|
||||
}
|
||||
|
||||
public BiomeProvider.BiomeProviderBuilder getBiomeProviderBuilder() {
|
||||
return biomeProviderBuilder;
|
||||
}
|
||||
|
||||
public CheckedRegistry<StructureScript> getScriptRegistry() {
|
||||
return new CheckedRegistry<>(scriptRegistry);
|
||||
}
|
||||
|
||||
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){
|
||||
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,62 +1,51 @@
|
||||
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);
|
||||
this.scriptRegistry = new LockedRegistry<>(pack.getScriptRegistry());
|
||||
|
||||
pack.getConfigTypeRegistry().forEach(configType -> registryMap.put(configType.getTypeClass(), new LockedRegistry<>(pack.getRegistry(configType.getTypeClass()))));
|
||||
|
||||
|
||||
OpenRegistry<TerraBiome> biomeOpenRegistry = new OpenRegistry<>();
|
||||
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());
|
||||
pack.getRegistry(BiomeBuilder.class).forEach((id, biome) -> biomeOpenRegistry.add(id, biome.apply(world.getWorld().getSeed())));
|
||||
registryMap.put(TerraBiome.class, new LockedRegistry<>(biomeOpenRegistry));
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -66,43 +55,7 @@ public class WorldConfig {
|
||||
}
|
||||
|
||||
public Set<UserDefinedCarver> getCarvers() {
|
||||
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;
|
||||
return new HashSet<>(getRegistry(UserDefinedCarver.class).entries());
|
||||
}
|
||||
|
||||
public BiomeProvider getProvider() {
|
||||
@@ -110,7 +63,7 @@ public class WorldConfig {
|
||||
}
|
||||
|
||||
public Set<TerraStructure> getStructures() {
|
||||
return structureRegistry.entries();
|
||||
return new HashSet<>(getRegistry(TerraStructure.class).entries());
|
||||
}
|
||||
|
||||
public ConfigPackTemplate getTemplate() {
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
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();
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
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,7 +13,6 @@ 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;
|
||||
@@ -124,7 +123,7 @@ public class BiomeTemplate extends AbstractableTemplate implements ValidatedConf
|
||||
@Value("ocean.palette")
|
||||
@Abstractable
|
||||
@Default
|
||||
private Palette<BlockData> oceanPalette;
|
||||
private Palette oceanPalette;
|
||||
|
||||
@Value("elevation.equation")
|
||||
@Default
|
||||
@@ -159,12 +158,12 @@ public class BiomeTemplate extends AbstractableTemplate implements ValidatedConf
|
||||
@Value("slabs.palettes")
|
||||
@Abstractable
|
||||
@Default
|
||||
private Map<BlockType, Palette<BlockData>> slabPalettes;
|
||||
private Map<BlockType, Palette> slabPalettes;
|
||||
|
||||
@Value("slabs.stair-palettes")
|
||||
@Abstractable
|
||||
@Default
|
||||
private Map<BlockType, Palette<BlockData>> stairPalettes;
|
||||
private Map<BlockType, Palette> stairPalettes;
|
||||
|
||||
@Value("slant.threshold")
|
||||
@Abstractable
|
||||
@@ -247,14 +246,6 @@ 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() {
|
||||
@@ -268,7 +259,15 @@ public class BiomeTemplate extends AbstractableTemplate implements ValidatedConf
|
||||
return 2;
|
||||
}
|
||||
};
|
||||
oceanPalette = new SinglePalette<>(main.getWorldHandle().createBlockData("minecraft:water"));
|
||||
oceanPalette = new SinglePalette(main.getWorldHandle().createBlockData("minecraft:water"));
|
||||
}
|
||||
|
||||
public Map<BlockType, Palette> getSlabPalettes() {
|
||||
return slabPalettes;
|
||||
}
|
||||
|
||||
public Map<BlockType, Palette> getStairPalettes() {
|
||||
return stairPalettes;
|
||||
}
|
||||
|
||||
public NoiseSeeded getBiomeNoise() {
|
||||
@@ -291,7 +290,7 @@ public class BiomeTemplate extends AbstractableTemplate implements ValidatedConf
|
||||
return seaLevel;
|
||||
}
|
||||
|
||||
public Palette<BlockData> getOceanPalette() {
|
||||
public Palette getOceanPalette() {
|
||||
return oceanPalette;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ public class OreTemplate extends AbstractableTemplate {
|
||||
@Abstractable
|
||||
private BlockData material;
|
||||
|
||||
@Value("type")
|
||||
@Value("algorithm")
|
||||
@Abstractable
|
||||
@Default
|
||||
private Ore.Type oreType = Ore.Type.VANILLA;
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
package com.dfsek.terra.profiler;
|
||||
|
||||
/**
|
||||
* Class to hold a profiler data value. Contains formatting method to highlight value based on desired range.
|
||||
*/
|
||||
public class DataHolder {
|
||||
private final long desired;
|
||||
private final DataType type;
|
||||
private final double desiredRangePercent;
|
||||
|
||||
/**
|
||||
* Constructs a DataHolder with a DataType and a desired value, including a percentage around the desired value considered acceptable
|
||||
*
|
||||
* @param type The type of data held in this instance.
|
||||
* @param desired The desired value. This should be the average value of whatever is being measured.
|
||||
* @param desiredRangePercent The percentage around the desired value to be considered acceptable.
|
||||
*/
|
||||
public DataHolder(DataType type, long desired, double desiredRangePercent) {
|
||||
this.desired = desired;
|
||||
this.type = type;
|
||||
this.desiredRangePercent = desiredRangePercent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a String, formatted with Bungee ChatColors.<br>
|
||||
* GREEN if the value is better than desired and outside of acceptable range.<br>
|
||||
* YELLOW if the value is better or worse than desired, and within acceptable range.<br>
|
||||
* RED if the value is worse than desired and outside of acceptable range.<br>
|
||||
*
|
||||
* @param data The data to format.
|
||||
* @return String - The formatted data.
|
||||
*/
|
||||
public String getFormattedData(long data) {
|
||||
return type.getFormatted(data);
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package com.dfsek.terra.profiler;
|
||||
|
||||
import net.jafama.FastMath;
|
||||
|
||||
public enum DataType {
|
||||
PERIOD_MILLISECONDS(Desire.LOW, 1000000, "ms"), PERIOD_NANOSECONDS(Desire.LOW, 1, "ns");
|
||||
private final Desire desire;
|
||||
private final long divisor;
|
||||
private final String unit;
|
||||
|
||||
DataType(Desire d, long divisor, String unit) {
|
||||
this.desire = d;
|
||||
this.divisor = divisor;
|
||||
this.unit = unit;
|
||||
}
|
||||
|
||||
public String getFormatted(long value) {
|
||||
return (double) FastMath.round(((double) value / divisor) * 100D) / 100D + unit;
|
||||
}
|
||||
|
||||
public Desire getDesire() {
|
||||
return desire;
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
package com.dfsek.terra.profiler;
|
||||
|
||||
|
||||
/**
|
||||
* Enum to represent the "goal" of a value, whether it is desirable for the value to be high (e.g. Frequency), or low (e.g. Period)
|
||||
*/
|
||||
public enum Desire {
|
||||
LOW, HIGH
|
||||
|
||||
}
|
||||
24
common/src/main/java/com/dfsek/terra/profiler/Frame.java
Normal file
24
common/src/main/java/com/dfsek/terra/profiler/Frame.java
Normal file
@@ -0,0 +1,24 @@
|
||||
package com.dfsek.terra.profiler;
|
||||
|
||||
public class Frame {
|
||||
private final String id;
|
||||
private final long start;
|
||||
|
||||
public Frame(String id) {
|
||||
this.id = id;
|
||||
this.start = System.nanoTime();
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public long getStart() {
|
||||
return start;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
package com.dfsek.terra.profiler;
|
||||
|
||||
import com.dfsek.terra.api.math.MathUtil;
|
||||
import com.dfsek.terra.api.util.GlueList;
|
||||
import net.jafama.FastMath;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Class to record and hold all data for a single type of measurement performed by the profiler.
|
||||
*/
|
||||
public class Measurement {
|
||||
private final List<Long> measurements = new LinkedList<>();
|
||||
private final long desirable;
|
||||
private final DataType type;
|
||||
private long min = Long.MAX_VALUE;
|
||||
private long max = Long.MIN_VALUE;
|
||||
|
||||
/**
|
||||
* Constructs a new Measurement with a desired value and DataType.
|
||||
*
|
||||
* @param desirable The desired value of the measurement.
|
||||
* @param type The type of data the measurement is holding.
|
||||
*/
|
||||
public Measurement(long desirable, DataType type) {
|
||||
this.desirable = desirable;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public void record(long value) {
|
||||
max = FastMath.max(value, max);
|
||||
min = FastMath.min(value, min);
|
||||
measurements.add(value);
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return measurements.size();
|
||||
}
|
||||
|
||||
public ProfileFuture beginMeasurement() {
|
||||
ProfileFuture future = new ProfileFuture();
|
||||
long current = System.nanoTime();
|
||||
future.thenRun(() -> record(System.nanoTime() - current));
|
||||
return future;
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
min = Long.MAX_VALUE;
|
||||
max = Long.MIN_VALUE;
|
||||
measurements.clear();
|
||||
}
|
||||
|
||||
public DataHolder getDataHolder() {
|
||||
return new DataHolder(type, desirable, 0.25);
|
||||
}
|
||||
|
||||
public long getMin() {
|
||||
if(min == Long.MAX_VALUE) return 0;
|
||||
return min;
|
||||
}
|
||||
|
||||
public long getMax() {
|
||||
if(max == Long.MIN_VALUE) return 0;
|
||||
return max;
|
||||
}
|
||||
|
||||
public long average() {
|
||||
BigInteger running = BigInteger.valueOf(0);
|
||||
List<Long> mTemp = new GlueList<>(measurements);
|
||||
for(Long l : mTemp) {
|
||||
running = running.add(BigInteger.valueOf(l));
|
||||
}
|
||||
if(measurements.size() == 0) return 0;
|
||||
return running.divide(BigInteger.valueOf(measurements.size())).longValue();
|
||||
}
|
||||
|
||||
public double getStdDev() {
|
||||
return MathUtil.standardDeviation(new GlueList<>(measurements));
|
||||
}
|
||||
|
||||
public int entries() {
|
||||
return measurements.size();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.dfsek.terra.profiler;
|
||||
|
||||
public class ProfileFrame implements AutoCloseable {
|
||||
private final Runnable action;
|
||||
|
||||
public ProfileFrame(Runnable action) {
|
||||
this.action = action;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
action.run();
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package com.dfsek.terra.profiler;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class ProfileFuture extends CompletableFuture<Boolean> implements AutoCloseable {
|
||||
public ProfileFuture() {
|
||||
super();
|
||||
}
|
||||
|
||||
public boolean complete() {
|
||||
return super.complete(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
this.complete();
|
||||
}
|
||||
}
|
||||
24
common/src/main/java/com/dfsek/terra/profiler/Profiler.java
Normal file
24
common/src/main/java/com/dfsek/terra/profiler/Profiler.java
Normal file
@@ -0,0 +1,24 @@
|
||||
package com.dfsek.terra.profiler;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public interface Profiler {
|
||||
void push(String frame);
|
||||
|
||||
void pop(String frame);
|
||||
|
||||
void start();
|
||||
|
||||
void stop();
|
||||
|
||||
Map<String, Timings> getTimings();
|
||||
|
||||
default ProfileFrame profile(String frame) {
|
||||
push(frame);
|
||||
return new ProfileFrame(() -> pop(frame));
|
||||
}
|
||||
|
||||
default void reset() {
|
||||
// todo: impl
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package com.dfsek.terra.profiler;
|
||||
|
||||
import com.dfsek.terra.api.util.mutable.MutableInteger;
|
||||
import com.dfsek.terra.profiler.exception.MalformedStackException;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Stack;
|
||||
|
||||
public class ProfilerImpl implements Profiler {
|
||||
private static final ThreadLocal<Stack<Frame>> THREAD_STACK = ThreadLocal.withInitial(Stack::new);
|
||||
private static final ThreadLocal<Map<String, List<Long>>> TIMINGS = ThreadLocal.withInitial(HashMap::new);
|
||||
private final List<Map<String, List<Long>>> accessibleThreadMaps = new ArrayList<>();
|
||||
private volatile boolean running = false;
|
||||
private static boolean instantiated = false;
|
||||
|
||||
private static final ThreadLocal<Boolean> SAFE = ThreadLocal.withInitial(() -> false);
|
||||
private static final ThreadLocal<MutableInteger> STACK_SIZE = ThreadLocal.withInitial(() -> new MutableInteger(0));
|
||||
|
||||
public ProfilerImpl() {
|
||||
if(instantiated) throw new IllegalStateException("Only one instance of Profiler may exist!");
|
||||
instantiated = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void push(String frame) {
|
||||
STACK_SIZE.get().increment();
|
||||
if(running && SAFE.get()) {
|
||||
Stack<Frame> stack = THREAD_STACK.get();
|
||||
stack.push(new Frame(stack.isEmpty() ? frame : stack.peek().getId() + "." + frame));
|
||||
} else SAFE.set(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pop(String frame) {
|
||||
MutableInteger size = STACK_SIZE.get();
|
||||
size.decrement();
|
||||
if(running && SAFE.get()) {
|
||||
long time = System.nanoTime();
|
||||
Stack<Frame> stack = THREAD_STACK.get();
|
||||
|
||||
Map<String, List<Long>> timingsMap = TIMINGS.get();
|
||||
|
||||
if(timingsMap.size() == 0) {
|
||||
synchronized(accessibleThreadMaps) {
|
||||
accessibleThreadMaps.add(timingsMap);
|
||||
}
|
||||
}
|
||||
|
||||
Frame top = stack.pop();
|
||||
if((stack.size() != 0 && !top.getId().endsWith("." + frame)) || (stack.size() == 0 && !top.getId().equals(frame)))
|
||||
throw new MalformedStackException("Expected " + frame + ", found " + top);
|
||||
|
||||
List<Long> timings = timingsMap.computeIfAbsent(top.getId(), id -> new ArrayList<>());
|
||||
|
||||
timings.add(time - top.getStart());
|
||||
}
|
||||
if(size.get() == 0) SAFE.set(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
running = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
running = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Timings> getTimings() {
|
||||
Map<String, Timings> map = new HashMap<>();
|
||||
accessibleThreadMaps.forEach(smap -> smap.forEach((key, list) -> {
|
||||
String[] keys = key.split("\\.");
|
||||
Timings timings = map.computeIfAbsent(keys[0], id -> new Timings());
|
||||
for(int i = 1; i < keys.length; i++) {
|
||||
timings = timings.getSubItem(keys[i]);
|
||||
}
|
||||
list.forEach(timings::addTime);
|
||||
}));
|
||||
return map;
|
||||
}
|
||||
}
|
||||
73
common/src/main/java/com/dfsek/terra/profiler/Timings.java
Normal file
73
common/src/main/java/com/dfsek/terra/profiler/Timings.java
Normal file
@@ -0,0 +1,73 @@
|
||||
package com.dfsek.terra.profiler;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class Timings {
|
||||
private final Map<String, Timings> subItems = new HashMap<>();
|
||||
|
||||
private final List<Long> timings = new ArrayList<>();
|
||||
|
||||
public void addTime(long time) {
|
||||
timings.add(time);
|
||||
}
|
||||
|
||||
public List<Long> getTimings() {
|
||||
return timings;
|
||||
}
|
||||
|
||||
public double average() {
|
||||
return (double) timings.stream().reduce(0L, Long::sum) / timings.size();
|
||||
}
|
||||
|
||||
public long max() {
|
||||
return timings.stream().mapToLong(Long::longValue).max().orElse(0L);
|
||||
}
|
||||
|
||||
public long min() {
|
||||
return timings.stream().mapToLong(Long::longValue).min().orElse(0L);
|
||||
}
|
||||
|
||||
public double sum() {
|
||||
return timings.stream().mapToDouble(Long::doubleValue).sum();
|
||||
}
|
||||
|
||||
public Timings getSubItem(String id) {
|
||||
return subItems.computeIfAbsent(id, s -> new Timings());
|
||||
}
|
||||
|
||||
public String toString(int indent, Timings parent, Set<Integer> branches) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
builder.append((double) min() / 1000000).append("ms min / ").append(average() / 1000000).append("ms avg / ")
|
||||
.append((double) max() / 1000000).append("ms max (").append(timings.size()).append(" samples, ")
|
||||
.append((sum() / parent.sum()) * 100).append("% of parent)");
|
||||
|
||||
List<String> frames = new ArrayList<>();
|
||||
Set<Integer> newBranches = new HashSet<>(branches);
|
||||
newBranches.add(indent);
|
||||
subItems.forEach((id, timings) -> frames.add(id + ": " + timings.toString(indent + 1, this, newBranches)));
|
||||
|
||||
for(int i = 0; i < frames.size(); i++) {
|
||||
builder.append('\n');
|
||||
for(int j = 0; j < indent; j++) {
|
||||
if(branches.contains(j)) builder.append("│ ");
|
||||
else builder.append(" ");
|
||||
}
|
||||
if(i == frames.size() - 1 && !frames.get(i).contains("\n")) builder.append("└───");
|
||||
else builder.append("├───");
|
||||
builder.append(frames.get(i));
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toString(1, this, Collections.emptySet());
|
||||
}
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
package com.dfsek.terra.profiler;
|
||||
|
||||
import com.dfsek.terra.api.platform.world.World;
|
||||
import com.dfsek.terra.world.TerraWorld;
|
||||
import com.google.common.collect.BiMap;
|
||||
import com.google.common.collect.HashBiMap;
|
||||
import net.jafama.FastMath;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class WorldProfiler {
|
||||
private final BiMap<String, Measurement> measures = HashBiMap.create();
|
||||
private final World world;
|
||||
private boolean isProfiling;
|
||||
|
||||
public WorldProfiler(World w) {
|
||||
if(!TerraWorld.isTerraWorld(w))
|
||||
throw new IllegalArgumentException("Attempted to instantiate profiler on non-Terra managed world!");
|
||||
this.addMeasurement(new Measurement(2500000, DataType.PERIOD_MILLISECONDS), "TotalChunkGenTime")
|
||||
.addMeasurement(new Measurement(1500000, DataType.PERIOD_MILLISECONDS), "FloraTime")
|
||||
.addMeasurement(new Measurement(10000000, DataType.PERIOD_MILLISECONDS), "TreeTime")
|
||||
.addMeasurement(new Measurement(1500000, DataType.PERIOD_MILLISECONDS), "OreTime")
|
||||
.addMeasurement(new Measurement(5000000, DataType.PERIOD_MILLISECONDS), "CaveTime")
|
||||
.addMeasurement(new Measurement(1500000, DataType.PERIOD_MILLISECONDS), "StructureTime");
|
||||
|
||||
isProfiling = false;
|
||||
this.world = w;
|
||||
}
|
||||
|
||||
public String getResultsFormatted() {
|
||||
if(! isProfiling) return "Profiler is not currently running.";
|
||||
StringBuilder result = new StringBuilder("Gaea World Profiler Results (Min / Avg / Max / Std Dev): \n");
|
||||
for(Map.Entry<String, Measurement> e : measures.entrySet()) {
|
||||
result
|
||||
.append(e.getKey())
|
||||
.append(": ")
|
||||
.append(e.getValue().getDataHolder().getFormattedData(e.getValue().getMin()))
|
||||
.append(" / ")
|
||||
.append(e.getValue().getDataHolder().getFormattedData(e.getValue().average()))
|
||||
.append(" / ")
|
||||
.append(e.getValue().getDataHolder().getFormattedData(e.getValue().getMax()))
|
||||
.append(" / ")
|
||||
.append((double) FastMath.round((e.getValue().getStdDev() / 1000000) * 100D) / 100D)
|
||||
.append("ms")
|
||||
.append(" (x").append(e.getValue().size()).append(")\n");
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
for(Map.Entry<String, Measurement> e : measures.entrySet()) {
|
||||
e.getValue().reset();
|
||||
}
|
||||
}
|
||||
|
||||
public com.dfsek.terra.profiler.WorldProfiler addMeasurement(Measurement m, String name) {
|
||||
measures.put(name, m);
|
||||
return this;
|
||||
}
|
||||
|
||||
public void setMeasurement(String id, long value) {
|
||||
if(isProfiling) measures.get(id).record(value);
|
||||
}
|
||||
|
||||
public ProfileFuture measure(String id) {
|
||||
if(isProfiling) return measures.get(id).beginMeasurement();
|
||||
else return null;
|
||||
}
|
||||
|
||||
public String getID(Measurement m) {
|
||||
return measures.inverse().get(m);
|
||||
}
|
||||
|
||||
public boolean isProfiling() {
|
||||
return isProfiling;
|
||||
}
|
||||
|
||||
public void setProfiling(boolean enabled) {
|
||||
this.isProfiling = enabled;
|
||||
}
|
||||
|
||||
public World getWorld() {
|
||||
return world;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.dfsek.terra.profiler.exception;
|
||||
|
||||
public class MalformedStackException extends ProfilerException {
|
||||
private static final long serialVersionUID = -3009539681021691054L;
|
||||
|
||||
public MalformedStackException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public MalformedStackException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public MalformedStackException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.dfsek.terra.profiler.exception;
|
||||
|
||||
public class ProfilerException extends RuntimeException {
|
||||
private static final long serialVersionUID = 8206737998791649002L;
|
||||
|
||||
public ProfilerException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public ProfilerException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public ProfilerException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
||||
@@ -6,19 +6,30 @@ 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.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;
|
||||
private static final Entry<?> NULL = new Entry<>(null);
|
||||
|
||||
public OpenRegistry() {
|
||||
objects = new HashMap<>();
|
||||
}
|
||||
|
||||
protected OpenRegistry(Map<String, Entry<T>> init) {
|
||||
this.objects = init;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T load(Type type, Object o, ConfigLoader configLoader) throws LoadException {
|
||||
@@ -35,6 +46,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;
|
||||
@@ -58,24 +73,25 @@ public class OpenRegistry<T> implements Registry<T> {
|
||||
return objects.containsKey(identifier);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public T get(String identifier) {
|
||||
return objects.get(identifier);
|
||||
return objects.getOrDefault(identifier, (Entry<T>) NULL).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());
|
||||
public Collection<T> entries() {
|
||||
return objects.values().stream().map(Entry::getRaw).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -83,10 +99,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
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;
|
||||
@@ -9,7 +8,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.NoiseSeeded;
|
||||
import com.dfsek.terra.api.util.seeded.NoiseProvider;
|
||||
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;
|
||||
@@ -26,9 +25,7 @@ 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;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class NoiseRegistry extends OpenRegistry<Supplier<ObjectTemplate<NoiseSeeded>>> {
|
||||
public class NoiseRegistry extends OpenRegistry<NoiseProvider> {
|
||||
public NoiseRegistry() {
|
||||
add("LINEAR", LinearNormalizerTemplate::new);
|
||||
add("NORMAL", NormalNormalizerTemplate::new);
|
||||
|
||||
@@ -1,22 +1,21 @@
|
||||
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<BlockData>> {
|
||||
public class PaletteRegistry extends OpenRegistry<Palette> {
|
||||
private final TerraPlugin main;
|
||||
|
||||
public PaletteRegistry(TerraPlugin main) {
|
||||
this.main = main;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Palette<BlockData> get(String identifier) {
|
||||
public Palette 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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@ 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.pack.WorldConfig;
|
||||
import com.dfsek.terra.profiler.WorldProfiler;
|
||||
import com.dfsek.terra.world.generation.math.samplers.Sampler;
|
||||
import net.jafama.FastMath;
|
||||
|
||||
@@ -21,7 +20,6 @@ public class TerraWorld {
|
||||
private final BiomeProvider provider;
|
||||
private final WorldConfig config;
|
||||
private final boolean safe;
|
||||
private final WorldProfiler profiler;
|
||||
private final World world;
|
||||
private final BlockData air;
|
||||
|
||||
@@ -31,7 +29,6 @@ public class TerraWorld {
|
||||
this.world = w;
|
||||
config = c.toWorldConfig(this);
|
||||
this.provider = config.getProvider();
|
||||
profiler = new WorldProfiler(w);
|
||||
air = main.getWorldHandle().createBlockData("minecraft:air");
|
||||
main.getEventManager().callEvent(new TerraWorldLoadEvent(this, c));
|
||||
safe = true;
|
||||
@@ -61,9 +58,6 @@ public class TerraWorld {
|
||||
return safe;
|
||||
}
|
||||
|
||||
public WorldProfiler getProfiler() {
|
||||
return profiler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a block at an ungenerated location
|
||||
@@ -75,7 +69,7 @@ public class TerraWorld {
|
||||
*/
|
||||
public BlockData getUngeneratedBlock(int x, int y, int z) {
|
||||
UserDefinedBiome biome = (UserDefinedBiome) provider.getBiome(x, z);
|
||||
Palette<BlockData> palette = biome.getGenerator(world).getPalette(y);
|
||||
Palette 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,10 +1,13 @@
|
||||
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"})
|
||||
@@ -67,7 +70,7 @@ public class WorldGenerator implements Generator {
|
||||
* @return BlockPalette - The biome's palette.
|
||||
*/
|
||||
@Override
|
||||
public Palette<BlockData> getPalette(int y) {
|
||||
public Palette getPalette(int y) {
|
||||
return palettes.getPalette(y);
|
||||
}
|
||||
|
||||
@@ -86,7 +89,12 @@ public class WorldGenerator implements Generator {
|
||||
return blendStep;
|
||||
}
|
||||
|
||||
public Palette<BlockData> getSlantPalette(int y) {
|
||||
@Override
|
||||
public List<TerrainSampler> getTerrainSamplers() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
public Palette getSlantPalette(int y) {
|
||||
return slantPalettes.getPalette(y);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,146 +0,0 @@
|
||||
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.ProfileFuture;
|
||||
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(ProfileFuture ignore = tw.getProfiler().measure("TotalChunkGenTime")) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,7 @@ import com.dfsek.terra.api.world.palette.Palette;
|
||||
import com.dfsek.terra.api.world.palette.SinglePalette;
|
||||
import com.dfsek.terra.config.pack.ConfigPack;
|
||||
import com.dfsek.terra.config.templates.BiomeTemplate;
|
||||
import com.dfsek.terra.profiler.ProfileFuture;
|
||||
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;
|
||||
@@ -45,7 +45,7 @@ public class DefaultChunkGenerator3D implements TerraChunkGenerator {
|
||||
private final ConfigPack configPack;
|
||||
private final TerraPlugin main;
|
||||
private final BlockType water;
|
||||
private final SinglePalette<BlockData> blank;
|
||||
private final SinglePalette blank;
|
||||
private final List<TerraBlockPopulator> blockPopulators = new ArrayList<>();
|
||||
|
||||
private final Carver carver;
|
||||
@@ -63,7 +63,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
|
||||
@@ -106,7 +106,7 @@ public class DefaultChunkGenerator3D implements TerraChunkGenerator {
|
||||
public ChunkData generateChunkData(@NotNull World world, Random random, int chunkX, int chunkZ, ChunkData chunk) {
|
||||
TerraWorld tw = main.getWorld(world);
|
||||
BiomeProvider grid = tw.getBiomeProvider();
|
||||
try(ProfileFuture ignore = tw.getProfiler().measure("TotalChunkGenTime")) {
|
||||
try(ProfileFrame ignore = main.getProfiler().profile("chunk_base_3d")) {
|
||||
if(!tw.isSafe()) return chunk;
|
||||
int xOrig = (chunkX << 4);
|
||||
int zOrig = (chunkZ << 4);
|
||||
@@ -124,7 +124,7 @@ public class DefaultChunkGenerator3D implements TerraChunkGenerator {
|
||||
BiomeTemplate c = ((UserDefinedBiome) b).getConfig();
|
||||
|
||||
int sea = c.getSeaLevel();
|
||||
Palette<BlockData> seaPalette = c.getOceanPalette();
|
||||
Palette 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<BlockData>> slabs,
|
||||
Map<BlockType, Palette<BlockData>> stairs, double thresh, Sampler sampler) {
|
||||
private void prepareBlockPartFloor(BlockData down, BlockData orig, ChunkData chunk, Vector3 block, Map<BlockType, Palette> slabs,
|
||||
Map<BlockType, Palette> stairs, double thresh, Sampler sampler) {
|
||||
if(sampler.sample(block.getX(), block.getY() - 0.4, block.getZ()) > thresh) {
|
||||
if(stairs != null) {
|
||||
Palette<BlockData> stairPalette = stairs.get(down.getBlockType());
|
||||
Palette 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<BlockData>> slabs,
|
||||
Map<BlockType, Palette<BlockData>> stairs, double thresh, Sampler sampler) {
|
||||
private void prepareBlockPartCeiling(BlockData up, BlockData orig, ChunkData chunk, Vector3 block, Map<BlockType, Palette> slabs,
|
||||
Map<BlockType, Palette> stairs, double thresh, Sampler sampler) {
|
||||
if(sampler.sample(block.getX(), block.getY() + 0.4, block.getZ()) > thresh) {
|
||||
if(stairs != null) {
|
||||
Palette<BlockData> stairPalette = stairs.get(up.getBlockType());
|
||||
Palette stairPalette = stairs.get(up.getBlockType());
|
||||
if(stairPalette != null) {
|
||||
BlockData stair = stairPalette.get(0, block.getX(), block.getY(), block.getZ()).clone();
|
||||
if(stair instanceof Stairs) {
|
||||
|
||||
@@ -3,22 +3,26 @@ package com.dfsek.terra.world.generation.math.interpolation;
|
||||
/**
|
||||
* Class for bilinear interpolation of values arranged on a unit square.
|
||||
*/
|
||||
public class Interpolator {
|
||||
public class BilinearInterpolator implements Interpolator2 {
|
||||
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 Interpolator(double v0, double v1, double v2, double v3) {
|
||||
public BilinearInterpolator(double v0, double v1, double v2, double v3, double width, double height) {
|
||||
this.v0 = v0;
|
||||
this.v1 = v1;
|
||||
this.v2 = v2;
|
||||
this.v3 = v3;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -40,7 +44,10 @@ public class Interpolator {
|
||||
* @param t - Z value
|
||||
* @return double - The interpolated value.
|
||||
*/
|
||||
public double bilerp(double s, double t) {
|
||||
@Override
|
||||
public double interpolate(double s, double t) {
|
||||
s/=width;
|
||||
t/=height;
|
||||
double v01 = lerp(s, v0, v1);
|
||||
double v23 = lerp(s, v2, v3);
|
||||
return lerp(t, v01, v23);
|
||||
@@ -1,88 +0,0 @@
|
||||
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 Interpolator3(
|
||||
interpGrid[x][y][z] = new TrilinearInterpolator(
|
||||
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]);
|
||||
noiseStorage[x + 1][z + 1][y + 1], 4, 4, 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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)].trilerp((x % 4) / 4, (y % 4) / 4, (z % 4) / 4);
|
||||
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));
|
||||
}
|
||||
|
||||
public double getNoise(int x, int y, int z) {
|
||||
return interpGrid[x / 4][y / 4][z / 4].trilerp((double) (x % 4) / 4, (double) (y % 4) / 4, (double) (z % 4) / 4);
|
||||
return interpGrid[x / 4][y / 4][z / 4].interpolate(x % 4, y % 4, z % 4);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
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,32 +1,5 @@
|
||||
package com.dfsek.terra.world.generation.math.interpolation;
|
||||
|
||||
/**
|
||||
* 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));
|
||||
}
|
||||
}
|
||||
public interface Interpolator3 {
|
||||
double interpolate(double x, double y, double z);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
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));
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
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));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
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);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@ import com.dfsek.terra.api.world.generation.TerraBlockPopulator;
|
||||
import com.dfsek.terra.carving.UserDefinedCarver;
|
||||
import com.dfsek.terra.config.pack.WorldConfig;
|
||||
import com.dfsek.terra.config.templates.CarverTemplate;
|
||||
import com.dfsek.terra.profiler.ProfileFuture;
|
||||
import com.dfsek.terra.profiler.ProfileFrame;
|
||||
import com.dfsek.terra.world.TerraWorld;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -38,7 +38,7 @@ public class CavePopulator implements TerraBlockPopulator, Chunkified {
|
||||
TerraWorld tw = main.getWorld(world);
|
||||
WorldHandle handle = main.getWorldHandle();
|
||||
BlockData AIR = handle.createBlockData("minecraft:air");
|
||||
try(ProfileFuture ignored = tw.getProfiler().measure("CaveTime")) {
|
||||
try(ProfileFrame ignore = main.getProfiler().profile("carving")) {
|
||||
Random random = PopulationUtil.getRandom(chunk);
|
||||
if(!tw.isSafe()) return;
|
||||
WorldConfig config = tw.getConfig();
|
||||
@@ -49,38 +49,40 @@ public class CavePopulator implements TerraBlockPopulator, Chunkified {
|
||||
Map<Location, BlockData> shiftCandidate = new HashMap<>();
|
||||
Set<Block> updateNeeded = new HashSet<>();
|
||||
c.carve(chunk.getX(), chunk.getZ(), world, (v, type) -> {
|
||||
Block b = chunk.getBlock(v.getBlockX(), v.getBlockY(), v.getBlockZ());
|
||||
BlockData m = b.getBlockData();
|
||||
BlockType re = m.getBlockType();
|
||||
switch(type) {
|
||||
case CENTER:
|
||||
if(template.getInner().canReplace(re)) {
|
||||
b.setBlockData(template.getInner().get(v.getBlockY()).get(random), false);
|
||||
if(template.getUpdate().contains(re)) updateNeeded.add(b);
|
||||
if(template.getShift().containsKey(re)) shiftCandidate.put(b.getLocation(), m);
|
||||
}
|
||||
break;
|
||||
case WALL:
|
||||
if(template.getOuter().canReplace(re)) {
|
||||
b.setBlockData(template.getOuter().get(v.getBlockY()).get(random), false);
|
||||
if(template.getUpdate().contains(re)) updateNeeded.add(b);
|
||||
if(template.getShift().containsKey(re)) shiftCandidate.put(b.getLocation(), m);
|
||||
}
|
||||
break;
|
||||
case TOP:
|
||||
if(template.getTop().canReplace(re)) {
|
||||
b.setBlockData(template.getTop().get(v.getBlockY()).get(random), false);
|
||||
if(template.getUpdate().contains(re)) updateNeeded.add(b);
|
||||
if(template.getShift().containsKey(re)) shiftCandidate.put(b.getLocation(), m);
|
||||
}
|
||||
break;
|
||||
case BOTTOM:
|
||||
if(template.getBottom().canReplace(re)) {
|
||||
b.setBlockData(template.getBottom().get(v.getBlockY()).get(random), false);
|
||||
if(template.getUpdate().contains(re)) updateNeeded.add(b);
|
||||
if(template.getShift().containsKey(re)) shiftCandidate.put(b.getLocation(), m);
|
||||
}
|
||||
break;
|
||||
try(ProfileFrame ignored = main.getProfiler().profile("carving:" + c.getConfig().getID())) {
|
||||
Block b = chunk.getBlock(v.getBlockX(), v.getBlockY(), v.getBlockZ());
|
||||
BlockData m = b.getBlockData();
|
||||
BlockType re = m.getBlockType();
|
||||
switch(type) {
|
||||
case CENTER:
|
||||
if(template.getInner().canReplace(re)) {
|
||||
b.setBlockData(template.getInner().get(v.getBlockY()).get(random), false);
|
||||
if(template.getUpdate().contains(re)) updateNeeded.add(b);
|
||||
if(template.getShift().containsKey(re)) shiftCandidate.put(b.getLocation(), m);
|
||||
}
|
||||
break;
|
||||
case WALL:
|
||||
if(template.getOuter().canReplace(re)) {
|
||||
b.setBlockData(template.getOuter().get(v.getBlockY()).get(random), false);
|
||||
if(template.getUpdate().contains(re)) updateNeeded.add(b);
|
||||
if(template.getShift().containsKey(re)) shiftCandidate.put(b.getLocation(), m);
|
||||
}
|
||||
break;
|
||||
case TOP:
|
||||
if(template.getTop().canReplace(re)) {
|
||||
b.setBlockData(template.getTop().get(v.getBlockY()).get(random), false);
|
||||
if(template.getUpdate().contains(re)) updateNeeded.add(b);
|
||||
if(template.getShift().containsKey(re)) shiftCandidate.put(b.getLocation(), m);
|
||||
}
|
||||
break;
|
||||
case BOTTOM:
|
||||
if(template.getBottom().canReplace(re)) {
|
||||
b.setBlockData(template.getBottom().get(v.getBlockY()).get(random), false);
|
||||
if(template.getUpdate().contains(re)) updateNeeded.add(b);
|
||||
if(template.getShift().containsKey(re)) shiftCandidate.put(b.getLocation(), m);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
for(Map.Entry<Location, BlockData> entry : shiftCandidate.entrySet()) {
|
||||
@@ -93,7 +95,7 @@ public class CavePopulator implements TerraBlockPopulator, Chunkified {
|
||||
if(template.getShift().get(entry.getValue().getBlockType()).contains(mut.getBlock().getBlockData().getBlockType())) {
|
||||
mut.getBlock().setBlockData(shiftStorage.computeIfAbsent(entry.getValue().getBlockType(), BlockType::getDefaultData), false);
|
||||
}
|
||||
} catch(NullPointerException ignore) {
|
||||
} catch(NullPointerException ignored) {
|
||||
}
|
||||
}
|
||||
for(Block b : updateNeeded) {
|
||||
|
||||
@@ -8,7 +8,7 @@ import com.dfsek.terra.api.util.world.PopulationUtil;
|
||||
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.profiler.ProfileFuture;
|
||||
import com.dfsek.terra.profiler.ProfileFrame;
|
||||
import com.dfsek.terra.world.TerraWorld;
|
||||
import com.dfsek.terra.world.population.items.flora.FloraLayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -32,7 +32,7 @@ public class FloraPopulator implements TerraBlockPopulator {
|
||||
@Override
|
||||
public void populate(@NotNull World world, @NotNull Chunk chunk) {
|
||||
TerraWorld tw = main.getWorld(world);
|
||||
try(ProfileFuture ignored = tw.getProfiler().measure("FloraTime")) {
|
||||
try(ProfileFrame ignore = main.getProfiler().profile("flora")) {
|
||||
if(tw.getConfig().getTemplate().disableCarvers()) return;
|
||||
|
||||
if(!tw.isSafe()) return;
|
||||
|
||||
@@ -10,7 +10,7 @@ import com.dfsek.terra.api.world.biome.TerraBiome;
|
||||
import com.dfsek.terra.api.world.biome.UserDefinedBiome;
|
||||
import com.dfsek.terra.api.world.generation.TerraBlockPopulator;
|
||||
import com.dfsek.terra.config.templates.BiomeTemplate;
|
||||
import com.dfsek.terra.profiler.ProfileFuture;
|
||||
import com.dfsek.terra.profiler.ProfileFrame;
|
||||
import com.dfsek.terra.world.TerraWorld;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -27,7 +27,7 @@ public class OrePopulator implements TerraBlockPopulator {
|
||||
@Override
|
||||
public void populate(@NotNull World world, @NotNull Chunk chunk) {
|
||||
TerraWorld tw = main.getWorld(world);
|
||||
try(ProfileFuture ignored = tw.getProfiler().measure("OreTime")) {
|
||||
try(ProfileFrame ignore = main.getProfiler().profile("ore")) {
|
||||
if(tw.getConfig().getTemplate().disableCarvers()) return;
|
||||
|
||||
if(!tw.isSafe()) return;
|
||||
@@ -40,11 +40,13 @@ public class OrePopulator implements TerraBlockPopulator {
|
||||
BiomeTemplate config = ((UserDefinedBiome) b).getConfig();
|
||||
int finalCx = cx;
|
||||
int finalCz = cz;
|
||||
config.getOreHolder().forEach((ore, oreConfig) -> {
|
||||
int amount = oreConfig.getAmount().get(random);
|
||||
for(int i = 0; i < amount; i++) {
|
||||
Vector3 location = new Vector3(random.nextInt(16) + 16 * finalCx, oreConfig.getHeight().get(random), random.nextInt(16) + 16 * finalCz);
|
||||
ore.generate(location, chunk, random);
|
||||
config.getOreHolder().forEach((id, orePair) -> {
|
||||
try(ProfileFrame ignored = main.getProfiler().profile("ore:" + id)) {
|
||||
int amount = orePair.getRight().getAmount().get(random);
|
||||
for(int i = 0; i < amount; i++) {
|
||||
Vector3 location = new Vector3(random.nextInt(16) + 16 * finalCx, orePair.getRight().getHeight().get(random), random.nextInt(16) + 16 * finalCz);
|
||||
orePair.getLeft().generate(location, chunk, random);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -11,9 +11,8 @@ import com.dfsek.terra.api.world.biome.UserDefinedBiome;
|
||||
import com.dfsek.terra.api.world.biome.provider.BiomeProvider;
|
||||
import com.dfsek.terra.api.world.generation.Chunkified;
|
||||
import com.dfsek.terra.api.world.generation.TerraBlockPopulator;
|
||||
import com.dfsek.terra.config.pack.ConfigPack;
|
||||
import com.dfsek.terra.config.pack.WorldConfig;
|
||||
import com.dfsek.terra.profiler.ProfileFuture;
|
||||
import com.dfsek.terra.profiler.ProfileFrame;
|
||||
import com.dfsek.terra.world.TerraWorld;
|
||||
import com.dfsek.terra.world.population.items.TerraStructure;
|
||||
import net.jafama.FastMath;
|
||||
@@ -32,7 +31,7 @@ public class StructurePopulator implements TerraBlockPopulator, Chunkified {
|
||||
@Override
|
||||
public void populate(@NotNull World world, @NotNull Chunk chunk) {
|
||||
TerraWorld tw = main.getWorld(world);
|
||||
try(ProfileFuture ignored = tw.getProfiler().measure("StructureTime")) {
|
||||
try(ProfileFrame ignore = main.getProfiler().profile("structure")) {
|
||||
if(tw.getConfig().getTemplate().disableCarvers()) return;
|
||||
|
||||
int cx = (chunk.getX() << 4);
|
||||
|
||||
@@ -8,7 +8,7 @@ import com.dfsek.terra.api.util.world.PopulationUtil;
|
||||
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.profiler.ProfileFuture;
|
||||
import com.dfsek.terra.profiler.ProfileFrame;
|
||||
import com.dfsek.terra.world.TerraWorld;
|
||||
import com.dfsek.terra.world.population.items.tree.TreeLayer;
|
||||
import net.jafama.FastMath;
|
||||
@@ -32,7 +32,7 @@ public class TreePopulator implements TerraBlockPopulator {
|
||||
@SuppressWarnings("try")
|
||||
public void populate(@NotNull World world, @NotNull Chunk chunk) {
|
||||
TerraWorld tw = main.getWorld(world);
|
||||
try(ProfileFuture ignored = tw.getProfiler().measure("TreeTime")) {
|
||||
try(ProfileFrame ignore = main.getProfiler().profile("tree")) {
|
||||
if(tw.getConfig().getTemplate().disableCarvers()) return;
|
||||
|
||||
if(!tw.isSafe()) return;
|
||||
@@ -42,8 +42,9 @@ public class TreePopulator implements TerraBlockPopulator {
|
||||
for(int z = 0; z < 16; z += 2) {
|
||||
UserDefinedBiome biome = (UserDefinedBiome) provider.getBiome((chunk.getX() << 4) + x, (chunk.getZ() << 4) + z);
|
||||
for(TreeLayer layer : biome.getConfig().getTrees()) {
|
||||
if(layer.getDensity() >= random.nextDouble() * 100)
|
||||
if(layer.getDensity() >= random.nextDouble() * 100) {
|
||||
layer.place(chunk, new Vector2(offset(random, x), offset(random, z)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class TerraFlora implements Flora {
|
||||
private final Palette<BlockData> floraPalette;
|
||||
private final Palette 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<BlockData> 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 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;
|
||||
|
||||
@@ -16,7 +16,6 @@ public abstract class Ore {
|
||||
protected TerraPlugin main;
|
||||
|
||||
public Ore(BlockData material, MaterialSet replaceable, boolean applyGravity, TerraPlugin main) {
|
||||
|
||||
this.material = material;
|
||||
this.replaceable = replaceable;
|
||||
this.applyGravity = applyGravity;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.dfsek.terra.world.population.items.ores;
|
||||
|
||||
import com.dfsek.terra.api.util.GlueList;
|
||||
import com.dfsek.terra.api.util.generic.pair.ImmutablePair;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.BiConsumer;
|
||||
@@ -11,22 +12,24 @@ import java.util.function.BiConsumer;
|
||||
public class OreHolder {
|
||||
private final List<Entry> entries = new GlueList<>();
|
||||
|
||||
public void forEach(BiConsumer<Ore, OreConfig> consumer) {
|
||||
entries.forEach(entry -> consumer.accept(entry.getOre(), entry.getConfig()));
|
||||
public void forEach(BiConsumer<String, ImmutablePair<Ore, OreConfig>> consumer) {
|
||||
entries.forEach(entry -> consumer.accept(entry.getId(), ImmutablePair.of(entry.getOre(), entry.getConfig())));
|
||||
}
|
||||
|
||||
public OreHolder add(Ore ore, OreConfig config) {
|
||||
entries.add(new Entry(ore, config));
|
||||
public OreHolder add(Ore ore, OreConfig config, String id) {
|
||||
entries.add(new Entry(ore, config, id));
|
||||
return this;
|
||||
}
|
||||
|
||||
private static final class Entry {
|
||||
private final Ore ore;
|
||||
private final OreConfig config;
|
||||
private final String id;
|
||||
|
||||
private Entry(Ore ore, OreConfig config) {
|
||||
private Entry(Ore ore, OreConfig config, String id) {
|
||||
this.ore = ore;
|
||||
this.config = config;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public OreConfig getConfig() {
|
||||
@@ -36,5 +39,9 @@ public class OreHolder {
|
||||
public Ore getOre() {
|
||||
return ore;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,352 +0,0 @@
|
||||
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.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.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 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.load(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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,218 +0,0 @@
|
||||
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.load(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;
|
||||
}
|
||||
}
|
||||
}
|
||||
63
common/src/test/java/profiler/ProfilerTest.java
Normal file
63
common/src/test/java/profiler/ProfilerTest.java
Normal file
@@ -0,0 +1,63 @@
|
||||
package profiler;
|
||||
|
||||
import com.dfsek.terra.profiler.Profiler;
|
||||
import com.dfsek.terra.profiler.ProfilerImpl;
|
||||
|
||||
public class ProfilerTest {
|
||||
private static final Profiler PROFILER = new ProfilerImpl();
|
||||
//@Test
|
||||
public static void main(String... a) throws InterruptedException {
|
||||
//PROFILER.start();
|
||||
for(int i = 0; i < 1000; i++) {
|
||||
doThing();
|
||||
}
|
||||
|
||||
for(int i = 0; i < 100; i++) {
|
||||
doThirdOtherThing();
|
||||
}
|
||||
|
||||
for(int i = 0; i < 100; i++) {
|
||||
doOtherThing();
|
||||
}
|
||||
PROFILER.stop();
|
||||
PROFILER.push("thing");
|
||||
PROFILER.push("thing2");
|
||||
PROFILER.start();
|
||||
PROFILER.pop("thing2");
|
||||
PROFILER.pop("thing");
|
||||
PROFILER.push("thing4");
|
||||
PROFILER.pop("thing4");
|
||||
|
||||
PROFILER.getTimings().forEach((id, timings) -> {
|
||||
System.out.println(id + ": " + timings.toString());
|
||||
});
|
||||
}
|
||||
|
||||
private static void doThing() throws InterruptedException {
|
||||
PROFILER.push("thing");
|
||||
Thread.sleep(1);
|
||||
doOtherThing();
|
||||
thing4();
|
||||
PROFILER.pop("thing");
|
||||
}
|
||||
|
||||
private static void doOtherThing() throws InterruptedException {
|
||||
PROFILER.push("thing2");
|
||||
Thread.sleep(2);
|
||||
doThirdOtherThing();
|
||||
thing4();
|
||||
PROFILER.pop("thing2");
|
||||
}
|
||||
|
||||
private static void doThirdOtherThing() throws InterruptedException {
|
||||
PROFILER.push("thing3");
|
||||
Thread.sleep(2);
|
||||
PROFILER.pop("thing3");
|
||||
}
|
||||
|
||||
private static void thing4() throws InterruptedException {
|
||||
PROFILER.push("thing4");
|
||||
Thread.sleep(2);
|
||||
PROFILER.pop("thing4");
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ import org.apache.commons.io.IOUtils;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -20,7 +21,7 @@ import java.util.Map;
|
||||
public class ParserTest {
|
||||
@Test
|
||||
public void parse() throws IOException, ParseException {
|
||||
Parser parser = new Parser(IOUtils.toString(getClass().getResourceAsStream("/test.tesf")));
|
||||
Parser parser = new Parser(IOUtils.toString(getClass().getResourceAsStream("/test.tesf"), Charset.defaultCharset()));
|
||||
|
||||
parser.registerFunction("test", new FunctionBuilder<Test1>() {
|
||||
@Override
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -40,6 +40,8 @@ import com.dfsek.terra.config.PluginConfig;
|
||||
import com.dfsek.terra.config.lang.LangUtil;
|
||||
import com.dfsek.terra.config.lang.Language;
|
||||
import com.dfsek.terra.config.pack.ConfigPack;
|
||||
import com.dfsek.terra.profiler.Profiler;
|
||||
import com.dfsek.terra.profiler.ProfilerImpl;
|
||||
import com.dfsek.terra.registry.master.AddonRegistry;
|
||||
import com.dfsek.terra.registry.master.ConfigRegistry;
|
||||
import com.dfsek.terra.world.TerraWorld;
|
||||
@@ -64,6 +66,8 @@ public class TerraBukkitPlugin extends JavaPlugin implements TerraPlugin {
|
||||
private final Map<World, TerraWorld> worldMap = new HashMap<>();
|
||||
private final Map<String, ConfigPack> worlds = new HashMap<>();
|
||||
|
||||
private final Profiler profiler = new ProfilerImpl();
|
||||
|
||||
private final ConfigRegistry registry = new ConfigRegistry();
|
||||
private final CheckedRegistry<ConfigPack> checkedRegistry = new CheckedRegistry<>(registry);
|
||||
|
||||
@@ -141,6 +145,11 @@ public class TerraBukkitPlugin extends JavaPlugin implements TerraPlugin {
|
||||
Bukkit.getScheduler().runTask(this, task);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Profiler getProfiler() {
|
||||
return profiler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
BukkitChunkGeneratorWrapper.saveAll();
|
||||
|
||||
@@ -3,19 +3,11 @@ package com.dfsek.terra.bukkit.generator;
|
||||
import com.dfsek.terra.api.TerraPlugin;
|
||||
import com.dfsek.terra.api.platform.world.Chunk;
|
||||
import com.dfsek.terra.api.platform.world.generator.GeneratorWrapper;
|
||||
import com.dfsek.terra.api.world.generation.TerraBlockPopulator;
|
||||
import com.dfsek.terra.api.world.generation.TerraChunkGenerator;
|
||||
import com.dfsek.terra.bukkit.population.PopulationManager;
|
||||
import com.dfsek.terra.bukkit.world.BukkitAdapter;
|
||||
import com.dfsek.terra.bukkit.world.BukkitBiomeGrid;
|
||||
import com.dfsek.terra.profiler.DataType;
|
||||
import com.dfsek.terra.profiler.Measurement;
|
||||
import com.dfsek.terra.world.TerraWorld;
|
||||
import com.dfsek.terra.world.population.CavePopulator;
|
||||
import com.dfsek.terra.world.population.FloraPopulator;
|
||||
import com.dfsek.terra.world.population.OrePopulator;
|
||||
import com.dfsek.terra.world.population.StructurePopulator;
|
||||
import com.dfsek.terra.world.population.TreePopulator;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.generator.BlockPopulator;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
@@ -24,13 +16,10 @@ import org.jetbrains.annotations.NotNull;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class BukkitChunkGeneratorWrapper extends ChunkGenerator implements GeneratorWrapper {
|
||||
|
||||
@@ -76,8 +65,6 @@ public class BukkitChunkGeneratorWrapper extends ChunkGenerator implements Gener
|
||||
e.printStackTrace();
|
||||
}
|
||||
popMap.put(w, popMan);
|
||||
main.getWorld(w).getProfiler().addMeasurement(new Measurement(15000000, DataType.PERIOD_MILLISECONDS), "PopulationManagerTime");
|
||||
popMan.attachProfiler(main.getWorld(w).getProfiler());
|
||||
needsLoad = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 new Pair<>(BukkitAdapter.adapt(locations[0]), BukkitAdapter.adapt(locations[1]));
|
||||
return Pair.of(BukkitAdapter.adapt(locations[0]), BukkitAdapter.adapt(locations[1]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.getTreeRegistry().get(TREE_TYPE_STRING_TRANSFORMER.translate(e.getSpecies()));
|
||||
Tree tree = c.getRegistry(Tree.class).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);
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ public class PaperListener implements Listener {
|
||||
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().getStructureRegistry().get(tw.getConfig().getTemplate().getLocatable().get(name));
|
||||
TerraStructure config = tw.getConfig().getRegistry(TerraStructure.class).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)
|
||||
|
||||
@@ -37,7 +37,7 @@ public class SpigotListener implements Listener {
|
||||
if(!TerraWorld.isTerraWorld(BukkitAdapter.adapt(e.getEntity().getWorld()))) return;
|
||||
TerraWorld tw = main.getWorld(BukkitAdapter.adapt(e.getEntity().getWorld()));
|
||||
EnderSignal signal = (EnderSignal) entity;
|
||||
TerraStructure config = tw.getConfig().getStructureRegistry().get(tw.getConfig().getTemplate().getLocatable().get("STRONGHOLD"));
|
||||
TerraStructure config = tw.getConfig().getRegistry(TerraStructure.class).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 -> {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user