mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2026-04-23 00:29:51 +00:00
Working state for pipeline implementation
This commit is contained in:
@@ -11,10 +11,8 @@ import com.dfsek.tectonic.api.config.template.object.ObjectTemplate;
|
|||||||
|
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import com.dfsek.terra.addons.biome.pipeline.api.delegate.BiomeDelegate;
|
|
||||||
import com.dfsek.terra.addons.biome.pipeline.api.stage.Stage;
|
|
||||||
import com.dfsek.terra.addons.biome.pipeline.config.BiomeDelegateLoader;
|
|
||||||
import com.dfsek.terra.addons.biome.pipeline.config.BiomePipelineTemplate;
|
import com.dfsek.terra.addons.biome.pipeline.config.BiomePipelineTemplate;
|
||||||
|
import com.dfsek.terra.addons.biome.pipeline.config.PipelineBiomeLoader;
|
||||||
import com.dfsek.terra.addons.biome.pipeline.config.SamplerSourceTemplate;
|
import com.dfsek.terra.addons.biome.pipeline.config.SamplerSourceTemplate;
|
||||||
import com.dfsek.terra.addons.biome.pipeline.config.stage.expander.ExpanderStageTemplate;
|
import com.dfsek.terra.addons.biome.pipeline.config.stage.expander.ExpanderStageTemplate;
|
||||||
import com.dfsek.terra.addons.biome.pipeline.config.stage.mutator.BorderListMutatorTemplate;
|
import com.dfsek.terra.addons.biome.pipeline.config.stage.mutator.BorderListMutatorTemplate;
|
||||||
@@ -22,7 +20,9 @@ import com.dfsek.terra.addons.biome.pipeline.config.stage.mutator.BorderMutatorT
|
|||||||
import com.dfsek.terra.addons.biome.pipeline.config.stage.mutator.ReplaceListMutatorTemplate;
|
import com.dfsek.terra.addons.biome.pipeline.config.stage.mutator.ReplaceListMutatorTemplate;
|
||||||
import com.dfsek.terra.addons.biome.pipeline.config.stage.mutator.ReplaceMutatorTemplate;
|
import com.dfsek.terra.addons.biome.pipeline.config.stage.mutator.ReplaceMutatorTemplate;
|
||||||
import com.dfsek.terra.addons.biome.pipeline.config.stage.mutator.SmoothMutatorTemplate;
|
import com.dfsek.terra.addons.biome.pipeline.config.stage.mutator.SmoothMutatorTemplate;
|
||||||
import com.dfsek.terra.addons.biome.pipeline.source.BiomeSource;
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.api.Source;
|
||||||
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.api.Stage;
|
||||||
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.api.biome.PipelineBiome;
|
||||||
import com.dfsek.terra.addons.manifest.api.AddonInitializer;
|
import com.dfsek.terra.addons.manifest.api.AddonInitializer;
|
||||||
import com.dfsek.terra.api.Platform;
|
import com.dfsek.terra.api.Platform;
|
||||||
import com.dfsek.terra.api.addon.BaseAddon;
|
import com.dfsek.terra.api.addon.BaseAddon;
|
||||||
@@ -39,7 +39,7 @@ import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
|
|||||||
|
|
||||||
public class BiomePipelineAddon implements AddonInitializer {
|
public class BiomePipelineAddon implements AddonInitializer {
|
||||||
|
|
||||||
public static final TypeKey<Supplier<ObjectTemplate<BiomeSource>>> SOURCE_REGISTRY_KEY = new TypeKey<>() {
|
public static final TypeKey<Supplier<ObjectTemplate<Source>>> SOURCE_REGISTRY_KEY = new TypeKey<>() {
|
||||||
};
|
};
|
||||||
|
|
||||||
public static final TypeKey<Supplier<ObjectTemplate<Stage>>> STAGE_REGISTRY_KEY = new TypeKey<>() {
|
public static final TypeKey<Supplier<ObjectTemplate<Stage>>> STAGE_REGISTRY_KEY = new TypeKey<>() {
|
||||||
@@ -63,7 +63,7 @@ public class BiomePipelineAddon implements AddonInitializer {
|
|||||||
providerRegistry.register(addon.key("PIPELINE"), BiomePipelineTemplate::new);
|
providerRegistry.register(addon.key("PIPELINE"), BiomePipelineTemplate::new);
|
||||||
})
|
})
|
||||||
.then(event -> {
|
.then(event -> {
|
||||||
CheckedRegistry<Supplier<ObjectTemplate<BiomeSource>>> sourceRegistry = event.getPack().getOrCreateRegistry(
|
CheckedRegistry<Supplier<ObjectTemplate<Source>>> sourceRegistry = event.getPack().getOrCreateRegistry(
|
||||||
SOURCE_REGISTRY_KEY);
|
SOURCE_REGISTRY_KEY);
|
||||||
sourceRegistry.register(addon.key("SAMPLER"), SamplerSourceTemplate::new);
|
sourceRegistry.register(addon.key("SAMPLER"), SamplerSourceTemplate::new);
|
||||||
})
|
})
|
||||||
@@ -83,7 +83,7 @@ public class BiomePipelineAddon implements AddonInitializer {
|
|||||||
.register(addon, ConfigPackPostLoadEvent.class)
|
.register(addon, ConfigPackPostLoadEvent.class)
|
||||||
.then(event -> {
|
.then(event -> {
|
||||||
Registry<Biome> biomeRegistry = event.getPack().getRegistry(Biome.class);
|
Registry<Biome> biomeRegistry = event.getPack().getRegistry(Biome.class);
|
||||||
event.getPack().applyLoader(BiomeDelegate.class, new BiomeDelegateLoader(biomeRegistry));
|
event.getPack().applyLoader(PipelineBiome.class, new PipelineBiomeLoader(biomeRegistry));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import com.dfsek.terra.api.world.biome.Biome;
|
|||||||
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
|
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
|
||||||
|
|
||||||
|
|
||||||
class BiomePipelineColumn implements Column<Biome> {
|
public class BiomePipelineColumn implements Column<Biome> {
|
||||||
private final int min;
|
private final int min;
|
||||||
private final int max;
|
private final int max;
|
||||||
|
|
||||||
@@ -17,7 +17,7 @@ class BiomePipelineColumn implements Column<Biome> {
|
|||||||
private final int z;
|
private final int z;
|
||||||
private final Biome biome;
|
private final Biome biome;
|
||||||
|
|
||||||
protected BiomePipelineColumn(BiomeProvider biomeProvider, int min, int max, int x, int z, long seed) {
|
public BiomePipelineColumn(BiomeProvider biomeProvider, int min, int max, int x, int z, long seed) {
|
||||||
this.min = min;
|
this.min = min;
|
||||||
this.max = max;
|
this.max = max;
|
||||||
this.x = x;
|
this.x = x;
|
||||||
|
|||||||
@@ -10,45 +10,50 @@ package com.dfsek.terra.addons.biome.pipeline.config;
|
|||||||
import com.dfsek.tectonic.api.config.template.annotations.Default;
|
import com.dfsek.tectonic.api.config.template.annotations.Default;
|
||||||
import com.dfsek.tectonic.api.config.template.annotations.Description;
|
import com.dfsek.tectonic.api.config.template.annotations.Description;
|
||||||
import com.dfsek.tectonic.api.config.template.annotations.Value;
|
import com.dfsek.tectonic.api.config.template.annotations.Value;
|
||||||
|
import com.dfsek.tectonic.api.config.template.object.ObjectTemplate;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.dfsek.terra.addons.biome.pipeline.BiomePipeline;
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.PipelineBiomeProvider;
|
||||||
import com.dfsek.terra.addons.biome.pipeline.BiomePipelineProvider;
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.PipelineImpl;
|
||||||
import com.dfsek.terra.addons.biome.pipeline.api.stage.Stage;
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.api.Source;
|
||||||
import com.dfsek.terra.addons.biome.pipeline.source.BiomeSource;
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.api.Stage;
|
||||||
import com.dfsek.terra.api.config.meta.Meta;
|
import com.dfsek.terra.api.config.meta.Meta;
|
||||||
|
import com.dfsek.terra.api.noise.NoiseSampler;
|
||||||
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
|
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
|
||||||
|
|
||||||
|
|
||||||
@SuppressWarnings({ "FieldMayBeFinal", "unused" })
|
@SuppressWarnings({ "FieldMayBeFinal", "unused" })
|
||||||
public class BiomePipelineTemplate extends BiomeProviderTemplate {
|
public class BiomePipelineTemplate implements ObjectTemplate<BiomeProvider> {
|
||||||
@Value("pipeline.initial-size")
|
@Value("resolution")
|
||||||
@Default
|
@Default
|
||||||
@Description("""
|
@Description("""
|
||||||
The initial size of biome chunks. This value must be at least 2.
|
The resolution at which to sample biomes.
|
||||||
<b>This is not the final size of biome chunks. Final chunks will be much larger</b>.
|
|
||||||
|
Larger values are quadratically faster, but produce lower quality results.
|
||||||
It is recommended to keep biome chunks' final size in the range of [50, 300]
|
For example, a value of 3 would sample every 3 blocks.""")
|
||||||
to prevent performance issues. To calculate the size of biome chunks, simply
|
protected @Meta int resolution = 1;
|
||||||
take initial-size and for each expand stage, multiply the running value by 2
|
|
||||||
and subtract 1. (The size is also printed to the server console if you
|
|
||||||
have debug mode enabled)""")
|
|
||||||
private @Meta int initialSize = 2;
|
|
||||||
|
|
||||||
@Value("pipeline.source")
|
@Value("pipeline.source")
|
||||||
@Description("The Biome Source to use for initial population of biomes.")
|
@Description("The Biome Source to use for initial population of biomes.")
|
||||||
private @Meta BiomeSource source;
|
private @Meta Source source;
|
||||||
|
|
||||||
@Value("pipeline.stages")
|
@Value("pipeline.stages")
|
||||||
@Description("A list of pipeline stages to apply to the result of #source")
|
@Description("A list of pipeline stages to apply to the result of #source")
|
||||||
private @Meta List<@Meta Stage> stages;
|
private @Meta List<@Meta Stage> stages;
|
||||||
|
|
||||||
|
@Value("blend.sampler")
|
||||||
|
@Default
|
||||||
|
@Description("A sampler to use for blending the edges of biomes via domain warping.")
|
||||||
|
protected @Meta NoiseSampler blendSampler = NoiseSampler.zero();
|
||||||
|
|
||||||
|
@Value("blend.amplitude")
|
||||||
|
@Default
|
||||||
|
@Description("The amplitude at which to perform blending.")
|
||||||
|
protected @Meta double blendAmplitude = 0d;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BiomeProvider get() {
|
public BiomeProvider get() {
|
||||||
BiomePipeline.BiomePipelineBuilder biomePipelineBuilder = new BiomePipeline.BiomePipelineBuilder(initialSize);
|
return new PipelineBiomeProvider(new PipelineImpl(source, stages, 10), resolution, blendSampler, blendAmplitude);
|
||||||
stages.forEach(biomePipelineBuilder::addStage);
|
|
||||||
BiomePipeline pipeline = biomePipelineBuilder.build(source);
|
|
||||||
return new BiomePipelineProvider(pipeline, resolution, blend, blendAmp);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,37 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.biome.pipeline.config;
|
|
||||||
|
|
||||||
import com.dfsek.tectonic.api.config.template.annotations.Default;
|
|
||||||
import com.dfsek.tectonic.api.config.template.annotations.Description;
|
|
||||||
import com.dfsek.tectonic.api.config.template.annotations.Value;
|
|
||||||
import com.dfsek.tectonic.api.config.template.object.ObjectTemplate;
|
|
||||||
|
|
||||||
import com.dfsek.terra.api.config.meta.Meta;
|
|
||||||
import com.dfsek.terra.api.noise.NoiseSampler;
|
|
||||||
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
|
|
||||||
|
|
||||||
|
|
||||||
public abstract class BiomeProviderTemplate implements ObjectTemplate<BiomeProvider> {
|
|
||||||
@Value("resolution")
|
|
||||||
@Default
|
|
||||||
@Description("""
|
|
||||||
The resolution at which to sample biomes.
|
|
||||||
|
|
||||||
Larger values are quadratically faster, but produce lower quality results.
|
|
||||||
For example, a value of 3 would sample every 3 blocks.""")
|
|
||||||
protected @Meta int resolution = 1;
|
|
||||||
@Value("blend.sampler")
|
|
||||||
@Default
|
|
||||||
@Description("A sampler to use for blending the edges of biomes via domain warping.")
|
|
||||||
protected @Meta NoiseSampler blend = NoiseSampler.zero();
|
|
||||||
@Value("blend.amplitude")
|
|
||||||
@Default
|
|
||||||
@Description("The amplitude at which to perform blending.")
|
|
||||||
protected @Meta double blendAmp = 0d;
|
|
||||||
}
|
|
||||||
@@ -8,25 +8,25 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
|
|
||||||
import java.lang.reflect.AnnotatedType;
|
import java.lang.reflect.AnnotatedType;
|
||||||
|
|
||||||
import com.dfsek.terra.addons.biome.pipeline.api.delegate.BiomeDelegate;
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.api.biome.PipelineBiome;
|
||||||
import com.dfsek.terra.api.registry.Registry;
|
import com.dfsek.terra.api.registry.Registry;
|
||||||
import com.dfsek.terra.api.world.biome.Biome;
|
import com.dfsek.terra.api.world.biome.Biome;
|
||||||
|
|
||||||
|
|
||||||
public class BiomeDelegateLoader implements TypeLoader<BiomeDelegate> {
|
public class PipelineBiomeLoader implements TypeLoader<PipelineBiome> {
|
||||||
private final Registry<Biome> biomeRegistry;
|
private final Registry<Biome> biomeRegistry;
|
||||||
|
|
||||||
public BiomeDelegateLoader(Registry<Biome> biomeRegistry) {
|
public PipelineBiomeLoader(Registry<Biome> biomeRegistry) {
|
||||||
this.biomeRegistry = biomeRegistry;
|
this.biomeRegistry = biomeRegistry;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BiomeDelegate load(@NotNull AnnotatedType t, @NotNull Object c, @NotNull ConfigLoader loader, DepthTracker depthTracker)
|
public PipelineBiome load(@NotNull AnnotatedType t, @NotNull Object c, @NotNull ConfigLoader loader, DepthTracker depthTracker)
|
||||||
throws LoadException {
|
throws LoadException {
|
||||||
if(c.equals("SELF")) return BiomeDelegate.self();
|
if(c.equals("SELF")) return PipelineBiome.self();
|
||||||
return biomeRegistry
|
return biomeRegistry
|
||||||
.getByID((String) c)
|
.getByID((String) c)
|
||||||
.map(BiomeDelegate::from)
|
.map(PipelineBiome::from)
|
||||||
.orElseGet(() -> BiomeDelegate.ephemeral((String) c));
|
.orElseGet(() -> PipelineBiome.ephemeral((String) c));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10,9 +10,9 @@ package com.dfsek.terra.addons.biome.pipeline.config;
|
|||||||
import com.dfsek.tectonic.api.config.template.annotations.Description;
|
import com.dfsek.tectonic.api.config.template.annotations.Description;
|
||||||
import com.dfsek.tectonic.api.config.template.annotations.Value;
|
import com.dfsek.tectonic.api.config.template.annotations.Value;
|
||||||
|
|
||||||
import com.dfsek.terra.addons.biome.pipeline.api.delegate.BiomeDelegate;
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.api.Source;
|
||||||
import com.dfsek.terra.addons.biome.pipeline.source.BiomeSource;
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.api.biome.PipelineBiome;
|
||||||
import com.dfsek.terra.addons.biome.pipeline.source.SamplerSource;
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.source.SamplerSource;
|
||||||
import com.dfsek.terra.api.config.meta.Meta;
|
import com.dfsek.terra.api.config.meta.Meta;
|
||||||
import com.dfsek.terra.api.noise.NoiseSampler;
|
import com.dfsek.terra.api.noise.NoiseSampler;
|
||||||
import com.dfsek.terra.api.util.collection.ProbabilityCollection;
|
import com.dfsek.terra.api.util.collection.ProbabilityCollection;
|
||||||
@@ -25,10 +25,10 @@ public class SamplerSourceTemplate extends SourceTemplate {
|
|||||||
|
|
||||||
@Value("biomes")
|
@Value("biomes")
|
||||||
@Description("The biomes to be distributed.")
|
@Description("The biomes to be distributed.")
|
||||||
private @Meta ProbabilityCollection<@Meta BiomeDelegate> biomes;
|
private @Meta ProbabilityCollection<@Meta PipelineBiome> biomes;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BiomeSource get() {
|
public Source get() {
|
||||||
return new SamplerSource(biomes, noise);
|
return new SamplerSource(biomes, noise);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,9 +9,9 @@ package com.dfsek.terra.addons.biome.pipeline.config;
|
|||||||
|
|
||||||
import com.dfsek.tectonic.api.config.template.object.ObjectTemplate;
|
import com.dfsek.tectonic.api.config.template.object.ObjectTemplate;
|
||||||
|
|
||||||
import com.dfsek.terra.addons.biome.pipeline.source.BiomeSource;
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.api.Source;
|
||||||
|
|
||||||
|
|
||||||
public abstract class SourceTemplate implements ObjectTemplate<BiomeSource> {
|
public abstract class SourceTemplate implements ObjectTemplate<Source> {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import com.dfsek.tectonic.api.config.template.annotations.Description;
|
|||||||
import com.dfsek.tectonic.api.config.template.annotations.Value;
|
import com.dfsek.tectonic.api.config.template.annotations.Value;
|
||||||
import com.dfsek.tectonic.api.config.template.object.ObjectTemplate;
|
import com.dfsek.tectonic.api.config.template.object.ObjectTemplate;
|
||||||
|
|
||||||
import com.dfsek.terra.addons.biome.pipeline.api.stage.Stage;
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.api.Stage;
|
||||||
import com.dfsek.terra.api.config.meta.Meta;
|
import com.dfsek.terra.api.config.meta.Meta;
|
||||||
import com.dfsek.terra.api.noise.NoiseSampler;
|
import com.dfsek.terra.api.noise.NoiseSampler;
|
||||||
|
|
||||||
|
|||||||
@@ -7,15 +7,14 @@
|
|||||||
|
|
||||||
package com.dfsek.terra.addons.biome.pipeline.config.stage.expander;
|
package com.dfsek.terra.addons.biome.pipeline.config.stage.expander;
|
||||||
|
|
||||||
import com.dfsek.terra.addons.biome.pipeline.api.stage.Stage;
|
|
||||||
import com.dfsek.terra.addons.biome.pipeline.config.stage.StageTemplate;
|
import com.dfsek.terra.addons.biome.pipeline.config.stage.StageTemplate;
|
||||||
import com.dfsek.terra.addons.biome.pipeline.expand.FractalExpander;
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.api.Expander;
|
||||||
import com.dfsek.terra.addons.biome.pipeline.stages.ExpanderStage;
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.stage.expander.FractalExpander;
|
||||||
|
|
||||||
|
|
||||||
public class ExpanderStageTemplate extends StageTemplate {
|
public class ExpanderStageTemplate extends StageTemplate {
|
||||||
@Override
|
@Override
|
||||||
public Stage get() {
|
public Expander get() {
|
||||||
return new ExpanderStage(new FractalExpander(noise));
|
return new FractalExpander(noise);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,11 +11,10 @@ import com.dfsek.tectonic.api.config.template.annotations.Value;
|
|||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import com.dfsek.terra.addons.biome.pipeline.api.delegate.BiomeDelegate;
|
|
||||||
import com.dfsek.terra.addons.biome.pipeline.api.stage.Stage;
|
|
||||||
import com.dfsek.terra.addons.biome.pipeline.config.stage.StageTemplate;
|
import com.dfsek.terra.addons.biome.pipeline.config.stage.StageTemplate;
|
||||||
import com.dfsek.terra.addons.biome.pipeline.mutator.BorderListMutator;
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.api.Stage;
|
||||||
import com.dfsek.terra.addons.biome.pipeline.stages.MutatorStage;
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.api.biome.PipelineBiome;
|
||||||
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.stage.mutators.BorderListMutator;
|
||||||
import com.dfsek.terra.api.config.meta.Meta;
|
import com.dfsek.terra.api.config.meta.Meta;
|
||||||
import com.dfsek.terra.api.util.collection.ProbabilityCollection;
|
import com.dfsek.terra.api.util.collection.ProbabilityCollection;
|
||||||
|
|
||||||
@@ -29,14 +28,14 @@ public class BorderListMutatorTemplate extends StageTemplate {
|
|||||||
private @Meta String defaultReplace;
|
private @Meta String defaultReplace;
|
||||||
|
|
||||||
@Value("default-to")
|
@Value("default-to")
|
||||||
private @Meta ProbabilityCollection<@Meta BiomeDelegate> defaultTo;
|
private @Meta ProbabilityCollection<@Meta PipelineBiome> defaultTo;
|
||||||
|
|
||||||
@Value("replace")
|
@Value("replace")
|
||||||
private @Meta Map<@Meta BiomeDelegate, @Meta ProbabilityCollection<@Meta BiomeDelegate>> replace;
|
private @Meta Map<@Meta PipelineBiome, @Meta ProbabilityCollection<@Meta PipelineBiome>> replace;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Stage get() {
|
public Stage get() {
|
||||||
return new MutatorStage(new BorderListMutator(replace, from, defaultReplace, noise, defaultTo));
|
return new BorderListMutator(replace, from, defaultReplace, noise, defaultTo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,11 +9,10 @@ package com.dfsek.terra.addons.biome.pipeline.config.stage.mutator;
|
|||||||
|
|
||||||
import com.dfsek.tectonic.api.config.template.annotations.Value;
|
import com.dfsek.tectonic.api.config.template.annotations.Value;
|
||||||
|
|
||||||
import com.dfsek.terra.addons.biome.pipeline.api.delegate.BiomeDelegate;
|
|
||||||
import com.dfsek.terra.addons.biome.pipeline.api.stage.Stage;
|
|
||||||
import com.dfsek.terra.addons.biome.pipeline.config.stage.StageTemplate;
|
import com.dfsek.terra.addons.biome.pipeline.config.stage.StageTemplate;
|
||||||
import com.dfsek.terra.addons.biome.pipeline.mutator.BorderMutator;
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.api.Stage;
|
||||||
import com.dfsek.terra.addons.biome.pipeline.stages.MutatorStage;
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.api.biome.PipelineBiome;
|
||||||
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.stage.mutators.BorderMutator;
|
||||||
import com.dfsek.terra.api.config.meta.Meta;
|
import com.dfsek.terra.api.config.meta.Meta;
|
||||||
import com.dfsek.terra.api.util.collection.ProbabilityCollection;
|
import com.dfsek.terra.api.util.collection.ProbabilityCollection;
|
||||||
|
|
||||||
@@ -27,10 +26,10 @@ public class BorderMutatorTemplate extends StageTemplate {
|
|||||||
private @Meta String replace;
|
private @Meta String replace;
|
||||||
|
|
||||||
@Value("to")
|
@Value("to")
|
||||||
private @Meta ProbabilityCollection<@Meta BiomeDelegate> to;
|
private @Meta ProbabilityCollection<@Meta PipelineBiome> to;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Stage get() {
|
public Stage get() {
|
||||||
return new MutatorStage(new BorderMutator(from, replace, noise, to));
|
return new BorderMutator(from, replace, noise, to);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,11 +11,10 @@ import com.dfsek.tectonic.api.config.template.annotations.Value;
|
|||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import com.dfsek.terra.addons.biome.pipeline.api.delegate.BiomeDelegate;
|
|
||||||
import com.dfsek.terra.addons.biome.pipeline.api.stage.Stage;
|
|
||||||
import com.dfsek.terra.addons.biome.pipeline.config.stage.StageTemplate;
|
import com.dfsek.terra.addons.biome.pipeline.config.stage.StageTemplate;
|
||||||
import com.dfsek.terra.addons.biome.pipeline.mutator.ReplaceListMutator;
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.api.Stage;
|
||||||
import com.dfsek.terra.addons.biome.pipeline.stages.MutatorStage;
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.api.biome.PipelineBiome;
|
||||||
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.stage.mutators.ReplaceListMutator;
|
||||||
import com.dfsek.terra.api.config.meta.Meta;
|
import com.dfsek.terra.api.config.meta.Meta;
|
||||||
import com.dfsek.terra.api.util.collection.ProbabilityCollection;
|
import com.dfsek.terra.api.util.collection.ProbabilityCollection;
|
||||||
|
|
||||||
@@ -26,13 +25,13 @@ public class ReplaceListMutatorTemplate extends StageTemplate {
|
|||||||
private @Meta String defaultFrom;
|
private @Meta String defaultFrom;
|
||||||
|
|
||||||
@Value("default-to")
|
@Value("default-to")
|
||||||
private @Meta ProbabilityCollection<@Meta BiomeDelegate> defaultTo;
|
private @Meta ProbabilityCollection<@Meta PipelineBiome> defaultTo;
|
||||||
|
|
||||||
@Value("to")
|
@Value("to")
|
||||||
private @Meta Map<@Meta BiomeDelegate, @Meta ProbabilityCollection<@Meta BiomeDelegate>> replace;
|
private @Meta Map<@Meta PipelineBiome, @Meta ProbabilityCollection<@Meta PipelineBiome>> replace;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Stage get() {
|
public Stage get() {
|
||||||
return new MutatorStage(new ReplaceListMutator(replace, defaultFrom, defaultTo, noise));
|
return new ReplaceListMutator(replace, defaultFrom, defaultTo, noise);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,11 +9,10 @@ package com.dfsek.terra.addons.biome.pipeline.config.stage.mutator;
|
|||||||
|
|
||||||
import com.dfsek.tectonic.api.config.template.annotations.Value;
|
import com.dfsek.tectonic.api.config.template.annotations.Value;
|
||||||
|
|
||||||
import com.dfsek.terra.addons.biome.pipeline.api.delegate.BiomeDelegate;
|
|
||||||
import com.dfsek.terra.addons.biome.pipeline.api.stage.Stage;
|
|
||||||
import com.dfsek.terra.addons.biome.pipeline.config.stage.StageTemplate;
|
import com.dfsek.terra.addons.biome.pipeline.config.stage.StageTemplate;
|
||||||
import com.dfsek.terra.addons.biome.pipeline.mutator.ReplaceMutator;
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.api.Stage;
|
||||||
import com.dfsek.terra.addons.biome.pipeline.stages.MutatorStage;
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.api.biome.PipelineBiome;
|
||||||
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.stage.mutators.ReplaceMutator;
|
||||||
import com.dfsek.terra.api.config.meta.Meta;
|
import com.dfsek.terra.api.config.meta.Meta;
|
||||||
import com.dfsek.terra.api.util.collection.ProbabilityCollection;
|
import com.dfsek.terra.api.util.collection.ProbabilityCollection;
|
||||||
|
|
||||||
@@ -24,10 +23,10 @@ public class ReplaceMutatorTemplate extends StageTemplate {
|
|||||||
private @Meta String from;
|
private @Meta String from;
|
||||||
|
|
||||||
@Value("to")
|
@Value("to")
|
||||||
private @Meta ProbabilityCollection<@Meta BiomeDelegate> to;
|
private @Meta ProbabilityCollection<@Meta PipelineBiome> to;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Stage get() {
|
public Stage get() {
|
||||||
return new MutatorStage(new ReplaceMutator(from, to, noise));
|
return new ReplaceMutator(from, to, noise);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,15 +7,14 @@
|
|||||||
|
|
||||||
package com.dfsek.terra.addons.biome.pipeline.config.stage.mutator;
|
package com.dfsek.terra.addons.biome.pipeline.config.stage.mutator;
|
||||||
|
|
||||||
import com.dfsek.terra.addons.biome.pipeline.api.stage.Stage;
|
|
||||||
import com.dfsek.terra.addons.biome.pipeline.config.stage.StageTemplate;
|
import com.dfsek.terra.addons.biome.pipeline.config.stage.StageTemplate;
|
||||||
import com.dfsek.terra.addons.biome.pipeline.mutator.SmoothMutator;
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.api.Stage;
|
||||||
import com.dfsek.terra.addons.biome.pipeline.stages.MutatorStage;
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.stage.mutators.SmoothMutator;
|
||||||
|
|
||||||
|
|
||||||
public class SmoothMutatorTemplate extends StageTemplate {
|
public class SmoothMutatorTemplate extends StageTemplate {
|
||||||
@Override
|
@Override
|
||||||
public Stage get() {
|
public Stage get() {
|
||||||
return new MutatorStage(new SmoothMutator(noise));
|
return new SmoothMutator(noise);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,27 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.biome.pipeline.expand;
|
|
||||||
|
|
||||||
import com.dfsek.terra.addons.biome.pipeline.api.delegate.BiomeDelegate;
|
|
||||||
import com.dfsek.terra.addons.biome.pipeline.api.stage.type.BiomeExpander;
|
|
||||||
import com.dfsek.terra.api.noise.NoiseSampler;
|
|
||||||
import com.dfsek.terra.api.util.MathUtil;
|
|
||||||
|
|
||||||
|
|
||||||
public class FractalExpander implements BiomeExpander {
|
|
||||||
private final NoiseSampler sampler;
|
|
||||||
|
|
||||||
public FractalExpander(NoiseSampler sampler) {
|
|
||||||
this.sampler = sampler;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BiomeDelegate getBetween(double x, double z, long seed, BiomeDelegate... others) {
|
|
||||||
return others[MathUtil.normalizeIndex(sampler.noise(seed, x, z), others.length)];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.biome.pipeline.mutator;
|
|
||||||
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.function.Predicate;
|
|
||||||
|
|
||||||
import com.dfsek.terra.addons.biome.pipeline.api.delegate.BiomeDelegate;
|
|
||||||
import com.dfsek.terra.addons.biome.pipeline.api.stage.type.BiomeMutator;
|
|
||||||
import com.dfsek.terra.api.noise.NoiseSampler;
|
|
||||||
import com.dfsek.terra.api.util.collection.ProbabilityCollection;
|
|
||||||
|
|
||||||
|
|
||||||
public class BorderListMutator implements BiomeMutator {
|
|
||||||
private final String border;
|
|
||||||
private final NoiseSampler noiseSampler;
|
|
||||||
private final ProbabilityCollection<BiomeDelegate> replaceDefault;
|
|
||||||
private final String defaultReplace;
|
|
||||||
private final Map<BiomeDelegate, ProbabilityCollection<BiomeDelegate>> replace;
|
|
||||||
|
|
||||||
public BorderListMutator(Map<BiomeDelegate, ProbabilityCollection<BiomeDelegate>> replace, String border, String defaultReplace,
|
|
||||||
NoiseSampler noiseSampler, ProbabilityCollection<BiomeDelegate> replaceDefault) {
|
|
||||||
this.border = border;
|
|
||||||
this.noiseSampler = noiseSampler;
|
|
||||||
this.replaceDefault = replaceDefault;
|
|
||||||
this.defaultReplace = defaultReplace;
|
|
||||||
this.replace = replace;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BiomeDelegate mutate(ViewPoint viewPoint, double x, double z, long seed) {
|
|
||||||
BiomeDelegate origin = viewPoint.getBiome(0, 0);
|
|
||||||
if(origin.getTags().contains(defaultReplace)) {
|
|
||||||
for(int xi = -1; xi <= 1; xi++) {
|
|
||||||
for(int zi = -1; zi <= 1; zi++) {
|
|
||||||
if(xi == 0 && zi == 0) continue;
|
|
||||||
BiomeDelegate current = viewPoint.getBiome(xi, zi);
|
|
||||||
if(current != null && current.getTags().contains(border)) {
|
|
||||||
if(replace.containsKey(origin)) {
|
|
||||||
BiomeDelegate biome = replace.get(origin).get(noiseSampler, x, z, seed);
|
|
||||||
return biome.isSelf() ? origin : biome;
|
|
||||||
}
|
|
||||||
BiomeDelegate biome = replaceDefault.get(noiseSampler, x, z, seed);
|
|
||||||
return biome.isSelf() ? origin : biome;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return origin;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Iterable<BiomeDelegate> getBiomes(Iterable<BiomeDelegate> biomes) {
|
|
||||||
Set<BiomeDelegate> biomeSet = new HashSet<>();
|
|
||||||
biomes.forEach(biomeSet::add);
|
|
||||||
biomeSet.addAll(replaceDefault.getContents().stream().filter(Predicate.not(BiomeDelegate::isSelf)).toList());
|
|
||||||
replace.forEach((biome, collection) -> biomeSet.addAll(collection.getContents()));
|
|
||||||
return biomeSet;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.biome.pipeline.mutator;
|
|
||||||
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.function.Predicate;
|
|
||||||
|
|
||||||
import com.dfsek.terra.addons.biome.pipeline.api.delegate.BiomeDelegate;
|
|
||||||
import com.dfsek.terra.addons.biome.pipeline.api.stage.type.BiomeMutator;
|
|
||||||
import com.dfsek.terra.api.noise.NoiseSampler;
|
|
||||||
import com.dfsek.terra.api.util.collection.ProbabilityCollection;
|
|
||||||
|
|
||||||
|
|
||||||
public class BorderMutator implements BiomeMutator {
|
|
||||||
private final String border;
|
|
||||||
private final NoiseSampler noiseSampler;
|
|
||||||
private final ProbabilityCollection<BiomeDelegate> replace;
|
|
||||||
private final String replaceTag;
|
|
||||||
|
|
||||||
public BorderMutator(String border, String replaceTag, NoiseSampler noiseSampler, ProbabilityCollection<BiomeDelegate> replace) {
|
|
||||||
this.border = border;
|
|
||||||
this.noiseSampler = noiseSampler;
|
|
||||||
this.replace = replace;
|
|
||||||
this.replaceTag = replaceTag;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BiomeDelegate mutate(ViewPoint viewPoint, double x, double z, long seed) {
|
|
||||||
BiomeDelegate origin = viewPoint.getBiome(0, 0);
|
|
||||||
if(origin.getTags().contains(replaceTag)) {
|
|
||||||
for(int xi = -1; xi <= 1; xi++) {
|
|
||||||
for(int zi = -1; zi <= 1; zi++) {
|
|
||||||
if(xi == 0 && zi == 0) continue;
|
|
||||||
BiomeDelegate current = viewPoint.getBiome(xi, zi);
|
|
||||||
if(current != null && current.getTags().contains(border)) {
|
|
||||||
BiomeDelegate biome = replace.get(noiseSampler, x, z, seed);
|
|
||||||
return biome.isSelf() ? origin : biome;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return origin;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Iterable<BiomeDelegate> getBiomes(Iterable<BiomeDelegate> biomes) {
|
|
||||||
Set<BiomeDelegate> biomeSet = new HashSet<>();
|
|
||||||
biomes.forEach(biomeSet::add);
|
|
||||||
biomeSet.addAll(
|
|
||||||
replace
|
|
||||||
.getContents()
|
|
||||||
.stream()
|
|
||||||
.filter(
|
|
||||||
Predicate.not(BiomeDelegate::isSelf)
|
|
||||||
)
|
|
||||||
.toList()
|
|
||||||
);
|
|
||||||
return biomeSet;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.biome.pipeline.mutator;
|
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import com.dfsek.terra.addons.biome.pipeline.api.delegate.BiomeDelegate;
|
|
||||||
import com.dfsek.terra.addons.biome.pipeline.api.stage.type.BiomeMutator;
|
|
||||||
import com.dfsek.terra.api.noise.NoiseSampler;
|
|
||||||
import com.dfsek.terra.api.util.MathUtil;
|
|
||||||
|
|
||||||
|
|
||||||
public class SmoothMutator implements BiomeMutator {
|
|
||||||
|
|
||||||
private final NoiseSampler sampler;
|
|
||||||
|
|
||||||
public SmoothMutator(NoiseSampler sampler) {
|
|
||||||
this.sampler = sampler;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BiomeDelegate mutate(ViewPoint viewPoint, double x, double z, long seed) {
|
|
||||||
BiomeDelegate top = viewPoint.getBiome(1, 0);
|
|
||||||
BiomeDelegate bottom = viewPoint.getBiome(-1, 0);
|
|
||||||
BiomeDelegate left = viewPoint.getBiome(0, 1);
|
|
||||||
BiomeDelegate right = viewPoint.getBiome(0, -1);
|
|
||||||
|
|
||||||
|
|
||||||
boolean vert = Objects.equals(top, bottom) && top != null;
|
|
||||||
boolean horiz = Objects.equals(left, right) && left != null;
|
|
||||||
|
|
||||||
if(vert && horiz) {
|
|
||||||
return MathUtil.normalizeIndex(sampler.noise(seed, x, z), 2) == 0 ? left : top;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(vert) return top;
|
|
||||||
if(horiz) return left;
|
|
||||||
|
|
||||||
return viewPoint.getBiome(0, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,215 @@
|
|||||||
|
package com.dfsek.terra.addons.biome.pipeline.reimplementation;
|
||||||
|
|
||||||
|
import net.jafama.FastMath;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.api.BiomeChunk;
|
||||||
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.api.Expander;
|
||||||
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.api.Stage;
|
||||||
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.api.biome.PipelineBiome;
|
||||||
|
|
||||||
|
|
||||||
|
public class BiomeChunkImpl implements BiomeChunk {
|
||||||
|
|
||||||
|
private PipelineBiome[][] biomes;
|
||||||
|
private final SeededVector worldOrigin;
|
||||||
|
private final int chunkOriginArrayIndex;
|
||||||
|
|
||||||
|
public BiomeChunkImpl(SeededVector worldOrigin, PipelineImpl pipeline) {
|
||||||
|
|
||||||
|
this.worldOrigin = worldOrigin;
|
||||||
|
this.chunkOriginArrayIndex = pipeline.getChunkOriginArrayIndex();
|
||||||
|
|
||||||
|
int size = pipeline.getArraySize();
|
||||||
|
|
||||||
|
int expanderCount = pipeline.getExpanderCount();
|
||||||
|
int expansionsApplied = 0;
|
||||||
|
|
||||||
|
// Allocate working arrays
|
||||||
|
this.biomes = new PipelineBiome[size][size];
|
||||||
|
PipelineBiome[][] lookupArray = new PipelineBiome[size][size];
|
||||||
|
// A second lookup array is required such that stage application doesn't affect lookups, otherwise application may cascade
|
||||||
|
|
||||||
|
// Construct working grid
|
||||||
|
int gridOrigin = 0;
|
||||||
|
int gridInterval = calculateGridInterval(expanderCount, expansionsApplied);
|
||||||
|
int gridSize = (size / gridInterval);
|
||||||
|
gridSize += expanderCount > 0 ? 1 : 0; // Add an extra border if expansion occurs
|
||||||
|
|
||||||
|
// Fill working grid with initial cells
|
||||||
|
for(int gridX = 0; gridX < gridSize; gridX++) {
|
||||||
|
for(int gridZ = 0; gridZ < gridSize; gridZ++) {
|
||||||
|
int xIndex = gridOrigin + gridX * gridInterval;
|
||||||
|
int zIndex = gridOrigin + gridZ * gridInterval;
|
||||||
|
biomes[xIndex][zIndex] = pipeline.getSource().get(worldOrigin.seed(), xIndexToWorldCoordinate(xIndex), zIndexToWorldCoordinate(zIndex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(Stage stage : pipeline.getStages()) {
|
||||||
|
if(stage instanceof Expander) {
|
||||||
|
// Shrink working grid size, the expander will fill in null cells (as a result of shrinking the grid) during mutation
|
||||||
|
expansionsApplied++;
|
||||||
|
gridInterval = calculateGridInterval(expanderCount, expansionsApplied);
|
||||||
|
gridSize = expandSize(gridSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
int stageReadDistance = stage.maxRelativeReadDistance();
|
||||||
|
if(stageReadDistance > 0) {
|
||||||
|
// Discard edges such that adjacent lookups are only ran on valid cells
|
||||||
|
gridSize = contractBordersFromSize(gridSize, stageReadDistance);
|
||||||
|
gridOrigin += stageReadDistance * gridInterval;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cycle arrays, the previously populated array is swapped to be used for lookups, and the result of the stage application
|
||||||
|
// overwrites the previous lookup array. This saves having to allocate a new array copy each time
|
||||||
|
PipelineBiome[][] tempArray = biomes;
|
||||||
|
biomes = lookupArray;
|
||||||
|
lookupArray = tempArray;
|
||||||
|
|
||||||
|
// Apply stage to working grid
|
||||||
|
for(int gridZ = 0; gridZ < gridSize; gridZ = gridZ + 1) {
|
||||||
|
for(int gridX = 0; gridX < gridSize; gridX = gridX + 1) {
|
||||||
|
int xIndex = gridOrigin + gridX * gridInterval;
|
||||||
|
int zIndex = gridOrigin + gridZ * gridInterval;
|
||||||
|
biomes[xIndex][zIndex] = stage.apply(new ViewPoint(this, gridInterval, gridX, gridZ, xIndex, zIndex, lookupArray));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PipelineBiome get(int xInChunk, int zInChunk) {
|
||||||
|
int xIndex = xInChunk + chunkOriginArrayIndex;
|
||||||
|
int zIndex = zInChunk + chunkOriginArrayIndex;
|
||||||
|
return biomes[xIndex][zIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
private int xIndexToWorldCoordinate(int xIndex) {
|
||||||
|
return worldOrigin.x() + xIndex - chunkOriginArrayIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int zIndexToWorldCoordinate(int zIndex) {
|
||||||
|
return worldOrigin.z() + zIndex - chunkOriginArrayIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static int initialSizeToArraySize(int expanderCount, int initialSize) {
|
||||||
|
int size = initialSize;
|
||||||
|
for(int i = 0; i < expanderCount; i++) {
|
||||||
|
size = expandSize(size);
|
||||||
|
}
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static int calculateChunkOriginArrayIndex(int totalExpanderCount, List<Stage> stages) {
|
||||||
|
int finalGridOrigin = calculateFinalGridOrigin(totalExpanderCount, stages);
|
||||||
|
int initialGridInterval = calculateGridInterval(totalExpanderCount, 0);
|
||||||
|
|
||||||
|
// Round the final grid origin up to the nearest multiple of initialGridInterval, such that each
|
||||||
|
// chunk samples points on the same overall grid.
|
||||||
|
// Without this, shared chunk borders (required because of adjacent cell reads) will not be identical
|
||||||
|
// because points would be sampled on grids at different offsets, resulting in artifacts at borders.
|
||||||
|
return FastMath.ceilToInt((double) finalGridOrigin / initialGridInterval) * initialGridInterval;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int calculateFinalGridOrigin(int totalExpanderCount, List<Stage> stages) {
|
||||||
|
int gridOrigin = 0;
|
||||||
|
int expansionsApplied = 0;
|
||||||
|
int gridInterval = calculateGridInterval(totalExpanderCount, expansionsApplied);
|
||||||
|
for (Stage stage : stages) {
|
||||||
|
if (stage instanceof Expander) {
|
||||||
|
expansionsApplied++;
|
||||||
|
gridInterval = calculateGridInterval(totalExpanderCount, expansionsApplied);
|
||||||
|
}
|
||||||
|
gridOrigin += stage.maxRelativeReadDistance() * gridInterval;
|
||||||
|
}
|
||||||
|
return gridOrigin;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static int calculateChunkSize(int arraySize, int chunkOriginArrayIndex, int totalExpanderCount) {
|
||||||
|
return contractBordersFromSize(arraySize, chunkOriginArrayIndex) - (totalExpanderCount > 0 ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int expandSize(int size) {
|
||||||
|
return size * 2 - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int contractBordersFromSize(int size, int border) {
|
||||||
|
return size - border * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int calculateGridInterval(int totalExpansions, int expansionsApplied) {
|
||||||
|
return 1 << (totalExpansions - expansionsApplied);
|
||||||
|
}
|
||||||
|
|
||||||
|
private SeededVector getOrigin() {
|
||||||
|
return worldOrigin;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a point on the operating grid within the biomes array
|
||||||
|
*/
|
||||||
|
public static class ViewPoint {
|
||||||
|
private final BiomeChunkImpl chunk;
|
||||||
|
private final PipelineBiome biome;
|
||||||
|
private final int gridInterval;
|
||||||
|
private final int gridX;
|
||||||
|
private final int gridZ;
|
||||||
|
private final int xIndex;
|
||||||
|
private final int zIndex;
|
||||||
|
private final PipelineBiome[][] lookupArray;
|
||||||
|
|
||||||
|
private ViewPoint(BiomeChunkImpl chunk, int gridInterval, int gridX, int gridZ, int xIndex, int zIndex, PipelineBiome[][] lookupArray) {
|
||||||
|
this.chunk = chunk;
|
||||||
|
this.gridInterval = gridInterval;
|
||||||
|
this.gridX = gridX;
|
||||||
|
this.gridZ = gridZ;
|
||||||
|
this.xIndex = xIndex;
|
||||||
|
this.zIndex = zIndex;
|
||||||
|
this.lookupArray = lookupArray;
|
||||||
|
this.biome = lookupArray[xIndex][zIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
public PipelineBiome getRelativeBiome(int x, int z) {
|
||||||
|
int lookupXIndex = this.xIndex + x * gridInterval;
|
||||||
|
int lookupZIndex = this.zIndex + z * gridInterval;
|
||||||
|
return lookupArray[lookupXIndex][lookupZIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
public PipelineBiome getBiome() {
|
||||||
|
return biome;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return X position of the point relative to the operating grid
|
||||||
|
*/
|
||||||
|
public int gridX() {
|
||||||
|
return gridX;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Z position of the point relative to the operating grid
|
||||||
|
*/
|
||||||
|
public int gridZ() {
|
||||||
|
return gridZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return X position of the point in the world
|
||||||
|
*/
|
||||||
|
public int worldX() {
|
||||||
|
return chunk.xIndexToWorldCoordinate(xIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Z position of the point in the world
|
||||||
|
*/
|
||||||
|
public int worldZ() {
|
||||||
|
return chunk.zIndexToWorldCoordinate(zIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public long worldSeed() {
|
||||||
|
return chunk.getOrigin().seed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,112 @@
|
|||||||
|
package com.dfsek.terra.addons.biome.pipeline.reimplementation;
|
||||||
|
|
||||||
|
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||||
|
import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||||
|
import net.jafama.FastMath;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.StreamSupport;
|
||||||
|
|
||||||
|
import com.dfsek.terra.addons.biome.pipeline.BiomePipelineColumn;
|
||||||
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.api.BiomeChunk;
|
||||||
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.api.Pipeline;
|
||||||
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.api.Stage;
|
||||||
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.api.biome.PipelineBiome;
|
||||||
|
import com.dfsek.terra.api.noise.NoiseSampler;
|
||||||
|
import com.dfsek.terra.api.registry.key.StringIdentifiable;
|
||||||
|
import com.dfsek.terra.api.util.Column;
|
||||||
|
import com.dfsek.terra.api.world.biome.Biome;
|
||||||
|
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
|
||||||
|
|
||||||
|
|
||||||
|
public class PipelineBiomeProvider implements BiomeProvider {
|
||||||
|
|
||||||
|
private final LoadingCache<SeededVector, BiomeChunk> biomeChunkCache;
|
||||||
|
private final int chunkSize;
|
||||||
|
private final int resolution;
|
||||||
|
private final NoiseSampler mutator;
|
||||||
|
private final double noiseAmp;
|
||||||
|
private final Set<Biome> biomes;
|
||||||
|
|
||||||
|
public PipelineBiomeProvider(Pipeline pipeline, int resolution, NoiseSampler mutator, double noiseAmp) {
|
||||||
|
this.resolution = resolution;
|
||||||
|
this.mutator = mutator;
|
||||||
|
this.noiseAmp = noiseAmp;
|
||||||
|
this.chunkSize = pipeline.getChunkSize();
|
||||||
|
this.biomeChunkCache = Caffeine.newBuilder()
|
||||||
|
.maximumSize(1024)
|
||||||
|
.build(pipeline::generateChunk);
|
||||||
|
|
||||||
|
Set<PipelineBiome> biomeSet = new HashSet<>();
|
||||||
|
pipeline.getSource().getBiomes().forEach(biomeSet::add);
|
||||||
|
Iterable<PipelineBiome> result = biomeSet;
|
||||||
|
for(Stage stage : pipeline.getStages()) {
|
||||||
|
result = stage.getBiomes(result);
|
||||||
|
}
|
||||||
|
this.biomes = new HashSet<>();
|
||||||
|
Iterable<PipelineBiome> finalResult = result;
|
||||||
|
result.forEach(pipelineBiome -> {
|
||||||
|
if(pipelineBiome.isEphemeral()) {
|
||||||
|
|
||||||
|
StringBuilder biomeList = new StringBuilder("\n");
|
||||||
|
StreamSupport.stream(finalResult.spliterator(), false)
|
||||||
|
.sorted(Comparator.comparing(StringIdentifiable::getID))
|
||||||
|
.forEach(delegate -> biomeList
|
||||||
|
.append(" - ")
|
||||||
|
.append(delegate.getID())
|
||||||
|
.append(':')
|
||||||
|
.append(delegate.getClass().getCanonicalName())
|
||||||
|
.append('\n'));
|
||||||
|
throw new IllegalArgumentException("Biome Pipeline leaks ephemeral biome \"" + pipelineBiome.getID() +
|
||||||
|
"\". Ensure there is a stage to guarantee replacement of the ephemeral biome. Biomes: " +
|
||||||
|
biomeList);
|
||||||
|
}
|
||||||
|
this.biomes.add(pipelineBiome.getBiome());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Biome getBiome(int x, int y, int z, long seed) {
|
||||||
|
return getBiome(x, z, seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Biome getBiome(int x, int z, long seed) {
|
||||||
|
|
||||||
|
// x += mutator.noise(seed + 1, x, z) * noiseAmp;
|
||||||
|
// z += mutator.noise(seed + 2, x, z) * noiseAmp;
|
||||||
|
|
||||||
|
// x /= resolution;
|
||||||
|
// z /= resolution;
|
||||||
|
|
||||||
|
// x *= resolution;
|
||||||
|
// z *= resolution;
|
||||||
|
|
||||||
|
int chunkX = FastMath.floorDiv(x, chunkSize);
|
||||||
|
int chunkZ = FastMath.floorDiv(z, chunkSize);
|
||||||
|
|
||||||
|
int chunkWorldX = chunkX * chunkSize;
|
||||||
|
int chunkWorldZ = chunkZ * chunkSize;
|
||||||
|
|
||||||
|
int xInChunk = x - chunkWorldX;
|
||||||
|
int zInChunk = z - chunkWorldZ;
|
||||||
|
|
||||||
|
return biomeChunkCache.get(new SeededVector(seed, chunkWorldX, chunkWorldZ)).get(xInChunk, zInChunk).getBiome();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<Biome> getBiomes() {
|
||||||
|
return biomes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Column<Biome> getColumn(int x, int z, long seed, int min, int max) {
|
||||||
|
return new BiomePipelineColumn(this, min, max, x, z, seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int resolution() {
|
||||||
|
return resolution;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
package com.dfsek.terra.addons.biome.pipeline.reimplementation;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.api.BiomeChunk;
|
||||||
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.api.Expander;
|
||||||
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.api.Pipeline;
|
||||||
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.api.Source;
|
||||||
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.api.Stage;
|
||||||
|
|
||||||
|
|
||||||
|
public class PipelineImpl implements Pipeline {
|
||||||
|
|
||||||
|
// private static final Logger logger = LoggerFactory.getLogger(PipelineImpl.class);
|
||||||
|
|
||||||
|
private final Source source;
|
||||||
|
private final List<Stage> stages;
|
||||||
|
private final int chunkSize;
|
||||||
|
private final int expanderCount;
|
||||||
|
private final int arraySize;
|
||||||
|
private final int chunkOriginArrayIndex;
|
||||||
|
|
||||||
|
public PipelineImpl(Source source, List<Stage> stages, int idealChunkArraySize) {
|
||||||
|
this.source = source;
|
||||||
|
this.stages = stages;
|
||||||
|
this.expanderCount = (int) stages.stream().filter(s -> s instanceof Expander).count();
|
||||||
|
|
||||||
|
// Optimize for the ideal array size
|
||||||
|
int arraySize;
|
||||||
|
int chunkOriginArrayIndex;
|
||||||
|
int chunkSize;
|
||||||
|
int initialSize = 1;
|
||||||
|
while (true) {
|
||||||
|
arraySize = BiomeChunkImpl.initialSizeToArraySize(expanderCount, initialSize);
|
||||||
|
chunkOriginArrayIndex = BiomeChunkImpl.calculateChunkOriginArrayIndex(expanderCount, stages);
|
||||||
|
chunkSize = BiomeChunkImpl.calculateChunkSize(arraySize, chunkOriginArrayIndex, expanderCount);
|
||||||
|
if (chunkSize > 1 && arraySize >= idealChunkArraySize) break;
|
||||||
|
initialSize++;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.arraySize = arraySize;
|
||||||
|
this.chunkOriginArrayIndex = chunkOriginArrayIndex;
|
||||||
|
this.chunkSize = chunkSize;
|
||||||
|
|
||||||
|
System.out.println("Initialized a new biome pipeline:");
|
||||||
|
System.out.println("Array size: " + arraySize + " (Target: " + idealChunkArraySize + ")");
|
||||||
|
System.out.println("Internal array origin: " + chunkOriginArrayIndex);
|
||||||
|
System.out.println("Chunk size: " + chunkSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BiomeChunk generateChunk(SeededVector worldCoordinates) {
|
||||||
|
return new BiomeChunkImpl(worldCoordinates, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getChunkSize() {
|
||||||
|
return chunkSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Source getSource() {
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Stage> getStages() {
|
||||||
|
return stages;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getExpanderCount() {
|
||||||
|
return expanderCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getArraySize() {
|
||||||
|
return arraySize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getChunkOriginArrayIndex() {
|
||||||
|
return chunkOriginArrayIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package com.dfsek.terra.addons.biome.pipeline.reimplementation;
|
||||||
|
|
||||||
|
public record SeededVector(long seed, int x, int z) {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if(obj instanceof SeededVector that) {
|
||||||
|
return this.z == that.z && this.x == that.x && this.seed == that.seed;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int code = x;
|
||||||
|
code = 31 * code + z;
|
||||||
|
return 31 * code + ((int) (seed ^ (seed >>> 32)));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package com.dfsek.terra.addons.biome.pipeline.reimplementation;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.properties.Context;
|
||||||
|
import com.dfsek.terra.api.world.biome.Biome;
|
||||||
|
import com.dfsek.terra.api.world.biome.PlatformBiome;
|
||||||
|
|
||||||
|
public record StringBiome(String name, String string) implements Biome {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Context getContext() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getID() {
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<PlatformBiome> getPlatformBiome() {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPlatformBiome(PlatformBiome biome) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getColor() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> getTags() {
|
||||||
|
return Set.of(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package com.dfsek.terra.addons.biome.pipeline.reimplementation.api;
|
||||||
|
|
||||||
|
|
||||||
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.api.biome.PipelineBiome;
|
||||||
|
|
||||||
|
|
||||||
|
public interface BiomeChunk {
|
||||||
|
|
||||||
|
PipelineBiome get(int xInChunk, int zInChunk);
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package com.dfsek.terra.addons.biome.pipeline.reimplementation.api;
|
||||||
|
|
||||||
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.BiomeChunkImpl.ViewPoint;
|
||||||
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.api.biome.PipelineBiome;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resizes the internal grid of a BiomeChunk when applied, serves the purpose of
|
||||||
|
* filling in null biomes as a result of this resizing.
|
||||||
|
*/
|
||||||
|
public interface Expander extends Stage {
|
||||||
|
|
||||||
|
PipelineBiome fillBiome(ViewPoint viewPoint);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default int maxRelativeReadDistance() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default PipelineBiome apply(ViewPoint viewPoint) {
|
||||||
|
PipelineBiome currentBiome = viewPoint.getBiome();
|
||||||
|
if(currentBiome == null) {
|
||||||
|
return fillBiome(viewPoint);
|
||||||
|
} else {
|
||||||
|
return currentBiome;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package com.dfsek.terra.addons.biome.pipeline.reimplementation.api;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.SeededVector;
|
||||||
|
|
||||||
|
|
||||||
|
public interface Pipeline {
|
||||||
|
BiomeChunk generateChunk(SeededVector worldCoordinates);
|
||||||
|
|
||||||
|
int getChunkSize();
|
||||||
|
|
||||||
|
Source getSource();
|
||||||
|
|
||||||
|
List<Stage> getStages();
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package com.dfsek.terra.addons.biome.pipeline.reimplementation.api;
|
||||||
|
|
||||||
|
|
||||||
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.api.biome.PipelineBiome;
|
||||||
|
|
||||||
|
|
||||||
|
public interface Source {
|
||||||
|
PipelineBiome get(long seed, int x, int z);
|
||||||
|
|
||||||
|
Iterable<PipelineBiome> getBiomes();
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package com.dfsek.terra.addons.biome.pipeline.reimplementation.api;
|
||||||
|
|
||||||
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.BiomeChunkImpl.ViewPoint;
|
||||||
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.api.biome.PipelineBiome;
|
||||||
|
|
||||||
|
|
||||||
|
public interface Stage {
|
||||||
|
PipelineBiome apply(ViewPoint viewPoint);
|
||||||
|
|
||||||
|
int maxRelativeReadDistance();
|
||||||
|
|
||||||
|
default Iterable<PipelineBiome> getBiomes(Iterable<PipelineBiome> biomes) {
|
||||||
|
return biomes;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package com.dfsek.terra.addons.biome.pipeline.reimplementation.api.biome;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.world.biome.Biome;
|
||||||
|
|
||||||
|
|
||||||
|
public final class DelegatedBiome implements PipelineBiome {
|
||||||
|
private final Biome biome;
|
||||||
|
|
||||||
|
public DelegatedBiome(Biome biome) {
|
||||||
|
this.biome = biome;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Biome getBiome() {
|
||||||
|
return biome;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return biome.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if(!(obj instanceof DelegatedBiome that)) return false;
|
||||||
|
return that.biome.equals(this.biome);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> getTags() {
|
||||||
|
return biome.getTags();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getID() {
|
||||||
|
return biome.getID();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package com.dfsek.terra.addons.biome.pipeline.reimplementation.api.biome;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.world.biome.Biome;
|
||||||
|
|
||||||
|
|
||||||
|
final class EphemeralBiomeDelegate implements PipelineBiome {
|
||||||
|
private final Set<String> tags;
|
||||||
|
private final String id;
|
||||||
|
|
||||||
|
public EphemeralBiomeDelegate(String id) {
|
||||||
|
this.id = id;
|
||||||
|
tags = new HashSet<>();
|
||||||
|
tags.add(id);
|
||||||
|
tags.add("ALL");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Biome getBiome() {
|
||||||
|
throw new UnsupportedOperationException("Cannot get biome from ephemeral delegate");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> getTags() {
|
||||||
|
return tags;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getID() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEphemeral() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return id.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if(!(obj instanceof EphemeralBiomeDelegate that)) return false;
|
||||||
|
|
||||||
|
return this.id.equals(that.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package com.dfsek.terra.addons.biome.pipeline.reimplementation.api.biome;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.registry.key.StringIdentifiable;
|
||||||
|
import com.dfsek.terra.api.world.biome.Biome;
|
||||||
|
|
||||||
|
|
||||||
|
public interface PipelineBiome extends StringIdentifiable {
|
||||||
|
Biome getBiome();
|
||||||
|
|
||||||
|
static PipelineBiome ephemeral(String id) {
|
||||||
|
return new EphemeralBiomeDelegate(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
static PipelineBiome from(Biome biome) {
|
||||||
|
return new DelegatedBiome(biome);
|
||||||
|
}
|
||||||
|
|
||||||
|
static PipelineBiome self() {
|
||||||
|
return SelfDelegate.INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<String> getTags();
|
||||||
|
|
||||||
|
default boolean isEphemeral() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
default boolean isSelf() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package com.dfsek.terra.addons.biome.pipeline.reimplementation.api.biome;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.world.biome.Biome;
|
||||||
|
|
||||||
|
|
||||||
|
final class SelfDelegate implements PipelineBiome {
|
||||||
|
public static final SelfDelegate INSTANCE = new SelfDelegate();
|
||||||
|
|
||||||
|
private SelfDelegate() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Biome getBiome() {
|
||||||
|
throw new UnsupportedOperationException("Cannot get biome from self delegate");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSelf() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEphemeral() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> getTags() {
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getID() {
|
||||||
|
return "SELF";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package com.dfsek.terra.addons.biome.pipeline.reimplementation.source;
|
||||||
|
|
||||||
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.api.Source;
|
||||||
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.api.biome.PipelineBiome;
|
||||||
|
import com.dfsek.terra.api.noise.NoiseSampler;
|
||||||
|
import com.dfsek.terra.api.util.collection.ProbabilityCollection;
|
||||||
|
|
||||||
|
|
||||||
|
public class SamplerSource implements Source {
|
||||||
|
private final ProbabilityCollection<PipelineBiome> biomes;
|
||||||
|
private final NoiseSampler sampler;
|
||||||
|
|
||||||
|
public SamplerSource(ProbabilityCollection<PipelineBiome> biomes, NoiseSampler sampler) {
|
||||||
|
this.biomes = biomes;
|
||||||
|
this.sampler = sampler;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PipelineBiome get(long seed, int x, int z) {
|
||||||
|
return biomes.get(sampler, x, z, seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<PipelineBiome> getBiomes() {
|
||||||
|
return biomes.getContents();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package com.dfsek.terra.addons.biome.pipeline.reimplementation.source;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.api.biome.PipelineBiome;
|
||||||
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.api.Source;
|
||||||
|
|
||||||
|
|
||||||
|
public class SingleSource implements Source {
|
||||||
|
|
||||||
|
private final PipelineBiome biome;
|
||||||
|
|
||||||
|
public SingleSource(PipelineBiome biome) {
|
||||||
|
this.biome = biome;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PipelineBiome get(long seed, int x, int z) {
|
||||||
|
return biome;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<PipelineBiome> getBiomes() {
|
||||||
|
return Collections.singleton(biome);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package com.dfsek.terra.addons.biome.pipeline.reimplementation.stage.expander;
|
||||||
|
|
||||||
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.BiomeChunkImpl.ViewPoint;
|
||||||
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.api.Expander;
|
||||||
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.api.biome.PipelineBiome;
|
||||||
|
|
||||||
|
|
||||||
|
public class DebugExpander implements Expander {
|
||||||
|
|
||||||
|
private final PipelineBiome biome;
|
||||||
|
|
||||||
|
public DebugExpander(PipelineBiome biome) {
|
||||||
|
this.biome = biome;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PipelineBiome fillBiome(ViewPoint viewPoint) {
|
||||||
|
return biome;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package com.dfsek.terra.addons.biome.pipeline.reimplementation.stage.expander;
|
||||||
|
|
||||||
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.BiomeChunkImpl.ViewPoint;
|
||||||
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.api.Expander;
|
||||||
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.api.biome.PipelineBiome;
|
||||||
|
import com.dfsek.terra.api.noise.NoiseSampler;
|
||||||
|
|
||||||
|
|
||||||
|
public class FractalExpander implements Expander {
|
||||||
|
|
||||||
|
private final NoiseSampler sampler;
|
||||||
|
|
||||||
|
public FractalExpander(NoiseSampler sampler) {
|
||||||
|
this.sampler = sampler;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PipelineBiome fillBiome(ViewPoint viewPoint) {
|
||||||
|
|
||||||
|
int xMod2 = viewPoint.gridX() % 2;
|
||||||
|
int zMod2 = viewPoint.gridZ() % 2;
|
||||||
|
|
||||||
|
double roll = sampler.noise(viewPoint.worldSeed(), viewPoint.worldX(), viewPoint.worldZ());
|
||||||
|
|
||||||
|
if (xMod2 == 1 && zMod2 == 0) { // Pick one of 2 neighbors on X axis randomly
|
||||||
|
return roll > 0 ? viewPoint.getRelativeBiome(-1, 0) : viewPoint.getRelativeBiome(1, 0);
|
||||||
|
|
||||||
|
} else if (xMod2 == 0 && zMod2 == 1) { // Pick one of 2 neighbors on Z axis randomly
|
||||||
|
return roll > 0 ? viewPoint.getRelativeBiome(0, -1) : viewPoint.getRelativeBiome(0, 1);
|
||||||
|
|
||||||
|
} else { // Pick one of 4 corners randomly
|
||||||
|
return roll > 0 ?
|
||||||
|
roll > 0.25 ? viewPoint.getRelativeBiome(-1, 1) : viewPoint.getRelativeBiome(1, 1) :
|
||||||
|
roll > -0.25 ? viewPoint.getRelativeBiome(-1, -1) : viewPoint.getRelativeBiome(1, -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* 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.biome.pipeline.reimplementation.stage.mutators;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.BiomeChunkImpl.ViewPoint;
|
||||||
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.api.Stage;
|
||||||
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.api.biome.PipelineBiome;
|
||||||
|
import com.dfsek.terra.api.noise.NoiseSampler;
|
||||||
|
import com.dfsek.terra.api.util.collection.ProbabilityCollection;
|
||||||
|
import com.dfsek.terra.api.util.vector.Vector2Int;
|
||||||
|
|
||||||
|
|
||||||
|
public class BorderListMutator implements Stage {
|
||||||
|
private final String border;
|
||||||
|
private final NoiseSampler noiseSampler;
|
||||||
|
private final ProbabilityCollection<PipelineBiome> replaceDefault;
|
||||||
|
private final String defaultReplace;
|
||||||
|
private final Map<PipelineBiome, ProbabilityCollection<PipelineBiome>> replace;
|
||||||
|
|
||||||
|
private final Vector2Int[] borderPoints;
|
||||||
|
|
||||||
|
public BorderListMutator(Map<PipelineBiome, ProbabilityCollection<PipelineBiome>> replace, String border, String defaultReplace,
|
||||||
|
NoiseSampler noiseSampler, ProbabilityCollection<PipelineBiome> replaceDefault) {
|
||||||
|
this.border = border;
|
||||||
|
this.noiseSampler = noiseSampler;
|
||||||
|
this.replaceDefault = replaceDefault;
|
||||||
|
this.defaultReplace = defaultReplace;
|
||||||
|
this.replace = replace;
|
||||||
|
|
||||||
|
List<Vector2Int> points = new ArrayList<>();
|
||||||
|
for(int x = -1; x <= 1; x++) {
|
||||||
|
for(int z = -1; z <= 1; z++) {
|
||||||
|
if(x == 0 && z == 0) continue;
|
||||||
|
points.add(Vector2Int.of(x, z));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.borderPoints = points.toArray(new Vector2Int[0]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<PipelineBiome> getBiomes(Iterable<PipelineBiome> biomes) {
|
||||||
|
Set<PipelineBiome> biomeSet = new HashSet<>();
|
||||||
|
biomes.forEach(biomeSet::add);
|
||||||
|
biomeSet.addAll(replaceDefault.getContents().stream().filter(Predicate.not(PipelineBiome::isSelf)).toList());
|
||||||
|
replace.forEach((biome, collection) -> biomeSet.addAll(collection.getContents()));
|
||||||
|
return biomeSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PipelineBiome apply(ViewPoint viewPoint) {
|
||||||
|
PipelineBiome center = viewPoint.getBiome();
|
||||||
|
if(center.getTags().contains(defaultReplace)) {
|
||||||
|
for(Vector2Int point : borderPoints) {
|
||||||
|
PipelineBiome current = viewPoint.getRelativeBiome(point.getX(), point.getZ());
|
||||||
|
if(current != null && current.getTags().contains(border)) {
|
||||||
|
if(replace.containsKey(center)) {
|
||||||
|
PipelineBiome replacement = replace.get(center).get(noiseSampler, viewPoint.worldX(), viewPoint.worldZ(),
|
||||||
|
viewPoint.worldSeed());
|
||||||
|
return replacement.isSelf() ? center : replacement;
|
||||||
|
}
|
||||||
|
PipelineBiome replacement = replaceDefault.get(noiseSampler, viewPoint.worldX(), viewPoint.worldZ(), viewPoint.worldSeed());
|
||||||
|
return replacement.isSelf() ? center : replacement;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return center;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int maxRelativeReadDistance() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
* 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.biome.pipeline.reimplementation.stage.mutators;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.BiomeChunkImpl.ViewPoint;
|
||||||
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.api.Stage;
|
||||||
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.api.biome.PipelineBiome;
|
||||||
|
import com.dfsek.terra.api.noise.NoiseSampler;
|
||||||
|
import com.dfsek.terra.api.util.collection.ProbabilityCollection;
|
||||||
|
import com.dfsek.terra.api.util.vector.Vector2Int;
|
||||||
|
|
||||||
|
|
||||||
|
public class BorderMutator implements Stage {
|
||||||
|
private final String border;
|
||||||
|
private final NoiseSampler noiseSampler;
|
||||||
|
private final ProbabilityCollection<PipelineBiome> replace;
|
||||||
|
private final String replaceTag;
|
||||||
|
private final Vector2Int[] borderPoints;
|
||||||
|
|
||||||
|
public BorderMutator(String border, String replaceTag, NoiseSampler noiseSampler, ProbabilityCollection<PipelineBiome> replace) {
|
||||||
|
this.border = border;
|
||||||
|
this.noiseSampler = noiseSampler;
|
||||||
|
this.replace = replace;
|
||||||
|
this.replaceTag = replaceTag;
|
||||||
|
List<Vector2Int> points = new ArrayList<>();
|
||||||
|
for(int x = -1; x <= 1; x++) {
|
||||||
|
for(int z = -1; z <= 1; z++) {
|
||||||
|
if(x == 0 && z == 0) continue;
|
||||||
|
points.add(Vector2Int.of(x, z));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.borderPoints = points.toArray(new Vector2Int[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PipelineBiome apply(ViewPoint viewPoint) {
|
||||||
|
PipelineBiome center = viewPoint.getBiome();
|
||||||
|
if(center.getTags().contains(replaceTag)) {
|
||||||
|
for(Vector2Int point : borderPoints) {
|
||||||
|
PipelineBiome current = viewPoint.getRelativeBiome(point.getX(), point.getZ());
|
||||||
|
if(current != null && current.getTags().contains(border)) {
|
||||||
|
PipelineBiome replacement = replace.get(noiseSampler, viewPoint.worldX(), viewPoint.worldZ(), viewPoint.worldSeed());
|
||||||
|
return replacement.isSelf() ? center : replacement;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return center;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<PipelineBiome> getBiomes(Iterable<PipelineBiome> biomes) {
|
||||||
|
Set<PipelineBiome> biomeSet = new HashSet<>();
|
||||||
|
biomes.forEach(biomeSet::add);
|
||||||
|
biomeSet.addAll(
|
||||||
|
replace
|
||||||
|
.getContents()
|
||||||
|
.stream()
|
||||||
|
.filter(
|
||||||
|
Predicate.not(PipelineBiome::isSelf)
|
||||||
|
)
|
||||||
|
.toList()
|
||||||
|
);
|
||||||
|
return biomeSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int maxRelativeReadDistance() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,27 +5,28 @@
|
|||||||
* reference the LICENSE file in this module's root directory.
|
* reference the LICENSE file in this module's root directory.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.dfsek.terra.addons.biome.pipeline.mutator;
|
package com.dfsek.terra.addons.biome.pipeline.reimplementation.stage.mutators;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import com.dfsek.terra.addons.biome.pipeline.api.delegate.BiomeDelegate;
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.BiomeChunkImpl.ViewPoint;
|
||||||
import com.dfsek.terra.addons.biome.pipeline.api.stage.type.BiomeMutator;
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.api.Stage;
|
||||||
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.api.biome.PipelineBiome;
|
||||||
import com.dfsek.terra.api.noise.NoiseSampler;
|
import com.dfsek.terra.api.noise.NoiseSampler;
|
||||||
import com.dfsek.terra.api.util.collection.ProbabilityCollection;
|
import com.dfsek.terra.api.util.collection.ProbabilityCollection;
|
||||||
|
|
||||||
|
|
||||||
public class ReplaceListMutator implements BiomeMutator {
|
public class ReplaceListMutator implements Stage {
|
||||||
private final Map<BiomeDelegate, ProbabilityCollection<BiomeDelegate>> replace;
|
private final Map<PipelineBiome, ProbabilityCollection<PipelineBiome>> replace;
|
||||||
private final NoiseSampler sampler;
|
private final NoiseSampler sampler;
|
||||||
private final ProbabilityCollection<BiomeDelegate> replaceDefault;
|
private final ProbabilityCollection<PipelineBiome> replaceDefault;
|
||||||
private final String defaultTag;
|
private final String defaultTag;
|
||||||
|
|
||||||
public ReplaceListMutator(Map<BiomeDelegate, ProbabilityCollection<BiomeDelegate>> replace, String defaultTag,
|
public ReplaceListMutator(Map<PipelineBiome, ProbabilityCollection<PipelineBiome>> replace, String defaultTag,
|
||||||
ProbabilityCollection<BiomeDelegate> replaceDefault, NoiseSampler sampler) {
|
ProbabilityCollection<PipelineBiome> replaceDefault, NoiseSampler sampler) {
|
||||||
this.replace = replace;
|
this.replace = replace;
|
||||||
this.sampler = sampler;
|
this.sampler = sampler;
|
||||||
this.defaultTag = defaultTag;
|
this.defaultTag = defaultTag;
|
||||||
@@ -33,24 +34,29 @@ public class ReplaceListMutator implements BiomeMutator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BiomeDelegate mutate(ViewPoint viewPoint, double x, double z, long seed) {
|
public PipelineBiome apply(ViewPoint viewPoint) {
|
||||||
BiomeDelegate center = viewPoint.getBiome(0, 0);
|
PipelineBiome center = viewPoint.getBiome();
|
||||||
if(replace.containsKey(center)) {
|
if(replace.containsKey(center)) {
|
||||||
BiomeDelegate biome = replace.get(center).get(sampler, x, z, seed);
|
PipelineBiome biome = replace.get(center).get(sampler, viewPoint.worldX(), viewPoint.worldZ(), viewPoint.worldSeed());
|
||||||
return biome.isSelf() ? viewPoint.getBiome(0, 0) : biome;
|
return biome.isSelf() ? viewPoint.getBiome() : biome;
|
||||||
}
|
}
|
||||||
if(viewPoint.getBiome(0, 0).getTags().contains(defaultTag)) {
|
if(viewPoint.getBiome().getTags().contains(defaultTag)) {
|
||||||
BiomeDelegate biome = replaceDefault.get(sampler, x, z, seed);
|
PipelineBiome biome = replaceDefault.get(sampler, viewPoint.worldX(), viewPoint.worldZ(), viewPoint.worldSeed());
|
||||||
return biome.isSelf() ? viewPoint.getBiome(0, 0) : biome;
|
return biome.isSelf() ? viewPoint.getBiome() : biome;
|
||||||
}
|
}
|
||||||
return center;
|
return center;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Iterable<BiomeDelegate> getBiomes(Iterable<BiomeDelegate> biomes) {
|
public int maxRelativeReadDistance() {
|
||||||
Set<BiomeDelegate> biomeSet = new HashSet<>();
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<PipelineBiome> getBiomes(Iterable<PipelineBiome> biomes) {
|
||||||
|
Set<PipelineBiome> biomeSet = new HashSet<>();
|
||||||
|
|
||||||
Set<BiomeDelegate> reject = new HashSet<>();
|
Set<PipelineBiome> reject = new HashSet<>();
|
||||||
|
|
||||||
biomes.forEach(biome -> {
|
biomes.forEach(biome -> {
|
||||||
if(!biome.getTags().contains(defaultTag) && !replace.containsKey(biome)) {
|
if(!biome.getTags().contains(defaultTag) && !replace.containsKey(biome)) {
|
||||||
@@ -5,42 +5,48 @@
|
|||||||
* reference the LICENSE file in this module's root directory.
|
* reference the LICENSE file in this module's root directory.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.dfsek.terra.addons.biome.pipeline.mutator;
|
package com.dfsek.terra.addons.biome.pipeline.reimplementation.stage.mutators;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import com.dfsek.terra.addons.biome.pipeline.api.delegate.BiomeDelegate;
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.BiomeChunkImpl.ViewPoint;
|
||||||
import com.dfsek.terra.addons.biome.pipeline.api.stage.type.BiomeMutator;
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.api.Stage;
|
||||||
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.api.biome.PipelineBiome;
|
||||||
import com.dfsek.terra.api.noise.NoiseSampler;
|
import com.dfsek.terra.api.noise.NoiseSampler;
|
||||||
import com.dfsek.terra.api.util.collection.ProbabilityCollection;
|
import com.dfsek.terra.api.util.collection.ProbabilityCollection;
|
||||||
|
|
||||||
|
|
||||||
public class ReplaceMutator implements BiomeMutator {
|
public class ReplaceMutator implements Stage {
|
||||||
private final String replaceableTag;
|
private final String replaceableTag;
|
||||||
private final ProbabilityCollection<BiomeDelegate> replace;
|
private final ProbabilityCollection<PipelineBiome> replace;
|
||||||
private final NoiseSampler sampler;
|
private final NoiseSampler sampler;
|
||||||
|
|
||||||
public ReplaceMutator(String replaceable, ProbabilityCollection<BiomeDelegate> replace, NoiseSampler sampler) {
|
public ReplaceMutator(String replaceable, ProbabilityCollection<PipelineBiome> replace, NoiseSampler sampler) {
|
||||||
this.replaceableTag = replaceable;
|
this.replaceableTag = replaceable;
|
||||||
this.replace = replace;
|
this.replace = replace;
|
||||||
this.sampler = sampler;
|
this.sampler = sampler;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BiomeDelegate mutate(ViewPoint viewPoint, double x, double z, long seed) {
|
public PipelineBiome apply(ViewPoint viewPoint) {
|
||||||
if(viewPoint.getBiome(0, 0).getTags().contains(replaceableTag)) {
|
if(viewPoint.getBiome().getTags().contains(replaceableTag)) {
|
||||||
BiomeDelegate biome = replace.get(sampler, x, z, seed);
|
PipelineBiome biome = replace.get(sampler, viewPoint.worldX(), viewPoint.worldZ(), viewPoint.worldSeed());
|
||||||
return biome.isSelf() ? viewPoint.getBiome(0, 0) : biome;
|
return biome.isSelf() ? viewPoint.getBiome() : biome;
|
||||||
}
|
}
|
||||||
return viewPoint.getBiome(0, 0);
|
return viewPoint.getBiome();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Iterable<BiomeDelegate> getBiomes(Iterable<BiomeDelegate> biomes) {
|
public int maxRelativeReadDistance() {
|
||||||
Set<BiomeDelegate> biomeSet = new HashSet<>();
|
return 0;
|
||||||
Set<BiomeDelegate> reject = new HashSet<>();
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<PipelineBiome> getBiomes(Iterable<PipelineBiome> biomes) {
|
||||||
|
Set<PipelineBiome> biomeSet = new HashSet<>();
|
||||||
|
Set<PipelineBiome> reject = new HashSet<>();
|
||||||
biomes.forEach(biome -> {
|
biomes.forEach(biome -> {
|
||||||
if(!biome.getTags().contains(replaceableTag)) {
|
if(!biome.getTags().contains(replaceableTag)) {
|
||||||
biomeSet.add(biome);
|
biomeSet.add(biome);
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* 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.biome.pipeline.reimplementation.stage.mutators;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.BiomeChunkImpl.ViewPoint;
|
||||||
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.api.Stage;
|
||||||
|
import com.dfsek.terra.addons.biome.pipeline.reimplementation.api.biome.PipelineBiome;
|
||||||
|
import com.dfsek.terra.api.noise.NoiseSampler;
|
||||||
|
|
||||||
|
|
||||||
|
public class SmoothMutator implements Stage {
|
||||||
|
|
||||||
|
private final NoiseSampler sampler;
|
||||||
|
|
||||||
|
public SmoothMutator(NoiseSampler sampler) {
|
||||||
|
this.sampler = sampler;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PipelineBiome apply(ViewPoint viewPoint) {
|
||||||
|
PipelineBiome top = viewPoint.getRelativeBiome(1, 0);
|
||||||
|
PipelineBiome bottom = viewPoint.getRelativeBiome(-1, 0);
|
||||||
|
PipelineBiome left = viewPoint.getRelativeBiome(0, 1);
|
||||||
|
PipelineBiome right = viewPoint.getRelativeBiome(0, -1);
|
||||||
|
|
||||||
|
double roll = sampler.noise(viewPoint.worldSeed(), viewPoint.worldX(), viewPoint.worldZ());
|
||||||
|
|
||||||
|
boolean vert = Objects.equals(top, bottom);
|
||||||
|
boolean horiz = Objects.equals(left, right);
|
||||||
|
|
||||||
|
if(vert && horiz) {
|
||||||
|
return roll > 0 ?
|
||||||
|
roll > 0.25 ? left : right :
|
||||||
|
roll > -0.25 ? top : bottom;
|
||||||
|
}
|
||||||
|
if(vert) {
|
||||||
|
return roll > 0 ? top : bottom;
|
||||||
|
}
|
||||||
|
if(horiz) {
|
||||||
|
return roll > 0 ? left : right;
|
||||||
|
}
|
||||||
|
return viewPoint.getBiome();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int maxRelativeReadDistance() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.biome.pipeline.source;
|
|
||||||
|
|
||||||
import com.dfsek.terra.addons.biome.pipeline.api.delegate.BiomeDelegate;
|
|
||||||
import com.dfsek.terra.api.noise.NoiseSampler;
|
|
||||||
import com.dfsek.terra.api.util.collection.ProbabilityCollection;
|
|
||||||
|
|
||||||
|
|
||||||
public class SamplerSource implements BiomeSource {
|
|
||||||
private final ProbabilityCollection<BiomeDelegate> biomes;
|
|
||||||
private final NoiseSampler sampler;
|
|
||||||
|
|
||||||
public SamplerSource(ProbabilityCollection<BiomeDelegate> biomes, NoiseSampler sampler) {
|
|
||||||
this.biomes = biomes;
|
|
||||||
this.sampler = sampler;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BiomeDelegate getBiome(double x, double z, long seed) {
|
|
||||||
return biomes.get(sampler, x, z, seed);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Iterable<BiomeDelegate> getBiomes() {
|
|
||||||
return biomes.getContents();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -9,11 +9,10 @@ package com.dfsek.terra.addons.biome.pipeline.stages;
|
|||||||
|
|
||||||
import com.dfsek.terra.addons.biome.pipeline.api.BiomeHolder;
|
import com.dfsek.terra.addons.biome.pipeline.api.BiomeHolder;
|
||||||
import com.dfsek.terra.addons.biome.pipeline.api.delegate.BiomeDelegate;
|
import com.dfsek.terra.addons.biome.pipeline.api.delegate.BiomeDelegate;
|
||||||
import com.dfsek.terra.addons.biome.pipeline.api.stage.Stage;
|
|
||||||
import com.dfsek.terra.addons.biome.pipeline.api.stage.type.BiomeMutator;
|
import com.dfsek.terra.addons.biome.pipeline.api.stage.type.BiomeMutator;
|
||||||
|
|
||||||
|
|
||||||
public class MutatorStage implements Stage {
|
public class MutatorStage implements com.dfsek.terra.addons.biome.pipeline.api.stage.Stage {
|
||||||
private final BiomeMutator mutator;
|
private final BiomeMutator mutator;
|
||||||
|
|
||||||
public MutatorStage(BiomeMutator mutator) {
|
public MutatorStage(BiomeMutator mutator) {
|
||||||
|
|||||||
Reference in New Issue
Block a user