diff --git a/common/addons/biome-provider-image/LICENSE b/common/addons/biome-provider-image/LICENSE new file mode 100644 index 000000000..64c1cd516 --- /dev/null +++ b/common/addons/biome-provider-image/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020-2021 Polyhedral Development + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/common/addons/biome-provider-image/README.md b/common/addons/biome-provider-image/README.md new file mode 100644 index 000000000..49e9b8fdb --- /dev/null +++ b/common/addons/biome-provider-image/README.md @@ -0,0 +1,6 @@ +# biome-provider-image + +Implements and registers the `IMAGE` biome provider, a biome provider which +generates biomes from an image, using the `color` attribute of biomes. + +This addon registers the provider type, and all associated config options. \ No newline at end of file diff --git a/common/addons/biome-provider-image/build.gradle.kts b/common/addons/biome-provider-image/build.gradle.kts new file mode 100644 index 000000000..15145b578 --- /dev/null +++ b/common/addons/biome-provider-image/build.gradle.kts @@ -0,0 +1,11 @@ +version = version("1.0.0") + +dependencies { + compileOnlyApi(project(":common:addons:manifest-addon-loader")) + implementation("net.jafama", "jafama", Versions.Libraries.Internal.jafama) + testImplementation("net.jafama", "jafama", Versions.Libraries.Internal.jafama) +} + +tasks.named("shadowJar") { + relocate("net.jafama", "com.dfsek.terra.addons.biome.image.lib.jafama") +} \ No newline at end of file diff --git a/common/addons/biome-provider-image/src/main/java/com/dfsek/terra/addons/biome/image/ImageBiomeProvider.java b/common/addons/biome-provider-image/src/main/java/com/dfsek/terra/addons/biome/image/ImageBiomeProvider.java new file mode 100644 index 000000000..aa2f647bb --- /dev/null +++ b/common/addons/biome-provider-image/src/main/java/com/dfsek/terra/addons/biome/image/ImageBiomeProvider.java @@ -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.image; + +import net.jafama.FastMath; + +import java.awt.Color; +import java.awt.image.BufferedImage; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +import com.dfsek.terra.api.world.biome.Biome; +import com.dfsek.terra.api.world.biome.generation.BiomeProvider; + + +public class ImageBiomeProvider implements BiomeProvider { + private final Map colorBiomeMap = new HashMap<>(); + private final BufferedImage image; + private final int resolution; + private final Align align; + + public ImageBiomeProvider(Set registry, BufferedImage image, int resolution, Align align) { + this.image = image; + this.resolution = resolution; + this.align = align; + registry.forEach(biome -> colorBiomeMap.put(new Color(biome.getColor()), biome)); + } + + private static int distance(Color a, Color b) { + return FastMath.abs(a.getRed() - b.getRed()) + FastMath.abs(a.getGreen() - b.getGreen()) + FastMath.abs(a.getBlue() - b.getBlue()); + } + + @Override + public Biome getBiome(int x, int y, int z, long seed) { + return getBiome(x, z); + } + + public Biome getBiome(int x, int z) { + x /= resolution; + z /= resolution; + Color color = align.getColor(image, x, z); + return colorBiomeMap.get(colorBiomeMap.keySet() + .stream() + .reduce(colorBiomeMap.keySet().stream().findAny().orElseThrow(IllegalStateException::new), + (running, element) -> { + int d1 = distance(color, running); + int d2 = distance(color, element); + return d1 < d2 ? running : element; + })); + } + + @Override + public Optional getBaseBiome(int x, int z, long seed) { + return Optional.of(getBiome(x, z)); + } + + @Override + public Iterable getBiomes() { + return colorBiomeMap.values(); + } + + public enum Align { + CENTER { + @Override + public Color getColor(BufferedImage image, int x, int z) { + return new Color(image.getRGB(FastMath.floorMod(x - image.getWidth() / 2, image.getWidth()), + FastMath.floorMod(z - image.getHeight() / 2, image.getHeight()))); + } + }, + NONE { + @Override + public Color getColor(BufferedImage image, int x, int z) { + return new Color(image.getRGB(FastMath.floorMod(x, image.getWidth()), FastMath.floorMod(z, image.getHeight()))); + } + }; + + public abstract Color getColor(BufferedImage image, int x, int z); + } +} diff --git a/common/addons/biome-provider-image/src/main/java/com/dfsek/terra/addons/biome/image/ImageBiomeProviderAddon.java b/common/addons/biome-provider-image/src/main/java/com/dfsek/terra/addons/biome/image/ImageBiomeProviderAddon.java new file mode 100644 index 000000000..5db8dd51f --- /dev/null +++ b/common/addons/biome-provider-image/src/main/java/com/dfsek/terra/addons/biome/image/ImageBiomeProviderAddon.java @@ -0,0 +1,49 @@ +/* + * 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.image; + +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; + +import java.util.function.Supplier; + +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.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.util.reflection.TypeKey; +import com.dfsek.terra.api.world.biome.Biome; +import com.dfsek.terra.api.world.biome.generation.BiomeProvider; + + +public class ImageBiomeProviderAddon implements AddonInitializer { + public static final TypeKey>> PROVIDER_REGISTRY_KEY = new TypeKey<>() { + }; + + @Inject + private Platform platform; + + @Inject + private BaseAddon addon; + + @Override + public void initialize() { + platform.getEventManager() + .getHandler(FunctionalEventHandler.class) + .register(addon, ConfigPackPreLoadEvent.class) + .then(event -> { + CheckedRegistry>> providerRegistry = event.getPack().getOrCreateRegistry( + PROVIDER_REGISTRY_KEY); + providerRegistry.register(addon.key("IMAGE"), + () -> new ImageProviderTemplate(event.getPack().getRegistry(Biome.class))); + }) + .failThrough(); + } +} diff --git a/common/addons/biome-provider-image/src/main/java/com/dfsek/terra/addons/biome/image/ImageProviderTemplate.java b/common/addons/biome-provider-image/src/main/java/com/dfsek/terra/addons/biome/image/ImageProviderTemplate.java new file mode 100644 index 000000000..6bb683eca --- /dev/null +++ b/common/addons/biome-provider-image/src/main/java/com/dfsek/terra/addons/biome/image/ImageProviderTemplate.java @@ -0,0 +1,45 @@ +/* + * 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.image; + +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 java.awt.image.BufferedImage; +import java.util.HashSet; + +import com.dfsek.terra.api.registry.Registry; +import com.dfsek.terra.api.world.biome.Biome; +import com.dfsek.terra.api.world.biome.generation.BiomeProvider; + + +@SuppressWarnings("FieldMayBeFinal") +public class ImageProviderTemplate implements ObjectTemplate { + private final Registry biomes; + @Value("resolution") + @Default + @Description("Sets the resolution at which to sample the image.") + private int resolution = 1; + @Value("image.name") + @Description("Sets the location of the image on the filesystem, relative to the pack root.") + private BufferedImage image; + @Value("image.align") + @Description("Sets the alignment style to use for the image.") + private ImageBiomeProvider.Align align; + + public ImageProviderTemplate(Registry set) { + this.biomes = set; + } + + @Override + public BiomeProvider get() { + return new ImageBiomeProvider(new HashSet<>(biomes.entries()), image, resolution, align); + } +} diff --git a/common/addons/biome-provider-image/src/main/resources/terra.addon.yml b/common/addons/biome-provider-image/src/main/resources/terra.addon.yml new file mode 100644 index 000000000..3fd86ad52 --- /dev/null +++ b/common/addons/biome-provider-image/src/main/resources/terra.addon.yml @@ -0,0 +1,12 @@ +schema-version: 1 +contributors: + - Terra contributors +id: biome-provider-image +version: @VERSION@ +entrypoints: + - "com.dfsek.terra.addons.biome.image.ImageBiomeProviderAddon" +website: + issues: https://github.com/PolyhedralDev/Terra/issues + source: https://github.com/PolyhedralDev/Terra + docs: https://terra.polydev.org +license: MIT License \ No newline at end of file