mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-10-26 22:10:18 +00:00
Kept mod trees on plantable ground
- A mod biome that brings its own vegetation pays a template penalty scaled by the share of the template's top surface layer that cannot hold plants, so snow, ice, sand, and stone templates no longer swallow its trees - The top layer palette is resolved through biome-palette snippets and weighted by palette entry weight - Mod biomes without their own vegetation keep the closest climate template
This commit is contained in:
1 parent
d749633829
commit
ad66538d7a
3 files changed
+171
-3
No files matched your search
@@ -29,6 +29,7 @@ import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
@@ -40,6 +41,9 @@ final class IngestPackModel {
|
||||
private static final int DEFAULT_MIN_Y = -64;
|
||||
private static final int DEFAULT_MAX_Y = 320;
|
||||
private static final String DEFAULT_DERIVATIVE = "minecraft:the_void";
|
||||
private static final Set<String> PLANTABLE_BLOCKS = Set.of("minecraft:grass_block", "minecraft:dirt", "minecraft:coarse_dirt",
|
||||
"minecraft:podzol", "minecraft:rooted_dirt", "minecraft:mycelium", "minecraft:moss_block", "minecraft:pale_moss_block",
|
||||
"minecraft:mud", "minecraft:muddy_mangrove_roots", "minecraft:farmland");
|
||||
|
||||
private final IngestPack pack;
|
||||
private final WorldgenCatalogIndex index;
|
||||
@@ -50,6 +54,7 @@ final class IngestPackModel {
|
||||
private final int packMaxY;
|
||||
private final List<RegionProfile> regions;
|
||||
private final Map<String, String> reachableBiomes;
|
||||
private final Map<String, Double> plantableShares = new HashMap<>();
|
||||
|
||||
private IngestPackModel(IngestPack pack, WorldgenCatalogIndex index, String dimensionPath, JsonObject dimension,
|
||||
int[] heightRange, List<RegionProfile> regions, Map<String, String> reachableBiomes) {
|
||||
@@ -115,6 +120,42 @@ final class IngestPackModel {
|
||||
return climateReference(index, reachableBiomes.get(biomeKey)).map(IngestClimate::of).orElse(null);
|
||||
}
|
||||
|
||||
double plantableShare(String biomeKey) throws IOException {
|
||||
Double cached = plantableShares.get(biomeKey);
|
||||
if (cached != null) {
|
||||
return cached;
|
||||
}
|
||||
double share = topLayerPlantableShare(biomeKey);
|
||||
plantableShares.put(biomeKey, share);
|
||||
return share;
|
||||
}
|
||||
|
||||
private double topLayerPlantableShare(String biomeKey) throws IOException {
|
||||
Optional<JsonObject> biome = pack.find(IngestPack.biomePath(biomeKey));
|
||||
JsonElement layers = biome.map((JsonObject value) -> value.get("layers")).orElse(null);
|
||||
if (layers == null || !layers.isJsonArray() || layers.getAsJsonArray().isEmpty()) {
|
||||
return 1D;
|
||||
}
|
||||
JsonObject top = pack.snippet(layers.getAsJsonArray().get(0), "biome-palette");
|
||||
JsonElement palette = top == null ? null : top.get("palette");
|
||||
if (palette == null || !palette.isJsonArray() || palette.getAsJsonArray().isEmpty()) {
|
||||
return 1D;
|
||||
}
|
||||
double total = 0D;
|
||||
double plantable = 0D;
|
||||
for (JsonElement entry : palette.getAsJsonArray()) {
|
||||
if (!entry.isJsonObject() || !entry.getAsJsonObject().has("block")) {
|
||||
continue;
|
||||
}
|
||||
double weight = Math.max(0D, number(entry.getAsJsonObject().get("weight"), 1D));
|
||||
total += weight;
|
||||
if (PLANTABLE_BLOCKS.contains(VanillaJson.namespaced(entry.getAsJsonObject().get("block").getAsString()))) {
|
||||
plantable += weight;
|
||||
}
|
||||
}
|
||||
return total <= 0D ? 1D : plantable / total;
|
||||
}
|
||||
|
||||
Set<String> biomeCategories(String biomeKey) {
|
||||
return climateReference(index, reachableBiomes.get(biomeKey)).map((CatalogBiome biome) -> BiomeCategories.of(biome.tags())).orElse(Set.of());
|
||||
}
|
||||
|
||||
@@ -44,6 +44,7 @@ final class ModBiomeAdopter {
|
||||
private static final double REGION_CLIMATE_WEIGHT = 0.25D;
|
||||
private static final double REUSE_WEIGHT = 0.05D;
|
||||
private static final double THEMED_REGION_PENALTY = 0.6D;
|
||||
private static final double BARE_SURFACE_PENALTY = 3D;
|
||||
private static final int THEMED_RARITY_FACTOR = 5;
|
||||
|
||||
private final IngestPackModel model;
|
||||
@@ -71,7 +72,8 @@ final class ModBiomeAdopter {
|
||||
continue;
|
||||
}
|
||||
BiomeRole role = classification.role();
|
||||
Placement placement = place(role, IngestClimate.of(biome), BiomeCategories.of(biome.tags()));
|
||||
boolean ownsVegetation = ownsVegetation(biome, namespace);
|
||||
Placement placement = place(role, IngestClimate.of(biome), BiomeCategories.of(biome.tags()), ownsVegetation);
|
||||
if (placement == null) {
|
||||
items.add(new ModIngestItem(namespace, biome.key(), "biome", ModIngestTier.SKIPPED, "",
|
||||
"no region in this dimension accepts a " + role.label() + " biome"));
|
||||
@@ -82,7 +84,7 @@ final class ModBiomeAdopter {
|
||||
templateUses.merge(template, 1, Integer::sum);
|
||||
String irisKey = irisKey(biome.key());
|
||||
JsonObject json = model.pack().require(IngestPack.biomePath(template)).deepCopy();
|
||||
transform(json, biome, ownsVegetation(biome, namespace));
|
||||
transform(json, biome, ownsVegetation);
|
||||
model.pack().create(IngestPack.biomePath(irisKey), json);
|
||||
appendToPool(region.key(), role, irisKey);
|
||||
adopted.put(biome.key(), new AdoptedBiome(biome.key(), irisKey, role, region.key()));
|
||||
@@ -98,7 +100,7 @@ final class ModBiomeAdopter {
|
||||
return INGEST_BIOME_FOLDER + namespace + "/" + modBiomeKey.substring(colon + 1);
|
||||
}
|
||||
|
||||
private Placement place(BiomeRole role, IngestClimate climate, Set<String> categories) {
|
||||
private Placement place(BiomeRole role, IngestClimate climate, Set<String> categories, boolean ownsVegetation) throws IOException {
|
||||
Placement best = null;
|
||||
double bestScore = Double.POSITIVE_INFINITY;
|
||||
for (IngestPackModel.RegionProfile region : model.regions()) {
|
||||
@@ -112,6 +114,7 @@ final class ModBiomeAdopter {
|
||||
double score = climate.distance(templateClimate == null ? region.climate() : templateClimate)
|
||||
+ CATEGORY_WEIGHT * BiomeCategories.distance(categories, model.biomeCategories(template))
|
||||
+ REUSE_WEIGHT * templateUses.getOrDefault(template, 0)
|
||||
+ (ownsVegetation ? BARE_SURFACE_PENALTY * (1D - model.plantableShare(template)) : 0D)
|
||||
+ regionPenalty;
|
||||
if (best == null || score < bestScore) {
|
||||
best = new Placement(region, template);
|
||||
|
||||
Reference in new issue
Block a user