mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2026-05-20 08:40:26 +00:00
Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8a028b193a | |||
| d31679e6be | |||
| 43d52e4bc1 | |||
| accc07fa07 | |||
| 1ae0d1f867 | |||
| 370b2e0122 | |||
| 331075e54d | |||
| 973590f5fd | |||
| 1a5ab6b505 | |||
| 14732328cd | |||
| 6c7974c302 | |||
| 1204b7a8c1 | |||
| fbe1c76e26 | |||
| add7803e65 | |||
| 4393a16b2f | |||
| b4fa635455 | |||
| 9f425c6159 | |||
| 158ffba2a5 | |||
| b7326c0ff6 | |||
| f70a83aec3 | |||
| 589cf83c38 | |||
| c374c2d5ef |
+3
-3
@@ -1,8 +1,8 @@
|
||||
preRelease(true)
|
||||
|
||||
versionProjects(":common:api", version("6.5.0"))
|
||||
versionProjects(":common:implementation", version("6.5.0"))
|
||||
versionProjects(":platforms", version("6.5.0"))
|
||||
versionProjects(":common:api", version("6.6.0"))
|
||||
versionProjects(":common:implementation", version("6.6.0"))
|
||||
versionProjects(":platforms", version("6.6.0"))
|
||||
|
||||
|
||||
allprojects {
|
||||
|
||||
@@ -74,5 +74,6 @@ object Versions {
|
||||
object CLI {
|
||||
const val nbt = "6.1"
|
||||
const val logback = "1.5.8"
|
||||
const val picocli = "4.7.6"
|
||||
}
|
||||
}
|
||||
+5
@@ -17,6 +17,7 @@ import com.dfsek.terra.addons.manifest.api.AddonInitializer;
|
||||
import com.dfsek.terra.addons.noise.config.CubicSplinePointTemplate;
|
||||
import com.dfsek.terra.addons.noise.config.DimensionApplicableNoiseSampler;
|
||||
import com.dfsek.terra.addons.noise.config.templates.BinaryArithmeticTemplate;
|
||||
import com.dfsek.terra.addons.noise.config.templates.CacheSamplerTemplate;
|
||||
import com.dfsek.terra.addons.noise.config.templates.DerivativeNoiseSamplerTemplate;
|
||||
import com.dfsek.terra.addons.noise.config.templates.DomainWarpTemplate;
|
||||
import com.dfsek.terra.addons.noise.config.templates.FunctionTemplate;
|
||||
@@ -37,6 +38,7 @@ import com.dfsek.terra.addons.noise.config.templates.noise.fractal.RidgedFractal
|
||||
import com.dfsek.terra.addons.noise.config.templates.normalizer.ClampNormalizerTemplate;
|
||||
import com.dfsek.terra.addons.noise.config.templates.normalizer.CubicSplineNormalizerTemplate;
|
||||
import com.dfsek.terra.addons.noise.config.templates.normalizer.ExpressionNormalizerTemplate;
|
||||
import com.dfsek.terra.addons.noise.config.templates.normalizer.LinearMapNormalizerTemplate;
|
||||
import com.dfsek.terra.addons.noise.config.templates.normalizer.LinearNormalizerTemplate;
|
||||
import com.dfsek.terra.addons.noise.config.templates.normalizer.NormalNormalizerTemplate;
|
||||
import com.dfsek.terra.addons.noise.config.templates.normalizer.PosterizationNormalizerTemplate;
|
||||
@@ -101,6 +103,7 @@ public class NoiseAddon implements AddonInitializer {
|
||||
.applyLoader(DerivativeNoiseSampler.class, DerivativeNoiseSamplerTemplate::new);
|
||||
|
||||
noiseRegistry.register(addon.key("LINEAR"), LinearNormalizerTemplate::new);
|
||||
noiseRegistry.register(addon.key("LINEAR_MAP"), LinearMapNormalizerTemplate::new);
|
||||
noiseRegistry.register(addon.key("NORMAL"), NormalNormalizerTemplate::new);
|
||||
noiseRegistry.register(addon.key("CLAMP"), ClampNormalizerTemplate::new);
|
||||
noiseRegistry.register(addon.key("PROBABILITY"), ProbabilityNormalizerTemplate::new);
|
||||
@@ -148,6 +151,8 @@ public class NoiseAddon implements AddonInitializer {
|
||||
noiseRegistry.register(addon.key("MAX"), () -> new BinaryArithmeticTemplate<>(MaxSampler::new));
|
||||
noiseRegistry.register(addon.key("MIN"), () -> new BinaryArithmeticTemplate<>(MinSampler::new));
|
||||
|
||||
noiseRegistry.register(addon.key("CACHE"), () -> new CacheSamplerTemplate(plugin.getGenerationThreads()));
|
||||
|
||||
|
||||
Map<String, DimensionApplicableNoiseSampler> packSamplers = new LinkedHashMap<>();
|
||||
Map<String, FunctionTemplate> packFunctions = new LinkedHashMap<>();
|
||||
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
package com.dfsek.terra.addons.noise.config.templates;
|
||||
|
||||
import com.dfsek.tectonic.api.config.template.annotations.Default;
|
||||
import com.dfsek.tectonic.api.config.template.annotations.Value;
|
||||
|
||||
import com.dfsek.terra.addons.noise.samplers.CacheSampler;
|
||||
import com.dfsek.terra.addons.noise.samplers.LinearHeightmapSampler;
|
||||
import com.dfsek.terra.api.noise.NoiseSampler;
|
||||
|
||||
|
||||
public class CacheSamplerTemplate extends SamplerTemplate<LinearHeightmapSampler> {
|
||||
@Value("sampler")
|
||||
@Default
|
||||
private NoiseSampler sampler;
|
||||
|
||||
private final int generationThreads;
|
||||
|
||||
public CacheSamplerTemplate(int generationThreads) {
|
||||
this.generationThreads = generationThreads;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NoiseSampler get() {
|
||||
return new CacheSampler(sampler, getDimensions(), generationThreads);
|
||||
}
|
||||
}
|
||||
+6
-1
@@ -34,7 +34,11 @@ public class CellularNoiseTemplate extends NoiseTemplate<CellularSampler> {
|
||||
@Value("lookup")
|
||||
@Default
|
||||
private @Meta NoiseSampler lookup = new OpenSimplex2Sampler();
|
||||
|
||||
|
||||
@Value("salt-lookup")
|
||||
@Default
|
||||
private @Meta boolean saltLookup = true;
|
||||
|
||||
@Override
|
||||
public NoiseSampler get() {
|
||||
CellularSampler sampler = new CellularSampler();
|
||||
@@ -44,6 +48,7 @@ public class CellularNoiseTemplate extends NoiseTemplate<CellularSampler> {
|
||||
sampler.setReturnType(cellularReturnType);
|
||||
sampler.setDistanceFunction(cellularDistanceFunction);
|
||||
sampler.setSalt(salt);
|
||||
sampler.setSaltLookup(saltLookup);
|
||||
return sampler;
|
||||
}
|
||||
}
|
||||
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
package com.dfsek.terra.addons.noise.config.templates.normalizer;
|
||||
|
||||
import com.dfsek.tectonic.api.config.template.annotations.Default;
|
||||
import com.dfsek.tectonic.api.config.template.annotations.Value;
|
||||
|
||||
import com.dfsek.terra.addons.noise.normalizer.LinearMapNormalizer;
|
||||
import com.dfsek.terra.api.config.meta.Meta;
|
||||
import com.dfsek.terra.api.noise.NoiseSampler;
|
||||
|
||||
|
||||
public class LinearMapNormalizerTemplate extends NormalizerTemplate<LinearMapNormalizer> {
|
||||
|
||||
@Value("from.a")
|
||||
@Default
|
||||
private @Meta double aFrom = -1;
|
||||
|
||||
@Value("from.b")
|
||||
@Default
|
||||
private @Meta double bFrom = 1;
|
||||
|
||||
@Value("to.a")
|
||||
private @Meta double aTo;
|
||||
|
||||
@Value("to.b")
|
||||
private @Meta double bTo;
|
||||
|
||||
@Override
|
||||
public NoiseSampler get() {
|
||||
return new LinearMapNormalizer(function, aFrom, aTo, bFrom, bTo);
|
||||
}
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
package com.dfsek.terra.addons.noise.normalizer;
|
||||
|
||||
import com.dfsek.terra.api.noise.NoiseSampler;
|
||||
|
||||
|
||||
public class LinearMapNormalizer extends Normalizer {
|
||||
|
||||
private final double aFrom;
|
||||
|
||||
private final double aTo;
|
||||
|
||||
private final double bFrom;
|
||||
|
||||
private final double bTo;
|
||||
|
||||
public LinearMapNormalizer(NoiseSampler sampler, double aFrom, double aTo, double bFrom, double bTo) {
|
||||
super(sampler);
|
||||
this.aFrom = aFrom;
|
||||
this.aTo = aTo;
|
||||
this.bFrom = bFrom;
|
||||
this.bTo = bTo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double normalize(double in) {
|
||||
return (in - aFrom) * (aTo - bTo) / (aFrom - bFrom) + aTo;
|
||||
}
|
||||
}
|
||||
+125
@@ -0,0 +1,125 @@
|
||||
package com.dfsek.terra.addons.noise.samplers;
|
||||
|
||||
import com.dfsek.terra.api.noise.DerivativeNoiseSampler;
|
||||
import com.dfsek.terra.api.noise.NoiseSampler;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||
|
||||
|
||||
public class CacheSampler implements DerivativeNoiseSampler {
|
||||
|
||||
private final NoiseSampler sampler;
|
||||
private final LoadingCache<DoubleSeededVector2, Double> cache2D;
|
||||
private final LoadingCache<DoubleSeededVector3, Double> cache3D;
|
||||
private final LoadingCache<DoubleSeededVector2, double[]> cache2DDirv;
|
||||
private final LoadingCache<DoubleSeededVector3, double[]> cache3DDirv;
|
||||
|
||||
public CacheSampler(NoiseSampler sampler, int dimensions, int generationThreads) {
|
||||
this.sampler = sampler;
|
||||
if (dimensions == 2) {
|
||||
this.cache2D = Caffeine
|
||||
.newBuilder()
|
||||
.initialCapacity(0)
|
||||
.maximumSize(256L * generationThreads) // 1 full chunk (high res)
|
||||
.build(vec -> sampler.noise(vec.seed, vec.x, vec.z));
|
||||
cache3D = null;
|
||||
cache3DDirv = null;
|
||||
if (DerivativeNoiseSampler.isDifferentiable(sampler)) {
|
||||
this.cache2DDirv = Caffeine
|
||||
.newBuilder()
|
||||
.initialCapacity(0)
|
||||
.maximumSize(256L * generationThreads) // 1 full chunk (high res)
|
||||
.build(vec -> ((DerivativeNoiseSampler) sampler).noised(vec.seed, vec.x, vec.z));
|
||||
} else {
|
||||
cache2DDirv = null;
|
||||
}
|
||||
} else {
|
||||
this.cache3D = Caffeine
|
||||
.newBuilder()
|
||||
.initialCapacity(0)
|
||||
.maximumSize(256L * generationThreads) // 1 full chunk (high res)
|
||||
.build(vec -> sampler.noise(vec.seed, vec.x, vec.y, vec.z));
|
||||
cache2D = null;
|
||||
cache2DDirv = null;
|
||||
if (DerivativeNoiseSampler.isDifferentiable(sampler)) {
|
||||
this.cache3DDirv = Caffeine
|
||||
.newBuilder()
|
||||
.initialCapacity(0)
|
||||
.maximumSize(256L * generationThreads) // 1 full chunk (high res)
|
||||
.build(vec -> ((DerivativeNoiseSampler) sampler).noised(vec.seed, vec.x, vec.y, vec.z));
|
||||
} else {
|
||||
cache3DDirv = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDifferentiable() {
|
||||
return DerivativeNoiseSampler.isDifferentiable(sampler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double[] noised(long seed, double x, double y) {
|
||||
return cache2DDirv.get(new DoubleSeededVector2(x, y, seed));
|
||||
}
|
||||
|
||||
@Override
|
||||
public double[] noised(long seed, double x, double y, double z) {
|
||||
return cache3DDirv.get(new DoubleSeededVector3(x, y, z, seed));
|
||||
}
|
||||
|
||||
@Override
|
||||
public double noise(long seed, double x, double y) {
|
||||
DoubleSeededVector2 vec = new DoubleSeededVector2(x, y, seed);
|
||||
if (cache2DDirv != null && cache2DDirv.estimatedSize() != 0) {
|
||||
return cache2DDirv.get(vec)[0];
|
||||
}
|
||||
return cache2D.get(vec);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double noise(long seed, double x, double y, double z) {
|
||||
DoubleSeededVector3 vec = new DoubleSeededVector3(x, y, z, seed);
|
||||
if (cache3DDirv != null && cache3DDirv.estimatedSize() != 0) {
|
||||
return cache3DDirv.get(vec)[0];
|
||||
}
|
||||
return cache3D.get(vec);
|
||||
}
|
||||
|
||||
private record DoubleSeededVector3(double x, double y, double z, long seed) {
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if(obj instanceof DoubleSeededVector3 that) {
|
||||
return this.y == that.y && this.z == that.z && this.x == that.x && this.seed == that.seed;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int code = (int) Double.doubleToLongBits(x);
|
||||
code = 31 * code + (int) Double.doubleToLongBits(y);
|
||||
code = 31 * code + (int) Double.doubleToLongBits(z);
|
||||
return 31 * code + (Long.hashCode(seed));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private record DoubleSeededVector2(double x, double z, long seed) {
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if(obj instanceof DoubleSeededVector2 that) {
|
||||
return this.z == that.z && this.x == that.x && this.seed == that.seed;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int code = (int) Double.doubleToLongBits(x);
|
||||
code = 31 * code + (int) Double.doubleToLongBits(z);
|
||||
return 31 * code + (Long.hashCode(seed));
|
||||
}
|
||||
}
|
||||
}
|
||||
+10
@@ -12,4 +12,14 @@ public class AdditionSampler extends BinaryArithmeticSampler {
|
||||
public double operate(double left, double right) {
|
||||
return left + right;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double[] operateDerivative(double[] left, double[] right) {
|
||||
int dimensions = left.length;
|
||||
double[] out = new double[dimensions];
|
||||
for(int i = 0; i < dimensions; i++) {
|
||||
out[i] = left[i] + right[i];
|
||||
}
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
+19
-1
@@ -1,9 +1,10 @@
|
||||
package com.dfsek.terra.addons.noise.samplers.arithmetic;
|
||||
|
||||
import com.dfsek.terra.api.noise.DerivativeNoiseSampler;
|
||||
import com.dfsek.terra.api.noise.NoiseSampler;
|
||||
|
||||
|
||||
public abstract class BinaryArithmeticSampler implements NoiseSampler {
|
||||
public abstract class BinaryArithmeticSampler implements DerivativeNoiseSampler {
|
||||
private final NoiseSampler left;
|
||||
private final NoiseSampler right;
|
||||
|
||||
@@ -12,6 +13,11 @@ public abstract class BinaryArithmeticSampler implements NoiseSampler {
|
||||
this.right = right;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDifferentiable() {
|
||||
return DerivativeNoiseSampler.isDifferentiable(left) && DerivativeNoiseSampler.isDifferentiable(right);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double noise(long seed, double x, double y) {
|
||||
return operate(left.noise(seed, x, y), right.noise(seed, x, y));
|
||||
@@ -22,5 +28,17 @@ public abstract class BinaryArithmeticSampler implements NoiseSampler {
|
||||
return operate(left.noise(seed, x, y, z), right.noise(seed, x, y, z));
|
||||
}
|
||||
|
||||
@Override
|
||||
public double[] noised(long seed, double x, double y) {
|
||||
return operateDerivative(((DerivativeNoiseSampler)left).noised(seed, x, y), ((DerivativeNoiseSampler)right).noised(seed, x, y));
|
||||
}
|
||||
|
||||
@Override
|
||||
public double[] noised(long seed, double x, double y, double z) {
|
||||
return operateDerivative(((DerivativeNoiseSampler)left).noised(seed, x, y, z), ((DerivativeNoiseSampler)right).noised(seed, x, y, z));
|
||||
}
|
||||
|
||||
public abstract double operate(double left, double right);
|
||||
|
||||
public abstract double[] operateDerivative(double[] left, double[] right);
|
||||
}
|
||||
|
||||
+11
@@ -12,4 +12,15 @@ public class DivisionSampler extends BinaryArithmeticSampler {
|
||||
public double operate(double left, double right) {
|
||||
return left / right;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double[] operateDerivative(double[] left, double[] right) {
|
||||
int dimensions = left.length;
|
||||
double[] out = new double[dimensions];
|
||||
out[0] = left[0] / right[0];
|
||||
for(int i = 1; i < dimensions; i++) {
|
||||
out[i] = (left[i] * right[0] - left[0] * right[i]) / (right[0] * right[0]);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
+7
@@ -12,4 +12,11 @@ public class MaxSampler extends BinaryArithmeticSampler {
|
||||
public double operate(double left, double right) {
|
||||
return Math.max(left, right);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double[] operateDerivative(double[] left, double[] right) {
|
||||
double leftValue = left[0];
|
||||
double rightValue = right[0];
|
||||
return leftValue > rightValue ? left : right;
|
||||
}
|
||||
}
|
||||
|
||||
+7
@@ -12,4 +12,11 @@ public class MinSampler extends BinaryArithmeticSampler {
|
||||
public double operate(double left, double right) {
|
||||
return Math.min(left, right);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double[] operateDerivative(double[] left, double[] right) {
|
||||
double leftValue = left[0];
|
||||
double rightValue = right[0];
|
||||
return leftValue < rightValue ? left : right;
|
||||
}
|
||||
}
|
||||
|
||||
+11
@@ -12,4 +12,15 @@ public class MultiplicationSampler extends BinaryArithmeticSampler {
|
||||
public double operate(double left, double right) {
|
||||
return left * right;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double[] operateDerivative(double[] left, double[] right) {
|
||||
int dimensions = left.length;
|
||||
double[] out = new double[dimensions];
|
||||
out[0] = left[0] * right[0];
|
||||
for(int i = 1; i < dimensions; i++) {
|
||||
out[i] = left[i] * right[0] + left[0] * right[i];
|
||||
}
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
+10
@@ -12,4 +12,14 @@ public class SubtractionSampler extends BinaryArithmeticSampler {
|
||||
public double operate(double left, double right) {
|
||||
return left - right;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double[] operateDerivative(double[] left, double[] right) {
|
||||
int dimensions = left.length;
|
||||
double[] out = new double[dimensions];
|
||||
for(int i = 0; i < dimensions; i++) {
|
||||
out[i] = left[i] - right[i];
|
||||
}
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
+12
-6
@@ -197,7 +197,9 @@ public class CellularSampler extends NoiseFunction {
|
||||
private double jitterModifier = 1.0;
|
||||
|
||||
private NoiseSampler noiseLookup;
|
||||
|
||||
|
||||
private boolean saltLookup;
|
||||
|
||||
public CellularSampler() {
|
||||
noiseLookup = new OpenSimplex2Sampler();
|
||||
}
|
||||
@@ -217,7 +219,11 @@ public class CellularSampler extends NoiseFunction {
|
||||
public void setReturnType(ReturnType returnType) {
|
||||
this.returnType = returnType;
|
||||
}
|
||||
|
||||
|
||||
public void setSaltLookup(boolean saltLookup) {
|
||||
this.saltLookup = saltLookup;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getNoiseRaw(long sl, double x, double y) {
|
||||
int seed = (int) sl;
|
||||
@@ -286,8 +292,8 @@ public class CellularSampler extends NoiseFunction {
|
||||
case Distance2Sub -> distance1 - distance0 - 1;
|
||||
case Distance2Mul -> distance1 * distance0 * 0.5 - 1;
|
||||
case Distance2Div -> distance0 / distance1 - 1;
|
||||
case NoiseLookup -> noiseLookup.noise(sl, centerX, centerY);
|
||||
case LocalNoiseLookup -> noiseLookup.noise(sl, x / frequency - centerX, y / frequency - centerY);
|
||||
case NoiseLookup -> noiseLookup.noise(sl - (saltLookup ? 0 : salt), centerX, centerY);
|
||||
case LocalNoiseLookup -> noiseLookup.noise(sl - (saltLookup ? 0 : salt), x / frequency - centerX, y / frequency - centerY);
|
||||
case Distance3 -> distance2 - 1;
|
||||
case Distance3Add -> (distance2 + distance0) * 0.5 - 1;
|
||||
case Distance3Sub -> distance2 - distance0 - 1;
|
||||
@@ -377,8 +383,8 @@ public class CellularSampler extends NoiseFunction {
|
||||
case Distance2Sub -> distance1 - distance0 - 1;
|
||||
case Distance2Mul -> distance1 * distance0 * 0.5 - 1;
|
||||
case Distance2Div -> distance0 / distance1 - 1;
|
||||
case NoiseLookup -> noiseLookup.noise(sl, centerX, centerY, centerZ);
|
||||
case LocalNoiseLookup -> noiseLookup.noise(sl, x / frequency - centerX, y / frequency - centerY, z / frequency - centerZ);
|
||||
case NoiseLookup -> noiseLookup.noise(sl - (saltLookup ? 0 : salt), centerX, centerY, centerZ);
|
||||
case LocalNoiseLookup -> noiseLookup.noise(sl - (saltLookup ? 0 : salt), x / frequency - centerX, y / frequency - centerY, z / frequency - centerZ);
|
||||
case Distance3 -> distance2 - 1;
|
||||
case Distance3Add -> (distance2 + distance0) * 0.5 - 1;
|
||||
case Distance3Sub -> distance2 - distance0 - 1;
|
||||
|
||||
+57
@@ -7,6 +7,7 @@
|
||||
|
||||
package com.dfsek.terra.addons.noise.samplers.noise.fractal;
|
||||
|
||||
import com.dfsek.terra.api.noise.DerivativeNoiseSampler;
|
||||
import com.dfsek.terra.api.noise.NoiseSampler;
|
||||
import com.dfsek.terra.api.util.MathUtil;
|
||||
|
||||
@@ -52,4 +53,60 @@ public class BrownianMotionSampler extends FractalNoiseFunction {
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDifferentiable() {
|
||||
return DerivativeNoiseSampler.isDifferentiable(input);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double[] getNoiseDerivativeRaw(long seed, double x, double y) {
|
||||
double[] sum = {0, 0, 0};
|
||||
double amp = fractalBounding;
|
||||
|
||||
for(int i = 0; i < octaves; i++) {
|
||||
// This should only be called after `input` is verified as a `DerivativeNoiseSampler`
|
||||
// so this should be a safe cast
|
||||
double[] noise = ((DerivativeNoiseSampler) input).noised(seed++, x, y);
|
||||
sum[0] += noise[0] * amp;
|
||||
|
||||
// Directional derivative of each octave can be subject to the same addition and product
|
||||
// as per derivative sum and product rules in order to produce the correct final derivative
|
||||
sum[1] += noise[1] * amp;
|
||||
sum[2] += noise[2] * amp;
|
||||
|
||||
amp *= MathUtil.lerp(weightedStrength, 1.0, Math.min(noise[0] + 1, 2) * 0.5);
|
||||
|
||||
x *= lacunarity;
|
||||
y *= lacunarity;
|
||||
amp *= gain;
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double[] getNoiseDerivativeRaw(long seed, double x, double y, double z) {
|
||||
double[] sum = {0, 0, 0, 0};
|
||||
double amp = fractalBounding;
|
||||
|
||||
for(int i = 0; i < octaves; i++) {
|
||||
double[] noise = ((DerivativeNoiseSampler) input).noised(seed++, x, y, z);
|
||||
sum[0] += noise[0] * amp;
|
||||
|
||||
// See comment in 2D version
|
||||
sum[1] += noise[1] * amp;
|
||||
sum[2] += noise[2] * amp;
|
||||
sum[3] += noise[3] * amp;
|
||||
|
||||
amp *= MathUtil.lerp(weightedStrength, 1.0, (noise[0] + 1) * 0.5);
|
||||
|
||||
x *= lacunarity;
|
||||
y *= lacunarity;
|
||||
z *= lacunarity;
|
||||
amp *= gain;
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
}
|
||||
|
||||
+17
-2
@@ -7,11 +7,11 @@
|
||||
|
||||
package com.dfsek.terra.addons.noise.samplers.noise.fractal;
|
||||
|
||||
import com.dfsek.terra.addons.noise.samplers.noise.NoiseFunction;
|
||||
import com.dfsek.terra.addons.noise.samplers.noise.DerivativeNoiseFunction;
|
||||
import com.dfsek.terra.api.noise.NoiseSampler;
|
||||
|
||||
|
||||
public abstract class FractalNoiseFunction extends NoiseFunction {
|
||||
public abstract class FractalNoiseFunction extends DerivativeNoiseFunction {
|
||||
protected final NoiseSampler input;
|
||||
protected double fractalBounding = 1 / 1.75;
|
||||
protected int octaves = 3;
|
||||
@@ -52,4 +52,19 @@ public abstract class FractalNoiseFunction extends NoiseFunction {
|
||||
public void setWeightedStrength(double weightedStrength) {
|
||||
this.weightedStrength = weightedStrength;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDifferentiable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double[] getNoiseDerivativeRaw(long seed, double x, double y) {
|
||||
throw new UnsupportedOperationException("Implementation failed to check or set isDifferentiable correctly");
|
||||
}
|
||||
|
||||
@Override
|
||||
public double[] getNoiseDerivativeRaw(long seed, double x, double y, double z) {
|
||||
throw new UnsupportedOperationException("Implementation failed to check or set isDifferentiable correctly");
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -62,7 +62,7 @@ public class OpenSimplex2Sampler extends SimplexStyleSampler {
|
||||
double x1 = x0 + (G2 - 1);
|
||||
double y1 = y0 + G2;
|
||||
double b = 0.5 - x1 * x1 - y1 * y1;
|
||||
if(b <= 0) {
|
||||
if(b > 0) {
|
||||
value += (b * b) * (b * b) * gradCoord(seed, i + PRIME_X, j, x1, y1);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -116,12 +116,12 @@ public abstract class SimplexStyleSampler extends DerivativeNoiseFunction {
|
||||
|
||||
@Override
|
||||
public double[] getNoiseDerivativeRaw(long seed, double x, double y) {
|
||||
return new double[]{ 0, 0, 0 };
|
||||
throw new UnsupportedOperationException("Implementation failed to check or set isDifferentiable correctly");
|
||||
}
|
||||
|
||||
@Override
|
||||
public double[] getNoiseDerivativeRaw(long seed, double x, double y, double z) {
|
||||
return new double[]{ 0, 0, 0, 0 };
|
||||
throw new UnsupportedOperationException("Implementation failed to check or set isDifferentiable correctly");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -81,4 +81,7 @@ public interface Platform extends LoaderRegistrar {
|
||||
@NotNull
|
||||
@Contract(pure = true)
|
||||
Profiler getProfiler();
|
||||
|
||||
@Contract(pure = true)
|
||||
int getGenerationThreads();
|
||||
}
|
||||
|
||||
@@ -6,10 +6,7 @@ package com.dfsek.terra.api.noise;
|
||||
public interface DerivativeNoiseSampler extends NoiseSampler {
|
||||
|
||||
static boolean isDifferentiable(NoiseSampler sampler) {
|
||||
if(sampler instanceof DerivativeNoiseSampler dSampler) {
|
||||
return dSampler.isDifferentiable();
|
||||
}
|
||||
return false;
|
||||
return sampler instanceof DerivativeNoiseSampler dSampler && dSampler.isDifferentiable();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+4
-2
@@ -7,6 +7,8 @@
|
||||
|
||||
package com.dfsek.terra.api.world.biome.generation;
|
||||
|
||||
import com.dfsek.terra.api.Platform;
|
||||
|
||||
import org.jetbrains.annotations.Contract;
|
||||
|
||||
import java.util.Optional;
|
||||
@@ -91,11 +93,11 @@ public interface BiomeProvider {
|
||||
return StreamSupport.stream(getBiomes().spliterator(), false);
|
||||
}
|
||||
|
||||
default CachingBiomeProvider caching() {
|
||||
default CachingBiomeProvider caching(Platform platform) {
|
||||
if(this instanceof CachingBiomeProvider cachingBiomeProvider) {
|
||||
return cachingBiomeProvider;
|
||||
}
|
||||
return new CachingBiomeProvider(this);
|
||||
return new CachingBiomeProvider(this, platform.getGenerationThreads());
|
||||
}
|
||||
|
||||
|
||||
|
||||
+7
-6
@@ -21,19 +21,20 @@ public class CachingBiomeProvider implements BiomeProvider, Handle {
|
||||
private final LoadingCache<SeededVector3, Biome> cache;
|
||||
private final LoadingCache<SeededVector2, Optional<Biome>> baseCache;
|
||||
|
||||
protected CachingBiomeProvider(BiomeProvider delegate) {
|
||||
protected CachingBiomeProvider(BiomeProvider delegate, int generationThreads) {
|
||||
this.delegate = delegate;
|
||||
this.res = delegate.resolution();
|
||||
int size = generationThreads * 98304;
|
||||
this.cache = Caffeine
|
||||
.newBuilder()
|
||||
.scheduler(Scheduler.disabledScheduler())
|
||||
.initialCapacity(98304)
|
||||
.maximumSize(98304) // 1 full chunk (high res)
|
||||
.initialCapacity(size)
|
||||
.maximumSize(size) // 1 full chunk (high res)
|
||||
.build(vec -> delegate.getBiome(vec.x * res, vec.y * res, vec.z * res, vec.seed));
|
||||
|
||||
this.baseCache = Caffeine
|
||||
.newBuilder()
|
||||
.maximumSize(256) // 1 full chunk (high res)
|
||||
.maximumSize(256L * generationThreads) // 1 full chunk (high res)
|
||||
.build(vec -> delegate.getBaseBiome(vec.x * res, vec.z * res, vec.seed));
|
||||
|
||||
}
|
||||
@@ -77,7 +78,7 @@ public class CachingBiomeProvider implements BiomeProvider, Handle {
|
||||
int code = x;
|
||||
code = 31 * code + y;
|
||||
code = 31 * code + z;
|
||||
return 31 * code + ((int) (seed ^ (seed >>> 32)));
|
||||
return 31 * code + (Long.hashCode(seed));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,7 +96,7 @@ public class CachingBiomeProvider implements BiomeProvider, Handle {
|
||||
public int hashCode() {
|
||||
int code = x;
|
||||
code = 31 * code + z;
|
||||
return 31 * code + ((int) (seed ^ (seed >>> 32)));
|
||||
return 31 * code + (Long.hashCode(seed));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -310,6 +310,24 @@ public abstract class AbstractPlatform implements Platform {
|
||||
}
|
||||
}
|
||||
|
||||
public static int getGenerationThreadsWithReflection(String className, String fieldName, String project) {
|
||||
try {
|
||||
Class aClass = Class.forName(className);
|
||||
int threads = aClass.getField(fieldName).getInt(null);
|
||||
logger.info("{} found, setting {} generation threads.", project, threads);
|
||||
return threads;
|
||||
} catch(ClassNotFoundException e) {
|
||||
logger.info("{} not found.", project);
|
||||
} catch(NoSuchFieldException e) {
|
||||
logger.warn("{} found, but {} field not found this probably means {0} has changed its code and " +
|
||||
"Terra has not updated to reflect that.", project, fieldName);
|
||||
} catch(IllegalAccessException e) {
|
||||
logger.error("Failed to access {} field in {}, assuming 1 generation thread.", fieldName, project, e);
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(TypeRegistry registry) {
|
||||
loaders.register(registry);
|
||||
@@ -339,4 +357,9 @@ public abstract class AbstractPlatform implements Platform {
|
||||
public @NotNull Profiler getProfiler() {
|
||||
return profiler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getGenerationThreads() {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -232,7 +232,7 @@ public class ConfigPackImpl implements ConfigPack {
|
||||
ConfigPackPostTemplate packPostTemplate = new ConfigPackPostTemplate();
|
||||
selfLoader.load(packPostTemplate, packManifest);
|
||||
seededBiomeProvider =
|
||||
template.getBiomeCache() ? packPostTemplate.getProviderBuilder().caching() : packPostTemplate.getProviderBuilder();
|
||||
template.getBiomeCache() ? packPostTemplate.getProviderBuilder().caching(platform) : packPostTemplate.getProviderBuilder();
|
||||
checkDeadEntries();
|
||||
}
|
||||
|
||||
|
||||
@@ -51,7 +51,13 @@ public class PlatformImpl extends AbstractPlatform {
|
||||
|
||||
private final TerraBukkitPlugin plugin;
|
||||
|
||||
private int generationThreads;
|
||||
|
||||
public PlatformImpl(TerraBukkitPlugin plugin) {
|
||||
generationThreads = getGenerationThreadsWithReflection("ca.spottedleaf.moonrise.common.util.MoonriseCommon", "WORKER_THREADS", "Moonrise");
|
||||
if (generationThreads == 0) {
|
||||
generationThreads = 1;
|
||||
}
|
||||
this.plugin = plugin;
|
||||
load();
|
||||
}
|
||||
@@ -108,6 +114,11 @@ public class PlatformImpl extends AbstractPlatform {
|
||||
return itemHandle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getGenerationThreads() {
|
||||
return generationThreads;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(TypeRegistry registry) {
|
||||
super.register(registry);
|
||||
|
||||
+2
-20
@@ -23,13 +23,11 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import com.dfsek.terra.api.block.state.BlockState;
|
||||
import com.dfsek.terra.api.entity.EntityType;
|
||||
import com.dfsek.terra.api.handle.WorldHandle;
|
||||
import com.dfsek.terra.bukkit.util.BukkitUtils;
|
||||
import com.dfsek.terra.bukkit.world.block.data.BukkitBlockState;
|
||||
import com.dfsek.terra.bukkit.world.entity.BukkitEntityType;
|
||||
|
||||
|
||||
public class BukkitWorldHandle implements WorldHandle {
|
||||
@@ -61,22 +59,6 @@ public class BukkitWorldHandle implements WorldHandle {
|
||||
|
||||
@Override
|
||||
public @NotNull EntityType getEntity(@NotNull String id) {
|
||||
if(!id.contains(":")) { //TODO: remove in 7.0
|
||||
String newid = "minecraft:" + id.toLowerCase();
|
||||
;
|
||||
logger.warn(
|
||||
"Translating " + id + " to " + newid + ". In 1.20.3 entity parsing was reworked" +
|
||||
". You are advised to perform this rename in your config backs as this translation will be removed in the next major " +
|
||||
"version of Terra.");
|
||||
}
|
||||
if(!id.startsWith("minecraft:")) throw new IllegalArgumentException("Invalid entity identifier " + id);
|
||||
String entityID = id.toUpperCase(Locale.ROOT).substring(10);
|
||||
|
||||
return new BukkitEntityType(switch(entityID) {
|
||||
case "END_CRYSTAL" -> org.bukkit.entity.EntityType.END_CRYSTAL;
|
||||
case "ENDER_CRYSTAL" -> throw new IllegalArgumentException(
|
||||
"Invalid entity identifier " + id); // make sure this issue can't happen the other way around.
|
||||
default -> org.bukkit.entity.EntityType.valueOf(entityID);
|
||||
});
|
||||
return BukkitUtils.getEntityType(id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,11 +2,40 @@ package com.dfsek.terra.bukkit.util;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import com.dfsek.terra.api.entity.EntityType;
|
||||
import com.dfsek.terra.bukkit.world.entity.BukkitEntityType;
|
||||
|
||||
|
||||
public class BukkitUtils {
|
||||
private static final Logger logger = LoggerFactory.getLogger(BukkitUtils.class);
|
||||
|
||||
public static boolean isLiquid(BlockData blockState) {
|
||||
Material material = blockState.getMaterial();
|
||||
return material == Material.WATER || material == Material.LAVA;
|
||||
}
|
||||
|
||||
public static EntityType getEntityType(String id) {
|
||||
if(!id.contains(":")) { //TODO: remove in 7.0
|
||||
String newid = "minecraft:" + id.toLowerCase();
|
||||
;
|
||||
logger.warn(
|
||||
"Translating " + id + " to " + newid + ". In 1.20.3 entity parsing was reworked" +
|
||||
". You are advised to perform this rename in your config backs as this translation will be removed in the next major " +
|
||||
"version of Terra.");
|
||||
}
|
||||
if(!id.startsWith("minecraft:")) throw new IllegalArgumentException("Invalid entity identifier " + id);
|
||||
String entityID = id.toUpperCase(Locale.ROOT).substring(10);
|
||||
|
||||
return new BukkitEntityType(switch(entityID) {
|
||||
case "END_CRYSTAL" -> org.bukkit.entity.EntityType.END_CRYSTAL;
|
||||
case "ENDER_CRYSTAL" -> throw new IllegalArgumentException(
|
||||
"Invalid entity identifier " + id); // make sure this issue can't happen the other way around.
|
||||
default -> org.bukkit.entity.EntityType.valueOf(entityID);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ package com.dfsek.terra.bukkit.world;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.TreeType;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.generator.WorldInfo;
|
||||
import org.bukkit.util.Vector;
|
||||
@@ -46,27 +45,12 @@ import com.dfsek.terra.bukkit.world.block.BukkitBlockTypeAndItem;
|
||||
import com.dfsek.terra.bukkit.world.block.data.BukkitBlockState;
|
||||
import com.dfsek.terra.bukkit.world.inventory.BukkitItemStack;
|
||||
import com.dfsek.terra.bukkit.world.inventory.meta.BukkitEnchantment;
|
||||
import com.dfsek.terra.transform.MapTransform;
|
||||
import com.dfsek.terra.transform.TransformerImpl;
|
||||
|
||||
|
||||
/**
|
||||
* Utility class to adapt Bukkit enums to Terra enums.
|
||||
*/
|
||||
public final class BukkitAdapter {
|
||||
public static TransformerImpl<TreeType, String> TREE_TRANSFORMER = new TransformerImpl.Builder<TreeType, String>()
|
||||
.addTransform(new MapTransform<TreeType, String>()
|
||||
.add(TreeType.COCOA_TREE, "JUNGLE_COCOA")
|
||||
.add(TreeType.BIG_TREE, "LARGE_OAK")
|
||||
.add(TreeType.TALL_REDWOOD, "LARGE_SPRUCE")
|
||||
.add(TreeType.REDWOOD, "SPRUCE")
|
||||
.add(TreeType.TREE, "OAK")
|
||||
.add(TreeType.MEGA_REDWOOD, "MEGA_SPRUCE")
|
||||
.add(TreeType.SWAMP, "SWAMP_OAK"))
|
||||
.addTransform(TreeType::toString)
|
||||
.build();
|
||||
|
||||
|
||||
public static BlockState adapt(org.bukkit.block.data.BlockData data) {
|
||||
return BukkitBlockState.newInstance(data);
|
||||
}
|
||||
|
||||
+2
-1
@@ -23,6 +23,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import com.dfsek.terra.api.block.entity.MobSpawner;
|
||||
import com.dfsek.terra.api.block.entity.SerialState;
|
||||
import com.dfsek.terra.api.entity.EntityType;
|
||||
import com.dfsek.terra.bukkit.util.BukkitUtils;
|
||||
import com.dfsek.terra.bukkit.world.entity.BukkitEntityType;
|
||||
|
||||
|
||||
@@ -115,7 +116,7 @@ public class BukkitMobSpawner extends BukkitBlockEntity implements MobSpawner {
|
||||
public void applyState(String state) {
|
||||
SerialState.parse(state).forEach((k, v) -> {
|
||||
switch(k) {
|
||||
case "type" -> setSpawnedType(new BukkitEntityType(org.bukkit.entity.EntityType.valueOf(v.toUpperCase())));
|
||||
case "type" -> setSpawnedType(BukkitUtils.getEntityType(v));
|
||||
case "delay" -> setDelay(Integer.parseInt(v));
|
||||
case "min_delay" -> setMinSpawnDelay(Integer.parseInt(v));
|
||||
case "max_delay" -> setMaxSpawnDelay(Integer.parseInt(v));
|
||||
|
||||
@@ -10,6 +10,9 @@ dependencies {
|
||||
shadedApi("commons-io", "commons-io", Versions.Libraries.Internal.apacheIO)
|
||||
shadedApi("com.github.Querz", "NBT", Versions.CLI.nbt)
|
||||
|
||||
shadedImplementation("info.picocli", "picocli", Versions.CLI.picocli)
|
||||
annotationProcessor("info.picocli", "picocli-codegen", Versions.CLI.picocli)
|
||||
|
||||
shadedImplementation("com.google.guava", "guava", Versions.Libraries.Internal.guava)
|
||||
|
||||
shadedImplementation("ch.qos.logback", "logback-classic", Versions.CLI.logback)
|
||||
@@ -26,6 +29,12 @@ tasks.withType<Jar> {
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType<JavaCompile> {
|
||||
doFirst {
|
||||
options.compilerArgs.add("-Aproject=${project.group}/${project.name}")
|
||||
}
|
||||
}
|
||||
|
||||
application {
|
||||
mainClass.set(javaMainClass)
|
||||
}
|
||||
|
||||
@@ -22,6 +22,8 @@ public class CLIPlatform extends AbstractPlatform {
|
||||
private final CLIWorldHandle worldHandle = new CLIWorldHandle();
|
||||
private final CLIItemHandle itemHandle = new CLIItemHandle();
|
||||
|
||||
private final int generationThreads = Runtime.getRuntime().availableProcessors() - 1;
|
||||
|
||||
public CLIPlatform() {
|
||||
LOGGER.info("Root directory: {}", getDataFolder().getAbsoluteFile());
|
||||
load();
|
||||
@@ -58,4 +60,9 @@ public class CLIPlatform extends AbstractPlatform {
|
||||
super.register(registry);
|
||||
registry.registerLoader(PlatformBiome.class, (TypeLoader<PlatformBiome>) (annotatedType, o, configLoader, depthTracker) -> () -> o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getGenerationThreads() {
|
||||
return generationThreads;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,41 +5,74 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import com.dfsek.terra.api.config.ConfigPack;
|
||||
import com.dfsek.terra.api.event.events.platform.PlatformInitializationEvent;
|
||||
import com.dfsek.terra.api.util.vector.Vector2Int;
|
||||
import com.dfsek.terra.cli.world.CLIWorld;
|
||||
|
||||
import picocli.CommandLine;
|
||||
import picocli.CommandLine.Command;
|
||||
import picocli.CommandLine.Option;
|
||||
|
||||
public final class TerraCLI {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(TerraCLI.class);
|
||||
|
||||
public static void main(String... args) {
|
||||
//TODO auto pull in version
|
||||
@Command(name = "TerraCLI", mixinStandardHelpOptions = true, version = "6.6.0",
|
||||
description = "Generates a Terra World and saves it in minecraft region format.")
|
||||
public final class TerraCLI implements Callable<Integer> {
|
||||
@Option(names = { "-s", "--size"}, description = "Number of regions to generate.")
|
||||
private int size = 2;
|
||||
|
||||
@Option(names = { "-p", "--pack"}, description = "Config pack to use.")
|
||||
private String pack = "OVERWORLD";
|
||||
|
||||
@Option(names = { "--seed"}, description = "Seed for world generation.")
|
||||
private long seed = 0;
|
||||
|
||||
@Option(names = { "--max-height"}, description = "Maximum height of the world.")
|
||||
private int maxHeight = 384;
|
||||
|
||||
@Option(names = { "--min-height"}, description = "Minimum height of the world.")
|
||||
private int minHeight = -64;
|
||||
|
||||
@Option(names = { "--no-save"}, description = "Don't save the world to disk.")
|
||||
private boolean noSave = false;
|
||||
|
||||
@Override
|
||||
public Integer call() {
|
||||
Logger LOGGER = LoggerFactory.getLogger(TerraCLI.class);
|
||||
LOGGER.info("Starting Terra CLI...");
|
||||
|
||||
CLIPlatform platform = new CLIPlatform();
|
||||
platform.getEventManager().callEvent(new PlatformInitializationEvent());
|
||||
|
||||
ConfigPack generate = platform.getConfigRegistry().getByID("OVERWORLD").orElseThrow(); // TODO: make this a cli argument
|
||||
ConfigPack generate = platform.getConfigRegistry().getByID(pack).orElseThrow();
|
||||
|
||||
CLIWorld world = new CLIWorld(2, 2, 384, -64, generate);
|
||||
CLIWorld world = new CLIWorld(size, seed, maxHeight, minHeight, generate, noSave);
|
||||
|
||||
world.generate();
|
||||
|
||||
world.serialize().parallel().forEach(mcaFile -> {
|
||||
Vector2Int pos = mcaFile.getLeft();
|
||||
String name = MCAUtil.createNameFromRegionLocation(pos.getX(), pos.getZ());
|
||||
LOGGER.info("Writing region ({}, {}) to {}", pos.getX(), pos.getZ(), name);
|
||||
if(!noSave) {
|
||||
world.serialize().parallel().forEach(mcaFile -> {
|
||||
Vector2Int pos = mcaFile.getLeft();
|
||||
String name = MCAUtil.createNameFromRegionLocation(pos.getX(), pos.getZ());
|
||||
LOGGER.info("Writing region ({}, {}) to {}", pos.getX(), pos.getZ(), name);
|
||||
|
||||
try {
|
||||
MCAUtil.write(mcaFile.getRight(), name);
|
||||
} catch(IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
LOGGER.info("Wrote region to file.");
|
||||
});
|
||||
try {
|
||||
MCAUtil.write(mcaFile.getRight(), name);
|
||||
} catch(IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
LOGGER.info("Wrote region to file.");
|
||||
});
|
||||
}
|
||||
LOGGER.info("Done.");
|
||||
System.exit(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static void main(String... args) {
|
||||
int exitCode = new CommandLine(new TerraCLI()).execute(args);
|
||||
System.exit(exitCode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ public class CLIWorld implements ServerWorld, NBTSerializable<Stream<Pair<Vector
|
||||
private final ChunkGenerator chunkGenerator;
|
||||
private final BiomeProvider biomeProvider;
|
||||
private final ConfigPack pack;
|
||||
private final boolean noSave;
|
||||
private final AtomicInteger amount = new AtomicInteger(0);
|
||||
|
||||
private final ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() - 1);
|
||||
@@ -51,7 +52,7 @@ public class CLIWorld implements ServerWorld, NBTSerializable<Stream<Pair<Vector
|
||||
long seed,
|
||||
int maxHeight,
|
||||
int minHeight,
|
||||
ConfigPack pack) {
|
||||
ConfigPack pack, boolean noSave) {
|
||||
this.size = size;
|
||||
this.maxHeight = maxHeight;
|
||||
this.minHeight = minHeight;
|
||||
@@ -59,6 +60,7 @@ public class CLIWorld implements ServerWorld, NBTSerializable<Stream<Pair<Vector
|
||||
this.chunkGenerator = pack.getGeneratorProvider().newInstance(pack);
|
||||
this.biomeProvider = pack.getBiomeProvider();
|
||||
this.pack = pack;
|
||||
this.noSave = noSave;
|
||||
|
||||
|
||||
size += 1;
|
||||
@@ -73,6 +75,7 @@ public class CLIWorld implements ServerWorld, NBTSerializable<Stream<Pair<Vector
|
||||
}
|
||||
|
||||
public void generate() {
|
||||
ArrayList<Double> CPSHistory = new ArrayList<>();
|
||||
int sizeChunks = size * 32;
|
||||
List<Future<?>> futures = new ArrayList<>();
|
||||
final AtomicLong start = new AtomicLong(System.nanoTime());
|
||||
@@ -83,7 +86,13 @@ public class CLIWorld implements ServerWorld, NBTSerializable<Stream<Pair<Vector
|
||||
futures.add(executor.submit(() -> {
|
||||
try {
|
||||
int num = amount.getAndIncrement();
|
||||
CLIChunk chunk = getChunkAt(finalX, finalZ);
|
||||
CLIChunk chunk;
|
||||
if (!noSave) {
|
||||
chunk = getChunkAt(finalX, finalZ);
|
||||
} else {
|
||||
chunk = new CLIChunk(Math.floorMod(finalX, 32), Math.floorMod(finalZ, 32), this);
|
||||
}
|
||||
|
||||
BiomeProvider cachingBiomeProvider = pack.getBiomeProvider();
|
||||
chunkGenerator.generateChunkData(chunk, this, cachingBiomeProvider, finalX, finalZ);
|
||||
CLIProtoWorld protoWorld = new CLIProtoWorld(this, cachingBiomeProvider, finalX, finalZ);
|
||||
@@ -91,6 +100,7 @@ public class CLIWorld implements ServerWorld, NBTSerializable<Stream<Pair<Vector
|
||||
if(num % 240 == 239) {
|
||||
long time = System.nanoTime();
|
||||
double cps = num / ((double) (time - start.get()) / 1000000000);
|
||||
CPSHistory.add(cps);
|
||||
LOGGER.info("Generating chunk at ({}, {}), generated {} chunks at {}cps", finalX, finalZ, num, cps);
|
||||
amount.set(0);
|
||||
start.set(System.nanoTime());
|
||||
@@ -109,6 +119,8 @@ public class CLIWorld implements ServerWorld, NBTSerializable<Stream<Pair<Vector
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
LOGGER.info("Average CPS: {}", CPSHistory.stream().mapToDouble(d -> d).average().orElse(0));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+12
@@ -3,6 +3,9 @@ package com.dfsek.terra.lifecycle;
|
||||
import ca.solostudios.strata.Versions;
|
||||
import ca.solostudios.strata.parser.tokenizer.ParseException;
|
||||
import ca.solostudios.strata.version.Version;
|
||||
|
||||
import com.dfsek.terra.api.util.reflection.ReflectionUtil;
|
||||
|
||||
import net.minecraft.MinecraftVersion;
|
||||
import net.minecraft.enchantment.Enchantment;
|
||||
import net.minecraft.registry.Registry;
|
||||
@@ -37,8 +40,15 @@ public abstract class LifecyclePlatform extends ModPlatform {
|
||||
private static final AtomicReference<Registry<MultiNoiseBiomeSourceParameterList>> NOISE = new AtomicReference<>();
|
||||
private static final AtomicReference<Registry<Enchantment>> ENCHANTMENT = new AtomicReference<>();
|
||||
private static MinecraftServer server;
|
||||
private int generationThreads;
|
||||
|
||||
public LifecyclePlatform() {
|
||||
generationThreads = getGenerationThreadsWithReflection("com.ishland.c2me.base.common.GlobalExecutors", "GLOBAL_EXECUTOR_PARALLELISM", "C2ME");
|
||||
if (generationThreads == 0) {
|
||||
generationThreads = getGenerationThreadsWithReflection("ca.spottedleaf.moonrise.common.util.MoonriseCommon", "WORKER_THREADS", "Moonrise");
|
||||
} if (generationThreads == 0) {
|
||||
generationThreads = 1;
|
||||
}
|
||||
CommonPlatform.initialize(this);
|
||||
load();
|
||||
}
|
||||
@@ -55,6 +65,8 @@ public abstract class LifecyclePlatform extends ModPlatform {
|
||||
ENCHANTMENT.set(enchantmentRegistry);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public MinecraftServer getServer() {
|
||||
return server;
|
||||
|
||||
Reference in New Issue
Block a user