diff --git a/src/main/java/org/terasology/biomesAPI/BaseConditionalBiome.java b/src/main/java/org/terasology/biomesAPI/BaseConditionalBiome.java new file mode 100644 index 0000000..feb9c2e --- /dev/null +++ b/src/main/java/org/terasology/biomesAPI/BaseConditionalBiome.java @@ -0,0 +1,56 @@ +/* + * Copyright 2019 MovingBlocks + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.terasology.biomesAPI; + +import org.terasology.math.geom.Vector2f; +import org.terasology.world.generation.facets.base.FieldFacet2D; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +public abstract class BaseConditionalBiome implements ConditionalBiome { + protected Map, Vector2f> limitedFacets = new HashMap<>(); + + @Override + public boolean isValid(Class facetClass, Float value) { + Vector2f constraints = limitedFacets.get(facetClass); + return constraints == null || (value >= constraints.x && value <= constraints.y); + } + + @Override + public Set> getLimitedFacets() { + return limitedFacets.keySet(); + } + + @Override + public void setLowerLimit(Class facetClass, Float minimum) { + limitedFacets.compute(facetClass, (k, v) -> { + if (v == null) v = new Vector2f(minimum, Float.MAX_VALUE); + v.x = minimum; + return v; + }); + } + + @Override + public void setUpperLimit(Class facetClass, Float maximum) { + limitedFacets.compute(facetClass, (k, v) -> { + if (v == null) v = new Vector2f(Float.MIN_VALUE, maximum); + v.y = maximum; + return v; + }); + } +} \ No newline at end of file diff --git a/src/main/java/org/terasology/biomesAPI/BiomeManager.java b/src/main/java/org/terasology/biomesAPI/BiomeManager.java index 6ddec81..ff79525 100644 --- a/src/main/java/org/terasology/biomesAPI/BiomeManager.java +++ b/src/main/java/org/terasology/biomesAPI/BiomeManager.java @@ -24,6 +24,7 @@ import org.terasology.entitySystem.systems.BaseComponentSystem; import org.terasology.entitySystem.systems.RegisterSystem; import org.terasology.logic.players.PlayerCharacterComponent; +import org.terasology.math.geom.BaseVector2i; import org.terasology.math.geom.Vector3f; import org.terasology.math.geom.Vector3i; import org.terasology.physics.events.MovedEvent; @@ -34,7 +35,9 @@ import org.terasology.world.chunks.CoreChunk; import org.terasology.world.chunks.blockdata.ExtraDataSystem; import org.terasology.world.chunks.blockdata.RegisterExtraData; +import org.terasology.world.generation.GeneratingRegion; +import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; @@ -97,6 +100,24 @@ public List getRegisteredBiomes(Class biomeClass) { return biomeMap.values().stream().filter(biomeClass::isInstance).map(biomeClass::cast).collect(Collectors.toList()); } + @Override + public List getValidBiomes(GeneratingRegion region, BaseVector2i pos) { + return getValidBiomes(region, pos, false); + } + + @Override + public List getValidBiomes(GeneratingRegion region, BaseVector2i pos, boolean conditionalOnly) { + List matches = new ArrayList<>(); + for (Biome biome : biomeMap.values()) { + if (biome instanceof ConditionalBiome) { + if (((ConditionalBiome) biome).isValid(region, pos)) matches.add(biome); + } else if (!conditionalOnly) { + matches.add(biome); + } + } + return matches; + } + /** * Blocks have id, no matter what kind of blocks they are. */ diff --git a/src/main/java/org/terasology/biomesAPI/BiomeRegistry.java b/src/main/java/org/terasology/biomesAPI/BiomeRegistry.java index 85fd083..c60950a 100644 --- a/src/main/java/org/terasology/biomesAPI/BiomeRegistry.java +++ b/src/main/java/org/terasology/biomesAPI/BiomeRegistry.java @@ -16,8 +16,10 @@ package org.terasology.biomesAPI; import org.terasology.entitySystem.systems.ComponentSystem; +import org.terasology.math.geom.BaseVector2i; import org.terasology.math.geom.Vector3i; import org.terasology.world.chunks.CoreChunk; +import org.terasology.world.generation.GeneratingRegion; import java.util.Collection; import java.util.Optional; @@ -96,4 +98,21 @@ public interface BiomeRegistry { * @return Collection of biomes of given subtype */ Collection getRegisteredBiomes(Class biomeClass); + + /** + * Returns all biomes that do not forbid themselves from the given location. + * @param region The world region + * @param pos The location in the world + * @return Collection of biomes that are valid for that location + */ + Collection getValidBiomes(GeneratingRegion region, BaseVector2i pos); + + /** + * Returns all biomes that do not forbid themselves from the given location. + * @param region The world region + * @param pos The location in the world + * @param conditionalOnly If true, ignore biomes that have no restrictions + * @return Collection of biomes that are valid for that location + */ + Collection getValidBiomes(GeneratingRegion region, BaseVector2i pos, boolean conditionalOnly); } diff --git a/src/main/java/org/terasology/biomesAPI/ConditionalBiome.java b/src/main/java/org/terasology/biomesAPI/ConditionalBiome.java new file mode 100644 index 0000000..018b2e7 --- /dev/null +++ b/src/main/java/org/terasology/biomesAPI/ConditionalBiome.java @@ -0,0 +1,74 @@ +/* + * Copyright 2019 MovingBlocks + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.terasology.biomesAPI; + +import org.terasology.math.geom.BaseVector2i; +import org.terasology.world.generation.GeneratingRegion; +import org.terasology.world.generation.facets.base.FieldFacet2D; + +import java.util.Set; + +/** + * This interface allows biomes to accept various limits on where they may generate. + */ +public interface ConditionalBiome extends Biome { + + /** + * Returns true if the biome can generate at the given value of the given facet. + * @param facetClass The facet to check, such as humidity or temperature. + * @param value This facet's value. + * @return True if possible. + */ + default boolean isValid(Class facetClass, Float value) + { + return true; + } + + /** + * Checks whether all facets of the given location meet this biome's restrictions. + * @param region The game region being generated. + * @param pos The particular position we are checking. + * @return True if this biome's conditions are met. + */ + default boolean isValid(GeneratingRegion region, BaseVector2i pos) + { + for (Class classy : getLimitedFacets()) + { + FieldFacet2D facetResult = region.getRegionFacet(classy); + if (!isValid(classy, facetResult.get(pos))) + { + return false; + } + } + return true; + } + + /** + * @return A list of all facets that this biome has restrictions towards. + */ + Set> getLimitedFacets(); + + void setLowerLimit(Class facetClass, Float minimum); + + void setUpperLimit(Class facetClass, Float maximum); + + default void setLimits(Class facetClass, Float minimum, Float maximum) + { + setLowerLimit(facetClass, minimum); + setUpperLimit(facetClass, maximum); + } + +} \ No newline at end of file