mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2026-05-20 08:40:26 +00:00
Compare commits
29 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b78edacd80 | |||
| dbacf70058 | |||
| 9b41af8a57 | |||
| 249e8282c5 | |||
| 81e354f91c | |||
| aab28ff4f9 | |||
| 0e3a756011 | |||
| 02198e1b88 | |||
| 00aeb98419 | |||
| 1a784b51ac | |||
| 34c0895c1f | |||
| 379fa601a3 | |||
| fcbf51d80b | |||
| 9d83dfd164 | |||
| 72686601ee | |||
| 73baaec6cd | |||
| 0be7213ee5 | |||
| 3f3e2fe97c | |||
| 549edd11ea | |||
| 36f89946d4 | |||
| 18644d6100 | |||
| 9d38ee4329 | |||
| b75a8f85e4 | |||
| aad58f5968 | |||
| a548c30484 | |||
| 9ba46ae3a5 | |||
| 49efbed6f5 | |||
| 4001a56100 | |||
| 70dbd2f2c0 |
+3
-3
@@ -1,8 +1,8 @@
|
||||
preRelease(true)
|
||||
|
||||
versionProjects(":common:api", version("6.3.0"))
|
||||
versionProjects(":common:implementation", version("6.3.0"))
|
||||
versionProjects(":platforms", version("6.3.0"))
|
||||
versionProjects(":common:api", version("6.4.0"))
|
||||
versionProjects(":common:implementation", version("6.4.0"))
|
||||
versionProjects(":platforms", version("6.4.0"))
|
||||
|
||||
|
||||
allprojects {
|
||||
|
||||
@@ -19,7 +19,7 @@ object Versions {
|
||||
|
||||
object Fabric {
|
||||
const val fabricLoader = "0.14.8"
|
||||
const val fabricAPI = "0.78.0+1.19.4"
|
||||
const val fabricAPI = "0.83.1+1.20.1"
|
||||
}
|
||||
|
||||
object Quilt {
|
||||
@@ -30,9 +30,9 @@ object Versions {
|
||||
object Mod {
|
||||
const val mixin = "0.11.2+mixin.0.8.5"
|
||||
|
||||
const val minecraft = "1.19.4"
|
||||
const val minecraft = "1.20.1"
|
||||
const val yarn = "$minecraft+build.2"
|
||||
const val fabricLoader = "0.14.2"
|
||||
const val fabricLoader = "0.14.21"
|
||||
|
||||
const val architecuryLoom = "0.12.0.290"
|
||||
const val architecturyPlugin = "3.4-SNAPSHOT"
|
||||
@@ -41,16 +41,16 @@ object Versions {
|
||||
}
|
||||
|
||||
object Forge {
|
||||
const val forge = "${Mod.minecraft}-45.0.43"
|
||||
const val forge = "${Mod.minecraft}-47.0.3"
|
||||
const val burningwave = "12.53.0"
|
||||
}
|
||||
|
||||
object Bukkit {
|
||||
const val paper = "1.18.2-R0.1-SNAPSHOT"
|
||||
const val paperLib = "1.0.5"
|
||||
const val minecraft = "1.19.4"
|
||||
const val minecraft = "1.20.1"
|
||||
const val reflectionRemapper = "0.1.0-SNAPSHOT"
|
||||
const val paperDevBundle = "1.19.4-R0.1-SNAPSHOT"
|
||||
const val paperDevBundle = "1.20.1-R0.1-SNAPSHOT"
|
||||
}
|
||||
|
||||
object Sponge {
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@ public class PipelineBiomeProvider implements BiomeProvider {
|
||||
this.noiseAmp = noiseAmp;
|
||||
this.chunkSize = pipeline.getChunkSize();
|
||||
this.biomeChunkCache = Caffeine.newBuilder()
|
||||
.maximumSize(1024)
|
||||
.maximumSize(64)
|
||||
.build(pipeline::generateChunk);
|
||||
|
||||
Set<PipelineBiome> biomeSet = new HashSet<>();
|
||||
|
||||
+1
-1
@@ -54,6 +54,6 @@ public class BiomePipelineTemplate implements ObjectTemplate<BiomeProvider> {
|
||||
|
||||
@Override
|
||||
public BiomeProvider get() {
|
||||
return new PipelineBiomeProvider(new PipelineImpl(source, stages, resolution, 500), resolution, blendSampler, blendAmplitude);
|
||||
return new PipelineBiomeProvider(new PipelineImpl(source, stages, resolution, 128), resolution, blendSampler, blendAmplitude);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
|
||||
|
||||
version = version("1.0.0")
|
||||
version = version("1.1.0")
|
||||
|
||||
dependencies {
|
||||
compileOnlyApi(project(":common:addons:manifest-addon-loader"))
|
||||
|
||||
+10
-1
@@ -21,8 +21,10 @@ import com.dfsek.terra.addons.noise.config.templates.FunctionTemplate;
|
||||
import com.dfsek.terra.addons.noise.config.templates.ImageSamplerTemplate;
|
||||
import com.dfsek.terra.addons.noise.config.templates.KernelTemplate;
|
||||
import com.dfsek.terra.addons.noise.config.templates.LinearHeightmapSamplerTemplate;
|
||||
import com.dfsek.terra.addons.noise.config.templates.TranslateSamplerTemplate;
|
||||
import com.dfsek.terra.addons.noise.config.templates.noise.CellularNoiseTemplate;
|
||||
import com.dfsek.terra.addons.noise.config.templates.noise.ConstantNoiseTemplate;
|
||||
import com.dfsek.terra.addons.noise.config.templates.noise.DistanceSamplerTemplate;
|
||||
import com.dfsek.terra.addons.noise.config.templates.noise.ExpressionFunctionTemplate;
|
||||
import com.dfsek.terra.addons.noise.config.templates.noise.GaborNoiseTemplate;
|
||||
import com.dfsek.terra.addons.noise.config.templates.noise.SimpleNoiseTemplate;
|
||||
@@ -30,6 +32,7 @@ import com.dfsek.terra.addons.noise.config.templates.noise.fractal.BrownianMotio
|
||||
import com.dfsek.terra.addons.noise.config.templates.noise.fractal.PingPongTemplate;
|
||||
import com.dfsek.terra.addons.noise.config.templates.noise.fractal.RidgedFractalTemplate;
|
||||
import com.dfsek.terra.addons.noise.config.templates.normalizer.ClampNormalizerTemplate;
|
||||
import com.dfsek.terra.addons.noise.config.templates.normalizer.ExpressionNormalizerTemplate;
|
||||
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;
|
||||
@@ -42,6 +45,7 @@ import com.dfsek.terra.addons.noise.samplers.arithmetic.MinSampler;
|
||||
import com.dfsek.terra.addons.noise.samplers.arithmetic.MultiplicationSampler;
|
||||
import com.dfsek.terra.addons.noise.samplers.arithmetic.SubtractionSampler;
|
||||
import com.dfsek.terra.addons.noise.samplers.noise.CellularSampler;
|
||||
import com.dfsek.terra.addons.noise.samplers.noise.DistanceSampler;
|
||||
import com.dfsek.terra.addons.noise.samplers.noise.random.GaussianNoiseSampler;
|
||||
import com.dfsek.terra.addons.noise.samplers.noise.random.PositiveWhiteNoiseSampler;
|
||||
import com.dfsek.terra.addons.noise.samplers.noise.random.WhiteNoiseSampler;
|
||||
@@ -83,6 +87,8 @@ public class NoiseAddon implements AddonInitializer {
|
||||
(type, o, loader, depthTracker) -> CellularSampler.DistanceFunction.valueOf((String) o))
|
||||
.applyLoader(CellularSampler.ReturnType.class,
|
||||
(type, o, loader, depthTracker) -> CellularSampler.ReturnType.valueOf((String) o))
|
||||
.applyLoader(DistanceSampler.DistanceFunction.class,
|
||||
(type, o, loader, depthTracker) -> DistanceSampler.DistanceFunction.valueOf((String) o))
|
||||
.applyLoader(DimensionApplicableNoiseSampler.class, DimensionApplicableNoiseSampler::new)
|
||||
.applyLoader(FunctionTemplate.class, FunctionTemplate::new);
|
||||
|
||||
@@ -116,12 +122,15 @@ public class NoiseAddon implements AddonInitializer {
|
||||
noiseRegistry.register(addon.key("WHITE_NOISE"), () -> new SimpleNoiseTemplate(WhiteNoiseSampler::new));
|
||||
noiseRegistry.register(addon.key("POSITIVE_WHITE_NOISE"), () -> new SimpleNoiseTemplate(PositiveWhiteNoiseSampler::new));
|
||||
noiseRegistry.register(addon.key("GAUSSIAN"), () -> new SimpleNoiseTemplate(GaussianNoiseSampler::new));
|
||||
|
||||
noiseRegistry.register(addon.key("DISTANCE"), DistanceSamplerTemplate::new);
|
||||
|
||||
noiseRegistry.register(addon.key("CONSTANT"), ConstantNoiseTemplate::new);
|
||||
|
||||
noiseRegistry.register(addon.key("KERNEL"), KernelTemplate::new);
|
||||
|
||||
noiseRegistry.register(addon.key("LINEAR_HEIGHTMAP"), LinearHeightmapSamplerTemplate::new);
|
||||
noiseRegistry.register(addon.key("TRANSLATE"), TranslateSamplerTemplate::new);
|
||||
|
||||
noiseRegistry.register(addon.key("ADD"), () -> new BinaryArithmeticTemplate<>(AdditionSampler::new));
|
||||
noiseRegistry.register(addon.key("SUB"), () -> new BinaryArithmeticTemplate<>(SubtractionSampler::new));
|
||||
@@ -134,7 +143,7 @@ public class NoiseAddon implements AddonInitializer {
|
||||
Map<String, DimensionApplicableNoiseSampler> packSamplers = new LinkedHashMap<>();
|
||||
Map<String, FunctionTemplate> packFunctions = new LinkedHashMap<>();
|
||||
noiseRegistry.register(addon.key("EXPRESSION"), () -> new ExpressionFunctionTemplate(packSamplers, packFunctions));
|
||||
|
||||
noiseRegistry.register(addon.key("EXPRESSION_NORMALIZER"), () -> new ExpressionNormalizerTemplate(packSamplers, packFunctions));
|
||||
|
||||
NoiseConfigPackTemplate template = event.loadTemplate(new NoiseConfigPackTemplate());
|
||||
packSamplers.putAll(template.getSamplers());
|
||||
|
||||
+4
-3
@@ -4,6 +4,7 @@ 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.LinearHeightmapSampler;
|
||||
import com.dfsek.terra.api.config.meta.Meta;
|
||||
import com.dfsek.terra.api.noise.NoiseSampler;
|
||||
|
||||
|
||||
@@ -11,14 +12,14 @@ import com.dfsek.terra.api.noise.NoiseSampler;
|
||||
public class LinearHeightmapSamplerTemplate extends SamplerTemplate<LinearHeightmapSampler> {
|
||||
@Value("sampler")
|
||||
@Default
|
||||
private NoiseSampler sampler = NoiseSampler.zero();
|
||||
private @Meta NoiseSampler sampler = NoiseSampler.zero();
|
||||
|
||||
@Value("base")
|
||||
private double base;
|
||||
private @Meta double base;
|
||||
|
||||
@Value("scale")
|
||||
@Default
|
||||
private double scale = 1;
|
||||
private @Meta double scale = 1;
|
||||
|
||||
@Override
|
||||
public NoiseSampler get() {
|
||||
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
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.TranslateSampler;
|
||||
import com.dfsek.terra.api.config.meta.Meta;
|
||||
import com.dfsek.terra.api.noise.NoiseSampler;
|
||||
|
||||
|
||||
public class TranslateSamplerTemplate extends SamplerTemplate<TranslateSampler> {
|
||||
|
||||
@Value("sampler")
|
||||
private NoiseSampler sampler;
|
||||
|
||||
@Value("x")
|
||||
@Default
|
||||
private @Meta double x = 0;
|
||||
|
||||
@Value("y")
|
||||
@Default
|
||||
private @Meta double y = 0;
|
||||
|
||||
@Value("z")
|
||||
@Default
|
||||
private @Meta double z = 0;
|
||||
|
||||
@Override
|
||||
public NoiseSampler get() {
|
||||
return new TranslateSampler(sampler, x, y ,z);
|
||||
}
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
package com.dfsek.terra.addons.noise.config.templates.noise;
|
||||
|
||||
import com.dfsek.tectonic.api.config.template.annotations.Default;
|
||||
import com.dfsek.tectonic.api.config.template.annotations.Value;
|
||||
|
||||
import com.dfsek.terra.addons.noise.config.templates.SamplerTemplate;
|
||||
import com.dfsek.terra.addons.noise.samplers.noise.DistanceSampler;
|
||||
import com.dfsek.terra.addons.noise.samplers.noise.DistanceSampler.DistanceFunction;
|
||||
import com.dfsek.terra.api.config.meta.Meta;
|
||||
|
||||
|
||||
public class DistanceSamplerTemplate extends SamplerTemplate<DistanceSampler> {
|
||||
|
||||
@Value("distance-function")
|
||||
@Default
|
||||
private DistanceSampler.@Meta DistanceFunction distanceFunction = DistanceFunction.Euclidean;
|
||||
|
||||
@Value("point.x")
|
||||
@Default
|
||||
private @Meta double x = 0;
|
||||
|
||||
@Value("point.y")
|
||||
@Default
|
||||
private @Meta double y = 0;
|
||||
|
||||
@Value("point.z")
|
||||
@Default
|
||||
private @Meta double z = 0;
|
||||
|
||||
@Value("normalize")
|
||||
@Default
|
||||
private @Meta boolean normalize = false;
|
||||
|
||||
@Value("radius")
|
||||
@Default
|
||||
private @Meta double normalizeRadius = 100;
|
||||
|
||||
@Override
|
||||
public DistanceSampler get() {
|
||||
return new DistanceSampler(distanceFunction, x, y, z, normalize, normalizeRadius);
|
||||
}
|
||||
}
|
||||
+9
-36
@@ -8,7 +8,6 @@
|
||||
package com.dfsek.terra.addons.noise.config.templates.noise;
|
||||
|
||||
import com.dfsek.paralithic.eval.tokenizer.ParseException;
|
||||
import com.dfsek.paralithic.functions.Function;
|
||||
import com.dfsek.tectonic.api.config.template.annotations.Default;
|
||||
import com.dfsek.tectonic.api.config.template.annotations.Value;
|
||||
|
||||
@@ -19,17 +18,16 @@ import java.util.Map;
|
||||
import com.dfsek.terra.addons.noise.config.DimensionApplicableNoiseSampler;
|
||||
import com.dfsek.terra.addons.noise.config.templates.FunctionTemplate;
|
||||
import com.dfsek.terra.addons.noise.config.templates.SamplerTemplate;
|
||||
import com.dfsek.terra.addons.noise.paralithic.defined.UserDefinedFunction;
|
||||
import com.dfsek.terra.addons.noise.paralithic.noise.NoiseFunction2;
|
||||
import com.dfsek.terra.addons.noise.paralithic.noise.NoiseFunction3;
|
||||
import com.dfsek.terra.addons.noise.samplers.noise.ExpressionFunction;
|
||||
import com.dfsek.terra.api.config.meta.Meta;
|
||||
import com.dfsek.terra.api.noise.NoiseSampler;
|
||||
|
||||
import static com.dfsek.terra.addons.noise.paralithic.FunctionUtil.convertFunctionsAndSamplers;
|
||||
|
||||
|
||||
@SuppressWarnings({ "FieldMayBeFinal", "unused" })
|
||||
public class ExpressionFunctionTemplate extends SamplerTemplate<ExpressionFunction> {
|
||||
private final Map<String, DimensionApplicableNoiseSampler> otherFunctions;
|
||||
private final Map<String, DimensionApplicableNoiseSampler> globalSamplers;
|
||||
private final Map<String, FunctionTemplate> globalFunctions;
|
||||
@Value("variables")
|
||||
@Default
|
||||
@@ -43,44 +41,19 @@ public class ExpressionFunctionTemplate extends SamplerTemplate<ExpressionFuncti
|
||||
@Default
|
||||
private @Meta LinkedHashMap<String, @Meta FunctionTemplate> functions = new LinkedHashMap<>();
|
||||
|
||||
public ExpressionFunctionTemplate(Map<String, DimensionApplicableNoiseSampler> otherFunctions, Map<String, FunctionTemplate> samplers) {
|
||||
this.otherFunctions = otherFunctions;
|
||||
this.globalFunctions = samplers;
|
||||
public ExpressionFunctionTemplate(Map<String, DimensionApplicableNoiseSampler> globalSamplers, Map<String, FunctionTemplate> globalFunctions) {
|
||||
this.globalSamplers = globalSamplers;
|
||||
this.globalFunctions = globalFunctions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NoiseSampler get() {
|
||||
var mergedFunctions = new HashMap<>(globalFunctions); mergedFunctions.putAll(functions);
|
||||
var mergedSamplers = new HashMap<>(globalSamplers); mergedSamplers.putAll(samplers);
|
||||
try {
|
||||
Map<String, Function> noiseFunctionMap = generateFunctions();
|
||||
return new ExpressionFunction(noiseFunctionMap, expression, vars);
|
||||
return new ExpressionFunction(convertFunctionsAndSamplers(mergedFunctions, mergedSamplers), expression, vars);
|
||||
} catch(ParseException e) {
|
||||
throw new RuntimeException("Failed to parse expression.", e);
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, Function> generateFunctions() throws ParseException {
|
||||
Map<String, Function> noiseFunctionMap = new HashMap<>();
|
||||
|
||||
for(Map.Entry<String, FunctionTemplate> entry : globalFunctions.entrySet()) {
|
||||
noiseFunctionMap.put(entry.getKey(), UserDefinedFunction.newInstance(entry.getValue()));
|
||||
}
|
||||
|
||||
for(Map.Entry<String, FunctionTemplate> entry : functions.entrySet()) {
|
||||
noiseFunctionMap.put(entry.getKey(), UserDefinedFunction.newInstance(entry.getValue()));
|
||||
}
|
||||
|
||||
otherFunctions.forEach((id, function) -> {
|
||||
if(function.getDimensions() == 2) {
|
||||
noiseFunctionMap.put(id, new NoiseFunction2(function.getSampler()));
|
||||
} else noiseFunctionMap.put(id, new NoiseFunction3(function.getSampler()));
|
||||
});
|
||||
|
||||
samplers.forEach((id, function) -> {
|
||||
if(function.getDimensions() == 2) {
|
||||
noiseFunctionMap.put(id, new NoiseFunction2(function.getSampler()));
|
||||
} else noiseFunctionMap.put(id, new NoiseFunction3(function.getSampler()));
|
||||
});
|
||||
|
||||
return noiseFunctionMap;
|
||||
}
|
||||
}
|
||||
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Polyhedral Development
|
||||
*
|
||||
* The Terra Core Addons are licensed under the terms of the MIT License. For more details,
|
||||
* reference the LICENSE file in this module's root directory.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.addons.noise.config.templates.normalizer;
|
||||
|
||||
import com.dfsek.paralithic.eval.tokenizer.ParseException;
|
||||
import com.dfsek.tectonic.api.config.template.annotations.Default;
|
||||
import com.dfsek.tectonic.api.config.template.annotations.Value;
|
||||
|
||||
import com.dfsek.terra.addons.noise.config.DimensionApplicableNoiseSampler;
|
||||
import com.dfsek.terra.addons.noise.config.templates.FunctionTemplate;
|
||||
import com.dfsek.terra.addons.noise.normalizer.ExpressionNormalizer;
|
||||
import com.dfsek.terra.api.config.meta.Meta;
|
||||
import com.dfsek.terra.api.noise.NoiseSampler;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.dfsek.terra.addons.noise.paralithic.FunctionUtil.convertFunctionsAndSamplers;
|
||||
|
||||
|
||||
@SuppressWarnings({ "unused", "FieldMayBeFinal" })
|
||||
public class ExpressionNormalizerTemplate extends NormalizerTemplate<ExpressionNormalizer> {
|
||||
|
||||
private final Map<String, DimensionApplicableNoiseSampler> globalSamplers;
|
||||
private final Map<String, FunctionTemplate> globalFunctions;
|
||||
|
||||
@Value("expression")
|
||||
private @Meta String expression;
|
||||
|
||||
@Value("variables")
|
||||
@Default
|
||||
private @Meta Map<String, @Meta Double> vars = new HashMap<>();
|
||||
|
||||
@Value("samplers")
|
||||
@Default
|
||||
private @Meta LinkedHashMap<String, @Meta DimensionApplicableNoiseSampler> samplers = new LinkedHashMap<>();
|
||||
|
||||
@Value("functions")
|
||||
@Default
|
||||
private @Meta LinkedHashMap<String, @Meta FunctionTemplate> functions = new LinkedHashMap<>();
|
||||
|
||||
public ExpressionNormalizerTemplate(Map<String, DimensionApplicableNoiseSampler> globalSamplers, Map<String, FunctionTemplate> globalFunctions) {
|
||||
this.globalSamplers = globalSamplers;
|
||||
this.globalFunctions = globalFunctions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NoiseSampler get() {
|
||||
var mergedFunctions = new HashMap<>(globalFunctions); mergedFunctions.putAll(functions);
|
||||
var mergedSamplers = new HashMap<>(globalSamplers); mergedSamplers.putAll(samplers);
|
||||
try {
|
||||
return new ExpressionNormalizer(function, convertFunctionsAndSamplers(mergedFunctions, mergedSamplers), expression, vars);
|
||||
} catch(ParseException e) {
|
||||
throw new RuntimeException("Failed to parse expression.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
package com.dfsek.terra.addons.noise.normalizer;
|
||||
|
||||
import com.dfsek.paralithic.Expression;
|
||||
import com.dfsek.paralithic.eval.parser.Parser;
|
||||
import com.dfsek.paralithic.eval.parser.Scope;
|
||||
import com.dfsek.paralithic.eval.tokenizer.ParseException;
|
||||
import com.dfsek.paralithic.functions.Function;
|
||||
|
||||
import com.dfsek.terra.api.noise.NoiseSampler;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
public class ExpressionNormalizer extends Normalizer {
|
||||
|
||||
private final Expression expression;
|
||||
|
||||
public ExpressionNormalizer(NoiseSampler sampler, Map<String, Function> functions, String eq, Map<String, Double> vars)
|
||||
throws ParseException {
|
||||
super(sampler);
|
||||
Parser p = new Parser();
|
||||
Scope scope = new Scope();
|
||||
scope.addInvocationVariable("in");
|
||||
vars.forEach(scope::create);
|
||||
functions.forEach(p::registerFunction);
|
||||
expression = p.parse(eq, scope);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double normalize(double in) {
|
||||
return expression.evaluate(in);
|
||||
}
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
package com.dfsek.terra.addons.noise.paralithic;
|
||||
|
||||
import com.dfsek.paralithic.eval.tokenizer.ParseException;
|
||||
import com.dfsek.paralithic.functions.Function;
|
||||
|
||||
import com.dfsek.terra.addons.noise.config.DimensionApplicableNoiseSampler;
|
||||
import com.dfsek.terra.addons.noise.config.templates.FunctionTemplate;
|
||||
import com.dfsek.terra.addons.noise.paralithic.defined.UserDefinedFunction;
|
||||
import com.dfsek.terra.addons.noise.paralithic.noise.NoiseFunction2;
|
||||
import com.dfsek.terra.addons.noise.paralithic.noise.NoiseFunction3;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
public class FunctionUtil {
|
||||
private FunctionUtil() {}
|
||||
|
||||
public static Map<String, Function> convertFunctionsAndSamplers(Map<String, FunctionTemplate> functions,
|
||||
Map<String, DimensionApplicableNoiseSampler> samplers) throws ParseException {
|
||||
Map<String, Function> functionMap = new HashMap<>();
|
||||
for(Map.Entry<String, FunctionTemplate> entry : functions.entrySet()) {
|
||||
functionMap.put(entry.getKey(), UserDefinedFunction.newInstance(entry.getValue()));
|
||||
}
|
||||
samplers.forEach((id, sampler) -> functionMap.put(id,
|
||||
sampler.getDimensions() == 2 ?
|
||||
new NoiseFunction2(sampler.getSampler()) :
|
||||
new NoiseFunction3(sampler.getSampler())));
|
||||
return functionMap;
|
||||
}
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
package com.dfsek.terra.addons.noise.samplers;
|
||||
|
||||
import com.dfsek.terra.api.noise.NoiseSampler;
|
||||
|
||||
|
||||
public class TranslateSampler implements NoiseSampler {
|
||||
|
||||
private final NoiseSampler sampler;
|
||||
private final double dx, dy, dz;
|
||||
|
||||
public TranslateSampler(NoiseSampler sampler, double dx, double dy, double dz) {
|
||||
this.sampler = sampler;
|
||||
this.dx = dx;
|
||||
this.dy = dy;
|
||||
this.dz = dz;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double noise(long seed, double x, double y) {
|
||||
return sampler.noise(seed, x - dx, y - dz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double noise(long seed, double x, double y, double z) {
|
||||
return sampler.noise(seed, x - dx, y - dy, z - dz);
|
||||
}
|
||||
}
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
package com.dfsek.terra.addons.noise.samplers.noise;
|
||||
|
||||
|
||||
public class DistanceSampler extends NoiseFunction {
|
||||
|
||||
private final DistanceFunction distanceFunction;
|
||||
private final double ox, oy, oz;
|
||||
private final boolean normalize;
|
||||
private final double radius;
|
||||
|
||||
private final double distanceAtRadius;
|
||||
|
||||
public DistanceSampler(DistanceFunction distanceFunction, double ox, double oy, double oz, boolean normalize, double radius) {
|
||||
frequency = 1;
|
||||
this.distanceFunction = distanceFunction;
|
||||
this.ox = ox;
|
||||
this.oy = oy;
|
||||
this.oz = oz;
|
||||
this.normalize = normalize;
|
||||
this.radius = radius;
|
||||
this.distanceAtRadius = distance2d(distanceFunction, radius, 0); // distance2d and distance3d should return the same value
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getNoiseRaw(long seed, double x, double y) {
|
||||
double dx = x - ox;
|
||||
double dy = y - oz;
|
||||
if (normalize && (fastAbs(dx) > radius || fastAbs(dy) > radius)) return 1;
|
||||
double dist = distance2d(distanceFunction, dx, dy);
|
||||
if (normalize) return fastMin(((2*dist)/distanceAtRadius)-1, 1);
|
||||
return dist;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getNoiseRaw(long seed, double x, double y, double z) {
|
||||
double dx = x - ox;
|
||||
double dy = y - oy;
|
||||
double dz = z - oz;
|
||||
if(normalize && (fastAbs(dx) > radius || fastAbs(dy) > radius || fastAbs(dz) > radius)) return 1;
|
||||
double dist = distance3d(distanceFunction, dx, dy, dz);
|
||||
if (normalize) return fastMin(((2*dist)/distanceAtRadius)-1, 1);
|
||||
return dist;
|
||||
}
|
||||
|
||||
private static double distance2d(DistanceFunction distanceFunction, double x, double z) {
|
||||
return switch(distanceFunction) {
|
||||
case Euclidean -> fastSqrt(x*x + z*z);
|
||||
case EuclideanSq -> x*x + z*z;
|
||||
case Manhattan -> fastAbs(x) + fastAbs(z);
|
||||
};
|
||||
}
|
||||
|
||||
private static double distance3d(DistanceFunction distanceFunction, double x, double y, double z) {
|
||||
return switch(distanceFunction) {
|
||||
case Euclidean -> fastSqrt(x*x + y*y + z*z);
|
||||
case EuclideanSq -> x*x + y*y + z*z;
|
||||
case Manhattan -> fastAbs(x) + fastAbs(y) + fastAbs(z);
|
||||
};
|
||||
}
|
||||
|
||||
public enum DistanceFunction {
|
||||
Euclidean,
|
||||
EuclideanSq,
|
||||
Manhattan
|
||||
}
|
||||
}
|
||||
+24
-2
@@ -17,10 +17,17 @@
|
||||
|
||||
package com.dfsek.terra.config.loaders;
|
||||
|
||||
import com.dfsek.tectonic.api.config.template.annotations.Value;
|
||||
import com.dfsek.tectonic.api.config.template.object.ObjectTemplate;
|
||||
import com.dfsek.tectonic.api.depth.DepthTracker;
|
||||
import com.dfsek.tectonic.api.exception.LoadException;
|
||||
import com.dfsek.tectonic.api.loader.ConfigLoader;
|
||||
import com.dfsek.tectonic.api.loader.type.TypeLoader;
|
||||
|
||||
import com.dfsek.tectonic.impl.MapConfiguration;
|
||||
|
||||
import com.dfsek.terra.api.config.meta.Meta;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.reflect.AnnotatedType;
|
||||
@@ -36,11 +43,26 @@ public class RangeLoader implements TypeLoader<Range> {
|
||||
public Range load(@NotNull AnnotatedType type, @NotNull Object o, @NotNull ConfigLoader configLoader, DepthTracker depthTracker)
|
||||
throws LoadException {
|
||||
if(o instanceof Map) {
|
||||
Map<String, Integer> map = (Map<String, Integer>) o;
|
||||
return new ConstantRange(map.get("min"), map.get("max"));
|
||||
return configLoader.load(new RangeMapTemplate(), new MapConfiguration((Map<String, Object>) o), depthTracker).get();
|
||||
} else {
|
||||
int h = configLoader.loadType(Integer.class, o, depthTracker);
|
||||
return new ConstantRange(h, h + 1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Template needed so keys can be meta annotated, otherwise the loader could just grab keys directly from the object
|
||||
*/
|
||||
public static class RangeMapTemplate implements ObjectTemplate<Range> {
|
||||
@Value("min")
|
||||
private @Meta int min;
|
||||
|
||||
@Value("max")
|
||||
private @Meta int max;
|
||||
|
||||
@Override
|
||||
public Range get() {
|
||||
return new ConstantRange(min, max);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -68,7 +68,7 @@ public class MetaListLikePreprocessor extends MetaPreprocessor<Meta> {
|
||||
|
||||
if(!(metaValue instanceof List)) {
|
||||
throw new LoadException(
|
||||
"MetaList/Set injection candidate must be list, is type " + metaValue.getClass().getCanonicalName(),
|
||||
"Meta list / set injection (via <<) must point to a list. '" + meta + "' points to type " + metaValue.getClass().getCanonicalName(),
|
||||
depthTracker);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,5 +8,4 @@ terra.license=MIT
|
||||
# Gradle options
|
||||
org.gradle.jvmargs=-Xmx4096M -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -XX:+UseParallelGC
|
||||
org.gradle.warning.mode=all
|
||||
#org.gradle.parallel=true
|
||||
|
||||
|
||||
@@ -12,12 +12,12 @@ dependencies {
|
||||
shaded(project(":platforms:bukkit:nms:v1_19_R1", configuration = "reobf"))
|
||||
shaded(project(":platforms:bukkit:nms:v1_19_R2", configuration = "reobf"))
|
||||
shaded(project(":platforms:bukkit:nms:v1_19_R3", configuration = "reobf"))
|
||||
shaded(project(":platforms:bukkit:nms:v1_20_R1", configuration = "reobf"))
|
||||
shaded("xyz.jpenilla", "reflection-remapper", Versions.Bukkit.reflectionRemapper)
|
||||
}
|
||||
|
||||
tasks {
|
||||
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")
|
||||
relocate("org.apache.logging.slf4j", "com.dfsek.terra.lib.slf4j-over-log4j")
|
||||
|
||||
@@ -6,7 +6,7 @@ repositories {
|
||||
|
||||
dependencies {
|
||||
api(project(":platforms:bukkit:common"))
|
||||
paperDevBundle(Versions.Bukkit.paperDevBundle)
|
||||
paperDevBundle("1.19.4-R0.1-SNAPSHOT")
|
||||
implementation("xyz.jpenilla", "reflection-remapper", "0.1.0-SNAPSHOT")
|
||||
}
|
||||
|
||||
|
||||
+2
-5
@@ -10,6 +10,7 @@ import net.minecraft.world.level.StructureManager;
|
||||
import net.minecraft.world.level.WorldGenLevel;
|
||||
import net.minecraft.world.level.biome.BiomeManager;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import net.minecraft.world.level.chunk.ChunkGenerator;
|
||||
import net.minecraft.world.level.levelgen.Beardifier;
|
||||
@@ -152,18 +153,14 @@ public class NMSChunkGeneratorDelegate extends ChunkGenerator {
|
||||
|
||||
@Override
|
||||
public @NotNull NoiseColumn getBaseColumn(int x, int z, @NotNull LevelHeightAccessor world, @NotNull RandomState noiseConfig) {
|
||||
/*
|
||||
BlockState[] array = new BlockState[world.getHeight()];
|
||||
WorldProperties properties = new NMSWorldProperties(seed, world);
|
||||
BiomeProvider biomeProvider = pack.getBiomeProvider().caching(properties);
|
||||
BiomeProvider biomeProvider = pack.getBiomeProvider();
|
||||
for(int y = properties.getMaxHeight() - 1; y >= properties.getMinHeight(); y--) {
|
||||
array[y - properties.getMinHeight()] = ((CraftBlockData) delegate.getBlock(properties, x, y, z, biomeProvider)
|
||||
.getHandle()).getState();
|
||||
}
|
||||
return new NoiseColumn(getMinY(), array);
|
||||
|
||||
*/
|
||||
return vanilla.getBaseColumn(x, z, world, noiseConfig);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
apply(plugin = "io.papermc.paperweight.userdev")
|
||||
|
||||
repositories {
|
||||
maven("https://s01.oss.sonatype.org/content/repositories/snapshots/")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api(project(":platforms:bukkit:common"))
|
||||
paperDevBundle(Versions.Bukkit.paperDevBundle)
|
||||
implementation("xyz.jpenilla", "reflection-remapper", "0.1.0-SNAPSHOT")
|
||||
}
|
||||
|
||||
tasks {
|
||||
assemble {
|
||||
dependsOn("reobfJar")
|
||||
}
|
||||
}
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_20_R1;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.mojang.serialization.Lifecycle;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.Holder.Reference;
|
||||
import net.minecraft.core.MappedRegistry;
|
||||
import net.minecraft.core.WritableRegistry;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import com.dfsek.terra.bukkit.world.BukkitPlatformBiome;
|
||||
import com.dfsek.terra.registry.master.ConfigRegistry;
|
||||
|
||||
|
||||
public class AwfulBukkitHacks {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(AwfulBukkitHacks.class);
|
||||
|
||||
private static final Map<ResourceLocation, List<ResourceLocation>> terraBiomeMap = new HashMap<>();
|
||||
|
||||
public static void registerBiomes(ConfigRegistry configRegistry) {
|
||||
try {
|
||||
LOGGER.info("Hacking biome registry...");
|
||||
WritableRegistry<Biome> biomeRegistry = (WritableRegistry<Biome>) RegistryFetcher.biomeRegistry();
|
||||
|
||||
Reflection.MAPPED_REGISTRY.setFrozen((MappedRegistry<?>) biomeRegistry, false);
|
||||
|
||||
configRegistry.forEach(pack -> pack.getRegistry(com.dfsek.terra.api.world.biome.Biome.class).forEach((key, biome) -> {
|
||||
try {
|
||||
BukkitPlatformBiome platformBiome = (BukkitPlatformBiome) biome.getPlatformBiome();
|
||||
NamespacedKey vanillaBukkitKey = platformBiome.getHandle().getKey();
|
||||
ResourceLocation vanillaMinecraftKey = new ResourceLocation(vanillaBukkitKey.getNamespace(), vanillaBukkitKey.getKey());
|
||||
Biome platform = NMSBiomeInjector.createBiome(biome, Objects.requireNonNull(biomeRegistry.get(vanillaMinecraftKey)));
|
||||
|
||||
ResourceKey<Biome> delegateKey = ResourceKey.create(
|
||||
Registries.BIOME,
|
||||
new ResourceLocation("terra", NMSBiomeInjector.createBiomeID(pack, key))
|
||||
);
|
||||
|
||||
Reference<Biome> holder = biomeRegistry.register(delegateKey, platform, Lifecycle.stable());
|
||||
Reflection.REFERENCE.invokeBindValue(holder, platform); // IMPORTANT: bind holder.
|
||||
|
||||
platformBiome.getContext().put(new NMSBiomeInfo(delegateKey));
|
||||
|
||||
terraBiomeMap.computeIfAbsent(vanillaMinecraftKey, i -> new ArrayList<>()).add(delegateKey.location());
|
||||
|
||||
LOGGER.debug("Registered biome: " + delegateKey);
|
||||
} catch(NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}));
|
||||
|
||||
Reflection.MAPPED_REGISTRY.setFrozen((MappedRegistry<?>) biomeRegistry, true); // freeze registry again :)
|
||||
|
||||
LOGGER.info("Doing tag garbage....");
|
||||
Map<TagKey<Biome>, List<Holder<Biome>>> collect = biomeRegistry
|
||||
.getTags() // streamKeysAndEntries
|
||||
.collect(HashMap::new,
|
||||
(map, pair) ->
|
||||
map.put(pair.getFirst(), new ArrayList<>(pair.getSecond().stream().toList())),
|
||||
HashMap::putAll);
|
||||
|
||||
terraBiomeMap
|
||||
.forEach((vb, terraBiomes) ->
|
||||
NMSBiomeInjector.getEntry(biomeRegistry, vb).ifPresentOrElse(
|
||||
vanilla -> terraBiomes.forEach(
|
||||
tb -> NMSBiomeInjector.getEntry(biomeRegistry, tb).ifPresentOrElse(
|
||||
terra -> {
|
||||
LOGGER.debug("{} (vanilla for {}): {}",
|
||||
vanilla.unwrapKey().orElseThrow().location(),
|
||||
terra.unwrapKey().orElseThrow().location(),
|
||||
vanilla.tags().toList());
|
||||
vanilla.tags()
|
||||
.forEach(tag -> collect
|
||||
.computeIfAbsent(tag, t -> new ArrayList<>())
|
||||
.add(terra));
|
||||
},
|
||||
() -> LOGGER.error("No such biome: {}", tb))),
|
||||
() -> LOGGER.error("No vanilla biome: {}", vb)));
|
||||
|
||||
biomeRegistry.resetTags();
|
||||
biomeRegistry.bindTags(ImmutableMap.copyOf(collect));
|
||||
|
||||
} catch(SecurityException | IllegalArgumentException exception) {
|
||||
throw new RuntimeException(exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_20_R1;
|
||||
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
|
||||
import com.dfsek.terra.api.properties.Properties;
|
||||
|
||||
|
||||
public record NMSBiomeInfo(ResourceKey<Biome> biomeKey) implements Properties {
|
||||
}
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_20_R1;
|
||||
|
||||
import net.minecraft.core.Holder;
|
||||
import java.util.stream.Stream;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.biome.BiomeSpecialEffects;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
|
||||
import com.dfsek.terra.api.config.ConfigPack;
|
||||
import com.dfsek.terra.bukkit.config.VanillaBiomeProperties;
|
||||
|
||||
import static net.minecraft.world.level.biome.Biome.ClimateSettings;
|
||||
import static net.minecraft.world.level.biome.Biome.Precipitation;
|
||||
|
||||
public class NMSBiomeInjector {
|
||||
|
||||
public static <T> Optional<Holder<T>> getEntry(Registry<T> registry, ResourceLocation identifier) {
|
||||
return registry.getOptional(identifier)
|
||||
.flatMap(registry::getResourceKey)
|
||||
.flatMap(registry::getHolder);
|
||||
}
|
||||
|
||||
public static Biome createBiome(com.dfsek.terra.api.world.biome.Biome biome, Biome vanilla)
|
||||
throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
|
||||
Biome.BiomeBuilder builder = new Biome.BiomeBuilder();
|
||||
|
||||
builder
|
||||
.downfall(vanilla.climateSettings.downfall())
|
||||
.temperature(vanilla.getBaseTemperature())
|
||||
.mobSpawnSettings(vanilla.getMobSettings())
|
||||
.generationSettings(vanilla.getGenerationSettings());
|
||||
|
||||
|
||||
BiomeSpecialEffects.Builder effects = new BiomeSpecialEffects.Builder();
|
||||
|
||||
effects.grassColorModifier(vanilla.getSpecialEffects().getGrassColorModifier());
|
||||
|
||||
VanillaBiomeProperties vanillaBiomeProperties = biome.getContext().get(VanillaBiomeProperties.class);
|
||||
|
||||
effects.fogColor(Objects.requireNonNullElse(vanillaBiomeProperties.getFogColor(), vanilla.getFogColor()))
|
||||
|
||||
.waterColor(Objects.requireNonNullElse(vanillaBiomeProperties.getWaterColor(), vanilla.getWaterColor()))
|
||||
|
||||
.waterFogColor(Objects.requireNonNullElse(vanillaBiomeProperties.getWaterFogColor(), vanilla.getWaterFogColor()))
|
||||
|
||||
.skyColor(Objects.requireNonNullElse(vanillaBiomeProperties.getSkyColor(), vanilla.getSkyColor()));
|
||||
|
||||
if(vanillaBiomeProperties.getFoliageColor() == null) {
|
||||
vanilla.getSpecialEffects().getFoliageColorOverride().ifPresent(effects::foliageColorOverride);
|
||||
} else {
|
||||
effects.foliageColorOverride(vanillaBiomeProperties.getFoliageColor());
|
||||
}
|
||||
|
||||
if(vanillaBiomeProperties.getGrassColor() == null) {
|
||||
vanilla.getSpecialEffects().getGrassColorOverride().ifPresent(effects::grassColorOverride);
|
||||
} else {
|
||||
// grass
|
||||
effects.grassColorOverride(vanillaBiomeProperties.getGrassColor());
|
||||
}
|
||||
|
||||
vanilla.getAmbientLoop().ifPresent(effects::ambientLoopSound);
|
||||
vanilla.getAmbientAdditions().ifPresent(effects::ambientAdditionsSound);
|
||||
vanilla.getAmbientMood().ifPresent(effects::ambientMoodSound);
|
||||
vanilla.getBackgroundMusic().ifPresent(effects::backgroundMusic);
|
||||
vanilla.getAmbientParticle().ifPresent(effects::ambientParticle);
|
||||
|
||||
builder.specialEffects(effects.build());
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
public static String createBiomeID(ConfigPack pack, com.dfsek.terra.api.registry.key.RegistryKey biomeID) {
|
||||
return pack.getID()
|
||||
.toLowerCase() + "/" + biomeID.getNamespace().toLowerCase(Locale.ROOT) + "/" + biomeID.getID().toLowerCase(Locale.ROOT);
|
||||
}
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_20_R1;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import net.minecraft.core.Holder;
|
||||
import java.util.stream.Stream;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.biome.BiomeSource;
|
||||
import net.minecraft.world.level.biome.Climate.Sampler;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
|
||||
import com.dfsek.terra.bukkit.world.BukkitPlatformBiome;
|
||||
|
||||
|
||||
public class NMSBiomeProvider extends BiomeSource {
|
||||
private final BiomeProvider delegate;
|
||||
private final long seed;
|
||||
private final Registry<Biome> biomeRegistry = RegistryFetcher.biomeRegistry();
|
||||
|
||||
public NMSBiomeProvider(BiomeProvider delegate, long seed) {
|
||||
super();
|
||||
this.delegate = delegate;
|
||||
this.seed = seed;
|
||||
}
|
||||
@Override
|
||||
protected Stream<Holder<Biome>> collectPossibleBiomes() {
|
||||
return delegate.stream()
|
||||
.map(biome -> RegistryFetcher.biomeRegistry()
|
||||
.getHolderOrThrow(((BukkitPlatformBiome) biome.getPlatformBiome()).getContext()
|
||||
.get(NMSBiomeInfo.class)
|
||||
.biomeKey()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull Codec<? extends BiomeSource> codec() {
|
||||
return BiomeSource.CODEC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Holder<Biome> getNoiseBiome(int x, int y, int z, @NotNull Sampler sampler) {
|
||||
return biomeRegistry.getHolderOrThrow(((BukkitPlatformBiome) delegate.getBiome(x << 2, y << 2, z << 2, seed)
|
||||
.getPlatformBiome()).getContext()
|
||||
.get(NMSBiomeInfo.class)
|
||||
.biomeKey());
|
||||
}
|
||||
}
|
||||
+170
@@ -0,0 +1,170 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_20_R1;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.server.level.WorldGenRegion;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.world.level.LevelHeightAccessor;
|
||||
import net.minecraft.world.level.NoiseColumn;
|
||||
import net.minecraft.world.level.StructureManager;
|
||||
import net.minecraft.world.level.WorldGenLevel;
|
||||
import net.minecraft.world.level.biome.BiomeManager;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import net.minecraft.world.level.chunk.ChunkGenerator;
|
||||
import net.minecraft.world.level.levelgen.Beardifier;
|
||||
import net.minecraft.world.level.levelgen.DensityFunction.SinglePointContext;
|
||||
import net.minecraft.world.level.levelgen.GenerationStep.Carving;
|
||||
import net.minecraft.world.level.levelgen.Heightmap.Types;
|
||||
import net.minecraft.world.level.levelgen.RandomState;
|
||||
import net.minecraft.world.level.levelgen.blending.Blender;
|
||||
import org.bukkit.craftbukkit.v1_20_R1.block.data.CraftBlockData;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import com.dfsek.terra.api.config.ConfigPack;
|
||||
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
|
||||
import com.dfsek.terra.api.world.info.WorldProperties;
|
||||
import com.dfsek.terra.bukkit.config.PreLoadCompatibilityOptions;
|
||||
import com.dfsek.terra.bukkit.world.BukkitWorldProperties;
|
||||
import com.dfsek.terra.bukkit.world.block.data.BukkitBlockState;
|
||||
|
||||
|
||||
public class NMSChunkGeneratorDelegate extends ChunkGenerator {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(NMSChunkGeneratorDelegate.class);
|
||||
private final com.dfsek.terra.api.world.chunk.generation.ChunkGenerator delegate;
|
||||
|
||||
private final ChunkGenerator vanilla;
|
||||
private final ConfigPack pack;
|
||||
|
||||
private final long seed;
|
||||
|
||||
public NMSChunkGeneratorDelegate(ChunkGenerator vanilla, ConfigPack pack, NMSBiomeProvider biomeProvider, long seed) {
|
||||
super(biomeProvider);
|
||||
this.delegate = pack.getGeneratorProvider().newInstance(pack);
|
||||
this.vanilla = vanilla;
|
||||
this.pack = pack;
|
||||
this.seed = seed;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull Codec<? extends ChunkGenerator> codec() {
|
||||
return ChunkGenerator.CODEC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyCarvers(@NotNull WorldGenRegion chunkRegion, long seed, @NotNull RandomState noiseConfig, @NotNull BiomeManager world,
|
||||
@NotNull StructureManager structureAccessor, @NotNull ChunkAccess chunk, @NotNull Carving carverStep) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildSurface(@NotNull WorldGenRegion region, @NotNull StructureManager structures, @NotNull RandomState noiseConfig,
|
||||
@NotNull ChunkAccess chunk) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyBiomeDecoration(@NotNull WorldGenLevel world, @NotNull ChunkAccess chunk,
|
||||
@NotNull StructureManager structureAccessor) {
|
||||
vanilla.applyBiomeDecoration(world, chunk, structureAccessor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void spawnOriginalMobs(@NotNull WorldGenRegion region) {
|
||||
vanilla.spawnOriginalMobs(region);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getGenDepth() {
|
||||
return vanilla.getGenDepth();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull CompletableFuture<ChunkAccess> fillFromNoise(@NotNull Executor executor, @NotNull Blender blender,
|
||||
@NotNull RandomState noiseConfig,
|
||||
@NotNull StructureManager structureAccessor, @NotNull ChunkAccess chunk) {
|
||||
return vanilla.fillFromNoise(executor, blender, noiseConfig, structureAccessor, chunk)
|
||||
.thenApply(c -> {
|
||||
LevelAccessor level = Reflection.STRUCTURE_MANAGER.getLevel(structureAccessor);
|
||||
BiomeProvider biomeProvider = pack.getBiomeProvider();
|
||||
PreLoadCompatibilityOptions compatibilityOptions = pack.getContext().get(PreLoadCompatibilityOptions.class);
|
||||
if(compatibilityOptions.isBeard()) {
|
||||
beard(structureAccessor, chunk, new BukkitWorldProperties(level.getMinecraftWorld().getWorld()), biomeProvider, compatibilityOptions);
|
||||
}
|
||||
return c;
|
||||
});
|
||||
}
|
||||
|
||||
private void beard(StructureManager structureAccessor, ChunkAccess chunk, WorldProperties world, BiomeProvider biomeProvider,
|
||||
PreLoadCompatibilityOptions compatibilityOptions) {
|
||||
Beardifier structureWeightSampler = Beardifier.forStructuresInChunk(structureAccessor, chunk.getPos());
|
||||
double threshold = compatibilityOptions.getBeardThreshold();
|
||||
double airThreshold = compatibilityOptions.getAirThreshold();
|
||||
int xi = chunk.getPos().x << 4;
|
||||
int zi = chunk.getPos().z << 4;
|
||||
for(int x = 0; x < 16; x++) {
|
||||
for(int z = 0; z < 16; z++) {
|
||||
int depth = 0;
|
||||
for(int y = world.getMaxHeight(); y >= world.getMinHeight(); y--) {
|
||||
double noise = structureWeightSampler.compute(new SinglePointContext(x + xi, y, z + zi));
|
||||
if(noise > threshold) {
|
||||
chunk.setBlockState(new BlockPos(x, y, z), ((CraftBlockData) ((BukkitBlockState) delegate
|
||||
.getPalette(x + xi, y, z + zi, world, biomeProvider)
|
||||
.get(depth, x + xi, y, z + zi, world.getSeed())).getHandle()).getState(), false);
|
||||
depth++;
|
||||
} else if(noise < airThreshold) {
|
||||
chunk.setBlockState(new BlockPos(x, y, z), Blocks.AIR.defaultBlockState(), false);
|
||||
} else {
|
||||
depth = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSeaLevel() {
|
||||
return vanilla.getSeaLevel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinY() {
|
||||
return vanilla.getMinY();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBaseHeight(int x, int z, @NotNull Types heightmap, @NotNull LevelHeightAccessor world, @NotNull RandomState noiseConfig) {
|
||||
WorldProperties properties = new NMSWorldProperties(seed, world);
|
||||
int y = properties.getMaxHeight();
|
||||
BiomeProvider biomeProvider = pack.getBiomeProvider();
|
||||
while(y >= getMinY() && !heightmap.isOpaque().test(
|
||||
((CraftBlockData) delegate.getBlock(properties, x, y - 1, z, biomeProvider).getHandle()).getState())) {
|
||||
y--;
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull NoiseColumn getBaseColumn(int x, int z, @NotNull LevelHeightAccessor world, @NotNull RandomState noiseConfig) {
|
||||
BlockState[] array = new BlockState[world.getHeight()];
|
||||
WorldProperties properties = new NMSWorldProperties(seed, world);
|
||||
BiomeProvider biomeProvider = pack.getBiomeProvider();
|
||||
for(int y = properties.getMaxHeight() - 1; y >= properties.getMinHeight(); y--) {
|
||||
array[y - properties.getMinHeight()] = ((CraftBlockData) delegate.getBlock(properties, x, y, z, biomeProvider)
|
||||
.getHandle()).getState();
|
||||
}
|
||||
return new NoiseColumn(getMinY(), array);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDebugScreenInfo(@NotNull List<String> text, @NotNull RandomState noiseConfig, @NotNull BlockPos pos) {
|
||||
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_20_R1;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
import com.dfsek.terra.bukkit.PlatformImpl;
|
||||
import com.dfsek.terra.bukkit.nms.Initializer;
|
||||
|
||||
|
||||
public class NMSInitializer implements Initializer {
|
||||
@Override
|
||||
public void initialize(PlatformImpl platform) {
|
||||
AwfulBukkitHacks.registerBiomes(platform.getRawConfigRegistry());
|
||||
Bukkit.getPluginManager().registerEvents(new NMSInjectListener(), platform.getPlugin());
|
||||
}
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_20_R1;
|
||||
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.level.chunk.ChunkGenerator;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.craftbukkit.v1_20_R1.CraftWorld;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.world.WorldInitEvent;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import com.dfsek.terra.api.config.ConfigPack;
|
||||
import com.dfsek.terra.bukkit.generator.BukkitChunkGeneratorWrapper;
|
||||
|
||||
|
||||
public class NMSInjectListener implements Listener {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(NMSInjectListener.class);
|
||||
private static final Set<World> INJECTED = new HashSet<>();
|
||||
private static final ReentrantLock INJECT_LOCK = new ReentrantLock();
|
||||
|
||||
@EventHandler
|
||||
public void onWorldInit(WorldInitEvent event) {
|
||||
if(!INJECTED.contains(event.getWorld()) &&
|
||||
event.getWorld().getGenerator() instanceof BukkitChunkGeneratorWrapper bukkitChunkGeneratorWrapper) {
|
||||
INJECT_LOCK.lock();
|
||||
INJECTED.add(event.getWorld());
|
||||
LOGGER.info("Preparing to take over the world: {}", event.getWorld().getName());
|
||||
CraftWorld craftWorld = (CraftWorld) event.getWorld();
|
||||
ServerLevel serverWorld = craftWorld.getHandle();
|
||||
|
||||
ConfigPack pack = bukkitChunkGeneratorWrapper.getPack();
|
||||
|
||||
ChunkGenerator vanilla = serverWorld.getChunkSource().getGenerator();
|
||||
NMSBiomeProvider provider = new NMSBiomeProvider(pack.getBiomeProvider(), craftWorld.getSeed());
|
||||
|
||||
serverWorld.getChunkSource().chunkMap.generator = new NMSChunkGeneratorDelegate(vanilla, pack, provider, craftWorld.getSeed());
|
||||
|
||||
LOGGER.info("Successfully injected into world.");
|
||||
|
||||
INJECT_LOCK.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_20_R1;
|
||||
|
||||
import net.minecraft.world.level.LevelHeightAccessor;
|
||||
|
||||
import com.dfsek.terra.api.world.info.WorldProperties;
|
||||
|
||||
|
||||
public class NMSWorldProperties implements WorldProperties {
|
||||
private final long seed;
|
||||
private final LevelHeightAccessor height;
|
||||
|
||||
public NMSWorldProperties(long seed, LevelHeightAccessor height) {
|
||||
this.seed = seed;
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getHandle() {
|
||||
return height;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSeed() {
|
||||
return seed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxHeight() {
|
||||
return height.getMaxBuildHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinHeight() {
|
||||
return height.getMinBuildHeight();
|
||||
}
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_20_R1;
|
||||
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.Holder.Reference;
|
||||
import net.minecraft.core.MappedRegistry;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.world.level.StructureManager;
|
||||
import xyz.jpenilla.reflectionremapper.ReflectionRemapper;
|
||||
import xyz.jpenilla.reflectionremapper.proxy.ReflectionProxyFactory;
|
||||
import xyz.jpenilla.reflectionremapper.proxy.annotation.FieldGetter;
|
||||
import xyz.jpenilla.reflectionremapper.proxy.annotation.FieldSetter;
|
||||
import xyz.jpenilla.reflectionremapper.proxy.annotation.MethodName;
|
||||
import xyz.jpenilla.reflectionremapper.proxy.annotation.Proxies;
|
||||
|
||||
|
||||
public class Reflection {
|
||||
public static final MappedRegistryProxy MAPPED_REGISTRY;
|
||||
public static final StructureManagerProxy STRUCTURE_MANAGER;
|
||||
|
||||
public static final ReferenceProxy REFERENCE;
|
||||
|
||||
static {
|
||||
ReflectionRemapper reflectionRemapper = ReflectionRemapper.forReobfMappingsInPaperJar();
|
||||
ReflectionProxyFactory reflectionProxyFactory = ReflectionProxyFactory.create(reflectionRemapper,
|
||||
Reflection.class.getClassLoader());
|
||||
|
||||
MAPPED_REGISTRY = reflectionProxyFactory.reflectionProxy(MappedRegistryProxy.class);
|
||||
STRUCTURE_MANAGER = reflectionProxyFactory.reflectionProxy(StructureManagerProxy.class);
|
||||
REFERENCE = reflectionProxyFactory.reflectionProxy(ReferenceProxy.class);
|
||||
}
|
||||
|
||||
|
||||
@Proxies(MappedRegistry.class)
|
||||
public interface MappedRegistryProxy {
|
||||
@FieldSetter("frozen")
|
||||
void setFrozen(MappedRegistry<?> instance, boolean frozen);
|
||||
}
|
||||
|
||||
@Proxies(StructureManager.class)
|
||||
public interface StructureManagerProxy {
|
||||
@FieldGetter("level")
|
||||
LevelAccessor getLevel(StructureManager instance);
|
||||
}
|
||||
|
||||
@Proxies(Holder.Reference.class)
|
||||
public interface ReferenceProxy {
|
||||
@MethodName("bindValue")
|
||||
<T> void invokeBindValue(Reference<T> instance, T value);
|
||||
}
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_20_R1;
|
||||
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.server.dedicated.DedicatedServer;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.craftbukkit.v1_20_R1.CraftServer;
|
||||
|
||||
|
||||
public class RegistryFetcher {
|
||||
private static <T> Registry<T> getRegistry(ResourceKey<Registry<T>> key) {
|
||||
CraftServer craftserver = (CraftServer) Bukkit.getServer();
|
||||
DedicatedServer dedicatedserver = craftserver.getServer();
|
||||
return dedicatedserver
|
||||
.registryAccess()
|
||||
.registryOrThrow(key);
|
||||
}
|
||||
|
||||
public static Registry<Biome> biomeRegistry() {
|
||||
return getRegistry(Registries.BIOME);
|
||||
}
|
||||
}
|
||||
@@ -17,35 +17,16 @@
|
||||
|
||||
package com.dfsek.terra.fabric;
|
||||
|
||||
import cloud.commandframework.execution.CommandExecutionCoordinator;
|
||||
import cloud.commandframework.fabric.FabricServerCommandManager;
|
||||
import net.fabricmc.api.ModInitializer;
|
||||
import net.minecraft.server.command.ServerCommandSource;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.dfsek.terra.api.command.CommandSender;
|
||||
import com.dfsek.terra.api.event.events.platform.CommandRegistrationEvent;
|
||||
import com.dfsek.terra.lifecycle.LifecycleEntryPoint;
|
||||
|
||||
|
||||
public class FabricEntryPoint implements ModInitializer {
|
||||
private static final Logger logger = LoggerFactory.getLogger(FabricEntryPoint.class);
|
||||
|
||||
public class FabricEntryPoint extends LifecycleEntryPoint implements ModInitializer {
|
||||
private static final FabricPlatform TERRA_PLUGIN = new FabricPlatform();
|
||||
|
||||
@Override
|
||||
public void onInitialize() {
|
||||
logger.info("Initializing Terra Fabric mod...");
|
||||
|
||||
FabricServerCommandManager<CommandSender> manager = new FabricServerCommandManager<>(
|
||||
CommandExecutionCoordinator.simpleCoordinator(),
|
||||
serverCommandSource -> (CommandSender) serverCommandSource,
|
||||
commandSender -> (ServerCommandSource) commandSender
|
||||
);
|
||||
|
||||
|
||||
manager.brigadierManager().setNativeNumberSuggestions(false);
|
||||
|
||||
TERRA_PLUGIN.getEventManager().callEvent(new CommandRegistrationEvent(manager));
|
||||
initialize("Fabric", TERRA_PLUGIN);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,43 +17,24 @@
|
||||
|
||||
package com.dfsek.terra.fabric;
|
||||
|
||||
import ca.solostudios.strata.Versions;
|
||||
import ca.solostudios.strata.parser.tokenizer.ParseException;
|
||||
import ca.solostudios.strata.version.Version;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collection;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import com.dfsek.terra.addon.EphemeralAddon;
|
||||
import com.dfsek.terra.api.addon.BaseAddon;
|
||||
import com.dfsek.terra.lifecycle.LifecyclePlatform;
|
||||
|
||||
|
||||
public class FabricPlatform extends LifecyclePlatform {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(FabricPlatform.class);
|
||||
|
||||
@Override
|
||||
protected Collection<BaseAddon> getPlatformMods() {
|
||||
return FabricLoader.getInstance().getAllMods().stream().flatMap(mod -> {
|
||||
String id = mod.getMetadata().getId();
|
||||
if(id.equals("terra") || id.equals("minecraft") || id.equals("java")) return Stream.empty();
|
||||
try {
|
||||
Version version = Versions.parseVersion(mod.getMetadata().getVersion().getFriendlyString());
|
||||
return Stream.<BaseAddon>of(new EphemeralAddon(version, "fabric:" + id));
|
||||
} catch(ParseException e) {
|
||||
LOGGER.warn(
|
||||
"Mod {}, version {} does not follow semantic versioning specification, Terra addons will be unable to depend on " +
|
||||
"it.",
|
||||
id, mod.getMetadata().getVersion().getFriendlyString());
|
||||
}
|
||||
return Stream.empty();
|
||||
}).collect(Collectors.toList());
|
||||
return FabricLoader.getInstance().getAllMods().stream().flatMap(
|
||||
mod -> parseModData(mod.getMetadata().getId(), mod.getMetadata().getVersion().getFriendlyString())).collect(
|
||||
Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -28,6 +28,6 @@
|
||||
"depends": {
|
||||
"fabricloader": ">=0.14.2",
|
||||
"java": ">=17",
|
||||
"minecraft": "1.19.x"
|
||||
"minecraft": "1.20.x"
|
||||
}
|
||||
}
|
||||
@@ -50,7 +50,6 @@ import com.dfsek.terra.mod.config.ProtoPlatformBiome;
|
||||
import com.dfsek.terra.mod.config.SoundEventTemplate;
|
||||
import com.dfsek.terra.mod.config.SpawnCostConfig;
|
||||
import com.dfsek.terra.mod.config.SpawnEntryTemplate;
|
||||
import com.dfsek.terra.mod.config.SpawnGroupTemplate;
|
||||
import com.dfsek.terra.mod.config.SpawnSettingsTemplate;
|
||||
import com.dfsek.terra.mod.config.SpawnTypeConfig;
|
||||
import com.dfsek.terra.mod.config.VillagerTypeTemplate;
|
||||
@@ -88,6 +87,7 @@ public abstract class ModPlatform extends AbstractPlatform {
|
||||
.registerLoader(GrassColorModifier.class,
|
||||
(type, o, loader, depthTracker) -> TemperatureModifier.valueOf(((String) o).toUpperCase(
|
||||
Locale.ROOT)))
|
||||
.registerLoader(SpawnGroup.class,(type, o, loader, depthTracker) -> SpawnGroup.valueOf((String) o))
|
||||
.registerLoader(BiomeParticleConfig.class, BiomeParticleConfigTemplate::new)
|
||||
.registerLoader(SoundEvent.class, SoundEventTemplate::new)
|
||||
.registerLoader(BiomeMoodSound.class, BiomeMoodSoundTemplate::new)
|
||||
@@ -96,7 +96,6 @@ public abstract class ModPlatform extends AbstractPlatform {
|
||||
.registerLoader(EntityType.class, EntityTypeTemplate::new)
|
||||
.registerLoader(SpawnCostConfig.class, SpawnCostConfig::new)
|
||||
.registerLoader(SpawnEntry.class, SpawnEntryTemplate::new)
|
||||
.registerLoader(SpawnGroup.class, SpawnGroupTemplate::new)
|
||||
.registerLoader(SpawnTypeConfig.class, SpawnTypeConfig::new)
|
||||
.registerLoader(SpawnSettings.class, SpawnSettingsTemplate::new)
|
||||
.registerLoader(VillagerType.class, VillagerTypeTemplate::new);
|
||||
|
||||
+7
-8
@@ -3,6 +3,9 @@ package com.dfsek.terra.mod.config;
|
||||
import com.dfsek.tectonic.api.config.template.annotations.Default;
|
||||
import com.dfsek.tectonic.api.config.template.annotations.Value;
|
||||
import com.dfsek.tectonic.api.config.template.object.ObjectTemplate;
|
||||
|
||||
import com.dfsek.terra.api.util.Range;
|
||||
|
||||
import net.minecraft.registry.Registries;
|
||||
import net.minecraft.sound.MusicSound;
|
||||
import net.minecraft.sound.SoundEvent;
|
||||
@@ -13,13 +16,9 @@ public class MusicSoundTemplate implements ObjectTemplate<MusicSound> {
|
||||
@Default
|
||||
private SoundEvent sound = null;
|
||||
|
||||
@Value("min-delay")
|
||||
@Value("delay")
|
||||
@Default
|
||||
private Integer minDelay = null;
|
||||
|
||||
@Value("max-delay")
|
||||
@Default
|
||||
private Integer maxDelay = null;
|
||||
private Range delay = null;
|
||||
|
||||
@Value("replace-current-music")
|
||||
@Default
|
||||
@@ -27,10 +26,10 @@ public class MusicSoundTemplate implements ObjectTemplate<MusicSound> {
|
||||
|
||||
@Override
|
||||
public MusicSound get() {
|
||||
if(sound == null || minDelay == null || maxDelay == null || replaceCurrentMusic == null) {
|
||||
if(sound == null || delay == null || replaceCurrentMusic == null) {
|
||||
return null;
|
||||
} else {
|
||||
return new MusicSound(Registries.SOUND_EVENT.getEntry(sound), minDelay, maxDelay, replaceCurrentMusic);
|
||||
return new MusicSound(Registries.SOUND_EVENT.getEntry(sound), delay.getMin(), delay.getMax(), replaceCurrentMusic);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+6
-7
@@ -3,6 +3,9 @@ package com.dfsek.terra.mod.config;
|
||||
import com.dfsek.tectonic.api.config.template.annotations.Default;
|
||||
import com.dfsek.tectonic.api.config.template.annotations.Value;
|
||||
import com.dfsek.tectonic.api.config.template.object.ObjectTemplate;
|
||||
|
||||
import com.dfsek.terra.api.util.Range;
|
||||
|
||||
import net.minecraft.entity.EntityType;
|
||||
import net.minecraft.world.biome.SpawnSettings.SpawnEntry;
|
||||
|
||||
@@ -16,16 +19,12 @@ public class SpawnEntryTemplate implements ObjectTemplate<SpawnEntry> {
|
||||
@Default
|
||||
private Integer weight = null;
|
||||
|
||||
@Value("min-group-size")
|
||||
@Value("group-size")
|
||||
@Default
|
||||
private Integer minGroupSize = null;
|
||||
|
||||
@Value("max-group-size")
|
||||
@Default
|
||||
private Integer maxGroupSize = null;
|
||||
private Range groupSize = null;
|
||||
|
||||
@Override
|
||||
public SpawnEntry get() {
|
||||
return new SpawnEntry(type, weight, minGroupSize, maxGroupSize);
|
||||
return new SpawnEntry(type, weight, groupSize.getMin(), groupSize.getMax());
|
||||
}
|
||||
}
|
||||
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
package com.dfsek.terra.mod.config;
|
||||
|
||||
import com.dfsek.tectonic.api.config.template.annotations.Default;
|
||||
import com.dfsek.tectonic.api.config.template.annotations.Value;
|
||||
import com.dfsek.tectonic.api.config.template.object.ObjectTemplate;
|
||||
import net.minecraft.entity.SpawnGroup;
|
||||
|
||||
|
||||
public class SpawnGroupTemplate implements ObjectTemplate<SpawnGroup> {
|
||||
@Value("group")
|
||||
@Default
|
||||
private String group = null;
|
||||
|
||||
@Override
|
||||
public SpawnGroup get() {
|
||||
return SpawnGroup.valueOf(group);
|
||||
}
|
||||
}
|
||||
+6
-1
@@ -3,7 +3,9 @@ package com.dfsek.terra.mod.config;
|
||||
import com.dfsek.tectonic.api.config.template.annotations.Default;
|
||||
import com.dfsek.tectonic.api.config.template.annotations.Value;
|
||||
import com.dfsek.tectonic.api.config.template.object.ObjectTemplate;
|
||||
import net.minecraft.entity.SpawnGroup;
|
||||
import net.minecraft.world.biome.SpawnSettings;
|
||||
import net.minecraft.world.biome.SpawnSettings.SpawnEntry;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -25,7 +27,10 @@ public class SpawnSettingsTemplate implements ObjectTemplate<SpawnSettings> {
|
||||
public SpawnSettings get() {
|
||||
SpawnSettings.Builder builder = new SpawnSettings.Builder();
|
||||
for(SpawnTypeConfig spawn : spawns) {
|
||||
builder.spawn(spawn.getGroup(), spawn.getEntry());
|
||||
SpawnGroup group = spawn.getGroup();
|
||||
for (SpawnEntry entry : spawn.getEntry()) {
|
||||
builder.spawn(group, entry);
|
||||
}
|
||||
}
|
||||
for(SpawnCostConfig cost : costs) {
|
||||
builder.spawnCost(cost.getType(), cost.getMass(), cost.getGravity());
|
||||
|
||||
+5
-3
@@ -6,21 +6,23 @@ import com.dfsek.tectonic.api.config.template.object.ObjectTemplate;
|
||||
import net.minecraft.entity.SpawnGroup;
|
||||
import net.minecraft.world.biome.SpawnSettings.SpawnEntry;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public class SpawnTypeConfig implements ObjectTemplate<SpawnTypeConfig> {
|
||||
@Value("group")
|
||||
@Default
|
||||
private SpawnGroup group = null;
|
||||
|
||||
@Value("entry")
|
||||
@Value("entries")
|
||||
@Default
|
||||
private SpawnEntry entry = null;
|
||||
private List<SpawnEntry> entry = null;
|
||||
|
||||
public SpawnGroup getGroup() {
|
||||
return group;
|
||||
}
|
||||
|
||||
public SpawnEntry getEntry() {
|
||||
public List<SpawnEntry> getEntry() {
|
||||
return entry;
|
||||
}
|
||||
|
||||
|
||||
+6
-5
@@ -18,6 +18,7 @@
|
||||
package com.dfsek.terra.mod.mixin.implementations.terra.block.entity;
|
||||
|
||||
import net.minecraft.block.entity.SignBlockEntity;
|
||||
import net.minecraft.block.entity.SignText;
|
||||
import net.minecraft.text.Text;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
@@ -34,17 +35,17 @@ import com.dfsek.terra.api.block.entity.Sign;
|
||||
@Implements(@Interface(iface = Sign.class, prefix = "terra$"))
|
||||
public abstract class SignBlockEntityMixin {
|
||||
@Shadow
|
||||
@Final
|
||||
private Text[] texts;
|
||||
private SignText frontText;
|
||||
|
||||
@Shadow
|
||||
public abstract void setTextOnRow(int row, Text text);
|
||||
public abstract boolean setText(SignText text, boolean front);
|
||||
|
||||
public void terra$setLine(int index, @NotNull String line) throws IndexOutOfBoundsException {
|
||||
setTextOnRow(index, Text.literal(line));
|
||||
setText(frontText.withMessage(index, Text.literal(line)), true);
|
||||
}
|
||||
|
||||
public @NotNull String[] terra$getLines() {
|
||||
Text[] texts = frontText.getMessages(false);
|
||||
String[] lines = new String[texts.length];
|
||||
for(int i = 0; i < texts.length; i++) {
|
||||
lines[i] = texts[i].getString();
|
||||
@@ -53,7 +54,7 @@ public abstract class SignBlockEntityMixin {
|
||||
}
|
||||
|
||||
public @NotNull String terra$getLine(int index) throws IndexOutOfBoundsException {
|
||||
return texts[index].getString();
|
||||
return frontText.getMessage(index, false).getString();
|
||||
}
|
||||
|
||||
public void terra$applyState(String state) {
|
||||
|
||||
+4
-4
@@ -37,9 +37,6 @@ import com.dfsek.terra.api.entity.Player;
|
||||
@Mixin(ServerCommandSource.class)
|
||||
@Implements(@Interface(iface = CommandSender.class, prefix = "terra$"))
|
||||
public abstract class ServerCommandSourceMixin {
|
||||
@Shadow
|
||||
public abstract void sendFeedback(Text message, boolean broadcastToOps);
|
||||
|
||||
@Shadow
|
||||
public abstract ServerPlayerEntity getPlayer() throws CommandSyntaxException;
|
||||
|
||||
@@ -47,8 +44,11 @@ public abstract class ServerCommandSourceMixin {
|
||||
@Nullable
|
||||
public abstract net.minecraft.entity.@Nullable Entity getEntity();
|
||||
|
||||
@Shadow
|
||||
public abstract void sendMessage(Text message);
|
||||
|
||||
public void terra$sendMessage(String message) {
|
||||
sendFeedback(Text.literal(message), true);
|
||||
sendMessage(Text.literal(message));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -15,6 +15,11 @@ dependencies {
|
||||
|
||||
minecraft("com.mojang:minecraft:${Versions.Mod.minecraft}")
|
||||
mappings("net.fabricmc:yarn:${Versions.Mod.yarn}:v2")
|
||||
|
||||
modImplementation("cloud.commandframework", "cloud-fabric", Versions.Libraries.cloud) {
|
||||
exclude("net.fabricmc")
|
||||
exclude("net.fabricmc.fabric-api")
|
||||
}
|
||||
}
|
||||
|
||||
loom {
|
||||
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
package com.dfsek.terra.lifecycle;
|
||||
|
||||
import cloud.commandframework.execution.CommandExecutionCoordinator;
|
||||
|
||||
import cloud.commandframework.fabric.FabricServerCommandManager;
|
||||
|
||||
import com.dfsek.terra.api.command.CommandSender;
|
||||
import com.dfsek.terra.api.event.events.platform.CommandRegistrationEvent;
|
||||
|
||||
import com.dfsek.terra.mod.MinecraftAddon;
|
||||
|
||||
import net.minecraft.server.command.ServerCommandSource;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
public class LifecycleEntryPoint {
|
||||
private static final Logger logger = LoggerFactory.getLogger(LifecycleEntryPoint.class);
|
||||
|
||||
protected static void initialize(String modName, LifecyclePlatform platform) {
|
||||
logger.info("Initializing Terra {} mod...", modName);
|
||||
|
||||
FabricServerCommandManager<CommandSender> manager = new FabricServerCommandManager<>(
|
||||
CommandExecutionCoordinator.simpleCoordinator(),
|
||||
serverCommandSource -> (CommandSender) serverCommandSource,
|
||||
commandSender -> (ServerCommandSource) commandSender
|
||||
);
|
||||
|
||||
|
||||
manager.brigadierManager().setNativeNumberSuggestions(false);
|
||||
|
||||
platform.getEventManager().callEvent(new CommandRegistrationEvent(manager));
|
||||
}
|
||||
}
|
||||
+18
-2
@@ -2,6 +2,7 @@ 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.lifecycle.util.BiomeUtil;
|
||||
|
||||
@@ -20,6 +21,7 @@ import org.slf4j.LoggerFactory;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import com.dfsek.terra.addon.EphemeralAddon;
|
||||
@@ -103,12 +105,26 @@ public abstract class LifecyclePlatform extends ModPlatform {
|
||||
LOGGER.warn("Failed to parse Minecraft version", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
addons.addAll(getPlatformMods());
|
||||
|
||||
|
||||
return addons;
|
||||
}
|
||||
|
||||
protected Stream<EphemeralAddon> parseModData(String id, String modVersion) {
|
||||
if(id.equals("terra") || id.equals("minecraft") || id.equals("java")) return Stream.empty();
|
||||
try {
|
||||
Version version = Versions.parseVersion(modVersion);
|
||||
return Stream.of(new EphemeralAddon(version, "quilt:" + id));
|
||||
} catch(ParseException e) {
|
||||
LOGGER.warn(
|
||||
"Mod {}, version {} does not follow semantic versioning specification, Terra addons will be unable to depend on " +
|
||||
"it.",
|
||||
id, modVersion);
|
||||
}
|
||||
return Stream.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Registry<DimensionType> dimensionTypeRegistry() {
|
||||
return DIMENSIONS.get();
|
||||
|
||||
@@ -17,36 +17,17 @@
|
||||
|
||||
package com.dfsek.terra.quilt;
|
||||
|
||||
import cloud.commandframework.execution.CommandExecutionCoordinator;
|
||||
import cloud.commandframework.fabric.FabricServerCommandManager;
|
||||
import net.minecraft.server.command.ServerCommandSource;
|
||||
import org.quiltmc.loader.api.ModContainer;
|
||||
import org.quiltmc.qsl.base.api.entrypoint.ModInitializer;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.dfsek.terra.api.command.CommandSender;
|
||||
import com.dfsek.terra.api.event.events.platform.CommandRegistrationEvent;
|
||||
import com.dfsek.terra.lifecycle.LifecycleEntryPoint;
|
||||
|
||||
|
||||
public class QuiltEntryPoint implements ModInitializer {
|
||||
private static final Logger logger = LoggerFactory.getLogger(QuiltEntryPoint.class);
|
||||
|
||||
public class QuiltEntryPoint extends LifecycleEntryPoint implements ModInitializer {
|
||||
private static final QuiltPlatform TERRA_PLUGIN = new QuiltPlatform();
|
||||
|
||||
|
||||
@Override
|
||||
public void onInitialize(ModContainer container) {
|
||||
logger.info("Initializing Terra Quilt mod...");
|
||||
|
||||
FabricServerCommandManager<CommandSender> manager = new FabricServerCommandManager<>(
|
||||
CommandExecutionCoordinator.simpleCoordinator(),
|
||||
serverCommandSource -> (CommandSender) serverCommandSource,
|
||||
commandSender -> (ServerCommandSource) commandSender
|
||||
);
|
||||
|
||||
|
||||
manager.brigadierManager().setNativeNumberSuggestions(false);
|
||||
|
||||
TERRA_PLUGIN.getEventManager().callEvent(new CommandRegistrationEvent(manager));
|
||||
initialize("Quilt", TERRA_PLUGIN);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,43 +17,23 @@
|
||||
|
||||
package com.dfsek.terra.quilt;
|
||||
|
||||
import ca.solostudios.strata.Versions;
|
||||
import ca.solostudios.strata.parser.tokenizer.ParseException;
|
||||
import ca.solostudios.strata.version.Version;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.quiltmc.loader.api.QuiltLoader;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collection;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import com.dfsek.terra.addon.EphemeralAddon;
|
||||
import com.dfsek.terra.api.addon.BaseAddon;
|
||||
import com.dfsek.terra.lifecycle.LifecyclePlatform;
|
||||
|
||||
|
||||
public class QuiltPlatform extends LifecyclePlatform {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(QuiltPlatform.class);
|
||||
|
||||
@Override
|
||||
protected Collection<BaseAddon> getPlatformMods() {
|
||||
return QuiltLoader.getAllMods().stream().flatMap(mod -> {
|
||||
String id = mod.metadata().id();
|
||||
if(id.equals("terra") || id.equals("minecraft") || id.equals("java")) return Stream.empty();
|
||||
try {
|
||||
Version version = Versions.parseVersion(mod.metadata().version().raw());
|
||||
return Stream.of(new EphemeralAddon(version, "quilt:" + id));
|
||||
} catch(ParseException e) {
|
||||
LOGGER.warn(
|
||||
"Mod {}, version {} does not follow semantic versioning specification, Terra addons will be unable to depend on " +
|
||||
"it.",
|
||||
id, mod.metadata().version().raw());
|
||||
}
|
||||
return Stream.empty();
|
||||
}).collect(Collectors.toList());
|
||||
return QuiltLoader.getAllMods().stream().flatMap(mod -> parseModData(mod.metadata().id(), mod.metadata().version().raw())).collect(
|
||||
Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user