From deb6de3d6c4996e453db927b92af797bd6662186 Mon Sep 17 00:00:00 2001 From: dfsek Date: Fri, 10 Jun 2022 17:09:39 -0700 Subject: [PATCH] implement ReplaceableBiome --- .../biome/extrusion/BiomeExtrusionAddon.java | 13 +++++++ .../biome/extrusion/api/PresentBiome.java | 23 +++++++++++ .../biome/extrusion/api/ReplaceableBiome.java | 31 +++++++++++++++ .../addons/biome/extrusion/api/SelfBiome.java | 21 ++++++++++ .../config/ReplaceableBiomeLoader.java | 32 +++++++++++++++ .../extrusions/SamplerExtrusion.java | 20 ---------- .../extrusion/extrusions/SetExtrusion.java | 39 ++++++++++++++++++- .../java/com/dfsek/terra/api/util/Range.java | 21 ++++++++++ 8 files changed, 179 insertions(+), 21 deletions(-) create mode 100644 common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/api/PresentBiome.java create mode 100644 common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/api/ReplaceableBiome.java create mode 100644 common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/api/SelfBiome.java create mode 100644 common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/config/ReplaceableBiomeLoader.java delete mode 100644 common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/extrusions/SamplerExtrusion.java diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionAddon.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionAddon.java index 4a33d8e57..b5b774dc3 100644 --- a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionAddon.java +++ b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/BiomeExtrusionAddon.java @@ -3,14 +3,19 @@ package com.dfsek.terra.addons.biome.extrusion; import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; import com.dfsek.terra.addons.biome.extrusion.api.Extrusion; +import com.dfsek.terra.addons.biome.extrusion.api.ReplaceableBiome; +import com.dfsek.terra.addons.biome.extrusion.config.ReplaceableBiomeLoader; import com.dfsek.terra.addons.manifest.api.AddonInitializer; import com.dfsek.terra.api.Platform; import com.dfsek.terra.api.addon.BaseAddon; +import com.dfsek.terra.api.event.events.config.pack.ConfigPackPostLoadEvent; import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent; import com.dfsek.terra.api.event.functional.FunctionalEventHandler; import com.dfsek.terra.api.inject.annotations.Inject; import com.dfsek.terra.api.registry.CheckedRegistry; +import com.dfsek.terra.api.registry.Registry; import com.dfsek.terra.api.util.reflection.TypeKey; +import com.dfsek.terra.api.world.biome.Biome; import com.dfsek.terra.api.world.biome.generation.BiomeProvider; import java.util.function.Supplier; @@ -35,5 +40,13 @@ public class BiomeExtrusionAddon implements AddonInitializer { }) .failThrough(); + + platform.getEventManager() + .getHandler(FunctionalEventHandler.class) + .register(addon, ConfigPackPostLoadEvent.class) + .then(event -> { + Registry biomeRegistry = event.getPack().getRegistry(Biome.class); + event.getPack().applyLoader(ReplaceableBiome.class, new ReplaceableBiomeLoader(biomeRegistry)); + }); } } diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/api/PresentBiome.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/api/PresentBiome.java new file mode 100644 index 000000000..385b01e0b --- /dev/null +++ b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/api/PresentBiome.java @@ -0,0 +1,23 @@ +package com.dfsek.terra.addons.biome.extrusion.api; + + +import com.dfsek.terra.api.world.biome.Biome; + + +final class PresentBiome implements ReplaceableBiome { + private final Biome biome; + + PresentBiome(Biome biome) { + this.biome = biome; + } + + @Override + public Biome get(Biome existing) { + return biome; + } + + @Override + public boolean isSelf() { + return false; + } +} diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/api/ReplaceableBiome.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/api/ReplaceableBiome.java new file mode 100644 index 000000000..31e742afa --- /dev/null +++ b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/api/ReplaceableBiome.java @@ -0,0 +1,31 @@ +package com.dfsek.terra.addons.biome.extrusion.api; + + +import com.dfsek.terra.api.world.biome.Biome; + +import java.util.Optional; + + +/** + * Basically just a specialised implementation of {@link Optional} for biomes where a biome may be a "self" reference. + */ +public sealed interface ReplaceableBiome permits PresentBiome, SelfBiome { + Biome get(Biome existing); + + default Biome get() { + if(isSelf()) { + throw new IllegalStateException("Cannot get() self biome!"); + } + return get(null); + } + + boolean isSelf(); + + static ReplaceableBiome of(Biome biome) { + return new PresentBiome(biome); + } + + static ReplaceableBiome self() { + return SelfBiome.INSTANCE; + } +} diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/api/SelfBiome.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/api/SelfBiome.java new file mode 100644 index 000000000..4e37192af --- /dev/null +++ b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/api/SelfBiome.java @@ -0,0 +1,21 @@ +package com.dfsek.terra.addons.biome.extrusion.api; + + +import com.dfsek.terra.api.world.biome.Biome; + +import java.util.Objects; + + +final class SelfBiome implements ReplaceableBiome { + public static final SelfBiome INSTANCE = new SelfBiome(); + + @Override + public Biome get(Biome existing) { + return Objects.requireNonNull(existing); + } + + @Override + public boolean isSelf() { + return true; + } +} diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/config/ReplaceableBiomeLoader.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/config/ReplaceableBiomeLoader.java new file mode 100644 index 000000000..9ef2573ab --- /dev/null +++ b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/config/ReplaceableBiomeLoader.java @@ -0,0 +1,32 @@ +package com.dfsek.terra.addons.biome.extrusion.config; + +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 org.jetbrains.annotations.NotNull; + +import java.lang.reflect.AnnotatedType; + +import com.dfsek.terra.addons.biome.extrusion.api.ReplaceableBiome; +import com.dfsek.terra.api.registry.Registry; +import com.dfsek.terra.api.world.biome.Biome; + + +public class ReplaceableBiomeLoader implements TypeLoader { + private final Registry biomeRegistry; + + public ReplaceableBiomeLoader(Registry biomeRegistry) { + this.biomeRegistry = biomeRegistry; + } + + @Override + public ReplaceableBiome load(@NotNull AnnotatedType t, @NotNull Object c, @NotNull ConfigLoader loader, DepthTracker depthTracker) + throws LoadException { + if(c.equals("SELF")) return ReplaceableBiome.self(); + return biomeRegistry + .getByID((String) c) + .map(ReplaceableBiome::of) + .orElseThrow(() -> new LoadException("No such biome: " + c, depthTracker)); + } +} diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/extrusions/SamplerExtrusion.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/extrusions/SamplerExtrusion.java deleted file mode 100644 index 0975265de..000000000 --- a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/extrusions/SamplerExtrusion.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.dfsek.terra.addons.biome.extrusion.extrusions; - -import com.dfsek.terra.addons.biome.extrusion.api.Extrusion; -import com.dfsek.terra.api.noise.NoiseSampler; -import com.dfsek.terra.api.world.biome.Biome; - -import java.security.cert.Extension; - - -/** - * Extrusion which operates using a noise sampler - */ -public abstract class SamplerExtrusion implements Extrusion { - protected NoiseSampler sampler; - - @Override - public Biome extrude(Biome original, int x, int y, int z, long seed) { - return null; - } -} diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/extrusions/SetExtrusion.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/extrusions/SetExtrusion.java index fae6a7b98..fdea728a1 100644 --- a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/extrusions/SetExtrusion.java +++ b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/extrusions/SetExtrusion.java @@ -1,7 +1,44 @@ package com.dfsek.terra.addons.biome.extrusion.extrusions; +import com.dfsek.terra.addons.biome.extrusion.api.Extrusion; +import com.dfsek.terra.addons.biome.extrusion.api.ReplaceableBiome; +import com.dfsek.terra.api.noise.NoiseSampler; +import com.dfsek.terra.api.util.Range; +import com.dfsek.terra.api.util.collection.ProbabilityCollection; +import com.dfsek.terra.api.world.biome.Biome; + +import java.util.function.Predicate; +import java.util.stream.Collectors; + + /** * Sets biomes at locations based on a sampler. */ -public class SetExtrusion { +public class SetExtrusion implements Extrusion { + private final NoiseSampler sampler; + + private final Range range; + + private final ProbabilityCollection biomes; + + public SetExtrusion(NoiseSampler sampler, Range range, ProbabilityCollection biomes) { + this.sampler = sampler; + this.range = range; + this.biomes = biomes; + } + + @Override + public Biome extrude(Biome original, int x, int y, int z, long seed) { + return range.ifInRange(y, () -> biomes.get(sampler, x, y, z, seed).get(original), original); + } + + @Override + public Iterable getBiomes() { + return biomes + .getContents() + .stream() + .filter(Predicate.not(ReplaceableBiome::isSelf)) + .map(ReplaceableBiome::get) + .collect(Collectors.toSet()); + } } diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/Range.java b/common/api/src/main/java/com/dfsek/terra/api/util/Range.java index 9aa57fde3..c417b8183 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/util/Range.java +++ b/common/api/src/main/java/com/dfsek/terra/api/util/Range.java @@ -11,6 +11,7 @@ import org.jetbrains.annotations.NotNull; import java.util.Iterator; import java.util.Random; +import java.util.function.Supplier; public interface Range extends Iterable { @@ -41,4 +42,24 @@ public interface Range extends Iterable { Range setMin(int min); int getRange(); + + default T ifInRange(int y, T inRange, T notInRange) { + if(isInRange(y)) return inRange; + return notInRange; + } + + default T ifInRange(int y, Supplier inRange, Supplier notInRange) { + if(isInRange(y)) return inRange.get(); + return notInRange.get(); + } + + default T ifInRange(int y, Supplier inRange, T notInRange) { + if(isInRange(y)) return inRange.get(); + return notInRange; + } + + default T ifInRange(int y, T inRange, Supplier notInRange) { + if(isInRange(y)) return inRange; + return notInRange.get(); + } }